Commit f2dbad19c684012a6ac235a253349ffe049668db

Authored by Georg Hopp
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.
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
... ...
... ... @@ -19,6 +19,7 @@ CLASS(HttpMessage) {
19 19 int handle;
20 20 char * body;
21 21 int nbody;
  22 + int dbody;
22 23 };
23 24
24 25 char httpMessageHasKeepAlive(HttpMessage);
... ...
... ... @@ -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
... ...
... ... @@ -8,8 +8,7 @@
8 8 #include "http/response/writer.h"
9 9
10 10 CLASS(HttpWorker) {
11   - char * remoteAddr;
12   - int handle;
  11 + char * id;
13 12
14 13 HttpRequestParser parser;
15 14 HttpResponseWriter writer;
... ...
... ... @@ -34,10 +34,7 @@ CLASS(Server) {
34 34
35 35 struct {
36 36 Sock sock;
37   -
38 37 void * worker;
39   -
40   - char keep_alive;
41 38 } conns[POLL_FD_NSIZE];
42 39 };
43 40
... ...
... ... @@ -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
... ...
  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:
... ...
  1 +#include <sys/types.h>
  2 +
  3 +#include "cbuf.h"
  4 +
  5 +size_t
  6 +cbufAddrIndex(Cbuf this, const void * c)
  7 +{
  8 + return c - (const void *)cbufGetRead(this);
  9 +}
  10 +
  11 +// vim: set ts=4 sw=4:
... ...
  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:
... ...
  1 +#include <sys/types.h>
  2 +
  3 +#include "cbuf.h"
  4 +
  5 +size_t
  6 +cbufGetFree(Cbuf this)
  7 +{
  8 + return this->bsize - this->bused;
  9 +}
  10 +
  11 +// vim: set ts=4 sw=4:
... ...
  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:
... ...
  1 +#include "cbuf.h"
  2 +
  3 +char *
  4 +cbufGetRead(Cbuf this)
  5 +{
  6 + return this->data + this->read;
  7 +}
  8 +
  9 +// vim: set ts=4 sw=4:
... ...
  1 +#include "cbuf.h"
  2 +
  3 +char *
  4 +cbufGetWrite(Cbuf this)
  5 +{
  6 + return this->data + this->write;
  7 +}
  8 +
  9 +// vim: set ts=4 sw=4:
... ...
  1 +#include <sys/types.h>
  2 +
  3 +#include "cbuf.h"
  4 +
  5 +void
  6 +cbufIncRead(Cbuf this, size_t n)
  7 +{
  8 + this->read += n;
  9 + this->read = (this->read >= this->bsize)?
  10 + this->read - this->bsize : this->read;
  11 + this->bused -= n;
  12 +}
  13 +
  14 +// vim: set ts=4 sw=4:
... ...
  1 +#include <sys/types.h>
  2 +
  3 +#include "cbuf.h"
  4 +
  5 +void
  6 +cbufIncWrite(Cbuf this, size_t n)
  7 +{
  8 + this->write += n;
  9 + this->write = (this->write >= this->bsize)?
  10 + this->write - this->bsize : this->write;
  11 + this->bused += n;
  12 +}
  13 +
  14 +// vim: set ts=4 sw=4:
... ...
  1 +#include "cbuf.h"
  2 +
  3 +char
  4 +cbufIsEmpty(Cbuf this)
  5 +{
  6 + return (0 == this->bused);
  7 +}
  8 +
  9 +// vim: set ts=4 sw=4:
... ...
  1 +#include <string.h>
  2 +
  3 +#include "cbuf.h"
  4 +
  5 +char *
  6 +cbufMemchr(Cbuf this, int c)
  7 +{
  8 + return memchr(cbufGetRead(this), c, this->bused);
  9 +}
  10 +
  11 +// vim: set ts=4 sw=4:
... ...
  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:
... ...
  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:
... ...
  1 +#include <ctype.h>
  2 +
  3 +#include "cbuf.h"
  4 +
  5 +void
  6 +cbufSkipNonAlpha(Cbuf this)
  7 +{
  8 + while(0 > this->bused && isalpha(*cbufGetRead(this)))
  9 + cbufIncRead(this, 1);
  10 +}
  11 +
  12 +// vim: set ts=4 sw=4:
... ...
  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 }
... ...
... ... @@ -12,8 +12,6 @@ serverCloseConn(Server this, unsigned int i)
12 12 delete(&((this->conns)[fd].sock));
13 13 delete(&((this->conns)[fd].worker));
14 14
15   - (this->conns)[fd].keep_alive = 0;
16   -
17 15 memset(&(this->fds[i]), 0, sizeof(struct pollfd));
18 16 }
19 17
... ...
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