aboutsummaryrefslogtreecommitdiff
path: root/src/daemon/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon/connection.c')
-rw-r--r--src/daemon/connection.c1845
1 files changed, 1155 insertions, 690 deletions
diff --git a/src/daemon/connection.c b/src/daemon/connection.c
index 318439a8..d07a2544 100644
--- a/src/daemon/connection.c
+++ b/src/daemon/connection.c
@@ -2,7 +2,6 @@
2 This file is part of libmicrohttpd 2 This file is part of libmicrohttpd
3 (C) 2007 Daniel Pittman and Christian Grothoff 3 (C) 2007 Daniel Pittman and Christian Grothoff
4 4
5
6 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public 6 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either 7 License as published by the Free Software Foundation; either
@@ -62,6 +61,14 @@
62 */ 61 */
63#define REQUEST_LACKS_HOST "" 62#define REQUEST_LACKS_HOST ""
64 63
64#define EXTRA_CHECKS MHD_YES
65
66#if EXTRA_CHECKS
67#define EXTRA_CHECK(a) if (!(a)) abort();
68#else
69#define EXTRA_CHECK(a)
70#endif
71
65/** 72/**
66 * Add extra debug messages with reasons for closing connections 73 * Add extra debug messages with reasons for closing connections
67 * (non-error reasons). 74 * (non-error reasons).
@@ -73,6 +80,10 @@
73 */ 80 */
74#define DEBUG_SEND_DATA MHD_NO 81#define DEBUG_SEND_DATA MHD_NO
75 82
83/**
84 * Should all state transitions be printed to stderr?
85 */
86#define DEBUG_STATES MHD_NO
76 87
77/** 88/**
78 * Get all of the headers from the request. 89 * Get all of the headers from the request.
@@ -109,7 +120,6 @@ MHD_get_connection_values (struct MHD_Connection *connection,
109 return ret; 120 return ret;
110} 121}
111 122
112
113/** 123/**
114 * Get a particular header value. If multiple 124 * Get a particular header value. If multiple
115 * values match the kind, return any one of them. 125 * values match the kind, return any one of them.
@@ -149,11 +159,11 @@ int
149MHD_queue_response (struct MHD_Connection *connection, 159MHD_queue_response (struct MHD_Connection *connection,
150 unsigned int status_code, struct MHD_Response *response) 160 unsigned int status_code, struct MHD_Response *response)
151{ 161{
152 if ((connection == NULL) || 162 if ( (connection == NULL) ||
153 (response == NULL) || 163 (response == NULL) ||
154 (connection->response != NULL) || 164 (connection->response != NULL) ||
155 (connection->have_received_body == MHD_NO) 165 ( (connection->state != MHD_CONNECTION_HEADERS_PROCESSED) &&
156 || (connection->have_received_headers == MHD_NO)) 166 (connection->state != MHD_CONNECTION_FOOTERS_RECEIVED) ) )
157 return MHD_NO; 167 return MHD_NO;
158 MHD_increment_response_rc (response); 168 MHD_increment_response_rc (response);
159 connection->response = response; 169 connection->response = response;
@@ -165,6 +175,21 @@ MHD_queue_response (struct MHD_Connection *connection,
165 have already sent the full message body */ 175 have already sent the full message body */
166 connection->response_write_position = response->total_size; 176 connection->response_write_position = response->total_size;
167 } 177 }
178 if ( (response->total_size == -1) &&
179 (0 == strcasecmp(connection->version,
180 MHD_HTTP_VERSION_1_1)) )
181 connection->have_chunked_response = MHD_YES;
182 else
183 connection->have_chunked_response = MHD_NO;
184 if (connection->state == MHD_CONNECTION_HEADERS_PROCESSED)
185 {
186 /* response was queued "early",
187 refuse to read body / footers or further
188 requests! */
189 SHUTDOWN (connection->socket_fd, SHUT_RD);
190 connection->read_closed = MHD_YES;
191 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
192 }
168 return MHD_YES; 193 return MHD_YES;
169} 194}
170 195
@@ -173,14 +198,14 @@ MHD_queue_response (struct MHD_Connection *connection,
173 * message for this connection? 198 * message for this connection?
174 */ 199 */
175static int 200static int
176MHD_need_100_continue (struct MHD_Connection *connection) 201need_100_continue (struct MHD_Connection *connection)
177{ 202{
178 const char *expect; 203 const char *expect;
179 204
180 return ((connection->version != NULL) && 205 return ((connection->response == NULL) &&
206 (connection->version != NULL) &&
181 (0 == strcasecmp (connection->version, 207 (0 == strcasecmp (connection->version,
182 MHD_HTTP_VERSION_1_1)) && 208 MHD_HTTP_VERSION_1_1)) &&
183 (connection->have_received_headers == MHD_YES) &&
184 (NULL != (expect = MHD_lookup_connection_value (connection, 209 (NULL != (expect = MHD_lookup_connection_value (connection,
185 MHD_HEADER_KIND, 210 MHD_HEADER_KIND,
186 MHD_HTTP_HEADER_EXPECT))) 211 MHD_HTTP_HEADER_EXPECT)))
@@ -199,6 +224,7 @@ connection_close_error (struct MHD_Connection *connection)
199 SHUTDOWN (connection->socket_fd, SHUT_RDWR); 224 SHUTDOWN (connection->socket_fd, SHUT_RDWR);
200 CLOSE (connection->socket_fd); 225 CLOSE (connection->socket_fd);
201 connection->socket_fd = -1; 226 connection->socket_fd = -1;
227 connection->state = MHD_CONNECTION_CLOSED;
202 if (connection->daemon->notify_completed != NULL) 228 if (connection->daemon->notify_completed != NULL)
203 connection->daemon->notify_completed (connection->daemon-> 229 connection->daemon->notify_completed (connection->daemon->
204 notify_completed_cls, connection, 230 notify_completed_cls, connection,
@@ -216,12 +242,14 @@ connection_close_error (struct MHD_Connection *connection)
216 * @return MHD_NO if readying the response failed 242 * @return MHD_NO if readying the response failed
217 */ 243 */
218static int 244static int
219ready_response (struct MHD_Connection *connection) 245try_ready_normal_body (struct MHD_Connection *connection)
220{ 246{
221 int ret; 247 int ret;
222 struct MHD_Response *response; 248 struct MHD_Response *response;
223 249
224 response = connection->response; 250 response = connection->response;
251 if (response->crc == NULL)
252 return MHD_YES;
225 ret = response->crc (response->crc_cls, 253 ret = response->crc (response->crc_cls,
226 connection->response_write_position, 254 connection->response_write_position,
227 response->data, 255 response->data,
@@ -230,7 +258,8 @@ ready_response (struct MHD_Connection *connection)
230 connection->response_write_position)); 258 connection->response_write_position));
231 if (ret == -1) 259 if (ret == -1)
232 { 260 {
233 /* end of message, signal other side by closing! */ 261 /* either error or http 1.0 transfer, close
262 socket! */
234#if DEBUG_CLOSE 263#if DEBUG_CLOSE
235#if HAVE_MESSAGES 264#if HAVE_MESSAGES
236 MHD_DLOG (connection->daemon, "Closing connection (end of response)\n"); 265 MHD_DLOG (connection->daemon, "Closing connection (end of response)\n");
@@ -239,94 +268,281 @@ ready_response (struct MHD_Connection *connection)
239 response->total_size = connection->response_write_position; 268 response->total_size = connection->response_write_position;
240 connection_close_error (connection); 269 connection_close_error (connection);
241 return MHD_NO; 270 return MHD_NO;
242 } 271 }
243 response->data_start = connection->response_write_position; 272 response->data_start = connection->response_write_position;
244 response->data_size = ret; 273 response->data_size = ret;
245 if (ret == 0) 274 if (ret == 0)
275 return MHD_NO;
276 return MHD_YES;
277}
278
279/**
280 * Prepare the response buffer of this connection for
281 * sending. Assumes that the response mutex is
282 * already held. If the transmission is complete,
283 * this function may close the socket (and return
284 * MHD_NO).
285 *
286 * @return MHD_NO if readying the response failed
287 */
288static int
289try_ready_chunked_body (struct MHD_Connection *connection)
290{
291 int ret;
292 char * buf;
293 struct MHD_Response *response;
294 unsigned int size;
295 char cbuf[9];
296
297 response = connection->response;
298 if (connection->write_buffer_size == 0)
246 { 299 {
247 /* avoid busy-waiting when using external select 300 size = connection->daemon->pool_size;
248 (we assume that the main application will 301 do
249 wake up the external select once more data 302 {
250 is ready). With internal selects, we 303 size /= 2;
251 have no choice; if the app uses a thread 304 if (size < 128)
252 per connection, ret==0 is likely a bug -- 305 {
253 the application should block until data 306 /* not enough memory */
254 is ready! */ 307#if DEBUG_CLOSE
255 if ((0 == 308#if HAVE_MESSAGES
256 (connection->daemon-> 309 MHD_DLOG (connection->daemon, "Closing connection (out of memory)\n");
257 options & (MHD_USE_SELECT_INTERNALLY | 310#endif
258 MHD_USE_THREAD_PER_CONNECTION)))) 311#endif
259 connection->response_unready = MHD_YES; 312 connection_close_error (connection);
313 return MHD_NO;
314 }
315 buf = MHD_pool_allocate (connection->pool,
316 size,
317 MHD_NO);
318 }
319 while (buf == NULL);
320 connection->write_buffer_size = size;
321 connection->write_buffer = buf;
322 }
323
324 ret = response->crc (response->crc_cls,
325 connection->response_write_position,
326 &connection->write_buffer[8],
327 connection->write_buffer_size - 8 - 2);
328 if (ret == -1)
329 {
330 /* end of message, signal other side! */
331 strcpy(connection->write_buffer,
332 "0\r\n");
333 connection->write_buffer_append_offset = 3;
334 connection->write_buffer_send_offset = 0;
335 response->total_size = connection->response_write_position;
336 return MHD_YES;
337 }
338 if (ret == 0)
339 {
340 connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY;
260 return MHD_NO; 341 return MHD_NO;
261 } 342 }
262 connection->response_unready = MHD_NO; 343 if (ret > 0xFFFFFF)
344 ret = 0xFFFFFF;
345 snprintf(cbuf,
346 8,
347 "%X\r\n",
348 ret);
349 memcpy(&connection->write_buffer[8 - strlen(cbuf)],
350 cbuf,
351 strlen(cbuf));
352 memcpy(&connection->write_buffer[8 + ret],
353 "\r\n",
354 2);
355 connection->response_write_position += ret;
356 connection->write_buffer_send_offset = 8 - strlen(cbuf);
357 connection->write_buffer_append_offset = 8 + ret + 2;
263 return MHD_YES; 358 return MHD_YES;
264} 359}
265 360
266/** 361/**
267 * Obtain the select sets for this connection 362 * Check if we need to set some additional headers
268 * 363 * for http-compiliance.
269 * @return MHD_YES on success
270 */ 364 */
271int 365static void
272MHD_connection_get_fdset (struct MHD_Connection *connection, 366add_extra_headers (struct MHD_Connection *connection)
273 fd_set * read_fd_set,
274 fd_set * write_fd_set,
275 fd_set * except_fd_set, int *max_fd)
276{ 367{
277 int fd; 368 const char *have;
278 void *buf; 369 char buf[128];
279 370
280 fd = connection->socket_fd; 371 connection->have_chunked_upload = MHD_NO;
281 if (fd == -1) 372 if (connection->response->total_size == -1)
282 return MHD_YES; 373 {
283 if ((connection->read_close == MHD_NO) && 374 have = MHD_get_response_header (connection->response,
284 ((connection->have_received_headers == MHD_NO) || 375 MHD_HTTP_HEADER_CONNECTION);
285 (connection->read_buffer_offset < connection->read_buffer_size))) 376 if ( (have == NULL) ||
377 (0 != strcasecmp(have, "close")) )
378 {
379 if ( (connection->version != NULL) &&
380 (0 == strcasecmp(connection->version,
381 MHD_HTTP_VERSION_1_1)) )
382 {
383 connection->have_chunked_upload = MHD_YES;
384 have = MHD_get_response_header (connection->response,
385 MHD_HTTP_HEADER_TRANSFER_ENCODING);
386 if (have == NULL)
387 MHD_add_response_header (connection->response,
388 MHD_HTTP_HEADER_TRANSFER_ENCODING,
389 "chunked");
390 }
391 else
392 {
393 MHD_add_response_header (connection->response,
394 MHD_HTTP_HEADER_CONNECTION, "close");
395 }
396 }
397 }
398 else if (NULL == MHD_get_response_header (connection->response,
399 MHD_HTTP_HEADER_CONTENT_LENGTH))
286 { 400 {
287 FD_SET (fd, read_fd_set); 401 _REAL_SNPRINTF (buf,
288 if (fd > *max_fd) 402 128,
289 *max_fd = fd; 403 "%llu",
404 (unsigned long long) connection->response->total_size);
405 MHD_add_response_header (connection->response,
406 MHD_HTTP_HEADER_CONTENT_LENGTH, buf);
407 }
408}
409
410/**
411 * Produce HTTP "Date:" header.
412 * @param date where to write the header
413 * @param max maximum number of characters to write
414 */
415static void
416get_date_string (char *date, unsigned int max)
417{
418 static const char *days[] =
419 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
420 static const char *mons[] =
421 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
422 "Nov", "Dec"
423 };
424 struct tm now;
425 time_t t;
426
427 time (&t);
428 gmtime_r (&t, &now);
429 snprintf (date,
430 max - 1,
431 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
432 days[now.tm_wday % 7],
433 now.tm_mday,
434 mons[now.tm_mon % 12],
435 now.tm_year, now.tm_hour, now.tm_min, now.tm_sec);
436}
437
438/**
439 * try growing the read buffer
440 * @return MHD_YES on success, MHD_NO on failure
441 */
442static int
443try_grow_read_buffer(struct MHD_Connection * connection)
444{
445 void * buf;
446
447 buf = MHD_pool_reallocate (connection->pool,
448 connection->read_buffer,
449 connection->read_buffer_size,
450 connection->read_buffer_size * 2 +
451 MHD_BUF_INC_SIZE + 1);
452 if (buf == NULL)
453 return MHD_NO;
454 /* we can actually grow the buffer, do it! */
455 connection->read_buffer = buf;
456 connection->read_buffer_size =
457 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
458 return MHD_YES;
459}
460
461/**
462 * Allocate the connection's write buffer and
463 * fill it with all of the headers (or footers,
464 * if we have already sent the body) from the
465 * HTTPd's response.
466 */
467static int
468build_header_response (struct MHD_Connection *connection)
469{
470 size_t size;
471 size_t off;
472 struct MHD_HTTP_Header *pos;
473 char code[128];
474 char date[128];
475 char *data;
476 enum MHD_ValueKind kind;
477 const char *reason_phrase;
478
479 if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
480 {
481 add_extra_headers (connection);
482 reason_phrase =
483 MHD_get_reason_phrase_for (connection->responseCode);
484 _REAL_SNPRINTF (code, 128, "%s %u %s\r\n", MHD_HTTP_VERSION_1_1,
485 connection->responseCode, reason_phrase);
486 off = strlen (code);
487 /* estimate size */
488 size = off + 2; /* extra \r\n at the end */
489 kind = MHD_HEADER_KIND;
490 if (NULL == MHD_get_response_header (connection->response,
491 MHD_HTTP_HEADER_DATE))
492 get_date_string (date, sizeof (date));
493 else
494 date[0] = '\0';
495 size += strlen (date);
290 } 496 }
291 else 497 else
292 { 498 {
293 if ((connection->read_close == MHD_NO) && 499 size = 2;
294 ((connection->have_received_headers == MHD_YES) && 500 kind = MHD_FOOTER_KIND;
295 (connection->read_buffer_offset == connection->read_buffer_size))) 501 off = 0;
296 { 502 }
297 /* try growing the read buffer, just in case */ 503 pos = connection->response->first_header;
298 buf = MHD_pool_reallocate (connection->pool, 504 while (pos != NULL)
299 connection->read_buffer, 505 {
300 connection->read_buffer_size, 506 if (pos->kind == kind)
301 connection->read_buffer_size * 2 + 507 size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
302 MHD_BUF_INC_SIZE); 508 pos = pos->next;
303 if (buf != NULL) 509 }
304 { 510 /* produce data */
305 /* we can actually grow the buffer, do it! */ 511 data = MHD_pool_allocate (connection->pool, size + 1, MHD_YES);
306 connection->read_buffer = buf; 512 if (data == NULL)
307 connection->read_buffer_size = 513 {
308 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; 514#if HAVE_MESSAGES
309 FD_SET (fd, read_fd_set); 515 MHD_DLOG (connection->daemon, "Not enough memory for write!\n");
310 if (fd > *max_fd) 516#endif
311 *max_fd = fd; 517 return MHD_NO;
312 } 518 }
313 } 519 if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
520 {
521 memcpy (data, code, off);
314 } 522 }
315 if ((connection->response != NULL) && 523 pos = connection->response->first_header;
316 (connection->response_unready == MHD_YES)) 524 while (pos != NULL)
317 { 525 {
318 pthread_mutex_lock (&connection->response->mutex); 526 if (pos->kind == kind)
319 ready_response (connection); 527 {
320 pthread_mutex_unlock (&connection->response->mutex); 528 SPRINTF (&data[off], "%s: %s\r\n", pos->header, pos->value);
529 off += strlen (pos->header) + strlen (pos->value) + 4;
530 }
531 pos = pos->next;
321 } 532 }
322 if (((connection->response != NULL) && 533 if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
323 (connection->response_unready == MHD_NO)) ||
324 MHD_need_100_continue (connection))
325 { 534 {
326 FD_SET (fd, write_fd_set); 535 strcpy (&data[off], date);
327 if (fd > *max_fd) 536 off += strlen (date);
328 *max_fd = fd;
329 } 537 }
538 sprintf (&data[off], "\r\n");
539 off += 2;
540 if (off != size)
541 abort ();
542 connection->write_buffer = data;
543 connection->write_buffer_append_offset = size;
544 connection->write_buffer_send_offset = 0;
545 connection->write_buffer_size = size + 1;
330 return MHD_YES; 546 return MHD_YES;
331} 547}
332 548
@@ -338,15 +554,14 @@ MHD_connection_get_fdset (struct MHD_Connection *connection,
338 * @param status_code the response code to send (413 or 414) 554 * @param status_code the response code to send (413 or 414)
339 */ 555 */
340static void 556static void
341MHD_excessive_data_handler (struct MHD_Connection *connection, 557excessive_data_handler (struct MHD_Connection *connection,
342 unsigned int status_code) 558 unsigned int status_code)
343{ 559{
344 struct MHD_Response *response; 560 struct MHD_Response *response;
345 561
346 /* die, header far too long to be reasonable */ 562 /* die, header far too long to be reasonable */
347 connection->read_close = MHD_YES; 563 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
348 connection->have_received_headers = MHD_YES; 564 connection->read_closed = MHD_YES;
349 connection->have_received_body = MHD_YES;
350#if HAVE_MESSAGES 565#if HAVE_MESSAGES
351 MHD_DLOG (connection->daemon, 566 MHD_DLOG (connection->daemon,
352 "Received excessively long header, closing connection.\n"); 567 "Received excessively long header, closing connection.\n");
@@ -354,7 +569,166 @@ MHD_excessive_data_handler (struct MHD_Connection *connection,
354 response = MHD_create_response_from_data (strlen (REQUEST_TOO_BIG), 569 response = MHD_create_response_from_data (strlen (REQUEST_TOO_BIG),
355 REQUEST_TOO_BIG, MHD_NO, MHD_NO); 570 REQUEST_TOO_BIG, MHD_NO, MHD_NO);
356 MHD_queue_response (connection, status_code, response); 571 MHD_queue_response (connection, status_code, response);
572 EXTRA_CHECK(connection->response != NULL);
357 MHD_destroy_response (response); 573 MHD_destroy_response (response);
574 if (MHD_NO == build_header_response (connection))
575 {
576 /* oops - close! */
577#if HAVE_MESSAGES
578 MHD_DLOG (connection->daemon,
579 "Closing connection (failed to create response header)\n");
580#endif
581 connection->state = MHD_CONNECTION_CLOSED;
582 }
583 else
584 {
585 connection->state = MHD_CONNECTION_HEADERS_SENDING;
586 }
587}
588
589/**
590 * Add "fd" to the "fd_set". If "fd" is
591 * greater than "*max", set "*max" to fd.
592 */
593static void
594do_fd_set(int fd,
595 fd_set * set,
596 int * max_fd)
597{
598 FD_SET (fd, set);
599 if (fd > *max_fd)
600 *max_fd = fd;
601}
602
603/**
604 * Obtain the select sets for this connection
605 *
606 * @return MHD_YES on success
607 */
608int
609MHD_connection_get_fdset (struct MHD_Connection *connection,
610 fd_set * read_fd_set,
611 fd_set * write_fd_set,
612 fd_set * except_fd_set, int *max_fd)
613{
614 int fd;
615
616 if (connection->pool == NULL)
617 connection->pool = MHD_pool_create (connection->daemon->pool_size);
618 if (connection->pool == NULL)
619 {
620#if HAVE_MESSAGES
621 MHD_DLOG (connection->daemon, "Failed to create memory pool!\n");
622#endif
623 connection_close_error (connection);
624 return MHD_NO;
625 }
626 fd = connection->socket_fd;
627 if (fd == -1)
628 return MHD_YES;
629 while (1) {
630#if DEBUG_STATES
631 fprintf(stderr,
632 "`%s' in state %u\n",
633 __FUNCTION__,
634 connection->state);
635#endif
636 switch (connection->state)
637 {
638 case MHD_CONNECTION_INIT:
639 case MHD_CONNECTION_URL_RECEIVED:
640 case MHD_CONNECTION_HEADER_PART_RECEIVED:
641 /* while reading headers, we always grow the
642 read buffer if needed, no size-check required */
643 if ( (connection->read_closed) &&
644 (connection->read_buffer_offset == 0) )
645 {
646 connection->state = MHD_CONNECTION_CLOSED;
647 continue;
648 }
649 if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
650 (MHD_NO == try_grow_read_buffer(connection)) )
651 {
652 excessive_data_handler (connection,
653 (connection->url != NULL)
654 ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
655 : MHD_HTTP_REQUEST_URI_TOO_LONG);
656 continue;
657 }
658 if (MHD_NO == connection->read_closed)
659 do_fd_set (fd, read_fd_set, max_fd);
660 break;
661 case MHD_CONNECTION_HEADERS_RECEIVED:
662 /* we should never get here */
663 EXTRA_CHECK(0);
664 break;
665 case MHD_CONNECTION_HEADERS_PROCESSED:
666 EXTRA_CHECK(0);
667 break;
668 case MHD_CONNECTION_CONTINUE_SENDING:
669 do_fd_set (fd, write_fd_set, max_fd);
670 break;
671 case MHD_CONNECTION_CONTINUE_SENT:
672 if (connection->read_buffer_offset == connection->read_buffer_size)
673 try_grow_read_buffer(connection);
674 if (connection->read_buffer_offset < connection->read_buffer_size)
675 do_fd_set (fd, read_fd_set, max_fd);
676 break;
677 case MHD_CONNECTION_BODY_RECEIVED:
678 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
679 /* while reading footers, we always grow the
680 read buffer if needed, no size-check required */
681 if (MHD_YES == connection->read_closed)
682 {
683 connection->state = MHD_CONNECTION_CLOSED;
684 continue;
685 }
686 do_fd_set (fd, read_fd_set, max_fd);
687 /* transition to FOOTERS_RECEIVED
688 happens in read handler */
689 break;
690 case MHD_CONNECTION_FOOTERS_RECEIVED:
691 /* no socket action, wait for client
692 to provide response */
693 break;
694 case MHD_CONNECTION_HEADERS_SENDING:
695 /* headers in buffer, keep writing */
696 do_fd_set(fd, write_fd_set, max_fd);
697 break;
698 case MHD_CONNECTION_HEADERS_SENT:
699 EXTRA_CHECK(0);
700 break;
701 case MHD_CONNECTION_NORMAL_BODY_READY:
702 do_fd_set (fd, write_fd_set, max_fd);
703 break;
704 case MHD_CONNECTION_NORMAL_BODY_UNREADY:
705 /* not ready, no socket action */
706 break;
707 case MHD_CONNECTION_CHUNKED_BODY_READY:
708 do_fd_set (fd, write_fd_set, max_fd);
709 break;
710 case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
711 /* not ready, no socket action */
712 break;
713 case MHD_CONNECTION_BODY_SENT:
714 EXTRA_CHECK(0);
715 break;
716 case MHD_CONNECTION_FOOTERS_SENDING:
717 do_fd_set (fd, write_fd_set, max_fd);
718 break;
719 case MHD_CONNECTION_FOOTERS_SENT:
720 EXTRA_CHECK(0);
721 break;
722 case MHD_CONNECTION_CLOSED:
723 if (connection->socket_fd != -1)
724 connection_close_error(connection);
725 return MHD_YES; /* do nothing, not even reading */
726 default:
727 EXTRA_CHECK(0);
728 }
729 break;
730 }
731 return MHD_YES;
358} 732}
359 733
360/** 734/**
@@ -366,7 +740,7 @@ MHD_excessive_data_handler (struct MHD_Connection *connection,
366 * return NULL. Otherwise return a pointer to the line. 740 * return NULL. Otherwise return a pointer to the line.
367 */ 741 */
368static char * 742static char *
369MHD_get_next_header_line (struct MHD_Connection *connection) 743get_next_header_line (struct MHD_Connection *connection)
370{ 744{
371 char *rbuf; 745 char *rbuf;
372 size_t pos; 746 size_t pos;
@@ -390,10 +764,10 @@ MHD_get_next_header_line (struct MHD_Connection *connection)
390 MHD_BUF_INC_SIZE); 764 MHD_BUF_INC_SIZE);
391 if (rbuf == NULL) 765 if (rbuf == NULL)
392 { 766 {
393 MHD_excessive_data_handler (connection, 767 excessive_data_handler (connection,
394 (connection->url != NULL) 768 (connection->url != NULL)
395 ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE 769 ? MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
396 : MHD_HTTP_REQUEST_URI_TOO_LONG); 770 : MHD_HTTP_REQUEST_URI_TOO_LONG);
397 } 771 }
398 else 772 else
399 { 773 {
@@ -418,8 +792,8 @@ MHD_get_next_header_line (struct MHD_Connection *connection)
418 * @return MHD_NO on failure (out of memory), MHD_YES for success 792 * @return MHD_NO on failure (out of memory), MHD_YES for success
419 */ 793 */
420static int 794static int
421MHD_connection_add_header (struct MHD_Connection *connection, 795connection_add_header (struct MHD_Connection *connection,
422 char *key, char *value, enum MHD_ValueKind kind) 796 char *key, char *value, enum MHD_ValueKind kind)
423{ 797{
424 struct MHD_HTTP_Header *hdr; 798 struct MHD_HTTP_Header *hdr;
425 799
@@ -431,8 +805,8 @@ MHD_connection_add_header (struct MHD_Connection *connection,
431 MHD_DLOG (connection->daemon, 805 MHD_DLOG (connection->daemon,
432 "Not enough memory to allocate header record!\n"); 806 "Not enough memory to allocate header record!\n");
433#endif 807#endif
434 MHD_excessive_data_handler (connection, 808 excessive_data_handler (connection,
435 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); 809 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
436 return MHD_NO; 810 return MHD_NO;
437 } 811 }
438 hdr->next = connection->headers_received; 812 hdr->next = connection->headers_received;
@@ -468,8 +842,8 @@ parse_arguments (enum MHD_ValueKind kind,
468 } 842 }
469 MHD_http_unescape (args); 843 MHD_http_unescape (args);
470 MHD_http_unescape (equals); 844 MHD_http_unescape (equals);
471 if (MHD_NO == MHD_connection_add_header (connection, 845 if (MHD_NO == connection_add_header (connection,
472 args, equals, kind)) 846 args, equals, kind))
473 return MHD_NO; 847 return MHD_NO;
474 args = amper; 848 args = amper;
475 } 849 }
@@ -482,7 +856,7 @@ parse_arguments (enum MHD_ValueKind kind,
482 * @return MHD_YES for success, MHD_NO for failure (malformed, out of memory) 856 * @return MHD_YES for success, MHD_NO for failure (malformed, out of memory)
483 */ 857 */
484static int 858static int
485MHD_parse_cookie_header (struct MHD_Connection *connection) 859parse_cookie_header (struct MHD_Connection *connection)
486{ 860{
487 const char *hdr; 861 const char *hdr;
488 char *cpy; 862 char *cpy;
@@ -500,8 +874,8 @@ MHD_parse_cookie_header (struct MHD_Connection *connection)
500#if HAVE_MESSAGES 874#if HAVE_MESSAGES
501 MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n"); 875 MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n");
502#endif 876#endif
503 MHD_excessive_data_handler (connection, 877 excessive_data_handler (connection,
504 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE); 878 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
505 return MHD_NO; 879 return MHD_NO;
506 } 880 }
507 memcpy (cpy, hdr, strlen (hdr) + 1); 881 memcpy (cpy, hdr, strlen (hdr) + 1);
@@ -536,8 +910,8 @@ MHD_parse_cookie_header (struct MHD_Connection *connection)
536 equals[strlen (equals) - 1] = '\0'; 910 equals[strlen (equals) - 1] = '\0';
537 equals++; 911 equals++;
538 } 912 }
539 if (MHD_NO == MHD_connection_add_header (connection, 913 if (MHD_NO == connection_add_header (connection,
540 pos, equals, MHD_COOKIE_KIND)) 914 pos, equals, MHD_COOKIE_KIND))
541 return MHD_NO; 915 return MHD_NO;
542 pos = semicolon; 916 pos = semicolon;
543 } 917 }
@@ -587,235 +961,29 @@ parse_initial_message_line (struct MHD_Connection *connection, char *line)
587 return MHD_YES; 961 return MHD_YES;
588} 962}
589 963
590
591/**
592 * This function is designed to parse the input buffer of a given
593 * connection for HTTP headers -- and in the case of chunked encoding,
594 * also for HTTP "footers".
595 *
596 * Once the header is complete, it should have set the
597 * headers_received, url and method values and set
598 * have_received_headers to MHD_YES. If no body is expected, it
599 * should also set "have_received_body" to MHD_YES. Otherwise, it
600 * should set "remaining_upload_size" to the expected size of the
601 * body. If the size of the body is unknown, it should be set to -1.
602 */
603static void
604MHD_parse_connection_headers (struct MHD_Connection *connection)
605{
606 char *last;
607 char *line;
608 char *colon;
609 char *tmp;
610 const char *clen;
611 unsigned long long cval;
612 struct MHD_Response *response;
613
614 if (((connection->have_received_body == MHD_YES) &&
615 (connection->have_chunked_upload == MHD_NO)) ||
616 (connection->have_received_headers == MHD_YES))
617 abort ();
618 colon = NULL; /* make gcc happy */
619 last = NULL;
620 while (NULL != (line = MHD_get_next_header_line (connection)))
621 {
622 if (last != NULL)
623 {
624 if ((line[0] == ' ') || (line[0] == '\t'))
625 {
626 /* value was continued on the next line, see
627 http://www.jmarshall.com/easy/http/ */
628 last = MHD_pool_reallocate (connection->pool,
629 last,
630 strlen (last) + 1,
631 strlen (line) + strlen (last) + 1);
632 if (last == NULL)
633 {
634 MHD_excessive_data_handler (connection,
635 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
636 break;
637 }
638 tmp = line;
639 while ((tmp[0] == ' ') || (tmp[0] == '\t'))
640 tmp++; /* skip whitespace at start of 2nd line */
641 strcat (last, tmp);
642 continue; /* possibly more than 2 lines... */
643 }
644 else
645 {
646 if (MHD_NO == MHD_connection_add_header (connection,
647 last,
648 colon,
649 MHD_HEADER_KIND))
650 return;
651 last = NULL;
652 }
653 }
654 if (connection->url == NULL)
655 {
656 /* line must be request line (first line of header) */
657 if (MHD_NO == parse_initial_message_line (connection, line))
658 goto DIE;
659 continue;
660 }
661 /* check if this is the end of the header */
662 if (strlen (line) == 0)
663 {
664 /* end of header */
665 connection->have_received_headers = MHD_YES;
666 clen = MHD_lookup_connection_value (connection,
667 MHD_HEADER_KIND,
668 MHD_HTTP_HEADER_CONTENT_LENGTH);
669 if (clen != NULL)
670 {
671 if (1 != sscanf (clen, "%llu", &cval))
672 {
673#if HAVE_MESSAGES
674 MHD_DLOG (connection->daemon,
675 "Failed to parse `%s' header `%s', closing connection.\n",
676 MHD_HTTP_HEADER_CONTENT_LENGTH, clen);
677#endif
678 goto DIE;
679 }
680 connection->remaining_upload_size = cval;
681 connection->have_received_body = cval == 0 ? MHD_YES : MHD_NO;
682 }
683 else
684 {
685 if (NULL == MHD_lookup_connection_value (connection,
686 MHD_HEADER_KIND,
687 MHD_HTTP_HEADER_TRANSFER_ENCODING))
688 {
689 /* this request does not have a body */
690 connection->remaining_upload_size = 0;
691 connection->have_received_body = MHD_YES;
692 }
693 else
694 {
695 if (connection->have_chunked_upload == MHD_NO)
696 {
697 connection->remaining_upload_size = -1; /* unknown size */
698 if (0 ==
699 strcasecmp (MHD_lookup_connection_value
700 (connection, MHD_HEADER_KIND,
701 MHD_HTTP_HEADER_TRANSFER_ENCODING),
702 "chunked"))
703 connection->have_chunked_upload = MHD_YES;
704 }
705 else
706 {
707 /* we were actually processing the footers at the
708 END of a chunked encoding; give connection
709 handler an extra chance... */
710 connection->have_chunked_upload = MHD_NO; /* no more! */
711 MHD_call_connection_handler (connection);
712 }
713 }
714 }
715 if ((0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options))
716 && (NULL != connection->version)
717 && (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version))
718 && (NULL ==
719 MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
720 MHD_HTTP_HEADER_HOST)))
721 {
722 /* die, http 1.1 request without host and we are pedantic */
723 connection->have_received_body = MHD_YES;
724 connection->read_close = MHD_YES;
725#if HAVE_MESSAGES
726 MHD_DLOG (connection->daemon,
727 "Received `%s' request without `%s' header.\n",
728 MHD_HTTP_VERSION_1_1, MHD_HTTP_HEADER_HOST);
729#endif
730 response =
731 MHD_create_response_from_data (strlen (REQUEST_LACKS_HOST),
732 REQUEST_LACKS_HOST, MHD_NO,
733 MHD_NO);
734 MHD_queue_response (connection, MHD_HTTP_BAD_REQUEST, response);
735 MHD_destroy_response (response);
736 }
737 break;
738 }
739 /* line should be normal header line, find colon */
740 colon = strstr (line, ":");
741 if (colon == NULL)
742 {
743 /* error in header line, die hard */
744#if HAVE_MESSAGES
745 MHD_DLOG (connection->daemon,
746 "Received malformed line (no colon), closing connection.\n");
747#endif
748 goto DIE;
749 }
750 /* zero-terminate header */
751 colon[0] = '\0';
752 colon++; /* advance to value */
753 while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t')))
754 colon++;
755 /* we do the actual adding of the connection
756 header at the beginning of the while
757 loop since we need to be able to inspect
758 the *next* header line (in case it starts
759 with a space...) */
760 last = line;
761 }
762 if ((last != NULL) &&
763 (MHD_NO == MHD_connection_add_header (connection,
764 last, colon, MHD_HEADER_KIND)))
765 return; /* error */
766 MHD_parse_cookie_header (connection);
767 return;
768DIE:
769#if HAVE_MESSAGES
770 MHD_DLOG (connection->daemon,
771 "Closing connection (problem parsing headers)\n");
772#endif
773 connection_close_error (connection);
774}
775
776
777/**
778 * Find the handler responsible for this request.
779 */
780static struct MHD_Access_Handler *
781MHD_find_access_handler (struct MHD_Connection *connection)
782{
783 struct MHD_Access_Handler *pos;
784
785 pos = connection->daemon->handlers;
786 while (pos != NULL)
787 {
788 if (0 == strcmp (connection->url, pos->uri_prefix))
789 return pos;
790 pos = pos->next;
791 }
792 return &connection->daemon->default_handler;
793}
794
795
796/** 964/**
797 * Call the handler of the application for this 965 * Call the handler of the application for this
798 * connection. 966 * connection. Handles chunking of the upload
967 * as well as normal uploads.
799 */ 968 */
800void 969static void
801MHD_call_connection_handler (struct MHD_Connection *connection) 970call_connection_handler (struct MHD_Connection *connection)
802{ 971{
803 struct MHD_Access_Handler *ah;
804 unsigned int processed; 972 unsigned int processed;
805 unsigned int available; 973 unsigned int available;
806 unsigned int used; 974 unsigned int used;
807 int instant_retry; 975 int instant_retry;
808 unsigned int i; 976 unsigned int i;
977 int malformed;
809 978
810 if (connection->response != NULL) 979 if (connection->response != NULL)
811 return; /* already queued a response */ 980 return; /* already queued a response */
812 if (connection->have_received_headers == MHD_NO)
813 abort (); /* bad timing... */
814 do 981 do
815 { 982 {
816 instant_retry = MHD_NO; 983 instant_retry = MHD_NO;
817 available = connection->read_buffer_offset; 984 available = connection->read_buffer_offset;
818 if (connection->have_chunked_upload == MHD_YES) 985 if ( (connection->have_chunked_upload == MHD_YES) &&
986 (connection->remaining_upload_size == -1) )
819 { 987 {
820 if ((connection->current_chunk_offset == 988 if ((connection->current_chunk_offset ==
821 connection->current_chunk_size) 989 connection->current_chunk_size)
@@ -876,18 +1044,17 @@ MHD_call_connection_handler (struct MHD_Connection *connection)
876 } 1044 }
877 if (i >= available) 1045 if (i >= available)
878 return; /* need more data... */ 1046 return; /* need more data... */
879 /* The following if-statement is a bit crazy -- we 1047 malformed = (i >= 6);
880 use the second clause only for the side-effect, 1048 if (! malformed)
881 0-terminating the buffer for the following sscanf 1049 {
882 attempts; yes, there should be only a single 1050 connection->read_buffer[i] = '\0';
883 "="-sign (assignment!) in the read_buffer[i]-line. */ 1051 malformed = (1 != sscanf (connection->read_buffer,
884 if ((i >= 6) || 1052 "%X",
885 ((connection->read_buffer[i] = '\0')) || 1053 &connection->current_chunk_size)) &&
886 ((1 != sscanf (connection->read_buffer, 1054 (1 != sscanf (connection->read_buffer,
887 "%X", 1055 "%x", &connection->current_chunk_size));
888 &connection->current_chunk_size)) && 1056 }
889 (1 != sscanf (connection->read_buffer, 1057 if (malformed)
890 "%x", &connection->current_chunk_size))))
891 { 1058 {
892 /* malformed encoding */ 1059 /* malformed encoding */
893#if HAVE_MESSAGES 1060#if HAVE_MESSAGES
@@ -908,11 +1075,7 @@ MHD_call_connection_handler (struct MHD_Connection *connection)
908 instant_retry = MHD_YES; 1075 instant_retry = MHD_YES;
909 if (connection->current_chunk_size == 0) 1076 if (connection->current_chunk_size == 0)
910 { 1077 {
911 /* we're back to reading HEADERS (footers!) */
912 connection->have_received_body = MHD_YES;
913 connection->remaining_upload_size = 0; 1078 connection->remaining_upload_size = 0;
914 connection->have_received_headers = MHD_NO;
915 MHD_parse_connection_headers (connection);
916 return; 1079 return;
917 } 1080 }
918 continue; 1081 continue;
@@ -925,8 +1088,7 @@ MHD_call_connection_handler (struct MHD_Connection *connection)
925 available = 0; 1088 available = 0;
926 } 1089 }
927 used = processed; 1090 used = processed;
928 ah = MHD_find_access_handler (connection); 1091 if (MHD_NO == connection->daemon->default_handler (connection->daemon->default_handler_cls,
929 if (MHD_NO == ah->dh (ah->dh_cls,
930 connection, 1092 connection,
931 connection->url, 1093 connection->url,
932 connection->method, 1094 connection->method,
@@ -942,6 +1104,8 @@ MHD_call_connection_handler (struct MHD_Connection *connection)
942 connection_close_error (connection); 1104 connection_close_error (connection);
943 return; 1105 return;
944 } 1106 }
1107 if (processed > used)
1108 abort(); /* fatal client API violation! */
945 if (processed != 0) 1109 if (processed != 0)
946 instant_retry = MHD_NO; /* client did not process everything */ 1110 instant_retry = MHD_NO; /* client did not process everything */
947 used -= processed; 1111 used -= processed;
@@ -953,79 +1117,26 @@ MHD_call_connection_handler (struct MHD_Connection *connection)
953 &connection->read_buffer[used], processed + available); 1117 &connection->read_buffer[used], processed + available);
954 if (connection->remaining_upload_size != -1) 1118 if (connection->remaining_upload_size != -1)
955 connection->remaining_upload_size -= used; 1119 connection->remaining_upload_size -= used;
956 connection->read_buffer_offset = processed + available; 1120 connection->read_buffer_offset = processed + available;
957 if ((connection->remaining_upload_size == 0) ||
958 ((connection->read_buffer_offset == 0) &&
959 (connection->remaining_upload_size == -1)
960 && (connection->socket_fd == -1)))
961 {
962 connection->have_received_body = MHD_YES;
963 if (connection->read_buffer != NULL)
964 MHD_pool_reallocate (connection->pool,
965 connection->read_buffer,
966 (connection->read_buffer ==
967 NULL) ? 0 : connection->read_buffer_size +
968 1, 0);
969 connection->read_buffer_offset = 0;
970 connection->read_buffer_size = 0;
971 connection->read_buffer = NULL;
972 }
973 } 1121 }
974 while (instant_retry == MHD_YES); 1122 while (instant_retry == MHD_YES);
975} 1123}
976 1124
977/** 1125/**
978 * This function handles a particular connection when it has been 1126 * Try reading data from the socket into the
979 * determined that there is data to be read off a socket. All implementations 1127 * read buffer of the connection.
980 * (multithreaded, external select, internal select) call this function 1128 *
981 * to handle reads. 1129 * @return MHD_YES if something changed,
1130 * MHD_NO if we were interrupted or if
1131 * no space was available
982 */ 1132 */
983int 1133static int
984MHD_connection_handle_read (struct MHD_Connection *connection) 1134do_read(struct MHD_Connection * connection)
985{ 1135{
986 int bytes_read; 1136 int bytes_read;
987 void *tmp; 1137
988 1138 if (connection->read_buffer_size == connection->read_buffer_offset)
989 if (connection->pool == NULL) 1139 return MHD_NO;
990 connection->pool = MHD_pool_create (connection->daemon->pool_size);
991 if (connection->pool == NULL)
992 {
993#if HAVE_MESSAGES
994 MHD_DLOG (connection->daemon, "Failed to create memory pool!\n");
995#endif
996 connection_close_error (connection);
997 return MHD_NO;
998 }
999 if ((connection->read_buffer_offset >= connection->read_buffer_size) &&
1000 (connection->have_received_headers == MHD_NO))
1001 {
1002 /* need to grow read buffer */
1003 tmp = MHD_pool_reallocate (connection->pool,
1004 connection->read_buffer,
1005 connection->read_buffer_size,
1006 connection->read_buffer_size * 2 +
1007 MHD_BUF_INC_SIZE + 1);
1008 if (tmp == NULL)
1009 {
1010#if HAVE_MESSAGES
1011 MHD_DLOG (connection->daemon,
1012 "Not enough memory for reading headers!\n");
1013#endif
1014 MHD_excessive_data_handler (connection,
1015 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
1016 return MHD_NO;
1017 }
1018 connection->read_buffer = tmp;
1019 connection->read_buffer_size =
1020 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
1021 }
1022 if (connection->read_buffer_offset >= connection->read_buffer_size)
1023 {
1024#if HAVE_MESSAGES
1025 MHD_DLOG (connection->daemon, "Unexpected call to %s.\n", __FUNCTION__);
1026#endif
1027 return MHD_NO;
1028 }
1029 bytes_read = RECV (connection->socket_fd, 1140 bytes_read = RECV (connection->socket_fd,
1030 &connection->read_buffer[connection->read_buffer_offset], 1141 &connection->read_buffer[connection->read_buffer_offset],
1031 connection->read_buffer_size - 1142 connection->read_buffer_size -
@@ -1044,150 +1155,297 @@ MHD_connection_handle_read (struct MHD_Connection *connection)
1044 if (bytes_read == 0) 1155 if (bytes_read == 0)
1045 { 1156 {
1046 /* other side closed connection */ 1157 /* other side closed connection */
1047 connection->read_close = MHD_YES; 1158 connection->read_closed = MHD_YES;
1048 if ((connection->have_received_headers == MHD_YES) 1159 return MHD_NO;
1049 && (connection->read_buffer_offset > 0))
1050 MHD_call_connection_handler (connection);
1051#if DEBUG_CLOSE
1052#if HAVE_MESSAGES
1053 MHD_DLOG (connection->daemon,
1054 "Shutting down connection for reading (other side closed connection)\n");
1055#endif
1056#endif
1057 shutdown (connection->socket_fd, SHUT_RD);
1058 if ((connection->have_received_headers == MHD_NO) ||
1059 (connection->have_received_body == MHD_NO))
1060 {
1061 /* no request => no response! */
1062 CLOSE (connection->socket_fd);
1063 connection->socket_fd = -1;
1064 }
1065 return MHD_YES;
1066 } 1160 }
1067 connection->read_buffer_offset += bytes_read; 1161 connection->read_buffer_offset += bytes_read;
1068 if (connection->have_received_headers == MHD_NO)
1069 MHD_parse_connection_headers (connection);
1070 if ((connection->have_received_headers == MHD_YES)
1071 && (connection->method != NULL))
1072 MHD_call_connection_handler (connection);
1073 return MHD_YES; 1162 return MHD_YES;
1074} 1163}
1075 1164
1076/** 1165/**
1077 * Check if we need to set some additional headers 1166 * We have received (possibly the beginning of) a line in the
1078 * for http-compiliance. 1167 * header (or footer). Validate (check for ":") and prepare
1168 * to process.
1079 */ 1169 */
1080static void 1170static void
1081MHD_add_extra_headers (struct MHD_Connection *connection) 1171process_header_line(struct MHD_Connection * connection,
1172 char * line)
1082{ 1173{
1083 const char *have; 1174 char *colon;
1084 char buf[128];
1085 1175
1086 if (connection->response->total_size == -1) 1176 /* line should be normal header line, find colon */
1177 colon = strstr (line, ":");
1178 if (colon == NULL)
1087 { 1179 {
1088 have = MHD_get_response_header (connection->response, 1180 /* error in header line, die hard */
1089 MHD_HTTP_HEADER_CONNECTION); 1181#if HAVE_MESSAGES
1090 if (have == NULL) 1182 MHD_DLOG (connection->daemon,
1091 MHD_add_response_header (connection->response, 1183 "Received malformed line (no colon), closing connection.\n");
1092 MHD_HTTP_HEADER_CONNECTION, "close"); 1184#endif
1093 } 1185 connection->state = MHD_CONNECTION_CLOSED;
1094 else if (NULL == MHD_get_response_header (connection->response, 1186 return;
1095 MHD_HTTP_HEADER_CONTENT_LENGTH))
1096 {
1097 _REAL_SNPRINTF (buf,
1098 128,
1099 "%llu",
1100 (unsigned long long) connection->response->total_size);
1101 MHD_add_response_header (connection->response,
1102 MHD_HTTP_HEADER_CONTENT_LENGTH, buf);
1103 } 1187 }
1188 /* zero-terminate header */
1189 colon[0] = '\0';
1190 colon++; /* advance to value */
1191 while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t')))
1192 colon++;
1193 /* we do the actual adding of the connection
1194 header at the beginning of the while
1195 loop since we need to be able to inspect
1196 the *next* header line (in case it starts
1197 with a space...) */
1198 connection->last = line;
1199 connection->colon = colon;
1104} 1200}
1105 1201
1202/**
1203 * Process a header value that spans multiple lines.
1204 * The previous line(s) are in connection->last.
1205 *
1206 * @param line the current input line
1207 * @param kind if the line is complete, add a header
1208 * of the given kind
1209 */
1106static void 1210static void
1107get_date_string (char *date, unsigned int max) 1211process_broken_line(struct MHD_Connection * connection,
1212 char * line,
1213 enum MHD_ValueKind kind)
1108{ 1214{
1109 static const char *days[] = 1215 char * last;
1110 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; 1216 char * tmp;
1111 static const char *mons[] =
1112 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
1113 "Nov", "Dec"
1114 };
1115 struct tm now;
1116 time_t t;
1117 1217
1118 time (&t); 1218 last = connection->last;
1119 gmtime_r (&t, &now); 1219 if ((line[0] == ' ') || (line[0] == '\t'))
1120 snprintf (date, 1220 {
1121 max - 1, 1221 /* value was continued on the next line, see
1122 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n", 1222 http://www.jmarshall.com/easy/http/ */
1123 days[now.tm_wday % 7], 1223 last = MHD_pool_reallocate (connection->pool,
1124 now.tm_mday, 1224 last,
1125 mons[now.tm_mon % 12], 1225 strlen (last) + 1,
1126 now.tm_year, now.tm_hour, now.tm_min, now.tm_sec); 1226 strlen (line) + strlen (last) + 1);
1227 if (last == NULL)
1228 {
1229 excessive_data_handler (connection,
1230 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
1231 return;
1232 }
1233 tmp = line;
1234 while ((tmp[0] == ' ') || (tmp[0] == '\t'))
1235 tmp++; /* skip whitespace at start of 2nd line */
1236 strcat (last, tmp);
1237 connection->last = last;
1238 return; /* possibly more than 2 lines... */
1239 }
1240 if (MHD_NO == connection_add_header (connection,
1241 last,
1242 connection->colon,
1243 kind))
1244 {
1245 excessive_data_handler (connection,
1246 MHD_HTTP_REQUEST_ENTITY_TOO_LARGE);
1247 return;
1248 }
1249 /* we still have the current line to deal with... */
1250 if (strlen(line) != 0)
1251 process_header_line(connection,
1252 line);
1127} 1253}
1128 1254
1129/** 1255/**
1130 * Allocate the connection's write buffer and 1256 * Parse the various headers; figure out the size
1131 * fill it with all of the headers from the 1257 * of the upload and make sure the headers follow
1132 * HTTPd's response. 1258 * the protocol. Advance to the appropriate state.
1133 */ 1259 */
1134static int 1260static void
1135MHD_build_header_response (struct MHD_Connection *connection) 1261parse_connection_headers(struct MHD_Connection * connection)
1136{ 1262{
1137 size_t size; 1263 const char *clen;
1138 size_t off; 1264 unsigned long long cval;
1139 struct MHD_HTTP_Header *pos; 1265 struct MHD_Response *response;
1140 char code[128];
1141 char date[128];
1142 char *data;
1143 1266
1144 MHD_add_extra_headers (connection); 1267 parse_cookie_header (connection);
1145 const char *reason_phrase = 1268 if ((0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options))
1146 MHD_get_reason_phrase_for (connection->responseCode); 1269 && (NULL != connection->version)
1147 _REAL_SNPRINTF (code, 128, "%s %u %s\r\n", MHD_HTTP_VERSION_1_1, 1270 && (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version))
1148 connection->responseCode, reason_phrase); 1271 && (NULL ==
1149 off = strlen (code); 1272 MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
1150 /* estimate size */ 1273 MHD_HTTP_HEADER_HOST)))
1151 size = off + 2; /* extra \r\n at the end */
1152 pos = connection->response->first_header;
1153 while (pos != NULL)
1154 { 1274 {
1155 size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */ 1275 /* die, http 1.1 request without host and we are pedantic */
1156 pos = pos->next; 1276 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1277 connection->read_closed = MHD_YES;
1278#if HAVE_MESSAGES
1279 MHD_DLOG (connection->daemon,
1280 "Received `%s' request without `%s' header.\n",
1281 MHD_HTTP_VERSION_1_1, MHD_HTTP_HEADER_HOST);
1282#endif
1283 response =
1284 MHD_create_response_from_data (strlen (REQUEST_LACKS_HOST),
1285 REQUEST_LACKS_HOST, MHD_NO,
1286 MHD_NO);
1287 MHD_queue_response (connection, MHD_HTTP_BAD_REQUEST, response);
1288 MHD_destroy_response (response);
1289 return;
1157 } 1290 }
1158 if (NULL == MHD_get_response_header (connection->response, 1291
1159 MHD_HTTP_HEADER_DATE)) 1292 clen = MHD_lookup_connection_value (connection,
1160 get_date_string (date, sizeof (date)); 1293 MHD_HEADER_KIND,
1161 else 1294 MHD_HTTP_HEADER_CONTENT_LENGTH);
1162 date[0] = '\0'; 1295 if (clen != NULL)
1163 size += strlen (date);
1164 /* produce data */
1165 data = MHD_pool_allocate (connection->pool, size + 1, MHD_YES);
1166 if (data == NULL)
1167 { 1296 {
1297 if (1 != sscanf (clen, "%llu", &cval))
1298 {
1168#if HAVE_MESSAGES 1299#if HAVE_MESSAGES
1169 MHD_DLOG (connection->daemon, "Not enough memory for write!\n"); 1300 MHD_DLOG (connection->daemon,
1301 "Failed to parse `%s' header `%s', closing connection.\n",
1302 MHD_HTTP_HEADER_CONTENT_LENGTH, clen);
1170#endif 1303#endif
1171 return MHD_NO; 1304 connection->state = MHD_CONNECTION_CLOSED;
1305 return;
1306 }
1307 connection->remaining_upload_size = cval;
1172 } 1308 }
1173 memcpy (data, code, off); 1309 else
1174 pos = connection->response->first_header;
1175 while (pos != NULL)
1176 { 1310 {
1177 SPRINTF (&data[off], "%s: %s\r\n", pos->header, pos->value); 1311 if (NULL == MHD_lookup_connection_value (connection,
1178 off += strlen (pos->header) + strlen (pos->value) + 4; 1312 MHD_HEADER_KIND,
1179 pos = pos->next; 1313 MHD_HTTP_HEADER_TRANSFER_ENCODING))
1314 {
1315 /* this request does not have a body */
1316 connection->remaining_upload_size = 0;
1317 }
1318 else
1319 {
1320 connection->remaining_upload_size = -1; /* unknown size */
1321 if (0 ==
1322 strcasecmp (MHD_lookup_connection_value
1323 (connection, MHD_HEADER_KIND,
1324 MHD_HTTP_HEADER_TRANSFER_ENCODING),
1325 "chunked"))
1326 connection->have_chunked_upload = MHD_YES;
1327 }
1328 }
1329}
1330
1331/**
1332 * This function handles a particular connection when it has been
1333 * determined that there is data to be read off a socket. All
1334 * implementations (multithreaded, external select, internal select)
1335 * call this function to handle reads.
1336 *
1337 * @return MHD_YES if we should continue to process the
1338 * connection (not dead yet), MHD_NO if it died
1339 */
1340int
1341MHD_connection_handle_read (struct MHD_Connection *connection)
1342{
1343 connection->last_activity = time(NULL);
1344 if (connection->state == MHD_CONNECTION_CLOSED)
1345 return MHD_NO;
1346 if (MHD_NO == do_read(connection))
1347 return MHD_YES;
1348 while (1) {
1349#if DEBUG_STATES
1350 fprintf(stderr,
1351 "`%s' in state %u\n",
1352 __FUNCTION__,
1353 connection->state);
1354#endif
1355 switch (connection->state)
1356 {
1357 case MHD_CONNECTION_INIT:
1358 case MHD_CONNECTION_URL_RECEIVED:
1359 case MHD_CONNECTION_HEADER_PART_RECEIVED:
1360 case MHD_CONNECTION_HEADERS_RECEIVED:
1361 case MHD_CONNECTION_HEADERS_PROCESSED:
1362 case MHD_CONNECTION_CONTINUE_SENDING:
1363 case MHD_CONNECTION_CONTINUE_SENT:
1364 case MHD_CONNECTION_BODY_RECEIVED:
1365 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
1366 /* nothing to do but default action */
1367 if (MHD_YES == connection->read_closed)
1368 {
1369 connection->state = MHD_CONNECTION_CLOSED;
1370 continue;
1371 }
1372 break;
1373 case MHD_CONNECTION_CLOSED:
1374 if (connection->socket_fd != -1)
1375 connection_close_error (connection);
1376 return MHD_NO;
1377 default:
1378 /* shrink read buffer to how much is actually used */
1379 MHD_pool_reallocate (connection->pool,
1380 connection->read_buffer,
1381 connection->read_buffer_size + 1,
1382 connection->read_buffer_offset);
1383 break;
1384 }
1385 break;
1386 }
1387 return MHD_YES;
1388}
1389
1390/**
1391 * Try writing data to the socket from the
1392 * write buffer of the connection.
1393 *
1394 * @return MHD_YES if something changed,
1395 * MHD_NO if we were interrupted
1396 */
1397static int
1398do_write(struct MHD_Connection * connection)
1399{
1400 int ret;
1401
1402 ret = SEND (connection->socket_fd,
1403 &connection->write_buffer[connection->
1404 write_buffer_send_offset],
1405 connection->write_buffer_append_offset -
1406 connection->write_buffer_send_offset, MSG_NOSIGNAL);
1407 if (ret < 0)
1408 {
1409 if (errno == EINTR)
1410 return MHD_NO;
1411#if HAVE_MESSAGES
1412 MHD_DLOG (connection->daemon,
1413 "Failed to send data: %s\n", STRERROR (errno));
1414#endif
1415 connection_close_error (connection);
1416 return MHD_YES;
1180 } 1417 }
1181 strcpy (&data[off], date); 1418#if DEBUG_SEND_DATA
1182 off += strlen (date); 1419 fprintf (stderr,
1183 sprintf (&data[off], "\r\n"); 1420 "Sent HEADER response: `%.*s'\n",
1184 off += 2; 1421 ret,
1185 if (off != size) 1422 &connection->write_buffer[connection->
1186 abort (); 1423 write_buffer_send_offset]);
1187 connection->write_buffer = data; 1424#endif
1188 connection->write_buffer_append_offset = size; 1425 connection->write_buffer_send_offset += ret;
1426 return MHD_YES;
1427}
1428
1429/**
1430 * Check if we are done sending the write-buffer.
1431 * If so, transition into "next_state".
1432 * @return MHY_NO if we are not done, MHD_YES if we are
1433 */
1434static int
1435check_write_done(struct MHD_Connection * connection,
1436 enum MHD_CONNECTION_STATE next_state)
1437{
1438 if (connection->write_buffer_append_offset !=
1439 connection->write_buffer_send_offset)
1440 return MHD_NO;
1441 connection->write_buffer_append_offset = 0;
1189 connection->write_buffer_send_offset = 0; 1442 connection->write_buffer_send_offset = 0;
1190 connection->write_buffer_size = size + 1; 1443 connection->state = next_state;
1444 MHD_pool_reallocate (connection->pool,
1445 connection->write_buffer,
1446 connection->write_buffer_size, 0);
1447 connection->write_buffer = NULL;
1448 connection->write_buffer_size = 0;
1191 return MHD_YES; 1449 return MHD_YES;
1192} 1450}
1193 1451
@@ -1196,207 +1454,414 @@ MHD_build_header_response (struct MHD_Connection *connection)
1196 * been determined that the socket can be written to. All 1454 * been determined that the socket can be written to. All
1197 * implementations (multithreaded, external select, internal select) 1455 * implementations (multithreaded, external select, internal select)
1198 * call this function 1456 * call this function
1457 *
1458 * @return MHD_YES if we should continue to process the
1459 * connection (not dead yet), MHD_NO if it died
1199 */ 1460 */
1200int 1461int
1201MHD_connection_handle_write (struct MHD_Connection *connection) 1462MHD_connection_handle_write (struct MHD_Connection *connection)
1202{ 1463{
1203 struct MHD_Response *response; 1464 struct MHD_Response *response;
1204 int ret; 1465 int ret;
1205 const char *end;
1206 1466
1207 if (MHD_need_100_continue (connection)) 1467 connection->last_activity = time(NULL);
1208 { 1468 while (1) {
1209 ret = SEND (connection->socket_fd, 1469#if DEBUG_STATES
1210 &HTTP_100_CONTINUE[connection-> 1470 fprintf(stderr,
1211 continue_message_write_offset], 1471 "`%s' in state %u\n",
1212 strlen (HTTP_100_CONTINUE) - 1472 __FUNCTION__,
1213 connection->continue_message_write_offset, MSG_NOSIGNAL); 1473 connection->state);
1214 if (ret < 0) 1474#endif
1215 { 1475 switch (connection->state)
1216 if (errno == EINTR) 1476 {
1217 return MHD_YES; 1477 case MHD_CONNECTION_INIT:
1478 case MHD_CONNECTION_URL_RECEIVED:
1479 case MHD_CONNECTION_HEADER_PART_RECEIVED:
1480 case MHD_CONNECTION_HEADERS_RECEIVED:
1481 EXTRA_CHECK(0);
1482 break;
1483 case MHD_CONNECTION_HEADERS_PROCESSED:
1484 break;
1485 case MHD_CONNECTION_CONTINUE_SENDING:
1486 ret = SEND (connection->socket_fd,
1487 &HTTP_100_CONTINUE[connection->
1488 continue_message_write_offset],
1489 strlen (HTTP_100_CONTINUE) -
1490 connection->continue_message_write_offset, MSG_NOSIGNAL);
1491 if (ret < 0)
1492 {
1493 if (errno == EINTR)
1494 break;
1218#if HAVE_MESSAGES 1495#if HAVE_MESSAGES
1219 MHD_DLOG (connection->daemon, 1496 MHD_DLOG (connection->daemon,
1220 "Failed to send data: %s\n", STRERROR (errno)); 1497 "Failed to send data: %s\n", STRERROR (errno));
1221#endif 1498#endif
1222 connection_close_error (connection); 1499 connection_close_error (connection);
1223 return MHD_YES; 1500 return MHD_NO;
1224 } 1501 }
1225#if DEBUG_SEND_DATA 1502#if DEBUG_SEND_DATA
1226 fprintf (stderr, 1503 fprintf (stderr,
1227 "Sent 100 continue response: `%.*s'\n", 1504 "Sent 100 continue response: `%.*s'\n",
1228 ret, 1505 ret,
1229 &HTTP_100_CONTINUE[connection->continue_message_write_offset]); 1506 &HTTP_100_CONTINUE[connection->continue_message_write_offset]);
1230#endif 1507#endif
1231 connection->continue_message_write_offset += ret; 1508 connection->continue_message_write_offset += ret;
1232 return MHD_YES; 1509 break;
1233 } 1510 case MHD_CONNECTION_CONTINUE_SENT:
1234 response = connection->response; 1511 case MHD_CONNECTION_BODY_RECEIVED:
1235 if (response == NULL) 1512 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
1236 { 1513 case MHD_CONNECTION_FOOTERS_RECEIVED:
1237#if HAVE_MESSAGES 1514 EXTRA_CHECK(0);
1238 MHD_DLOG (connection->daemon, "Unexpected call to %s.\n", __FUNCTION__); 1515 break;
1239#endif 1516 case MHD_CONNECTION_HEADERS_SENDING:
1240 return MHD_NO; 1517 do_write(connection);
1241 } 1518 check_write_done(connection,
1242 if (MHD_NO == connection->have_sent_headers) 1519 MHD_CONNECTION_HEADERS_SENT);
1243 { 1520 break;
1244 if ((connection->write_buffer == NULL) && 1521 case MHD_CONNECTION_HEADERS_SENT:
1245 (MHD_NO == MHD_build_header_response (connection))) 1522 EXTRA_CHECK(0);
1246 { 1523 break;
1247 /* oops - close! */ 1524 case MHD_CONNECTION_NORMAL_BODY_READY:
1525 response = connection->response;
1526 if (response->crc != NULL)
1527 pthread_mutex_lock (&response->mutex);
1528 if (MHD_YES != try_ready_normal_body(connection))
1529 {
1530 if (response->crc != NULL)
1531 pthread_mutex_unlock (&response->mutex);
1532 connection->state = MHD_CONNECTION_NORMAL_BODY_UNREADY;
1533 break;
1534 }
1535 ret = SEND (connection->socket_fd,
1536 &response->data[connection->response_write_position -
1537 response->data_start],
1538 response->data_size - (connection->response_write_position -
1539 response->data_start), MSG_NOSIGNAL);
1540#if DEBUG_SEND_DATA
1541 if (ret > 0)
1542 fprintf (stderr,
1543 "Sent DATA response: `%.*s'\n",
1544 ret,
1545 &response->data[connection->response_write_position -
1546 response->data_start]);
1547#endif
1548 if (response->crc != NULL)
1549 pthread_mutex_unlock (&response->mutex);
1550 if (ret < 0)
1551 {
1552 if (errno == EINTR)
1553 return MHD_YES;
1248#if HAVE_MESSAGES 1554#if HAVE_MESSAGES
1249 MHD_DLOG (connection->daemon, 1555 MHD_DLOG (connection->daemon,
1250 "Closing connection (failed to create response header)\n"); 1556 "Failed to send data: %s\n", STRERROR (errno));
1251#endif 1557#endif
1252 connection_close_error (connection); 1558 connection_close_error (connection);
1253 return MHD_NO; 1559 return MHD_NO;
1254 } 1560 }
1255 ret = SEND (connection->socket_fd, 1561 connection->response_write_position += ret;
1256 &connection->write_buffer[connection-> 1562 if (connection->response_write_position == connection->response->total_size)
1257 write_buffer_send_offset], 1563 connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers... */
1258 connection->write_buffer_append_offset - 1564 break;
1259 connection->write_buffer_send_offset, MSG_NOSIGNAL); 1565 case MHD_CONNECTION_NORMAL_BODY_UNREADY:
1260 if (ret < 0) 1566 EXTRA_CHECK(0);
1261 { 1567 break;
1262 if (errno == EINTR) 1568 case MHD_CONNECTION_CHUNKED_BODY_READY:
1263 return MHD_YES; 1569 do_write(connection);
1570 check_write_done(connection,
1571 (connection->response->total_size == connection->response_write_position)
1572 ? MHD_CONNECTION_BODY_SENT
1573 : MHD_CONNECTION_CHUNKED_BODY_UNREADY);
1574 break;
1575 case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
1576 case MHD_CONNECTION_BODY_SENT:
1577 EXTRA_CHECK(0);
1578 break;
1579 case MHD_CONNECTION_FOOTERS_SENDING:
1580 do_write(connection);
1581 check_write_done(connection,
1582 MHD_CONNECTION_FOOTERS_SENT);
1583 break;
1584 case MHD_CONNECTION_FOOTERS_SENT:
1585 EXTRA_CHECK(0);
1586 break;
1587 case MHD_CONNECTION_CLOSED:
1588 if (connection->socket_fd != -1)
1589 connection_close_error(connection);
1590 return MHD_NO;
1591 }
1592 break;
1593 }
1594 return MHD_YES;
1595}
1596
1597/**
1598 * This function was created to handle per-connection processing that
1599 * has to happen even if the socket cannot be read or written to. All
1600 * implementations (multithreaded, external select, internal select)
1601 * call this function.
1602 *
1603 * @return MHD_YES if we should continue to process the
1604 * connection (not dead yet), MHD_NO if it died
1605 */
1606int
1607MHD_connection_handle_idle (struct MHD_Connection *connection)
1608{
1609 unsigned int timeout;
1610 const char * end;
1611 char * line;
1612
1613 while (1) {
1614#if DEBUG_STATES
1615 fprintf(stderr,
1616 "`%s' in state %u\n",
1617 __FUNCTION__,
1618 connection->state);
1619#endif
1620 switch (connection->state)
1621 {
1622 case MHD_CONNECTION_INIT:
1623 line = get_next_header_line(connection);
1624 if (line == NULL)
1625 break;
1626 if (MHD_NO == parse_initial_message_line (connection, line))
1627 connection->state = MHD_CONNECTION_CLOSED;
1628 else
1629 connection->state = MHD_CONNECTION_URL_RECEIVED;
1630 continue;
1631 case MHD_CONNECTION_URL_RECEIVED:
1632 line = get_next_header_line(connection);
1633 if (line == NULL)
1634 break;
1635 if (strlen(line) == 0)
1636 {
1637 connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
1638 continue;
1639 }
1640 process_header_line(connection, line);
1641 connection->state = MHD_CONNECTION_HEADER_PART_RECEIVED;
1642 continue;
1643 case MHD_CONNECTION_HEADER_PART_RECEIVED:
1644 line = get_next_header_line(connection);
1645 if (line == NULL)
1646 break;
1647 process_broken_line(connection,
1648 line,
1649 MHD_HEADER_KIND);
1650 if (strlen(line) == 0)
1651 {
1652 connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
1653 continue;
1654 }
1655 continue;
1656 case MHD_CONNECTION_HEADERS_RECEIVED:
1657 parse_connection_headers (connection);
1658 if (connection->state == MHD_CONNECTION_CLOSED)
1659 continue;
1660 connection->state = MHD_CONNECTION_HEADERS_PROCESSED;
1661 continue;
1662 case MHD_CONNECTION_HEADERS_PROCESSED:
1663 call_connection_handler (connection); /* first call */
1664 if (need_100_continue(connection))
1665 {
1666 connection->state = MHD_CONNECTION_CONTINUE_SENDING;
1667 break;
1668 }
1669 connection->state = (connection->remaining_upload_size == 0)
1670 ? MHD_CONNECTION_FOOTERS_RECEIVED
1671 : MHD_CONNECTION_CONTINUE_SENT;
1672 continue;
1673 case MHD_CONNECTION_CONTINUE_SENDING:
1674 if (connection->continue_message_write_offset ==
1675 strlen (HTTP_100_CONTINUE))
1676 {
1677 connection->state = MHD_CONNECTION_CONTINUE_SENT;
1678 continue;
1679 }
1680 break;
1681 case MHD_CONNECTION_CONTINUE_SENT:
1682 if (connection->read_buffer_offset != 0) {
1683 call_connection_handler(connection); /* loop call */
1684 if (connection->state == MHD_CONNECTION_CLOSED)
1685 continue;
1686 }
1687 if ( (connection->remaining_upload_size == 0) ||
1688 ( (connection->remaining_upload_size == -1) &&
1689 (connection->read_buffer_offset == 0) &&
1690 (MHD_YES == connection->read_closed) ) )
1691 {
1692 if ( (MHD_YES == connection->have_chunked_upload) &&
1693 (MHD_NO == connection->read_closed) )
1694 connection->state = MHD_CONNECTION_BODY_RECEIVED;
1695 else
1696 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1697 continue;
1698 }
1699 break;
1700 case MHD_CONNECTION_BODY_RECEIVED:
1701 line = get_next_header_line(connection);
1702 if (line == NULL)
1703 break;
1704 if (strlen(line) == 0)
1705 {
1706 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1707 continue;
1708 }
1709 process_header_line(connection, line);
1710 connection->state = MHD_CONNECTION_FOOTER_PART_RECEIVED;
1711 continue;
1712 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
1713 line = get_next_header_line(connection);
1714 if (line == NULL)
1715 break;
1716 process_broken_line(connection,
1717 line,
1718 MHD_FOOTER_KIND);
1719 if (strlen(line) == 0)
1720 {
1721 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1722 continue;
1723 }
1724 continue;
1725 case MHD_CONNECTION_FOOTERS_RECEIVED:
1726 call_connection_handler (connection); /* "final" call */
1727 if (connection->state == MHD_CONNECTION_CLOSED)
1728 continue;
1729 if (connection->response == NULL)
1730 break; /* try again next time */
1731 if (MHD_NO == build_header_response (connection))
1732 {
1733 /* oops - close! */
1264#if HAVE_MESSAGES 1734#if HAVE_MESSAGES
1265 MHD_DLOG (connection->daemon, 1735 MHD_DLOG (connection->daemon,
1266 "Failed to send data: %s\n", STRERROR (errno)); 1736 "Closing connection (failed to create response header)\n");
1267#endif 1737#endif
1268 connection_close_error (connection); 1738 connection->state = MHD_CONNECTION_CLOSED;
1269 return MHD_YES; 1739 continue;
1270 } 1740 }
1271#if DEBUG_SEND_DATA 1741 connection->state = MHD_CONNECTION_HEADERS_SENDING;
1272 fprintf (stderr, 1742 break;
1273 "Sent HEADER response: `%.*s'\n", 1743 case MHD_CONNECTION_HEADERS_SENDING:
1274 ret, 1744 /* no default action */
1275 &connection->write_buffer[connection-> 1745 break;
1276 write_buffer_send_offset]); 1746 case MHD_CONNECTION_HEADERS_SENT:
1277#endif 1747 if (connection->have_chunked_upload)
1278 connection->write_buffer_send_offset += ret; 1748 connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY;
1279 if (connection->write_buffer_append_offset == 1749 else
1280 connection->write_buffer_send_offset) 1750 connection->state = MHD_CONNECTION_NORMAL_BODY_UNREADY;
1281 { 1751 continue;
1282 connection->write_buffer_append_offset = 0; 1752 case MHD_CONNECTION_NORMAL_BODY_READY:
1283 connection->write_buffer_send_offset = 0; 1753 /* nothing to do here */
1284 connection->have_sent_headers = MHD_YES; 1754 break;
1285 MHD_pool_reallocate (connection->pool, 1755 case MHD_CONNECTION_NORMAL_BODY_UNREADY:
1286 connection->write_buffer, 1756 if (connection->response->crc != NULL)
1287 connection->write_buffer_size, 0); 1757 pthread_mutex_lock (&connection->response->mutex);
1288 connection->write_buffer = NULL; 1758 if (MHD_YES == try_ready_normal_body(connection))
1289 connection->write_buffer_size = 0; 1759 {
1290 } 1760 if (connection->response->crc != NULL)
1291 return MHD_YES; 1761 pthread_mutex_unlock (&connection->response->mutex);
1292 } 1762 connection->state = MHD_CONNECTION_NORMAL_BODY_READY;
1293 if (response->total_size < connection->response_write_position) 1763 break;
1294 abort (); /* internal error */ 1764 }
1295 if (response->crc != NULL) 1765 if (connection->response->crc != NULL)
1296 pthread_mutex_lock (&response->mutex); 1766 pthread_mutex_unlock (&connection->response->mutex);
1297 1767 /* not ready, no socket action */
1298 /* prepare send buffer */ 1768 break;
1299 if ((response->crc != NULL) && 1769 case MHD_CONNECTION_CHUNKED_BODY_READY:
1300 ((response->data_start > connection->response_write_position) || 1770 /* nothing to do here */
1301 (response->data_start + response->data_size <= 1771 break;
1302 connection->response_write_position)) 1772 case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
1303 && (MHD_YES != ready_response (connection))) 1773 if (connection->response->crc != NULL)
1304 { 1774 pthread_mutex_lock (&connection->response->mutex);
1305 pthread_mutex_unlock (&response->mutex); 1775 if (MHD_YES == try_ready_chunked_body(connection))
1306 return MHD_YES; 1776 {
1307 } 1777 if (connection->response->crc != NULL)
1308 /* transmit */ 1778 pthread_mutex_unlock (&connection->response->mutex);
1309 ret = SEND (connection->socket_fd, 1779 connection->state = MHD_CONNECTION_CHUNKED_BODY_READY;
1310 &response->data[connection->response_write_position - 1780 continue;
1311 response->data_start], 1781 }
1312 response->data_size - (connection->response_write_position - 1782 if (connection->response->crc != NULL)
1313 response->data_start), MSG_NOSIGNAL); 1783 pthread_mutex_unlock (&connection->response->mutex);
1314 if (response->crc != NULL) 1784 break;
1315 pthread_mutex_unlock (&response->mutex); 1785 case MHD_CONNECTION_BODY_SENT:
1316 if (ret < 0) 1786 build_header_response(connection);
1787 if (connection->write_buffer_send_offset == connection->write_buffer_append_offset)
1788 connection->state = MHD_CONNECTION_FOOTERS_SENT;
1789 else
1790 connection->state = MHD_CONNECTION_FOOTERS_SENDING;
1791 continue;
1792 case MHD_CONNECTION_FOOTERS_SENDING:
1793 /* no default action */
1794 break;
1795 case MHD_CONNECTION_FOOTERS_SENT:
1796 MHD_destroy_response (connection->response);
1797 if (connection->daemon->notify_completed != NULL)
1798 connection->daemon->notify_completed (connection->daemon->
1799 notify_completed_cls,
1800 connection,
1801 &connection->client_context,
1802 MHD_REQUEST_TERMINATED_COMPLETED_OK);
1803 end = MHD_lookup_connection_value (connection,
1804 MHD_HEADER_KIND,
1805 MHD_HTTP_HEADER_CONNECTION);
1806 connection->client_context = NULL;
1807 connection->continue_message_write_offset = 0;
1808 connection->responseCode = 0;
1809 connection->response = NULL;
1810 connection->headers_received = NULL;
1811 connection->response_write_position = 0;
1812 connection->have_chunked_upload = MHD_NO;
1813 connection->method = NULL;
1814 connection->url = NULL;
1815 connection->write_buffer = NULL;
1816 connection->write_buffer_size = 0;
1817 connection->write_buffer_send_offset = 0;
1818 connection->write_buffer_append_offset = 0;
1819 if ((end != NULL) && (0 == strcasecmp (end, "close")))
1820 {
1821 connection->read_closed = MHD_YES;
1822 connection->read_buffer_offset = 0;
1823 }
1824 if ( ( (MHD_YES == connection->read_closed) &&
1825 (0 == connection->read_buffer_offset) ) ||
1826 (connection->version == NULL) ||
1827 (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)) )
1828 {
1829 connection->state = MHD_CONNECTION_CLOSED;
1830 MHD_pool_destroy (connection->pool);
1831 connection->pool = NULL;
1832 connection->read_buffer = NULL;
1833 connection->read_buffer_size = 0;
1834 connection->read_buffer_offset = 0;
1835 }
1836 else
1837 {
1838 connection->version = NULL;
1839 connection->state = MHD_CONNECTION_INIT;
1840 connection->read_buffer
1841 = MHD_pool_reset(connection->pool,
1842 connection->read_buffer,
1843 connection->read_buffer_size);
1844 }
1845 continue;
1846 case MHD_CONNECTION_CLOSED:
1847 if (connection->socket_fd != -1)
1848 connection_close_error (connection);
1849 break;
1850 default:
1851 EXTRA_CHECK(0);
1852 break;
1853 }
1854 break;
1855 }
1856 timeout = connection->daemon->connection_timeout;
1857 if ( (timeout != 0) &&
1858 (time(NULL) - timeout > connection->last_activity) )
1317 { 1859 {
1318 if (errno == EINTR)
1319 return MHD_YES;
1320#if HAVE_MESSAGES
1321 MHD_DLOG (connection->daemon,
1322 "Failed to send data: %s\n", STRERROR (errno));
1323#endif
1324 connection_close_error (connection); 1860 connection_close_error (connection);
1325 return MHD_YES; 1861 return MHD_NO;
1326 }
1327#if DEBUG_SEND_DATA
1328 fprintf (stderr,
1329 "Sent DATA response: `%.*s'\n",
1330 ret,
1331 &response->data[connection->response_write_position -
1332 response->data_start]);
1333#endif
1334 connection->response_write_position += ret;
1335 if (connection->response_write_position > response->total_size)
1336 abort (); /* internal error */
1337 if (connection->response_write_position == response->total_size)
1338 {
1339 if ((connection->have_received_body == MHD_NO) ||
1340 (connection->have_received_headers == MHD_NO))
1341 abort (); /* internal error */
1342 MHD_destroy_response (response);
1343 if (connection->daemon->notify_completed != NULL)
1344 connection->daemon->notify_completed (connection->daemon->
1345 notify_completed_cls,
1346 connection,
1347 &connection->client_context,
1348 MHD_REQUEST_TERMINATED_COMPLETED_OK);
1349 end = MHD_lookup_connection_value (connection,
1350 MHD_HEADER_KIND,
1351 MHD_HTTP_HEADER_CONNECTION);
1352 connection->client_context = NULL;
1353 connection->continue_message_write_offset = 0;
1354 connection->responseCode = 0;
1355 connection->response = NULL;
1356 connection->headers_received = NULL;
1357 connection->have_received_headers = MHD_NO;
1358 connection->have_sent_headers = MHD_NO;
1359 connection->have_received_body = MHD_NO;
1360 connection->response_write_position = 0;
1361 connection->have_chunked_upload = MHD_NO;
1362 connection->method = NULL;
1363 connection->url = NULL;
1364 if ((end != NULL) && (0 == strcasecmp (end, "close")))
1365 {
1366 /* other side explicitly requested
1367 that we close the connection after
1368 this request */
1369 connection->read_close = MHD_YES;
1370 }
1371 if ((connection->read_close == MHD_YES) ||
1372 (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
1373 {
1374 /* closed for reading => close for good! */
1375 if (connection->socket_fd != -1)
1376 {
1377#if DEBUG_CLOSE
1378#if HAVE_MESSAGES
1379 MHD_DLOG (connection->daemon,
1380 "Closing connection (http 1.0 or end-of-stream for unknown content length)\n");
1381#endif
1382#endif
1383 SHUTDOWN (connection->socket_fd, SHUT_RDWR);
1384 CLOSE (connection->socket_fd);
1385 }
1386 connection->socket_fd = -1;
1387 }
1388 connection->version = NULL;
1389 connection->read_buffer = NULL;
1390 connection->write_buffer = NULL;
1391 connection->read_buffer_size = 0;
1392 connection->read_buffer_offset = 0;
1393 connection->write_buffer_size = 0;
1394 connection->write_buffer_send_offset = 0;
1395 connection->write_buffer_append_offset = 0;
1396 MHD_pool_destroy (connection->pool);
1397 connection->pool = NULL;
1398 } 1862 }
1399 return MHD_YES; 1863 return MHD_YES;
1864
1400} 1865}
1401 1866
1402/* end of connection.c */ 1867/* end of connection.c */