27 #if defined(MHD_WINSOCK_SOCKETS) 29 #define FD_SETSIZE 1024 30 #define MHD_DEFAULT_FD_SETSIZE 64 32 #define MHD_DEFAULT_FD_SETSIZE FD_SETSIZE 54 #if defined(HAVE_POLL_H) && defined(HAVE_POLL) 59 #include <sys/sendfile.h> 63 #ifndef WIN32_LEAN_AND_MEAN 64 #define WIN32_LEAN_AND_MEAN 1 71 #define HAVE_ACCEPT4 0 77 #ifndef MHD_WINSOCK_SOCKETS 78 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE - 4 80 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE 86 #define MHD_POOL_SIZE_DEFAULT (32 * 1024) 92 #define MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT 10 99 #define DEBUG_CLOSE MHD_NO 105 #define DEBUG_CONNECT MHD_NO 109 #define MSG_NOSIGNAL 0 114 #define SOCK_CLOEXEC 0 117 #ifndef EPOLL_CLOEXEC 118 #define EPOLL_CLOEXEC 0 139 "Fatal error in GNU libmicrohttpd %s:%u: %s\n",
160 static int mhd_winsock_inited_ = 0;
202 struct in6_addr ipv6;
223 MHD_PANIC (
"Failed to acquire IP connection limit mutex\n");
238 MHD_PANIC (
"Failed to release IP connection limit mutex\n");
255 return memcmp (a1, a2, offsetof (
struct MHD_IPCount, count));
270 struct MHD_IPCount *key)
272 memset(key, 0,
sizeof(*key));
275 if (
sizeof (
struct sockaddr_in) == addrlen)
277 const struct sockaddr_in *addr4 = (
const struct sockaddr_in*) addr;
278 key->family = AF_INET;
279 memcpy (&key->addr.ipv4, &addr4->sin_addr,
sizeof(addr4->sin_addr));
285 if (
sizeof (
struct sockaddr_in6) == addrlen)
287 const struct sockaddr_in6 *addr6 = (
const struct sockaddr_in6*) addr;
288 key->family = AF_INET6;
289 memcpy (&key->addr.ipv6, &addr6->sin6_addr,
sizeof(addr6->sin6_addr));
310 const struct sockaddr *addr,
313 struct MHD_IPCount *key;
323 if (
NULL == (key = malloc (
sizeof(*key))))
342 "Failed to add IP connection count node\n");
352 key = (
struct MHD_IPCount *) node;
374 const struct sockaddr *addr,
377 struct MHD_IPCount search_key;
378 struct MHD_IPCount *found_key;
398 MHD_PANIC (
"Failed to find previously-added IP address\n");
400 found_key = (
struct MHD_IPCount *) *nodep;
402 if (0 == found_key->count)
404 MHD_PANIC (
"Previously-added IP address had 0 count\n");
407 if (0 == --found_key->count)
429 recv_tls_adapter (
struct MHD_Connection *connection,
void *other,
size_t i)
433 if (
MHD_YES == connection->tls_read_ready)
435 connection->
daemon->num_tls_read_ready--;
436 connection->tls_read_ready =
MHD_NO;
438 res = gnutls_record_recv (connection->tls_session, other, i);
439 if ( (GNUTLS_E_AGAIN == res) ||
440 (GNUTLS_E_INTERRUPTED == res) )
456 if ((
size_t)res == i)
458 connection->tls_read_ready =
MHD_YES;
459 connection->
daemon->num_tls_read_ready++;
475 const void *other,
size_t i)
479 res = gnutls_record_send (connection->tls_session, other, i);
480 if ( (GNUTLS_E_AGAIN == res) ||
481 (GNUTLS_E_INTERRUPTED == res) )
509 MHD_init_daemon_certificate (
struct MHD_Daemon *daemon)
515 #if GNUTLS_VERSION_MAJOR >= 3 516 if (
NULL != daemon->cert_callback)
518 gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
519 daemon->cert_callback);
522 if (
NULL != daemon->https_mem_trust)
524 cert.data = (
unsigned char *) daemon->https_mem_trust;
525 cert.size = strlen (daemon->https_mem_trust);
526 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred, &cert,
527 GNUTLS_X509_FMT_PEM) < 0)
531 "Bad trust certificate format\n");
537 if (
MHD_YES == daemon->have_dhparams)
539 gnutls_certificate_set_dh_params (daemon->x509_cred,
540 daemon->https_mem_dhparams);
543 if ( (
NULL != daemon->https_mem_cert) &&
544 (
NULL != daemon->https_mem_key) )
546 key.data = (
unsigned char *) daemon->https_mem_key;
547 key.size = strlen (daemon->https_mem_key);
548 cert.data = (
unsigned char *) daemon->https_mem_cert;
549 cert.size = strlen (daemon->https_mem_cert);
551 if (
NULL != daemon->https_key_password) {
552 #if GNUTLS_VERSION_NUMBER >= 0x030111 553 ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
556 daemon->https_key_password,
561 "Failed to setup x509 certificate/key: pre 3.X.X version " \
562 "of GnuTLS does not support setting key password");
568 ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
570 GNUTLS_X509_FMT_PEM);
574 "GnuTLS failed to setup x509 certificate/key: %s\n",
575 gnutls_strerror (ret));
579 #if GNUTLS_VERSION_MAJOR >= 3 580 if (
NULL != daemon->cert_callback)
585 "You need to specify a certificate and key location\n");
600 switch (daemon->cred_type)
602 case GNUTLS_CRD_CERTIFICATE:
604 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
605 return GNUTLS_E_MEMORY_ERROR;
606 return MHD_init_daemon_certificate (daemon);
610 "Error: invalid credentials type %d specified.\n",
633 unsigned int fd_setsize)
637 #ifdef MHD_WINSOCK_SOCKETS 638 if (set->fd_count >= fd_setsize)
640 if (FD_ISSET(fd,
set))
681 fd_set *write_fd_set,
682 fd_set *except_fd_set,
686 write_fd_set, except_fd_set,
714 fd_set *write_fd_set,
715 fd_set *except_fd_set,
717 unsigned int fd_setsize)
721 if ( (
NULL == daemon)
722 || (
NULL == read_fd_set)
723 || (
NULL == write_fd_set)
734 return add_to_fd_set (daemon->epoll_fd, read_fd_set, max_fd, fd_setsize);
770 "Maximum socket in select set: %d\n",
785 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
795 unsigned int timeout;
803 #define EXTRA_SLOTS 1 805 #define EXTRA_SLOTS 0 808 struct pollfd p[1 + EXTRA_SLOTS];
817 if (
MHD_YES == con->tls_read_ready)
825 if (
NULL == tvp && timeout > 0)
832 const time_t seconds_left = timeout - (now - con->
last_activity);
834 tv.tv_sec = seconds_left;
893 "Can't add FD to fd_set\n");
905 "Error during select (%d): `%s'\n",
914 (FD_ISSET (spipe, &rs)) )
920 || (
MHD_YES == con->tls_read_ready)
933 memset (&p, 0,
sizeof (p));
938 p[0].events |= POLLIN;
941 p[0].events |= POLLOUT;
943 p[0].events |= POLLIN;
947 p[0].events |= POLLIN;
960 p[1].events |= POLLIN;
966 if (MHD_sys_poll_ (p,
972 (
NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
978 "Error during poll: `%s'\n",
986 (0 != (p[1].revents & (POLLERR | POLLHUP))) )
989 if ( (0 != (p[0].revents & POLLIN))
991 || (
MHD_YES == con->tls_read_ready)
995 if (0 != (p[0].revents & POLLOUT))
997 if (0 != (p[0].revents & (POLLERR | POLLHUP)))
1010 "Processing thread terminating, closing connection\n");
1031 return (MHD_THRD_RTRN_TYPE_) 0;
1050 const size_t requested_size = i;
1059 #ifdef MHD_POSIX_SOCKETS 1069 if ( (0 > ret) || (requested_size > (size_t) ret))
1094 const size_t requested_size = i;
1106 #ifdef MHD_POSIX_SOCKETS 1126 #ifndef HAVE_SENDFILE64 1133 #ifndef HAVE_SENDFILE64 1134 offset = (off_t) offsetu64;
1135 if ( (offsetu64 <= (uint64_t)
OFF_T_MAX) &&
1136 (0 < (ret = sendfile (connection->
socket_fd, fd, &offset, left))) )
1138 offset = (off64_t) offsetu64;
1139 if ( (offsetu64 <= (uint64_t) OFF64_T_MAX) &&
1140 (0 < (ret = sendfile64 (connection->
socket_fd, fd, &offset, left))) )
1144 if (requested_size > (
size_t) ret)
1153 if ( (EINTR == err) || (EAGAIN == err) || (
EWOULDBLOCK == err) )
1155 if ( (EINVAL == err) || (EBADF == err) )
1165 if ( (0 > ret) || (requested_size > (size_t) ret) )
1204 #if defined(MHD_USE_POSIX_THREADS) 1205 pthread_attr_t attr;
1206 pthread_attr_t *pattr;
1211 if (0 != (ret = pthread_attr_init (&attr)))
1215 pthread_attr_destroy (&attr);
1224 ret = pthread_create (thread, pattr,
1225 start_routine, arg);
1226 #ifdef HAVE_PTHREAD_SETNAME_NP 1227 (void) pthread_setname_np (*thread,
"libmicrohttpd");
1230 pthread_attr_destroy (&attr);
1235 "Failed to set thread stack size\n");
1239 #elif defined(MHD_USE_W32_THREADS) 1243 if (
NULL == (*thread))
1282 const struct sockaddr *addr,
1287 int res_thread_create;
1318 #ifndef MHD_WINSOCK_SOCKETS 1319 if ( (client_socket >= FD_SETSIZE) &&
1324 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
1341 "Accepted connection on socket %d\n",
1351 "Server reached connection limit (closing inbound connection)\n");
1369 "Connection rejected, closing connection\n");
1384 setsockopt (client_socket,
1385 SOL_SOCKET, SO_NOSIGPIPE,
1396 "Error allocating memory: %s\n",
1413 "Error allocating memory: %s\n",
1427 if (
NULL == (connection->
addr = malloc (addrlen)))
1432 "Error allocating memory: %s\n",
1443 memcpy (connection->
addr, addr, addrlen);
1446 connection->
daemon = daemon;
1465 #if !defined(MHD_WINSOCK_SOCKETS) 1466 int flags = fcntl (connection->
socket_fd, F_GETFL);
1467 if ( (-1 == flags) ||
1468 (0 != fcntl (connection->
socket_fd, F_SETFL, flags | O_NONBLOCK)) )
1472 "Failed to make socket non-blocking: %s\n",
1477 unsigned long flags = 1;
1478 if (0 != ioctlsocket (connection->
socket_fd, FIONBIO, &flags))
1482 "Failed to make socket non-blocking: %s\n",
1493 connection->
recv_cls = &recv_tls_adapter;
1494 connection->
send_cls = &send_tls_adapter;
1497 gnutls_init (&connection->tls_session, GNUTLS_SERVER);
1498 gnutls_priority_set (connection->tls_session,
1499 daemon->priority_cache);
1500 switch (daemon->cred_type)
1503 case GNUTLS_CRD_CERTIFICATE:
1504 gnutls_credentials_set (connection->tls_session,
1505 GNUTLS_CRD_CERTIFICATE,
1510 MHD_DLOG (connection->
daemon,
1511 "Failed to setup TLS credentials: unknown credential type %d\n",
1517 free (connection->
addr);
1525 gnutls_transport_set_ptr (connection->tls_session,
1526 (gnutls_transport_ptr_t) connection);
1527 gnutls_transport_set_pull_function (connection->tls_session,
1529 gnutls_transport_set_push_function (connection->tls_session,
1532 if (daemon->https_mem_trust)
1533 gnutls_certificate_server_set_request (connection->tls_session,
1534 GNUTLS_CERT_REQUEST);
1540 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1549 MHD_PANIC (
"Failed to release cleanup mutex\n");
1564 if (0 != res_thread_create)
1569 "Failed to create a thread: %s\n",
1576 if ( (
MHD_YES == external_add) &&
1582 "failed to signal new connection via pipe");
1590 struct epoll_event event;
1592 event.events = EPOLLIN | EPOLLOUT | EPOLLET;
1593 event.data.ptr = connection;
1594 if (0 != epoll_ctl (daemon->epoll_fd,
1602 "Call to epoll_ctl failed: %s\n",
1614 daemon->eready_tail,
1632 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1641 MHD_PANIC (
"Failed to release cleanup mutex\n");
1643 free (connection->
addr);
1684 daemon = connection->
daemon;
1686 MHD_PANIC (
"Cannot suspend connections without enabling MHD_USE_SUSPEND_RESUME!\n");
1689 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1710 daemon->eready_tail,
1716 if (0 != epoll_ctl (daemon->epoll_fd,
1720 MHD_PANIC (
"Failed to remove FD from epoll set\n");
1729 MHD_PANIC (
"Failed to release cleanup mutex\n");
1746 daemon = connection->
daemon;
1748 MHD_PANIC (
"Cannot resume connections without enabling MHD_USE_SUSPEND_RESUME!\n");
1751 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1759 "failed to signal resume via pipe");
1764 MHD_PANIC (
"Failed to release cleanup mutex\n");
1785 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1789 while (
NULL != (pos = next))
1813 MHD_PANIC (
"Resumed connection was already in EREADY set\n");
1817 daemon->eready_tail,
1829 MHD_PANIC (
"Failed to release cleanup mutex\n");
1844 #ifdef MHD_WINSOCK_SOCKETS 1846 unsigned long flags = 1;
1848 if (0 != ioctlsocket (sock, FIONBIO, &flags))
1852 "Failed to make socket non-blocking: %s\n",
1856 if (!GetHandleInformation ((HANDLE) sock, &dwFlags) ||
1857 ((dwFlags != (dwFlags & ~HANDLE_FLAG_INHERIT)) &&
1858 !SetHandleInformation ((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)))
1862 "Failed to make socket non-inheritable: %u\n",
1863 (
unsigned int) GetLastError ());
1870 nonblock = O_NONBLOCK;
1875 flags = fcntl (sock, F_GETFD);
1876 if ( ( (-1 == flags) ||
1877 ( (flags != (flags | FD_CLOEXEC)) &&
1878 (0 != fcntl (sock, F_SETFD, flags | nonblock | FD_CLOEXEC)) ) ) )
1882 "Failed to make socket non-inheritable: %s\n",
1922 const struct sockaddr *
addr,
1950 struct sockaddr_in6 addrstorage;
1952 struct sockaddr_in addrstorage;
1954 struct sockaddr *addr = (
struct sockaddr *) &addrstorage;
1960 addrlen =
sizeof (addrstorage);
1961 memset (addr, 0,
sizeof (addrstorage));
1964 #ifdef HAVE_SOCK_NONBLOCK 1965 nonblock = SOCK_NONBLOCK;
1974 s = accept4 (fd, addr, &addrlen,
SOCK_CLOEXEC | nonblock);
1976 s = accept (fd, addr, &addrlen);
1983 if ( (EINVAL == err) &&
1988 "Error accepting connection: %s\n",
1999 #if !defined(HAVE_ACCEPT4) || HAVE_ACCEPT4+0 == 0 || !defined(HAVE_SOCK_NONBLOCK) || SOCK_CLOEXEC+0 == 0 2005 "Accepted connection on socket %d\n",
2030 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
2039 if (0 != MHD_join_thread_ (pos->
pid))
2041 MHD_PANIC (
"Failed to join a thread\n");
2046 if (
NULL != pos->tls_session)
2047 gnutls_deinit (pos->tls_session);
2060 daemon->eready_tail,
2074 if (0 != epoll_ctl (daemon->epoll_fd,
2078 MHD_PANIC (
"Failed to remove FD from epoll set\n");
2101 MHD_PANIC (
"Failed to release cleanup mutex\n");
2123 time_t earliest_deadline;
2132 "Illegal call to MHD_get_timeout\n");
2138 if (0 != daemon->num_tls_read_ready)
2148 earliest_deadline = 0;
2153 if ( (! have_timeout) ||
2158 (0 != gnutls_record_check_pending (pos->tls_session)) )
2159 earliest_deadline = 0;
2166 if ( (
NULL != pos) &&
2169 if ( (! have_timeout) ||
2174 (0 != gnutls_record_check_pending (pos->tls_session)) )
2175 earliest_deadline = 0;
2180 if (
MHD_NO == have_timeout)
2183 if (earliest_deadline < now)
2187 const time_t second_left = earliest_deadline - now;
2188 if (second_left > ULLONG_MAX / 1000)
2189 *timeout = ULLONG_MAX;
2191 *timeout = 1000 * second_left;
2218 const fd_set *read_fd_set,
2219 const fd_set *write_fd_set,
2220 const fd_set *except_fd_set)
2238 if (daemon->epoll_fd >= FD_SETSIZE)
2240 if (FD_ISSET (daemon->epoll_fd, read_fd_set))
2248 (FD_ISSET (ds, read_fd_set)) )
2252 (FD_ISSET (daemon->
wpipe[0], read_fd_set)) )
2259 while (
NULL != (pos = next))
2268 if ( (FD_ISSET (ds, read_fd_set))
2270 || (
MHD_YES == pos->tls_read_ready)
2276 if ( (FD_ISSET (ds, read_fd_set)) &&
2279 if (FD_ISSET (ds, write_fd_set))
2283 if ( (FD_ISSET (ds, read_fd_set)) &&
2316 struct timeval timeout;
2321 timeout.tv_usec = 0;
2368 timeout.tv_usec = 0;
2376 timeout.tv_usec = (ltimeout % 1000) * 1000;
2392 "select failed: %s\n",
2414 unsigned int num_connections;
2423 num_connections = 0;
2430 unsigned int poll_server;
2436 p = malloc(
sizeof (
struct pollfd) * (2 + num_connections));
2441 "Error allocating memory: %s\n",
2446 memset (p, 0,
sizeof (
struct pollfd) * (2 + num_connections));
2454 p[poll_server].events = POLLIN;
2455 p[poll_server].revents = 0;
2456 poll_listen = (int) poll_server;
2462 p[poll_server].fd = daemon->
wpipe[0];
2463 p[poll_server].events = POLLIN;
2464 p[poll_server].revents = 0;
2465 poll_pipe = (int) poll_server;
2474 timeout = (ltimeout > INT_MAX) ? INT_MAX : (
int) ltimeout;
2483 p[poll_server+i].events |= POLLIN;
2486 p[poll_server+i].events |= POLLOUT;
2488 p[poll_server+i].events |= POLLIN;
2492 p[poll_server+i].events |= POLLIN;
2500 if (0 == poll_server + num_connections)
2505 if (MHD_sys_poll_(p, poll_server + num_connections, timeout) < 0)
2514 "poll failed: %s\n",
2528 while (
NULL != (pos = next))
2535 if (i >= num_connections)
2540 if (0 != (p[poll_server+i].revents & POLLIN))
2547 if (i >= num_connections)
2552 if (0 != (p[poll_server+i].revents & POLLIN))
2554 if (0 != (p[poll_server+i].revents & POLLOUT))
2560 if (0 != (p[poll_server+i].revents & POLLIN))
2570 if ( (-1 != poll_listen) &&
2571 (0 != (p[poll_listen].revents & POLLIN)) )
2575 if ( (-1 != poll_pipe) &&
2576 (0 != (p[poll_pipe].revents & POLLIN)) )
2593 MHD_poll_listen_socket (
struct MHD_Daemon *daemon,
2598 unsigned int poll_count;
2601 memset (&p, 0,
sizeof (p));
2607 p[poll_count].events = POLLIN;
2608 p[poll_count].revents = 0;
2609 poll_listen = poll_count;
2614 p[poll_count].fd = daemon->
wpipe[0];
2615 p[poll_count].events = POLLIN;
2616 p[poll_count].revents = 0;
2623 if (0 == poll_count)
2625 if (MHD_sys_poll_(p, poll_count, timeout) < 0)
2631 "poll failed: %s\n",
2639 if ( (-1 != poll_listen) &&
2640 (0 != (p[poll_listen].revents & POLLIN)) )
2662 return MHD_poll_all (daemon, may_block);
2664 return MHD_poll_listen_socket (daemon, may_block);
2681 #define MAX_EVENTS 128 2698 struct epoll_event events[MAX_EVENTS];
2699 struct epoll_event event;
2704 unsigned int series_length;
2707 if (-1 == daemon->epoll_fd)
2713 (
MHD_NO == daemon->listen_socket_in_epoll) )
2715 event.events = EPOLLIN;
2716 event.data.ptr = daemon;
2717 if (0 != epoll_ctl (daemon->epoll_fd,
2724 "Call to epoll_ctl failed: %s\n",
2729 daemon->listen_socket_in_epoll =
MHD_YES;
2731 if ( (
MHD_YES == daemon->listen_socket_in_epoll) &&
2736 if (0 != epoll_ctl (daemon->epoll_fd,
2740 MHD_PANIC (
"Failed to remove listen FD from epoll set\n");
2741 daemon->listen_socket_in_epoll =
MHD_NO;
2749 timeout_ms = INT_MAX;
2751 timeout_ms = (int) timeout_ll;
2763 num_events = MAX_EVENTS;
2764 while (MAX_EVENTS == num_events)
2767 num_events = epoll_wait (daemon->epoll_fd,
2768 events, MAX_EVENTS, timeout_ms);
2769 if (-1 == num_events)
2775 "Call to epoll_wait failed: %s\n",
2780 for (i=0;i<(
unsigned int) num_events;i++)
2785 (daemon->
wpipe[0] == events[i].data.fd) )
2790 if (daemon != events[i].
data.ptr)
2795 pos = events[i].data.ptr;
2796 if (0 != (events[i].events & EPOLLIN))
2804 daemon->eready_tail,
2809 if (0 != (events[i].events & EPOLLOUT))
2816 daemon->eready_tail,
2829 (series_length < 128) )
2842 while (
NULL != (pos = daemon->eready_tail))
2845 daemon->eready_tail,
2864 while (
NULL != (pos = next))
2874 while (
NULL != (pos = next))
2920 MHD_epoll (daemon,
MHD_NO);
2940 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
2957 return (MHD_THRD_RTRN_TYPE_)0;
3007 va_start (ap, dh_cls);
3047 "Using MHD_quiesce_daemon in this mode requires MHD_USE_PIPE_FOR_SHUTDOWN\n");
3061 if (0 != epoll_ctl (daemon->
worker_pool[i].epoll_fd,
3065 MHD_PANIC (
"Failed to remove listen FD from epoll set\n");
3073 (-1 != daemon->epoll_fd) &&
3074 (
MHD_YES == daemon->listen_socket_in_epoll) )
3076 if (0 != epoll_ctl (daemon->epoll_fd,
3080 MHD_PANIC (
"Failed to remove listen FD from epoll set\n");
3081 daemon->listen_socket_in_epoll =
MHD_NO;
3110 const struct sockaddr **servaddr,
3124 const struct sockaddr **servaddr,
3130 va_start (ap, servaddr);
3147 const struct sockaddr **servaddr,
3163 daemon->
pool_size = va_arg (ap,
size_t);
3188 *servaddr = va_arg (ap,
const struct sockaddr *);
3201 "Specified thread pool size (%u) too big\n",
3210 daemon->https_mem_key = va_arg (ap,
const char *);
3214 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
3220 daemon->https_key_password = va_arg (ap,
const char *);
3224 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
3230 daemon->https_mem_cert = va_arg (ap,
const char *);
3234 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
3240 daemon->https_mem_trust = va_arg (ap,
const char *);
3244 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
3249 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
int);
3254 const char *arg = va_arg (ap,
const char *);
3255 gnutls_datum_t dhpar;
3257 if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
3261 "Error initializing DH parameters\n");
3265 dhpar.data = (
unsigned char *) arg;
3266 dhpar.size = strlen (arg);
3267 if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams, &dhpar,
3268 GNUTLS_X509_FMT_PEM) < 0)
3272 "Bad Diffie-Hellman parameters format\n");
3274 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
3277 daemon->have_dhparams =
MHD_YES;
3283 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
3292 gnutls_priority_deinit (daemon->priority_cache);
3293 ret = gnutls_priority_init (&daemon->priority_cache,
3294 pstr = va_arg (ap,
const char*),
3296 if (GNUTLS_E_SUCCESS != ret)
3300 "Setting priorities to `%s' failed: %s\n",
3302 gnutls_strerror (ret));
3304 daemon->priority_cache =
NULL;
3310 #if GNUTLS_VERSION_MAJOR < 3 3313 "MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n");
3318 daemon->cert_callback = va_arg (ap, gnutls_certificate_retrieve_function2 *);
3322 #ifdef DAUTH_SUPPORT 3324 daemon->digest_auth_rand_size = va_arg (ap,
size_t);
3325 daemon->digest_auth_random = va_arg (ap,
const char *);
3328 daemon->nonce_nc_size = va_arg (ap,
unsigned int);
3336 daemon->custom_error_log =
3338 daemon->custom_error_log_cls = va_arg (ap,
void *);
3341 va_arg (ap,
void *);
3349 daemon->fastopen_queue_size = va_arg (ap,
unsigned int);
3369 (
size_t) oa[i].
value,
3384 (
unsigned int) oa[i].value,
3432 (
void *) oa[i].value,
3442 (
size_t) oa[i].value,
3464 "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
3470 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
3491 int domain,
int type,
int protocol)
3498 fd = socket (domain, ctype, protocol);
3502 fd = socket(domain, type, protocol);
3521 setup_epoll_to_listen (
struct MHD_Daemon *daemon)
3523 struct epoll_event event;
3525 #ifdef HAVE_EPOLL_CREATE1 3528 daemon->epoll_fd = epoll_create (MAX_EVENTS);
3530 if (-1 == daemon->epoll_fd)
3534 "Call to epoll_create1 failed: %s\n",
3539 #ifndef HAVE_EPOLL_CREATE1 3542 int fdflags = fcntl (daemon->epoll_fd, F_GETFD);
3543 if (0 > fdflags || 0 > fcntl (daemon->epoll_fd, F_SETFD, fdflags | FD_CLOEXEC))
3547 "Failed to change flags on epoll fd: %s\n",
3558 event.events = EPOLLIN;
3559 event.data.ptr = daemon;
3560 if (0 != epoll_ctl (daemon->epoll_fd,
3567 "Call to epoll_ctl failed: %s\n",
3575 event.events = EPOLLIN | EPOLLET;
3576 event.data.ptr =
NULL;
3577 event.data.fd = daemon->
wpipe[0];
3578 if (0 != epoll_ctl (daemon->epoll_fd,
3585 "Call to epoll_ctl failed: %s\n",
3591 daemon->listen_socket_in_epoll =
MHD_YES;
3622 #if defined(MHD_POSIX_SOCKETS) 3624 #elif defined(MHD_WINSOCK_SOCKETS) 3625 const uint32_t on = 1;
3629 struct sockaddr_in servaddr4;
3631 struct sockaddr_in6 servaddr6;
3633 const struct sockaddr *servaddr =
NULL;
3636 int res_thread_create;
3651 #ifndef TCP_FASTOPEN 3659 memset (daemon, 0,
sizeof (
struct MHD_Daemon));
3661 daemon->epoll_fd = -1;
3665 if (0 != (flags & MHD_USE_SSL))
3667 gnutls_priority_init (&daemon->priority_cache,
3675 #if defined(MHD_WINSOCK_SOCKETS) || defined(CYGWIN) 3680 daemon->
port = port;
3695 daemon->custom_error_log_cls = stderr;
3697 #ifdef HAVE_LISTEN_SHUTDOWN 3708 "Failed to create control pipe: %s\n",
3714 #ifndef MHD_WINSOCK_SOCKETS 3717 (daemon->
wpipe[0] >= FD_SETSIZE) )
3721 "file descriptor for control pipe exceeds maximum value\n");
3731 #ifdef DAUTH_SUPPORT 3732 daemon->digest_auth_rand_size = 0;
3733 daemon->digest_auth_random =
NULL;
3734 daemon->nonce_nc_size = 4;
3737 if (0 != (flags & MHD_USE_SSL))
3739 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
3747 if ( (0 != (flags & MHD_USE_SSL)) &&
3748 (
NULL != daemon->priority_cache) )
3749 gnutls_priority_deinit (daemon->priority_cache);
3754 #ifdef DAUTH_SUPPORT 3755 if (daemon->nonce_nc_size > 0)
3757 if ( ( (
size_t) (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc))) /
3758 sizeof(
struct MHD_NonceNc) != daemon->nonce_nc_size)
3762 "Specified value for NC_SIZE too large\n");
3765 if (0 != (flags & MHD_USE_SSL))
3766 gnutls_priority_deinit (daemon->priority_cache);
3771 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc));
3772 if (
NULL == daemon->nnc)
3776 "Failed to allocate memory for nonce-nc map: %s\n",
3780 if (0 != (flags & MHD_USE_SSL))
3781 gnutls_priority_deinit (daemon->priority_cache);
3788 if (
MHD_YES != MHD_mutex_create_ (&daemon->nnc_lock))
3792 "MHD failed to initialize nonce-nc mutex\n");
3795 if (0 != (flags & MHD_USE_SSL))
3796 gnutls_priority_deinit (daemon->priority_cache);
3810 "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n");
3820 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_SUSPEND_RESUME is not supported.\n");
3825 #ifdef __SYMBIAN32__ 3826 if (0 != (flags & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
3830 "Threaded operations are not supported on Symbian.\n");
3839 if (0 != (flags & MHD_USE_IPv6))
3841 PF_INET6, SOCK_STREAM, 0);
3844 PF_INET, SOCK_STREAM, 0);
3849 "Call to socket failed: %s\n",
3860 if (0 > setsockopt (socket_fd,
3863 (
void*)&on,
sizeof (on)))
3867 "setsockopt failed: %s\n",
3881 if (0 > setsockopt (socket_fd,
3884 (
void*)&on,
sizeof (on)))
3888 "setsockopt failed: %s\n",
3894 #ifndef SO_REUSEPORT 3899 #define SO_REUSEPORT 15 3903 if (0 > setsockopt (socket_fd,
3906 (
void*)&on,
sizeof (on)))
3910 "setsockopt failed: %s\n",
3920 "Cannot allow listening address reuse: SO_REUSEPORT not defined\n");
3933 #ifdef SO_EXCLUSIVEADDRUSE 3934 if (0 > setsockopt (socket_fd,
3936 SO_EXCLUSIVEADDRUSE,
3937 (
void*)&on,
sizeof (on)))
3941 "setsockopt failed: %s\n",
3949 "Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n");
3958 if (0 != (flags & MHD_USE_IPv6))
3959 addrlen =
sizeof (
struct sockaddr_in6);
3962 addrlen =
sizeof (
struct sockaddr_in);
3963 if (
NULL == servaddr)
3966 if (0 != (flags & MHD_USE_IPv6))
3968 memset (&servaddr6, 0,
sizeof (
struct sockaddr_in6));
3969 servaddr6.sin6_family = AF_INET6;
3970 servaddr6.sin6_port = htons (port);
3971 #if HAVE_SOCKADDR_IN_SIN_LEN 3972 servaddr6.sin6_len =
sizeof (
struct sockaddr_in6);
3974 servaddr = (
struct sockaddr *) &servaddr6;
3979 memset (&servaddr4, 0,
sizeof (
struct sockaddr_in));
3980 servaddr4.sin_family = AF_INET;
3981 servaddr4.sin_port = htons (port);
3982 #if HAVE_SOCKADDR_IN_SIN_LEN 3983 servaddr4.sin_len =
sizeof (
struct sockaddr_in);
3985 servaddr = (
struct sockaddr *) &servaddr4;
3990 if (0 != (flags & MHD_USE_IPv6))
3998 #ifndef MHD_WINSOCK_SOCKETS 4004 if (0 > setsockopt (socket_fd,
4005 IPPROTO_IPV6, IPV6_V6ONLY,
4006 (
const void*)&v6_only,
sizeof (v6_only)))
4010 "setsockopt failed: %s\n",
4017 if (-1 == bind (socket_fd, servaddr, addrlen))
4021 "Failed to bind to port %u: %s\n",
4022 (
unsigned int) port,
4030 if (0 != (flags & MHD_USE_TCP_FASTOPEN))
4032 if (0 == daemon->fastopen_queue_size)
4033 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
4034 if (0 != setsockopt (socket_fd,
4035 IPPROTO_TCP, TCP_FASTOPEN,
4036 &daemon->fastopen_queue_size,
4037 sizeof (daemon->fastopen_queue_size)))
4041 "setsockopt failed: %s\n",
4050 int sk_flags = fcntl (socket_fd, F_GETFL);
4051 if (0 != fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK))
4055 "Failed to make listen socket non-blocking: %s\n",
4064 if (listen (socket_fd, 32) < 0)
4068 "Failed to listen for connections: %s\n",
4080 #ifndef MHD_WINSOCK_SOCKETS 4081 if ( (socket_fd >= FD_SETSIZE) &&
4086 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
4101 if (0 != (flags & MHD_USE_THREAD_PER_CONNECTION))
4105 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL_LINUX_ONLY is not supported.\n");
4109 if (
MHD_YES != setup_epoll_to_listen (daemon))
4113 if (0 != (flags & MHD_USE_EPOLL_LINUX_ONLY))
4117 "epoll is not supported on this platform by this build.\n");
4127 "MHD failed to initialize IP connection limit mutex\n");
4138 "MHD failed to initialize IP connection limit mutex\n");
4149 if ((0 != (flags & MHD_USE_SSL)) && (0 != MHD_TLS_init (daemon)))
4153 "Failed to initialize TLS support\n");
4163 if ( ( (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) ||
4167 (0 != (res_thread_create =
4172 "Failed to create listen thread: %s\n",
4185 #if !defined(MHD_WINSOCK_SOCKETS) 4188 unsigned long sk_flags;
4204 #if !defined(MHD_WINSOCK_SOCKETS) 4205 sk_flags = fcntl (socket_fd, F_GETFL);
4208 if (0 != fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK))
4212 if (SOCKET_ERROR == ioctlsocket (socket_fd, FIONBIO, &sk_flags))
4228 memcpy (d, daemon,
sizeof (
struct MHD_Daemon));
4236 if ( (MHD_USE_SUSPEND_RESUME == (flags & MHD_USE_SUSPEND_RESUME)) &&
4241 "Failed to create worker control pipe: %s\n",
4246 #ifndef MHD_WINSOCK_SOCKETS 4247 if ( (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL_LINUX_ONLY))) &&
4248 (MHD_USE_SUSPEND_RESUME == (flags & MHD_USE_SUSPEND_RESUME)) &&
4249 (d->
wpipe[0] >= FD_SETSIZE) )
4253 "File descriptor for worker control pipe exceeds maximum value\n");
4267 if (i < leftover_conns)
4270 if ( (0 != (daemon->
options & MHD_USE_EPOLL_LINUX_ONLY)) &&
4271 (
MHD_YES != setup_epoll_to_listen (d)) )
4279 "MHD failed to initialize cleanup connection mutex for thread worker %d\n", i);
4285 if (0 != (res_thread_create =
4290 "Failed to create pool thread: %s\n",
4303 daemon->https_key_password =
NULL;
4337 if (-1 != daemon->epoll_fd)
4338 close (daemon->epoll_fd);
4340 #ifdef DAUTH_SUPPORT 4342 (void) MHD_mutex_destroy_ (&daemon->nnc_lock);
4345 if (0 != (flags & MHD_USE_SSL))
4346 gnutls_priority_deinit (daemon->priority_cache);
4402 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
4404 MHD_PANIC (
"MHD_stop_daemon() called while we have suspended connections.\n");
4409 #if MHD_WINSOCK_SOCKETS 4413 MHD_PANIC (
"Failed to signal shutdown via pipe");
4418 MHD_PANIC (
"Failed to release cleanup mutex\n");
4428 if (0 != MHD_join_thread_ (pos->
pid))
4429 MHD_PANIC (
"Failed to join a thread\n");
4444 MHD_PANIC (
"Failed to join a thread\n");
4460 struct epoll_event event;
4467 event.events = EPOLLOUT;
4468 event.data.ptr =
NULL;
4469 if (0 != epoll_ctl (daemon->epoll_fd,
4473 MHD_PANIC (
"Failed to add wpipe to epoll set to signal termination\n");
4514 MHD_PANIC (
"failed to signal shutdown via pipe");
4516 #ifdef HAVE_LISTEN_SHUTDOWN 4522 (void) shutdown (fd, SHUT_RDWR);
4527 (-1 != daemon->epoll_fd) &&
4529 epoll_shutdown (daemon);
4535 "MHD listen socket shutdown\n");
4549 MHD_PANIC (
"failed to signal shutdown via pipe");
4552 MHD_PANIC (
"Failed to join a thread\n");
4580 if (0 != MHD_join_thread_ (daemon->
pid))
4582 MHD_PANIC (
"Failed to join a thread\n");
4593 if (
MHD_YES == daemon->have_dhparams)
4595 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
4596 daemon->have_dhparams =
MHD_NO;
4600 gnutls_priority_deinit (daemon->priority_cache);
4601 if (daemon->x509_cred)
4602 gnutls_certificate_free_credentials (daemon->x509_cred);
4607 (-1 != daemon->epoll_fd) &&
4612 #ifdef DAUTH_SUPPORT 4614 (void) MHD_mutex_destroy_ (&daemon->nnc_lock);
4713 #ifdef PACKAGE_VERSION 4714 return PACKAGE_VERSION;
4716 static char ver[12] =
"\0\0\0\0\0\0\0\0\0\0\0";
4723 if (0 >= res ||
sizeof(ver) <= res)
4760 #if HTTPS_SUPPORT && GNUTLS_VERSION_MAJOR >= 3 4772 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) 4790 #ifdef HAVE_LISTEN_SHUTDOWN 4796 #ifdef MHD_DONT_USE_PIPES 4820 #if HAVE_POSTPROCESSOR 4826 #if HTTPS_SUPPORT && GNUTLS_VERSION_NUMBER >= 0x030111 4832 #if defined(HAVE___LSEEKI64) || defined(HAVE_LSEEK64) 4835 return (
sizeof(uint64_t) >
sizeof(off_t)) ?
MHD_NO :
MHD_YES;
4842 #if HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 4843 #if defined(MHD_USE_POSIX_THREADS) 4844 GCRY_THREAD_OPTION_PTHREAD_IMPL;
4845 #elif defined(MHD_W32_MUTEX_) 4848 gcry_w32_mutex_init (
void **ppmtx)
4850 *ppmtx = malloc (
sizeof (MHD_mutex_));
4854 if (
MHD_YES != MHD_mutex_create_ ((MHD_mutex_*)*ppmtx))
4866 gcry_w32_mutex_destroy (
void **ppmtx)
4868 int res = (
MHD_YES == MHD_mutex_destroy_ ((MHD_mutex_*)*ppmtx)) ? 0 : 1;
4875 gcry_w32_mutex_lock (
void **ppmtx)
4877 return (
MHD_YES == MHD_mutex_lock_ ((MHD_mutex_*)*ppmtx)) ? 0 : 1;
4882 gcry_w32_mutex_unlock (
void **ppmtx)
4884 return (
MHD_YES == MHD_mutex_unlock_ ((MHD_mutex_*)*ppmtx)) ? 0 : 1;
4888 static struct gcry_thread_cbs gcry_threads_w32 = {
4889 (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
4890 NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
4891 gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
4909 if (0 != WSAStartup(MAKEWORD(2, 2), &wsd))
4910 MHD_PANIC (
"Failed to initialize winsock\n");
4911 mhd_winsock_inited_ = 1;
4912 if (2 != LOBYTE(wsd.wVersion) && 2 != HIBYTE(wsd.wVersion))
4913 MHD_PANIC (
"Winsock version 2.2 is not available\n");
4916 #if GCRYPT_VERSION_NUMBER < 0x010600 4917 #if defined(MHD_USE_POSIX_THREADS) 4918 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread))
4919 MHD_PANIC (
"Failed to initialise multithreading in libgcrypt\n");
4920 #elif defined(MHD_W32_MUTEX_) 4921 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_w32))
4922 MHD_PANIC (
"Failed to initialise multithreading in libgcrypt\n");
4924 gcry_check_version (
NULL);
4926 if (
NULL == gcry_check_version (
"1.6.0"))
4927 MHD_PANIC (
"libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n");
4929 gnutls_global_init ();
4939 gnutls_global_deinit ();
4942 if (mhd_winsock_inited_)
unsigned int per_ip_connection_limit
void * unescape_callback_cls
#define XDLL_insert(head, tail, element)
_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 parse_options(struct MHD_Daemon *daemon, const struct sockaddr **servaddr,...)
_MHD_EXTERN const char * MHD_get_version(void)
static int MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
enum MHD_CONNECTION_STATE state
uint64_t response_write_position
#define EDLL_remove(head, tail, element)
void MHD_pool_destroy(struct MemoryPool *pool)
enum MHD_ConnectionEventLoopInfo event_loop_info
#define MHD_DEFAULT_FD_SETSIZE
#define DLL_remove(head, tail, element)
Methods for managing connections.
_MHD_EXTERN int MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
static int MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen, struct MHD_IPCount *key)
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
_MHD_EXTERN int MHD_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen)
static ssize_t send_param_adapter(struct MHD_Connection *connection, const void *other, size_t i)
struct MHD_Response * response
struct MHD_Connection * normal_timeout_tail
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ MHD_handle_connection(void *data)
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
MHD_AccessHandlerCallback default_handler
_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,...)
static void W32_SetThreadName(const DWORD thread_id, const char *thread_name)
#define MHD_MAX_CONNECTIONS_DEFAULT
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
Methods for managing response objects.
_MHD_EXTERN void MHD_set_panic_func(MHD_PanicCallback cb, void *cls)
#define MHD_UNSIGNED_LONG_LONG
void * uri_log_callback_cls
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
MHD_THRD_RTRN_TYPE_(MHD_THRD_CALL_SPEC_ * ThreadStartRoutine)(void *cls)
struct MHD_Connection * manual_timeout_head
MHD_NotifyConnectionCallback notify_connection
struct MHD_Connection * cleanup_head
struct MHD_Connection * cleanup_tail
static void close_connection(struct MHD_Connection *pos)
size_t write_buffer_send_offset
struct MHD_Daemon * worker_pool
static void mhd_panic_std(void *cls, const char *file, unsigned int line, const char *reason)
static void MHD_ip_limit_del(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
struct MHD_Connection * nextX
static void MHD_ip_count_unlock(struct MHD_Daemon *daemon)
struct MHD_Connection * manual_timeout_tail
void MHD_suspend_connection(struct MHD_Connection *connection)
void MHD_resume_connection(struct MHD_Connection *connection)
#define MHD_INVALID_SOCKET
internal shared structures
void MHD_set_https_callbacks(struct MHD_Connection *connection)
static int MHD_select(struct MHD_Daemon *daemon, int may_block)
unsigned int connection_limit
unsigned int worker_pool_size
_MHD_EXTERN 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
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
static void cleanup(struct Proxy *proxy)
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
Methods for managing connections.
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ MHD_select_thread(void *cls)
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 *))
void * tfind(const void *vkey, void *const *vrootp, int(*compar)(const void *, const void *))
_SET_INIT_AND_DEINIT_FUNCS(MHD_init, MHD_fini)
static void make_nonblocking_noninheritable(struct MHD_Daemon *daemon, MHD_socket sock)
limits values definitions
void MHD_monotonic_sec_counter_init(void)
UnescapeCallback unescape_callback
static int MHD_ip_addr_compare(const void *a1, const void *a2)
internal monotonic clock functions implementations
int(* write_handler)(struct MHD_Connection *connection)
static struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *daemon)
static int add_to_fd_set(MHD_socket fd, fd_set *set, MHD_socket *max_fd, unsigned int fd_setsize)
static MHD_socket create_socket(struct MHD_Daemon *daemon, int domain, int type, int protocol)
struct MHD_Connection * connections_head
struct MHD_Daemon * master
struct MHD_Connection * next
static int MHD_poll(struct MHD_Daemon *daemon, int may_block)
static int parse_options_va(struct MHD_Daemon *daemon, const struct sockaddr **servaddr, va_list ap)
MHD_AcceptPolicyCallback apc
unsigned int connection_timeout
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)
_MHD_EXTERN 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 int create_thread(MHD_thread_handle_ *thread, const struct MHD_Daemon *daemon, ThreadStartRoutine start_routine, void *arg)
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
MHD_RequestCompletedCallback notify_completed
struct MHD_Connection * prevX
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
#define MHD_POOL_SIZE_DEFAULT
static void close_all_connections(struct MHD_Daemon *daemon)
void * notify_completed_cls
struct MemoryPool * MHD_pool_create(size_t max)
TransmitCallback send_cls
_MHD_EXTERN int MHD_run(struct MHD_Daemon *daemon)
#define XDLL_remove(head, tail, element)
#define DLL_insert(head, tail, element)
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
#define TIMEVAL_TV_SEC_MAX
void * notify_connection_cls
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
static int resume_suspended_connections(struct MHD_Daemon *daemon)
static int internal_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, int external_add)
static size_t unescape_wrapper(void *cls, struct MHD_Connection *connection, char *val)
struct MHD_Connection * suspended_connections_tail
MHD_PanicCallback mhd_panic
void * per_ip_connection_count
_MHD_EXTERN int MHD_is_feature_supported(enum MHD_FEATURE feature)
size_t read_buffer_offset
_MHD_EXTERN 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
unsigned int connection_timeout
static int MHD_accept_connection(struct MHD_Daemon *daemon)
MHD_mutex_ cleanup_connection_mutex
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
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)
_MHD_EXTERN const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
_MHD_EXTERN size_t MHD_http_unescape(char *val)
struct MHD_Connection * connections_tail
void MHD_monotonic_sec_counter_finish(void)
#define EDLL_insert(head, tail, element)
struct MHD_Connection * suspended_connections_head
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...