|
|
@@ -101,16 +101,17 @@ close_all_connections (struct MHD_Daemon *daemon);
|
|
|
#ifdef EPOLL_SUPPORT
|
|
|
|
|
|
/**
|
|
|
- * Do epoll()-based processing (this function is allowed to
|
|
|
- * block if @a may_block is set to #MHD_YES).
|
|
|
+ * Do epoll()-based processing.
|
|
|
*
|
|
|
* @param daemon daemon to run poll loop for
|
|
|
- * @param may_block #MHD_YES if blocking, #MHD_NO if non-blocking
|
|
|
+ * @param millisec the maximum time in milliseconds to wait for events,
|
|
|
+ * set to '0' for non-blocking processing,
|
|
|
+ * set to '-1' to wait indefinitely.
|
|
|
* @return #MHD_NO on serious errors, #MHD_YES on success
|
|
|
*/
|
|
|
static enum MHD_Result
|
|
|
MHD_epoll (struct MHD_Daemon *daemon,
|
|
|
- int may_block);
|
|
|
+ int32_t millisec);
|
|
|
|
|
|
#endif /* EPOLL_SUPPORT */
|
|
|
|
|
|
@@ -3834,6 +3835,35 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
|
|
|
}
|
|
|
|
|
|
|
|
|
+/**
|
|
|
+ * Obtain timeout value for polling function for this daemon.
|
|
|
+ * @remark To be called only from the thread that processes
|
|
|
+ * daemon's select()/poll()/etc.
|
|
|
+ *
|
|
|
+ * @param daemon the daemon to query for timeout
|
|
|
+ * @param max_timeout the maximum return value (in milliseconds),
|
|
|
+ * ignored if set to '-1'
|
|
|
+ * @return timeout value in milliseconds or -1 if no timeout is expected.
|
|
|
+ */
|
|
|
+static int
|
|
|
+get_timeout_millisec_ (struct MHD_Daemon *daemon,
|
|
|
+ int32_t max_timeout)
|
|
|
+{
|
|
|
+ MHD_UNSIGNED_LONG_LONG ulltimeout;
|
|
|
+ if (0 == max_timeout)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (MHD_NO == MHD_get_timeout (daemon, &ulltimeout))
|
|
|
+ return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
|
|
|
+
|
|
|
+ if ( (0 > max_timeout) ||
|
|
|
+ ((uint32_t) max_timeout > ulltimeout) )
|
|
|
+ return (INT_MAX < ulltimeout) ? INT_MAX : (int) ulltimeout;
|
|
|
+
|
|
|
+ return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* Internal version of #MHD_run_from_select().
|
|
|
*
|
|
|
@@ -3978,7 +4008,7 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
|
|
|
{
|
|
|
#ifdef EPOLL_SUPPORT
|
|
|
enum MHD_Result ret = MHD_epoll (daemon,
|
|
|
- MHD_NO);
|
|
|
+ 0);
|
|
|
|
|
|
MHD_cleanup_connections (daemon);
|
|
|
return ret;
|
|
|
@@ -4003,12 +4033,14 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
|
|
|
* and then #internal_run_from_select with the result.
|
|
|
*
|
|
|
* @param daemon daemon to run select() loop for
|
|
|
- * @param may_block #MHD_YES if blocking, #MHD_NO if non-blocking
|
|
|
+ * @param millisec the maximum time in milliseconds to wait for events,
|
|
|
+ * set to '0' for non-blocking processing,
|
|
|
+ * set to '-1' to wait indefinitely.
|
|
|
* @return #MHD_NO on serious errors, #MHD_YES on success
|
|
|
*/
|
|
|
static enum MHD_Result
|
|
|
MHD_select (struct MHD_Daemon *daemon,
|
|
|
- int may_block)
|
|
|
+ int32_t millisec)
|
|
|
{
|
|
|
int num_ready;
|
|
|
fd_set rs;
|
|
|
@@ -4017,7 +4049,6 @@ MHD_select (struct MHD_Daemon *daemon,
|
|
|
MHD_socket maxsock;
|
|
|
struct timeval timeout;
|
|
|
struct timeval *tv;
|
|
|
- MHD_UNSIGNED_LONG_LONG ltimeout;
|
|
|
int err_state;
|
|
|
MHD_socket ls;
|
|
|
|
|
|
@@ -4033,7 +4064,7 @@ MHD_select (struct MHD_Daemon *daemon,
|
|
|
if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
|
|
|
(MHD_NO != resume_suspended_connections (daemon)) &&
|
|
|
(0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
|
|
|
- may_block = MHD_NO;
|
|
|
+ millisec = 0;
|
|
|
|
|
|
if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
|
|
|
{
|
|
|
@@ -4118,25 +4149,47 @@ MHD_select (struct MHD_Daemon *daemon,
|
|
|
FD_CLR (ls,
|
|
|
&rs);
|
|
|
}
|
|
|
- tv = NULL;
|
|
|
+
|
|
|
if (MHD_NO != err_state)
|
|
|
- may_block = MHD_NO;
|
|
|
- if (MHD_NO == may_block)
|
|
|
+ millisec = 0;
|
|
|
+ tv = NULL;
|
|
|
+ if (0 == millisec)
|
|
|
{
|
|
|
timeout.tv_usec = 0;
|
|
|
timeout.tv_sec = 0;
|
|
|
tv = &timeout;
|
|
|
}
|
|
|
- else if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
|
|
|
- (MHD_NO != MHD_get_timeout (daemon, <imeout)) )
|
|
|
+ else
|
|
|
{
|
|
|
- /* ltimeout is in ms */
|
|
|
- timeout.tv_usec = (ltimeout % 1000) * 1000;
|
|
|
- if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
|
|
|
- timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
|
|
|
- else
|
|
|
- timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (ltimeout / 1000);
|
|
|
- tv = &timeout;
|
|
|
+ MHD_UNSIGNED_LONG_LONG ltimeout;
|
|
|
+
|
|
|
+ if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
|
|
|
+ (MHD_NO != MHD_get_timeout (daemon, <imeout)) )
|
|
|
+ {
|
|
|
+ tv = &timeout; /* have timeout value */
|
|
|
+ if ( (0 < millisec) &&
|
|
|
+ (ltimeout > (MHD_UNSIGNED_LONG_LONG) millisec) )
|
|
|
+ ltimeout = (MHD_UNSIGNED_LONG_LONG) millisec;
|
|
|
+ }
|
|
|
+ else if (0 < millisec)
|
|
|
+ {
|
|
|
+ tv = &timeout; /* have timeout value */
|
|
|
+ ltimeout = (MHD_UNSIGNED_LONG_LONG) millisec;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (NULL != tv)
|
|
|
+ { /* have timeout value */
|
|
|
+ if (ltimeout / 1000 > TIMEVAL_TV_SEC_MAX)
|
|
|
+ {
|
|
|
+ timeout.tv_sec = TIMEVAL_TV_SEC_MAX;
|
|
|
+ timeout.tv_usec = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ timeout.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) (ltimeout / 1000);
|
|
|
+ timeout.tv_usec = (ltimeout % 1000) * 1000;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
num_ready = MHD_SYS_select_ (maxsock + 1,
|
|
|
&rs,
|
|
|
@@ -4172,12 +4225,14 @@ MHD_select (struct MHD_Daemon *daemon,
|
|
|
* socket using poll().
|
|
|
*
|
|
|
* @param daemon daemon to run poll loop for
|
|
|
- * @param may_block #MHD_YES if blocking, #MHD_NO if non-blocking
|
|
|
+ * @param millisec the maximum time in milliseconds to wait for events,
|
|
|
+ * set to '0' for non-blocking processing,
|
|
|
+ * set to '-1' to wait indefinitely.
|
|
|
* @return #MHD_NO on serious errors, #MHD_YES on success
|
|
|
*/
|
|
|
static enum MHD_Result
|
|
|
MHD_poll_all (struct MHD_Daemon *daemon,
|
|
|
- int may_block)
|
|
|
+ int32_t millisec)
|
|
|
{
|
|
|
unsigned int num_connections;
|
|
|
struct MHD_Connection *pos;
|
|
|
@@ -4189,7 +4244,7 @@ MHD_poll_all (struct MHD_Daemon *daemon,
|
|
|
|
|
|
if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
|
|
|
(MHD_NO != resume_suspended_connections (daemon)) )
|
|
|
- may_block = MHD_NO;
|
|
|
+ millisec = 0;
|
|
|
|
|
|
/* count number of connections and thus determine poll set size */
|
|
|
num_connections = 0;
|
|
|
@@ -4200,7 +4255,6 @@ MHD_poll_all (struct MHD_Daemon *daemon,
|
|
|
num_connections += 2;
|
|
|
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
|
|
|
{
|
|
|
- MHD_UNSIGNED_LONG_LONG ltimeout;
|
|
|
unsigned int i;
|
|
|
int timeout;
|
|
|
unsigned int poll_server;
|
|
|
@@ -4243,14 +4297,8 @@ MHD_poll_all (struct MHD_Daemon *daemon,
|
|
|
poll_itc_idx = (int) poll_server;
|
|
|
poll_server++;
|
|
|
}
|
|
|
- if (may_block == MHD_NO)
|
|
|
- timeout = 0;
|
|
|
- else if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
|
|
|
- (MHD_NO == MHD_get_timeout (daemon,
|
|
|
- <imeout)) )
|
|
|
- timeout = -1;
|
|
|
- else
|
|
|
- timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
|
|
|
+
|
|
|
+ timeout = get_timeout_millisec_ (daemon, millisec);
|
|
|
|
|
|
i = 0;
|
|
|
for (pos = daemon->connections_tail; NULL != pos; pos = pos->prev)
|
|
|
@@ -4494,7 +4542,7 @@ MHD_poll (struct MHD_Daemon *daemon,
|
|
|
return MHD_NO;
|
|
|
if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
|
|
|
return MHD_poll_all (daemon,
|
|
|
- may_block);
|
|
|
+ may_block ? -1 : 0);
|
|
|
return MHD_poll_listen_socket (daemon,
|
|
|
may_block);
|
|
|
#else
|
|
|
@@ -4685,16 +4733,17 @@ static const char *const epoll_itc_marker = "itc_marker";
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * Do epoll()-based processing (this function is allowed to
|
|
|
- * block if @a may_block is set to #MHD_YES).
|
|
|
+ * Do epoll()-based processing.
|
|
|
*
|
|
|
* @param daemon daemon to run poll loop for
|
|
|
- * @param may_block #MHD_YES if blocking, #MHD_NO if non-blocking
|
|
|
+ * @param millisec the maximum time in milliseconds to wait for events,
|
|
|
+ * set to '0' for non-blocking processing,
|
|
|
+ * set to '-1' to wait indefinitely.
|
|
|
* @return #MHD_NO on serious errors, #MHD_YES on success
|
|
|
*/
|
|
|
static enum MHD_Result
|
|
|
MHD_epoll (struct MHD_Daemon *daemon,
|
|
|
- int may_block)
|
|
|
+ int32_t millisec)
|
|
|
{
|
|
|
#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
|
|
|
static const char *const upgrade_marker = "upgrade_ptr";
|
|
|
@@ -4704,7 +4753,6 @@ MHD_epoll (struct MHD_Daemon *daemon,
|
|
|
struct epoll_event events[MAX_EVENTS];
|
|
|
struct epoll_event event;
|
|
|
int timeout_ms;
|
|
|
- MHD_UNSIGNED_LONG_LONG timeout_ll;
|
|
|
int num_events;
|
|
|
unsigned int i;
|
|
|
MHD_socket ls;
|
|
|
@@ -4790,23 +4838,9 @@ MHD_epoll (struct MHD_Daemon *daemon,
|
|
|
|
|
|
if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
|
|
|
(MHD_NO != resume_suspended_connections (daemon)) )
|
|
|
- may_block = MHD_NO;
|
|
|
+ millisec = 0;
|
|
|
|
|
|
- if (MHD_NO != may_block)
|
|
|
- {
|
|
|
- if (MHD_NO != MHD_get_timeout (daemon,
|
|
|
- &timeout_ll))
|
|
|
- {
|
|
|
- if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
|
|
|
- timeout_ms = INT_MAX;
|
|
|
- else
|
|
|
- timeout_ms = (int) timeout_ll;
|
|
|
- }
|
|
|
- else
|
|
|
- timeout_ms = -1;
|
|
|
- }
|
|
|
- else
|
|
|
- timeout_ms = 0;
|
|
|
+ timeout_ms = get_timeout_millisec_ (daemon, millisec);
|
|
|
|
|
|
/* Reset. New value will be set when connections are processed. */
|
|
|
/* Note: Used mostly for uniformity here as same situation is
|
|
|
@@ -5026,24 +5060,69 @@ MHD_run (struct MHD_Daemon *daemon)
|
|
|
if ( (daemon->shutdown) ||
|
|
|
(0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
|
|
|
return MHD_NO;
|
|
|
+
|
|
|
+ (void) MHD_run_wait (daemon, 0);
|
|
|
+ return MHD_YES;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * Run websever operation with possible blocking.
|
|
|
+ * This function do the following: waits for any network event not more than
|
|
|
+ * specified number of milliseconds, processes all incoming and outgoing
|
|
|
+ * data, processes new connections, processes any timed-out connection, and
|
|
|
+ * do other things required to run webserver.
|
|
|
+ * Once all connections are processed, function returns.
|
|
|
+ * This function is useful for quick and simple webserver implementation if
|
|
|
+ * application needs to run a single thread only and does not have any other
|
|
|
+ * network activity.
|
|
|
+ * @param daemon the daemon to run
|
|
|
+ * @param millisec the maximum time in milliseconds to wait for network and
|
|
|
+ * other events. Note: there is no guarantee that function
|
|
|
+ * blocks for specified amount of time. The real processing
|
|
|
+ * time can be shorter (if some data comes earlier) or
|
|
|
+ * longer (if data processing requires more time, especially
|
|
|
+ * in the user callbacks).
|
|
|
+ * If set to '0' then function does not block and processes
|
|
|
+ * only already available data (if any).
|
|
|
+ * If set to '-1' then function waits for events
|
|
|
+ * indefinitely (blocks until next network activity).
|
|
|
+ * @return #MHD_YES on success, #MHD_NO if this
|
|
|
+ * daemon was not started with the right
|
|
|
+ * options for this call or some serious
|
|
|
+ * unrecoverable error occurs.
|
|
|
+ * @note Available since #MHD_VERSION 0x00097206
|
|
|
+ * @ingroup event
|
|
|
+ */
|
|
|
+enum MHD_Result
|
|
|
+MHD_run_wait (struct MHD_Daemon *daemon,
|
|
|
+ int32_t millisec)
|
|
|
+{
|
|
|
+ enum MHD_Result res;
|
|
|
+ if ( (daemon->shutdown) ||
|
|
|
+ (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
|
|
|
+ return MHD_NO;
|
|
|
+
|
|
|
+ if (0 > millisec)
|
|
|
+ millisec = -1;
|
|
|
if (0 != (daemon->options & MHD_USE_POLL))
|
|
|
{
|
|
|
- MHD_poll (daemon, MHD_NO);
|
|
|
+ res = MHD_poll_all (daemon, millisec);
|
|
|
MHD_cleanup_connections (daemon);
|
|
|
}
|
|
|
#ifdef EPOLL_SUPPORT
|
|
|
else if (0 != (daemon->options & MHD_USE_EPOLL))
|
|
|
{
|
|
|
- MHD_epoll (daemon, MHD_NO);
|
|
|
+ res = MHD_epoll (daemon, millisec);
|
|
|
MHD_cleanup_connections (daemon);
|
|
|
}
|
|
|
#endif
|
|
|
else
|
|
|
{
|
|
|
- MHD_select (daemon, MHD_NO);
|
|
|
+ res = MHD_select (daemon, millisec);
|
|
|
/* MHD_select does MHD_cleanup_connections already */
|
|
|
}
|
|
|
- return MHD_YES;
|
|
|
+ return res;
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -5139,10 +5218,10 @@ MHD_polling_thread (void *cls)
|
|
|
MHD_poll (daemon, MHD_YES);
|
|
|
#ifdef EPOLL_SUPPORT
|
|
|
else if (0 != (daemon->options & MHD_USE_EPOLL))
|
|
|
- MHD_epoll (daemon, MHD_YES);
|
|
|
+ MHD_epoll (daemon, -1);
|
|
|
#endif
|
|
|
else
|
|
|
- MHD_select (daemon, MHD_YES);
|
|
|
+ MHD_select (daemon, -1);
|
|
|
MHD_cleanup_connections (daemon);
|
|
|
}
|
|
|
|