Commit f678adcae4b89de9558cfd023e3bc678853bee9d
1 parent
ca023b99
access to headers via hash, read body (actually only with content-length header …
…should also look for content-encoding)
Showing
6 changed files
with
101 additions
and
8 deletions
| 1 | +2012-02-09 09:34:21 +0100 Georg Hopp | |
| 2 | + | |
| 3 | + * access to headers via hash, read body (actually only with content-length header should also look for content-encoding) (HEAD, master) | |
| 4 | + | |
| 5 | +2012-02-08 16:51:49 +0100 Georg Hopp | |
| 6 | + | |
| 7 | + * fix handling of remote close - i should have another eye on this...there still seems to be something wrong. | |
| 8 | + | |
| 9 | +2012-02-08 15:04:52 +0100 Georg Hopp | |
| 10 | + | |
| 11 | + * fixed some warnings | |
| 12 | + | |
| 13 | +2012-02-08 13:12:59 +0100 Georg Hopp | |
| 14 | + | |
| 15 | + * changed documentation | |
| 16 | + | |
| 17 | +2012-02-08 13:05:23 +0100 Georg Hopp | |
| 18 | + | |
| 19 | + * added first generated documentation | |
| 20 | + | |
| 21 | +2012-02-08 12:14:44 +0100 Georg Hopp | |
| 22 | + | |
| 23 | + * oops commit...forgot to add request_queue.c | |
| 24 | + | |
| 1 | 25 | 2012-02-08 11:52:30 +0100 Georg Hopp |
| 2 | 26 | |
| 3 | - * found the file handle lost...made a first workaround and added an todo. (HEAD, master) | |
| 27 | + * found the file handle lost...made a first workaround and added an todo. | |
| 4 | 28 | |
| 5 | 29 | 2012-02-08 10:21:04 +0100 Georg Hopp |
| 6 | 30 | ... | ... |
| ... | ... | @@ -8,15 +8,20 @@ CLASS(HttpRequest) { |
| 8 | 8 | char * uri; |
| 9 | 9 | char * method; |
| 10 | 10 | |
| 11 | - struct { | |
| 12 | - char * name; | |
| 13 | - char * value; | |
| 11 | + struct HttpRequestHeader { | |
| 12 | + unsigned long hash; | |
| 13 | + char * name; | |
| 14 | + char * value; | |
| 14 | 15 | } header[128]; |
| 16 | + int nheader; | |
| 15 | 17 | |
| 16 | 18 | char * body; |
| 17 | - char done; | |
| 19 | + int nbody; | |
| 18 | 20 | }; |
| 19 | 21 | |
| 22 | +char * | |
| 23 | +httpRequestHeaderGet(HttpRequest this, const char * name); | |
| 24 | + | |
| 20 | 25 | #endif /* __HTTP_REQUEST_H__ */ |
| 21 | 26 | |
| 22 | 27 | // vim: set ts=4 sw=4: | ... | ... |
| ... | ... | @@ -5,7 +5,7 @@ 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 | |
| 8 | +HTTP = interface/stream_reader.c http/request_parser.c http/request.c http/request_queue.c http/request/header_get.c | |
| 9 | 9 | |
| 10 | 10 | AM_CFLAGS = -Wall -I ../include/ |
| 11 | 11 | ... | ... |
| ... | ... | @@ -129,6 +129,43 @@ httpRequestSkip(char ** data) |
| 129 | 129 | for (; 0 != **data && ! isalpha(**data); (*data)++); |
| 130 | 130 | } |
| 131 | 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 = *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 | + | |
| 132 | 169 | static |
| 133 | 170 | void |
| 134 | 171 | httpRequestParserParse(HttpRequestParser this) |
| ... | ... | @@ -207,21 +244,43 @@ httpRequestParserParse(HttpRequestParser this) |
| 207 | 244 | *delim = 0; |
| 208 | 245 | (request->header)[header_idx].name = malloc(strlen(line) + 1); |
| 209 | 246 | strcpy((request->header)[header_idx].name, line); |
| 247 | + (request->header)[header_idx].hash = sdbm((unsigned char *)line); | |
| 210 | 248 | |
| 211 | 249 | line = delim + 1; |
| 212 | 250 | for (; *line == ' ' && *line != 0; line++); |
| 213 | 251 | |
| 214 | 252 | (request->header)[header_idx].value = malloc(strlen(line) + 1); |
| 215 | 253 | strcpy((request->header)[header_idx].value, line); |
| 254 | + | |
| 255 | + header_idx++; | |
| 256 | + request->nheader++; | |
| 216 | 257 | } |
| 217 | 258 | |
| 218 | - header_idx++; | |
| 219 | 259 | break; |
| 220 | 260 | |
| 221 | 261 | case HTTP_REQUEST_HEADERS_DONE: |
| 222 | 262 | /** |
| 223 | 263 | * @TODO: here comes the body handling |
| 224 | 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 | + | |
| 225 | 284 | this->state = HTTP_REQUEST_DONE; |
| 226 | 285 | break; |
| 227 | 286 | ... | ... |
| ... | ... | @@ -80,6 +80,11 @@ serverRun(Server this) |
| 80 | 80 | for (j=0; j<queue->nrequests; j++) { |
| 81 | 81 | HttpRequest request = queue->requests[j]; |
| 82 | 82 | |
| 83 | + if (NULL != request->body) { | |
| 84 | + puts("==REQUEST BODY=="); | |
| 85 | + puts(request->body); | |
| 86 | + } | |
| 87 | + | |
| 83 | 88 | /** |
| 84 | 89 | * @TODO: for now simply remove request and send not found. |
| 85 | 90 | * Make this sane. | ... | ... |
| ... | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | int |
| 14 | 14 | main() |
| 15 | 15 | { |
| 16 | - Logger logger = new(LoggerStderr, LOGGER_INFO); | |
| 16 | + Logger logger = new(LoggerStderr, LOGGER_ERR); | |
| 17 | 17 | HttpRequestParser parser = new(HttpRequestParser); |
| 18 | 18 | Server server = new(Server, logger, parser, 11212, SOMAXCONN); |
| 19 | 19 | //Server server = new(Server, logger, parser, 11212, 20); | ... | ... |
Please
register
or
login
to post a comment