Commit 228b1d0d29b12379a20ec0d950fd76d3b0b1021d
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.
Showing
11 changed files
with
193 additions
and
114 deletions
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 | 2012-02-07 13:41:49 +0100 Georg Hopp | 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 | 2012-02-07 11:12:30 +0100 Georg Hopp | 13 | 2012-02-07 11:12:30 +0100 Georg Hopp |
6 | 14 |
@@ -21,21 +21,28 @@ | @@ -21,21 +21,28 @@ | ||
21 | MOVE_SIZE(sizeof(((server)->conns)[0]),(idx))) | 21 | MOVE_SIZE(sizeof(((server)->conns)[0]),(idx))) |
22 | 22 | ||
23 | 23 | ||
24 | -typedef void (*server_read_hook)(const char *, size_t); | ||
25 | - | ||
26 | CLASS(Server) { | 24 | CLASS(Server) { |
27 | Logger logger; | 25 | Logger logger; |
28 | Sock sock; | 26 | Sock sock; |
29 | void * reader; | 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 | nfds_t nfds; | 37 | nfds_t nfds; |
38 | + nfds_t ndel; | ||
32 | struct pollfd fds[POLL_FD_NSIZE]; | 39 | struct pollfd fds[POLL_FD_NSIZE]; |
33 | 40 | ||
34 | struct { | 41 | struct { |
35 | Sock sock; | 42 | Sock sock; |
36 | void * reader; | 43 | void * reader; |
37 | 44 | ||
38 | - char * wbuf; | 45 | + char wbuf[2048]; |
39 | char * rbuf; | 46 | char * rbuf; |
40 | unsigned int rpos; | 47 | unsigned int rpos; |
41 | unsigned int wpos; | 48 | unsigned int wpos; |
@@ -142,7 +142,6 @@ httpRequestParserParse(HttpRequestParser this) | @@ -142,7 +142,6 @@ httpRequestParserParse(HttpRequestParser this) | ||
142 | while(cont) { | 142 | while(cont) { |
143 | switch(this->state) { | 143 | switch(this->state) { |
144 | case HTTP_REQUEST_GARBAGE: | 144 | case HTTP_REQUEST_GARBAGE: |
145 | - puts("==skip garbage=="); | ||
146 | data = this->buffer; // initialize static pointer | 145 | data = this->buffer; // initialize static pointer |
147 | httpRequestSkip(&data); | 146 | httpRequestSkip(&data); |
148 | request = new(HttpRequest); | 147 | request = new(HttpRequest); |
@@ -151,7 +150,6 @@ httpRequestParserParse(HttpRequestParser this) | @@ -151,7 +150,6 @@ httpRequestParserParse(HttpRequestParser this) | ||
151 | break; | 150 | break; |
152 | 151 | ||
153 | case HTTP_REQUEST_START: | 152 | case HTTP_REQUEST_START: |
154 | - puts("==request line=="); | ||
155 | if (NULL == (line = httpRequestLineGet(&data))) { | 153 | if (NULL == (line = httpRequestLineGet(&data))) { |
156 | cont = 0; | 154 | cont = 0; |
157 | break; | 155 | break; |
@@ -193,7 +191,6 @@ httpRequestParserParse(HttpRequestParser this) | @@ -193,7 +191,6 @@ httpRequestParserParse(HttpRequestParser this) | ||
193 | break; | 191 | break; |
194 | 192 | ||
195 | case HTTP_REQUEST_REQUEST_LINE_DONE: | 193 | case HTTP_REQUEST_REQUEST_LINE_DONE: |
196 | - puts("==read header=="); | ||
197 | if (NULL == (line = httpRequestLineGet(&data))) { | 194 | if (NULL == (line = httpRequestLineGet(&data))) { |
198 | cont = 0; | 195 | cont = 0; |
199 | break; | 196 | break; |
@@ -222,8 +219,6 @@ httpRequestParserParse(HttpRequestParser this) | @@ -222,8 +219,6 @@ httpRequestParserParse(HttpRequestParser this) | ||
222 | break; | 219 | break; |
223 | 220 | ||
224 | case HTTP_REQUEST_HEADERS_DONE: | 221 | case HTTP_REQUEST_HEADERS_DONE: |
225 | - puts("==headers done=="); | ||
226 | - | ||
227 | /** | 222 | /** |
228 | * @TODO: here comes the body handling | 223 | * @TODO: here comes the body handling |
229 | */ | 224 | */ |
@@ -231,8 +226,6 @@ httpRequestParserParse(HttpRequestParser this) | @@ -231,8 +226,6 @@ httpRequestParserParse(HttpRequestParser this) | ||
231 | break; | 226 | break; |
232 | 227 | ||
233 | case HTTP_REQUEST_DONE: | 228 | case HTTP_REQUEST_DONE: |
234 | - puts("==request done=="); | ||
235 | - | ||
236 | /** | 229 | /** |
237 | * enqueue current request | 230 | * enqueue current request |
238 | */ | 231 | */ |
@@ -6,10 +6,14 @@ | @@ -6,10 +6,14 @@ | ||
6 | void | 6 | void |
7 | serverCloseConn(Server this, unsigned int i) | 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 | // vim: set ts=4 sw=4: | 19 | // vim: set ts=4 sw=4: |
@@ -2,28 +2,26 @@ static | @@ -2,28 +2,26 @@ static | ||
2 | void | 2 | void |
3 | serverHandleAccept(Server this) | 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 | // vim: set ts=4 sw=4: | 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 | static | 23 | static |
2 | int | 24 | int |
3 | serverPoll(Server this) { | 25 | serverPoll(Server this) { |
4 | int events; | 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 | * wait for handles to become ready | 33 | * wait for handles to become ready |
8 | */ | 34 | */ |
@@ -23,6 +49,8 @@ serverPoll(Server this) { | @@ -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 | return events; | 54 | return events; |
27 | } | 55 | } |
28 | 56 |
1 | static | 1 | static |
2 | int | 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 | return 0; | 35 | return 0; |
40 | } | 36 | } |
41 | 37 |
@@ -3,6 +3,7 @@ | @@ -3,6 +3,7 @@ | ||
3 | #include <stdlib.h> /* for exit */ | 3 | #include <stdlib.h> /* for exit */ |
4 | #include <errno.h> /* for errno */ | 4 | #include <errno.h> /* for errno */ |
5 | #include <unistd.h> | 5 | #include <unistd.h> |
6 | +#include <time.h> | ||
6 | 7 | ||
7 | #include "server.h" | 8 | #include "server.h" |
8 | #include "socket.h" | 9 | #include "socket.h" |
@@ -42,64 +43,100 @@ serverRun(Server this) | @@ -42,64 +43,100 @@ serverRun(Server this) | ||
42 | */ | 43 | */ |
43 | while (!doShutdown) /* until error or signal */ | 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 | events = serverPoll(this); | 49 | events = serverPoll(this); |
52 | if (doShutdown) break; | 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,7 +21,14 @@ ctor(void * _this, va_list * params) | ||
21 | loggerLog(this->log, LOGGER_CRIT, | 21 | loggerLog(this->log, LOGGER_CRIT, |
22 | "error opening socket: %s - service terminated", | 22 | "error opening socket: %s - service terminated", |
23 | strerror(errno)); | 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 | /* Make the socket REUSE a TIME_WAIT socket */ | 34 | /* Make the socket REUSE a TIME_WAIT socket */ |
@@ -22,7 +22,7 @@ socketAccept(Sock this, char remoteAddr[16]) | @@ -22,7 +22,7 @@ socketAccept(Sock this, char remoteAddr[16]) | ||
22 | sock->handle = accept(this->handle, (struct sockaddr *) &(sock->addr), &len); | 22 | sock->handle = accept(this->handle, (struct sockaddr *) &(sock->addr), &len); |
23 | if (-1 == sock->handle) { | 23 | if (-1 == sock->handle) { |
24 | loggerLog(this->log, LOGGER_WARNING, | 24 | loggerLog(this->log, LOGGER_WARNING, |
25 | - "error acception connection: %s", strerror(errno)); | 25 | + "error accepting connection: %s", strerror(errno)); |
26 | } else { | 26 | } else { |
27 | loggerLog(this->log, LOGGER_INFO, | 27 | loggerLog(this->log, LOGGER_INFO, |
28 | "handling client %s\n", inet_ntoa((sock->addr).sin_addr)); | 28 | "handling client %s\n", inet_ntoa((sock->addr).sin_addr)); |
@@ -16,6 +16,7 @@ main() | @@ -16,6 +16,7 @@ main() | ||
16 | Logger logger = new(LoggerStderr, LOGGER_INFO); | 16 | Logger logger = new(LoggerStderr, LOGGER_INFO); |
17 | HttpRequestParser parser = new(HttpRequestParser); | 17 | HttpRequestParser parser = new(HttpRequestParser); |
18 | Server server = new(Server, logger, parser, 11212, SOMAXCONN); | 18 | Server server = new(Server, logger, parser, 11212, SOMAXCONN); |
19 | + //Server server = new(Server, logger, parser, 11212, 20); | ||
19 | 20 | ||
20 | init_signals(); | 21 | init_signals(); |
21 | serverRun(server); | 22 | serverRun(server); |
Please
register
or
login
to post a comment