Commit e8a21ace314922f3db29446bc56e10f9b557169f
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.
Showing
26 changed files
with
703 additions
and
218 deletions
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 |
doc/file-upload.txt
0 → 100644
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-- |
doc/file-upload2.txt
0 → 100644
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 | }; |
include/ringbuffer.h
0 → 100644
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; |
src/rbtest.c
0 → 100644
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: |
src/ringbuffer.c
0 → 100644
1 | +#define _POSIX_SOURCE | ||
2 | +#define _POSIX_C_SOURCE 200112L | ||
3 | + | ||
4 | +#include <sys/types.h> | ||
5 | +#include <sys/stat.h> | ||
6 | +#include <sys/mman.h> | ||
7 | +#include <stdarg.h> | ||
8 | +#include <stdlib.h> | ||
9 | +#include <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: |
src/ringbuffer/rb_read.c
0 → 100644
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