diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-08-30 11:54:56 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-08-30 11:54:56 +0000 |
commit | 6578d480c57c6fef92b5a980d41eabb22192f2cf (patch) | |
tree | a4fae34fa82525abfd65ecaa9d17e4024c3351a2 | |
parent | 02171fdaeb0c1e02f778cd1e595319fd63941b8e (diff) | |
download | libmicrohttpd-6578d480c57c6fef92b5a980d41eabb22192f2cf.tar.gz libmicrohttpd-6578d480c57c6fef92b5a980d41eabb22192f2cf.zip |
towards fixing #3008
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | src/include/microhttpd.h | 12 | ||||
-rw-r--r-- | src/microhttpd/connection.c | 32 | ||||
-rw-r--r-- | src/microhttpd/daemon.c | 36 | ||||
-rw-r--r-- | src/testcurl/test_post.c | 4 |
5 files changed, 69 insertions, 22 deletions
@@ -1,3 +1,10 @@ | |||
1 | Fri 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 | |||
1 | Wed Aug 28 18:40:47 CEST 2013 | 8 | Wed 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 | |||
484 | static size_t | 485 | static size_t |
485 | readBuffer(void *p, size_t size, size_t nmemb, void *opaque) | 486 | readBuffer(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 | |||
500 | static size_t | 502 | static size_t |
501 | slowReadBuffer(void *p, size_t size, size_t nmemb, void *opaque) | 503 | slowReadBuffer(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 | |||
607 | static int | 611 | static int |
608 | testMultithreadedPostCancel() | 612 | testMultithreadedPostCancel() |
609 | { | 613 | { |