Commit e8a21ace314922f3db29446bc56e10f9b557169f

Authored by Georg Hopp
1 parent 5c1c6a80

lots of changes but primarily change the request parser to use a ringbuffer. The…

… ringbuffer is implemented using the shared memory trick.
  1 +2012-02-18 20:12:27 +0100 Georg Hopp
  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)
  4 +
1 2012-02-15 12:30:33 +0100 Georg Hopp 5 2012-02-15 12:30:33 +0100 Georg Hopp
2 6
3 - * some more cleanups in the server code. Removing not needed header includes (HEAD, master) 7 + * some more cleanups in the server code. Removing not needed header includes (origin/master, origin/HEAD)
4 8
5 2012-02-15 12:17:39 +0100 Georg Hopp 9 2012-02-15 12:17:39 +0100 Georg Hopp
6 10
7 - * Merge branch 'master' of 192.168.100.2:/var/lib/git/server (origin/master, origin/HEAD) 11 + * Merge branch 'master' of 192.168.100.2:/var/lib/git/server
8 12
9 2012-02-15 12:17:00 +0100 Georg Hopp 13 2012-02-15 12:17:00 +0100 Georg Hopp
10 14
  1 +POST / HTTP/1.1
  2 +Host: localhost:11213
  3 +User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:8.0) Gecko/20100101 Firefox/8.0
  4 +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  5 +Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
  6 +Accept-Encoding: gzip, deflate
  7 +Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
  8 +Connection: keep-alive
  9 +Referer: http://localhost:11213/
  10 +Content-Type: multipart/form-data; boundary=---------------------------2713599294882465121951036798
  11 +Content-Length: 2652
  12 +
  13 +-----------------------------2713599294882465121951036798
  14 +Content-Disposition: form-data; name="submitter"
  15 +
  16 +fooo
  17 +-----------------------------2713599294882465121951036798
  18 +Content-Disposition: form-data; name="pics"; filename="bar.c"
  19 +Content-Type: text/x-csrc
  20 +
  21 +#include <stdio.h>
  22 +
  23 +#define _B64(chr, ref) (chr)==_##ref?__##ref
  24 +#define B64(_) \
  25 + ( _B64(_,A):_B64(_,B):_B64(_,C):_B64(_,D):_B64(_,E):_B64(_,F):_B64(_,G): \
  26 + _B64(_,H):_B64(_,I):_B64(_,J):_B64(_,K):_B64(_,L):_B64(_,M):_B64(_,N): \
  27 + _B64(_,O):_B64(_,P):_B64(_,Q):_B64(_,R):_B64(_,S):_B64(_,T):_B64(_,U): \
  28 + _B64(_,V):_B64(_,W):_B64(_,X):_B64(_,Y):_B64(_,Z):_B64(_,a):_B64(_,b): \
  29 + _B64(_,c):_B64(_,d):_B64(_,e):_B64(_,f):_B64(_,g):_B64(_,h):_B64(_,i): \
  30 + _B64(_,j):_B64(_,k):_B64(_,l):_B64(_,m):_B64(_,n):_B64(_,o):_B64(_,p): \
  31 + _B64(_,q):_B64(_,r):_B64(_,s):_B64(_,t):_B64(_,u):_B64(_,v):_B64(_,w): \
  32 + _B64(_,x):_B64(_,y):_B64(_,z):_B64(_,0):_B64(_,1):_B64(_,2):_B64(_,3): \
  33 + _B64(_,4):_B64(_,5):_B64(_,6):_B64(_,7):_B64(_,8):_B64(_,9): \
  34 + _B64(_,PLUS):_B64(_,SLASH):-1 )
  35 +
  36 +
  37 +#define B64_8(_) \
  38 + B64(_),B64(_+1),B64(_+2),B64(_+3),B64(_+4),B64(_+5),B64(_+6),B64(_+7)
  39 +
  40 +#define B64_64(_) \
  41 + B64_8(_),B64_8(_+8), B64_8(_+16),B64_8(_+24), \
  42 + B64_8(_+32),B64_8(_+40),B64_8(_+48),B64_8(_+56)
  43 +
  44 +#define IS_BASE64(ch) ( \
  45 + UCHAR_IN_RANGE((unsigned char)(ch)) \
  46 + && 0 <= b64[(unsigned char)(ch)] )
  47 +
  48 +
  49 +static const char b64str[64] =
  50 +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  51 +
  52 +enum b64vals {
  53 + __A=0,__B,__C,__D,__E,__F,__G,__H,__I,__J,__K,__L,__M,__N,__O,__P,__Q,__R,
  54 + __S,__T,__U,__V,__W,__X,__Y,__Z,__a,__b,__c,__d,__e,__f,__g,__h,__i,__j,
  55 + __k,__l,__m,__n,__o,__p,__q,__r,__s,__t,__u,__v,__w,__x,__y,__z,__0,__1,
  56 + __2,__3,__4,__5,__6,__7,__8,__9,__PLUS,__SLASH
  57 +};
  58 +
  59 +enum b64chars {
  60 + _A='A',_B='B',_C='C',_D='D',_E='E',_F='F',_G='G',_H='H',_I='I',_J='J',_K='K',
  61 + _L='L',_M='M',_N='N',_O='O',_P='P',_Q='Q',_R='R',_S='S',_T='T',_U='U',_V='V',
  62 + _W='W',_X='X',_Y='Y',_Z='Z',_a='a',_b='b',_c='c',_d='d',_e='e',_f='f',_g='g',
  63 + _h='h',_i='i',_j='j',_k='k',_l='l',_m='m',_n='n',_o='o',_p='p',_q='q',_r='r',
  64 + _s='s',_t='t',_u='u',_v='v',_w='w',_x='x',_y='y',_z='z',_0='0',_1='1',_2='2',
  65 + _3='3',_4='4',_5='5',_6='6',_7='7',_8='8',_9='9',_PLUS='+',_SLASH='/'
  66 +};
  67 +
  68 +#define __46B(chr) __##chr
  69 +inline
  70 +char
  71 +__B64(int val)
  72 +{
  73 + return b64str[val];
  74 +}
  75 +
  76 +int main()
  77 +{
  78 + int i=12;
  79 + char a='k';
  80 +
  81 + //printf("i => %c | a => %d\n", __B64(12), __46B('k'));
  82 + printf("i => %c | a => %d\n", __B64(i), __46B(a));
  83 +}
  84 +
  85 +// vim: set ts=4 sw=4:
  86 +
  87 +-----------------------------2713599294882465121951036798--
  1 +-----------------------------2713599294882465121951036798
  2 +Content-Disposition: form-data; name="submitter"
  3 +
  4 +fooo
  5 +-----------------------------2713599294882465121951036798
  6 +Content-Disposition: form-data; name="pics"; filename="bar.c"
  7 +Content-Type: text/x-csrc
  8 +
  9 +#include <stdio.h>
  10 +
  11 +#define _B64(chr, ref) (chr)==_##ref?__##ref
  12 +#define B64(_) \
  13 + ( _B64(_,A):_B64(_,B):_B64(_,C):_B64(_,D):_B64(_,E):_B64(_,F):_B64(_,G): \
  14 + _B64(_,H):_B64(_,I):_B64(_,J):_B64(_,K):_B64(_,L):_B64(_,M):_B64(_,N): \
  15 + _B64(_,O):_B64(_,P):_B64(_,Q):_B64(_,R):_B64(_,S):_B64(_,T):_B64(_,U): \
  16 + _B64(_,V):_B64(_,W):_B64(_,X):_B64(_,Y):_B64(_,Z):_B64(_,a):_B64(_,b): \
  17 + _B64(_,c):_B64(_,d):_B64(_,e):_B64(_,f):_B64(_,g):_B64(_,h):_B64(_,i): \
  18 + _B64(_,j):_B64(_,k):_B64(_,l):_B64(_,m):_B64(_,n):_B64(_,o):_B64(_,p): \
  19 + _B64(_,q):_B64(_,r):_B64(_,s):_B64(_,t):_B64(_,u):_B64(_,v):_B64(_,w): \
  20 + _B64(_,x):_B64(_,y):_B64(_,z):_B64(_,0):_B64(_,1):_B64(_,2):_B64(_,3): \
  21 + _B64(_,4):_B64(_,5):_B64(_,6):_B64(_,7):_B64(_,8):_B64(_,9): \
  22 + _B64(_,PLUS):_B64(_,SLASH):-1 )
  23 +
  24 +
  25 +#define B64_8(_) \
  26 + B64(_),B64(_+1),B64(_+2),B64(_+3),B64(_+4),B64(_+5),B64(_+6),B64(_+7)
  27 +
  28 +#define B64_64(_) \
  29 + B64_8(_),B64_8(_+8), B64_8(_+16),B64_8(_+24), \
  30 + B64_8(_+32),B64_8(_+40),B64_8(_+48),B64_8(_+56)
  31 +
  32 +#define IS_BASE64(ch) ( \
  33 + UCHAR_IN_RANGE((unsigned char)(ch)) \
  34 + && 0 <= b64[(unsigned char)(ch)] )
  35 +
  36 +
  37 +static const char b64str[64] =
  38 +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  39 +
  40 +enum b64vals {
  41 + __A=0,__B,__C,__D,__E,__F,__G,__H,__I,__J,__K,__L,__M,__N,__O,__P,__Q,__R,
  42 + __S,__T,__U,__V,__W,__X,__Y,__Z,__a,__b,__c,__d,__e,__f,__g,__h,__i,__j,
  43 + __k,__l,__m,__n,__o,__p,__q,__r,__s,__t,__u,__v,__w,__x,__y,__z,__0,__1,
  44 + __2,__3,__4,__5,__6,__7,__8,__9,__PLUS,__SLASH
  45 +};
  46 +
  47 +enum b64chars {
  48 + _A='A',_B='B',_C='C',_D='D',_E='E',_F='F',_G='G',_H='H',_I='I',_J='J',_K='K',
  49 + _L='L',_M='M',_N='N',_O='O',_P='P',_Q='Q',_R='R',_S='S',_T='T',_U='U',_V='V',
  50 + _W='W',_X='X',_Y='Y',_Z='Z',_a='a',_b='b',_c='c',_d='d',_e='e',_f='f',_g='g',
  51 + _h='h',_i='i',_j='j',_k='k',_l='l',_m='m',_n='n',_o='o',_p='p',_q='q',_r='r',
  52 + _s='s',_t='t',_u='u',_v='v',_w='w',_x='x',_y='y',_z='z',_0='0',_1='1',_2='2',
  53 + _3='3',_4='4',_5='5',_6='6',_7='7',_8='8',_9='9',_PLUS='+',_SLASH='/'
  54 +};
  55 +
  56 +#define __46B(chr) __##chr
  57 +inline
  58 +char
  59 +__B64(int val)
  60 +{
  61 + return b64str[val];
  62 +}
  63 +
  64 +int main()
  65 +{
  66 + int i=12;
  67 + char a='k';
  68 +
  69 + //printf("i => %c | a => %d\n", __B64(12), __46B('k'));
  70 + printf("i => %c | a => %d\n", __B64(i), __46B(a));
  71 +}
  72 +
  73 +// vim: set ts=4 sw=4:
  74 +
  75 +-----------------------------2713599294882465121951036798--
