Commit 56fdd4bd00d7de8cb9553630c0d69f7f94cb6db0

Authored by Georg Hopp
1 parent 81775827

changed socket handling according to my definition...and make sockets nonblockin…

…g as the answer of poll is just a guess...
... ... @@ -17,3 +17,6 @@ VERY BIG TODO:
17 17
18 18 GET /images/waldschrat.jpg HTTP/1.1^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D^[[D
19 19 ^[[D = backspace...
  20 +
  21 +- the unexpected connection close seems to occur just on concurrency over
  22 + 1000 paralell connections...maybe this gives a hint.
... ...
... ... @@ -40,6 +40,7 @@ CLASS(Sock) {
40 40 void socketConnect(Sock this, const char * addr, char (*)[16]);
41 41 void socketListen(Sock this, int backlog);
42 42 Sock socketAccept(Sock this, char (*remoteAddr)[16]);
  43 +void socketNonblock(Sock this);
43 44
44 45 #endif // __SOCKET_H__
45 46
... ...
... ... @@ -31,8 +31,8 @@
31 31 ssize_t
32 32 cbufRead(Cbuf this, Stream st)
33 33 {
34   - ssize_t rrsize = 0;
35   - size_t rsize = cbufGetFree(this);
  34 + size_t rsize = cbufGetFree(this);
  35 + ssize_t rrsize;
36 36
37 37 if (0 == rsize) {
38 38 errno = ECBUFOVFL;
... ... @@ -41,17 +41,8 @@ cbufRead(Cbuf this, Stream st)
41 41
42 42 rrsize = streamRead(st, cbufGetWrite(this), rsize);
43 43
44   - switch (rrsize) {
45   - case 0:
46   - rrsize = -2;
47   - // DROP THROUGH
48   -
49   - case -1:
50   - break;
51   -
52   - default:
53   - cbufIncWrite(this, rrsize);
54   - break;
  44 + if (0 < rrsize) {
  45 + cbufIncWrite(this, rrsize);
55 46 }
56 47
57 48 return rrsize;
... ...
... ... @@ -61,6 +61,8 @@ httpParserParse(void * _this, Stream st)
61 61 }
62 62
63 63 if (0 > (read = cbufRead(this->buffer, st))) {
  64 + cbufRelease(this->buffer);
  65 + this->ourLock = FALSE;
64 66 return read;
65 67 }
66 68
... ... @@ -75,10 +77,9 @@ httpParserParse(void * _this, Stream st)
75 77 cbufRelease(this->buffer);
76 78 this->ourLock = FALSE;
77 79 cont = 0;
  80 + break;
78 81 }
79 82
80   - break;
81   -
82 83 case HTTP_MESSAGE_START:
83 84 if (NULL == (line = cbufGetLine(this->buffer, &line_end))) {
84 85 if (! cbufIsEmpty(this->buffer)) {
... ... @@ -98,17 +99,16 @@ httpParserParse(void * _this, Stream st)
98 99 if (NULL == this->current) {
99 100 cbufRelease(this->buffer);
100 101 this->ourLock = FALSE;
101   - return -1;
  102 + return -2; // a server error occured can't process...
102 103 }
103 104 httpParserRequestVars(this);
104 105
105 106 this->state = HTTP_MESSAGE_INTRO_DONE;
106   - break;
107 107
108 108 case HTTP_MESSAGE_INTRO_DONE:
109 109 if (NULL == (line = cbufGetLine(this->buffer, &line_end))) {
110 110 if (! cbufIsEmpty(this->buffer)) {
111   - this->isize = this->buffer->bused;
  111 + this->isize = this->buffer->bused;
112 112 this->incomplete = memMalloc(this->isize);
113 113 memcpy(this->incomplete,
114 114 cbufGetData(this->buffer, this->isize),
... ... @@ -120,35 +120,34 @@ httpParserParse(void * _this, Stream st)
120 120 break;
121 121 }
122 122
123   - if (0 == strlen(line)) {
124   - this->state = HTTP_MESSAGE_HEADERS_DONE;
  123 + if (0 != strlen(line)) {
  124 + httpParserHeader(this, line, line_end);
125 125 break;
126 126 }
127 127
128   - httpParserHeader(this, line, line_end);
129   - break;
  128 + this->state = HTTP_MESSAGE_HEADERS_DONE;
130 129
131 130 case HTTP_MESSAGE_HEADERS_DONE:
132 131 if (this->current->dbody == this->current->nbody) {
133 132 this->state = HTTP_MESSAGE_DONE;
134   - break;
135   - }
  133 + } else {
  134 + if (cbufIsEmpty(this->buffer)) {
  135 + cbufRelease(this->buffer);
  136 + this->ourLock = FALSE;
  137 + cont = 0;
  138 + break;
  139 + }
  140 +
  141 + cbufIncRead(
  142 + this->buffer,
  143 + httpParserBody(
  144 + this,
  145 + cbufGetRead(this->buffer),
  146 + this->buffer->bused));
136 147
137   - if (cbufIsEmpty(this->buffer)) {
138   - cbufRelease(this->buffer);
139   - this->ourLock = FALSE;
140   - cont = 0;
141 148 break;
142 149 }
143 150
144   - cbufIncRead(
145   - this->buffer,
146   - httpParserBody(
147   - this,
148   - cbufGetRead(this->buffer),
149   - this->buffer->bused));
150   - break;
151   -
152 151 case HTTP_MESSAGE_DONE:
153 152 {
154 153 HttpHeader enc = hashGet(
... ...
... ... @@ -54,10 +54,13 @@ char * httpWorkerGetMimeType(HttpWorker, const char * extension);
54 54 ssize_t
55 55 httpWorkerProcess(HttpWorker this, Stream st)
56 56 {
57   - ssize_t size;
  57 + ssize_t requests = httpParserParse(this->parser, st);
58 58
59   - if (0 < (size = httpParserParse(this->parser, st))) {
  59 + if (0 > requests) {
  60 + return requests;
  61 + }
60 62
  63 + if (0 < requests) {
61 64 while (! queueEmpty(this->parser->queue)) {
62 65 HttpRequest request = queueGet(this->parser->queue);
63 66 HttpMessage response = NULL;
... ... @@ -212,18 +215,13 @@ httpWorkerProcess(HttpWorker this, Stream st)
212 215 }
213 216
214 217 httpWorkerAddCommonHeader((HttpMessage)request, response);
215   -
216 218 delete(request);
217   -
218 219 queuePut(this->writer->queue, response);
219   -
220   - size = this->writer->queue->nmsg;
221   -
222 220 response = NULL;
223 221 }
224 222 }
225 223
226   - return size;
  224 + return this->writer->queue->nmsg;
227 225 }
228 226
229 227 // vim: set ts=4 sw=4:
... ...
... ... @@ -44,6 +44,7 @@ serverHandleAccept(Server this, unsigned int i)
44 44 }
45 45
46 46 acc = socketAccept((0 == i)? this->sock : this->sockSSL, &remoteAddr);
  47 + socketNonblock(acc);
47 48
48 49 if (-1 != acc->handle) {
49 50 switch(i) {
... ...
... ... @@ -33,11 +33,12 @@ ssize_t serverWrite(Server, unsigned int);
33 33 void
34 34 serverRun(Server this)
35 35 {
  36 + int events = 0;
  37 +
36 38 loggerLog(this->logger, LOGGER_INFO, "service started");
37 39
38 40 while (!doShutdown) //! until error or signal
39 41 {
40   - int events = 0;
41 42 unsigned int i;
42 43
43 44 if (0 == events) {
... ... @@ -71,12 +72,25 @@ serverRun(Server this)
71 72 if (0 != ((this->fds)[i].revents & POLLIN)) {
72 73 ssize_t processed = serverRead(this, i);
73 74
74   - if (0 < processed) {
75   - (this->fds)[i].revents &= ~POLLIN;
  75 + // don't poll this one until I say.
  76 + (this->fds)[i].events &= ~POLLIN;
  77 +
  78 + if (0 > processed) {
76 79 events--;
  80 +
  81 + switch (processed) {
  82 + case -1: // poll me again
  83 + (this->fds)[i].events |= POLLIN;
  84 + (this->fds)[i].revents &= ~POLLIN;
  85 + break;
  86 +
  87 + case -2: // close me...
  88 + serverCloseConn(this, i);
  89 + break;
  90 + }
77 91 }
78 92
79   - if (processed > 0) {
  93 + if (0 < processed) {
80 94 (this->fds)[i].events |= POLLOUT;
81 95 }
82 96 }
... ... @@ -87,11 +101,20 @@ serverRun(Server this)
87 101 if (0 != ((this->fds)[i].revents & POLLOUT)) {
88 102 ssize_t remaining = serverWrite(this, i);
89 103
90   - if (0 > remaining) {
  104 + (this->fds)[i].events &= ~POLLOUT;
  105 +
  106 + if (0 >= remaining) {
  107 + /*
  108 + * 0 means queue was empty...try again next
  109 + * time...no need to poll again.
  110 + * Anyway, most likely we need to read again
  111 + * so lets finish this event for now.
  112 + */
91 113 events--;
92 114
93 115 switch (remaining) {
94 116 case -1: // poll me again
  117 + (this->fds)[i].events |= POLLOUT;
95 118 (this->fds)[i].revents &= ~POLLOUT;
96 119 break;
97 120
... ... @@ -100,10 +123,6 @@ serverRun(Server this)
100 123 break;
101 124 }
102 125 }
103   -
104   - if (0 == remaining) {
105   - (this->fds)[i].events &= ~POLLOUT;
106   - }
107 126 }
108 127
109 128 if (0 > events)
... ...
... ... @@ -70,6 +70,7 @@ serverCtor(void * _this, va_list * params)
70 70 this->conns = memCalloc(sizeof(struct conns), this->max_fds);
71 71
72 72 this->sock = new(Sock, this->logger, port);
  73 + socketNonblock(this->sock);
73 74 flags = fcntl(this->sock->handle, F_GETFL, 0);
74 75 fcntl(this->sock->handle, F_SETFL, flags | O_NONBLOCK);
75 76
... ...
... ... @@ -2,5 +2,5 @@ ACLOCAL_AMFLAGS = -I m4
2 2
3 3 noinst_LIBRARIES = libsocket.a
4 4
5   -libsocket_a_SOURCES = socket.c accept.c connect.c listen.c
  5 +libsocket_a_SOURCES = socket.c accept.c connect.c listen.c nonblock.c
6 6 libsocket_a_CFLAGS = $(CFLAGS) -Wall -I ../../include/
... ...
... ... @@ -22,6 +22,7 @@
22 22
23 23 #include <errno.h> // for errno
24 24 #include <unistd.h>
  25 +#include <fcntl.h>
25 26
26 27 #include "socket.h"
27 28 #include "class.h"
... ... @@ -36,13 +37,6 @@ socketAccept(Sock this, char (*remoteAddr)[16])
36 37 // Set the size of the in-out parameter
37 38 len = sizeof(this->addr);
38 39
39   - /**
40   - * \todo Uhh, this is bad. we open a new socket additionally to
41   - * the one we get from the accept call.
42   - * i have to change the socket constructor to be able to create
43   - * the data structure without creation of a socket at all.
44   - * For now i simply close the socket here.... :D
45   - */
46 40 sock = new(Sock, this->log, -1);
47 41
48 42 // Wait for a client to connect
... ...
... ... @@ -35,6 +35,7 @@ socketCtor(void * _this, va_list * params)
35 35 Sock this = _this;
36 36 int reUse = 1; //! \todo make this configurable
37 37 int port;
  38 + int nonblock;
38 39
39 40 this->log = va_arg(* params, Logger);
40 41 port = va_arg(* params, int);
... ...
... ... @@ -22,6 +22,7 @@
22 22
23 23 #include <openssl/ssl.h>
24 24 #include <unistd.h>
  25 +#include <errno.h>
25 26
26 27 #include "stream.h"
27 28
... ... @@ -31,8 +32,30 @@ streamRead(Stream this, void * buf, size_t count)
31 32 ssize_t done;
32 33
33 34 switch(this->type) {
  35 + ssize_t _read;
  36 +
34 37 case STREAM_FD:
35   - done = read((this->handle).fd, buf, count);
  38 + _read = read((this->handle).fd, buf, count);
  39 +
  40 + if (_read < 0) {
  41 + switch (errno) {
  42 + case EINTR:
  43 + case ENOMEM:
  44 + done = 0;
  45 + break;
  46 + case (EAGAIN|EWOULDBLOCK):
  47 + done = -1;
  48 + break;
  49 + default:
  50 + done = -2;
  51 + break;
  52 + }
  53 + } else if (_read == 0) {
  54 + done = -2;
  55 + } else {
  56 + done = _read;
  57 + }
  58 +
36 59 break;
37 60
38 61 case STREAM_SSL:
... ...
... ... @@ -45,6 +45,7 @@
45 45
46 46 #include "utils/signalHandling.h"
47 47 #include "utils/memory.h"
  48 +#include "utils/mime_type.h"
48 49
49 50 #define DEFAULT_SECS 10
50 51 //#define DEFAULT_USECS (1000000 / HZ * 2)
... ...
Please register or login to post a comment