aboutsummaryrefslogtreecommitdiff
path: root/src/daemon/connection.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2007-08-12 06:01:48 +0000
committerChristian Grothoff <christian@grothoff.org>2007-08-12 06:01:48 +0000
commit85b7d00955a8adb9e6d8d42ba37c5c0d53cafc53 (patch)
treea5c244da50ef0a5659e368cb9c1ac91b0861076c /src/daemon/connection.c
parentc75bf1093162231d4e2f09f399f2d6039d2c321f (diff)
downloadlibmicrohttpd-85b7d00955a8adb9e6d8d42ba37c5c0d53cafc53.tar.gz
libmicrohttpd-85b7d00955a8adb9e6d8d42ba37c5c0d53cafc53.zip
formatting and versioning
Diffstat (limited to 'src/daemon/connection.c')
-rw-r--r--src/daemon/connection.c1541
1 files changed, 777 insertions, 764 deletions
diff --git a/src/daemon/connection.c b/src/daemon/connection.c
index b5d0b3dd..fdbc975c 100644
--- a/src/daemon/connection.c
+++ b/src/daemon/connection.c
@@ -50,29 +50,29 @@
50 * @return number of entries iterated over 50 * @return number of entries iterated over
51 */ 51 */
52int 52int
53MHD_get_connection_values(struct MHD_Connection * connection, 53MHD_get_connection_values (struct MHD_Connection *connection,
54 enum MHD_ValueKind kind, 54 enum MHD_ValueKind kind,
55 MHD_KeyValueIterator iterator, 55 MHD_KeyValueIterator iterator, void *iterator_cls)
56 void * iterator_cls) { 56{
57 int ret; 57 int ret;
58 struct MHD_HTTP_Header * pos; 58 struct MHD_HTTP_Header *pos;
59 59
60 if (connection == NULL) 60 if (connection == NULL)
61 return -1; 61 return -1;
62 ret = 0; 62 ret = 0;
63 pos = connection->headers_received; 63 pos = connection->headers_received;
64 while (pos != NULL) { 64 while (pos != NULL)
65 if (0 != (pos->kind & kind)) { 65 {
66 ret++; 66 if (0 != (pos->kind & kind))
67 if ( (iterator != NULL) && 67 {
68 (MHD_YES != iterator(iterator_cls, 68 ret++;
69 kind, 69 if ((iterator != NULL) &&
70 pos->header, 70 (MHD_YES != iterator (iterator_cls,
71 pos->value)) ) 71 kind, pos->header, pos->value)))
72 return ret; 72 return ret;
73 }
74 pos = pos->next;
73 } 75 }
74 pos = pos->next;
75 }
76 return ret; 76 return ret;
77} 77}
78 78
@@ -85,21 +85,20 @@ MHD_get_connection_values(struct MHD_Connection * connection,
85 * @return NULL if no such item was found 85 * @return NULL if no such item was found
86 */ 86 */
87const char * 87const char *
88MHD_lookup_connection_value(struct MHD_Connection * connection, 88MHD_lookup_connection_value (struct MHD_Connection *connection,
89 enum MHD_ValueKind kind, 89 enum MHD_ValueKind kind, const char *key)
90 const char * key) { 90{
91 struct MHD_HTTP_Header * pos; 91 struct MHD_HTTP_Header *pos;
92 92
93 if (connection == NULL) 93 if (connection == NULL)
94 return NULL; 94 return NULL;
95 pos = connection->headers_received; 95 pos = connection->headers_received;
96 while (pos != NULL) { 96 while (pos != NULL)
97 if ( (0 != (pos->kind & kind)) && 97 {
98 (0 == strcasecmp(key, 98 if ((0 != (pos->kind & kind)) && (0 == strcasecmp (key, pos->header)))
99 pos->header)) ) 99 return pos->value;
100 return pos->value; 100 pos = pos->next;
101 pos = pos->next; 101 }
102 }
103 return NULL; 102 return NULL;
104} 103}
105 104
@@ -114,25 +113,24 @@ MHD_lookup_connection_value(struct MHD_Connection * connection,
114 * MHD_YES on success or if message has been queued 113 * MHD_YES on success or if message has been queued
115 */ 114 */
116int 115int
117MHD_queue_response(struct MHD_Connection * connection, 116MHD_queue_response (struct MHD_Connection *connection,
118 unsigned int status_code, 117 unsigned int status_code, struct MHD_Response *response)
119 struct MHD_Response * response) { 118{
120 if ( (connection == NULL) || 119 if ((connection == NULL) ||
121 (response == NULL) || 120 (response == NULL) ||
122 (connection->response != NULL) || 121 (connection->response != NULL) ||
123 (connection->bodyReceived == 0) || 122 (connection->bodyReceived == 0) || (connection->headersReceived == 0))
124 (connection->headersReceived == 0) ) 123 return MHD_NO;
125 return MHD_NO; 124 MHD_increment_response_rc (response);
126 MHD_increment_response_rc(response);
127 connection->response = response; 125 connection->response = response;
128 connection->responseCode = status_code; 126 connection->responseCode = status_code;
129 if ( (connection->method != NULL) && 127 if ((connection->method != NULL) &&
130 (0 == strcasecmp(connection->method, 128 (0 == strcasecmp (connection->method, MHD_HTTP_METHOD_HEAD)))
131 MHD_HTTP_METHOD_HEAD)) ) { 129 {
132 /* if this is a "HEAD" request, pretend that we 130 /* if this is a "HEAD" request, pretend that we
133 have already sent the full message body */ 131 have already sent the full message body */
134 connection->messagePos = response->total_size; 132 connection->messagePos = response->total_size;
135 } 133 }
136 return MHD_YES; 134 return MHD_YES;
137} 135}
138 136
@@ -140,20 +138,20 @@ MHD_queue_response(struct MHD_Connection * connection,
140 * Do we (still) need to send a 100 continue 138 * Do we (still) need to send a 100 continue
141 * message for this connection? 139 * message for this connection?
142 */ 140 */
143static int 141static int
144MHD_need_100_continue(struct MHD_Connection * connection) { 142MHD_need_100_continue (struct MHD_Connection *connection)
145 const char * expect; 143{
144 const char *expect;
146 145
147 return ( (connection->version != NULL) && 146 return ((connection->version != NULL) &&
148 (0 == strcasecmp(connection->version, 147 (0 == strcasecmp (connection->version,
149 MHD_HTTP_VERSION_1_1)) && 148 MHD_HTTP_VERSION_1_1)) &&
150 (connection->headersReceived == 1) && 149 (connection->headersReceived == 1) &&
151 (NULL != (expect = MHD_lookup_connection_value(connection, 150 (NULL != (expect = MHD_lookup_connection_value (connection,
152 MHD_HEADER_KIND, 151 MHD_HEADER_KIND,
153 MHD_HTTP_HEADER_EXPECT))) && 152 MHD_HTTP_HEADER_EXPECT)))
154 (0 == strcasecmp(expect, 153 && (0 == strcasecmp (expect, "100-continue"))
155 "100-continue")) && 154 && (connection->continuePos < strlen (HTTP_100_CONTINUE)));
156 (connection->continuePos < strlen(HTTP_100_CONTINUE)) );
157} 155}
158 156
159/** 157/**
@@ -162,49 +160,56 @@ MHD_need_100_continue(struct MHD_Connection * connection) {
162 * @return MHD_YES on success 160 * @return MHD_YES on success
163 */ 161 */
164int 162int
165MHD_connection_get_fdset(struct MHD_Connection * connection, 163MHD_connection_get_fdset (struct MHD_Connection *connection,
166 fd_set * read_fd_set, 164 fd_set * read_fd_set,
167 fd_set * write_fd_set, 165 fd_set * write_fd_set,
168 fd_set * except_fd_set, 166 fd_set * except_fd_set, int *max_fd)
169 int * max_fd) { 167{
170 int fd; 168 int fd;
171 void * buf; 169 void *buf;
172 170
173 fd = connection->socket_fd; 171 fd = connection->socket_fd;
174 if (fd == -1) 172 if (fd == -1)
175 return MHD_YES; 173 return MHD_YES;
176 if ( (connection->read_close == MHD_NO) && 174 if ((connection->read_close == MHD_NO) &&
177 ( (connection->headersReceived == 0) || 175 ((connection->headersReceived == 0) ||
178 (connection->readLoc < connection->read_buffer_size) ) ) { 176 (connection->readLoc < connection->read_buffer_size)))
179 FD_SET(fd, read_fd_set); 177 {
180 if (fd > *max_fd) 178 FD_SET (fd, read_fd_set);
181 *max_fd = fd; 179 if (fd > *max_fd)
182 } else { 180 *max_fd = fd;
183 if ( (connection->read_close == MHD_NO) && 181 }
184 ( (connection->headersReceived == 1) && 182 else
185 (connection->post_processed == MHD_NO) && 183 {
186 (connection->readLoc == connection->read_buffer_size) ) ) { 184 if ((connection->read_close == MHD_NO) &&
187 /* try growing the read buffer, just in case */ 185 ((connection->headersReceived == 1) &&
188 buf = MHD_pool_reallocate(connection->pool, 186 (connection->post_processed == MHD_NO) &&
189 connection->read_buffer, 187 (connection->readLoc == connection->read_buffer_size)))
190 connection->read_buffer_size, 188 {
191 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE); 189 /* try growing the read buffer, just in case */
192 if (buf != NULL) { 190 buf = MHD_pool_reallocate (connection->pool,
193 /* we can actually grow the buffer, do it! */ 191 connection->read_buffer,
194 connection->read_buffer = buf; 192 connection->read_buffer_size,
195 connection->read_buffer_size = connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; 193 connection->read_buffer_size * 2 +
196 FD_SET(fd, read_fd_set); 194 MHD_BUF_INC_SIZE);
197 if (fd > *max_fd) 195 if (buf != NULL)
198 *max_fd = fd; 196 {
199 } 197 /* we can actually grow the buffer, do it! */
198 connection->read_buffer = buf;
199 connection->read_buffer_size =
200 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
201 FD_SET (fd, read_fd_set);
202 if (fd > *max_fd)
203 *max_fd = fd;
204 }
205 }
206 }
207 if ((connection->response != NULL) || MHD_need_100_continue (connection))
208 {
209 FD_SET (fd, write_fd_set);
210 if (fd > *max_fd)
211 *max_fd = fd;
200 } 212 }
201 }
202 if ( (connection->response != NULL) ||
203 MHD_need_100_continue(connection) ) {
204 FD_SET(fd, write_fd_set);
205 if (fd > *max_fd)
206 *max_fd = fd;
207 }
208 return MHD_YES; 213 return MHD_YES;
209} 214}
210 215
@@ -216,9 +221,10 @@ MHD_connection_get_fdset(struct MHD_Connection * connection,
216 * @param status_code the response code to send (413 or 414) 221 * @param status_code the response code to send (413 or 414)
217 */ 222 */
218static void 223static void
219MHD_excessive_data_handler(struct MHD_Connection * connection, 224MHD_excessive_data_handler (struct MHD_Connection *connection,
220 unsigned int status_code) { 225 unsigned int status_code)
221 struct MHD_Response * response; 226{
227 struct MHD_Response *response;
222 228
223 /* die, header far too long to be reasonable; 229 /* die, header far too long to be reasonable;
224 FIXME: send proper response to client 230 FIXME: send proper response to client
@@ -226,16 +232,12 @@ MHD_excessive_data_handler(struct MHD_Connection * connection,
226 connection->read_close = MHD_YES; 232 connection->read_close = MHD_YES;
227 connection->headersReceived = MHD_YES; 233 connection->headersReceived = MHD_YES;
228 connection->bodyReceived = MHD_YES; 234 connection->bodyReceived = MHD_YES;
229 MHD_DLOG(connection->daemon, 235 MHD_DLOG (connection->daemon,
230 "Received excessively long header, closing connection.\n"); 236 "Received excessively long header, closing connection.\n");
231 response = MHD_create_response_from_data(strlen(REQUEST_TOO_BIG), 237 response = MHD_create_response_from_data (strlen (REQUEST_TOO_BIG),
232 REQUEST_TOO_BIG, 238 REQUEST_TOO_BIG, MHD_NO, MHD_NO);
233 MHD_NO, 239 MHD_queue_response (connection, status_code, response);
234 MHD_NO); 240 MHD_destroy_response (response);
235 MHD_queue_response(connection,
236 status_code,
237 response);
238 MHD_destroy_response(response);
239} 241}
240 242
241/** 243/**
@@ -247,41 +249,47 @@ MHD_excessive_data_handler(struct MHD_Connection * connection,
247 * return NULL. Otherwise return a pointer to the line. 249 * return NULL. Otherwise return a pointer to the line.
248 */ 250 */
249static char * 251static char *
250MHD_get_next_header_line(struct MHD_Connection * connection) { 252MHD_get_next_header_line (struct MHD_Connection *connection)
251 char * rbuf; 253{
254 char *rbuf;
252 size_t pos; 255 size_t pos;
253 256
254 if (connection->readLoc == 0) 257 if (connection->readLoc == 0)
255 return NULL; 258 return NULL;
256 pos = 0; 259 pos = 0;
257 rbuf = connection->read_buffer; 260 rbuf = connection->read_buffer;
258 while ( (pos < connection->readLoc - 1) && 261 while ((pos < connection->readLoc - 1) &&
259 (rbuf[pos] != '\r') && 262 (rbuf[pos] != '\r') && (rbuf[pos] != '\n'))
260 (rbuf[pos] != '\n') )
261 pos++; 263 pos++;
262 if (pos == connection->readLoc - 1) { 264 if (pos == connection->readLoc - 1)
263 /* not found, consider growing... */ 265 {
264 if (connection->readLoc == connection->read_buffer_size) { 266 /* not found, consider growing... */
265 rbuf = MHD_pool_reallocate(connection->pool, 267 if (connection->readLoc == connection->read_buffer_size)
266 connection->read_buffer, 268 {
267 connection->read_buffer_size, 269 rbuf = MHD_pool_reallocate (connection->pool,
268 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE); 270 connection->read_buffer,
269 if (rbuf == NULL) { 271 connection->read_buffer_size,
270 MHD_excessive_data_handler(connection, 272 connection->read_buffer_size * 2 +
271 (connection->url != NULL) 273 MHD_BUF_INC_SIZE);
272 ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE 274 if (rbuf == NULL)
273 : MHD_HTTP_REQUEST_URI_TOO_LONG); 275 {
274 } else { 276 MHD_excessive_data_handler (connection,
275 connection->read_buffer_size = connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; 277 (connection->url != NULL)
276 connection->read_buffer = rbuf; 278 ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
277 } 279 : MHD_HTTP_REQUEST_URI_TOO_LONG);
280 }
281 else
282 {
283 connection->read_buffer_size =
284 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
285 connection->read_buffer = rbuf;
286 }
287 }
288 return NULL;
278 } 289 }
279 return NULL;
280 }
281 /* found, check if we have proper CRLF */ 290 /* found, check if we have proper CRLF */
282 if ( (rbuf[pos] == '\r') && 291 if ((rbuf[pos] == '\r') && (rbuf[pos + 1] == '\n'))
283 (rbuf[pos+1] == '\n') ) 292 rbuf[pos++] = '\0'; /* skip both r and n */
284 rbuf[pos++] = '\0'; /* skip both r and n */
285 rbuf[pos++] = '\0'; 293 rbuf[pos++] = '\0';
286 connection->read_buffer += pos; 294 connection->read_buffer += pos;
287 connection->read_buffer_size -= pos; 295 connection->read_buffer_size -= pos;
@@ -293,22 +301,21 @@ MHD_get_next_header_line(struct MHD_Connection * connection) {
293 * @return MHD_NO on failure (out of memory), MHD_YES for success 301 * @return MHD_NO on failure (out of memory), MHD_YES for success
294 */ 302 */
295static int 303static int
296MHD_connection_add_header(struct MHD_Connection * connection, 304MHD_connection_add_header (struct MHD_Connection *connection,
297 char * key, 305 char *key, char *value, enum MHD_ValueKind kind)
298 char * value, 306{
299 enum MHD_ValueKind kind) { 307 struct MHD_HTTP_Header *hdr;
300 struct MHD_HTTP_Header * hdr;
301 308
302 hdr = MHD_pool_allocate(connection->pool, 309 hdr = MHD_pool_allocate (connection->pool,
303 sizeof(struct MHD_HTTP_Header), 310 sizeof (struct MHD_HTTP_Header), MHD_YES);
304 MHD_YES); 311 if (hdr == NULL)
305 if (hdr == NULL) { 312 {
306 MHD_DLOG(connection->daemon, 313 MHD_DLOG (connection->daemon,
307 "Not enough memory to allocate header record!\n"); 314 "Not enough memory to allocate header record!\n");
308 MHD_excessive_data_handler(connection, 315 MHD_excessive_data_handler (connection,
309 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); 316 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
310 return MHD_NO; 317 return MHD_NO;
311 } 318 }
312 hdr->next = connection->headers_received; 319 hdr->next = connection->headers_received;
313 hdr->header = key; 320 hdr->header = key;
314 hdr->value = value; 321 hdr->value = value;
@@ -319,60 +326,57 @@ MHD_connection_add_header(struct MHD_Connection * connection,
319 326
320/** 327/**
321 * Process escape sequences ('+'=space, %HH) 328 * Process escape sequences ('+'=space, %HH)
322 */ 329 */
323static void 330static void
324MHD_http_unescape(char * val) { 331MHD_http_unescape (char *val)
325 char * esc; 332{
333 char *esc;
326 unsigned int num; 334 unsigned int num;
327 335
328 while (NULL != (esc = strstr(val, "+"))) 336 while (NULL != (esc = strstr (val, "+")))
329 *esc = ' '; 337 *esc = ' ';
330 while (NULL != (esc = strstr(val, "%"))) { 338 while (NULL != (esc = strstr (val, "%")))
331 if ( (1 == sscanf(&esc[1], 339 {
332 "%2x", 340 if ((1 == sscanf (&esc[1],
333 &num)) || 341 "%2x", &num)) || (1 == sscanf (&esc[1], "%2X", &num)))
334 (1 == sscanf(&esc[1], 342 {
335 "%2X", 343 esc[0] = (unsigned char) num;
336 &num)) ) { 344 memmove (&esc[1], &esc[3], strlen (&esc[3]));
337 esc[0] = (unsigned char) num; 345 }
338 memmove(&esc[1], 346 val = esc + 1;
339 &esc[3],
340 strlen(&esc[3]));
341 } 347 }
342 val = esc+1;
343 }
344} 348}
345 349
346/** 350/**
347 * @return MHD_NO on failure (out of memory), MHD_YES for success 351 * @return MHD_NO on failure (out of memory), MHD_YES for success
348 */ 352 */
349static int 353static int
350parse_arguments(enum MHD_ValueKind kind, 354parse_arguments (enum MHD_ValueKind kind,
351 struct MHD_Connection * connection, 355 struct MHD_Connection *connection, char *args)
352 char * args) { 356{
353 char * equals; 357 char *equals;
354 char * amper; 358 char *amper;
355 359
356 while (args != NULL) { 360 while (args != NULL)
357 equals = strstr(args, "="); 361 {
358 if (equals == NULL) 362 equals = strstr (args, "=");
359 return MHD_NO; /* invalid, ignore */ 363 if (equals == NULL)
360 equals[0] = '\0'; 364 return MHD_NO; /* invalid, ignore */
361 equals++; 365 equals[0] = '\0';
362 amper = strstr(equals, "&"); 366 equals++;
363 if (amper != NULL) { 367 amper = strstr (equals, "&");
364 amper[0] = '\0'; 368 if (amper != NULL)
365 amper++; 369 {
370 amper[0] = '\0';
371 amper++;
372 }
373 MHD_http_unescape (args);
374 MHD_http_unescape (equals);
375 if (MHD_NO == MHD_connection_add_header (connection,
376 args, equals, kind))
377 return MHD_NO;
378 args = amper;
366 } 379 }
367 MHD_http_unescape(args);
368 MHD_http_unescape(equals);
369 if (MHD_NO == MHD_connection_add_header(connection,
370 args,
371 equals,
372 kind))
373 return MHD_NO;
374 args = amper;
375 }
376 return MHD_YES; 380 return MHD_YES;
377} 381}
378 382
@@ -382,68 +386,63 @@ parse_arguments(enum MHD_ValueKind kind,
382 * @return MHD_YES for success, MHD_NO for failure (malformed, out of memory) 386 * @return MHD_YES for success, MHD_NO for failure (malformed, out of memory)
383 */ 387 */
384static int 388static int
385MHD_parse_cookie_header(struct MHD_Connection * connection) { 389MHD_parse_cookie_header (struct MHD_Connection *connection)
386 const char * hdr; 390{
387 char * cpy; 391 const char *hdr;
388 char * pos; 392 char *cpy;
389 char * semicolon; 393 char *pos;
390 char * equals; 394 char *semicolon;
395 char *equals;
391 int quotes; 396 int quotes;
392 397
393 hdr = MHD_lookup_connection_value(connection, 398 hdr = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "Cookie");
394 MHD_HEADER_KIND,
395 "Cookie");
396 if (hdr == NULL) 399 if (hdr == NULL)
397 return MHD_YES; 400 return MHD_YES;
398 cpy = MHD_pool_allocate(connection->pool, 401 cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES);
399 strlen(hdr)+1, 402 if (cpy == NULL)
400 MHD_YES); 403 {
401 if (cpy == NULL) { 404 MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n");
402 MHD_DLOG(connection->daemon, 405 MHD_excessive_data_handler (connection,
403 "Not enough memory to parse cookies!\n"); 406 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
404 MHD_excessive_data_handler(connection, 407 return MHD_NO;
405 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
406 return MHD_NO;
407 }
408 memcpy(cpy,
409 hdr,
410 strlen(hdr)+1);
411 pos = cpy;
412 while (pos != NULL) {
413 equals = strstr(pos, "=");
414 if (equals == NULL)
415 break;
416 equals[0] = '\0';
417 equals++;
418 quotes = 0;
419 semicolon = equals;
420 while ( (semicolon[0] != '\0') &&
421 ( (quotes != 0) ||
422 ( (semicolon[0] != ';') &&
423 (semicolon[0] != ',') ) ) ) {
424 if (semicolon[0] == '"')
425 quotes = (quotes + 1) & 1;
426 semicolon++;
427 }
428 if (semicolon[0] == '\0')
429 semicolon = NULL;
430 if (semicolon != NULL) {
431 semicolon[0] = '\0';
432 semicolon++;
433 } 408 }
434 /* remove quotes */ 409 memcpy (cpy, hdr, strlen (hdr) + 1);
435 if ( (equals[0] == '"') && 410 pos = cpy;
436 (equals[strlen(equals)-1] == '"') ) { 411 while (pos != NULL)
437 equals[strlen(equals)-1] = '\0'; 412 {
413 equals = strstr (pos, "=");
414 if (equals == NULL)
415 break;
416 equals[0] = '\0';
438 equals++; 417 equals++;
418 quotes = 0;
419 semicolon = equals;
420 while ((semicolon[0] != '\0') &&
421 ((quotes != 0) ||
422 ((semicolon[0] != ';') && (semicolon[0] != ','))))
423 {
424 if (semicolon[0] == '"')
425 quotes = (quotes + 1) & 1;
426 semicolon++;
427 }
428 if (semicolon[0] == '\0')
429 semicolon = NULL;
430 if (semicolon != NULL)
431 {
432 semicolon[0] = '\0';
433 semicolon++;
434 }
435 /* remove quotes */
436 if ((equals[0] == '"') && (equals[strlen (equals) - 1] == '"'))
437 {
438 equals[strlen (equals) - 1] = '\0';
439 equals++;
440 }
441 if (MHD_NO == MHD_connection_add_header (connection,
442 pos, equals, MHD_COOKIE_KIND))
443 return MHD_NO;
444 pos = semicolon;
439 } 445 }
440 if (MHD_NO == MHD_connection_add_header(connection,
441 pos,
442 equals,
443 MHD_COOKIE_KIND))
444 return MHD_NO;
445 pos = semicolon;
446 }
447 return MHD_YES; 446 return MHD_YES;
448} 447}
449 448
@@ -455,33 +454,33 @@ MHD_parse_cookie_header(struct MHD_Connection * connection) {
455 * @return MHD_YES if the line is ok, MHD_NO if it is malformed 454 * @return MHD_YES if the line is ok, MHD_NO if it is malformed
456 */ 455 */
457static int 456static int
458parse_initial_message_line(struct MHD_Connection * connection, 457parse_initial_message_line (struct MHD_Connection *connection, char *line)
459 char * line) { 458{
460 char * uri; 459 char *uri;
461 char * httpVersion; 460 char *httpVersion;
462 char * args; 461 char *args;
463 462
464 uri = strstr(line, " "); 463 uri = strstr (line, " ");
465 if (uri == NULL) 464 if (uri == NULL)
466 return MHD_NO; /* serious error */ 465 return MHD_NO; /* serious error */
467 uri[0] = '\0'; 466 uri[0] = '\0';
468 connection->method = line; 467 connection->method = line;
469 uri++; 468 uri++;
470 while (uri[0] == ' ') 469 while (uri[0] == ' ')
471 uri++; 470 uri++;
472 httpVersion = strstr(uri, " "); 471 httpVersion = strstr (uri, " ");
473 if (httpVersion != NULL) { 472 if (httpVersion != NULL)
474 httpVersion[0] = '\0'; 473 {
475 httpVersion++; 474 httpVersion[0] = '\0';
476 } 475 httpVersion++;
477 args = strstr(uri, "?"); 476 }
478 if (args != NULL) { 477 args = strstr (uri, "?");
479 args[0] = '\0'; 478 if (args != NULL)
480 args++; 479 {
481 parse_arguments(MHD_GET_ARGUMENT_KIND, 480 args[0] = '\0';
482 connection, 481 args++;
483 args); 482 parse_arguments (MHD_GET_ARGUMENT_KIND, connection, args);
484 } 483 }
485 connection->url = uri; 484 connection->url = uri;
486 if (httpVersion == NULL) 485 if (httpVersion == NULL)
487 connection->version = ""; 486 connection->version = "";
@@ -502,131 +501,137 @@ parse_initial_message_line(struct MHD_Connection * connection,
502 * size of the body is unknown, it should be set to -1. 501 * size of the body is unknown, it should be set to -1.
503 */ 502 */
504static void 503static void
505MHD_parse_connection_headers(struct MHD_Connection * connection) { 504MHD_parse_connection_headers (struct MHD_Connection *connection)
506 char * last; 505{
507 char * line; 506 char *last;
508 char * colon; 507 char *line;
509 char * tmp; 508 char *colon;
510 const char * clen; 509 char *tmp;
511 const char * end; 510 const char *clen;
511 const char *end;
512 unsigned long long cval; 512 unsigned long long cval;
513 513
514 if (connection->bodyReceived == 1) 514 if (connection->bodyReceived == 1)
515 abort(); 515 abort ();
516 last = NULL; 516 last = NULL;
517 while (NULL != (line = MHD_get_next_header_line(connection))) { 517 while (NULL != (line = MHD_get_next_header_line (connection)))
518 if (last != NULL) { 518 {
519 if ( (line[0] == ' ') || 519 if (last != NULL)
520 (line[0] == '\t') ) { 520 {
521 /* value was continued on the next line, see 521 if ((line[0] == ' ') || (line[0] == '\t'))
522 http://www.jmarshall.com/easy/http/ */ 522 {
523 last = MHD_pool_reallocate(connection->pool, 523 /* value was continued on the next line, see
524 last, 524 http://www.jmarshall.com/easy/http/ */
525 strlen(last)+1, 525 last = MHD_pool_reallocate (connection->pool,
526 strlen(line) + strlen(last) + 1); 526 last,
527 if (last == NULL) { 527 strlen (last) + 1,
528 MHD_excessive_data_handler(connection, 528 strlen (line) + strlen (last) + 1);
529 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); 529 if (last == NULL)
530 break; 530 {
531 } 531 MHD_excessive_data_handler (connection,
532 tmp = line; 532 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
533 while ( (tmp[0] == ' ') || 533 break;
534 (tmp[0] == '\t') ) 534 }
535 tmp++; /* skip whitespace at start of 2nd line */ 535 tmp = line;
536 strcat(last, tmp); 536 while ((tmp[0] == ' ') || (tmp[0] == '\t'))
537 continue; /* possibly more than 2 lines... */ 537 tmp++; /* skip whitespace at start of 2nd line */
538 } else { 538 strcat (last, tmp);
539 if (MHD_NO == MHD_connection_add_header(connection, 539 continue; /* possibly more than 2 lines... */
540 last, 540 }
541 colon, 541 else
542 MHD_HEADER_KIND)) 542 {
543 return; 543 if (MHD_NO == MHD_connection_add_header (connection,
544 last = NULL; 544 last,
545 } 545 colon,
546 MHD_HEADER_KIND))
547 return;
548 last = NULL;
549 }
550 }
551 if (connection->url == NULL)
552 {
553 /* line must be request line (first line of header) */
554 if (MHD_NO == parse_initial_message_line (connection, line))
555 goto DIE;
556 continue;
557 }
558 /* check if this is the end of the header */
559 if (strlen (line) == 0)
560 {
561 /* end of header */
562 connection->headersReceived = 1;
563 clen = MHD_lookup_connection_value (connection,
564 MHD_HEADER_KIND,
565 MHD_HTTP_HEADER_CONTENT_LENGTH);
566 if (clen != NULL)
567 {
568 if (1 != sscanf (clen, "%llu", &cval))
569 {
570 MHD_DLOG (connection->daemon,
571 "Failed to parse `%s' header `%s', closing connection.\n",
572 MHD_HTTP_HEADER_CONTENT_LENGTH, clen);
573 goto DIE;
574 }
575 connection->uploadSize = cval;
576 connection->bodyReceived = cval == 0 ? 1 : 0;
577 }
578 else
579 {
580 if (NULL == MHD_lookup_connection_value (connection,
581 MHD_HEADER_KIND,
582 MHD_HTTP_HEADER_TRANSFER_ENCODING))
583 {
584 /* this request does not have a body */
585 connection->uploadSize = 0;
586 connection->bodyReceived = 1;
587 }
588 else
589 {
590 connection->uploadSize = -1; /* unknown size */
591 connection->bodyReceived = 0;
592 }
593 }
594 end = MHD_lookup_connection_value (connection,
595 MHD_HEADER_KIND,
596 MHD_HTTP_HEADER_CONNECTION);
597 if ((end != NULL) && (0 == strcasecmp (end, "close")))
598 {
599 /* other side explicitly requested
600 that we close the connection after
601 this request */
602 connection->read_close = MHD_YES;
603 }
604 break;
605 }
606 /* line should be normal header line, find colon */
607 colon = strstr (line, ":");
608 if (colon == NULL)
609 {
610 /* error in header line, die hard */
611 MHD_DLOG (connection->daemon,
612 "Received malformed line (no colon), closing connection.\n");
613 goto DIE;
614 }
615 /* zero-terminate header */
616 colon[0] = '\0';
617 colon++; /* advance to value */
618 while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t')))
619 colon++;
620 /* we do the actual adding of the connection
621 header at the beginning of the while
622 loop since we need to be able to inspect
623 the *next* header line (in case it starts
624 with a space...) */
625 last = line;
546 } 626 }
547 if (connection->url == NULL) { 627 if ((last != NULL) &&
548 /* line must be request line (first line of header) */ 628 (MHD_NO == MHD_connection_add_header (connection,
549 if (MHD_NO == parse_initial_message_line(connection, 629 last, colon, MHD_HEADER_KIND)))
550 line)) 630 return; /* error */
551 goto DIE; 631 MHD_parse_cookie_header (connection);
552 continue;
553 }
554 /* check if this is the end of the header */
555 if (strlen(line) == 0) {
556 /* end of header */
557 connection->headersReceived = 1;
558 clen = MHD_lookup_connection_value(connection,
559 MHD_HEADER_KIND,
560 MHD_HTTP_HEADER_CONTENT_LENGTH);
561 if (clen != NULL) {
562 if (1 != sscanf(clen,
563 "%llu",
564 &cval)) {
565 MHD_DLOG(connection->daemon,
566 "Failed to parse `%s' header `%s', closing connection.\n",
567 MHD_HTTP_HEADER_CONTENT_LENGTH,
568 clen);
569 goto DIE;
570 }
571 connection->uploadSize = cval;
572 connection->bodyReceived = cval == 0 ? 1 : 0;
573 } else {
574 if (NULL == MHD_lookup_connection_value(connection,
575 MHD_HEADER_KIND,
576 MHD_HTTP_HEADER_TRANSFER_ENCODING)) {
577 /* this request does not have a body */
578 connection->uploadSize = 0;
579 connection->bodyReceived = 1;
580 } else {
581 connection->uploadSize = -1; /* unknown size */
582 connection->bodyReceived = 0;
583 }
584 }
585 end = MHD_lookup_connection_value(connection,
586 MHD_HEADER_KIND,
587 MHD_HTTP_HEADER_CONNECTION);
588 if ( (end != NULL) &&
589 (0 == strcasecmp(end,
590 "close")) ) {
591 /* other side explicitly requested
592 that we close the connection after
593 this request */
594 connection->read_close = MHD_YES;
595 }
596 break;
597 }
598 /* line should be normal header line, find colon */
599 colon = strstr(line, ":");
600 if (colon == NULL) {
601 /* error in header line, die hard */
602 MHD_DLOG(connection->daemon,
603 "Received malformed line (no colon), closing connection.\n");
604 goto DIE;
605 }
606 /* zero-terminate header */
607 colon[0] = '\0';
608 colon++; /* advance to value */
609 while ( (colon[0] != '\0') &&
610 ( (colon[0] == ' ') ||
611 (colon[0] == '\t') ) )
612 colon++;
613 /* we do the actual adding of the connection
614 header at the beginning of the while
615 loop since we need to be able to inspect
616 the *next* header line (in case it starts
617 with a space...) */
618 last = line;
619 }
620 if ( (last != NULL) &&
621 (MHD_NO == MHD_connection_add_header(connection,
622 last,
623 colon,
624 MHD_HEADER_KIND)) )
625 return; /* error */
626 MHD_parse_cookie_header(connection);
627 return; 632 return;
628 DIE: 633DIE:
629 CLOSE(connection->socket_fd); 634 CLOSE (connection->socket_fd);
630 connection->socket_fd = -1; 635 connection->socket_fd = -1;
631} 636}
632 637
@@ -635,16 +640,17 @@ MHD_parse_connection_headers(struct MHD_Connection * connection) {
635 * Find the handler responsible for this request. 640 * Find the handler responsible for this request.
636 */ 641 */
637static struct MHD_Access_Handler * 642static struct MHD_Access_Handler *
638MHD_find_access_handler(struct MHD_Connection * connection) { 643MHD_find_access_handler (struct MHD_Connection *connection)
639 struct MHD_Access_Handler * pos; 644{
645 struct MHD_Access_Handler *pos;
640 646
641 pos = connection->daemon->handlers; 647 pos = connection->daemon->handlers;
642 while (pos != NULL) { 648 while (pos != NULL)
643 if (0 == strcmp(connection->url, 649 {
644 pos->uri_prefix)) 650 if (0 == strcmp (connection->url, pos->uri_prefix))
645 return pos; 651 return pos;
646 pos = pos->next; 652 pos = pos->next;
647 } 653 }
648 return &connection->daemon->default_handler; 654 return &connection->daemon->default_handler;
649} 655}
650 656
@@ -659,33 +665,33 @@ MHD_find_access_handler(struct MHD_Connection * connection) {
659 * @return MHD_YES if so 665 * @return MHD_YES if so
660 */ 666 */
661static int 667static int
662MHD_test_post_data(struct MHD_Connection * connection) { 668MHD_test_post_data (struct MHD_Connection *connection)
663 const char * encoding; 669{
664 void * buf; 670 const char *encoding;
671 void *buf;
665 672
666 if ( (connection->method == NULL) || 673 if ((connection->method == NULL) ||
667 (connection->response != NULL) || 674 (connection->response != NULL) ||
668 (0 != strcasecmp(connection->method, 675 (0 != strcasecmp (connection->method, MHD_HTTP_METHOD_POST)))
669 MHD_HTTP_METHOD_POST)) )
670 return MHD_NO; 676 return MHD_NO;
671 encoding = MHD_lookup_connection_value(connection, 677 encoding = MHD_lookup_connection_value (connection,
672 MHD_HEADER_KIND, 678 MHD_HEADER_KIND,
673 MHD_HTTP_HEADER_CONTENT_TYPE); 679 MHD_HTTP_HEADER_CONTENT_TYPE);
674 if (encoding == NULL) 680 if (encoding == NULL)
675 return MHD_NO; 681 return MHD_NO;
676 if ( (0 == strcasecmp(MHD_HTTP_POST_ENCODING_FORM_URLENCODED, 682 if ((0 == strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED,
677 encoding)) && 683 encoding)) && (connection->uploadSize != -1))
678 (connection->uploadSize != -1) ) { 684 {
679 buf = MHD_pool_reallocate(connection->pool, 685 buf = MHD_pool_reallocate (connection->pool,
680 connection->read_buffer, 686 connection->read_buffer,
681 connection->read_buffer_size, 687 connection->read_buffer_size,
682 connection->uploadSize + 1); 688 connection->uploadSize + 1);
683 if (buf == NULL) 689 if (buf == NULL)
684 return MHD_NO; 690 return MHD_NO;
685 connection->read_buffer_size = connection->uploadSize + 1; 691 connection->read_buffer_size = connection->uploadSize + 1;
686 connection->read_buffer = buf; 692 connection->read_buffer = buf;
687 return MHD_YES; 693 return MHD_YES;
688 } 694 }
689 return MHD_NO; 695 return MHD_NO;
690} 696}
691 697
@@ -704,47 +710,47 @@ MHD_test_post_data(struct MHD_Connection * connection) {
704 * memory). 710 * memory).
705 */ 711 */
706static int 712static int
707MHD_parse_post_data(struct MHD_Connection * connection) { 713MHD_parse_post_data (struct MHD_Connection *connection)
708 const char * encoding; 714{
715 const char *encoding;
709 int ret; 716 int ret;
710 717
711 encoding = MHD_lookup_connection_value(connection, 718 encoding = MHD_lookup_connection_value (connection,
712 MHD_HEADER_KIND, 719 MHD_HEADER_KIND,
713 MHD_HTTP_HEADER_CONTENT_TYPE); 720 MHD_HTTP_HEADER_CONTENT_TYPE);
714 if (encoding == NULL) 721 if (encoding == NULL)
715 return MHD_NO;
716 if (0 == strcasecmp(MHD_HTTP_POST_ENCODING_FORM_URLENCODED,
717 encoding)) {
718 ret = parse_arguments(MHD_POSTDATA_KIND,
719 connection,
720 connection->read_buffer);
721 /* invalidate read buffer for other uses --
722 in particular, do not give it to the
723 client; if this were to be needed, we would
724 have to make a copy, which would double memory
725 requirements */
726 connection->read_buffer_size = 0;
727 connection->readLoc = 0;
728 connection->uploadSize = 0;
729 connection->read_buffer = NULL;
730 return ret;
731 }
732 if (0 == strcasecmp(MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA,
733 encoding)) {
734 /* this code should never been reached right now,
735 since the test_post_data function would already
736 return MHD_NO; code is here only for future
737 extensions... */
738 /* see http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 */
739 MHD_DLOG(connection->daemon,
740 "Unsupported multipart encoding of POST data specified, not processing POST data.\n");
741 return MHD_NO; 722 return MHD_NO;
742 } 723 if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding))
724 {
725 ret = parse_arguments (MHD_POSTDATA_KIND,
726 connection, connection->read_buffer);
727 /* invalidate read buffer for other uses --
728 in particular, do not give it to the
729 client; if this were to be needed, we would
730 have to make a copy, which would double memory
731 requirements */
732 connection->read_buffer_size = 0;
733 connection->readLoc = 0;
734 connection->uploadSize = 0;
735 connection->read_buffer = NULL;
736 return ret;
737 }
738 if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding))
739 {
740 /* this code should never been reached right now,
741 since the test_post_data function would already
742 return MHD_NO; code is here only for future
743 extensions... */
744 /* see http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 */
745 MHD_DLOG (connection->daemon,
746 "Unsupported multipart encoding of POST data specified, not processing POST data.\n");
747 return MHD_NO;
748 }
743 /* this should never be reached, just here for 749 /* this should never be reached, just here for
744 error checking */ 750 error checking */
745 MHD_DLOG(connection->daemon, 751 MHD_DLOG (connection->daemon,
746 "Unknown encoding of POST data specified, not processing POST data.\n"); 752 "Unknown encoding of POST data specified, not processing POST data.\n");
747 return MHD_NO; 753 return MHD_NO;
748} 754}
749 755
750/** 756/**
@@ -752,46 +758,47 @@ MHD_parse_post_data(struct MHD_Connection * connection) {
752 * connection. 758 * connection.
753 */ 759 */
754void 760void
755MHD_call_connection_handler(struct MHD_Connection * connection) { 761MHD_call_connection_handler (struct MHD_Connection *connection)
756 struct MHD_Access_Handler * ah; 762{
763 struct MHD_Access_Handler *ah;
757 unsigned int processed; 764 unsigned int processed;
758 765
759 if (connection->response != NULL) 766 if (connection->response != NULL)
760 return; /* already queued a response */ 767 return; /* already queued a response */
761 if (connection->headersReceived == 0) 768 if (connection->headersReceived == 0)
762 abort(); /* bad timing... */ 769 abort (); /* bad timing... */
763 ah = MHD_find_access_handler(connection); 770 ah = MHD_find_access_handler (connection);
764 processed = connection->readLoc; 771 processed = connection->readLoc;
765 if (MHD_NO == ah->dh(ah->dh_cls, 772 if (MHD_NO == ah->dh (ah->dh_cls,
766 connection, 773 connection,
767 connection->url, 774 connection->url,
768 connection->method, 775 connection->method,
769 connection->version, 776 connection->version,
770 connection->read_buffer, 777 connection->read_buffer, &processed))
771 &processed)) { 778 {
772 /* serios internal error, close connection */ 779 /* serios internal error, close connection */
773 MHD_DLOG(connection->daemon, 780 MHD_DLOG (connection->daemon,
774 "Internal application error, closing connection.\n"); 781 "Internal application error, closing connection.\n");
775 CLOSE(connection->socket_fd); 782 CLOSE (connection->socket_fd);
776 connection->socket_fd = -1; 783 connection->socket_fd = -1;
777 return; 784 return;
778 } 785 }
779 /* dh left "processed" bytes in buffer for next time... */ 786 /* dh left "processed" bytes in buffer for next time... */
780 memmove(connection->read_buffer, 787 memmove (connection->read_buffer,
781 &connection->read_buffer[connection->readLoc - processed], 788 &connection->read_buffer[connection->readLoc - processed],
782 processed); 789 processed);
783 if (connection->uploadSize != -1) 790 if (connection->uploadSize != -1)
784 connection->uploadSize -= (connection->readLoc - processed); 791 connection->uploadSize -= (connection->readLoc - processed);
785 connection->readLoc = processed; 792 connection->readLoc = processed;
786 if ( (connection->uploadSize == 0) || 793 if ((connection->uploadSize == 0) ||
787 ( (connection->readLoc == 0) && 794 ((connection->readLoc == 0) &&
788 (connection->uploadSize == -1) && 795 (connection->uploadSize == -1) && (connection->socket_fd == -1)))
789 (connection->socket_fd == -1) ) ) { 796 {
790 connection->bodyReceived = 1; 797 connection->bodyReceived = 1;
791 connection->readLoc = 0; 798 connection->readLoc = 0;
792 connection->read_buffer_size = 0; 799 connection->read_buffer_size = 0;
793 connection->read_buffer = NULL; 800 connection->read_buffer = NULL;
794 } 801 }
795} 802}
796 803
797 804
@@ -802,81 +809,88 @@ MHD_call_connection_handler(struct MHD_Connection * connection) {
802 * to handle reads. 809 * to handle reads.
803 */ 810 */
804int 811int
805MHD_connection_handle_read(struct MHD_Connection * connection) { 812MHD_connection_handle_read (struct MHD_Connection *connection)
813{
806 int bytes_read; 814 int bytes_read;
807 void * tmp; 815 void *tmp;
808 816
809 if (connection->pool == NULL) 817 if (connection->pool == NULL)
810 connection->pool = MHD_pool_create(connection->daemon->pool_size); 818 connection->pool = MHD_pool_create (connection->daemon->pool_size);
811 if (connection->pool == NULL) { 819 if (connection->pool == NULL)
812 MHD_DLOG(connection->daemon, 820 {
813 "Failed to create memory pool!\n"); 821 MHD_DLOG (connection->daemon, "Failed to create memory pool!\n");
814 CLOSE(connection->socket_fd); 822 CLOSE (connection->socket_fd);
815 connection->socket_fd = -1; 823 connection->socket_fd = -1;
816 return MHD_NO;
817 }
818 if ( (connection->readLoc >= connection->read_buffer_size) &&
819 (connection->headersReceived == 0) ) {
820 /* need to grow read buffer */
821 tmp = MHD_pool_reallocate(connection->pool,
822 connection->read_buffer,
823 connection->read_buffer_size,
824 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE);
825 if (tmp == NULL) {
826 MHD_DLOG(connection->daemon,
827 "Not enough memory for reading headers!\n");
828 MHD_excessive_data_handler(connection,
829 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
830 return MHD_NO; 824 return MHD_NO;
831 } 825 }
832 connection->read_buffer = tmp; 826 if ((connection->readLoc >= connection->read_buffer_size) &&
833 connection->read_buffer_size = connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; 827 (connection->headersReceived == 0))
834 } 828 {
835 if (connection->readLoc >= connection->read_buffer_size) { 829 /* need to grow read buffer */
836 MHD_DLOG(connection->daemon, 830 tmp = MHD_pool_reallocate (connection->pool,
837 "Unexpected call to %s.\n", 831 connection->read_buffer,
838 __FUNCTION__); 832 connection->read_buffer_size,
839 return MHD_NO; 833 connection->read_buffer_size * 2 +
840 } 834 MHD_BUF_INC_SIZE);
841 bytes_read = RECV(connection->socket_fd, 835 if (tmp == NULL)
842 &connection->read_buffer[connection->readLoc], 836 {
843 connection->read_buffer_size - connection->readLoc, 837 MHD_DLOG (connection->daemon,
844 0); 838 "Not enough memory for reading headers!\n");
845 if (bytes_read < 0) { 839 MHD_excessive_data_handler (connection,
846 if (errno == EINTR) 840 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
841 return MHD_NO;
842 }
843 connection->read_buffer = tmp;
844 connection->read_buffer_size =
845 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
846 }
847 if (connection->readLoc >= connection->read_buffer_size)
848 {
849 MHD_DLOG (connection->daemon, "Unexpected call to %s.\n", __FUNCTION__);
847 return MHD_NO; 850 return MHD_NO;
848 MHD_DLOG(connection->daemon, 851 }
849 "Failed to receive data: %s\n", 852 bytes_read = RECV (connection->socket_fd,
850 STRERROR(errno)); 853 &connection->read_buffer[connection->readLoc],
851 CLOSE(connection->socket_fd); 854 connection->read_buffer_size - connection->readLoc, 0);
852 connection->socket_fd = -1; 855 if (bytes_read < 0)
853 return MHD_YES; 856 {
854 } 857 if (errno == EINTR)
855 if (bytes_read == 0) { 858 return MHD_NO;
856 /* other side closed connection */ 859 MHD_DLOG (connection->daemon,
857 connection->read_close = MHD_YES; 860 "Failed to receive data: %s\n", STRERROR (errno));
858 if (connection->readLoc > 0) 861 CLOSE (connection->socket_fd);
859 MHD_call_connection_handler(connection); 862 connection->socket_fd = -1;
860 shutdown(connection->socket_fd, SHUT_RD); 863 return MHD_YES;
861 return MHD_YES; 864 }
862 } 865 if (bytes_read == 0)
866 {
867 /* other side closed connection */
868 connection->read_close = MHD_YES;
869 if (connection->readLoc > 0)
870 MHD_call_connection_handler (connection);
871 shutdown (connection->socket_fd, SHUT_RD);
872 return MHD_YES;
873 }
863 connection->readLoc += bytes_read; 874 connection->readLoc += bytes_read;
864 if (connection->headersReceived == 0) { 875 if (connection->headersReceived == 0)
865 MHD_parse_connection_headers(connection); 876 {
866 if (connection->headersReceived == 1) { 877 MHD_parse_connection_headers (connection);
867 connection->post_processed = MHD_test_post_data(connection); 878 if (connection->headersReceived == 1)
879 {
880 connection->post_processed = MHD_test_post_data (connection);
881 }
882 }
883 if (connection->headersReceived == 1)
884 {
885 if ((connection->post_processed == MHD_YES) &&
886 (connection->uploadSize == connection->readLoc))
887 if (MHD_NO == MHD_parse_post_data (connection))
888 connection->post_processed = MHD_NO;
889 if (((connection->post_processed == MHD_NO) ||
890 (connection->read_buffer_size == connection->readLoc)) &&
891 (connection->method != NULL))
892 MHD_call_connection_handler (connection);
868 } 893 }
869 }
870 if (connection->headersReceived == 1) {
871 if ( (connection->post_processed == MHD_YES) &&
872 (connection->uploadSize == connection->readLoc) )
873 if (MHD_NO == MHD_parse_post_data(connection))
874 connection->post_processed = MHD_NO;
875 if ( ( (connection->post_processed == MHD_NO) ||
876 (connection->read_buffer_size == connection->readLoc) ) &&
877 (connection->method != NULL) )
878 MHD_call_connection_handler(connection);
879 }
880 return MHD_YES; 894 return MHD_YES;
881} 895}
882 896
@@ -885,48 +899,51 @@ MHD_connection_handle_read(struct MHD_Connection * connection) {
885 * for http-compiliance. 899 * for http-compiliance.
886 */ 900 */
887static void 901static void
888MHD_add_extra_headers(struct MHD_Connection * connection) { 902MHD_add_extra_headers (struct MHD_Connection *connection)
889 const char * have; 903{
904 const char *have;
890 char buf[128]; 905 char buf[128];
891 906
892 if (connection->response->total_size == -1) { 907 if (connection->response->total_size == -1)
893 have = MHD_get_response_header(connection->response, 908 {
894 MHD_HTTP_HEADER_CONNECTION); 909 have = MHD_get_response_header (connection->response,
895 if (have == NULL) 910 MHD_HTTP_HEADER_CONNECTION);
896 MHD_add_response_header(connection->response, 911 if (have == NULL)
897 MHD_HTTP_HEADER_CONNECTION, 912 MHD_add_response_header (connection->response,
898 "close"); 913 MHD_HTTP_HEADER_CONNECTION, "close");
899 } else if (NULL == MHD_get_response_header(connection->response, 914 }
900 MHD_HTTP_HEADER_CONTENT_LENGTH)) { 915 else if (NULL == MHD_get_response_header (connection->response,
901 _REAL_SNPRINTF(buf, 916 MHD_HTTP_HEADER_CONTENT_LENGTH))
902 128, 917 {
903 "%llu", 918 _REAL_SNPRINTF (buf,
904 (unsigned long long) connection->response->total_size); 919 128,
905 MHD_add_response_header(connection->response, 920 "%llu",
906 MHD_HTTP_HEADER_CONTENT_LENGTH, 921 (unsigned long long) connection->response->total_size);
907 buf); 922 MHD_add_response_header (connection->response,
908 } 923 MHD_HTTP_HEADER_CONTENT_LENGTH, buf);
924 }
909} 925}
910 926
911static void get_date_string(char * date, 927static void
912 unsigned int max) { 928get_date_string (char *date, unsigned int max)
913 static const char * days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; 929{
914 static const char * mons[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; 930 static const char *days[] =
931 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
932 static const char *mons[] =
933 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
934"Nov", "Dec" };
915 struct tm now; 935 struct tm now;
916 time_t t; 936 time_t t;
917 937
918 time(&t); 938 time (&t);
919 gmtime_r(&t, &now); 939 gmtime_r (&t, &now);
920 snprintf(date, 940 snprintf (date,
921 max-1, 941 max - 1,
922 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n", 942 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
923 days[now.tm_wday % 7], 943 days[now.tm_wday % 7],
924 now.tm_mday, 944 now.tm_mday,
925 mons[now.tm_mon % 12], 945 mons[now.tm_mon % 12],
926 now.tm_year, 946 now.tm_year, now.tm_hour, now.tm_min, now.tm_sec);
927 now.tm_hour,
928 now.tm_min,
929 now.tm_sec);
930} 947}
931 948
932/** 949/**
@@ -935,62 +952,53 @@ static void get_date_string(char * date,
935 * HTTPd's response. 952 * HTTPd's response.
936 */ 953 */
937static int 954static int
938MHD_build_header_response(struct MHD_Connection * connection) { 955MHD_build_header_response (struct MHD_Connection *connection)
956{
939 size_t size; 957 size_t size;
940 size_t off; 958 size_t off;
941 struct MHD_HTTP_Header * pos; 959 struct MHD_HTTP_Header *pos;
942 char code[32]; 960 char code[32];
943 char date[128]; 961 char date[128];
944 char * data; 962 char *data;
945 963
946 MHD_add_extra_headers(connection); 964 MHD_add_extra_headers (connection);
947 SPRINTF(code, 965 SPRINTF (code, "%s %u\r\n", MHD_HTTP_VERSION_1_1, connection->responseCode);
948 "%s %u\r\n", 966 off = strlen (code);
949 MHD_HTTP_VERSION_1_1,
950 connection->responseCode);
951 off = strlen(code);
952 /* estimate size */ 967 /* estimate size */
953 size = off + 2; /* extra \r\n at the end */ 968 size = off + 2; /* extra \r\n at the end */
954 pos = connection->response->first_header; 969 pos = connection->response->first_header;
955 while (pos != NULL) { 970 while (pos != NULL)
956 size += strlen(pos->header) + strlen(pos->value) + 4; /* colon, space, linefeeds */ 971 {
957 pos = pos->next; 972 size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
958 } 973 pos = pos->next;
959 if (NULL == MHD_get_response_header(connection->response, 974 }
960 MHD_HTTP_HEADER_DATE)) 975 if (NULL == MHD_get_response_header (connection->response,
961 get_date_string(date, sizeof(date)); 976 MHD_HTTP_HEADER_DATE))
977 get_date_string (date, sizeof (date));
962 else 978 else
963 date[0] = '\0'; 979 date[0] = '\0';
964 size += strlen(date); 980 size += strlen (date);
965 /* produce data */ 981 /* produce data */
966 data = MHD_pool_allocate(connection->pool, 982 data = MHD_pool_allocate (connection->pool, size + 1, MHD_YES);
967 size + 1, 983 if (data == NULL)
968 MHD_YES); 984 {
969 if (data == NULL) { 985 MHD_DLOG (connection->daemon, "Not enough memory for write!\n");
970 MHD_DLOG(connection->daemon, 986 return MHD_NO;
971 "Not enough memory for write!\n"); 987 }
972 return MHD_NO; 988 memcpy (data, code, off);
973 }
974 memcpy(data,
975 code,
976 off);
977 pos = connection->response->first_header; 989 pos = connection->response->first_header;
978 while (pos != NULL) { 990 while (pos != NULL)
979 SPRINTF(&data[off], 991 {
980 "%s: %s\r\n", 992 SPRINTF (&data[off], "%s: %s\r\n", pos->header, pos->value);
981 pos->header, 993 off += strlen (pos->header) + strlen (pos->value) + 4;
982 pos->value); 994 pos = pos->next;
983 off += strlen(pos->header) + strlen(pos->value) + 4; 995 }
984 pos = pos->next; 996 strcpy (&data[off], date);
985 } 997 off += strlen (date);
986 strcpy(&data[off], 998 sprintf (&data[off], "\r\n");
987 date);
988 off += strlen(date);
989 sprintf(&data[off],
990 "\r\n");
991 off += 2; 999 off += 2;
992 if (off != size) 1000 if (off != size)
993 abort(); 1001 abort ();
994 connection->write_buffer = data; 1002 connection->write_buffer = data;
995 connection->writeLoc = size; 1003 connection->writeLoc = size;
996 connection->writePos = 0; 1004 connection->writePos = 0;
@@ -1005,159 +1013,164 @@ MHD_build_header_response(struct MHD_Connection * connection) {
1005 * call this function 1013 * call this function
1006 */ 1014 */
1007int 1015int
1008MHD_connection_handle_write(struct MHD_Connection * connection) { 1016MHD_connection_handle_write (struct MHD_Connection *connection)
1009 struct MHD_Response * response; 1017{
1018 struct MHD_Response *response;
1010 int ret; 1019 int ret;
1011 1020
1012 if (MHD_need_100_continue(connection)) { 1021 if (MHD_need_100_continue (connection))
1013 ret = SEND(connection->socket_fd, 1022 {
1014 &HTTP_100_CONTINUE[connection->continuePos], 1023 ret = SEND (connection->socket_fd,
1015 strlen(HTTP_100_CONTINUE) - connection->continuePos, 1024 &HTTP_100_CONTINUE[connection->continuePos],
1016 0); 1025 strlen (HTTP_100_CONTINUE) - connection->continuePos, 0);
1017 if (ret < 0) { 1026 if (ret < 0)
1018 if (errno == EINTR) 1027 {
1019 return MHD_YES; 1028 if (errno == EINTR)
1020 MHD_DLOG(connection->daemon, 1029 return MHD_YES;
1021 "Failed to send data: %s\n", 1030 MHD_DLOG (connection->daemon,
1022 STRERROR(errno)); 1031 "Failed to send data: %s\n", STRERROR (errno));
1023 CLOSE(connection->socket_fd); 1032 CLOSE (connection->socket_fd);
1024 connection->socket_fd = -1; 1033 connection->socket_fd = -1;
1034 return MHD_YES;
1035 }
1036 connection->continuePos += ret;
1025 return MHD_YES; 1037 return MHD_YES;
1026 } 1038 }
1027 connection->continuePos += ret;
1028 return MHD_YES;
1029 }
1030 response = connection->response; 1039 response = connection->response;
1031 if(response == NULL) { 1040 if (response == NULL)
1032 MHD_DLOG(connection->daemon, 1041 {
1033 "Unexpected call to %s.\n", 1042 MHD_DLOG (connection->daemon, "Unexpected call to %s.\n", __FUNCTION__);
1034 __FUNCTION__); 1043 return MHD_NO;
1035 return MHD_NO;
1036 }
1037 if (! connection->headersSent) {
1038 if ( (connection->write_buffer == NULL) &&
1039 (MHD_NO == MHD_build_header_response(connection)) ) {
1040 /* oops - close! */
1041 CLOSE(connection->socket_fd);
1042 connection->socket_fd = -1;
1043 return MHD_NO;
1044 } 1044 }
1045 ret = SEND(connection->socket_fd, 1045 if (!connection->headersSent)
1046 &connection->write_buffer[connection->writePos], 1046 {
1047 connection->writeLoc - connection->writePos, 1047 if ((connection->write_buffer == NULL) &&
1048 0); 1048 (MHD_NO == MHD_build_header_response (connection)))
1049 if (ret < 0) { 1049 {
1050 if (errno == EINTR) 1050 /* oops - close! */
1051 return MHD_YES; 1051 CLOSE (connection->socket_fd);
1052 MHD_DLOG(connection->daemon, 1052 connection->socket_fd = -1;
1053 "Failed to send data: %s\n", 1053 return MHD_NO;
1054 STRERROR(errno)); 1054 }
1055 CLOSE(connection->socket_fd); 1055 ret = SEND (connection->socket_fd,
1056 connection->socket_fd = -1; 1056 &connection->write_buffer[connection->writePos],
1057 connection->writeLoc - connection->writePos, 0);
1058 if (ret < 0)
1059 {
1060 if (errno == EINTR)
1061 return MHD_YES;
1062 MHD_DLOG (connection->daemon,
1063 "Failed to send data: %s\n", STRERROR (errno));
1064 CLOSE (connection->socket_fd);
1065 connection->socket_fd = -1;
1066 return MHD_YES;
1067 }
1068 connection->writePos += ret;
1069 if (connection->writeLoc == connection->writePos)
1070 {
1071 connection->writeLoc = 0;
1072 connection->writePos = 0;
1073 connection->headersSent = 1;
1074 MHD_pool_reallocate (connection->pool,
1075 connection->write_buffer,
1076 connection->write_buffer_size, 0);
1077 connection->write_buffer = NULL;
1078 connection->write_buffer_size = 0;
1079 }
1057 return MHD_YES; 1080 return MHD_YES;
1058 } 1081 }
1059 connection->writePos += ret;
1060 if (connection->writeLoc == connection->writePos) {
1061 connection->writeLoc = 0;
1062 connection->writePos = 0;
1063 connection->headersSent = 1;
1064 MHD_pool_reallocate(connection->pool,
1065 connection->write_buffer,
1066 connection->write_buffer_size,
1067 0);
1068 connection->write_buffer = NULL;
1069 connection->write_buffer_size = 0;
1070 }
1071 return MHD_YES;
1072 }
1073 if (response->total_size < connection->messagePos) 1082 if (response->total_size < connection->messagePos)
1074 abort(); /* internal error */ 1083 abort (); /* internal error */
1075 if (response->crc != NULL) 1084 if (response->crc != NULL)
1076 pthread_mutex_lock(&response->mutex); 1085 pthread_mutex_lock (&response->mutex);
1077 1086
1078 /* prepare send buffer */ 1087 /* prepare send buffer */
1079 if ( (response->crc != NULL) && 1088 if ((response->crc != NULL) &&
1080 ( (response->data_start > connection->messagePos) || 1089 ((response->data_start > connection->messagePos) ||
1081 (response->data_start + response->data_size <= connection->messagePos) ) ) { 1090 (response->data_start + response->data_size <=
1082 ret = response->crc(response->crc_cls, 1091 connection->messagePos)))
1083 connection->messagePos, 1092 {
1084 response->data, 1093 ret = response->crc (response->crc_cls,
1085 MIN(response->data_buffer_size, 1094 connection->messagePos,
1086 response->total_size - connection->messagePos)); 1095 response->data,
1087 if (ret == -1) { 1096 MIN (response->data_buffer_size,
1088 /* end of message, signal other side by closing! */ 1097 response->total_size -
1089 response->total_size = connection->messagePos; 1098 connection->messagePos));
1090 CLOSE(connection->socket_fd); 1099 if (ret == -1)
1091 connection->socket_fd = -1; 1100 {
1092 if (response->crc != NULL) 1101 /* end of message, signal other side by closing! */
1093 pthread_mutex_unlock(&response->mutex); 1102 response->total_size = connection->messagePos;
1094 return MHD_YES; 1103 CLOSE (connection->socket_fd);
1095 } 1104 connection->socket_fd = -1;
1096 response->data_start = connection->messagePos; 1105 if (response->crc != NULL)
1097 response->data_size = ret; 1106 pthread_mutex_unlock (&response->mutex);
1098 if (ret == 0) { 1107 return MHD_YES;
1099 if (response->crc != NULL) 1108 }
1100 pthread_mutex_unlock(&response->mutex); 1109 response->data_start = connection->messagePos;
1101 return MHD_YES; 1110 response->data_size = ret;
1111 if (ret == 0)
1112 {
1113 if (response->crc != NULL)
1114 pthread_mutex_unlock (&response->mutex);
1115 return MHD_YES;
1116 }
1102 } 1117 }
1103 }
1104 /* transmit */ 1118 /* transmit */
1105 ret = SEND(connection->socket_fd, 1119 ret = SEND (connection->socket_fd,
1106 &response->data[connection->messagePos - response->data_start], 1120 &response->data[connection->messagePos - response->data_start],
1107 response->data_size - (connection->messagePos - response->data_start), 1121 response->data_size - (connection->messagePos -
1108 0); 1122 response->data_start), 0);
1109 if (response->crc != NULL) 1123 if (response->crc != NULL)
1110 pthread_mutex_unlock(&response->mutex); 1124 pthread_mutex_unlock (&response->mutex);
1111 if (ret < 0) { 1125 if (ret < 0)
1112 if (errno == EINTR) 1126 {
1127 if (errno == EINTR)
1128 return MHD_YES;
1129 MHD_DLOG (connection->daemon,
1130 "Failed to send data: %s\n", STRERROR (errno));
1131 CLOSE (connection->socket_fd);
1132 connection->socket_fd = -1;
1113 return MHD_YES; 1133 return MHD_YES;
1114 MHD_DLOG(connection->daemon, 1134 }
1115 "Failed to send data: %s\n",
1116 STRERROR(errno));
1117 CLOSE(connection->socket_fd);
1118 connection->socket_fd = -1;
1119 return MHD_YES;
1120 }
1121 connection->messagePos += ret; 1135 connection->messagePos += ret;
1122 if (connection->messagePos > response->total_size) 1136 if (connection->messagePos > response->total_size)
1123 abort(); /* internal error */ 1137 abort (); /* internal error */
1124 if (connection->messagePos == response->total_size) { 1138 if (connection->messagePos == response->total_size)
1125 if ( (connection->bodyReceived == 0) || 1139 {
1126 (connection->headersReceived == 0) ) 1140 if ((connection->bodyReceived == 0) ||
1127 abort(); /* internal error */ 1141 (connection->headersReceived == 0))
1128 MHD_destroy_response(response); 1142 abort (); /* internal error */
1129 connection->continuePos = 0; 1143 MHD_destroy_response (response);
1130 connection->responseCode = 0; 1144 connection->continuePos = 0;
1131 connection->response = NULL; 1145 connection->responseCode = 0;
1132 connection->headers_received = NULL; 1146 connection->response = NULL;
1133 connection->headersReceived = 0; 1147 connection->headers_received = NULL;
1134 connection->headersSent = 0; 1148 connection->headersReceived = 0;
1135 connection->bodyReceived = 0; 1149 connection->headersSent = 0;
1136 connection->messagePos = 0; 1150 connection->bodyReceived = 0;
1137 connection->method = NULL; 1151 connection->messagePos = 0;
1138 connection->url = NULL; 1152 connection->method = NULL;
1139 if ( (connection->read_close == MHD_YES) || 1153 connection->url = NULL;
1140 (0 != strcasecmp(MHD_HTTP_VERSION_1_1, 1154 if ((connection->read_close == MHD_YES) ||
1141 connection->version)) ) { 1155 (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
1142 /* closed for reading => close for good! */ 1156 {
1143 if (connection->socket_fd != -1) 1157 /* closed for reading => close for good! */
1144 CLOSE(connection->socket_fd); 1158 if (connection->socket_fd != -1)
1145 connection->socket_fd = -1; 1159 CLOSE (connection->socket_fd);
1160 connection->socket_fd = -1;
1161 }
1162 connection->version = NULL;
1163 connection->read_buffer = NULL;
1164 connection->write_buffer = NULL;
1165 connection->read_buffer_size = 0;
1166 connection->readLoc = 0;
1167 connection->write_buffer_size = 0;
1168 connection->writePos = 0;
1169 connection->writeLoc = 0;
1170 MHD_pool_destroy (connection->pool);
1171 connection->pool = NULL;
1146 } 1172 }
1147 connection->version = NULL;
1148 connection->read_buffer = NULL;
1149 connection->write_buffer = NULL;
1150 connection->read_buffer_size = 0;
1151 connection->readLoc = 0;
1152 connection->write_buffer_size = 0;
1153 connection->writePos = 0;
1154 connection->writeLoc = 0;
1155 MHD_pool_destroy(connection->pool);
1156 connection->pool = NULL;
1157 }
1158 return MHD_YES; 1173 return MHD_YES;
1159} 1174}
1160 1175
1161/* end of connection.c */ 1176/* end of connection.c */
1162
1163