30#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
40#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
50#ifdef MHD_USE_SYS_TSEARCH
58#ifdef MHD_HTTPS_REQUIRE_GCRYPT
63#if defined(_WIN32) && ! defined(__CYGWIN__)
64#ifndef WIN32_LEAN_AND_MEAN
65#define WIN32_LEAN_AND_MEAN 1
70#ifdef MHD_USE_POSIX_THREADS
79#ifdef MHD_POSIX_SOCKETS
80#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 3 - 1 - MHD_ITC_NUM_FDS_)
82#define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2)
88#define MHD_POOL_SIZE_DEFAULT (32 * 1024)
134#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
139#define MHD_check_global_init_() (void) 0
146#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
147#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
151MHD_MUTEX_STATIC_DEFN_INIT_ (global_init_mutex_);
163#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
164#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
170#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
171#ifdef MHD_MUTEX_STATIC_DEFN_INIT_
185MHD_default_logger_ (
void *cls,
189 vfprintf ((FILE *) cls, fm, ap);
191 fflush ((FILE *) cls);
242 struct in6_addr ipv6;
262#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
279#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
302 offsetof (
struct MHD_IPCount,
318 struct MHD_IPCount *key)
325 if (
sizeof (
struct sockaddr_in) <= (
size_t) addrlen)
327 if (AF_INET == addr->ss_family)
329 key->family = AF_INET;
330 memcpy (&key->addr.ipv4,
331 &((
const struct sockaddr_in *) addr)->sin_addr,
332 sizeof(((
const struct sockaddr_in *)
NULL)->sin_addr));
338 if (
sizeof (
struct sockaddr_in6) <= (
size_t) addrlen)
341 if (AF_INET6 == addr->ss_family)
343 key->family = AF_INET6;
344 memcpy (&key->addr.ipv6,
345 &((
const struct sockaddr_in6 *) addr)->sin6_addr,
346 sizeof(((
const struct sockaddr_in6 *)
NULL)->sin6_addr));
370 const struct sockaddr_storage *addr,
373 struct MHD_IPCount *newkeyp;
374 struct MHD_IPCount *keyp;
375 struct MHD_IPCount **nodep;
383 newkeyp = (
struct MHD_IPCount *) malloc (
sizeof(
struct MHD_IPCount));
399 nodep = (
struct MHD_IPCount **)
tsearch (newkeyp,
408 _ (
"Failed to add IP connection count node.\n"));
438 const struct sockaddr_storage *addr,
441 struct MHD_IPCount search_key;
442 struct MHD_IPCount *found_key;
464 MHD_PANIC (
_ (
"Failed to find previously-added IP address.\n"));
466 found_key = (
struct MHD_IPCount *) *nodep;
468 if (0 == found_key->count)
470 MHD_PANIC (
_ (
"Previously-added IP address had counter of zero.\n"));
473 if (0 == --found_key->count)
494MHD_init_daemon_certificate (
struct MHD_Daemon *daemon)
500#if GNUTLS_VERSION_MAJOR >= 3
501 if (
NULL != daemon->cert_callback)
503 gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
504 daemon->cert_callback);
507#if GNUTLS_VERSION_NUMBER >= 0x030603
508 else if (
NULL != daemon->cert_callback2)
510 gnutls_certificate_set_retrieve_function3 (daemon->x509_cred,
511 daemon->cert_callback2);
515 if (
NULL != daemon->https_mem_trust)
518 paramlen = strlen (daemon->https_mem_trust);
523 _ (
"Too long trust certificate.\n"));
527 cert.data = (
unsigned char *)
_MHD_DROP_CONST (daemon->https_mem_trust);
528 cert.size = (
unsigned int) paramlen;
529 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred,
531 GNUTLS_X509_FMT_PEM) < 0)
535 _ (
"Bad trust certificate format.\n"));
541 if (daemon->have_dhparams)
543 gnutls_certificate_set_dh_params (daemon->x509_cred,
544 daemon->https_mem_dhparams);
547 if ( (
NULL != daemon->https_mem_cert) &&
548 (
NULL != daemon->https_mem_key) )
553 param1len = strlen (daemon->https_mem_key);
554 param2len = strlen (daemon->https_mem_cert);
560 _ (
"Too long key or certificate.\n"));
565 key.size = (
unsigned int) param1len;
566 cert.data = (
unsigned char *)
_MHD_DROP_CONST (daemon->https_mem_cert);
567 cert.size = (
unsigned int) param2len;
569 if (
NULL != daemon->https_key_password)
571#if GNUTLS_VERSION_NUMBER >= 0x030111
572 ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
576 daemon->https_key_password,
581 _ (
"Failed to setup x509 certificate/key: pre 3.X.X version " \
582 "of GnuTLS does not support setting key password.\n"));
588 ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
591 GNUTLS_X509_FMT_PEM);
595 _ (
"GnuTLS failed to setup x509 certificate/key: %s\n"),
596 gnutls_strerror (ret));
600#if GNUTLS_VERSION_MAJOR >= 3
601 if (
NULL != daemon->cert_callback)
604#if GNUTLS_VERSION_NUMBER >= 0x030603
605 else if (
NULL != daemon->cert_callback2)
610 _ (
"You need to specify a certificate and key location.\n"));
625 switch (daemon->cred_type)
627 case GNUTLS_CRD_CERTIFICATE:
629 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
630 return GNUTLS_E_MEMORY_ERROR;
631 return MHD_init_daemon_certificate (daemon);
634 gnutls_psk_allocate_server_credentials (&daemon->psk_cred))
635 return GNUTLS_E_MEMORY_ERROR;
637 case GNUTLS_CRD_ANON:
643 _ (
"Error: invalid credentials type %d specified.\n"),
665tls_cleanup_failed_start (
struct MHD_Daemon *daemon)
667 if (daemon->have_dhparams)
669 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
670 daemon->have_dhparams =
false;
672 if (
NULL != daemon->priority_cache)
674 gnutls_priority_deinit (daemon->priority_cache);
675 daemon->priority_cache =
NULL;
677 if (
NULL != daemon->x509_cred)
679 gnutls_certificate_free_credentials (daemon->x509_cred);
680 daemon->x509_cred =
NULL;
682 if (
NULL != daemon->psk_cred)
684 gnutls_psk_free_server_credentials (daemon->psk_cred);
685 daemon->psk_cred =
NULL;
729 fd_set *write_fd_set,
730 fd_set *except_fd_set,
738#ifdef HAS_FD_SETSIZE_OVERRIDABLE
739 daemon->fdset_size_set_by_app ?
740 ((
unsigned int) daemon->fdset_size) :
749#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
763urh_to_fdset (
struct MHD_UpgradeResponseHandle *urh,
770 const MHD_socket conn_sckt = urh->connection->socket_fd;
774#ifndef HAS_FD_SETSIZE_OVERRIDABLE
776 fd_setsize = (int) FD_SETSIZE;
783 if ( (urh->in_buffer_used < urh->in_buffer_size) &&
789 if ( (0 != urh->out_buffer_used) &&
798 ((0 != urh->in_buffer_size) ||
799 (0 != urh->out_buffer_size) ||
800 (0 != urh->out_buffer_used))
809 if ( (urh->out_buffer_used < urh->out_buffer_size) &&
815 if ( (0 != urh->in_buffer_used) &&
824 ((0 != urh->out_buffer_size) ||
825 (0 != urh->in_buffer_size) ||
826 (0 != urh->in_buffer_used))
849urh_from_fdset (
struct MHD_UpgradeResponseHandle *urh,
855 const MHD_socket conn_sckt = urh->connection->socket_fd;
866#ifndef HAS_FD_SETSIZE_OVERRIDABLE
868 mhd_assert (((
int) FD_SETSIZE) <= fd_setsize);
869 fd_setsize = FD_SETSIZE;
922urh_update_pollfd (
struct MHD_UpgradeResponseHandle *urh,
928 if (urh->in_buffer_used < urh->in_buffer_size)
929 p[0].events |= POLLIN;
930 if (0 != urh->out_buffer_used)
931 p[0].events |= POLLOUT;
936 ((0 != urh->in_buffer_size) ||
937 (0 != urh->out_buffer_size) ||
938 (0 != urh->out_buffer_used)))
939 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
941 if (urh->out_buffer_used < urh->out_buffer_size)
942 p[1].events |= POLLIN;
943 if (0 != urh->in_buffer_used)
944 p[1].events |= POLLOUT;
949 ((0 != urh->out_buffer_size) ||
950 (0 != urh->in_buffer_size) ||
951 (0 != urh->in_buffer_used)))
952 p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
963urh_to_pollfd (
struct MHD_UpgradeResponseHandle *urh,
966 p[0].fd = urh->connection->socket_fd;
967 p[1].fd = urh->mhd.socket;
968 urh_update_pollfd (urh,
979urh_from_pollfd (
struct MHD_UpgradeResponseHandle *urh,
988 if (0 != (p[0].revents & POLLIN))
990 if (0 != (p[0].revents & POLLOUT))
992 if (0 != (p[0].revents & POLLHUP))
994 if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
996 if (0 != (p[1].revents & POLLIN))
998 if (0 != (p[1].revents & POLLOUT))
1000 if (0 != (p[1].revents & POLLHUP))
1002 if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
1027 fd_set *read_fd_set,
1028 fd_set *write_fd_set,
1029 fd_set *except_fd_set,
1039#ifndef HAS_FD_SETSIZE_OVERRIDABLE
1041 fd_setsize = (int) FD_SETSIZE;
1096#ifdef MHD_POSIX_SOCKETS
1097 if (
NULL != except_fd_set)
1110#ifdef MHD_POSIX_SOCKETS
1111 if (
NULL != except_fd_set)
1119 if ( (
NULL == except_fd_set) ||
1131#ifdef MHD_WINSOCK_SOCKETS
1135 if (
NULL != except_fd_set)
1147#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1150 struct MHD_UpgradeResponseHandle *urh;
1152 for (urh = daemon->urh_tail;
NULL != urh; urh = urh->prev)
1180#if _MHD_DEBUG_CONNECT
1184 _ (
"Maximum socket in select set: %d\n"),
1228 fd_set *read_fd_set,
1229 fd_set *write_fd_set,
1230 fd_set *except_fd_set,
1232 unsigned int fd_setsize)
1234 if ( (
NULL == daemon) ||
1235 (
NULL == read_fd_set) ||
1236 (
NULL == write_fd_set) ||
1242 if (
NULL == except_fd_set)
1245 _ (
"MHD_get_fdset2() called with except_fd_set "
1246 "set to NULL. Such behavior is unsupported.\n"));
1250#ifdef HAS_FD_SETSIZE_OVERRIDABLE
1251 if (0 == fd_setsize)
1253 else if (((
unsigned int)
INT_MAX) < fd_setsize)
1254 fd_setsize = (
unsigned int)
INT_MAX;
1256 else if (daemon->fdset_size > ((
int) fd_setsize))
1258 if (daemon->fdset_size_set_by_app)
1261 _ (
"%s() called with fd_setsize (%u) " \
1262 "less than value set by MHD_OPTION_APP_FD_SETSIZE (%d). " \
1263 "Some socket FDs may be not processed. " \
1264 "Use MHD_OPTION_APP_FD_SETSIZE with the correct value.\n"),
1265 "MHD_get_fdset2", fd_setsize, daemon->fdset_size);
1270 _ (
"%s() called with fd_setsize (%u) " \
1271 "less than FD_SETSIZE used by MHD (%d). " \
1272 "Some socket FDs may be not processed. " \
1273 "Consider using MHD_OPTION_APP_FD_SETSIZE option.\n"),
1274 "MHD_get_fdset2", fd_setsize, daemon->fdset_size);
1279 if (((
unsigned int) FD_SETSIZE) > fd_setsize)
1283 _ (
"%s() called with fd_setsize (%u) " \
1284 "less than fixed FD_SETSIZE value (%d) used on the " \
1286 "MHD_get_fdset2", fd_setsize, (
int) FD_SETSIZE);
1290 fd_setsize = (int) FD_SETSIZE;
1338 bool states_info_processed =
false;
1351 if (con->tls_read_ready)
1367 states_info_processed =
true;
1370 (read_ready || (force_close && con->
sk_nonblck)) )
1396 states_info_processed =
true;
1407 states_info_processed =
true;
1417 if (! states_info_processed)
1465 else if ( (con->tls_read_ready) &&
1474#ifdef UPGRADE_SUPPORT
1485 struct MHD_UpgradeResponseHandle *urh = connection->urh;
1493 gnutls_bye (connection->tls_session,
1502 connection->urh =
NULL;
1510#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1520process_urh (
struct MHD_UpgradeResponseHandle *urh)
1533#ifdef MHD_USE_THREADS
1544 if (! urh->was_closed)
1547 _ (
"Initiated daemon shutdown while \"upgraded\" " \
1548 "connection was not closed.\n"));
1551 urh->was_closed =
true;
1553 was_closed = urh->was_closed;
1558 if (0 < urh->in_buffer_used)
1562 _ (
"Failed to forward to application %" PRIu64 \
1563 " bytes of data received from remote side: " \
1564 "application closed data forwarding.\n"),
1565 (uint64_t) urh->in_buffer_used);
1570 urh->in_buffer_used = 0;
1574 urh->in_buffer_size = 0;
1576 connection->tls_read_ready =
false;
1591 & urh->app.celi)) ||
1592 (connection->tls_read_ready)) &&
1593 (urh->in_buffer_used < urh->in_buffer_size))
1598 buf_size = urh->in_buffer_size - urh->in_buffer_used;
1602 res = gnutls_record_recv (connection->tls_session,
1603 &urh->in_buffer[urh->in_buffer_used],
1607 connection->tls_read_ready =
false;
1608 if (GNUTLS_E_INTERRUPTED != res)
1611 if ((GNUTLS_E_AGAIN != res) ||
1618 urh->in_buffer_size = 0;
1624 urh->in_buffer_used += (size_t) res;
1625 connection->tls_read_ready =
1626 (0 < gnutls_record_check_pending (connection->tls_session));
1641 && (urh->out_buffer_used < urh->out_buffer_size))
1646 buf_size = urh->out_buffer_size - urh->out_buffer_used;
1651 &urh->out_buffer[urh->out_buffer_used],
1671 urh->out_buffer_size = 0;
1677 urh->out_buffer_used += (size_t) res;
1678 if (buf_size > (
size_t) res)
1687 (urh->out_buffer_used > 0) )
1692 data_size = urh->out_buffer_used;
1696 res = gnutls_record_send (connection->tls_session,
1701 if (GNUTLS_E_INTERRUPTED != res)
1704 if (GNUTLS_E_AGAIN != res)
1710 _ (
"Failed to forward to remote client %" PRIu64 \
1711 " bytes of data received from application: %s\n"),
1712 (uint64_t) urh->out_buffer_used,
1713 gnutls_strerror ((
int) res));
1716 urh->out_buffer_used = 0;
1718 urh->out_buffer_size = 0;
1725 const size_t next_out_buffer_used = urh->out_buffer_used - (size_t) res;
1726 if (0 != next_out_buffer_used)
1728 memmove (urh->out_buffer,
1729 &urh->out_buffer[res],
1730 next_out_buffer_used);
1732 urh->out_buffer_used = next_out_buffer_used;
1734 if ( (0 == urh->out_buffer_used) &&
1742 urh->out_buffer_size = 0;
1751 (urh->in_buffer_used > 0) )
1756 data_size = urh->in_buffer_used;
1776 _ (
"Failed to forward to application %" PRIu64 \
1777 " bytes of data received from remote side: %s\n"),
1778 (uint64_t) urh->in_buffer_used,
1782 urh->in_buffer_used = 0;
1784 urh->in_buffer_size = 0;
1786 connection->tls_read_ready =
false;
1792 const size_t next_in_buffer_used = urh->in_buffer_used - (size_t) res;
1793 if (0 != next_in_buffer_used)
1795 memmove (urh->in_buffer,
1796 &urh->in_buffer[res],
1797 next_in_buffer_used);
1798 if (data_size > (
size_t) res)
1801 urh->in_buffer_used = next_in_buffer_used;
1803 if ( (0 == urh->in_buffer_used) &&
1809 urh->in_buffer_size = 0;
1811 connection->tls_read_ready =
false;
1817 if ( (connection->tls_read_ready) &&
1818 (urh->in_buffer_used < urh->in_buffer_size) &&
1823 ( (0 != urh->out_buffer_size) ||
1824 (0 != urh->out_buffer_used) ) )
1828 if (0 < urh->out_buffer_used)
1830 _ (
"Failed to forward to remote client %" PRIu64 \
1831 " bytes of data received from application: daemon shut down.\n"),
1832 (uint64_t) urh->out_buffer_used);
1835 urh->out_buffer_used = 0;
1839 urh->out_buffer_size = 0;
1843 if (! was_closed && urh->was_closed)
1850#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1851#ifdef UPGRADE_SUPPORT
1864 struct MHD_UpgradeResponseHandle *urh = con->urh;
1875 while ( (0 != urh->in_buffer_size) ||
1876 (0 != urh->out_buffer_size) ||
1877 (0 != urh->in_buffer_used) ||
1878 (0 != urh->out_buffer_used) )
1892 result = urh_to_fdset (urh,
1902 _ (
"Error preparing select.\n"));
1909 struct timeval *tvp;
1911 if (((con->tls_read_ready) &&
1912 (urh->in_buffer_used < urh->in_buffer_size)) ||
1937 _ (
"Error during select (%d): `%s'\n"),
1943 urh_from_fdset (urh,
1959 p[0].fd = urh->connection->socket_fd;
1960 p[1].fd = urh->mhd.socket;
1962 while ( (0 != urh->in_buffer_size) ||
1963 (0 != urh->out_buffer_size) ||
1964 (0 != urh->in_buffer_used) ||
1965 (0 != urh->out_buffer_used) )
1969 urh_update_pollfd (urh, p);
1971 if (((con->tls_read_ready) &&
1972 (urh->in_buffer_used < urh->in_buffer_size)) ||
1978 if (MHD_sys_poll_ (p,
1988 _ (
"Error during poll: `%s'\n"),
1993 urh_from_pollfd (urh,
2025 uint64_t mseconds_left;
2030 if (timeout < since_actv)
2037 if (5000 >= jump_back)
2045 else if (since_actv == timeout)
2054 mseconds_left = timeout - since_actv;
2056 return mseconds_left;
2081#ifdef UPGRADE_SUPPORT
2084#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2097#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2114static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
2115thread_main_handle_connection (
void *
data)
2126 unsigned int extra_slot;
2128#define EXTRA_SLOTS 1
2130#define EXTRA_SLOTS 0
2133 struct pollfd p[1 + EXTRA_SLOTS];
2139 const bool use_poll = 0;
2141 bool was_suspended =
false;
2147 bool use_zero_timeout;
2148#ifdef UPGRADE_SUPPORT
2149 struct MHD_UpgradeResponseHandle *
const urh = con->urh;
2151 static const void *
const urh =
NULL;
2158 was_suspended =
true;
2165 resume_connection_own_thread_ (con);
2177 #ifdef HAVE_MESSAGES
2179 _ (
"Failed to add FD to fd_set.\n"));
2195 _ (
"Error during select (%d): `%s'\n"),
2205 p[0].events = POLLIN;
2208 if (0 > MHD_sys_poll_ (p,
2216 _ (
"Error during poll: `%s'\n"),
2232 was_suspended =
false;
2238 || ( (con->tls_read_ready) &&
2245 bool err_state =
false;
2247 struct timeval *tvp;
2248 if (use_zero_timeout)
2256 const uint64_t mseconds_left = connection_get_wait (con);
2257#if (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC
2264 tv.tv_usec = ((uint16_t) (mseconds_left % 1000)) * ((int32_t) 1000);
2303 if (MHD_ITC_IS_VALID_ (daemon->
itc) )
2316 _ (
"Failed to add FD to fd_set.\n"));
2334 _ (
"Error during select (%d): `%s'\n"),
2343 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2344 (FD_ISSET (MHD_itc_r_fd_ (daemon->
itc),
2346 MHD_itc_clear_ (daemon->
itc);
2363 if (use_zero_timeout)
2367 const uint64_t mseconds_left = connection_get_wait (con);
2368#if SIZEOF_UINT64_T >= SIZEOF_INT
2373 timeout_val = (int) mseconds_left;
2385 p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
2388 p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
2391 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
2399 if (MHD_ITC_IS_VALID_ (daemon->
itc))
2401 p[1].events |= POLLIN;
2402 p[1].fd = MHD_itc_r_fd_ (daemon->
itc);
2407 if (MHD_sys_poll_ (p,
2419 _ (
"Error during poll: `%s'\n"),
2427 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2428 (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2429 MHD_itc_clear_ (daemon->
itc);
2433 (0 != (p[0].revents & POLLIN)),
2434 (0 != (p[0].revents & POLLOUT)),
2435 (0 != (p[0].revents & MHD_POLL_REVENTS_ERR_DISC)) ))
2439#ifdef UPGRADE_SUPPORT
2440 if (MHD_CONNECTION_UPGRADE == con->
state)
2452 thread_main_connection_upgrade (con);
2456 con->urh->clean_ready =
true;
2464 return (MHD_THRD_RTRN_TYPE_) 0;
2471 _ (
"Processing thread terminating. Closing connection.\n"));
2495 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
2496 (! MHD_itc_activate_ (daemon->
itc,
"t")) )
2500 _ (
"Failed to signal thread termination via inter-thread " \
2501 "communication channel.\n"));
2504 return (MHD_THRD_RTRN_TYPE_) 0;
2521#if defined(HTTPS_SUPPORT)
2522#if defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED) && \
2523 defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) && \
2524 ! defined(MHD_socket_nosignal_) && \
2525 (GNUTLS_VERSION_NUMBER + 0 < 0x030402) && defined(MSG_NOSIGNAL)
2531#define MHD_TLSLIB_NEED_PUSH_FUNC 1
2537#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2543MHD_tls_push_func_ (gnutls_transport_ptr_t trnsp,
2547#if (MHD_SCKT_SEND_MAX_SIZE_ < SSIZE_MAX) || (0 == SSIZE_MAX)
2566#define MHD_PSK_MIN_SIZE 16
2577psk_gnutls_adapter (gnutls_session_t session,
2578 const char *username,
2579 gnutls_datum_t *key)
2583#if GNUTLS_VERSION_MAJOR >= 3
2585 size_t app_psk_size;
2588 connection = gnutls_session_get_ptr (session);
2589 if (
NULL == connection)
2593 MHD_PANIC (
_ (
"Internal server error. This should be impossible.\n"));
2597 daemon = connection->
daemon;
2598#if GNUTLS_VERSION_MAJOR >= 3
2599 if (
NULL == daemon->cred_callback)
2603 _ (
"PSK not supported by this server.\n"));
2607 if (0 != daemon->cred_callback (daemon->cred_callback_cls,
2613 if (MHD_PSK_MIN_SIZE > app_psk_size)
2617 _ (
"PSK authentication failed: PSK too short.\n"));
2626 _ (
"PSK authentication failed: PSK too long.\n"));
2634 if (
NULL == (key->data = gnutls_malloc (app_psk_size)))
2638 _ (
"PSK authentication failed: gnutls_malloc failed to " \
2639 "allocate memory.\n"));
2644 key->size = (
unsigned int) app_psk_size;
2651 (void) username; (void) key;
2654 _ (
"PSK not supported by this server.\n"));
2689 const struct sockaddr_storage *
addr,
2693 bool sk_spipe_supprs,
2700#if _MHD_DEBUG_CONNECT
2702 _ (
"Accepted connection on socket %d.\n"),
2714 _ (
"Server reached connection limit. " \
2715 "Closing inbound connection.\n"));
2718#if defined(ENFILE) && (ENFILE + 0 != 0)
2727 (
const struct sockaddr *)
addr,
2733 _ (
"Connection rejected by application. Closing connection.\n"));
2740#if defined(EACCESS) && (EACCESS + 0 != 0)
2751 _ (
"Error allocating memory: %s\n"),
2775 if (
NULL == (connection->
addr = malloc ((
size_t) addrlen)))
2780 _ (
"Error allocating memory: %s\n"),
2791 memcpy (connection->
addr,
2800 connection->
is_nonip = sk_is_nonip;
2802#ifdef MHD_USE_THREADS
2811 MHD_itc_set_invalid_ (connection->
resume_itc);
2819 _ (
"Failed to create inter-thread communication channel " \
2820 "for the connection: %s\n"),
2821 MHD_itc_last_strerror_ ());
2828 free (connection->
addr);
2842#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030500)
2849 flags = GNUTLS_SERVER;
2850#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030402)
2851 flags |= GNUTLS_NO_SIGNAL;
2853#if GNUTLS_VERSION_MAJOR >= 3
2854 flags |= GNUTLS_NONBLOCK;
2856#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030603)
2858 flags |= GNUTLS_POST_HANDSHAKE_AUTH;
2860#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030605)
2862 flags |= GNUTLS_ENABLE_EARLY_DATA;
2866 if ((GNUTLS_E_SUCCESS != gnutls_init (&connection->tls_session, flags)) ||
2867 (GNUTLS_E_SUCCESS != gnutls_priority_set (connection->tls_session,
2868 daemon->priority_cache)))
2870 if (
NULL != connection->tls_session)
2871 gnutls_deinit (connection->tls_session);
2877 free (connection->
addr);
2881 _ (
"Failed to initialise TLS session.\n"));
2883#if defined(EPROTO) && (EPROTO + 0 != 0)
2888#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030200)
2889 if (!
daemon->disable_alpn)
2891 static const char prt1[] =
"http/1.1";
2892 static const char prt2[] =
"http/1.0";
2893 static const gnutls_datum_t prts[2] =
2897 if (GNUTLS_E_SUCCESS !=
2898 gnutls_alpn_set_protocols (connection->tls_session,
2900 sizeof(prts) /
sizeof(prts[0]),
2905 _ (
"Failed to set ALPN protocols.\n"));
2912 gnutls_session_set_ptr (connection->tls_session,
2914 switch (
daemon->cred_type)
2917 case GNUTLS_CRD_CERTIFICATE:
2918 gnutls_credentials_set (connection->tls_session,
2919 GNUTLS_CRD_CERTIFICATE,
2922 case GNUTLS_CRD_PSK:
2923 gnutls_credentials_set (connection->tls_session,
2926 gnutls_psk_set_server_credentials_function (
daemon->psk_cred,
2927 &psk_gnutls_adapter);
2929 case GNUTLS_CRD_ANON:
2930 case GNUTLS_CRD_SRP:
2935 _ (
"Failed to setup TLS credentials: " \
2936 "unknown credential type %d.\n"),
2939 gnutls_deinit (connection->tls_session);
2945 free (connection->
addr);
2947 MHD_PANIC (
_ (
"Unknown credential type.\n"));
2948#if defined(EINVAL) && (EINVAL + 0 != 0)
2953#if (GNUTLS_VERSION_NUMBER + 0 >= 0x030109) && ! defined(_WIN64)
2954 gnutls_transport_set_int (connection->tls_session,
2955 (
int) (client_socket));
2957 gnutls_transport_set_ptr (connection->tls_session,
2958 (gnutls_transport_ptr_t) \
2959 (intptr_t) client_socket);
2961#ifdef MHD_TLSLIB_NEED_PUSH_FUNC
2962 gnutls_transport_set_push_function (connection->tls_session,
2963 MHD_tls_push_func_);
2965 if (
daemon->https_mem_trust)
2966 gnutls_certificate_server_set_request (connection->tls_session,
2967 GNUTLS_CERT_REQUEST);
2973 free (connection->
addr);
2975 MHD_PANIC (
_ (
"TLS connection on non-TLS daemon.\n"));
2988#ifdef MHD_USE_THREADS
3007 if (
NULL != connection->tls_session)
3010 gnutls_deinit (connection->tls_session);
3014 if (MHD_ITC_IS_VALID_ (connection->
resume_itc))
3020 free (connection->
addr);
3046#ifdef MHD_USE_THREADS
3063 _ (
"Error allocating memory: %s\n"),
3066#if defined(ENOMEM) && (ENOMEM + 0 != 0)
3080 _ (
"Server reached connection limit. "
3081 "Closing inbound connection.\n"));
3083#if defined(ENFILE) && (ENFILE + 0 != 0)
3109#ifdef MHD_USE_THREADS
3115 daemon->thread_stack_size,
3116 &thread_main_handle_connection,
3124 _ (
"Failed to create a new thread because it would "
3125 "have exceeded the system limit on the number of "
3126 "threads or no system resources available.\n"));
3130 _ (
"Failed to create a thread: %s\n"),
3142#ifdef MHD_USE_THREADS
3143 connection->tid =
daemon->tid;
3150 struct epoll_event event;
3152 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET | EPOLLRDHUP;
3153 event.data.ptr = connection;
3154 if (0 != epoll_ctl (daemon->epoll_fd,
3162 _ (
"Call to epoll_ctl failed: %s\n"),
3179 daemon->eready_tail,
3213 if (
NULL != connection->tls_session)
3214 gnutls_deinit (connection->tls_session);
3220 free (connection->
addr);
3264 const struct sockaddr_storage *addr,
3268 bool sk_spipe_supprs,
3273#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3283 _ (
"New connection socket descriptor (%d) is not less " \
3284 "than FD_SETSIZE (%d).\n"),
3285 (
int) client_socket,
3289#if defined(ENFILE) && (ENFILE + 0 != 0)
3300 _ (
"Epoll mode supports only non-blocking sockets\n"));
3303#if defined(EINVAL) && (EINVAL + 0 != 0)
3316 if (
NULL == connection)
3319 if ((external_add) &&
3332 if ((MHD_ITC_IS_VALID_ (
daemon->
itc)) &&
3333 (! MHD_itc_activate_ (
daemon->
itc,
"n")))
3337 _ (
"Failed to signal new connection via inter-thread " \
3338 "communication channel.\n"));
3382 _ (
"Failed to start serving new connection.\n"));
3386 }
while (
NULL != local_tail);
3406#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3416#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3446 daemon->eready_tail,
3448 connection->epoll_state &=
3453 if (0 != epoll_ctl (daemon->epoll_fd,
3457 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
3458 connection->epoll_state &=
3464#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3503#ifdef MHD_USE_THREADS
3510 MHD_PANIC (
_ (
"Cannot suspend connections without " \
3511 "enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
3512#ifdef UPGRADE_SUPPORT
3513 if (
NULL != connection->urh)
3517 _ (
"Error: connection scheduled for \"upgrade\" cannot " \
3518 "be suspended.\n"));
3546#if defined(MHD_USE_THREADS)
3551 MHD_PANIC (
_ (
"Cannot resume connections without enabling " \
3552 "MHD_ALLOW_SUSPEND_RESUME!\n"));
3553#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3561#ifdef UPGRADE_SUPPORT
3562 && (
NULL == connection->urh)
3567#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3575 if (! MHD_itc_activate_ (connection->
resume_itc,
"r"))
3579 _ (
"Failed to signal resume via the connection's " \
3580 "inter-thread communication channel.\n"));
3584 else if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
3585 (! MHD_itc_activate_ (daemon->
itc,
"r")) )
3589 _ (
"Failed to signal resume via inter-thread " \
3590 "communication channel.\n"));
3596#ifdef UPGRADE_SUPPORT
3605MHD_upgraded_connection_mark_app_closed_ (
struct MHD_Connection *connection)
3609#if defined(MHD_USE_THREADS)
3616 connection->urh->was_closed =
true;
3620 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
3621 (! MHD_itc_activate_ (daemon->
itc,
"r")) )
3625 _ (
"Failed to signal resume via " \
3626 "inter-thread communication channel.\n"));
3651#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3658#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3674#ifdef UPGRADE_SUPPORT
3675 struct MHD_UpgradeResponseHandle *
const urh = pos->urh;
3677 static const void *
const urh =
NULL;
3681#ifdef UPGRADE_SUPPORT
3682 || ( (
NULL != urh) &&
3683 ( (! urh->was_closed) ||
3684 (! urh->clean_ready) ) )
3728 MHD_PANIC (
"Resumed connection was already in EREADY set.\n");
3732 daemon->eready_tail,
3741#ifdef UPGRADE_SUPPORT
3765#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3768 if ( (used_thr_p_c) &&
3771 if (! MHD_itc_activate_ (daemon->
itc,
3776 _ (
"Failed to signal resume of connection via " \
3777 "inter-thread communication channel.\n"));
3815 const struct sockaddr *addr,
3819 bool sk_spipe_supprs;
3820 struct sockaddr_storage addrstorage;
3832 _ (
"MHD_add_connection() has been called for daemon started"
3833 " without MHD_USE_ITC flag.\nDaemon will not process newly"
3834 " added connection until any activity occurs in already"
3835 " added sockets.\n"));
3840 if (AF_INET == addr->sa_family)
3842 if (
sizeof(
struct sockaddr_in) > (
size_t) addrlen)
3846 _ (
"MHD_add_connection() has been called with "
3847 "incorrect 'addrlen' value.\n"));
3851#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
3852 if ((0 != addr->sa_len) &&
3853 (
sizeof(
struct sockaddr_in) > (
size_t) addr->sa_len) )
3857 _ (
"MHD_add_connection() has been called with " \
3858 "non-zero value of 'sa_len' member of " \
3859 "'struct sockaddr' which does not match 'sa_family'.\n"));
3866 if (AF_INET6 == addr->sa_family)
3868 if (
sizeof(
struct sockaddr_in6) > (
size_t) addrlen)
3872 _ (
"MHD_add_connection() has been called with "
3873 "incorrect 'addrlen' value.\n"));
3877#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
3878 if ((0 != addr->sa_len) &&
3879 (
sizeof(
struct sockaddr_in6) > (
size_t) addr->sa_len) )
3883 _ (
"MHD_add_connection() has been called with " \
3884 "non-zero value of 'sa_len' member of " \
3885 "'struct sockaddr' which does not match 'sa_family'.\n"));
3891#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
3892 if ((0 != addr->sa_len) &&
3893 (addrlen > addr->sa_len))
3894 addrlen = (socklen_t) addr->sa_len;
3903 _ (
"Failed to set nonblocking mode on new client socket: %s\n"),
3911#ifndef MHD_WINSOCK_SOCKETS
3912 sk_spipe_supprs =
false;
3914 sk_spipe_supprs =
true;
3916#if defined(MHD_socket_nosignal_)
3917 if (! sk_spipe_supprs)
3918 sk_spipe_supprs = MHD_socket_nosignal_ (client_socket);
3919 if (! sk_spipe_supprs)
3923 _ (
"Failed to suppress SIGPIPE on new client socket: %s\n"),
3947 _ (
"Failed to set noninheritable mode on new client socket.\n"));
3953 memcpy (&addrstorage, addr, (
size_t) addrlen);
3954#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
3955 addrstorage.ss_len = addrlen;
3958#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3959 if (
NULL != daemon->worker_pool)
3965 for (i = 0; i < daemon->worker_pool_size; ++i)
3968 &daemon->worker_pool[(i + (
unsigned int) client_socket)
3969 % daemon->worker_pool_size];
3982#if defined(ENFILE) && (ENFILE + 0 != 0)
4017 struct sockaddr_storage addrstorage;
4022 bool sk_spipe_supprs;
4025#if defined(_DEBUG) && defined (USE_ACCEPT4)
4026 const bool use_accept4 = ! daemon->avoid_accept4;
4027#elif defined (USE_ACCEPT4)
4028 static const bool use_accept4 =
true;
4030 static const bool use_accept4 =
false;
4033#ifdef MHD_USE_THREADS
4043 addrlen = (socklen_t)
sizeof (addrstorage);
4044 memset (&addrstorage,
4047#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
4048 addrstorage.ss_len = addrlen;
4053 sk_spipe_supprs =
false;
4061 (
struct sockaddr *) &addrstorage,
4067#ifndef MHD_WINSOCK_SOCKETS
4070 sk_spipe_supprs =
true;
4075#if defined(_DEBUG) || ! defined(USE_ACCEPT4)
4076 if (! use_accept4 &&
4079 (
struct sockaddr *) &addrstorage,
4082#ifdef MHD_ACCEPT_INHERIT_NONBLOCK
4087#ifndef MHD_WINSOCK_SOCKETS
4088 sk_spipe_supprs =
false;
4090 sk_spipe_supprs =
true;
4109 _ (
"Error accepting connection: %s\n"),
4122 _ (
"Hit process or system resource limit at FIRST " \
4123 "connection. This is really bad as there is no sane " \
4124 "way to proceed. Will try busy waiting for system " \
4125 "resources to become magically available.\n"));
4130#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4134#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4139 _ (
"Hit process or system resource limit at %u " \
4140 "connections, temporarily suspending accept(). " \
4141 "Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
4155 _ (
"Accepted socket has zero-length address. "
4156 "Processing the new socket as a socket with " \
4157 "unknown type.\n"));
4162 if (((socklen_t)
sizeof (addrstorage)) < addrlen)
4168 _ (
"Accepted socket address is larger than expected by " \
4169 "system headers. Processing the new socket as a socket with " \
4170 "unknown type.\n"));
4180 _ (
"Failed to set nonblocking mode on incoming connection " \
4194 _ (
"Failed to set noninheritable mode on incoming connection " \
4201#if defined(MHD_socket_nosignal_)
4202 if (! sk_spipe_supprs && ! MHD_socket_nosignal_ (s))
4206 _ (
"Failed to suppress SIGPIPE on incoming connection " \
4223 sk_spipe_supprs =
true;
4226#if _MHD_DEBUG_CONNECT
4228 _ (
"Accepted connection on socket %d\n"),
4257#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4269#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4272 (! pos->thread_joined) &&
4274 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
4276#ifdef UPGRADE_SUPPORT
4277 cleanup_upgraded_connection (pos);
4281 if (
NULL != pos->tls_session)
4282 gnutls_deinit (pos->tls_session);
4305 if ( (-1 !=
daemon->epoll_fd) &&
4314 if (0 != epoll_ctl (
daemon->epoll_fd,
4318 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
4338#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4344#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4392#if SIZEOF_UINT64_T > SIZEOF_UNSIGNED_LONG_LONG
4440 uint64_t *timeout64)
4442 uint64_t earliest_deadline;
4447#ifdef MHD_USE_THREADS
4456 _ (
"Illegal call to MHD_get_timeout.\n"));
4464#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4468#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4484#
if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
4495 earliest_tmot_conn =
NULL;
4496 earliest_deadline = 0;
4499 if ( (
NULL != pos) &&
4502 earliest_tmot_conn = pos;
4512 if ( (
NULL == earliest_tmot_conn) ||
4513 (earliest_deadline >
4516 earliest_tmot_conn = pos;
4522 if (
NULL != earliest_tmot_conn)
4524 *timeout64 = connection_get_wait (earliest_tmot_conn);
4531#if defined(HAVE_POLL) || defined(EPOLL_SUPPORT)
4579 return (int64_t) utimeout;
4625#if SIZEOF_INT >= SIZEOF_INT64_T
4648 int32_t max_timeout)
4651 mhd_assert (0 <= max_timeout || -1 == max_timeout);
4652 if (0 == max_timeout)
4658 if ((0 < max_timeout) && ((uint64_t) max_timeout < d_timeout))
4664 return (int64_t) d_timeout;
4681 int32_t max_timeout)
4685 res = get_timeout_millisec_ (
daemon, max_timeout);
4686#if SIZEOF_INT < SIZEOF_INT64_T
4709 const fd_set *read_fd_set,
4710 const fd_set *write_fd_set,
4711 const fd_set *except_fd_set,
4715#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4716 struct MHD_UpgradeResponseHandle *urh;
4717 struct MHD_UpgradeResponseHandle *urhn;
4729#ifndef HAS_FD_SETSIZE_OVERRIDABLE
4731 mhd_assert (((
int) FD_SETSIZE) <= fd_setsize);
4732 fd_setsize = FD_SETSIZE;
4738 if (MHD_ITC_IS_VALID_ (daemon->
itc))
4740 bool need_to_clear_itc =
true;
4743 need_to_clear_itc = FD_ISSET (MHD_itc_r_fd_ (daemon->
itc), \
4745 if (need_to_clear_itc)
4746 MHD_itc_clear_ (daemon->
itc);
4762 bool need_to_accept;
4764 need_to_accept = FD_ISSET (ds,
4793 r_ready = FD_ISSET (cs,
4795 w_ready = FD_ISSET (cs,
4797 has_err = (
NULL != except_fd_set) &&
4814#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
4816 for (urh =
daemon->urh_tail;
NULL != urh; urh = urhn)
4820 urh_from_fdset (urh,
4828 if ( (0 == urh->in_buffer_size) &&
4829 (0 == urh->out_buffer_size) &&
4830 (0 == urh->in_buffer_used) &&
4831 (0 == urh->out_buffer_used) )
4834 urh->clean_ready =
true;
4845#undef MHD_run_from_select
4880 const fd_set *read_fd_set,
4881 const fd_set *write_fd_set,
4882 const fd_set *except_fd_set,
4883 unsigned int fd_setsize)
4888 if ((
NULL == read_fd_set) || (
NULL == write_fd_set))
4891 if (
NULL == except_fd_set)
4894 _ (
"MHD_run_from_select() called with except_fd_set "
4895 "set to NULL. Such behavior is deprecated.\n"));
4899#ifdef HAS_FD_SETSIZE_OVERRIDABLE
4900 if (0 == fd_setsize)
4902 else if (((
unsigned int)
INT_MAX) < fd_setsize)
4903 fd_setsize = (
unsigned int)
INT_MAX;
4905 else if (
daemon->fdset_size > ((
int) fd_setsize))
4907 if (
daemon->fdset_size_set_by_app)
4910 _ (
"%s() called with fd_setsize (%u) " \
4911 "less than value set by MHD_OPTION_APP_FD_SETSIZE (%d). " \
4912 "Some socket FDs may be not processed. " \
4913 "Use MHD_OPTION_APP_FD_SETSIZE with the correct value.\n"),
4914 "MHD_run_from_select2", fd_setsize,
daemon->fdset_size);
4919 _ (
"%s() called with fd_setsize (%u) " \
4920 "less than FD_SETSIZE used by MHD (%d). " \
4921 "Some socket FDs may be not processed. " \
4922 "Consider using MHD_OPTION_APP_FD_SETSIZE option.\n"),
4923 "MHD_run_from_select2", fd_setsize,
daemon->fdset_size);
4928 if (((
unsigned int) FD_SETSIZE) > fd_setsize)
4932 _ (
"%s() called with fd_setsize (%u) " \
4933 "less than fixed FD_SETSIZE value (%d) used on the " \
4935 "MHD_run_from_select2", fd_setsize, (
int) FD_SETSIZE);
4994 const fd_set *read_fd_set,
4995 const fd_set *write_fd_set,
4996 const fd_set *except_fd_set)
5002#ifdef HAS_FD_SETSIZE_OVERRIDABLE
5003 daemon->fdset_size_set_by_app ?
5004 ((
unsigned int)
daemon->fdset_size) :
5032 struct timeval timeout;
5038 timeout.tv_usec = 0;
5064 _ (
"Could not obtain daemon fdsets.\n"));
5074 if (MHD_ITC_IS_VALID_ (daemon->
itc))
5083 MHD_DLOG (daemon,
_ (
"Could not add control inter-thread " \
5084 "communication channel FD to fdset.\n"));
5109 _ (
"Could not add listen socket to fdset.\n"));
5121 timeout.tv_usec = 0;
5128 uint64_t select_tmo;
5133 if ( (0 < millisec) &&
5134 (mhd_tmo > (uint64_t) millisec) )
5135 select_tmo = (uint64_t) millisec;
5137 select_tmo = mhd_tmo;
5140 else if (0 < millisec)
5142 select_tmo = (uint64_t) millisec;
5153#if (SIZEOF_UINT64_T - 2) >= SIZEOF_STRUCT_TIMEVAL_TV_SEC
5160 timeout.tv_usec = ((uint16_t) (select_tmo % 1000)) * ((int32_t) 1000);
5177 _ (
"select failed: %s\n"),
5207 unsigned int num_connections;
5210#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5211 struct MHD_UpgradeResponseHandle *urh;
5212 struct MHD_UpgradeResponseHandle *urhn;
5227 num_connections = 0;
5230#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5231 for (urh = daemon->urh_head;
NULL != urh; urh = urh->next)
5232 num_connections += 2;
5237 unsigned int poll_server;
5244 sizeof (
struct pollfd));
5249 _ (
"Error allocating memory: %s\n"),
5262 p[poll_server].fd = ls;
5263 p[poll_server].events = POLLIN;
5264 p[poll_server].revents = 0;
5265 poll_listen = (int) poll_server;
5269 if (MHD_ITC_IS_VALID_ (daemon->
itc))
5271 p[poll_server].fd = MHD_itc_r_fd_ (daemon->
itc);
5272 p[poll_server].events = POLLIN;
5273 p[poll_server].revents = 0;
5274 poll_itc_idx = (int) poll_server;
5278 timeout = get_timeout_millisec_int (daemon, millisec);
5288 p[poll_server + i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
5291 p[poll_server + i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
5294 p[poll_server + i].events |= MHD_POLL_EVENTS_ERR_DISC;
5302#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5303 for (urh = daemon->urh_tail;
NULL != urh; urh = urh->prev)
5305 urh_to_pollfd (urh, &(p[poll_server + i]));
5309 if (0 == poll_server + num_connections)
5314 if (MHD_sys_poll_ (p,
5315 poll_server + num_connections,
5326 _ (
"poll failed: %s\n"),
5336 if ( (-1 != poll_itc_idx) &&
5337 (0 != (p[poll_itc_idx].revents & POLLIN)) )
5338 MHD_itc_clear_ (daemon->
itc);
5352 if ( (-1 != poll_listen) &&
5353 (0 != (p[poll_listen].revents & POLLIN)) )
5361 while (
NULL != (pos = prev))
5365 if (i >= num_connections)
5370 0 != (p[poll_server + i].revents & POLLIN),
5371 0 != (p[poll_server + i].revents & POLLOUT),
5372 0 != (p[poll_server + i].revents
5373 & MHD_POLL_REVENTS_ERR_DISC));
5376#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5377 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
5379 if (i >= num_connections)
5386 if ((p[poll_server + i].
fd != urh->connection->socket_fd) ||
5387 (p[poll_server + i + 1].fd != urh->mhd.socket))
5389 urh_from_pollfd (urh,
5390 &p[poll_server + i]);
5394 if ( (0 == urh->in_buffer_size) &&
5395 (0 == urh->out_buffer_size) &&
5396 (0 == urh->in_buffer_used) &&
5397 (0 == urh->out_buffer_used) )
5402 urh->clean_ready =
true;
5426MHD_poll_listen_socket (
struct MHD_Daemon *daemon,
5431 unsigned int poll_count;
5449 p[poll_count].fd = ls;
5450 p[poll_count].events = POLLIN;
5451 p[poll_count].revents = 0;
5452 poll_listen = (int) poll_count;
5455 if (MHD_ITC_IS_VALID_ (daemon->
itc))
5457 p[poll_count].fd = MHD_itc_r_fd_ (daemon->
itc);
5458 p[poll_count].events = POLLIN;
5459 p[poll_count].revents = 0;
5460 poll_itc_idx = (int) poll_count;
5471 if (0 == poll_count)
5473 if (MHD_sys_poll_ (p,
5483 _ (
"poll failed: %s\n"),
5488 if ( (0 <= poll_itc_idx) &&
5489 (0 != (p[poll_itc_idx].revents & POLLIN)) )
5490 MHD_itc_clear_ (daemon->
itc);
5500 if ( (0 <= poll_listen) &&
5501 (0 != (p[poll_listen].revents & POLLIN)) )
5523 return MHD_poll_all (daemon,
5524 may_block ? -1 : 0);
5525 return MHD_poll_listen_socket (daemon,
5543#define MAX_EVENTS 128
5546#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5556is_urh_ready (
struct MHD_UpgradeResponseHandle *
const urh)
5560 if ( (0 == urh->in_buffer_size) &&
5561 (0 == urh->out_buffer_size) &&
5562 (0 == urh->in_buffer_used) &&
5563 (0 == urh->out_buffer_used) )
5568 & urh->app.celi)) ||
5569 (connection->tls_read_ready) ) &&
5570 (urh->in_buffer_used < urh->in_buffer_size) )
5573 & urh->mhd.celi)) ||
5575 (urh->out_buffer_used < urh->out_buffer_size) )
5578 (urh->out_buffer_used > 0) )
5581 (urh->in_buffer_used > 0) )
5598 struct epoll_event events[MAX_EVENTS];
5600 struct MHD_UpgradeResponseHandle *pos;
5601 struct MHD_UpgradeResponseHandle *prev;
5603#ifdef MHD_USE_THREADS
5608 num_events = MAX_EVENTS;
5609 while (0 != num_events)
5613 num_events = epoll_wait (daemon->epoll_upgrade_fd,
5617 if (-1 == num_events)
5625 _ (
"Call to epoll_wait failed: %s\n"),
5630 for (i = 0; i < (
unsigned int) num_events; i++)
5632 struct UpgradeEpollHandle *
const ueh = events[i].data.ptr;
5633 struct MHD_UpgradeResponseHandle *
const urh = ueh->urh;
5634 bool new_err_state =
false;
5636 if (urh->clean_ready)
5640 if (0 != (events[i].events & EPOLLIN))
5644 if (0 != (events[i].events & EPOLLOUT))
5648 if (0 != (events[i].events & EPOLLHUP))
5654 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
5659 new_err_state =
true;
5661 if (! urh->in_eready_list)
5663 if (new_err_state ||
5667 daemon->eready_urh_tail,
5669 urh->in_eready_list =
true;
5674 prev = daemon->eready_urh_tail;
5675 while (
NULL != (pos = prev))
5679 if (! is_urh_ready (pos))
5682 daemon->eready_urh_tail,
5684 pos->in_eready_list =
false;
5687 if ( (0 == pos->in_buffer_size) &&
5688 (0 == pos->out_buffer_size) &&
5689 (0 == pos->in_buffer_used) &&
5690 (0 == pos->out_buffer_used) )
5693 pos->clean_ready =
true;
5712static const char *
const epoll_itc_marker =
"itc_marker";
5728#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5729 static const char *
const upgrade_marker =
"upgrade_ptr";
5733 struct epoll_event events[MAX_EVENTS];
5734 struct epoll_event event;
5739#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5740 bool run_upgraded =
false;
5742 bool need_to_accept;
5751 if (-1 == daemon->epoll_fd)
5759#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5765 (! daemon->listen_socket_in_epoll) &&
5768 event.events = EPOLLIN | EPOLLRDHUP;
5769 event.data.ptr = daemon;
5770 if (0 != epoll_ctl (daemon->epoll_fd,
5775#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5780 _ (
"Call to epoll_ctl failed: %s\n"),
5785 daemon->listen_socket_in_epoll =
true;
5788 (daemon->listen_socket_in_epoll) )
5790 if (0 != epoll_ctl (daemon->epoll_fd,
5794 MHD_PANIC (
"Failed to remove listen FD from epoll set.\n");
5795 daemon->listen_socket_in_epoll =
false;
5797#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5801#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5802 if ( ( (! daemon->upgrade_fd_in_epoll) &&
5803 (-1 != daemon->epoll_upgrade_fd) ) )
5805 event.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP;
5807 if (0 != epoll_ctl (daemon->epoll_fd,
5809 daemon->epoll_upgrade_fd,
5814 _ (
"Call to epoll_ctl failed: %s\n"),
5819 daemon->upgrade_fd_in_epoll =
true;
5822#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5825 if ( (daemon->listen_socket_in_epoll) &&
5832 if (0 != epoll_ctl (daemon->epoll_fd,
5836 MHD_PANIC (
_ (
"Failed to remove listen FD from epoll set.\n"));
5837 daemon->listen_socket_in_epoll =
false;
5839#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
5847 timeout_ms = get_timeout_millisec_int (daemon,
5855 need_to_accept =
false;
5860 num_events = MAX_EVENTS;
5861 while (MAX_EVENTS == num_events)
5864 num_events = epoll_wait (daemon->epoll_fd,
5868 if (-1 == num_events)
5875 _ (
"Call to epoll_wait failed: %s\n"),
5880 for (i = 0; i < (
unsigned int) num_events; i++)
5886#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
5887 if (upgrade_marker == events[i].
data.ptr)
5891 run_upgraded =
true;
5895 if (epoll_itc_marker == events[i].
data.ptr)
5899 MHD_itc_clear_ (daemon->
itc);
5902 if (daemon == events[i].
data.ptr)
5906 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
5907 need_to_accept =
true;
5913 pos = events[i].data.ptr;
5915 if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
5921 daemon->eready_tail,
5928 if (0 != (events[i].events & EPOLLIN))
5936 daemon->eready_tail,
5941 if (0 != (events[i].events & EPOLLOUT))
5948 daemon->eready_tail,
5963 unsigned int series_length = 0;
5970 (series_length < 10) &&
5985 while (
NULL != (pos = prev))
5995 while (
NULL != (pos = prev))
6003#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
6004 if (run_upgraded || (
NULL != daemon->eready_urh_head))
6005 run_epoll_for_upgrade (daemon);
6009 prev = daemon->eready_tail;
6010 while (
NULL != (pos = prev))
6028 daemon->eready_tail,
6136 res = MHD_poll_all (daemon, millisec);
6144 res = MHD_epoll (daemon, millisec);
6152#ifdef HAS_FD_SETSIZE_OVERRIDABLE
6154 if (daemon->fdset_size_set_by_app
6155 && (((
int) FD_SETSIZE) < daemon->fdset_size))
6158 _ (
"MHD_run()/MHD_run_wait() called for daemon started with " \
6159 "MHD_OPTION_APP_FD_SETSIZE option (%d). " \
6160 "The library was compiled with smaller FD_SETSIZE (%d). " \
6161 "Some socket FDs may be not processed. " \
6162 "Use MHD_run_from_select2() instead of MHD_run() or " \
6163 "do not use MHD_OPTION_APP_FD_SETSIZE option.\n"),
6164 daemon->fdset_size, (
int) FD_SETSIZE);
6189#ifdef MHD_USE_THREADS
6202#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6222#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6228#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6236static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
6237MHD_polling_thread (
void *cls)
6240#ifdef HAVE_PTHREAD_SIGMASK
6246#ifdef HAVE_PTHREAD_SIGMASK
6247 if ((0 == sigemptyset (&s_mask)) &&
6248 (0 == sigaddset (&s_mask, SIGPIPE)))
6250 err = pthread_sigmask (SIG_BLOCK, &s_mask,
NULL);
6259 _ (
"Failed to block SIGPIPE on daemon thread: %s\n"),
6272 MHD_epoll (daemon, -1);
6286 return (MHD_THRD_RTRN_TYPE_) 0;
6321 MHD_DLOG (connection->
daemon,
6322 _ (
"The URL encoding is broken.\n"));
6397#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6411 _ (
"Using MHD_quiesce_daemon in this mode " \
6412 "requires MHD_USE_ITC.\n"));
6417#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6418 if (
NULL != daemon->worker_pool)
6419 for (i = 0; i < daemon->worker_pool_size; i++)
6426#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6432 (-1 != daemon->worker_pool[i].epoll_fd) &&
6433 (daemon->worker_pool[i].listen_socket_in_epoll) )
6435 if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
6439 MHD_PANIC (
_ (
"Failed to remove listen FD from epoll set.\n"));
6440 daemon->worker_pool[i].listen_socket_in_epoll =
false;
6444 if (MHD_ITC_IS_VALID_ (daemon->worker_pool[i].
itc))
6446 if (! MHD_itc_activate_ (daemon->worker_pool[i].
itc,
"q"))
6447 MHD_PANIC (
_ (
"Failed to signal quiesce via inter-thread " \
6448 "communication channel.\n"));
6450#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6455#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6461 (-1 != daemon->epoll_fd) &&
6462 (daemon->listen_socket_in_epoll) )
6464 if (0 != epoll_ctl (daemon->epoll_fd,
6468 MHD_PANIC (
"Failed to remove listen FD from epoll set.\n");
6469 daemon->listen_socket_in_epoll =
false;
6472#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
6475 if ( (MHD_ITC_IS_VALID_ (daemon->
itc)) &&
6476 (! MHD_itc_activate_ (daemon->
itc,
"q")) )
6477 MHD_PANIC (
_ (
"failed to signal quiesce via inter-thread " \
6478 "communication channel.\n"));
6488struct MHD_InterimParams_
6501 bool fdset_size_set;
6517 bool pserver_addr_set;
6521 const struct sockaddr *pserver_addr;
6525 bool server_addr_len_set;
6529 socklen_t server_addr_len;
6556 struct MHD_InterimParams_ *params,
6571 struct MHD_InterimParams_ *params,
6577 va_start (ap, params);
6590enum MHD_TlsPrioritiesBaseType
6592 MHD_TLS_PRIO_BASE_LIBMHD = 0,
6593 MHD_TLS_PRIO_BASE_SYSTEM = 1,
6594#if GNUTLS_VERSION_NUMBER >= 0x030300
6595 MHD_TLS_PRIO_BASE_DEFAULT,
6597 MHD_TLS_PRIO_BASE_NORMAL
6603#if GNUTLS_VERSION_NUMBER >= 0x030300
6615daemon_tls_priorities_init_default (
struct MHD_Daemon *daemon)
6622 mhd_assert (MHD_TLS_PRIO_BASE_NORMAL + 1 == \
6623 sizeof(MHD_TlsBasePriotities) /
sizeof(MHD_TlsBasePriotities[0]));
6625 res = GNUTLS_E_SUCCESS;
6628 p <
sizeof(MHD_TlsBasePriotities) /
sizeof(MHD_TlsBasePriotities[0]);
6631 res = gnutls_priority_init (&daemon->priority_cache,
6632 MHD_TlsBasePriotities[p].str,
NULL);
6633 if (GNUTLS_E_SUCCESS == res)
6637 switch ((
enum MHD_TlsPrioritiesBaseType) p)
6639 case MHD_TLS_PRIO_BASE_LIBMHD:
6641 _ (
"GnuTLS priorities have been initialised with " \
6642 "@LIBMICROHTTPD application-specific system-wide " \
6643 "configuration.\n") );
6645 case MHD_TLS_PRIO_BASE_SYSTEM:
6647 _ (
"GnuTLS priorities have been initialised with " \
6648 "@SYSTEM system-wide configuration.\n") );
6650#if GNUTLS_VERSION_NUMBER >= 0x030300
6651 case MHD_TLS_PRIO_BASE_DEFAULT:
6653 _ (
"GnuTLS priorities have been initialised with " \
6654 "GnuTLS default configuration.\n") );
6657 case MHD_TLS_PRIO_BASE_NORMAL:
6659 _ (
"GnuTLS priorities have been initialised with " \
6660 "NORMAL configuration.\n") );
6672 _ (
"Failed to set GnuTLS priorities. Last error: %s\n"),
6673 gnutls_strerror (res));
6689daemon_tls_priorities_init_append_inner_ (
struct MHD_Daemon *daemon,
6693 const size_t buf_size)
6697 const char *err_pos;
6702 mhd_assert (MHD_TLS_PRIO_BASE_NORMAL + 1 == \
6703 sizeof(MHD_TlsBasePriotities) /
sizeof(MHD_TlsBasePriotities[0]));
6705 res = GNUTLS_E_SUCCESS;
6708 p <
sizeof(MHD_TlsBasePriotities) /
sizeof(MHD_TlsBasePriotities[0]);
6712#if GNUTLS_VERSION_NUMBER >= 0x030300
6713#if GNUTLS_VERSION_NUMBER >= 0x030603
6714 if (
NULL == MHD_TlsBasePriotities[p].
str)
6715 res = gnutls_priority_init2 (&daemon->priority_cache, prio, &err_pos,
6716 GNUTLS_PRIORITY_INIT_DEF_APPEND);
6720 if (
NULL == MHD_TlsBasePriotities[p].
str)
6731 memcpy (buf + buf_pos, MHD_TlsBasePriotities[p].
str,
6732 MHD_TlsBasePriotities[p].
len);
6733 buf_pos += MHD_TlsBasePriotities[p].
len;
6734 buf[buf_pos++] =
':';
6735 memcpy (buf + buf_pos, prio, prio_len + 1);
6737 buf_pos += prio_len + 1;
6740 res = gnutls_priority_init (&daemon->priority_cache, buf, &err_pos);
6742 if (GNUTLS_E_SUCCESS == res)
6746 switch ((
enum MHD_TlsPrioritiesBaseType) p)
6748 case MHD_TLS_PRIO_BASE_LIBMHD:
6750 _ (
"GnuTLS priorities have been initialised with " \
6751 "priorities specified by application appended to " \
6752 "@LIBMICROHTTPD application-specific system-wide " \
6753 "configuration.\n") );
6755 case MHD_TLS_PRIO_BASE_SYSTEM:
6757 _ (
"GnuTLS priorities have been initialised with " \
6758 "priorities specified by application appended to " \
6759 "@SYSTEM system-wide configuration.\n") );
6761#if GNUTLS_VERSION_NUMBER >= 0x030300
6762 case MHD_TLS_PRIO_BASE_DEFAULT:
6764 _ (
"GnuTLS priorities have been initialised with " \
6765 "priorities specified by application appended to " \
6766 "GnuTLS default configuration.\n") );
6769 case MHD_TLS_PRIO_BASE_NORMAL:
6771 _ (
"GnuTLS priorities have been initialised with " \
6772 "priorities specified by application appended to " \
6773 "NORMAL configuration.\n") );
6785 _ (
"Failed to set GnuTLS priorities. Last error: %s. " \
6786 "The problematic part starts at: %s\n"),
6787 gnutls_strerror (res), err_pos);
6793#define LOCAL_BUFF_SIZE 128
6804daemon_tls_priorities_init_append (
struct MHD_Daemon *daemon,
const char *prio)
6809 size_t buf_size_needed;
6812 return daemon_tls_priorities_init_default (daemon);
6817 prio_len = strlen (prio);
6819 buf_size_needed = longest_base_prio + 1 + prio_len + 1;
6821 if (LOCAL_BUFF_SIZE >= buf_size_needed)
6823 char local_buffer[LOCAL_BUFF_SIZE];
6824 ret = daemon_tls_priorities_init_append_inner_ (daemon, prio, prio_len,
6830 char *allocated_buffer;
6831 allocated_buffer = (
char *) malloc (buf_size_needed);
6832 if (
NULL == allocated_buffer)
6836 _ (
"Error allocating memory: %s\n"),
6841 ret = daemon_tls_priorities_init_append_inner_ (daemon, prio, prio_len,
6844 free (allocated_buffer);
6863 struct MHD_InterimParams_ *params,
6872#if GNUTLS_VERSION_MAJOR >= 3
6873 gnutls_certificate_retrieve_function2 * pgcrf;
6875#if GNUTLS_VERSION_NUMBER >= 0x030603
6876 gnutls_certificate_retrieve_function3 * pgcrf2;
6901 _ (
"Warning: specified " \
6902 "MHD_OPTION_CONNECTION_MEMORY_LIMIT " \
6903 "value is too small and rounded up to 64.\n"));
6927 _ (
"Warning: specified " \
6928 "MHD_OPTION_CONNECTION_MEMORY_INCREMENT value is " \
6929 "too large and rounded down to 1/4 of " \
6930 "MHD_OPTION_CONNECTION_MEMORY_LIMIT.\n"));
6944#if (SIZEOF_UINT64_T - 2) <= SIZEOF_UNSIGNED_INT
6949 _ (
"The specified connection timeout (%u) is too large. " \
6950 "Maximum allowed value (%" PRIu64 ") will be used " \
6977 params->server_addr_len = va_arg (ap,
6979 params->server_addr_len_set =
true;
6980 params->pserver_addr = va_arg (ap,
6981 const struct sockaddr *);
6982 params->pserver_addr_set =
true;
6985 params->server_addr_len_set =
false;
6986 params->pserver_addr = va_arg (ap,
6987 const struct sockaddr *);
6988 params->pserver_addr_set =
true;
7001#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7003 daemon->worker_pool_size = va_arg (ap,
7005 if (0 == daemon->worker_pool_size)
7009 else if (1 == daemon->worker_pool_size)
7013 _ (
"Warning: value \"1\", specified as the thread pool " \
7014 "size, is ignored. Thread pool is not used.\n"));
7016 daemon->worker_pool_size = 0;
7018#if SIZEOF_UNSIGNED_INT >= (SIZEOF_SIZE_T - 2)
7022 else if (daemon->worker_pool_size >=
7027 _ (
"Specified thread pool size (%u) too big.\n"),
7028 daemon->worker_pool_size);
7039 _ (
"MHD_OPTION_THREAD_POOL_SIZE option is specified but "
7040 "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
7048 _ (
"Both MHD_OPTION_THREAD_POOL_SIZE option and "
7049 "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
7061 daemon->https_mem_key = pstr;
7065 _ (
"MHD HTTPS option %d passed to MHD but " \
7066 "MHD_USE_TLS not set.\n"),
7074 daemon->https_key_password = pstr;
7078 _ (
"MHD HTTPS option %d passed to MHD but " \
7079 "MHD_USE_TLS not set.\n"),
7087 daemon->https_mem_cert = pstr;
7091 _ (
"MHD HTTPS option %d passed to MHD but " \
7092 "MHD_USE_TLS not set.\n"),
7100 daemon->https_mem_trust = pstr;
7104 _ (
"MHD HTTPS option %d passed to MHD but " \
7105 "MHD_USE_TLS not set.\n"),
7110 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
7118 gnutls_datum_t dhpar;
7121 if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
7125 _ (
"Error initializing DH parameters.\n"));
7130 pstr_len = strlen (pstr);
7135 _ (
"Diffie-Hellman parameters string too long.\n"));
7139 dhpar.size = (
unsigned int) pstr_len;
7140 if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
7142 GNUTLS_X509_FMT_PEM) < 0)
7146 _ (
"Bad Diffie-Hellman parameters format.\n"));
7148 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
7151 daemon->have_dhparams =
true;
7156 _ (
"MHD HTTPS option %d passed to MHD but " \
7157 "MHD_USE_TLS not set.\n"),
7167 if (
NULL != daemon->priority_cache)
7168 gnutls_priority_deinit (daemon->priority_cache);
7173 const char *err_pos;
7174 init_res = gnutls_priority_init (&daemon->priority_cache,
7177 if (GNUTLS_E_SUCCESS != init_res)
7181 _ (
"Setting priorities to '%s' failed: %s " \
7182 "The problematic part starts at: %s\n"),
7184 gnutls_strerror (init_res),
7187 daemon->priority_cache =
NULL;
7194 daemon->priority_cache =
NULL;
7195 if (! daemon_tls_priorities_init_append (daemon, pstr))
7202 _ (
"MHD HTTPS option %d passed to MHD but " \
7203 "MHD_USE_TLS not set.\n"),
7208#if GNUTLS_VERSION_MAJOR < 3
7211 _ (
"MHD_OPTION_HTTPS_CERT_CALLBACK requires building " \
7212 "MHD with GnuTLS >= 3.0.\n"));
7217 gnutls_certificate_retrieve_function2 *);
7219 daemon->cert_callback = pgcrf;
7223 _ (
"MHD HTTPS option %d passed to MHD but " \
7224 "MHD_USE_TLS not set.\n"),
7230#if GNUTLS_VERSION_NUMBER < 0x030603
7233 _ (
"MHD_OPTION_HTTPS_CERT_CALLBACK2 requires building " \
7234 "MHD with GnuTLS >= 3.6.3.\n"));
7238 pgcrf2 = va_arg (ap,
7239 gnutls_certificate_retrieve_function3 *);
7241 daemon->cert_callback2 = pgcrf2;
7245 _ (
"MHD HTTPS option %d passed to MHD but " \
7246 "MHD_USE_TLS not set.\n"),
7255 daemon->digest_auth_rand_size = va_arg (ap,
7257 daemon->digest_auth_random = va_arg (ap,
7261 daemon->digest_auth_random_copy = daemon;
7263 daemon->digest_auth_random_copy =
NULL;
7266 daemon->nonce_nc_size = va_arg (ap,
7269 case MHD_OPTION_DIGEST_AUTH_NONCE_BIND_TYPE:
7270 daemon->dauth_bind_type = va_arg (ap,
7282 daemon->dauth_def_nonce_timeout = val;
7292 daemon->dauth_def_max_nc = val;
7299 case MHD_OPTION_DIGEST_AUTH_NONCE_BIND_TYPE:
7304 _ (
"Digest Auth is disabled for this build " \
7305 "of GNU libmicrohttpd.\n"));
7310 params->listen_fd = va_arg (ap,
7312 params->listen_fd_set =
true;
7316 daemon->custom_error_log = va_arg (ap,
7318 daemon->custom_error_log_cls = va_arg (ap,
7320 if (1 != params->num_opts)
7322 _ (
"MHD_OPTION_EXTERNAL_LOGGER is not the first option "
7323 "specified for the daemon. Some messages may be "
7324 "printed by the standard MHD logger.\n"));
7333#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7335 daemon->thread_stack_size = va_arg (ap,
7341 daemon->fastopen_queue_size = va_arg (ap,
7347 _ (
"TCP fastopen is not supported on this platform.\n"));
7353 unsigned int) ? 1 : -1;
7371 _ (
"Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
7372 "another behaviour is specified by "
7373 "MHD_OPTION_STRICT_CLIENT.\n"));
7384 _ (
"Flag MHD_USE_PEDANTIC_CHECKS is ignored because "
7385 "another behaviour is specified by "
7386 "MHD_OPTION_CLIENT_DISCIPLINE_LVL.\n"));
7411 (
size_t) oa[i].
value,
7425 case MHD_OPTION_DIGEST_AUTH_NONCE_BIND_TYPE:
7430 (
unsigned int) oa[i].
value,
7440 (gnutls_credentials_type_t) oa[i].
value,
7473 (uint32_t) oa[i].
value,
7506 (
void *) oa[i].
value,
7517 (
size_t) oa[i].
value,
7527 (socklen_t) oa[i].
value,
7547#if GNUTLS_VERSION_MAJOR >= 3
7548 daemon->cred_callback = va_arg (ap,
7550 daemon->cred_callback_cls = va_arg (ap,
7555 _ (
"MHD HTTPS option %d passed to MHD compiled " \
7556 "without GNUtls >= 3.\n"),
7573 daemon->disable_alpn = (va_arg (ap,
7576 (void) va_arg (ap,
int);
7581 _ (
"MHD HTTPS option %d passed to MHD " \
7582 "but MHD_USE_TLS not set.\n"),
7587 params->fdset_size_set =
true;
7588 params->fdset_size = va_arg (ap,
7591#ifndef HTTPS_SUPPORT
7605 _ (
"MHD HTTPS option %d passed to MHD "
7606 "compiled without HTTPS support.\n"),
7615 _ (
"Invalid option %d! (Did you terminate "
7616 "the list with MHD_OPTION_END?).\n"),
7632#ifndef HAVE_MESSAGES
7636#ifdef USE_EPOLL_CREATE1
7637 fd = epoll_create1 (EPOLL_CLOEXEC);
7639 fd = epoll_create (MAX_EVENTS);
7645 _ (
"Call to epoll_create1 failed: %s\n"),
7650#if ! defined(USE_EPOLL_CREATE1)
7655 _ (
"Failed to set noninheritable mode on epoll FD.\n"));
7672setup_epoll_to_listen (
struct MHD_Daemon *daemon)
7674 struct epoll_event event;
7681 MHD_ITC_IS_VALID_ (daemon->
itc) );
7682 daemon->epoll_fd = setup_epoll_fd (daemon);
7697 _ (
"The epoll FD is too large to be used with fd_set.\n"));
7702 if (-1 == daemon->epoll_fd)
7704#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
7707 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
7715 event.events = EPOLLIN | EPOLLRDHUP;
7716 event.data.ptr = daemon;
7717 if (0 != epoll_ctl (daemon->epoll_fd,
7724 _ (
"Call to epoll_ctl failed: %s\n"),
7729 daemon->listen_socket_in_epoll =
true;
7732 if (MHD_ITC_IS_VALID_ (daemon->
itc))
7734 event.events = EPOLLIN | EPOLLRDHUP;
7736 if (0 != epoll_ctl (daemon->epoll_fd,
7738 MHD_itc_r_fd_ (daemon->
itc),
7743 _ (
"Call to epoll_ctl failed: %s\n"),
7769 const struct sockaddr **ppsockaddr,
7770 socklen_t *psockaddr_len,
7771 struct MHD_InterimParams_ *params)
7773 if (params->fdset_size_set)
7775 if (0 >= params->fdset_size)
7779 _ (
"MHD_OPTION_APP_FD_SETSIZE value (%d) is not positive.\n"),
7780 params->fdset_size);
7788 _ (
"MHD_OPTION_APP_FD_SETSIZE is ignored for daemon started " \
7789 "with MHD_USE_INTERNAL_POLLING_THREAD.\n"));
7797 _ (
"MHD_OPTION_APP_FD_SETSIZE is ignored for daemon started " \
7798 "with MHD_USE_POLL.\n"));
7804#ifndef HAS_FD_SETSIZE_OVERRIDABLE
7805 if (((
int) FD_SETSIZE) != params->fdset_size)
7809 _ (
"MHD_OPTION_APP_FD_SETSIZE value (%d) does not match " \
7810 "the platform FD_SETSIZE value (%d) and this platform " \
7811 "does not support overriding of FD_SETSIZE.\n"),
7812 params->fdset_size, (
int) FD_SETSIZE);
7817 d->fdset_size = params->fdset_size;
7818 d->fdset_size_set_by_app =
true;
7823 if (params->listen_fd_set)
7829#ifdef HAS_SIGNED_SOCKET
7830 else if (0 > params->listen_fd)
7834 _ (
"The value provided for MHD_OPTION_LISTEN_SOCKET " \
7844 _ (
"MHD_OPTION_LISTEN_SOCKET specified for daemon "
7845 "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
7854#ifdef MHD_USE_GETSOCKNAME
7860 mhd_assert (! params->server_addr_len_set || params->pserver_addr_set);
7861 if (params->pserver_addr_set)
7863 if (
NULL == params->pserver_addr)
7866 if (params->server_addr_len_set && (0 != params->server_addr_len))
7874 _ (
"MHD_OPTION_LISTEN_SOCKET cannot be used together with " \
7875 "MHD_OPTION_SOCK_ADDR_LEN or MHD_OPTION_SOCK_ADDR.\n"));
7883 _ (
"MHD_OPTION_SOCK_ADDR_LEN or MHD_OPTION_SOCK_ADDR " \
7884 "specified for daemon with MHD_USE_NO_LISTEN_SOCKET " \
7896 *ppsockaddr = params->pserver_addr;
7897 if (params->server_addr_len_set)
7900 if (0 == params->server_addr_len)
7902 *psockaddr_len = params->server_addr_len;
7944 const struct sockaddr *pservaddr =
NULL;
7946#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
7951 struct MHD_InterimParams_ *interim_params;
7968#ifndef EPOLL_SUPPORT
7972#ifndef HTTPS_SUPPORT
7982#ifdef UPGRADE_SUPPORT
7988#ifdef MHD_USE_THREADS
8017#if defined(EPOLL_SUPPORT) && defined(HAVE_POLL)
8022#elif defined(HAVE_POLL)
8025#elif defined(EPOLL_SUPPORT)
8037#ifdef HAVE_LISTEN_SHUTDOWN
8045 interim_params = (
struct MHD_InterimParams_ *) \
8046 MHD_calloc_ (1,
sizeof (
struct MHD_InterimParams_));
8047 if (
NULL == interim_params)
8049 int err_num = errno;
8055 daemon->epoll_fd = -1;
8056#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
8057 daemon->epoll_upgrade_fd = -1;
8062 daemon->priority_cache =
NULL;
8071 daemon->
port = port;
8082 MHD_itc_set_invalid_ (daemon->
itc);
8083#ifdef MHD_USE_THREADS
8092 daemon->custom_error_log = &MHD_default_logger_;
8093 daemon->custom_error_log_cls = stderr;
8095#ifndef MHD_WINSOCK_SOCKETS
8101#if defined(_DEBUG) && defined(HAVE_ACCEPT4)
8102 daemon->avoid_accept4 =
false;
8104#ifdef HAS_FD_SETSIZE_OVERRIDABLE
8105 daemon->fdset_size = (int) FD_SETSIZE;
8106 daemon->fdset_size_set_by_app =
false;
8110 daemon->digest_auth_rand_size = 0;
8111 daemon->digest_auth_random =
NULL;
8112 daemon->nonce_nc_size = 4;
8119 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
8123 interim_params->num_opts = 0;
8124 interim_params->fdset_size_set =
false;
8125 interim_params->fdset_size = 0;
8126 interim_params->listen_fd_set =
false;
8128 interim_params->pserver_addr_set =
false;
8129 interim_params->pserver_addr =
NULL;
8130 interim_params->server_addr_len_set =
false;
8131 interim_params->server_addr_len = 0;
8138 tls_cleanup_failed_start (daemon);
8140 free (interim_params);
8150 tls_cleanup_failed_start (daemon);
8152 free (interim_params);
8156 free (interim_params);
8157 interim_params =
NULL;
8160 && (
NULL == daemon->priority_cache)
8161 && ! daemon_tls_priorities_init_default (daemon))
8165 _ (
"Failed to initialise GnuTLS priorities.\n"));
8167 tls_cleanup_failed_start (daemon);
8178 _ (
"Warning: MHD_USE_THREAD_PER_CONNECTION must be used " \
8179 "only with MHD_USE_INTERNAL_POLLING_THREAD. " \
8180 "Flag MHD_USE_INTERNAL_POLLING_THREAD was added. " \
8181 "Consider setting MHD_USE_INTERNAL_POLLING_THREAD " \
8194 _ (
"Using debug build of libmicrohttpd.\n") );
8199#
if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8200 && (0 == daemon->worker_pool_size)
8204 if (! MHD_itc_init_ (daemon->
itc))
8208 _ (
"Failed to create inter-thread communication channel: %s\n"),
8209 MHD_itc_last_strerror_ ());
8212 if (
NULL != daemon->priority_cache)
8213 gnutls_priority_deinit (daemon->priority_cache);
8223 _ (
"file descriptor for inter-thread communication " \
8224 "channel exceeds maximum value.\n"));
8228 if (
NULL != daemon->priority_cache)
8229 gnutls_priority_deinit (daemon->priority_cache);
8237 if (
NULL != daemon->digest_auth_random_copy)
8239 mhd_assert (daemon == daemon->digest_auth_random_copy);
8240 daemon->digest_auth_random_copy = malloc (daemon->digest_auth_rand_size);
8241 if (
NULL == daemon->digest_auth_random_copy)
8245 gnutls_priority_deinit (daemon->priority_cache);
8250 memcpy (daemon->digest_auth_random_copy,
8251 daemon->digest_auth_random,
8252 daemon->digest_auth_rand_size);
8253 daemon->digest_auth_random = daemon->digest_auth_random_copy;
8255 if (daemon->nonce_nc_size > 0)
8257 if ( ( (
size_t) (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc)))
8258 /
sizeof(
struct MHD_NonceNc) != daemon->nonce_nc_size)
8262 _ (
"Specified value for NC_SIZE too large.\n"));
8266 gnutls_priority_deinit (daemon->priority_cache);
8268 free (daemon->digest_auth_random_copy);
8274 if (
NULL == daemon->nnc)
8278 _ (
"Failed to allocate memory for nonce-nc map: %s\n"),
8283 gnutls_priority_deinit (daemon->priority_cache);
8285 free (daemon->digest_auth_random_copy);
8291#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8296 _ (
"MHD failed to initialize nonce-nc mutex.\n"));
8300 gnutls_priority_deinit (daemon->priority_cache);
8302 free (daemon->digest_auth_random_copy);
8311#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8313 (daemon->worker_pool_size > 0) )
8317 _ (
"MHD thread polling only works with " \
8318 "MHD_USE_INTERNAL_POLLING_THREAD.\n"));
8328 struct sockaddr_in servaddr4;
8330 struct sockaddr_in6 servaddr6;
8333 const bool use_ipv6 =
false;
8337 if (
NULL != pservaddr)
8339#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
8340 const socklen_t sa_len = pservaddr->sa_len;
8343 if (use_ipv6 && (AF_INET6 != pservaddr->sa_family))
8347 _ (
"MHD_USE_IPv6 is enabled, but 'struct sockaddr *' " \
8348 "specified for MHD_OPTION_SOCK_ADDR_LEN or " \
8349 "MHD_OPTION_SOCK_ADDR is not IPv6 address.\n"));
8354 switch (pservaddr->sa_family)
8359 struct sockaddr_in sa4;
8362 && (((socklen_t)
sizeof(sa4)) > addrlen))
8366 _ (
"The size specified for MHD_OPTION_SOCK_ADDR_LEN " \
8367 "option is wrong.\n"));
8371#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
8374 if (((socklen_t)
sizeof(sa4)) > sa_len)
8378 _ (
"The value of 'struct sockaddr.sa_len' provided " \
8379 "via MHD_OPTION_SOCK_ADDR_LEN option is not zero " \
8380 "and does not match 'sa_family' value of the " \
8381 "same structure.\n"));
8385 if ((0 == addrlen) || (sa_len < addrlen))
8390 addrlen =
sizeof(sa4);
8391 memcpy (&sa4, pservaddr,
sizeof(sa4));
8392 sa4_port = (uint16_t) ntohs (sa4.sin_port);
8393#ifndef MHD_USE_GETSOCKNAME
8396 daemon->
port = sa4_port;
8404 struct sockaddr_in6 sa6;
8407 && (((socklen_t)
sizeof(sa6)) > addrlen))
8411 _ (
"The size specified for MHD_OPTION_SOCK_ADDR_LEN " \
8412 "option is wrong.\n"));
8416#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
8419 if (((socklen_t)
sizeof(sa6)) > sa_len)
8423 _ (
"The value of 'struct sockaddr.sa_len' provided " \
8424 "via MHD_OPTION_SOCK_ADDR_LEN option is not zero " \
8425 "and does not match 'sa_family' value of the " \
8426 "same structure.\n"));
8430 if ((0 == addrlen) || (sa_len < addrlen))
8435 addrlen =
sizeof(sa6);
8436 memcpy (&sa6, pservaddr,
sizeof(sa6));
8437 sa6_port = (uint16_t) ntohs (sa6.sin6_port);
8438#ifndef MHD_USE_GETSOCKNAME
8441 daemon->
port = sa6_port;
8451#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
8454 else if ((0 != sa_len) && (sa_len < addrlen))
8461 _ (
"The 'sa_family' of the 'struct sockaddr' provided " \
8462 "via MHD_OPTION_SOCK_ADDR option is not supported.\n"));
8467 if (AF_UNIX == pservaddr->sa_family)
8484 domain = pservaddr->sa_family;
8495 sizeof (
struct sockaddr_in));
8496 servaddr4.sin_family = AF_INET;
8497 servaddr4.sin_port = htons (port);
8498 if (0 != INADDR_ANY)
8499 servaddr4.sin_addr.s_addr = htonl (INADDR_ANY);
8500#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
8501 servaddr4.sin_len =
sizeof (
struct sockaddr_in);
8503 pservaddr = (
struct sockaddr *) &servaddr4;
8504 addrlen = (socklen_t)
sizeof(servaddr4);
8511#ifdef IN6ADDR_ANY_INIT
8512 static const struct in6_addr static_in6any = IN6ADDR_ANY_INIT;
8516 sizeof (
struct sockaddr_in6));
8517 servaddr6.sin6_family = AF_INET6;
8518 servaddr6.sin6_port = htons (port);
8519#ifdef IN6ADDR_ANY_INIT
8520 servaddr6.sin6_addr = static_in6any;
8522#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
8523 servaddr6.sin6_len =
sizeof (
struct sockaddr_in6);
8525 pservaddr = (
struct sockaddr *) &servaddr6;
8526 addrlen = (socklen_t)
sizeof (servaddr6);
8538 _ (
"Failed to create socket for listening: %s\n"),
8549 _ (
"Listen socket descriptor (%d) is not " \
8550 "less than daemon FD_SETSIZE value (%d).\n"),
8560#ifndef MHD_WINSOCK_SOCKETS
8568 (
const void *) &on, sizeof (on)))
8572 _ (
"setsockopt failed: %s\n"),
8581#ifndef MHD_WINSOCK_SOCKETS
8587 (
const void *) &on, sizeof (on)))
8591 _ (
"setsockopt failed: %s\n"),
8601#if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT)
8604#ifndef MHD_WINSOCK_SOCKETS
8614 _ (
"setsockopt failed: %s\n"),
8624 _ (
"Cannot allow listening address reuse: " \
8625 "SO_REUSEPORT not defined.\n"));
8638#if (defined(MHD_WINSOCK_SOCKETS) && defined(SO_EXCLUSIVEADDRUSE)) || \
8639 (defined(__sun) && defined(SO_EXCLBIND))
8642#ifdef SO_EXCLUSIVEADDRUSE
8643 SO_EXCLUSIVEADDRUSE,
8652 _ (
"setsockopt failed: %s\n"),
8657#elif defined(MHD_WINSOCK_SOCKETS)
8660 _ (
"Cannot disallow listening address reuse: " \
8661 "SO_EXCLUSIVEADDRUSE not defined.\n"));
8679 IPPROTO_IPV6, IPV6_V6ONLY,
8680 (
const void *) &v6_only,
8685 _ (
"setsockopt failed: %s\n"),
8698 _ (
"Failed to bind to port %u: %s\n"),
8699 (
unsigned int) port,
8707 if (0 == daemon->fastopen_queue_size)
8708 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
8712 (
const void *) &daemon->fastopen_queue_size,
8713 sizeof (daemon->fastopen_queue_size)))
8717 _ (
"setsockopt failed: %s\n"),
8728 _ (
"Failed to listen for connections: %s\n"),
8742 _ (
"Listen socket descriptor (%d) is not " \
8743 "less than daemon FD_SETSIZE value (%d).\n"),
8751#if defined(SOL_SOCKET) && (defined(SO_DOMAIN) || defined(SO_PROTOCOL_INFOW))
8755 socklen_t optval_size;
8757 opt_name = SO_DOMAIN;
8759 optval_size = (socklen_t)
sizeof (af);
8761 WSAPROTOCOL_INFOW prot_info;
8762 opt_name = SO_PROTOCOL_INFOW;
8763 poptval = &prot_info;
8764 optval_size = (socklen_t)
sizeof (prot_info);
8774 af = prot_info.iAddressFamily;
8804#ifdef MHD_USE_GETSOCKNAME
8809#ifdef MHD_USE_GETSOCKNAME
8810 if ( (0 == daemon->
port) &&
8814 struct sockaddr_storage bindaddr;
8818 sizeof (
struct sockaddr_storage));
8819 addrlen =
sizeof (
struct sockaddr_storage);
8820#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
8821 bindaddr.ss_len = (socklen_t) addrlen;
8823 if (0 != getsockname (daemon->
listen_fd,
8824 (
struct sockaddr *) &bindaddr,
8829 _ (
"Failed to get listen port number: %s\n"),
8830 MHD_socket_last_strerr_ ());
8834 else if (
sizeof (bindaddr) < addrlen)
8839 _ (
"Failed to get listen port number " \
8840 "(`struct sockaddr_storage` too small!?).\n"));
8844 else if (0 == addrlen)
8856 switch (bindaddr.ss_family)
8860 struct sockaddr_in *s4 = (
struct sockaddr_in *) &bindaddr;
8862 daemon->
port = ntohs (s4->sin_port);
8869 struct sockaddr_in6 *s6 = (
struct sockaddr_in6 *) &bindaddr;
8871 daemon->
port = ntohs (s6->sin6_port);
8886 _ (
"Listen socket has unknown address family!\n"));
8903 _ (
"Failed to set nonblocking mode on listening socket: %s\n"),
8907#
if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8908 || (daemon->worker_pool_size > 0)
8930#
if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8931 && (0 == daemon->worker_pool_size)
8939 _ (
"Combining MHD_USE_THREAD_PER_CONNECTION and " \
8940 "MHD_USE_EPOLL is not supported.\n"));
8944 if (
MHD_NO == setup_epoll_to_listen (daemon))
8949#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8954 _ (
"MHD failed to initialize IP connection limit mutex.\n"));
8963 (0 != MHD_TLS_init (daemon)) )
8967 _ (
"Failed to initialize TLS support.\n"));
8969#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8975#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
8983#ifdef HAVE_LISTEN_SHUTDOWN
8984 mhd_assert ((1 < daemon->worker_pool_size) || \
8985 (MHD_ITC_IS_VALID_ (daemon->
itc)) || \
8988 mhd_assert ((1 < daemon->worker_pool_size) || \
8989 (MHD_ITC_IS_VALID_ (daemon->
itc)));
8991 if (0 == daemon->worker_pool_size)
8997 _ (
"Failed to initialise internal lists mutex.\n"));
9006 _ (
"Failed to initialise mutex.\n"));
9016 _ (
"Failed to initialise mutex.\n"));
9025 "MHD-listen" :
"MHD-single",
9026 daemon->thread_stack_size,
9027 &MHD_polling_thread,
9032 if (EAGAIN == errno)
9034 _ (
"Failed to create a new thread because it would have " \
9035 "exceeded the system limit on the number of threads or " \
9036 "no system resources available.\n"));
9040 _ (
"Failed to create listen thread: %s\n"),
9056 / daemon->worker_pool_size;
9058 % daemon->worker_pool_size;
9064 daemon->worker_pool = malloc (
sizeof (
struct MHD_Daemon)
9065 * daemon->worker_pool_size);
9066 if (
NULL == daemon->worker_pool)
9070 for (i = 0; i < daemon->worker_pool_size; ++i)
9073 struct MHD_Daemon *d = &daemon->worker_pool[i];
9075 memcpy (d, daemon,
sizeof (
struct MHD_Daemon));
9080 d->worker_pool_size = 0;
9081 d->worker_pool =
NULL;
9086 _ (
"Failed to initialise internal lists mutex.\n"));
9094 _ (
"Failed to initialise mutex.\n"));
9103 _ (
"Failed to initialise mutex.\n"));
9112 if (! MHD_itc_init_ (d->
itc))
9116 _ (
"Failed to create worker inter-thread " \
9117 "communication channel: %s\n"),
9118 MHD_itc_last_strerror_ () );
9130 _ (
"File descriptor for worker inter-thread " \
9131 "communication channel exceeds maximum value.\n"));
9141 MHD_itc_set_invalid_ (d->
itc);
9143#ifdef HAVE_LISTEN_SHUTDOWN
9154 if (i < leftover_conns)
9158 (
MHD_NO == setup_epoll_to_listen (d)) )
9160 if (MHD_ITC_IS_VALID_ (d->
itc))
9169#if defined(MHD_USE_THREADS)
9170 memset (&d->per_ip_connection_mutex, 0x7F,
9171 sizeof(d->per_ip_connection_mutex));
9175 d->nonce_nc_size = 0;
9176 d->digest_auth_random_copy =
NULL;
9177#if defined(MHD_USE_THREADS)
9178 memset (&d->nnc_lock, 0x7F,
sizeof(d->nnc_lock));
9185 daemon->thread_stack_size,
9186 &MHD_polling_thread,
9191 if (EAGAIN == errno)
9193 _ (
"Failed to create a new pool thread because it would " \
9194 "have exceeded the system limit on the number of " \
9195 "threads or no system resources available.\n"));
9199 _ (
"Failed to create pool thread: %s\n"),
9204 if (MHD_ITC_IS_VALID_ (d->
itc))
9220 _ (
"Failed to initialise internal lists mutex.\n"));
9229 _ (
"Failed to initialise mutex.\n"));
9239 _ (
"Failed to initialise mutex.\n"));
9251 daemon->https_key_password =
NULL;
9256#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9265 if (
NULL != daemon->worker_pool)
9266 free (daemon->worker_pool);
9274 daemon->worker_pool_size = i;
9283#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9284 if (daemon->upgrade_fd_in_epoll)
9286 if (0 != epoll_ctl (daemon->epoll_fd,
9288 daemon->epoll_upgrade_fd,
9290 MHD_PANIC (
_ (
"Failed to remove FD from epoll set.\n"));
9291 daemon->upgrade_fd_in_epoll =
false;
9294 if (-1 != daemon->epoll_fd)
9295 close (daemon->epoll_fd);
9296#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9297 if (-1 != daemon->epoll_upgrade_fd)
9298 close (daemon->epoll_upgrade_fd);
9302 free (daemon->digest_auth_random_copy);
9304#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9309 tls_cleanup_failed_start (daemon);
9311 if (MHD_ITC_IS_VALID_ (daemon->
itc))
9333#ifdef UPGRADE_SUPPORT
9336#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9337 struct MHD_UpgradeResponseHandle *urh;
9338 struct MHD_UpgradeResponseHandle *urhn;
9342#ifdef MHD_USE_THREADS
9350#ifdef MHD_USE_THREADS
9367 new_connection_close_ (daemon, pos);
9372#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9375 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
9383 urh->clean_ready =
true;
9400#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9403#ifdef UPGRADE_SUPPORT
9409 while (
NULL != susp)
9411 if (
NULL == susp->urh)
9412 MHD_PANIC (
_ (
"MHD_stop_daemon() called while we have " \
9413 "suspended connections.\n"));
9415 else if (used_tls &&
9417 (! susp->urh->clean_ready) )
9418 shutdown (susp->urh->app.socket,
9424 if (! susp->urh->was_closed)
9426 _ (
"Initiated daemon shutdown while \"upgraded\" " \
9427 "connection was not closed.\n"));
9429 susp->urh->was_closed =
true;
9445 MHD_PANIC (
_ (
"MHD_stop_daemon() called while we have " \
9446 "suspended connections.\n"));
9447#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
9448#ifdef MHD_USE_THREADS
9449 if (upg_allowed && used_tls && used_thr_p_c)
9460 if (! pos->thread_joined)
9468 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
9469 pos->thread_joined =
true;
9480#ifdef MHD_WINSOCK_SOCKETS
9483 (! MHD_itc_activate_ (
daemon->
itc,
"e")) )
9484 MHD_PANIC (
_ (
"Failed to signal shutdown via inter-thread " \
9485 "communication channel.\n"));
9489#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9496 if (! pos->thread_joined)
9500 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
9502 pos->thread_joined =
true;
9514#ifdef UPGRADE_SUPPORT
9530#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9532 (! pos->thread_joined) )
9533 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
9551#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9558 MHD_PANIC (
_ (
"MHD_stop_daemon() was called twice."));
9576#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9583 for (i = 0; i <
daemon->worker_pool_size; ++i)
9586 if (MHD_ITC_IS_VALID_ (
daemon->worker_pool[i].
itc))
9588 if (! MHD_itc_activate_ (
daemon->worker_pool[i].
itc,
9590 MHD_PANIC (
_ (
"Failed to signal shutdown via inter-thread " \
9591 "communication channel.\n"));
9596#ifdef HAVE_LISTEN_SHUTDOWN
9599 (void) shutdown (
fd,
9603 for (i = 0; i <
daemon->worker_pool_size; ++i)
9607 free (
daemon->worker_pool);
9611#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9619#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9628 MHD_PANIC (
_ (
"Failed to signal shutdown via inter-thread " \
9629 "communication channel.\n"));
9633#ifdef HAVE_LISTEN_SHUTDOWN
9637 (void) shutdown (
fd,
9647 MHD_PANIC (
_ (
"Failed to join a thread.\n"));
9661#if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
9670 (-1 !=
daemon->epoll_fd) )
9672#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
9674 (-1 !=
daemon->epoll_upgrade_fd) )
9679#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9695 if (
daemon->have_dhparams)
9697 gnutls_dh_params_deinit (
daemon->https_mem_dhparams);
9698 daemon->have_dhparams =
false;
9702 gnutls_priority_deinit (
daemon->priority_cache);
9704 gnutls_certificate_free_credentials (
daemon->x509_cred);
9706 gnutls_psk_free_server_credentials (
daemon->psk_cred);
9711 free (
daemon->digest_auth_random_copy);
9713#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9717#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9746 (
NULL != daemon->worker_pool) || \
9749 (
NULL == daemon->worker_pool)) || \
9763 daemon->daemon_info_dummy_epoll_fd.epoll_fd = daemon->epoll_fd;
9764 return &daemon->daemon_info_dummy_epoll_fd;
9771#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
9772 else if (daemon->worker_pool)
9777 for (i = 0; i < daemon->worker_pool_size; i++)
9808#ifdef PACKAGE_VERSION
9809 return PACKAGE_VERSION;
9811 static char ver[12] =
"\0\0\0\0\0\0\0\0\0\0\0";
9814 int res = MHD_snprintf_ (ver,
9820 if ((0 >= res) || (
sizeof(ver) <= res))
9872#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3
9878#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030603
9890#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
9908#ifdef HAVE_LISTEN_SHUTDOWN
9914#ifdef _MHD_ITC_SOCKETPAIR
9938#ifdef HAVE_POSTPROCESSOR
9944#if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111
9950#if defined(HAVE_PREAD64) || defined(_WIN32)
9952#elif defined(HAVE_PREAD)
9953 return (
sizeof(uint64_t) >
sizeof(off_t)) ?
MHD_NO :
MHD_YES;
9954#elif defined(HAVE_LSEEK64)
9957 return (
sizeof(uint64_t) >
sizeof(off_t)) ?
MHD_NO :
MHD_YES;
9960#if defined(MHD_USE_THREAD_NAME_)
9966#if defined(UPGRADE_SUPPORT)
9972#if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
9978#ifdef MHD_USE_GETSOCKNAME
9984#if defined(MHD_SEND_SPIPE_SUPPRESS_POSSIBLE) || \
9985 ! defined(MHD_SEND_SPIPE_SUPPRESS_NEEDED)
9991#ifdef _MHD_HAVE_SENDFILE
9997#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
10003#if defined(COOKIE_SUPPORT)
10009#ifdef DAUTH_SUPPORT
10015#if defined(DAUTH_SUPPORT) && defined(MHD_MD5_SUPPORT)
10021#if defined(DAUTH_SUPPORT) && defined(MHD_SHA256_SUPPORT)
10027#if defined(DAUTH_SUPPORT) && defined(MHD_SHA512_256_SUPPORT)
10033#ifdef DAUTH_SUPPORT
10039#ifdef DAUTH_SUPPORT
10045#ifdef DAUTH_SUPPORT
10051#if defined(MHD_MD5_TLSLIB) || defined(MHD_SHA256_TLSLIB)
10063#ifdef HAS_FD_SETSIZE_OVERRIDABLE
10076#ifdef MHD_HTTPS_REQUIRE_GCRYPT
10077#if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600
10078#if defined(MHD_USE_POSIX_THREADS)
10079GCRY_THREAD_OPTION_PTHREAD_IMPL;
10080#elif defined(MHD_W32_MUTEX_)
10083gcry_w32_mutex_init (
void **ppmtx)
10085 *ppmtx = malloc (
sizeof (MHD_mutex_));
10087 if (
NULL == *ppmtx)
10101gcry_w32_mutex_destroy (
void **ppmtx)
10110gcry_w32_mutex_lock (
void **ppmtx)
10117gcry_w32_mutex_unlock (
void **ppmtx)
10123static struct gcry_thread_cbs gcry_threads_w32 = {
10124 (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
10125 NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
10126 gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
10140#if defined(MHD_WINSOCK_SOCKETS)
10146#if defined(MHD_WINSOCK_SOCKETS)
10147 if (0 != WSAStartup (MAKEWORD (2, 2), &wsd))
10148 MHD_PANIC (
_ (
"Failed to initialize winsock.\n"));
10149 if ((2 != LOBYTE (wsd.wVersion)) && (2 != HIBYTE (wsd.wVersion)))
10150 MHD_PANIC (
_ (
"Winsock version 2.2 is not available.\n"));
10152#ifdef HTTPS_SUPPORT
10153#ifdef MHD_HTTPS_REQUIRE_GCRYPT
10154#if GCRYPT_VERSION_NUMBER < 0x010600
10155#if GNUTLS_VERSION_NUMBER <= 0x020b00
10156#if defined(MHD_USE_POSIX_THREADS)
10157 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
10158 &gcry_threads_pthread))
10159 MHD_PANIC (
_ (
"Failed to initialise multithreading in libgcrypt.\n"));
10160#elif defined(MHD_W32_MUTEX_)
10161 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
10162 &gcry_threads_w32))
10163 MHD_PANIC (
_ (
"Failed to initialise multithreading in libgcrypt.\n"));
10166 gcry_check_version (
NULL);
10168 if (
NULL == gcry_check_version (
"1.6.0"))
10169 MHD_PANIC (
_ (
"libgcrypt is too old. MHD was compiled for " \
10170 "libgcrypt 1.6.0 or newer.\n"));
10173 gnutls_global_init ();
10183 mhd_assert (
sizeof(tv.tv_sec) == SIZEOF_STRUCT_TIMEVAL_TV_SEC);
10186 mhd_assert (
sizeof(uint64_t) == SIZEOF_UINT64_T);
10193#ifdef HTTPS_SUPPORT
10194 gnutls_global_deinit ();
10196#if defined(MHD_WINSOCK_SOCKETS)
10203#ifdef _AUTOINIT_FUNCS_ARE_SUPPORTED
#define _SET_INIT_AND_DEINIT_FUNCS(FI, FD)
void MHD_connection_set_initial_state_(struct MHD_Connection *c)
void MHD_connection_handle_write(struct MHD_Connection *connection)
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
enum MHD_Result MHD_connection_handle_idle(struct MHD_Connection *connection)
void MHD_connection_handle_read(struct MHD_Connection *connection, bool socket_error)
void MHD_update_last_activity_(struct MHD_Connection *connection)
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
Methods for managing connections.
#define MHD_connection_finish_forward_(conn)
void MHD_set_https_callbacks(struct MHD_Connection *connection)
Methods for managing connections.
static void MHD_ip_limit_del(struct MHD_Daemon *daemon, const struct sockaddr_storage *addr, socklen_t addrlen)
static void close_all_connections(struct MHD_Daemon *daemon)
static enum MHD_Result MHD_ip_addr_to_key(const struct sockaddr_storage *addr, socklen_t addrlen, struct MHD_IPCount *key)
void internal_suspend_connection_(struct MHD_Connection *connection)
static enum MHD_Result MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr_storage *addr, socklen_t addrlen)
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_storage *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
void MHD_check_global_init_(void)
static void close_connection(struct MHD_Connection *pos)
_MHD_EXTERN void MHD_resume_connection(struct MHD_Connection *connection)
static enum MHD_Result MHD_select(struct MHD_Daemon *daemon, int32_t millisec)
static enum MHD_Result parse_options(struct MHD_Daemon *daemon, struct MHD_InterimParams_ *params,...)
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 enum MHD_Result parse_options_va(struct MHD_Daemon *daemon, struct MHD_InterimParams_ *params, va_list ap)
#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 enum MHD_Result internal_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr_storage *addr, socklen_t addrlen, bool external_add, bool non_blck, bool sk_spipe_supprs, enum MHD_tristate sk_is_nonip)
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
static enum MHD_Result resume_suspended_connections(struct MHD_Daemon *daemon)
#define MHD_POOL_SIZE_DEFAULT
static bool process_interim_params(struct MHD_Daemon *d, const struct sockaddr **ppsockaddr, socklen_t *psockaddr_len, struct MHD_InterimParams_ *params)
_MHD_EXTERN void MHD_suspend_connection(struct MHD_Connection *connection)
else if(MHD_DIGEST_ALG_MD5==algo)
_MHD_EXTERN int MHD_get_timeout_i(struct MHD_Daemon *daemon)
_MHD_EXTERN int64_t MHD_get_timeout64s(struct MHD_Daemon *daemon)
#define MHD_run_from_select(d, r, w, e)
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
_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)
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, int fd_setsize)
_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)
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, int fd_setsize)
#define MHD_get_fdset(daemon, read_fd_set, write_fd_set, except_fd_set, max_fd)
_MHD_EXTERN enum MHD_Result MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
_MHD_EXTERN enum MHD_Result MHD_get_timeout64(struct MHD_Daemon *daemon, uint64_t *timeout)
_MHD_EXTERN enum MHD_Result MHD_run_from_select2(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set, unsigned int fd_setsize)
_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_run_wait(struct MHD_Daemon *daemon, int32_t millisec)
_MHD_EXTERN void MHD_set_panic_func(MHD_PanicCallback cb, void *cls)
void(* MHD_RequestCompletedCallback)(void *cls, struct MHD_Connection *connection, void **req_cls, enum MHD_RequestTerminationCode toe)
void(* MHD_NotifyConnectionCallback)(void *cls, struct MHD_Connection *connection, void **socket_context, enum MHD_ConnectionNotificationCode 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 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 MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
_MHD_EXTERN const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
_MHD_EXTERN uint32_t MHD_get_version_bin(void)
_MHD_EXTERN const char * MHD_get_version(void)
_MHD_EXTERN void MHD_free(void *ptr)
MHD internal shared structures.
@ MHD_CONNECTION_HEADERS_SENDING
@ MHD_CONNECTION_NORMAL_BODY_READY
@ MHD_CONNECTION_CHUNKED_BODY_READY
#define MHD_D_IS_USING_POLL_(d)
#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 MHD_D_DOES_SCKT_FIT_FDSET_(sckt, d)
@ MHD_EVENT_LOOP_INFO_PROCESS_READ
@ MHD_EVENT_LOOP_INFO_PROCESS
@ MHD_EVENT_LOOP_INFO_READ
@ MHD_EVENT_LOOP_INFO_WRITE
@ MHD_EVENT_LOOP_INFO_CLEANUP
#define MHD_D_IS_USING_SELECT_(d)
#define EDLL_insert(head, tail, element)
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
_MHD_static_inline struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *const daemon)
#define _MHD_DROP_CONST(ptr)
#define MHD_D_GET_FD_SETSIZE_(d)
#define EDLL_remove(head, tail, element)
#define XDLL_remove(head, tail, element)
#define MHD_D_IS_USING_THREAD_PER_CONN_(d)
#define DLL_remove(head, tail, element)
#define MHD_D_IS_USING_THREADS_(d)
#define MHD_TEST_ALLOW_SUSPEND_RESUME
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
#define MHD_D_IS_USING_EPOLL_(d)
#define MHD_D_IS_THREAD_SAFE_(d)
void MHD_init_mem_pools_(void)
void MHD_pool_destroy(struct MemoryPool *pool)
struct MemoryPool * MHD_pool_create(size_t max)
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...
#define mhd_assert(ignore)
void * MHD_calloc_(size_t nelem, size_t elsize)
Header for platform missing functions.
#define MHD_strerror_(errnum)
Header for platform-independent inter-thread communication.
#define MHD_ITC_IS_INVALID_(itc)
#define MHD_itc_destroy_chk_(itc)
limits values definitions
#define TIMEVAL_TV_SEC_MAX
Header for platform-independent locks abstraction.
#define MHD_mutex_unlock_chk_(ignore)
#define MHD_mutex_destroy_(ignore)
#define MHD_mutex_unlock_(ignore)
#define MHD_mutex_lock_(ignore)
#define MHD_mutex_init_(ignore)
#define MHD_mutex_lock_chk_(ignore)
#define MHD_mutex_destroy_chk_(ignore)
uint64_t MHD_monotonic_msec_counter(void)
void MHD_monotonic_sec_counter_finish(void)
void MHD_monotonic_sec_counter_init(void)
internal monotonic clock functions implementations
#define MHD_DAUTH_DEF_TIMEOUT_
#define MHD_DAUTH_DEF_MAX_NC_
void MHD_send_init_static_vars_(void)
Declarations of send() wrappers.
int MHD_socket_noninheritable_(MHD_socket sock)
int MHD_socket_nonblocking_(MHD_socket sock)
int MHD_add_to_fd_set_(MHD_socket fd, fd_set *set, MHD_socket *max_fd, int fd_setsize)
MHD_socket MHD_socket_create_listen_(int pf)
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
#define MHD_SCKT_FD_FITS_FDSET_SETSIZE_(fd, pset, setsize)
#define MHD_SCKT_ERR_IS_(err, code)
#define SOCK_NONBLOCK_OR_ZERO
#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 SOCK_NOSIGPIPE_OR_ZERO
#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 SOCK_CLOEXEC_OR_ZERO
size_t MHD_str_pct_decode_in_place_lenient_(char *str, bool *broken_encoding)
size_t MHD_str_pct_decode_in_place_strict_(char *str)
Header for string manipulating helpers.
#define _MHD_S_STR_W_LEN(str)
#define MHD_STATICSTR_LEN_(macro)
Header for platform-independent threads abstraction.
#define MHD_thread_handle_ID_set_current_thread_ID_(hndl_id_ptr)
#define MHD_thread_handle_ID_is_current_thread_(hndl_id)
#define MHD_thread_handle_ID_is_valid_handle_(hndl_id)
#define MHD_thread_handle_ID_join_thread_(hndl_id)
#define MHD_thread_handle_ID_set_invalid_(hndl_id_ptr)
#define MHD_thread_handle_ID_is_valid_ID_(hndl_id)
#define MHD_create_named_thread_(t, n, s, r, a)
@ MHD_FEATURE_POSTPROCESSOR
@ MHD_FEATURE_SHUTDOWN_LISTEN_SOCKET
@ MHD_FEATURE_DIGEST_AUTH_USERHASH
@ MHD_FEATURE_DIGEST_AUTH_AUTH_INT
@ MHD_FEATURE_DIGEST_AUTH_SHA256
@ MHD_FEATURE_AUTODETECT_BIND_PORT
@ MHD_FEATURE_DIGEST_AUTH_SHA512_256
@ MHD_FEATURE_EXTERN_HASH
@ MHD_FEATURE_HTTPS_CERT_CALLBACK
@ MHD_FEATURE_DIGEST_AUTH
@ MHD_FEATURE_THREAD_NAMES
@ MHD_FEATURE_DEBUG_BUILD
@ MHD_FEATURE_FLEXIBLE_FD_SETSIZE
@ MHD_FEATURE_HTTPS_KEY_PASSWORD
@ MHD_FEATURE_AUTOSUPPRESS_SIGPIPE
@ MHD_FEATURE_RESPONSES_SHARED_FD
@ MHD_FEATURE_DIGEST_AUTH_ALGO_SESSION
@ MHD_FEATURE_COOKIE_PARSING
@ MHD_FEATURE_DIGEST_AUTH_MD5
@ MHD_FEATURE_TCP_FASTOPEN
@ MHD_FEATURE_DIGEST_AUTH_RFC2069
@ MHD_FEATURE_HTTPS_CERT_CALLBACK2
@ MHD_OPTION_HTTPS_PRIORITIES_APPEND
@ MHD_OPTION_CONNECTION_MEMORY_INCREMENT
@ MHD_OPTION_HTTPS_CRED_TYPE
@ MHD_OPTION_URI_LOG_CALLBACK
@ MHD_OPTION_HTTPS_CERT_CALLBACK2
@ MHD_OPTION_DIGEST_AUTH_DEFAULT_NONCE_TIMEOUT
@ MHD_OPTION_CLIENT_DISCIPLINE_LVL
@ MHD_OPTION_SOCK_ADDR_LEN
@ MHD_OPTION_APP_FD_SETSIZE
@ 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_DIGEST_AUTH_DEFAULT_MAX_NC
@ 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_ALLOW_BIN_ZERO_IN_URI_PATH
@ MHD_OPTION_CONNECTION_MEMORY_LIMIT
@ MHD_OPTION_THREAD_STACK_SIZE
@ MHD_OPTION_DIGEST_AUTH_RANDOM_COPY
@ 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
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 **req_cls)
#define MHD_POSIX_SOCKETS
#define MHD_INVALID_SOCKET
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_SELECT_INTERNALLY
@ MHD_USE_INSECURE_TLS_EARLY_DATA
@ MHD_USE_NO_LISTEN_SOCKET
@ MHD_USE_PEDANTIC_CHECKS
@ MHD_USE_INTERNAL_POLLING_THREAD
@ MHD_USE_NO_THREAD_SAFETY
@ MHD_DAUTH_BIND_NONCE_URI
@ MHD_DAUTH_BIND_NONCE_URI_PARAMS
Methods for managing response objects.
enum MHD_tristate sk_nodelay
struct MHD_Connection * prev
enum MHD_ConnectionEventLoopInfo event_loop_info
enum MHD_tristate is_nonip
struct MHD_itc_ resume_itc
struct MHD_Connection * nextX
struct MHD_Connection * next
size_t read_buffer_offset
enum MHD_CONNECTION_STATE state
struct MHD_Connection * prevX
struct MHD_Daemon * daemon
uint64_t connection_timeout_ms
struct sockaddr_storage * addr
enum MHD_tristate sk_corked
MHD_NotifyConnectionCallback notify_connection
MHD_AccessHandlerCallback default_handler
LogCallback uri_log_callback
bool data_already_pending
union MHD_DaemonInfo daemon_info_dummy_port
struct MHD_Connection * normal_timeout_tail
struct MHD_Connection * new_connections_tail
unsigned int connection_limit
void * unescape_callback_cls
enum MHD_DisableSanityCheck insanity_level
struct MHD_Connection * connections_tail
struct MHD_Connection * suspended_connections_tail
union MHD_DaemonInfo daemon_info_dummy_listen_fd
struct MHD_Connection * manual_timeout_head
unsigned int listen_backlog_size
struct MHD_Connection * normal_timeout_head
union MHD_DaemonInfo daemon_info_dummy_flags
MHD_RequestCompletedCallback notify_completed
struct MHD_Connection * cleanup_head
int listening_address_reuse
uint64_t connection_timeout_ms
unsigned int per_ip_connection_limit
struct MHD_Connection * manual_timeout_tail
union MHD_DaemonInfo daemon_info_dummy_num_connections
void * notify_connection_cls
struct MHD_Connection * cleanup_tail
UnescapeCallback unescape_callback
void * notify_completed_cls
volatile bool was_quiesced
struct MHD_Connection * suspended_connections_head
struct MHD_Connection * new_connections_head
enum MHD_tristate listen_is_unix
void * default_handler_cls
struct MHD_Connection * connections_head
MHD_AcceptPolicyCallback apc
void * per_ip_connection_count
void * uri_log_callback_cls
struct MHD_Daemon * master
struct MHD_Response * response
void * tfind(const void *vkey, void *const *vrootp, int(*compar)(const void *, const void *))
void * tdelete(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
unsigned int num_connections