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