aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-08-30 11:54:56 +0000
committerChristian Grothoff <christian@grothoff.org>2013-08-30 11:54:56 +0000
commit6578d480c57c6fef92b5a980d41eabb22192f2cf (patch)
treea4fae34fa82525abfd65ecaa9d17e4024c3351a2
parent02171fdaeb0c1e02f778cd1e595319fd63941b8e (diff)
downloadlibmicrohttpd-6578d480c57c6fef92b5a980d41eabb22192f2cf.tar.gz
libmicrohttpd-6578d480c57c6fef92b5a980d41eabb22192f2cf.zip
towards fixing #3008
-rw-r--r--ChangeLog7
-rw-r--r--src/include/microhttpd.h12
-rw-r--r--src/microhttpd/connection.c32
-rw-r--r--src/microhttpd/daemon.c36
-rw-r--r--src/testcurl/test_post.c4
5 files changed, 69 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog
index 08d5cbcf..3b6aaa0c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
1Fri Aug 30 13:53:04 CEST 2013
2 Started to implement #3008 (RFC 2616, section 8.1.4
3 says HTTP server SHOULD terminate connection if the
4 client closes it for writing via TCP FIN, so we should
5 to continue to try to read and react differently
6 if recv() returns zero). -CG
7
1Wed Aug 28 18:40:47 CEST 2013 8Wed Aug 28 18:40:47 CEST 2013
2 Fix #3007 (build issue if messages are disabled). -CG 9 Fix #3007 (build issue if messages are disabled). -CG
3 10
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index d944bae5..c7620eb0 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -120,7 +120,7 @@ extern "C"
120/** 120/**
121 * Current version of the library. 121 * Current version of the library.
122 */ 122 */
123#define MHD_VERSION 0x00092201 123#define MHD_VERSION 0x00092202
124 124
125/** 125/**
126 * MHD-internal return code for "YES". 126 * MHD-internal return code for "YES".
@@ -882,7 +882,15 @@ enum MHD_RequestTerminationCode
882 * data. 882 * data.
883 * @ingroup request 883 * @ingroup request
884 */ 884 */
885 MHD_REQUEST_TERMINATED_READ_ERROR = 4 885 MHD_REQUEST_TERMINATED_READ_ERROR = 4,
886
887 /**
888 * The client terminated the connection by closing the socket
889 * for writing (TCP half-closed); MHD aborted sending the
890 * response according to RFC 2616, section 8.1.4.
891 * @ingroup request
892 */
893 MHD_REQUEST_TERMINATED_CLIENT_ABORT = 5
886 894
887}; 895};
888 896
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 27bff077..eafcd98a 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -1494,7 +1494,6 @@ do_read (struct MHD_Connection *connection)
1494 1494
1495 if (connection->read_buffer_size == connection->read_buffer_offset) 1495 if (connection->read_buffer_size == connection->read_buffer_offset)
1496 return MHD_NO; 1496 return MHD_NO;
1497
1498 bytes_read = connection->recv_cls (connection, 1497 bytes_read = connection->recv_cls (connection,
1499 &connection->read_buffer 1498 &connection->read_buffer
1500 [connection->read_buffer_offset], 1499 [connection->read_buffer_offset],
@@ -1520,11 +1519,11 @@ do_read (struct MHD_Connection *connection)
1520 } 1519 }
1521 if (0 == bytes_read) 1520 if (0 == bytes_read)
1522 { 1521 {
1523 /* other side closed connection */ 1522 /* other side closed connection; RFC 2616, section 8.1.4 suggests
1523 we should then shutdown ourselves as well. */
1524 connection->read_closed = MHD_YES; 1524 connection->read_closed = MHD_YES;
1525 /* shutdown is not required here, as the other side already 1525 MHD_connection_close (connection,
1526 knows; so flagging this internally should suffice */ 1526 MHD_REQUEST_TERMINATED_CLIENT_ABORT);
1527 /* SHUTDOWN (connection->socket_fd, SHUT_RD); */
1528 return MHD_YES; 1527 return MHD_YES;
1529 } 1528 }
1530 connection->read_buffer_offset += bytes_read; 1529 connection->read_buffer_offset += bytes_read;
@@ -2465,6 +2464,15 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2465 } 2464 }
2466 break; 2465 break;
2467 case MHD_EVENT_LOOP_INFO_WRITE: 2466 case MHD_EVENT_LOOP_INFO_WRITE:
2467 if ( (connection->read_buffer_size > connection->read_buffer_offset) &&
2468 (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
2469 (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
2470 {
2471 EDLL_insert (daemon->eready_head,
2472 daemon->eready_tail,
2473 connection);
2474 connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2475 }
2468 if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) && 2476 if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) &&
2469 (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) ) 2477 (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
2470 { 2478 {
@@ -2498,8 +2506,8 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2498 2506
2499#if EPOLL_SUPPORT 2507#if EPOLL_SUPPORT
2500/** 2508/**
2501 * Perform epoll processing, possibly moving the connection back into 2509 * Perform epoll() processing, possibly moving the connection back into
2502 * the epoll set if needed. 2510 * the epoll() set if needed.
2503 * 2511 *
2504 * @param connection connection to process 2512 * @param connection connection to process
2505 * @return MHD_YES if we should continue to process the 2513 * @return MHD_YES if we should continue to process the
@@ -2514,7 +2522,8 @@ MHD_connection_epoll_update_ (struct MHD_Connection *connection)
2514 (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) && 2522 (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
2515 ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) || 2523 ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ||
2516 ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) && 2524 ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
2517 (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) && 2525 ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) ||
2526 (connection->read_buffer_size > connection->read_buffer_offset) ) &&
2518 (MHD_NO == connection->read_closed) ) ) ) 2527 (MHD_NO == connection->read_closed) ) ) )
2519 { 2528 {
2520 /* add to epoll set */ 2529 /* add to epoll set */
@@ -2694,11 +2703,8 @@ MHD_queue_response (struct MHD_Connection *connection,
2694 (0 == strcasecmp (connection->method, 2703 (0 == strcasecmp (connection->method,
2695 MHD_HTTP_METHOD_PUT))) ) 2704 MHD_HTTP_METHOD_PUT))) )
2696 { 2705 {
2697 /* response was queued "early", 2706 /* response was queued "early", refuse to read body / footers or
2698 refuse to read body / footers or further 2707 further requests! */
2699 requests! */
2700 if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO))
2701 (void) SHUTDOWN (connection->socket_fd, SHUT_RD);
2702 connection->read_closed = MHD_YES; 2708 connection->read_closed = MHD_YES;
2703 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; 2709 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2704 } 2710 }
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 1a47b972..7bbb2533 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -615,9 +615,12 @@ MHD_get_fdset (struct MHD_Daemon *daemon,
615 break; 615 break;
616 case MHD_EVENT_LOOP_INFO_WRITE: 616 case MHD_EVENT_LOOP_INFO_WRITE:
617 add_to_fd_set (pos->socket_fd, write_fd_set, max_fd); 617 add_to_fd_set (pos->socket_fd, write_fd_set, max_fd);
618 if (pos->read_buffer_size > pos->read_buffer_offset)
619 add_to_fd_set (pos->socket_fd, read_fd_set, max_fd);
618 break; 620 break;
619 case MHD_EVENT_LOOP_INFO_BLOCK: 621 case MHD_EVENT_LOOP_INFO_BLOCK:
620 /* not in any FD set */ 622 if (pos->read_buffer_size > pos->read_buffer_offset)
623 add_to_fd_set (pos->socket_fd, read_fd_set, max_fd);
621 break; 624 break;
622 case MHD_EVENT_LOOP_INFO_CLEANUP: 625 case MHD_EVENT_LOOP_INFO_CLEANUP:
623 /* this should never happen */ 626 /* this should never happen */
@@ -693,8 +696,12 @@ MHD_handle_connection (void *data)
693 break; 696 break;
694 case MHD_EVENT_LOOP_INFO_WRITE: 697 case MHD_EVENT_LOOP_INFO_WRITE:
695 add_to_fd_set (con->socket_fd, &ws, &max); 698 add_to_fd_set (con->socket_fd, &ws, &max);
699 if (con->read_buffer_size > con->read_buffer_offset)
700 add_to_fd_set (con->socket_fd, &rs, &max);
696 break; 701 break;
697 case MHD_EVENT_LOOP_INFO_BLOCK: 702 case MHD_EVENT_LOOP_INFO_BLOCK:
703 if (con->read_buffer_size > con->read_buffer_offset)
704 add_to_fd_set (con->socket_fd, &rs, &max);
698 tv.tv_sec = 0; 705 tv.tv_sec = 0;
699 tv.tv_usec = 0; 706 tv.tv_usec = 0;
700 tvp = &tv; 707 tvp = &tv;
@@ -741,8 +748,12 @@ MHD_handle_connection (void *data)
741 break; 748 break;
742 case MHD_EVENT_LOOP_INFO_WRITE: 749 case MHD_EVENT_LOOP_INFO_WRITE:
743 p[0].events |= POLLOUT; 750 p[0].events |= POLLOUT;
751 if (con->read_buffer_size > con->read_buffer_offset)
752 p[0].events |= POLLIN;
744 break; 753 break;
745 case MHD_EVENT_LOOP_INFO_BLOCK: 754 case MHD_EVENT_LOOP_INFO_BLOCK:
755 if (con->read_buffer_size > con->read_buffer_offset)
756 p[0].events |= POLLIN;
746 tv.tv_sec = 0; 757 tv.tv_sec = 0;
747 tv.tv_usec = 0; 758 tv.tv_usec = 0;
748 tvp = &tv; 759 tvp = &tv;
@@ -1774,11 +1785,16 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
1774 pos->read_handler (pos); 1785 pos->read_handler (pos);
1775 break; 1786 break;
1776 case MHD_EVENT_LOOP_INFO_WRITE: 1787 case MHD_EVENT_LOOP_INFO_WRITE:
1788 if ( (FD_ISSET (ds, read_fd_set)) &&
1789 (pos->read_buffer_size > pos->read_buffer_offset) )
1790 pos->read_handler (pos);
1777 if (FD_ISSET (ds, write_fd_set)) 1791 if (FD_ISSET (ds, write_fd_set))
1778 pos->write_handler (pos); 1792 pos->write_handler (pos);
1779 break; 1793 break;
1780 case MHD_EVENT_LOOP_INFO_BLOCK: 1794 case MHD_EVENT_LOOP_INFO_BLOCK:
1781 /* only idle handler */ 1795 if ( (FD_ISSET (ds, read_fd_set)) &&
1796 (pos->read_buffer_size > pos->read_buffer_offset) )
1797 pos->read_handler (pos);
1782 break; 1798 break;
1783 case MHD_EVENT_LOOP_INFO_CLEANUP: 1799 case MHD_EVENT_LOOP_INFO_CLEANUP:
1784 /* should never happen */ 1800 /* should never happen */
@@ -1903,9 +1919,7 @@ MHD_poll_all (struct MHD_Daemon *daemon,
1903 /* count number of connections and thus determine poll set size */ 1919 /* count number of connections and thus determine poll set size */
1904 num_connections = 0; 1920 num_connections = 0;
1905 for (pos = daemon->connections_head; NULL != pos; pos = pos->next) 1921 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
1906 if ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) || 1922 num_connections++;
1907 (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info) )
1908 num_connections++;
1909 { 1923 {
1910 struct pollfd p[2 + num_connections]; 1924 struct pollfd p[2 + num_connections];
1911 MHD_UNSIGNED_LONG_LONG ltimeout; 1925 MHD_UNSIGNED_LONG_LONG ltimeout;
@@ -1953,9 +1967,12 @@ MHD_poll_all (struct MHD_Daemon *daemon,
1953 break; 1967 break;
1954 case MHD_EVENT_LOOP_INFO_WRITE: 1968 case MHD_EVENT_LOOP_INFO_WRITE:
1955 p[poll_server+i].events |= POLLOUT; 1969 p[poll_server+i].events |= POLLOUT;
1970 if (pos->read_buffer_size > pos->read_buffer_offset)
1971 p[poll_server+i].events |= POLLIN;
1956 break; 1972 break;
1957 case MHD_EVENT_LOOP_INFO_BLOCK: 1973 case MHD_EVENT_LOOP_INFO_BLOCK:
1958 /* not in poll */ 1974 if (pos->read_buffer_size > pos->read_buffer_offset)
1975 p[poll_server+i].events |= POLLIN;
1959 break; 1976 break;
1960 case MHD_EVENT_LOOP_INFO_CLEANUP: 1977 case MHD_EVENT_LOOP_INFO_CLEANUP:
1961 /* should never happen */ 1978 /* should never happen */
@@ -2005,12 +2022,16 @@ MHD_poll_all (struct MHD_Daemon *daemon,
2005 if (p[poll_server+i].fd != pos->socket_fd) 2022 if (p[poll_server+i].fd != pos->socket_fd)
2006 break; /* fd mismatch, something else happened, retry later ... */ 2023 break; /* fd mismatch, something else happened, retry later ... */
2007 /* normal handling */ 2024 /* normal handling */
2025 if (0 != (p[poll_server+i].revents & POLLIN))
2026 pos->read_handler (pos);
2008 if (0 != (p[poll_server+i].revents & POLLOUT)) 2027 if (0 != (p[poll_server+i].revents & POLLOUT))
2009 pos->write_handler (pos); 2028 pos->write_handler (pos);
2010 pos->idle_handler (pos); 2029 pos->idle_handler (pos);
2011 i++; 2030 i++;
2012 break; 2031 break;
2013 case MHD_EVENT_LOOP_INFO_BLOCK: 2032 case MHD_EVENT_LOOP_INFO_BLOCK:
2033 if (0 != (p[poll_server+i].revents & POLLIN))
2034 pos->read_handler (pos);
2014 pos->idle_handler (pos); 2035 pos->idle_handler (pos);
2015 break; 2036 break;
2016 case MHD_EVENT_LOOP_INFO_CLEANUP: 2037 case MHD_EVENT_LOOP_INFO_CLEANUP:
@@ -2234,7 +2255,8 @@ MHD_epoll (struct MHD_Daemon *daemon,
2234 if (0 != (events[i].events & EPOLLIN)) 2255 if (0 != (events[i].events & EPOLLIN))
2235 { 2256 {
2236 pos->epoll_state |= MHD_EPOLL_STATE_READ_READY; 2257 pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
2237 if ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) && 2258 if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) ||
2259 (pos->read_buffer_size > pos->read_buffer_offset) ) &&
2238 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) ) 2260 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
2239 { 2261 {
2240 EDLL_insert (daemon->eready_head, 2262 EDLL_insert (daemon->eready_head,
diff --git a/src/testcurl/test_post.c b/src/testcurl/test_post.c
index 31fd16a2..2501a3d9 100644
--- a/src/testcurl/test_post.c
+++ b/src/testcurl/test_post.c
@@ -481,6 +481,7 @@ struct CRBC
481 size_t pos; 481 size_t pos;
482}; 482};
483 483
484
484static size_t 485static size_t
485readBuffer(void *p, size_t size, size_t nmemb, void *opaque) 486readBuffer(void *p, size_t size, size_t nmemb, void *opaque)
486{ 487{
@@ -497,6 +498,7 @@ readBuffer(void *p, size_t size, size_t nmemb, void *opaque)
497 return required/size; 498 return required/size;
498} 499}
499 500
501
500static size_t 502static size_t
501slowReadBuffer(void *p, size_t size, size_t nmemb, void *opaque) 503slowReadBuffer(void *p, size_t size, size_t nmemb, void *opaque)
502{ 504{
@@ -504,6 +506,7 @@ slowReadBuffer(void *p, size_t size, size_t nmemb, void *opaque)
504 return readBuffer(p, size, nmemb, opaque); 506 return readBuffer(p, size, nmemb, opaque);
505} 507}
506 508
509
507#define FLAG_EXPECT_CONTINUE 1 510#define FLAG_EXPECT_CONTINUE 1
508#define FLAG_CHUNKED 2 511#define FLAG_CHUNKED 2
509#define FLAG_FORM_DATA 4 512#define FLAG_FORM_DATA 4
@@ -604,6 +607,7 @@ testMultithreadedPostCancelPart(int flags)
604 return result; 607 return result;
605} 608}
606 609
610
607static int 611static int
608testMultithreadedPostCancel() 612testMultithreadedPostCancel()
609{ 613{