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)
40 #include "mhd_locks.h"
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)
170 static 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_
190 MHD_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_
224 MHD_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)
536 MHD_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)
754 urh_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)))
832 urh_from_fdset (
struct MHD_UpgradeResponseHandle *urh,
837 const MHD_socket conn_sckt = urh->connection->socket_fd;
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))
876 urh_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;
917 urh_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,
933 urh_from_pollfd (
struct MHD_UpgradeResponseHandle *urh,
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
1083 #ifdef HAVE_MESSAGES
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)
1145 #ifdef HAVE_MESSAGES
1147 _ (
"MHD_get_fdset2() called with except_fd_set "
1148 "set to NULL. Such behavior is unsupported.\n"));
1151 except_fd_set = &es;
1154 #ifdef EPOLL_SUPPORT
1199 bool states_info_processed =
false;
1203 #ifdef HTTPS_SUPPORT
1214 states_info_processed =
true;
1223 states_info_processed =
true;
1233 if (! states_info_processed)
1280 #ifdef HTTPS_SUPPORT
1290 #ifdef UPGRADE_SUPPORT
1301 struct MHD_UpgradeResponseHandle *urh = connection->urh;
1305 #ifdef HTTPS_SUPPORT
1309 gnutls_bye (connection->tls_session,
1318 connection->urh =
NULL;
1326 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1336 process_urh (
struct MHD_UpgradeResponseHandle *urh)
1349 #ifdef MHD_USE_THREADS
1351 MHD_thread_ID_match_current_ (connection->
pid) );
1356 #ifdef HAVE_MESSAGES
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)
1373 #ifdef HAVE_MESSAGES
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;
1394 urh->in_buffer_size = 0;
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)
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],
1494 urh->out_buffer_size = 0;
1500 urh->out_buffer_used += res;
1501 if (buf_size > (
size_t) res)
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)
1536 if (GNUTLS_E_AGAIN != res)
1540 #ifdef HAVE_MESSAGES
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;
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)
1568 urh->out_buffer_used = next_out_buffer_used;
1570 if ( (0 == urh->out_buffer_used) &&
1578 urh->out_buffer_size = 0;
1587 (urh->in_buffer_used > 0) )
1592 data_size = urh->in_buffer_used;
1610 #ifdef HAVE_MESSAGES
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;
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)
1639 urh->in_buffer_used = next_in_buffer_used;
1641 if ( (0 == urh->in_buffer_used) &&
1647 urh->in_buffer_size = 0;
1656 (urh->in_buffer_used < urh->in_buffer_size) &&
1661 ( (0 != urh->out_buffer_size) ||
1662 (0 != urh->out_buffer_used) ) )
1665 #ifdef HAVE_MESSAGES
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;
1679 urh->out_buffer_size = 0;
1687 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1688 #ifdef UPGRADE_SUPPORT
1700 #ifdef HTTPS_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,
1737 #ifdef HAVE_MESSAGES
1739 _ (
"Error preparing select.\n"));
1749 (urh->in_buffer_used < urh->in_buffer_size)) ||
1772 #ifdef HAVE_MESSAGES
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,
1822 #ifdef HAVE_MESSAGES
1824 _ (
"Error during poll: `%s'\n"),
1829 urh_from_pollfd (urh,
1855 static 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"));
1927 #ifdef HAVE_MESSAGES
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,
1948 #ifdef HAVE_MESSAGES
1950 _ (
"Error during poll: `%s'\n"),
1957 MHD_itc_clear_ (daemon->
itc);
1966 was_suspended =
false;
1972 #ifdef HTTPS_SUPPORT
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) )
2053 #ifdef HAVE_MESSAGES
2055 _ (
"Failed to add FD to fd_set.\n"));
2071 #ifdef HAVE_MESSAGES
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)
2140 #ifdef HAVE_MESSAGES
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;
2192 #if _MHD_DEBUG_CLOSE
2193 #ifdef HAVE_MESSAGES
2195 _ (
"Processing thread terminating. Closing connection.\n"));
2219 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2220 (! MHD_itc_activate_ (daemon->
itc,
"t")) )
2222 #ifdef HAVE_MESSAGES
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
2267 MHD_tls_push_func_ (gnutls_transport_ptr_t trnsp,
2271 #if (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX)
2291 psk_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)
2303 #ifdef HAVE_MESSAGES
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)
2313 #ifdef HAVE_MESSAGES
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)))
2327 #ifdef HAVE_MESSAGES
2330 "PSK authentication failed: gnutls_malloc failed to allocate memory.\n"));
2337 #ifdef HAVE_MESSAGES
2339 _ (
"PSK authentication failed: PSK too long.\n"));
2344 key->size = (
unsigned int) app_psk_size;
2351 #ifdef HAVE_MESSAGES
2353 _ (
"PSK not supported by this server.\n"));
2388 const struct sockaddr *
addr,
2392 bool sk_spipe_supprs,
2398 #ifdef HAVE_MESSAGES
2399 #if _MHD_DEBUG_CONNECT
2401 _ (
"Accepted connection on socket %d.\n"),
2411 #ifdef HAVE_MESSAGES
2414 "Server reached connection limit. Closing inbound connection.\n"));
2429 #if _MHD_DEBUG_CLOSE
2430 #ifdef HAVE_MESSAGES
2432 _ (
"Connection rejected by application. Closing connection.\n"));
2448 #ifdef HAVE_MESSAGES
2450 _ (
"Error allocating memory: %s\n"),
2473 if (
NULL == (connection->
addr = malloc (addrlen)))
2476 #ifdef HAVE_MESSAGES
2478 _ (
"Error allocating memory: %s\n"),
2489 memcpy (connection->
addr,
2495 connection->
is_nonip = sk_is_nonip;
2507 #ifdef HTTPS_SUPPORT
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);
2544 #ifdef HAVE_MESSAGES
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]),
2570 #ifdef HAVE_MESSAGES
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);
2597 #ifdef HAVE_MESSAGES
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
2661 #ifdef EPOLL_SUPPORT
2665 #ifdef HTTPS_SUPPORT
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) );
2716 #ifdef HAVE_MESSAGES
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)
2742 #ifdef HAVE_MESSAGES
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,
2781 #ifdef HAVE_MESSAGES
2783 _ (
"Failed to create a thread: %s\n"),
2792 #ifdef EPOLL_SUPPORT
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,
2807 #ifdef HAVE_MESSAGES
2809 _ (
"Call to epoll_ctl failed: %s\n"),
2822 daemon->eready_tail,
2836 #ifdef HTTPS_SUPPORT
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)
2918 #ifdef HAVE_MESSAGES
2920 _ (
"New connection socket descriptor (%d) is not less " \
2921 "than FD_SETSIZE (%d).\n"),
2922 (
int) client_socket,
2935 #ifdef HAVE_MESSAGES
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"));
3017 #ifdef HAVE_MESSAGES
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)
3076 #ifdef EPOLL_SUPPORT
3082 daemon->eready_tail,
3088 if (0 != epoll_ctl (daemon->epoll_fd,
3092 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
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)
3152 #ifdef HAVE_MESSAGES
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")) )
3191 #ifdef HAVE_MESSAGES
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) ) )
3280 #ifdef EPOLL_SUPPORT
3284 MHD_PANIC (
"Resumed connection was already in EREADY set.\n");
3288 daemon->eready_tail,
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,
3331 #ifdef HAVE_MESSAGES
3334 "Failed to signal resume of connection via inter-thread communication channel.\n"));
3372 const struct sockaddr *addr,
3376 bool sk_spipe_supprs;
3383 #ifdef HAVE_MESSAGES
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"));
3397 #ifdef HAVE_MESSAGES
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))
3415 #ifdef HAVE_MESSAGES
3418 "Failed to suppress SIGPIPE on new client socket: %s\n"),
3423 #ifndef MSG_NOSIGNAL
3436 sk_spipe_supprs =
true;
3442 #ifdef HAVE_MESSAGES
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;
3564 #ifdef HAVE_MESSAGES
3567 _ (
"Error accepting connection: %s\n"),
3579 #ifdef HAVE_MESSAGES
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)
3597 #ifdef HAVE_MESSAGES
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)
3610 #ifdef HAVE_MESSAGES
3613 "Failed to set nonblocking mode on incoming connection socket: %s\n"),
3620 #if ! defined(USE_ACCEPT4) || ! defined(SOCK_CLOEXEC)
3623 #ifdef HAVE_MESSAGES
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))
3633 #ifdef HAVE_MESSAGES
3636 "Failed to suppress SIGPIPE on incoming connection socket: %s\n"),
3641 #ifndef MSG_NOSIGNAL
3652 sk_spipe_supprs =
true;
3654 #ifdef HAVE_MESSAGES
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);
3708 #ifdef HTTPS_SUPPORT
3709 if (
NULL != pos->tls_session)
3710 gnutls_deinit (pos->tls_session);
3722 #ifdef EPOLL_SUPPORT
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"));
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) );
3809 #ifdef HAVE_MESSAGES
3811 _ (
"Illegal call to MHD_get_timeout.\n"));
3821 #ifdef EPOLL_SUPPORT
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)
4037 #ifdef HAVE_MESSAGES
4039 _ (
"MHD_run_from_select() called with except_fd_set "
4040 "set to NULL. Such behavior is deprecated.\n"));
4043 except_fd_set = &es;
4047 #ifdef EPOLL_SUPPORT
4088 struct timeval timeout;
4094 timeout.tv_usec = 0;
4118 #ifdef HAVE_MESSAGES
4120 _ (
"Could not obtain daemon fdsets.\n"));
4135 #ifdef HAVE_MESSAGES
4137 _ (
"Could not add listen socket to fdset.\n"));
4142 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
4148 #if defined(MHD_WINSOCK_SOCKETS)
4163 #ifdef HAVE_MESSAGES
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;
4244 #ifdef HAVE_MESSAGES
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));
4308 #ifdef HAVE_MESSAGES
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,
4384 #ifdef HAVE_MESSAGES
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;
4486 MHD_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,
4538 #ifdef HAVE_MESSAGES
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,
4594 #ifdef EPOLL_SUPPORT
4604 #define MAX_EVENTS 128
4607 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4617 is_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)
4681 #ifdef HAVE_MESSAGES
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;
4770 static 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,
4819 #ifdef HAVE_MESSAGES
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,
4852 #ifdef HAVE_MESSAGES
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)
4906 #ifdef HAVE_MESSAGES
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,
5153 res = MHD_poll_all (daemon, millisec);
5157 #ifdef EPOLL_SUPPORT
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)
5232 static 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);
5252 #ifdef HAVE_MESSAGES
5255 _ (
"Failed to block SIGPIPE on daemon thread: %s\n"),
5263 #ifdef EPOLL_SUPPORT
5265 MHD_epoll (daemon, -1);
5279 return (MHD_THRD_RTRN_TYPE_) 0;
5377 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5388 #ifdef HAVE_MESSAGES
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)
5401 #ifdef EPOLL_SUPPORT
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"));
5424 #ifdef EPOLL_SUPPORT
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,
5516 #ifdef HTTPS_SUPPORT
5519 #if GNUTLS_VERSION_MAJOR >= 3
5520 gnutls_certificate_retrieve_function2 *pgcrf;
5522 #if GNUTLS_VERSION_NUMBER >= 0x030603
5523 gnutls_certificate_retrieve_function3 *pgcrf2;
5557 #ifdef HAVE_MESSAGES
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)
5601 #ifdef HAVE_MESSAGES
5604 "Warning: Zero size, specified for thread pool size, is ignored. "
5605 "Thread pool is not used.\n"));
5610 #ifdef HAVE_MESSAGES
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)))
5625 #ifdef HAVE_MESSAGES
5627 _ (
"Specified thread pool size (%u) too big.\n"),
5637 #ifdef HAVE_MESSAGES
5639 _ (
"MHD_OPTION_THREAD_POOL_SIZE option is specified but "
5640 "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
5646 #ifdef HAVE_MESSAGES
5648 _ (
"Both MHD_OPTION_THREAD_POOL_SIZE option and "
5649 "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
5656 #ifdef HTTPS_SUPPORT
5661 daemon->https_mem_key = pstr;
5662 #ifdef HAVE_MESSAGES
5666 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5674 daemon->https_key_password = pstr;
5675 #ifdef HAVE_MESSAGES
5679 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5687 daemon->https_mem_cert = pstr;
5688 #ifdef HAVE_MESSAGES
5692 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5700 daemon->https_mem_trust = pstr;
5701 #ifdef HAVE_MESSAGES
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)
5723 #ifdef HAVE_MESSAGES
5725 _ (
"Error initializing DH parameters.\n"));
5729 dhpar.data = (
unsigned char *) pstr;
5730 pstr_len = strlen (pstr);
5733 #ifdef HAVE_MESSAGES
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)
5744 #ifdef HAVE_MESSAGES
5746 _ (
"Bad Diffie-Hellman parameters format.\n"));
5748 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
5751 daemon->have_dhparams =
true;
5753 #ifdef HAVE_MESSAGES
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)
5772 #ifdef HAVE_MESSAGES
5774 _ (
"Setting priorities to `%s' failed: %s\n"),
5776 gnutls_strerror (ret));
5778 daemon->priority_cache =
NULL;
5782 #ifdef HAVE_MESSAGES
5786 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5791 #if GNUTLS_VERSION_MAJOR < 3
5792 #ifdef HAVE_MESSAGES
5795 "MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0.\n"));
5800 gnutls_certificate_retrieve_function2 *);
5802 daemon->cert_callback = pgcrf;
5803 #ifdef HAVE_MESSAGES
5807 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5813 #if GNUTLS_VERSION_NUMBER < 0x030603
5814 #ifdef HAVE_MESSAGES
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;
5825 #ifdef HAVE_MESSAGES
5829 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5835 #ifdef DAUTH_SUPPORT
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,
5850 #ifdef HAVE_MESSAGES
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);
5883 #ifdef HAVE_MESSAGES
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,
5913 #ifdef HAVE_MESSAGES
5915 _ (
"TCP fastopen is not supported on this platform.\n"));
5921 unsigned int) ? 1 : -1;
5929 #ifdef HAVE_MESSAGES
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,
5976 #ifdef HTTPS_SUPPORT
5981 (gnutls_credentials_type_t) oa[i].
value,
6034 (
void *) oa[i].
value,
6044 (
size_t) oa[i].
value,
6061 #ifdef HTTPS_SUPPORT
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"),
6088 #ifdef HTTPS_SUPPORT
6089 daemon->disable_alpn = (va_arg (ap,
6092 (void) va_arg (ap,
int);
6094 #ifdef HAVE_MESSAGES
6097 _ (
"MHD HTTPS option %d passed to MHD " \
6098 "but MHD_USE_TLS not set.\n"),
6103 #ifdef HAVE_MESSAGES
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"),
6129 #ifdef EPOLL_SUPPORT
6135 #ifndef HAVE_MESSAGES
6139 #ifdef USE_EPOLL_CREATE1
6140 fd = epoll_create1 (EPOLL_CLOEXEC);
6142 fd = epoll_create (MAX_EVENTS);
6146 #ifdef HAVE_MESSAGES
6148 _ (
"Call to epoll_create1 failed: %s\n"),
6153 #if ! defined(USE_EPOLL_CREATE1)
6156 #ifdef HAVE_MESSAGES
6158 _ (
"Failed to set noninheritable mode on epoll FD.\n"));
6175 setup_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,
6206 #ifdef HAVE_MESSAGES
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),
6225 #ifdef HAVE_MESSAGES
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
6304 #ifndef TCP_FASTOPEN
6310 #ifdef UPGRADE_SUPPORT
6346 #if defined(EPOLL_SUPPORT)
6348 #elif defined(HAVE_POLL)
6357 #if defined(EPOLL_SUPPORT)
6367 #ifdef EPOLL_SUPPORT
6368 daemon->epoll_fd = -1;
6369 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6370 daemon->epoll_upgrade_fd = -1;
6374 #ifdef HTTPS_SUPPORT
6375 daemon->priority_cache =
NULL;
6378 gnutls_priority_init (&daemon->priority_cache,
6390 daemon->
port = port;
6401 MHD_itc_set_invalid_ (daemon->
itc);
6407 #ifdef HAVE_MESSAGES
6408 daemon->custom_error_log = &MHD_default_logger_;
6409 daemon->custom_error_log_cls = stderr;
6411 #ifndef MHD_WINSOCK_SOCKETS
6428 #ifdef HAVE_LISTEN_SHUTDOWN
6433 #ifdef DAUTH_SUPPORT
6434 daemon->digest_auth_rand_size = 0;
6435 daemon->digest_auth_random =
NULL;
6436 daemon->nonce_nc_size = 4;
6438 #ifdef HTTPS_SUPPORT
6441 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
6450 #ifdef HTTPS_SUPPORT
6452 (
NULL != daemon->priority_cache) )
6453 gnutls_priority_deinit (daemon->priority_cache);
6459 #ifdef HAVE_MESSAGES
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"));
6476 #ifdef HAVE_MESSAGES
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))
6490 #ifdef HAVE_MESSAGES
6492 _ (
"Failed to create inter-thread communication channel: %s\n"),
6493 MHD_itc_last_strerror_ ());
6495 #ifdef HTTPS_SUPPORT
6496 if (
NULL != daemon->priority_cache)
6497 gnutls_priority_deinit (daemon->priority_cache);
6506 #ifdef HAVE_MESSAGES
6509 "file descriptor for inter-thread communication channel exceeds maximum value.\n"));
6512 #ifdef HTTPS_SUPPORT
6513 if (
NULL != daemon->priority_cache)
6514 gnutls_priority_deinit (daemon->priority_cache);
6521 #ifdef DAUTH_SUPPORT
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)
6527 #ifdef HAVE_MESSAGES
6529 _ (
"Specified value for NC_SIZE too large.\n"));
6531 #ifdef HTTPS_SUPPORT
6533 gnutls_priority_deinit (daemon->priority_cache);
6538 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc));
6539 if (
NULL == daemon->nnc)
6541 #ifdef HAVE_MESSAGES
6543 _ (
"Failed to allocate memory for nonce-nc map: %s\n"),
6546 #ifdef HTTPS_SUPPORT
6548 gnutls_priority_deinit (daemon->priority_cache);
6555 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6558 #ifdef HAVE_MESSAGES
6560 _ (
"MHD failed to initialize nonce-nc mutex.\n"));
6562 #ifdef HTTPS_SUPPORT
6564 gnutls_priority_deinit (daemon->priority_cache);
6574 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6578 #ifdef HAVE_MESSAGES
6581 "MHD thread polling only works with MHD_USE_INTERNAL_POLLING_THREAD.\n"));
6593 domain = (*pflags &
MHD_USE_IPv6) ? PF_INET6 : PF_INET;
6603 #ifdef HAVE_MESSAGES
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)))
6624 #ifdef HAVE_MESSAGES
6626 _ (
"setsockopt failed: %s\n"),
6635 #ifndef MHD_WINSOCK_SOCKETS
6638 if (0 > setsockopt (listen_fd,
6641 (
void*) &on,
sizeof (on)))
6643 #ifdef HAVE_MESSAGES
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
6666 #ifdef HAVE_MESSAGES
6668 _ (
"setsockopt failed: %s\n"),
6676 #ifdef HAVE_MESSAGES
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,
6704 #ifdef HAVE_MESSAGES
6706 _ (
"setsockopt failed: %s\n"),
6711 #elif defined(MHD_WINSOCK_SOCKETS)
6712 #ifdef HAVE_MESSAGES
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,
6781 #ifdef HAVE_MESSAGES
6783 _ (
"setsockopt failed: %s\n"),
6790 if (-1 == bind (listen_fd, servaddr, addrlen))
6792 #ifdef HAVE_MESSAGES
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)))
6812 #ifdef HAVE_MESSAGES
6814 _ (
"setsockopt failed: %s\n"),
6820 if (listen (listen_fd,
6823 #ifdef HAVE_MESSAGES
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,
6854 #ifdef HAVE_MESSAGES
6856 _ (
"Failed to get listen port number: %s\n"),
6860 #ifdef MHD_POSIX_SOCKETS
6861 else if (
sizeof (bindaddr) < addrlen)
6864 #ifdef HAVE_MESSAGES
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);
6906 #ifdef HAVE_MESSAGES
6908 _ (
"Unknown address family!\n"));
6919 #ifdef HAVE_MESSAGES
6921 _ (
"Failed to set nonblocking mode on listening socket: %s\n"),
6925 #
if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6942 #ifdef HAVE_MESSAGES
6944 _ (
"Listen socket descriptor (%d) is not " \
6945 "less than FD_SETSIZE (%d).\n"),
6953 #ifdef EPOLL_SUPPORT
6955 #
if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6962 #ifdef HAVE_MESSAGES
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)
6977 #ifdef HAVE_MESSAGES
6979 _ (
"MHD failed to initialize IP connection limit mutex.\n"));
6987 #ifdef HAVE_MESSAGES
6989 _ (
"MHD failed to initialize IP connection limit mutex.\n"));
6991 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7000 #ifdef HTTPS_SUPPORT
7003 (0 != MHD_TLS_init (daemon)) )
7005 #ifdef HAVE_MESSAGES
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)));
7038 #ifdef HAVE_MESSAGES
7040 _ (
"Failed to initialise mutex.\n"));
7051 "MHD-listen" :
"MHD-single",
7052 daemon->thread_stack_size,
7056 #ifdef HAVE_MESSAGES
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))
7113 #ifdef HAVE_MESSAGES
7116 "Failed to create worker inter-thread communication channel: %s\n"),
7117 MHD_itc_last_strerror_ () );
7126 #ifdef HAVE_MESSAGES
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)
7152 #ifdef EPOLL_SUPPORT
7154 (
MHD_NO == setup_epoll_to_listen (d)) )
7156 if (MHD_ITC_IS_VALID_ (d->
itc))
7165 #ifdef HAVE_MESSAGES
7167 _ (
"MHD failed to initialize cleanup connection mutex.\n"));
7169 if (MHD_ITC_IS_VALID_ (d->
itc))
7178 daemon->thread_stack_size,
7182 #ifdef HAVE_MESSAGES
7184 _ (
"Failed to create pool thread: %s\n"),
7190 if (MHD_ITC_IS_VALID_ (d->
itc))
7202 #ifdef HAVE_MESSAGES
7204 _ (
"Failed to initialise mutex.\n"));
7210 #ifdef HTTPS_SUPPORT
7213 daemon->https_key_password =
NULL;
7218 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7246 #ifdef EPOLL_SUPPORT
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);
7265 #ifdef DAUTH_SUPPORT
7267 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7271 #ifdef HTTPS_SUPPORT
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"));
7374 #ifdef HTTPS_SUPPORT
7375 else if (used_tls &&
7377 (! susp->urh->clean_ready) )
7378 shutdown (susp->urh->app.socket,
7383 #ifdef HAVE_MESSAGES
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,
7561 #ifdef EPOLL_SUPPORT
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)
7624 #ifdef EPOLL_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)
7648 #ifdef HTTPS_SUPPORT
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);
7664 #ifdef DAUTH_SUPPORT
7666 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7670 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7704 #ifdef EPOLL_SUPPORT
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))
7810 #ifdef HAVE_MESSAGES
7816 #ifdef HTTPS_SUPPORT
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)
7852 #ifdef EPOLL_SUPPORT
7858 #ifdef HAVE_LISTEN_SHUTDOWN
7864 #ifdef _MHD_ITC_SOCKETPAIR
7876 #ifdef BAUTH_SUPPORT
7882 #ifdef DAUTH_SUPPORT
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)
7961 GCRY_THREAD_OPTION_PTHREAD_IMPL;
7962 #elif defined(MHD_W32_MUTEX_)
7965 gcry_w32_mutex_init (
void **ppmtx)
7967 *ppmtx = malloc (
sizeof (MHD_mutex_));
7983 gcry_w32_mutex_destroy (
void **ppmtx)
7992 gcry_w32_mutex_lock (
void **ppmtx)
7999 gcry_w32_mutex_unlock (
void **ppmtx)
8005 static 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"));
8036 #ifdef HTTPS_SUPPORT
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 ();
8066 #ifdef HTTPS_SUPPORT
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.
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_connection_finish_forward_(struct MHD_Connection *connection) MHD_NONNULL(1)
void MHD_set_https_callbacks(struct MHD_Connection *connection)
Methods for managing connections.
void MHD_update_last_activity_(struct MHD_Connection *connection)
void MHD_suspend_connection(struct MHD_Connection *connection)
static void close_all_connections(struct MHD_Daemon *daemon)
static struct MHD_Daemon * MHD_get_master(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)
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)
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 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 enum MHD_Result MHD_get_fdset(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd)
_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)
_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 * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
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 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