@@ -4,11 +4,21 @@ @@ -4,11 +4,21 @@
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 8
8 -#define HTTP_REQUEST_PARSER_READ_CHUNK 1024 9 +#define HTTP_REQUEST_PARSER_MAX_BUF 131072
9 10
10 -#define REMAINS(pars) \  
11 - ((pars)->buffer_used - ((pars)->cur_data - (pars)->buffer)) 11 +/**
  12 + * limits to stop invalid requests from killing
  13 + * the server.
  14 + * If any of these limits is reached the server
  15 + * will send an error message and kill the connection
  16 + * immediate.
  17 + *
  18 + * The given limits include any trailing \r\n
  19 + */
  20 +#define HTTP_REQUEST_LINE_MAX 8192
  21 +#define HTTP_REQUEST_HEADER_LINE_MAX 2048
12 22
13 23
14 typedef enum e_HttpRequestState { 24 typedef enum e_HttpRequestState {
@@ -21,11 +31,7 @@ typedef enum e_HttpRequestState { @@ -21,11 +31,7 @@ typedef enum e_HttpRequestState {
21 31
22 32
23 CLASS(HttpRequestParser) { 33 CLASS(HttpRequestParser) {
24 - char * buffer;  
25 - char * cur_data;  
26 -  
27 - size_t buffer_used;  
28 - size_t buffer_size; 34 + Ringbuffer buffer;
29 35
30 HttpMessageQueue request_queue; 36 HttpMessageQueue request_queue;
31 HttpRequest cur_request; 37 HttpRequest cur_request;
@@ -34,11 +40,11 @@ CLASS(HttpRequestParser) { @@ -34,11 +40,11 @@ CLASS(HttpRequestParser) {
34 }; 40 };
35 41
36 ssize_t httpRequestParserRead(HttpRequestParser, int); 42 ssize_t httpRequestParserRead(HttpRequestParser, int);
37 -ssize_t httpRequestParserParse(HttpRequestParser);  
38 -void httpRequestParserGetBody(HttpRequestParser); 43 +ssize_t httpRequestParserParse(HttpRequestParser, int);
39 44
40 -void httpRequestParserGetRequestLine(HttpRequest, char *);  
41 -void httpRequestParserGetHeader(HttpRequest, char *); 45 +ssize_t httpRequestParserGetRequestLine(HttpRequestParser, char *);
  46 +ssize_t httpRequestParserGetHeader(HttpRequestParser, char *);
  47 +void httpRequestParserGetBody(HttpRequestParser);
42 48
43 #endif /* __HTTP_REQUEST_PARSER_H__ */ 49 #endif /* __HTTP_REQUEST_PARSER_H__ */
44 50
@@ -8,6 +8,9 @@ @@ -8,6 +8,9 @@
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;
  13 +
11 HttpRequestParser parser; 14 HttpRequestParser parser;
12 HttpResponseWriter writer; 15 HttpResponseWriter writer;
13 }; 16 };
  1 +/**
  2 + * my implementation of a ringbuffer.
  3 + * It maps a shared memory object twice directly following
  4 + * thus make it possible to read and write from any
  5 + * position within the buffer without the nasty wrap
  6 + * calculations.
  7 + * This is achived because the same memory region is mapped
  8 + * at the two addresses.
  9 + */
  10 +#ifndef __RINGBUFFER_H__
  11 +#define __RINGBUFFER_H__
  12 +
  13 +#include <sys/types.h>
  14 +
  15 +#include "class.h"
  16 +
  17 +#define ERBOVRFL 100
  18 +
  19 +
  20 +CLASS(Ringbuffer) {
  21 + char * shm_name; // shared memory identifier
  22 +
  23 + char * buffer;
  24 + char * mirror;
  25 +
  26 + size_t bsize;
  27 + size_t bused;
  28 + size_t bstart;
  29 + size_t bend;
  30 +};
  31 +
  32 +ssize_t rbRead(Ringbuffer, int fd);
  33 +ssize_t rbWrite(Ringbuffer, int fd);
  34 +
  35 +#endif // __RINGBUFFER_H__
  36 +
  37 +// vim: set ts=4 sw=4:
@@ -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[16]); 18 +Sock socketAccept(Sock this, char (*remoteAddr)[]);
19 19
20 #endif // __SOCKET_H__ 20 #endif // __SOCKET_H__
21 21
@@ -5,6 +5,7 @@ IFACE = interface/class.c interface/stream_reader.c interface/logger.c \ @@ -5,6 +5,7 @@ IFACE = interface/class.c interface/stream_reader.c interface/logger.c \
5 interface/stream_writer.c interface/http_intro.c \ 5 interface/stream_writer.c interface/http_intro.c \
6 interface/subject.c interface/observer.c 6 interface/subject.c interface/observer.c
7 CLASS = class.c interface.c 7 CLASS = class.c interface.c
  8 +RB = ringbuffer.c ringbuffer/rb_read.c
8 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
9 SERVER = server.c server/run.c server/close_conn.c 10 SERVER = server.c server/run.c server/close_conn.c
10 LOGGER = logger.c logger/stderr.c logger/syslog.c 11 LOGGER = logger.c logger/stderr.c logger/syslog.c
@@ -21,7 +22,7 @@ HEADER = http/header.c http/header/get.c http/header/add.c \ @@ -21,7 +22,7 @@ HEADER = http/header.c http/header/get.c http/header/add.c \
21 http/header/size_get.c http/header/to_string.c 22 http/header/size_get.c http/header/to_string.c
22 PARSER = http/request/parser.c http/request/parser/get_header.c \ 23 PARSER = http/request/parser.c http/request/parser/get_header.c \
23 http/request/parser/parse.c http/request/parser/get_request_line.c \ 24 http/request/parser/parse.c http/request/parser/get_request_line.c \
24 - http/request/parser/read.c http/request/parser/get_body.c 25 + http/request/parser/get_body.c
25 26
26 27
27 AM_CFLAGS = -Wall -I ../include/ 28 AM_CFLAGS = -Wall -I ../include/
@@ -30,6 +31,7 @@ bin_PROGRAMS = testserver @@ -30,6 +31,7 @@ bin_PROGRAMS = testserver
30 31
31 testserver_SOURCES = testserver.c \ 32 testserver_SOURCES = testserver.c \
32 $(IFACE) $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(MSG) $(REQ) \ 33 $(IFACE) $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(MSG) $(REQ) \
33 - $(WRITER) $(RESP) $(HEADER) $(PARSER) $(WORKER) \ 34 + $(WRITER) $(RESP) $(HEADER) $(PARSER) $(WORKER) $(RB) \
34 signalHandling.c daemonize.c 35 signalHandling.c daemonize.c
35 testserver_CFLAGS = -Wall -I ../include/ 36 testserver_CFLAGS = -Wall -I ../include/
  37 +testserver_LDFLAGS = -lrt
@@ -10,18 +10,18 @@ @@ -10,18 +10,18 @@
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 14
14 15
15 static 16 static
16 void 17 void
17 ctor(void * _this, va_list * params) 18 ctor(void * _this, va_list * params)
18 { 19 {
19 - HttpRequestParser this = _this; 20 + HttpRequestParser this = _this;
  21 + char * shm_name = va_arg(*params, char*);
20 22
  23 + this->buffer = new(Ringbuffer, shm_name, HTTP_REQUEST_LINE_MAX);
21 this->request_queue = new(HttpMessageQueue); 24 this->request_queue = new(HttpMessageQueue);
22 -  
23 - this->buffer = malloc(HTTP_REQUEST_PARSER_READ_CHUNK);  
24 - this->buffer[0] = 0;  
25 } 25 }
26 26
27 static 27 static
@@ -30,36 +30,16 @@ dtor(void * _this) @@ -30,36 +30,16 @@ dtor(void * _this)
30 { 30 {
31 HttpRequestParser this = _this; 31 HttpRequestParser this = _this;
32 32
33 - free(this->buffer);  
34 delete(&(this->request_queue)); 33 delete(&(this->request_queue));
  34 + delete(&(this->buffer));
35 35
36 if (NULL != this->cur_request) 36 if (NULL != this->cur_request)
37 delete(&(this->cur_request)); 37 delete(&(this->cur_request));
38 } 38 }
39 39
40 -static  
41 -void  
42 -_clone(void * _this, void * _base)  
43 -{  
44 - HttpRequestParser this = _this;  
45 - HttpRequestParser base = _base;  
46 - size_t chunks;  
47 -  
48 - /**  
49 - * every parser has its own queue...  
50 - */  
51 - this->request_queue = new(HttpMessageQueue);  
52 - this->buffer_used = base->buffer_used;  
53 -  
54 - chunks = this->buffer_used / HTTP_REQUEST_PARSER_READ_CHUNK;  
55 - chunks++;  
56 -  
57 - this->buffer = malloc(chunks * HTTP_REQUEST_PARSER_READ_CHUNK);  
58 - memcpy(this->buffer, base->buffer, this->buffer_used);  
59 -}  
60 40
61 -INIT_IFACE(Class, ctor, dtor, _clone);  
62 -INIT_IFACE(StreamReader, (fptr_streamReaderRead)httpRequestParserRead); 41 +INIT_IFACE(Class, ctor, dtor, NULL);
  42 +INIT_IFACE(StreamReader, (fptr_streamReaderRead)httpRequestParserParse);
63 CREATE_CLASS(HttpRequestParser, NULL, IFACE(Class), IFACE(StreamReader)); 43 CREATE_CLASS(HttpRequestParser, NULL, IFACE(Class), IFACE(StreamReader));
64 44
65 // vim: set ts=4 sw=4: 45 // vim: set ts=4 sw=4:
@@ -4,33 +4,50 @@ @@ -4,33 +4,50 @@
4 #include "http/message.h" 4 #include "http/message.h"
5 #include "http/request/parser.h" 5 #include "http/request/parser.h"
6 6
  7 +#define MAX(x,y) ((x) > (y) ? (x) : (y))
  8 +
  9 +
  10 +/**
  11 + * @TODO: not final...input buffer handling not final
  12 + */
7 void 13 void
8 httpRequestParserGetBody(HttpRequestParser this) 14 httpRequestParserGetBody(HttpRequestParser this)
9 { 15 {
10 HttpMessage message = (HttpMessage)(this->cur_request); 16 HttpMessage message = (HttpMessage)(this->cur_request);
11 - char * nbody; 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);
12 31
13 if (0 == message->nbody) { 32 if (0 == message->nbody) {
14 - nbody = httpHeaderGet(  
15 - &(message->header),  
16 - "Content-Length");  
17 -  
18 - if (NULL == nbody) {  
19 - this->state = HTTP_REQUEST_DONE;  
20 - return;  
21 - }  
22 - else {  
23 - message->type = HTTP_MESSAGE_BUFFERED;  
24 - message->nbody = atoi(nbody);  
25 - } 33 + message->type = HTTP_MESSAGE_BUFFERED;
  34 + if (0 < nbody)
  35 + message->body = malloc(nbody);
  36 + }
  37 +
  38 + len = MAX(nbody - message->nbody, this->buffer->bused);
  39 + memcpy(message->body + message->nbody,
  40 + this->buffer->buffer + this->buffer->bstart,
  41 + len);
  42 +
  43 + message->nbody += len;
  44 + this->buffer->bstart += len;
  45 + if (this->buffer->bstart >= this->buffer->bsize) {
  46 + this->buffer->bstart -= this->buffer->bsize;
26 } 47 }
  48 + this->buffer->bused -= len;
27 49
28 - if (REMAINS(this) >= message->nbody) {  
29 - message->body = calloc(1, message->nbody + 1);  
30 - memcpy(message->body,  
31 - this->cur_data,  
32 - message->nbody);  
33 - this->cur_data += message->nbody; 50 + if (message->nbody == nbody) {
34 this->state = HTTP_REQUEST_DONE; 51 this->state = HTTP_REQUEST_DONE;
35 } 52 }
36 } 53 }
  1 +#include <stdlib.h>
  2 +#include <string.h>
1 #include <search.h> 3 #include <search.h>
2 #include <ctype.h> 4 #include <ctype.h>
3 #include <stdio.h> 5 #include <stdio.h>
@@ -6,17 +8,32 @@ @@ -6,17 +8,32 @@
6 #include "interface/class.h" 8 #include "interface/class.h"
7 #include "http/header.h" 9 #include "http/header.h"
8 #include "http/message.h" 10 #include "http/message.h"
  11 +#include "http/request/parser.h"
  12 +#include "ringbuffer.h"
9 13
10 -void  
11 -httpRequestParserGetHeader(HttpMessage request, char * line) 14 +ssize_t
  15 +httpRequestParserGetHeader(HttpRequestParser this, char * cr)
12 { 16 {
13 - char * name = line;  
14 - char * value = strchr(line, ':'); 17 + HttpMessage message = (HttpMessage)this->cur_request;
  18 + char * value;
  19 + char * name = this->buffer->buffer + this->buffer->bstart;
  20 + size_t len = cr - name;
15 21
  22 + value = memchr(
  23 + this->buffer->buffer + this->buffer->bstart,
  24 + ':', len);
  25 +
  26 + if (NULL == value) {
  27 + return -1;
  28 + }
  29 +
  30 + *cr = 0;
16 *(value++) = 0; 31 *(value++) = 0;
17 - for (; *value == ' ' && *value != 0; value++); 32 + while(' ' == *value) value++;
  33 +
  34 + httpHeaderAdd(&(message->header), new(HttpHeader, name, value));
18 35
19 - httpHeaderAdd(&(request->header), new(HttpHeader, name, value)); 36 + return 1; //* @TODO: return something useful here
20 } 37 }
21 38
22 // vim: set ts=4 sw=4: 39 // vim: set ts=4 sw=4:
1 #include <stdlib.h> 1 #include <stdlib.h>
2 #include <string.h> 2 #include <string.h>
3 3
  4 +#include "http/message.h"
4 #include "http/request.h" 5 #include "http/request.h"
  6 +#include "http/request/parser.h"
  7 +#include "ringbuffer.h"
5 8
  9 +#define MAX(x,y) ((x) > (y) ? (x) : (y))
  10 +#define MIN(x,y) ((x) < (y) ? (x) : (y))
  11 +#define MIN_SIZE(x,y) (MAX(strlen((x)), (y)))
6 12
7 -void  
8 -httpRequestParserGetRequestLine(HttpRequest request, char * line) 13 +enum e_method {
  14 + OPTIONS=0,
  15 + GET,
  16 + HEAD,
  17 + POST,
  18 + PUT,
  19 + DELETE,
  20 + TRACE,
  21 + CONNECT
  22 +};
  23 +
  24 +#define N_METHODS 8
  25 +
  26 +static
  27 +const
  28 +char * method[N_METHODS] = {
  29 + "OPTIONS",
  30 + "GET",
  31 + "HEAD",
  32 + "POST",
  33 + "PUT",
  34 + "DELETE",
  35 + "TRACE",
  36 + "CONNECT"
  37 +};
  38 +
  39 +ssize_t
  40 +httpRequestParserGetRequestLine(HttpRequestParser this, char * cr)
9 { 41 {
  42 + HttpRequest request = this->cur_request;
10 HttpMessage message = (HttpMessage)request; 43 HttpMessage message = (HttpMessage)request;
11 - char * method, * uri, * version; 44 + char * space1, * space2;
  45 + size_t len = cr - this->buffer->buffer - this->buffer->bstart;
  46 + int i;
  47 +
  48 + space1 = memchr(
  49 + this->buffer->buffer + this->buffer->bstart,
  50 + ' ', len);
  51 +
  52 + if (NULL == space1) {
  53 + return -1;
  54 + }
  55 +
  56 + len = cr - space1;
  57 + space2 = memchr(space1 + 1, ' ', len);
  58 +
  59 + if (NULL == space2) {
  60 + return -1;
  61 + }
  62 +
  63 + len = space1 - this->buffer->buffer - this->buffer->bstart;
  64 + request->method = calloc(1, len + 1);
  65 + memcpy(request->method,
  66 + this->buffer->buffer + this->buffer->bstart,
  67 + len);
  68 +
  69 + for (i= 0; i< N_METHODS; i++) {
  70 + if (0 == memcmp(method[i], request->method, MIN_SIZE(method[i], len))) {
  71 + break;
  72 + }
  73 + }
  74 +
  75 + if (i == N_METHODS) {
  76 + return -1;
  77 + }
12 78
13 - method = line; 79 + len = space2 - space1 - 1;
  80 + request->uri = calloc(1, len + 1);
  81 + memcpy(request->uri, space1 + 1, len);
14 82
15 - uri = strchr(line, ' ');  
16 - *uri++ = 0;  
17 - for (; *uri == ' ' && *uri != 0; uri++); 83 + len = cr - space2 - 1;
  84 + message->version = calloc(1, len + 1);
  85 + memcpy(message->version, space2 + 1, len);
18 86
19 - version = strchr(uri, ' ');  
20 - *version++ = 0;  
21 - for (; *version == ' ' && *version != 0; version++); 87 + if (len+1 != sizeof("HTTP/1.1") ||
  88 + 0 != memcmp("HTTP/1.", message->version, len-1)) {
  89 + return -1;
  90 + }
22 91
23 - request->method = malloc(strlen(method) + 1);  
24 - strcpy(request->method, method);  
25 - request->uri = malloc(strlen(uri) + 1);  
26 - strcpy(request->uri, uri);  
27 - message->version = malloc(strlen(version) + 1);  
28 - strcpy(message->version, method); 92 + return 1; //* @TODO: return something useful here
29 } 93 }
30 94
31 // vim: set ts=4 sw=4: 95 // vim: set ts=4 sw=4:
@@ -3,112 +3,147 @@ @@ -3,112 +3,147 @@
3 #include <unistd.h> 3 #include <unistd.h>
4 #include <ctype.h> 4 #include <ctype.h>
5 5
  6 +#include "http/request.h"
  7 +#include "http/message.h"
6 #include "http/request/parser.h" 8 #include "http/request/parser.h"
7 #include "interface/class.h" 9 #include "interface/class.h"
8 10
  11 +#ifndef TRUE
  12 +#define TRUE 1
  13 +#endif
  14 +
  15 +#ifndef FALSE
  16 +#define FALSE 0
  17 +#endif
9 18
10 static 19 static
11 inline 20 inline
12 char * 21 char *
13 -httpRequestParserGetLine(char ** data) 22 +getLine(HttpRequestParser this)
14 { 23 {
15 - char * line_end = strstr(*data, "\r\n");  
16 - char * ret = *data; 24 + char * cr = memchr(
  25 + this->buffer->buffer + this->buffer->bstart,
  26 + '\r',
  27 + this->buffer->bused);
17 28
18 - if (NULL == line_end) {  
19 - return NULL;  
20 - } 29 + char * nl = (NULL == cr)? NULL : cr + 1;
21 30
22 - *line_end = 0;  
23 - *data = line_end + 2; 31 + if (NULL != cr && NULL != nl && '\n' == *nl) {
  32 + *cr = 0;
  33 + return cr;
  34 + }
24 35
25 - return ret; 36 + return NULL;
26 } 37 }
27 38
28 static 39 static
29 inline 40 inline
30 -void  
31 -httpRequestSkip(char ** data) 41 +char
  42 +httpRequestSkip(HttpRequestParser this)
32 { 43 {
33 - for (; 0 != **data && ! isalpha(**data); (*data)++); 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;
34 } 52 }
35 53
36 ssize_t 54 ssize_t
37 -httpRequestParserParse(HttpRequestParser this) 55 +httpRequestParserParse(HttpRequestParser this, int fd)
38 { 56 {
39 - char * line;  
40 int cont = 1; 57 int cont = 1;
41 - ssize_t ret = this->request_queue->nmsgs; 58 + ssize_t ret;
  59 +
  60 + if (0 > (ret = rbRead(this->buffer, fd))) {
  61 + cont = 0;
  62 + }
42 63
43 while (cont) { 64 while (cont) {
44 switch(this->state) { 65 switch(this->state) {
45 - case HTTP_REQUEST_GARBAGE:  
46 - this->cur_data = this->buffer; // initialize static pointer  
47 - httpRequestSkip(&(this->cur_data));  
48 - this->cur_request = new(HttpRequest); 66 + char * line_end;
  67 + size_t len;
49 68
50 - this->state = HTTP_REQUEST_START; 69 + case HTTP_REQUEST_GARBAGE:
  70 + if (httpRequestSkip(this)) {
  71 + this->cur_request = new(HttpRequest);
  72 + this->state = HTTP_REQUEST_START;
  73 + }
  74 + else {
  75 + cont = 0;
  76 + }
51 break; 77 break;
52 78
53 case HTTP_REQUEST_START: 79 case HTTP_REQUEST_START:
54 - if (NULL == (line = httpRequestParserGetLine(&(this->cur_data)))) { 80 + if (NULL == (line_end = getLine(this))) {
55 cont = 0; 81 cont = 0;
56 break; 82 break;
57 } 83 }
58 84
59 - httpRequestParserGetRequestLine(this->cur_request, line); 85 + if (0 > httpRequestParserGetRequestLine(this, line_end)) {
  86 + ret = -1;
  87 + cont = 0;
  88 + break;
  89 + }
  90 +
  91 + len = line_end - this->buffer->buffer - this->buffer->bstart + 2;
  92 + this->buffer->bstart += len;
  93 + if (this->buffer->bstart >= this->buffer->bsize) {
  94 + this->buffer->bstart -= this->buffer->bsize;
  95 + }
  96 + this->buffer->bused -= len;
60 97
61 this->state = HTTP_REQUEST_REQUEST_LINE_DONE; 98 this->state = HTTP_REQUEST_REQUEST_LINE_DONE;
62 break; 99 break;
63 100
64 case HTTP_REQUEST_REQUEST_LINE_DONE: 101 case HTTP_REQUEST_REQUEST_LINE_DONE:
65 - if (NULL == (line = httpRequestParserGetLine(&(this->cur_data)))) { 102 + if (NULL == (line_end = getLine(this))) {
66 cont = 0; 103 cont = 0;
67 break; 104 break;
68 } 105 }
69 106
70 - if (0 == strlen(line)) { 107 + if (0 == line_end - this->buffer->buffer - this->buffer->bstart) {
  108 + this->buffer->bstart += 2;
  109 + if (this->buffer->bstart >= this->buffer->bsize) {
  110 + this->buffer->bstart -= this->buffer->bsize;
  111 + }
  112 + this->buffer->bused -= 2;
  113 +
71 this->state = HTTP_REQUEST_HEADERS_DONE; 114 this->state = HTTP_REQUEST_HEADERS_DONE;
72 break; 115 break;
73 } 116 }
74 117
75 - httpRequestParserGetHeader(this->cur_request, line); 118 + httpRequestParserGetHeader(this, line_end);
  119 +
  120 + len = line_end - this->buffer->buffer - this->buffer->bstart + 2;
  121 + this->buffer->bstart += len;
  122 + if (this->buffer->bstart >= this->buffer->bsize) {
  123 + this->buffer->bstart -= this->buffer->bsize;
  124 + }
  125 + this->buffer->bused -= len;
  126 +
76 break; 127 break;
77 128
78 case HTTP_REQUEST_HEADERS_DONE: 129 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 + */
79 httpRequestParserGetBody(this); 137 httpRequestParserGetBody(this);
80 break; 138 break;
81 139
82 case HTTP_REQUEST_DONE: 140 case HTTP_REQUEST_DONE:
83 - /**  
84 - * enqueue current request  
85 - */  
86 this->request_queue->msgs[(this->request_queue->nmsgs)++] = 141 this->request_queue->msgs[(this->request_queue->nmsgs)++] =
87 (HttpMessage)this->cur_request; 142 (HttpMessage)this->cur_request;
88 143
89 - if (! httpMessageHasKeepAlive((HttpMessage)this->cur_request)) {  
90 - ret = -2;  
91 - }  
92 - 144 + ret = this->request_queue->nmsgs;
93 this->cur_request = NULL; 145 this->cur_request = NULL;
94 146
95 - /**  
96 - * remove processed stuff from input buffer.  
97 - */  
98 - memmove(this->buffer, this->cur_data, REMAINS(this));  
99 -  
100 - this->buffer_used -= this->cur_data - this->buffer;  
101 -  
102 - /**  
103 - * dont continue loop if input buffer is empty  
104 - */  
105 - if (0 == this->buffer_used) {  
106 - cont = 0;  
107 - }  
108 -  
109 - /**  
110 - * prepare for next request  
111 - */  
112 this->state = HTTP_REQUEST_GARBAGE; 147 this->state = HTTP_REQUEST_GARBAGE;
113 148
114 break; 149 break;
@@ -118,7 +153,7 @@ httpRequestParserParse(HttpRequestParser this) @@ -118,7 +153,7 @@ httpRequestParserParse(HttpRequestParser this)
118 } 153 }
119 } 154 }
120 155
121 - return this->request_queue->nmsgs; 156 + return ret;
122 } 157 }
123 158
124 // vim: set ts=4 sw=4: 159 // vim: set ts=4 sw=4:
@@ -3,46 +3,40 @@ @@ -3,46 +3,40 @@
3 3
4 #include "http/request/parser.h" 4 #include "http/request/parser.h"
5 5
  6 +#define MAX(x,y) ((x) > (y) ? (x) : (y))
  7 +#define _BSIZE(x) (MAX((x),RESPONSE_WRITER_MAX_BUF))
  8 +#define BSIZE _BSIZE(this->nheader+message->nbody)
6 9
  10 +
  11 +/**
  12 + * @deprecated
  13 + */
7 ssize_t 14 ssize_t
8 httpRequestParserRead(HttpRequestParser this, int fd) 15 httpRequestParserRead(HttpRequestParser this, int fd)
9 { 16 {
10 - size_t remaining, chunks;  
11 - char buffer[1024]; 17 + size_t rsize;
  18 + ssize_t temp;
12 19
13 - ssize_t size = read(fd, buffer, 1024); 20 + this->bend = (this->bsize == this->bend)?
  21 + 0 : this->bend;
14 22
15 - if (0 < size) {  
16 - remaining = this->buffer_used % HTTP_REQUEST_PARSER_READ_CHUNK;  
17 - remaining = HTTP_REQUEST_PARSER_READ_CHUNK - remaining;  
18 - chunks = this->buffer_used / HTTP_REQUEST_PARSER_READ_CHUNK; 23 + rsize = (this->bstart <= this->bend)?
  24 + this->bsize - this->bend :
  25 + this->bstart - 1;
19 26
  27 + if (0 >= (temp = read(fd, &(this->buffer[this->bend]), rsize))) {
20 /** 28 /**
21 - * because a division always rounds down  
22 - * chunks holds exactly the currently allocated chunks if  
23 - * remaining equals 0 but there is no space left.  
24 - * Else chunks holds the actually allocated amount of chunks  
25 - * minus 1.  
26 - * For this reason chunks always has to be increased by 1. 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.
27 */ 33 */
28 - chunks++;  
29 -  
30 - if (size >= remaining) {  
31 - this->buffer =  
32 - realloc(this->buffer, chunks * HTTP_REQUEST_PARSER_READ_CHUNK);  
33 - }  
34 -  
35 - memcpy(this->buffer + this->buffer_used, buffer, size);  
36 - this->buffer_used += size;  
37 - this->buffer[this->buffer_used] = 0;  
38 -  
39 - size = httpRequestParserParse(this);  
40 - }  
41 - else {  
42 - size = (0 == size)? -2 : size; 34 + return (0 == temp)? -2 : -1;
43 } 35 }
44 36
45 - return size; 37 + this->bend += temp;
  38 +
  39 + return temp;
46 } 40 }
47 41
48 // vim: set ts=4 sw=4: 42 // vim: set ts=4 sw=4:
1 #include <stdlib.h> 1 #include <stdlib.h>
2 #include <string.h> 2 #include <string.h>
3 #include <stdio.h> 3 #include <stdio.h>
4 -#include <time.h>  
5 4
6 #include "class.h" 5 #include "class.h"
7 #include "interface/class.h" 6 #include "interface/class.h"
@@ -23,8 +22,6 @@ @@ -23,8 +22,6 @@
23 HttpResponse 22 HttpResponse
24 httpResponse404() 23 httpResponse404()
25 { 24 {
26 - time_t t;  
27 - struct tm * tmp;  
28 char buffer[200]; 25 char buffer[200];
29 HttpResponse response; 26 HttpResponse response;
30 HttpMessage message; 27 HttpMessage message;
@@ -46,12 +43,6 @@ httpResponse404() @@ -46,12 +43,6 @@ httpResponse404()
46 httpHeaderAdd(&(message->header), 43 httpHeaderAdd(&(message->header),
47 new(HttpHeader, "Content-Length", buffer)); 44 new(HttpHeader, "Content-Length", buffer));
48 45
49 - t = time(NULL);  
50 - tmp = localtime(&t);  
51 - strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp);  
52 - httpHeaderAdd(&(message->header),  
53 - new(HttpHeader, "Date", buffer));  
54 -  
55 return response; 46 return response;
56 } 47 }
57 48
1 #include <stdlib.h> 1 #include <stdlib.h>
2 #include <string.h> 2 #include <string.h>
3 #include <stdio.h> 3 #include <stdio.h>
4 -#include <time.h>  
5 #include <sys/stat.h> 4 #include <sys/stat.h>
6 #include <fcntl.h> 5 #include <fcntl.h>
7 6
@@ -16,8 +15,6 @@ @@ -16,8 +15,6 @@
16 HttpResponse 15 HttpResponse
17 httpResponseImage() 16 httpResponseImage()
18 { 17 {
19 - time_t t;  
20 - struct tm * tmp;  
21 char buffer[200]; 18 char buffer[200];
22 struct stat st; 19 struct stat st;
23 HttpResponse response; 20 HttpResponse response;
@@ -40,12 +37,6 @@ httpResponseImage() @@ -40,12 +37,6 @@ httpResponseImage()
40 httpHeaderAdd(&(message->header), 37 httpHeaderAdd(&(message->header),
41 new(HttpHeader, "Content-Length", buffer)); 38 new(HttpHeader, "Content-Length", buffer));
42 39
43 - t = time(NULL);  
44 - tmp = localtime(&t);  
45 - strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp);  
46 - httpHeaderAdd(&(message->header),  
47 - new(HttpHeader, "Date", buffer));  
48 -  
49 return response; 40 return response;
50 } 41 }
51 42
1 #include <stdlib.h> 1 #include <stdlib.h>
2 #include <string.h> 2 #include <string.h>
3 #include <stdio.h> 3 #include <stdio.h>
4 -#include <time.h>  
5 4
6 #include "class.h" 5 #include "class.h"
7 #include "interface/class.h" 6 #include "interface/class.h"
@@ -23,8 +22,6 @@ @@ -23,8 +22,6 @@
23 HttpResponse 22 HttpResponse
24 httpResponseMe() 23 httpResponseMe()
25 { 24 {
26 - time_t t;  
27 - struct tm * tmp;  
28 char buffer[200]; 25 char buffer[200];
29 HttpResponse response; 26 HttpResponse response;
30 HttpMessage message; 27 HttpMessage message;
@@ -46,12 +43,6 @@ httpResponseMe() @@ -46,12 +43,6 @@ httpResponseMe()
46 httpHeaderAdd(&(message->header), 43 httpHeaderAdd(&(message->header),
47 new(HttpHeader, "Content-Length", buffer)); 44 new(HttpHeader, "Content-Length", buffer));
48 45
49 - t = time(NULL);  
50 - tmp = localtime(&t);  
51 - strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp);  
52 - httpHeaderAdd(&(message->header),  
53 - new(HttpHeader, "Date", buffer));  
54 -  
55 return response; 46 return response;
56 } 47 }
57 48
@@ -21,7 +21,7 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd) @@ -21,7 +21,7 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd)
21 { 21 {
22 HttpMessageQueue respq = this->response_queue; 22 HttpMessageQueue respq = this->response_queue;
23 HttpMessage message = (HttpMessage)this->cur_response; 23 HttpMessage message = (HttpMessage)this->cur_response;
24 - ssize_t processed = (message)? 1 : 0; 24 + ssize_t processed = (message)? 1 : 0;
25 int cont = 1; 25 int cont = 1;
26 26
27 while (cont) { 27 while (cont) {
@@ -74,7 +74,6 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd) @@ -74,7 +74,6 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd)
74 &(this->pipe[this->pend]), 74 &(this->pipe[this->pend]),
75 &(message->body[this->nbuffer]), 75 &(message->body[this->nbuffer]),
76 temp); 76 temp);
77 -  
78 break; 77 break;
79 78
80 case HTTP_MESSAGE_PIPED: 79 case HTTP_MESSAGE_PIPED:
  1 +#include <stdlib.h>
