Commit fa58a6cc8143e592dd489716e3770775fd8b058c

Authored by Georg Hopp
1 parent ab21de50

make http request and response childs of a common parent http message

  1 +2012-02-12 12:43:56 +0100 Georg Hopp
  2 +
  3 + * make http request and response childs of a common parent http message (HEAD, master)
  4 +
1 5 2012-02-12 04:13:54 +0100 Georg Hopp
2 6
3   - * remove now obsoleted header_sort (HEAD, master)
  7 + * remove now obsoleted header_sort
4 8
5 9 2012-02-12 04:05:38 +0100 Georg Hopp
6 10
... ...
... ... @@ -42,28 +42,44 @@
42 42 * @TODO: actually i use gcc feature ## for variadoc... think about
43 43 * a way to make this standard.
44 44 */
45   -#define _CALL(object,_iface,method,...) \
46   - class_ptr class = class_getClass((object)); \
47   - struct i_##_iface * iface; \
48   - if (class->init) class->init(); \
49   - iface = (struct i_##_iface *)class_getInterface(&class, &i_##_iface); \
50   - while ((NULL == iface || NULL == iface->method) && HAS_PARENT(class)) { \
51   - class = class->parent; \
52   - if (class->init) class->init(); \
53   - iface = (struct i_##_iface *)class_getInterface(&class, &i_##_iface); \
54   - }; \
55   - assert(NULL != iface->method);
  45 +#define _CALL(object,_iface,method,...) \
  46 + do { \
  47 + class_ptr class = class_getClass((object)); \
  48 + if (class->init) class->init(); \
  49 + iface = (struct i_##_iface *)class_getInterface(&class, &i_##_iface); \
  50 + while ((NULL == iface || NULL == iface->method) && HAS_PARENT(class)) { \
  51 + class = class->parent; \
  52 + if (class->init) class->init(); \
  53 + iface = (struct i_##_iface *)class_getInterface(&class, &i_##_iface); \
  54 + }; \
  55 + assert(NULL != iface->method); \
  56 + } while(0)
56 57
57   -#define CALL(object,_iface,method,...) \
58   - do { \
  58 +#define CALL(object,_iface,method,...) \
  59 + do { \
  60 + struct i_##_iface * iface; \
59 61 _CALL(object, _iface, method, ##__VA_ARGS__); \
60   - iface->method(object, ##__VA_ARGS__); \
  62 + iface->method(object, ##__VA_ARGS__); \
61 63 } while(0)
62 64
63   -#define RETCALL(object,_iface,method,ret,...) \
64   - do { \
  65 +#define RETCALL(object,_iface,method,ret,...) \
  66 + do { \
  67 + struct i_##_iface * iface; \
65 68 _CALL(object, _iface, method, ##__VA_ARGS__); \
66   - ret = iface->method(object, ##__VA_ARGS__); \
  69 + ret = iface->method(object, ##__VA_ARGS__); \
  70 + } while(0)
  71 +
  72 +#define PARENTCALL(object,_iface,method,...) \
  73 + do { \
  74 + struct i_##_iface * iface; \
  75 + class_ptr class = class_getClass((object)); \
  76 + if (class->init) class->init(); \
  77 + assert(HAS_PARENT(class)); \
  78 + class = class->parent; \
  79 + if (class->init) class->init(); \
  80 + iface = (struct i_##_iface *)class_getInterface(&class, &i_##_iface); \
  81 + assert(NULL != iface->method); \
  82 + iface->method(object, ##__VA_ARGS__); \
67 83 } while(0)
68 84
69 85
... ...
  1 +#ifndef __HTTP_MESSAGE__
  2 +#define __HTTP_MESSAGE__
  3 +
  4 +#include "class.h"
  5 +#include "http/header.h"
  6 +
  7 +typedef enum e_HttpMessageType {
  8 + HTTP_MESSAGE_BUFFERED=0,
  9 + HTTP_MESSAGE_PIPED
  10 +} HttpMessageType;
  11 +
  12 +
  13 +CLASS(HttpMessage) {
  14 + char * version;
  15 +
  16 + HttpHeader header;
  17 +
  18 + HttpMessageType type;
  19 + union {
  20 + char * buffer;
  21 + int handle;
  22 + } body;
  23 + int nbody;
  24 +};
  25 +
  26 +#endif // __HTTP_MESSAGE__
  27 +
  28 +// vim: set ts=4 sw=4:
... ...
... ... @@ -2,17 +2,13 @@
2 2 #define __HTTP_REQUEST_H__
3 3
4 4 #include "class.h"
5   -#include "http/header.h"
  5 +#include "http/message.h"
6 6
7 7 CLASS(HttpRequest) {
  8 + EXTENDS(HttpMessage);
  9 +
8 10 char * method;
9 11 char * uri;
10   - char * version;
11   -
12   - HttpHeader header;
13   -
14   - char * body;
15   - int nbody;
16 12 };
17 13
18 14 char httpRequestHasKeepAlive(HttpRequest);
... ...
... ... @@ -7,6 +7,9 @@
7 7
8 8 #define HTTP_REQUEST_PARSER_READ_CHUNK 1024
9 9
  10 +#define REMAINS(pars) \
  11 + ((pars)->buffer_used - ((pars)->cur_data - (pars)->buffer))
  12 +
10 13
11 14 typedef enum e_HttpRequestState {
12 15 HTTP_REQUEST_GARBAGE=0,
... ... @@ -32,6 +35,8 @@ CLASS(HttpRequestParser) {
32 35
33 36 size_t httpRequestParserRead(HttpRequestParser, int);
34 37 void httpRequestParserParse(HttpRequestParser);
  38 +void httpRequestParserGetBody(HttpRequestParser);
  39 +
35 40 void httpRequestParserGetRequestLine(HttpRequest, char *);
36 41 void httpRequestParserGetHeader(HttpRequest, char *);
37 42
... ...
... ... @@ -4,18 +4,14 @@
4 4 #include <sys/types.h>
5 5
6 6 #include "class.h"
7   -#include "http/header.h"
  7 +#include "http/message.h"
8 8
9 9
10 10 CLASS(HttpResponse) {
11   - char * version;
  11 + EXTENDS(HttpMessage);
  12 +
12 13 unsigned int status;
13 14 char * reason;
14   -
15   - HttpHeader header;
16   -
17   - char * body;
18   - int nbody;
19 15 };
20 16
21 17 HttpResponse httpResponse404();
... ...
  1 +#ifndef __HTTP_WORKER_H__
  2 +#define __HTTP_WORKER_H__
  3 +
  4 +#include "class.h"
  5 +#include "http/request/parser.h"
  6 +
  7 +CLASS(HttpWorker) {
  8 + HttpRequestParser parser;
  9 +};
  10 +
  11 +#endif // __HTTP_WORKER_H__
  12 +
  13 +// vim: set ts=4 sw=4:
... ...
... ... @@ -6,6 +6,7 @@ CLASS = class.c interface.c
6 6 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 +MSG = http/message.c
9 10 REQ = http/request.c http/request/queue.c http/request/has_keep_alive.c
10 11 RESP = http/response.c http/response/404.c http/response/size_get.c \
11 12 http/response/to_string.c
... ... @@ -13,7 +14,7 @@ HEADER = http/header.c http/header/get.c http/header/add.c \
13 14 http/header/size_get.c http/header/to_string.c
14 15 PARSER = http/request/parser.c http/request/parser/get_header.c \
15 16 http/request/parser/parse.c http/request/parser/get_request_line.c \
16   - http/request/parser/read.c
  17 + http/request/parser/read.c http/request/parser/get_body.c
17 18
18 19
19 20 AM_CFLAGS = -Wall -I ../include/
... ... @@ -21,6 +22,6 @@ AM_CFLAGS = -Wall -I ../include/
21 22 bin_PROGRAMS = testserver
22 23
23 24 testserver_SOURCES = testserver.c \
24   - $(IFACE) $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(REQ) \
  25 + $(IFACE) $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(MSG) $(REQ) \
25 26 $(RESP) $(HEADER) $(PARSER) signalHandling.c daemonize.c
26 27 testserver_CFLAGS = -Wall -I ../include/
... ...
  1 +#include <search.h>
  2 +#include <stdlib.h>
  3 +#include <ctype.h>
  4 +#include <stdio.h>
  5 +
  6 +#include "class.h"
  7 +#include "interface/class.h"
  8 +#include "http/header.h"
  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 +void
  35 +httpHeaderAdd(const HttpHeader * root, HttpHeader header)
  36 +{
  37 + HttpHeader * found = tsearch(header, (void **)root, comp);
  38 +
  39 + if (*found != header) {
  40 + puts("uhh, duplicate header set. "
  41 + "This is not implemented right now. "
  42 + "Keep the first one found.");
  43 + delete(&header);
  44 + }
  45 +}
  46 +
  47 +// vim: set ts=4 sw=4:
... ...
  1 +#ifndef _GNU_SOURCE
  2 +#define _GNU_SOURCE
  3 +#endif
  4 +
  5 +#include <search.h>
  6 +#include <stdlib.h>
  7 +#include <string.h>
  8 +#include <stdarg.h>
  9 +#include <unistd.h>
  10 +
  11 +#include "class.h"
  12 +#include "interface/class.h"
  13 +
  14 +#include "http/message.h"
  15 +#include "message/helper.c"
  16 +
  17 +
  18 +static
  19 +void
  20 +ctor(void * _this, va_list * params)
  21 +{
  22 + HttpMessage this = _this;
  23 + char * version = va_arg(* params, char *);
  24 +
  25 + this->version = calloc(1, strlen(version)+1);
  26 + strcpy(this->version, version);
  27 +}
  28 +
  29 +static
  30 +void
  31 +dtor(void * _this)
  32 +{
  33 + HttpMessage this = _this;
  34 +
  35 + _free((void **)&(this->version));
  36 +
  37 + /**
  38 + * this is a GNU extension...anyway on most non
  39 + * GNUish systems i would not use tsearch anyway
  40 + * as the trees will be unbalanced.
  41 + */
  42 + tdestroy(this->header, tDelete);
  43 +
  44 + switch (this->type) {
  45 + case HTTP_MESSAGE_BUFFERED:
  46 + _free((void **)&((this->body).buffer));
  47 + break;
  48 +
  49 + case HTTP_MESSAGE_PIPED:
  50 + close((this->body).handle);
  51 + break;
  52 +
  53 + default:
  54 + break;
  55 + }
  56 +}
  57 +
  58 +INIT_IFACE(Class, ctor, dtor, NULL);
  59 +CREATE_CLASS(HttpMessage, NULL, IFACE(Class));
  60 +
  61 +// vim: set ts=4 sw=4:
... ...
  1 +#ifndef __HTTP_MESSAGE_HELPER_C__
  2 +#define __HTTP_MESSAGE_HELPER_C__
  3 +
  4 +#include <stdlib.h>
  5 +
  6 +#include "class.h"
  7 +#include "interface/class.h"
  8 +
  9 +
  10 +static
  11 +inline
  12 +void
  13 +_free(void ** data)
  14 +{
  15 + if (NULL != *data) {
  16 + free(*data);
  17 + }
  18 +}
  19 +
  20 +static
  21 +inline
  22 +void
  23 +tDelete(void * node)
  24 +{
  25 + delete(&node);
  26 +}
  27 +
  28 +#endif // __HTTP_MESSAGE_HELPER_C__
  29 +
  30 +// vim: set ts=4 sw=4:
... ...
1   -#ifndef _GNU_SOURCE
2   -#define _GNU_SOURCE
3   -#endif
4   -
5 1 #include <stdlib.h>
6 2 #include <stdarg.h>
7   -#include <search.h>
8 3
9 4 #include "class.h"
10 5 #include "interface/class.h"
11 6
12 7 #include "http/request.h"
  8 +#include "message/helper.c"
13 9
14 10
15 11 static
16   -inline
17   -void
18   -_free(void ** data)
19   -{
20   - if (NULL != *data) {
21   - free(*data);
22   - }
23   -}
24   -
25   -static
26   -inline
27   -void
28   -tDelete(void * node)
29   -{
30   - delete(&node);
31   -}
32   -
33   -static
34 12 void
35 13 ctor(void * _this, va_list * params) {}
36 14
... ... @@ -40,21 +18,13 @@ dtor(void * _this)
40 18 {
41 19 HttpRequest this = _this;
42 20
43   - _free((void **)&(this->version));
44 21 _free((void **)&(this->uri));
45 22 _free((void **)&(this->method));
46 23
47   - /**
48   - * this is a GNU extension...anyway on most non
49   - * GNUish systems i would not use tsearch anyway
50   - * as the trees will be unbalanced.
51   - */
52   - tdestroy(this->header, tDelete);
53   -
54   - _free((void **)&(this->body));
  24 + PARENTCALL(_this, Class, dtor);
55 25 }
56 26
57 27 INIT_IFACE(Class, ctor, dtor, NULL);
58   -CREATE_CLASS(HttpRequest, NULL, IFACE(Class));
  28 +CREATE_CLASS(HttpRequest, HttpMessage, IFACE(Class));
59 29
60 30 // vim: set ts=4 sw=4:
... ...
1 1 #include <string.h>
2 2 #include <ctype.h>
3 3
  4 +#include "http/message.h"
4 5 #include "http/request.h"
5 6 #include "http/header.h"
6 7
... ... @@ -8,10 +9,11 @@
8 9 char
9 10 httpRequestHasKeepAlive(HttpRequest request)
10 11 {
11   - char * header;
12   - char * header_ptr;
  12 + HttpMessage message = (HttpMessage)request;
  13 + char * header;
  14 + char * header_ptr;
13 15
14   - header = httpHeaderGet(&(request->header), "connection");
  16 + header = httpHeaderGet(&(message->header), "connection");
15 17
16 18 if (NULL == header) {
17 19 return 0;
... ...
  1 +#include <stdlib.h>
  2 +
  3 +#include "http/header.h"
  4 +#include "http/message.h"
  5 +#include "http/request/parser.h"
  6 +
  7 +void
  8 +httpRequestParserGetBody(HttpRequestParser this)
  9 +{
  10 + HttpMessage message = (HttpMessage)(this->cur_request);
  11 + char * nbody;
  12 +
  13 + if (0 == message->nbody) {
  14 + nbody = httpHeaderGet(
  15 + &(message->header),
  16 + "Content-Length");
  17 +
  18 + if (NULL == nbody) {
  19 + this->state = HTTP_REQUEST_DONE;
  20 + return;
  21 + }
  22 + else {
  23 + message->type = HTTP_MESSAGE_BUFFERED;
  24 + message->nbody = atoi(nbody);
  25 + }
  26 + }
  27 +
  28 + if (REMAINS(this) >= message->nbody) {
  29 + (message->body).buffer = calloc(1, message->nbody + 1);
  30 + memcpy((message->body).buffer,
  31 + this->cur_data,
  32 + message->nbody);
  33 + this->cur_data += message->nbody;
  34 + this->state = HTTP_REQUEST_DONE;
  35 + }
  36 +}
  37 +
  38 +// vim: set ts=4 sw=4:
... ...
... ... @@ -5,10 +5,10 @@
5 5 #include "class.h"
6 6 #include "interface/class.h"
7 7 #include "http/header.h"
8   -#include "http/request.h"
  8 +#include "http/message.h"
9 9
10 10 void
11   -httpRequestParserGetHeader(HttpRequest request, char * line)
  11 +httpRequestParserGetHeader(HttpMessage request, char * line)
12 12 {
13 13 char * name = line;
14 14 char * value = strchr(line, ':');
... ...
... ... @@ -7,6 +7,7 @@
7 7 void
8 8 httpRequestParserGetRequestLine(HttpRequest request, char * line)
9 9 {
  10 + HttpMessage message = (HttpMessage)request;
10 11 char * method, * uri, * version;
11 12
12 13 method = line;
... ... @@ -23,8 +24,8 @@ httpRequestParserGetRequestLine(HttpRequest request, char * line)
23 24 strcpy(request->method, method);
24 25 request->uri = malloc(strlen(uri) + 1);
25 26 strcpy(request->uri, uri);
26   - request->version = malloc(strlen(version) + 1);
27   - strcpy(request->version, method);
  27 + message->version = malloc(strlen(version) + 1);
  28 + strcpy(message->version, method);
28 29 }
29 30
30 31 // vim: set ts=4 sw=4:
... ...
... ... @@ -7,10 +7,6 @@
7 7 #include "interface/class.h"
8 8
9 9
10   -#define REMAINS(pars) \
11   - ((pars)->buffer_used - ((pars)->cur_data - (pars)->buffer))
12   -
13   -
14 10 static
15 11 inline
16 12 char *
... ... @@ -79,33 +75,7 @@ httpRequestParserParse(HttpRequestParser this)
79 75 break;
80 76
81 77 case HTTP_REQUEST_HEADERS_DONE:
82   - {
83   - char * nbody;
84   -
85   - if (0 == this->cur_request->nbody) {
86   - nbody = httpHeaderGet(
87   - &(this->cur_request->header),
88   - "Content-Length");
89   -
90   - if (NULL == nbody) {
91   - this->state = HTTP_REQUEST_DONE;
92   - break;
93   - }
94   - else {
95   - this->cur_request->nbody = atoi(nbody);
96   - }
97   - }
98   -
99   - if (REMAINS(this) >= this->cur_request->nbody) {
100   - this->cur_request->body = calloc(1, this->cur_request->nbody + 1);
101   - memcpy(this->cur_request->body,
102   - this->cur_data,
103   - this->cur_request->nbody);
104   - this->cur_data += this->cur_request->nbody;
105   - this->state = HTTP_REQUEST_DONE;
106   - }
107   - }
108   -
  78 + httpRequestParserGetBody(this);
109 79 break;
110 80
111 81 case HTTP_REQUEST_DONE:
... ...
  1 +#include <stdlib.h>
  2 +#include <unistd.h>
  3 +
  4 +#include "http/request/parser.h"
  5 +
  6 +
  7 +size_t
  8 +httpRequestParserRead(HttpRequestParser this, int fd)
  9 +{
  10 + size_t remaining, chunks;
  11 + char buffer[1024];
  12 +
  13 + ssize_t size = read(fd, buffer, 1024);
  14 +
  15 + if (0 < size) {
  16 + remaining = this->buffer_used % HTTP_REQUEST_PARSER_READ_CHUNK;
  17 + chunks = this->buffer_used / HTTP_REQUEST_PARSER_READ_CHUNK;
  18 +
  19 + /**
  20 + * because a division always rounds down
  21 + * chunks holds exactly the currently allocated chunks if
  22 + * remaining equals 0 but there is no space left.
  23 + * Else chunks holds the actually allocated amount of chunks
  24 + * minus 1.
  25 + * For this reason chunks always has to be increased by 1.
  26 + */
  27 + chunks++;
  28 +
  29 + if (size >= remaining) {
  30 + this->buffer =
  31 + realloc(this->buffer, chunks * HTTP_REQUEST_PARSER_READ_CHUNK);
  32 + }
  33 +
  34 + memcpy(this->buffer + this->buffer_used, buffer, size);
  35 + this->buffer_used += size;
  36 + this->buffer[this->buffer_used] = 0;
  37 +
  38 + httpRequestParserParse(this);
  39 + }
  40 +
  41 + return size;
  42 +}
  43 +
  44 +// vim: set ts=4 sw=4:
... ...
1   -#ifndef _GNU_SOURCE
2   -#define _GNU_SOURCE
3   -#endif
4   -
5   -#include <search.h>
6 1 #include <stdlib.h>
7 2 #include <stdarg.h>
8 3
... ... @@ -10,60 +5,38 @@
10 5 #include "interface/class.h"
11 6
12 7 #include "http/response.h"
  8 +#include "message/helper.c"
13 9
14 10
15 11 static
16 12 void
17   -_free(void ** data)
18   -{
19   - if (NULL != *data) {
20   - free(*data);
21   - }
22   -}
23   -
24   -static
25   -void
26 13 ctor(void * _this, va_list * params)
27 14 {
28   - char * version;
  15 + HttpResponse this = _this;
  16 + char * status;
29 17 char * reason;
30 18
31   - HttpResponse this = _this;
  19 + PARENTCALL(_this, Class, ctor, params);
32 20
33   - version = va_arg(* params, char *);
34 21 this->status = va_arg(* params, unsigned int);
35 22 reason = va_arg(* params, char *);
36 23
37   - this->version = calloc(1, strlen(version)+1);
38   - strcpy(this->version, version);
39   -
40 24 this->reason = calloc(1, strlen(reason)+1);
41 25 strcpy(this->reason, reason);
42 26 }
43 27
44 28 static
45   -inline
46   -void
47   -tDelete(void * node)
48   -{
49   - delete(&node);
50   -}
51   -
52   -static
53 29 void
54 30 dtor(void * _this)
55 31 {
56 32 HttpResponse this = _this;
57 33
58   - _free((void **)&(this->version));
59 34 _free((void **)&(this->reason));
60 35
61   - tdestroy(this->header, tDelete);
62   -
63   - _free((void **)&(this->body));
  36 + PARENTCALL(_this, Class, dtor);
64 37 }
65 38
66 39 INIT_IFACE(Class, ctor, dtor, NULL);
67   -CREATE_CLASS(HttpResponse, NULL, IFACE(Class));
  40 +CREATE_CLASS(HttpResponse, HttpMessage, IFACE(Class));
68 41
69 42 // vim: set ts=4 sw=4:
... ...
... ... @@ -7,6 +7,7 @@
7 7 #include "interface/class.h"
8 8
9 9 #include "http/response.h"
  10 +#include "http/message.h"
10 11 #include "http/header.h"
11 12
12 13
... ... @@ -26,26 +27,29 @@ httpResponse404()
26 27 struct tm * tmp;
27 28 char buffer[200];
28 29 HttpResponse response;
  30 + HttpMessage message;
29 31
30 32 response = new(HttpResponse, "HTTP/1.1", 404, "Not Found");
  33 + message = (HttpMessage)response;
31 34
32   - httpHeaderAdd(&(response->header),
  35 + httpHeaderAdd(&(message->header),
33 36 new(HttpHeader, "Content-Type", "text/html"));
34   - httpHeaderAdd(&(response->header),
  37 + httpHeaderAdd(&(message->header),
35 38 new(HttpHeader, "Server", "testserver"));
36 39
37   - response->nbody = sizeof(RESP_DATA) - 1;
38   - response->body = calloc(1, sizeof(RESP_DATA));
39   - strcpy(response->body, RESP_DATA);
  40 + message->type = HTTP_MESSAGE_BUFFERED;
  41 + message->nbody = sizeof(RESP_DATA) - 1;
  42 + (message->body).buffer = calloc(1, sizeof(RESP_DATA));
  43 + strcpy((message->body).buffer, RESP_DATA);
40 44
41   - sprintf(buffer, "%d", response->nbody);
42   - httpHeaderAdd(&(response->header),
  45 + sprintf(buffer, "%d", message->nbody);
  46 + httpHeaderAdd(&(message->header),
43 47 new(HttpHeader, "Content-Length", buffer));
44 48
45 49 t = time(NULL);
46 50 tmp = localtime(&t);
47 51 strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp);
48   - httpHeaderAdd(&(response->header),
  52 + httpHeaderAdd(&(message->header),
49 53 new(HttpHeader, "Date", buffer));
50 54
51 55 return response;
... ...
... ... @@ -2,6 +2,7 @@
2 2 #include <string.h>
3 3 #include <sys/types.h>
4 4
  5 +#include "http/message.h"
5 6 #include "http/response.h"
6 7 #include "http/header.h"
7 8
... ... @@ -20,16 +21,21 @@ addHeaderSize(const void * node, const VISIT which, const int depth)
20 21 size_t
21 22 httpResponseSizeGet(HttpResponse response)
22 23 {
  24 + HttpMessage message = (HttpMessage)response;
  25 +
23 26 size = 0;
24 27
25   - size += strlen(response->version) + 1;
  28 + size += strlen(message->version) + 1;
26 29 size += 4; // for status
27 30 size += strlen(response->reason) + 2;
28 31
29   - twalk(response->header, addHeaderSize);
  32 + twalk(message->header, addHeaderSize);
30 33
31 34 size += 2;
32   - size += response->nbody;
  35 +
  36 + if (HTTP_MESSAGE_BUFFERED == message->type) {
  37 + size += message->nbody;
  38 + }
33 39
34 40 return size;
35 41 }
... ...
... ... @@ -20,13 +20,14 @@ addHeaderString(const void * node, const VISIT which, const int depth)
20 20 char *
21 21 httpResponseToString(HttpResponse response, char * _string)
22 22 {
23   - char status[4];
  23 + HttpMessage message = (HttpMessage)response;
  24 + char status[4];
24 25
25 26 string = _string;
26 27
27 28 snprintf(status, 4, "%d", response->status);
28 29
29   - strcpy(string, response->version);
  30 + strcpy(string, message->version);
30 31 string += strlen(string);
31 32
32 33 *string++ = ' ';
... ... @@ -42,12 +43,14 @@ httpResponseToString(HttpResponse response, char * _string)
42 43 *string++ = '\r';
43 44 *string++ = '\n';
44 45
45   - twalk(response->header, addHeaderString);
  46 + twalk(message->header, addHeaderString);
46 47
47 48 *string++ = '\r';
48 49 *string++ = '\n';
49 50
50   - memcpy(string, response->body, response->nbody);
  51 + if (HTTP_MESSAGE_BUFFERED == message->type) {
  52 + memcpy(string, (message->body).buffer, message->nbody);
  53 + }
51 54
52 55 return string;
53 56 }
... ...
... ... @@ -117,13 +117,13 @@ serverRun(Server this)
117 117 if (httpRequestHasKeepAlive(queue->requests[j])) {
118 118 (this->conns)[fd].keep_alive = 1;
119 119 httpHeaderAdd(
120   - &(response->header),
  120 + &(((HttpMessage)response)->header),
121 121 new(HttpHeader, "Connection", "Keep-Alive"));
122 122 }
123 123 else {
124 124 (this->conns)[fd].keep_alive = 0;
125 125 httpHeaderAdd(
126   - &(response->header),
  126 + &(((HttpMessage)response)->header),
127 127 new(HttpHeader, "Connection", "Close"));
128 128 }
129 129
... ...
  1 +/* Test program for tsearch et al.
  2 + Copyright (C) 1997, 2000, 2001 Free Software Foundation, Inc.
  3 + This file is part of the GNU C Library.
  4 +
  5 + The GNU C Library is free software; you can redistribute it and/or
  6 + modify it under the terms of the GNU Lesser General Public
  7 + License as published by the Free Software Foundation; either
  8 + version 2.1 of the License, or (at your option) any later version.
  9 +
  10 + The GNU C Library is distributed in the hope that it will be useful,
  11 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13 + Lesser General Public License for more details.
  14 +
  15 + You should have received a copy of the GNU Lesser General Public
  16 + License along with the GNU C Library; if not, write to the Free
  17 + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  18 + 02111-1307 USA. */
  19 +
  20 +#ifndef _GNU_SOURCE
  21 +# define _GNU_SOURCE 1
  22 +#endif
  23 +
  24 +#include <stdio.h>
  25 +#include <stdlib.h>
  26 +#include <string.h>
  27 +#include <search.h>
  28 +
  29 +#define SEED 0
  30 +#define BALANCED 1
  31 +#define PASSES 100
  32 +
  33 +#if BALANCED
  34 +#include <math.h>
  35 +#define SIZE 1000
  36 +#else
  37 +#define SIZE 100
  38 +#endif
  39 +
  40 +enum order
  41 +{
  42 + ascending,
  43 + descending,
  44 + randomorder
  45 +};
  46 +
  47 +enum action
  48 +{
  49 + build,
  50 + build_and_del,
  51 + delete,
  52 + find
  53 +};
  54 +
  55 +/* Set to 1 if a test is flunked. */
  56 +static int error = 0;
  57 +
  58 +/* The keys we add to the tree. */
  59 +static int x[SIZE];
  60 +
  61 +/* Pointers into the key array, possibly permutated, to define an order
  62 + for insertion/removal. */
  63 +static int y[SIZE];
  64 +
  65 +/* Flags set for each element visited during a tree walk. */
  66 +static int z[SIZE];
  67 +
  68 +/* Depths for all the elements, to check that the depth is constant for
  69 + all three visits. */
  70 +static int depths[SIZE];
  71 +
  72 +/* Maximum depth during a tree walk. */
  73 +static int max_depth;
  74 +
  75 +/* Compare two keys. */
  76 +static int
  77 +cmp_fn (const void *a, const void *b)
  78 +{
  79 + return *(const int *) a - *(const int *) b;
  80 +}
  81 +
  82 +/* Permute an array of integers. */
  83 +static void
  84 +memfry (int *string)
  85 +{
  86 + int i;
  87 +
  88 + for (i = 0; i < SIZE; ++i)
  89 + {
  90 + int32_t j;
  91 + int c;
  92 +
  93 + j = random () % SIZE;
  94 +
  95 + c = string[i];
  96 + string[i] = string[j];
  97 + string[j] = c;
  98 + }
  99 +}
  100 +
  101 +static void
  102 +walk_action (const void *nodep, const VISIT which, const int depth)
  103 +{
  104 + int key = **(int **) nodep;
  105 +
  106 + if (depth > max_depth)
  107 + max_depth = depth;
  108 + if (which == leaf || which == preorder)
  109 + {
  110 + ++z[key];
  111 + depths[key] = depth;
  112 + }
  113 + else
  114 + {
  115 + if (depths[key] != depth)
  116 + {
  117 + fputs ("Depth for one element is not constant during tree walk.\n",
  118 + stdout);
  119 + }
  120 + }
  121 +}
  122 +
  123 +static void
  124 +walk_tree (void *root, int expected_count)
  125 +{
  126 + int i;
  127 +
  128 + memset (z, 0, sizeof z);
  129 + max_depth = 0;
  130 +
  131 + twalk (root, walk_action);
  132 + for (i = 0; i < expected_count; ++i)
  133 + if (z[i] != 1)
  134 + {
  135 + fputs ("Node was not visited.\n", stdout);
  136 + error = 1;
  137 + }
  138 +
  139 +#if BALANCED
  140 + if (max_depth > log (expected_count) * 2 + 2)
  141 +#else
  142 + if (max_depth > expected_count)
  143 +#endif
  144 + {
  145 + fputs ("Depth too large during tree walk.\n", stdout);
  146 + error = 1;
  147 + }
  148 +}
  149 +
  150 +/* Perform an operation on a tree. */
  151 +static void
  152 +mangle_tree (enum order how, enum action what, void **root, int lag)
  153 +{
  154 + int i;
  155 +
  156 + if (how == randomorder)
  157 + {
  158 + for (i = 0; i < SIZE; ++i)
  159 + y[i] = i;
  160 + memfry (y);
  161 + }
  162 +
  163 + for (i = 0; i < SIZE + lag; ++i)
  164 + {
  165 + void *elem;
  166 + int j, k;
  167 +
  168 + switch (how)
  169 + {
  170 + case randomorder:
  171 + if (i >= lag)
  172 + k = y[i - lag];
  173 + else
  174 + /* Ensure that the array index is within bounds. */
  175 + k = y[(SIZE - i - 1 + lag) % SIZE];
  176 + j = y[i % SIZE];
  177 + break;
  178 +
  179 + case ascending:
  180 + k = i - lag;
  181 + j = i;
  182 + break;
  183 +
  184 + case descending:
  185 + k = SIZE - i - 1 + lag;
  186 + j = SIZE - i - 1;
  187 + break;
  188 +
  189 + default:
  190 + /* This never should happen, but gcc isn't smart enough to
  191 + recognize it. */
  192 + abort ();
  193 + }
  194 +
  195 + switch (what)
  196 + {
  197 + case build_and_del:
  198 + case build:
  199 + if (i < SIZE)
  200 + {
  201 + if (tfind (x + j, (void *const *) root, cmp_fn) != NULL)
  202 + {
  203 + fputs ("Found element which is not in tree yet.\n", stdout);
  204 + error = 1;
  205 + }
  206 + elem = tsearch (x + j, root, cmp_fn);
  207 + if (elem == 0
  208 + || tfind (x + j, (void *const *) root, cmp_fn) == NULL)
  209 + {
  210 + fputs ("Couldn't find element after it was added.\n",
  211 + stdout);
  212 + error = 1;
  213 + }
  214 + }
  215 +
  216 + if (what == build || i < lag)
  217 + break;
  218 +
  219 + j = k;
  220 + /* fall through */
  221 +
  222 + case delete:
  223 + elem = tfind (x + j, (void *const *) root, cmp_fn);
  224 + if (elem == NULL || tdelete (x + j, root, cmp_fn) == NULL)
  225 + {
  226 + fputs ("Error deleting element.\n", stdout);
  227 + error = 1;
  228 + }
  229 + break;
  230 +
  231 + case find:
  232 + if (tfind (x + j, (void *const *) root, cmp_fn) == NULL)
  233 + {
  234 + fputs ("Couldn't find element after it was added.\n", stdout);
  235 + error = 1;
  236 + }
  237 + break;
  238 +
  239 + }
  240 + }
  241 +}
  242 +
  243 +
  244 +int
  245 +main (int argc, char **argv)
  246 +{
  247 + int total_error = 0;
  248 + static char state[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  249 + void *root = NULL;
  250 + int i, j;
  251 +
  252 + initstate (SEED, state, 8);
  253 +
  254 + for (i = 0; i < SIZE; ++i)
  255 + x[i] = i;
  256 +
  257 + /* Do this loop several times to get different permutations for the
  258 + random case. */
  259 + fputs ("Series I\n", stdout);
  260 + for (i = 0; i < PASSES; ++i)
  261 + {
  262 + fprintf (stdout, "Pass %d... ", i + 1);
  263 + fflush (stdout);
  264 + error = 0;
  265 +
  266 + mangle_tree (ascending, build, &root, 0);
  267 + mangle_tree (ascending, find, &root, 0);
  268 + mangle_tree (descending, find, &root, 0);
  269 + mangle_tree (randomorder, find, &root, 0);
  270 + walk_tree (root, SIZE);
  271 + mangle_tree (ascending, delete, &root, 0);
  272 +
  273 + mangle_tree (ascending, build, &root, 0);
  274 + walk_tree (root, SIZE);
  275 + mangle_tree (descending, delete, &root, 0);
  276 +
  277 + mangle_tree (ascending, build, &root, 0);
  278 + walk_tree (root, SIZE);
  279 + mangle_tree (randomorder, delete, &root, 0);
  280 +
  281 + mangle_tree (descending, build, &root, 0);
  282 + mangle_tree (ascending, find, &root, 0);
  283 + mangle_tree (descending, find, &root, 0);
  284 + mangle_tree (randomorder, find, &root, 0);
  285 + walk_tree (root, SIZE);
  286 + mangle_tree (descending, delete, &root, 0);
  287 +
  288 + mangle_tree (descending, build, &root, 0);
  289 + walk_tree (root, SIZE);
  290 + mangle_tree (descending, delete, &root, 0);
  291 +
  292 + mangle_tree (descending, build, &root, 0);
  293 + walk_tree (root, SIZE);
  294 + mangle_tree (randomorder, delete, &root, 0);
  295 +
  296 + mangle_tree (randomorder, build, &root, 0);
  297 + mangle_tree (ascending, find, &root, 0);
  298 + mangle_tree (descending, find, &root, 0);
  299 + mangle_tree (randomorder, find, &root, 0);
  300 + walk_tree (root, SIZE);
  301 + mangle_tree (randomorder, delete, &root, 0);
  302 +
  303 + for (j = 1; j < SIZE; j *= 2)
  304 + {
  305 + mangle_tree (randomorder, build_and_del, &root, j);
  306 + }
  307 +
  308 + fputs (error ? " failed!\n" : " ok.\n", stdout);
  309 + total_error |= error;
  310 + }
  311 +
  312 + fputs ("Series II\n", stdout);
  313 + for (i = 1; i < SIZE; i *= 2)
  314 + {
  315 + fprintf (stdout, "For size %d... ", i);
  316 + fflush (stdout);
  317 + error = 0;
  318 +
  319 + mangle_tree (ascending, build_and_del, &root, i);
  320 + mangle_tree (descending, build_and_del, &root, i);
  321 + mangle_tree (ascending, build_and_del, &root, i);
  322 + mangle_tree (descending, build_and_del, &root, i);
  323 + mangle_tree (ascending, build_and_del, &root, i);
  324 + mangle_tree (descending, build_and_del, &root, i);
  325 + mangle_tree (ascending, build_and_del, &root, i);
  326 + mangle_tree (descending, build_and_del, &root, i);
  327 +
  328 + fputs (error ? " failed!\n" : " ok.\n", stdout);
  329 + total_error |= error;
  330 + }
  331 +
  332 + return total_error;
  333 +}
... ...
Please register or login to post a comment