From f678adcae4b89de9558cfd023e3bc678853bee9d Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Thu, 9 Feb 2012 09:34:21 +0100 Subject: [PATCH] access to headers via hash, read body (actually only with content-length header should also look for content-encoding) --- ChangeLog | 26 ++++++++++++++++- include/http/request.h | 13 ++++++--- src/Makefile.am | 2 +- src/http/request_parser.c | 61 ++++++++++++++++++++++++++++++++++++++- src/server/run.c | 5 ++++ src/testserver.c | 2 +- 6 files changed, 101 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index d036b49..367e858 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,30 @@ +2012-02-09 09:34:21 +0100 Georg Hopp + + * access to headers via hash, read body (actually only with content-length header should also look for content-encoding) (HEAD, master) + +2012-02-08 16:51:49 +0100 Georg Hopp + + * fix handling of remote close - i should have another eye on this...there still seems to be something wrong. + +2012-02-08 15:04:52 +0100 Georg Hopp + + * fixed some warnings + +2012-02-08 13:12:59 +0100 Georg Hopp + + * changed documentation + +2012-02-08 13:05:23 +0100 Georg Hopp + + * added first generated documentation + +2012-02-08 12:14:44 +0100 Georg Hopp + + * oops commit...forgot to add request_queue.c + 2012-02-08 11:52:30 +0100 Georg Hopp - * found the file handle lost...made a first workaround and added an todo. (HEAD, master) + * found the file handle lost...made a first workaround and added an todo. 2012-02-08 10:21:04 +0100 Georg Hopp diff --git a/include/http/request.h b/include/http/request.h index 0a4f83c..22cb46c 100644 --- a/include/http/request.h +++ b/include/http/request.h @@ -8,15 +8,20 @@ CLASS(HttpRequest) { char * uri; char * method; - struct { - char * name; - char * value; + struct HttpRequestHeader { + unsigned long hash; + char * name; + char * value; } header[128]; + int nheader; char * body; - char done; + int nbody; }; +char * +httpRequestHeaderGet(HttpRequest this, const char * name); + #endif /* __HTTP_REQUEST_H__ */ // vim: set ts=4 sw=4: diff --git a/src/Makefile.am b/src/Makefile.am index ba46b98..003da48 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,7 +5,7 @@ CLASS = class.c interface.c interface/class.c SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c SERVER = server.c server/run.c server/close_conn.c LOGGER = logger.c logger/stderr.c logger/syslog.c interface/logger.c -HTTP = interface/stream_reader.c http/request_parser.c http/request.c http/request_queue.c +HTTP = interface/stream_reader.c http/request_parser.c http/request.c http/request_queue.c http/request/header_get.c AM_CFLAGS = -Wall -I ../include/ diff --git a/src/http/request_parser.c b/src/http/request_parser.c index 50c7842..4df71ce 100644 --- a/src/http/request_parser.c +++ b/src/http/request_parser.c @@ -129,6 +129,43 @@ httpRequestSkip(char ** data) for (; 0 != **data && ! isalpha(**data); (*data)++); } +/** + * SDBM hashing algorithm: + * + * this algorithm was created for sdbm (a public-domain reimplementation of + * ndbm) database library. it was found to do well in scrambling bits, + * causing better distribution of the keys and fewer splits. it also happens + * to be a good general hashing function with good distribution. the actual + * function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below + * is the faster version used in gawk. [there is even a faster, duff-device + * version] the magic constant 65599 was picked out of thin air while + * experimenting with different constants, and turns out to be a prime. this + * is one of the algorithms used in berkeley db (see sleepycat) and elsewhere. + */ +static +inline +unsigned long +sdbm(unsigned char * str) +{ + unsigned long hash = 0; + int c; + + while ((c = *str++)) + hash = c + (hash << 6) + (hash << 16) - hash; + + return hash; +} + +static +inline +int +comp (const void * _a, const void * _b) +{ + const struct HttpRequestHeader * a = _a; + const struct HttpRequestHeader * b = _b; + return (a->hash < b->hash)? -1 : (a->hash > b->hash)? 1 : 0; +} + static void httpRequestParserParse(HttpRequestParser this) @@ -207,21 +244,43 @@ httpRequestParserParse(HttpRequestParser this) *delim = 0; (request->header)[header_idx].name = malloc(strlen(line) + 1); strcpy((request->header)[header_idx].name, line); + (request->header)[header_idx].hash = sdbm((unsigned char *)line); line = delim + 1; for (; *line == ' ' && *line != 0; line++); (request->header)[header_idx].value = malloc(strlen(line) + 1); strcpy((request->header)[header_idx].value, line); + + header_idx++; + request->nheader++; } - header_idx++; break; case HTTP_REQUEST_HEADERS_DONE: /** * @TODO: here comes the body handling */ + qsort( + request->header, + request->nheader, + sizeof(struct HttpRequestHeader), + comp); + + { + char * bodylen; + + bodylen = httpRequestHeaderGet(request, "Content-Length"); + + if (NULL != bodylen) { + request->nbody = atoi(bodylen); + request->body = calloc(1, request->nbody + 1); + memcpy(request->body, data, request->nbody); + data += request->nbody; + } + } + this->state = HTTP_REQUEST_DONE; break; diff --git a/src/server/run.c b/src/server/run.c index e4f6207..5bccaa2 100644 --- a/src/server/run.c +++ b/src/server/run.c @@ -80,6 +80,11 @@ serverRun(Server this) for (j=0; jnrequests; j++) { HttpRequest request = queue->requests[j]; + if (NULL != request->body) { + puts("==REQUEST BODY=="); + puts(request->body); + } + /** * @TODO: for now simply remove request and send not found. * Make this sane. diff --git a/src/testserver.c b/src/testserver.c index 4ce896f..818776f 100644 --- a/src/testserver.c +++ b/src/testserver.c @@ -13,7 +13,7 @@ int main() { - Logger logger = new(LoggerStderr, LOGGER_INFO); + Logger logger = new(LoggerStderr, LOGGER_ERR); HttpRequestParser parser = new(HttpRequestParser); Server server = new(Server, logger, parser, 11212, SOMAXCONN); //Server server = new(Server, logger, parser, 11212, 20);