1 #include <stdarg.h> 2 #include <stdarg.h>
  3 +#include <string.h>
2 4
3 #include "class.h" 5 #include "class.h"
4 #include "http/worker.h" 6 #include "http/worker.h"
@@ -9,13 +11,19 @@ @@ -9,13 +11,19 @@
9 #include "interface/stream_reader.h" 11 #include "interface/stream_reader.h"
10 #include "interface/stream_writer.h" 12 #include "interface/stream_writer.h"
11 13
  14 +#define SHMN "/worker_"
12 static 15 static
13 void 16 void
14 ctor(void * _this, va_list * params) 17 ctor(void * _this, va_list * params)
15 { 18 {
16 HttpWorker this = _this; 19 HttpWorker this = _this;
  20 + char id[sizeof(SHMN) + 15 + 5];
17 21
18 - this->parser = new(HttpRequestParser); 22 + this->remoteAddr = va_arg(*params, char *);
  23 + this->handle = va_arg(*params, int);
  24 + sprintf(id, SHMN "%s_%05d", this->remoteAddr, this->handle);
  25 +
  26 + this->parser = new(HttpRequestParser, id);
19 this->writer = new(HttpResponseWriter); 27 this->writer = new(HttpResponseWriter);
20 } 28 }
21 29
@@ -29,20 +37,7 @@ dtor(void * _this) @@ -29,20 +37,7 @@ dtor(void * _this)
29 delete(&this->writer); 37 delete(&this->writer);
30 } 38 }
31 39
32 -static  
33 -void  
34 -_clone(void * _this, void * _base)  
35 -{  
36 - /**  
37 - * TODO: this actually simply creates a new worker  
38 - * and ignores the base. Think about this.  
39 - */  
40 - va_list foo;  
41 -  
42 - ctor(_this, &foo);  
43 -}  
44 -  
45 -INIT_IFACE(Class, ctor, dtor, _clone); 40 +INIT_IFACE(Class, ctor, dtor, NULL);
46 INIT_IFACE(StreamReader, (fptr_streamReaderRead)httpWorkerProcess); 41 INIT_IFACE(StreamReader, (fptr_streamReaderRead)httpWorkerProcess);
47 INIT_IFACE(StreamWriter, (fptr_streamWriterWrite)httpWorkerWrite); 42 INIT_IFACE(StreamWriter, (fptr_streamWriterWrite)httpWorkerWrite);
48 CREATE_CLASS( 43 CREATE_CLASS(
  1 +#include <time.h>
  2 +
1 #include "class.h" 3 #include "class.h"
2 #include "interface/class.h" 4 #include "interface/class.h"
3 5
4 #include "http/worker.h" 6 #include "http/worker.h"
5 #include "http/request/parser.h" 7 #include "http/request/parser.h"
  8 +#include "http/header.h"
  9 +#include "http/request.h"
  10 +#include "http/message.h"
6 11
7 ssize_t 12 ssize_t
8 httpWorkerProcess(HttpWorker this, int fd) 13 httpWorkerProcess(HttpWorker this, int fd)
9 { 14 {
10 - ssize_t size; 15 + time_t t;
  16 + struct tm * tmp;
  17 + char buffer[200];
  18 + ssize_t size;
11 19
12 - if (0 < (size = httpRequestParserRead(this->parser, fd))) { 20 + if (0 < (size = httpRequestParserParse(this->parser, fd))) {
13 int i; 21 int i;
14 HttpMessageQueue reqq = this->parser->request_queue; 22 HttpMessageQueue reqq = this->parser->request_queue;
15 HttpMessageQueue respq = this->writer->response_queue; 23 HttpMessageQueue respq = this->writer->response_queue;
@@ -19,8 +27,8 @@ httpWorkerProcess(HttpWorker this, int fd) @@ -19,8 +27,8 @@ httpWorkerProcess(HttpWorker this, int fd)
19 * @TODO: for now simply remove request and send not found. 27 * @TODO: for now simply remove request and send not found.
20 * Make this sane. 28 * Make this sane.
21 */ 29 */
22 - HttpRequest request = (HttpRequest)(reqq->msgs[i]);  
23 - HttpMessage response = NULL; 30 + HttpRequest request = (HttpRequest)(reqq->msgs[i]);
  31 + HttpMessage response = NULL;
24 32
25 if (0 == strcmp("GET", request->method) && 33 if (0 == strcmp("GET", request->method) &&
26 0 == strcmp("/me/", request->uri)) { 34 0 == strcmp("/me/", request->uri)) {
@@ -45,12 +53,19 @@ httpWorkerProcess(HttpWorker this, int fd) @@ -45,12 +53,19 @@ httpWorkerProcess(HttpWorker this, int fd)
45 new(HttpHeader, "Connection", "Close")); 53 new(HttpHeader, "Connection", "Close"));
46 } 54 }
47 55
  56 + t = time(NULL);
  57 + tmp = localtime(&t);
  58 + strftime(buffer, sizeof(buffer), "%a, %d %b %Y %T %Z", tmp);
  59 + httpHeaderAdd(&(response->header),
  60 + new(HttpHeader, "Date", buffer));
  61 +
48 respq->msgs[(respq->nmsgs)++] = response; 62 respq->msgs[(respq->nmsgs)++] = response;
49 response = NULL; 63 response = NULL;
50 delete(&(reqq->msgs[i])); 64 delete(&(reqq->msgs[i]));
51 } 65 }
52 66
53 reqq->nmsgs = 0; 67 reqq->nmsgs = 0;
  68 + size = respq->nmsgs;
54 } 69 }
55 70
56 return size; 71 return size;
  1 +#include <stdio.h>
  2 +
  3 +#include "ringbuffer.h"
  4 +#include "interface/class.h"
  5 +
  6 +int
  7 +main()
  8 +{
  9 + Ringbuffer buf = new(Ringbuffer, "/rbtest", 1);
  10 +
  11 + strcpy(buf->buffer + buf->bsize - 5, "Dies ist ein foobar test");
  12 +
  13 + printf("%s\n", buf->buffer);
  14 + printf("%s\n", buf->buffer + buf->bsize - 5);
  15 +
  16 + delete(&buf);
  17 +
  18 + return 0;
  19 +}
  20 +
  21 +// vim: set ts=4 sw=4:
  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 <string.h>
  10 +#include <unistd.h>
  11 +#include <fcntl.h>
  12 +
  13 +#include "class.h"
  14 +#include "interface/class.h"
  15 +
  16 +#include "ringbuffer.h"
  17 +
  18 +#define PAGES(size, psize) ((size)/(psize)+(0 == (size)%(psize))?0:1)
  19 +
  20 +
  21 +static void dtor(void*);
  22 +
  23 +static
  24 +void
  25 +ctor(void * _this, va_list * params)
  26 +{
  27 + Ringbuffer this = _this;
  28 + char state = 0;
  29 + char * shm_name = va_arg(*params, char*);
  30 + long psize = sysconf(_SC_PAGESIZE);
  31 + size_t size;
  32 + int shm;
  33 + void * shm_addr;
  34 +
  35 + this->shm_name = malloc(strlen(shm_name) + 1);
  36 + strcpy(this->shm_name, shm_name);
  37 +
  38 + /**
  39 + * align size at page boundary.
  40 + * increase as neccessary
  41 + */
  42 + size = va_arg(*params, size_t);
  43 + size = (0 <= size)? 1 : size;
  44 + this->bsize = psize * PAGES(size, psize);
  45 +
  46 + while (0 == state) {
  47 + shm = shm_open(this->shm_name, O_RDWR|O_CREAT|O_EXCL, S_IRWXU);
  48 + if (-1 == shm) {
  49 + break;
  50 + }
  51 + else {
  52 + ftruncate(shm, this->bsize);
  53 + }
  54 +
  55 + shm_addr = mmap (0, this->bsize<<1,
  56 + PROT_READ|PROT_WRITE, MAP_SHARED, shm, 0);
  57 + if (shm_addr == MAP_FAILED)
  58 + break;
  59 +
  60 + munmap(shm_addr, this->bsize<<1);
  61 +
  62 + this->buffer = mmap (shm_addr, this->bsize,
  63 + PROT_READ|PROT_WRITE, MAP_SHARED, shm, 0);
  64 + if (this->buffer == MAP_FAILED) {
  65 + shm_addr = NULL;
  66 + break;
  67 + }
  68 +
  69 + this->mirror = mmap (shm_addr + this->bsize, this->bsize,
  70 + PROT_READ|PROT_WRITE, MAP_SHARED, shm, 0);
  71 + if (this->mirror != shm_addr + this->bsize) {
  72 + shm_addr = NULL;
  73 + break;
  74 + }
  75 +
  76 + state = 1;
  77 + }
  78 +
  79 + if (-1 != shm) {
  80 + shm_unlink(this->shm_name);
  81 + close(shm);
  82 + }
  83 +
  84 + if (1 != state) {
  85 + if (shm_addr) {
  86 + munmap(shm_addr, this->bsize<<1);
  87 + }
  88 +
  89 + dtor(this);
  90 + }
  91 +}
  92 +
  93 +static
  94 +void
  95 +dtor(void * _this)
  96 +{
  97 + Ringbuffer this = _this;
  98 +
  99 + if (NULL != this->shm_name) {
  100 + free(this->shm_name);
  101 + }
  102 +
  103 + if (this->buffer) {
  104 + munmap(this->buffer, this->bsize);
  105 + this->buffer = NULL;
  106 + }
  107 +
  108 + if (this->mirror) {
  109 + munmap(this->mirror, this->bsize);
  110 + this->mirror = NULL;
  111 + }
  112 +}
  113 +
  114 +INIT_IFACE(Class, ctor, dtor, NULL);
  115 +CREATE_CLASS(Ringbuffer, NULL, IFACE(Class));
  116 +
  117 +// vim: set ts=4 sw=4:
  1 +#include <sys/types.h>
  2 +#include <unistd.h>
  3 +#include <errno.h>
  4 +
  5 +#include "ringbuffer.h"
  6 +
  7 +ssize_t
  8 +rbRead(Ringbuffer this, int fd)
  9 +{
  10 + ssize_t rrsize = 0;
  11 + size_t rsize = this->bsize - this->bused;
  12 +
  13 + if (0 == rsize) {
  14 + errno = ERBOVRFL;
  15 + return -1;
  16 + }
  17 +
  18 + rrsize = read(fd, this->buffer + this->bend, rsize);
  19 +
  20 + switch (rrsize) {
  21 + case 0:
  22 + rsize = -2;
  23 +
  24 + case -1:
  25 + break;
  26 +
  27 + default:
  28 + this->bend += rrsize;
  29 + this->bused += rrsize;
  30 +
  31 + if (this->bend >= this->bsize) {
  32 + this->bend -= this->bsize;
  33 + }
  34 +
  35 + break;
  36 + }
  37 +
  38 + return rrsize;
  39 +}
  40 +
  41 +// vim: set ts=4 sw=4:
