diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h index 9ed8362f..2324d8b2 100644 --- a/src/include/microhttpd2.h +++ b/src/include/microhttpd2.h @@ -988,6 +988,16 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode */ MHD_SC_POLL_HARD_ERROR = 50122 , + /** + * Encountered a (potentially) recoverable error from select(). + */ + MHD_SC_SELECT_SOFT_ERROR = 50123 + , + /** + * Encountered an unrecoverable error from select(). + */ + MHD_SC_SELECT_HARD_ERROR = 50124 + , /** * System reported error conditions on the listening socket. */ @@ -1298,6 +1308,13 @@ enum MHD_FIXED_ENUM_MHD_SET_ MHD_StatusCode */ MHD_SC_REPLY_CONTENT_LENGTH_NOT_ALLOWED = 60102 , + /** + * The new connection cannot be used because the FD number is higher than + * the limit set by FD_SETSIZE (if internal polling with select is used) or + * by application. + */ + MHD_SC_NEW_CONN_FD_OUTSIDE_OF_SET_RANGE = 60140 + , /** * The requested type of information is not recognised. */ diff --git a/src/mhd2/daemon_add_conn.c b/src/mhd2/daemon_add_conn.c index 882b7af1..3f0d4a0b 100644 --- a/src/mhd2/daemon_add_conn.c +++ b/src/mhd2/daemon_add_conn.c @@ -405,15 +405,7 @@ internal_add_connection (struct MHD_Daemon *daemon, /* Direct add to master daemon could never happen. */ mhd_assert (! mhd_D_HAS_WORKERS (daemon)); - - if (! mhd_FD_FITS_DAEMON (daemon, client_socket)) - { - mhd_LOG_MSG (daemon, MHD_SC_SOCKET_OUTSIDE_OF_SET_RANGE, \ - "New connection socket descriptor value is too large for " \ - "the daemon configuration."); - (void) mhd_socket_close (client_socket); - return MHD_SC_SOCKET_OUTSIDE_OF_SET_RANGE; - } + mhd_assert (mhd_FD_FITS_DAEMON (daemon, client_socket)); if ((! non_blck) && ((mhd_POLL_TYPE_EPOLL == daemon->events.poll_type) || @@ -588,6 +580,13 @@ MHD_daemon_add_connection (struct MHD_Daemon *daemon, #endif /* HAVE_INET6 */ } + if (! mhd_FD_FITS_DAEMON (daemon, client_socket)) + { + mhd_LOG_MSG (daemon, MHD_SC_NEW_CONN_FD_OUTSIDE_OF_SET_RANGE, \ + "The new connection FD value is higher than allowed"); + return MHD_SC_NEW_CONN_FD_OUTSIDE_OF_SET_RANGE; + } + if (! mhd_socket_nonblocking (client_socket)) { mhd_LOG_MSG (daemon, MHD_SC_ACCEPT_CONFIGURE_NONBLOCKING_FAILED, \ diff --git a/src/mhd2/daemon_start.c b/src/mhd2/daemon_start.c index c48ec907..d5232ae0 100644 --- a/src/mhd2/daemon_start.c +++ b/src/mhd2/daemon_start.c @@ -32,24 +32,16 @@ #include #include "sys_sockets_types.h" #include "sys_sockets_headers.h" +#include "mhd_sockets_macros.h" #include "sys_ip_headers.h" #ifdef MHD_POSIX_SOCKETS -# include +# include "sys_errno.h" #endif #ifdef MHD_USE_EPOLL # include #endif -#include "mhd_public_api.h" - -#include "mhd_daemon.h" -#include "daemon_options.h" - -#include "daemon_logger.h" -#include "mhd_assert.h" -#include "mhd_sockets_funcs.h" -#include "mhd_sockets_macros.h" #ifdef MHD_POSIX_SOCKETS # include # ifdef MHD_USE_SELECT @@ -69,6 +61,15 @@ # endif #endif +#include "mhd_limits.h" + +#include "mhd_daemon.h" +#include "daemon_options.h" + +#include "mhd_assert.h" +#include "mhd_sockets_funcs.h" +#include "daemon_logger.h" + #ifdef MHD_USE_THREADS # include "mhd_itc.h" # include "mhd_threads.h" @@ -76,7 +77,7 @@ # include "daemon_funcs.h" #endif -#include "mhd_limits.h" +#include "mhd_public_api.h" /** @@ -1483,6 +1484,22 @@ static MHD_FN_PAR_NONNULL_ (1) MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode allocate_events (struct MHD_Daemon *restrict d) { +#if ! defined(NDEBUG) && \ + (defined(MHD_USE_POLL) || defined(MHD_USE_EPOLL)) + /** + * The number of elements to be monitored by sockets polling function + */ + unsigned int num_elements; + num_elements = 0; +#ifdef MHD_USE_THREADS + ++num_elements; /* For the ITC */ +#endif + if (MHD_INVALID_SOCKET != d->net.listen.fd) + ++num_elements; /* For the listening socket */ + if (! mhd_D_HAS_THR_PER_CONN (d)) + num_elements += d->conns.cfg.count_limit; +#endif /* ! NDEBUG && (MHD_USE_POLL || MHD_USE_EPOLL) */ + mhd_assert (0 != d->conns.cfg.count_limit); mhd_assert (mhd_D_TYPE_HAS_EVENTS_PROCESSING (d->threading.d_type)); @@ -1513,6 +1530,7 @@ allocate_events (struct MHD_Daemon *restrict d) if (NULL != d->events.data.select.efds) { #ifndef NDEBUG + d->dbg.num_events_elements = FD_SETSIZE; d->dbg.events_allocated = true; #endif return MHD_SC_OK; /* Success exit point */ @@ -1532,22 +1550,19 @@ allocate_events (struct MHD_Daemon *restrict d) /* The pointers have been set to NULL during pre-initialisations of the events */ mhd_assert (NULL == d->events.data.poll.fds); mhd_assert (NULL == d->events.data.poll.rel); - if (1) + if (num_elements > d->conns.cfg.count_limit) /* Check for value overflow */ { - unsigned int num_slots; - num_slots = 2; /* For ITC and listening, even if they are unused */ - if (mhd_WM_INT_INTERNAL_EVENTS_THREAD_PER_CONNECTION != d->wmode_int) - num_slots += d->conns.cfg.count_limit; d->events.data.poll.fds = - (struct pollfd *) malloc (sizeof(struct pollfd) * num_slots); + (struct pollfd *) malloc (sizeof(struct pollfd) * num_elements); if (NULL != d->events.data.poll.fds) { d->events.data.poll.rel = (union mhd_SocketRelation *) malloc (sizeof(union mhd_SocketRelation) - * num_slots); + * num_elements); if (NULL != d->events.data.poll.rel) { #ifndef NDEBUG + d->dbg.num_events_elements = num_elements; d->dbg.events_allocated = true; #endif return MHD_SC_OK; /* Success exit point */ @@ -1562,23 +1577,16 @@ allocate_events (struct MHD_Daemon *restrict d) #endif /* MHD_USE_POLL */ #ifdef MHD_USE_EPOLL case mhd_POLL_TYPE_EPOLL: + mhd_assert (! mhd_D_HAS_THR_PER_CONN (d)); /* The event FD has been created during pre-initialisations of the events */ mhd_assert (MHD_INVALID_SOCKET != d->events.data.epoll.e_fd); /* The pointer has been set to NULL during pre-initialisations of the events */ mhd_assert (NULL == d->events.data.epoll.events); mhd_assert (0 == d->events.data.epoll.num_elements); - if (1) + if (num_elements > d->conns.cfg.count_limit) /* Check for value overflow */ { - size_t num_elements; const size_t upper_limit = (sizeof(void*) >= 8) ? 4096 : 1024; - num_elements = d->conns.cfg.count_limit; -#ifdef MHD_USE_THREADS - ++num_elements; /* For ITC */ -#endif - if (MHD_INVALID_SOCKET != d->net.listen.fd) - ++num_elements; - /* Trade neglectable performance penalty for memory saving */ /* Very large amount of new events processed in batches */ if (num_elements > upper_limit) @@ -1591,6 +1599,7 @@ allocate_events (struct MHD_Daemon *restrict d) { d->events.data.epoll.num_elements = num_elements; #ifndef NDEBUG + d->dbg.num_events_elements = num_elements; d->dbg.events_allocated = true; #endif return MHD_SC_OK; /* Success exit point */ @@ -1707,6 +1716,15 @@ init_itc (struct MHD_Daemon *restrict d) #endif return MHD_SC_ITC_INITIALIZATION_FAILED; } + if (! mhd_FD_FITS_DAEMON (d,mhd_itc_r_fd (d->threading.itc))) + { + mhd_LOG_MSG (d, MHD_SC_ITC_FD_OUTSIDE_OF_SET_RANGE, \ + "The inter-thread communication FD value is " \ + "higher than allowed"); + mhd_itc_destroy (d->threading.itc); + mhd_itc_set_invalid (&(d->threading.itc)); + return MHD_SC_ITC_FD_OUTSIDE_OF_SET_RANGE; + } #endif /* MHD_USE_THREADS */ return MHD_SC_OK; } @@ -1975,7 +1993,7 @@ set_connections_total_limits (struct MHD_Daemon *restrict d, bool error_by_fd_setsize; unsigned int num_worker_daemons; - mhd_assert (! mhd_D_TYPE_IS_INTERNAL_ONLY (d->threading.d_type)); + mhd_assert (! mhd_D_HAS_MASTER (d)); mhd_assert (mhd_D_TYPE_IS_VALID (d->threading.d_type)); if (mhd_WM_INT_INTERNAL_EVENTS_THREAD_POOL == d->wmode_int) @@ -2037,7 +2055,7 @@ set_connections_total_limits (struct MHD_Daemon *restrict d, } } else - limit_by_num = UINT_MAX; + limit_by_num = (unsigned int) INT_MAX; } #elif defined(MHD_WINSOCK_SOCKETS) if (1) diff --git a/src/mhd2/events_process.c b/src/mhd2/events_process.c index 99f3276c..3a8bc170 100644 --- a/src/mhd2/events_process.c +++ b/src/mhd2/events_process.c @@ -35,7 +35,7 @@ #ifdef MHD_POSIX_SOCKETS # ifdef MHD_USE_SELECT # ifdef HAVE_SYS_SELECT_H -# include /* For FD_SETSIZE */ +# include # else # ifdef HAVE_SYS_TIME_H # include @@ -48,9 +48,7 @@ # endif # endif # endif -#endif -#ifdef MHD_POSIX_SOCKETS -# include +# include "sys_errno.h" #endif #include "mhd_itc.h" @@ -86,7 +84,7 @@ get_max_wait (struct MHD_Daemon *restrict d) if (NULL != mhd_DLINKEDL_GET_FIRST (&(d->events), proc_ready)) return 0; - return -1; // TODO: calculate correct timeout value + return INT_MAX; // TODO: calculate correct timeout value } @@ -271,7 +269,7 @@ daemon_process_all_active_conns (struct MHD_Daemon *restrict d) static void -close_all_daemon_conns (struct MHD_Daemon *restrict d) +close_all_daemon_conns (struct MHD_Daemon *d) { struct MHD_Connection *c; @@ -285,9 +283,317 @@ close_all_daemon_conns (struct MHD_Daemon *restrict d) } +#ifdef MHD_USE_SELECT + +/** + * Add socket to the fd_set + * @param fd the socket to add + * @param fs the pointer to fd_set + * @param max the pointer to variable to be updated with maximum FD value (or + * set to non-zero in case of WinSock) + * @param d the daemon object + */ +MHD_static_inline_ MHD_FN_PAR_NONNULL_ALL_ +MHD_FN_PAR_INOUT_ (2) +MHD_FN_PAR_INOUT_ (3) void +fd_set_wrap (MHD_Socket fd, + fd_set *restrict fs, + int *restrict max, + struct MHD_Daemon *restrict d) +{ + mhd_assert (mhd_FD_FITS_DAEMON (d, fd)); /* Must be checked for every FD before + it is added */ + mhd_assert (mhd_POLL_TYPE_SELECT == d->events.poll_type); + (void) d; /* Unused with non-debug builds */ +#if defined(MHD_POSIX_SOCKETS) + FD_SET (fd, fs); + if (*max < fd) + *max = fd; +#elif defined(MHD_WINSOCK_SOCKETS) + /* Use custom set function to take advantage of know uniqueness of + * used sockets (to skip useless (for this function) check for duplicated + * sockets implemented in system's macro). */ + mhd_assert (fs->fd_count < FD_SETSIZE - 1); /* Daemon limits set to always fit FD_SETSIZE */ + mhd_assert (! FD_ISSET (fd, fs)); /* All sockets must be unique */ + fs->fd_array[fs->fd_count++] = fd; + *max = 1; +#else +#error Unknown sockets type +#endif +} + + +/** + * Set daemon's FD_SETs to monitor all daemon's sockets + * @param d the daemon to use + * @param listen_only set to 'true' if connections's sockets should NOT + * be monitored + * @return with POSIX sockets: the maximum number of the socket used in + * the FD_SETs; + * with winsock: non-zero if at least one socket has been added to + * the FD_SETs, + * zero if no sockets in the FD_SETs + */ +static MHD_FN_PAR_NONNULL_ (1) int +select_update_fdsets (struct MHD_Daemon *restrict d, + bool listen_only) +{ + struct MHD_Connection *c; + fd_set *const restrict rfds = d->events.data.select.rfds; + fd_set *const restrict wfds = d->events.data.select.wfds; + fd_set *const restrict efds = d->events.data.select.efds; + int ret; + + mhd_assert (mhd_POLL_TYPE_SELECT == d->events.poll_type); + mhd_assert (NULL != rfds); + mhd_assert (NULL != wfds); + mhd_assert (NULL != efds); + FD_ZERO (rfds); + FD_ZERO (wfds); + FD_ZERO (efds); + + ret = 0; +#ifdef MHD_USE_THREADS + mhd_assert (mhd_ITC_IS_VALID (d->threading.itc)); + fd_set_wrap (mhd_itc_r_fd (d->threading.itc), + rfds, + &ret, + d); + fd_set_wrap (mhd_itc_r_fd (d->threading.itc), + efds, + &ret, + d); +#endif + if (MHD_INVALID_SOCKET != d->net.listen.fd) + { + fd_set_wrap (d->net.listen.fd, + rfds, + &ret, + d); + fd_set_wrap (d->net.listen.fd, + efds, + &ret, + d); + } + if (listen_only) + return ret; + + for (c = mhd_DLINKEDL_GET_FIRST (&(d->conns),all_conn); NULL != c; + c = mhd_DLINKEDL_GET_NEXT (c,all_conn)) + { + mhd_assert (MHD_CONNECTION_CLOSED != c->state); + + if (0 != (c->event_loop_info & MHD_EVENT_LOOP_INFO_READ)) + fd_set_wrap (c->socket_fd, + rfds, + &ret, + d); + if (0 != (c->event_loop_info & MHD_EVENT_LOOP_INFO_WRITE)) + fd_set_wrap (c->socket_fd, + wfds, + &ret, + d); + fd_set_wrap (c->socket_fd, + efds, + &ret, + d); + } + + return ret; +} + + +static MHD_FN_PAR_NONNULL_ (1) bool +select_update_statuses_from_fdsets (struct MHD_Daemon *d, + int num_events) +{ + struct MHD_Connection *c; + fd_set *const restrict rfds = d->events.data.select.rfds; + fd_set *const restrict wfds = d->events.data.select.wfds; + fd_set *const restrict efds = d->events.data.select.efds; + + mhd_assert (mhd_POLL_TYPE_SELECT == d->events.poll_type); + mhd_assert (0 <= num_events); + mhd_assert (((unsigned int) num_events) <= d->dbg.num_events_elements); + +#ifndef MHD_FAVOR_SMALL_CODE + if (0 == num_events) + return true; +#endif /* MHD_FAVOR_SMALL_CODE */ + +#ifdef MHD_USE_THREADS + mhd_assert (mhd_ITC_IS_VALID (d->threading.itc)); + if (FD_ISSET (mhd_itc_r_fd (d->threading.itc), efds)) + { + mhd_LOG_MSG (d, MHD_SC_ITC_STATUS_ERROR, \ + "System reported that ITC has an error status."); + /* ITC is broken, need to stop the daemon thread now as otherwise + application will not be able to stop the thread. */ + return false; + } + if (FD_ISSET (mhd_itc_r_fd (d->threading.itc), rfds)) + { + --num_events; + /* Clear ITC here, as before any other data processing. + * Any external events may activate ITC again if any data to process is + * added externally. Cleaning ITC early ensures guaranteed that new data + * will not be missed. */ + mhd_itc_clear (d->threading.itc); + } + +#ifndef MHD_FAVOR_SMALL_CODE + if (0 == num_events) + return true; +#endif /* MHD_FAVOR_SMALL_CODE */ +#endif /* MHD_USE_THREADS */ + + if (MHD_INVALID_SOCKET != d->net.listen.fd) + { + if (FD_ISSET (d->net.listen.fd, efds)) + { + --num_events; + mhd_LOG_MSG (d, MHD_SC_ITC_STATUS_ERROR, \ + "System reported that the listening socket has an error " \ + "status. The daemon will not listen any more."); + /* Close the listening socket unless the master daemon should close it */ + if (! mhd_D_HAS_MASTER (d)) + mhd_socket_close (d->net.listen.fd); + + /* Stop monitoring socket to avoid spinning with busy-waiting */ + d->net.listen.fd = MHD_INVALID_SOCKET; + } + else if (FD_ISSET (d->net.listen.fd, rfds)) + { + --num_events; + d->events.act_req.accept = true; + } + } + + mhd_assert ((0 == num_events) || \ + (mhd_DAEMON_TYPE_LISTEN_ONLY != d->threading.d_type)); + +#ifdef MHD_FAVOR_SMALL_CODE + (void) num_events; + num_events = 1; /* Use static value to optimise out the next look */ +#endif /* ! MHD_FAVOR_SMALL_CODE */ + + for (c = mhd_DLINKEDL_GET_FIRST (&(d->conns), all_conn); + (NULL != c) && (0 != num_events); + c = mhd_DLINKEDL_GET_NEXT (c, all_conn)) + { + const MHD_Socket sk = c->socket_fd; + bool recv_ready = FD_ISSET (sk, rfds); + bool send_ready = FD_ISSET (sk, wfds); + bool err_state = FD_ISSET (sk, efds); + + update_conn_net_status (d, + c, + recv_ready, + send_ready, + err_state); +#ifndef MHD_FAVOR_SMALL_CODE + if (recv_ready || send_ready || err_state) + --num_events; +#endif /* MHD_FAVOR_SMALL_CODE */ + } + + #ifndef MHD_FAVOR_SMALL_CODE + mhd_assert (0 == num_events); +#endif /* MHD_FAVOR_SMALL_CODE */ + return true; +} + + +/** + * Update states of all connections, check for connection pending + * to be accept()'ed, check for the events on ITC. + * @param listen_only set to 'true' if connections's sockets should NOT + * be monitored + * @return 'true' if processed successfully, + * 'false' is unrecoverable error occurs and the daemon must be + * closed + */ +static MHD_FN_PAR_NONNULL_ (1) bool +get_all_net_updates_by_select (struct MHD_Daemon *restrict d, + bool listen_only) +{ + int max_socket; + int max_wait; + struct timeval tmvl; + int num_events; + mhd_assert (mhd_POLL_TYPE_SELECT == d->events.poll_type); + + max_socket = select_update_fdsets (d, + listen_only); + + max_wait = get_max_wait (d); // TODO: use correct timeout value + +#ifdef MHD_WINSOCK_SOCKETS + if (0 == max_socket) + { + Sleep ((unsigned int) max_wait); + return true; + } +#endif /* MHD_WINSOCK_SOCKETS */ + + tmvl.tv_sec = max_wait / 1000; +#ifndef MHD_WINSOCK_SOCKETS + tmvl.tv_usec = (uint_least16_t) ((max_wait % 1000) * 1000); +#else + tmvl.tv_usec = (int) ((max_wait % 1000) * 1000); +#endif + + num_events = select (max_socket + 1, + d->events.data.select.rfds, + d->events.data.select.wfds, + d->events.data.select.efds, + &tmvl); + + if (0 > num_events) + { + int err; + bool is_hard_error; + bool is_ignored_error; + is_hard_error = false; + is_ignored_error = false; +#if defined(MHD_POSIX_SOCKETS) + err = errno; + if (0 != err) + { + is_hard_error = + ((mhd_EBADF_OR_ZERO == err) || (mhd_EINVAL_OR_ZERO == err)); + is_ignored_error = (mhd_EINTR_OR_ZERO == err); + } +#elif defined(MHD_WINSOCK_SOCKETS) + err = WSAGetLastError (); + is_hard_error = + ((WSAENETDOWN == err) || (WSAEFAULT == err) || (WSAEINVAL == err) || + (WSANOTINITIALISED == err)); +#endif + if (! is_ignored_error) + { + if (is_hard_error) + { + mhd_LOG_MSG (d, MHD_SC_SELECT_HARD_ERROR, \ + "The select() encountered unrecoverable error."); + return false; + } + mhd_LOG_MSG (d, MHD_SC_SELECT_SOFT_ERROR, \ + "The select() encountered error."); + return true; + } + } + + return select_update_statuses_from_fdsets (d, num_events); +} + + +#endif /* MHD_USE_SELECT */ + + #ifdef MHD_USE_POLL -MHD_FN_PAR_NONNULL_ (1) static unsigned int +static MHD_FN_PAR_NONNULL_ (1) unsigned int poll_update_fds (struct MHD_Daemon *restrict d, bool listen_only) { @@ -321,6 +627,7 @@ poll_update_fds (struct MHD_Daemon *restrict d, { unsigned short events; /* 'unsigned' for correct bits manipulations */ mhd_assert ((i_c - i_s) < d->conns.cfg.count_limit); + mhd_assert (i_c < d->dbg.num_events_elements); mhd_assert (MHD_CONNECTION_CLOSED != c->state); d->events.data.poll.fds[i_c].fd = c->socket_fd; @@ -335,11 +642,12 @@ poll_update_fds (struct MHD_Daemon *restrict d, ++i_c; } mhd_assert (d->conns.count == (i_c - i_s)); + mhd_assert (i_c <= d->dbg.num_events_elements); return i_c; } -MHD_FN_PAR_NONNULL_ (1) static bool +static MHD_FN_PAR_NONNULL_ (1) bool poll_update_statuses_from_fds (struct MHD_Daemon *restrict d, int num_events) { @@ -347,6 +655,7 @@ poll_update_statuses_from_fds (struct MHD_Daemon *restrict d, unsigned int i_c; mhd_assert (mhd_POLL_TYPE_POLL == d->events.poll_type); mhd_assert (0 <= num_events); + mhd_assert (((unsigned int) num_events) <= d->dbg.num_events_elements); if (0 == num_events) return true; @@ -420,6 +729,7 @@ poll_update_statuses_from_fds (struct MHD_Daemon *restrict d, bool send_ready; bool err_state; short revents; + mhd_assert (i_c < d->dbg.num_events_elements); mhd_assert (mhd_SOCKET_REL_MARKER_EMPTY != \ d->events.data.poll.rel[i_c].fd_id); mhd_assert (mhd_SOCKET_REL_MARKER_ITC != \ @@ -459,11 +769,12 @@ poll_update_statuses_from_fds (struct MHD_Daemon *restrict d, update_conn_net_status (d, c, recv_ready, send_ready, err_state); } mhd_assert (d->conns.count >= (i_c - i_s)); + mhd_assert (i_c <= d->dbg.num_events_elements); return true; } -MHD_FN_PAR_NONNULL_ (1) static bool +static MHD_FN_PAR_NONNULL_ (1) bool get_all_net_updates_by_poll (struct MHD_Daemon *restrict d, bool listen_only) { @@ -490,8 +801,8 @@ get_all_net_updates_by_poll (struct MHD_Daemon *restrict d, if (0 != err) { is_hard_error = - ((MHD_EFAULT_OR_ZERO == err) || (MHD_EINVAL_OR_ZERO == err)); - is_ignored_error = (MHD_EINTR_OR_ZERO == err); + ((mhd_EFAULT_OR_ZERO == err) || (mhd_EINVAL_OR_ZERO == err)); + is_ignored_error = (mhd_EINTR_OR_ZERO == err); } #elif defined(MHD_WINSOCK_SOCKETS) err = WSAGetLastError (); @@ -509,12 +820,10 @@ get_all_net_updates_by_poll (struct MHD_Daemon *restrict d, mhd_LOG_MSG (d, MHD_SC_POLL_SOFT_ERROR, \ "The poll() encountered error."); } + return true; } - if (! poll_update_statuses_from_fds (d, num_events)) - return false; - - return true; + return poll_update_statuses_from_fds (d, num_events); } @@ -526,7 +835,7 @@ get_all_net_updates_by_poll (struct MHD_Daemon *restrict d, * Map events provided by epoll to connection states, ITC and * listen socket states */ -MHD_FN_PAR_NONNULL_ (1) static bool +static MHD_FN_PAR_NONNULL_ (1) bool poll_update_statuses_from_eevents (struct MHD_Daemon *restrict d, unsigned int num_events) { @@ -597,7 +906,7 @@ poll_update_statuses_from_eevents (struct MHD_Daemon *restrict d, * Update states of all connections, check for connection pending * to be accept()'ed, check for the events on ITC. */ -MHD_FN_PAR_NONNULL_ (1) static bool +static MHD_FN_PAR_NONNULL_ (1) bool get_all_net_updates_by_epoll (struct MHD_Daemon *restrict d) { int num_events; @@ -609,6 +918,7 @@ get_all_net_updates_by_epoll (struct MHD_Daemon *restrict d) (size_t) ((int) d->events.data.epoll.num_elements)); mhd_assert (0 != d->events.data.epoll.num_elements); mhd_assert (0 != d->conns.cfg.count_limit); + mhd_assert (d->events.data.epoll.num_elements == d->dbg.num_events_elements); // TODO: add listen socket enable/disable @@ -646,7 +956,7 @@ get_all_net_updates_by_epoll (struct MHD_Daemon *restrict d) #endif /* MHD_USE_EPOLL */ -MHD_FN_PAR_NONNULL_ (1) static bool +static MHD_FN_PAR_NONNULL_ (1) bool process_all_events_and_data (struct MHD_Daemon *restrict d) { switch (d->events.poll_type) @@ -656,7 +966,8 @@ process_all_events_and_data (struct MHD_Daemon *restrict d) break; #ifdef MHD_USE_SELECT case mhd_POLL_TYPE_SELECT: - return false; // TODO: implement + if (! get_all_net_updates_by_select (d, false)) + return false; break; #endif /* MHD_USE_SELECT */ #ifdef MHD_USE_POLL @@ -737,7 +1048,7 @@ mhd_worker_all_events (void *cls) } -MHD_FN_PAR_NONNULL_ (1) static bool +static MHD_FN_PAR_NONNULL_ (1) bool process_listening_and_itc_only (struct MHD_Daemon *restrict d) { if (false) diff --git a/src/mhd2/mhd_daemon.h b/src/mhd2/mhd_daemon.h index 09821449..9ccc17c3 100644 --- a/src/mhd2/mhd_daemon.h +++ b/src/mhd2/mhd_daemon.h @@ -861,6 +861,7 @@ struct mhd_daemon_debug bool net_inited; bool net_deinited; bool events_allocated; + unsigned int num_events_elements; bool events_fully_inited; bool thread_pool_inited; bool threading_inited; diff --git a/src/mhd2/mhd_itc.h b/src/mhd2/mhd_itc.h index 2f0348c7..acd08a46 100644 --- a/src/mhd2/mhd_itc.h +++ b/src/mhd2/mhd_itc.h @@ -46,7 +46,7 @@ # else # include # endif /* HAVE_UNISTD_H */ -# include +# include "sys_errno.h" /** * Number of FDs used by every ITC. @@ -137,7 +137,7 @@ static const uint_fast64_t mhd_ITC_WR_DATA = 1; # else # include # endif /* HAVE_UNISTD_H */ -# include +# include "sys_errno.h" # if defined(HAVE_PIPE2_FUNC) && defined(O_CLOEXEC) && defined(O_NONBLOCK) # define MHD_USE_PIPE2 1 # else diff --git a/src/mhd2/mhd_sockets_macros.h b/src/mhd2/mhd_sockets_macros.h index d3668234..b6bb7e80 100644 --- a/src/mhd2/mhd_sockets_macros.h +++ b/src/mhd2/mhd_sockets_macros.h @@ -40,6 +40,7 @@ # else # include # endif +# include "sys_errno.h" #elif defined(MHD_WINSOCK_SOCKETS) # include #endif @@ -87,48 +88,6 @@ #define mhd_sys_recv(s,b,l) \ ((ssize_t) recv ((s),(void*) (b),(mhd_SCKT_SEND_SIZE) (l), 0)) -#ifdef EMFILE -# define MHD_EMFILE_OR_ZERO EMFILE -#else -# define MHD_EMFILE_OR_ZERO (0) -#endif - -#ifdef ENFILE -# define MHD_ENFILE_OR_ZERO ENFILE -#else -# define MHD_ENFILE_OR_ZERO (0) -#endif - -#ifdef ENOMEM -# define MHD_ENOMEM_OR_ZERO ENOMEM -#else -# define MHD_ENOMEM_OR_ZERO (0) -#endif - -#ifdef ENOBUFS -# define MHD_ENOBUFS_OR_ZERO ENOBUFS -#else -# define MHD_ENOBUFS_OR_ZERO (0) -#endif - -#ifdef EHOSTUNREACH -# define MHD_EHOSTUNREACH_OR_ZERO EHOSTUNREACH -#else -# define MHD_EHOSTUNREACH_OR_ZERO (0) -#endif - -#ifdef ETIMEDOUT -# define MHD_ETIMEDOUT_OR_ZERO ETIMEDOUT -#else -# define MHD_ETIMEDOUT_OR_ZERO (0) -#endif - -#ifdef ENETUNREACH -# define MHD_ENETUNREACH_OR_ZERO ENETUNREACH -#else -# define MHD_ENETUNREACH_OR_ZERO (0) -#endif - /** * Last socket error */ @@ -286,9 +245,9 @@ + ENETUNREACH: probably cable physically disconnected or similar */ # define mhd_SCKT_ERR_IS_CONN_BROKEN(err) \ ((0 != (err)) && \ - ((MHD_EHOSTUNREACH_OR_ZERO == (err)) || \ - (MHD_ETIMEDOUT_OR_ZERO == (err)) || \ - (MHD_ENETUNREACH_OR_ZERO == (err)))) + ((mhd_EHOSTUNREACH_OR_ZERO == (err)) || \ + (mhd_ETIMEDOUT_OR_ZERO == (err)) || \ + (mhd_ENETUNREACH_OR_ZERO == (err)))) #elif defined(MHD_WINSOCK_SOCKETS) # define mhd_SCKT_ERR_IS_CONN_BROKEN(err) \ ( (WSAENETRESET == (err)) || (WSAECONNABORTED == (err)) || \ @@ -303,8 +262,8 @@ #if defined(MHD_POSIX_SOCKETS) # define mhd_SCKT_ERR_IS_LOW_RESOURCES(err) \ ((0 != (err)) && \ - ((MHD_EMFILE_OR_ZERO == (err)) || (MHD_ENFILE_OR_ZERO == (err)) || \ - (MHD_ENOMEM_OR_ZERO == (err)) || (MHD_ENOBUFS_OR_ZERO == (err)))) + ((mhd_EMFILE_OR_ZERO == (err)) || (mhd_ENFILE_OR_ZERO == (err)) || \ + (mhd_ENOMEM_OR_ZERO == (err)) || (mhd_ENOBUFS_OR_ZERO == (err)))) #elif defined(MHD_WINSOCK_SOCKETS) # define mhd_SCKT_ERR_IS_LOW_RESOURCES(err) \ ( (WSAEMFILE == (err)) || (WSAENOBUFS == (err)) ) @@ -319,7 +278,7 @@ #if defined(MHD_POSIX_SOCKETS) # define mhd_SCKT_ERR_IS_LOW_MEM(err) \ ((0 != (err)) && \ - ((MHD_ENOMEM_OR_ZERO == (err)) || (MHD_ENOBUFS_OR_ZERO == (err)))) + ((mhd_ENOMEM_OR_ZERO == (err)) || (mhd_ENOBUFS_OR_ZERO == (err)))) #elif defined(MHD_WINSOCK_SOCKETS) # define mhd_SCKT_ERR_IS_LOW_MEM(err) (WSAENOBUFS == (err)) #endif diff --git a/src/mhd2/mhd_threads.c b/src/mhd2/mhd_threads.c index 66cec793..239eff2a 100644 --- a/src/mhd2/mhd_threads.c +++ b/src/mhd2/mhd_threads.c @@ -37,7 +37,7 @@ # include # endif /* HAVE_PTHREAD_NP_H */ #endif /* MHD_USE_THREAD_NAME_ */ -#include +#include "sys_errno.h" #include "mhd_assert.h" #ifndef MHD_USE_THREAD_NAME_ diff --git a/src/mhd2/stream_process_request.c b/src/mhd2/stream_process_request.c index 03306375..8b4c8e9c 100644 --- a/src/mhd2/stream_process_request.c +++ b/src/mhd2/stream_process_request.c @@ -2829,11 +2829,11 @@ need_100_continue (struct MHD_Connection *restrict c) if (NULL == hvalue) return false; - if (! mhd_str_equal_caseless_n_st ("100-continue", \ - hvalue->cstr, hvalue->len)) - return false; + if (mhd_str_equal_caseless_n_st ("100-continue", \ + hvalue->cstr, hvalue->len)) + return true; - return true; + return false; } diff --git a/src/mhd2/sys_errno.h b/src/mhd2/sys_errno.h index ab9b957f..23f66e49 100644 --- a/src/mhd2/sys_errno.h +++ b/src/mhd2/sys_errno.h @@ -30,23 +30,70 @@ #include "mhd_sys_options.h" #include -#ifdef EFAULT -# define MHD_EFAULT_OR_ZERO EFAULT +#ifdef EBADF +# define mhd_EBADF_OR_ZERO EBADF #else -# define MHD_EFAULT_OR_ZERO (0) +# define mhd_EBADF_OR_ZERO (0) +#endif + +#ifdef EFAULT +# define mhd_EFAULT_OR_ZERO EFAULT +#else +# define mhd_EFAULT_OR_ZERO (0) #endif #ifdef EINVAL -# define MHD_EINVAL_OR_ZERO EINVAL +# define mhd_EINVAL_OR_ZERO EINVAL #else -# define MHD_EINVAL_OR_ZERO (0) +# define mhd_EINVAL_OR_ZERO (0) #endif #ifdef EINTR -# define MHD_EINTR_OR_ZERO EINTR +# define mhd_EINTR_OR_ZERO EINTR #else -# define MHD_EINTR_OR_ZERO (0) +# define mhd_EINTR_OR_ZERO (0) #endif +#ifdef ENOMEM +# define mhd_ENOMEM_OR_ZERO ENOMEM +#else +# define mhd_ENOMEM_OR_ZERO (0) +#endif + +#ifdef EMFILE +# define mhd_EMFILE_OR_ZERO EMFILE +#else +# define mhd_EMFILE_OR_ZERO (0) +#endif + +#ifdef ENFILE +# define mhd_ENFILE_OR_ZERO ENFILE +#else +# define mhd_ENFILE_OR_ZERO (0) +#endif + +#ifdef ENOBUFS +# define mhd_ENOBUFS_OR_ZERO ENOBUFS +#else +# define mhd_ENOBUFS_OR_ZERO (0) +#endif + +#ifdef EHOSTUNREACH +# define mhd_EHOSTUNREACH_OR_ZERO EHOSTUNREACH +#else +# define mhd_EHOSTUNREACH_OR_ZERO (0) +#endif + +#ifdef ETIMEDOUT +# define mhd_ETIMEDOUT_OR_ZERO ETIMEDOUT +#else +# define mhd_ETIMEDOUT_OR_ZERO (0) +#endif + +#ifdef ENETUNREACH +# define mhd_ENETUNREACH_OR_ZERO ENETUNREACH +#else +# define mhd_ENETUNREACH_OR_ZERO (0) +#endif #endif /* ! MHD_SYS_ERRNO_H */