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)
54#ifdef MHD_HTTPS_REQUIRE_GRYPT
59#if defined(_WIN32) && ! defined(__CYGWIN__)
60#ifndef WIN32_LEAN_AND_MEAN
61#define WIN32_LEAN_AND_MEAN 1
69#ifdef MHD_POSIX_SOCKETS
70#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 4)
72#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2)
78#define MHD_POOL_SIZE_DEFAULT (32 * 1024)
84#define DEBUG_CLOSE MHD_NO
90#define DEBUG_CONNECT MHD_NO
140 _ (
"Fatal error in GNU libmicrohttpd %s:%u: %s\n"),
170#if defined(MHD_WINSOCK_SOCKETS)
174static int mhd_winsock_inited_ = 0;
177#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
182#define MHD_check_global_init_() (void) 0
189#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
190#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
194MHD_MUTEX_STATIC_DEFN_INIT_ (global_init_mutex_);
206#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
207#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
213#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
214#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
232 vfprintf ((FILE*) cls, fm, ap);
234 fflush ((FILE*) cls);
293 struct in6_addr ipv6;
312#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
328#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
351 offsetof (
struct MHD_IPCount,
367 struct MHD_IPCount *key)
374 if (
sizeof (
struct sockaddr_in) == addrlen)
376 const struct sockaddr_in *addr4 = (
const struct sockaddr_in*) addr;
378 key->family = AF_INET;
379 memcpy (&key->addr.ipv4,
381 sizeof(addr4->sin_addr));
387 if (
sizeof (
struct sockaddr_in6) == addrlen)
389 const struct sockaddr_in6 *addr6 = (
const struct sockaddr_in6*) addr;
391 key->family = AF_INET6;
392 memcpy (&key->addr.ipv6,
394 sizeof(addr6->sin6_addr));
417 const struct sockaddr *addr,
420 struct MHD_IPCount *key;
430 if (
NULL == (key = malloc (
sizeof(*key))))
451 _ (
"Failed to add IP connection count node.\n"));
461 key = (
struct MHD_IPCount *) node;
483 const struct sockaddr *addr,
486 struct MHD_IPCount search_key;
487 struct MHD_IPCount *found_key;
509 MHD_PANIC (
_ (
"Failed to find previously-added IP address.\n"));
511 found_key = (
struct MHD_IPCount *) *nodep;
513 if (0 == found_key->count)
515 MHD_PANIC (
_ (
"Previously-added IP address had counter of zero.\n"));
518 if (0 == --found_key->count)
538MHD_init_daemon_certificate (
struct MHD_Daemon *daemon)
544#if GNUTLS_VERSION_MAJOR >= 3
545 if (
NULL != daemon->cert_callback)
547 gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
548 daemon->cert_callback);
551#if GNUTLS_VERSION_NUMBER >= 0x030603
552 else if (
NULL != daemon->cert_callback2)
554 gnutls_certificate_set_retrieve_function3 (daemon->x509_cred,
555 daemon->cert_callback2);
559 if (
NULL != daemon->https_mem_trust)
562 paramlen = strlen (daemon->https_mem_trust);
567 "Too long trust certificate.\n");
571 cert.data = (
unsigned char *) daemon->https_mem_trust;
572 cert.size = (
unsigned int) paramlen;
573 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred,
575 GNUTLS_X509_FMT_PEM) < 0)
579 "Bad trust certificate format.\n");
585 if (daemon->have_dhparams)
587 gnutls_certificate_set_dh_params (daemon->x509_cred,
588 daemon->https_mem_dhparams);
591 if ( (
NULL != daemon->https_mem_cert) &&
592 (
NULL != daemon->https_mem_key) )
597 param1len = strlen (daemon->https_mem_key);
598 param2len = strlen (daemon->https_mem_cert);
604 "Too long key or certificate.\n");
608 key.data = (
unsigned char *) daemon->https_mem_key;
609 key.size = (
unsigned int) param1len;
610 cert.data = (
unsigned char *) daemon->https_mem_cert;
611 cert.size = (
unsigned int) param2len;
613 if (
NULL != daemon->https_key_password)
615#if GNUTLS_VERSION_NUMBER >= 0x030111
616 ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
620 daemon->https_key_password,
625 _ (
"Failed to setup x509 certificate/key: pre 3.X.X version " \
626 "of GnuTLS does not support setting key password.\n"));
632 ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
635 GNUTLS_X509_FMT_PEM);
639 "GnuTLS failed to setup x509 certificate/key: %s\n",
640 gnutls_strerror (ret));
644#if GNUTLS_VERSION_MAJOR >= 3
645 if (
NULL != daemon->cert_callback)
648#if GNUTLS_VERSION_NUMBER >= 0x030603
649 else if (
NULL != daemon->cert_callback2)
654 "You need to specify a certificate and key location.\n");
669 switch (daemon->cred_type)
671 case GNUTLS_CRD_CERTIFICATE:
673 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
674 return GNUTLS_E_MEMORY_ERROR;
675 return MHD_init_daemon_certificate (daemon);
678 gnutls_psk_allocate_server_credentials (&daemon->psk_cred))
679 return GNUTLS_E_MEMORY_ERROR;
684 _ (
"Error: invalid credentials type %d specified.\n"),
729 fd_set *write_fd_set,
730 fd_set *except_fd_set,
742#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
756urh_to_fdset (
struct MHD_UpgradeResponseHandle *urh,
761 unsigned int fd_setsize)
763 const MHD_socket conn_sckt = urh->connection->socket_fd;
771 if ( (urh->in_buffer_used < urh->in_buffer_size) &&
777 if ( (0 != urh->out_buffer_used) &&
786 ((0 != urh->in_buffer_size) ||
787 (0 != urh->out_buffer_size) ||
788 (0 != urh->out_buffer_used)))
796 if ( (urh->out_buffer_used < urh->out_buffer_size) &&
802 if ( (0 != urh->in_buffer_used) &&
811 ((0 != urh->out_buffer_size) ||
812 (0 != urh->in_buffer_size) ||
813 (0 != urh->in_buffer_used)))
834urh_from_fdset (
struct MHD_UpgradeResponseHandle *urh,
839 const MHD_socket conn_sckt = urh->connection->socket_fd;
843 urh->app.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
844 urh->mhd.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
848 if (FD_ISSET (conn_sckt, rs))
850 if (FD_ISSET (conn_sckt, ws))
852 if (FD_ISSET (conn_sckt, es))
857 if (FD_ISSET (mhd_sckt, rs))
859 if (FD_ISSET (mhd_sckt, ws))
861 if (FD_ISSET (mhd_sckt, es))
878urh_update_pollfd (
struct MHD_UpgradeResponseHandle *urh,
884 if (urh->in_buffer_used < urh->in_buffer_size)
885 p[0].events |= POLLIN;
886 if (0 != urh->out_buffer_used)
887 p[0].events |= POLLOUT;
892 ((0 != urh->in_buffer_size) ||
893 (0 != urh->out_buffer_size) ||
894 (0 != urh->out_buffer_used)))
895 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
897 if (urh->out_buffer_used < urh->out_buffer_size)
898 p[1].events |= POLLIN;
899 if (0 != urh->in_buffer_used)
900 p[1].events |= POLLOUT;
905 ((0 != urh->out_buffer_size) ||
906 (0 != urh->in_buffer_size) ||
907 (0 != urh->in_buffer_used)))
908 p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
919urh_to_pollfd (
struct MHD_UpgradeResponseHandle *urh,
922 p[0].fd = urh->connection->socket_fd;
923 p[1].fd = urh->mhd.socket;
924 urh_update_pollfd (urh,
935urh_from_pollfd (
struct MHD_UpgradeResponseHandle *urh,
939 urh->app.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
940 urh->mhd.celi &= (~MHD_EPOLL_STATE_READ_READY & ~MHD_EPOLL_STATE_WRITE_READY);
942 if (0 != (p[0].revents & POLLIN))
944 if (0 != (p[0].revents & POLLOUT))
946 if (0 != (p[0].revents & POLLHUP))
948 if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
950 if (0 != (p[1].revents & POLLIN))
952 if (0 != (p[1].revents & POLLOUT))
954 if (0 != (p[1].revents & POLLHUP))
956 if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
982 fd_set *write_fd_set,
983 fd_set *except_fd_set,
985 unsigned int fd_setsize)
1021#ifdef MHD_POSIX_SOCKETS
1034#ifdef MHD_POSIX_SOCKETS
1042 if ( (
NULL == except_fd_set) ||
1054#ifdef MHD_WINSOCK_SOCKETS
1067#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1069 struct MHD_UpgradeResponseHandle *urh;
1071 for (urh = daemon->urh_tail;
NULL != urh; urh = urh->prev)
1088 _ (
"Maximum socket in select set: %d\n"),
1130 fd_set *read_fd_set,
1131 fd_set *write_fd_set,
1132 fd_set *except_fd_set,
1134 unsigned int fd_setsize)
1138 if ( (
NULL == daemon) ||
1139 (
NULL == read_fd_set) ||
1140 (
NULL == write_fd_set) ||
1145 if (
NULL == except_fd_set)
1149 _ (
"MHD_get_fdset2() called with except_fd_set "
1150 "set to NULL. Such behavior is unsupported.\n"));
1153 except_fd_set = &es;
1201 bool states_info_processed =
false;
1216 states_info_processed =
true;
1225 states_info_processed =
true;
1235 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)
1352 if (! urh->was_closed)
1356 "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
1359 urh->was_closed =
true;
1361 was_closed = urh->was_closed;
1366 if (0 < urh->in_buffer_used)
1371 "Failed to forward to application "
1373 " bytes of data received from remote side: application shut down socket.\n"),
1382if (0 != urh->out_buffer_size)
1385 urh->in_buffer_used = 0;
1387 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1389 urh->in_buffer_size = 0;
1390 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1409 (urh->in_buffer_used < urh->in_buffer_size) )
1414 buf_size = urh->in_buffer_size - urh->in_buffer_used;
1419 res = gnutls_record_recv (connection->tls_session,
1420 &urh->in_buffer[urh->in_buffer_used],
1424 if (GNUTLS_E_INTERRUPTED != res)
1426 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1427 if (GNUTLS_E_AGAIN != res)
1432 urh->in_buffer_size = 0;
1438 urh->in_buffer_used += res;
1439 if (buf_size > (
size_t) res)
1440 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1441 else if (0 < gnutls_record_check_pending (connection->tls_session))
1450 urh->in_buffer_size = 0;
1458 (urh->out_buffer_used < urh->out_buffer_size) )
1463 buf_size = urh->out_buffer_size - urh->out_buffer_used;
1468 &urh->out_buffer[urh->out_buffer_used],
1477 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1487 urh->out_buffer_size = 0;
1493 urh->out_buffer_used += res;
1494 if (buf_size > (
size_t) res)
1495 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1504 urh->out_buffer_size = 0;
1512 (urh->out_buffer_used > 0) )
1517 data_size = urh->out_buffer_used;
1521 res = gnutls_record_send (connection->tls_session,
1526 if (GNUTLS_E_INTERRUPTED != res)
1528 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1529 if (GNUTLS_E_AGAIN != res)
1536 "Failed to forward to remote client "
1538 " bytes of data received from application: %s\n"),
1540 gnutls_strerror (res));
1543 urh->out_buffer_used = 0;
1545 urh->out_buffer_size = 0;
1546 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1552 const size_t next_out_buffer_used = urh->out_buffer_used - res;
1553 if (0 != next_out_buffer_used)
1555 memmove (urh->out_buffer,
1556 &urh->out_buffer[res],
1557 next_out_buffer_used);
1558 if (data_size > (
size_t) res)
1559 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1561 urh->out_buffer_used = next_out_buffer_used;
1563 if ( (0 == urh->out_buffer_used) &&
1569 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1571 urh->out_buffer_size = 0;
1572 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1580 (urh->in_buffer_used > 0) )
1585 data_size = urh->in_buffer_used;
1598 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1606 "Failed to forward to application "
1608 " bytes of data received from remote side: %s\n"),
1613 urh->in_buffer_used = 0;
1615 urh->in_buffer_size = 0;
1616 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1623 const size_t next_in_buffer_used = urh->in_buffer_used - res;
1624 if (0 != next_in_buffer_used)
1626 memmove (urh->in_buffer,
1627 &urh->in_buffer[res],
1628 next_in_buffer_used);
1629 if (data_size > (
size_t) res)
1630 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1632 urh->in_buffer_used = next_in_buffer_used;
1634 if ( (0 == urh->in_buffer_used) &&
1638 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1640 urh->in_buffer_size = 0;
1641 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1649 (urh->in_buffer_used < urh->in_buffer_size) &&
1654 ( (0 != urh->out_buffer_size) ||
1655 (0 != urh->out_buffer_used) ) )
1659 if (0 < urh->out_buffer_used)
1662 "Failed to forward to remote client "
1664 " bytes of data received from application: daemon shut down.\n"),
1668 urh->out_buffer_used = 0;
1670 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1672 urh->out_buffer_size = 0;
1673 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1680#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1681#ifdef UPGRADE_SUPPORT
1694 struct MHD_UpgradeResponseHandle *urh = con->urh;
1703 while ( (0 != urh->in_buffer_size) ||
1704 (0 != urh->out_buffer_size) ||
1705 (0 != urh->in_buffer_used) ||
1706 (0 != urh->out_buffer_used) )
1720 result = urh_to_fdset (urh,
1730 _ (
"Error preparing select.\n"));
1740 (urh->in_buffer_used < urh->in_buffer_size))
1764 _ (
"Error during select (%d): `%s'\n"),
1770 urh_from_fdset (urh,
1785 p[0].fd = urh->connection->socket_fd;
1786 p[1].fd = urh->mhd.socket;
1788 while ( (0 != urh->in_buffer_size) ||
1789 (0 != urh->out_buffer_size) ||
1790 (0 != urh->in_buffer_used) ||
1791 (0 != urh->out_buffer_used) )
1795 urh_update_pollfd (urh, p);
1798 (urh->in_buffer_used < urh->in_buffer_size))
1803 if (MHD_sys_poll_ (p,
1813 _ (
"Error during poll: `%s'\n"),
1818 urh_from_pollfd (urh,
1844static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
1855 struct timeval *tvp;
1861#define EXTRA_SLOTS 1
1863#define EXTRA_SLOTS 0
1872 const bool use_poll = 0;
1874 bool was_suspended =
false;
1875 MHD_thread_init_ (&(con->
pid));
1881#ifdef UPGRADE_SUPPORT
1882 struct MHD_UpgradeResponseHandle *
const urh = con->urh;
1884 static const void *
const urh =
NULL;
1891 was_suspended =
true;
1900 #ifdef HAVE_MESSAGES
1902 _ (
"Failed to add FD to fd_set.\n"));
1918 _ (
"Error during select (%d): `%s'\n"),
1928 p[0].events = POLLIN;
1929 p[0].fd = MHD_itc_r_fd_ (daemon->
itc);
1931 if (0 > MHD_sys_poll_ (p,
1939 _ (
"Error during poll: `%s'\n"),
1946 MHD_itc_clear_ (daemon->
itc);
1955 was_suspended =
false;
1973 if ( (
NULL == tvp) &&
1981 const time_t seconds_left = timeout - (now - con->
last_activity);
1982#if ! defined(_WIN32) || defined(__CYGWIN__)
1983 tv.tv_sec = seconds_left;
1997 bool err_state =
false;
2031 if (MHD_ITC_IS_VALID_ (daemon->
itc) )
2044 _ (
"Failed to add FD to fd_set.\n"));
2062 _ (
"Error during select (%d): `%s'\n"),
2071 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2072 (FD_ISSET (MHD_itc_r_fd_ (daemon->
itc),
2074 MHD_itc_clear_ (daemon->
itc);
2097 p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
2100 p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
2103 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
2111 if (MHD_ITC_IS_VALID_ (daemon->
itc))
2113 p[1].events |= POLLIN;
2114 p[1].fd = MHD_itc_r_fd_ (daemon->
itc);
2119 if (MHD_sys_poll_ (p,
2125 (
NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
2131 _ (
"Error during poll: `%s'\n"),
2139 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2140 (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2141 MHD_itc_clear_ (daemon->
itc);
2145 (0 != (p[0].revents & POLLIN)),
2146 (0 != (p[0].revents & POLLOUT)),
2147 (0 != (p[0].revents & (POLLERR
2148 | MHD_POLL_REVENTS_ERR_DISC))) ))
2152#ifdef UPGRADE_SUPPORT
2153 if (MHD_CONNECTION_UPGRADE == con->
state)
2165 thread_main_connection_upgrade (con);
2169 con->urh->clean_ready =
true;
2177 return (MHD_THRD_RTRN_TYPE_) 0;
2184 _ (
"Processing thread terminating. Closing connection.\n"));
2208 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2209 (! MHD_itc_activate_ (daemon->
itc,
"t")) )
2214 "Failed to signal thread termination via inter-thread communication channel.\n"));
2217 return (MHD_THRD_RTRN_TYPE_) 0;
2234#if defined(HTTPS_SUPPORT)
2235#if ! defined(MHD_WINSOCK_SOCKETS) && ! defined(MHD_socket_nosignal_) && \
2236 (GNUTLS_VERSION_NUMBER + 0 < 0x030402) && defined(MSG_NOSIGNAL)
2242#define MHD_TLSLIB_NEED_PUSH_FUNC 1
2245#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2251MHD_tls_push_func_ (gnutls_transport_ptr_t trnsp,
2255#if (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX)
2275psk_gnutls_adapter (gnutls_session_t session,
2276 const char *username,
2277 gnutls_datum_t *key)
2282 size_t app_psk_size;
2284 connection = gnutls_session_get_ptr (session);
2285 if (
NULL == connection)
2289 MHD_PANIC (
_ (
"Internal server error. This should be impossible.\n"));
2293 daemon = connection->
daemon;
2294#if GNUTLS_VERSION_MAJOR >= 3
2295 if (
NULL == daemon->cred_callback)
2299 _ (
"PSK not supported by this server.\n"));
2303 if (0 != daemon->cred_callback (daemon->cred_callback_cls,
2309 if (
NULL == (key->data = gnutls_malloc (app_psk_size)))
2314 "PSK authentication failed: gnutls_malloc failed to allocate memory.\n"));
2323 _ (
"PSK authentication failed: PSK too long.\n"));
2328 key->size = (
unsigned int) app_psk_size;
2337 _ (
"PSK not supported by this server.\n"));
2375 const struct sockaddr *addr,
2381#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2387#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2421 _ (
"Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
2422 (
int) client_socket,
2432#ifdef MHD_socket_nosignal_
2433 if (! MHD_socket_nosignal_ (client_socket))
2437 _ (
"Failed to set SO_NOSIGPIPE on accepted socket: %s\n"),
2454 _ (
"Accepted connection on socket %d.\n"),
2467 "Server reached connection limit. Closing inbound connection.\n"));
2485 _ (
"Connection rejected by application. Closing connection.\n"));
2503 "Error allocating memory: %s\n",
2519 _ (
"Error allocating memory: %s\n"),
2534 if (
NULL == (connection->
addr = malloc (addrlen)))
2539 _ (
"Error allocating memory: %s\n"),
2551 memcpy (connection->
addr,
2557 connection->
daemon = daemon;
2568#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030500)
2575 flags = GNUTLS_SERVER;
2576#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030402)
2577 flags |= GNUTLS_NO_SIGNAL;
2579#if GNUTLS_VERSION_MAJOR >= 3
2580 flags |= GNUTLS_NONBLOCK;
2582#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030603)
2584 flags |= GNUTLS_POST_HANDSHAKE_AUTH;
2586#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030605)
2588 flags |= GNUTLS_ENABLE_EARLY_DATA;
2592 gnutls_init (&connection->tls_session,
2594 gnutls_priority_set (connection->tls_session,
2595 daemon->priority_cache);
2596 gnutls_session_set_ptr (connection->tls_session,
2598 switch (daemon->cred_type)
2601 case GNUTLS_CRD_CERTIFICATE:
2602 gnutls_credentials_set (connection->tls_session,
2603 GNUTLS_CRD_CERTIFICATE,
2606 case GNUTLS_CRD_PSK:
2607 gnutls_credentials_set (connection->tls_session,
2610 gnutls_psk_set_server_credentials_function (daemon->psk_cred,
2611 &psk_gnutls_adapter);
2615 MHD_DLOG (connection->
daemon,
2617 "Failed to setup TLS credentials: unknown credential type %d.\n"),
2624 free (connection->
addr);
2626 MHD_PANIC (
_ (
"Unknown credential type.\n"));
2632#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030109) && ! defined(_WIN64)
2633 gnutls_transport_set_int (connection->tls_session,
2634 (
int) (client_socket));
2636 gnutls_transport_set_ptr (connection->tls_session,
2637 (gnutls_transport_ptr_t) (intptr_t) (client_socket));
2639#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2640 gnutls_transport_set_push_function (connection->tls_session,
2641 MHD_tls_push_func_);
2643 if (daemon->https_mem_trust)
2644 gnutls_certificate_server_set_request (connection->tls_session,
2645 GNUTLS_CERT_REQUEST);
2652#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2658#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2665 "Server reached connection limit. Closing inbound connection.\n"));
2682#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2690#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2696 daemon->thread_stack_size,
2703 "Failed to create a thread: %s\n",
2710 connection->
pid = daemon->
pid;
2717 struct epoll_event event;
2719 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2720 event.data.ptr = connection;
2721 if (0 != epoll_ctl (daemon->epoll_fd,
2729 _ (
"Call to epoll_ctl failed: %s\n"),
2742 daemon->eready_tail,
2750 (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2751 (! MHD_itc_activate_ (daemon->
itc,
"n")) )
2756 "Failed to signal new connection via inter-thread communication channel.\n"));
2767 if (
NULL != connection->tls_session)
2768 gnutls_deinit (connection->tls_session);
2774#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2786#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2790 free (connection->
addr);
2814#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2821#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2851 daemon->eready_tail,
2853 connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
2857 if (0 != epoll_ctl (daemon->epoll_fd,
2861 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
2862 connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
2867#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2911 "Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2912#ifdef UPGRADE_SUPPORT
2913 if (
NULL != connection->urh)
2918 "Error: connection scheduled for \"upgrade\" cannot be suspended.\n"));
2942 "Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2943#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2948#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2951 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2952 (! MHD_itc_activate_ (daemon->
itc,
"r")) )
2957 "Failed to signal resume via inter-thread communication channel.\n"));
2980#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2984#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2998#ifdef UPGRADE_SUPPORT
2999 struct MHD_UpgradeResponseHandle *
const urh = pos->urh;
3001 static const void *
const urh =
NULL;
3005#ifdef UPGRADE_SUPPORT
3006 || ( (
NULL != urh) &&
3007 ( (! urh->was_closed) ||
3008 (! urh->clean_ready) ) )
3042 MHD_PANIC (
"Resumed connection was already in EREADY set.\n");
3046 daemon->eready_tail,
3051 pos->epoll_state &= ~MHD_EPOLL_STATE_SUSPENDED;
3055#ifdef UPGRADE_SUPPORT
3080#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3083 if ( (used_thr_p_c) &&
3086 if (! MHD_itc_activate_ (daemon->
itc,
3092 "Failed to signal resume of connection via inter-thread communication channel.\n"));
3130 const struct sockaddr *addr,
3140 _ (
"Failed to set nonblocking mode on new client socket: %s\n"),
3153 _ (
"Failed to set noninheritable mode on new client socket.\n"));
3162 _ (
"Failed to reset buffering mode on new client socket.\n"));
3192 struct sockaddr_in6 addrstorage;
3194 struct sockaddr_in addrstorage;
3196 struct sockaddr *addr = (
struct sockaddr *) &addrstorage;
3202 addrlen =
sizeof (addrstorage);
3205 sizeof (addrstorage));
3235 _ (
"Error accepting connection: %s\n"),
3253 "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"));
3258#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3262#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3268 "Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
3275#if defined(MHD_TCP_CORK_NOPUSH) || defined(HAVE_MSG_MORE)
3280 (EOPNOTSUPP != errno) )
3284 _ (
"Failed to disable TCP Nagle on socket: %s\n"),
3289#if ! defined(USE_ACCEPT4) || ! defined(HAVE_SOCK_NONBLOCK)
3295 "Failed to set nonblocking mode on incoming connection socket: %s\n"),
3302#if ! defined(USE_ACCEPT4) || ! defined(SOCK_CLOEXEC)
3308 "Failed to set noninheritable mode on incoming connection socket.\n"));
3315 _ (
"Accepted connection on socket %d\n"),
3343#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3351#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3355 (! MHD_join_thread_ (pos->
pid.handle)) )
3356 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
3358#ifdef UPGRADE_SUPPORT
3359 cleanup_upgraded_connection (pos);
3363 if (
NULL != pos->tls_session)
3364 gnutls_deinit (pos->tls_session);
3384 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
3386 if ( (-1 !=
daemon->epoll_fd) &&
3394if (0 != epoll_ctl (
daemon->epoll_fd,
3398 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
3399 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
3414#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3420#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3450 time_t earliest_deadline;
3459 _ (
"Illegal call to MHD_get_timeout.\n"));
3474#
if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
3485 have_timeout =
false;
3486 earliest_deadline = 0;
3491 if ( (! have_timeout) ||
3494 have_timeout =
true;
3499 if ( (
NULL != pos) &&
3502 if ( (! have_timeout) ||
3505 have_timeout =
true;
3511 if (earliest_deadline < now)
3515 const time_t second_left = earliest_deadline - now;
3517 if (((
unsigned long long) second_left) >
ULLONG_MAX / 1000)
3520 *timeout = 1000LLU * (
unsigned long long) second_left;
3538 const fd_set *read_fd_set,
3539 const fd_set *write_fd_set,
3540 const fd_set *except_fd_set)
3545#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3546 struct MHD_UpgradeResponseHandle *urh;
3547 struct MHD_UpgradeResponseHandle *urhn;
3556 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
3557 (FD_ISSET (MHD_itc_r_fd_ (daemon->
itc),
3559 MHD_itc_clear_ (daemon->
itc);
3572 while (
NULL != (pos = prev))
3588#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3590 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
3594 urh_from_fdset (urh,
3601 if ( (0 == urh->in_buffer_size) &&
3602 (0 == urh->out_buffer_size) &&
3603 (0 == urh->in_buffer_used) &&
3604 (0 == urh->out_buffer_used) )
3607 urh->clean_ready =
true;
3642 const fd_set *read_fd_set,
3643 const fd_set *write_fd_set,
3644 const fd_set *except_fd_set)
3650 if ((
NULL == read_fd_set) || (
NULL == write_fd_set))
3652 if (
NULL == except_fd_set)
3656 _ (
"MHD_run_from_select() called with except_fd_set "
3657 "set to NULL. Such behavior is deprecated.\n"));
3660 except_fd_set = &es;
3703 struct timeval timeout;
3710 timeout.tv_usec = 0;
3736 _ (
"Could not obtain daemon fdsets.\n"));
3753 _ (
"Could not add listen socket to fdset.\n"));
3758 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
3764#if defined(MHD_WINSOCK_SOCKETS)
3782 "Could not add control inter-thread communication channel FD to fdset.\n"));
3785#if defined(MHD_WINSOCK_SOCKETS)
3799 (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
3811 timeout.tv_usec = 0;
3819 timeout.tv_usec = (ltimeout % 1000) * 1000;
3840 _ (
"select failed: %s\n"),
3867 unsigned int num_connections;
3870#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3871 struct MHD_UpgradeResponseHandle *urh;
3872 struct MHD_UpgradeResponseHandle *urhn;
3880 num_connections = 0;
3883#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3884 for (urh = daemon->urh_head;
NULL != urh; urh = urh->next)
3885 num_connections += 2;
3891 unsigned int poll_server;
3898 sizeof (
struct pollfd));
3903 _ (
"Error allocating memory: %s\n"),
3916 p[poll_server].fd = ls;
3917 p[poll_server].events = POLLIN;
3918 p[poll_server].revents = 0;
3919 poll_listen = (int) poll_server;
3923 if (MHD_ITC_IS_VALID_ (daemon->
itc))
3925 p[poll_server].fd = MHD_itc_r_fd_ (daemon->
itc);
3926 p[poll_server].events = POLLIN;
3927 p[poll_server].revents = 0;
3928 poll_itc_idx = (int) poll_server;
3938 timeout = (ltimeout > INT_MAX) ? INT_MAX : (
int) ltimeout;
3947 p[poll_server + i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
3950 p[poll_server + i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
3953 p[poll_server + i].events |= MHD_POLL_EVENTS_ERR_DISC;
3961#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3962 for (urh = daemon->urh_tail;
NULL != urh; urh = urh->prev)
3964 urh_to_pollfd (urh, &(p[poll_server + i]));
3968 if (0 == poll_server + num_connections)
3973 if (MHD_sys_poll_ (p,
3974 poll_server + num_connections,
3985 _ (
"poll failed: %s\n"),
3998 if ( (-1 != poll_itc_idx) &&
3999 (0 != (p[poll_itc_idx].revents & POLLIN)) )
4000 MHD_itc_clear_ (daemon->
itc);
4010 while (
NULL != (pos = prev))
4014 if (i >= num_connections)
4019 0 != (p[poll_server + i].revents & POLLIN),
4020 0 != (p[poll_server + i].revents & POLLOUT),
4021 0 != (p[poll_server + i].revents
4022 & MHD_POLL_REVENTS_ERR_DISC));
4025#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4026 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
4028 if (i >= num_connections)
4035 if ((p[poll_server + i].
fd != urh->connection->socket_fd) ||
4036 (p[poll_server + i + 1].fd != urh->mhd.socket))
4038 urh_from_pollfd (urh,
4039 &p[poll_server + i]);
4043 if ( (0 == urh->in_buffer_size) &&
4044 (0 == urh->out_buffer_size) &&
4045 (0 == urh->in_buffer_used) &&
4046 (0 == urh->out_buffer_used) )
4051 urh->clean_ready =
true;
4061 if ( (-1 != poll_listen) &&
4062 (0 != (p[poll_listen].revents & POLLIN)) )
4079MHD_poll_listen_socket (
struct MHD_Daemon *daemon,
4084 unsigned int poll_count;
4099 p[poll_count].fd = ls;
4100 p[poll_count].events = POLLIN;
4101 p[poll_count].revents = 0;
4102 poll_listen = poll_count;
4105 if (MHD_ITC_IS_VALID_ (daemon->
itc))
4107 p[poll_count].fd = MHD_itc_r_fd_ (daemon->
itc);
4108 p[poll_count].events = POLLIN;
4109 p[poll_count].revents = 0;
4110 poll_itc_idx = poll_count;
4121 if (0 == poll_count)
4123 if (MHD_sys_poll_ (p,
4133 _ (
"poll failed: %s\n"),
4138 if ( (-1 != poll_itc_idx) &&
4139 (0 != (p[poll_itc_idx].revents & POLLIN)) )
4140 MHD_itc_clear_ (daemon->
itc);
4145 if ( (-1 != poll_listen) &&
4146 (0 != (p[poll_listen].revents & POLLIN)) )
4170 return MHD_poll_all (daemon,
4172 return MHD_poll_listen_socket (daemon,
4192#define MAX_EVENTS 128
4195#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4205is_urh_ready (
struct MHD_UpgradeResponseHandle *
const urh)
4209 if ( (0 == urh->in_buffer_size) &&
4210 (0 == urh->out_buffer_size) &&
4211 (0 == urh->in_buffer_used) &&
4212 (0 == urh->out_buffer_used) )
4218 (urh->in_buffer_used < urh->in_buffer_size) )
4221 (urh->out_buffer_used < urh->out_buffer_size) )
4224 (urh->out_buffer_used > 0) )
4227 (urh->in_buffer_used > 0) )
4244 struct epoll_event events[MAX_EVENTS];
4246 struct MHD_UpgradeResponseHandle *pos;
4247 struct MHD_UpgradeResponseHandle *prev;
4249 num_events = MAX_EVENTS;
4250 while (0 != num_events)
4254 num_events = epoll_wait (daemon->epoll_upgrade_fd,
4258 if (-1 == num_events)
4266 _ (
"Call to epoll_wait failed: %s\n"),
4271 for (i = 0; i < (
unsigned int) num_events; i++)
4273 struct UpgradeEpollHandle *
const ueh = events[i].data.ptr;
4274 struct MHD_UpgradeResponseHandle *
const urh = ueh->urh;
4275 bool new_err_state =
false;
4277 if (urh->clean_ready)
4281 if (0 != (events[i].events & EPOLLIN))
4283 if (0 != (events[i].events & EPOLLOUT))
4285 if (0 != (events[i].events & EPOLLHUP))
4289 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
4295 new_err_state =
true;
4298 if (! urh->in_eready_list)
4300 if (new_err_state ||
4304 daemon->eready_urh_tail,
4306 urh->in_eready_list =
true;
4311 prev = daemon->eready_urh_tail;
4312 while (
NULL != (pos = prev))
4316 if (! is_urh_ready (pos))
4319 daemon->eready_urh_tail,
4321 pos->in_eready_list =
false;
4324 if ( (0 == pos->in_buffer_size) &&
4325 (0 == pos->out_buffer_size) &&
4326 (0 == pos->in_buffer_used) &&
4327 (0 == pos->out_buffer_used) )
4330 pos->clean_ready =
true;
4349static const char *
const epoll_itc_marker =
"itc_marker";
4364#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4365 static const char *
const upgrade_marker =
"upgrade_ptr";
4369 struct epoll_event events[MAX_EVENTS];
4370 struct epoll_event event;
4376#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4377 bool run_upgraded =
false;
4380 if (-1 == daemon->epoll_fd)
4387 (! daemon->listen_socket_in_epoll) &&
4390 event.events = EPOLLIN;
4391 event.data.ptr = daemon;
4392 if (0 != epoll_ctl (daemon->epoll_fd,
4399 _ (
"Call to epoll_ctl failed: %s\n"),
4404 daemon->listen_socket_in_epoll =
true;
4407 (daemon->listen_socket_in_epoll) )
4409 if ( (0 != epoll_ctl (daemon->epoll_fd,
4415 MHD_PANIC (
"Failed to remove listen FD from epoll set.\n");
4416 daemon->listen_socket_in_epoll =
false;
4419#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4420 if ( ( (! daemon->upgrade_fd_in_epoll) &&
4421 (-1 != daemon->epoll_upgrade_fd) ) )
4423 event.events = EPOLLIN | EPOLLOUT;
4424 event.data.ptr = (
void *) upgrade_marker;
4425 if (0 != epoll_ctl (daemon->epoll_fd,
4427 daemon->epoll_upgrade_fd,
4432 _ (
"Call to epoll_ctl failed: %s\n"),
4437 daemon->upgrade_fd_in_epoll =
true;
4440 if ( (daemon->listen_socket_in_epoll) &&
4447 if (0 != epoll_ctl (daemon->epoll_fd,
4451 MHD_PANIC (
_ (
"Failed to remove listen FD from epoll set.\n"));
4452 daemon->listen_socket_in_epoll =
false;
4465 timeout_ms = INT_MAX;
4467 timeout_ms = (int) timeout_ll;
4484 num_events = MAX_EVENTS;
4485 while (MAX_EVENTS == num_events)
4488 num_events = epoll_wait (daemon->epoll_fd,
4492 if (-1 == num_events)
4499 _ (
"Call to epoll_wait failed: %s\n"),
4504 for (i = 0; i<(
unsigned int) num_events; i++)
4510#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4511 if (upgrade_marker == events[i].
data.ptr)
4515 run_upgraded =
true;
4519 if (epoll_itc_marker == events[i].
data.ptr)
4523 MHD_itc_clear_ (daemon->
itc);
4526 if (daemon == events[i].
data.ptr)
4530 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
4532 unsigned int series_length = 0;
4538 (series_length < 10) &&
4548 pos = events[i].data.ptr;
4550 if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
4556 daemon->eready_tail,
4563 if (0 != (events[i].events & EPOLLIN))
4571 daemon->eready_tail,
4576 if (0 != (events[i].events & EPOLLOUT))
4583 daemon->eready_tail,
4592#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4593 if (run_upgraded || (
NULL != daemon->eready_urh_head))
4594 run_epoll_for_upgrade (daemon);
4598 prev = daemon->eready_tail;
4599 while (
NULL != (pos = prev))
4617 daemon->eready_tail,
4619 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
4632 while (
NULL != (pos = prev))
4642 while (
NULL != (pos = prev))
4690 MHD_epoll (daemon,
MHD_NO);
4723#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4742#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4748#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4756static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
4761 MHD_thread_init_ (&(daemon->
pid));
4782 return (MHD_THRD_RTRN_TYPE_) 0;
4880#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4893 "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC.\n");
4898#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4908 if (0 != epoll_ctl (daemon->
worker_pool[i].epoll_fd,
4912 MHD_PANIC (
_ (
"Failed to remove listen FD from epoll set.\n"));
4913 daemon->
worker_pool[i].listen_socket_in_epoll =
false;
4921 "Failed to signal quiesce via inter-thread communication channel.\n"));
4928 (-1 != daemon->epoll_fd) &&
4929 (daemon->listen_socket_in_epoll) )
4931 if ( (0 != epoll_ctl (daemon->epoll_fd,
4937 MHD_PANIC (
"Failed to remove listen FD from epoll set.\n");
4938 daemon->listen_socket_in_epoll =
false;
4941 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
4942 (! MHD_itc_activate_ (daemon->
itc,
"q")) )
4944 "failed to signal quiesce via inter-thread communication channel.\n"));
4972 const struct sockaddr **servaddr,
4986 const struct sockaddr **servaddr,
4992 va_start (ap, servaddr);
5011 const struct sockaddr **servaddr,
5021#if GNUTLS_VERSION_MAJOR >= 3
5022 gnutls_certificate_retrieve_function2 *pgcrf;
5024#if GNUTLS_VERSION_NUMBER >= 0x030603
5025 gnutls_certificate_retrieve_function3 *pgcrf2;
5058 _ (
"Warning: Too large timeout value, ignored.\n"));
5080 *servaddr = va_arg (ap,
5081 const struct sockaddr *);
5094#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5103 "Warning: Zero size, specified for thread pool size, is ignored. "
5104 "Thread pool is not used.\n"));
5112 "Warning: \"1\", specified for thread pool size, is ignored. "
5113 "Thread pool is not used.\n"));
5125 _ (
"Specified thread pool size (%u) too big.\n"),
5136 _ (
"MHD_OPTION_THREAD_POOL_SIZE option is specified but "
5137 "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
5145 _ (
"Both MHD_OPTION_THREAD_POOL_SIZE option and "
5146 "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
5158 daemon->https_mem_key = pstr;
5163 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5171 daemon->https_key_password = pstr;
5176 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5184 daemon->https_mem_cert = pstr;
5189 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5197 daemon->https_mem_trust = pstr;
5202 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5207 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
5215 gnutls_datum_t dhpar;
5218 if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
5222 _ (
"Error initializing DH parameters.\n"));
5226 dhpar.data = (
unsigned char *) pstr;
5227 pstr_len = strlen (pstr);
5232 _ (
"Diffie-Hellman parameters string too long.\n"));
5236 dhpar.size = (
unsigned int) pstr_len;
5237 if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
5239 GNUTLS_X509_FMT_PEM) < 0)
5243 _ (
"Bad Diffie-Hellman parameters format.\n"));
5245 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
5248 daemon->have_dhparams =
true;
5254 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5263 gnutls_priority_deinit (daemon->priority_cache);
5264 ret = gnutls_priority_init (&daemon->priority_cache,
5267 if (GNUTLS_E_SUCCESS != ret)
5271 _ (
"Setting priorities to `%s' failed: %s\n"),
5273 gnutls_strerror (ret));
5275 daemon->priority_cache =
NULL;
5283 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5288#if GNUTLS_VERSION_MAJOR < 3
5292 "MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0.\n"));
5297 gnutls_certificate_retrieve_function2 *);
5299 daemon->cert_callback = pgcrf;
5304 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5310#if GNUTLS_VERSION_NUMBER < 0x030603
5314 "MHD_OPTION_HTTPS_CERT_CALLBACK2 requires building MHD with GnuTLS >= 3.6.3.\n"));
5318 pgcrf2 = va_arg (ap,
5319 gnutls_certificate_retrieve_function3 *);
5321 daemon->cert_callback2 = pgcrf2;
5326 "MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set.\n"),
5334 daemon->digest_auth_rand_size = va_arg (ap,
5336 daemon->digest_auth_random = va_arg (ap,
5340 daemon->nonce_nc_size = va_arg (ap,
5349 _ (
"MHD_OPTION_LISTEN_SOCKET specified for daemon "
5350 "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
5360 daemon->custom_error_log = va_arg (ap,
5362 daemon->custom_error_log_cls = va_arg (ap,
5371#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5373 daemon->thread_stack_size = va_arg (ap,
5379 daemon->fastopen_queue_size = va_arg (ap,
5385 _ (
"TCP fastopen is not supported on this platform.\n"));
5391 unsigned int) ? 1 : -1;
5404 _ (
"Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
5405 "another behavior is specified by MHD_OPTION_STRICT_CLIENT.\n"));
5423 (
size_t) oa[i].
value,
5440 (
unsigned int) oa[i].
value,
5450 (gnutls_credentials_type_t) oa[i].
value,
5501 (
void *) oa[i].
value,
5511 (
size_t) oa[i].
value,
5530#if GNUTLS_VERSION_MAJOR >= 3
5531 daemon->cred_callback = va_arg (ap,
5533 daemon->cred_callback_cls = va_arg (ap,
5539 "MHD HTTPS option %d passed to MHD compiled without GNUtls >= 3.\n"),
5553 "MHD HTTPS option %d passed to MHD compiled without HTTPS support.\n"),
5560 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?).\n"),
5577#ifndef HAVE_MESSAGES
5581#ifdef USE_EPOLL_CREATE1
5582 fd = epoll_create1 (EPOLL_CLOEXEC);
5584 fd = epoll_create (MAX_EVENTS);
5590 _ (
"Call to epoll_create1 failed: %s\n"),
5595#if ! defined(USE_EPOLL_CREATE1)
5600 _ (
"Failed to set noninheritable mode on epoll FD.\n"));
5618setup_epoll_to_listen (
struct MHD_Daemon *daemon)
5620 struct epoll_event event;
5623 daemon->epoll_fd = setup_epoll_fd (daemon);
5624 if (-1 == daemon->epoll_fd)
5626#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5629 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
5637 event.events = EPOLLIN;
5638 event.data.ptr = daemon;
5639 if (0 != epoll_ctl (daemon->epoll_fd,
5646 _ (
"Call to epoll_ctl failed: %s\n"),
5651 daemon->listen_socket_in_epoll =
true;
5652 if (MHD_ITC_IS_VALID_ (daemon->
itc))
5654 event.events = EPOLLIN;
5655 event.data.ptr = (
void *) epoll_itc_marker;
5656 if (0 != epoll_ctl (daemon->epoll_fd,
5658 MHD_itc_r_fd_ (daemon->
itc),
5663 _ (
"Call to epoll_ctl failed: %s\n"),
5709 struct sockaddr_in servaddr4;
5711 struct sockaddr_in6 servaddr6;
5713 const struct sockaddr *servaddr =
NULL;
5715#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5732#ifndef EPOLL_SUPPORT
5736#ifndef HTTPS_SUPPORT
5746#ifdef UPGRADE_SUPPORT
5782#if defined(EPOLL_SUPPORT)
5784#elif defined(HAVE_POLL)
5793#if defined(EPOLL_SUPPORT)
5804 daemon->epoll_fd = -1;
5805#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5806 daemon->epoll_upgrade_fd = -1;
5811 daemon->priority_cache =
NULL;
5814 gnutls_priority_init (&daemon->priority_cache,
5825 daemon->
port = port;
5836 MHD_itc_set_invalid_ (daemon->
itc);
5844 daemon->custom_error_log_cls = stderr;
5852 "Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with "
5853 "MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD "
5854 "was added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"));
5859 *pflags &= ~MHD_USE_ITC;
5862#ifdef HAVE_LISTEN_SHUTDOWN
5868 daemon->digest_auth_rand_size = 0;
5869 daemon->digest_auth_random =
NULL;
5870 daemon->nonce_nc_size = 4;
5875 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
5886 (
NULL != daemon->priority_cache) )
5887 gnutls_priority_deinit (daemon->priority_cache);
5900 _ (
"Using debug build of libmicrohttpd.\n") );
5905#
if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5910 if (! MHD_itc_init_ (daemon->
itc))
5914 _ (
"Failed to create inter-thread communication channel: %s\n"),
5915 MHD_itc_last_strerror_ ());
5918 if (
NULL != daemon->priority_cache)
5919 gnutls_priority_deinit (daemon->priority_cache);
5931 "file descriptor for inter-thread communication channel exceeds maximum value.\n"));
5935 if (
NULL != daemon->priority_cache)
5936 gnutls_priority_deinit (daemon->priority_cache);
5944 if (daemon->nonce_nc_size > 0)
5946 if ( ( (
size_t) (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc)))
5947 /
sizeof(
struct MHD_NonceNc) != daemon->nonce_nc_size)
5951 _ (
"Specified value for NC_SIZE too large.\n"));
5955 gnutls_priority_deinit (daemon->priority_cache);
5960 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc));
5961 if (
NULL == daemon->nnc)
5965 _ (
"Failed to allocate memory for nonce-nc map: %s\n"),
5970 gnutls_priority_deinit (daemon->priority_cache);
5977#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5978 if (! MHD_mutex_init_ (&daemon->nnc_lock))
5982 _ (
"MHD failed to initialize nonce-nc mutex.\n"));
5986 gnutls_priority_deinit (daemon->priority_cache);
5996#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6003 "MHD thread polling only works with MHD_USE_INTERNAL_POLLING_THREAD.\n"));
6015 domain = (*pflags &
MHD_USE_IPv6) ? PF_INET6 : PF_INET;
6027 _ (
"Failed to create socket for listening: %s\n"),
6036#ifndef MHD_WINSOCK_SOCKETS
6041 if (0 > setsockopt (listen_fd,
6044 (
void*) &on,
sizeof (on)))
6048 _ (
"setsockopt failed: %s\n"),
6057#ifndef MHD_WINSOCK_SOCKETS
6060 if (0 > setsockopt (listen_fd,
6063 (
void*) &on,
sizeof (on)))
6067 _ (
"setsockopt failed: %s\n"),
6077#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
6078 if (0 > setsockopt (listen_fd,
6080#ifndef MHD_WINSOCK_SOCKETS
6090 _ (
"setsockopt failed: %s\n"),
6101 "Cannot allow listening address reuse: SO_REUSEPORT not defined.\n"));
6114#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
6115 (defined(__sun) && defined(SO_EXCLBIND))
6116 if (0 > setsockopt (listen_fd,
6118#ifdef SO_EXCLUSIVEADDRUSE
6119 SO_EXCLUSIVEADDRUSE,
6128 _ (
"setsockopt failed: %s\n"),
6133#elif defined(MHD_WINSOCK_SOCKETS)
6137 "Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined.\n"));
6146 addrlen =
sizeof (
struct sockaddr_in6);
6149 addrlen =
sizeof (
struct sockaddr_in);
6150 if (
NULL == servaddr)
6155#ifdef IN6ADDR_ANY_INIT
6156 static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
6160 sizeof (
struct sockaddr_in6));
6161 servaddr6.sin6_family = AF_INET6;
6162 servaddr6.sin6_port = htons (port);
6163#ifdef IN6ADDR_ANY_INIT
6164 servaddr6.sin6_addr = static_in6any;
6166#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
6167 servaddr6.sin6_len =
sizeof (
struct sockaddr_in6);
6169 servaddr = (
struct sockaddr *) &servaddr6;
6176 sizeof (
struct sockaddr_in));
6177 servaddr4.sin_family = AF_INET;
6178 servaddr4.sin_port = htons (port);
6179 if (0 != INADDR_ANY)
6180 servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
6181#if HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
6182 servaddr4.sin_len =
sizeof (
struct sockaddr_in);
6184 servaddr = (
struct sockaddr *) &servaddr4;
6199 if (0 > setsockopt (listen_fd,
6200 IPPROTO_IPV6, IPV6_V6ONLY,
6201 (
const void *) &v6_only,
6206 _ (
"setsockopt failed: %s\n"),
6213 if (-1 == bind (listen_fd, servaddr, addrlen))
6217 _ (
"Failed to bind to port %u: %s\n"),
6218 (
unsigned int) port,
6227 if (0 == daemon->fastopen_queue_size)
6228 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
6229 if (0 != setsockopt (listen_fd,
6232 (
const void*) &daemon->fastopen_queue_size,
6233 sizeof (daemon->fastopen_queue_size)))
6237 _ (
"setsockopt failed: %s\n"),
6243 if (listen (listen_fd,
6248 _ (
"Failed to listen for connections: %s\n"),
6260#ifdef HAVE_GETSOCKNAME
6261 if ( (0 == daemon->
port) &&
6264 struct sockaddr_storage bindaddr;
6268 sizeof (
struct sockaddr_storage));
6269 addrlen =
sizeof (
struct sockaddr_storage);
6270#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
6271 bindaddr.ss_len = addrlen;
6273 if (0 != getsockname (listen_fd,
6274 (
struct sockaddr *) &bindaddr,
6279 _ (
"Failed to get listen port number: %s\n"),
6283#ifdef MHD_POSIX_SOCKETS
6284 else if (
sizeof (bindaddr) < addrlen)
6290 "Failed to get listen port number (`struct sockaddr_storage` too small!?).\n"));
6294 else if (0 == addrlen)
6304 switch (bindaddr.ss_family)
6308 struct sockaddr_in *s4 = (
struct sockaddr_in *) &bindaddr;
6310 daemon->
port = ntohs (s4->sin_port);
6316 struct sockaddr_in6 *s6 = (
struct sockaddr_in6 *) &bindaddr;
6318 daemon->
port = ntohs (s6->sin6_port);
6331 _ (
"Unknown address family!\n"));
6344 _ (
"Failed to set nonblocking mode on listening socket: %s\n"),
6348#
if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6367 _ (
"Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
6377#
if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6387 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
6391 if (
MHD_YES != setup_epoll_to_listen (daemon))
6396#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6401 _ (
"MHD failed to initialize IP connection limit mutex.\n"));
6411 _ (
"MHD failed to initialize IP connection limit mutex.\n"));
6413#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6425 (0 != MHD_TLS_init (daemon)) )
6429 _ (
"Failed to initialize TLS support.\n"));
6433#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6440#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6449 "MHD-listen" :
"MHD-single",
6450 daemon->thread_stack_size,
6456 _ (
"Failed to create listen thread: %s\n"),
6490 memcpy (d, daemon,
sizeof (
struct MHD_Daemon));
6500 if (! MHD_itc_init_ (d->
itc))
6505 "Failed to create worker inter-thread communication channel: %s\n"),
6506 MHD_itc_last_strerror_ () );
6517 "File descriptor for worker inter-thread communication channel exceeds maximum value.\n"));
6524 MHD_itc_set_invalid_ (d->
itc);
6530 if (i < leftover_conns)
6534 (
MHD_YES != setup_epoll_to_listen (d)) )
6542 _ (
"MHD failed to initialize cleanup connection mutex.\n"));
6550 daemon->thread_stack_size,
6556 _ (
"Failed to create pool thread: %s\n"),
6571 daemon->https_key_password =
NULL;
6576#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6605#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6606 if (daemon->upgrade_fd_in_epoll)
6608 if (0 != epoll_ctl (daemon->epoll_fd,
6610 daemon->epoll_upgrade_fd,
6612 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
6613 daemon->upgrade_fd_in_epoll =
false;
6616 if (-1 != daemon->epoll_fd)
6617 close (daemon->epoll_fd);
6618#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6619 if (-1 != daemon->epoll_upgrade_fd)
6620 close (daemon->epoll_upgrade_fd);
6625#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6632 gnutls_priority_deinit (daemon->priority_cache);
6633 if (daemon->x509_cred)
6634 gnutls_certificate_free_credentials (daemon->x509_cred);
6635 if (daemon->psk_cred)
6636 gnutls_psk_free_server_credentials (daemon->psk_cred);
6639 if (MHD_ITC_IS_VALID_ (daemon->
itc))
6660#ifdef UPGRADE_SUPPORT
6663#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6664 struct MHD_UpgradeResponseHandle *urh;
6665 struct MHD_UpgradeResponseHandle *urhn;
6668#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6674 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
6681 urh->clean_ready =
true;
6698#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6701#ifdef UPGRADE_SUPPORT
6707 while (
NULL != susp)
6709 if (
NULL == susp->urh)
6711 "MHD_stop_daemon() called while we have suspended connections.\n"));
6713 else if (used_tls &&
6715 (! susp->urh->clean_ready) )
6716 shutdown (susp->urh->app.socket,
6722 if (! susp->urh->was_closed)
6725 "Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
6727 susp->urh->was_closed =
true;
6744 "MHD_stop_daemon() called while we have suspended connections.\n"));
6749#if MHD_WINSOCK_SOCKETS
6752 (! MHD_itc_activate_ (
daemon->
itc,
"e")) )
6754 "Failed to signal shutdown via inter-thread communication channel.\n"));
6758#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6768 if (! MHD_join_thread_ (pos->
pid.handle))
6769 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
6783#ifdef UPGRADE_SUPPORT
6798#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6801 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
6819#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6832#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6847 "Failed to signal shutdown via inter-thread communication channel.\n"));
6852#ifdef HAVE_LISTEN_SHUTDOWN
6855 (void) shutdown (
fd,
6867#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6875#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6885 "Failed to signal shutdown via inter-thread communication channel.\n"));
6889#ifdef HAVE_LISTEN_SHUTDOWN
6893 (void) shutdown (
fd,
6901 if (! MHD_join_thread_ (
daemon->
pid.handle))
6903 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
6918 (-1 !=
daemon->epoll_fd) )
6920#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6922 (-1 !=
daemon->epoll_upgrade_fd) )
6927#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6941 if (
daemon->have_dhparams)
6943 gnutls_dh_params_deinit (
daemon->https_mem_dhparams);
6944 daemon->have_dhparams =
false;
6948 gnutls_priority_deinit (
daemon->priority_cache);
6950 gnutls_certificate_free_credentials (
daemon->x509_cred);
6952 gnutls_psk_free_server_credentials (
daemon->psk_cred);
6958#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6962#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7007#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7065#ifdef PACKAGE_VERSION
7066 return PACKAGE_VERSION;
7068 static char ver[12] =
"\0\0\0\0\0\0\0\0\0\0\0";
7071 int res = MHD_snprintf_ (ver,
7077 if ((0 >= res) || (
sizeof(ver) <= res))
7114#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
7120#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030603
7132#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
7150#ifdef HAVE_LISTEN_SHUTDOWN
7156#ifdef _MHD_ITC_SOCKETPAIR
7180#ifdef HAVE_POSTPROCESSOR
7186#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
7192#if defined(HAVE_PREAD64) || defined(_WIN32)
7194#elif defined(HAVE_PREAD)
7195 return (
sizeof(uint64_t) >
sizeof(off_t)) ?
MHD_NO :
MHD_YES;
7196#elif defined(HAVE_LSEEK64)
7199 return (
sizeof(uint64_t) >
sizeof(off_t)) ?
MHD_NO :
MHD_YES;
7202#if defined(MHD_USE_THREAD_NAME_)
7208#if defined(UPGRADE_SUPPORT)
7214#if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
7220#ifdef MHD_USE_GETSOCKNAME
7226#if defined(MHD_WINSOCK_SOCKETS) || defined(MHD_socket_nosignal_) || \
7227 defined (MSG_NOSIGNAL)
7233#ifdef _MHD_HAVE_SENDFILE
7239#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7250#ifdef MHD_HTTPS_REQUIRE_GRYPT
7251#if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
7252#if defined(MHD_USE_POSIX_THREADS)
7253GCRY_THREAD_OPTION_PTHREAD_IMPL;
7254#elif defined(MHD_W32_MUTEX_)
7257gcry_w32_mutex_init (
void **ppmtx)
7259 *ppmtx = malloc (
sizeof (MHD_mutex_));
7263 if (! MHD_mutex_init_ ((MHD_mutex_*) *ppmtx))
7275gcry_w32_mutex_destroy (
void **ppmtx)
7277 int res = (MHD_mutex_destroy_ ((MHD_mutex_*) *ppmtx)) ? 0 : EINVAL;
7284gcry_w32_mutex_lock (
void **ppmtx)
7286 return MHD_mutex_lock_ ((MHD_mutex_*) *ppmtx) ? 0 : EINVAL;
7291gcry_w32_mutex_unlock (
void **ppmtx)
7293 return MHD_mutex_unlock_ ((MHD_mutex_*) *ppmtx) ? 0 : EINVAL;
7297static struct gcry_thread_cbs gcry_threads_w32 = {
7298 (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
7299 NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
7300 gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
7314#if defined(MHD_WINSOCK_SOCKETS)
7321#if defined(MHD_WINSOCK_SOCKETS)
7322 if (0 != WSAStartup (MAKEWORD (2, 2), &wsd))
7323 MHD_PANIC (
_ (
"Failed to initialize winsock.\n"));
7324 mhd_winsock_inited_ = 1;
7325 if ((2 != LOBYTE (wsd.wVersion)) && (2 != HIBYTE (wsd.wVersion)))
7326 MHD_PANIC (
_ (
"Winsock version 2.2 is not available.\n"));
7329#ifdef MHD_HTTPS_REQUIRE_GRYPT
7330#if GCRYPT_VERSION_NUMBER < 0x010600
7331#if defined(MHD_USE_POSIX_THREADS)
7332 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
7333 &gcry_threads_pthread))
7334 MHD_PANIC (
_ (
"Failed to initialise multithreading in libgcrypt.\n"));
7335#elif defined(MHD_W32_MUTEX_)
7336 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
7338 MHD_PANIC (
_ (
"Failed to initialise multithreading in libgcrypt.\n"));
7340 gcry_check_version (
NULL);
7342 if (
NULL == gcry_check_version (
"1.6.0"))
7344 "libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer.\n"));
7347 gnutls_global_init ();
7350#ifdef HAVE_FREEBSD_SENDFILE
7351 MHD_conn_init_static_ ();
7361 gnutls_global_deinit ();
7363#if defined(MHD_WINSOCK_SOCKETS)
7364 if (mhd_winsock_inited_)
7371#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)
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)
static enum MHD_Result MHD_select(struct MHD_Daemon *daemon, int may_block)
MHD_PanicCallback mhd_panic
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)
static void MHD_default_logger_(void *cls, const char *fm, va_list ap)
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 int MHD_ip_addr_compare(const void *a1, const void *a2)
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 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 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_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_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 MAYBE_SOCK_NONBLOCK
#define MHD_socket_close_chk_(fd)
#define MHD_SCKT_ERR_IS_EINTR_(err)
#define MHD_SCKT_SEND_MAX_SIZE_
#define MAYBE_SOCK_CLOEXEC
#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_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 *))
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
internal monotonic clock functions implementations
int MHD_socket_buffering_reset_(MHD_socket sock)
int MHD_socket_set_nodelay_(MHD_socket sock, bool on)
#define MAYBE_SOCK_NOSIGPIPE
@ 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_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.
struct MHD_Connection * prevX
enum MHD_ConnectionEventLoopInfo event_loop_info
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
enum MHD_CONNECTION_STATE state
struct MHD_Daemon * daemon
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
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
MHD_thread_handle_ID_ pid
struct MHD_Connection * manual_timeout_head
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