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 | 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 | 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 | 2 | #define __HTTP_REQUEST_H__ |
| 3 | 3 | |
| 4 | 4 | #include "class.h" |
| 5 | +#include "http/header.h" | |
| 5 | 6 | |
| 6 | 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 | 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 | 5 | SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c |
| 6 | 6 | SERVER = server.c server/run.c server/close_conn.c |
| 7 | 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 | 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 | 26 | HttpRequest this = _this; |
| 27 | 27 | int i; |
| 28 | 28 | |
| 29 | - _free((void **)&(this->http_version)); | |
| 29 | + _free((void **)&(this->version)); | |
| 30 | 30 | _free((void **)&(this->uri)); |
| 31 | 31 | _free((void **)&(this->method)); |
| 32 | 32 | |
| 33 | 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 | 38 | _free((void **)&(this->body)); | ... | ... |
| 1 | -#include <stdlib.h> | |
| 2 | 1 | #include <string.h> |
| 3 | 2 | #include <stdlib.h> |
| 4 | -#include <stdio.h> | |
| 5 | -#include <unistd.h> | |
| 6 | -#include <ctype.h> | |
| 7 | 3 | #include <sys/types.h> |
| 8 | 4 | |
| 9 | 5 | #include "class.h" |
| ... | ... | @@ -13,9 +9,7 @@ |
| 13 | 9 | #include "http/request.h" |
| 14 | 10 | #include "http/request_queue.h" |
| 15 | 11 | |
| 16 | -static | |
| 17 | -void | |
| 18 | -httpRequestParserParse(HttpRequestParser); | |
| 12 | +void httpRequestParserParse(HttpRequestParser); | |
| 19 | 13 | |
| 20 | 14 | static |
| 21 | 15 | void |
| ... | ... | @@ -103,221 +97,4 @@ INIT_IFACE(Class, ctor, dtor, _clone); |
| 103 | 97 | INIT_IFACE(StreamReader, get_data); |
| 104 | 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 | 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