select() support, unrelated fixes

This commit is contained in:
Evgeny Grin (Karlson2k)
2024-07-23 17:27:16 +02:00
parent 2cce91f703
commit b0d2092b7d
10 changed files with 472 additions and 120 deletions
+17
View File
@@ -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.
*/
+8 -9
View File
@@ -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, \
+47 -29
View File
@@ -32,24 +32,16 @@
#include <string.h>
#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 <errno.h>
# include "sys_errno.h"
#endif
#ifdef MHD_USE_EPOLL
# include <sys/epoll.h>
#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 <fcntl.h>
# 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)
+331 -20
View File
@@ -35,7 +35,7 @@
#ifdef MHD_POSIX_SOCKETS
# ifdef MHD_USE_SELECT
# ifdef HAVE_SYS_SELECT_H
# include <sys/select.h> /* For FD_SETSIZE */
# include <sys/select.h>
# else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
@@ -48,9 +48,7 @@
# endif
# endif
# endif
#endif
#ifdef MHD_POSIX_SOCKETS
# include <errno.h>
# 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)
+1
View File
@@ -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;
+2 -2
View File
@@ -46,7 +46,7 @@
# else
# include <stdlib.h>
# endif /* HAVE_UNISTD_H */
# include <errno.h>
# 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 <stdlib.h>
# endif /* HAVE_UNISTD_H */
# include <errno.h>
# include "sys_errno.h"
# if defined(HAVE_PIPE2_FUNC) && defined(O_CLOEXEC) && defined(O_NONBLOCK)
# define MHD_USE_PIPE2 1
# else
+7 -48
View File
@@ -40,6 +40,7 @@
# else
# include <stdlib.h>
# endif
# include "sys_errno.h"
#elif defined(MHD_WINSOCK_SOCKETS)
# include <winsock2.h>
#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
+1 -1
View File
@@ -37,7 +37,7 @@
# include <pthread_np.h>
# endif /* HAVE_PTHREAD_NP_H */
#endif /* MHD_USE_THREAD_NAME_ */
#include <errno.h>
#include "sys_errno.h"
#include "mhd_assert.h"
#ifndef MHD_USE_THREAD_NAME_
+4 -4
View File
@@ -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;
}
+54 -7
View File
@@ -30,23 +30,70 @@
#include "mhd_sys_options.h"
#include <errno.h>
#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 */