libmicrohttpd

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

commit 2b7fe489663da068f511313fe690ed24b5b56fb4
parent b3a45b40e034a077f2a31b141223580218ee4fdd
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Mon, 27 Feb 2017 22:08:15 +0300

Optimized epoll ready states processing:
Clear read/write ready flag when not full buffer was used by send()/recv()

Diffstat:
Msrc/microhttpd/daemon.c | 89++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 63 insertions(+), 26 deletions(-)

diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -428,9 +428,12 @@ recv_tls_adapter (struct MHD_Connection *connection, { ssize_t res; + if (i > SSIZE_MAX) + i = SSIZE_MAX; + res = gnutls_record_recv (connection->tls_session, other, - (i > SSIZE_MAX) ? SSIZE_MAX : i); + i); if ( (GNUTLS_E_AGAIN == res) || (GNUTLS_E_INTERRUPTED == res) ) { @@ -451,6 +454,12 @@ recv_tls_adapter (struct MHD_Connection *connection, return res; } +#ifdef EPOLL_SUPPORT + /* If data not available to fill whole buffer - socket is not read ready anymore. */ + if (i > (size_t)res) + connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY; +#endif /* EPOLL_SUPPORT */ + /* Check whether TLS buffers still have some unread data. */ connection->tls_read_ready = ( ((size_t)res == i) && (0 != gnutls_record_check_pending (connection->tls_session)) ); @@ -471,11 +480,14 @@ send_tls_adapter (struct MHD_Connection *connection, const void *other, size_t i) { - int res; + ssize_t res; + + if (i > SSIZE_MAX) + i = SSIZE_MAX; res = gnutls_record_send (connection->tls_session, other, - (i > SSIZE_MAX) ? SSIZE_MAX : i); + i); if ( (GNUTLS_E_AGAIN == res) || (GNUTLS_E_INTERRUPTED == res) ) { @@ -495,6 +507,11 @@ send_tls_adapter (struct MHD_Connection *connection, MHD_socket_set_error_ (MHD_SCKT_ECONNRESET_); return -1; } +#ifdef EPOLL_SUPPORT + /* If NOT all available data was sent - socket is not write ready anymore. */ + if (i > (size_t)res) + connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; +#endif /* EPOLL_SUPPORT */ return res; } @@ -1075,10 +1092,10 @@ process_urh (struct MHD_UpgradeResponseHandle *urh) else if (res > 0) { urh->in_buffer_used += res; - if (0 < gnutls_record_check_pending (connection->tls_session)) - { - connection->tls_read_ready = true; - } + if (buf_size > (size_t)res) + urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY; + else if (0 < gnutls_record_check_pending (connection->tls_session)) + connection->tls_read_ready = true; } else if ( (0 >= res ) && (GNUTLS_E_INTERRUPTED != res) ) @@ -1138,6 +1155,8 @@ process_urh (struct MHD_UpgradeResponseHandle *urh) &urh->in_buffer[res], urh->in_buffer_used - res); urh->in_buffer_used -= res; + if (data_size > (size_t)res) + urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY; } else { @@ -1193,6 +1212,8 @@ process_urh (struct MHD_UpgradeResponseHandle *urh) else { urh->out_buffer_used += res; + if (buf_size > (size_t)res) + urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY; } if (0 == res) { @@ -1228,6 +1249,8 @@ process_urh (struct MHD_UpgradeResponseHandle *urh) &urh->out_buffer[res], urh->out_buffer_used - res); urh->out_buffer_used -= res; + if (data_size > (size_t)res) + urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY; } else { @@ -1860,12 +1883,14 @@ recv_param_adapter (struct MHD_Connection *connection, other, i); #ifdef EPOLL_SUPPORT - if ( (0 > ret) && - (MHD_SCKT_ERR_IS_EAGAIN_ (MHD_socket_get_error_ ())) ) + if (0 > ret) { /* Got EAGAIN --- no longer read-ready */ - connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY; + if (MHD_SCKT_ERR_IS_EAGAIN_ (MHD_socket_get_error_ ())) + connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY; } + else if (i > ret) + connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY; #endif return ret; } @@ -1918,24 +1943,34 @@ send_param_adapter (struct MHD_Connection *connection, offsetu64 = connection->response_write_position + connection->response->fd_off; left = connection->response->total_size - connection->response_write_position; ret = 0; - MHD_socket_set_error_to_ENOMEM (); #ifndef HAVE_SENDFILE64 - offset = (off_t) offsetu64; - if ( (offsetu64 <= (uint64_t) OFF_T_MAX) && - (0 < (ret = sendfile (connection->socket_fd, - file_fd, - &offset, - left))) ) + if ((uint64_t)OFF_T_MAX < offsetu64) + MHD_socket_set_error_to_ENOMEM (); + else + { + offset = (off_t) offsetu64; + ret = sendfile (connection->socket_fd, + file_fd, + &offset, + left); + } #else /* HAVE_SENDFILE64 */ - offset = (off64_t) offsetu64; - if ( (offsetu64 <= (uint64_t) OFF64_T_MAX) && - (0 < (ret = sendfile64 (connection->socket_fd, - file_fd, - &offset, - left))) ) + if ((uint64_t)OFF64_T_MAX < offsetu64) + MHD_socket_set_error_to_ENOMEM (); + else + { + offset = (off64_t) offsetu64; + ret = sendfile64 (connection->socket_fd, + file_fd, + &offset, + left); + } #endif /* HAVE_SENDFILE64 */ + if (0 < ret) { /* write successful */ + if (left > ret) + connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; return ret; } err = MHD_socket_get_error_(); @@ -1965,12 +2000,14 @@ send_param_adapter (struct MHD_Connection *connection, i); err = MHD_socket_get_error_(); #ifdef EPOLL_SUPPORT - if ( (0 > ret) && - (MHD_SCKT_ERR_IS_EAGAIN_(err)) ) + if (0 > ret) { /* EAGAIN --- no longer write-ready */ - connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; + if (MHD_SCKT_ERR_IS_EAGAIN_(err)) + connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; } + else if (i > ret) + connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; #endif /* Handle broken kernel / libc, returning -1 but not setting errno; kill connection as that should be safe; reported on mailinglist here: