Showing
14 changed files
with
388 additions
and
240 deletions
1 | +2012-02-09 22:34:32 +0100 Georg Hopp | ||
2 | + | ||
3 | + * start split of request parser (HEAD, master) | ||
4 | + | ||
1 | 2012-02-09 11:44:17 +0100 Georg Hopp | 5 | 2012-02-09 11:44:17 +0100 Georg Hopp |
2 | 6 | ||
3 | - * no more request body debig output (HEAD, master) | 7 | + * no more request body debig output (origin/master, origin/HEAD) |
4 | 8 | ||
5 | 2012-02-09 11:32:28 +0100 Georg Hopp | 9 | 2012-02-09 11:32:28 +0100 Georg Hopp |
6 | 10 |
include/http/header.h
0 → 100644
1 | +#ifndef __HTTP_HEADER_H__ | ||
2 | +#define __HTTP_HEADER_H__ | ||
3 | + | ||
4 | +#include "class.h" | ||
5 | + | ||
6 | +CLASS(HttpHeader) { | ||
7 | + unsigned long hash; | ||
8 | + char * name; | ||
9 | + char * value; | ||
10 | +}; | ||
11 | + | ||
12 | +HttpHeader httpHeaderParse(char * line); // @INFO: destructive | ||
13 | +void httpHeaderSort(const HttpHeader [], int); | ||
14 | +char * httpHeaderGet(const HttpHeader [], int, const char *); | ||
15 | + | ||
16 | +#endif // __HTTP_HEADER_H__ | ||
17 | + | ||
18 | +// vim: set ts=4 sw=4: |
@@ -2,21 +2,18 @@ | @@ -2,21 +2,18 @@ | ||
2 | #define __HTTP_REQUEST_H__ | 2 | #define __HTTP_REQUEST_H__ |
3 | 3 | ||
4 | #include "class.h" | 4 | #include "class.h" |
5 | +#include "http/header.h" | ||
5 | 6 | ||
6 | CLASS(HttpRequest) { | 7 | CLASS(HttpRequest) { |
7 | - char * http_version; | ||
8 | - char * uri; | ||
9 | - char * method; | 8 | + char * method; |
9 | + char * uri; | ||
10 | + char * version; | ||
10 | 11 | ||
11 | - struct HttpRequestHeader { | ||
12 | - unsigned long hash; | ||
13 | - char * name; | ||
14 | - char * value; | ||
15 | - } header[128]; | ||
16 | - int nheader; | 12 | + HttpHeader header[128]; |
13 | + int nheader; | ||
17 | 14 | ||
18 | - char * body; | ||
19 | - int nbody; | 15 | + char * body; |
16 | + int nbody; | ||
20 | }; | 17 | }; |
21 | 18 | ||
22 | char * | 19 | char * |
include/http/response.h
0 → 100644
1 | +#ifndef __HTTP_RESPONSE_H__ | ||
2 | +#define __HTTP_RESPONSE_H__ | ||
3 | + | ||
4 | +#include "class.h" | ||
5 | + | ||
6 | +CLASS(HttpResponse) { | ||
7 | + char * http_version; | ||
8 | + char * status; | ||
9 | + char * reson; | ||
10 | + | ||
11 | + HttpHeader header[128]; | ||
12 | + int nheader; | ||
13 | + | ||
14 | + char * body; | ||
15 | + int nbody; | ||
16 | +}; | ||
17 | + | ||
18 | +char * | ||
19 | +httpRequestHeaderGet(HttpRequest this, const char * name); | ||
20 | + | ||
21 | +#endif /* __HTTP_RESPONSE_H__ */ | ||
22 | + | ||
23 | +// vim: set ts=4 sw=4: |
@@ -5,7 +5,10 @@ CLASS = class.c interface.c interface/class.c | @@ -5,7 +5,10 @@ CLASS = class.c interface.c interface/class.c | ||
5 | SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c | 5 | SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c |
6 | SERVER = server.c server/run.c server/close_conn.c | 6 | SERVER = server.c server/run.c server/close_conn.c |
7 | LOGGER = logger.c logger/stderr.c logger/syslog.c interface/logger.c | 7 | LOGGER = logger.c logger/stderr.c logger/syslog.c interface/logger.c |
8 | -HTTP = interface/stream_reader.c http/request_parser.c http/request.c http/request_queue.c http/request/header_get.c | 8 | +HTTP = interface/stream_reader.c http/request/parser.c http/request.c \ |
9 | + http/request/queue.c http/header.c http/header/get.c \ | ||
10 | + http/header/sort.c http/request/parser/get_header.c \ | ||
11 | + http/request/parser/parse.c http/request/parser/get_request_line.c | ||
9 | 12 | ||
10 | AM_CFLAGS = -Wall -I ../include/ | 13 | AM_CFLAGS = -Wall -I ../include/ |
11 | 14 |
src/http/header.c
0 → 100644
1 | +#include <stdlib.h> | ||
2 | +#include <string.h> | ||
3 | +#include <ctype.h> | ||
4 | + | ||
5 | +#include "class.h" | ||
6 | +#include "interface/class.h" | ||
7 | + | ||
8 | +#include "http/header.h" | ||
9 | + | ||
10 | +/** | ||
11 | + * SDBM hashing algorithm: | ||
12 | + * | ||
13 | + * this algorithm was created for sdbm (a public-domain reimplementation of | ||
14 | + * ndbm) database library. it was found to do well in scrambling bits, | ||
15 | + * causing better distribution of the keys and fewer splits. it also happens | ||
16 | + * to be a good general hashing function with good distribution. the actual | ||
17 | + * function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below | ||
18 | + * is the faster version used in gawk. [there is even a faster, duff-device | ||
19 | + * version] the magic constant 65599 was picked out of thin air while | ||
20 | + * experimenting with different constants, and turns out to be a prime. this | ||
21 | + * is one of the algorithms used in berkeley db (see sleepycat) and elsewhere. | ||
22 | + */ | ||
23 | +static | ||
24 | +inline | ||
25 | +unsigned long | ||
26 | +sdbm(unsigned char * str) | ||
27 | +{ | ||
28 | + unsigned long hash = 0; | ||
29 | + int c; | ||
30 | + | ||
31 | + while ((c = tolower(*str++))) | ||
32 | + hash = c + (hash << 6) + (hash << 16) - hash; | ||
33 | + | ||
34 | + return hash; | ||
35 | +} | ||
36 | + | ||
37 | +static | ||
38 | +void | ||
39 | +ctor(void * _this, va_list * params) { | ||
40 | + HttpHeader this = _this; | ||
41 | + char * name; | ||
42 | + char * value; | ||
43 | + | ||
44 | + name = va_arg(* params, char *); | ||
45 | + value = va_arg(* params, char *); | ||
46 | + | ||
47 | + this->name = malloc(strlen(name) + 1); | ||
48 | + strcpy(this->name, name); | ||
49 | + | ||
50 | + this->hash = sdbm((unsigned char *)name); | ||
51 | + | ||
52 | + this->value = malloc(strlen(value) + 1); | ||
53 | + strcpy(this->value, value); | ||
54 | +} | ||
55 | + | ||
56 | +static | ||
57 | +void | ||
58 | +dtor(void * _this) | ||
59 | +{ | ||
60 | + HttpHeader this = _this; | ||
61 | + | ||
62 | + free(this->name); | ||
63 | + free(this->value); | ||
64 | +} | ||
65 | + | ||
66 | +INIT_IFACE(Class, ctor, dtor, NULL); | ||
67 | +CREATE_CLASS(HttpHeader, NULL, IFACE(Class)); | ||
68 | + | ||
69 | +// vim: set ts=4 sw=4: |
src/http/header/get.c
0 → 100644
1 | +#include <stdlib.h> | ||
2 | +#include <ctype.h> | ||
3 | + | ||
4 | +#include "http/header.h" | ||
5 | + | ||
6 | +static | ||
7 | +inline | ||
8 | +unsigned long | ||
9 | +sdbm(const unsigned char * str) | ||
10 | +{ | ||
11 | + unsigned long hash = 0; | ||
12 | + int c; | ||
13 | + | ||
14 | + while ((c = tolower(*str++))) | ||
15 | + hash = c + (hash << 6) + (hash << 16) - hash; | ||
16 | + | ||
17 | + return hash; | ||
18 | +} | ||
19 | + | ||
20 | +static | ||
21 | +inline | ||
22 | +int | ||
23 | +comp (const void * _a, const void * _b) | ||
24 | +{ | ||
25 | + unsigned long a = *(unsigned long *)_a; | ||
26 | + const HttpHeader b = *(const HttpHeader *)_b; | ||
27 | + return (a < b->hash)? -1 : (a > b->hash)? 1 : 0; | ||
28 | +} | ||
29 | + | ||
30 | +char * | ||
31 | +httpHeaderGet(const HttpHeader header[], int nheader, const char * name) | ||
32 | +{ | ||
33 | + unsigned long hash = sdbm((unsigned char *)name); | ||
34 | + HttpHeader found; | ||
35 | + | ||
36 | + found = bsearch(&hash, header, nheader, sizeof(HttpHeader), comp); | ||
37 | + | ||
38 | + return (NULL != found)? found->value : NULL; | ||
39 | +} | ||
40 | + | ||
41 | +// vim: set ts=4 sw=4: |
src/http/header/sort.c
0 → 100644
1 | +#include "http/header.h" | ||
2 | + | ||
3 | +static | ||
4 | +inline | ||
5 | +int | ||
6 | +comp (const void * _a, const void * _b) | ||
7 | +{ | ||
8 | + const HttpHeader a = *(const HttpHeader *)_a; | ||
9 | + const HttpHeader b = *(const HttpHeader *)_b; | ||
10 | + return (a->hash < b->hash)? -1 : (a->hash > b->hash)? 1 : 0; | ||
11 | +} | ||
12 | + | ||
13 | +void | ||
14 | +httpHeaderSort(const HttpHeader header[], int nheader) | ||
15 | +{ | ||
16 | + qsort(header, nheader, sizeof(HttpHeader), comp); | ||
17 | +} | ||
18 | + | ||
19 | +// vim: set ts=4 sw=4: |
@@ -26,13 +26,13 @@ dtor(void * _this) | @@ -26,13 +26,13 @@ dtor(void * _this) | ||
26 | HttpRequest this = _this; | 26 | HttpRequest this = _this; |
27 | int i; | 27 | int i; |
28 | 28 | ||
29 | - _free((void **)&(this->http_version)); | 29 | + _free((void **)&(this->version)); |
30 | _free((void **)&(this->uri)); | 30 | _free((void **)&(this->uri)); |
31 | _free((void **)&(this->method)); | 31 | _free((void **)&(this->method)); |
32 | 32 | ||
33 | for (i=0; i<128; i++) { | 33 | for (i=0; i<128; i++) { |
34 | - _free((void **)&((this->header)[i].name)); | ||
35 | - _free((void **)&((this->header)[i].value)); | 34 | + if (NULL == (this->header)[i]) break; |
35 | + delete(&(this->header)[i]); | ||
36 | } | 36 | } |
37 | 37 | ||
38 | _free((void **)&(this->body)); | 38 | _free((void **)&(this->body)); |
1 | -#include <stdlib.h> | ||
2 | #include <string.h> | 1 | #include <string.h> |
3 | #include <stdlib.h> | 2 | #include <stdlib.h> |
4 | -#include <stdio.h> | ||
5 | -#include <unistd.h> | ||
6 | -#include <ctype.h> | ||
7 | #include <sys/types.h> | 3 | #include <sys/types.h> |
8 | 4 | ||
9 | #include "class.h" | 5 | #include "class.h" |
@@ -13,9 +9,7 @@ | @@ -13,9 +9,7 @@ | ||
13 | #include "http/request.h" | 9 | #include "http/request.h" |
14 | #include "http/request_queue.h" | 10 | #include "http/request_queue.h" |
15 | 11 | ||
16 | -static | ||
17 | -void | ||
18 | -httpRequestParserParse(HttpRequestParser); | 12 | +void httpRequestParserParse(HttpRequestParser); |
19 | 13 | ||
20 | static | 14 | static |
21 | void | 15 | void |
@@ -103,221 +97,4 @@ INIT_IFACE(Class, ctor, dtor, _clone); | @@ -103,221 +97,4 @@ INIT_IFACE(Class, ctor, dtor, _clone); | ||
103 | INIT_IFACE(StreamReader, get_data); | 97 | INIT_IFACE(StreamReader, get_data); |
104 | CREATE_CLASS(HttpRequestParser, NULL, IFACE(Class), IFACE(StreamReader)); | 98 | CREATE_CLASS(HttpRequestParser, NULL, IFACE(Class), IFACE(StreamReader)); |
105 | 99 | ||
106 | -static | ||
107 | -inline | ||
108 | -char * | ||
109 | -httpRequestLineGet(char ** data) | ||
110 | -{ | ||
111 | - char * line_end = strstr(*data, "\r\n"); | ||
112 | - char * ret = *data; | ||
113 | - | ||
114 | - if (NULL == line_end) { | ||
115 | - return NULL; | ||
116 | - } | ||
117 | - | ||
118 | - *line_end = 0; | ||
119 | - *data = line_end + 2; | ||
120 | - | ||
121 | - return ret; | ||
122 | -} | ||
123 | - | ||
124 | -static | ||
125 | -inline | ||
126 | -void | ||
127 | -httpRequestSkip(char ** data) | ||
128 | -{ | ||
129 | - for (; 0 != **data && ! isalpha(**data); (*data)++); | ||
130 | -} | ||
131 | - | ||
132 | -/** | ||
133 | - * SDBM hashing algorithm: | ||
134 | - * | ||
135 | - * this algorithm was created for sdbm (a public-domain reimplementation of | ||
136 | - * ndbm) database library. it was found to do well in scrambling bits, | ||
137 | - * causing better distribution of the keys and fewer splits. it also happens | ||
138 | - * to be a good general hashing function with good distribution. the actual | ||
139 | - * function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below | ||
140 | - * is the faster version used in gawk. [there is even a faster, duff-device | ||
141 | - * version] the magic constant 65599 was picked out of thin air while | ||
142 | - * experimenting with different constants, and turns out to be a prime. this | ||
143 | - * is one of the algorithms used in berkeley db (see sleepycat) and elsewhere. | ||
144 | - */ | ||
145 | -static | ||
146 | -inline | ||
147 | -unsigned long | ||
148 | -sdbm(unsigned char * str) | ||
149 | -{ | ||
150 | - unsigned long hash = 0; | ||
151 | - int c; | ||
152 | - | ||
153 | - while ((c = tolower(*str++))) | ||
154 | - hash = c + (hash << 6) + (hash << 16) - hash; | ||
155 | - | ||
156 | - return hash; | ||
157 | -} | ||
158 | - | ||
159 | -static | ||
160 | -inline | ||
161 | -int | ||
162 | -comp (const void * _a, const void * _b) | ||
163 | -{ | ||
164 | - const struct HttpRequestHeader * a = _a; | ||
165 | - const struct HttpRequestHeader * b = _b; | ||
166 | - return (a->hash < b->hash)? -1 : (a->hash > b->hash)? 1 : 0; | ||
167 | -} | ||
168 | - | ||
169 | -static | ||
170 | -void | ||
171 | -httpRequestParserParse(HttpRequestParser this) | ||
172 | -{ | ||
173 | - static HttpRequest request = NULL; | ||
174 | - static char * data; // static pointer to unprocessed data | ||
175 | - char * line; | ||
176 | - int cont = 1; | ||
177 | - static int header_idx; | ||
178 | - | ||
179 | - while(cont) { | ||
180 | - switch(this->state) { | ||
181 | - case HTTP_REQUEST_GARBAGE: | ||
182 | - data = this->buffer; // initialize static pointer | ||
183 | - httpRequestSkip(&data); | ||
184 | - request = new(HttpRequest); | ||
185 | - | ||
186 | - this->state = HTTP_REQUEST_START; | ||
187 | - break; | ||
188 | - | ||
189 | - case HTTP_REQUEST_START: | ||
190 | - if (NULL == (line = httpRequestLineGet(&data))) { | ||
191 | - cont = 0; | ||
192 | - break; | ||
193 | - } | ||
194 | - | ||
195 | - { | ||
196 | - char * delim = strchr(line, ' '); | ||
197 | - | ||
198 | - if (NULL != delim) { | ||
199 | - *delim = 0; | ||
200 | - request->method = malloc(strlen(line) + 1); | ||
201 | - strcpy(request->method, line); | ||
202 | - line = delim + 1; | ||
203 | - | ||
204 | - for (; *line == ' ' && *line != 0; line++); | ||
205 | - | ||
206 | - if (0 != *line) { | ||
207 | - delim = strchr(line, ' '); | ||
208 | - | ||
209 | - if (NULL != delim) { | ||
210 | - *delim = 0; | ||
211 | - request->uri = malloc(strlen(line) + 1); | ||
212 | - strcpy(request->uri, line); | ||
213 | - line = delim + 1; | ||
214 | - | ||
215 | - for (; *line == ' ' && *line != 0; line++); | ||
216 | - | ||
217 | - if (0 != *line) { | ||
218 | - request->http_version = malloc(strlen(line) + 1); | ||
219 | - strcpy(request->http_version, line); | ||
220 | - } | ||
221 | - } | ||
222 | - } | ||
223 | - } | ||
224 | - } | ||
225 | - | ||
226 | - header_idx = 0; | ||
227 | - this->state = HTTP_REQUEST_REQUEST_LINE_DONE; | ||
228 | - break; | ||
229 | - | ||
230 | - case HTTP_REQUEST_REQUEST_LINE_DONE: | ||
231 | - if (NULL == (line = httpRequestLineGet(&data))) { | ||
232 | - cont = 0; | ||
233 | - break; | ||
234 | - } | ||
235 | - | ||
236 | - if (0 == strlen(line)) { | ||
237 | - this->state = HTTP_REQUEST_HEADERS_DONE; | ||
238 | - break; | ||
239 | - } | ||
240 | - | ||
241 | - { | ||
242 | - char * delim = strchr(line, ':'); | ||
243 | - | ||
244 | - *delim = 0; | ||
245 | - (request->header)[header_idx].name = malloc(strlen(line) + 1); | ||
246 | - strcpy((request->header)[header_idx].name, line); | ||
247 | - (request->header)[header_idx].hash = sdbm((unsigned char *)line); | ||
248 | - | ||
249 | - line = delim + 1; | ||
250 | - for (; *line == ' ' && *line != 0; line++); | ||
251 | - | ||
252 | - (request->header)[header_idx].value = malloc(strlen(line) + 1); | ||
253 | - strcpy((request->header)[header_idx].value, line); | ||
254 | - | ||
255 | - header_idx++; | ||
256 | - request->nheader++; | ||
257 | - } | ||
258 | - | ||
259 | - break; | ||
260 | - | ||
261 | - case HTTP_REQUEST_HEADERS_DONE: | ||
262 | - /** | ||
263 | - * @TODO: here comes the body handling | ||
264 | - */ | ||
265 | - qsort( | ||
266 | - request->header, | ||
267 | - request->nheader, | ||
268 | - sizeof(struct HttpRequestHeader), | ||
269 | - comp); | ||
270 | - | ||
271 | - { | ||
272 | - char * bodylen; | ||
273 | - | ||
274 | - bodylen = httpRequestHeaderGet(request, "Content-Length"); | ||
275 | - | ||
276 | - if (NULL != bodylen) { | ||
277 | - request->nbody = atoi(bodylen); | ||
278 | - request->body = calloc(1, request->nbody + 1); | ||
279 | - memcpy(request->body, data, request->nbody); | ||
280 | - data += request->nbody; | ||
281 | - } | ||
282 | - } | ||
283 | - | ||
284 | - this->state = HTTP_REQUEST_DONE; | ||
285 | - break; | ||
286 | - | ||
287 | - case HTTP_REQUEST_DONE: | ||
288 | - /** | ||
289 | - * enqueue current request | ||
290 | - */ | ||
291 | - this->request_queue->requests[(this->request_queue->nrequests)++] = | ||
292 | - request; | ||
293 | - | ||
294 | - /** | ||
295 | - * remove processed stuff from input buffer. | ||
296 | - */ | ||
297 | - memmove(this->buffer, | ||
298 | - data, | ||
299 | - this->buffer_used - (data - this->buffer) + 1); | ||
300 | - | ||
301 | - this->buffer_used -= data - this->buffer; | ||
302 | - | ||
303 | - /** | ||
304 | - * dont continue loop if input buffer is empty | ||
305 | - */ | ||
306 | - if (0 == this->buffer_used) { | ||
307 | - cont = 0; | ||
308 | - } | ||
309 | - | ||
310 | - /** | ||
311 | - * prepare for next request | ||
312 | - */ | ||
313 | - this->state = HTTP_REQUEST_GARBAGE; | ||
314 | - | ||
315 | - break; | ||
316 | - | ||
317 | - default: | ||
318 | - break; | ||
319 | - } | ||
320 | - } | ||
321 | -} | ||
322 | - | ||
323 | // vim: set ts=4 sw=4: | 100 | // vim: set ts=4 sw=4: |
src/http/request/parser/get_header.c
0 → 100644
1 | +#include "class.h" | ||
2 | +#include "interface/class.h" | ||
3 | +#include "http/header.h" | ||
4 | +#include "http/request.h" | ||
5 | + | ||
6 | +void | ||
7 | +httpRequestParserGetHeader(HttpRequest request, char * line) | ||
8 | +{ | ||
9 | + char * name = line; | ||
10 | + char * value = strchr(line, ':'); | ||
11 | + | ||
12 | + *value = 0; | ||
13 | + for (; *value == ' ' && *value != 0; value++); | ||
14 | + | ||
15 | + (request->header)[request->nheader++] = new(HttpHeader, name, value); | ||
16 | +} | ||
17 | + | ||
18 | +// vim: set ts=4 sw=4: |
src/http/request/parser/get_request_line.c
0 → 100644
1 | +#include <string.h> | ||
2 | + | ||
3 | +#include "http/request.h" | ||
4 | + | ||
5 | + | ||
6 | +void | ||
7 | +httpRequestParserGetRequestLine(HttpRequest request, char * line) | ||
8 | +{ | ||
9 | + char * method, * uri, * version; | ||
10 | + | ||
11 | + method = line; | ||
12 | + | ||
13 | + uri = strchr(line, ' '); | ||
14 | + *uri++ = 0; | ||
15 | + for (; *uri == ' ' && *uri != 0; uri++); | ||
16 | + | ||
17 | + version = strchr(uri, ' '); | ||
18 | + *version++ = 0; | ||
19 | + for (; *version == ' ' && *version != 0; version++); | ||
20 | + | ||
21 | + request->method = malloc(strlen(method) + 1); | ||
22 | + strcpy(request->method, method); | ||
23 | + request->uri = malloc(strlen(uri) + 1); | ||
24 | + strcpy(request->uri, uri); | ||
25 | + request->version = malloc(strlen(version) + 1); | ||
26 | + strcpy(request->version, method); | ||
27 | +} | ||
28 | + | ||
29 | +// vim: set ts=4 sw=4: |
src/http/request/parser/parse.c
0 → 100644
1 | +#include <stdlib.h> | ||
2 | +#include <string.h> | ||
3 | +#include <unistd.h> | ||
4 | +#include <ctype.h> | ||
5 | + | ||
6 | +#include "http/request_parser.h" | ||
7 | +#include "interface/class.h" | ||
8 | + | ||
9 | + | ||
10 | +#define REMAINS(pars,done) \ | ||
11 | + ((pars)->buffer_used - ((done) - (pars)->buffer)) | ||
12 | + | ||
13 | + | ||
14 | +static | ||
15 | +inline | ||
16 | +char * | ||
17 | +httpRequestParserGetLine(char ** data) | ||
18 | +{ | ||
19 | + char * line_end = strstr(*data, "\r\n"); | ||
20 | + char * ret = *data; | ||
21 | + | ||
22 | + if (NULL == line_end) { | ||
23 | + return NULL; | ||
24 | + } | ||
25 | + | ||
26 | + *line_end = 0; | ||
27 | + *data = line_end + 2; | ||
28 | + | ||
29 | + return ret; | ||
30 | +} | ||
31 | + | ||
32 | +static | ||
33 | +inline | ||
34 | +void | ||
35 | +httpRequestSkip(char ** data) | ||
36 | +{ | ||
37 | + for (; 0 != **data && ! isalpha(**data); (*data)++); | ||
38 | +} | ||
39 | + | ||
40 | +void httpRequestParserGetRequestLine(HttpRequest, char *); | ||
41 | + | ||
42 | +void | ||
43 | +httpRequestParserParse(HttpRequestParser this) | ||
44 | +{ | ||
45 | + static HttpRequest request = NULL; | ||
46 | + static char * data; // static pointer to unprocessed data | ||
47 | + char * line; | ||
48 | + int cont = 1; | ||
49 | + | ||
50 | + while(cont) { | ||
51 | + switch(this->state) { | ||
52 | + case HTTP_REQUEST_GARBAGE: | ||
53 | + data = this->buffer; // initialize static pointer | ||
54 | + httpRequestSkip(&data); | ||
55 | + request = new(HttpRequest); | ||
56 | + | ||
57 | + this->state = HTTP_REQUEST_START; | ||
58 | + break; | ||
59 | + | ||
60 | + case HTTP_REQUEST_START: | ||
61 | + if (NULL == (line = httpRequestParserGetLine(&data))) { | ||
62 | + cont = 0; | ||
63 | + break; | ||
64 | + } | ||
65 | + | ||
66 | + httpRequestParserGetRequestLine(request, line); | ||
67 | + | ||
68 | + this->state = HTTP_REQUEST_REQUEST_LINE_DONE; | ||
69 | + break; | ||
70 | + | ||
71 | + case HTTP_REQUEST_REQUEST_LINE_DONE: | ||
72 | + if (NULL == (line = httpRequestParserGetLine(&data))) { | ||
73 | + cont = 0; | ||
74 | + break; | ||
75 | + } | ||
76 | + | ||
77 | + if (0 == strlen(line)) { | ||
78 | + this->state = HTTP_REQUEST_HEADERS_DONE; | ||
79 | + break; | ||
80 | + } | ||
81 | + | ||
82 | + httpRequestParserGetHeader(request, line); | ||
83 | + break; | ||
84 | + | ||
85 | + case HTTP_REQUEST_HEADERS_DONE: | ||
86 | + httpHeaderSort(request->header, request->nheader); | ||
87 | + | ||
88 | + { | ||
89 | + char * nbody; | ||
90 | + | ||
91 | + if (0 == request->nbody) { | ||
92 | + nbody = httpHeaderGet( | ||
93 | + request->header, | ||
94 | + request->nheader, | ||
95 | + "Content-Length"); | ||
96 | + | ||
97 | + if (NULL == nbody) { | ||
98 | + this->state = HTTP_REQUEST_DONE; | ||
99 | + break; | ||
100 | + } | ||
101 | + else { | ||
102 | + request->nbody = atoi(nbody); | ||
103 | + } | ||
104 | + } | ||
105 | + | ||
106 | + if (REMAINS(this, data) >= request->nbody) { | ||
107 | + request->body = calloc(1, request->nbody + 1); | ||
108 | + memcpy(request->body, data, request->nbody); | ||
109 | + data += request->nbody; | ||
110 | + this->state = HTTP_REQUEST_DONE; | ||
111 | + } | ||
112 | + } | ||
113 | + | ||
114 | + break; | ||
115 | + | ||
116 | + case HTTP_REQUEST_DONE: | ||
117 | + /** | ||
118 | + * enqueue current request | ||
119 | + */ | ||
120 | + this->request_queue->requests[(this->request_queue->nrequests)++] = | ||
121 | + request; | ||
122 | + | ||
123 | + /** | ||
124 | + * remove processed stuff from input buffer. | ||
125 | + */ | ||
126 | + memmove(this->buffer, data, REMAINS(this, data)); | ||
127 | + | ||
128 | + this->buffer_used -= data - this->buffer; | ||
129 | + | ||
130 | + /** | ||
131 | + * dont continue loop if input buffer is empty | ||
132 | + */ | ||
133 | + if (0 == this->buffer_used) { | ||
134 | + cont = 0; | ||
135 | + } | ||
136 | + | ||
137 | + /** | ||
138 | + * prepare for next request | ||
139 | + */ | ||
140 | + this->state = HTTP_REQUEST_GARBAGE; | ||
141 | + | ||
142 | + break; | ||
143 | + | ||
144 | + default: | ||
145 | + break; | ||
146 | + } | ||
147 | + } | ||
148 | +} | ||
149 | + | ||
150 | +// vim: set ts=4 sw=4: |
Please
register
or
login
to post a comment