Commit 228b1d0d29b12379a20ec0d950fd76d3b0b1021d

Authored by Georg Hopp
1 parent 68e96823

changed request handling. @TODO: I still seem to have the problem that the file …

…handles are not closed and freed correctly as the service refuses connections after about a 1000.
  1 +2012-02-08 10:21:04 +0100 Georg Hopp
  2 +
  3 + * changed request handling. @TODO: I still seem to have the problem that the file handles are not closed and freed correctly as the service refuses connections after about a 1000. (HEAD, master)
  4 +
  5 +2012-02-07 14:20:00 +0100 Georg Hopp
  6 +
  7 + * now stuff seems to work correct even if read does not provide a complete request (tested with telnet)
  8 +
1 9 2012-02-07 13:41:49 +0100 Georg Hopp
2 10
3   - * now each HttpRequestParser initializes its own request queue and enqueus completed requests there. The server now gets the queue and prints completed requests. (HEAD, master)
  11 + * now each HttpRequestParser initializes its own request queue and enqueus completed requests there. The server now gets the queue and prints completed requests.
4 12
5 13 2012-02-07 11:12:30 +0100 Georg Hopp
6 14
... ...
... ... @@ -21,21 +21,28 @@
21 21 MOVE_SIZE(sizeof(((server)->conns)[0]),(idx)))
22 22
23 23
24   -typedef void (*server_read_hook)(const char *, size_t);
25   -
26 24 CLASS(Server) {
27 25 Logger logger;
28 26 Sock sock;
29 27 void * reader;
30 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 + */
31 37 nfds_t nfds;
  38 + nfds_t ndel;
32 39 struct pollfd fds[POLL_FD_NSIZE];
33 40
34 41 struct {
35 42 Sock sock;
36 43 void * reader;
37 44
38   - char * wbuf;
  45 + char wbuf[2048];
39 46 char * rbuf;
40 47 unsigned int rpos;
41 48 unsigned int wpos;
... ...
... ... @@ -142,7 +142,6 @@ httpRequestParserParse(HttpRequestParser this)
142 142 while(cont) {
143 143 switch(this->state) {
144 144 case HTTP_REQUEST_GARBAGE:
145   - puts("==skip garbage==");
146 145 data = this->buffer; // initialize static pointer
147 146 httpRequestSkip(&data);
148 147 request = new(HttpRequest);
... ... @@ -151,7 +150,6 @@ httpRequestParserParse(HttpRequestParser this)
151 150 break;
152 151
153 152 case HTTP_REQUEST_START:
154   - puts("==request line==");
155 153 if (NULL == (line = httpRequestLineGet(&data))) {
156 154 cont = 0;
157 155 break;
... ... @@ -193,7 +191,6 @@ httpRequestParserParse(HttpRequestParser this)
193 191 break;
194 192
195 193 case HTTP_REQUEST_REQUEST_LINE_DONE:
196   - puts("==read header==");
197 194 if (NULL == (line = httpRequestLineGet(&data))) {
198 195 cont = 0;
199 196 break;
... ... @@ -222,8 +219,6 @@ httpRequestParserParse(HttpRequestParser this)
222 219 break;
223 220
224 221 case HTTP_REQUEST_HEADERS_DONE:
225   - puts("==headers done==");
226   -
227 222 /**
228 223 * @TODO: here comes the body handling
229 224 */
... ... @@ -231,8 +226,6 @@ httpRequestParserParse(HttpRequestParser this)
231 226 break;
232 227
233 228 case HTTP_REQUEST_DONE:
234   - puts("==request done==");
235   -
236 229 /**
237 230 * enqueue current request
238 231 */
... ...
... ... @@ -6,10 +6,14 @@
6 6 void
7 7 serverCloseConn(Server this, unsigned int i)
8 8 {
9   - delete(&((this->conns)[i].sock));
10   - delete(&((this->conns)[i].reader));
11   - CLEAR_CONN(this, i);
12   - this->nfds--;
  9 + int fd = (this->fds)[i].fd;
  10 +
  11 + delete(&((this->conns)[fd].sock));
  12 + delete(&((this->conns)[fd].reader));
  13 + (this->fds)[i].events = 0;
  14 + this->ndel++;
  15 +// CLEAR_CONN(this, i);
  16 +// this->nfds--;
13 17 }
14 18
15 19 // vim: set ts=4 sw=4:
... ...
... ... @@ -2,28 +2,26 @@ static
2 2 void
3 3 serverHandleAccept(Server this)
4 4 {
5   - if (0 != ((this->fds)[0].revents & POLLIN)) {
6   - char remoteAddr[16] = "";
7   - Sock acc;
  5 + char remoteAddr[16] = "";
  6 + Sock acc;
8 7
9   - acc = socketAccept(this->sock, remoteAddr);
  8 + acc = socketAccept(this->sock, remoteAddr);
10 9
11   - if (-1 != acc->handle) {
12   - //* save the socket handle
13   - (this->conns)[this->nfds].sock = acc;
  10 + if (-1 != acc->handle) {
  11 + //* save the socket handle
  12 + (this->conns)[acc->handle].sock = acc;
14 13
15   - //* clone reader
16   - (this->conns)[this->nfds].reader = clone(this->reader);
  14 + //* clone reader
  15 + (this->conns)[acc->handle].reader = clone(this->reader);
17 16
18   - (this->fds)[this->nfds].fd = acc->handle;
19   - (this->fds)[this->nfds].events = POLLIN;
20   - this->nfds++;
21   - } else {
22   - delete(&acc);
23   - }
24   -
25   - (this->fds)[0].revents |= POLLIN;
  17 + (this->fds)[this->nfds].fd = acc->handle;
  18 + (this->fds)[this->nfds].events = POLLIN;
  19 + this->nfds++;
  20 + } else {
  21 + delete(&acc);
26 22 }
  23 +
  24 + (this->fds)[0].revents |= POLLIN;
27 25 }
28 26
29 27 // vim: set ts=4 sw=4:
... ...
  1 +#define POLLFD(ptr) ((struct pollfd *)(ptr))
  2 +
  3 +static
  4 +inline
  5 +int
  6 +sortEvents(const void * a, const void * b)
  7 +{
  8 + return POLLFD(a)->events > POLLFD(b)->events ?
  9 + -1 : POLLFD(a)->events < POLLFD(b)->events ?
  10 + 1 : 0;
  11 +}
  12 +
  13 +static
  14 +inline
  15 +int
  16 +sortRevents(const void * a, const void * b)
  17 +{
  18 + return POLLFD(a)->revents > POLLFD(b)->revents ?
  19 + -1 : POLLFD(a)->revents < POLLFD(b)->revents ?
  20 + 1 : 0;
  21 +}
  22 +
1 23 static
2 24 int
3 25 serverPoll(Server this) {
4 26 int events;
5 27
  28 + qsort(this->fds, this->nfds, sizeof(struct pollfd), sortEvents);
  29 + this->nfds -= this->ndel;
  30 + this->ndel = 0;
  31 +
6 32 /*
7 33 * wait for handles to become ready
8 34 */
... ... @@ -23,6 +49,8 @@ serverPoll(Server this) {
23 49 }
24 50 }
25 51
  52 + qsort(this->fds, this->nfds, sizeof(struct pollfd), sortRevents);
  53 +
26 54 return events;
27 55 }
28 56
... ...
1 1 static
2 2 int
3   -serverRead(Server this)
  3 +serverRead(Server this, unsigned int i)
4 4 {
5   - unsigned int i;
  5 + int fd = (this->fds)[i].fd;
6 6
7   - for (i=1; i<this->nfds; i++) {
8   - if (0 != ((this->fds)[i].revents & POLLIN)) {
9   - if (NULL == (this->conns)[i].reader) {
10   - loggerLog(
11   - this->logger,
12   - LOGGER_INFO,
13   - "initialization error: NULL reader");
14   - serverCloseConn(this, i);
15   - }
  7 + if (NULL == (this->conns)[fd].reader) {
  8 + loggerLog(
  9 + this->logger,
  10 + LOGGER_INFO,
  11 + "initialization error: NULL reader");
  12 + serverCloseConn(this, i);
  13 + }
16 14
17   - switch (streamReaderRead((this->conns)[i].reader, (this->fds)[i].fd)) {
18   - case 0:
19   - /*
20   - * normal close: write remaining data
21   - * @TODO: actually we have no remaining data here....
22   - */
23   - /* DROP-THROUGH */
  15 + switch (streamReaderRead((this->conns)[fd].reader, fd)) {
  16 + case 0:
  17 + /*
  18 + * normal close: write remaining data
  19 + * @TODO: actually we have no remaining data here....
  20 + */
  21 + /* DROP-THROUGH */
24 22
25   - case -1:
26   - /*
27   - * read failure / close connection
28   - */
29   - loggerLog(this->logger, LOGGER_INFO, "connection closed...");
30   - serverCloseConn(this, i);
31   - break;
  23 + case -1:
  24 + /*
  25 + * read failure / close connection
  26 + */
  27 + loggerLog(this->logger, LOGGER_INFO, "connection closed...");
  28 + serverCloseConn(this, i);
  29 + break;
32 30
33   - default:
34   - break;
35   - }
36   - }
  31 + default:
  32 + break;
37 33 }
38   -
  34 +
39 35 return 0;
40 36 }
41 37
... ...
... ... @@ -3,6 +3,7 @@
3 3 #include <stdlib.h> /* for exit */
4 4 #include <errno.h> /* for errno */
5 5 #include <unistd.h>
  6 +#include <time.h>
6 7
7 8 #include "server.h"
8 9 #include "socket.h"
... ... @@ -42,64 +43,100 @@ serverRun(Server this)
42 43 */
43 44 while (!doShutdown) /* until error or signal */
44 45 {
45   - int events;
  46 + int events;
  47 + unsigned int i;
46 48
47   - /**
48   - * @TODO take return value of poll into account with
49   - * further handling!
50   - */
51 49 events = serverPoll(this);
52 50 if (doShutdown) break;
53 51
54   - /**
55   - * handle accept
56   - */
57   - serverHandleAccept(this);
58   -
59   - /**
60   - * handle reads
61   - */
62   - serverRead(this);
63   -
64   - /**
65   - * do some other processing
66   - * @TODO: actually this will hard assume that our stream reader
67   - * is a http parser and it has its queue...think about more
68   - * generalizing here.
69   - */
70   - {
71   - int i;
72   -
73   - for (i=1; i<this->nfds; i++) {
74   - int j;
75   - HttpRequestQueue queue =
76   - ((HttpRequestParser)(this->conns)[i].reader)->request_queue;
77   -
78   - for (j=0; j<queue->nrequests; j++) {
79   - int k;
80   - HttpRequest request = queue->requests[j];
81   -
82   - printf("method: %s\n", request->method);
83   - printf("uri: %s\n", request->uri);
84   - printf("version: %s\n", request->http_version);
85   - puts("");
86   -
87   - for (k=0; k<128; k++) {
88   - if (NULL == (request->header)[k].name) break;
89   - printf("header-name: %s\n", (request->header)[k].name);
90   - printf("header-value: %s\n", (request->header)[k].value);
91   - }
  52 + for (i=0; i < events; i++) {
  53 + int fd = (this->fds)[i].fd;
  54 + //int nreads = 0, nwrites = 0;
92 55
93   - delete(&request);
  56 + if (0 != ((this->fds)[i].revents & POLLIN)) {
  57 + /**
  58 + * handle accept
  59 + */
  60 + if (this->sock->handle == (this->fds)[i].fd) {
  61 + serverHandleAccept(this);
94 62 }
95   - queue->nrequests = 0;
96   - }
97   - }
98 63
  64 + /**
  65 + * handle reads
  66 + */
  67 + else {
  68 + serverRead(this, i);
  69 +
  70 + /**
  71 + * do some other processing
  72 + * @TODO: actually this will hard assume that our stream reader
  73 + * is a http parser and it has its queue...think about more
  74 + * generalizing here.
  75 + */
  76 + {
  77 + int j;
  78 + HttpRequestQueue queue =
  79 + ((HttpRequestParser)(this->conns)[fd].reader)->request_queue;
  80 +
  81 + for (j=0; j<queue->nrequests; j++) {
  82 + HttpRequest request = queue->requests[j];
  83 +
  84 + /**
  85 + * @TODO: for now simply remove request and send not found.
  86 + * Make this sane.
  87 + */
  88 + delete(&request);
  89 +
  90 + /**
  91 + * @TODO: the complete response stuff have to be removed here.
  92 + */
  93 + time_t t;
  94 + struct tm * tmp;
  95 + char timestr[200];
  96 +
  97 +#define RESP_HEAD "HTTP/1.1 404 Not Found\r\n" \
  98 + "Content-Type: text/html\r\n" \
  99 + "Content-Length: %lu\r\n" \
  100 + "Date: %s\r\n" \
  101 + "Server: testserver\r\n"
  102 +
  103 +#define RESP_DATA "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n" \
  104 + "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" \
  105 + " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" \
  106 + "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n" \
  107 + "<head><title>404 - Not Found</title></head>" \
  108 + "<body><h1>404 - Not Found</h1></body>" \
  109 + "</html>"
  110 +
  111 + t = time(NULL);
  112 + tmp = localtime(&t);
  113 + strftime(timestr, sizeof(timestr), "%a, %d %b %Y %T %Z", tmp);
  114 +
  115 + /**
  116 + * @TODO: just to send an answer and be able to make some
  117 + * apache benchs i do it here...this definetly MUST BE moved
  118 + */
  119 + sprintf((this->conns)[fd].wbuf, RESP_HEAD "\r\n" RESP_DATA, sizeof(RESP_DATA), timestr);
  120 + (this->fds)[i].events = (this->fds)[i].events | POLLOUT;
  121 + }
  122 +
  123 + queue->nrequests = 0;
  124 + }
  125 + }
  126 + }
99 127
100   - /**
101   - * handle writes
102   - */
  128 + /**
  129 + * handle writes
  130 + */
  131 + if (0 != ((this->fds)[i].revents & POLLOUT)) {
  132 + write(
  133 + (this->fds)[i].fd,
  134 + (this->conns)[fd].wbuf,
  135 + strlen((this->conns)[fd].wbuf));
  136 + (this->fds)[i].events = (this->fds)[i].events & ~POLLOUT;
  137 + serverCloseConn(this, i);
  138 + }
  139 + }
103 140 }
104 141 }
105 142
... ...
... ... @@ -21,7 +21,14 @@ ctor(void * _this, va_list * params)
21 21 loggerLog(this->log, LOGGER_CRIT,
22 22 "error opening socket: %s - service terminated",
23 23 strerror(errno));
24   - exit(EXIT_FAILURE);
  24 + //exit(EXIT_FAILURE);
  25 + /**
  26 + * @TODO: uhhhh, here we are leaking memory the socket is not
  27 + * initialized correctly and no one notices...
  28 + * Think about a way to prevent this.
  29 + * Well maybe we notice in server....
  30 + */
  31 + return;
25 32 }
26 33
27 34 /* Make the socket REUSE a TIME_WAIT socket */
... ...
... ... @@ -22,7 +22,7 @@ socketAccept(Sock this, char remoteAddr[16])
22 22 sock->handle = accept(this->handle, (struct sockaddr *) &(sock->addr), &len);
23 23 if (-1 == sock->handle) {
24 24 loggerLog(this->log, LOGGER_WARNING,
25   - "error acception connection: %s", strerror(errno));
  25 + "error accepting connection: %s", strerror(errno));
26 26 } else {
27 27 loggerLog(this->log, LOGGER_INFO,
28 28 "handling client %s\n", inet_ntoa((sock->addr).sin_addr));
... ...
... ... @@ -16,6 +16,7 @@ main()
16 16 Logger logger = new(LoggerStderr, LOGGER_INFO);
17 17 HttpRequestParser parser = new(HttpRequestParser);
18 18 Server server = new(Server, logger, parser, 11212, SOMAXCONN);
  19 + //Server server = new(Server, logger, parser, 11212, 20);
19 20
20 21 init_signals();
21 22 serverRun(server);
... ...
Please register or login to post a comment