libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 679f259b952f418a8cf5edec9c071f3fa0e5850e
parent 13cc9afe06a06e9f28a913b156922469f32be122
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Sun, 28 Nov 2021 14:37:44 +0300

If socket error is detected, try to detect the type of error before closing

Diffstat:
Msrc/microhttpd/connection.c | 20+++++++++++++++-----
Msrc/microhttpd/connection.h | 6++++--
Msrc/microhttpd/daemon.c | 17++++++++++-------
3 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c @@ -3683,12 +3683,16 @@ MHD_update_last_activity_ (struct MHD_Connection *connection) /** * This function handles a particular connection when it has been - * determined that there is data to be read off a socket. + * determined that there is data to be read off a socket. All + * implementations (multithreaded, external polling, internal polling) + * call this function to handle reads. * * @param connection connection to handle + * @param socket_error set to true if socket error was detected */ void -MHD_connection_handle_read (struct MHD_Connection *connection) +MHD_connection_handle_read (struct MHD_Connection *connection, + bool socket_error) { ssize_t bytes_read; @@ -3721,10 +3725,15 @@ MHD_connection_handle_read (struct MHD_Connection *connection) [connection->read_buffer_offset], connection->read_buffer_size - connection->read_buffer_offset); - if (bytes_read < 0) + if ((bytes_read < 0) || socket_error) { - if (MHD_ERR_AGAIN_ == bytes_read) + if ((MHD_ERR_AGAIN_ == bytes_read) && ! socket_error) return; /* No new data to process. */ + if ((bytes_read > 0) && connection->sk_nonblck) + { /* Try to detect the socket error */ + int dummy; + bytes_read = connection->recv_cls (connection, &dummy, sizeof (dummy)); + } if (MHD_ERR_CONNRESET_ == bytes_read) { if ( (MHD_CONNECTION_INIT < connection->state) && @@ -3746,7 +3755,8 @@ MHD_connection_handle_read (struct MHD_Connection *connection) MHD_DLOG (connection->daemon, _ ("Connection socket is closed when reading " \ "request due to the error: %s\n"), - str_conn_error_ (bytes_read)); + (bytes_read < 0) ? str_conn_error_ (bytes_read) : + "detected connection closure"); #endif CONNECTION_CLOSE_ERROR (connection, NULL); diff --git a/src/microhttpd/connection.h b/src/microhttpd/connection.h @@ -89,13 +89,15 @@ MHD_set_http_callbacks_ (struct MHD_Connection *connection); /** * This function handles a particular connection when it has been * determined that there is data to be read off a socket. All - * implementations (multithreaded, external select, internal select) + * implementations (multithreaded, external polling, internal polling) * call this function to handle reads. * * @param connection connection to handle + * @param socket_error set to true if socket error was detected */ void -MHD_connection_handle_read (struct MHD_Connection *connection); +MHD_connection_handle_read (struct MHD_Connection *connection, + bool socket_error); /** diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -1213,15 +1213,18 @@ call_handlers (struct MHD_Connection *con, if (con->tls_read_ready) read_ready = true; #endif /* HTTPS_SUPPORT */ + if ( (MHD_EVENT_LOOP_INFO_READ == con->event_loop_info) && + (read_ready || (force_close && con->sk_nonblck)) ) + { + MHD_connection_handle_read (con, force_close); + mhd_assert (! force_close || MHD_CONNECTION_CLOSED == con->state); + ret = MHD_connection_handle_idle (con); + if (force_close) + return ret; + states_info_processed = true; + } if (! force_close) { - if ( (MHD_EVENT_LOOP_INFO_READ == con->event_loop_info) && - read_ready) - { - MHD_connection_handle_read (con); - ret = MHD_connection_handle_idle (con); - states_info_processed = true; - } /* No need to check value of 'ret' here as closed connection * cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */ if ( (MHD_EVENT_LOOP_INFO_WRITE == con->event_loop_info) &&