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 | 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