Commit e67667881fd1026ccbc5960dc96feb20a3bd988b

Authored by Georg Hopp
1 parent bf6a341b

change response to tree based header storage and make everything work.

  1 +2012-02-12 04:05:38 +0100 Georg Hopp
  2 +
  3 + * change response to tree based header storage and make everything work. (HEAD, master)
  4 +
1 5 2012-02-12 00:05:13 +0100 Georg Hopp
2 6
3   - * changed header hashing to use btree (GNU only). @TODO: make this conditional for other systems. Removed the qsort calls on server->fds making O(2nlogn) to O(n) (HEAD, master)
  7 + * changed header hashing to use btree (GNU only). @TODO: make this conditional for other systems. Removed the qsort calls on server->fds making O(2nlogn) to O(n) (origin/master, origin/HEAD)
4 8
5 9 2012-02-11 13:52:32 +0100 Georg Hopp
6 10
7   - * daemonize testserver now (origin/master, origin/HEAD)
  11 + * daemonize testserver now
8 12
9 13 2012-02-11 12:47:01 +0100 Georg Hopp
10 14
... ...
... ... @@ -11,8 +11,8 @@ CLASS(HttpHeader) {
11 11
12 12 HttpHeader httpHeaderParse(char * line); // @INFO: destructive
13 13
14   -void httpHeaderSort(const HttpHeader [], int);
15   -char * httpHeaderGet(const HttpHeader [], int, const char *);
  14 +void httpHeaderAdd(const HttpHeader *, HttpHeader);
  15 +char * httpHeaderGet(const HttpHeader *, const char *);
16 16 size_t httpHeaderSizeGet(HttpHeader);
17 17 size_t httpHeaderToString(HttpHeader, char *);
18 18
... ...
... ... @@ -15,9 +15,6 @@ CLASS(HttpRequest) {
15 15 int nbody;
16 16 };
17 17
18   -void httpHeaderAdd(HttpHeader *, HttpHeader);
19   -char * XhttpHeaderGet(HttpHeader *, const char *);
20   -char * httpRequestHeaderGet(HttpRequest, const char *);
21 18 char httpRequestHasKeepAlive(HttpRequest);
22 19
23 20 #endif /* __HTTP_REQUEST_H__ */
... ...
... ... @@ -7,6 +7,7 @@
7 7
8 8 #define HTTP_REQUEST_PARSER_READ_CHUNK 1024
9 9
  10 +
10 11 typedef enum e_HttpRequestState {
11 12 HTTP_REQUEST_GARBAGE=0,
12 13 HTTP_REQUEST_START,
... ... @@ -29,6 +30,11 @@ CLASS(HttpRequestParser) {
29 30 HttpRequestState state;
30 31 };
31 32
  33 +size_t httpRequestParserRead(HttpRequestParser, int);
  34 +void httpRequestParserParse(HttpRequestParser);
  35 +void httpRequestParserGetRequestLine(HttpRequest, char *);
  36 +void httpRequestParserGetHeader(HttpRequest, char *);
  37 +
32 38 #endif /* __HTTP_REQUEST_PARSER_H__ */
33 39
34 40 // vim: set ts=4 sw=4:
... ...
... ... @@ -12,8 +12,7 @@ CLASS(HttpResponse) {
12 12 unsigned int status;
13 13 char * reason;
14 14
15   - HttpHeader header[128];
16   - int nheader;
  15 + HttpHeader header;
17 16
18 17 char * body;
19 18 int nbody;
... ... @@ -23,7 +22,7 @@ HttpResponse httpResponse404();
23 22
24 23 void httpResponseHeaderSet(HttpResponse, const char *, const char *);
25 24 size_t httpResponseSizeGet(HttpResponse);
26   -size_t httpResponseToString(HttpResponse, char *);
  25 +char * httpResponseToString(HttpResponse, char *);
27 26
28 27 #endif /* __HTTP_RESPONSE_H__ */
29 28
... ...
... ... @@ -6,17 +6,11 @@
6 6 #define MAX_IFACE 32 // ATTENTION: every iface_impl will use MAX_IFACE * sizeof(void*)
7 7
8 8 #define IFACE(name) ((const struct i_##name const*)&i_##name##_impl)
9   -
10 9 #define INIT_IFACE(name,...) \
11 10 static const struct i_##name i_##name##_impl = {&i_##name,__VA_ARGS__}
12 11
13 12 #define NUMARGS(...) (sizeof((const void*[]){__VA_ARGS__})/sizeof(void*))
14   -
15 13 #define INIT_IMPL(...) {NUMARGS(__VA_ARGS__), 0, {__VA_ARGS__}}
16   -#define CREATE_IMPL(...) \
17   - static struct iface_impl iface_impl = INIT_IMPL(__VA_ARGS__)
18   -
19   -#define METHOD_GET(iface,method) (iface->method)
20 14
21 15
22 16 struct interface {
... ...
... ... @@ -7,13 +7,13 @@ SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c
7 7 SERVER = server.c server/run.c server/close_conn.c
8 8 LOGGER = logger.c logger/stderr.c logger/syslog.c
9 9 REQ = http/request.c http/request/queue.c http/request/has_keep_alive.c
10   -RESP = http/response.c http/response/header_set.c \
11   - http/response/404.c http/response/size_get.c \
  10 +RESP = http/response.c http/response/404.c http/response/size_get.c \
12 11 http/response/to_string.c
13   -HEADER = http/header.c http/header/get.c http/header/sort.c \
  12 +HEADER = http/header.c http/header/get.c http/header/add.c http/header/sort.c \
14 13 http/header/size_get.c http/header/to_string.c
15 14 PARSER = http/request/parser.c http/request/parser/get_header.c \
16   - http/request/parser/parse.c http/request/parser/get_request_line.c
  15 + http/request/parser/parse.c http/request/parser/get_request_line.c \
  16 + http/request/parser/read.c
17 17
18 18
19 19 AM_CFLAGS = -Wall -I ../include/
... ...
  1 +#include <search.h>
1 2 #include <stdlib.h>
2 3 #include <ctype.h>
3 4
... ... @@ -20,20 +21,18 @@ sdbm(const unsigned char * str)
20 21 static
21 22 inline
22 23 int
23   -comp (const void * _a, const void * _b)
  24 +comp(const void * _a, const void * _b)
24 25 {
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;
  26 + HttpHeader a = (HttpHeader)_a;
  27 + HttpHeader b = (HttpHeader)_b;
  28 + return (a->hash < b->hash)? -1 : (a->hash > b->hash)? 1 : 0;
28 29 }
29 30
30 31 char *
31   -httpHeaderGet(const HttpHeader header[], int nheader, const char * name)
  32 +httpHeaderGet(const HttpHeader * root, const char * name)
32 33 {
33   - unsigned long hash = sdbm((unsigned char *)name);
34   - HttpHeader * found;
35   -
36   - found = bsearch(&hash, header, nheader, sizeof(HttpHeader), comp);
  34 + struct c_HttpHeader search = {sdbm((const unsigned char*)name), NULL, NULL};
  35 + HttpHeader * found = tfind(&search, (void**)root, comp);
37 36
38 37 return (NULL != found)? (*found)->value : NULL;
39 38 }
... ...
... ... @@ -11,7 +11,7 @@ httpRequestHasKeepAlive(HttpRequest request)
11 11 char * header;
12 12 char * header_ptr;
13 13
14   - header = XhttpHeaderGet(&(request->header), "connection");
  14 + header = httpHeaderGet(&(request->header), "connection");
15 15
16 16 if (NULL == header) {
17 17 return 0;
... ...
1   -#include <stdlib.h>
2   -#include <ctype.h>
3   -
4   -#include "http/request.h"
5   -
6   -char *
7   -httpRequestHeaderGet(HttpRequest this, const char * name)
8   -{
9   - return XhttpHeaderGet(&(this->header), name);
10   -}
11   -
12   -// vim: set ts=4 sw=4:
... ... @@ -56,47 +56,9 @@ _clone(void * _this, void * _base)
56 56 memcpy(this->buffer, base->buffer, this->buffer_used);
57 57 }
58 58
59   -static
60   -size_t
61   -get_data(void * _this, int fd)
62   -{
63   - HttpRequestParser this = _this;
64   - size_t remaining, chunks;
65   - char buffer[1024];
66   -
67   - ssize_t size = read(fd, buffer, 1024);
68   -
69   - if (0 < size) {
70   - remaining = this->buffer_used % HTTP_REQUEST_PARSER_READ_CHUNK;
71   - chunks = this->buffer_used / HTTP_REQUEST_PARSER_READ_CHUNK;
72   -
73   - /**
74   - * because a division always rounds down
75   - * chunks holds exactly the currently allocated chunks if
76   - * remaining equals 0 but there is no space left.
77   - * Else chunks holds the actually allocated amount of chunks
78   - * minus 1.
79   - * For this reason chunks always has to be increased by 1.
80   - */
81   - chunks++;
82   -
83   - if (size >= remaining) {
84   - this->buffer =
85   - realloc(this->buffer, chunks * HTTP_REQUEST_PARSER_READ_CHUNK);
86   - }
87   -
88   - memcpy(this->buffer + this->buffer_used, buffer, size);
89   - this->buffer_used += size;
90   - this->buffer[this->buffer_used] = 0;
91   -
92   - httpRequestParserParse(this);
93   - }
94   -
95   - return size;
96   -}
97   -
98 59 INIT_IFACE(Class, ctor, dtor, _clone);
99   -INIT_IFACE(StreamReader, get_data);
  60 +INIT_IFACE(StreamReader,
  61 + (fptr_streamReaderRead)httpRequestParserRead);
100 62 CREATE_CLASS(HttpRequestParser, NULL, IFACE(Class), IFACE(StreamReader));
101 63
102 64 // vim: set ts=4 sw=4:
... ...
... ... @@ -7,30 +7,6 @@
7 7 #include "http/header.h"
8 8 #include "http/request.h"
9 9
10   -static
11   -inline
12   -unsigned long
13   -sdbm(const unsigned char * str)
14   -{
15   - unsigned long hash = 0;
16   - int c;
17   -
18   - while ((c = tolower(*str++)))
19   - hash = c + (hash << 6) + (hash << 16) - hash;
20   -
21   - return hash;
22   -}
23   -
24   -static
25   -inline
26   -int
27   -comp(const void * _a, const void * _b)
28   -{
29   - HttpHeader a = (HttpHeader)_a;
30   - HttpHeader b = (HttpHeader)_b;
31   - return (a->hash < b->hash)? -1 : (a->hash > b->hash)? 1 : 0;
32   -}
33   -
34 10 void
35 11 httpRequestParserGetHeader(HttpRequest request, char * line)
36 12 {
... ... @@ -43,26 +19,4 @@ httpRequestParserGetHeader(HttpRequest request, char * line)
43 19 httpHeaderAdd(&(request->header), new(HttpHeader, name, value));
44 20 }
45 21
46   -void
47   -httpHeaderAdd(HttpHeader * root, HttpHeader header)
48   -{
49   - HttpHeader * found = tsearch(header, (void **)root, comp);
50   -
51   - if (*found != header) {
52   - puts("uhh, duplicate header set. "
53   - "This is not implemented right now. "
54   - "Keep the first one found.");
55   - delete(&header);
56   - }
57   -}
58   -
59   -char *
60   -XhttpHeaderGet(HttpHeader * root, const char * name)
61   -{
62   - struct c_HttpHeader search = {sdbm((const unsigned char*)name), NULL, NULL};
63   - HttpHeader * found = tfind(&search, (void **)root, comp);
64   -
65   - return (NULL != found)? (*found)->value : NULL;
66   -}
67   -
68 22 // vim: set ts=4 sw=4:
... ...
... ... @@ -37,9 +37,6 @@ httpRequestSkip(char ** data)
37 37 for (; 0 != **data && ! isalpha(**data); (*data)++);
38 38 }
39 39
40   -void httpRequestParserGetRequestLine(HttpRequest, char *);
41   -void httpRequestParserGetHeader(HttpRequest, char *);
42   -
43 40 void
44 41 httpRequestParserParse(HttpRequestParser this)
45 42 {
... ... @@ -86,7 +83,7 @@ httpRequestParserParse(HttpRequestParser this)
86 83 char * nbody;
87 84
88 85 if (0 == this->cur_request->nbody) {
89   - nbody = XhttpHeaderGet(
  86 + nbody = httpHeaderGet(
90 87 &(this->cur_request->header),
91 88 "Content-Length");
92 89
... ...
  1 +#ifndef _GNU_SOURCE
  2 +#define _GNU_SOURCE
  3 +#endif
  4 +
  5 +#include <search.h>
1 6 #include <stdlib.h>
2 7 #include <stdarg.h>
3 8
... ... @@ -37,19 +42,23 @@ ctor(void * _this, va_list * params)
37 42 }
38 43
39 44 static
  45 +inline
  46 +void
  47 +tDelete(void * node)
  48 +{
  49 + delete(&node);
  50 +}
  51 +
  52 +static
40 53 void
41 54 dtor(void * _this)
42 55 {
43 56 HttpResponse this = _this;
44   - int i;
45 57
46 58 _free((void **)&(this->version));
47 59 _free((void **)&(this->reason));
48 60
49   - for (i=0; i<128; i++) {
50   - if (NULL == (this->header)[i]) break;
51   - delete(&(this->header)[i]);
52   - }
  61 + tdestroy(this->header, tDelete);
53 62
54 63 _free((void **)&(this->body));
55 64 }
... ...
... ... @@ -7,6 +7,7 @@
7 7 #include "interface/class.h"
8 8
9 9 #include "http/response.h"
  10 +#include "http/header.h"
10 11
11 12
12 13 #define RESP_DATA "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n" \
... ... @@ -28,20 +29,24 @@ httpResponse404()
28 29
29 30 response = new(HttpResponse, "HTTP/1.1", 404, "Not Found");
30 31
31   - httpResponseHeaderSet(response, "Content-Type", "text/html");
32   - httpResponseHeaderSet(response, "Server", "testserver");
  32 + httpHeaderAdd(&(response->header),
  33 + new(HttpHeader, "Content-Type", "text/html"));
  34 + httpHeaderAdd(&(response->header),
  35 + new(HttpHeader, "Server", "testserver"));
33 36
34 37 response->nbody = sizeof(RESP_DATA) - 1;
35 38 response->body = calloc(1, sizeof(RESP_DATA));
36 39 strcpy(response->body, RESP_DATA);
37 40
38 41 sprintf(buffer, "%d", response->nbody);
39   - httpResponseHeaderSet(response, "Content-Length", buffer);
  42 + httpHeaderAdd(&(response->header),
  43 + new(HttpHeader, "Content-Length", buffer));
40 44
41 45 t = time(NULL);
42 46 tmp = localtime(&t);
43 47 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp);
44   - httpResponseHeaderSet(response, "Date", buffer);
  48 + httpHeaderAdd(&(response->header),
  49 + new(HttpHeader, "Date", buffer));
45 50
46 51 return response;
47 52 }
... ...
1   -#include "class.h"
2   -#include "interface/class.h"
3   -
4   -#include "http/response.h"
5   -#include "http/header.h"
6   -
7   -void
8   -httpResponseHeaderSet(HttpResponse this, const char * name, const char * value)
9   -{
10   - (this->header)[this->nheader++] = new(HttpHeader, name, value);
11   -}
12   -
13   -// vim: set ts=4 sw=4:
  1 +#include <search.h>
1 2 #include <string.h>
2 3 #include <sys/types.h>
3 4
4 5 #include "http/response.h"
5 6 #include "http/header.h"
6 7
  8 +static size_t size;
  9 +
  10 +static
  11 +inline
  12 +void
  13 +addHeaderSize(const void * node, const VISIT which, const int depth)
  14 +{
  15 + if (endorder == which || leaf == which) {
  16 + size += httpHeaderSizeGet(*(HttpHeader *)node) + 2;
  17 + }
  18 +}
  19 +
7 20 size_t
8 21 httpResponseSizeGet(HttpResponse response)
9 22 {
10   - int i;
11   - size_t size = 0;
  23 + size = 0;
12 24
13 25 size += strlen(response->version) + 1;
14 26 size += 4; // for status
15 27 size += strlen(response->reason) + 2;
16 28
17   - for (i=0; i<response->nheader; i++) {
18   - size += httpHeaderSizeGet(response->header[i]) + 2;
19   - }
  29 + twalk(response->header, addHeaderSize);
20 30
21 31 size += 2;
22 32 size += response->nbody;
... ...
  1 +#include <search.h>
1 2 #include <string.h>
2 3 #include <stdio.h>
3 4
4 5 #include "http/response.h"
5 6 #include "http/header.h"
6 7
7   -size_t
8   -httpResponseToString(HttpResponse response, char * string)
  8 +static char * string;
  9 +
  10 +void
  11 +addHeaderString(const void * node, const VISIT which, const int depth)
  12 +{
  13 + if (endorder == which || leaf == which) {
  14 + string += httpHeaderToString(*(HttpHeader *)node, string);
  15 + *string++ = '\r';
  16 + *string++ = '\n';
  17 + }
  18 +}
  19 +
  20 +char *
  21 +httpResponseToString(HttpResponse response, char * _string)
9 22 {
10   - int i;
11   - size_t size = httpResponseSizeGet(response);
12 23 char status[4];
13 24
  25 + string = _string;
  26 +
14 27 snprintf(status, 4, "%d", response->status);
15 28
16 29 strcpy(string, response->version);
... ... @@ -29,18 +42,14 @@ httpResponseToString(HttpResponse response, char * string)
29 42 *string++ = '\r';
30 43 *string++ = '\n';
31 44
32   - for (i=0; i<response->nheader; i++) {
33   - string += httpHeaderToString(response->header[i], string);
34   - *string++ = '\r';
35   - *string++ = '\n';
36   - }
  45 + twalk(response->header, addHeaderString);
37 46
38 47 *string++ = '\r';
39 48 *string++ = '\n';
40 49
41 50 memcpy(string, response->body, response->nbody);
42 51
43   - return size;
  52 + return string;
44 53 }
45 54
46 55 // vim: set ts=4 sw=4:
... ...
... ... @@ -116,17 +116,15 @@ serverRun(Server this)
116 116
117 117 if (httpRequestHasKeepAlive(queue->requests[j])) {
118 118 (this->conns)[fd].keep_alive = 1;
119   - httpResponseHeaderSet(
120   - response,
121   - "Connection",
122   - "Keep-Alive");
  119 + httpHeaderAdd(
  120 + &(response->header),
  121 + new(HttpHeader, "Connection", "Keep-Alive"));
123 122 }
124 123 else {
125 124 (this->conns)[fd].keep_alive = 0;
126   - httpResponseHeaderSet(
127   - response,
128   - "Connection",
129   - "Close");
  125 + httpHeaderAdd(
  126 + &(response->header),
  127 + new(HttpHeader, "Connection", "Close"));
130 128 }
131 129
132 130 delete(&(queue->requests[j]));
... ...
Please register or login to post a comment