Commit f2dbad19c684012a6ac235a253349ffe049668db
1 parent
45b4b354
another try with a shared memory based ringbuffer...this performs well for keep-…
…alive sessions but is much slower without. actually i am not sure why but most likely the shared memory setup is quite expensive. @TODO: make a profiling.
Showing
35 changed files
with
557 additions
and
223 deletions
1 | -2012-02-18 20:12:27 +0100 Georg Hopp | |
1 | +2012-02-19 11:35:15 +0100 Georg Hopp | |
2 | 2 | |
3 | - * lots of changes but primarily change the request parser to use a ringbuffer. The ringbuffer is implemented using the shared memory trick. (HEAD, master) | |
3 | + * another try with a shared memory based ringbuffer...this performs well for keep-alive sessions but is much slower without. actually i am not sure why but most likely the shared memory setup is quite expensive. @TODO: make a profiling. (HEAD, ringbuffer) | |
4 | 4 | |
5 | 5 | 2012-02-15 12:30:33 +0100 Georg Hopp |
6 | 6 | |
7 | - * some more cleanups in the server code. Removing not needed header includes (origin/master, origin/HEAD) | |
7 | + * some more cleanups in the server code. Removing not needed header includes | |
8 | 8 | |
9 | 9 | 2012-02-15 12:17:39 +0100 Georg Hopp |
10 | 10 | ... | ... |
... | ... | @@ -4,9 +4,10 @@ |
4 | 4 | #include "class.h" |
5 | 5 | #include "http/request.h" |
6 | 6 | #include "http/message/queue.h" |
7 | -#include "ringbuffer.h" | |
7 | +#include "cbuf.h" | |
8 | + | |
9 | +#define HTTP_REQUEST_PARSER_BUFFER_MAX 8192 | |
8 | 10 | |
9 | -#define HTTP_REQUEST_PARSER_MAX_BUF 131072 | |
10 | 11 | |
11 | 12 | /** |
12 | 13 | * limits to stop invalid requests from killing |
... | ... | @@ -31,7 +32,7 @@ typedef enum e_HttpRequestState { |
31 | 32 | |
32 | 33 | |
33 | 34 | CLASS(HttpRequestParser) { |
34 | - Ringbuffer buffer; | |
35 | + Cbuf buffer; | |
35 | 36 | |
36 | 37 | HttpMessageQueue request_queue; |
37 | 38 | HttpRequest cur_request; |
... | ... | @@ -41,6 +42,7 @@ CLASS(HttpRequestParser) { |
41 | 42 | |
42 | 43 | ssize_t httpRequestParserRead(HttpRequestParser, int); |
43 | 44 | ssize_t httpRequestParserParse(HttpRequestParser, int); |
45 | +void httpRequestParserGetBody(HttpRequestParser); | |
44 | 46 | |
45 | 47 | ssize_t httpRequestParserGetRequestLine(HttpRequestParser, char *); |
46 | 48 | ssize_t httpRequestParserGetHeader(HttpRequestParser, char *); | ... | ... |
1 | 1 | #ifndef __HTTP_RESPONSE_WRITER_H__ |
2 | 2 | #define __HTTP_RESPONSE_WRITER_H__ |
3 | 3 | |
4 | +#include <sys/types.h> | |
5 | + | |
4 | 6 | #include "class.h" |
5 | 7 | #include "http/response.h" |
6 | 8 | #include "http/message/queue.h" |
9 | +#include "cbuf.h" | |
7 | 10 | |
8 | 11 | #define RESPONSE_WRITER_MAX_BUF 131072 |
9 | 12 | |
... | ... | @@ -15,17 +18,15 @@ typedef enum e_HttpResponseState { |
15 | 18 | } HttpResponseState; |
16 | 19 | |
17 | 20 | CLASS(HttpResponseWriter) { |
18 | - char * pipe; | |
19 | - | |
20 | - size_t nheader; | |
21 | - size_t nbuffer; | |
22 | - size_t written; | |
23 | - size_t pstart; | |
24 | - size_t pend; | |
21 | + Cbuf buffer; | |
25 | 22 | |
26 | 23 | HttpMessageQueue response_queue; |
27 | 24 | HttpResponse cur_response; |
28 | 25 | |
26 | + size_t nheader; | |
27 | + size_t nbody; | |
28 | + size_t written; | |
29 | + | |
29 | 30 | HttpResponseState state; |
30 | 31 | }; |
31 | 32 | ... | ... |
... | ... | @@ -15,7 +15,7 @@ CLASS(Sock) { |
15 | 15 | |
16 | 16 | void socketConnect(Sock this, const char * addr); |
17 | 17 | void socketListen(Sock this, int backlog); |
18 | -Sock socketAccept(Sock this, char (*remoteAddr)[]); | |
18 | +Sock socketAccept(Sock this, char (*remoteAddr)[16]); | |
19 | 19 | |
20 | 20 | #endif // __SOCKET_H__ |
21 | 21 | ... | ... |
... | ... | @@ -9,6 +9,11 @@ RB = ringbuffer.c ringbuffer/rb_read.c |
9 | 9 | SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c |
10 | 10 | SERVER = server.c server/run.c server/close_conn.c |
11 | 11 | LOGGER = logger.c logger/stderr.c logger/syslog.c |
12 | +CB = cbuf.c cbuf/read.c cbuf/write.c \ | |
13 | + cbuf/get_line.c cbuf/set_data.c cbuf/get_data.c \ | |
14 | + cbuf/addr_index.c cbuf/get_free.c cbuf/get_read.c cbuf/get_write.c \ | |
15 | + cbuf/inc_read.c cbuf/inc_write.c cbuf/is_empty.c cbuf/memchr.c \ | |
16 | + cbuf/skip_non_alpha.c | |
12 | 17 | MSG = http/message.c http/message/queue.c http/message/has_keep_alive.c \ |
13 | 18 | http/message/header_size_get.c http/message/header_to_string.c |
14 | 19 | REQ = http/request.c |
... | ... | @@ -31,7 +36,7 @@ bin_PROGRAMS = testserver |
31 | 36 | |
32 | 37 | testserver_SOURCES = testserver.c \ |
33 | 38 | $(IFACE) $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(MSG) $(REQ) \ |
34 | - $(WRITER) $(RESP) $(HEADER) $(PARSER) $(WORKER) $(RB) \ | |
39 | + $(WRITER) $(RESP) $(HEADER) $(PARSER) $(WORKER) $(CB) \ | |
35 | 40 | signalHandling.c daemonize.c |
36 | 41 | testserver_CFLAGS = -Wall -I ../include/ |
37 | 42 | testserver_LDFLAGS = -lrt | ... | ... |
src/cbuf.c
0 → 100644
1 | +#define _POSIX_SOURCE | |
2 | +#define _POSIX_C_SOURCE 200112L | |
3 | + | |
4 | +#include <sys/types.h> | |
5 | +#include <sys/stat.h> | |
6 | +#include <sys/mman.h> | |
7 | +#include <stdarg.h> | |
8 | +#include <stdlib.h> | |
9 | +#include <stdio.h> | |
10 | +#include <unistd.h> | |
11 | +#include <fcntl.h> | |
12 | + | |
13 | +#include "class.h" | |
14 | +#include "interface/class.h" | |
15 | + | |
16 | +#include "cbuf.h" | |
17 | + | |
18 | + | |
19 | +static void dtor(void*); | |
20 | + | |
21 | +static | |
22 | +void | |
23 | +ctor(void * _this, va_list * params) | |
24 | +{ | |
25 | + Cbuf this = _this; | |
26 | + char state = 0; | |
27 | + char * shm_name = va_arg(*params, char*); | |
28 | + long psize = sysconf(_SC_PAGESIZE); | |
29 | + size_t size; | |
30 | + int shm; | |
31 | + | |
32 | + this->shm_name = malloc(strlen(shm_name) + 7 + 2); | |
33 | + sprintf(this->shm_name, "/%06d_%s", getpid(), shm_name); | |
34 | + | |
35 | + /** | |
36 | + * align size at page boundary. | |
37 | + * increase as neccessary | |
38 | + */ | |
39 | + size = va_arg(*params, size_t); | |
40 | + size = (0 >= size)? 1 : (0 != size%psize)? (size/psize)+1 : size/psize; | |
41 | + this->bsize = psize * size; | |
42 | + | |
43 | + while (0 == state) { | |
44 | + shm = shm_open(this->shm_name, O_RDWR|O_CREAT|O_EXCL, S_IRWXU); | |
45 | + if (-1 == shm) { | |
46 | + break; | |
47 | + } | |
48 | + | |
49 | + if (-1 == ftruncate(shm, this->bsize)) { | |
50 | + break; | |
51 | + } | |
52 | + | |
53 | + this->data = mmap (0, this->bsize << 1, | |
54 | + PROT_READ|PROT_WRITE, MAP_SHARED, shm, 0); | |
55 | + if (this->data == MAP_FAILED) { | |
56 | + this->data = NULL; | |
57 | + break; | |
58 | + } | |
59 | + | |
60 | + munmap(this->data + this->bsize, this->bsize); | |
61 | + | |
62 | + this->mirror = mmap (this->data + this->bsize, this->bsize, | |
63 | + PROT_READ|PROT_WRITE, MAP_SHARED, shm, 0); | |
64 | + if (this->mirror != this->data + this->bsize) { | |
65 | + if (this->mirror == this->data - this->bsize) { | |
66 | + this->data = this->mirror; | |
67 | + this->mirror += this->bsize; | |
68 | + } | |
69 | + else { | |
70 | + this->mirror = NULL; | |
71 | + break; | |
72 | + } | |
73 | + } | |
74 | + | |
75 | + state = 1; | |
76 | + } | |
77 | + | |
78 | + if (-1 != shm) { | |
79 | + shm_unlink(this->shm_name); | |
80 | + close(shm); | |
81 | + } | |
82 | + | |
83 | + if (1 != state) { | |
84 | + dtor(this); | |
85 | + } | |
86 | +} | |
87 | + | |
88 | +static | |
89 | +void | |
90 | +dtor(void * _this) | |
91 | +{ | |
92 | + Cbuf this = _this; | |
93 | + | |
94 | + if (NULL != this->shm_name) { | |
95 | + free(this->shm_name); | |
96 | + this->shm_name = NULL; | |
97 | + } | |
98 | + | |
99 | + if (NULL != this->data) { | |
100 | + munmap(this->data, this->bsize); | |
101 | + this->data = NULL; | |
102 | + } | |
103 | + | |
104 | + if (NULL != this->mirror) { | |
105 | + munmap(this->mirror, this->bsize); | |
106 | + this->mirror = NULL; | |
107 | + } | |
108 | +} | |
109 | + | |
110 | +INIT_IFACE(Class, ctor, dtor, NULL); | |
111 | +CREATE_CLASS(Cbuf, NULL, IFACE(Class)); | |
112 | + | |
113 | +// vim: set ts=4 sw=4: | ... | ... |
src/cbuf/addr_index.c
0 → 100644
src/cbuf/get_data.c
0 → 100644
1 | +#include <sys/types.h> | |
2 | +#include <string.h> | |
3 | + | |
4 | +#include "cbuf.h" | |
5 | + | |
6 | +char * | |
7 | +cbufGetData(Cbuf this, size_t n) | |
8 | +{ | |
9 | + char * ret = cbufGetRead(this); | |
10 | + | |
11 | + if (n > this->bused) { | |
12 | + return -1; | |
13 | + } | |
14 | + | |
15 | + cbufIncRead(this, n); | |
16 | + return ret; | |
17 | +} | |
18 | + | |
19 | +// vim: set ts=4 sw=4: | ... | ... |
src/cbuf/get_free.c
0 → 100644
src/cbuf/get_line.c
0 → 100644
1 | +#include <sys/types.h> | |
2 | + | |
3 | +#include <string.h> | |
4 | + | |
5 | +#include "cbuf.h" | |
6 | + | |
7 | +char * | |
8 | +cbufGetLine(Cbuf this) | |
9 | +{ | |
10 | + char * nl = cbufMemchr(this, '\n'); | |
11 | + char * ret = NULL; | |
12 | + | |
13 | + if (NULL != nl) { | |
14 | + size_t len = cbufAddrIndex(this, nl) + 1; | |
15 | + | |
16 | + *nl = 0; | |
17 | + *(nl-1) = ('\r' == *(nl-1))? 0 : *(nl-1); | |
18 | + | |
19 | + ret = cbufGetRead(this); | |
20 | + cbufIncRead(this, len); | |
21 | + } | |
22 | + | |
23 | + return ret; | |
24 | +} | |
25 | + | |
26 | +// vim: set ts=4 sw=4: | ... | ... |
src/cbuf/get_read.c
0 → 100644
src/cbuf/get_write.c
0 → 100644
src/cbuf/inc_read.c
0 → 100644
src/cbuf/inc_write.c
0 → 100644
src/cbuf/is_empty.c
0 → 100644
src/cbuf/memchr.c
0 → 100644
src/cbuf/read.c
0 → 100644
1 | +#include <sys/types.h> | |
2 | +#include <unistd.h> | |
3 | +#include <errno.h> | |
4 | + | |
5 | +#include "cbuf.h" | |
6 | + | |
7 | + | |
8 | +ssize_t | |
9 | +cbufRead(Cbuf this, int fd) | |
10 | +{ | |
11 | + ssize_t rrsize = 0; | |
12 | + size_t rsize = cbufGetFree(this); | |
13 | + | |
14 | + if (0 == rsize) { | |
15 | + errno = ECBUFOVFL; | |
16 | + return -1; | |
17 | + } | |
18 | + | |
19 | + rrsize = read(fd, cbufGetWrite(this), rsize); | |
20 | + | |
21 | + switch (rrsize) { | |
22 | + case 0: | |
23 | + rrsize = -2; | |
24 | + // DROP THROUGH | |
25 | + | |
26 | + case -1: | |
27 | + break; | |
28 | + | |
29 | + default: | |
30 | + cbufIncWrite(this, rrsize); | |
31 | + break; | |
32 | + } | |
33 | + | |
34 | + return rrsize; | |
35 | +} | |
36 | + | |
37 | +// vim: set ts=4 sw=4: | ... | ... |
src/cbuf/set_data.c
0 → 100644
1 | +#include <sys/types.h> | |
2 | +#include <string.h> | |
3 | +#include <errno.h> | |
4 | + | |
5 | +#include "cbuf.h" | |
6 | + | |
7 | +char * | |
8 | +cbufSetData(Cbuf this, const void * src, size_t n) | |
9 | +{ | |
10 | + char * addr; | |
11 | + | |
12 | + if (n > cbufGetFree(this)) { | |
13 | + errno = ECBUFOVFL; | |
14 | + return -1; | |
15 | + } | |
16 | + | |
17 | + addr = memcpy(cbufGetWrite(this), src, n); | |
18 | + cbufIncWrite(this, n); | |
19 | + | |
20 | + return addr; | |
21 | +} | |
22 | + | |
23 | +// vim: set ts=4 sw=4: | ... | ... |
src/cbuf/skip_non_alpha.c
0 → 100644
src/cbuf/write.c
0 → 100644
1 | +#include <sys/types.h> | |
2 | +#include <unistd.h> | |
3 | + | |
4 | +#include "cbuf.h" | |
5 | + | |
6 | + | |
7 | +ssize_t | |
8 | +cbufWrite(Cbuf this, int fd) | |
9 | +{ | |
10 | + ssize_t wwsize = 0; | |
11 | + size_t wsize = this->bused; | |
12 | + | |
13 | + if (0 == wsize) return 0; | |
14 | + | |
15 | + wwsize = write(fd, cbufGetRead(this), wsize); | |
16 | + | |
17 | + switch (wwsize) { | |
18 | + case -1: | |
19 | + break; | |
20 | + | |
21 | + default: | |
22 | + cbufIncRead(this, wwsize); | |
23 | + break; | |
24 | + } | |
25 | + | |
26 | + return wwsize; | |
27 | +} | |
28 | + | |
29 | +// vim: set ts=4 sw=4: | ... | ... |
1 | 1 | #include <unistd.h> |
2 | -#include <string.h> | |
2 | +#include <stdio.h> | |
3 | 3 | #include <stdlib.h> |
4 | 4 | #include <sys/types.h> |
5 | 5 | |
... | ... | @@ -10,17 +10,20 @@ |
10 | 10 | #include "http/request/parser.h" |
11 | 11 | #include "http/message/queue.h" |
12 | 12 | #include "http/request.h" |
13 | -#include "ringbuffer.h" | |
13 | +#include "cbuf.h" | |
14 | 14 | |
15 | 15 | |
16 | 16 | static |
17 | 17 | void |
18 | 18 | ctor(void * _this, va_list * params) |
19 | 19 | { |
20 | - HttpRequestParser this = _this; | |
21 | - char * shm_name = va_arg(*params, char*); | |
20 | + HttpRequestParser this = _this; | |
21 | + char * id = va_arg(*params, char*); | |
22 | + char cbuf_id[100]; | |
23 | + | |
24 | + sprintf(cbuf_id, "%s_%s", "parser", id); | |
22 | 25 | |
23 | - this->buffer = new(Ringbuffer, shm_name, HTTP_REQUEST_LINE_MAX); | |
26 | + this->buffer = new(Cbuf, cbuf_id, HTTP_REQUEST_PARSER_BUFFER_MAX); | |
24 | 27 | this->request_queue = new(HttpMessageQueue); |
25 | 28 | } |
26 | 29 | |
... | ... | @@ -37,9 +40,8 @@ dtor(void * _this) |
37 | 40 | delete(&(this->cur_request)); |
38 | 41 | } |
39 | 42 | |
40 | - | |
41 | 43 | INIT_IFACE(Class, ctor, dtor, NULL); |
42 | -INIT_IFACE(StreamReader, (fptr_streamReaderRead)httpRequestParserParse); | |
44 | +INIT_IFACE(StreamReader, (fptr_streamReaderRead)httpRequestParserRead); | |
43 | 45 | CREATE_CLASS(HttpRequestParser, NULL, IFACE(Class), IFACE(StreamReader)); |
44 | 46 | |
45 | 47 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -3,6 +3,10 @@ |
3 | 3 | #include "http/header.h" |
4 | 4 | #include "http/message.h" |
5 | 5 | #include "http/request/parser.h" |
6 | +#include "cbuf.h" | |
7 | + | |
8 | +#define MAX(a,b) (((a) > (b))? (a) : (b)) | |
9 | + | |
6 | 10 | |
7 | 11 | #define MAX(x,y) ((x) > (y) ? (x) : (y)) |
8 | 12 | |
... | ... | @@ -14,41 +18,34 @@ void |
14 | 18 | httpRequestParserGetBody(HttpRequestParser this) |
15 | 19 | { |
16 | 20 | HttpMessage message = (HttpMessage)(this->cur_request); |
17 | - char * str_nbody; | |
18 | - int nbody; | |
19 | - int len; | |
20 | - | |
21 | - str_nbody = httpHeaderGet( | |
22 | - &(message->header), | |
23 | - "Content-Length"); | |
24 | - | |
25 | - if (NULL == str_nbody) { | |
26 | - this->state = HTTP_REQUEST_DONE; | |
27 | - return -1; | |
28 | - } | |
29 | - | |
30 | - nbody = atoi(str_nbody); | |
21 | + size_t len; | |
31 | 22 | |
32 | 23 | if (0 == message->nbody) { |
33 | - message->type = HTTP_MESSAGE_BUFFERED; | |
34 | - if (0 < nbody) | |
35 | - message->body = malloc(nbody); | |
24 | + char * nbody = httpHeaderGet( | |
25 | + &(message->header), | |
26 | + "Content-Length"); | |
27 | + | |
28 | + if (NULL == nbody) { | |
29 | + this->state = HTTP_REQUEST_DONE; | |
30 | + return; | |
31 | + } | |
32 | + else { | |
33 | + message->type = HTTP_MESSAGE_BUFFERED; | |
34 | + message->nbody = atoi(nbody); | |
35 | + message->body = calloc(1, message->nbody); | |
36 | + message->dbody = 0; | |
37 | + } | |
36 | 38 | } |
39 | + this->buffer->bused -= len; | |
37 | 40 | |
38 | - len = MAX(nbody - message->nbody, this->buffer->bused); | |
39 | - memcpy(message->body + message->nbody, | |
40 | - this->buffer->buffer + this->buffer->bstart, | |
41 | - len); | |
41 | + if (message->dbody < message->nbody) { | |
42 | + len = MAX( | |
43 | + message->nbody - message->dbody, | |
44 | + this->buffer->bused); | |
42 | 45 | |
43 | - message->nbody += len; | |
44 | - this->buffer->bstart += len; | |
45 | - if (this->buffer->bstart >= this->buffer->bsize) { | |
46 | - this->buffer->bstart -= this->buffer->bsize; | |
47 | - } | |
48 | - this->buffer->bused -= len; | |
46 | + memcpy(message->body, cbufGetData(this->buffer, len), len); | |
49 | 47 | |
50 | - if (message->nbody == nbody) { | |
51 | - this->state = HTTP_REQUEST_DONE; | |
48 | + message->dbody += len; | |
52 | 49 | } |
53 | 50 | } |
54 | 51 | ... | ... |
... | ... | @@ -7,81 +7,35 @@ |
7 | 7 | #include "http/message.h" |
8 | 8 | #include "http/request/parser.h" |
9 | 9 | #include "interface/class.h" |
10 | - | |
11 | -#ifndef TRUE | |
12 | -#define TRUE 1 | |
13 | -#endif | |
14 | - | |
15 | -#ifndef FALSE | |
16 | -#define FALSE 0 | |
17 | -#endif | |
18 | - | |
19 | -static | |
20 | -inline | |
21 | -char * | |
22 | -getLine(HttpRequestParser this) | |
23 | -{ | |
24 | - char * cr = memchr( | |
25 | - this->buffer->buffer + this->buffer->bstart, | |
26 | - '\r', | |
27 | - this->buffer->bused); | |
28 | - | |
29 | - char * nl = (NULL == cr)? NULL : cr + 1; | |
30 | - | |
31 | - if (NULL != cr && NULL != nl && '\n' == *nl) { | |
32 | - *cr = 0; | |
33 | - return cr; | |
34 | - } | |
35 | - | |
36 | - return NULL; | |
37 | -} | |
38 | - | |
39 | -static | |
40 | -inline | |
41 | -char | |
42 | -httpRequestSkip(HttpRequestParser this) | |
43 | -{ | |
44 | - while (this->buffer->bused > 0 && | |
45 | - ! isalpha(this->buffer->buffer[this->buffer->bstart])) { | |
46 | - this->buffer->bstart = (this->buffer->bstart >= this->buffer->bsize)? | |
47 | - 0 : this->buffer->bstart + 1; | |
48 | - this->buffer->bused--; | |
49 | - } | |
50 | - | |
51 | - return (isalpha(this->buffer->buffer[this->buffer->bstart]))? TRUE : FALSE; | |
52 | -} | |
10 | +#include "cbuf.h" | |
53 | 11 | |
54 | 12 | ssize_t |
55 | 13 | httpRequestParserParse(HttpRequestParser this, int fd) |
56 | 14 | { |
57 | 15 | int cont = 1; |
58 | - ssize_t ret; | |
16 | + ssize_t read; | |
17 | + char * line; | |
59 | 18 | |
60 | - if (0 > (ret = rbRead(this->buffer, fd))) { | |
61 | - cont = 0; | |
19 | + if(0 > (read = cbufRead(this->buffer, fd))) { | |
20 | + return read; | |
62 | 21 | } |
63 | 22 | |
64 | 23 | while (cont) { |
65 | 24 | switch(this->state) { |
66 | - char * line_end; | |
67 | - size_t len; | |
68 | - | |
69 | 25 | case HTTP_REQUEST_GARBAGE: |
70 | - if (httpRequestSkip(this)) { | |
26 | + cbufSkipNonAlpha(this->buffer); | |
27 | + if (! cbufIsEmpty(this->buffer)) { | |
71 | 28 | this->cur_request = new(HttpRequest); |
72 | 29 | this->state = HTTP_REQUEST_START; |
73 | 30 | } |
74 | - else { | |
75 | - cont = 0; | |
76 | - } | |
77 | 31 | break; |
78 | 32 | |
79 | 33 | case HTTP_REQUEST_START: |
80 | - if (NULL == (line_end = getLine(this))) { | |
34 | + if (NULL == (line = cbufGetLine(this->buffer))) { | |
81 | 35 | cont = 0; |
82 | 36 | break; |
83 | 37 | } |
84 | - | |
38 | + | |
85 | 39 | if (0 > httpRequestParserGetRequestLine(this, line_end)) { |
86 | 40 | ret = -1; |
87 | 41 | cont = 0; |
... | ... | @@ -99,7 +53,7 @@ httpRequestParserParse(HttpRequestParser this, int fd) |
99 | 53 | break; |
100 | 54 | |
101 | 55 | case HTTP_REQUEST_REQUEST_LINE_DONE: |
102 | - if (NULL == (line_end = getLine(this))) { | |
56 | + if (NULL == (line = cbufGetLine(this->buffer))) { | |
103 | 57 | cont = 0; |
104 | 58 | break; |
105 | 59 | } |
... | ... | @@ -127,23 +81,33 @@ httpRequestParserParse(HttpRequestParser this, int fd) |
127 | 81 | break; |
128 | 82 | |
129 | 83 | case HTTP_REQUEST_HEADERS_DONE: |
130 | - /** | |
131 | - * allocate memory according to content-length. | |
132 | - * If content length is to large reject request. | |
133 | - * | |
134 | - * @FUTURE check for multipart mime and handle it | |
135 | - * with temporary file. | |
136 | - */ | |
137 | - httpRequestParserGetBody(this); | |
84 | + { | |
85 | + HttpMessage message = (HttpMessage)this->cur_request; | |
86 | + | |
87 | + httpRequestParserGetBody(this); | |
88 | + | |
89 | + if (message->dbody == message->nbody) { | |
90 | + this->state = HTTP_REQUEST_DONE; | |
91 | + } | |
92 | + } | |
138 | 93 | break; |
139 | 94 | |
140 | 95 | case HTTP_REQUEST_DONE: |
141 | 96 | this->request_queue->msgs[(this->request_queue->nmsgs)++] = |
142 | 97 | (HttpMessage)this->cur_request; |
143 | 98 | |
144 | - ret = this->request_queue->nmsgs; | |
145 | 99 | this->cur_request = NULL; |
146 | 100 | |
101 | + /** | |
102 | + * dont continue loop if input buffer is empty | |
103 | + */ | |
104 | + if (cbufIsEmpty(this->buffer)) { | |
105 | + cont = 0; | |
106 | + } | |
107 | + | |
108 | + /** | |
109 | + * prepare for next request | |
110 | + */ | |
147 | 111 | this->state = HTTP_REQUEST_GARBAGE; |
148 | 112 | |
149 | 113 | break; | ... | ... |
... | ... | @@ -14,29 +14,46 @@ |
14 | 14 | ssize_t |
15 | 15 | httpRequestParserRead(HttpRequestParser this, int fd) |
16 | 16 | { |
17 | - size_t rsize; | |
18 | - ssize_t temp; | |
19 | - | |
20 | - this->bend = (this->bsize == this->bend)? | |
21 | - 0 : this->bend; | |
22 | - | |
23 | - rsize = (this->bstart <= this->bend)? | |
24 | - this->bsize - this->bend : | |
25 | - this->bstart - 1; | |
26 | - | |
27 | - if (0 >= (temp = read(fd, &(this->buffer[this->bend]), rsize))) { | |
28 | - /** | |
29 | - * this means either we had an rsize of 0 what indicates that | |
30 | - * the buffer ran full without any processing took place or | |
31 | - * the connection was terminated in some way. In both cases | |
32 | - * we want to terminate the connection. | |
33 | - */ | |
34 | - return (0 == temp)? -2 : -1; | |
35 | - } | |
36 | - | |
37 | - this->bend += temp; | |
38 | - | |
39 | - return temp; | |
17 | + /** | |
18 | + * @obsolete | |
19 | + */ | |
20 | + return -1; | |
21 | +// size_t remaining, chunks; | |
22 | +// char buffer[1024]; | |
23 | +// | |
24 | +// ssize_t size = read(fd, buffer, 1024); | |
25 | +// | |
26 | +// if (0 < size) { | |
27 | +// remaining = this->buffer_used % HTTP_REQUEST_PARSER_READ_CHUNK; | |
28 | +// remaining = HTTP_REQUEST_PARSER_READ_CHUNK - remaining; | |
29 | +// chunks = this->buffer_used / HTTP_REQUEST_PARSER_READ_CHUNK; | |
30 | +// | |
31 | +// /** | |
32 | +// * because a division always rounds down | |
33 | +// * chunks holds exactly the currently allocated chunks if | |
34 | +// * remaining equals 0 but there is no space left. | |
35 | +// * Else chunks holds the actually allocated amount of chunks | |
36 | +// * minus 1. | |
37 | +// * For this reason chunks always has to be increased by 1. | |
38 | +// */ | |
39 | +// chunks++; | |
40 | +// | |
41 | +// if (size >= remaining) { | |
42 | +// this->buffer = | |
43 | +// realloc(this->buffer, chunks * HTTP_REQUEST_PARSER_READ_CHUNK); | |
44 | +// } | |
45 | +// | |
46 | +// memcpy(this->buffer + this->buffer_used, buffer, size); | |
47 | +// this->buffer_used += size; | |
48 | +// this->buffer[this->buffer_used] = 0; | |
49 | +// | |
50 | +// size = httpRequestParserParse(this); | |
51 | +// } | |
52 | +// else { | |
53 | +// size = (0 == size)? -2 : size; | |
54 | +// } | |
55 | +// | |
56 | +// return size; | |
40 | 57 | } |
41 | 58 | |
42 | 59 | // vim: set ts=4 sw=4: | ... | ... |
1 | 1 | #include <stdlib.h> |
2 | +#include <stdio.h> | |
2 | 3 | |
3 | 4 | #include "class.h" |
4 | 5 | #include "interface/class.h" |
... | ... | @@ -12,7 +13,12 @@ void |
12 | 13 | ctor(void * _this, va_list * params) |
13 | 14 | { |
14 | 15 | HttpResponseWriter this = _this; |
16 | + char * id = va_arg(*params, char*); | |
17 | + char cbuf_id[100]; | |
15 | 18 | |
19 | + sprintf(cbuf_id, "%s_%s", "writer", id); | |
20 | + | |
21 | + this->buffer = new(Cbuf, cbuf_id, RESPONSE_WRITER_MAX_BUF); | |
16 | 22 | this->response_queue = new(HttpMessageQueue); |
17 | 23 | } |
18 | 24 | |
... | ... | @@ -23,6 +29,7 @@ dtor(void * _this) |
23 | 29 | HttpResponseWriter this = _this; |
24 | 30 | |
25 | 31 | delete(&(this->response_queue)); |
32 | + delete(&(this->buffer)); | |
26 | 33 | |
27 | 34 | if (NULL != this->cur_response) |
28 | 35 | delete(&(this->cur_response)); | ... | ... |
... | ... | @@ -11,7 +11,9 @@ |
11 | 11 | #include "http/message.h" |
12 | 12 | #include "http/response.h" |
13 | 13 | #include "http/response/writer.h" |
14 | +#include "cbuf.h" | |
14 | 15 | |
16 | +#define MIN(x,y) ((x) < (y) ? (x) : (y)) | |
15 | 17 | #define MAX(x,y) ((x) > (y) ? (x) : (y)) |
16 | 18 | #define _PSIZE(x) (MAX((x),RESPONSE_WRITER_MAX_BUF)) |
17 | 19 | #define PSIZE _PSIZE(this->nheader+message->nbody) |
... | ... | @@ -21,7 +23,6 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd) |
21 | 23 | { |
22 | 24 | HttpMessageQueue respq = this->response_queue; |
23 | 25 | HttpMessage message = (HttpMessage)this->cur_response; |
24 | - ssize_t processed = (message)? 1 : 0; | |
25 | 26 | int cont = 1; |
26 | 27 | |
27 | 28 | while (cont) { |
... | ... | @@ -30,19 +31,13 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd) |
30 | 31 | if (NULL == this->cur_response && 0 < respq->nmsgs) { |
31 | 32 | message = respq->msgs[0]; |
32 | 33 | this->cur_response = (HttpResponse)message; |
33 | - processed++; | |
34 | 34 | |
35 | - memmove(respq->msgs, | |
36 | - &(respq->msgs[1]), | |
37 | - sizeof(void*) * (--respq->nmsgs + 1)); | |
38 | - | |
39 | - this->nbuffer = 0; | |
40 | 35 | this->written = 0; |
41 | - this->pstart = 0; | |
36 | + this->nbody = 0; | |
42 | 37 | this->nheader = httpMessageHeaderSizeGet(message); |
43 | - this->pend = this->nheader; | |
44 | - this->pipe = malloc(PSIZE); | |
45 | - httpMessageHeaderToString(message, this->pipe); | |
38 | + | |
39 | + httpMessageHeaderToString(message, cbufGetWrite(this->buffer)); | |
40 | + cbufIncWrite(this->buffer, this->nheader); | |
46 | 41 | |
47 | 42 | this->state = HTTP_RESPONSE_WRITE; |
48 | 43 | } |
... | ... | @@ -55,57 +50,41 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd) |
55 | 50 | /** |
56 | 51 | * read |
57 | 52 | */ |
58 | - if (this->nbuffer < message->nbody) { | |
59 | - size_t temp = 0; | |
60 | - size_t rsize; | |
61 | - | |
62 | - this->pend = (PSIZE == this->pend)? | |
63 | - 0 : this->pend; | |
64 | - | |
65 | - rsize = (this->pstart <= this->pend)? | |
66 | - PSIZE - this->pend : | |
67 | - this->pstart - 1; | |
53 | + if (this->nbody < message->nbody) { | |
54 | + size_t size = MIN( | |
55 | + message->nbody - this->nbody, | |
56 | + cbufGetFree(this->buffer)); | |
68 | 57 | |
69 | 58 | switch (message->type) { |
70 | 59 | case HTTP_MESSAGE_BUFFERED: |
71 | - temp = message->nbody - this->nbuffer; | |
72 | - temp = (rsize<temp)? rsize : temp; | |
73 | - memcpy( | |
74 | - &(this->pipe[this->pend]), | |
75 | - &(message->body[this->nbuffer]), | |
76 | - temp); | |
60 | + cbufSetData(this->buffer, | |
61 | + message->body + this->nbody, | |
62 | + size); | |
77 | 63 | break; |
78 | 64 | |
79 | 65 | case HTTP_MESSAGE_PIPED: |
80 | - temp = read( | |
81 | - message->handle, | |
82 | - &(this->pipe[this->pend]), | |
83 | - rsize); | |
66 | + size = cbufRead(this->buffer, message->handle); | |
84 | 67 | break; |
68 | + | |
69 | + default: | |
70 | + return -1; | |
85 | 71 | } |
86 | 72 | |
87 | - this->nbuffer += temp; | |
88 | - this->pend += temp; | |
73 | + this->nbody += size; | |
89 | 74 | } |
90 | 75 | |
91 | 76 | /** |
92 | 77 | * write |
93 | 78 | */ |
94 | 79 | { |
95 | - size_t wsize; | |
96 | - size_t temp; | |
97 | - | |
98 | - wsize = (this->pstart <= this->pend)? | |
99 | - this->pend - this->pstart : | |
100 | - PSIZE - this->pstart; | |
80 | + ssize_t written = cbufWrite(this->buffer, fd); | |
101 | 81 | |
102 | - temp = write(fd, &(this->pipe[this->pstart]), wsize); | |
103 | - | |
104 | - this->written += temp; | |
105 | - this->pstart += temp; | |
106 | - | |
107 | - this->pstart = (PSIZE == this->pstart)? | |
108 | - 0 : this->pstart; | |
82 | + if (0 <= written) { | |
83 | + this->written += written; | |
84 | + } | |
85 | + else { | |
86 | + return -1; | |
87 | + } | |
109 | 88 | } |
110 | 89 | |
111 | 90 | if (this->written == message->nbody + this->nheader) { |
... | ... | @@ -121,33 +100,30 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd) |
121 | 100 | close(message->handle); |
122 | 101 | } |
123 | 102 | |
124 | - free(this->pipe); | |
103 | + this->state = HTTP_RESPONSE_GET; | |
125 | 104 | |
126 | - this->nheader = 0; | |
127 | - this->nbuffer = 0; | |
128 | - this->written = 0; | |
129 | - this->pstart = 0; | |
130 | - this->pend = 0; | |
105 | + memmove(respq->msgs, | |
106 | + &(respq->msgs[1]), | |
107 | + sizeof(void*) * (--respq->nmsgs + 1)); | |
131 | 108 | |
132 | 109 | if (! httpMessageHasKeepAlive(message)) { |
133 | 110 | /** |
134 | 111 | * if the message did not have the keep-alive feature |
135 | 112 | * we don't care about further pipelined messages and |
136 | - * return the to caller with a 0 indicating that the | |
113 | + * return to the caller with a 0 indicating that the | |
137 | 114 | * underlying connection should be closed. |
138 | 115 | */ |
139 | - processed = 0; | |
140 | - cont = 0; | |
116 | + delete(&this->cur_response); | |
117 | + return -1; | |
141 | 118 | } |
142 | 119 | |
143 | 120 | delete(&this->cur_response); |
144 | 121 | |
145 | - this->state = HTTP_RESPONSE_GET; | |
146 | 122 | break; |
147 | 123 | } |
148 | 124 | } |
149 | 125 | |
150 | - return processed; | |
126 | + return respq->nmsgs; | |
151 | 127 | } |
152 | 128 | |
153 | 129 | // vim: set ts=4 sw=4: | ... | ... |
1 | 1 | #include <stdlib.h> |
2 | 2 | #include <stdarg.h> |
3 | +#include <stdlib.h> | |
3 | 4 | #include <string.h> |
4 | 5 | |
5 | 6 | #include "class.h" |
... | ... | @@ -17,14 +18,13 @@ void |
17 | 18 | ctor(void * _this, va_list * params) |
18 | 19 | { |
19 | 20 | HttpWorker this = _this; |
20 | - char id[sizeof(SHMN) + 15 + 5]; | |
21 | + char * id = va_arg(*params, char *); | |
21 | 22 | |
22 | - this->remoteAddr = va_arg(*params, char *); | |
23 | - this->handle = va_arg(*params, int); | |
24 | - sprintf(id, SHMN "%s_%05d", this->remoteAddr, this->handle); | |
23 | + this->id = malloc(strlen(id) + 1); | |
24 | + strcpy(this->id, id); | |
25 | 25 | |
26 | - this->parser = new(HttpRequestParser, id); | |
27 | - this->writer = new(HttpResponseWriter); | |
26 | + this->parser = new(HttpRequestParser, this->id); | |
27 | + this->writer = new(HttpResponseWriter, this->id); | |
28 | 28 | } |
29 | 29 | |
30 | 30 | static |
... | ... | @@ -33,6 +33,8 @@ dtor(void * _this) |
33 | 33 | { |
34 | 34 | HttpWorker this = _this; |
35 | 35 | |
36 | + free(this->id); | |
37 | + | |
36 | 38 | delete(&this->parser); |
37 | 39 | delete(&this->writer); |
38 | 40 | } | ... | ... |
1 | 1 | #include <errno.h> |
2 | +#include <stdio.h> | |
3 | + | |
4 | +#include "http/worker.h" | |
5 | + | |
2 | 6 | |
3 | 7 | #include "http/worker.h" |
4 | 8 | |
... | ... | @@ -12,11 +16,15 @@ serverHandleAccept(Server this) |
12 | 16 | acc = socketAccept(this->sock, &remoteAddr); |
13 | 17 | |
14 | 18 | if (-1 != acc->handle) { |
19 | + char id[21]; | |
20 | + | |
21 | + sprintf(id, "my_%s_%05d", remoteAddr, acc->handle); | |
22 | + | |
15 | 23 | //* save the socket handle |
16 | 24 | (this->conns)[acc->handle].sock = acc; |
17 | 25 | |
18 | 26 | //* clone reader |
19 | - (this->conns)[acc->handle].worker = new(HttpWorker, remoteAddr, acc->handle); | |
27 | + (this->conns)[acc->handle].worker = new(HttpWorker, id); | |
20 | 28 | |
21 | 29 | (this->fds)[this->nfds].fd = acc->handle; |
22 | 30 | (this->fds)[this->nfds].events = POLLIN; | ... | ... |
... | ... | @@ -62,12 +62,12 @@ serverRun(Server this) |
62 | 62 | nreads--; |
63 | 63 | |
64 | 64 | switch (serverRead(this, i)) { |
65 | - case -2: | |
66 | - case -1: | |
67 | - serverCloseConn(this, i); | |
65 | + case 0: | |
68 | 66 | break; |
69 | 67 | |
70 | - case 0: | |
68 | + case -1: | |
69 | + case -2: | |
70 | + serverCloseConn(this, i); | |
71 | 71 | break; |
72 | 72 | |
73 | 73 | default: |
... | ... | @@ -80,14 +80,24 @@ serverRun(Server this) |
80 | 80 | * handle writes |
81 | 81 | */ |
82 | 82 | if (0 != ((this->fds)[i].revents & POLLOUT) && 0 < nwrites) { |
83 | + size_t remaining; | |
84 | + | |
83 | 85 | events--; |
84 | 86 | nwrites--; |
85 | 87 | |
86 | - if (0 >= streamWriterWrite((this->conns)[fd].worker, fd)) { | |
87 | - serverCloseConn(this, i); | |
88 | - } | |
88 | + remaining = streamWriterWrite((this->conns)[fd].worker, fd); | |
89 | + switch(remaining) { | |
90 | + case -1: | |
91 | + serverCloseConn(this, i); | |
92 | + break; | |
93 | + | |
94 | + case 0: | |
95 | + (this->fds)[i].events &= ~POLLOUT; | |
96 | + break; | |
89 | 97 | |
90 | - (this->fds)[i].events &= ~POLLOUT; | |
98 | + default: | |
99 | + break; | |
100 | + } | |
91 | 101 | } |
92 | 102 | } |
93 | 103 | } | ... | ... |
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 | #include "interface/logger.h" |
7 | 7 | |
8 | 8 | Sock |
9 | -socketAccept(Sock this, char (*remoteAddr)[]) | |
9 | +socketAccept(Sock this, char (*remoteAddr)[16]) | |
10 | 10 | { |
11 | 11 | Sock sock; /* Socket for client */ |
12 | 12 | unsigned int len; /* Length of client address data structure */ |
... | ... | @@ -33,7 +33,8 @@ socketAccept(Sock this, char (*remoteAddr)[]) |
33 | 33 | loggerLog(this->log, LOGGER_WARNING, |
34 | 34 | "error accepting connection: %s", strerror(errno)); |
35 | 35 | } else { |
36 | - memcpy(*remoteAddr, inet_ntoa((sock->addr).sin_addr), 15); | |
36 | + strcpy(*remoteAddr, inet_ntoa((sock->addr).sin_addr)); | |
37 | + | |
37 | 38 | loggerLog(this->log, LOGGER_INFO, |
38 | 39 | "handling client %s\n", *remoteAddr); |
39 | 40 | } | ... | ... |
... | ... | @@ -19,8 +19,8 @@ int |
19 | 19 | main() |
20 | 20 | { |
21 | 21 | Logger logger = new(LoggerSyslog, LOGGER_ERR); |
22 | - HttpWorker worker = new(HttpWorker, "", 0); | |
23 | - Server server = new(Server, logger, worker, 11212, SOMAXCONN); | |
22 | + //HttpWorker worker = new(HttpWorker); | |
23 | + Server server = new(Server, logger, NULL /*worker*/, 11212, SOMAXCONN); | |
24 | 24 | |
25 | 25 | struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY}; |
26 | 26 | setrlimit(RLIMIT_CPU, &limit); |
... | ... | @@ -30,7 +30,7 @@ main() |
30 | 30 | serverRun(server); |
31 | 31 | |
32 | 32 | delete(&server); |
33 | - delete(&worker); | |
33 | +// delete(&worker); | |
34 | 34 | delete(&logger); |
35 | 35 | |
36 | 36 | return 0; | ... | ... |
Please
register
or
login
to post a comment