30#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
31#include "mhd_threads.h"
40#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
56#ifdef MHD_HTTPS_REQUIRE_GRYPT
61#if defined(_WIN32) && ! defined(__CYGWIN__)
62#ifndef WIN32_LEAN_AND_MEAN
63#define WIN32_LEAN_AND_MEAN 1
68#ifdef MHD_USE_POSIX_THREADS
77#ifdef MHD_POSIX_SOCKETS
78#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 4)
80#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2)
86#define MHD_POOL_SIZE_DEFAULT (32 * 1024)
128_MHD_NORETURN
static void
137 _ (
"Fatal error in GNU libmicrohttpd %s:%u: %s\n"),
167#if defined(MHD_WINSOCK_SOCKETS)
171static int mhd_winsock_inited_ = 0;
174#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
179#define MHD_check_global_init_() (void) 0
186#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
187#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
191MHD_MUTEX_STATIC_DEFN_INIT_ (global_init_mutex_);
203#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
204#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
210#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
211#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
225MHD_default_logger_ (
void *cls,
229 vfprintf ((FILE *) cls, fm, ap);
231 fflush ((FILE *) cls);
292 struct in6_addr ipv6;
311#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
327#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
350 offsetof (
struct MHD_IPCount,
366 struct MHD_IPCount *key)
373 if (
sizeof (
struct sockaddr_in) == addrlen)
375 const struct sockaddr_in *addr4 = (
const struct sockaddr_in *) addr;
377 key->family = AF_INET;
378 memcpy (&key->addr.ipv4,
380 sizeof(addr4->sin_addr));
386 if (
sizeof (
struct sockaddr_in6) == addrlen)
388 const struct sockaddr_in6 *addr6 = (
const struct sockaddr_in6 *) addr;
390 key->family = AF_INET6;
391 memcpy (&key->addr.ipv6,
393 sizeof(addr6->sin6_addr));
416 const struct sockaddr *addr,
419 struct MHD_IPCount *key;
429 if (
NULL == (key = malloc (
sizeof(*key))))
450 _ (
"Failed to add IP connection count node.\n"));
460 key = (
struct MHD_IPCount *) node;
482 const struct sockaddr *addr,
485 struct MHD_IPCount search_key;
486 struct MHD_IPCount *found_key;
508 MHD_PANIC (
_ (
"Failed to find previously-added IP address.\n"));
510 found_key = (
struct MHD_IPCount *) *nodep;
512 if (0 == found_key->count)
514 MHD_PANIC (
_ (
"Previously-added IP address had counter of zero.\n"));
517 if (0 == --found_key->count)
537MHD_init_daemon_certificate (
struct MHD_Daemon *daemon)
543#if GNUTLS_VERSION_MAJOR >= 3
544 if (
NULL != daemon->cert_callback)
546 gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
547 daemon->cert_callback);
550#if GNUTLS_VERSION_NUMBER >= 0x030603
551 else if (
NULL != daemon->cert_callback2)
553 gnutls_certificate_set_retrieve_function3 (daemon->x509_cred,
554 daemon->cert_callback2);
558 if (
NULL != daemon->https_mem_trust)
561 paramlen = strlen (daemon->https_mem_trust);
566 _ (
"Too long trust certificate.\n"));
570 cert.data = (
unsigned char *) daemon->https_mem_trust;
571 cert.size = (
unsigned int) paramlen;
572 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred,
574 GNUTLS_X509_FMT_PEM) < 0)
578 _ (
"Bad trust certificate format.\n"));
584 if (daemon->have_dhparams)
586 gnutls_certificate_set_dh_params (daemon->x509_cred,
587 daemon->https_mem_dhparams);
590 if ( (
NULL != daemon->https_mem_cert) &&
591 (
NULL != daemon->https_mem_key) )
596 param1len = strlen (daemon->https_mem_key);
597 param2len = strlen (daemon->https_mem_cert);
603 _ (
"Too long key or certificate.\n"));
607 key.data = (
unsigned char *) daemon->https_mem_key;
608 key.size = (
unsigned int) param1len;
609 cert.data = (
unsigned char *) daemon->https_mem_cert;
610 cert.size = (
unsigned int) param2len;
612 if (
NULL != daemon->https_key_password)
614#if GNUTLS_VERSION_NUMBER >= 0x030111
615 ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
619 daemon->https_key_password,
624 _ (
"Failed to setup x509 certificate/key: pre 3.X.X version " \
625 "of GnuTLS does not support setting key password.\n"));
631 ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
634 GNUTLS_X509_FMT_PEM);
638 _ (
"GnuTLS failed to setup x509 certificate/key: %s\n"),
639 gnutls_strerror (ret));
643#if GNUTLS_VERSION_MAJOR >= 3
644 if (
NULL != daemon->cert_callback)
647#if GNUTLS_VERSION_NUMBER >= 0x030603
648 else if (
NULL != daemon->cert_callback2)
653 _ (
"You need to specify a certificate and key location.\n"));
668 switch (daemon->cred_type)
670 case GNUTLS_CRD_CERTIFICATE:
672 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
673 return GNUTLS_E_MEMORY_ERROR;
674 return MHD_init_daemon_certificate (daemon);
677 gnutls_psk_allocate_server_credentials (&daemon->psk_cred))
678 return GNUTLS_E_MEMORY_ERROR;
683 _ (
"Error: invalid credentials type %d specified.\n"),
730 fd_set *write_fd_set,
731 fd_set *except_fd_set,
743#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
757urh_to_fdset (
struct MHD_UpgradeResponseHandle *urh,
762 unsigned int fd_setsize)
764 const MHD_socket conn_sckt = urh->connection->socket_fd;
772 if ( (urh->in_buffer_used < urh->in_buffer_size) &&
778 if ( (0 != urh->out_buffer_used) &&
787 ((0 != urh->in_buffer_size) ||
788 (0 != urh->out_buffer_size) ||
789 (0 != urh->out_buffer_used)))
797 if ( (urh->out_buffer_used < urh->out_buffer_size) &&
803 if ( (0 != urh->in_buffer_used) &&
812 ((0 != urh->out_buffer_size) ||
813 (0 != urh->in_buffer_size) ||
814 (0 != urh->in_buffer_used)))
835urh_from_fdset (
struct MHD_UpgradeResponseHandle *urh,
840 const MHD_socket conn_sckt = urh->connection->socket_fd;
851 if (FD_ISSET (conn_sckt, rs))
853 if (FD_ISSET (conn_sckt, ws))
855 if (FD_ISSET (conn_sckt, es))
860 if (FD_ISSET (mhd_sckt, rs))
862 if (FD_ISSET (mhd_sckt, ws))
864 if (FD_ISSET (mhd_sckt, es))
881urh_update_pollfd (
struct MHD_UpgradeResponseHandle *urh,
887 if (urh->in_buffer_used < urh->in_buffer_size)
888 p[0].events |= POLLIN;
889 if (0 != urh->out_buffer_used)
890 p[0].events |= POLLOUT;
895 ((0 != urh->in_buffer_size) ||
896 (0 != urh->out_buffer_size) ||
897 (0 != urh->out_buffer_used)))
898 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
900 if (urh->out_buffer_used < urh->out_buffer_size)
901 p[1].events |= POLLIN;
902 if (0 != urh->in_buffer_used)
903 p[1].events |= POLLOUT;
908 ((0 != urh->out_buffer_size) ||
909 (0 != urh->in_buffer_size) ||
910 (0 != urh->in_buffer_used)))
911 p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
922urh_to_pollfd (
struct MHD_UpgradeResponseHandle *urh,
925 p[0].fd = urh->connection->socket_fd;
926 p[1].fd = urh->mhd.socket;
927 urh_update_pollfd (urh,
938urh_from_pollfd (
struct MHD_UpgradeResponseHandle *urh,
947 if (0 != (p[0].revents & POLLIN))
949 if (0 != (p[0].revents & POLLOUT))
951 if (0 != (p[0].revents & POLLHUP))
953 if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
955 if (0 != (p[1].revents & POLLIN))
957 if (0 != (p[1].revents & POLLOUT))
959 if (0 != (p[1].revents & POLLHUP))
961 if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
987 fd_set *write_fd_set,
988 fd_set *except_fd_set,
990 unsigned int fd_setsize)
1026#ifdef MHD_POSIX_SOCKETS
1039#ifdef MHD_POSIX_SOCKETS
1047 if ( (
NULL == except_fd_set) ||
1059#ifdef MHD_WINSOCK_SOCKETS
1072#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1074 struct MHD_UpgradeResponseHandle *urh;
1076 for (urh = daemon->urh_tail;
NULL != urh; urh = urh->prev)
1089#if _MHD_DEBUG_CONNECT
1093 _ (
"Maximum socket in select set: %d\n"),
1137 fd_set *read_fd_set,
1138 fd_set *write_fd_set,
1139 fd_set *except_fd_set,
1141 unsigned int fd_setsize)
1145 if ( (
NULL == daemon) ||
1146 (
NULL == read_fd_set) ||
1147 (
NULL == write_fd_set) ||
1152 if (
NULL == except_fd_set)
1156 _ (
"MHD_get_fdset2() called with except_fd_set "
1157 "set to NULL. Such behavior is unsupported.\n"));
1160 except_fd_set = &es;
1208 bool states_info_processed =
false;
1217 (read_ready || (force_close && con->
sk_nonblck)) )
1224 states_info_processed =
true;
1235 states_info_processed =
true;
1245 if (! states_info_processed)
1302#ifdef UPGRADE_SUPPORT
1313 struct MHD_UpgradeResponseHandle *urh = connection->urh;
1321 gnutls_bye (connection->tls_session,
1330 connection->urh =
NULL;
1338#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1348process_urh (
struct MHD_UpgradeResponseHandle *urh)
1361#ifdef MHD_USE_THREADS
1363 MHD_thread_ID_match_current_ (connection->
pid) );
1369 if (! urh->was_closed)
1373 "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
1376 urh->was_closed =
true;
1378 was_closed = urh->was_closed;
1383 if (0 < urh->in_buffer_used)
1387 _ (
"Failed to forward to application "
1389 " bytes of data received from remote side: application shut down socket.\n"),
1390 (uint64_t) urh->in_buffer_used);
1399 if (0 != urh->out_buffer_size)
1402 urh->in_buffer_used = 0;
1406 urh->in_buffer_size = 0;
1428 (urh->in_buffer_used < urh->in_buffer_size) )
1433 buf_size = urh->in_buffer_size - urh->in_buffer_used;
1438 res = gnutls_record_recv (connection->tls_session,
1439 &urh->in_buffer[urh->in_buffer_used],
1443 if (GNUTLS_E_INTERRUPTED != res)
1446 if (GNUTLS_E_AGAIN != res)
1451 urh->in_buffer_size = 0;
1457 urh->in_buffer_used += res;
1458 if (0 < gnutls_record_check_pending (connection->tls_session))
1469 urh->in_buffer_size = 0;
1477 (urh->out_buffer_used < urh->out_buffer_size) )
1482 buf_size = urh->out_buffer_size - urh->out_buffer_used;
1487 &urh->out_buffer[urh->out_buffer_used],
1506 urh->out_buffer_size = 0;
1512 urh->out_buffer_used += res;
1513 if (buf_size > (
size_t) res)
1523 urh->out_buffer_size = 0;
1531 (urh->out_buffer_used > 0) )
1536 data_size = urh->out_buffer_used;
1540 res = gnutls_record_send (connection->tls_session,
1545 if (GNUTLS_E_INTERRUPTED != res)
1548 if (GNUTLS_E_AGAIN != res)
1555 "Failed to forward to remote client "
1557 " bytes of data received from application: %s\n"),
1558 (uint64_t) urh->out_buffer_used,
1559 gnutls_strerror (res));
1562 urh->out_buffer_used = 0;
1564 urh->out_buffer_size = 0;
1571 const size_t next_out_buffer_used = urh->out_buffer_used - res;
1572 if (0 != next_out_buffer_used)
1574 memmove (urh->out_buffer,
1575 &urh->out_buffer[res],
1576 next_out_buffer_used);
1577 if (data_size > (
size_t) res)
1580 urh->out_buffer_used = next_out_buffer_used;
1582 if ( (0 == urh->out_buffer_used) &&
1590 urh->out_buffer_size = 0;
1599 (urh->in_buffer_used > 0) )
1604 data_size = urh->in_buffer_used;
1625 "Failed to forward to application "
1627 " bytes of data received from remote side: %s\n"),
1628 (uint64_t) urh->in_buffer_used,
1632 urh->in_buffer_used = 0;
1634 urh->in_buffer_size = 0;
1642 const size_t next_in_buffer_used = urh->in_buffer_used - res;
1643 if (0 != next_in_buffer_used)
1645 memmove (urh->in_buffer,
1646 &urh->in_buffer[res],
1647 next_in_buffer_used);
1648 if (data_size > (
size_t) res)
1651 urh->in_buffer_used = next_in_buffer_used;
1653 if ( (0 == urh->in_buffer_used) &&
1659 urh->in_buffer_size = 0;
1668 (urh->in_buffer_used < urh->in_buffer_size) &&
1673 ( (0 != urh->out_buffer_size) ||
1674 (0 != urh->out_buffer_used) ) )
1678 if (0 < urh->out_buffer_used)
1681 "Failed to forward to remote client "
1683 " bytes of data received from application: daemon shut down.\n"),
1684 (uint64_t) urh->out_buffer_used);
1687 urh->out_buffer_used = 0;
1691 urh->out_buffer_size = 0;
1699#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1700#ifdef UPGRADE_SUPPORT
1713 struct MHD_UpgradeResponseHandle *urh = con->urh;
1717 MHD_thread_ID_match_current_ (con->
pid) );
1724 while ( (0 != urh->in_buffer_size) ||
1725 (0 != urh->out_buffer_size) ||
1726 (0 != urh->in_buffer_used) ||
1727 (0 != urh->out_buffer_used) )
1741 result = urh_to_fdset (urh,
1751 _ (
"Error preparing select.\n"));
1758 struct timeval *tvp;
1761 (urh->in_buffer_used < urh->in_buffer_size)) ||
1786 _ (
"Error during select (%d): `%s'\n"),
1792 urh_from_fdset (urh,
1807 p[0].fd = urh->connection->socket_fd;
1808 p[1].fd = urh->mhd.socket;
1810 while ( (0 != urh->in_buffer_size) ||
1811 (0 != urh->out_buffer_size) ||
1812 (0 != urh->in_buffer_used) ||
1813 (0 != urh->out_buffer_used) )
1817 urh_update_pollfd (urh, p);
1820 (urh->in_buffer_used < urh->in_buffer_size)) ||
1826 if (MHD_sys_poll_ (p,
1836 _ (
"Error during poll: `%s'\n"),
1841 urh_from_pollfd (urh,
1873 uint64_t mseconds_left;
1878 if (timeout < since_actv)
1885 if (5000 >= jump_back)
1893 else if (since_actv == timeout)
1902 mseconds_left = timeout - since_actv;
1904 return mseconds_left;
1915static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
1926 struct timeval *tvp;
1931#define EXTRA_SLOTS 1
1933#define EXTRA_SLOTS 0
1942 const bool use_poll = 0;
1944 bool was_suspended =
false;
1945 MHD_thread_init_ (&(con->
pid));
1951#ifdef UPGRADE_SUPPORT
1952 struct MHD_UpgradeResponseHandle *
const urh = con->urh;
1954 static const void *
const urh =
NULL;
1961 was_suspended =
true;
1970 #ifdef HAVE_MESSAGES
1972 _ (
"Failed to add FD to fd_set.\n"));
1988 _ (
"Error during select (%d): `%s'\n"),
1998 p[0].events = POLLIN;
1999 p[0].fd = MHD_itc_r_fd_ (daemon->
itc);
2001 if (0 > MHD_sys_poll_ (p,
2009 _ (
"Error during poll: `%s'\n"),
2016 MHD_itc_clear_ (daemon->
itc);
2025 was_suspended =
false;
2043 if ( (
NULL == tvp) &&
2046 const uint64_t mseconds_left = connection_get_wait (con);
2047#if (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC
2054 tv.tv_usec = (mseconds_left % 1000) * 1000;
2061 bool err_state =
false;
2095 if (MHD_ITC_IS_VALID_ (daemon->
itc) )
2108 _ (
"Failed to add FD to fd_set.\n"));
2126 _ (
"Error during select (%d): `%s'\n"),
2135 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2136 (FD_ISSET (MHD_itc_r_fd_ (daemon->
itc),
2138 MHD_itc_clear_ (daemon->
itc);
2161 p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
2164 p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
2167 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
2175 if (MHD_ITC_IS_VALID_ (daemon->
itc))
2177 p[1].events |= POLLIN;
2178 p[1].fd = MHD_itc_r_fd_ (daemon->
itc);
2183 if (MHD_sys_poll_ (p,
2189 (
NULL == tvp) ? -1 : (tv.tv_sec * 1000)) < 0)
2195 _ (
"Error during poll: `%s'\n"),
2203 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2204 (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2205 MHD_itc_clear_ (daemon->
itc);
2209 (0 != (p[0].revents & POLLIN)),
2210 (0 != (p[0].revents & POLLOUT)),
2211 (0 != (p[0].revents & MHD_POLL_REVENTS_ERR_DISC)) ))
2215#ifdef UPGRADE_SUPPORT
2216 if (MHD_CONNECTION_UPGRADE == con->
state)
2228 thread_main_connection_upgrade (con);
2232 con->urh->clean_ready =
true;
2240 return (MHD_THRD_RTRN_TYPE_) 0;
2247 _ (
"Processing thread terminating. Closing connection.\n"));
2271 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2272 (! MHD_itc_activate_ (daemon->
itc,
"t")) )
2277 "Failed to signal thread termination via inter-thread communication channel.\n"));
2280 return (MHD_THRD_RTRN_TYPE_) 0;
2297#if defined(HTTPS_SUPPORT)
2298#if defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED) && \
2299 defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) && \
2300 ! defined(MHD_socket_nosignal_) && \
2301 (GNUTLS_VERSION_NUMBER + 0 < 0x030402) && defined(MSG_NOSIGNAL)
2307#define MHD_TLSLIB_NEED_PUSH_FUNC 1
2313#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2319MHD_tls_push_func_ (gnutls_transport_ptr_t trnsp,
2323#if (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX)
2343psk_gnutls_adapter (gnutls_session_t session,
2344 const char *username,
2345 gnutls_datum_t *key)
2349#if GNUTLS_VERSION_MAJOR >= 3
2351 size_t app_psk_size;
2354 connection = gnutls_session_get_ptr (session);
2355 if (
NULL == connection)
2359 MHD_PANIC (
_ (
"Internal server error. This should be impossible.\n"));
2363 daemon = connection->
daemon;
2364#if GNUTLS_VERSION_MAJOR >= 3
2365 if (
NULL == daemon->cred_callback)
2369 _ (
"PSK not supported by this server.\n"));
2373 if (0 != daemon->cred_callback (daemon->cred_callback_cls,
2379 if (
NULL == (key->data = gnutls_malloc (app_psk_size)))
2384 "PSK authentication failed: gnutls_malloc failed to allocate memory.\n"));
2393 _ (
"PSK authentication failed: PSK too long.\n"));
2398 key->size = (
unsigned int) app_psk_size;
2405 (void) username; (void) key;
2408 _ (
"PSK not supported by this server.\n"));
2443 const struct sockaddr *
addr,
2447 bool sk_spipe_supprs,
2454#if _MHD_DEBUG_CONNECT
2456 _ (
"Accepted connection on socket %d.\n"),
2469 "Server reached connection limit. Closing inbound connection.\n"));
2487 _ (
"Connection rejected by application. Closing connection.\n"));
2505 _ (
"Error allocating memory: %s\n"),
2527 if (
NULL == (connection->
addr = malloc (addrlen)))
2532 _ (
"Error allocating memory: %s\n"),
2543 memcpy (connection->
addr,
2549 connection->
is_nonip = sk_is_nonip;
2564#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030500)
2571 flags = GNUTLS_SERVER;
2572#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030402)
2573 flags |= GNUTLS_NO_SIGNAL;
2575#if GNUTLS_VERSION_MAJOR >= 3
2576 flags |= GNUTLS_NONBLOCK;
2578#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030603)
2580 flags |= GNUTLS_POST_HANDSHAKE_AUTH;
2582#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030605)
2584 flags |= GNUTLS_ENABLE_EARLY_DATA;
2588 if ((GNUTLS_E_SUCCESS != gnutls_init (&connection->tls_session, flags)) ||
2589 (GNUTLS_E_SUCCESS != gnutls_priority_set (connection->tls_session,
2590 daemon->priority_cache)))
2592 if (
NULL != connection->tls_session)
2593 gnutls_deinit (connection->tls_session);
2598 free (connection->
addr);
2602 _ (
"Failed to initialise TLS session.\n"));
2609#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030200)
2610 if (!
daemon->disable_alpn)
2612 gnutls_datum_t prts[2];
2613 const char prt1[] =
"http/1.1";
2614 const char prt2[] =
"http/1.0";
2616 prts[0].data = (
void *) prt1;
2618 prts[1].data = (
void *) prt2;
2620 if (GNUTLS_E_SUCCESS !=
2621 gnutls_alpn_set_protocols (connection->tls_session,
2623 sizeof(prts) /
sizeof(prts[0]),
2628 _ (
"Failed to set ALPN protocols.\n"));
2635 gnutls_session_set_ptr (connection->tls_session,
2637 switch (
daemon->cred_type)
2640 case GNUTLS_CRD_CERTIFICATE:
2641 gnutls_credentials_set (connection->tls_session,
2642 GNUTLS_CRD_CERTIFICATE,
2645 case GNUTLS_CRD_PSK:
2646 gnutls_credentials_set (connection->tls_session,
2649 gnutls_psk_set_server_credentials_function (
daemon->psk_cred,
2650 &psk_gnutls_adapter);
2656 "Failed to setup TLS credentials: unknown credential type %d.\n"),
2659 gnutls_deinit (connection->tls_session);
2664 free (connection->
addr);
2666 MHD_PANIC (
_ (
"Unknown credential type.\n"));
2672#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030109) && ! defined(_WIN64)
2673 gnutls_transport_set_int (connection->tls_session,
2674 (
int) (client_socket));
2676 gnutls_transport_set_ptr (connection->tls_session,
2677 (gnutls_transport_ptr_t) (intptr_t) (client_socket));
2679#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2680 gnutls_transport_set_push_function (connection->tls_session,
2681 MHD_tls_push_func_);
2683 if (
daemon->https_mem_trust)
2684 gnutls_certificate_server_set_request (connection->tls_session,
2685 GNUTLS_CERT_REQUEST);
2691 free (connection->
addr);
2693 MHD_PANIC (
_ (
"TLS connection on non-TLS daemon.\n"));
2703#ifdef MHD_USE_THREADS
2722 if (
NULL != connection->tls_session)
2725 gnutls_deinit (connection->tls_session);
2732 free (connection->
addr);
2758#ifdef MHD_USE_THREADS
2762 MHD_thread_ID_match_current_ (
daemon->
pid) );
2774 _ (
"Error allocating memory: %s\n"),
2790 _ (
"Server reached connection limit. "
2791 "Closing inbound connection.\n"));
2816#ifdef MHD_USE_THREADS
2822 daemon->thread_stack_size,
2831 _ (
"Failed to create a new thread because it would "
2832 "have exceeded the system limit on the number of "
2833 "threads or no system resources available.\n"));
2837 _ (
"Failed to create a thread: %s\n"),
2849#ifdef MHD_USE_THREADS
2857 struct epoll_event event;
2859 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2860 event.data.ptr = connection;
2861 if (0 != epoll_ctl (daemon->epoll_fd,
2869 _ (
"Call to epoll_ctl failed: %s\n"),
2886 daemon->eready_tail,
2920 if (
NULL != connection->tls_session)
2921 gnutls_deinit (connection->tls_session);
2926 free (connection->
addr);
2970 const struct sockaddr *addr,
2974 bool sk_spipe_supprs,
2979#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2989 _ (
"New connection socket descriptor (%d) is not less " \
2990 "than FD_SETSIZE (%d).\n"),
2991 (
int) client_socket,
3006 _ (
"Epoll mode supports only non-blocking sockets\n"));
3022 if (
NULL == connection)
3025 if ((external_add) &&
3038 if ((MHD_ITC_IS_VALID_ (
daemon->
itc)) &&
3039 (! MHD_itc_activate_ (
daemon->
itc,
"n")))
3041 #ifdef HAVE_MESSAGES
3043 _ (
"Failed to signal new connection via inter-thread " \
3044 "communication channel.\n"));
3088 _ (
"Failed to start serving new connection.\n"));
3092 }
while (
NULL != local_tail);
3111#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3114 MHD_thread_ID_match_current_ (daemon->
pid) );
3121#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3151 daemon->eready_tail,
3153 connection->epoll_state &=
3158 if (0 != epoll_ctl (daemon->epoll_fd,
3162 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
3163 connection->epoll_state &=
3169#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3212#ifdef MHD_USE_THREADS
3215 MHD_thread_ID_match_current_ (daemon->
pid) );
3220 "Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
3221#ifdef UPGRADE_SUPPORT
3222 if (
NULL != connection->urh)
3227 "Error: connection scheduled for \"upgrade\" cannot be suspended.\n"));
3251 "Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
3252#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3257#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3260 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
3261 (! MHD_itc_activate_ (daemon->
itc,
"r")) )
3266 "Failed to signal resume via inter-thread communication channel.\n"));
3289#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3292 MHD_thread_ID_match_current_ (
daemon->
pid) );
3296#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3312#ifdef UPGRADE_SUPPORT
3313 struct MHD_UpgradeResponseHandle *
const urh = pos->urh;
3315 static const void *
const urh =
NULL;
3319#ifdef UPGRADE_SUPPORT
3320 || ( (
NULL != urh) &&
3321 ( (! urh->was_closed) ||
3322 (! urh->clean_ready) ) )
3356 MHD_PANIC (
"Resumed connection was already in EREADY set.\n");
3360 daemon->eready_tail,
3369#ifdef UPGRADE_SUPPORT
3394#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3397 if ( (used_thr_p_c) &&
3400 if (! MHD_itc_activate_ (daemon->
itc,
3406 "Failed to signal resume of connection via inter-thread communication channel.\n"));
3444 const struct sockaddr *addr,
3448 bool sk_spipe_supprs;
3460 _ (
"MHD_add_connection() has been called for daemon started"
3461 " without MHD_USE_ITC flag.\nDaemon will not process newly"
3462 " added connection until any activity occurs in already"
3463 " added sockets.\n"));
3471 _ (
"Failed to set nonblocking mode on new client socket: %s\n"),
3479#ifndef MHD_WINSOCK_SOCKETS
3480 sk_spipe_supprs =
false;
3482 sk_spipe_supprs =
true;
3484#if defined(MHD_socket_nosignal_)
3485 if (! sk_spipe_supprs && ! MHD_socket_nosignal_ (client_socket))
3490 "Failed to suppress SIGPIPE on new client socket: %s\n"),
3508 sk_spipe_supprs =
true;
3516 _ (
"Failed to set noninheritable mode on new client socket.\n"));
3520#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3579 struct sockaddr_in6 addrstorage;
3581 struct sockaddr_in addrstorage;
3583 struct sockaddr *addr = (
struct sockaddr *) &addrstorage;
3588 bool sk_spipe_supprs;
3591#ifdef MHD_USE_THREADS
3593 MHD_thread_ID_match_current_ (daemon->
pid) );
3596 addrlen =
sizeof (addrstorage);
3599 sizeof (addrstorage));
3610#ifndef MHD_WINSOCK_SOCKETS
3613 sk_spipe_supprs =
true;
3620#ifdef MHD_ACCEPT_INHERIT_NONBLOCK
3625#ifndef MHD_WINSOCK_SOCKETS
3626 sk_spipe_supprs =
false;
3628 sk_spipe_supprs =
true;
3646 _ (
"Error accepting connection: %s\n"),
3663 _ (
"Hit process or system resource limit at FIRST " \
3664 "connection. This is really bad as there is no sane " \
3665 "way to proceed. Will try busy waiting for system " \
3666 "resources to become magically available.\n"));
3671#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3675#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3680 _ (
"Hit process or system resource limit at %u " \
3681 "connections, temporarily suspending accept(). " \
3682 "Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
3694 _ (
"Failed to set nonblocking mode on incoming connection " \
3708 _ (
"Failed to set noninheritable mode on incoming connection " \
3715#if defined(MHD_socket_nosignal_)
3716 if (! sk_spipe_supprs && ! MHD_socket_nosignal_ (s))
3720 _ (
"Failed to suppress SIGPIPE on incoming connection " \
3737 sk_spipe_supprs =
true;
3740#if _MHD_DEBUG_CONNECT
3742 _ (
"Accepted connection on socket %d\n"),
3771#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3773 MHD_thread_ID_match_current_ (
daemon->
pid) );
3782#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3786 (! MHD_join_thread_ (pos->
pid.handle)) )
3787 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
3789#ifdef UPGRADE_SUPPORT
3790 cleanup_upgraded_connection (pos);
3794 if (
NULL != pos->tls_session)
3795 gnutls_deinit (pos->tls_session);
3818 if ( (-1 !=
daemon->epoll_fd) &&
3827 if (0 != epoll_ctl (
daemon->epoll_fd,
3832 "Failed to remove FD from epoll set.\n"));
3850#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3856#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3898 uint64_t earliest_deadline;
3902#ifdef MHD_USE_THREADS
3904 MHD_thread_ID_match_current_ (
daemon->
pid) );
3911 _ (
"Illegal call to MHD_get_timeout.\n"));
3924#
if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
3935 earliest_tmot_conn =
NULL;
3936 earliest_deadline = 0;
3939 if ( (
NULL != pos) &&
3942 earliest_tmot_conn = pos;
3950 if ( (
NULL == earliest_tmot_conn) ||
3954 earliest_tmot_conn = pos;
3960 if (
NULL != earliest_tmot_conn)
3962 const uint64_t mssecond_left = connection_get_wait (earliest_tmot_conn);
3963#if SIZEOF_UINT64_T > SIZEOF_UNSIGNED_LONG_LONG
3968 *timeout = (
unsigned long long) mssecond_left;
3987 int32_t max_timeout)
3990 if (0 == max_timeout)
3994 return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
3996 if ( (0 > max_timeout) ||
3997 ((uint32_t) max_timeout > ulltimeout) )
3998 return (INT_MAX < ulltimeout) ? INT_MAX : (int) ulltimeout;
4000 return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
4016 const fd_set *read_fd_set,
4017 const fd_set *write_fd_set,
4018 const fd_set *except_fd_set)
4023#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4024 struct MHD_UpgradeResponseHandle *urh;
4025 struct MHD_UpgradeResponseHandle *urhn;
4034 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
4035 (FD_ISSET (MHD_itc_r_fd_ (daemon->
itc),
4037 MHD_itc_clear_ (daemon->
itc);
4054 while (
NULL != (pos = prev))
4070#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4072 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
4076 urh_from_fdset (urh,
4083 if ( (0 == urh->in_buffer_size) &&
4084 (0 == urh->out_buffer_size) &&
4085 (0 == urh->in_buffer_used) &&
4086 (0 == urh->out_buffer_used) )
4089 urh->clean_ready =
true;
4128 const fd_set *read_fd_set,
4129 const fd_set *write_fd_set,
4130 const fd_set *except_fd_set)
4136 if ((
NULL == read_fd_set) || (
NULL == write_fd_set))
4138 if (
NULL == except_fd_set)
4142 _ (
"MHD_run_from_select() called with except_fd_set "
4143 "set to NULL. Such behavior is deprecated.\n"));
4146 except_fd_set = &es;
4191 struct timeval timeout;
4197 timeout.tv_usec = 0;
4223 _ (
"Could not obtain daemon fdsets.\n"));
4240 _ (
"Could not add listen socket to fdset.\n"));
4245 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
4251#if defined(MHD_WINSOCK_SOCKETS)
4269 "Could not add control inter-thread communication channel FD to fdset.\n"));
4272#if defined(MHD_WINSOCK_SOCKETS)
4286 (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
4299 timeout.tv_usec = 0;
4311 if ( (0 < millisec) &&
4315 else if (0 < millisec)
4326 timeout.tv_usec = 0;
4331 timeout.tv_usec = (ltimeout % 1000) * 1000;
4349 _ (
"select failed: %s\n"),
4378 unsigned int num_connections;
4381#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4382 struct MHD_UpgradeResponseHandle *urh;
4383 struct MHD_UpgradeResponseHandle *urhn;
4391 num_connections = 0;
4394#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4395 for (urh = daemon->urh_head;
NULL != urh; urh = urh->next)
4396 num_connections += 2;
4401 unsigned int poll_server;
4408 sizeof (
struct pollfd));
4413 _ (
"Error allocating memory: %s\n"),
4426 p[poll_server].fd = ls;
4427 p[poll_server].events = POLLIN;
4428 p[poll_server].revents = 0;
4429 poll_listen = (int) poll_server;
4433 if (MHD_ITC_IS_VALID_ (daemon->
itc))
4435 p[poll_server].fd = MHD_itc_r_fd_ (daemon->
itc);
4436 p[poll_server].events = POLLIN;
4437 p[poll_server].revents = 0;
4438 poll_itc_idx = (int) poll_server;
4451 p[poll_server + i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
4454 p[poll_server + i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
4457 p[poll_server + i].events |= MHD_POLL_EVENTS_ERR_DISC;
4465#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4466 for (urh = daemon->urh_tail;
NULL != urh; urh = urh->prev)
4468 urh_to_pollfd (urh, &(p[poll_server + i]));
4472 if (0 == poll_server + num_connections)
4477 if (MHD_sys_poll_ (p,
4478 poll_server + num_connections,
4489 _ (
"poll failed: %s\n"),
4499 if ( (-1 != poll_itc_idx) &&
4500 (0 != (p[poll_itc_idx].revents & POLLIN)) )
4501 MHD_itc_clear_ (daemon->
itc);
4515 if ( (-1 != poll_listen) &&
4516 (0 != (p[poll_listen].revents & POLLIN)) )
4524 while (
NULL != (pos = prev))
4528 if (i >= num_connections)
4533 0 != (p[poll_server + i].revents & POLLIN),
4534 0 != (p[poll_server + i].revents & POLLOUT),
4535 0 != (p[poll_server + i].revents
4536 & MHD_POLL_REVENTS_ERR_DISC));
4539#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4540 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
4542 if (i >= num_connections)
4549 if ((p[poll_server + i].
fd != urh->connection->socket_fd) ||
4550 (p[poll_server + i + 1].fd != urh->mhd.socket))
4552 urh_from_pollfd (urh,
4553 &p[poll_server + i]);
4557 if ( (0 == urh->in_buffer_size) &&
4558 (0 == urh->out_buffer_size) &&
4559 (0 == urh->in_buffer_used) &&
4560 (0 == urh->out_buffer_used) )
4565 urh->clean_ready =
true;
4589MHD_poll_listen_socket (
struct MHD_Daemon *daemon,
4594 unsigned int poll_count;
4609 p[poll_count].fd = ls;
4610 p[poll_count].events = POLLIN;
4611 p[poll_count].revents = 0;
4612 poll_listen = poll_count;
4615 if (MHD_ITC_IS_VALID_ (daemon->
itc))
4617 p[poll_count].fd = MHD_itc_r_fd_ (daemon->
itc);
4618 p[poll_count].events = POLLIN;
4619 p[poll_count].revents = 0;
4620 poll_itc_idx = poll_count;
4631 if (0 == poll_count)
4633 if (MHD_sys_poll_ (p,
4643 _ (
"poll failed: %s\n"),
4648 if ( (-1 != poll_itc_idx) &&
4649 (0 != (p[poll_itc_idx].revents & POLLIN)) )
4650 MHD_itc_clear_ (daemon->
itc);
4660 if ( (-1 != poll_listen) &&
4661 (0 != (p[poll_listen].revents & POLLIN)) )
4685 return MHD_poll_all (daemon,
4686 may_block ? -1 : 0);
4687 return MHD_poll_listen_socket (daemon,
4707#define MAX_EVENTS 128
4710#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4720is_urh_ready (
struct MHD_UpgradeResponseHandle *
const urh)
4724 if ( (0 == urh->in_buffer_size) &&
4725 (0 == urh->out_buffer_size) &&
4726 (0 == urh->in_buffer_used) &&
4727 (0 == urh->out_buffer_used) )
4733 (urh->in_buffer_used < urh->in_buffer_size) )
4736 (urh->out_buffer_used < urh->out_buffer_size) )
4739 (urh->out_buffer_used > 0) )
4742 (urh->in_buffer_used > 0) )
4759 struct epoll_event events[MAX_EVENTS];
4761 struct MHD_UpgradeResponseHandle *pos;
4762 struct MHD_UpgradeResponseHandle *prev;
4764#ifdef MHD_USE_THREADS
4766 MHD_thread_ID_match_current_ (daemon->
pid) );
4769 num_events = MAX_EVENTS;
4770 while (0 != num_events)
4774 num_events = epoll_wait (daemon->epoll_upgrade_fd,
4778 if (-1 == num_events)
4786 _ (
"Call to epoll_wait failed: %s\n"),
4791 for (i = 0; i < (
unsigned int) num_events; i++)
4793 struct UpgradeEpollHandle *
const ueh = events[i].data.ptr;
4794 struct MHD_UpgradeResponseHandle *
const urh = ueh->urh;
4795 bool new_err_state =
false;
4797 if (urh->clean_ready)
4801 if (0 != (events[i].events & EPOLLIN))
4805 if (0 != (events[i].events & EPOLLOUT))
4809 if (0 != (events[i].events & EPOLLHUP))
4815 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
4820 new_err_state =
true;
4822 if (! urh->in_eready_list)
4824 if (new_err_state ||
4828 daemon->eready_urh_tail,
4830 urh->in_eready_list =
true;
4835 prev = daemon->eready_urh_tail;
4836 while (
NULL != (pos = prev))
4840 if (! is_urh_ready (pos))
4843 daemon->eready_urh_tail,
4845 pos->in_eready_list =
false;
4848 if ( (0 == pos->in_buffer_size) &&
4849 (0 == pos->out_buffer_size) &&
4850 (0 == pos->in_buffer_used) &&
4851 (0 == pos->out_buffer_used) )
4854 pos->clean_ready =
true;
4873static const char *
const epoll_itc_marker =
"itc_marker";
4889#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4890 static const char *
const upgrade_marker =
"upgrade_ptr";
4894 struct epoll_event events[MAX_EVENTS];
4895 struct epoll_event event;
4900#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4901 bool run_upgraded =
false;
4903 bool need_to_accept;
4905 if (-1 == daemon->epoll_fd)
4912 (! daemon->listen_socket_in_epoll) &&
4915 event.events = EPOLLIN;
4916 event.data.ptr = daemon;
4917 if (0 != epoll_ctl (daemon->epoll_fd,
4924 _ (
"Call to epoll_ctl failed: %s\n"),
4929 daemon->listen_socket_in_epoll =
true;
4932 (daemon->listen_socket_in_epoll) )
4934 if ( (0 != epoll_ctl (daemon->epoll_fd,
4940 MHD_PANIC (
"Failed to remove listen FD from epoll set.\n");
4941 daemon->listen_socket_in_epoll =
false;
4944#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4945 if ( ( (! daemon->upgrade_fd_in_epoll) &&
4946 (-1 != daemon->epoll_upgrade_fd) ) )
4948 event.events = EPOLLIN | EPOLLOUT;
4949 event.data.ptr = (
void *) upgrade_marker;
4950 if (0 != epoll_ctl (daemon->epoll_fd,
4952 daemon->epoll_upgrade_fd,
4957 _ (
"Call to epoll_ctl failed: %s\n"),
4962 daemon->upgrade_fd_in_epoll =
true;
4965 if ( (daemon->listen_socket_in_epoll) &&
4972 if (0 != epoll_ctl (daemon->epoll_fd,
4976 MHD_PANIC (
_ (
"Failed to remove listen FD from epoll set.\n"));
4977 daemon->listen_socket_in_epoll =
false;
4991 need_to_accept =
false;
4996 num_events = MAX_EVENTS;
4997 while (MAX_EVENTS == num_events)
5000 num_events = epoll_wait (daemon->epoll_fd,
5004 if (-1 == num_events)
5011 _ (
"Call to epoll_wait failed: %s\n"),
5016 for (i = 0; i < (
unsigned int) num_events; i++)
5022#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5023 if (upgrade_marker == events[i].
data.ptr)
5027 run_upgraded =
true;
5031 if (epoll_itc_marker == events[i].
data.ptr)
5035 MHD_itc_clear_ (daemon->
itc);
5038 if (daemon == events[i].
data.ptr)
5042 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
5043 need_to_accept =
true;
5049 pos = events[i].data.ptr;
5051 if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
5057 daemon->eready_tail,
5064 if (0 != (events[i].events & EPOLLIN))
5072 daemon->eready_tail,
5077 if (0 != (events[i].events & EPOLLOUT))
5084 daemon->eready_tail,
5099 unsigned int series_length = 0;
5106 (series_length < 10) &&
5121 while (
NULL != (pos = prev))
5131 while (
NULL != (pos = prev))
5139#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5140 if (run_upgraded || (
NULL != daemon->eready_urh_head))
5141 run_epoll_for_upgrade (daemon);
5145 prev = daemon->eready_tail;
5146 while (
NULL != (pos = prev))
5164 daemon->eready_tail,
5274 res = MHD_poll_all (daemon, millisec);
5281 res = MHD_epoll (daemon, millisec);
5307#ifdef MHD_USE_THREADS
5309 MHD_thread_ID_match_current_ (daemon->
pid) );
5319#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5339#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5345#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5353static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
5357#ifdef HAVE_PTHREAD_SIGMASK
5362 MHD_thread_init_ (&(daemon->
pid));
5363#ifdef HAVE_PTHREAD_SIGMASK
5364 if ((0 == sigemptyset (&s_mask)) &&
5365 (0 == sigaddset (&s_mask, SIGPIPE)))
5367 err = pthread_sigmask (SIG_BLOCK, &s_mask,
NULL);
5376 _ (
"Failed to block SIGPIPE on daemon thread: %s\n"),
5386 MHD_epoll (daemon, -1);
5400 return (MHD_THRD_RTRN_TYPE_) 0;
5498#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5512 "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC.\n"));
5517#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5527 if (0 != epoll_ctl (daemon->
worker_pool[i].epoll_fd,
5531 MHD_PANIC (
_ (
"Failed to remove listen FD from epoll set.\n"));
5532 daemon->
worker_pool[i].listen_socket_in_epoll =
false;
5540 "Failed to signal quiesce via inter-thread communication channel.\n"));
5547 (-1 != daemon->epoll_fd) &&
5548 (daemon->listen_socket_in_epoll) )
5550 if ( (0 != epoll_ctl (daemon->epoll_fd,
5556 MHD_PANIC (
"Failed to remove listen FD from epoll set.\n");
5557 daemon->listen_socket_in_epoll =
false;
5560 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
5561 (! MHD_itc_activate_ (daemon->
itc,
"q")) )
5563 "failed to signal quiesce via inter-thread communication channel.\n"));
5591 const struct sockaddr **servaddr,
5605 const struct sockaddr **servaddr,
5611 va_start (ap, servaddr);
5630 const struct sockaddr **servaddr,
5640#if GNUTLS_VERSION_MAJOR >= 3
5641 gnutls_certificate_retrieve_function2 *pgcrf;
5643#if GNUTLS_VERSION_NUMBER >= 0x030603
5644 gnutls_certificate_retrieve_function3 *pgcrf2;
5670#if (SIZEOF_UINT64_T - 2) <= SIZEOF_UNSIGNED_INT
5675 _ (
"The specified connection timeout (%u) is too large. " \
5676 "Maximum allowed value (%" PRIu64 ") will be used " \
5703 *servaddr = va_arg (ap,
5704 const struct sockaddr *);
5717#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5726 "Warning: Zero size, specified for thread pool size, is ignored. "
5727 "Thread pool is not used.\n"));
5735 "Warning: \"1\", specified for thread pool size, is ignored. "
5736 "Thread pool is not used.\n"));
5740#if SIZEOF_UNSIGNED_INT >= (SIZEOF_SIZE_T - 2)
5749 _ (
"Specified thread pool size (%u) too big.\n"),
5761 _ (
"MHD_OPTION_THREAD_POOL_SIZE option is specified but "
5762 "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
5770 _ (
"Both MHD_OPTION_THREAD_POOL_SIZE option and "
5771 "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
5783 daemon->https_mem_key = pstr;
5788 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5796 daemon->https_key_password = pstr;
5801 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5809 daemon->https_mem_cert = pstr;
5814 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5822 daemon->https_mem_trust = pstr;
5827 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5832 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
5840 gnutls_datum_t dhpar;
5843 if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
5847 _ (
"Error initializing DH parameters.\n"));
5851 dhpar.data = (
unsigned char *) pstr;
5852 pstr_len = strlen (pstr);
5857 _ (
"Diffie-Hellman parameters string too long.\n"));
5861 dhpar.size = (
unsigned int) pstr_len;
5862 if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
5864 GNUTLS_X509_FMT_PEM) < 0)
5868 _ (
"Bad Diffie-Hellman parameters format.\n"));
5870 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
5873 daemon->have_dhparams =
true;
5879 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5888 gnutls_priority_deinit (daemon->priority_cache);
5889 ret = gnutls_priority_init (&daemon->priority_cache,
5892 if (GNUTLS_E_SUCCESS != ret)
5896 _ (
"Setting priorities to `%s' failed: %s\n"),
5898 gnutls_strerror (ret));
5900 daemon->priority_cache =
NULL;
5908 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5913#if GNUTLS_VERSION_MAJOR < 3
5917 "MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0.\n"));
5922 gnutls_certificate_retrieve_function2 *);
5924 daemon->cert_callback = pgcrf;
5929 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5935#if GNUTLS_VERSION_NUMBER < 0x030603
5939 "MHD_OPTION_HTTPS_CERT_CALLBACK2 requires building MHD with GnuTLS >= 3.6.3.\n"));
5943 pgcrf2 = va_arg (ap,
5944 gnutls_certificate_retrieve_function3 *);
5946 daemon->cert_callback2 = pgcrf2;
5951 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5959 daemon->digest_auth_rand_size = va_arg (ap,
5961 daemon->digest_auth_random = va_arg (ap,
5965 daemon->nonce_nc_size = va_arg (ap,
5974 _ (
"MHD_OPTION_LISTEN_SOCKET specified for daemon "
5975 "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
5983#if defined(SO_DOMAIN) && defined(AF_UNIX)
5986 socklen_t len =
sizeof (af);
6006 daemon->custom_error_log = va_arg (ap,
6008 daemon->custom_error_log_cls = va_arg (ap,
6012 _ (
"MHD_OPTION_EXTERNAL_LOGGER is not the first option "
6013 "specified for the daemon. Some messages may be "
6014 "printed by the standard MHD logger.\n"));
6023#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6025 daemon->thread_stack_size = va_arg (ap,
6031 daemon->fastopen_queue_size = va_arg (ap,
6037 _ (
"TCP fastopen is not supported on this platform.\n"));
6043 unsigned int) ? 1 : -1;
6056 _ (
"Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
6057 "another behavior is specified by MHD_OPTION_STRICT_CLIENT.\n"));
6076 (
size_t) oa[i].
value,
6093 (
unsigned int) oa[i].
value,
6103 (gnutls_credentials_type_t) oa[i].
value,
6156 (
void *) oa[i].
value,
6166 (
size_t) oa[i].
value,
6185#if GNUTLS_VERSION_MAJOR >= 3
6186 daemon->cred_callback = va_arg (ap,
6188 daemon->cred_callback_cls = va_arg (ap,
6194 "MHD HTTPS option %d passed to MHD compiled without GNUtls >= 3.\n"),
6211 daemon->disable_alpn = (va_arg (ap,
6214 (void) va_arg (ap,
int);
6219 _ (
"MHD HTTPS option %d passed to MHD " \
6220 "but MHD_USE_TLS not set.\n"),
6233 "MHD HTTPS option %d passed to MHD compiled without HTTPS support.\n"),
6240 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?).\n"),
6257#ifndef HAVE_MESSAGES
6261#ifdef USE_EPOLL_CREATE1
6262 fd = epoll_create1 (EPOLL_CLOEXEC);
6264 fd = epoll_create (MAX_EVENTS);
6270 _ (
"Call to epoll_create1 failed: %s\n"),
6275#if ! defined(USE_EPOLL_CREATE1)
6280 _ (
"Failed to set noninheritable mode on epoll FD.\n"));
6297setup_epoll_to_listen (
struct MHD_Daemon *daemon)
6299 struct epoll_event event;
6306 MHD_ITC_IS_VALID_ (daemon->
itc) );
6307 daemon->epoll_fd = setup_epoll_fd (daemon);
6308 if (-1 == daemon->epoll_fd)
6310#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6313 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
6321 event.events = EPOLLIN;
6322 event.data.ptr = daemon;
6323 if (0 != epoll_ctl (daemon->epoll_fd,
6330 _ (
"Call to epoll_ctl failed: %s\n"),
6335 daemon->listen_socket_in_epoll =
true;
6338 if (MHD_ITC_IS_VALID_ (daemon->
itc))
6340 event.events = EPOLLIN;
6341 event.data.ptr = (
void *) epoll_itc_marker;
6342 if (0 != epoll_ctl (daemon->epoll_fd,
6344 MHD_itc_r_fd_ (daemon->
itc),
6349 _ (
"Call to epoll_ctl failed: %s\n"),
6395 struct sockaddr_in servaddr4;
6397 struct sockaddr_in6 servaddr6;
6399 const struct sockaddr *servaddr =
NULL;
6401#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6418#ifndef EPOLL_SUPPORT
6422#ifndef HTTPS_SUPPORT
6432#ifdef UPGRADE_SUPPORT
6468#if defined(EPOLL_SUPPORT)
6470#elif defined(HAVE_POLL)
6479#if defined(EPOLL_SUPPORT)
6490 daemon->epoll_fd = -1;
6491#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6492 daemon->epoll_upgrade_fd = -1;
6497 daemon->priority_cache =
NULL;
6500 gnutls_priority_init (&daemon->priority_cache,
6512 daemon->
port = port;
6523 MHD_itc_set_invalid_ (daemon->
itc);
6530 daemon->custom_error_log = &MHD_default_logger_;
6531 daemon->custom_error_log_cls = stderr;
6533#ifndef MHD_WINSOCK_SOCKETS
6550#ifdef HAVE_LISTEN_SHUTDOWN
6556 daemon->digest_auth_rand_size = 0;
6557 daemon->digest_auth_random =
NULL;
6558 daemon->nonce_nc_size = 4;
6563 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
6574 (
NULL != daemon->priority_cache) )
6575 gnutls_priority_deinit (daemon->priority_cache);
6587 "Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with "
6588 "MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD "
6589 "was added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"));
6600 _ (
"Using debug build of libmicrohttpd.\n") );
6605#
if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6610 if (! MHD_itc_init_ (daemon->
itc))
6614 _ (
"Failed to create inter-thread communication channel: %s\n"),
6615 MHD_itc_last_strerror_ ());
6618 if (
NULL != daemon->priority_cache)
6619 gnutls_priority_deinit (daemon->priority_cache);
6631 "file descriptor for inter-thread communication channel exceeds maximum value.\n"));
6635 if (
NULL != daemon->priority_cache)
6636 gnutls_priority_deinit (daemon->priority_cache);
6644 if (daemon->nonce_nc_size > 0)
6646 if ( ( (
size_t) (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc)))
6647 /
sizeof(
struct MHD_NonceNc) != daemon->nonce_nc_size)
6651 _ (
"Specified value for NC_SIZE too large.\n"));
6655 gnutls_priority_deinit (daemon->priority_cache);
6660 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc));
6661 if (
NULL == daemon->nnc)
6665 _ (
"Failed to allocate memory for nonce-nc map: %s\n"),
6670 gnutls_priority_deinit (daemon->priority_cache);
6677#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6682 _ (
"MHD failed to initialize nonce-nc mutex.\n"));
6686 gnutls_priority_deinit (daemon->priority_cache);
6696#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6703 "MHD thread polling only works with MHD_USE_INTERNAL_POLLING_THREAD.\n"));
6715 domain = (*pflags &
MHD_USE_IPv6) ? PF_INET6 : PF_INET;
6727 _ (
"Failed to create socket for listening: %s\n"),
6736#ifndef MHD_WINSOCK_SOCKETS
6741 if (0 > setsockopt (listen_fd,
6744 (
void *) &on,
sizeof (on)))
6748 _ (
"setsockopt failed: %s\n"),
6757#ifndef MHD_WINSOCK_SOCKETS
6760 if (0 > setsockopt (listen_fd,
6763 (
void *) &on,
sizeof (on)))
6767 _ (
"setsockopt failed: %s\n"),
6777#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
6778 if (0 > setsockopt (listen_fd,
6780#ifndef MHD_WINSOCK_SOCKETS
6790 _ (
"setsockopt failed: %s\n"),
6801 "Cannot allow listening address reuse: SO_REUSEPORT not defined.\n"));
6814#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
6815 (defined(__sun) && defined(SO_EXCLBIND))
6816 if (0 > setsockopt (listen_fd,
6818#ifdef SO_EXCLUSIVEADDRUSE
6819 SO_EXCLUSIVEADDRUSE,
6828 _ (
"setsockopt failed: %s\n"),
6833#elif defined(MHD_WINSOCK_SOCKETS)
6837 "Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined.\n"));
6846 addrlen =
sizeof (
struct sockaddr_in6);
6849 addrlen =
sizeof (
struct sockaddr_in);
6850 if (
NULL == servaddr)
6855#ifdef IN6ADDR_ANY_INIT
6856 static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
6860 sizeof (
struct sockaddr_in6));
6861 servaddr6.sin6_family = AF_INET6;
6862 servaddr6.sin6_port = htons (port);
6863#ifdef IN6ADDR_ANY_INIT
6864 servaddr6.sin6_addr = static_in6any;
6866#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
6867 servaddr6.sin6_len =
sizeof (
struct sockaddr_in6);
6869 servaddr = (
struct sockaddr *) &servaddr6;
6876 sizeof (
struct sockaddr_in));
6877 servaddr4.sin_family = AF_INET;
6878 servaddr4.sin_port = htons (port);
6879 if (0 != INADDR_ANY)
6880 servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
6881#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
6882 servaddr4.sin_len =
sizeof (
struct sockaddr_in);
6884 servaddr = (
struct sockaddr *) &servaddr4;
6898 if (0 > setsockopt (listen_fd,
6899 IPPROTO_IPV6, IPV6_V6ONLY,
6900 (
const void *) &v6_only,
6905 _ (
"setsockopt failed: %s\n"),
6912 if (-1 == bind (listen_fd, servaddr, addrlen))
6916 _ (
"Failed to bind to port %u: %s\n"),
6917 (
unsigned int) port,
6926 if (0 == daemon->fastopen_queue_size)
6927 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
6928 if (0 != setsockopt (listen_fd,
6931 (
const void *) &daemon->fastopen_queue_size,
6932 sizeof (daemon->fastopen_queue_size)))
6936 _ (
"setsockopt failed: %s\n"),
6942 if (listen (listen_fd,
6947 _ (
"Failed to listen for connections: %s\n"),
6959#ifdef HAVE_GETSOCKNAME
6960 if ( (0 == daemon->
port) &&
6963 struct sockaddr_storage bindaddr;
6967 sizeof (
struct sockaddr_storage));
6968 addrlen =
sizeof (
struct sockaddr_storage);
6969#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
6970 bindaddr.ss_len = addrlen;
6972 if (0 != getsockname (listen_fd,
6973 (
struct sockaddr *) &bindaddr,
6978 _ (
"Failed to get listen port number: %s\n"),
6982#ifdef MHD_POSIX_SOCKETS
6983 else if (
sizeof (bindaddr) < addrlen)
6989 "Failed to get listen port number (`struct sockaddr_storage` too small!?).\n"));
6993 else if (0 == addrlen)
7003 switch (bindaddr.ss_family)
7007 struct sockaddr_in *s4 = (
struct sockaddr_in *) &bindaddr;
7009 daemon->
port = ntohs (s4->sin_port);
7015 struct sockaddr_in6 *s6 = (
struct sockaddr_in6 *) &bindaddr;
7017 daemon->
port = ntohs (s6->sin6_port);
7030 _ (
"Unknown address family!\n"));
7045 _ (
"Failed to set nonblocking mode on listening socket: %s\n"),
7049#
if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7070 _ (
"Listen socket descriptor (%d) is not " \
7071 "less than FD_SETSIZE (%d).\n"),
7084#
if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7094 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
7098 if (
MHD_NO == setup_epoll_to_listen (daemon))
7103#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7108 _ (
"MHD failed to initialize IP connection limit mutex.\n"));
7118 _ (
"MHD failed to initialize IP connection limit mutex.\n"));
7120#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7132 (0 != MHD_TLS_init (daemon)) )
7136 _ (
"Failed to initialize TLS support.\n"));
7140#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7147#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7155#ifdef HAVE_LISTEN_SHUTDOWN
7157 (MHD_ITC_IS_VALID_ (daemon->
itc)) || \
7161 (MHD_ITC_IS_VALID_ (daemon->
itc)));
7169 _ (
"Failed to initialise mutex.\n"));
7180 "MHD-listen" :
"MHD-single",
7181 daemon->thread_stack_size,
7187 if (EAGAIN == errno)
7189 _ (
"Failed to create a new thread because it would have " \
7190 "exceeded the system limit on the number of threads or " \
7191 "no system resources available.\n"));
7195 _ (
"Failed to create listen thread: %s\n"),
7231 memcpy (d, daemon,
sizeof (
struct MHD_Daemon));
7240 #ifdef HAVE_MESSAGES
7242 _ (
"Failed to initialise mutex.\n"));
7248 if (! MHD_itc_init_ (d->
itc))
7253 "Failed to create worker inter-thread communication channel: %s\n"),
7254 MHD_itc_last_strerror_ () );
7266 "File descriptor for worker inter-thread communication channel exceeds maximum value.\n"));
7274 MHD_itc_set_invalid_ (d->
itc);
7276#ifdef HAVE_LISTEN_SHUTDOWN
7287 if (i < leftover_conns)
7291 (
MHD_NO == setup_epoll_to_listen (d)) )
7293 if (MHD_ITC_IS_VALID_ (d->
itc))
7304 _ (
"MHD failed to initialize cleanup connection mutex.\n"));
7306 if (MHD_ITC_IS_VALID_ (d->
itc))
7315 daemon->thread_stack_size,
7321 if (EAGAIN == errno)
7323 _ (
"Failed to create a new pool thread because it would " \
7324 "have exceeded the system limit on the number of " \
7325 "threads or no system resources available.\n"));
7329 _ (
"Failed to create pool thread: %s\n"),
7335 if (MHD_ITC_IS_VALID_ (d->
itc))
7349 _ (
"Failed to initialise mutex.\n"));
7358 daemon->https_key_password =
NULL;
7363#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7392#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7393 if (daemon->upgrade_fd_in_epoll)
7395 if (0 != epoll_ctl (daemon->epoll_fd,
7397 daemon->epoll_upgrade_fd,
7399 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
7400 daemon->upgrade_fd_in_epoll =
false;
7403 if (-1 != daemon->epoll_fd)
7404 close (daemon->epoll_fd);
7405#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7406 if (-1 != daemon->epoll_upgrade_fd)
7407 close (daemon->epoll_upgrade_fd);
7412#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7419 gnutls_priority_deinit (daemon->priority_cache);
7420 if (daemon->x509_cred)
7421 gnutls_certificate_free_credentials (daemon->x509_cred);
7422 if (daemon->psk_cred)
7423 gnutls_psk_free_server_credentials (daemon->psk_cred);
7426 if (MHD_ITC_IS_VALID_ (daemon->
itc))
7447#ifdef UPGRADE_SUPPORT
7450#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7451 struct MHD_UpgradeResponseHandle *urh;
7452 struct MHD_UpgradeResponseHandle *urhn;
7456#ifdef MHD_USE_THREADS
7459 MHD_thread_ID_match_current_ (daemon->
pid) );
7464#ifdef MHD_USE_THREADS
7473 new_connection_close_ (daemon, pos);
7477#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7480 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
7488 urh->clean_ready =
true;
7505#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7508#ifdef UPGRADE_SUPPORT
7514 while (
NULL != susp)
7516 if (
NULL == susp->urh)
7518 "MHD_stop_daemon() called while we have suspended connections.\n"));
7520 else if (used_tls &&
7522 (! susp->urh->clean_ready) )
7523 shutdown (susp->urh->app.socket,
7529 if (! susp->urh->was_closed)
7532 "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
7534 susp->urh->was_closed =
true;
7551 "MHD_stop_daemon() called while we have suspended connections.\n"));
7552#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
7553#ifdef MHD_USE_THREADS
7554 if (upg_allowed && used_tls && used_thr_p_c)
7572 if (! MHD_join_thread_ (pos->
pid.handle))
7573 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
7585#if MHD_WINSOCK_SOCKETS
7588 (! MHD_itc_activate_ (
daemon->
itc,
"e")) )
7590 "Failed to signal shutdown via inter-thread communication channel.\n"));
7594#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7604 if (! MHD_join_thread_ (pos->
pid.handle))
7605 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
7619#ifdef UPGRADE_SUPPORT
7635#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7638 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
7656#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7663 MHD_PANIC (
_ (
"MHD_stop_daemon() was called twice."));
7673#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7688 "Failed to signal shutdown via inter-thread communication channel.\n"));
7693#ifdef HAVE_LISTEN_SHUTDOWN
7696 (void) shutdown (
fd,
7708#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7716#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7726 "Failed to signal shutdown via inter-thread communication channel.\n"));
7730#ifdef HAVE_LISTEN_SHUTDOWN
7734 (void) shutdown (
fd,
7742 if (! MHD_join_thread_ (
daemon->
pid.handle))
7744 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
7754#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7762#if defined(UPGRADE_SUPPORT) && defined (HTTPS_SUPPORT)
7771 (-1 !=
daemon->epoll_fd) )
7773#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7775 (-1 !=
daemon->epoll_upgrade_fd) )
7780#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7794 if (
daemon->have_dhparams)
7796 gnutls_dh_params_deinit (
daemon->https_mem_dhparams);
7797 daemon->have_dhparams =
false;
7801 gnutls_priority_deinit (
daemon->priority_cache);
7803 gnutls_certificate_free_credentials (
daemon->x509_cred);
7805 gnutls_psk_free_server_credentials (
daemon->psk_cred);
7811#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7815#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7860#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7918#ifdef PACKAGE_VERSION
7919 return PACKAGE_VERSION;
7921 static char ver[12] =
"\0\0\0\0\0\0\0\0\0\0\0";
7924 int res = MHD_snprintf_ (ver,
7930 if ((0 >= res) || (
sizeof(ver) <= res))
7967#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
7973#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030603
7985#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
8003#ifdef HAVE_LISTEN_SHUTDOWN
8009#ifdef _MHD_ITC_SOCKETPAIR
8033#ifdef HAVE_POSTPROCESSOR
8039#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
8045#if defined(HAVE_PREAD64) || defined(_WIN32)
8047#elif defined(HAVE_PREAD)
8048 return (
sizeof(uint64_t) >
sizeof(off_t)) ?
MHD_NO :
MHD_YES;
8049#elif defined(HAVE_LSEEK64)
8052 return (
sizeof(uint64_t) >
sizeof(off_t)) ?
MHD_NO :
MHD_YES;
8055#if defined(MHD_USE_THREAD_NAME_)
8061#if defined(UPGRADE_SUPPORT)
8067#if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
8073#ifdef MHD_USE_GETSOCKNAME
8079#if defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) || \
8080 ! defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED)
8086#ifdef _MHD_HAVE_SENDFILE
8092#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8103#ifdef MHD_HTTPS_REQUIRE_GRYPT
8104#if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
8105#if defined(MHD_USE_POSIX_THREADS)
8106GCRY_THREAD_OPTION_PTHREAD_IMPL;
8107#elif defined(MHD_W32_MUTEX_)
8110gcry_w32_mutex_init (
void **ppmtx)
8112 *ppmtx = malloc (
sizeof (MHD_mutex_));
8128gcry_w32_mutex_destroy (
void **ppmtx)
8137gcry_w32_mutex_lock (
void **ppmtx)
8144gcry_w32_mutex_unlock (
void **ppmtx)
8150static struct gcry_thread_cbs gcry_threads_w32 = {
8151 (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
8152 NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
8153 gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
8167#if defined(MHD_WINSOCK_SOCKETS)
8174#if defined(MHD_WINSOCK_SOCKETS)
8175 if (0 != WSAStartup (MAKEWORD (2, 2), &wsd))
8176 MHD_PANIC (
_ (
"Failed to initialize winsock.\n"));
8177 mhd_winsock_inited_ = 1;
8178 if ((2 != LOBYTE (wsd.wVersion)) && (2 != HIBYTE (wsd.wVersion)))
8179 MHD_PANIC (
_ (
"Winsock version 2.2 is not available.\n"));
8182#ifdef MHD_HTTPS_REQUIRE_GRYPT
8183#if GCRYPT_VERSION_NUMBER < 0x010600
8184#if defined(MHD_USE_POSIX_THREADS)
8185 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
8186 &gcry_threads_pthread))
8187 MHD_PANIC (
_ (
"Failed to initialise multithreading in libgcrypt.\n"));
8188#elif defined(MHD_W32_MUTEX_)
8189 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
8191 MHD_PANIC (
_ (
"Failed to initialise multithreading in libgcrypt.\n"));
8193 gcry_check_version (
NULL);
8195 if (
NULL == gcry_check_version (
"1.6.0"))
8197 "libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer.\n"));
8200 gnutls_global_init ();
8210 mhd_assert (
sizeof(tv.tv_sec) == SIZEOF_STRUCT_TIMEVAL_TV_SEC);
8213 mhd_assert (
sizeof(uint64_t) == SIZEOF_UINT64_T);
8221 gnutls_global_deinit ();
8223#if defined(MHD_WINSOCK_SOCKETS)
8224 if (mhd_winsock_inited_)
8231#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
#define _SET_INIT_AND_DEINIT_FUNCS(FI, FD)
void MHD_connection_handle_write(struct MHD_Connection *connection)
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
enum MHD_Result MHD_connection_handle_idle(struct MHD_Connection *connection)
void MHD_connection_handle_read(struct MHD_Connection *connection, bool socket_error)
Methods for managing connections.
#define MHD_connection_finish_forward_(conn)
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ thread_main_handle_connection(void *data)
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode rtc)
void MHD_set_https_callbacks(struct MHD_Connection *connection)
Methods for managing connections.
void MHD_update_last_activity_(struct MHD_Connection *connection)
static struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *daemon)
void MHD_suspend_connection(struct MHD_Connection *connection)
static void close_all_connections(struct MHD_Daemon *daemon)
MHD_PanicCallback mhd_panic
static int get_timeout_millisec_(struct MHD_Daemon *daemon, int32_t max_timeout)
static enum MHD_Result MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
void MHD_resume_connection(struct MHD_Connection *connection)
void internal_suspend_connection_(struct MHD_Connection *connection)
static enum MHD_Result parse_options_va(struct MHD_Daemon *daemon, const struct sockaddr **servaddr, va_list ap)
static enum MHD_Result call_handlers(struct MHD_Connection *con, bool read_ready, bool write_ready, bool force_close)
static void MHD_ip_count_unlock(struct MHD_Daemon *daemon)
volatile int global_init_count
static enum MHD_Result MHD_poll(struct MHD_Daemon *daemon, int may_block)
void MHD_check_global_init_(void)
static void close_connection(struct MHD_Connection *pos)
static enum MHD_Result MHD_select(struct MHD_Daemon *daemon, int32_t millisec)
static _MHD_NORETURN void mhd_panic_std(void *cls, const char *file, unsigned int line, const char *reason)
static int MHD_ip_addr_compare(const void *a1, const void *a2)
static void new_connections_list_process_(struct MHD_Daemon *daemon)
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
static enum MHD_Result MHD_accept_connection(struct MHD_Daemon *daemon)
static void MHD_ip_limit_del(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
#define MHD_MAX_CONNECTIONS_DEFAULT
static size_t unescape_wrapper(void *cls, struct MHD_Connection *connection, char *val)
static enum MHD_Result new_connection_process_(struct MHD_Daemon *daemon, struct MHD_Connection *connection)
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
static enum MHD_Result MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen, struct MHD_IPCount *key)
static enum MHD_Result parse_options(struct MHD_Daemon *daemon, const struct sockaddr **servaddr,...)
static struct MHD_Connection * new_connection_prepare_(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, bool external_add, bool non_blck, bool sk_spipe_supprs, enum MHD_tristate sk_is_nonip)
static enum MHD_Result resume_suspended_connections(struct MHD_Daemon *daemon)
#define MHD_POOL_SIZE_DEFAULT
static enum MHD_Result internal_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, bool external_add, bool non_blck, bool sk_spipe_supprs, enum MHD_tristate sk_is_nonip)
_MHD_EXTERN void MHD_free(void *ptr)
static enum MHD_Result internal_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, unsigned int fd_setsize)
static enum MHD_Result internal_run_from_select(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set)
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ MHD_polling_thread(void *cls)
_MHD_EXTERN struct MHD_Daemon * MHD_start_daemon(unsigned int flags, uint16_t port, MHD_AcceptPolicyCallback apc, void *apc_cls, MHD_AccessHandlerCallback dh, void *dh_cls,...)
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
_MHD_EXTERN enum MHD_Result MHD_run_from_select(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set)
_MHD_EXTERN struct MHD_Daemon * MHD_start_daemon_va(unsigned int flags, uint16_t port, MHD_AcceptPolicyCallback apc, void *apc_cls, MHD_AccessHandlerCallback dh, void *dh_cls, va_list ap)
_MHD_EXTERN enum MHD_Result MHD_run(struct MHD_Daemon *daemon)
_MHD_EXTERN enum MHD_Result MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
#define MHD_get_fdset(daemon, read_fd_set, write_fd_set, except_fd_set, max_fd)
_MHD_EXTERN enum MHD_Result MHD_run_wait(struct MHD_Daemon *daemon, int32_t millisec)
_MHD_EXTERN enum MHD_Result MHD_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, unsigned int fd_setsize)
void(* MHD_PanicCallback)(void *cls, const char *file, unsigned int line, const char *reason)
_MHD_EXTERN void MHD_set_panic_func(MHD_PanicCallback cb, void *cls)
void(* MHD_NotifyConnectionCallback)(void *cls, struct MHD_Connection *connection, void **socket_context, enum MHD_ConnectionNotificationCode toe)
void(* MHD_RequestCompletedCallback)(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
@ MHD_CONNECTION_NOTIFY_STARTED
@ MHD_CONNECTION_NOTIFY_CLOSED
@ MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN
@ MHD_REQUEST_TERMINATED_COMPLETED_OK
@ MHD_REQUEST_TERMINATED_WITH_ERROR
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
_MHD_EXTERN const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
_MHD_EXTERN enum MHD_Result MHD_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen)
_MHD_EXTERN enum MHD_Result MHD_is_feature_supported(enum MHD_FEATURE feature)
_MHD_EXTERN const char * MHD_get_version(void)
#define XDLL_insert(head, tail, element)
@ MHD_EPOLL_STATE_SUSPENDED
@ MHD_EPOLL_STATE_IN_EREADY_EDLL
@ MHD_EPOLL_STATE_READ_READY
@ MHD_EPOLL_STATE_IN_EPOLL_SET
@ MHD_EPOLL_STATE_WRITE_READY
#define DLL_insert(head, tail, element)
#define EDLL_insert(head, tail, element)
#define EDLL_remove(head, tail, element)
#define XDLL_remove(head, tail, element)
#define DLL_remove(head, tail, element)
void MHD_pool_destroy(struct MemoryPool *pool)
struct MemoryPool * MHD_pool_create(size_t max)
void * MHD_calloc_(size_t nelem, size_t elsize)
#define MHD_strerror_(errnum)
#define MHD_ITC_IS_INVALID_(itc)
#define MHD_itc_destroy_chk_(itc)
#define TIMEVAL_TV_SEC_MAX
#define MHD_mutex_unlock_chk_(pmutex)
#define MHD_mutex_destroy_chk_(pmutex)
#define MHD_mutex_lock_chk_(pmutex)
void MHD_monotonic_sec_counter_finish(void)
void MHD_monotonic_sec_counter_init(void)
int MHD_add_to_fd_set_(MHD_socket fd, fd_set *set, MHD_socket *max_fd, unsigned int fd_setsize)
int MHD_socket_noninheritable_(MHD_socket sock)
int MHD_socket_nonblocking_(MHD_socket sock)
MHD_socket MHD_socket_create_listen_(int pf)
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
#define MHD_SCKT_ERR_IS_(err, code)
#define MHD_socket_close_(fd)
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
#define _MHD_SYS_DEFAULT_FD_SETSIZE
#define MHD_socket_strerr_(err)
#define MHD_socket_last_strerr_()
#define MHD_socket_get_error_()
#define MHD_socket_close_chk_(fd)
#define MHD_SCKT_ERR_IS_EINTR_(err)
#define MHD_socket_fset_error_(err)
#define MHD_SCKT_SEND_MAX_SIZE_
#define MHD_recv_(s, b, l)
#define MHD_send_(s, b, l)
#define MHD_SCKT_LAST_ERR_IS_(code)
#define MHD_SYS_select_(n, r, w, e, t)
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
#define MHD_STATICSTR_LEN_(macro)
#define MHD_create_named_thread_(t, n, s, r, a)
void * tfind(const void *vkey, void *const *vrootp, int(*compar)(const void *, const void *))
void * tdelete(const void *__restrict vkey, void **__restrict vrootp, int(*compar)(const void *, const void *))
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
void MHD_send_init_static_vars_(void)
Declarations of send() wrappers.
MHD internal shared structures.
@ MHD_CONNECTION_HEADERS_SENDING
@ MHD_CONNECTION_NORMAL_BODY_READY
@ MHD_CONNECTION_CHUNKED_BODY_READY
@ MHD_EVENT_LOOP_INFO_READ
@ MHD_EVENT_LOOP_INFO_WRITE
@ MHD_EVENT_LOOP_INFO_CLEANUP
@ MHD_EVENT_LOOP_INFO_BLOCK
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
#define MHD_TEST_ALLOW_SUSPEND_RESUME
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
void MHD_init_mem_pools_(void)
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...
Header for platform missing functions.
Header for platform-independent inter-thread communication.
limits values definitions
#define MHD_mutex_destroy_(ignore)
#define MHD_mutex_unlock_(ignore)
#define MHD_mutex_lock_(ignore)
#define MHD_mutex_init_(ignore)
uint64_t MHD_monotonic_msec_counter(void)
internal monotonic clock functions implementations
#define SOCK_NONBLOCK_OR_ZERO
#define SOCK_NOSIGPIPE_OR_ZERO
#define SOCK_CLOEXEC_OR_ZERO
@ MHD_FEATURE_POSTPROCESSOR
@ MHD_FEATURE_SHUTDOWN_LISTEN_SOCKET
@ MHD_FEATURE_AUTODETECT_BIND_PORT
@ MHD_FEATURE_HTTPS_CERT_CALLBACK
@ MHD_FEATURE_DIGEST_AUTH
@ MHD_FEATURE_THREAD_NAMES
@ MHD_FEATURE_HTTPS_KEY_PASSWORD
@ MHD_FEATURE_AUTOSUPPRESS_SIGPIPE
@ MHD_FEATURE_RESPONSES_SHARED_FD
@ MHD_FEATURE_TCP_FASTOPEN
@ MHD_FEATURE_HTTPS_CERT_CALLBACK2
@ MHD_OPTION_CONNECTION_MEMORY_INCREMENT
@ MHD_OPTION_HTTPS_CRED_TYPE
@ MHD_OPTION_URI_LOG_CALLBACK
@ MHD_OPTION_HTTPS_CERT_CALLBACK2
@ MHD_OPTION_SIGPIPE_HANDLED_BY_APP
@ MHD_OPTION_UNESCAPE_CALLBACK
@ MHD_OPTION_EXTERNAL_LOGGER
@ MHD_OPTION_LISTEN_BACKLOG_SIZE
@ MHD_OPTION_HTTPS_PRIORITIES
@ MHD_OPTION_HTTPS_MEM_DHPARAMS
@ MHD_OPTION_NOTIFY_CONNECTION
@ MHD_OPTION_LISTENING_ADDRESS_REUSE
@ MHD_OPTION_THREAD_POOL_SIZE
@ MHD_OPTION_CONNECTION_LIMIT
@ MHD_OPTION_PER_IP_CONNECTION_LIMIT
@ MHD_OPTION_TCP_FASTOPEN_QUEUE_SIZE
@ MHD_OPTION_HTTPS_MEM_CERT
@ MHD_OPTION_SERVER_INSANITY
@ MHD_OPTION_LISTEN_SOCKET
@ MHD_OPTION_HTTPS_MEM_KEY
@ MHD_OPTION_DIGEST_AUTH_RANDOM
@ MHD_OPTION_HTTPS_KEY_PASSWORD
@ MHD_OPTION_NONCE_NC_SIZE
@ MHD_OPTION_CONNECTION_MEMORY_LIMIT
@ MHD_OPTION_THREAD_STACK_SIZE
@ MHD_OPTION_STRICT_FOR_CLIENT
@ MHD_OPTION_CONNECTION_TIMEOUT
@ MHD_OPTION_GNUTLS_PSK_CRED_HANDLER
@ MHD_OPTION_HTTPS_MEM_TRUST
@ MHD_OPTION_HTTPS_CERT_CALLBACK
@ MHD_OPTION_NOTIFY_COMPLETED
enum MHD_Result(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
#define MHD_UNSIGNED_LONG_LONG
_MHD_EXTERN size_t MHD_http_unescape(char *val)
#define MHD_INVALID_SOCKET
enum MHD_Result(* MHD_AccessHandlerCallback)(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls)
int(* MHD_PskServerCredentialsCallback)(void *cls, const struct MHD_Connection *connection, const char *username, void **psk, size_t *psk_size)
@ MHD_DAEMON_INFO_MAC_KEY_SIZE
@ MHD_DAEMON_INFO_BIND_PORT
@ MHD_DAEMON_INFO_EPOLL_FD
@ MHD_DAEMON_INFO_KEY_SIZE
@ MHD_DAEMON_INFO_CURRENT_CONNECTIONS
@ MHD_DAEMON_INFO_LISTEN_FD
MHD_FLAG
Flags for the struct MHD_Daemon.
@ MHD_ALLOW_SUSPEND_RESUME
@ MHD_USE_THREAD_PER_CONNECTION
@ MHD_USE_POST_HANDSHAKE_AUTH_SUPPORT
@ MHD_USE_INSECURE_TLS_EARLY_DATA
@ MHD_USE_NO_LISTEN_SOCKET
@ MHD_USE_PEDANTIC_CHECKS
@ MHD_USE_INTERNAL_POLLING_THREAD
Methods for managing response objects.
enum MHD_tristate sk_nodelay
struct MHD_Connection * prevX
enum MHD_ConnectionEventLoopInfo event_loop_info
enum MHD_tristate is_nonip
struct MHD_Response * response
struct MHD_Connection * next
struct sockaddr_storage addr
size_t read_buffer_offset
struct MHD_Connection * prev
MHD_thread_handle_ID_ pid
struct MHD_Connection * nextX
enum MHD_CONNECTION_STATE state
struct MHD_Daemon * daemon
uint64_t connection_timeout_ms
enum MHD_tristate sk_corked
MHD_NotifyConnectionCallback notify_connection
MHD_AccessHandlerCallback default_handler
LogCallback uri_log_callback
bool data_already_pending
MHD_mutex_ per_ip_connection_mutex
void * per_ip_connection_count
struct MHD_Connection * new_connections_tail
unsigned int connection_limit
void * unescape_callback_cls
MHD_mutex_ cleanup_connection_mutex
enum MHD_DisableSanityCheck insanity_level
struct MHD_Connection * connections_head
unsigned int listen_backlog_size
MHD_RequestCompletedCallback notify_completed
unsigned int worker_pool_size
int listening_address_reuse
uint64_t connection_timeout_ms
unsigned int per_ip_connection_limit
struct MHD_Connection * manual_timeout_tail
void * notify_connection_cls
UnescapeCallback unescape_callback
void * notify_completed_cls
struct MHD_Connection * cleanup_tail
struct MHD_Daemon * worker_pool
struct MHD_Connection * new_connections_head
MHD_thread_handle_ID_ pid
struct MHD_Connection * manual_timeout_head
enum MHD_tristate listen_is_unix
void * default_handler_cls
struct MHD_Connection * suspended_connections_tail
MHD_AcceptPolicyCallback apc
struct MHD_Connection * cleanup_head
struct MHD_Daemon * master
struct MHD_Connection * normal_timeout_head
struct MHD_Connection * normal_timeout_tail
void * uri_log_callback_cls
struct MHD_Connection * suspended_connections_head
struct MHD_Connection * connections_tail