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 | 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 | 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 | 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 | 4 | #include "class.h" |
5 | 5 | #include "http/request.h" |
6 | 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 | 24 | typedef enum e_HttpRequestState { |
... | ... | @@ -21,11 +31,7 @@ typedef enum e_HttpRequestState { |
21 | 31 | |
22 | 32 | |
23 | 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 | 36 | HttpMessageQueue request_queue; |
31 | 37 | HttpRequest cur_request; |
... | ... | @@ -34,11 +40,11 @@ CLASS(HttpRequestParser) { |
34 | 40 | }; |
35 | 41 | |
36 | 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 | 49 | #endif /* __HTTP_REQUEST_PARSER_H__ */ |
44 | 50 | ... | ... |
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 | 15 | |
16 | 16 | void socketConnect(Sock this, const char * addr); |
17 | 17 | void socketListen(Sock this, int backlog); |
18 | -Sock socketAccept(Sock this, char remoteAddr[16]); | |
18 | +Sock socketAccept(Sock this, char (*remoteAddr)[]); | |
19 | 19 | |
20 | 20 | #endif // __SOCKET_H__ |
21 | 21 | ... | ... |
... | ... | @@ -5,6 +5,7 @@ IFACE = interface/class.c interface/stream_reader.c interface/logger.c \ |
5 | 5 | interface/stream_writer.c interface/http_intro.c \ |
6 | 6 | interface/subject.c interface/observer.c |
7 | 7 | CLASS = class.c interface.c |
8 | +RB = ringbuffer.c ringbuffer/rb_read.c | |
8 | 9 | SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c |
9 | 10 | SERVER = server.c server/run.c server/close_conn.c |
10 | 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 | 22 | http/header/size_get.c http/header/to_string.c |
22 | 23 | PARSER = http/request/parser.c http/request/parser/get_header.c \ |
23 | 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 | 28 | AM_CFLAGS = -Wall -I ../include/ |
... | ... | @@ -30,6 +31,7 @@ bin_PROGRAMS = testserver |
30 | 31 | |
31 | 32 | testserver_SOURCES = testserver.c \ |
32 | 33 | $(IFACE) $(CLASS) $(SOCKET) $(SERVER) $(LOGGER) $(MSG) $(REQ) \ |
33 | - $(WRITER) $(RESP) $(HEADER) $(PARSER) $(WORKER) \ | |
34 | + $(WRITER) $(RESP) $(HEADER) $(PARSER) $(WORKER) $(RB) \ | |
34 | 35 | signalHandling.c daemonize.c |
35 | 36 | testserver_CFLAGS = -Wall -I ../include/ |
37 | +testserver_LDFLAGS = -lrt | ... | ... |
... | ... | @@ -10,18 +10,18 @@ |
10 | 10 | #include "http/request/parser.h" |
11 | 11 | #include "http/message/queue.h" |
12 | 12 | #include "http/request.h" |
13 | +#include "ringbuffer.h" | |
13 | 14 | |
14 | 15 | |
15 | 16 | static |
16 | 17 | void |
17 | 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 | 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 | 27 | static |
... | ... | @@ -30,36 +30,16 @@ dtor(void * _this) |
30 | 30 | { |
31 | 31 | HttpRequestParser this = _this; |
32 | 32 | |
33 | - free(this->buffer); | |
34 | 33 | delete(&(this->request_queue)); |
34 | + delete(&(this->buffer)); | |
35 | 35 | |
36 | 36 | if (NULL != this->cur_request) |
37 | 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 | 43 | CREATE_CLASS(HttpRequestParser, NULL, IFACE(Class), IFACE(StreamReader)); |
64 | 44 | |
65 | 45 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -4,33 +4,50 @@ |
4 | 4 | #include "http/message.h" |
5 | 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 | 13 | void |
8 | 14 | httpRequestParserGetBody(HttpRequestParser this) |
9 | 15 | { |
10 | 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 | 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 | 51 | this->state = HTTP_REQUEST_DONE; |
35 | 52 | } |
36 | 53 | } | ... | ... |
1 | +#include <stdlib.h> | |
2 | +#include <string.h> | |
1 | 3 | #include <search.h> |
2 | 4 | #include <ctype.h> |
3 | 5 | #include <stdio.h> |
... | ... | @@ -6,17 +8,32 @@ |
6 | 8 | #include "interface/class.h" |
7 | 9 | #include "http/header.h" |
8 | 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 | 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 | 39 | // vim: set ts=4 sw=4: | ... | ... |
1 | 1 | #include <stdlib.h> |
2 | 2 | #include <string.h> |
3 | 3 | |
4 | +#include "http/message.h" | |
4 | 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 | 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 | 95 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -3,112 +3,147 @@ |
3 | 3 | #include <unistd.h> |
4 | 4 | #include <ctype.h> |
5 | 5 | |
6 | +#include "http/request.h" | |
7 | +#include "http/message.h" | |
6 | 8 | #include "http/request/parser.h" |
7 | 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 | 19 | static |
11 | 20 | inline |
12 | 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 | 39 | static |
29 | 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 | 54 | ssize_t |
37 | -httpRequestParserParse(HttpRequestParser this) | |
55 | +httpRequestParserParse(HttpRequestParser this, int fd) | |
38 | 56 | { |
39 | - char * line; | |
40 | 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 | 64 | while (cont) { |
44 | 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 | 77 | break; |
52 | 78 | |
53 | 79 | case HTTP_REQUEST_START: |
54 | - if (NULL == (line = httpRequestParserGetLine(&(this->cur_data)))) { | |
80 | + if (NULL == (line_end = getLine(this))) { | |
55 | 81 | cont = 0; |
56 | 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 | 98 | this->state = HTTP_REQUEST_REQUEST_LINE_DONE; |
62 | 99 | break; |
63 | 100 | |
64 | 101 | case HTTP_REQUEST_REQUEST_LINE_DONE: |
65 | - if (NULL == (line = httpRequestParserGetLine(&(this->cur_data)))) { | |
102 | + if (NULL == (line_end = getLine(this))) { | |
66 | 103 | cont = 0; |
67 | 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 | 114 | this->state = HTTP_REQUEST_HEADERS_DONE; |
72 | 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 | 127 | break; |
77 | 128 | |
78 | 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 | 137 | httpRequestParserGetBody(this); |
80 | 138 | break; |
81 | 139 | |
82 | 140 | case HTTP_REQUEST_DONE: |
83 | - /** | |
84 | - * enqueue current request | |
85 | - */ | |
86 | 141 | this->request_queue->msgs[(this->request_queue->nmsgs)++] = |
87 | 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 | 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 | 147 | this->state = HTTP_REQUEST_GARBAGE; |
113 | 148 | |
114 | 149 | break; |
... | ... | @@ -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 | 159 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -3,46 +3,40 @@ |
3 | 3 | |
4 | 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 | 14 | ssize_t |
8 | 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 | 42 | // vim: set ts=4 sw=4: | ... | ... |
1 | 1 | #include <stdlib.h> |
2 | 2 | #include <string.h> |
3 | 3 | #include <stdio.h> |
4 | -#include <time.h> | |
5 | 4 | |
6 | 5 | #include "class.h" |
7 | 6 | #include "interface/class.h" |
... | ... | @@ -23,8 +22,6 @@ |
23 | 22 | HttpResponse |
24 | 23 | httpResponse404() |
25 | 24 | { |
26 | - time_t t; | |
27 | - struct tm * tmp; | |
28 | 25 | char buffer[200]; |
29 | 26 | HttpResponse response; |
30 | 27 | HttpMessage message; |
... | ... | @@ -46,12 +43,6 @@ httpResponse404() |
46 | 43 | httpHeaderAdd(&(message->header), |
47 | 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 | 46 | return response; |
56 | 47 | } |
57 | 48 | ... | ... |
1 | 1 | #include <stdlib.h> |
2 | 2 | #include <string.h> |
3 | 3 | #include <stdio.h> |
4 | -#include <time.h> | |
5 | 4 | #include <sys/stat.h> |
6 | 5 | #include <fcntl.h> |
7 | 6 | |
... | ... | @@ -16,8 +15,6 @@ |
16 | 15 | HttpResponse |
17 | 16 | httpResponseImage() |
18 | 17 | { |
19 | - time_t t; | |
20 | - struct tm * tmp; | |
21 | 18 | char buffer[200]; |
22 | 19 | struct stat st; |
23 | 20 | HttpResponse response; |
... | ... | @@ -40,12 +37,6 @@ httpResponseImage() |
40 | 37 | httpHeaderAdd(&(message->header), |
41 | 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 | 40 | return response; |
50 | 41 | } |
51 | 42 | ... | ... |
1 | 1 | #include <stdlib.h> |
2 | 2 | #include <string.h> |
3 | 3 | #include <stdio.h> |
4 | -#include <time.h> | |
5 | 4 | |
6 | 5 | #include "class.h" |
7 | 6 | #include "interface/class.h" |
... | ... | @@ -23,8 +22,6 @@ |
23 | 22 | HttpResponse |
24 | 23 | httpResponseMe() |
25 | 24 | { |
26 | - time_t t; | |
27 | - struct tm * tmp; | |
28 | 25 | char buffer[200]; |
29 | 26 | HttpResponse response; |
30 | 27 | HttpMessage message; |
... | ... | @@ -46,12 +43,6 @@ httpResponseMe() |
46 | 43 | httpHeaderAdd(&(message->header), |
47 | 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 | 46 | return response; |
56 | 47 | } |
57 | 48 | ... | ... |
... | ... | @@ -21,7 +21,7 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd) |
21 | 21 | { |
22 | 22 | HttpMessageQueue respq = this->response_queue; |
23 | 23 | HttpMessage message = (HttpMessage)this->cur_response; |
24 | - ssize_t processed = (message)? 1 : 0; | |
24 | + ssize_t processed = (message)? 1 : 0; | |
25 | 25 | int cont = 1; |
26 | 26 | |
27 | 27 | while (cont) { |
... | ... | @@ -74,7 +74,6 @@ httpResponseWriterWrite(HttpResponseWriter this, int fd) |
74 | 74 | &(this->pipe[this->pend]), |
75 | 75 | &(message->body[this->nbuffer]), |
76 | 76 | temp); |
77 | - | |
78 | 77 | break; |
79 | 78 | |
80 | 79 | case HTTP_MESSAGE_PIPED: | ... | ... |
1 | +#include <stdlib.h> | |
1 | 2 | #include <stdarg.h> |
3 | +#include <string.h> | |
2 | 4 | |
3 | 5 | #include "class.h" |
4 | 6 | #include "http/worker.h" |
... | ... | @@ -9,13 +11,19 @@ |
9 | 11 | #include "interface/stream_reader.h" |
10 | 12 | #include "interface/stream_writer.h" |
11 | 13 | |
14 | +#define SHMN "/worker_" | |
12 | 15 | static |
13 | 16 | void |
14 | 17 | ctor(void * _this, va_list * params) |
15 | 18 | { |
16 | 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 | 27 | this->writer = new(HttpResponseWriter); |
20 | 28 | } |
21 | 29 | |
... | ... | @@ -29,20 +37,7 @@ dtor(void * _this) |
29 | 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 | 41 | INIT_IFACE(StreamReader, (fptr_streamReaderRead)httpWorkerProcess); |
47 | 42 | INIT_IFACE(StreamWriter, (fptr_streamWriterWrite)httpWorkerWrite); |
48 | 43 | CREATE_CLASS( | ... | ... |
1 | +#include <time.h> | |
2 | + | |
1 | 3 | #include "class.h" |
2 | 4 | #include "interface/class.h" |
3 | 5 | |
4 | 6 | #include "http/worker.h" |
5 | 7 | #include "http/request/parser.h" |
8 | +#include "http/header.h" | |
9 | +#include "http/request.h" | |
10 | +#include "http/message.h" | |
6 | 11 | |
7 | 12 | ssize_t |
8 | 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 | 21 | int i; |
14 | 22 | HttpMessageQueue reqq = this->parser->request_queue; |
15 | 23 | HttpMessageQueue respq = this->writer->response_queue; |
... | ... | @@ -19,8 +27,8 @@ httpWorkerProcess(HttpWorker this, int fd) |
19 | 27 | * @TODO: for now simply remove request and send not found. |
20 | 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 | 33 | if (0 == strcmp("GET", request->method) && |
26 | 34 | 0 == strcmp("/me/", request->uri)) { |
... | ... | @@ -45,12 +53,19 @@ httpWorkerProcess(HttpWorker this, int fd) |
45 | 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 | 62 | respq->msgs[(respq->nmsgs)++] = response; |
49 | 63 | response = NULL; |
50 | 64 | delete(&(reqq->msgs[i])); |
51 | 65 | } |
52 | 66 | |
53 | 67 | reqq->nmsgs = 0; |
68 | + size = respq->nmsgs; | |
54 | 69 | } |
55 | 70 | |
56 | 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 | 1 | #include <errno.h> |
2 | 2 | |
3 | +#include "http/worker.h" | |
4 | + | |
3 | 5 | static |
4 | 6 | int |
5 | 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 | 10 | Sock acc; |
9 | 11 | |
10 | - acc = socketAccept(this->sock, remoteAddr); | |
12 | + acc = socketAccept(this->sock, &remoteAddr); | |
11 | 13 | |
12 | 14 | if (-1 != acc->handle) { |
13 | 15 | //* save the socket handle |
14 | 16 | (this->conns)[acc->handle].sock = acc; |
15 | 17 | |
16 | 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 | 21 | (this->fds)[this->nfds].fd = acc->handle; |
20 | 22 | (this->fds)[this->nfds].events = POLLIN; | ... | ... |
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 | #include "interface/logger.h" |
7 | 7 | |
8 | 8 | Sock |
9 | -socketAccept(Sock this, char remoteAddr[16]) | |
9 | +socketAccept(Sock this, char (*remoteAddr)[]) | |
10 | 10 | { |
11 | 11 | Sock sock; /* Socket for client */ |
12 | 12 | unsigned int len; /* Length of client address data structure */ |
... | ... | @@ -33,8 +33,9 @@ socketAccept(Sock this, char remoteAddr[16]) |
33 | 33 | loggerLog(this->log, LOGGER_WARNING, |
34 | 34 | "error accepting connection: %s", strerror(errno)); |
35 | 35 | } else { |
36 | + memcpy(*remoteAddr, inet_ntoa((sock->addr).sin_addr), 15); | |
36 | 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 | 41 | return sock; | ... | ... |
... | ... | @@ -19,7 +19,7 @@ int |
19 | 19 | main() |
20 | 20 | { |
21 | 21 | Logger logger = new(LoggerSyslog, LOGGER_ERR); |
22 | - HttpWorker worker = new(HttpWorker); | |
22 | + HttpWorker worker = new(HttpWorker, "", 0); | |
23 | 23 | Server server = new(Server, logger, worker, 11212, SOMAXCONN); |
24 | 24 | |
25 | 25 | struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY}; | ... | ... |
Please
register
or
login
to post a comment