54 #include <sys/sendfile.h> 58 #ifndef WIN32_LEAN_AND_MEAN 59 #define WIN32_LEAN_AND_MEAN 1 67 #ifdef MHD_POSIX_SOCKETS 68 #define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 4) 70 #define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2) 76 #define MHD_POOL_SIZE_DEFAULT (32 * 1024) 82 #define DEBUG_CLOSE MHD_NO 88 #define DEBUG_CONNECT MHD_NO 137 _(
"Fatal error in GNU libmicrohttpd %s:%u: %s\n"),
160 static int mhd_winsock_inited_ = 0;
203 struct in6_addr ipv6;
253 offsetof (
struct MHD_IPCount,
269 struct MHD_IPCount *key)
276 if (
sizeof (
struct sockaddr_in) == addrlen)
278 const struct sockaddr_in *addr4 = (
const struct sockaddr_in*) addr;
280 key->family = AF_INET;
281 memcpy (&key->addr.ipv4,
283 sizeof(addr4->sin_addr));
289 if (
sizeof (
struct sockaddr_in6) == addrlen)
291 const struct sockaddr_in6 *addr6 = (
const struct sockaddr_in6*) addr;
293 key->family = AF_INET6;
294 memcpy (&key->addr.ipv6,
296 sizeof(addr6->sin6_addr));
319 const struct sockaddr *addr,
322 struct MHD_IPCount *key;
332 if (
NULL == (key = malloc (
sizeof(*key))))
353 _(
"Failed to add IP connection count node\n"));
363 key = (
struct MHD_IPCount *) node;
385 const struct sockaddr *addr,
388 struct MHD_IPCount search_key;
389 struct MHD_IPCount *found_key;
411 MHD_PANIC (
_(
"Failed to find previously-added IP address\n"));
413 found_key = (
struct MHD_IPCount *) *nodep;
415 if (0 == found_key->count)
417 MHD_PANIC (
_(
"Previously-added IP address had counter of zero\n"));
420 if (0 == --found_key->count)
451 res = gnutls_record_recv (connection->tls_session,
454 if ( (GNUTLS_E_AGAIN == res) ||
455 (GNUTLS_E_INTERRUPTED == res) )
459 if (GNUTLS_E_AGAIN == res)
470 connection->tls_read_ready =
false;
481 connection->tls_read_ready = ( ((size_t)res == i) &&
482 (0 != gnutls_record_check_pending (connection->tls_session)) );
505 res = gnutls_record_send (connection->tls_session,
508 if ( (GNUTLS_E_AGAIN == res) ||
509 (GNUTLS_E_INTERRUPTED == res) )
513 if (GNUTLS_E_AGAIN == res)
543 MHD_init_daemon_certificate (
struct MHD_Daemon *daemon)
549 #if GNUTLS_VERSION_MAJOR >= 3 550 if (
NULL != daemon->cert_callback)
552 gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
553 daemon->cert_callback);
556 if (
NULL != daemon->https_mem_trust)
558 cert.data = (
unsigned char *) daemon->https_mem_trust;
559 cert.size = strlen (daemon->https_mem_trust);
560 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred,
562 GNUTLS_X509_FMT_PEM) < 0)
566 "Bad trust certificate format\n");
572 if (daemon->have_dhparams)
574 gnutls_certificate_set_dh_params (daemon->x509_cred,
575 daemon->https_mem_dhparams);
578 if ( (
NULL != daemon->https_mem_cert) &&
579 (
NULL != daemon->https_mem_key) )
581 key.data = (
unsigned char *) daemon->https_mem_key;
582 key.size = strlen (daemon->https_mem_key);
583 cert.data = (
unsigned char *) daemon->https_mem_cert;
584 cert.size = strlen (daemon->https_mem_cert);
586 if (
NULL != daemon->https_key_password) {
587 #if GNUTLS_VERSION_NUMBER >= 0x030111 588 ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
592 daemon->https_key_password,
597 _(
"Failed to setup x509 certificate/key: pre 3.X.X version " \
598 "of GnuTLS does not support setting key password"));
604 ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
607 GNUTLS_X509_FMT_PEM);
611 "GnuTLS failed to setup x509 certificate/key: %s\n",
612 gnutls_strerror (ret));
616 #if GNUTLS_VERSION_MAJOR >= 3 617 if (
NULL != daemon->cert_callback)
622 "You need to specify a certificate and key location\n");
637 switch (daemon->cred_type)
639 case GNUTLS_CRD_CERTIFICATE:
641 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
642 return GNUTLS_E_MEMORY_ERROR;
643 return MHD_init_daemon_certificate (daemon);
647 _(
"Error: invalid credentials type %d specified.\n"),
680 fd_set *write_fd_set,
681 fd_set *except_fd_set,
693 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 707 urh_to_fdset (
struct MHD_UpgradeResponseHandle *urh,
712 unsigned int fd_setsize)
714 const MHD_socket conn_sckt = urh->connection->socket_fd;
722 if ( (urh->in_buffer_used < urh->in_buffer_size) &&
728 if ( (0 != urh->out_buffer_used) &&
737 ((0 != urh->in_buffer_size) ||
738 (0 != urh->out_buffer_size) ||
739 (0 != urh->out_buffer_used)))
747 if ( (urh->out_buffer_used < urh->out_buffer_size) &&
753 if ( (0 != urh->in_buffer_used) &&
762 ((0 != urh->out_buffer_size) ||
763 (0 != urh->in_buffer_size) ||
764 (0 != urh->in_buffer_used)))
785 urh_from_fdset (
struct MHD_UpgradeResponseHandle *urh,
790 const MHD_socket conn_sckt = urh->connection->socket_fd;
799 if (FD_ISSET (conn_sckt, rs))
801 if (FD_ISSET (conn_sckt, ws))
803 if (FD_ISSET (conn_sckt, es))
808 if (FD_ISSET (mhd_sckt, rs))
810 if (FD_ISSET (mhd_sckt, ws))
812 if (FD_ISSET (mhd_sckt, es))
828 urh_update_pollfd(
struct MHD_UpgradeResponseHandle *urh,
834 if (urh->in_buffer_used < urh->in_buffer_size)
835 p[0].events |= POLLIN;
836 if (0 != urh->out_buffer_used)
837 p[0].events |= POLLOUT;
842 ((0 != urh->in_buffer_size) ||
843 (0 != urh->out_buffer_size) ||
844 (0 != urh->out_buffer_used)))
845 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
847 if (urh->out_buffer_used < urh->out_buffer_size)
848 p[1].events |= POLLIN;
849 if (0 != urh->in_buffer_used)
850 p[1].events |= POLLOUT;
855 ((0 != urh->out_buffer_size) ||
856 (0 != urh->in_buffer_size) ||
857 (0 != urh->in_buffer_used)))
858 p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
869 urh_to_pollfd(
struct MHD_UpgradeResponseHandle *urh,
872 p[0].fd = urh->connection->socket_fd;
873 p[1].fd = urh->mhd.socket;
874 urh_update_pollfd(urh, p);
884 urh_from_pollfd(
struct MHD_UpgradeResponseHandle *urh,
891 if (0 != (p[0].revents & POLLIN))
893 if (0 != (p[0].revents & POLLOUT))
895 if (0 != (p[0].revents & POLLHUP))
897 if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
899 if (0 != (p[1].revents & POLLIN))
901 if (0 != (p[1].revents & POLLOUT))
903 if (0 != (p[1].revents & POLLHUP))
905 if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
929 fd_set *write_fd_set,
930 fd_set *except_fd_set,
932 unsigned int fd_setsize)
968 #ifdef MHD_POSIX_SOCKETS 981 #ifdef MHD_POSIX_SOCKETS 989 if ( (
NULL == except_fd_set) ||
1001 #ifdef MHD_WINSOCK_SOCKETS 1014 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 1016 struct MHD_UpgradeResponseHandle *urh;
1018 for (urh = daemon->urh_tail;
NULL != urh; urh = urh->prev)
1032 #ifdef HAVE_MESSAGES 1035 _(
"Maximum socket in select set: %d\n"),
1069 fd_set *read_fd_set,
1070 fd_set *write_fd_set,
1071 fd_set *except_fd_set,
1073 unsigned int fd_setsize)
1077 if ( (
NULL == daemon) ||
1078 (
NULL == read_fd_set) ||
1079 (
NULL == write_fd_set) ||
1084 if (
NULL == except_fd_set)
1086 #ifdef HAVE_MESSAGES 1088 _(
"MHD_get_fdset2() called with except_fd_set " 1089 "set to NULL. Such behavior is unsupported.\n"));
1092 except_fd_set = &es;
1095 #ifdef EPOLL_SUPPORT 1140 bool states_info_processed =
false;
1144 #ifdef HTTPS_SUPPORT 1145 if (con->tls_read_ready)
1155 states_info_processed =
true;
1164 states_info_processed =
true;
1174 if (!states_info_processed)
1221 #ifdef HTTPS_SUPPORT 1222 else if ( (con->tls_read_ready) &&
1231 #ifdef UPGRADE_SUPPORT 1242 struct MHD_UpgradeResponseHandle *urh = connection->urh;
1246 #ifdef HTTPS_SUPPORT 1250 gnutls_bye (connection->tls_session,
1259 connection->urh =
NULL;
1265 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 1275 process_urh (
struct MHD_UpgradeResponseHandle *urh)
1290 #ifdef HAVE_MESSAGES 1291 if (! urh->was_closed)
1294 _(
"Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
1297 urh->was_closed =
true;
1299 was_closed = urh->was_closed;
1304 if (0 < urh->in_buffer_used)
1306 #ifdef HAVE_MESSAGES 1309 " bytes of data received from remote side: application shut down socket\n"),
1319 if (0 != urh->out_buffer_size)
1322 urh->in_buffer_used = 0;
1326 urh->in_buffer_size = 0;
1328 connection->tls_read_ready =
false;
1348 (connection->tls_read_ready) ) &&
1349 (urh->in_buffer_used < urh->in_buffer_size) )
1354 buf_size = urh->in_buffer_size - urh->in_buffer_used;
1355 if (buf_size > SSIZE_MAX)
1356 buf_size = SSIZE_MAX;
1358 connection->tls_read_ready =
false;
1359 res = gnutls_record_recv (connection->tls_session,
1360 &urh->in_buffer[urh->in_buffer_used],
1364 if (GNUTLS_E_INTERRUPTED != res)
1367 if (GNUTLS_E_AGAIN != res)
1372 urh->in_buffer_size = 0;
1378 urh->in_buffer_used += res;
1379 if (buf_size > (
size_t)res)
1381 else if (0 < gnutls_record_check_pending (connection->tls_session))
1382 connection->tls_read_ready =
true;
1390 urh->in_buffer_size = 0;
1398 (urh->out_buffer_used < urh->out_buffer_size) )
1403 buf_size = urh->out_buffer_size - urh->out_buffer_used;
1408 &urh->out_buffer[urh->out_buffer_used],
1427 urh->out_buffer_size = 0;
1433 urh->out_buffer_used += res;
1434 if (buf_size > (
size_t)res)
1444 urh->out_buffer_size = 0;
1452 (urh->out_buffer_used > 0) )
1457 data_size = urh->out_buffer_used;
1458 if (data_size > SSIZE_MAX)
1459 data_size = SSIZE_MAX;
1461 res = gnutls_record_send (connection->tls_session,
1466 if (GNUTLS_E_INTERRUPTED != res)
1469 if (GNUTLS_E_INTERRUPTED != res)
1473 #ifdef HAVE_MESSAGES 1476 " bytes of data received from application: %s\n"),
1478 gnutls_strerror(res));
1481 urh->out_buffer_used = 0;
1483 urh->out_buffer_size = 0;
1490 const size_t next_out_buffer_used = urh->out_buffer_used - res;
1491 if (0 != next_out_buffer_used)
1493 memmove (urh->out_buffer,
1494 &urh->out_buffer[res],
1495 next_out_buffer_used);
1496 if (data_size > (
size_t)res)
1499 urh->out_buffer_used = next_out_buffer_used;
1501 if ( (0 == urh->out_buffer_used) &&
1509 urh->out_buffer_size = 0;
1518 (urh->in_buffer_used > 0) )
1523 data_size = urh->in_buffer_used;
1541 #ifdef HAVE_MESSAGES 1544 " bytes of data received from remote side: %s\n"),
1549 urh->in_buffer_used = 0;
1551 urh->in_buffer_size = 0;
1553 connection->tls_read_ready =
false;
1559 const size_t next_in_buffer_used = urh->in_buffer_used - res;
1560 if (0 != next_in_buffer_used)
1562 memmove (urh->in_buffer,
1563 &urh->in_buffer[res],
1564 next_in_buffer_used);
1565 if (data_size > (
size_t)res)
1568 urh->in_buffer_used = next_in_buffer_used;
1570 if ( (0 == urh->in_buffer_used) &&
1576 urh->in_buffer_size = 0;
1578 connection->tls_read_ready =
false;
1584 if ( (connection->tls_read_ready) &&
1585 (urh->in_buffer_used < urh->in_buffer_size) &&
1590 ( (0 != urh->out_buffer_size) ||
1591 (0 != urh->out_buffer_used) ) )
1594 #ifdef HAVE_MESSAGES 1595 if (0 < urh->out_buffer_used)
1598 " bytes of data received from application: daemon shut down\n"),
1602 urh->out_buffer_used = 0;
1606 urh->out_buffer_size = 0;
1613 #ifdef UPGRADE_SUPPORT 1625 #ifdef HTTPS_SUPPORT 1626 struct MHD_UpgradeResponseHandle *urh = con->urh;
1635 while ( (0 != urh->in_buffer_size) ||
1636 (0 != urh->out_buffer_size) ||
1637 (0 != urh->in_buffer_used) ||
1638 (0 != urh->out_buffer_used) )
1652 result = urh_to_fdset (urh,
1660 #ifdef HAVE_MESSAGES 1662 _(
"Error preparing select\n"));
1669 struct timeval* tvp;
1671 if ( (con->tls_read_ready) &&
1672 (urh->in_buffer_used < urh->in_buffer_size))
1694 #ifdef HAVE_MESSAGES 1696 _(
"Error during select (%d): `%s'\n"),
1702 urh_from_fdset (urh,
1717 p[0].fd = urh->connection->socket_fd;
1718 p[1].fd = urh->mhd.socket;
1720 while ( (0 != urh->in_buffer_size) ||
1721 (0 != urh->out_buffer_size) ||
1722 (0 != urh->in_buffer_used) ||
1723 (0 != urh->out_buffer_used) )
1727 urh_update_pollfd(urh, p);
1729 if ( (con->tls_read_ready) &&
1730 (urh->in_buffer_used < urh->in_buffer_size))
1735 if (MHD_sys_poll_ (p,
1743 #ifdef HAVE_MESSAGES 1745 _(
"Error during poll: `%s'\n"),
1750 urh_from_pollfd(urh, p);
1773 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
1784 struct timeval *tvp;
1790 #define EXTRA_SLOTS 1 1792 #define EXTRA_SLOTS 0 1795 struct pollfd p[1 + EXTRA_SLOTS];
1801 const bool use_poll = 0;
1803 bool was_suspended =
false;
1809 #ifdef UPGRADE_SUPPORT 1810 struct MHD_UpgradeResponseHandle *
const urh = con->urh;
1812 static const void *
const urh =
NULL;
1819 was_suspended =
true;
1828 #ifdef HAVE_MESSAGES 1830 _(
"Failed to add FD to fd_set\n"));
1844 #ifdef HAVE_MESSAGES 1846 _(
"Error during select (%d): `%s'\n"),
1856 p[0].events = POLLIN;
1857 p[0].fd = MHD_itc_r_fd_ (daemon->
itc);
1859 if (0 > MHD_sys_poll_ (p,
1865 #ifdef HAVE_MESSAGES 1867 _(
"Error during poll: `%s'\n"),
1874 MHD_itc_clear_ (daemon->
itc);
1883 was_suspended =
false;
1889 #ifdef HTTPS_SUPPORT
1890 || ( (con->tls_read_ready) &&
1901 if ( (
NULL == tvp) &&
1909 const time_t seconds_left = timeout - (now - con->
last_activity);
1911 tv.tv_sec = seconds_left;
1925 bool err_state =
false;
1959 if (MHD_ITC_IS_VALID_(daemon->
itc) )
1970 #ifdef HAVE_MESSAGES 1972 _(
"Failed to add FD to fd_set\n"));
1988 #ifdef HAVE_MESSAGES 1990 _(
"Error during select (%d): `%s'\n"),
1999 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
2000 (FD_ISSET (MHD_itc_r_fd_ (daemon->
itc),
2002 MHD_itc_clear_ (daemon->
itc);
2025 p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
2028 p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
2031 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
2039 if (MHD_ITC_IS_VALID_(daemon->
itc))
2041 p[1].events |= POLLIN;
2042 p[1].fd = MHD_itc_r_fd_ (daemon->
itc);
2047 if (MHD_sys_poll_ (p,
2053 (
NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
2057 #ifdef HAVE_MESSAGES 2059 _(
"Error during poll: `%s'\n"),
2067 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
2068 (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2069 MHD_itc_clear_ (daemon->
itc);
2073 0 != (p[0].revents & POLLIN),
2074 0 != (p[0].revents & POLLOUT),
2075 0 != (p[0].revents & (POLLERR | MHD_POLL_REVENTS_ERR_DISC))))
2079 #ifdef UPGRADE_SUPPORT 2080 if (MHD_CONNECTION_UPGRADE == con->
state)
2092 thread_main_connection_upgrade (con);
2096 con->urh->clean_ready =
true;
2104 return (MHD_THRD_RTRN_TYPE_) 0;
2111 #ifdef HAVE_MESSAGES 2113 _(
"Processing thread terminating. Closing connection\n"));
2138 return (MHD_THRD_RTRN_TYPE_) 0;
2169 #ifdef EPOLL_SUPPORT 2176 else if (i > (
size_t)ret)
2216 (MHD_resp_sender_sendfile == connection->resp_sender) )
2222 #ifndef HAVE_SENDFILE64 2230 #ifndef HAVE_SENDFILE64 2235 offset = (off_t) offsetu64;
2242 if ((uint64_t)OFF64_T_MAX < offsetu64)
2246 offset = (off64_t) offsetu64;
2247 ret = sendfile64 (connection->
socket_fd,
2256 #ifdef EPOLL_SUPPORT 2257 if (left > (uint64_t)ret)
2263 #ifdef EPOLL_SUPPORT 2281 connection->resp_sender = MHD_resp_sender_std;
2288 #ifdef EPOLL_SUPPORT 2295 else if (i > (
size_t)ret)
2352 const struct sockaddr *addr,
2390 #ifdef HAVE_MESSAGES 2392 _(
"Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
2393 (
int) client_socket,
2403 #ifdef MHD_socket_nosignal_ 2404 if (! MHD_socket_nosignal_ (client_socket))
2406 #ifdef HAVE_MESSAGES 2408 _(
"Failed to set SO_NOSIGPIPE on accepted socket: %s\n"),
2411 #ifndef MSG_NOSIGNAL 2422 #ifdef HAVE_MESSAGES 2425 _(
"Accepted connection on socket %d\n"),
2435 #ifdef HAVE_MESSAGES 2437 _(
"Server reached connection limit. Closing inbound connection.\n"));
2453 #ifdef HAVE_MESSAGES 2455 _(
"Connection rejected by application. Closing connection.\n"));
2471 #ifdef HAVE_MESSAGES 2473 "Error allocating memory: %s\n",
2486 #ifdef HAVE_MESSAGES 2488 _(
"Error allocating memory: %s\n"),
2503 if (
NULL == (connection->
addr = malloc (addrlen)))
2506 #ifdef HAVE_MESSAGES 2508 _(
"Error allocating memory: %s\n"),
2520 memcpy (connection->
addr,
2526 connection->
daemon = daemon;
2538 #ifdef HTTPS_SUPPORT 2539 connection->
recv_cls = &recv_tls_adapter;
2540 connection->
send_cls = &send_tls_adapter;
2543 gnutls_init (&connection->tls_session,
2545 gnutls_priority_set (connection->tls_session,
2546 daemon->priority_cache);
2547 switch (daemon->cred_type)
2550 case GNUTLS_CRD_CERTIFICATE:
2551 gnutls_credentials_set (connection->tls_session,
2552 GNUTLS_CRD_CERTIFICATE,
2556 #ifdef HAVE_MESSAGES 2557 MHD_DLOG (connection->
daemon,
2558 _(
"Failed to setup TLS credentials: unknown credential type %d\n"),
2565 free (connection->
addr);
2573 gnutls_transport_set_ptr (connection->tls_session,
2574 (gnutls_transport_ptr_t) connection);
2575 gnutls_transport_set_pull_function (connection->tls_session,
2577 gnutls_transport_set_push_function (connection->tls_session,
2580 if (daemon->https_mem_trust)
2581 gnutls_certificate_server_set_request (connection->tls_session,
2582 GNUTLS_CERT_REQUEST);
2618 #ifdef HAVE_MESSAGES 2620 "Failed to create a thread: %s\n",
2627 if ( (
MHD_YES == external_add) &&
2628 (MHD_ITC_IS_VALID_(daemon->
itc)) &&
2629 (! MHD_itc_activate_ (daemon->
itc,
"n")) )
2631 #ifdef HAVE_MESSAGES 2633 _(
"Failed to signal new connection via inter-thread communication channel."));
2636 #ifdef EPOLL_SUPPORT 2641 struct epoll_event event;
2643 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2644 event.data.ptr = connection;
2645 if (0 != epoll_ctl (daemon->epoll_fd,
2651 #ifdef HAVE_MESSAGES 2653 _(
"Call to epoll_ctl failed: %s\n"),
2665 daemon->eready_tail,
2694 free (connection->
addr);
2742 #ifdef EPOLL_SUPPORT 2748 daemon->eready_tail,
2754 if (0 != epoll_ctl (daemon->epoll_fd,
2758 MHD_PANIC (
_(
"Failed to remove FD from epoll set\n"));
2805 MHD_PANIC (
_(
"Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2806 #ifdef UPGRADE_SUPPORT 2807 if (
NULL != connection->urh)
2809 #ifdef HAVE_MESSAGES 2811 _(
"Error: connection scheduled for \"upgrade\" cannot be suspended"));
2833 daemon = connection->
daemon;
2835 MHD_PANIC (
_(
"Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2840 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
2841 (! MHD_itc_activate_ (daemon->
itc,
"r")) )
2843 #ifdef HAVE_MESSAGES 2845 _(
"Failed to signal resume via inter-thread communication channel."));
2877 while (
NULL != (pos = prev))
2879 #ifdef UPGRADE_SUPPORT 2880 struct MHD_UpgradeResponseHandle *
const urh = pos->urh;
2882 static const void *
const urh =
NULL;
2886 #ifdef UPGRADE_SUPPORT
2887 || ( (
NULL != urh) &&
2888 ( (! urh->was_closed) ||
2889 (! urh->clean_ready) ) )
2919 #ifdef EPOLL_SUPPORT 2923 MHD_PANIC (
"Resumed connection was already in EREADY set\n");
2927 daemon->eready_tail,
2935 #ifdef UPGRADE_SUPPORT 2950 if ( (used_thr_p_c) &&
2953 if (! MHD_itc_activate_(daemon->
itc,
2956 #ifdef HAVE_MESSAGES 2958 _(
"Failed to signal resume of connection via inter-thread communication channel."));
2998 const struct sockaddr *addr,
3004 #ifdef HAVE_MESSAGES 3006 _(
"Failed to set nonblocking mode on new client socket: %s\n"),
3017 #ifdef HAVE_MESSAGES 3019 _(
"Failed to set noninheritable mode on new client socket.\n"));
3049 struct sockaddr_in6 addrstorage;
3051 struct sockaddr_in addrstorage;
3053 struct sockaddr *addr = (
struct sockaddr *) &addrstorage;
3059 addrlen =
sizeof (addrstorage);
3062 sizeof (addrstorage));
3089 #ifdef HAVE_MESSAGES 3092 _(
"Error accepting connection: %s\n"),
3104 #ifdef HAVE_MESSAGES 3109 _(
"Hit process or system resource limit at FIRST connection. This is really bad as there is no sane way to proceed. Will try busy waiting for system resources to become magically available.\n"));
3115 #ifdef HAVE_MESSAGES 3117 _(
"Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
3124 #if !defined(USE_ACCEPT4) || !defined(HAVE_SOCK_NONBLOCK) 3127 #ifdef HAVE_MESSAGES 3129 _(
"Failed to set nonblocking mode on incoming connection socket: %s\n"),
3136 #if !defined(USE_ACCEPT4) || !defined(SOCK_CLOEXEC) 3139 #ifdef HAVE_MESSAGES 3141 _(
"Failed to set noninheritable mode on incoming connection socket.\n"));
3145 #ifdef HAVE_MESSAGES 3148 _(
"Accepted connection on socket %d\n"),
3186 (! MHD_join_thread_ (pos->
pid)) )
3188 #ifdef UPGRADE_SUPPORT 3189 cleanup_upgraded_connection (pos);
3192 #ifdef HTTPS_SUPPORT 3193 if (
NULL != pos->tls_session)
3194 gnutls_deinit (pos->tls_session);
3208 #ifdef EPOLL_SUPPORT 3214 daemon->eready_tail,
3218 if ( (-1 != daemon->epoll_fd) &&
3227 if (0 != epoll_ctl (daemon->epoll_fd,
3231 MHD_PANIC (
_(
"Failed to remove FD from epoll set\n"));
3273 time_t earliest_deadline;
3280 #ifdef HAVE_MESSAGES 3282 _(
"Illegal call to MHD_get_timeout\n"));
3294 #ifdef EPOLL_SUPPORT 3296 ((
NULL != daemon->eready_head)
3297 #
if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
3298 || (
NULL != daemon->eready_urh_head)
3308 have_timeout =
false;
3309 earliest_deadline = 0;
3314 if ( (! have_timeout) ||
3317 have_timeout =
true;
3322 if ( (
NULL != pos) &&
3325 if ( (! have_timeout) ||
3328 have_timeout =
true;
3334 if (earliest_deadline < now)
3338 const time_t second_left = earliest_deadline - now;
3342 *timeout = 1000LL * second_left;
3360 const fd_set *read_fd_set,
3361 const fd_set *write_fd_set,
3362 const fd_set *except_fd_set)
3367 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3368 struct MHD_UpgradeResponseHandle *urh;
3369 struct MHD_UpgradeResponseHandle *urhn;
3378 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
3379 (FD_ISSET (MHD_itc_r_fd_ (daemon->
itc),
3381 MHD_itc_clear_ (daemon->
itc);
3394 while (
NULL != (pos = prev))
3410 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3412 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
3416 urh_from_fdset (urh,
3423 if ( (0 == urh->in_buffer_size) &&
3424 (0 == urh->out_buffer_size) &&
3425 (0 == urh->in_buffer_used) &&
3426 (0 == urh->out_buffer_used) )
3429 urh->clean_ready =
true;
3464 const fd_set *read_fd_set,
3465 const fd_set *write_fd_set,
3466 const fd_set *except_fd_set)
3472 if (
NULL == read_fd_set ||
NULL == write_fd_set)
3474 if (
NULL == except_fd_set)
3476 #ifdef HAVE_MESSAGES 3478 _(
"MHD_run_from_select() called with except_fd_set " 3479 "set to NULL. Such behavior is deprecated.\n"));
3482 except_fd_set = &es;
3486 #ifdef EPOLL_SUPPORT 3488 ret = MHD_epoll (daemon,
MHD_NO);
3501 write_fd_set, except_fd_set);
3522 struct timeval timeout;
3529 timeout.tv_usec = 0;
3553 #ifdef HAVE_MESSAGES 3555 _(
"Could not obtain daemon fdsets"));
3570 #ifdef HAVE_MESSAGES 3572 _(
"Could not add listen socket to fdset"));
3577 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
3583 #if defined(MHD_WINSOCK_SOCKETS) 3598 #ifdef HAVE_MESSAGES 3600 _(
"Could not add control inter-thread communication channel FD to fdset"));
3603 #if defined(MHD_WINSOCK_SOCKETS) 3615 (MHD_ITC_IS_VALID_(daemon->
itc)) &&
3627 timeout.tv_usec = 0;
3635 timeout.tv_usec = (ltimeout % 1000) * 1000;
3654 #ifdef HAVE_MESSAGES 3656 _(
"select failed: %s\n"),
3683 unsigned int num_connections;
3686 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3687 struct MHD_UpgradeResponseHandle *urh;
3688 struct MHD_UpgradeResponseHandle *urhn;
3696 num_connections = 0;
3699 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3700 for (urh = daemon->urh_head;
NULL != urh; urh = urh->next)
3701 num_connections += 2;
3707 unsigned int poll_server;
3713 p =
MHD_calloc_ ((2 + num_connections),
sizeof (
struct pollfd));
3716 #ifdef HAVE_MESSAGES 3718 _(
"Error allocating memory: %s\n"),
3731 p[poll_server].fd = ls;
3732 p[poll_server].events = POLLIN;
3733 p[poll_server].revents = 0;
3734 poll_listen = (int) poll_server;
3738 if (MHD_ITC_IS_VALID_(daemon->
itc))
3740 p[poll_server].fd = MHD_itc_r_fd_ (daemon->
itc);
3741 p[poll_server].events = POLLIN;
3742 p[poll_server].revents = 0;
3743 poll_itc_idx = (int) poll_server;
3753 timeout = (ltimeout > INT_MAX) ? INT_MAX : (
int) ltimeout;
3762 p[poll_server+i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
3765 p[poll_server+i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
3768 p[poll_server+i].events |= MHD_POLL_EVENTS_ERR_DISC;
3776 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3777 for (urh = daemon->urh_tail;
NULL != urh; urh = urh->prev)
3779 urh_to_pollfd(urh, &(p[poll_server+i]));
3783 if (0 == poll_server + num_connections)
3788 if (MHD_sys_poll_(p,
3789 poll_server + num_connections,
3798 #ifdef HAVE_MESSAGES 3800 _(
"poll failed: %s\n"),
3813 if ( (-1 != poll_itc_idx) &&
3814 (0 != (p[poll_itc_idx].revents & POLLIN)) )
3815 MHD_itc_clear_ (daemon->
itc);
3825 while (
NULL != (pos = prev))
3829 if (i >= num_connections)
3831 if (p[poll_server+i].fd != pos->
socket_fd)
3834 0 != (p[poll_server+i].revents & POLLIN),
3835 0 != (p[poll_server+i].revents & POLLOUT),
3836 0 != (p[poll_server+i].revents & MHD_POLL_REVENTS_ERR_DISC));
3839 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3840 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
3842 if (i >= num_connections)
3849 if ((p[poll_server+i].fd != urh->connection->socket_fd) ||
3850 (p[poll_server+i+1].fd != urh->mhd.socket))
3852 urh_from_pollfd(urh, &(p[poll_server+i]));
3856 if ( (0 == urh->in_buffer_size) &&
3857 (0 == urh->out_buffer_size) &&
3858 (0 == urh->in_buffer_used) &&
3859 (0 == urh->out_buffer_used) )
3864 urh->clean_ready =
true;
3874 if ( (-1 != poll_listen) &&
3875 (0 != (p[poll_listen].revents & POLLIN)) )
3892 MHD_poll_listen_socket (
struct MHD_Daemon *daemon,
3897 unsigned int poll_count;
3912 p[poll_count].fd = ls;
3913 p[poll_count].events = POLLIN;
3914 p[poll_count].revents = 0;
3915 poll_listen = poll_count;
3918 if (MHD_ITC_IS_VALID_(daemon->
itc))
3920 p[poll_count].fd = MHD_itc_r_fd_ (daemon->
itc);
3921 p[poll_count].events = POLLIN;
3922 p[poll_count].revents = 0;
3923 poll_itc_idx = poll_count;
3934 if (0 == poll_count)
3936 if (MHD_sys_poll_(p,
3944 #ifdef HAVE_MESSAGES 3946 _(
"poll failed: %s\n"),
3951 if ( (-1 != poll_itc_idx) &&
3952 (0 != (p[poll_itc_idx].revents & POLLIN)) )
3953 MHD_itc_clear_ (daemon->
itc);
3958 if ( (-1 != poll_listen) &&
3959 (0 != (p[poll_listen].revents & POLLIN)) )
3981 return MHD_poll_all (daemon,
3983 return MHD_poll_listen_socket (daemon,
3991 #ifdef EPOLL_SUPPORT 4001 #define MAX_EVENTS 128 4004 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4014 is_urh_ready(
struct MHD_UpgradeResponseHandle *
const urh)
4016 const struct MHD_Connection *
const connection = urh->connection;
4018 if ( (0 == urh->in_buffer_size) &&
4019 (0 == urh->out_buffer_size) &&
4020 (0 == urh->in_buffer_used) &&
4021 (0 == urh->out_buffer_used) )
4028 (connection->tls_read_ready) ) &&
4029 (urh->in_buffer_used < urh->in_buffer_size) )
4033 (urh->out_buffer_used < urh->out_buffer_size) )
4037 (urh->out_buffer_used > 0) )
4041 (urh->in_buffer_used > 0) )
4056 run_epoll_for_upgrade (
struct MHD_Daemon *daemon)
4058 struct epoll_event events[MAX_EVENTS];
4060 struct MHD_UpgradeResponseHandle * pos;
4061 struct MHD_UpgradeResponseHandle * prev;
4063 num_events = MAX_EVENTS;
4064 while (MAX_EVENTS == num_events)
4068 num_events = epoll_wait (daemon->epoll_upgrade_fd,
4072 if (-1 == num_events)
4077 #ifdef HAVE_MESSAGES 4079 _(
"Call to epoll_wait failed: %s\n"),
4084 for (i = 0; i < (
unsigned int) num_events; i++)
4086 struct UpgradeEpollHandle *
const ueh = events[i].data.ptr;
4087 struct MHD_UpgradeResponseHandle *
const urh = ueh->urh;
4088 bool new_err_state =
false;
4090 if (urh->clean_ready)
4094 if (0 != (events[i].events & EPOLLIN))
4096 if (0 != (events[i].events & EPOLLOUT))
4098 if (0 != (events[i].events & EPOLLHUP))
4102 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
4108 new_err_state =
true;
4111 if (! urh->in_eready_list)
4113 if (new_err_state ||
4117 daemon->eready_urh_tail,
4119 urh->in_eready_list =
true;
4124 prev = daemon->eready_urh_tail;
4125 while (
NULL != (pos = prev))
4129 if (! is_urh_ready(pos))
4132 daemon->eready_urh_tail,
4134 pos->in_eready_list =
false;
4137 if ( (0 == pos->in_buffer_size) &&
4138 (0 == pos->out_buffer_size) &&
4139 (0 == pos->in_buffer_used) &&
4140 (0 == pos->out_buffer_used) )
4143 pos->clean_ready =
true;
4159 static const char *
const epoll_itc_marker =
"itc_marker";
4173 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4174 static const char *
const upgrade_marker =
"upgrade_ptr";
4178 struct epoll_event events[MAX_EVENTS];
4179 struct epoll_event event;
4185 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4186 int run_upgraded =
MHD_NO;
4189 if (-1 == daemon->epoll_fd)
4196 (! daemon->listen_socket_in_epoll) &&
4199 event.events = EPOLLIN;
4200 event.data.ptr = daemon;
4201 if (0 != epoll_ctl (daemon->epoll_fd,
4206 #ifdef HAVE_MESSAGES 4208 _(
"Call to epoll_ctl failed: %s\n"),
4213 daemon->listen_socket_in_epoll =
true;
4216 (daemon->listen_socket_in_epoll) )
4218 if (0 != epoll_ctl (daemon->epoll_fd,
4222 MHD_PANIC (
"Failed to remove listen FD from epoll set\n");
4223 daemon->listen_socket_in_epoll =
false;
4226 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4227 if ( (! daemon->upgrade_fd_in_epoll) &&
4228 (-1 != daemon->epoll_upgrade_fd) )
4230 event.events = EPOLLIN | EPOLLOUT;
4231 event.data.ptr = (
void *) upgrade_marker;
4232 if (0 != epoll_ctl (daemon->epoll_fd,
4234 daemon->epoll_upgrade_fd,
4237 #ifdef HAVE_MESSAGES 4239 _(
"Call to epoll_ctl failed: %s\n"),
4244 daemon->upgrade_fd_in_epoll =
true;
4247 if ( (daemon->listen_socket_in_epoll) &&
4254 if (0 != epoll_ctl (daemon->epoll_fd,
4258 MHD_PANIC (
_(
"Failed to remove listen FD from epoll set\n"));
4259 daemon->listen_socket_in_epoll =
false;
4272 timeout_ms = INT_MAX;
4274 timeout_ms = (int) timeout_ll;
4291 num_events = MAX_EVENTS;
4292 while (MAX_EVENTS == num_events)
4295 num_events = epoll_wait (daemon->epoll_fd,
4299 if (-1 == num_events)
4304 #ifdef HAVE_MESSAGES 4306 _(
"Call to epoll_wait failed: %s\n"),
4311 for (i=0;i<(
unsigned int) num_events;i++)
4315 if (
NULL == events[i].data.ptr)
4317 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4318 if (upgrade_marker == events[i].data.ptr)
4326 if (epoll_itc_marker == events[i].data.ptr)
4330 MHD_itc_clear_ (daemon->
itc);
4333 if (daemon == events[i].data.ptr)
4337 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
4339 unsigned int series_length = 0;
4345 (series_length < 10) &&
4355 pos = events[i].data.ptr;
4357 if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
4363 daemon->eready_tail,
4370 if (0 != (events[i].events & EPOLLIN))
4378 daemon->eready_tail,
4383 if (0 != (events[i].events & EPOLLOUT))
4390 daemon->eready_tail,
4399 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4401 run_epoll_for_upgrade (daemon);
4405 prev = daemon->eready_tail;
4406 while (
NULL != (pos = prev))
4423 daemon->eready_tail,
4439 while (
NULL != (pos = prev))
4449 while (
NULL != (pos = prev))
4491 #ifdef EPOLL_SUPPORT 4494 MHD_epoll (daemon,
MHD_NO);
4558 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
4567 #ifdef EPOLL_SUPPORT 4581 return (MHD_THRD_RTRN_TYPE_)0;
4678 #ifdef HAVE_MESSAGES 4680 "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC\n");
4689 #ifdef EPOLL_SUPPORT 4694 if (0 != epoll_ctl (daemon->
worker_pool[i].epoll_fd,
4698 MHD_PANIC (
_(
"Failed to remove listen FD from epoll set\n"));
4699 daemon->
worker_pool[i].listen_socket_in_epoll =
false;
4706 MHD_PANIC (
_(
"Failed to signal quiesce via inter-thread communication channel"));
4710 #ifdef EPOLL_SUPPORT 4712 (-1 != daemon->epoll_fd) &&
4713 (daemon->listen_socket_in_epoll) )
4715 if (0 != epoll_ctl (daemon->epoll_fd,
4719 MHD_PANIC (
"Failed to remove listen FD from epoll set\n");
4720 daemon->listen_socket_in_epoll =
false;
4723 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
4724 (! MHD_itc_activate_ (daemon->
itc,
"q")) )
4725 MHD_PANIC (
_(
"failed to signal quiesce via inter-thread communication channel"));
4753 const struct sockaddr **servaddr,
4767 const struct sockaddr **servaddr,
4773 va_start (ap, servaddr);
4792 const struct sockaddr **servaddr,
4799 #ifdef HTTPS_SUPPORT 4825 #ifdef HAVE_MESSAGES 4827 _(
"Warning: Too large timeout value, ignored.\n"));
4851 *servaddr = va_arg (ap,
4852 const struct sockaddr *);
4865 #ifdef HAVE_MESSAGES 4867 _(
"Warning: Zero size, specified for thread pool size, is ignored. " 4868 "Thread pool is not used.\n"));
4873 #ifdef HAVE_MESSAGES 4875 _(
"Warning: \"1\", specified for thread pool size, is ignored. " 4876 "Thread pool is not used.\n"));
4882 #ifdef HAVE_MESSAGES 4884 _(
"Specified thread pool size (%u) too big\n"),
4893 #ifdef HAVE_MESSAGES 4895 _(
"MHD_OPTION_THREAD_POOL_SIZE option is specified but " 4896 "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
4902 #ifdef HAVE_MESSAGES 4904 _(
"Both MHD_OPTION_THREAD_POOL_SIZE option and " 4905 "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
4911 #ifdef HTTPS_SUPPORT 4914 daemon->https_mem_key = va_arg (ap,
4916 #ifdef HAVE_MESSAGES 4919 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4925 daemon->https_key_password = va_arg (ap,
4927 #ifdef HAVE_MESSAGES 4930 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4936 daemon->https_mem_cert = va_arg (ap,
4938 #ifdef HAVE_MESSAGES 4941 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4947 daemon->https_mem_trust = va_arg (ap,
4949 #ifdef HAVE_MESSAGES 4952 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4957 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
4963 const char *arg = va_arg (ap,
4965 gnutls_datum_t dhpar;
4967 if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
4969 #ifdef HAVE_MESSAGES 4971 _(
"Error initializing DH parameters\n"));
4975 dhpar.data = (
unsigned char *) arg;
4976 dhpar.size = strlen (arg);
4977 if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
4979 GNUTLS_X509_FMT_PEM) < 0)
4981 #ifdef HAVE_MESSAGES 4983 _(
"Bad Diffie-Hellman parameters format\n"));
4985 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
4988 daemon->have_dhparams =
true;
4992 #ifdef HAVE_MESSAGES 4994 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
5003 gnutls_priority_deinit (daemon->priority_cache);
5004 ret = gnutls_priority_init (&daemon->priority_cache,
5005 pstr = va_arg (ap,
const char*),
5007 if (GNUTLS_E_SUCCESS != ret)
5009 #ifdef HAVE_MESSAGES 5011 _(
"Setting priorities to `%s' failed: %s\n"),
5013 gnutls_strerror (ret));
5015 daemon->priority_cache =
NULL;
5021 #if GNUTLS_VERSION_MAJOR < 3 5022 #ifdef HAVE_MESSAGES 5024 _(
"MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n"));
5029 daemon->cert_callback = va_arg (ap,
5030 gnutls_certificate_retrieve_function2 *);
5034 #ifdef DAUTH_SUPPORT 5036 daemon->digest_auth_rand_size = va_arg (ap,
5038 daemon->digest_auth_random = va_arg (ap,
5042 daemon->nonce_nc_size = va_arg (ap,
5049 #ifdef HAVE_MESSAGES 5051 _(
"MHD_OPTION_LISTEN_SOCKET specified for daemon " 5052 "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
5061 #ifdef HAVE_MESSAGES 5062 daemon->custom_error_log = va_arg (ap,
5064 daemon->custom_error_log_cls = va_arg (ap,
5079 daemon->fastopen_queue_size = va_arg (ap,
5085 unsigned int) ? 1 : -1;
5093 #ifdef HAVE_MESSAGES 5098 _(
"Flag MHD_USE_PEDANTIC_CHECKS is ignored because " 5099 "another behavior is specified by MHD_OPTION_STRICT_CLIENT.\n"));
5117 (
size_t) oa[i].
value,
5133 (
unsigned int) oa[i].value,
5138 #ifdef HTTPS_SUPPORT 5143 (gnutls_credentials_type_t) oa[i].value,
5192 (
void *) oa[i].value,
5202 (
size_t) oa[i].value,
5220 #ifdef HAVE_MESSAGES 5226 _(
"MHD HTTPS option %d passed to MHD compiled without HTTPS support\n"),
5232 _(
"Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n"),
5243 #ifdef EPOLL_SUPPORT 5249 #ifdef USE_EPOLL_CREATE1 5250 fd = epoll_create1 (EPOLL_CLOEXEC);
5252 fd = epoll_create (MAX_EVENTS);
5256 #ifdef HAVE_MESSAGES 5258 _(
"Call to epoll_create1 failed: %s\n"),
5263 #if !defined(USE_EPOLL_CREATE1) 5266 #ifdef HAVE_MESSAGES 5268 _(
"Failed to set noninheritable mode on epoll FD.\n"));
5286 setup_epoll_to_listen (
struct MHD_Daemon *daemon)
5288 struct epoll_event event;
5291 daemon->epoll_fd = setup_epoll_fd (daemon);
5292 if (-1 == daemon->epoll_fd)
5294 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 5297 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
5305 event.events = EPOLLIN;
5306 event.data.ptr = daemon;
5307 if (0 != epoll_ctl (daemon->epoll_fd,
5312 #ifdef HAVE_MESSAGES 5314 _(
"Call to epoll_ctl failed: %s\n"),
5319 daemon->listen_socket_in_epoll =
true;
5320 if (MHD_ITC_IS_VALID_(daemon->
itc))
5322 event.events = EPOLLIN;
5323 event.data.ptr = (
void *) epoll_itc_marker;
5324 if (0 != epoll_ctl (daemon->epoll_fd,
5326 MHD_itc_r_fd_ (daemon->
itc),
5329 #ifdef HAVE_MESSAGES 5331 _(
"Call to epoll_ctl failed: %s\n"),
5371 struct sockaddr_in servaddr4;
5373 struct sockaddr_in6 servaddr6;
5375 const struct sockaddr *servaddr =
NULL;
5391 #ifndef EPOLL_SUPPORT 5395 #ifndef HTTPS_SUPPORT 5399 #ifndef TCP_FASTOPEN 5405 #ifdef UPGRADE_SUPPORT 5415 if ( ((0 != (*pflags & MHD_USE_POLL)) && (0 != (*pflags & MHD_USE_EPOLL))) ||
5417 ((0 != (*pflags & MHD_USE_POLL)) &&
5419 ((0 != (*pflags &
MHD_USE_AUTO)) && (0 != (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)))) )
5422 if (0 != (*pflags & MHD_USE_AUTO))
5436 #if defined(EPOLL_SUPPORT) 5438 #elif defined(HAVE_POLL) 5447 #if defined(EPOLL_SUPPORT) 5457 #ifdef EPOLL_SUPPORT 5458 daemon->epoll_fd = -1;
5459 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 5460 daemon->epoll_upgrade_fd = -1;
5464 #ifdef HTTPS_SUPPORT 5465 daemon->priority_cache =
NULL;
5466 if (0 != (*pflags & MHD_USE_TLS))
5468 gnutls_priority_init (&daemon->priority_cache,
5478 daemon->
port = port;
5489 MHD_itc_set_invalid_ (daemon->
itc);
5495 #ifdef HAVE_MESSAGES 5497 daemon->custom_error_log_cls = stderr;
5502 #ifdef HAVE_MESSAGES 5504 _(
"Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with " 5505 "MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD " 5506 "was added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"));
5514 #ifdef HAVE_LISTEN_SHUTDOWN 5519 #ifdef DAUTH_SUPPORT 5520 daemon->digest_auth_rand_size = 0;
5521 daemon->digest_auth_random =
NULL;
5522 daemon->nonce_nc_size = 4;
5524 #ifdef HTTPS_SUPPORT 5525 if (0 != (*pflags & MHD_USE_TLS))
5527 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
5536 #ifdef HTTPS_SUPPORT 5537 if ( (0 != (*pflags & MHD_USE_TLS)) &&
5538 (
NULL != daemon->priority_cache) )
5539 gnutls_priority_deinit (daemon->priority_cache);
5547 if (! MHD_itc_init_ (daemon->
itc))
5549 #ifdef HAVE_MESSAGES 5551 _(
"Failed to create inter-thread communication channel: %s\n"),
5552 MHD_itc_last_strerror_ ());
5554 #ifdef HTTPS_SUPPORT 5555 if (
NULL != daemon->priority_cache)
5556 gnutls_priority_deinit (daemon->priority_cache);
5561 if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
5565 #ifdef HAVE_MESSAGES 5567 _(
"file descriptor for inter-thread communication channel exceeds maximum value\n"));
5570 #ifdef HTTPS_SUPPORT 5571 if (
NULL != daemon->priority_cache)
5572 gnutls_priority_deinit (daemon->priority_cache);
5579 #ifdef DAUTH_SUPPORT 5580 if (daemon->nonce_nc_size > 0)
5582 if ( ( (
size_t) (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc))) /
5583 sizeof(
struct MHD_NonceNc) != daemon->nonce_nc_size)
5585 #ifdef HAVE_MESSAGES 5587 _(
"Specified value for NC_SIZE too large\n"));
5589 #ifdef HTTPS_SUPPORT 5590 if (0 != (*pflags & MHD_USE_TLS))
5591 gnutls_priority_deinit (daemon->priority_cache);
5596 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc));
5597 if (
NULL == daemon->nnc)
5599 #ifdef HAVE_MESSAGES 5601 _(
"Failed to allocate memory for nonce-nc map: %s\n"),
5604 #ifdef HTTPS_SUPPORT 5605 if (0 != (*pflags & MHD_USE_TLS))
5606 gnutls_priority_deinit (daemon->priority_cache);
5613 if (! MHD_mutex_init_ (&daemon->nnc_lock))
5615 #ifdef HAVE_MESSAGES 5617 _(
"MHD failed to initialize nonce-nc mutex\n"));
5619 #ifdef HTTPS_SUPPORT 5620 if (0 != (*pflags & MHD_USE_TLS))
5621 gnutls_priority_deinit (daemon->priority_cache);
5630 if ( (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
5633 #ifdef HAVE_MESSAGES 5635 _(
"MHD thread pooling only works with MHD_USE_INTERNAL_POLLING_THREAD\n"));
5640 #ifdef __SYMBIAN32__ 5641 if (0 != (*pflags & (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_THREAD_PER_CONNECTION)))
5643 #ifdef HAVE_MESSAGES 5645 _(
"Threaded operations are not supported on Symbian.\n"));
5657 #ifdef HAVE_MESSAGES 5659 _(
"Failed to create socket for listening: %s\n"),
5673 if (0 > setsockopt (listen_fd,
5676 (
void*)&on,
sizeof (on)))
5678 #ifdef HAVE_MESSAGES 5680 _(
"setsockopt failed: %s\n"),
5692 if (0 > setsockopt (listen_fd,
5695 (
void*)&on,
sizeof (on)))
5697 #ifdef HAVE_MESSAGES 5699 _(
"setsockopt failed: %s\n"),
5709 #if defined(_WIN32) || defined(SO_REUSEPORT) 5710 if (0 > setsockopt (listen_fd,
5720 #ifdef HAVE_MESSAGES 5722 _(
"setsockopt failed: %s\n"),
5730 #ifdef HAVE_MESSAGES 5732 _(
"Cannot allow listening address reuse: SO_REUSEPORT not defined\n"));
5745 #if (defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE)) || \ 5746 (defined(__sun) && defined(SO_EXCLBIND)) 5747 if (0 > setsockopt (listen_fd,
5749 #ifdef SO_EXCLUSIVEADDRUSE
5750 SO_EXCLUSIVEADDRUSE,
5757 #ifdef HAVE_MESSAGES 5759 _(
"setsockopt failed: %s\n"),
5764 #elif defined(_WIN32) 5765 #ifdef HAVE_MESSAGES 5767 _(
"Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n"));
5775 if (0 != (*pflags & MHD_USE_IPv6))
5776 addrlen =
sizeof (
struct sockaddr_in6);
5779 addrlen =
sizeof (
struct sockaddr_in);
5780 if (
NULL == servaddr)
5783 if (0 != (*pflags & MHD_USE_IPv6))
5787 sizeof (
struct sockaddr_in6));
5788 servaddr6.sin6_family = AF_INET6;
5789 servaddr6.sin6_port = htons (port);
5790 #if HAVE_SOCKADDR_IN_SIN_LEN 5791 servaddr6.sin6_len =
sizeof (
struct sockaddr_in6);
5793 servaddr = (
struct sockaddr *) &servaddr6;
5800 sizeof (
struct sockaddr_in));
5801 servaddr4.sin_family = AF_INET;
5802 servaddr4.sin_port = htons (port);
5803 #if HAVE_SOCKADDR_IN_SIN_LEN 5804 servaddr4.sin_len =
sizeof (
struct sockaddr_in);
5806 servaddr = (
struct sockaddr *) &servaddr4;
5811 if (0 != (*pflags & MHD_USE_IPv6))
5821 if (0 > setsockopt (listen_fd,
5822 IPPROTO_IPV6, IPV6_V6ONLY,
5823 (
const void *) &v6_only,
5826 #ifdef HAVE_MESSAGES 5828 _(
"setsockopt failed: %s\n"),
5835 if (-1 == bind (listen_fd, servaddr, addrlen))
5837 #ifdef HAVE_MESSAGES 5839 _(
"Failed to bind to port %u: %s\n"),
5840 (
unsigned int) port,
5847 if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
5849 if (0 == daemon->fastopen_queue_size)
5850 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
5851 if (0 != setsockopt (listen_fd,
5854 &daemon->fastopen_queue_size,
5855 sizeof (daemon->fastopen_queue_size)))
5857 #ifdef HAVE_MESSAGES 5859 _(
"setsockopt failed: %s\n"),
5865 if (listen (listen_fd,
5868 #ifdef HAVE_MESSAGES 5870 _(
"Failed to listen for connections: %s\n"),
5885 #ifdef HAVE_MESSAGES 5887 _(
"Failed to set nonblocking mode on listening socket: %s\n"),
5890 if (0 != (*pflags & MHD_USE_EPOLL) ||
5903 (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)) ) )
5905 #ifdef HAVE_MESSAGES 5907 _(
"Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
5915 #ifdef EPOLL_SUPPORT 5916 if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
5918 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
5920 if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
5922 #ifdef HAVE_MESSAGES 5924 _(
"Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
5928 if (
MHD_YES != setup_epoll_to_listen (daemon))
5935 #ifdef HAVE_MESSAGES 5937 _(
"MHD failed to initialize IP connection limit mutex\n"));
5945 #ifdef HAVE_MESSAGES 5947 _(
"MHD failed to initialize IP connection limit mutex\n"));
5955 #ifdef HTTPS_SUPPORT 5957 if ( (0 != (*pflags & MHD_USE_TLS)) &&
5958 (0 != MHD_TLS_init (daemon)) )
5960 #ifdef HAVE_MESSAGES 5962 _(
"Failed to initialize TLS support\n"));
5971 if ( ( (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
5973 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) &&
5975 (*pflags & MHD_USE_THREAD_PER_CONNECTION) ?
5976 "MHD-listen" :
"MHD-single",
5981 #ifdef HAVE_MESSAGES 5983 _(
"Failed to create listen thread: %s\n"),
5993 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
6017 memcpy (d, daemon,
sizeof (
struct MHD_Daemon));
6025 if (0 != (*pflags & MHD_USE_ITC))
6027 if (! MHD_itc_init_ (d->
itc))
6029 #ifdef HAVE_MESSAGES 6031 _(
"Failed to create worker inter-thread communication channel: %s\n"),
6032 MHD_itc_last_strerror_() );
6036 if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
6040 #ifdef HAVE_MESSAGES 6042 _(
"File descriptor for worker inter-thread communication channel exceeds maximum value\n"));
6049 MHD_itc_set_invalid_ (d->
itc);
6055 if (i < leftover_conns)
6057 #ifdef EPOLL_SUPPORT 6058 if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
6059 (
MHD_YES != setup_epoll_to_listen (d)) )
6065 #ifdef HAVE_MESSAGES 6067 _(
"MHD failed to initialize cleanup connection mutex\n"));
6079 #ifdef HAVE_MESSAGES 6081 _(
"Failed to create pool thread: %s\n"),
6091 #ifdef HTTPS_SUPPORT 6094 daemon->https_key_password =
NULL;
6126 #ifdef EPOLL_SUPPORT 6127 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 6128 if (daemon->upgrade_fd_in_epoll)
6130 if (0 != epoll_ctl (daemon->epoll_fd,
6132 daemon->epoll_upgrade_fd,
6134 MHD_PANIC (
_(
"Failed to remove FD from epoll set\n"));
6135 daemon->upgrade_fd_in_epoll =
false;
6138 if (-1 != daemon->epoll_fd)
6139 close (daemon->epoll_fd);
6140 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 6141 if (-1 != daemon->epoll_upgrade_fd)
6142 close (daemon->epoll_upgrade_fd);
6145 #ifdef DAUTH_SUPPORT 6149 #ifdef HTTPS_SUPPORT 6150 if (0 != (*pflags & MHD_USE_TLS))
6151 gnutls_priority_deinit (daemon->priority_cache);
6153 if (MHD_ITC_IS_VALID_(daemon->
itc))
6173 #ifdef UPGRADE_SUPPORT 6176 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 6177 struct MHD_UpgradeResponseHandle *urh;
6178 struct MHD_UpgradeResponseHandle *urhn;
6183 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
6190 urh->clean_ready =
true;
6208 #ifdef UPGRADE_SUPPORT 6214 while (
NULL != susp)
6216 if (
NULL == susp->urh)
6217 MHD_PANIC (
_(
"MHD_stop_daemon() called while we have suspended connections.\n"));
6218 #ifdef HTTPS_SUPPORT 6219 else if (used_tls &&
6221 (! susp->urh->clean_ready) )
6222 shutdown (susp->urh->app.socket,
6227 #ifdef HAVE_MESSAGES 6228 if (! susp->urh->was_closed)
6230 _(
"Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
6232 susp->urh->was_closed =
true;
6248 MHD_PANIC (
_(
"MHD_stop_daemon() called while we have suspended connections.\n"));
6253 #if MHD_WINSOCK_SOCKETS 6255 (MHD_ITC_IS_VALID_(daemon->
itc)) &&
6256 (! MHD_itc_activate_ (daemon->
itc,
"e")) )
6257 MHD_PANIC (
_(
"Failed to signal shutdown via inter-thread communication channel"));
6270 if (! MHD_join_thread_ (pos->
pid))
6284 #ifdef UPGRADE_SUPPORT 6342 MHD_PANIC (
_(
"Failed to signal shutdown via inter-thread communication channel."));
6344 #ifdef HAVE_LISTEN_SHUTDOWN 6349 (void) shutdown (fd,
6359 #ifdef EPOLL_SUPPORT 6362 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 6363 if (-1 != daemon->
worker_pool[i].epoll_upgrade_fd)
6376 if (MHD_ITC_IS_VALID_(daemon->
itc))
6378 if (! MHD_itc_activate_ (daemon->
itc,
"e"))
6379 MHD_PANIC (
_(
"Failed to signal shutdown via inter-thread communication channel"));
6381 #ifdef HAVE_LISTEN_SHUTDOWN 6387 (void) shutdown (fd,
6391 if (! MHD_join_thread_ (daemon->
pid))
6407 if (MHD_ITC_IS_VALID_ (daemon->
itc))
6410 #ifdef EPOLL_SUPPORT 6412 (-1 != daemon->epoll_fd) )
6414 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 6416 (-1 != daemon->epoll_upgrade_fd) )
6422 #ifdef HTTPS_SUPPORT 6423 if (daemon->have_dhparams)
6425 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
6426 daemon->have_dhparams =
false;
6430 gnutls_priority_deinit (daemon->priority_cache);
6431 if (daemon->x509_cred)
6432 gnutls_certificate_free_credentials (daemon->x509_cred);
6436 #ifdef DAUTH_SUPPORT 6458 const union MHD_DaemonInfo *
6472 return (
const union MHD_DaemonInfo *) &daemon->
listen_fd;
6473 #ifdef EPOLL_SUPPORT 6475 return (
const union MHD_DaemonInfo *) &daemon->epoll_fd;
6495 return (
const union MHD_DaemonInfo *) &daemon->
connections;
6497 return (
const union MHD_DaemonInfo *) &daemon->
options;
6538 #ifdef PACKAGE_VERSION 6539 return PACKAGE_VERSION;
6541 static char ver[12] =
"\0\0\0\0\0\0\0\0\0\0\0";
6544 int res = MHD_snprintf_(ver,
6550 if (0 >= res ||
sizeof(ver) <= res)
6574 case MHD_FEATURE_MESSAGES:
6575 #ifdef HAVE_MESSAGES 6580 case MHD_FEATURE_TLS:
6581 #ifdef HTTPS_SUPPORT 6586 case MHD_FEATURE_HTTPS_CERT_CALLBACK:
6587 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3 6592 case MHD_FEATURE_IPv6:
6598 case MHD_FEATURE_IPv6_ONLY:
6599 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) 6604 case MHD_FEATURE_POLL:
6610 case MHD_FEATURE_EPOLL:
6611 #ifdef EPOLL_SUPPORT 6616 case MHD_FEATURE_SHUTDOWN_LISTEN_SOCKET:
6617 #ifdef HAVE_LISTEN_SHUTDOWN 6622 case MHD_FEATURE_SOCKETPAIR:
6623 #ifdef _MHD_ITC_SOCKETPAIR 6628 case MHD_FEATURE_TCP_FASTOPEN:
6634 case MHD_FEATURE_BASIC_AUTH:
6635 #ifdef BAUTH_SUPPORT 6640 case MHD_FEATURE_DIGEST_AUTH:
6641 #ifdef DAUTH_SUPPORT 6646 case MHD_FEATURE_POSTPROCESSOR:
6647 #ifdef HAVE_POSTPROCESSOR 6652 case MHD_FEATURE_HTTPS_KEY_PASSWORD:
6653 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111 6658 case MHD_FEATURE_LARGE_FILE:
6659 #if defined(HAVE_PREAD64) || defined(_WIN32) 6661 #elif defined(HAVE_PREAD) 6662 return (
sizeof(uint64_t) >
sizeof(off_t)) ?
MHD_NO :
MHD_YES;
6663 #elif defined(HAVE_LSEEK64) 6666 return (
sizeof(uint64_t) >
sizeof(off_t)) ?
MHD_NO :
MHD_YES;
6668 case MHD_FEATURE_THREAD_NAMES:
6669 #if defined(MHD_USE_THREAD_NAME_) 6674 case MHD_FEATURE_UPGRADE:
6675 #if defined(UPGRADE_SUPPORT) 6680 case MHD_FEATURE_RESPONSES_SHARED_FD:
6681 #if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32) 6691 #if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600 6692 #if defined(MHD_USE_POSIX_THREADS) 6693 GCRY_THREAD_OPTION_PTHREAD_IMPL;
6694 #elif defined(MHD_W32_MUTEX_) 6697 gcry_w32_mutex_init (
void **ppmtx)
6699 *ppmtx = malloc (
sizeof (MHD_mutex_));
6703 if (!MHD_mutex_init_ ((MHD_mutex_*)*ppmtx))
6715 gcry_w32_mutex_destroy (
void **ppmtx)
6717 int res = (MHD_mutex_destroy_ ((MHD_mutex_*)*ppmtx)) ? 0 : EINVAL;
6724 gcry_w32_mutex_lock (
void **ppmtx)
6726 return MHD_mutex_lock_ ((MHD_mutex_*)*ppmtx) ? 0 : EINVAL;
6731 gcry_w32_mutex_unlock (
void **ppmtx)
6733 return MHD_mutex_unlock_ ((MHD_mutex_*)*ppmtx) ? 0 : EINVAL;
6737 static struct gcry_thread_cbs gcry_threads_w32 = {
6738 (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
6739 NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
6740 gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
6760 if (0 != WSAStartup(MAKEWORD(2, 2), &wsd))
6761 MHD_PANIC (
_(
"Failed to initialize winsock\n"));
6762 mhd_winsock_inited_ = 1;
6763 if (2 != LOBYTE(wsd.wVersion) && 2 != HIBYTE(wsd.wVersion))
6764 MHD_PANIC (
_(
"Winsock version 2.2 is not available\n"));
6766 #ifdef HTTPS_SUPPORT 6767 #if GCRYPT_VERSION_NUMBER < 0x010600 6768 #if defined(MHD_USE_POSIX_THREADS) 6769 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
6770 &gcry_threads_pthread))
6771 MHD_PANIC (
_(
"Failed to initialise multithreading in libgcrypt\n"));
6772 #elif defined(MHD_W32_MUTEX_) 6773 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
6775 MHD_PANIC (
_(
"Failed to initialise multithreading in libgcrypt\n"));
6777 gcry_check_version (NULL);
6779 if (NULL == gcry_check_version (
"1.6.0"))
6780 MHD_PANIC (
_(
"libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n"));
6782 gnutls_global_init ();
6791 #ifdef HTTPS_SUPPORT 6792 gnutls_global_deinit ();
6795 if (mhd_winsock_inited_)
unsigned int per_ip_connection_limit
int MHD_socket_nonblocking_(MHD_socket sock)
void * unescape_callback_cls
#define MHD_send_(s, b, l)
_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)
static int internal_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, int external_add, bool non_blck)
static int parse_options(struct MHD_Daemon *daemon, const struct sockaddr **servaddr,...)
#define DLL_insert(head, tail, element)
bool data_already_pending
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
enum MHD_CONNECTION_STATE state
uint64_t response_write_position
static int call_handlers(struct MHD_Connection *con, bool read_ready, bool write_ready, bool force_close)
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ MHD_select_thread(void *cls)
void MHD_pool_destroy(struct MemoryPool *pool)
#define MHD_SCKT_SEND_MAX_SIZE_
enum MHD_ConnectionEventLoopInfo event_loop_info
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
time_t connection_timeout
Methods for managing connections.
int MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
#define MHD_socket_set_error_(err)
_MHD_EXTERN int MHD_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen)
struct MHD_Response * response
#define MHD_socket_get_error_()
struct MHD_Connection * normal_timeout_tail
Header for platform missing functions.
volatile bool was_quiesced
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
#define MHD_MAX_CONNECTIONS_DEFAULT
static void mhd_panic_std(void *cls, const char *file, unsigned int line, const char *reason)
static int internal_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, unsigned int fd_setsize)
MHD_AccessHandlerCallback default_handler
static ssize_t send_param_adapter(struct MHD_Connection *connection, const void *other, size_t i)
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
void MHD_suspend_connection(struct MHD_Connection *connection)
static size_t unescape_wrapper(void *cls, struct MHD_Connection *connection, char *val)
_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,...)
#define MHD_mutex_destroy_chk_(pmutex)
#define EDLL_insert(head, tail, element)
#define MHD_SCKT_ERR_IS_(err, code)
static int parse_options_va(struct MHD_Daemon *daemon, const struct sockaddr **servaddr, va_list ap)
#define MHD_strerror_(errnum)
#define MHD_itc_destroy_chk_(itc)
static int 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)
Methods for managing response objects.
void MHD_set_panic_func(MHD_PanicCallback cb, void *cls)
void MHD_update_last_activity_(struct MHD_Connection *connection)
#define MHD_UNSIGNED_LONG_LONG
void * uri_log_callback_cls
static struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *daemon)
void(* MHD_PanicCallback)(void *cls, const char *file, unsigned int line, const char *reason)
void(* MHD_LogCallback)(void *cls, const char *fm, va_list ap)
struct MHD_Daemon * daemon
int(* idle_handler)(struct MHD_Connection *connection)
int listening_address_reuse
MHD_mutex_ per_ip_connection_mutex
struct MHD_Connection * manual_timeout_head
MHD_NotifyConnectionCallback notify_connection
struct MHD_Connection * cleanup_head
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
#define XDLL_remove(head, tail, element)
#define MHD_mutex_unlock_chk_(pmutex)
#define XDLL_insert(head, tail, element)
MHD_socket MHD_socket_create_listen_(int use_ipv6)
struct MHD_Connection * cleanup_tail
Header for platform-independent inter-thread communication.
struct MHD_Connection * prev
static int MHD_ip_addr_compare(const void *a1, const void *a2)
size_t write_buffer_send_offset
struct MHD_Daemon * worker_pool
#define MAYBE_SOCK_CLOEXEC
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
#define MHD_socket_close_chk_(fd)
struct MHD_Connection * manual_timeout_tail
static int MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen, struct MHD_IPCount *key)
#define MHD_INVALID_SOCKET
static int MHD_select(struct MHD_Daemon *daemon, int may_block)
#define MHD_POOL_SIZE_DEFAULT
void MHD_set_https_callbacks(struct MHD_Connection *connection)
#define MHD_create_named_thread_(t, n, s, r, a)
int MHD_add_to_fd_set_(MHD_socket fd, fd_set *set, MHD_socket *max_fd, unsigned int fd_setsize)
unsigned int connection_limit
#define MHD_recv_(s, b, l)
unsigned int worker_pool_size
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
int MHD_run_from_select(struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, const fd_set *except_fd_set)
LogCallback uri_log_callback
#define MHD_SYS_select_(n, r, w, e, t)
void MHD_destroy_response(struct MHD_Response *response)
time_t connection_timeout
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ thread_main_handle_connection(void *data)
static int MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
Methods for managing connections.
int(* read_handler)(struct MHD_Connection *connection)
struct MHD_Connection * normal_timeout_head
void * tdelete(const void *__restrict vkey, void **__restrict vrootp, int(*compar)(const void *, const void *))
static void MHD_ip_limit_del(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
_SET_INIT_AND_DEINIT_FUNCS(MHD_init, MHD_fini)
int MHD_socket_noninheritable_(MHD_socket sock)
void * tfind(const void *vkey, void *const *vrootp, int(*compar)(const void *, const void *))
#define MAYBE_SOCK_NONBLOCK
limits values definitions
Header for platform-independent threads abstraction.
void MHD_monotonic_sec_counter_init(void)
#define MHD_SCKT_ENOTCONN_
internal shared structures
void * MHD_calloc_(size_t nelem, size_t elsize)
UnescapeCallback unescape_callback
#define MHD_socket_last_strerr_()
void internal_suspend_connection_(struct MHD_Connection *connection)
#define MHD_SCKT_LAST_ERR_IS_(code)
internal monotonic clock functions implementations
int(* write_handler)(struct MHD_Connection *connection)
unsigned int listen_backlog_size
#define MHD_fd_close_chk_(fd)
struct MHD_Connection * connections_head
struct MHD_Daemon * master
struct MHD_Connection * next
MHD_AcceptPolicyCallback apc
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
int MHD_connection_handle_idle(struct MHD_Connection *connection)
static int resume_suspended_connections(struct MHD_Daemon *daemon)
#define MHD_socket_strerr_(err)
int(* MHD_AccessHandlerCallback)(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls)
static int MHD_poll(struct MHD_Daemon *daemon, int may_block)
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
static int MHD_accept_connection(struct MHD_Daemon *daemon)
int MHD_get_fdset(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd)
static void MHD_ip_count_unlock(struct MHD_Daemon *daemon)
#define MHD_connection_finish_forward_(conn)
time_t MHD_monotonic_sec_counter(void)
void(* MHD_RequestCompletedCallback)(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
size_t write_buffer_append_offset
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
MHD_RequestCompletedCallback notify_completed
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
struct MHD_Connection * prevX
static void close_connection(struct MHD_Connection *pos)
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
#define DLL_remove(head, tail, element)
void * notify_completed_cls
struct MemoryPool * MHD_pool_create(size_t max)
TransmitCallback send_cls
#define EDLL_remove(head, tail, element)
int MHD_run(struct MHD_Daemon *daemon)
#define TIMEVAL_TV_SEC_MAX
void * notify_connection_cls
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
MHD_PanicCallback mhd_panic
struct MHD_Connection * suspended_connections_tail
#define MHD_UNSIGNED_LONG_LONG_PRINTF
void MHD_resume_connection(struct MHD_Connection *connection)
const char * MHD_get_version(void)
void * per_ip_connection_count
_MHD_EXTERN int MHD_is_feature_supported(enum MHD_FEATURE feature)
#define MHD_SCKT_ECONNRESET_
size_t read_buffer_offset
int MHD_get_fdset2(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, unsigned int fd_setsize)
void * default_handler_cls
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
#define MHD_SCKT_ERR_IS_EINTR_(err)
MHD_mutex_ cleanup_connection_mutex
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
Header for platform-independent locks abstraction.
int(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
void(* MHD_NotifyConnectionCallback)(void *cls, struct MHD_Connection *connection, void **socket_context, enum MHD_ConnectionNotificationCode toe)
static void close_all_connections(struct MHD_Daemon *daemon)
struct MHD_Connection * connections_tail
#define MHD_socket_set_error_to_ENOMEM()
void MHD_monotonic_sec_counter_finish(void)
#define MHD_TEST_ALLOW_SUSPEND_RESUME
size_t MHD_http_unescape(char *val)
MHD_FLAG
Flags for the struct MHD_Daemon.
#define MHD_mutex_lock_chk_(pmutex)
struct MHD_Connection * suspended_connections_head
#define _MHD_SYS_DEFAULT_FD_SETSIZE
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...