1 #include <errno.h> 1 #include <errno.h>
2 2
  3 +#include "http/worker.h"
  4 +
3 static 5 static
4 int 6 int
5 serverHandleAccept(Server this) 7 serverHandleAccept(Server this)
6 { 8 {
7 - char remoteAddr[16] = ""; 9 + char remoteAddr[16] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
8 Sock acc; 10 Sock acc;
9 11
10 - acc = socketAccept(this->sock, remoteAddr); 12 + acc = socketAccept(this->sock, &remoteAddr);
11 13
12 if (-1 != acc->handle) { 14 if (-1 != acc->handle) {
13 //* save the socket handle 15 //* save the socket handle
14 (this->conns)[acc->handle].sock = acc; 16 (this->conns)[acc->handle].sock = acc;
15 17
16 //* clone reader 18 //* clone reader
17 - (this->conns)[acc->handle].worker = clone(this->worker); 19 + (this->conns)[acc->handle].worker = new(HttpWorker, remoteAddr, acc->handle);
18 20
19 (this->fds)[this->nfds].fd = acc->handle; 21 (this->fds)[this->nfds].fd = acc->handle;
20 (this->fds)[this->nfds].events = POLLIN; 22 (this->fds)[this->nfds].events = POLLIN;
@@ -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[16]) 9 +socketAccept(Sock this, char (*remoteAddr)[])
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,8 +33,9 @@ socketAccept(Sock this, char remoteAddr[16]) @@ -33,8 +33,9 @@ socketAccept(Sock this, char remoteAddr[16])
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 loggerLog(this->log, LOGGER_INFO, 37 loggerLog(this->log, LOGGER_INFO,
37 - "handling client %s\n", inet_ntoa((sock->addr).sin_addr)); 38 + "handling client %s\n", *remoteAddr);
38 } 39 }
39 40
40 return sock; 41 return sock;
@@ -19,7 +19,7 @@ int @@ -19,7 +19,7 @@ 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); 22 + HttpWorker worker = new(HttpWorker, "", 0);
23 Server server = new(Server, logger, worker, 11212, SOMAXCONN); 23 Server server = new(Server, logger, worker, 11212, SOMAXCONN);
24 24
25 struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY}; 25 struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY};
Please register or login to post a comment