Commit d87cd09ba183f1191109735e871566f4e14080a8

Authored by Georg Hopp
1 parent fa58a6cc

more generalizing of response writing (implemented a response writer...now it sh…

…ould be possible to implement a stream writer for images
... ... @@ -2,14 +2,14 @@
2 2 #define __HTTP_REQUEST_QUEUE_H__
3 3
4 4 #include "class.h"
5   -#include "http/request.h"
  5 +#include "http/message.h"
6 6
7   -#define HTTP_REQUEST_QUEUE_MAX 1024
  7 +#define HTTP_MESSAGE_QUEUE_MAX 1024
8 8
9 9
10   -CLASS(HttpRequestQueue) {
11   - HttpRequest requests[HTTP_REQUEST_QUEUE_MAX];
12   - size_t nrequests;
  10 +CLASS(HttpMessageQueue) {
  11 + HttpMessage msgs[HTTP_MESSAGE_QUEUE_MAX];
  12 + size_t nmsgs;
13 13 };
14 14
15 15 #endif /* __HTTP_REQUEST_QUEUE_H__ */
... ...
... ... @@ -3,7 +3,7 @@
3 3
4 4 #include "class.h"
5 5 #include "http/request.h"
6   -#include "http/request/queue.h"
  6 +#include "http/message/queue.h"
7 7
8 8 #define HTTP_REQUEST_PARSER_READ_CHUNK 1024
9 9
... ... @@ -27,7 +27,7 @@ CLASS(HttpRequestParser) {
27 27 size_t buffer_used;
28 28 size_t buffer_size;
29 29
30   - HttpRequestQueue request_queue;
  30 + HttpMessageQueue request_queue;
31 31 HttpRequest cur_request;
32 32
33 33 HttpRequestState state;
... ...
  1 +#ifndef __HTTP_RESPONSE_WRITER_H__
  2 +#define __HTTP_RESPONSE_WRITER_H__
  3 +
  4 +#include "class.h"
  5 +#include "http/response.h"
  6 +#include "http/message/queue.h"
  7 +
  8 +typedef enum e_HttpResponseState {
  9 + HTTP_RESPONSE_NO=0,
  10 + HTTP_RESPONSE_START,
  11 + HTTP_RESPONSE_PIPE,
  12 + HTTP_RESPONSE_DONE
  13 +} HttpResponseState;
  14 +
  15 +CLASS(HttpResponseWriter) {
  16 + char * buffer;
  17 + char pipe[1024];
  18 +
  19 + size_t nbuffer;
  20 + size_t rpipe;
  21 + size_t wpipe;
  22 + char pipe_flip;
  23 +
  24 + HttpMessageQueue response_queue;
  25 + HttpResponse cur_response;
  26 +
  27 + HttpResponseState state;
  28 +};
  29 +
  30 +size_t httpResponseWriterWrite(HttpResponseWriter, int);
  31 +
  32 +#endif // __HTTP_RESPONSE_WRITER_H__
  33 +
  34 +// vim: set ts=4 sw=4:
... ...
  1 +#ifndef __STREAM_WRITER_H__
  2 +#define __STREAM_WRITER_H__
  3 +
  4 +#include <sys/types.h>
  5 +
  6 +typedef size_t (* fptr_streamWriterWrite)(void *, int fd);
  7 +
  8 +extern const struct interface i_StreamWriter;
  9 +
  10 +struct i_StreamWriter {
  11 + const struct interface * const _;
  12 + fptr_streamWriterWrite write;
  13 +};
  14 +
  15 +extern size_t streamWriterWrite(void *, int fd);
  16 +
  17 +#endif // __STREAM_WRITER_H__
  18 +
  19 +// vim: set ts=4 sw=4:
... ...
... ... @@ -7,6 +7,8 @@
7 7 #include "class.h"
8 8 #include "socket.h"
9 9 #include "logger.h"
  10 +#include "http/response.h"
  11 +
10 12
11 13 #define POLL_FD_NSIZE 1024
12 14 #define POLL_FD_SIZE (sizeof(struct pollfd) * POLL_FD_NSIZE)
... ... @@ -24,29 +26,16 @@
24 26 CLASS(Server) {
25 27 Logger logger;
26 28 Sock sock;
27   - void * reader;
28   -
29   - /**
30   - * loeschen: fds[i].event auf 0
31   - * dann nfds um die anzahl der geloeschten elemente verkleinern.
32   - * die in close pending stehenden socket schliessen.
33   - * vor jedem poll qsort auf fds ueber event.
34   - * nach dem poll qsort auf fds ueber revent und reuckgebewert
35   - * von poll beruecksichtigen.
36   - */
  29 +
37 30 nfds_t nfds;
38 31 struct pollfd fds[POLL_FD_NSIZE];
39 32
40 33 struct {
41 34 Sock sock;
42 35 void * reader;
  36 + void * writer;
43 37
44 38 char keep_alive;
45   -
46   - char * wbuf;
47   - char * rbuf;
48   - unsigned int rpos;
49   - unsigned int wpos;
50 39 } conns[POLL_FD_NSIZE];
51 40 };
52 41
... ...
1 1 ACLOCAL_AMFLAGS = -I m4
2 2 AUTOMAKE_OPTIONS = subdir-objects
3 3
4   -IFACE = interface/class.c interface/stream_reader.c interface/logger.c
  4 +IFACE = interface/class.c interface/stream_reader.c interface/logger.c \
  5 + interface/stream_writer.c
5 6 CLASS = class.c interface.c
6 7 SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c
7 8 SERVER = server.c server/run.c server/close_conn.c
8 9 LOGGER = logger.c logger/stderr.c logger/syslog.c
9   -MSG = http/message.c
10   -REQ = http/request.c http/request/queue.c http/request/has_keep_alive.c
  10 +MSG = http/message.c http/message/queue.c
  11 +REQ = http/request.c http/request/has_keep_alive.c
11 12 RESP = http/response.c http/response/404.c http/response/size_get.c \
12 13 http/response/to_string.c
  14 +WRITER = http/response/writer.c http/response/writer/write.c
13 15 HEADER = http/header.c http/header/get.c http/header/add.c \
14 16 http/header/size_get.c http/header/to_string.c
15 17 PARSER = http/request/parser.c http/request/parser/get_header.c \
... ... @@ -23,5 +25,5 @@ bin_PROGRAMS = testserver
23 25
24 26 testserver_SOURCES = testserver.c \
25 27 $(IFACE) $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(MSG) $(REQ) \
26   - $(RESP) $(HEADER) $(PARSER) signalHandling.c daemonize.c
  28 + $(WRITER) $(RESP) $(HEADER) $(PARSER) signalHandling.c daemonize.c
27 29 testserver_CFLAGS = -Wall -I ../include/
... ...
... ... @@ -3,7 +3,7 @@
3 3 #include "class.h"
4 4 #include "interface/class.h"
5 5
6   -#include "http/request/queue.h"
  6 +#include "http/message/queue.h"
7 7
8 8 static
9 9 void
... ... @@ -13,15 +13,15 @@ static
13 13 void
14 14 dtor(void * _this)
15 15 {
16   - HttpRequestQueue this = _this;
  16 + HttpMessageQueue this = _this;
17 17 int i;
18 18
19   - for (i=0; i<this->nrequests; i++) {
20   - delete(&(this->requests)[i]);
  19 + for (i=0; i<this->nmsgs; i++) {
  20 + delete(&(this->msgs)[i]);
21 21 }
22 22 }
23 23
24 24 INIT_IFACE(Class, ctor, dtor, NULL);
25   -CREATE_CLASS(HttpRequestQueue, NULL, IFACE(Class));
  25 +CREATE_CLASS(HttpMessageQueue, NULL, IFACE(Class));
26 26
27 27 // vim: set ts=4 sw=4:
... ...
... ... @@ -8,10 +8,9 @@
8 8 #include "interface/stream_reader.h"
9 9
10 10 #include "http/request/parser.h"
11   -#include "http/request/queue.h"
  11 +#include "http/message/queue.h"
12 12 #include "http/request.h"
13 13
14   -void httpRequestParserParse(HttpRequestParser);
15 14
16 15 static
17 16 void
... ... @@ -19,7 +18,7 @@ ctor(void * _this, va_list * params)
19 18 {
20 19 HttpRequestParser this = _this;
21 20
22   - this->request_queue = new(HttpRequestQueue);
  21 + this->request_queue = new(HttpMessageQueue);
23 22
24 23 this->buffer = malloc(HTTP_REQUEST_PARSER_READ_CHUNK);
25 24 this->buffer[0] = 0;
... ... @@ -33,6 +32,9 @@ dtor(void * _this)
33 32
34 33 free(this->buffer);
35 34 delete(&(this->request_queue));
  35 +
  36 + if (NULL != this->cur_request)
  37 + delete(&(this->cur_request));
36 38 }
37 39
38 40 static
... ... @@ -46,7 +48,7 @@ _clone(void * _this, void * _base)
46 48 /**
47 49 * every parser has its own queue...
48 50 */
49   - this->request_queue = new(HttpRequestQueue);
  51 + this->request_queue = new(HttpMessageQueue);
50 52 this->buffer_used = base->buffer_used;
51 53
52 54 chunks = this->buffer_used / HTTP_REQUEST_PARSER_READ_CHUNK;
... ...
... ... @@ -36,10 +36,10 @@ httpRequestSkip(char ** data)
36 36 void
37 37 httpRequestParserParse(HttpRequestParser this)
38 38 {
39   - char * line;
40   - int cont = 1;
  39 + char * line;
  40 + int cont = 1;
41 41
42   - while(cont) {
  42 + while (cont) {
43 43 switch(this->state) {
44 44 case HTTP_REQUEST_GARBAGE:
45 45 this->cur_data = this->buffer; // initialize static pointer
... ... @@ -82,8 +82,9 @@ httpRequestParserParse(HttpRequestParser this)
82 82 /**
83 83 * enqueue current request
84 84 */
85   - this->request_queue->requests[(this->request_queue->nrequests)++] =
86   - this->cur_request;
  85 + this->request_queue->msgs[(this->request_queue->nmsgs)++] =
  86 + (HttpMessage)this->cur_request;
  87 + this->cur_request = NULL;
87 88
88 89 /**
89 90 * remove processed stuff from input buffer.
... ...
... ... @@ -13,7 +13,6 @@ void
13 13 ctor(void * _this, va_list * params)
14 14 {
15 15 HttpResponse this = _this;
16   - char * status;
17 16 char * reason;
18 17
19 18 PARENTCALL(_this, Class, ctor, params);
... ...
  1 +#include <stdlib.h>
  2 +
  3 +#include "class.h"
  4 +#include "interface/class.h"
  5 +#include "interface/stream_writer.h"
  6 +
  7 +#include "http/message/queue.h"
  8 +#include "http/response/writer.h"
  9 +
  10 +static
  11 +void
  12 +ctor(void * _this, va_list * params)
  13 +{
  14 + HttpResponseWriter this = _this;
  15 +
  16 + this->response_queue = new(HttpMessageQueue);
  17 +}
  18 +
  19 +static
  20 +void
  21 +dtor(void * _this)
  22 +{
  23 + HttpResponseWriter this = _this;
  24 +
  25 + if (NULL != this->buffer) free(this->buffer);
  26 + delete(&(this->response_queue));
  27 +
  28 + if (NULL != this->cur_response)
  29 + delete(&(this->cur_response));
  30 +}
  31 +
  32 +static
  33 +void
  34 +_clone(void * _this, void * _base)
  35 +{
  36 + HttpResponseWriter this = _this;
  37 + //HttpResponseWriter base = _base;
  38 +
  39 + this->response_queue = new(HttpMessageQueue);
  40 +}
  41 +
  42 +INIT_IFACE(Class, ctor, dtor, _clone);
  43 +INIT_IFACE(StreamWriter,
  44 + (fptr_streamWriterWrite)httpResponseWriterWrite);
  45 +CREATE_CLASS(HttpResponseWriter, NULL, IFACE(Class), IFACE(StreamWriter));
  46 +
  47 +// vim: set ts=4 sw=4:
... ...
  1 +#include <unistd.h>
  2 +#include <stdlib.h>
  3 +#include <string.h>
  4 +#include <sys/types.h>
  5 +
  6 +#include "class.h"
  7 +#include "interface/class.h"
  8 +#include "http/response.h"
  9 +#include "http/response/writer.h"
  10 +
  11 +size_t
  12 +httpResponseWriterWrite(HttpResponseWriter this, int fd)
  13 +{
  14 + HttpMessageQueue respq = this->response_queue;
  15 + int cont = 1;
  16 + size_t written = 0;
  17 +
  18 + while (cont) {
  19 + switch (this->state) {
  20 + case HTTP_RESPONSE_NO:
  21 + if (NULL == this->cur_response && 0 < respq->nmsgs) {
  22 + this->cur_response = (HttpResponse)respq->msgs[0];
  23 + memmove(respq->msgs, &(respq->msgs[1]), --respq->nmsgs);
  24 + this->state = HTTP_RESPONSE_START;
  25 + }
  26 + else {
  27 + cont = 0;
  28 + }
  29 + break;
  30 +
  31 + case HTTP_RESPONSE_START:
  32 + if (NULL == this->buffer) {
  33 + this->nbuffer = httpResponseSizeGet(this->cur_response);
  34 + this->buffer = calloc(1, this->nbuffer);
  35 + httpResponseToString(this->cur_response, this->buffer);
  36 + }
  37 + {
  38 + written = write(fd, this->buffer, this->nbuffer);
  39 +
  40 + if (-1 == written) {
  41 + free (this->buffer);
  42 + this->buffer = NULL;
  43 + return written;
  44 + }
  45 +
  46 + if (written == this->nbuffer) {
  47 + if (HTTP_MESSAGE_BUFFERED ==
  48 + ((HttpMessage)(this->cur_response))->type) {
  49 + this->state = HTTP_RESPONSE_DONE;
  50 + }
  51 + else {
  52 + this->state = HTTP_RESPONSE_PIPE;
  53 + }
  54 + }
  55 + else {
  56 + this->nbuffer -= written;
  57 + memmove(this->buffer, this->buffer + written, this->nbuffer);
  58 + cont = 0;
  59 + }
  60 + }
  61 + break;
  62 +
  63 + case HTTP_RESPONSE_PIPE:
  64 + break;
  65 +
  66 + case HTTP_RESPONSE_DONE:
  67 + free (this->buffer);
  68 + this->buffer = NULL;
  69 + delete(&(this->cur_response));
  70 + this->state = HTTP_RESPONSE_NO;
  71 +
  72 + break;
  73 + }
  74 + }
  75 +
  76 + return written;
  77 +}
  78 +
  79 +// vim: set ts=4 sw=4:
... ...
  1 +#include "class.h"
  2 +#include "interface/stream_writer.h"
  3 +
  4 +const struct interface i_StreamWriter = {
  5 + "streamWriter",
  6 + 1
  7 +};
  8 +
  9 +size_t
  10 +streamWriterWrite(void * object, int fd)
  11 +{
  12 + size_t ret;
  13 +
  14 + RETCALL(object, StreamWriter, write, ret, fd);
  15 +
  16 + return ret;
  17 +}
  18 +
  19 +// vim: set ts=4 sw=4:
... ...
... ... @@ -20,7 +20,6 @@ ctor(void * _this, va_list * params)
20 20 int flags;
21 21
22 22 this->logger = va_arg(* params, Logger);
23   - this->reader = va_arg(* params, void*);
24 23 port = va_arg(* params, int);
25 24 backlog = va_arg(* params, unsigned int);
26 25
... ... @@ -47,9 +46,7 @@ dtor(void * _this)
47 46 if (this->sock->handle != (this->fds)[i].fd) {
48 47 delete(&(this->conns[(this->fds)[i].fd]).sock);
49 48 delete(&(this->conns[(this->fds)[i].fd]).reader);
50   -
51   - if (this->conns[(this->fds)[i].fd].wbuf)
52   - free(this->conns[(this->fds)[i].fd].wbuf);
  49 + delete(&(this->conns[(this->fds)[i].fd]).writer);
53 50 }
54 51 }
55 52
... ...
... ... @@ -11,11 +11,8 @@ serverCloseConn(Server this, unsigned int i)
11 11
12 12 delete(&((this->conns)[fd].sock));
13 13 delete(&((this->conns)[fd].reader));
  14 + delete(&((this->conns)[fd].writer));
14 15
15   - if ((this->conns)[fd].wbuf != NULL) {
16   - free((this->conns)[fd].wbuf);
17   - (this->conns)[fd].wbuf = NULL;
18   - }
19 16 (this->conns)[fd].keep_alive = 0;
20 17
21 18 memset(&(this->fds[i]), 0, sizeof(struct pollfd));
... ...
... ... @@ -12,7 +12,8 @@ serverHandleAccept(Server this)
12 12 (this->conns)[acc->handle].sock = acc;
13 13
14 14 //* clone reader
15   - (this->conns)[acc->handle].reader = clone(this->reader);
  15 + (this->conns)[acc->handle].reader = new(HttpRequestParser);
  16 + (this->conns)[acc->handle].writer = new(HttpResponseWriter);
16 17
17 18 (this->fds)[this->nfds].fd = acc->handle;
18 19 (this->fds)[this->nfds].events = POLLIN;
... ...
... ... @@ -13,13 +13,15 @@
13 13 #include "signalHandling.h"
14 14 #include "interface/class.h"
15 15 #include "interface/stream_reader.h"
  16 +#include "interface/stream_writer.h"
16 17 #include "interface/logger.h"
17 18
18 19 //* @TODO: to be removed
19 20 #include "http/request.h"
20 21 #include "http/request/parser.h"
21   -#include "http/request/queue.h"
  22 +#include "http/message/queue.h"
22 23 #include "http/response.h"
  24 +#include "http/response/writer.h"
23 25 //* until here
24 26
25 27 #undef MAX
... ... @@ -102,43 +104,39 @@ serverRun(Server this)
102 104 }
103 105 else {
104 106 int j;
105   - HttpRequestQueue queue =
106   - ((HttpRequestParser)(this->conns)[fd].reader)->request_queue;
107   -
108   - for (j=0; j<queue->nrequests; j++) {
109   - HttpResponse response;
  107 + HttpMessageQueue reqq = ((HttpRequestParser) \
  108 + (this->conns)[fd].reader)->request_queue;
  109 + HttpMessageQueue respq = ((HttpResponseWriter) \
  110 + (this->conns)[fd].writer)->response_queue;
110 111
  112 + for (j=0; j<reqq->nmsgs; j++) {
111 113 /**
112 114 * @TODO: for now simply remove request and send not found.
113 115 * Make this sane.
114 116 */
115   - response = httpResponse404();
  117 + HttpMessage response = (HttpMessage)httpResponse404();
116 118
117   - if (httpRequestHasKeepAlive(queue->requests[j])) {
  119 + if (httpRequestHasKeepAlive((HttpRequest)reqq->msgs[j])) {
118 120 (this->conns)[fd].keep_alive = 1;
119 121 httpHeaderAdd(
120   - &(((HttpMessage)response)->header),
  122 + &(response->header),
121 123 new(HttpHeader, "Connection", "Keep-Alive"));
122 124 }
123 125 else {
124 126 (this->conns)[fd].keep_alive = 0;
125 127 httpHeaderAdd(
126   - &(((HttpMessage)response)->header),
  128 + &(response->header),
127 129 new(HttpHeader, "Connection", "Close"));
128 130 }
129 131
130   - delete(&(queue->requests[j]));
131   -
132   - (this->conns)[fd].wbuf = calloc(
133   - 1, httpResponseSizeGet(response) + 1);
134   - httpResponseToString(response, (this->conns)[fd].wbuf);
135   -
136   - delete(&response);
  132 + respq->msgs[(respq->nmsgs)++] = response;
  133 + response = NULL;
  134 + delete(&(reqq->msgs[j]));
137 135
138 136 (this->fds)[i].events |= POLLOUT;
139 137 }
140 138
141   - queue->nrequests = 0;
  139 + reqq->nmsgs = 0;
142 140 }
143 141 }
144 142 }
... ... @@ -152,31 +150,13 @@ serverRun(Server this)
152 150 events--;
153 151 nwrites--;
154 152
155   - size = write(
156   - (this->fds)[i].fd,
157   - (this->conns)[fd].wbuf,
158   - strlen((this->conns)[fd].wbuf));
159   -
160   - if (size == strlen((this->conns)[fd].wbuf) ||
161   - -1 == size) {
162   - if (-1 == size) {
163   - loggerLog(this->logger, LOGGER_ERR,
164   - "write error, closing connection");
165   - }
  153 + size = streamWriterWrite((this->conns)[fd].writer, fd);
166 154
167   - if ((this->conns)[fd].keep_alive) {
168   - (this->fds)[i].events &= ~POLLOUT;
169   - }
170   - else {
171   - serverCloseConn(this, i);
172   - }
173   - free((this->conns)[fd].wbuf);
174   - (this->conns)[fd].wbuf = NULL;
  155 + if ((this->conns)[fd].keep_alive) {
  156 + (this->fds)[i].events &= ~POLLOUT;
175 157 }
176 158 else {
177   - memmove((this->conns)[fd].wbuf,
178   - (this->conns)[fd].wbuf + size,
179   - strlen((this->conns)[fd].wbuf) - size + 1);
  159 + serverCloseConn(this, i);
180 160 }
181 161 }
182 162 }
... ...
... ... @@ -18,9 +18,8 @@ void daemonize(void);
18 18 int
19 19 main()
20 20 {
21   - Logger logger = new(LoggerSyslog, LOGGER_ERR);
22   - HttpRequestParser parser = new(HttpRequestParser);
23   - Server server = new(Server, logger, parser, 11212, SOMAXCONN);
  21 + Logger logger = new(LoggerSyslog, LOGGER_ERR);
  22 + Server server = new(Server, logger, 11212, SOMAXCONN);
24 23
25 24 struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY};
26 25 setrlimit(RLIMIT_CPU, &limit);
... ... @@ -31,7 +30,6 @@ main()
31 30
32 31 delete(&server);
33 32 delete(&logger);
34   - delete(&parser);
35 33
36 34 return 0;
37 35 }
... ...
Please register or login to post a comment