50 #include <sys/sendfile.h>
54 #ifndef WIN32_LEAN_AND_MEAN
55 #define WIN32_LEAN_AND_MEAN 1
61 #define HAVE_ACCEPT4 0
68 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE - 4
70 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE
76 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
82 #define MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT 10
89 #define DEBUG_CLOSE MHD_NO
95 #define DEBUG_CONNECT MHD_NO
99 #define MSG_NOSIGNAL 0
104 #define SOCK_CLOEXEC 0
107 #ifndef EPOLL_CLOEXEC
108 #define EPOLL_CLOEXEC 0
128 fprintf (stderr,
"Fatal error in GNU libmicrohttpd %s:%u: %s\n",
149 static int mhd_winsock_inited_ = 0;
191 struct in6_addr ipv6;
212 MHD_PANIC (
"Failed to acquire IP connection limit mutex\n");
227 MHD_PANIC (
"Failed to release IP connection limit mutex\n");
244 return memcmp (a1, a2, offsetof (
struct MHD_IPCount, count));
259 struct MHD_IPCount *key)
261 memset(key, 0,
sizeof(*key));
264 if (
sizeof (
struct sockaddr_in) == addrlen)
266 const struct sockaddr_in *addr4 = (
const struct sockaddr_in*) addr;
267 key->family = AF_INET;
268 memcpy (&key->addr.ipv4, &addr4->sin_addr,
sizeof(addr4->sin_addr));
274 if (
sizeof (
struct sockaddr_in6) == addrlen)
276 const struct sockaddr_in6 *addr6 = (
const struct sockaddr_in6*) addr;
277 key->family = AF_INET6;
278 memcpy (&key->addr.ipv6, &addr6->sin6_addr,
sizeof(addr6->sin6_addr));
299 const struct sockaddr *addr,
302 struct MHD_IPCount *key;
312 if (
NULL == (key = malloc (
sizeof(*key))))
331 "Failed to add IP connection count node\n");
341 key = (
struct MHD_IPCount *) node;
363 const struct sockaddr *addr,
366 struct MHD_IPCount search_key;
367 struct MHD_IPCount *found_key;
387 MHD_PANIC (
"Failed to find previously-added IP address\n");
389 found_key = (
struct MHD_IPCount *) *nodep;
391 if (0 == found_key->count)
393 MHD_PANIC (
"Previously-added IP address had 0 count\n");
396 if (0 == --found_key->count)
418 recv_tls_adapter (
struct MHD_Connection *connection,
void *other,
size_t i)
422 if (
MHD_YES == connection->tls_read_ready)
424 connection->
daemon->num_tls_read_ready--;
425 connection->tls_read_ready =
MHD_NO;
427 res = gnutls_record_recv (connection->tls_session, other, i);
428 if ( (GNUTLS_E_AGAIN == res) ||
429 (GNUTLS_E_INTERRUPTED == res) )
447 connection->tls_read_ready =
MHD_YES;
448 connection->
daemon->num_tls_read_ready++;
464 const void *other,
size_t i)
468 res = gnutls_record_send (connection->tls_session, other, i);
469 if ( (GNUTLS_E_AGAIN == res) ||
470 (GNUTLS_E_INTERRUPTED == res) )
489 MHD_init_daemon_certificate (
struct MHD_Daemon *daemon)
494 #if GNUTLS_VERSION_MAJOR >= 3
495 if (
NULL != daemon->cert_callback)
497 gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
498 daemon->cert_callback);
501 if (
NULL != daemon->https_mem_trust)
503 cert.data = (
unsigned char *) daemon->https_mem_trust;
504 cert.size = strlen (daemon->https_mem_trust);
505 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred, &cert,
506 GNUTLS_X509_FMT_PEM) < 0)
510 "Bad trust certificate format\n");
517 if ( (
NULL != daemon->https_mem_cert) &&
518 (
NULL != daemon->https_mem_key) )
520 key.data = (
unsigned char *) daemon->https_mem_key;
521 key.size = strlen (daemon->https_mem_key);
522 cert.data = (
unsigned char *) daemon->https_mem_cert;
523 cert.size = strlen (daemon->https_mem_cert);
525 return gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
527 GNUTLS_X509_FMT_PEM);
529 #if GNUTLS_VERSION_MAJOR >= 3
530 if (
NULL != daemon->cert_callback)
534 MHD_DLOG (daemon,
"You need to specify a certificate and key location\n");
549 switch (daemon->cred_type)
551 case GNUTLS_CRD_CERTIFICATE:
553 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
554 return GNUTLS_E_MEMORY_ERROR;
555 return MHD_init_daemon_certificate (daemon);
559 "Error: invalid credentials type %d specified.\n",
608 fd_set *write_fd_set,
609 fd_set *except_fd_set,
615 if ( (
NULL == daemon)
616 || (
NULL == read_fd_set)
617 || (
NULL == write_fd_set)
618 || (
NULL == except_fd_set)
629 if (daemon->epoll_fd >= FD_SETSIZE)
631 FD_SET (daemon->epoll_fd, read_fd_set);
632 if ( (
NULL != max_fd) && ((*max_fd) < daemon->epoll_fd) )
633 *max_fd = daemon->epoll_fd;
640 FD_SET (fd, read_fd_set);
642 if ( (
NULL != max_fd) &&
670 MHD_DLOG (daemon,
"Maximum socket in select set: %d\n", *max_fd);
694 unsigned int timeout;
716 if (
MHD_YES == con->tls_read_ready)
758 "Error during select (%d): `%s'\n",
767 || (
MHD_YES == con->tls_read_ready)
780 memset (&p, 0,
sizeof (p));
785 p[0].events |= POLLIN;
788 p[0].events |= POLLOUT;
790 p[0].events |= POLLIN;
794 p[0].events |= POLLIN;
804 (
NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
809 MHD_DLOG (con->
daemon,
"Error during poll: `%s'\n",
814 if ( (0 != (p[0].revents & POLLIN))
816 || (
MHD_YES == con->tls_read_ready)
820 if (0 != (p[0].revents & POLLOUT))
822 if (0 != (p[0].revents & (POLLERR | POLLHUP)))
834 "Processing thread terminating, closing connection\n");
875 if (ret < (ssize_t) i)
922 if (left > SSIZE_MAX)
924 if (-1 != (ret = sendfile (connection->
socket_fd,
939 if ( (EINTR == err) || (EAGAIN == err) || (
EWOULDBLOCK == err) )
941 if ( (EINVAL == err) || (EBADF == err) )
951 if (ret < (ssize_t) i)
967 typedef void *(*ThreadStartRoutine)(
void *cls);
986 pthread_attr_t *pattr;
991 if (0 != (ret = pthread_attr_init (&attr)))
995 pthread_attr_destroy (&attr);
1004 ret = pthread_create (thread, pattr,
1005 start_routine, arg);
1006 #if (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)
1008 (void) pthread_setname_np (*thread,
"libmicrohttpd");
1012 pthread_attr_destroy (&attr);
1017 "Failed to set thread stack size\n");
1053 const struct sockaddr *addr,
1058 int res_thread_create;
1085 if ( (client_socket >= FD_SETSIZE) &&
1090 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
1106 MHD_DLOG (daemon,
"Accepted connection on socket %d\n", client_socket);
1115 "Server reached connection limit (closing inbound connection)\n");
1132 MHD_DLOG (daemon,
"Connection rejected, closing connection\n");
1147 setsockopt (client_socket,
1148 SOL_SOCKET, SO_NOSIGPIPE,
1159 "Error allocating memory: %s\n",
1174 "Error allocating memory: %s\n",
1188 if (
NULL == (connection->
addr = malloc (addrlen)))
1193 "Error allocating memory: %s\n",
1204 memcpy (connection->
addr, addr, addrlen);
1227 int flags = fcntl (connection->
socket_fd, F_GETFL);
1228 if ( (-1 == flags) ||
1229 (0 != fcntl (connection->
socket_fd, F_SETFL, flags | O_NONBLOCK)) )
1233 "Failed to make socket non-blocking: %s\n",
1238 unsigned long flags = 1;
1239 if (0 != ioctlsocket (connection->
socket_fd, FIONBIO, &flags))
1243 "Failed to make socket non-blocking: %s\n",
1254 connection->
recv_cls = &recv_tls_adapter;
1255 connection->
send_cls = &send_tls_adapter;
1258 gnutls_init (&connection->tls_session, GNUTLS_SERVER);
1259 gnutls_priority_set (connection->tls_session,
1260 daemon->priority_cache);
1261 switch (daemon->cred_type)
1264 case GNUTLS_CRD_CERTIFICATE:
1265 gnutls_credentials_set (connection->tls_session,
1266 GNUTLS_CRD_CERTIFICATE,
1271 MHD_DLOG (connection->
daemon,
1272 "Failed to setup TLS credentials: unknown credential type %d\n",
1278 free (connection->
addr);
1286 gnutls_transport_set_ptr (connection->tls_session,
1287 (gnutls_transport_ptr_t) connection);
1288 gnutls_transport_set_pull_function (connection->tls_session,
1290 gnutls_transport_set_push_function (connection->tls_session,
1293 if (daemon->https_mem_trust)
1294 gnutls_certificate_server_set_request (connection->tls_session,
1295 GNUTLS_CERT_REQUEST);
1301 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1310 MHD_PANIC (
"Failed to release cleanup mutex\n");
1317 if (0 != res_thread_create)
1321 MHD_DLOG (daemon,
"Failed to create a thread: %s\n",
1328 if ( (
MHD_YES == external_add) &&
1334 "failed to signal new connection via pipe");
1342 struct epoll_event event;
1344 event.events = EPOLLIN | EPOLLOUT | EPOLLET;
1345 event.data.ptr = connection;
1346 if (0 != epoll_ctl (daemon->epoll_fd,
1354 "Call to epoll_ctl failed: %s\n",
1366 daemon->eready_tail,
1379 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1388 MHD_PANIC (
"Failed to release cleanup mutex\n");
1390 free (connection->
addr);
1431 daemon = connection->
daemon;
1433 MHD_PANIC (
"Cannot suspend connections without enabling MHD_USE_SUSPEND_RESUME!\n");
1436 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1457 daemon->eready_tail,
1462 if (0 != epoll_ctl (daemon->epoll_fd,
1466 MHD_PANIC (
"Failed to remove FD from epoll set\n");
1475 MHD_PANIC (
"Failed to release cleanup mutex\n");
1492 daemon = connection->
daemon;
1494 MHD_PANIC (
"Cannot resume connections without enabling MHD_USE_SUSPEND_RESUME!\n");
1497 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1505 "failed to signal resume via pipe");
1510 MHD_PANIC (
"Failed to release cleanup mutex\n");
1527 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1532 while (
NULL != (pos = next))
1558 daemon->eready_tail,
1563 struct epoll_event event;
1565 event.events = EPOLLIN | EPOLLOUT | EPOLLET;
1566 event.data.ptr = pos;
1567 if (0 != epoll_ctl (daemon->epoll_fd,
1571 MHD_PANIC (
"Failed to add FD to epoll set\n");
1584 MHD_PANIC (
"Failed to release cleanup mutex\n");
1600 unsigned long flags = 1;
1602 if (0 != ioctlsocket (sock, FIONBIO, &flags))
1606 "Failed to make socket non-blocking: %s\n",
1610 if (!GetHandleInformation ((HANDLE) sock, &dwFlags) ||
1611 ((dwFlags != (dwFlags & ~HANDLE_FLAG_INHERIT)) &&
1612 !SetHandleInformation ((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)))
1616 "Failed to make socket non-inheritable: %u\n",
1617 (
unsigned int) GetLastError ());
1624 nonblock = O_NONBLOCK;
1629 flags = fcntl (sock, F_GETFD);
1630 if ( ( (-1 == flags) ||
1631 ( (flags != (flags | FD_CLOEXEC)) &&
1632 (0 != fcntl (sock, F_SETFD, flags | nonblock | FD_CLOEXEC)) ) ) )
1636 "Failed to make socket non-inheritable: %s\n",
1676 const struct sockaddr *addr,
1704 struct sockaddr_in6 addrstorage;
1706 struct sockaddr_in addrstorage;
1708 struct sockaddr *addr = (
struct sockaddr *) &addrstorage;
1714 addrlen =
sizeof (addrstorage);
1715 memset (addr, 0,
sizeof (addrstorage));
1718 #ifdef HAVE_SOCK_NONBLOCK
1719 nonblock = SOCK_NONBLOCK;
1728 s = accept4 (fd, addr, &addrlen,
SOCK_CLOEXEC | nonblock);
1730 s = accept (fd, addr, &addrlen);
1739 "Error accepting connection: %s\n",
1750 #if !defined(HAVE_ACCEPT4) || !defined(HAVE_SOCK_NONBLOCK) || SOCK_CLOEXEC+0 == 0
1755 MHD_DLOG (daemon,
"Accepted connection on socket %d\n", s);
1781 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1790 if (0 != (rc = pthread_join (pos->
pid, &unused)))
1792 MHD_PANIC (
"Failed to join a thread\n");
1797 if (pos->tls_session !=
NULL)
1798 gnutls_deinit (pos->tls_session);
1801 (
struct sockaddr *) pos->
addr,
1807 daemon->eready_tail,
1821 if (0 != epoll_ctl (daemon->epoll_fd,
1825 MHD_PANIC (
"Failed to remove FD from epoll set\n");
1849 MHD_PANIC (
"Failed to release cleanup mutex\n");
1871 time_t earliest_deadline;
1879 MHD_DLOG (daemon,
"Illegal call to MHD_get_timeout\n");
1885 if (0 != daemon->num_tls_read_ready)
1895 earliest_deadline = 0;
1900 if ( (! have_timeout) ||
1905 (0 != gnutls_record_check_pending (pos->tls_session)) )
1906 earliest_deadline = 0;
1913 if ( (
NULL != pos) &&
1916 if ( (! have_timeout) ||
1921 (0 != gnutls_record_check_pending (pos->tls_session)) )
1922 earliest_deadline = 0;
1927 if (
MHD_NO == have_timeout)
1930 if (earliest_deadline < now)
1933 *timeout = 1000 * (1 + earliest_deadline - now);
1959 const fd_set *read_fd_set,
1960 const fd_set *write_fd_set,
1961 const fd_set *except_fd_set)
1973 if (daemon->epoll_fd >= FD_SETSIZE)
1975 if (FD_ISSET (daemon->epoll_fd, read_fd_set))
1983 (FD_ISSET (ds, read_fd_set)) )
1987 (FD_ISSET (daemon->
wpipe[0], read_fd_set)) )
1994 while (
NULL != (pos = next))
2003 if ( (FD_ISSET (ds, read_fd_set))
2005 || (
MHD_YES == pos->tls_read_ready)
2011 if ( (FD_ISSET (ds, read_fd_set)) &&
2014 if (FD_ISSET (ds, write_fd_set))
2018 if ( (FD_ISSET (ds, read_fd_set)) &&
2051 struct timeval timeout;
2056 timeout.tv_usec = 0;
2089 FD_SET (daemon->
wpipe[0], &rs);
2092 max = daemon->
wpipe[0];
2098 timeout.tv_usec = 0;
2106 timeout.tv_usec = (ltimeout % 1000) * 1000;
2107 timeout.tv_sec = ltimeout / 1000;
2141 unsigned int num_connections;
2149 num_connections = 0;
2153 struct pollfd p[2 + num_connections];
2157 unsigned int poll_server;
2160 memset (p, 0,
sizeof (p));
2168 p[poll_server].events = POLLIN;
2169 p[poll_server].revents = 0;
2170 poll_listen = (int) poll_server;
2175 p[poll_server].fd = daemon->
wpipe[0];
2176 p[poll_server].events = POLLIN;
2177 p[poll_server].revents = 0;
2186 timeout = (ltimeout > INT_MAX) ? INT_MAX : (
int) ltimeout;
2195 p[poll_server+i].events |= POLLIN;
2198 p[poll_server+i].events |= POLLOUT;
2200 p[poll_server+i].events |= POLLIN;
2204 p[poll_server+i].events |= POLLIN;
2212 if (0 == poll_server + num_connections)
2214 if (poll (p, poll_server + num_connections, timeout) < 0)
2220 "poll failed: %s\n",
2230 while (
NULL != (pos = next))
2237 if (i >= num_connections)
2239 if (p[poll_server+i].fd != pos->
socket_fd)
2242 if (0 != (p[poll_server+i].revents & POLLIN))
2249 if (i >= num_connections)
2251 if (p[poll_server+i].fd != pos->
socket_fd)
2254 if (0 != (p[poll_server+i].revents & POLLIN))
2256 if (0 != (p[poll_server+i].revents & POLLOUT))
2262 if (0 != (p[poll_server+i].revents & POLLIN))
2272 if ( (-1 != poll_listen) &&
2273 (0 != (p[poll_listen].revents & POLLIN)) )
2288 MHD_poll_listen_socket (
struct MHD_Daemon *daemon,
2293 unsigned int poll_count;
2296 memset (&p, 0,
sizeof (p));
2302 p[poll_count].events = POLLIN;
2303 p[poll_count].revents = 0;
2304 poll_listen = poll_count;
2309 p[poll_count].fd = daemon->
wpipe[0];
2310 p[poll_count].events = POLLIN;
2311 p[poll_count].revents = 0;
2318 if (0 == poll_count)
2320 if (poll (p, poll_count, timeout) < 0)
2332 if ( (-1 != poll_listen) &&
2333 (0 != (p[poll_listen].revents & POLLIN)) )
2355 return MHD_poll_all (daemon, may_block);
2357 return MHD_poll_listen_socket (daemon, may_block);
2374 #define MAX_EVENTS 128
2391 struct epoll_event events[MAX_EVENTS];
2392 struct epoll_event event;
2397 unsigned int series_length;
2400 if (-1 == daemon->epoll_fd)
2406 (
MHD_NO == daemon->listen_socket_in_epoll) )
2408 event.events = EPOLLIN;
2409 event.data.ptr = daemon;
2410 if (0 != epoll_ctl (daemon->epoll_fd,
2418 "Call to epoll_ctl failed: %s\n",
2423 daemon->listen_socket_in_epoll =
MHD_YES;
2425 if ( (
MHD_YES == daemon->listen_socket_in_epoll) &&
2430 if (0 != epoll_ctl (daemon->epoll_fd,
2434 MHD_PANIC (
"Failed to remove listen FD from epoll set\n");
2435 daemon->listen_socket_in_epoll =
MHD_NO;
2443 timeout_ms = INT_MAX;
2445 timeout_ms = (int) timeout_ll;
2457 num_events = MAX_EVENTS;
2458 while (MAX_EVENTS == num_events)
2461 num_events = epoll_wait (daemon->epoll_fd,
2462 events, MAX_EVENTS, timeout_ms);
2463 if (-1 == num_events)
2470 "Call to epoll_wait failed: %s\n",
2475 for (i=0;i<(
unsigned int) num_events;i++)
2477 if (
NULL == events[i].data.ptr)
2480 (daemon->
wpipe[0] == events[i].data.fd) )
2485 if (daemon != events[i].data.ptr)
2490 pos = events[i].data.ptr;
2491 if (0 != (events[i].events & EPOLLIN))
2499 daemon->eready_tail,
2504 if (0 != (events[i].events & EPOLLOUT))
2511 daemon->eready_tail,
2524 (series_length < 128) )
2536 while (
NULL != (pos = daemon->eready_tail))
2539 daemon->eready_tail,
2557 while (
NULL != (pos = next))
2567 while (
NULL != (pos = next))
2613 MHD_epoll (daemon,
MHD_NO);
2680 va_start (ap, dh_cls);
2720 "Using MHD_quiesce_daemon in this mode requires MHD_USE_PIPE_FOR_SHUTDOWN\n");
2734 if (0 != epoll_ctl (daemon->
worker_pool[i].epoll_fd,
2738 MHD_PANIC (
"Failed to remove listen FD from epoll set\n");
2746 (-1 != daemon->epoll_fd) &&
2747 (
MHD_YES == daemon->listen_socket_in_epoll) )
2749 if (0 != epoll_ctl (daemon->epoll_fd,
2753 MHD_PANIC (
"Failed to remove listen FD from epoll set\n");
2754 daemon->listen_socket_in_epoll =
MHD_NO;
2783 const struct sockaddr **servaddr,
2797 const struct sockaddr **servaddr,
2803 va_start (ap, servaddr);
2820 const struct sockaddr **servaddr,
2836 daemon->
pool_size = va_arg (ap,
size_t);
2856 *servaddr = va_arg (ap,
const struct sockaddr *);
2869 "Specified thread pool size (%u) too big\n",
2878 daemon->https_mem_key = va_arg (ap,
const char *);
2882 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
2888 daemon->https_mem_cert = va_arg (ap,
const char *);
2892 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
2898 daemon->https_mem_trust = va_arg (ap,
const char *);
2902 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
2907 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
int);
2912 gnutls_priority_deinit (daemon->priority_cache);
2913 ret = gnutls_priority_init (&daemon->priority_cache,
2914 pstr = va_arg (ap,
const char*),
2916 if (ret != GNUTLS_E_SUCCESS)
2920 "Setting priorities to `%s' failed: %s\n",
2922 gnutls_strerror (ret));
2924 daemon->priority_cache =
NULL;
2930 #if GNUTLS_VERSION_MAJOR < 3
2933 "MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n");
2938 daemon->cert_callback = va_arg (ap, gnutls_certificate_retrieve_function2 *);
2942 #ifdef DAUTH_SUPPORT
2944 daemon->digest_auth_rand_size = va_arg (ap,
size_t);
2945 daemon->digest_auth_random = va_arg (ap,
const char *);
2948 daemon->nonce_nc_size = va_arg (ap,
unsigned int);
2956 daemon->custom_error_log =
2958 daemon->custom_error_log_cls = va_arg (ap,
void *);
2961 va_arg (ap,
void *);
2969 daemon->fastopen_queue_size = va_arg (ap,
unsigned int);
2986 (
size_t) oa[i].
value,
3000 (
unsigned int) oa[i].value,
3045 (
void *) oa[i].value,
3055 (
size_t) oa[i].value,
3077 "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
3083 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
3104 int domain,
int type,
int protocol)
3111 fd = socket (domain, ctype, protocol);
3115 fd = socket(domain, type, protocol);
3134 setup_epoll_to_listen (
struct MHD_Daemon *daemon)
3136 struct epoll_event event;
3139 if (-1 == daemon->epoll_fd)
3144 "Call to epoll_create1 failed: %s\n",
3154 event.events = EPOLLIN;
3155 event.data.ptr = daemon;
3156 if (0 != epoll_ctl (daemon->epoll_fd,
3164 "Call to epoll_ctl failed: %s\n",
3172 event.events = EPOLLIN | EPOLLET;
3173 event.data.ptr =
NULL;
3174 event.data.fd = daemon->
wpipe[0];
3175 if (0 != epoll_ctl (daemon->epoll_fd,
3183 "Call to epoll_ctl failed: %s\n",
3189 daemon->listen_socket_in_epoll =
MHD_YES;
3223 struct sockaddr_in servaddr4;
3225 struct sockaddr_in6 servaddr6;
3227 const struct sockaddr *servaddr =
NULL;
3230 int res_thread_create;
3245 #ifndef TCP_FASTOPEN
3253 memset (daemon, 0,
sizeof (
struct MHD_Daemon));
3255 daemon->epoll_fd = -1;
3259 if (0 != (flags & MHD_USE_SSL))
3261 gnutls_priority_init (&daemon->priority_cache,
3273 daemon->
port = port;
3287 daemon->custom_error_log_cls = stderr;
3289 #ifdef HAVE_LISTEN_SHUTDOWN
3300 "Failed to create control pipe: %s\n",
3307 if ( (0 == (flags & MHD_USE_POLL)) &&
3309 (daemon->
wpipe[0] >= FD_SETSIZE) )
3313 "file descriptor for control pipe exceeds maximum value\n");
3323 #ifdef DAUTH_SUPPORT
3324 daemon->digest_auth_rand_size = 0;
3325 daemon->digest_auth_random =
NULL;
3326 daemon->nonce_nc_size = 4;
3329 if (0 != (flags & MHD_USE_SSL))
3331 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
3339 if ( (0 != (flags & MHD_USE_SSL)) &&
3340 (
NULL != daemon->priority_cache) )
3341 gnutls_priority_deinit (daemon->priority_cache);
3346 #ifdef DAUTH_SUPPORT
3347 if (daemon->nonce_nc_size > 0)
3349 if ( ( (
size_t) (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc))) /
3350 sizeof(
struct MHD_NonceNc) != daemon->nonce_nc_size)
3354 "Specified value for NC_SIZE too large\n");
3357 if (0 != (flags & MHD_USE_SSL))
3358 gnutls_priority_deinit (daemon->priority_cache);
3363 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc));
3364 if (
NULL == daemon->nnc)
3368 "Failed to allocate memory for nonce-nc map: %s\n",
3372 if (0 != (flags & MHD_USE_SSL))
3373 gnutls_priority_deinit (daemon->priority_cache);
3380 if (0 != pthread_mutex_init (&daemon->nnc_lock,
NULL))
3384 "MHD failed to initialize nonce-nc mutex\n");
3387 if (0 != (flags & MHD_USE_SSL))
3388 gnutls_priority_deinit (daemon->priority_cache);
3402 "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n");
3412 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_SUSPEND_RESUME is not supported.\n");
3417 #ifdef __SYMBIAN32__
3418 if (0 != (flags & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
3422 "Threaded operations are not supported on Symbian.\n");
3432 if (0 != (flags & MHD_USE_THREAD_PER_CONNECTION))
3436 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL_LINUX_ONLY is not supported.\n");
3440 if (
MHD_YES != setup_epoll_to_listen (daemon))
3444 if (0 != (flags & MHD_USE_EPOLL_LINUX_ONLY))
3448 "epoll is not supported on this platform by this build.\n");
3457 if ((flags & MHD_USE_IPv6) != 0)
3459 PF_INET6, SOCK_STREAM, 0);
3462 PF_INET, SOCK_STREAM, 0);
3468 "Call to socket failed: %s\n",
3473 if ( (0 > setsockopt (socket_fd,
3476 (
void*)&on,
sizeof (on))) &&
3481 "setsockopt failed: %s\n",
3488 if (0 != (flags & MHD_USE_IPv6))
3489 addrlen =
sizeof (
struct sockaddr_in6);
3492 addrlen =
sizeof (
struct sockaddr_in);
3493 if (
NULL == servaddr)
3496 if (0 != (flags & MHD_USE_IPv6))
3498 memset (&servaddr6, 0,
sizeof (
struct sockaddr_in6));
3499 servaddr6.sin6_family = AF_INET6;
3500 servaddr6.sin6_port = htons (port);
3501 #if HAVE_SOCKADDR_IN_SIN_LEN
3502 servaddr6.sin6_len =
sizeof (
struct sockaddr_in6);
3504 servaddr = (
struct sockaddr *) &servaddr6;
3509 memset (&servaddr4, 0,
sizeof (
struct sockaddr_in));
3510 servaddr4.sin_family = AF_INET;
3511 servaddr4.sin_port = htons (port);
3512 #if HAVE_SOCKADDR_IN_SIN_LEN
3513 servaddr4.sin_len =
sizeof (
struct sockaddr_in);
3515 servaddr = (
struct sockaddr *) &servaddr4;
3520 if (0 != (flags & MHD_USE_IPv6))
3534 if ( (0 > setsockopt (socket_fd,
3535 IPPROTO_IPV6, IPV6_V6ONLY,
3536 &on,
sizeof (on))) &&
3541 "setsockopt failed: %s\n",
3548 if (-1 == bind (socket_fd, servaddr, addrlen))
3551 if (0 != (flags & MHD_USE_DEBUG))
3553 "Failed to bind to port %u: %s\n",
3554 (
unsigned int) port,
3562 if (0 != (flags & MHD_USE_TCP_FASTOPEN))
3564 if (0 == daemon->fastopen_queue_size)
3565 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
3566 if (0 != setsockopt (socket_fd,
3567 IPPROTO_TCP, TCP_FASTOPEN,
3568 &daemon->fastopen_queue_size,
3569 sizeof (daemon->fastopen_queue_size)))
3573 "setsockopt failed: %s\n",
3580 if (0 != (flags & MHD_USE_EPOLL_LINUX_ONLY))
3582 int sk_flags = fcntl (socket_fd, F_GETFL);
3583 if (0 != fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK))
3587 "Failed to make listen socket non-blocking: %s\n",
3596 if (listen (socket_fd, 32) < 0)
3599 if (0 != (flags & MHD_USE_DEBUG))
3601 "Failed to listen for connections: %s\n",
3614 if ( (socket_fd >= FD_SETSIZE) &&
3615 (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL_LINUX_ONLY)) ) )
3620 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
3634 "MHD failed to initialize IP connection limit mutex\n");
3645 "MHD failed to initialize IP connection limit mutex\n");
3656 if ((0 != (flags & MHD_USE_SSL)) && (0 != MHD_TLS_init (daemon)))
3660 "Failed to initialize TLS support\n");
3670 if ( ( (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) ||
3671 ( (0 != (flags & MHD_USE_SELECT_INTERNALLY)) &&
3674 (0 != (res_thread_create =
3679 "Failed to create listen thread: %s\n",
3695 unsigned long sk_flags;
3712 sk_flags = fcntl (socket_fd, F_GETFL);
3715 if (0 != fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK))
3719 if (SOCKET_ERROR == ioctlsocket (socket_fd, FIONBIO, &sk_flags))
3735 memcpy (d, daemon,
sizeof (
struct MHD_Daemon));
3743 if ( (MHD_USE_SUSPEND_RESUME == (flags & MHD_USE_SUSPEND_RESUME)) &&
3748 "Failed to create worker control pipe: %s\n",
3754 if ( (0 == (flags & MHD_USE_POLL)) &&
3755 (MHD_USE_SUSPEND_RESUME == (flags & MHD_USE_SUSPEND_RESUME)) &&
3756 (d->
wpipe[0] >= FD_SETSIZE) )
3760 "file descriptor for worker control pipe exceeds maximum value\n");
3774 if (i < leftover_conns)
3777 if ( (0 != (daemon->
options & MHD_USE_EPOLL_LINUX_ONLY)) &&
3778 (
MHD_YES != setup_epoll_to_listen (d)) )
3786 "MHD failed to initialize cleanup connection mutex for thread worker %d\n", i);
3792 if (0 != (res_thread_create =
3797 "Failed to create pool thread: %s\n",
3838 if (-1 != daemon->epoll_fd)
3839 close (daemon->epoll_fd);
3841 #ifdef DAUTH_SUPPORT
3843 pthread_mutex_destroy (&daemon->nnc_lock);
3846 if (0 != (flags & MHD_USE_SSL))
3847 gnutls_priority_deinit (daemon->priority_cache);
3903 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
3909 MHD_PANIC (
"Failed to release cleanup mutex\n");
3916 if (0 != (rc = pthread_join (pos->
pid, &unused)))
3917 MHD_PANIC (
"Failed to join a thread\n");
3938 struct epoll_event event;
3945 event.events = EPOLLOUT;
3946 event.data.ptr =
NULL;
3947 if (0 != epoll_ctl (daemon->epoll_fd,
3951 MHD_PANIC (
"Failed to add wpipe to epoll set to signal termination\n");
3994 MHD_PANIC (
"failed to signal shutdown via pipe");
3996 #ifdef HAVE_LISTEN_SHUTDOWN
4001 (void) shutdown (fd, SHUT_RDWR);
4006 (-1 != daemon->epoll_fd) &&
4008 epoll_shutdown (daemon);
4013 MHD_DLOG (daemon,
"MHD listen socket shutdown\n");
4027 MHD_PANIC (
"failed to signal shutdown via pipe");
4029 if (0 != (rc = pthread_join (daemon->
worker_pool[i].
pid, &unused)))
4030 MHD_PANIC (
"Failed to join a thread\n");
4058 if (0 != (rc = pthread_join (daemon->
pid, &unused)))
4060 MHD_PANIC (
"Failed to join a thread\n");
4073 gnutls_priority_deinit (daemon->priority_cache);
4074 if (daemon->x509_cred)
4075 gnutls_certificate_free_credentials (daemon->x509_cred);
4080 (-1 != daemon->epoll_fd) &&
4085 #ifdef DAUTH_SUPPORT
4087 pthread_mutex_destroy (&daemon->nnc_lock);
4170 return PACKAGE_VERSION;
4175 #define FUNC_CONSTRUCTOR(f) static void __attribute__ ((constructor)) f
4176 #define FUNC_DESTRUCTOR(f) static void __attribute__ ((destructor)) f
4178 #define FUNC_CONSTRUCTOR(f) _MHD_EXTERN void f
4179 #define FUNC_DESTRUCTOR(f) _MHD_EXTERN void f
4183 #if GCRYPT_VERSION_NUMBER < 0x010600
4184 GCRY_THREAD_OPTION_PTHREAD_IMPL;
4199 if (0 != WSAStartup(MAKEWORD(2, 2), &wsd))
4200 MHD_PANIC (
"Failed to initialize winsock\n");
4201 mhd_winsock_inited_ = 1;
4202 if (2 != LOBYTE(wsd.wVersion) && 2 != HIBYTE(wsd.wVersion))
4203 MHD_PANIC (
"Winsock version 2.2 is not available\n");
4206 #if GCRYPT_VERSION_NUMBER < 0x010600
4207 gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
4209 gcry_check_version (
NULL);
4210 gnutls_global_init ();
4218 gnutls_global_deinit ();
4221 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,...)
pthread_mutex_t per_ip_connection_mutex
_MHD_EXTERN const char * MHD_get_version(void)
pthread_mutex_t cleanup_connection_mutex
static int MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
int(* write_handler)(struct MHD_Connection *connection)
enum MHD_CONNECTION_STATE state
int(* idle_handler)(struct MHD_Connection *connection)
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 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)
_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
void(* MHD_RequestCompletedCallback)(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
struct MHD_Connection * normal_timeout_tail
#define FUNC_CONSTRUCTOR(f)
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
MHD_AccessHandlerCallback default_handler
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
#define FUNC_DESTRUCTOR(f)
_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_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
int(* read_handler)(struct MHD_Connection *connection)
struct MHD_Daemon * daemon
struct MHD_Connection * manual_timeout_head
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
static int create_thread(pthread_t *thread, const struct MHD_Daemon *daemon, ThreadStartRoutine start_routine, void *arg)
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 worker_pool_size
time_t MHD_monotonic_time(void)
static void resume_suspended_connections(struct MHD_Daemon *daemon)
_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)
int(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Methods for managing connections.
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
struct MHD_Connection * normal_timeout_head
void * tdelete(const void *__restrict vkey, void **__restrict vrootp, int(*compar)(const void *, const void *))
FUNC_DESTRUCTOR() MHD_fini()
static void make_nonblocking_noninheritable(struct MHD_Daemon *daemon, MHD_socket sock)
UnescapeCallback unescape_callback
static int MHD_ip_addr_compare(const void *a1, const void *a2)
static struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *daemon)
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
size_t MHD_http_unescape(void *cls, struct MHD_Connection *connection, char *val)
_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 void * MHD_handle_connection(void *data)
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)
FUNC_CONSTRUCTOR() MHD_init()
void * tfind(void *vkey, void *const *vrootp, int *compar) const
void *(* ThreadStartRoutine)(void *cls)
static int internal_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, int external_add)
static void add_to_fd_set(MHD_socket fd, fd_set *set, MHD_socket *max_fd)
struct MHD_Connection * suspended_connections_tail
MHD_PanicCallback mhd_panic
void * per_ip_connection_count
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)
size_t read_buffer_offset
void * default_handler_cls
unsigned int connection_timeout
static int MHD_accept_connection(struct MHD_Daemon *daemon)
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
_MHD_EXTERN const union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
struct MHD_Connection * connections_tail
#define EDLL_insert(head, tail, element)
void MHD_connection_close(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
static void * MHD_select_thread(void *cls)
void(* MHD_LogCallback)(void *cls, const char *fm, va_list ap)
void * tsearch(void *vkey, void **vrootp, int *compar) const
unsigned int max_connections
struct MHD_Connection * suspended_connections_head
void(* MHD_PanicCallback)(void *cls, const char *file, unsigned int line, const char *reason)
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...