Commit 56fdd4bd00d7de8cb9553630c0d69f7f94cb6db0
1 parent
81775827
changed socket handling according to my definition...and make sockets nonblockin…
…g as the answer of poll is just a guess...
Showing
13 changed files
with
94 additions
and
62 deletions
... | ... | @@ -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: | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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: | ... | ... |
Please
register
or
login
to post a comment