mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
test case for external event loop
This commit is contained in:
@@ -4728,7 +4728,7 @@ MHD_FN_PAR_NONNULL_ALL_;
|
|||||||
* error code otherwise
|
* error code otherwise
|
||||||
*/
|
*/
|
||||||
#define MHD_daemon_set_option(daemon, option_ptr) \
|
#define MHD_daemon_set_option(daemon, option_ptr) \
|
||||||
MHD_daemon_set_options (daemon, options_ptr, 1)
|
MHD_daemon_set_options (daemon, option_ptr, 1)
|
||||||
|
|
||||||
|
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
@@ -6098,10 +6098,10 @@ MHD_response_from_callback (enum MHD_HTTP_StatusCode sc,
|
|||||||
* needs to be valid while the response is used
|
* needs to be valid while the response is used
|
||||||
* @param free_cb the callback to free any allocated data, called
|
* @param free_cb the callback to free any allocated data, called
|
||||||
* when response is being destroyed, can be NULL
|
* when response is being destroyed, can be NULL
|
||||||
* to skip the free/cleanup callback
|
* to skip the free/cleanup callback;
|
||||||
* @param free_cb_cls the parameter for @a free_cb
|
* @param free_cb_cls the parameter for @a free_cb
|
||||||
* @return NULL on error (i.e. invalid arguments, out of memory)
|
* @return NULL on error (i.e. invalid arguments, out of memory)
|
||||||
* FIXME: Call free callback on error?
|
* on error, @a free_cb is NOT called
|
||||||
* @ingroup response
|
* @ingroup response
|
||||||
*/
|
*/
|
||||||
MHD_EXTERN_ struct MHD_Response *
|
MHD_EXTERN_ struct MHD_Response *
|
||||||
@@ -6975,7 +6975,7 @@ MHD_upgraded_recv (struct MHD_UpgradedHandle *MHD_RESTRICT urh,
|
|||||||
void *MHD_RESTRICT recv_buf,
|
void *MHD_RESTRICT recv_buf,
|
||||||
size_t *MHD_RESTRICT received_size,
|
size_t *MHD_RESTRICT received_size,
|
||||||
uint_fast64_t max_wait_millisec)
|
uint_fast64_t max_wait_millisec)
|
||||||
MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_SIZE_(3,2)
|
MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_OUT_SIZE_ (3,2)
|
||||||
MHD_FN_PAR_OUT_ (4);
|
MHD_FN_PAR_OUT_ (4);
|
||||||
|
|
||||||
|
|
||||||
@@ -7030,7 +7030,7 @@ MHD_upgraded_send (struct MHD_UpgradedHandle *MHD_RESTRICT urh,
|
|||||||
size_t *MHD_RESTRICT sent_size,
|
size_t *MHD_RESTRICT sent_size,
|
||||||
uint_fast64_t max_wait_millisec,
|
uint_fast64_t max_wait_millisec,
|
||||||
enum MHD_Bool more_data_to_come)
|
enum MHD_Bool more_data_to_come)
|
||||||
MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_SIZE_(3,2)
|
MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_SIZE_ (3,2)
|
||||||
MHD_FN_PAR_OUT_ (4);
|
MHD_FN_PAR_OUT_ (4);
|
||||||
|
|
||||||
|
|
||||||
@@ -8365,7 +8365,7 @@ MHD_response_add_auth_basic_challenge (
|
|||||||
struct MHD_Response *MHD_RESTRICT response,
|
struct MHD_Response *MHD_RESTRICT response,
|
||||||
const char *MHD_RESTRICT realm,
|
const char *MHD_RESTRICT realm,
|
||||||
enum MHD_Bool prefer_utf8)
|
enum MHD_Bool prefer_utf8)
|
||||||
MHD_FN_PAR_NONNULL_(2) MHD_FN_PAR_CSTR_ (2);
|
MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_CSTR_ (2);
|
||||||
|
|
||||||
#ifndef MHD_NO_STATIC_INLINE
|
#ifndef MHD_NO_STATIC_INLINE
|
||||||
|
|
||||||
|
|||||||
@@ -741,6 +741,19 @@ MHDT_server_setup_minimal (const void *cls,
|
|||||||
struct MHD_Daemon *d);
|
struct MHD_Daemon *d);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize MHD daemon for an external event loop.
|
||||||
|
* Must be used together with #MHDT_server_run_external().
|
||||||
|
*
|
||||||
|
* @param cls closure (use NULL)
|
||||||
|
* @param[in,out] d daemon to initialize
|
||||||
|
* @return error message, NULL on success
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
MHDT_server_setup_external (const void *cls,
|
||||||
|
struct MHD_Daemon *d);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize MHD daemon with TLS support, binding to any free port.
|
* Initialize MHD daemon with TLS support, binding to any free port.
|
||||||
*
|
*
|
||||||
@@ -824,6 +837,20 @@ MHDT_server_run_blocking (void *cls,
|
|||||||
struct MHD_Daemon *d);
|
struct MHD_Daemon *d);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that runs an MHD daemon with an external event loop until
|
||||||
|
* a read() against @a finsig succeeds.
|
||||||
|
*
|
||||||
|
* @param cls closure
|
||||||
|
* @param finsig fd to read from to detect termination request
|
||||||
|
* @param[in,out] d daemon to run
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
MHDT_server_run_external (void *cls,
|
||||||
|
int finsig,
|
||||||
|
struct MHD_Daemon *d);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run test suite with @a phases for a daemon initialized
|
* Run test suite with @a phases for a daemon initialized
|
||||||
* using @a ss_cb on the local machine.
|
* using @a ss_cb on the local machine.
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
@@ -290,3 +291,200 @@ MHDT_server_run_blocking (void *cls,
|
|||||||
"Failed to drain termination signal\n");
|
"Failed to drain termination signal\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int my_epoll_fd = -1;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The callback for registration/de-registration of the sockets to watch.
|
||||||
|
*
|
||||||
|
* This callback must not call #MHD_daemon_destroy(), #MHD_daemon_quiesce(),
|
||||||
|
* #MHD_daemon_add_connection().
|
||||||
|
*
|
||||||
|
* @param cls the closure
|
||||||
|
* @param fd the socket to watch
|
||||||
|
* @param watch_for the states of the @a fd to watch, if set to
|
||||||
|
* #MHD_FD_STATE_NONE the socket must be de-registred
|
||||||
|
* @param app_cntx_old the old application defined context for the socket,
|
||||||
|
* NULL if @a fd socket was not registered before
|
||||||
|
* @param ecb_cntx the context handle to be used
|
||||||
|
* with #MHD_daemon_event_update()
|
||||||
|
* @return NULL if error (to connection will be aborted),
|
||||||
|
* or the new socket context
|
||||||
|
* @ingroup event
|
||||||
|
*/
|
||||||
|
static void *
|
||||||
|
update_fd (
|
||||||
|
void *cls,
|
||||||
|
MHD_Socket fd,
|
||||||
|
enum MHD_FdState watch_for,
|
||||||
|
MHD_APP_SOCKET_CNTX_TYPE *app_cntx_old,
|
||||||
|
struct MHD_EventUpdateContext *ecb_cntx)
|
||||||
|
{
|
||||||
|
struct epoll_event ev;
|
||||||
|
|
||||||
|
if (watch_for == MHD_FD_STATE_NONE)
|
||||||
|
{
|
||||||
|
epoll_ctl (my_epoll_fd,
|
||||||
|
EPOLL_CTL_DEL,
|
||||||
|
fd,
|
||||||
|
&ev /* for Linux 2.6.9-compatibility */);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ev.data.ptr = ecb_cntx;
|
||||||
|
ev.events = 0;
|
||||||
|
if (0 != (watch_for & MHD_FD_STATE_RECV))
|
||||||
|
ev.events |= EPOLLIN;
|
||||||
|
if (0 != (watch_for & MHD_FD_STATE_SEND))
|
||||||
|
ev.events |= EPOLLOUT;
|
||||||
|
if (0 != (watch_for & MHD_FD_STATE_EXCEPT))
|
||||||
|
ev.events |= EPOLLRDHUP | EPOLLHUP | EPOLLERR;
|
||||||
|
if (0 !=
|
||||||
|
epoll_ctl (my_epoll_fd,
|
||||||
|
NULL == app_cntx_old
|
||||||
|
? EPOLL_CTL_ADD
|
||||||
|
: EPOLL_CTL_MOD,
|
||||||
|
fd,
|
||||||
|
&ev))
|
||||||
|
{
|
||||||
|
fprintf (stderr,
|
||||||
|
"epoll_ctl failed: %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ecb_cntx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *
|
||||||
|
MHDT_server_setup_external (const void *cls,
|
||||||
|
struct MHD_Daemon *d)
|
||||||
|
{
|
||||||
|
(void) cls;
|
||||||
|
if (MHD_SC_OK !=
|
||||||
|
MHD_DAEMON_SET_OPTIONS (
|
||||||
|
d,
|
||||||
|
MHD_D_OPTION_WM_EXTERNAL_EVENT_LOOP_CB_LEVEL (&update_fd,
|
||||||
|
NULL)))
|
||||||
|
return "Failed to configure external mode!";
|
||||||
|
if (MHD_SC_OK !=
|
||||||
|
MHD_DAEMON_SET_OPTIONS (
|
||||||
|
d,
|
||||||
|
MHD_D_OPTION_BIND_PORT (MHD_AF_AUTO,
|
||||||
|
0)))
|
||||||
|
return "Failed to bind to port 0!";
|
||||||
|
my_epoll_fd = epoll_create1 (0);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MHDT_server_run_external (void *cls,
|
||||||
|
int finsig,
|
||||||
|
struct MHD_Daemon *d)
|
||||||
|
{
|
||||||
|
fd_set r;
|
||||||
|
|
||||||
|
(void) cls; /* Unused */
|
||||||
|
if (-1 == my_epoll_fd)
|
||||||
|
abort ();
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
uint_fast64_t next_wait;
|
||||||
|
struct timeval timeout;
|
||||||
|
|
||||||
|
if (MHD_SC_OK !=
|
||||||
|
MHD_daemon_process_reg_events (d,
|
||||||
|
&next_wait))
|
||||||
|
{
|
||||||
|
fprintf (stderr,
|
||||||
|
"MHD_daemon_process_reg_events() failed\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
timeout.tv_usec = next_wait;
|
||||||
|
|
||||||
|
FD_ZERO (&r);
|
||||||
|
FD_SET (finsig,
|
||||||
|
&r);
|
||||||
|
FD_SET (my_epoll_fd,
|
||||||
|
&r);
|
||||||
|
if ( (-1 ==
|
||||||
|
select ((my_epoll_fd > finsig ? my_epoll_fd : finsig) + 1,
|
||||||
|
&r,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&timeout)) &&
|
||||||
|
(EAGAIN != errno) )
|
||||||
|
{
|
||||||
|
fprintf (stderr,
|
||||||
|
"Failure in select(): %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (FD_ISSET (finsig,
|
||||||
|
&r))
|
||||||
|
break;
|
||||||
|
if (FD_ISSET (my_epoll_fd,
|
||||||
|
&r))
|
||||||
|
{
|
||||||
|
int maxevents = 40;
|
||||||
|
struct epoll_event events[maxevents];
|
||||||
|
int n;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
n = epoll_wait (my_epoll_fd,
|
||||||
|
events,
|
||||||
|
maxevents,
|
||||||
|
0);
|
||||||
|
if (-1 == n)
|
||||||
|
{
|
||||||
|
fprintf (stderr,
|
||||||
|
"epoll_wait() failed: %s\n",
|
||||||
|
strerror (errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
enum MHD_FdState state = MHD_FD_STATE_NONE;
|
||||||
|
|
||||||
|
if (0 != (events[i].events & EPOLLIN))
|
||||||
|
state |= MHD_FD_STATE_RECV;
|
||||||
|
if (0 != (events[i].events & EPOLLOUT))
|
||||||
|
state |= MHD_FD_STATE_SEND;
|
||||||
|
if (0 != (events[i].events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) )
|
||||||
|
state |= MHD_FD_STATE_EXCEPT;
|
||||||
|
MHD_daemon_event_update (d,
|
||||||
|
events[i].data.ptr,
|
||||||
|
state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MHD_SC_OK !=
|
||||||
|
MHD_daemon_process_blocking (d,
|
||||||
|
1000))
|
||||||
|
{
|
||||||
|
fprintf (stderr,
|
||||||
|
"Failure running MHD_daemon_process_blocking()\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
|
||||||
|
if ( (FD_ISSET (finsig,
|
||||||
|
&r)) &&
|
||||||
|
(1 != read (finsig,
|
||||||
|
&c,
|
||||||
|
1)) )
|
||||||
|
{
|
||||||
|
fprintf (stderr,
|
||||||
|
"Failed to drain termination signal\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close (my_epoll_fd);
|
||||||
|
my_epoll_fd = -1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -138,6 +138,12 @@ main (int argc, char *argv[])
|
|||||||
.server_setup_cls = external0auto,
|
.server_setup_cls = external0auto,
|
||||||
.server_runner = &MHDT_server_run_blocking,
|
.server_runner = &MHDT_server_run_blocking,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.label = "auto-selected external event loop mode, no threads",
|
||||||
|
.server_setup = &MHDT_server_setup_external,
|
||||||
|
.server_setup_cls = NULL,
|
||||||
|
.server_runner = &MHDT_server_run_external,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.label = "END"
|
.label = "END"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user