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 2012-02-15 12:30:33 +0100 Georg Hopp 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 2012-02-15 12:17:39 +0100 Georg Hopp 9 2012-02-15 12:17:39 +0100 Georg Hopp
10 10
@@ -19,6 +19,7 @@ CLASS(HttpMessage) { @@ -19,6 +19,7 @@ CLASS(HttpMessage) {
19 int handle; 19 int handle;
20 char * body; 20 char * body;
21 int nbody; 21 int nbody;
  22 + int dbody;
22 }; 23 };
23 24
24 char httpMessageHasKeepAlive(HttpMessage); 25 char httpMessageHasKeepAlive(HttpMessage);
@@ -4,9 +4,10 @@ @@ -4,9 +4,10 @@
4 #include "class.h" 4 #include "class.h"
5 #include "http/request.h" 5 #include "http/request.h"
6 #include "http/message/queue.h" 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 * limits to stop invalid requests from killing 13 * limits to stop invalid requests from killing
@@ -31,7 +32,7 @@ typedef enum e_HttpRequestState { @@ -31,7 +32,7 @@ typedef enum e_HttpRequestState {
31 32
32 33
33 CLASS(HttpRequestParser) { 34 CLASS(HttpRequestParser) {
34 - Ringbuffer buffer; 35 + Cbuf buffer;
35 36
36 HttpMessageQueue request_queue; 37 HttpMessageQueue request_queue;
37 HttpRequest cur_request; 38 HttpRequest cur_request;
@@ -41,6 +42,7 @@ CLASS(HttpRequestParser) { @@ -41,6 +42,7 @@ CLASS(HttpRequestParser) {
41 42
42 ssize_t httpRequestParserRead(HttpRequestParser, int); 43 ssize_t httpRequestParserRead(HttpRequestParser, int);
43 ssize_t httpRequestParserParse(HttpRequestParser, int); 44 ssize_t httpRequestParserParse(HttpRequestParser, int);
  45 +void httpRequestParserGetBody(HttpRequestParser);
44 46
45 ssize_t httpRequestParserGetRequestLine(HttpRequestParser, char *); 47 ssize_t httpRequestParserGetRequestLine(HttpRequestParser, char *);
46 ssize_t httpRequestParserGetHeader(HttpRequestParser, char *); 48 ssize_t httpRequestParserGetHeader(HttpRequestParser, char *);
1 #ifndef __HTTP_RESPONSE_WRITER_H__ 1 #ifndef __HTTP_RESPONSE_WRITER_H__
2 #define __HTTP_RESPONSE_WRITER_H__ 2 #define __HTTP_RESPONSE_WRITER_H__
3 3
  4 +#include <sys/types.h>
  5 +
4 #include "class.h" 6 #include "class.h"
5 #include "http/response.h" 7 #include "http/response.h"
6 #include "http/message/queue.h" 8 #include "http/message/queue.h"
  9 +#include "cbuf.h"
7 10
8 #define RESPONSE_WRITER_MAX_BUF 131072 11 #define RESPONSE_WRITER_MAX_BUF 131072
9 12
@@ -15,17 +18,15 @@ typedef enum e_HttpResponseState { @@ -15,17 +18,15 @@ typedef enum e_HttpResponseState {
15 } HttpResponseState; 18 } HttpResponseState;
16 19
17 CLASS(HttpResponseWriter) { 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 HttpMessageQueue response_queue; 23 HttpMessageQueue response_queue;
27 HttpResponse cur_response; 24 HttpResponse cur_response;
28 25
  26 + size_t nheader;
  27 + size_t nbody;
  28 + size_t written;
  29 +
29 HttpResponseState state; 30 HttpResponseState state;
30 }; 31 };
31 32
@@ -8,8 +8,7 @@ @@ -8,8 +8,7 @@
8 #include "http/response/writer.h" 8 #include "http/response/writer.h"
9 9
10 CLASS(HttpWorker) { 10 CLASS(HttpWorker) {
11 - char * remoteAddr;  
12 - int handle; 11 + char * id;
13 12
14 HttpRequestParser parser; 13 HttpRequestParser parser;
15 HttpResponseWriter writer; 14 HttpResponseWriter writer;
@@ -34,10 +34,7 @@ CLASS(Server) { @@ -34,10 +34,7 @@ CLASS(Server) {
34 34
35 struct { 35 struct {
36 Sock sock; 36 Sock sock;
37 -  
38 void * worker; 37 void * worker;
39 -  
40 - char keep_alive;  
41 } conns[POLL_FD_NSIZE]; 38 } conns[POLL_FD_NSIZE];
42 }; 39 };
43 40
@@ -15,7 +15,7 @@ CLASS(Sock) { @@ -15,7 +15,7 @@ CLASS(Sock) {
15 15
16 void socketConnect(Sock this, const char * addr); 16 void socketConnect(Sock this, const char * addr);
17 void socketListen(Sock this, int backlog); 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 #endif // __SOCKET_H__ 20 #endif // __SOCKET_H__
21 21
@@ -9,6 +9,11 @@ RB = ringbuffer.c ringbuffer/rb_read.c @@ -9,6 +9,11 @@ RB = ringbuffer.c ringbuffer/rb_read.c
9 SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c 9 SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c
10 SERVER = server.c server/run.c server/close_conn.c 10 SERVER = server.c server/run.c server/close_conn.c
11 LOGGER = logger.c logger/stderr.c logger/syslog.c 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 MSG = http/message.c http/message/queue.c http/message/has_keep_alive.c \ 17 MSG = http/message.c http/message/queue.c http/message/has_keep_alive.c \
13 http/message/header_size_get.c http/message/header_to_string.c 18 http/message/header_size_get.c http/message/header_to_string.c
14 REQ = http/request.c 19 REQ = http/request.c
@@ -31,7 +36,7 @@ bin_PROGRAMS = testserver @@ -31,7 +36,7 @@ bin_PROGRAMS = testserver
31 36
32 testserver_SOURCES = testserver.c \ 37 testserver_SOURCES = testserver.c \
33 $(IFACE) $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(MSG) $(REQ) \ 38 $(IFACE) $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(MSG) $(REQ) \
34 - $(WRITER) $(RESP) $(HEADER) $(PARSER) $(WORKER) $(RB) \ 39 + $(WRITER) $(RESP) $(HEADER) $(PARSER) $(WORKER) $(CB) \
35 signalHandling.c daemonize.c 40 signalHandling.c daemonize.c
36 testserver_CFLAGS = -Wall -I ../include/ 41 testserver_CFLAGS = -Wall -I ../include/
37 testserver_LDFLAGS = -lrt 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 #include <unistd.h> 1 #include <unistd.h>
2 -#include <string.h> 2 +#include <stdio.h>
3 #include <stdlib.h> 3 #include <stdlib.h>
4 #include <sys/types.h> 4 #include <sys/types.h>
5 5
@@ -10,17 +10,20 @@ @@ -10,17 +10,20 @@
10 #include "http/request/parser.h" 10 #include "http/request/parser.h"
11 #include "http/message/queue.h" 11 #include "http/message/queue.h"
12 #include "http/request.h" 12 #include "http/request.h"
13 -#include "ringbuffer.h" 13 +#include "cbuf.h"
14 14
15 15
16 static 16 static
17 void 17 void
18 ctor(void * _this, va_list * params) 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 this->request_queue = new(HttpMessageQueue); 27 this->request_queue = new(HttpMessageQueue);
25 } 28 }
26 29
@@ -37,9 +40,8 @@ dtor(void * _this) @@ -37,9 +40,8 @@ dtor(void * _this)
37 delete(&(this->cur_request)); 40 delete(&(this->cur_request));
38 } 41 }
39 42
40 -  
41 INIT_IFACE(Class, ctor, dtor, NULL); 43 INIT_IFACE(Class, ctor, dtor, NULL);
42 -INIT_IFACE(StreamReader, (fptr_streamReaderRead)httpRequestParserParse); 44 +INIT_IFACE(StreamReader, (fptr_streamReaderRead)httpRequestParserRead);
43 CREATE_CLASS(HttpRequestParser, NULL, IFACE(Class), IFACE(StreamReader)); 45 CREATE_CLASS(HttpRequestParser, NULL, IFACE(Class), IFACE(StreamReader));
44 46
45 // vim: set ts=4 sw=4: 47 // vim: set ts=4 sw=4:
@@ -3,6 +3,10 @@ @@ -3,6 +3,10 @@
3 #include "http/header.h" 3 #include "http/header.h"
4 #include "http/message.h" 4 #include "http/message.h"
5 #include "http/request/parser.h" 5 #include "http/request/parser.h"
  6 +#include "cbuf.h"
  7 +
  8 +#define MAX(a,b) (((a) > (b))? (a) : (b))
  9 +
6 10
7 #define MAX(x,y) ((x) > (y) ? (x) : (y)) 11 #define MAX(x,y) ((x) > (y) ? (x) : (y))
8 12
@@ -14,41 +18,34 @@ void @@ -14,41 +18,34 @@ void
14 httpRequestParserGetBody(HttpRequestParser this) 18 httpRequestParserGetBody(HttpRequestParser this)
15 { 19 {
16 HttpMessage message = (HttpMessage)(this->cur_request); 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 if (0 == message->nbody) { 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,81 +7,35 @@
7 #include "http/message.h" 7 #include "http/message.h"
8 #include "http/request/parser.h" 8 #include "http/request/parser.h"
9 #include "interface/class.h" 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 ssize_t 12 ssize_t
55 httpRequestParserParse(HttpRequestParser this, int fd) 13 httpRequestParserParse(HttpRequestParser this, int fd)
56 { 14 {
57 int cont = 1; 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 while (cont) { 23 while (cont) {
65 switch(this->state) { 24 switch(this->state) {
66 - char * line_end;  
67 - size_t len;  
68 -  
69 case HTTP_REQUEST_GARBAGE: 25 case HTTP_REQUEST_GARBAGE:
70 - if (httpRequestSkip(this)) { 26 + cbufSkipNonAlpha(this->buffer);
  27 + if (! cbufIsEmpty(this->buffer)) {
71 this->cur_request = new(HttpRequest); 28 this->cur_request = new(HttpRequest);
72 this->state = HTTP_REQUEST_START; 29 this->state = HTTP_REQUEST_START;
73 } 30 }
74 - else {  
75 - cont = 0;  
76 - }  
77 break; 31 break;
78 32
79 case HTTP_REQUEST_START: 33 case HTTP_REQUEST_START:
80 - if (NULL == (line_end = getLine(this))) { 34 + if (NULL == (line = cbufGetLine(this->buffer))) {
81 cont = 0; 35 cont = 0;
82 break; 36 break;
83 } 37 }
84 - 38 +
85 if (0 > httpRequestParserGetRequestLine(this, line_end)) { 39 if (0 > httpRequestParserGetRequestLine(this, line_end)) {
86 ret = -1; 40 ret = -1;
87 cont = 0; 41 cont = 0;
@@ -99,7 +53,7 @@ httpRequestParserParse(HttpRequestParser this, int fd) @@ -99,7 +53,7 @@ httpRequestParserParse(HttpRequestParser this, int fd)
99 break; 53 break;
100 54
101 case HTTP_REQUEST_REQUEST_LINE_DONE: 55 case HTTP_REQUEST_REQUEST_LINE_DONE:
102 - if (NULL == (line_end = getLine(this))) { 56 + if (NULL == (line = cbufGetLine(this->buffer))) {
103 cont = 0; 57 cont = 0;
104 break; 58 break;
105 } 59 }
@@ -127,23 +81,33 @@ httpRequestParserParse(HttpRequestParser this, int fd) @@ -127,23 +81,33 @@ httpRequestParserParse(HttpRequestParser this, int fd)
127 break; 81 break;
128 82
129 case HTTP_REQUEST_HEADERS_DONE: 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 break; 93 break;
139 94
140 case HTTP_REQUEST_DONE: 95 case HTTP_REQUEST_DONE:
141 this->request_queue->msgs[(this->request_queue->nmsgs)++] = 96 this->request_queue->msgs[(this->request_queue->nmsgs)++] =
142 (HttpMessage)this->cur_request; 97 (HttpMessage)this->cur_request;
143 98
144 - ret = this->request_queue->nmsgs;  
145 this->cur_request = NULL; 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 this->state = HTTP_REQUEST_GARBAGE; 111 this->state = HTTP_REQUEST_GARBAGE;
148 112
149 break; 113 break;
@@ -14,29 +14,46 @@ @@ -14,29 +14,46 @@
14 ssize_t 14 ssize_t
15 httpRequestParserRead(HttpRequestParser this, int fd) 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 // vim: set ts=4 sw=4: 59 // vim: set ts=4 sw=4:
1 #include <stdlib.h> 1 #include <stdlib.h>
  2 +#include <stdio.h>
2 3
3 #include "class.h" 4 #include "class.h"
4 #include "interface/class.h" 5 #include "interface/class.h"
@@ -12,7 +13,12 @@ void @@ -12,7 +13,12 @@ void
12 ctor(void * _this, va_list * params) 13 ctor(void * _this, va_list * params)
13 { 14 {
14 HttpResponseWriter this = _this; 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 this->response_queue = new(HttpMessageQueue); 22 this->response_queue = new(HttpMessageQueue);
17 } 23 }
18 24
@@ -23,6 +29,7 @@ dtor(void * _this) @@ -23,6 +29,7 @@ dtor(void * _this)
23 HttpResponseWriter this = _this; 29 HttpResponseWriter this = _this;
24 30
25 delete(&(this->response_queue)); 31 delete(&(this->response_queue));
  32 + delete(&(this->buffer));
26 33
27 if (NULL != this->cur_response) 34 if (NULL != this->cur_response)
28 delete(&(this->cur_response)); 35 delete(&(this->cur_response));
@@ -11,7 +11,9 @@ @@ -11,7 +11,9 @@
11 #include "http/message.h" 11 #include "http/message.h"
12 #include "http/response.h" 12 #include "http/response.h"
13 #include "http/response/writer.h" 13 #include "http/response/writer.h"
  14 +#include "cbuf.h"
14 15
  16 +#define MIN(x,y) ((x) < (y) ? (x) : (y))
15 #define MAX(x,y) ((x) > (y) ? (x) : (y)) 17 #define MAX(x,y) ((x) > (y) ? (x) : (y))
16 #define _PSIZE(x) (MAX((x),RESPONSE_WRITER_MAX_BUF)) 18 #define _PSIZE(x) (MAX((x),RESPONSE_WRITER_MAX_BUF))
17 #define PSIZE _PSIZE(this->nheader+message->nbody) 19 #define PSIZE _PSIZE(this->nheader+message->nbody)
@@ -21,7 +23,6 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd) @@ -21,7 +23,6 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd)
21 { 23 {
22 HttpMessageQueue respq = this->response_queue; 24 HttpMessageQueue respq = this->response_queue;
23 HttpMessage message = (HttpMessage)this->cur_response; 25 HttpMessage message = (HttpMessage)this->cur_response;
24 - ssize_t processed = (message)? 1 : 0;  
25 int cont = 1; 26 int cont = 1;
26 27
27 while (cont) { 28 while (cont) {
@@ -30,19 +31,13 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd) @@ -30,19 +31,13 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd)
30 if (NULL == this->cur_response && 0 < respq->nmsgs) { 31 if (NULL == this->cur_response && 0 < respq->nmsgs) {
31 message = respq->msgs[0]; 32 message = respq->msgs[0];
32 this->cur_response = (HttpResponse)message; 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 this->written = 0; 35 this->written = 0;
41 - this->pstart = 0; 36 + this->nbody = 0;
42 this->nheader = httpMessageHeaderSizeGet(message); 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 this->state = HTTP_RESPONSE_WRITE; 42 this->state = HTTP_RESPONSE_WRITE;
48 } 43 }
@@ -55,57 +50,41 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd) @@ -55,57 +50,41 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd)
55 /** 50 /**
56 * read 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 switch (message->type) { 58 switch (message->type) {
70 case HTTP_MESSAGE_BUFFERED: 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 break; 63 break;
78 64
79 case HTTP_MESSAGE_PIPED: 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 break; 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 * write 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 if (this->written == message->nbody + this->nheader) { 90 if (this->written == message->nbody + this->nheader) {
@@ -121,33 +100,30 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd) @@ -121,33 +100,30 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd)
121 close(message->handle); 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 if (! httpMessageHasKeepAlive(message)) { 109 if (! httpMessageHasKeepAlive(message)) {
133 /** 110 /**
134 * if the message did not have the keep-alive feature 111 * if the message did not have the keep-alive feature
135 * we don't care about further pipelined messages and 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 * underlying connection should be closed. 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 delete(&this->cur_response); 120 delete(&this->cur_response);
144 121
145 - this->state = HTTP_RESPONSE_GET;  
146 break; 122 break;
147 } 123 }
148 } 124 }
149 125
150 - return processed; 126 + return respq->nmsgs;
151 } 127 }
152 128
153 // vim: set ts=4 sw=4: 129 // vim: set ts=4 sw=4:
1 #include <stdlib.h> 1 #include <stdlib.h>
2 #include <stdarg.h> 2 #include <stdarg.h>
  3 +#include <stdlib.h>
3 #include <string.h> 4 #include <string.h>
4 5
5 #include "class.h" 6 #include "class.h"
@@ -17,14 +18,13 @@ void @@ -17,14 +18,13 @@ void
17 ctor(void * _this, va_list * params) 18 ctor(void * _this, va_list * params)
18 { 19 {
19 HttpWorker this = _this; 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 static 30 static
@@ -33,6 +33,8 @@ dtor(void * _this) @@ -33,6 +33,8 @@ dtor(void * _this)
33 { 33 {
34 HttpWorker this = _this; 34 HttpWorker this = _this;
35 35
  36 + free(this->id);
  37 +
36 delete(&this->parser); 38 delete(&this->parser);
37 delete(&this->writer); 39 delete(&this->writer);
38 } 40 }
@@ -12,8 +12,6 @@ serverCloseConn(Server this, unsigned int i) @@ -12,8 +12,6 @@ serverCloseConn(Server this, unsigned int i)
12 delete(&((this->conns)[fd].sock)); 12 delete(&((this->conns)[fd].sock));
13 delete(&((this->conns)[fd].worker)); 13 delete(&((this->conns)[fd].worker));
14 14
15 - (this->conns)[fd].keep_alive = 0;  
16 -  
17 memset(&(this->fds[i]), 0, sizeof(struct pollfd)); 15 memset(&(this->fds[i]), 0, sizeof(struct pollfd));
18 } 16 }
19 17
1 #include <errno.h> 1 #include <errno.h>
  2 +#include <stdio.h>
  3 +
  4 +#include "http/worker.h"
  5 +
2 6
3 #include "http/worker.h" 7 #include "http/worker.h"
4 8
@@ -12,11 +16,15 @@ serverHandleAccept(Server this) @@ -12,11 +16,15 @@ serverHandleAccept(Server this)
12 acc = socketAccept(this->sock, &remoteAddr); 16 acc = socketAccept(this->sock, &remoteAddr);
13 17
14 if (-1 != acc->handle) { 18 if (-1 != acc->handle) {
  19 + char id[21];
  20 +
  21 + sprintf(id, "my_%s_%05d", remoteAddr, acc->handle);
  22 +
15 //* save the socket handle 23 //* save the socket handle
16 (this->conns)[acc->handle].sock = acc; 24 (this->conns)[acc->handle].sock = acc;
17 25
18 //* clone reader 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 (this->fds)[this->nfds].fd = acc->handle; 29 (this->fds)[this->nfds].fd = acc->handle;
22 (this->fds)[this->nfds].events = POLLIN; 30 (this->fds)[this->nfds].events = POLLIN;
@@ -62,12 +62,12 @@ serverRun(Server this) @@ -62,12 +62,12 @@ serverRun(Server this)
62 nreads--; 62 nreads--;
63 63
64 switch (serverRead(this, i)) { 64 switch (serverRead(this, i)) {
65 - case -2:  
66 - case -1:  
67 - serverCloseConn(this, i); 65 + case 0:
68 break; 66 break;
69 67
70 - case 0: 68 + case -1:
  69 + case -2:
  70 + serverCloseConn(this, i);
71 break; 71 break;
72 72
73 default: 73 default:
@@ -80,14 +80,24 @@ serverRun(Server this) @@ -80,14 +80,24 @@ serverRun(Server this)
80 * handle writes 80 * handle writes
81 */ 81 */
82 if (0 != ((this->fds)[i].revents & POLLOUT) && 0 < nwrites) { 82 if (0 != ((this->fds)[i].revents & POLLOUT) && 0 < nwrites) {
  83 + size_t remaining;
  84 +
83 events--; 85 events--;
84 nwrites--; 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,7 +6,7 @@
6 #include "interface/logger.h" 6 #include "interface/logger.h"
7 7
8 Sock 8 Sock
9 -socketAccept(Sock this, char (*remoteAddr)[]) 9 +socketAccept(Sock this, char (*remoteAddr)[16])
10 { 10 {
11 Sock sock; /* Socket for client */ 11 Sock sock; /* Socket for client */
12 unsigned int len; /* Length of client address data structure */ 12 unsigned int len; /* Length of client address data structure */
@@ -33,7 +33,8 @@ socketAccept(Sock this, char (*remoteAddr)[]) @@ -33,7 +33,8 @@ socketAccept(Sock this, char (*remoteAddr)[])
33 loggerLog(this->log, LOGGER_WARNING, 33 loggerLog(this->log, LOGGER_WARNING,
34 "error accepting connection: %s", strerror(errno)); 34 "error accepting connection: %s", strerror(errno));
35 } else { 35 } else {
36 - memcpy(*remoteAddr, inet_ntoa((sock->addr).sin_addr), 15); 36 + strcpy(*remoteAddr, inet_ntoa((sock->addr).sin_addr));
  37 +
37 loggerLog(this->log, LOGGER_INFO, 38 loggerLog(this->log, LOGGER_INFO,
38 "handling client %s\n", *remoteAddr); 39 "handling client %s\n", *remoteAddr);
39 } 40 }
@@ -19,8 +19,8 @@ int @@ -19,8 +19,8 @@ int
19 main() 19 main()
20 { 20 {
21 Logger logger = new(LoggerSyslog, LOGGER_ERR); 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 struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY}; 25 struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY};
26 setrlimit(RLIMIT_CPU, &limit); 26 setrlimit(RLIMIT_CPU, &limit);
@@ -30,7 +30,7 @@ main() @@ -30,7 +30,7 @@ main()
30 serverRun(server); 30 serverRun(server);
31 31
32 delete(&server); 32 delete(&server);
33 - delete(&worker); 33 +// delete(&worker);
34 delete(&logger); 34 delete(&logger);
35 35
36 return 0; 36 return 0;
Please register or login to post a comment