29#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
30#include "mhd_threads.h"
39#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
55#ifdef MHD_HTTPS_REQUIRE_GRYPT
60#if defined(_WIN32) && ! defined(__CYGWIN__)
61#ifndef WIN32_LEAN_AND_MEAN
62#define WIN32_LEAN_AND_MEAN 1
67#ifdef MHD_USE_POSIX_THREADS
76#ifdef MHD_POSIX_SOCKETS
77#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 4)
79#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2)
85#define MHD_POOL_SIZE_DEFAULT (32 * 1024)
136 _ (
"Fatal error in GNU libmicrohttpd %s:%u: %s\n"),
166#if defined(MHD_WINSOCK_SOCKETS)
170static int mhd_winsock_inited_ = 0;
173#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
178#define MHD_check_global_init_() (void) 0
185#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
186#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
190MHD_MUTEX_STATIC_DEFN_INIT_ (global_init_mutex_);
202#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
203#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
209#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
210#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
224MHD_default_logger_ (
void *cls,
228 vfprintf ((FILE*) cls, fm, ap);
230 fflush ((FILE*) cls);
291 struct in6_addr ipv6;
310#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
326#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
349 offsetof (
struct MHD_IPCount,
365 struct MHD_IPCount *key)
372 if (
sizeof (
struct sockaddr_in) == addrlen)
374 const struct sockaddr_in *addr4 = (
const struct sockaddr_in*) addr;
376 key->family = AF_INET;
377 memcpy (&key->addr.ipv4,
379 sizeof(addr4->sin_addr));
385 if (
sizeof (
struct sockaddr_in6) == addrlen)
387 const struct sockaddr_in6 *addr6 = (
const struct sockaddr_in6*) addr;
389 key->family = AF_INET6;
390 memcpy (&key->addr.ipv6,
392 sizeof(addr6->sin6_addr));
415 const struct sockaddr *addr,
418 struct MHD_IPCount *key;
428 if (
NULL == (key = malloc (
sizeof(*key))))
449 _ (
"Failed to add IP connection count node.\n"));
459 key = (
struct MHD_IPCount *) node;
481 const struct sockaddr *addr,
484 struct MHD_IPCount search_key;
485 struct MHD_IPCount *found_key;
507 MHD_PANIC (
_ (
"Failed to find previously-added IP address.\n"));
509 found_key = (
struct MHD_IPCount *) *nodep;
511 if (0 == found_key->count)
513 MHD_PANIC (
_ (
"Previously-added IP address had counter of zero.\n"));
516 if (0 == --found_key->count)
536MHD_init_daemon_certificate (
struct MHD_Daemon *daemon)
542#if GNUTLS_VERSION_MAJOR >= 3
543 if (
NULL != daemon->cert_callback)
545 gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
546 daemon->cert_callback);
549#if GNUTLS_VERSION_NUMBER >= 0x030603
550 else if (
NULL != daemon->cert_callback2)
552 gnutls_certificate_set_retrieve_function3 (daemon->x509_cred,
553 daemon->cert_callback2);
557 if (
NULL != daemon->https_mem_trust)
560 paramlen = strlen (daemon->https_mem_trust);
565 _ (
"Too long trust certificate.\n"));
569 cert.data = (
unsigned char *) daemon->https_mem_trust;
570 cert.size = (
unsigned int) paramlen;
571 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred,
573 GNUTLS_X509_FMT_PEM) < 0)
577 _ (
"Bad trust certificate format.\n"));
583 if (daemon->have_dhparams)
585 gnutls_certificate_set_dh_params (daemon->x509_cred,
586 daemon->https_mem_dhparams);
589 if ( (
NULL != daemon->https_mem_cert) &&
590 (
NULL != daemon->https_mem_key) )
595 param1len = strlen (daemon->https_mem_key);
596 param2len = strlen (daemon->https_mem_cert);
602 _ (
"Too long key or certificate.\n"));
606 key.data = (
unsigned char *) daemon->https_mem_key;
607 key.size = (
unsigned int) param1len;
608 cert.data = (
unsigned char *) daemon->https_mem_cert;
609 cert.size = (
unsigned int) param2len;
611 if (
NULL != daemon->https_key_password)
613#if GNUTLS_VERSION_NUMBER >= 0x030111
614 ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
618 daemon->https_key_password,
623 _ (
"Failed to setup x509 certificate/key: pre 3.X.X version " \
624 "of GnuTLS does not support setting key password.\n"));
630 ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
633 GNUTLS_X509_FMT_PEM);
637 _ (
"GnuTLS failed to setup x509 certificate/key: %s\n"),
638 gnutls_strerror (ret));
642#if GNUTLS_VERSION_MAJOR >= 3
643 if (
NULL != daemon->cert_callback)
646#if GNUTLS_VERSION_NUMBER >= 0x030603
647 else if (
NULL != daemon->cert_callback2)
652 _ (
"You need to specify a certificate and key location.\n"));
667 switch (daemon->cred_type)
669 case GNUTLS_CRD_CERTIFICATE:
671 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
672 return GNUTLS_E_MEMORY_ERROR;
673 return MHD_init_daemon_certificate (daemon);
676 gnutls_psk_allocate_server_credentials (&daemon->psk_cred))
677 return GNUTLS_E_MEMORY_ERROR;
682 _ (
"Error: invalid credentials type %d specified.\n"),
727 fd_set *write_fd_set,
728 fd_set *except_fd_set,
740#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
754urh_to_fdset (
struct MHD_UpgradeResponseHandle *urh,
759 unsigned int fd_setsize)
761 const MHD_socket conn_sckt = urh->connection->socket_fd;
769 if ( (urh->in_buffer_used < urh->in_buffer_size) &&
775 if ( (0 != urh->out_buffer_used) &&
784 ((0 != urh->in_buffer_size) ||
785 (0 != urh->out_buffer_size) ||
786 (0 != urh->out_buffer_used)))
794 if ( (urh->out_buffer_used < urh->out_buffer_size) &&
800 if ( (0 != urh->in_buffer_used) &&
809 ((0 != urh->out_buffer_size) ||
810 (0 != urh->in_buffer_size) ||
811 (0 != urh->in_buffer_used)))
832urh_from_fdset (
struct MHD_UpgradeResponseHandle *urh,
837 const MHD_socket conn_sckt = urh->connection->socket_fd;
841 urh->app.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
842 urh->mhd.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
846 if (FD_ISSET (conn_sckt, rs))
848 if (FD_ISSET (conn_sckt, ws))
850 if (FD_ISSET (conn_sckt, es))
855 if (FD_ISSET (mhd_sckt, rs))
857 if (FD_ISSET (mhd_sckt, ws))
859 if (FD_ISSET (mhd_sckt, es))
876urh_update_pollfd (
struct MHD_UpgradeResponseHandle *urh,
882 if (urh->in_buffer_used < urh->in_buffer_size)
883 p[0].events |= POLLIN;
884 if (0 != urh->out_buffer_used)
885 p[0].events |= POLLOUT;
890 ((0 != urh->in_buffer_size) ||
891 (0 != urh->out_buffer_size) ||
892 (0 != urh->out_buffer_used)))
893 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
895 if (urh->out_buffer_used < urh->out_buffer_size)
896 p[1].events |= POLLIN;
897 if (0 != urh->in_buffer_used)
898 p[1].events |= POLLOUT;
903 ((0 != urh->out_buffer_size) ||
904 (0 != urh->in_buffer_size) ||
905 (0 != urh->in_buffer_used)))
906 p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
917urh_to_pollfd (
struct MHD_UpgradeResponseHandle *urh,
920 p[0].fd = urh->connection->socket_fd;
921 p[1].fd = urh->mhd.socket;
922 urh_update_pollfd (urh,
933urh_from_pollfd (
struct MHD_UpgradeResponseHandle *urh,
937 urh->app.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
938 urh->mhd.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
940 if (0 != (p[0].revents & POLLIN))
942 if (0 != (p[0].revents & POLLOUT))
944 if (0 != (p[0].revents & POLLHUP))
946 if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
948 if (0 != (p[1].revents & POLLIN))
950 if (0 != (p[1].revents & POLLOUT))
952 if (0 != (p[1].revents & POLLHUP))
954 if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
980 fd_set *write_fd_set,
981 fd_set *except_fd_set,
983 unsigned int fd_setsize)
1019#ifdef MHD_POSIX_SOCKETS
1032#ifdef MHD_POSIX_SOCKETS
1040 if ( (
NULL == except_fd_set) ||
1052#ifdef MHD_WINSOCK_SOCKETS
1065#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1067 struct MHD_UpgradeResponseHandle *urh;
1069 for (urh = daemon->urh_tail;
NULL != urh; urh = urh->prev)
1082#if _MHD_DEBUG_CONNECT
1086 _ (
"Maximum socket in select set: %d\n"),
1128 fd_set *read_fd_set,
1129 fd_set *write_fd_set,
1130 fd_set *except_fd_set,
1132 unsigned int fd_setsize)
1136 if ( (
NULL == daemon) ||
1137 (
NULL == read_fd_set) ||
1138 (
NULL == write_fd_set) ||
1143 if (
NULL == except_fd_set)
1147 _ (
"MHD_get_fdset2() called with except_fd_set "
1148 "set to NULL. Such behavior is unsupported.\n"));
1151 except_fd_set = &es;
1199 bool states_info_processed =
false;
1214 states_info_processed =
true;
1223 states_info_processed =
true;
1233 if (! states_info_processed)
1290#ifdef UPGRADE_SUPPORT
1301 struct MHD_UpgradeResponseHandle *urh = connection->urh;
1309 gnutls_bye (connection->tls_session,
1318 connection->urh =
NULL;
1326#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1336process_urh (
struct MHD_UpgradeResponseHandle *urh)
1349#ifdef MHD_USE_THREADS
1351 MHD_thread_ID_match_current_ (connection->
pid) );
1357 if (! urh->was_closed)
1361 "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
1364 urh->was_closed =
true;
1366 was_closed = urh->was_closed;
1371 if (0 < urh->in_buffer_used)
1375 _ (
"Failed to forward to application "
1377 " bytes of data received from remote side: application shut down socket.\n"),
1387 if (0 != urh->out_buffer_size)
1390 urh->in_buffer_used = 0;
1392 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1394 urh->in_buffer_size = 0;
1395 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1416 (urh->in_buffer_used < urh->in_buffer_size) )
1421 buf_size = urh->in_buffer_size - urh->in_buffer_used;
1426 res = gnutls_record_recv (connection->tls_session,
1427 &urh->in_buffer[urh->in_buffer_used],
1431 if (GNUTLS_E_INTERRUPTED != res)
1433 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1434 if (GNUTLS_E_AGAIN != res)
1439 urh->in_buffer_size = 0;
1445 urh->in_buffer_used += res;
1446 if (0 < gnutls_record_check_pending (connection->tls_session))
1457 urh->in_buffer_size = 0;
1465 (urh->out_buffer_used < urh->out_buffer_size) )
1470 buf_size = urh->out_buffer_size - urh->out_buffer_used;
1475 &urh->out_buffer[urh->out_buffer_used],
1484 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1494 urh->out_buffer_size = 0;
1500 urh->out_buffer_used += res;
1501 if (buf_size > (
size_t) res)
1502 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1511 urh->out_buffer_size = 0;
1519 (urh->out_buffer_used > 0) )
1524 data_size = urh->out_buffer_used;
1528 res = gnutls_record_send (connection->tls_session,
1533 if (GNUTLS_E_INTERRUPTED != res)
1535 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1536 if (GNUTLS_E_AGAIN != res)
1543 "Failed to forward to remote client "
1545 " bytes of data received from application: %s\n"),
1547 gnutls_strerror (res));
1550 urh->out_buffer_used = 0;
1552 urh->out_buffer_size = 0;
1553 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1559 const size_t next_out_buffer_used = urh->out_buffer_used - res;
1560 if (0 != next_out_buffer_used)
1562 memmove (urh->out_buffer,
1563 &urh->out_buffer[res],
1564 next_out_buffer_used);
1565 if (data_size > (
size_t) res)
1566 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1568 urh->out_buffer_used = next_out_buffer_used;
1570 if ( (0 == urh->out_buffer_used) &&
1576 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1578 urh->out_buffer_size = 0;
1579 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1587 (urh->in_buffer_used > 0) )
1592 data_size = urh->in_buffer_used;
1605 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1613 "Failed to forward to application "
1615 " bytes of data received from remote side: %s\n"),
1620 urh->in_buffer_used = 0;
1622 urh->in_buffer_size = 0;
1623 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1630 const size_t next_in_buffer_used = urh->in_buffer_used - res;
1631 if (0 != next_in_buffer_used)
1633 memmove (urh->in_buffer,
1634 &urh->in_buffer[res],
1635 next_in_buffer_used);
1636 if (data_size > (
size_t) res)
1637 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1639 urh->in_buffer_used = next_in_buffer_used;
1641 if ( (0 == urh->in_buffer_used) &&
1645 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1647 urh->in_buffer_size = 0;
1648 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1656 (urh->in_buffer_used < urh->in_buffer_size) &&
1661 ( (0 != urh->out_buffer_size) ||
1662 (0 != urh->out_buffer_used) ) )
1666 if (0 < urh->out_buffer_used)
1669 "Failed to forward to remote client "
1671 " bytes of data received from application: daemon shut down.\n"),
1675 urh->out_buffer_used = 0;
1677 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1679 urh->out_buffer_size = 0;
1680 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1687#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1688#ifdef UPGRADE_SUPPORT
1701 struct MHD_UpgradeResponseHandle *urh = con->urh;
1705 MHD_thread_ID_match_current_ (con->
pid) );
1712 while ( (0 != urh->in_buffer_size) ||
1713 (0 != urh->out_buffer_size) ||
1714 (0 != urh->in_buffer_used) ||
1715 (0 != urh->out_buffer_used) )
1729 result = urh_to_fdset (urh,
1739 _ (
"Error preparing select.\n"));
1749 (urh->in_buffer_used < urh->in_buffer_size)) ||
1774 _ (
"Error during select (%d): `%s'\n"),
1780 urh_from_fdset (urh,
1795 p[0].fd = urh->connection->socket_fd;
1796 p[1].fd = urh->mhd.socket;
1798 while ( (0 != urh->in_buffer_size) ||
1799 (0 != urh->out_buffer_size) ||
1800 (0 != urh->in_buffer_used) ||
1801 (0 != urh->out_buffer_used) )
1805 urh_update_pollfd (urh, p);
1808 (urh->in_buffer_used < urh->in_buffer_size)) ||
1814 if (MHD_sys_poll_ (p,
1824 _ (
"Error during poll: `%s'\n"),
1829 urh_from_pollfd (urh,
1855static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
1866 struct timeval *tvp;
1872#define EXTRA_SLOTS 1
1874#define EXTRA_SLOTS 0
1883 const bool use_poll = 0;
1885 bool was_suspended =
false;
1886 MHD_thread_init_ (&(con->
pid));
1892#ifdef UPGRADE_SUPPORT
1893 struct MHD_UpgradeResponseHandle *
const urh = con->urh;
1895 static const void *
const urh =
NULL;
1902 was_suspended =
true;
1911 #ifdef HAVE_MESSAGES
1913 _ (
"Failed to add FD to fd_set.\n"));
1929 _ (
"Error during select (%d): `%s'\n"),
1939 p[0].events = POLLIN;
1940 p[0].fd = MHD_itc_r_fd_ (daemon->
itc);
1942 if (0 > MHD_sys_poll_ (p,
1950 _ (
"Error during poll: `%s'\n"),
1957 MHD_itc_clear_ (daemon->
itc);
1966 was_suspended =
false;
1984 if ( (
NULL == tvp) &&
1992 const time_t seconds_left = timeout - (now - con->
last_activity);
1993#if ! defined(_WIN32) || defined(__CYGWIN__)
1994 tv.tv_sec = seconds_left;
2008 bool err_state =
false;
2042 if (MHD_ITC_IS_VALID_ (daemon->
itc) )
2055 _ (
"Failed to add FD to fd_set.\n"));
2073 _ (
"Error during select (%d): `%s'\n"),
2082 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2083 (FD_ISSET (MHD_itc_r_fd_ (daemon->
itc),
2085 MHD_itc_clear_ (daemon->
itc);
2108 p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
2111 p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
2114 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
2122 if (MHD_ITC_IS_VALID_ (daemon->
itc))
2124 p[1].events |= POLLIN;
2125 p[1].fd = MHD_itc_r_fd_ (daemon->
itc);
2130 if (MHD_sys_poll_ (p,
2136 (
NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
2142 _ (
"Error during poll: `%s'\n"),
2150 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2151 (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2152 MHD_itc_clear_ (daemon->
itc);
2156 (0 != (p[0].revents & POLLIN)),
2157 (0 != (p[0].revents & POLLOUT)),
2158 (0 != (p[0].revents & (POLLERR
2159 | MHD_POLL_REVENTS_ERR_DISC))) ))
2163#ifdef UPGRADE_SUPPORT
2164 if (MHD_CONNECTION_UPGRADE == con->
state)
2176 thread_main_connection_upgrade (con);
2180 con->urh->clean_ready =
true;
2188 return (MHD_THRD_RTRN_TYPE_) 0;
2195 _ (
"Processing thread terminating. Closing connection.\n"));
2219 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2220 (! MHD_itc_activate_ (daemon->
itc,
"t")) )
2225 "Failed to signal thread termination via inter-thread communication channel.\n"));
2228 return (MHD_THRD_RTRN_TYPE_) 0;
2245#if defined(HTTPS_SUPPORT)
2246#if defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED) && \
2247 defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) && \
2248 ! defined(MHD_socket_nosignal_) && \
2249 (GNUTLS_VERSION_NUMBER + 0 < 0x030402) && defined(MSG_NOSIGNAL)
2255#define MHD_TLSLIB_NEED_PUSH_FUNC 1
2261#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2267MHD_tls_push_func_ (gnutls_transport_ptr_t trnsp,
2271#if (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX)
2291psk_gnutls_adapter (gnutls_session_t session,
2292 const char *username,
2293 gnutls_datum_t *key)
2298 size_t app_psk_size;
2300 connection = gnutls_session_get_ptr (session);
2301 if (
NULL == connection)
2305 MHD_PANIC (
_ (
"Internal server error. This should be impossible.\n"));
2309 daemon = connection->
daemon;
2310#if GNUTLS_VERSION_MAJOR >= 3
2311 if (
NULL == daemon->cred_callback)
2315 _ (
"PSK not supported by this server.\n"));
2319 if (0 != daemon->cred_callback (daemon->cred_callback_cls,
2325 if (
NULL == (key->data = gnutls_malloc (app_psk_size)))
2330 "PSK authentication failed: gnutls_malloc failed to allocate memory.\n"));
2339 _ (
"PSK authentication failed: PSK too long.\n"));
2344 key->size = (
unsigned int) app_psk_size;
2353 _ (
"PSK not supported by this server.\n"));
2388 const struct sockaddr *
addr,
2392 bool sk_spipe_supprs,
2399#if _MHD_DEBUG_CONNECT
2401 _ (
"Accepted connection on socket %d.\n"),
2414 "Server reached connection limit. Closing inbound connection.\n"));
2432 _ (
"Connection rejected by application. Closing connection.\n"));
2450 _ (
"Error allocating memory: %s\n"),
2473 if (
NULL == (connection->
addr = malloc (addrlen)))
2478 _ (
"Error allocating memory: %s\n"),
2489 memcpy (connection->
addr,
2495 connection->
is_nonip = sk_is_nonip;
2508#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030500)
2515 flags = GNUTLS_SERVER;
2516#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030402)
2517 flags |= GNUTLS_NO_SIGNAL;
2519#if GNUTLS_VERSION_MAJOR >= 3
2520 flags |= GNUTLS_NONBLOCK;
2522#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030603)
2524 flags |= GNUTLS_POST_HANDSHAKE_AUTH;
2526#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030605)
2528 flags |= GNUTLS_ENABLE_EARLY_DATA;
2532 if ((GNUTLS_E_SUCCESS != gnutls_init (&connection->tls_session, flags)) ||
2533 (GNUTLS_E_SUCCESS != gnutls_priority_set (connection->tls_session,
2534 daemon->priority_cache)))
2536 if (
NULL != connection->tls_session)
2537 gnutls_deinit (connection->tls_session);
2542 free (connection->
addr);
2546 _ (
"Failed to initialise TLS session.\n"));
2553#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030200)
2554 if (!
daemon->disable_alpn)
2556 gnutls_datum_t prts[2];
2557 const char prt1[] =
"http/1.1";
2558 const char prt2[] =
"http/1.0";
2560 prts[0].data = (
void*) prt1;
2562 prts[1].data = (
void*) prt2;
2564 if (GNUTLS_E_SUCCESS !=
2565 gnutls_alpn_set_protocols (connection->tls_session,
2567 sizeof(prts) /
sizeof(prts[0]),
2572 _ (
"Failed to set ALPN protocols.\n"));
2579 gnutls_session_set_ptr (connection->tls_session,
2581 switch (
daemon->cred_type)
2584 case GNUTLS_CRD_CERTIFICATE:
2585 gnutls_credentials_set (connection->tls_session,
2586 GNUTLS_CRD_CERTIFICATE,
2589 case GNUTLS_CRD_PSK:
2590 gnutls_credentials_set (connection->tls_session,
2593 gnutls_psk_set_server_credentials_function (
daemon->psk_cred,
2594 &psk_gnutls_adapter);
2600 "Failed to setup TLS credentials: unknown credential type %d.\n"),
2603 gnutls_deinit (connection->tls_session);
2608 free (connection->
addr);
2610 MHD_PANIC (
_ (
"Unknown credential type.\n"));
2616#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030109) && ! defined(_WIN64)
2617 gnutls_transport_set_int (connection->tls_session,
2618 (
int) (client_socket));
2620 gnutls_transport_set_ptr (connection->tls_session,
2621 (gnutls_transport_ptr_t) (intptr_t) (client_socket));
2623#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2624 gnutls_transport_set_push_function (connection->tls_session,
2625 MHD_tls_push_func_);
2627 if (
daemon->https_mem_trust)
2628 gnutls_certificate_server_set_request (connection->tls_session,
2629 GNUTLS_CERT_REQUEST);
2635 free (connection->
addr);
2637 MHD_PANIC (
_ (
"TLS connection on non-TLS daemon.\n"));
2647#ifdef MHD_USE_THREADS
2666 if (
NULL != connection->tls_session)
2669 gnutls_deinit (connection->tls_session);
2676 free (connection->
addr);
2702#ifdef MHD_USE_THREADS
2706 MHD_thread_ID_match_current_ (
daemon->
pid) );
2718 _ (
"Error allocating memory: %s\n"),
2732#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2738#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2745 "Server reached connection limit. Closing inbound connection.\n"));
2762#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2770#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2776 daemon->thread_stack_size,
2783 _ (
"Failed to create a thread: %s\n"),
2797 struct epoll_event event;
2799 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2800 event.data.ptr = connection;
2801 if (0 != epoll_ctl (daemon->epoll_fd,
2809 _ (
"Call to epoll_ctl failed: %s\n"),
2822 daemon->eready_tail,
2837 if (
NULL != connection->tls_session)
2838 gnutls_deinit (connection->tls_session);
2844#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2856#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2860 free (connection->
addr);
2901 const struct sockaddr *addr,
2905 bool sk_spipe_supprs,
2910#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2920 _ (
"New connection socket descriptor (%d) is not less " \
2921 "than FD_SETSIZE (%d).\n"),
2922 (
int) client_socket,
2937 _ (
"Epoll mode supports only non-blocking sockets\n"));
2953 if (
NULL == connection)
2956 if ((external_add) &&
2969 if ((MHD_ITC_IS_VALID_ (
daemon->
itc)) &&
2970 (! MHD_itc_activate_ (
daemon->
itc,
"n")))
2972 #ifdef HAVE_MESSAGES
2974 _ (
"Failed to signal new connection via inter-thread " \
2975 "communication channel.\n"));
3019 _ (
"Failed to start serving new connection.\n"));
3023 }
while (
NULL != local_tail);
3042#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3045 MHD_thread_ID_match_current_ (daemon->
pid) );
3052#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3082 daemon->eready_tail,
3084 connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
3088 if (0 != epoll_ctl (daemon->epoll_fd,
3092 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
3093 connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
3098#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3140#ifdef MHD_USE_THREADS
3143 MHD_thread_ID_match_current_ (daemon->
pid) );
3148 "Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
3149#ifdef UPGRADE_SUPPORT
3150 if (
NULL != connection->urh)
3155 "Error: connection scheduled for \"upgrade\" cannot be suspended.\n"));
3179 "Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
3180#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3185#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3188 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
3189 (! MHD_itc_activate_ (daemon->
itc,
"r")) )
3194 "Failed to signal resume via inter-thread communication channel.\n"));
3217#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3220 MHD_thread_ID_match_current_ (
daemon->
pid) );
3224#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3240#ifdef UPGRADE_SUPPORT
3241 struct MHD_UpgradeResponseHandle *
const urh = pos->urh;
3243 static const void *
const urh =
NULL;
3247#ifdef UPGRADE_SUPPORT
3248 || ( (
NULL != urh) &&
3249 ( (! urh->was_closed) ||
3250 (! urh->clean_ready) ) )
3284 MHD_PANIC (
"Resumed connection was already in EREADY set.\n");
3288 daemon->eready_tail,
3293 pos->epoll_state &= ~MHD_EPOLL_STATE_SUSPENDED;
3297#ifdef UPGRADE_SUPPORT
3322#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3325 if ( (used_thr_p_c) &&
3328 if (! MHD_itc_activate_ (daemon->
itc,
3334 "Failed to signal resume of connection via inter-thread communication channel.\n"));
3372 const struct sockaddr *addr,
3376 bool sk_spipe_supprs;
3388 _ (
"MHD_add_connection() has been called for daemon started"
3389 " without MHD_USE_ITC flag.\nDaemon will not process newly"
3390 " added connection until any activity occurs in already"
3391 " added sockets.\n"));
3399 _ (
"Failed to set nonblocking mode on new client socket: %s\n"),
3407#ifndef MHD_WINSOCK_SOCKETS
3408 sk_spipe_supprs =
false;
3410 sk_spipe_supprs =
true;
3412#if defined(MHD_socket_nosignal_)
3413 if (! sk_spipe_supprs && ! MHD_socket_nosignal_ (client_socket))
3418 "Failed to suppress SIGPIPE on new client socket: %s\n"),
3436 sk_spipe_supprs =
true;
3444 _ (
"Failed to set noninheritable mode on new client socket.\n"));
3448#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3507 struct sockaddr_in6 addrstorage;
3509 struct sockaddr_in addrstorage;
3511 struct sockaddr *addr = (
struct sockaddr *) &addrstorage;
3516 bool sk_spipe_supprs;
3518#ifdef MHD_USE_THREADS
3520 MHD_thread_ID_match_current_ (daemon->
pid) );
3523 addrlen =
sizeof (addrstorage);
3526 sizeof (addrstorage));
3537#ifndef MHD_WINSOCK_SOCKETS
3540 sk_spipe_supprs =
true;
3547#ifndef MHD_WINSOCK_SOCKETS
3548 sk_spipe_supprs =
false;
3550 sk_spipe_supprs =
true;
3567 _ (
"Error accepting connection: %s\n"),
3585 "Hit process or system resource limit at FIRST connection. This is really bad as there is no sane way to proceed. Will try busy waiting for system resources to become magically available.\n"));
3590#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3594#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3600 "Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
3607#if ! defined(USE_ACCEPT4) || ! defined(HAVE_SOCK_NONBLOCK)
3613 "Failed to set nonblocking mode on incoming connection socket: %s\n"),
3620#if ! defined(USE_ACCEPT4) || ! defined(SOCK_CLOEXEC)
3626 "Failed to set noninheritable mode on incoming connection socket.\n"));
3630#if defined(MHD_socket_nosignal_)
3631 if (! sk_spipe_supprs && ! MHD_socket_nosignal_ (s))
3636 "Failed to suppress SIGPIPE on incoming connection socket: %s\n"),
3652 sk_spipe_supprs =
true;
3655#if _MHD_DEBUG_CONNECT
3657 _ (
"Accepted connection on socket %d\n"),
3686#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3688 MHD_thread_ID_match_current_ (
daemon->
pid) );
3697#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3701 (! MHD_join_thread_ (pos->
pid.handle)) )
3702 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
3704#ifdef UPGRADE_SUPPORT
3705 cleanup_upgraded_connection (pos);
3709 if (
NULL != pos->tls_session)
3710 gnutls_deinit (pos->tls_session);
3730 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
3732 if ( (-1 !=
daemon->epoll_fd) &&
3741 if (0 != epoll_ctl (
daemon->epoll_fd,
3745 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
3746 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
3761#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3767#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3797 time_t earliest_deadline;
3802#ifdef MHD_USE_THREADS
3804 MHD_thread_ID_match_current_ (
daemon->
pid) );
3811 _ (
"Illegal call to MHD_get_timeout.\n"));
3824#
if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
3835 have_timeout =
false;
3836 earliest_deadline = 0;
3841 if ( (! have_timeout) ||
3844 have_timeout =
true;
3849 if ( (
NULL != pos) &&
3852 if ( (! have_timeout) ||
3855 have_timeout =
true;
3861 if (earliest_deadline < now)
3865 const time_t second_left = earliest_deadline - now;
3867 if (((
unsigned long long) second_left) >
ULLONG_MAX / 1000)
3870 *timeout = 1000LLU * (
unsigned long long) second_left;
3888 int32_t max_timeout)
3891 if (0 == max_timeout)
3895 return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
3897 if ( (0 > max_timeout) ||
3898 ((uint32_t) max_timeout > ulltimeout) )
3899 return (INT_MAX < ulltimeout) ? INT_MAX : (int) ulltimeout;
3901 return (INT_MAX < max_timeout) ? INT_MAX : (int) max_timeout;
3917 const fd_set *read_fd_set,
3918 const fd_set *write_fd_set,
3919 const fd_set *except_fd_set)
3924#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3925 struct MHD_UpgradeResponseHandle *urh;
3926 struct MHD_UpgradeResponseHandle *urhn;
3935 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
3936 (FD_ISSET (MHD_itc_r_fd_ (daemon->
itc),
3938 MHD_itc_clear_ (daemon->
itc);
3955 while (
NULL != (pos = prev))
3971#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3973 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
3977 urh_from_fdset (urh,
3984 if ( (0 == urh->in_buffer_size) &&
3985 (0 == urh->out_buffer_size) &&
3986 (0 == urh->in_buffer_used) &&
3987 (0 == urh->out_buffer_used) )
3990 urh->clean_ready =
true;
4025 const fd_set *read_fd_set,
4026 const fd_set *write_fd_set,
4027 const fd_set *except_fd_set)
4033 if ((
NULL == read_fd_set) || (
NULL == write_fd_set))
4035 if (
NULL == except_fd_set)
4039 _ (
"MHD_run_from_select() called with except_fd_set "
4040 "set to NULL. Such behavior is deprecated.\n"));
4043 except_fd_set = &es;
4088 struct timeval timeout;
4094 timeout.tv_usec = 0;
4120 _ (
"Could not obtain daemon fdsets.\n"));
4137 _ (
"Could not add listen socket to fdset.\n"));
4142 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
4148#if defined(MHD_WINSOCK_SOCKETS)
4166 "Could not add control inter-thread communication channel FD to fdset.\n"));
4169#if defined(MHD_WINSOCK_SOCKETS)
4183 (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
4196 timeout.tv_usec = 0;
4208 if ( (0 < millisec) &&
4212 else if (0 < millisec)
4223 timeout.tv_usec = 0;
4228 timeout.tv_usec = (ltimeout % 1000) * 1000;
4246 _ (
"select failed: %s\n"),
4275 unsigned int num_connections;
4278#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4279 struct MHD_UpgradeResponseHandle *urh;
4280 struct MHD_UpgradeResponseHandle *urhn;
4288 num_connections = 0;
4291#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4292 for (urh = daemon->urh_head;
NULL != urh; urh = urh->next)
4293 num_connections += 2;
4298 unsigned int poll_server;
4305 sizeof (
struct pollfd));
4310 _ (
"Error allocating memory: %s\n"),
4323 p[poll_server].fd = ls;
4324 p[poll_server].events = POLLIN;
4325 p[poll_server].revents = 0;
4326 poll_listen = (int) poll_server;
4330 if (MHD_ITC_IS_VALID_ (daemon->
itc))
4332 p[poll_server].fd = MHD_itc_r_fd_ (daemon->
itc);
4333 p[poll_server].events = POLLIN;
4334 p[poll_server].revents = 0;
4335 poll_itc_idx = (int) poll_server;
4348 p[poll_server + i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
4351 p[poll_server + i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
4354 p[poll_server + i].events |= MHD_POLL_EVENTS_ERR_DISC;
4362#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4363 for (urh = daemon->urh_tail;
NULL != urh; urh = urh->prev)
4365 urh_to_pollfd (urh, &(p[poll_server + i]));
4369 if (0 == poll_server + num_connections)
4374 if (MHD_sys_poll_ (p,
4375 poll_server + num_connections,
4386 _ (
"poll failed: %s\n"),
4396 if ( (-1 != poll_itc_idx) &&
4397 (0 != (p[poll_itc_idx].revents & POLLIN)) )
4398 MHD_itc_clear_ (daemon->
itc);
4412 if ( (-1 != poll_listen) &&
4413 (0 != (p[poll_listen].revents & POLLIN)) )
4421 while (
NULL != (pos = prev))
4425 if (i >= num_connections)
4430 0 != (p[poll_server + i].revents & POLLIN),
4431 0 != (p[poll_server + i].revents & POLLOUT),
4432 0 != (p[poll_server + i].revents
4433 & MHD_POLL_REVENTS_ERR_DISC));
4436#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4437 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
4439 if (i >= num_connections)
4446 if ((p[poll_server + i].
fd != urh->connection->socket_fd) ||
4447 (p[poll_server + i + 1].fd != urh->mhd.socket))
4449 urh_from_pollfd (urh,
4450 &p[poll_server + i]);
4454 if ( (0 == urh->in_buffer_size) &&
4455 (0 == urh->out_buffer_size) &&
4456 (0 == urh->in_buffer_used) &&
4457 (0 == urh->out_buffer_used) )
4462 urh->clean_ready =
true;
4486MHD_poll_listen_socket (
struct MHD_Daemon *daemon,
4491 unsigned int poll_count;
4506 p[poll_count].fd = ls;
4507 p[poll_count].events = POLLIN;
4508 p[poll_count].revents = 0;
4509 poll_listen = poll_count;
4512 if (MHD_ITC_IS_VALID_ (daemon->
itc))
4514 p[poll_count].fd = MHD_itc_r_fd_ (daemon->
itc);
4515 p[poll_count].events = POLLIN;
4516 p[poll_count].revents = 0;
4517 poll_itc_idx = poll_count;
4528 if (0 == poll_count)
4530 if (MHD_sys_poll_ (p,
4540 _ (
"poll failed: %s\n"),
4545 if ( (-1 != poll_itc_idx) &&
4546 (0 != (p[poll_itc_idx].revents & POLLIN)) )
4547 MHD_itc_clear_ (daemon->
itc);
4557 if ( (-1 != poll_listen) &&
4558 (0 != (p[poll_listen].revents & POLLIN)) )
4582 return MHD_poll_all (daemon,
4583 may_block ? -1 : 0);
4584 return MHD_poll_listen_socket (daemon,
4604#define MAX_EVENTS 128
4607#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4617is_urh_ready (
struct MHD_UpgradeResponseHandle *
const urh)
4621 if ( (0 == urh->in_buffer_size) &&
4622 (0 == urh->out_buffer_size) &&
4623 (0 == urh->in_buffer_used) &&
4624 (0 == urh->out_buffer_used) )
4630 (urh->in_buffer_used < urh->in_buffer_size) )
4633 (urh->out_buffer_used < urh->out_buffer_size) )
4636 (urh->out_buffer_used > 0) )
4639 (urh->in_buffer_used > 0) )
4656 struct epoll_event events[MAX_EVENTS];
4658 struct MHD_UpgradeResponseHandle *pos;
4659 struct MHD_UpgradeResponseHandle *prev;
4661#ifdef MHD_USE_THREADS
4663 MHD_thread_ID_match_current_ (daemon->
pid) );
4666 num_events = MAX_EVENTS;
4667 while (0 != num_events)
4671 num_events = epoll_wait (daemon->epoll_upgrade_fd,
4675 if (-1 == num_events)
4683 _ (
"Call to epoll_wait failed: %s\n"),
4688 for (i = 0; i < (
unsigned int) num_events; i++)
4690 struct UpgradeEpollHandle *
const ueh = events[i].data.ptr;
4691 struct MHD_UpgradeResponseHandle *
const urh = ueh->urh;
4692 bool new_err_state =
false;
4694 if (urh->clean_ready)
4698 if (0 != (events[i].events & EPOLLIN))
4702 if (0 != (events[i].events & EPOLLOUT))
4706 if (0 != (events[i].events & EPOLLHUP))
4712 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
4717 new_err_state =
true;
4719 if (! urh->in_eready_list)
4721 if (new_err_state ||
4725 daemon->eready_urh_tail,
4727 urh->in_eready_list =
true;
4732 prev = daemon->eready_urh_tail;
4733 while (
NULL != (pos = prev))
4737 if (! is_urh_ready (pos))
4740 daemon->eready_urh_tail,
4742 pos->in_eready_list =
false;
4745 if ( (0 == pos->in_buffer_size) &&
4746 (0 == pos->out_buffer_size) &&
4747 (0 == pos->in_buffer_used) &&
4748 (0 == pos->out_buffer_used) )
4751 pos->clean_ready =
true;
4770static const char *
const epoll_itc_marker =
"itc_marker";
4786#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4787 static const char *
const upgrade_marker =
"upgrade_ptr";
4791 struct epoll_event events[MAX_EVENTS];
4792 struct epoll_event event;
4797#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4798 bool run_upgraded =
false;
4800 bool need_to_accept;
4802 if (-1 == daemon->epoll_fd)
4809 (! daemon->listen_socket_in_epoll) &&
4812 event.events = EPOLLIN;
4813 event.data.ptr = daemon;
4814 if (0 != epoll_ctl (daemon->epoll_fd,
4821 _ (
"Call to epoll_ctl failed: %s\n"),
4826 daemon->listen_socket_in_epoll =
true;
4829 (daemon->listen_socket_in_epoll) )
4831 if ( (0 != epoll_ctl (daemon->epoll_fd,
4837 MHD_PANIC (
"Failed to remove listen FD from epoll set.\n");
4838 daemon->listen_socket_in_epoll =
false;
4841#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4842 if ( ( (! daemon->upgrade_fd_in_epoll) &&
4843 (-1 != daemon->epoll_upgrade_fd) ) )
4845 event.events = EPOLLIN | EPOLLOUT;
4846 event.data.ptr = (
void *) upgrade_marker;
4847 if (0 != epoll_ctl (daemon->epoll_fd,
4849 daemon->epoll_upgrade_fd,
4854 _ (
"Call to epoll_ctl failed: %s\n"),
4859 daemon->upgrade_fd_in_epoll =
true;
4862 if ( (daemon->listen_socket_in_epoll) &&
4869 if (0 != epoll_ctl (daemon->epoll_fd,
4873 MHD_PANIC (
_ (
"Failed to remove listen FD from epoll set.\n"));
4874 daemon->listen_socket_in_epoll =
false;
4888 need_to_accept =
false;
4893 num_events = MAX_EVENTS;
4894 while (MAX_EVENTS == num_events)
4897 num_events = epoll_wait (daemon->epoll_fd,
4901 if (-1 == num_events)
4908 _ (
"Call to epoll_wait failed: %s\n"),
4913 for (i = 0; i<(
unsigned int) num_events; i++)
4919#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4920 if (upgrade_marker == events[i].
data.ptr)
4924 run_upgraded =
true;
4928 if (epoll_itc_marker == events[i].
data.ptr)
4932 MHD_itc_clear_ (daemon->
itc);
4935 if (daemon == events[i].
data.ptr)
4939 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
4940 need_to_accept =
true;
4946 pos = events[i].data.ptr;
4948 if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
4954 daemon->eready_tail,
4961 if (0 != (events[i].events & EPOLLIN))
4969 daemon->eready_tail,
4974 if (0 != (events[i].events & EPOLLOUT))
4981 daemon->eready_tail,
4996 unsigned int series_length = 0;
5003 (series_length < 10) &&
5018 while (
NULL != (pos = prev))
5028 while (
NULL != (pos = prev))
5036#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5037 if (run_upgraded || (
NULL != daemon->eready_urh_head))
5038 run_epoll_for_upgrade (daemon);
5042 prev = daemon->eready_tail;
5043 while (
NULL != (pos = prev))
5061 daemon->eready_tail,
5063 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
5153 res = MHD_poll_all (daemon, millisec);
5160 res = MHD_epoll (daemon, millisec);
5186#ifdef MHD_USE_THREADS
5188 MHD_thread_ID_match_current_ (daemon->
pid) );
5198#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5218#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5224#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5232static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
5236#ifdef HAVE_PTHREAD_SIGMASK
5241 MHD_thread_init_ (&(daemon->
pid));
5242#ifdef HAVE_PTHREAD_SIGMASK
5243 if ((0 == sigemptyset (&s_mask)) &&
5244 (0 == sigaddset (&s_mask, SIGPIPE)))
5246 err = pthread_sigmask (SIG_BLOCK, &s_mask,
NULL);
5255 _ (
"Failed to block SIGPIPE on daemon thread: %s\n"),
5265 MHD_epoll (daemon, -1);
5279 return (MHD_THRD_RTRN_TYPE_) 0;
5377#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5391 "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC.\n"));
5396#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5406 if (0 != epoll_ctl (daemon->
worker_pool[i].epoll_fd,
5410 MHD_PANIC (
_ (
"Failed to remove listen FD from epoll set.\n"));
5411 daemon->
worker_pool[i].listen_socket_in_epoll =
false;
5419 "Failed to signal quiesce via inter-thread communication channel.\n"));
5426 (-1 != daemon->epoll_fd) &&
5427 (daemon->listen_socket_in_epoll) )
5429 if ( (0 != epoll_ctl (daemon->epoll_fd,
5435 MHD_PANIC (
"Failed to remove listen FD from epoll set.\n");
5436 daemon->listen_socket_in_epoll =
false;
5439 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
5440 (! MHD_itc_activate_ (daemon->
itc,
"q")) )
5442 "failed to signal quiesce via inter-thread communication channel.\n"));
5470 const struct sockaddr **servaddr,
5484 const struct sockaddr **servaddr,
5490 va_start (ap, servaddr);
5509 const struct sockaddr **servaddr,
5519#if GNUTLS_VERSION_MAJOR >= 3
5520 gnutls_certificate_retrieve_function2 *pgcrf;
5522#if GNUTLS_VERSION_NUMBER >= 0x030603
5523 gnutls_certificate_retrieve_function3 *pgcrf2;
5559 _ (
"Warning: Too large timeout value, ignored.\n"));
5581 *servaddr = va_arg (ap,
5582 const struct sockaddr *);
5595#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5604 "Warning: Zero size, specified for thread pool size, is ignored. "
5605 "Thread pool is not used.\n"));
5613 "Warning: \"1\", specified for thread pool size, is ignored. "
5614 "Thread pool is not used.\n"));
5618#if (0 == (UINT_MAX + 0)) || (UINT_MAX >= (SIZE_MAX / (64 * 1024)))
5627 _ (
"Specified thread pool size (%u) too big.\n"),
5639 _ (
"MHD_OPTION_THREAD_POOL_SIZE option is specified but "
5640 "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
5648 _ (
"Both MHD_OPTION_THREAD_POOL_SIZE option and "
5649 "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
5661 daemon->https_mem_key = pstr;
5666 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5674 daemon->https_key_password = pstr;
5679 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5687 daemon->https_mem_cert = pstr;
5692 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5700 daemon->https_mem_trust = pstr;
5705 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5710 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
5718 gnutls_datum_t dhpar;
5721 if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
5725 _ (
"Error initializing DH parameters.\n"));
5729 dhpar.data = (
unsigned char *) pstr;
5730 pstr_len = strlen (pstr);
5735 _ (
"Diffie-Hellman parameters string too long.\n"));
5739 dhpar.size = (
unsigned int) pstr_len;
5740 if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
5742 GNUTLS_X509_FMT_PEM) < 0)
5746 _ (
"Bad Diffie-Hellman parameters format.\n"));
5748 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
5751 daemon->have_dhparams =
true;
5757 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5766 gnutls_priority_deinit (daemon->priority_cache);
5767 ret = gnutls_priority_init (&daemon->priority_cache,
5770 if (GNUTLS_E_SUCCESS != ret)
5774 _ (
"Setting priorities to `%s' failed: %s\n"),
5776 gnutls_strerror (ret));
5778 daemon->priority_cache =
NULL;
5786 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5791#if GNUTLS_VERSION_MAJOR < 3
5795 "MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0.\n"));
5800 gnutls_certificate_retrieve_function2 *);
5802 daemon->cert_callback = pgcrf;
5807 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5813#if GNUTLS_VERSION_NUMBER < 0x030603
5817 "MHD_OPTION_HTTPS_CERT_CALLBACK2 requires building MHD with GnuTLS >= 3.6.3.\n"));
5821 pgcrf2 = va_arg (ap,
5822 gnutls_certificate_retrieve_function3 *);
5824 daemon->cert_callback2 = pgcrf2;
5829 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5837 daemon->digest_auth_rand_size = va_arg (ap,
5839 daemon->digest_auth_random = va_arg (ap,
5843 daemon->nonce_nc_size = va_arg (ap,
5852 _ (
"MHD_OPTION_LISTEN_SOCKET specified for daemon "
5853 "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
5861#if defined(SO_DOMAIN) && defined(AF_UNIX)
5864 socklen_t len =
sizeof (af);
5884 daemon->custom_error_log = va_arg (ap,
5886 daemon->custom_error_log_cls = va_arg (ap,
5890 _ (
"MHD_OPTION_EXTERNAL_LOGGER is not the first option "
5891 "specified for the daemon. Some messages may be "
5892 "printed by the standard MHD logger.\n"));
5901#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5903 daemon->thread_stack_size = va_arg (ap,
5909 daemon->fastopen_queue_size = va_arg (ap,
5915 _ (
"TCP fastopen is not supported on this platform.\n"));
5921 unsigned int) ? 1 : -1;
5934 _ (
"Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
5935 "another behavior is specified by MHD_OPTION_STRICT_CLIENT.\n"));
5954 (
size_t) oa[i].
value,
5971 (
unsigned int) oa[i].
value,
5981 (gnutls_credentials_type_t) oa[i].
value,
6034 (
void *) oa[i].
value,
6044 (
size_t) oa[i].
value,
6063#if GNUTLS_VERSION_MAJOR >= 3
6064 daemon->cred_callback = va_arg (ap,
6066 daemon->cred_callback_cls = va_arg (ap,
6072 "MHD HTTPS option %d passed to MHD compiled without GNUtls >= 3.\n"),
6089 daemon->disable_alpn = (va_arg (ap,
6092 (void) va_arg (ap,
int);
6097 _ (
"MHD HTTPS option %d passed to MHD " \
6098 "but MHD_USE_TLS not set.\n"),
6111 "MHD HTTPS option %d passed to MHD compiled without HTTPS support.\n"),
6118 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?).\n"),
6135#ifndef HAVE_MESSAGES
6139#ifdef USE_EPOLL_CREATE1
6140 fd = epoll_create1 (EPOLL_CLOEXEC);
6142 fd = epoll_create (MAX_EVENTS);
6148 _ (
"Call to epoll_create1 failed: %s\n"),
6153#if ! defined(USE_EPOLL_CREATE1)
6158 _ (
"Failed to set noninheritable mode on epoll FD.\n"));
6175setup_epoll_to_listen (
struct MHD_Daemon *daemon)
6177 struct epoll_event event;
6184 MHD_ITC_IS_VALID_ (daemon->
itc) );
6185 daemon->epoll_fd = setup_epoll_fd (daemon);
6186 if (-1 == daemon->epoll_fd)
6188#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6191 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
6199 event.events = EPOLLIN;
6200 event.data.ptr = daemon;
6201 if (0 != epoll_ctl (daemon->epoll_fd,
6208 _ (
"Call to epoll_ctl failed: %s\n"),
6213 daemon->listen_socket_in_epoll =
true;
6216 if (MHD_ITC_IS_VALID_ (daemon->
itc))
6218 event.events = EPOLLIN;
6219 event.data.ptr = (
void *) epoll_itc_marker;
6220 if (0 != epoll_ctl (daemon->epoll_fd,
6222 MHD_itc_r_fd_ (daemon->
itc),
6227 _ (
"Call to epoll_ctl failed: %s\n"),
6273 struct sockaddr_in servaddr4;
6275 struct sockaddr_in6 servaddr6;
6277 const struct sockaddr *servaddr =
NULL;
6279#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6296#ifndef EPOLL_SUPPORT
6300#ifndef HTTPS_SUPPORT
6310#ifdef UPGRADE_SUPPORT
6346#if defined(EPOLL_SUPPORT)
6348#elif defined(HAVE_POLL)
6357#if defined(EPOLL_SUPPORT)
6368 daemon->epoll_fd = -1;
6369#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6370 daemon->epoll_upgrade_fd = -1;
6375 daemon->priority_cache =
NULL;
6378 gnutls_priority_init (&daemon->priority_cache,
6390 daemon->
port = port;
6401 MHD_itc_set_invalid_ (daemon->
itc);
6408 daemon->custom_error_log = &MHD_default_logger_;
6409 daemon->custom_error_log_cls = stderr;
6411#ifndef MHD_WINSOCK_SOCKETS
6425 *pflags &= ~MHD_USE_ITC;
6428#ifdef HAVE_LISTEN_SHUTDOWN
6434 daemon->digest_auth_rand_size = 0;
6435 daemon->digest_auth_random =
NULL;
6436 daemon->nonce_nc_size = 4;
6441 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
6452 (
NULL != daemon->priority_cache) )
6453 gnutls_priority_deinit (daemon->priority_cache);
6465 "Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with "
6466 "MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD "
6467 "was added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"));
6478 _ (
"Using debug build of libmicrohttpd.\n") );
6483#
if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6488 if (! MHD_itc_init_ (daemon->
itc))
6492 _ (
"Failed to create inter-thread communication channel: %s\n"),
6493 MHD_itc_last_strerror_ ());
6496 if (
NULL != daemon->priority_cache)
6497 gnutls_priority_deinit (daemon->priority_cache);
6509 "file descriptor for inter-thread communication channel exceeds maximum value.\n"));
6513 if (
NULL != daemon->priority_cache)
6514 gnutls_priority_deinit (daemon->priority_cache);
6522 if (daemon->nonce_nc_size > 0)
6524 if ( ( (
size_t) (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc)))
6525 /
sizeof(
struct MHD_NonceNc) != daemon->nonce_nc_size)
6529 _ (
"Specified value for NC_SIZE too large.\n"));
6533 gnutls_priority_deinit (daemon->priority_cache);
6538 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc));
6539 if (
NULL == daemon->nnc)
6543 _ (
"Failed to allocate memory for nonce-nc map: %s\n"),
6548 gnutls_priority_deinit (daemon->priority_cache);
6555#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6560 _ (
"MHD failed to initialize nonce-nc mutex.\n"));
6564 gnutls_priority_deinit (daemon->priority_cache);
6574#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6581 "MHD thread polling only works with MHD_USE_INTERNAL_POLLING_THREAD.\n"));
6593 domain = (*pflags &
MHD_USE_IPv6) ? PF_INET6 : PF_INET;
6605 _ (
"Failed to create socket for listening: %s\n"),
6614#ifndef MHD_WINSOCK_SOCKETS
6619 if (0 > setsockopt (listen_fd,
6622 (
void*) &on,
sizeof (on)))
6626 _ (
"setsockopt failed: %s\n"),
6635#ifndef MHD_WINSOCK_SOCKETS
6638 if (0 > setsockopt (listen_fd,
6641 (
void*) &on,
sizeof (on)))
6645 _ (
"setsockopt failed: %s\n"),
6655#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
6656 if (0 > setsockopt (listen_fd,
6658#ifndef MHD_WINSOCK_SOCKETS
6668 _ (
"setsockopt failed: %s\n"),
6679 "Cannot allow listening address reuse: SO_REUSEPORT not defined.\n"));
6692#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
6693 (defined(__sun) && defined(SO_EXCLBIND))
6694 if (0 > setsockopt (listen_fd,
6696#ifdef SO_EXCLUSIVEADDRUSE
6697 SO_EXCLUSIVEADDRUSE,
6706 _ (
"setsockopt failed: %s\n"),
6711#elif defined(MHD_WINSOCK_SOCKETS)
6715 "Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined.\n"));
6724 addrlen =
sizeof (
struct sockaddr_in6);
6727 addrlen =
sizeof (
struct sockaddr_in);
6728 if (
NULL == servaddr)
6733#ifdef IN6ADDR_ANY_INIT
6734 static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
6738 sizeof (
struct sockaddr_in6));
6739 servaddr6.sin6_family = AF_INET6;
6740 servaddr6.sin6_port = htons (port);
6741#ifdef IN6ADDR_ANY_INIT
6742 servaddr6.sin6_addr = static_in6any;
6744#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
6745 servaddr6.sin6_len =
sizeof (
struct sockaddr_in6);
6747 servaddr = (
struct sockaddr *) &servaddr6;
6754 sizeof (
struct sockaddr_in));
6755 servaddr4.sin_family = AF_INET;
6756 servaddr4.sin_port = htons (port);
6757 if (0 != INADDR_ANY)
6758 servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
6759#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
6760 servaddr4.sin_len =
sizeof (
struct sockaddr_in);
6762 servaddr = (
struct sockaddr *) &servaddr4;
6776 if (0 > setsockopt (listen_fd,
6777 IPPROTO_IPV6, IPV6_V6ONLY,
6778 (
const void *) &v6_only,
6783 _ (
"setsockopt failed: %s\n"),
6790 if (-1 == bind (listen_fd, servaddr, addrlen))
6794 _ (
"Failed to bind to port %u: %s\n"),
6795 (
unsigned int) port,
6804 if (0 == daemon->fastopen_queue_size)
6805 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
6806 if (0 != setsockopt (listen_fd,
6809 (
const void*) &daemon->fastopen_queue_size,
6810 sizeof (daemon->fastopen_queue_size)))
6814 _ (
"setsockopt failed: %s\n"),
6820 if (listen (listen_fd,
6825 _ (
"Failed to listen for connections: %s\n"),
6837#ifdef HAVE_GETSOCKNAME
6838 if ( (0 == daemon->
port) &&
6841 struct sockaddr_storage bindaddr;
6845 sizeof (
struct sockaddr_storage));
6846 addrlen =
sizeof (
struct sockaddr_storage);
6847#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
6848 bindaddr.ss_len = addrlen;
6850 if (0 != getsockname (listen_fd,
6851 (
struct sockaddr *) &bindaddr,
6856 _ (
"Failed to get listen port number: %s\n"),
6860#ifdef MHD_POSIX_SOCKETS
6861 else if (
sizeof (bindaddr) < addrlen)
6867 "Failed to get listen port number (`struct sockaddr_storage` too small!?).\n"));
6871 else if (0 == addrlen)
6881 switch (bindaddr.ss_family)
6885 struct sockaddr_in *s4 = (
struct sockaddr_in *) &bindaddr;
6887 daemon->
port = ntohs (s4->sin_port);
6893 struct sockaddr_in6 *s6 = (
struct sockaddr_in6 *) &bindaddr;
6895 daemon->
port = ntohs (s6->sin6_port);
6908 _ (
"Unknown address family!\n"));
6921 _ (
"Failed to set nonblocking mode on listening socket: %s\n"),
6925#
if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6944 _ (
"Listen socket descriptor (%d) is not " \
6945 "less than FD_SETSIZE (%d).\n"),
6955#
if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6965 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
6969 if (
MHD_NO == setup_epoll_to_listen (daemon))
6974#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6979 _ (
"MHD failed to initialize IP connection limit mutex.\n"));
6989 _ (
"MHD failed to initialize IP connection limit mutex.\n"));
6991#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7003 (0 != MHD_TLS_init (daemon)) )
7007 _ (
"Failed to initialize TLS support.\n"));
7011#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7018#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7026#ifdef HAVE_LISTEN_SHUTDOWN
7028 (MHD_ITC_IS_VALID_ (daemon->
itc)) || \
7032 (MHD_ITC_IS_VALID_ (daemon->
itc)));
7040 _ (
"Failed to initialise mutex.\n"));
7051 "MHD-listen" :
"MHD-single",
7052 daemon->thread_stack_size,
7058 _ (
"Failed to create listen thread: %s\n"),
7094 memcpy (d, daemon,
sizeof (
struct MHD_Daemon));
7103 #ifdef HAVE_MESSAGES
7105 _ (
"Failed to initialise mutex.\n"));
7111 if (! MHD_itc_init_ (d->
itc))
7116 "Failed to create worker inter-thread communication channel: %s\n"),
7117 MHD_itc_last_strerror_ () );
7129 "File descriptor for worker inter-thread communication channel exceeds maximum value.\n"));
7137 MHD_itc_set_invalid_ (d->
itc);
7139#ifdef HAVE_LISTEN_SHUTDOWN
7150 if (i < leftover_conns)
7154 (
MHD_NO == setup_epoll_to_listen (d)) )
7156 if (MHD_ITC_IS_VALID_ (d->
itc))
7167 _ (
"MHD failed to initialize cleanup connection mutex.\n"));
7169 if (MHD_ITC_IS_VALID_ (d->
itc))
7178 daemon->thread_stack_size,
7184 _ (
"Failed to create pool thread: %s\n"),
7190 if (MHD_ITC_IS_VALID_ (d->
itc))
7204 _ (
"Failed to initialise mutex.\n"));
7213 daemon->https_key_password =
NULL;
7218#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7247#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7248 if (daemon->upgrade_fd_in_epoll)
7250 if (0 != epoll_ctl (daemon->epoll_fd,
7252 daemon->epoll_upgrade_fd,
7254 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
7255 daemon->upgrade_fd_in_epoll =
false;
7258 if (-1 != daemon->epoll_fd)
7259 close (daemon->epoll_fd);
7260#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7261 if (-1 != daemon->epoll_upgrade_fd)
7262 close (daemon->epoll_upgrade_fd);
7267#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7274 gnutls_priority_deinit (daemon->priority_cache);
7275 if (daemon->x509_cred)
7276 gnutls_certificate_free_credentials (daemon->x509_cred);
7277 if (daemon->psk_cred)
7278 gnutls_psk_free_server_credentials (daemon->psk_cred);
7281 if (MHD_ITC_IS_VALID_ (daemon->
itc))
7302#ifdef UPGRADE_SUPPORT
7305#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7306 struct MHD_UpgradeResponseHandle *urh;
7307 struct MHD_UpgradeResponseHandle *urhn;
7311#ifdef MHD_USE_THREADS
7314 MHD_thread_ID_match_current_ (daemon->
pid) );
7319#ifdef MHD_USE_THREADS
7328 new_connection_close_ (daemon, pos);
7332#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7335 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
7343 urh->clean_ready =
true;
7360#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7363#ifdef UPGRADE_SUPPORT
7369 while (
NULL != susp)
7371 if (
NULL == susp->urh)
7373 "MHD_stop_daemon() called while we have suspended connections.\n"));
7375 else if (used_tls &&
7377 (! susp->urh->clean_ready) )
7378 shutdown (susp->urh->app.socket,
7384 if (! susp->urh->was_closed)
7387 "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
7389 susp->urh->was_closed =
true;
7406 "MHD_stop_daemon() called while we have suspended connections.\n"));
7407#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
7408#ifdef MHD_USE_THREADS
7409 if (upg_allowed && used_tls && used_thr_p_c)
7427 if (! MHD_join_thread_ (pos->
pid.handle))
7428 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
7440#if MHD_WINSOCK_SOCKETS
7443 (! MHD_itc_activate_ (
daemon->
itc,
"e")) )
7445 "Failed to signal shutdown via inter-thread communication channel.\n"));
7449#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7459 if (! MHD_join_thread_ (pos->
pid.handle))
7460 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
7474#ifdef UPGRADE_SUPPORT
7490#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7493 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
7511#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7518 MHD_PANIC (
_ (
"MHD_stop_daemon() was called twice."));
7528#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7543 "Failed to signal shutdown via inter-thread communication channel.\n"));
7548#ifdef HAVE_LISTEN_SHUTDOWN
7551 (void) shutdown (
fd,
7563#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7571#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7581 "Failed to signal shutdown via inter-thread communication channel.\n"));
7585#ifdef HAVE_LISTEN_SHUTDOWN
7589 (void) shutdown (
fd,
7597 if (! MHD_join_thread_ (
daemon->
pid.handle))
7599 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
7609#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7617#if defined(UPGRADE_SUPPORT) && defined (HTTPS_SUPPORT)
7626 (-1 !=
daemon->epoll_fd) )
7628#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7630 (-1 !=
daemon->epoll_upgrade_fd) )
7635#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7649 if (
daemon->have_dhparams)
7651 gnutls_dh_params_deinit (
daemon->https_mem_dhparams);
7652 daemon->have_dhparams =
false;
7656 gnutls_priority_deinit (
daemon->priority_cache);
7658 gnutls_certificate_free_credentials (
daemon->x509_cred);
7660 gnutls_psk_free_server_credentials (
daemon->psk_cred);
7666#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7670#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7715#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7773#ifdef PACKAGE_VERSION
7774 return PACKAGE_VERSION;
7776 static char ver[12] =
"\0\0\0\0\0\0\0\0\0\0\0";
7779 int res = MHD_snprintf_ (ver,
7785 if ((0 >= res) || (
sizeof(ver) <= res))
7822#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
7828#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030603
7840#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
7858#ifdef HAVE_LISTEN_SHUTDOWN
7864#ifdef _MHD_ITC_SOCKETPAIR
7888#ifdef HAVE_POSTPROCESSOR
7894#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
7900#if defined(HAVE_PREAD64) || defined(_WIN32)
7902#elif defined(HAVE_PREAD)
7903 return (
sizeof(uint64_t) >
sizeof(off_t)) ?
MHD_NO :
MHD_YES;
7904#elif defined(HAVE_LSEEK64)
7907 return (
sizeof(uint64_t) >
sizeof(off_t)) ?
MHD_NO :
MHD_YES;
7910#if defined(MHD_USE_THREAD_NAME_)
7916#if defined(UPGRADE_SUPPORT)
7922#if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
7928#ifdef MHD_USE_GETSOCKNAME
7934#if defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) && \
7935 defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED)
7941#ifdef _MHD_HAVE_SENDFILE
7947#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7958#ifdef MHD_HTTPS_REQUIRE_GRYPT
7959#if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
7960#if defined(MHD_USE_POSIX_THREADS)
7961GCRY_THREAD_OPTION_PTHREAD_IMPL;
7962#elif defined(MHD_W32_MUTEX_)
7965gcry_w32_mutex_init (
void **ppmtx)
7967 *ppmtx = malloc (
sizeof (MHD_mutex_));
7983gcry_w32_mutex_destroy (
void **ppmtx)
7992gcry_w32_mutex_lock (
void **ppmtx)
7999gcry_w32_mutex_unlock (
void **ppmtx)
8005static struct gcry_thread_cbs gcry_threads_w32 = {
8006 (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
8007 NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
8008 gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
8022#if defined(MHD_WINSOCK_SOCKETS)
8029#if defined(MHD_WINSOCK_SOCKETS)
8030 if (0 != WSAStartup (MAKEWORD (2, 2), &wsd))
8031 MHD_PANIC (
_ (
"Failed to initialize winsock.\n"));
8032 mhd_winsock_inited_ = 1;
8033 if ((2 != LOBYTE (wsd.wVersion)) && (2 != HIBYTE (wsd.wVersion)))
8034 MHD_PANIC (
_ (
"Winsock version 2.2 is not available.\n"));
8037#ifdef MHD_HTTPS_REQUIRE_GRYPT
8038#if GCRYPT_VERSION_NUMBER < 0x010600
8039#if defined(MHD_USE_POSIX_THREADS)
8040 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
8041 &gcry_threads_pthread))
8042 MHD_PANIC (
_ (
"Failed to initialise multithreading in libgcrypt.\n"));
8043#elif defined(MHD_W32_MUTEX_)
8044 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
8046 MHD_PANIC (
_ (
"Failed to initialise multithreading in libgcrypt.\n"));
8048 gcry_check_version (
NULL);
8050 if (
NULL == gcry_check_version (
"1.6.0"))
8052 "libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer.\n"));
8055 gnutls_global_init ();
8067 gnutls_global_deinit ();
8069#if defined(MHD_WINSOCK_SOCKETS)
8070 if (mhd_winsock_inited_)
8077#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
#define _SET_INIT_AND_DEINIT_FUNCS(FI, FD)
void MHD_connection_handle_read(struct MHD_Connection *connection)
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)
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 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)
static void mhd_panic_std(void *cls, const char *file, unsigned int line, const char *reason)
_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 MHD_TYPE_IS_SIGNED_(type)
#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)
time_t MHD_monotonic_sec_counter(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.
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)
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
#define MHD_UNSIGNED_LONG_LONG_PRINTF
_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
time_t connection_timeout
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
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
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
time_t connection_timeout
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