libmicrohttpd

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

commit 61fa3896442b5629e28d36d4e9e924440e03d873
parent ec591a702237f8a4141d7f85dc0c2923788db45f
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Fri, 16 Apr 2021 17:11:21 +0300

Fixes and improvements for 6c751386a2e06d35b6d072c064bd581ddd561c52

Fixed build on platforms without epoll,
saved one sys-call for externally added connections.

Diffstat:
Msrc/microhttpd/daemon.c | 57+++++++++++++++++++++++++--------------------------------
Msrc/microhttpd/internal.h | 20+++++++++++---------
Msrc/microhttpd/mhd_send.c | 71++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
3 files changed, 84 insertions(+), 64 deletions(-)

diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -2376,7 +2376,7 @@ psk_gnutls_adapter (gnutls_session_t session, * @param non_blck indicate that socket in non-blocking mode * @param sk_spipe_supprs indicate that the @a client_socket has * set SIGPIPE suppression - * @param sk_is_unix true if this is a UNIX domain socket (AF_UNIX) + * @param sk_is_nonip _MHD_YES if this is not a TCP/IP socket * @return pointer to the connection on success, NULL if this daemon could * not handle the connection (i.e. malloc failed, etc). * The socket will be closed in case of error; 'errno' is @@ -2390,7 +2390,7 @@ new_connection_prepare_ (struct MHD_Daemon *daemon, bool external_add, bool non_blck, bool sk_spipe_supprs, - bool sk_is_unix) + enum MHD_tristate sk_is_nonip) { struct MHD_Connection *connection; int eno = 0; @@ -2492,7 +2492,7 @@ new_connection_prepare_ (struct MHD_Daemon *daemon, connection->addr_len = addrlen; connection->socket_fd = client_socket; connection->sk_nonblck = non_blck; - connection->is_unix = sk_is_unix; + connection->is_nonip = sk_is_nonip; connection->sk_spipe_suppress = sk_spipe_supprs; connection->daemon = daemon; connection->last_activity = MHD_monotonic_sec_counter (); @@ -2863,7 +2863,7 @@ cleanup: * @param non_blck indicate that socket in non-blocking mode * @param sk_spipe_supprs indicate that the @a client_socket has * set SIGPIPE suppression - * @param sk_is_unix true if this is a UNIX domain socket (AF_UNIX) + * @param sk_is_nonip _MHD_YES if this is not a TCP/IP socket * @return #MHD_YES on success, #MHD_NO if this daemon could * not handle the connection (i.e. malloc failed, etc). * The socket will be closed in any case; 'errno' is @@ -2877,7 +2877,7 @@ internal_add_connection (struct MHD_Daemon *daemon, bool external_add, bool non_blck, bool sk_spipe_supprs, - bool sk_is_unix) + enum MHD_tristate sk_is_nonip) { struct MHD_Connection *connection; @@ -2923,7 +2923,7 @@ internal_add_connection (struct MHD_Daemon *daemon, external_add, non_blck, sk_spipe_supprs, - sk_is_unix); + sk_is_nonip); if (NULL == connection) return MHD_NO; @@ -3348,7 +3348,6 @@ MHD_add_connection (struct MHD_Daemon *daemon, { bool sk_nonbl; bool sk_spipe_supprs; - bool sk_is_unix = false; /* NOT thread safe with internal thread. TODO: fix thread safety. */ if ((0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) && @@ -3419,20 +3418,6 @@ MHD_add_connection (struct MHD_Daemon *daemon, _ ("Failed to set noninheritable mode on new client socket.\n")); #endif } -#ifdef SO_DOMAIN - { - int af; - socklen_t len = sizeof (af); - - if ( (0 == getsockopt (daemon->listen_fd, - SOL_SOCKET, - SO_DOMAIN, - &af, - &len)) && - (AF_UNIX == af) ) - sk_is_unix = true; - } -#endif #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) if (NULL != daemon->worker_pool) @@ -3453,7 +3438,7 @@ MHD_add_connection (struct MHD_Daemon *daemon, true, sk_nonbl, sk_spipe_supprs, - sk_is_unix); + _MHD_UNKNOWN); } /* all pools are at their connection limit, must refuse */ MHD_socket_close_chk_ (client_socket); @@ -3471,7 +3456,7 @@ MHD_add_connection (struct MHD_Daemon *daemon, true, sk_nonbl, sk_spipe_supprs, - sk_is_unix); + _MHD_UNKNOWN); } @@ -5840,20 +5825,25 @@ parse_options_va (struct MHD_Daemon *daemon, { daemon->listen_fd = va_arg (ap, MHD_socket); -#ifdef SO_DOMAIN +#if defined(SO_DOMAIN) && defined(AF_UNIX) { int af; socklen_t len = sizeof (af); - if ( (0 == getsockopt (daemon->listen_fd, - SOL_SOCKET, - SO_DOMAIN, - &af, - &len)) && - (AF_UNIX == af) ) - daemon->listen_is_unix = true; + if (0 == getsockopt (daemon->listen_fd, + SOL_SOCKET, + SO_DOMAIN, + &af, + &len)) + { + daemon->listen_is_unix = (AF_UNIX == af) ? _MHD_YES : MHD_NO; + } + else + daemon->listen_is_unix = _MHD_UNKNOWN; } -#endif +#else /* ! SO_DOMAIN || ! AF_UNIX */ + daemon->listen_is_unix = _MHD_UNKNOWN; +#endif /* ! SO_DOMAIN || ! AF_UNIX */ } break; case MHD_OPTION_EXTERNAL_LOGGER: @@ -6342,6 +6332,7 @@ MHD_start_daemon_va (unsigned int flags, } #endif /* HTTPS_SUPPORT */ daemon->listen_fd = MHD_INVALID_SOCKET; + daemon->listen_is_unix = _MHD_NO; daemon->listening_address_reuse = 0; daemon->options = *pflags; pflags = &daemon->options; @@ -6722,6 +6713,8 @@ MHD_start_daemon_va (unsigned int flags, servaddr = (struct sockaddr *) &servaddr4; } } + else + daemon->listen_is_unix = _MHD_UNKNOWN; daemon->listen_fd = listen_fd; if (0 != (*pflags & MHD_USE_IPv6)) { diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h @@ -174,7 +174,9 @@ enum MHD_tristate { _MHD_UNKNOWN = -1, /**< State is not yet checked nor set */ _MHD_OFF = false, /**< State is "off" / "disabled" */ - _MHD_ON = true /**< State is "on" / "enabled" */ + _MHD_NO = false, /**< State is "off" / "disabled" */ + _MHD_ON = true, /**< State is "on" / "enabled" */ + _MHD_YES = true /**< State is "on" / "enabled" */ }; @@ -994,9 +996,10 @@ struct MHD_Connection MHD_socket socket_fd; /** - * true if #socket_fd is a UNIX domain socket, false (TCP) otherwise. + * true if @e socket_fd is not TCP/IP (a UNIX domain socket, a pipe), + * false (TCP/IP) otherwise. */ - bool is_unix; + enum MHD_tristate is_nonip; /** * true if #socket_fd is non-blocking, false otherwise. @@ -1444,6 +1447,11 @@ struct MHD_Daemon */ struct MHD_Connection *cleanup_tail; + /** + * _MHD_YES if the @e listen_fd socket is a UNIX domain socket. + */ + enum MHD_tristate listen_is_unix; + #ifdef EPOLL_SUPPORT /** * Head of EDLL of connections ready for processing (in epoll mode). @@ -1469,12 +1477,6 @@ struct MHD_Daemon */ bool listen_socket_in_epoll; - /** - * true if the @e listen_fd socket is a UNIX domain socket, - * false if not. - */ - bool listen_is_unix; - #ifdef UPGRADE_SUPPORT #ifdef HTTPS_SUPPORT /** diff --git a/src/microhttpd/mhd_send.c b/src/microhttpd/mhd_send.c @@ -174,6 +174,9 @@ MHD_connection_set_nodelay_state_ (struct MHD_Connection *connection, const MHD_SCKT_OPT_BOOL_ on_val = 1; int err_code; + if (_MHD_YES == connection->is_nonip) + return true; + if (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_NODELAY, @@ -186,18 +189,29 @@ MHD_connection_set_nodelay_state_ (struct MHD_Connection *connection, err_code = MHD_socket_get_error_ (); switch (err_code) { - case ENOTSOCK: - /* FIXME: Could be we are talking to a pipe, maybe remember this - and avoid all setsockopt() in the future? */ + case EINVAL: + case ENOPROTOOPT: + case ENOTSOCK: + if (_MHD_NO == connection->is_nonip) + { +#ifdef HAVE_MESSAGES + MHD_DLOG (connection->daemon, + _ ("Setting %s option to %s state failed " + "for TCP/IP socket %d: %s\n"), + "TCP_NODELAY", + nodelay_state ? _ ("ON") : _ ("OFF"), + (int) connection->socket_fd, + MHD_socket_strerr_ (err_code)); +#endif /* HAVE_MESSAGES */ + } + else + connection->is_nonip = _MHD_YES; break; case EBADF: - /* FIXME: should we die hard here? */ - case EINVAL: - /* FIXME: optlen invalid, should at least log this, maybe die */ case EFAULT: - /* wopsie, should at least log this, FIXME: maybe die */ - case ENOPROTOOPT: - /* optlen unknown, should at least log this */ + /* Hard errors, something is wrong. Too tricky to + * break connection here, just log the message. + * Shound't really happen too often. */ default: #ifdef HAVE_MESSAGES MHD_DLOG (connection->daemon, @@ -230,7 +244,7 @@ connection_set_cork_state_ (struct MHD_Connection *connection, const MHD_SCKT_OPT_BOOL_ on_val = 1; int err_code; - if (connection->is_unix) + if (_MHD_YES == connection->is_nonip) return true; if (0 == setsockopt (connection->socket_fd, IPPROTO_TCP, @@ -244,18 +258,29 @@ connection_set_cork_state_ (struct MHD_Connection *connection, err_code = MHD_socket_get_error_ (); switch (err_code) { - case ENOTSOCK: - /* FIXME: Could be we are talking to a pipe, maybe remember this - and avoid all setsockopt() in the future? */ + case EINVAL: + case ENOPROTOOPT: + case ENOTSOCK: + if (_MHD_NO == connection->is_nonip) + { +#ifdef HAVE_MESSAGES + MHD_DLOG (connection->daemon, + _ ("Setting %s option to %s state failed " + "for TCP/IP socket %d: %s\n"), + "TCP_NODELAY", + nodelay_state ? _ ("ON") : _ ("OFF"), + (int) connection->socket_fd, + MHD_socket_strerr_ (err_code)); +#endif /* HAVE_MESSAGES */ + } + else + connection->is_nonip = _MHD_YES; break; case EBADF: - /* FIXME: should we die hard here? */ - case EINVAL: - /* FIXME: optlen invalid, should at least log this, maybe die */ case EFAULT: - /* wopsie, should at least log this, FIXME: maybe die */ - case ENOPROTOOPT: - /* optlen unknown, should at least log this */ + /* Hard errors, something is wrong. Too tricky to + * break connection here, just log the message. + * Shound't really happen too often. */ default: #ifdef HAVE_MESSAGES MHD_DLOG (connection->daemon, @@ -295,7 +320,7 @@ pre_send_setopt (struct MHD_Connection *connection, * Final piece is indicated by push_data == true. */ const bool buffer_data = (! push_data); - if (connection->is_unix) + if (_MHD_YES == connection->is_nonip) return; /* The goal is to minimise the total number of additional sys-calls * before and after send(). @@ -519,8 +544,8 @@ zero_send_ (struct MHD_Connection *connection) { int dummy; - if (connection->is_unix) - return; + if (_MHD_YES == connection->is_nonip) + return false; mhd_assert (_MHD_OFF == connection->sk_corked); mhd_assert (_MHD_ON == connection->sk_nodelay); dummy = 0; /* Mute compiler and analyzer warnings */ @@ -556,7 +581,7 @@ post_send_setopt (struct MHD_Connection *connection, * Final piece is indicated by push_data == true. */ const bool buffer_data = (! push_data); - if (connection->is_unix) + if (_MHD_YES == connection->is_nonip) return; if (buffer_data) return; /* Nothing to do after send(). */