mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
select() support, unrelated fixes
This commit is contained in:
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user