aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2014-01-01 20:43:44 +0000
committerChristian Grothoff <christian@grothoff.org>2014-01-01 20:43:44 +0000
commite4e05d001ce05928d72aa07f34a3a7581107d842 (patch)
tree1364a8b1c645fe662ef25f2c00f53f35c4c1898c /src
parentcb11cac74d2a5dca1039dd2ab70d42e8fe1d501b (diff)
downloadlibmicrohttpd-e4e05d001ce05928d72aa07f34a3a7581107d842.tar.gz
libmicrohttpd-e4e05d001ce05928d72aa07f34a3a7581107d842.zip
enable use of keep-alive with http 1.0 if explicitly requested by the client
Diffstat (limited to 'src')
-rw-r--r--src/examples/demo.c6
-rw-r--r--src/microhttpd/connection.c256
2 files changed, 174 insertions, 88 deletions
diff --git a/src/examples/demo.c b/src/examples/demo.c
index d22f005b..4a16b656 100644
--- a/src/examples/demo.c
+++ b/src/examples/demo.c
@@ -43,7 +43,7 @@
43 * Number of threads to run in the thread pool. Should (roughly) match 43 * Number of threads to run in the thread pool. Should (roughly) match
44 * the number of cores on your system. 44 * the number of cores on your system.
45 */ 45 */
46#define NUMBER_OF_THREADS 4 46#define NUMBER_OF_THREADS 8
47 47
48/** 48/**
49 * How many bytes of a file do we give to libmagic to determine the mime type? 49 * How many bytes of a file do we give to libmagic to determine the mime type?
@@ -362,9 +362,11 @@ update_directory ()
362 rdc.buf, 362 rdc.buf,
363 MHD_RESPMEM_MUST_FREE); 363 MHD_RESPMEM_MUST_FREE);
364 mark_as_html (response); 364 mark_as_html (response);
365#if FORCE_CLOSE
365 (void) MHD_add_response_header (response, 366 (void) MHD_add_response_header (response,
366 MHD_HTTP_HEADER_CONNECTION, 367 MHD_HTTP_HEADER_CONNECTION,
367 "close"); 368 "close");
369#endif
368 update_cached_response (response); 370 update_cached_response (response);
369} 371}
370 372
@@ -775,7 +777,9 @@ generate_page (void *cls,
775 } 777 }
776 } 778 }
777 if (0 == strcmp (method, MHD_HTTP_METHOD_GET)) 779 if (0 == strcmp (method, MHD_HTTP_METHOD_GET))
780 {
778 return return_directory_response (connection); 781 return return_directory_response (connection);
782 }
779 783
780 /* unexpected request, refuse */ 784 /* unexpected request, refuse */
781 return MHD_queue_response (connection, 785 return MHD_queue_response (connection,
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index aec86880..7709a92d 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -484,8 +484,56 @@ try_ready_chunked_body (struct MHD_Connection *connection)
484 484
485 485
486/** 486/**
487 * Are we allowed to keep the given connection alive? We can use the
488 * TCP stream for a second request if the connection is HTTP 1.1 and
489 * the "Connection" header either does not exist or is not set to
490 * "close", or if the connection is HTTP 1.0 and the "Connection"
491 * header is explicitly set to "keep-alive". If no HTTP version is
492 * specified (or if it is not 1.0 or 1.1), we definitively close the
493 * connection. If the "Connection" header is not exactly "close" or
494 * "keep-alive", we proceed to use the default for the respective HTTP
495 * version (which is conservative for HTTP 1.0, but might be a bit
496 * optimistic for HTTP 1.1).
497 *
498 * @param connection the connection to check for keepalive
499 * @return #MHD_YES if (based on the request), a keepalive is
500 * legal
501 */
502static int
503keepalive_possible (struct MHD_Connection *connection)
504{
505 const char *end;
506
507 if (NULL == connection->version)
508 return MHD_NO;
509 end = MHD_lookup_connection_value (connection,
510 MHD_HEADER_KIND,
511 MHD_HTTP_HEADER_CONNECTION);
512 if (0 == strcasecmp (connection->version,
513 MHD_HTTP_VERSION_1_1))
514 {
515 if (NULL == end)
516 return MHD_YES;
517 if (0 == strcasecmp (end, "close"))
518 return MHD_NO;
519 return MHD_YES;
520 }
521 if (0 == strcasecmp (connection->version,
522 MHD_HTTP_VERSION_1_0))
523 {
524 if (NULL == end)
525 return MHD_NO;
526 if (0 == strcasecmp (end, "Keep-Alive"))
527 return MHD_YES;
528 return MHD_NO;
529 }
530 return MHD_NO;
531}
532
533
534/**
487 * Check if we need to set some additional headers 535 * Check if we need to set some additional headers
488 * for http-compiliance. 536 * for HTTP-compiliance.
489 * 537 *
490 * @param connection connection to check (and possibly modify) 538 * @param connection connection to check (and possibly modify)
491 */ 539 */
@@ -493,6 +541,7 @@ static void
493add_extra_headers (struct MHD_Connection *connection) 541add_extra_headers (struct MHD_Connection *connection)
494{ 542{
495 const char *have_close; 543 const char *have_close;
544 const char *have_keepalive;
496 const char *client_close; 545 const char *client_close;
497 const char *have_encoding; 546 const char *have_encoding;
498 char buf[128]; 547 char buf[128];
@@ -502,12 +551,18 @@ add_extra_headers (struct MHD_Connection *connection)
502 MHD_HEADER_KIND, 551 MHD_HEADER_KIND,
503 MHD_HTTP_HEADER_CONNECTION); 552 MHD_HTTP_HEADER_CONNECTION);
504 /* we only care about 'close', everything else is ignored */ 553 /* we only care about 'close', everything else is ignored */
505 if ( (NULL != client_close) && (0 != strcasecmp (client_close, "close")) ) 554 if ( (NULL != client_close) &&
555 (0 != strcasecmp (client_close, "close")) )
506 client_close = NULL; 556 client_close = NULL;
507 have_close = MHD_get_response_header (connection->response, 557 have_close = MHD_get_response_header (connection->response,
508 MHD_HTTP_HEADER_CONNECTION); 558 MHD_HTTP_HEADER_CONNECTION);
509 if ( (NULL != have_close) && (0 != strcasecmp (have_close, "close")) ) 559 have_keepalive = have_close;
560 if ( (NULL != have_close) &&
561 (0 != strcasecmp (have_close, "close")) )
510 have_close = NULL; 562 have_close = NULL;
563 if ( (NULL != have_keepalive) &&
564 (0 != strcasecmp (have_keepalive, "keep-alive")) )
565 have_keepalive = NULL;
511 connection->have_chunked_upload = MHD_NO; 566 connection->have_chunked_upload = MHD_NO;
512 add_close = MHD_NO; 567 add_close = MHD_NO;
513 if (MHD_SIZE_UNKNOWN == connection->response->total_size) 568 if (MHD_SIZE_UNKNOWN == connection->response->total_size)
@@ -518,9 +573,10 @@ add_extra_headers (struct MHD_Connection *connection)
518 { 573 {
519 /* 'close' header doesn't exist yet, see if we need to add one; 574 /* 'close' header doesn't exist yet, see if we need to add one;
520 if the client asked for a close, no need to start chunk'ing */ 575 if the client asked for a close, no need to start chunk'ing */
521 if ((NULL == client_close) && 576 if ( (NULL == client_close) &&
522 (NULL != connection->version) && 577 (MHD_YES == keepalive_possible (connection)) &&
523 (0 == strcasecmp (connection->version, MHD_HTTP_VERSION_1_1))) 578 (0 == strcasecmp (connection->version,
579 MHD_HTTP_VERSION_1_1)) )
524 { 580 {
525 connection->have_chunked_upload = MHD_YES; 581 connection->have_chunked_upload = MHD_YES;
526 have_encoding = MHD_get_response_header (connection->response, 582 have_encoding = MHD_get_response_header (connection->response,
@@ -578,7 +634,15 @@ add_extra_headers (struct MHD_Connection *connection)
578 } 634 }
579 if (MHD_YES == add_close) 635 if (MHD_YES == add_close)
580 MHD_add_response_header (connection->response, 636 MHD_add_response_header (connection->response,
581 MHD_HTTP_HEADER_CONNECTION, "close"); 637 MHD_HTTP_HEADER_CONNECTION,
638 "close");
639 if ( (NULL == have_keepalive) &&
640 (NULL == have_close) &&
641 (MHD_NO == add_close) &&
642 (MHD_YES == keepalive_possible (connection)) )
643 MHD_add_response_header (connection->response,
644 MHD_HTTP_HEADER_CONNECTION,
645 "Keep-Alive");
582} 646}
583 647
584 648
@@ -669,6 +733,7 @@ build_header_response (struct MHD_Connection *connection)
669 const char *reason_phrase; 733 const char *reason_phrase;
670 uint32_t rc; 734 uint32_t rc;
671 int must_add_close; 735 int must_add_close;
736 const char *end;
672 737
673 EXTRA_CHECK (NULL != connection->version); 738 EXTRA_CHECK (NULL != connection->version);
674 if (0 == strlen (connection->version)) 739 if (0 == strlen (connection->version))
@@ -709,16 +774,17 @@ build_header_response (struct MHD_Connection *connection)
709 } 774 }
710 else 775 else
711 { 776 {
777 /* 2 bytes for final CRLF of a Chunked-Body */
712 size = 2; 778 size = 2;
713 kind = MHD_FOOTER_KIND; 779 kind = MHD_FOOTER_KIND;
714 off = 0; 780 off = 0;
715 } 781 }
782 end = MHD_get_response_header (connection->response,
783 MHD_HTTP_HEADER_CONNECTION);
716 must_add_close = ( (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state) && 784 must_add_close = ( (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state) &&
717 (MHD_YES == connection->read_closed) && 785 (MHD_YES == connection->read_closed) &&
718 (0 == strcasecmp (connection->version, 786 (MHD_YES == keepalive_possible (connection)) &&
719 MHD_HTTP_VERSION_1_1)) && 787 (NULL == end) );
720 (NULL == MHD_get_response_header (connection->response,
721 MHD_HTTP_HEADER_CONNECTION)) );
722 if (must_add_close) 788 if (must_add_close)
723 size += strlen ("Connection: close\r\n"); 789 size += strlen ("Connection: close\r\n");
724 for (pos = connection->response->first_header; NULL != pos; pos = pos->next) 790 for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
@@ -729,7 +795,8 @@ build_header_response (struct MHD_Connection *connection)
729 if (NULL == data) 795 if (NULL == data)
730 { 796 {
731#if HAVE_MESSAGES 797#if HAVE_MESSAGES
732 MHD_DLOG (connection->daemon, "Not enough memory for write!\n"); 798 MHD_DLOG (connection->daemon,
799 "Not enough memory for write!\n");
733#endif 800#endif
734 return MHD_NO; 801 return MHD_NO;
735 } 802 }
@@ -834,8 +901,10 @@ MHD_connection_update_event_loop_info (struct MHD_Connection *connection)
834 while (1) 901 while (1)
835 { 902 {
836#if DEBUG_STATES 903#if DEBUG_STATES
837 MHD_DLOG (connection->daemon, "%s: state: %s\n", 904 MHD_DLOG (connection->daemon,
838 __FUNCTION__, MHD_state_to_string (connection->state)); 905 "%s: state: %s\n",
906 __FUNCTION__,
907 MHD_state_to_string (connection->state));
839#endif 908#endif
840 switch (connection->state) 909 switch (connection->state)
841 { 910 {
@@ -1194,15 +1263,16 @@ parse_cookie_header (struct MHD_Connection *connection)
1194 equals = sce + 1; 1263 equals = sce + 1;
1195 quotes = 0; 1264 quotes = 0;
1196 semicolon = equals; 1265 semicolon = equals;
1197 while ((semicolon[0] != '\0') && 1266 while ( ('\0' != semicolon[0]) &&
1198 ((quotes != 0) || 1267 ( (0 != quotes) ||
1199 ((semicolon[0] != ';') && (semicolon[0] != ',')))) 1268 ( (';' != semicolon[0]) &&
1269 (',' != semicolon[0]) ) ) )
1200 { 1270 {
1201 if (semicolon[0] == '"') 1271 if ('"' == semicolon[0])
1202 quotes = (quotes + 1) & 1; 1272 quotes = (quotes + 1) & 1;
1203 semicolon++; 1273 semicolon++;
1204 } 1274 }
1205 if (semicolon[0] == '\0') 1275 if ('\0' == semicolon[0])
1206 semicolon = NULL; 1276 semicolon = NULL;
1207 if (NULL != semicolon) 1277 if (NULL != semicolon)
1208 { 1278 {
@@ -1210,7 +1280,8 @@ parse_cookie_header (struct MHD_Connection *connection)
1210 semicolon++; 1280 semicolon++;
1211 } 1281 }
1212 /* remove quotes */ 1282 /* remove quotes */
1213 if ((equals[0] == '"') && (equals[strlen (equals) - 1] == '"')) 1283 if ( ('"' == equals[0]) &&
1284 ('"' == equals[strlen (equals) - 1]) )
1214 { 1285 {
1215 equals[strlen (equals) - 1] = '\0'; 1286 equals[strlen (equals) - 1] = '\0';
1216 equals++; 1287 equals++;
@@ -1232,7 +1303,8 @@ parse_cookie_header (struct MHD_Connection *connection)
1232 * @return #MHD_YES if the line is ok, #MHD_NO if it is malformed 1303 * @return #MHD_YES if the line is ok, #MHD_NO if it is malformed
1233 */ 1304 */
1234static int 1305static int
1235parse_initial_message_line (struct MHD_Connection *connection, char *line) 1306parse_initial_message_line (struct MHD_Connection *connection,
1307 char *line)
1236{ 1308{
1237 char *uri; 1309 char *uri;
1238 char *http_version; 1310 char *http_version;
@@ -1243,7 +1315,7 @@ parse_initial_message_line (struct MHD_Connection *connection, char *line)
1243 uri[0] = '\0'; 1315 uri[0] = '\0';
1244 connection->method = line; 1316 connection->method = line;
1245 uri++; 1317 uri++;
1246 while (uri[0] == ' ') 1318 while (' ' == uri[0])
1247 uri++; 1319 uri++;
1248 http_version = strchr (uri, ' '); 1320 http_version = strchr (uri, ' ');
1249 if (NULL != http_version) 1321 if (NULL != http_version)
@@ -1292,9 +1364,9 @@ call_connection_handler (struct MHD_Connection *connection)
1292 processed = 0; 1364 processed = 0;
1293 connection->client_aware = MHD_YES; 1365 connection->client_aware = MHD_YES;
1294 if (MHD_NO == 1366 if (MHD_NO ==
1295 connection->daemon->default_handler (connection->daemon-> 1367 connection->daemon->default_handler (connection->daemon-> default_handler_cls,
1296 default_handler_cls, 1368 connection,
1297 connection, connection->url, 1369 connection->url,
1298 connection->method, 1370 connection->method,
1299 connection->version, 1371 connection->version,
1300 NULL, &processed, 1372 NULL, &processed,
@@ -1336,12 +1408,12 @@ process_request_body (struct MHD_Connection *connection)
1336 do 1408 do
1337 { 1409 {
1338 instant_retry = MHD_NO; 1410 instant_retry = MHD_NO;
1339 if ((connection->have_chunked_upload == MHD_YES) && 1411 if ( (MHD_YES == connection->have_chunked_upload) &&
1340 (connection->remaining_upload_size == MHD_SIZE_UNKNOWN)) 1412 (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
1341 { 1413 {
1342 if ((connection->current_chunk_offset == 1414 if ( (connection->current_chunk_offset == connection->current_chunk_size) &&
1343 connection->current_chunk_size) 1415 (0 != connection->current_chunk_offset) &&
1344 && (connection->current_chunk_offset != 0) && (available >= 2)) 1416 (available >= 2) )
1345 { 1417 {
1346 /* skip new line at the *end* of a chunk */ 1418 /* skip new line at the *end* of a chunk */
1347 i = 0; 1419 i = 0;
@@ -1448,12 +1520,13 @@ process_request_body (struct MHD_Connection *connection)
1448 used = processed; 1520 used = processed;
1449 connection->client_aware = MHD_YES; 1521 connection->client_aware = MHD_YES;
1450 if (MHD_NO == 1522 if (MHD_NO ==
1451 connection->daemon->default_handler (connection->daemon-> 1523 connection->daemon->default_handler (connection->daemon->default_handler_cls,
1452 default_handler_cls, 1524 connection,
1453 connection, connection->url, 1525 connection->url,
1454 connection->method, 1526 connection->method,
1455 connection->version, 1527 connection->version,
1456 buffer_head, &processed, 1528 buffer_head,
1529 &processed,
1457 &connection->client_context)) 1530 &connection->client_context))
1458 { 1531 {
1459 /* serious internal error, close connection */ 1532 /* serious internal error, close connection */
@@ -1510,7 +1583,7 @@ do_read (struct MHD_Connection *connection)
1510 connection->read_buffer_offset); 1583 connection->read_buffer_offset);
1511 if (bytes_read < 0) 1584 if (bytes_read < 0)
1512 { 1585 {
1513 if ((EINTR == errno) || (EAGAIN == errno)) 1586 if ((EINTR == errno) || (EAGAIN == errno) || (ECONNRESET == errno))
1514 return MHD_NO; 1587 return MHD_NO;
1515#if HAVE_MESSAGES 1588#if HAVE_MESSAGES
1516#if HTTPS_SUPPORT 1589#if HTTPS_SUPPORT
@@ -1521,7 +1594,8 @@ do_read (struct MHD_Connection *connection)
1521 else 1594 else
1522#endif 1595#endif
1523 MHD_DLOG (connection->daemon, 1596 MHD_DLOG (connection->daemon,
1524 "Failed to receive data: %s\n", STRERROR (errno)); 1597 "Failed to receive data: %s\n",
1598 STRERROR (errno));
1525#endif 1599#endif
1526 CONNECTION_CLOSE_ERROR (connection, NULL); 1600 CONNECTION_CLOSE_ERROR (connection, NULL);
1527 return MHD_YES; 1601 return MHD_YES;
@@ -1539,6 +1613,7 @@ do_read (struct MHD_Connection *connection)
1539 return MHD_YES; 1613 return MHD_YES;
1540} 1614}
1541 1615
1616
1542/** 1617/**
1543 * Try writing data to the socket from the 1618 * Try writing data to the socket from the
1544 * write buffer of the connection. 1619 * write buffer of the connection.
@@ -1750,12 +1825,13 @@ parse_connection_headers (struct MHD_Connection *connection)
1750 char *end; 1825 char *end;
1751 1826
1752 parse_cookie_header (connection); 1827 parse_cookie_header (connection);
1753 if ((0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options)) 1828 if ( (0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options)) &&
1754 && (NULL != connection->version) 1829 (NULL != connection->version) &&
1755 && (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)) 1830 (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)) &&
1756 && (NULL == 1831 (NULL ==
1757 MHD_lookup_connection_value (connection, MHD_HEADER_KIND, 1832 MHD_lookup_connection_value (connection,
1758 MHD_HTTP_HEADER_HOST))) 1833 MHD_HEADER_KIND,
1834 MHD_HTTP_HEADER_HOST)) )
1759 { 1835 {
1760 /* die, http 1.1 request without host and we are pedantic */ 1836 /* die, http 1.1 request without host and we are pedantic */
1761 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; 1837 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
@@ -1765,7 +1841,7 @@ parse_connection_headers (struct MHD_Connection *connection)
1765 "Received `%s' request without `%s' header.\n", 1841 "Received `%s' request without `%s' header.\n",
1766 MHD_HTTP_VERSION_1_1, MHD_HTTP_HEADER_HOST); 1842 MHD_HTTP_VERSION_1_1, MHD_HTTP_HEADER_HOST);
1767#endif 1843#endif
1768 EXTRA_CHECK (connection->response == NULL); 1844 EXTRA_CHECK (NULL == connection->response);
1769 response = 1845 response =
1770 MHD_create_response_from_buffer (strlen (REQUEST_LACKS_HOST), 1846 MHD_create_response_from_buffer (strlen (REQUEST_LACKS_HOST),
1771 REQUEST_LACKS_HOST, 1847 REQUEST_LACKS_HOST,
@@ -1798,8 +1874,9 @@ parse_connection_headers (struct MHD_Connection *connection)
1798 { 1874 {
1799#if HAVE_MESSAGES 1875#if HAVE_MESSAGES
1800 MHD_DLOG (connection->daemon, 1876 MHD_DLOG (connection->daemon,
1801 "Failed to parse `%s' header `%s', closing connection.\n", 1877 "Failed to parse `%s' header `%s', closing connection.\n",
1802 MHD_HTTP_HEADER_CONTENT_LENGTH, clen); 1878 MHD_HTTP_HEADER_CONTENT_LENGTH,
1879 clen);
1803#endif 1880#endif
1804 CONNECTION_CLOSE_ERROR (connection, NULL); 1881 CONNECTION_CLOSE_ERROR (connection, NULL);
1805 return; 1882 return;
@@ -1868,7 +1945,8 @@ MHD_connection_handle_read (struct MHD_Connection *connection)
1868 { 1945 {
1869#if DEBUG_STATES 1946#if DEBUG_STATES
1870 MHD_DLOG (connection->daemon, "%s: state: %s\n", 1947 MHD_DLOG (connection->daemon, "%s: state: %s\n",
1871 __FUNCTION__, MHD_state_to_string (connection->state)); 1948 __FUNCTION__,
1949 MHD_state_to_string (connection->state));
1872#endif 1950#endif
1873 switch (connection->state) 1951 switch (connection->state)
1874 { 1952 {
@@ -1925,7 +2003,8 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1925 { 2003 {
1926#if DEBUG_STATES 2004#if DEBUG_STATES
1927 MHD_DLOG (connection->daemon, "%s: state: %s\n", 2005 MHD_DLOG (connection->daemon, "%s: state: %s\n",
1928 __FUNCTION__, MHD_state_to_string (connection->state)); 2006 __FUNCTION__,
2007 MHD_state_to_string (connection->state));
1929#endif 2008#endif
1930 switch (connection->state) 2009 switch (connection->state)
1931 { 2010 {
@@ -1949,7 +2028,8 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1949 break; 2028 break;
1950#if HAVE_MESSAGES 2029#if HAVE_MESSAGES
1951 MHD_DLOG (connection->daemon, 2030 MHD_DLOG (connection->daemon,
1952 "Failed to send data: %s\n", STRERROR (errno)); 2031 "Failed to send data: %s\n",
2032 STRERROR (errno));
1953#endif 2033#endif
1954 CONNECTION_CLOSE_ERROR (connection, NULL); 2034 CONNECTION_CLOSE_ERROR (connection, NULL);
1955 return MHD_YES; 2035 return MHD_YES;
@@ -1958,8 +2038,7 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1958 FPRINTF (stderr, 2038 FPRINTF (stderr,
1959 "Sent 100 continue response: `%.*s'\n", 2039 "Sent 100 continue response: `%.*s'\n",
1960 ret, 2040 ret,
1961 &HTTP_100_CONTINUE 2041 &HTTP_100_CONTINUE[connection->continue_message_write_offset]);
1962 [connection->continue_message_write_offset]);
1963#endif 2042#endif
1964 connection->continue_message_write_offset += ret; 2043 connection->continue_message_write_offset += ret;
1965 break; 2044 break;
@@ -2007,7 +2086,8 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
2007 return MHD_YES; 2086 return MHD_YES;
2008#if HAVE_MESSAGES 2087#if HAVE_MESSAGES
2009 MHD_DLOG (connection->daemon, 2088 MHD_DLOG (connection->daemon,
2010 "Failed to send data: %s\n", STRERROR (errno)); 2089 "Failed to send data: %s\n",
2090 STRERROR (errno));
2011#endif 2091#endif
2012 CONNECTION_CLOSE_ERROR (connection, NULL); 2092 CONNECTION_CLOSE_ERROR (connection, NULL);
2013 return MHD_YES; 2093 return MHD_YES;
@@ -2015,7 +2095,7 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
2015 connection->response_write_position += ret; 2095 connection->response_write_position += ret;
2016 if (connection->response_write_position == 2096 if (connection->response_write_position ==
2017 connection->response->total_size) 2097 connection->response->total_size)
2018 connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers... */ 2098 connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
2019 break; 2099 break;
2020 case MHD_CONNECTION_NORMAL_BODY_UNREADY: 2100 case MHD_CONNECTION_NORMAL_BODY_UNREADY:
2021 EXTRA_CHECK (0); 2101 EXTRA_CHECK (0);
@@ -2050,7 +2130,8 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
2050 break; 2130 break;
2051 default: 2131 default:
2052 EXTRA_CHECK (0); 2132 EXTRA_CHECK (0);
2053 CONNECTION_CLOSE_ERROR (connection, "Internal error\n"); 2133 CONNECTION_CLOSE_ERROR (connection,
2134 "Internal error\n");
2054 return MHD_YES; 2135 return MHD_YES;
2055 } 2136 }
2056 break; 2137 break;
@@ -2121,15 +2202,16 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2121 struct MHD_Daemon *daemon = connection->daemon; 2202 struct MHD_Daemon *daemon = connection->daemon;
2122 unsigned int timeout; 2203 unsigned int timeout;
2123 const char *end; 2204 const char *end;
2124 int rend;
2125 char *line; 2205 char *line;
2126 2206
2127 connection->in_idle = MHD_YES; 2207 connection->in_idle = MHD_YES;
2128 while (1) 2208 while (1)
2129 { 2209 {
2130#if DEBUG_STATES 2210#if DEBUG_STATES
2131 MHD_DLOG (daemon, "%s: state: %s\n", 2211 MHD_DLOG (daemon,
2132 __FUNCTION__, MHD_state_to_string (connection->state)); 2212 "%s: state: %s\n",
2213 __FUNCTION__,
2214 MHD_state_to_string (connection->state));
2133#endif 2215#endif
2134 switch (connection->state) 2216 switch (connection->state)
2135 { 2217 {
@@ -2241,15 +2323,15 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2241 } 2323 }
2242 break; 2324 break;
2243 case MHD_CONNECTION_CONTINUE_SENT: 2325 case MHD_CONNECTION_CONTINUE_SENT:
2244 if (connection->read_buffer_offset != 0) 2326 if (0 != connection->read_buffer_offset)
2245 { 2327 {
2246 process_request_body (connection); /* loop call */ 2328 process_request_body (connection); /* loop call */
2247 if (MHD_CONNECTION_CLOSED == connection->state) 2329 if (MHD_CONNECTION_CLOSED == connection->state)
2248 continue; 2330 continue;
2249 } 2331 }
2250 if ((connection->remaining_upload_size == 0) || 2332 if ((0 == connection->remaining_upload_size) ||
2251 ((connection->remaining_upload_size == MHD_SIZE_UNKNOWN) && 2333 ((connection->remaining_upload_size == MHD_SIZE_UNKNOWN) &&
2252 (connection->read_buffer_offset == 0) && 2334 (0 == connection->read_buffer_offset) &&
2253 (MHD_YES == connection->read_closed))) 2335 (MHD_YES == connection->read_closed)))
2254 { 2336 {
2255 if ((MHD_YES == connection->have_chunked_upload) && 2337 if ((MHD_YES == connection->have_chunked_upload) &&
@@ -2262,7 +2344,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2262 break; 2344 break;
2263 case MHD_CONNECTION_BODY_RECEIVED: 2345 case MHD_CONNECTION_BODY_RECEIVED:
2264 line = get_next_header_line (connection); 2346 line = get_next_header_line (connection);
2265 if (line == NULL) 2347 if (NULL == line)
2266 { 2348 {
2267 if (connection->state != MHD_CONNECTION_BODY_RECEIVED) 2349 if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
2268 continue; 2350 continue;
@@ -2274,7 +2356,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2274 } 2356 }
2275 break; 2357 break;
2276 } 2358 }
2277 if (strlen (line) == 0) 2359 if (0 == strlen (line))
2278 { 2360 {
2279 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; 2361 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2280 continue; 2362 continue;
@@ -2290,7 +2372,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2290 continue; 2372 continue;
2291 case MHD_CONNECTION_FOOTER_PART_RECEIVED: 2373 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
2292 line = get_next_header_line (connection); 2374 line = get_next_header_line (connection);
2293 if (line == NULL) 2375 if (NULL == line)
2294 { 2376 {
2295 if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED) 2377 if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
2296 continue; 2378 continue;
@@ -2305,7 +2387,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2305 if (MHD_NO == 2387 if (MHD_NO ==
2306 process_broken_line (connection, line, MHD_FOOTER_KIND)) 2388 process_broken_line (connection, line, MHD_FOOTER_KIND))
2307 continue; 2389 continue;
2308 if (strlen (line) == 0) 2390 if (0 == strlen (line))
2309 { 2391 {
2310 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; 2392 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2311 continue; 2393 continue;
@@ -2315,7 +2397,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2315 call_connection_handler (connection); /* "final" call */ 2397 call_connection_handler (connection); /* "final" call */
2316 if (connection->state == MHD_CONNECTION_CLOSED) 2398 if (connection->state == MHD_CONNECTION_CLOSED)
2317 continue; 2399 continue;
2318 if (connection->response == NULL) 2400 if (NULL == connection->response)
2319 break; /* try again next time */ 2401 break; /* try again next time */
2320 if (MHD_NO == build_header_response (connection)) 2402 if (MHD_NO == build_header_response (connection))
2321 { 2403 {
@@ -2412,44 +2494,29 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2412 end = 2494 end =
2413 MHD_get_response_header (connection->response, 2495 MHD_get_response_header (connection->response,
2414 MHD_HTTP_HEADER_CONNECTION); 2496 MHD_HTTP_HEADER_CONNECTION);
2415 rend = ( (MHD_YES == connection->read_closed) ||
2416 ( (end != NULL) && (0 == strcasecmp (end, "close")) ) );
2417 MHD_destroy_response (connection->response); 2497 MHD_destroy_response (connection->response);
2418 connection->response = NULL; 2498 connection->response = NULL;
2419 if (daemon->notify_completed != NULL) 2499 if (NULL != daemon->notify_completed)
2420 daemon->notify_completed (daemon->notify_completed_cls, 2500 daemon->notify_completed (daemon->notify_completed_cls,
2421 connection, 2501 connection,
2422 &connection->client_context, 2502 &connection->client_context,
2423 MHD_REQUEST_TERMINATED_COMPLETED_OK); 2503 MHD_REQUEST_TERMINATED_COMPLETED_OK);
2424 connection->client_aware = MHD_NO;
2425 end = 2504 end =
2426 MHD_lookup_connection_value (connection, MHD_HEADER_KIND, 2505 MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
2427 MHD_HTTP_HEADER_CONNECTION); 2506 MHD_HTTP_HEADER_CONNECTION);
2428 connection->client_context = NULL; 2507 if ( (MHD_YES == connection->read_closed) ||
2429 connection->continue_message_write_offset = 0; 2508 ((NULL != end) && (0 == strcasecmp (end, "close"))) )
2430 connection->responseCode = 0;
2431 connection->headers_received = NULL;
2432 connection->headers_received_tail = NULL;
2433 connection->response_write_position = 0;
2434 connection->have_chunked_upload = MHD_NO;
2435 connection->method = NULL;
2436 connection->url = NULL;
2437 connection->write_buffer = NULL;
2438 connection->write_buffer_size = 0;
2439 connection->write_buffer_send_offset = 0;
2440 connection->write_buffer_append_offset = 0;
2441 if ( (rend) || ((end != NULL) && (0 == strcasecmp (end, "close"))) )
2442 { 2509 {
2443 connection->read_closed = MHD_YES; 2510 connection->read_closed = MHD_YES;
2444 connection->read_buffer_offset = 0; 2511 connection->read_buffer_offset = 0;
2445 } 2512 }
2446 if (((MHD_YES == connection->read_closed) && 2513 if (((MHD_YES == connection->read_closed) &&
2447 (0 == connection->read_buffer_offset)) || 2514 (0 == connection->read_buffer_offset)) ||
2448 (connection->version == NULL) || 2515 (MHD_NO == keepalive_possible (connection)))
2449 (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
2450 { 2516 {
2451 /* http 1.0, version-less requests cannot be pipelined */ 2517 /* have to close for some reason */
2452 MHD_connection_close (connection, MHD_REQUEST_TERMINATED_COMPLETED_OK); 2518 MHD_connection_close (connection,
2519 MHD_REQUEST_TERMINATED_COMPLETED_OK);
2453 MHD_pool_destroy (connection->pool); 2520 MHD_pool_destroy (connection->pool);
2454 connection->pool = NULL; 2521 connection->pool = NULL;
2455 connection->read_buffer = NULL; 2522 connection->read_buffer = NULL;
@@ -2458,6 +2525,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2458 } 2525 }
2459 else 2526 else
2460 { 2527 {
2528 /* can try to keep-alive */
2461 connection->version = NULL; 2529 connection->version = NULL;
2462 connection->state = MHD_CONNECTION_INIT; 2530 connection->state = MHD_CONNECTION_INIT;
2463 connection->read_buffer 2531 connection->read_buffer
@@ -2465,6 +2533,20 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2465 connection->read_buffer, 2533 connection->read_buffer,
2466 connection->read_buffer_size); 2534 connection->read_buffer_size);
2467 } 2535 }
2536 connection->client_aware = MHD_NO;
2537 connection->client_context = NULL;
2538 connection->continue_message_write_offset = 0;
2539 connection->responseCode = 0;
2540 connection->headers_received = NULL;
2541 connection->headers_received_tail = NULL;
2542 connection->response_write_position = 0;
2543 connection->have_chunked_upload = MHD_NO;
2544 connection->method = NULL;
2545 connection->url = NULL;
2546 connection->write_buffer = NULL;
2547 connection->write_buffer_size = 0;
2548 connection->write_buffer_send_offset = 0;
2549 connection->write_buffer_append_offset = 0;
2468 continue; 2550 continue;
2469 case MHD_CONNECTION_CLOSED: 2551 case MHD_CONNECTION_CLOSED:
2470 cleanup_connection (connection); 2552 cleanup_connection (connection);
@@ -2476,7 +2558,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2476 break; 2558 break;
2477 } 2559 }
2478 timeout = connection->connection_timeout; 2560 timeout = connection->connection_timeout;
2479 if ( (timeout != 0) && 2561 if ( (0 != timeout) &&
2480 (timeout <= (MHD_monotonic_time() - connection->last_activity)) ) 2562 (timeout <= (MHD_monotonic_time() - connection->last_activity)) )
2481 { 2563 {
2482 MHD_connection_close (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); 2564 MHD_connection_close (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);