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);
1881 was_suspended =
false;
1887 #ifdef HTTPS_SUPPORT
1888 || ( (con->tls_read_ready) &&
1899 if ( (
NULL == tvp) &&
1907 const time_t seconds_left = timeout - (now - con->
last_activity);
1909 tv.tv_sec = seconds_left;
1923 bool err_state =
false;
1957 if (MHD_ITC_IS_VALID_(daemon->
itc) )
1968 #ifdef HAVE_MESSAGES 1970 _(
"Failed to add FD to fd_set\n"));
1986 #ifdef HAVE_MESSAGES 1988 _(
"Error during select (%d): `%s'\n"),
1997 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
1998 (FD_ISSET (MHD_itc_r_fd_ (daemon->
itc),
2000 MHD_itc_clear_ (daemon->
itc);
2023 p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
2026 p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
2029 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
2037 if (MHD_ITC_IS_VALID_(daemon->
itc))
2039 p[1].events |= POLLIN;
2040 p[1].fd = MHD_itc_r_fd_ (daemon->
itc);
2045 if (MHD_sys_poll_ (p,
2051 (
NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
2055 #ifdef HAVE_MESSAGES 2057 _(
"Error during poll: `%s'\n"),
2065 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
2066 (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
2067 MHD_itc_clear_ (daemon->
itc);
2071 0 != (p[0].revents & POLLIN),
2072 0 != (p[0].revents & POLLOUT),
2073 0 != (p[0].revents & (POLLERR | MHD_POLL_REVENTS_ERR_DISC))))
2077 #ifdef UPGRADE_SUPPORT 2078 if (MHD_CONNECTION_UPGRADE == con->
state)
2090 thread_main_connection_upgrade (con);
2094 con->urh->clean_ready =
true;
2102 return (MHD_THRD_RTRN_TYPE_) 0;
2109 #ifdef HAVE_MESSAGES 2111 _(
"Processing thread terminating. Closing connection\n"));
2136 return (MHD_THRD_RTRN_TYPE_) 0;
2167 #ifdef EPOLL_SUPPORT 2174 else if (i > (
size_t)ret)
2214 (MHD_resp_sender_sendfile == connection->resp_sender) )
2220 #ifndef HAVE_SENDFILE64 2228 #ifndef HAVE_SENDFILE64 2233 offset = (off_t) offsetu64;
2240 if ((uint64_t)OFF64_T_MAX < offsetu64)
2244 offset = (off64_t) offsetu64;
2245 ret = sendfile64 (connection->
socket_fd,
2254 #ifdef EPOLL_SUPPORT 2255 if (left > (uint64_t)ret)
2261 #ifdef EPOLL_SUPPORT 2279 connection->resp_sender = MHD_resp_sender_std;
2286 #ifdef EPOLL_SUPPORT 2293 else if (i > (
size_t)ret)
2350 const struct sockaddr *addr,
2388 #ifdef HAVE_MESSAGES 2390 _(
"Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
2391 (
int) client_socket,
2401 #ifdef MHD_socket_nosignal_ 2402 if (! MHD_socket_nosignal_ (client_socket))
2404 #ifdef HAVE_MESSAGES 2406 _(
"Failed to set SO_NOSIGPIPE on accepted socket: %s\n"),
2409 #ifndef MSG_NOSIGNAL 2420 #ifdef HAVE_MESSAGES 2423 _(
"Accepted connection on socket %d\n"),
2433 #ifdef HAVE_MESSAGES 2435 _(
"Server reached connection limit. Closing inbound connection.\n"));
2451 #ifdef HAVE_MESSAGES 2453 _(
"Connection rejected by application. Closing connection.\n"));
2469 #ifdef HAVE_MESSAGES 2471 "Error allocating memory: %s\n",
2484 #ifdef HAVE_MESSAGES 2486 _(
"Error allocating memory: %s\n"),
2501 if (
NULL == (connection->
addr = malloc (addrlen)))
2504 #ifdef HAVE_MESSAGES 2506 _(
"Error allocating memory: %s\n"),
2518 memcpy (connection->
addr,
2524 connection->
daemon = daemon;
2536 #ifdef HTTPS_SUPPORT 2537 connection->
recv_cls = &recv_tls_adapter;
2538 connection->
send_cls = &send_tls_adapter;
2541 gnutls_init (&connection->tls_session,
2543 gnutls_priority_set (connection->tls_session,
2544 daemon->priority_cache);
2545 switch (daemon->cred_type)
2548 case GNUTLS_CRD_CERTIFICATE:
2549 gnutls_credentials_set (connection->tls_session,
2550 GNUTLS_CRD_CERTIFICATE,
2554 #ifdef HAVE_MESSAGES 2555 MHD_DLOG (connection->
daemon,
2556 _(
"Failed to setup TLS credentials: unknown credential type %d\n"),
2563 free (connection->
addr);
2571 gnutls_transport_set_ptr (connection->tls_session,
2572 (gnutls_transport_ptr_t) connection);
2573 gnutls_transport_set_pull_function (connection->tls_session,
2575 gnutls_transport_set_push_function (connection->tls_session,
2578 if (daemon->https_mem_trust)
2579 gnutls_certificate_server_set_request (connection->tls_session,
2580 GNUTLS_CERT_REQUEST);
2616 #ifdef HAVE_MESSAGES 2618 "Failed to create a thread: %s\n",
2625 if ( (
MHD_YES == external_add) &&
2626 (MHD_ITC_IS_VALID_(daemon->
itc)) &&
2627 (! MHD_itc_activate_ (daemon->
itc,
"n")) )
2629 #ifdef HAVE_MESSAGES 2631 _(
"Failed to signal new connection via inter-thread communication channel."));
2634 #ifdef EPOLL_SUPPORT 2639 struct epoll_event event;
2641 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2642 event.data.ptr = connection;
2643 if (0 != epoll_ctl (daemon->epoll_fd,
2649 #ifdef HAVE_MESSAGES 2651 _(
"Call to epoll_ctl failed: %s\n"),
2663 daemon->eready_tail,
2692 free (connection->
addr);
2736 MHD_PANIC (
_(
"Cannot suspend connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2764 #ifdef EPOLL_SUPPORT 2770 daemon->eready_tail,
2776 if (0 != epoll_ctl (daemon->epoll_fd,
2780 MHD_PANIC (
_(
"Failed to remove FD from epoll set\n"));
2803 daemon = connection->
daemon;
2805 MHD_PANIC (
_(
"Cannot resume connections without enabling MHD_ALLOW_SUSPEND_RESUME!\n"));
2810 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
2811 (! MHD_itc_activate_ (daemon->
itc,
"r")) )
2813 #ifdef HAVE_MESSAGES 2815 _(
"Failed to signal resume via inter-thread communication channel."));
2846 while (
NULL != (pos = prev))
2848 #ifdef UPGRADE_SUPPORT 2849 struct MHD_UpgradeResponseHandle *
const urh = pos->urh;
2851 static const void *
const urh =
NULL;
2855 #ifdef UPGRADE_SUPPORT
2856 || ( (
NULL != urh) &&
2857 ( (! urh->was_closed) ||
2858 (! urh->clean_ready) ) )
2888 #ifdef EPOLL_SUPPORT 2892 MHD_PANIC (
"Resumed connection was already in EREADY set\n");
2896 daemon->eready_tail,
2903 #ifdef UPGRADE_SUPPORT 2921 if (! MHD_itc_activate_(daemon->
itc,
2924 #ifdef HAVE_MESSAGES 2926 _(
"Failed to signal resume of connection via inter-thread communication channel."));
2966 const struct sockaddr *addr,
2972 #ifdef HAVE_MESSAGES 2974 _(
"Failed to set nonblocking mode on new client socket: %s\n"),
2985 #ifdef HAVE_MESSAGES 2987 _(
"Failed to set noninheritable mode on new client socket.\n"));
3017 struct sockaddr_in6 addrstorage;
3019 struct sockaddr_in addrstorage;
3021 struct sockaddr *addr = (
struct sockaddr *) &addrstorage;
3027 addrlen =
sizeof (addrstorage);
3030 sizeof (addrstorage));
3057 #ifdef HAVE_MESSAGES 3060 _(
"Error accepting connection: %s\n"),
3072 #ifdef HAVE_MESSAGES 3077 _(
"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"));
3083 #ifdef HAVE_MESSAGES 3085 _(
"Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
3092 #if !defined(USE_ACCEPT4) || !defined(HAVE_SOCK_NONBLOCK) 3095 #ifdef HAVE_MESSAGES 3097 _(
"Failed to set nonblocking mode on incoming connection socket: %s\n"),
3104 #if !defined(USE_ACCEPT4) || !defined(SOCK_CLOEXEC) 3107 #ifdef HAVE_MESSAGES 3109 _(
"Failed to set noninheritable mode on incoming connection socket.\n"));
3113 #ifdef HAVE_MESSAGES 3116 _(
"Accepted connection on socket %d\n"),
3154 (! MHD_join_thread_ (pos->
pid)) )
3156 #ifdef UPGRADE_SUPPORT 3157 cleanup_upgraded_connection (pos);
3160 #ifdef HTTPS_SUPPORT 3161 if (
NULL != pos->tls_session)
3162 gnutls_deinit (pos->tls_session);
3176 #ifdef EPOLL_SUPPORT 3182 daemon->eready_tail,
3186 if ( (-1 != daemon->epoll_fd) &&
3195 if (0 != epoll_ctl (daemon->epoll_fd,
3199 MHD_PANIC (
_(
"Failed to remove FD from epoll set\n"));
3241 time_t earliest_deadline;
3248 #ifdef HAVE_MESSAGES 3250 _(
"Illegal call to MHD_get_timeout\n"));
3262 #ifdef EPOLL_SUPPORT 3264 ((
NULL != daemon->eready_head)
3265 #
if defined(UPGRADE_SUPPORT) && defined(HTTPS_SUPPORT)
3266 || (
NULL != daemon->eready_urh_head)
3276 have_timeout =
false;
3277 earliest_deadline = 0;
3282 if ( (! have_timeout) ||
3285 have_timeout =
true;
3290 if ( (
NULL != pos) &&
3293 if ( (! have_timeout) ||
3296 have_timeout =
true;
3302 if (earliest_deadline < now)
3306 const time_t second_left = earliest_deadline - now;
3310 *timeout = 1000LL * second_left;
3328 const fd_set *read_fd_set,
3329 const fd_set *write_fd_set,
3330 const fd_set *except_fd_set)
3335 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3336 struct MHD_UpgradeResponseHandle *urh;
3337 struct MHD_UpgradeResponseHandle *urhn;
3346 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
3347 (FD_ISSET (MHD_itc_r_fd_ (daemon->
itc),
3349 MHD_itc_clear_ (daemon->
itc);
3351 #ifdef EPOLL_SUPPORT 3359 if (FD_ISSET (daemon->epoll_fd,
3377 while (
NULL != (pos = prev))
3393 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3395 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
3399 urh_from_fdset (urh,
3406 if ( (0 == urh->in_buffer_size) &&
3407 (0 == urh->out_buffer_size) &&
3408 (0 == urh->in_buffer_used) &&
3409 (0 == urh->out_buffer_used) )
3412 urh->clean_ready =
true;
3447 const fd_set *read_fd_set,
3448 const fd_set *write_fd_set,
3449 const fd_set *except_fd_set)
3455 if (
NULL == read_fd_set ||
NULL == write_fd_set)
3457 if (
NULL == except_fd_set)
3459 #ifdef HAVE_MESSAGES 3461 _(
"MHD_run_from_select() called with except_fd_set " 3462 "set to NULL. Such behavior is deprecated.\n"));
3465 except_fd_set = &es;
3469 #ifdef EPOLL_SUPPORT 3471 ret = MHD_epoll (daemon,
MHD_NO);
3483 write_fd_set, except_fd_set);
3504 struct timeval timeout;
3511 timeout.tv_usec = 0;
3534 #ifdef HAVE_MESSAGES 3536 _(
"Could not obtain daemon fdsets"));
3551 #ifdef HAVE_MESSAGES 3553 _(
"Could not add listen socket to fdset"));
3558 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
3564 #if defined(MHD_WINSOCK_SOCKETS) 3579 #ifdef HAVE_MESSAGES 3581 _(
"Could not add control inter-thread communication channel FD to fdset"));
3584 #if defined(MHD_WINSOCK_SOCKETS) 3596 (MHD_ITC_IS_VALID_(daemon->
itc)) &&
3608 timeout.tv_usec = 0;
3616 timeout.tv_usec = (ltimeout % 1000) * 1000;
3635 #ifdef HAVE_MESSAGES 3637 _(
"select failed: %s\n"),
3664 unsigned int num_connections;
3667 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3668 struct MHD_UpgradeResponseHandle *urh;
3669 struct MHD_UpgradeResponseHandle *urhn;
3677 num_connections = 0;
3680 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3681 for (urh = daemon->urh_head;
NULL != urh; urh = urh->next)
3682 num_connections += 2;
3688 unsigned int poll_server;
3694 p =
MHD_calloc_ ((2 + num_connections),
sizeof (
struct pollfd));
3697 #ifdef HAVE_MESSAGES 3699 _(
"Error allocating memory: %s\n"),
3712 p[poll_server].fd = ls;
3713 p[poll_server].events = POLLIN;
3714 p[poll_server].revents = 0;
3715 poll_listen = (int) poll_server;
3719 if (MHD_ITC_IS_VALID_(daemon->
itc))
3721 p[poll_server].fd = MHD_itc_r_fd_ (daemon->
itc);
3722 p[poll_server].events = POLLIN;
3723 p[poll_server].revents = 0;
3724 poll_itc_idx = (int) poll_server;
3734 timeout = (ltimeout > INT_MAX) ? INT_MAX : (
int) ltimeout;
3743 p[poll_server+i].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
3746 p[poll_server+i].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
3749 p[poll_server+i].events |= MHD_POLL_EVENTS_ERR_DISC;
3757 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3758 for (urh = daemon->urh_tail;
NULL != urh; urh = urh->prev)
3760 urh_to_pollfd(urh, &(p[poll_server+i]));
3764 if (0 == poll_server + num_connections)
3769 if (MHD_sys_poll_(p,
3770 poll_server + num_connections,
3779 #ifdef HAVE_MESSAGES 3781 _(
"poll failed: %s\n"),
3794 if ( (-1 != poll_itc_idx) &&
3795 (0 != (p[poll_itc_idx].revents & POLLIN)) )
3796 MHD_itc_clear_ (daemon->
itc);
3806 while (
NULL != (pos = prev))
3810 if (i >= num_connections)
3812 if (p[poll_server+i].fd != pos->
socket_fd)
3815 0 != (p[poll_server+i].revents & POLLIN),
3816 0 != (p[poll_server+i].revents & POLLOUT),
3817 0 != (p[poll_server+i].revents & MHD_POLL_REVENTS_ERR_DISC));
3820 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3821 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
3823 if (i >= num_connections)
3830 if ((p[poll_server+i].fd != urh->connection->socket_fd) ||
3831 (p[poll_server+i+1].fd != urh->mhd.socket))
3833 urh_from_pollfd(urh, &(p[poll_server+i]));
3837 if ( (0 == urh->in_buffer_size) &&
3838 (0 == urh->out_buffer_size) &&
3839 (0 == urh->in_buffer_used) &&
3840 (0 == urh->out_buffer_used) )
3845 urh->clean_ready =
true;
3855 if ( (-1 != poll_listen) &&
3856 (0 != (p[poll_listen].revents & POLLIN)) )
3873 MHD_poll_listen_socket (
struct MHD_Daemon *daemon,
3878 unsigned int poll_count;
3893 p[poll_count].fd = ls;
3894 p[poll_count].events = POLLIN;
3895 p[poll_count].revents = 0;
3896 poll_listen = poll_count;
3899 if (MHD_ITC_IS_VALID_(daemon->
itc))
3901 p[poll_count].fd = MHD_itc_r_fd_ (daemon->
itc);
3902 p[poll_count].events = POLLIN;
3903 p[poll_count].revents = 0;
3904 poll_itc_idx = poll_count;
3911 if (0 == poll_count)
3913 if (MHD_sys_poll_(p,
3921 #ifdef HAVE_MESSAGES 3923 _(
"poll failed: %s\n"),
3928 if ( (-1 != poll_itc_idx) &&
3929 (0 != (p[poll_itc_idx].revents & POLLIN)) )
3930 MHD_itc_clear_ (daemon->
itc);
3935 if ( (-1 != poll_listen) &&
3936 (0 != (p[poll_listen].revents & POLLIN)) )
3958 return MHD_poll_all (daemon,
3960 return MHD_poll_listen_socket (daemon,
3968 #ifdef EPOLL_SUPPORT 3978 #define MAX_EVENTS 128 3981 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3991 is_urh_ready(
struct MHD_UpgradeResponseHandle *
const urh)
3993 const struct MHD_Connection *
const connection = urh->connection;
3995 if ( (0 == urh->in_buffer_size) &&
3996 (0 == urh->out_buffer_size) &&
3997 (0 == urh->in_buffer_used) &&
3998 (0 == urh->out_buffer_used) )
4005 (connection->tls_read_ready) ) &&
4006 (urh->in_buffer_used < urh->in_buffer_size) )
4010 (urh->out_buffer_used < urh->out_buffer_size) )
4014 (urh->out_buffer_used > 0) )
4018 (urh->in_buffer_used > 0) )
4033 run_epoll_for_upgrade (
struct MHD_Daemon *daemon)
4035 struct epoll_event events[MAX_EVENTS];
4037 struct MHD_UpgradeResponseHandle * pos;
4038 struct MHD_UpgradeResponseHandle * prev;
4040 num_events = MAX_EVENTS;
4041 while (MAX_EVENTS == num_events)
4045 num_events = epoll_wait (daemon->epoll_upgrade_fd,
4049 if (-1 == num_events)
4054 #ifdef HAVE_MESSAGES 4056 _(
"Call to epoll_wait failed: %s\n"),
4061 for (i = 0; i < (
unsigned int) num_events; i++)
4063 struct UpgradeEpollHandle *
const ueh = events[i].data.ptr;
4064 struct MHD_UpgradeResponseHandle *
const urh = ueh->urh;
4065 bool new_err_state =
false;
4067 if (urh->clean_ready)
4071 if (0 != (events[i].events & EPOLLIN))
4073 if (0 != (events[i].events & EPOLLOUT))
4075 if (0 != (events[i].events & EPOLLHUP))
4079 (0 != (events[i].events & (EPOLLERR | EPOLLPRI))) )
4085 new_err_state =
true;
4088 if (! urh->in_eready_list)
4090 if (new_err_state ||
4094 daemon->eready_urh_tail,
4096 urh->in_eready_list =
true;
4101 prev = daemon->eready_urh_tail;
4102 while (
NULL != (pos = prev))
4106 if (! is_urh_ready(pos))
4109 daemon->eready_urh_tail,
4111 pos->in_eready_list =
false;
4114 if ( (0 == pos->in_buffer_size) &&
4115 (0 == pos->out_buffer_size) &&
4116 (0 == pos->in_buffer_used) &&
4117 (0 == pos->out_buffer_used) )
4120 pos->clean_ready =
true;
4136 static const char *
const epoll_itc_marker =
"itc_marker";
4150 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4151 static const char *
const upgrade_marker =
"upgrade_ptr";
4155 struct epoll_event events[MAX_EVENTS];
4156 struct epoll_event event;
4162 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4163 int run_upgraded =
MHD_NO;
4166 if (-1 == daemon->epoll_fd)
4173 (! daemon->listen_socket_in_epoll) &&
4176 event.events = EPOLLIN;
4177 event.data.ptr = daemon;
4178 if (0 != epoll_ctl (daemon->epoll_fd,
4183 #ifdef HAVE_MESSAGES 4185 _(
"Call to epoll_ctl failed: %s\n"),
4190 daemon->listen_socket_in_epoll =
true;
4193 (daemon->listen_socket_in_epoll) )
4195 if (0 != epoll_ctl (daemon->epoll_fd,
4199 MHD_PANIC (
"Failed to remove listen FD from epoll set\n");
4200 daemon->listen_socket_in_epoll =
false;
4203 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4204 if ( (! daemon->upgrade_fd_in_epoll) &&
4205 (-1 != daemon->epoll_upgrade_fd) )
4207 event.events = EPOLLIN | EPOLLOUT;
4208 event.data.ptr = (
void *) upgrade_marker;
4209 if (0 != epoll_ctl (daemon->epoll_fd,
4211 daemon->epoll_upgrade_fd,
4214 #ifdef HAVE_MESSAGES 4216 _(
"Call to epoll_ctl failed: %s\n"),
4221 daemon->upgrade_fd_in_epoll =
true;
4224 if ( (daemon->listen_socket_in_epoll) &&
4231 if (0 != epoll_ctl (daemon->epoll_fd,
4235 MHD_PANIC (
_(
"Failed to remove listen FD from epoll set\n"));
4236 daemon->listen_socket_in_epoll =
false;
4244 timeout_ms = INT_MAX;
4246 timeout_ms = (int) timeout_ll;
4263 num_events = MAX_EVENTS;
4264 while (MAX_EVENTS == num_events)
4267 num_events = epoll_wait (daemon->epoll_fd,
4271 if (-1 == num_events)
4276 #ifdef HAVE_MESSAGES 4278 _(
"Call to epoll_wait failed: %s\n"),
4283 for (i=0;i<(
unsigned int) num_events;i++)
4287 if (
NULL == events[i].data.ptr)
4289 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4290 if (upgrade_marker == events[i].data.ptr)
4298 if (epoll_itc_marker == events[i].data.ptr)
4302 MHD_itc_clear_ (daemon->
itc);
4305 if (daemon == events[i].data.ptr)
4309 if (0 == (events[i].events & (EPOLLERR | EPOLLHUP)))
4311 unsigned int series_length = 0;
4317 (series_length < 10) &&
4327 pos = events[i].data.ptr;
4329 if (0 != (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)))
4335 daemon->eready_tail,
4342 if (0 != (events[i].events & EPOLLIN))
4350 daemon->eready_tail,
4355 if (0 != (events[i].events & EPOLLOUT))
4362 daemon->eready_tail,
4371 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 4373 run_epoll_for_upgrade (daemon);
4382 prev = daemon->eready_tail;
4383 while (
NULL != (pos = prev))
4400 daemon->eready_tail,
4416 while (
NULL != (pos = prev))
4426 while (
NULL != (pos = prev))
4468 #ifdef EPOLL_SUPPORT 4471 MHD_epoll (daemon,
MHD_NO);
4533 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
4542 #ifdef EPOLL_SUPPORT 4556 return (MHD_THRD_RTRN_TYPE_)0;
4653 #ifdef HAVE_MESSAGES 4655 "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC\n");
4664 #ifdef EPOLL_SUPPORT 4669 if (0 != epoll_ctl (daemon->
worker_pool[i].epoll_fd,
4673 MHD_PANIC (
_(
"Failed to remove listen FD from epoll set\n"));
4674 daemon->
worker_pool[i].listen_socket_in_epoll =
false;
4681 MHD_PANIC (
_(
"Failed to signal quiesce via inter-thread communication channel"));
4685 #ifdef EPOLL_SUPPORT 4687 (-1 != daemon->epoll_fd) &&
4688 (daemon->listen_socket_in_epoll) )
4690 if (0 != epoll_ctl (daemon->epoll_fd,
4694 MHD_PANIC (
"Failed to remove listen FD from epoll set\n");
4695 daemon->listen_socket_in_epoll =
false;
4698 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
4699 (! MHD_itc_activate_ (daemon->
itc,
"q")) )
4700 MHD_PANIC (
_(
"failed to signal quiesce via inter-thread communication channel"));
4728 const struct sockaddr **servaddr,
4742 const struct sockaddr **servaddr,
4748 va_start (ap, servaddr);
4767 const struct sockaddr **servaddr,
4774 #ifdef HTTPS_SUPPORT 4800 #ifdef HAVE_MESSAGES 4802 _(
"Warning: Too large timeout value, ignored.\n"));
4826 *servaddr = va_arg (ap,
4827 const struct sockaddr *);
4840 #ifdef HAVE_MESSAGES 4842 _(
"Warning: Zero size, specified for thread pool size, is ignored. " 4843 "Thread pool is not used.\n"));
4848 #ifdef HAVE_MESSAGES 4850 _(
"Warning: \"1\", specified for thread pool size, is ignored. " 4851 "Thread pool is not used.\n"));
4857 #ifdef HAVE_MESSAGES 4859 _(
"Specified thread pool size (%u) too big\n"),
4868 #ifdef HAVE_MESSAGES 4870 _(
"MHD_OPTION_THREAD_POOL_SIZE option is specified but " 4871 "MHD_USE_INTERNAL_POLLING_THREAD flag is not specified.\n"));
4877 #ifdef HAVE_MESSAGES 4879 _(
"Both MHD_OPTION_THREAD_POOL_SIZE option and " 4880 "MHD_USE_THREAD_PER_CONNECTION flag are specified.\n"));
4886 #ifdef HTTPS_SUPPORT 4889 daemon->https_mem_key = va_arg (ap,
4891 #ifdef HAVE_MESSAGES 4894 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4900 daemon->https_key_password = va_arg (ap,
4902 #ifdef HAVE_MESSAGES 4905 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4911 daemon->https_mem_cert = va_arg (ap,
4913 #ifdef HAVE_MESSAGES 4916 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4922 daemon->https_mem_trust = va_arg (ap,
4924 #ifdef HAVE_MESSAGES 4927 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4932 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
4938 const char *arg = va_arg (ap,
4940 gnutls_datum_t dhpar;
4942 if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
4944 #ifdef HAVE_MESSAGES 4946 _(
"Error initializing DH parameters\n"));
4950 dhpar.data = (
unsigned char *) arg;
4951 dhpar.size = strlen (arg);
4952 if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
4954 GNUTLS_X509_FMT_PEM) < 0)
4956 #ifdef HAVE_MESSAGES 4958 _(
"Bad Diffie-Hellman parameters format\n"));
4960 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
4963 daemon->have_dhparams =
true;
4967 #ifdef HAVE_MESSAGES 4969 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4978 gnutls_priority_deinit (daemon->priority_cache);
4979 ret = gnutls_priority_init (&daemon->priority_cache,
4980 pstr = va_arg (ap,
const char*),
4982 if (GNUTLS_E_SUCCESS != ret)
4984 #ifdef HAVE_MESSAGES 4986 _(
"Setting priorities to `%s' failed: %s\n"),
4988 gnutls_strerror (ret));
4990 daemon->priority_cache =
NULL;
4996 #if GNUTLS_VERSION_MAJOR < 3 4997 #ifdef HAVE_MESSAGES 4999 _(
"MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n"));
5004 daemon->cert_callback = va_arg (ap,
5005 gnutls_certificate_retrieve_function2 *);
5009 #ifdef DAUTH_SUPPORT 5011 daemon->digest_auth_rand_size = va_arg (ap,
5013 daemon->digest_auth_random = va_arg (ap,
5017 daemon->nonce_nc_size = va_arg (ap,
5024 #ifdef HAVE_MESSAGES 5026 _(
"MHD_OPTION_LISTEN_SOCKET specified for daemon " 5027 "with MHD_USE_NO_LISTEN_SOCKET flag set.\n"));
5036 #ifdef HAVE_MESSAGES 5037 daemon->custom_error_log = va_arg (ap,
5039 daemon->custom_error_log_cls = va_arg (ap,
5054 daemon->fastopen_queue_size = va_arg (ap,
5060 unsigned int) ? 1 : -1;
5068 #ifdef HAVE_MESSAGES 5073 _(
"Flag MHD_USE_PEDANTIC_CHECKS is ignored because " 5074 "another behavior is specified by MHD_OPTION_STRICT_CLIENT.\n"));
5092 (
size_t) oa[i].
value,
5108 (
unsigned int) oa[i].value,
5113 #ifdef HTTPS_SUPPORT 5118 (gnutls_credentials_type_t) oa[i].value,
5167 (
void *) oa[i].value,
5177 (
size_t) oa[i].value,
5195 #ifdef HAVE_MESSAGES 5201 _(
"MHD HTTPS option %d passed to MHD compiled without HTTPS support\n"),
5207 _(
"Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n"),
5218 #ifdef EPOLL_SUPPORT 5224 #ifdef USE_EPOLL_CREATE1 5225 fd = epoll_create1 (EPOLL_CLOEXEC);
5227 fd = epoll_create (MAX_EVENTS);
5231 #ifdef HAVE_MESSAGES 5233 _(
"Call to epoll_create1 failed: %s\n"),
5238 #if !defined(USE_EPOLL_CREATE1) 5241 #ifdef HAVE_MESSAGES 5243 _(
"Failed to set noninheritable mode on epoll FD.\n"));
5261 setup_epoll_to_listen (
struct MHD_Daemon *daemon)
5263 struct epoll_event event;
5266 daemon->epoll_fd = setup_epoll_fd (daemon);
5267 if (-1 == daemon->epoll_fd)
5269 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 5272 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
5280 event.events = EPOLLIN;
5281 event.data.ptr = daemon;
5282 if (0 != epoll_ctl (daemon->epoll_fd,
5287 #ifdef HAVE_MESSAGES 5289 _(
"Call to epoll_ctl failed: %s\n"),
5294 daemon->listen_socket_in_epoll =
true;
5295 if (MHD_ITC_IS_VALID_(daemon->
itc))
5297 event.events = EPOLLIN;
5298 event.data.ptr = (
void *) epoll_itc_marker;
5299 if (0 != epoll_ctl (daemon->epoll_fd,
5301 MHD_itc_r_fd_ (daemon->
itc),
5304 #ifdef HAVE_MESSAGES 5306 _(
"Call to epoll_ctl failed: %s\n"),
5346 struct sockaddr_in servaddr4;
5348 struct sockaddr_in6 servaddr6;
5350 const struct sockaddr *servaddr =
NULL;
5366 #ifndef EPOLL_SUPPORT 5370 #ifndef HTTPS_SUPPORT 5374 #ifndef TCP_FASTOPEN 5380 #ifdef UPGRADE_SUPPORT 5390 if ( ((0 != (*pflags & MHD_USE_POLL)) && (0 != (*pflags & MHD_USE_EPOLL))) ||
5392 ((0 != (*pflags & MHD_USE_POLL)) &&
5394 ((0 != (*pflags &
MHD_USE_AUTO)) && (0 != (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)))) )
5397 if (0 != (*pflags & MHD_USE_AUTO))
5411 #if defined(EPOLL_SUPPORT) 5413 #elif defined(HAVE_POLL) 5422 #if defined(EPOLL_SUPPORT) 5432 #ifdef EPOLL_SUPPORT 5433 daemon->epoll_fd = -1;
5434 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 5435 daemon->epoll_upgrade_fd = -1;
5439 #ifdef HTTPS_SUPPORT 5440 daemon->priority_cache =
NULL;
5441 if (0 != (*pflags & MHD_USE_TLS))
5443 gnutls_priority_init (&daemon->priority_cache,
5453 daemon->
port = port;
5464 MHD_itc_set_invalid_ (daemon->
itc);
5470 #ifdef HAVE_MESSAGES 5472 daemon->custom_error_log_cls = stderr;
5477 #ifdef HAVE_MESSAGES 5479 _(
"Warning: MHD_USE_THREAD_PER_CONNECTION must be used only with " 5480 "MHD_USE_INTERNAL_POLLING_THREAD. Flag MHD_USE_INTERNAL_POLLING_THREAD " 5481 "was added. Consider setting MHD_USE_INTERNAL_POLLING_THREAD explicitly.\n"));
5489 #ifdef HAVE_LISTEN_SHUTDOWN 5494 #ifdef DAUTH_SUPPORT 5495 daemon->digest_auth_rand_size = 0;
5496 daemon->digest_auth_random =
NULL;
5497 daemon->nonce_nc_size = 4;
5499 #ifdef HTTPS_SUPPORT 5500 if (0 != (*pflags & MHD_USE_TLS))
5502 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
5511 #ifdef HTTPS_SUPPORT 5512 if ( (0 != (*pflags & MHD_USE_TLS)) &&
5513 (
NULL != daemon->priority_cache) )
5514 gnutls_priority_deinit (daemon->priority_cache);
5522 if (! MHD_itc_init_ (daemon->
itc))
5524 #ifdef HAVE_MESSAGES 5526 _(
"Failed to create inter-thread communication channel: %s\n"),
5527 MHD_itc_last_strerror_ ());
5529 #ifdef HTTPS_SUPPORT 5530 if (
NULL != daemon->priority_cache)
5531 gnutls_priority_deinit (daemon->priority_cache);
5536 if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
5540 #ifdef HAVE_MESSAGES 5542 _(
"file descriptor for inter-thread communication channel exceeds maximum value\n"));
5545 #ifdef HTTPS_SUPPORT 5546 if (
NULL != daemon->priority_cache)
5547 gnutls_priority_deinit (daemon->priority_cache);
5554 #ifdef DAUTH_SUPPORT 5555 if (daemon->nonce_nc_size > 0)
5557 if ( ( (
size_t) (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc))) /
5558 sizeof(
struct MHD_NonceNc) != daemon->nonce_nc_size)
5560 #ifdef HAVE_MESSAGES 5562 _(
"Specified value for NC_SIZE too large\n"));
5564 #ifdef HTTPS_SUPPORT 5565 if (0 != (*pflags & MHD_USE_TLS))
5566 gnutls_priority_deinit (daemon->priority_cache);
5571 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc));
5572 if (
NULL == daemon->nnc)
5574 #ifdef HAVE_MESSAGES 5576 _(
"Failed to allocate memory for nonce-nc map: %s\n"),
5579 #ifdef HTTPS_SUPPORT 5580 if (0 != (*pflags & MHD_USE_TLS))
5581 gnutls_priority_deinit (daemon->priority_cache);
5588 if (! MHD_mutex_init_ (&daemon->nnc_lock))
5590 #ifdef HAVE_MESSAGES 5592 _(
"MHD failed to initialize nonce-nc mutex\n"));
5594 #ifdef HTTPS_SUPPORT 5595 if (0 != (*pflags & MHD_USE_TLS))
5596 gnutls_priority_deinit (daemon->priority_cache);
5605 if ( (0 == (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
5608 #ifdef HAVE_MESSAGES 5610 _(
"MHD thread pooling only works with MHD_USE_INTERNAL_POLLING_THREAD\n"));
5615 #ifdef __SYMBIAN32__ 5616 if (0 != (*pflags & (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_THREAD_PER_CONNECTION)))
5618 #ifdef HAVE_MESSAGES 5620 _(
"Threaded operations are not supported on Symbian.\n"));
5632 #ifdef HAVE_MESSAGES 5634 _(
"Failed to create socket for listening: %s\n"),
5648 if (0 > setsockopt (listen_fd,
5651 (
void*)&on,
sizeof (on)))
5653 #ifdef HAVE_MESSAGES 5655 _(
"setsockopt failed: %s\n"),
5667 if (0 > setsockopt (listen_fd,
5670 (
void*)&on,
sizeof (on)))
5672 #ifdef HAVE_MESSAGES 5674 _(
"setsockopt failed: %s\n"),
5684 #if defined(_WIN32) || defined(SO_REUSEPORT) 5685 if (0 > setsockopt (listen_fd,
5695 #ifdef HAVE_MESSAGES 5697 _(
"setsockopt failed: %s\n"),
5705 #ifdef HAVE_MESSAGES 5707 _(
"Cannot allow listening address reuse: SO_REUSEPORT not defined\n"));
5720 #if (defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE)) || \ 5721 (defined(__sun) && defined(SO_EXCLBIND)) 5722 if (0 > setsockopt (listen_fd,
5724 #ifdef SO_EXCLUSIVEADDRUSE
5725 SO_EXCLUSIVEADDRUSE,
5732 #ifdef HAVE_MESSAGES 5734 _(
"setsockopt failed: %s\n"),
5739 #elif defined(_WIN32) 5740 #ifdef HAVE_MESSAGES 5742 _(
"Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n"));
5750 if (0 != (*pflags & MHD_USE_IPv6))
5751 addrlen =
sizeof (
struct sockaddr_in6);
5754 addrlen =
sizeof (
struct sockaddr_in);
5755 if (
NULL == servaddr)
5758 if (0 != (*pflags & MHD_USE_IPv6))
5762 sizeof (
struct sockaddr_in6));
5763 servaddr6.sin6_family = AF_INET6;
5764 servaddr6.sin6_port = htons (port);
5765 #if HAVE_SOCKADDR_IN_SIN_LEN 5766 servaddr6.sin6_len =
sizeof (
struct sockaddr_in6);
5768 servaddr = (
struct sockaddr *) &servaddr6;
5775 sizeof (
struct sockaddr_in));
5776 servaddr4.sin_family = AF_INET;
5777 servaddr4.sin_port = htons (port);
5778 #if HAVE_SOCKADDR_IN_SIN_LEN 5779 servaddr4.sin_len =
sizeof (
struct sockaddr_in);
5781 servaddr = (
struct sockaddr *) &servaddr4;
5786 if (0 != (*pflags & MHD_USE_IPv6))
5796 if (0 > setsockopt (listen_fd,
5797 IPPROTO_IPV6, IPV6_V6ONLY,
5798 (
const void *) &v6_only,
5801 #ifdef HAVE_MESSAGES 5803 _(
"setsockopt failed: %s\n"),
5810 if (-1 == bind (listen_fd, servaddr, addrlen))
5812 #ifdef HAVE_MESSAGES 5814 _(
"Failed to bind to port %u: %s\n"),
5815 (
unsigned int) port,
5822 if (0 != (*pflags & MHD_USE_TCP_FASTOPEN))
5824 if (0 == daemon->fastopen_queue_size)
5825 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
5826 if (0 != setsockopt (listen_fd,
5829 &daemon->fastopen_queue_size,
5830 sizeof (daemon->fastopen_queue_size)))
5832 #ifdef HAVE_MESSAGES 5834 _(
"setsockopt failed: %s\n"),
5840 if (listen (listen_fd,
5843 #ifdef HAVE_MESSAGES 5845 _(
"Failed to listen for connections: %s\n"),
5860 #ifdef HAVE_MESSAGES 5862 _(
"Failed to set nonblocking mode on listening socket: %s\n"),
5865 if (0 != (*pflags & MHD_USE_EPOLL) ||
5878 (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL)) ) )
5880 #ifdef HAVE_MESSAGES 5882 _(
"Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
5890 #ifdef EPOLL_SUPPORT 5891 if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
5893 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
5895 if (0 != (*pflags & MHD_USE_THREAD_PER_CONNECTION))
5897 #ifdef HAVE_MESSAGES 5899 _(
"Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
5903 if (
MHD_YES != setup_epoll_to_listen (daemon))
5910 #ifdef HAVE_MESSAGES 5912 _(
"MHD failed to initialize IP connection limit mutex\n"));
5920 #ifdef HAVE_MESSAGES 5922 _(
"MHD failed to initialize IP connection limit mutex\n"));
5930 #ifdef HTTPS_SUPPORT 5932 if ( (0 != (*pflags & MHD_USE_TLS)) &&
5933 (0 != MHD_TLS_init (daemon)) )
5935 #ifdef HAVE_MESSAGES 5937 _(
"Failed to initialize TLS support\n"));
5946 if ( ( (0 != (*pflags & MHD_USE_INTERNAL_POLLING_THREAD)) &&
5948 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) &&
5950 (*pflags & MHD_USE_THREAD_PER_CONNECTION) ?
5951 "MHD-listen" :
"MHD-single",
5956 #ifdef HAVE_MESSAGES 5958 _(
"Failed to create listen thread: %s\n"),
5968 (0 == (*pflags & MHD_USE_NO_LISTEN_SOCKET)) )
5992 memcpy (d, daemon,
sizeof (
struct MHD_Daemon));
6000 if (0 != (*pflags & MHD_USE_ITC))
6002 if (! MHD_itc_init_ (d->
itc))
6004 #ifdef HAVE_MESSAGES 6006 _(
"Failed to create worker inter-thread communication channel: %s\n"),
6007 MHD_itc_last_strerror_() );
6011 if ( (0 == (*pflags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
6015 #ifdef HAVE_MESSAGES 6017 _(
"File descriptor for worker inter-thread communication channel exceeds maximum value\n"));
6024 MHD_itc_set_invalid_ (d->
itc);
6030 if (i < leftover_conns)
6032 #ifdef EPOLL_SUPPORT 6033 if ( (0 != (*pflags & MHD_USE_EPOLL)) &&
6034 (
MHD_YES != setup_epoll_to_listen (d)) )
6040 #ifdef HAVE_MESSAGES 6042 _(
"MHD failed to initialize cleanup connection mutex\n"));
6054 #ifdef HAVE_MESSAGES 6056 _(
"Failed to create pool thread: %s\n"),
6066 #ifdef HTTPS_SUPPORT 6069 daemon->https_key_password =
NULL;
6101 #ifdef EPOLL_SUPPORT 6102 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 6103 if (daemon->upgrade_fd_in_epoll)
6105 if (0 != epoll_ctl (daemon->epoll_fd,
6107 daemon->epoll_upgrade_fd,
6109 MHD_PANIC (
_(
"Failed to remove FD from epoll set\n"));
6110 daemon->upgrade_fd_in_epoll =
false;
6113 if (-1 != daemon->epoll_fd)
6114 close (daemon->epoll_fd);
6115 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 6116 if (-1 != daemon->epoll_upgrade_fd)
6117 close (daemon->epoll_upgrade_fd);
6120 #ifdef DAUTH_SUPPORT 6124 #ifdef HTTPS_SUPPORT 6125 if (0 != (*pflags & MHD_USE_TLS))
6126 gnutls_priority_deinit (daemon->priority_cache);
6128 if (MHD_ITC_IS_VALID_(daemon->
itc))
6148 #ifdef UPGRADE_SUPPORT 6151 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 6152 struct MHD_UpgradeResponseHandle *urh;
6153 struct MHD_UpgradeResponseHandle *urhn;
6158 for (urh = daemon->urh_tail;
NULL != urh; urh = urhn)
6165 urh->clean_ready =
true;
6183 #ifdef UPGRADE_SUPPORT 6189 while (
NULL != susp)
6191 if (
NULL == susp->urh)
6192 MHD_PANIC (
_(
"MHD_stop_daemon() called while we have suspended connections.\n"));
6193 #ifdef HTTPS_SUPPORT 6194 else if (used_tls &&
6196 (! susp->urh->clean_ready) )
6197 shutdown (susp->urh->app.socket,
6202 #ifdef HAVE_MESSAGES 6203 if (! susp->urh->was_closed)
6205 _(
"Initiated daemon shutdown while \"upgraded\" connection was not closed.\n"));
6207 susp->urh->was_closed =
true;
6223 MHD_PANIC (
_(
"MHD_stop_daemon() called while we have suspended connections.\n"));
6228 #if MHD_WINSOCK_SOCKETS 6230 (MHD_ITC_IS_VALID_(daemon->
itc)) &&
6231 (! MHD_itc_activate_ (daemon->
itc,
"e")) )
6232 MHD_PANIC (
_(
"Failed to signal shutdown via inter-thread communication channel"));
6245 if (! MHD_join_thread_ (pos->
pid))
6259 #ifdef UPGRADE_SUPPORT 6317 MHD_PANIC (
_(
"Failed to signal shutdown via inter-thread communication channel."));
6319 #ifdef HAVE_LISTEN_SHUTDOWN 6324 (void) shutdown (fd,
6334 #ifdef EPOLL_SUPPORT 6337 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 6338 if (-1 != daemon->
worker_pool[i].epoll_upgrade_fd)
6351 if (MHD_ITC_IS_VALID_(daemon->
itc))
6353 if (! MHD_itc_activate_ (daemon->
itc,
"e"))
6354 MHD_PANIC (
_(
"Failed to signal shutdown via inter-thread communication channel"));
6356 #ifdef HAVE_LISTEN_SHUTDOWN 6362 (void) shutdown (fd,
6366 if (! MHD_join_thread_ (daemon->
pid))
6382 if (MHD_ITC_IS_VALID_ (daemon->
itc))
6385 #ifdef EPOLL_SUPPORT 6387 (-1 != daemon->epoll_fd) )
6389 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 6391 (-1 != daemon->epoll_upgrade_fd) )
6397 #ifdef HTTPS_SUPPORT 6398 if (daemon->have_dhparams)
6400 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
6401 daemon->have_dhparams =
false;
6405 gnutls_priority_deinit (daemon->priority_cache);
6406 if (daemon->x509_cred)
6407 gnutls_certificate_free_credentials (daemon->x509_cred);
6411 #ifdef DAUTH_SUPPORT 6433 const union MHD_DaemonInfo *
6447 return (
const union MHD_DaemonInfo *) &daemon->
listen_fd;
6448 #ifdef EPOLL_SUPPORT 6450 return (
const union MHD_DaemonInfo *) &daemon->epoll_fd;
6470 return (
const union MHD_DaemonInfo *) &daemon->
connections;
6472 return (
const union MHD_DaemonInfo *) &daemon->
options;
6513 #ifdef PACKAGE_VERSION 6514 return PACKAGE_VERSION;
6516 static char ver[12] =
"\0\0\0\0\0\0\0\0\0\0\0";
6519 int res = MHD_snprintf_(ver,
6525 if (0 >= res ||
sizeof(ver) <= res)
6549 case MHD_FEATURE_MESSAGES:
6550 #ifdef HAVE_MESSAGES 6555 case MHD_FEATURE_TLS:
6556 #ifdef HTTPS_SUPPORT 6561 case MHD_FEATURE_HTTPS_CERT_CALLBACK:
6562 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_MAJOR >= 3 6567 case MHD_FEATURE_IPv6:
6573 case MHD_FEATURE_IPv6_ONLY:
6574 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) 6579 case MHD_FEATURE_POLL:
6585 case MHD_FEATURE_EPOLL:
6586 #ifdef EPOLL_SUPPORT 6591 case MHD_FEATURE_SHUTDOWN_LISTEN_SOCKET:
6592 #ifdef HAVE_LISTEN_SHUTDOWN 6597 case MHD_FEATURE_SOCKETPAIR:
6598 #ifdef _MHD_ITC_SOCKETPAIR 6603 case MHD_FEATURE_TCP_FASTOPEN:
6609 case MHD_FEATURE_BASIC_AUTH:
6610 #ifdef BAUTH_SUPPORT 6615 case MHD_FEATURE_DIGEST_AUTH:
6616 #ifdef DAUTH_SUPPORT 6621 case MHD_FEATURE_POSTPROCESSOR:
6622 #ifdef HAVE_POSTPROCESSOR 6627 case MHD_FEATURE_HTTPS_KEY_PASSWORD:
6628 #if defined(HTTPS_SUPPORT) && GNUTLS_VERSION_NUMBER >= 0x030111 6633 case MHD_FEATURE_LARGE_FILE:
6634 #if defined(HAVE_PREAD64) || defined(_WIN32) 6636 #elif defined(HAVE_PREAD) 6637 return (
sizeof(uint64_t) >
sizeof(off_t)) ?
MHD_NO :
MHD_YES;
6638 #elif defined(HAVE_LSEEK64) 6641 return (
sizeof(uint64_t) >
sizeof(off_t)) ?
MHD_NO :
MHD_YES;
6643 case MHD_FEATURE_THREAD_NAMES:
6644 #if defined(MHD_USE_THREAD_NAME_) 6649 case MHD_FEATURE_UPGRADE:
6650 #if defined(UPGRADE_SUPPORT) 6655 case MHD_FEATURE_RESPONSES_SHARED_FD:
6656 #if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32) 6666 #if defined(HTTPS_SUPPORT) && GCRYPT_VERSION_NUMBER < 0x010600 6667 #if defined(MHD_USE_POSIX_THREADS) 6668 GCRY_THREAD_OPTION_PTHREAD_IMPL;
6669 #elif defined(MHD_W32_MUTEX_) 6672 gcry_w32_mutex_init (
void **ppmtx)
6674 *ppmtx = malloc (
sizeof (MHD_mutex_));
6678 if (!MHD_mutex_init_ ((MHD_mutex_*)*ppmtx))
6690 gcry_w32_mutex_destroy (
void **ppmtx)
6692 int res = (MHD_mutex_destroy_ ((MHD_mutex_*)*ppmtx)) ? 0 : EINVAL;
6699 gcry_w32_mutex_lock (
void **ppmtx)
6701 return MHD_mutex_lock_ ((MHD_mutex_*)*ppmtx) ? 0 : EINVAL;
6706 gcry_w32_mutex_unlock (
void **ppmtx)
6708 return MHD_mutex_unlock_ ((MHD_mutex_*)*ppmtx) ? 0 : EINVAL;
6712 static struct gcry_thread_cbs gcry_threads_w32 = {
6713 (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
6714 NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
6715 gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
6735 if (0 != WSAStartup(MAKEWORD(2, 2), &wsd))
6736 MHD_PANIC (
_(
"Failed to initialize winsock\n"));
6737 mhd_winsock_inited_ = 1;
6738 if (2 != LOBYTE(wsd.wVersion) && 2 != HIBYTE(wsd.wVersion))
6739 MHD_PANIC (
_(
"Winsock version 2.2 is not available\n"));
6741 #ifdef HTTPS_SUPPORT 6742 #if GCRYPT_VERSION_NUMBER < 0x010600 6743 #if defined(MHD_USE_POSIX_THREADS) 6744 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
6745 &gcry_threads_pthread))
6746 MHD_PANIC (
_(
"Failed to initialise multithreading in libgcrypt\n"));
6747 #elif defined(MHD_W32_MUTEX_) 6748 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
6750 MHD_PANIC (
_(
"Failed to initialise multithreading in libgcrypt\n"));
6752 gcry_check_version (NULL);
6754 if (NULL == gcry_check_version (
"1.6.0"))
6755 MHD_PANIC (
_(
"libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n"));
6757 gnutls_global_init ();
6766 #ifdef HTTPS_SUPPORT 6767 gnutls_global_deinit ();
6770 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)
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)
#define MHD_MAX_CONNECTIONS_DEFAULT
static void mhd_panic_std(void *cls, const char *file, unsigned int line, const char *reason)
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_()
#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)
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...