50 #include <sys/sendfile.h>
54 #define HAVE_ACCEPT4 0
61 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE - 4
63 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE
69 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
75 #define DEBUG_CLOSE MHD_NO
81 #define DEBUG_CONNECT MHD_NO
85 #define MSG_NOSIGNAL 0
90 #define SOCK_CLOEXEC 0
94 #define EPOLL_CLOEXEC 0
114 fprintf (stderr,
"Fatal error in GNU libmicrohttpd %s:%u: %s\n",
171 struct in6_addr ipv6;
192 MHD_PANIC (
"Failed to acquire IP connection limit mutex\n");
207 MHD_PANIC (
"Failed to release IP connection limit mutex\n");
224 return memcmp (a1, a2, offsetof (
struct MHD_IPCount, count));
239 struct MHD_IPCount *key)
241 memset(key, 0,
sizeof(*key));
244 if (
sizeof (
struct sockaddr_in) == addrlen)
246 const struct sockaddr_in *addr4 = (
const struct sockaddr_in*) addr;
247 key->family = AF_INET;
248 memcpy (&key->addr.ipv4, &addr4->sin_addr,
sizeof(addr4->sin_addr));
254 if (
sizeof (
struct sockaddr_in6) == addrlen)
256 const struct sockaddr_in6 *addr6 = (
const struct sockaddr_in6*) addr;
257 key->family = AF_INET6;
258 memcpy (&key->addr.ipv6, &addr6->sin6_addr,
sizeof(addr6->sin6_addr));
279 const struct sockaddr *addr,
282 struct MHD_IPCount *key;
292 if (
NULL == (key = malloc (
sizeof(*key))))
305 if (
NULL == (nodep = TSEARCH (key,
311 "Failed to add IP connection count node\n");
321 key = (
struct MHD_IPCount *) node;
343 const struct sockaddr *addr,
346 struct MHD_IPCount search_key;
347 struct MHD_IPCount *found_key;
361 if (
NULL == (nodep = TFIND (&search_key,
367 MHD_PANIC (
"Failed to find previously-added IP address\n");
369 found_key = (
struct MHD_IPCount *) *nodep;
371 if (0 == found_key->count)
373 MHD_PANIC (
"Previously-added IP address had 0 count\n");
376 if (0 == --found_key->count)
398 recv_tls_adapter (
struct MHD_Connection *connection,
void *other,
size_t i)
402 if (
MHD_YES == connection->tls_read_ready)
404 connection->
daemon->num_tls_read_ready--;
405 connection->tls_read_ready =
MHD_NO;
407 res = gnutls_record_recv (connection->tls_session, other, i);
408 if ( (GNUTLS_E_AGAIN == res) ||
409 (GNUTLS_E_INTERRUPTED == res) )
427 connection->tls_read_ready =
MHD_YES;
428 connection->
daemon->num_tls_read_ready++;
444 const void *other,
size_t i)
448 res = gnutls_record_send (connection->tls_session, other, i);
449 if ( (GNUTLS_E_AGAIN == res) ||
450 (GNUTLS_E_INTERRUPTED == res) )
469 MHD_init_daemon_certificate (
struct MHD_Daemon *daemon)
474 #if GNUTLS_VERSION_MAJOR >= 3
475 if (
NULL != daemon->cert_callback)
477 gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
478 daemon->cert_callback);
481 if (
NULL != daemon->https_mem_trust)
483 cert.data = (
unsigned char *) daemon->https_mem_trust;
484 cert.size = strlen (daemon->https_mem_trust);
485 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred, &cert,
486 GNUTLS_X509_FMT_PEM) < 0)
490 "Bad trust certificate format\n");
497 if ( (
NULL != daemon->https_mem_cert) &&
498 (
NULL != daemon->https_mem_key) )
500 key.data = (
unsigned char *) daemon->https_mem_key;
501 key.size = strlen (daemon->https_mem_key);
502 cert.data = (
unsigned char *) daemon->https_mem_cert;
503 cert.size = strlen (daemon->https_mem_cert);
505 return gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
507 GNUTLS_X509_FMT_PEM);
509 #if GNUTLS_VERSION_MAJOR >= 3
510 if (
NULL != daemon->cert_callback)
514 MHD_DLOG (daemon,
"You need to specify a certificate and key location\n");
529 switch (daemon->cred_type)
531 case GNUTLS_CRD_CERTIFICATE:
533 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
534 return GNUTLS_E_MEMORY_ERROR;
535 return MHD_init_daemon_certificate (daemon);
539 "Error: invalid credentials type %d specified.\n",
562 if ( (
NULL != max_fd) &&
585 fd_set *write_fd_set,
586 fd_set *except_fd_set,
592 if ( (
NULL == daemon)
593 || (
NULL == read_fd_set)
594 || (
NULL == write_fd_set)
595 || (
NULL == except_fd_set)
607 if (daemon->epoll_fd >= FD_SETSIZE)
609 FD_SET (daemon->epoll_fd, read_fd_set);
610 if ((*max_fd) < daemon->epoll_fd)
611 *max_fd = daemon->epoll_fd;
618 FD_SET (fd, read_fd_set);
646 MHD_DLOG (daemon,
"Maximum socket in select set: %d\n", *max_fd);
670 unsigned int timeout;
692 if (
MHD_YES == con->tls_read_ready)
727 num_ready = SELECT (max + 1, &rs, &ws,
NULL, tvp);
734 "Error during select (%d): `%s'\n",
743 || (
MHD_YES == con->tls_read_ready)
756 memset (&p, 0,
sizeof (p));
761 p[0].events |= POLLIN;
764 p[0].events |= POLLOUT;
766 p[0].events |= POLLIN;
770 p[0].events |= POLLIN;
780 (
NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
785 MHD_DLOG (con->
daemon,
"Error during poll: `%s'\n",
790 if ( (0 != (p[0].revents & POLLIN))
792 || (
MHD_YES == con->tls_read_ready)
796 if (0 != (p[0].revents & POLLOUT))
798 if (0 != (p[0].revents & (POLLERR | POLLHUP)))
810 "Processing thread terminating, closing connection\n");
851 if (ret < (ssize_t) i)
898 if (left > SSIZE_MAX)
900 if (-1 != (ret = sendfile (connection->
socket_fd,
914 if ( (EINTR == errno) || (EAGAIN == errno) )
916 if ( (EINVAL == errno) || (EBADF == errno) )
926 if (ret < (ssize_t) i)
942 typedef void *(*ThreadStartRoutine)(
void *cls);
961 pthread_attr_t *pattr;
966 if (0 != (ret = pthread_attr_init (&attr)))
970 pthread_attr_destroy (&attr);
979 ret = pthread_create (thread, pattr,
981 #if (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)
983 (void) pthread_setname_np (*thread,
"libmicrohttpd");
987 pthread_attr_destroy (&attr);
992 "Failed to set thread stack size\n");
1028 const struct sockaddr *addr,
1033 int res_thread_create;
1051 if (0 != CLOSE (client_socket))
1060 if ( (client_socket >= FD_SETSIZE) &&
1065 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
1069 if (0 != CLOSE (client_socket))
1081 MHD_DLOG (daemon,
"Accepted connection on socket %d\n", client_socket);
1090 "Server reached connection limit (closing inbound connection)\n");
1092 if (0 != CLOSE (client_socket))
1107 MHD_DLOG (daemon,
"Connection rejected, closing connection\n");
1110 if (0 != CLOSE (client_socket))
1122 setsockopt (client_socket,
1123 SOL_SOCKET, SO_NOSIGPIPE,
1134 "Error allocating memory: %s\n",
1137 if (0 != CLOSE (client_socket))
1149 "Error allocating memory: %s\n",
1152 if (0 != CLOSE (client_socket))
1163 if (
NULL == (connection->
addr = malloc (addrlen)))
1168 "Error allocating memory: %s\n",
1171 if (0 != CLOSE (client_socket))
1179 memcpy (connection->
addr, addr, addrlen);
1202 int flags = fcntl (connection->
socket_fd, F_GETFL);
1203 if ( (-1 == flags) ||
1204 (0 != fcntl (connection->
socket_fd, F_SETFL, flags | O_NONBLOCK)) )
1208 "Failed to make socket %d non-blocking: %s\n",
1214 unsigned long flags = 1;
1215 if (0 != ioctlsocket (connection->
socket_fd, FIONBIO, &flags))
1219 "Failed to make socket non-blocking: %s\n",
1230 connection->
recv_cls = &recv_tls_adapter;
1231 connection->
send_cls = &send_tls_adapter;
1234 gnutls_init (&connection->tls_session, GNUTLS_SERVER);
1235 gnutls_priority_set (connection->tls_session,
1236 daemon->priority_cache);
1237 switch (daemon->cred_type)
1240 case GNUTLS_CRD_CERTIFICATE:
1241 gnutls_credentials_set (connection->tls_session,
1242 GNUTLS_CRD_CERTIFICATE,
1247 MHD_DLOG (connection->
daemon,
1248 "Failed to setup TLS credentials: unknown credential type %d\n",
1251 if (0 != CLOSE (client_socket))
1254 free (connection->
addr);
1262 gnutls_transport_set_ptr (connection->tls_session,
1263 (gnutls_transport_ptr_t) connection);
1264 gnutls_transport_set_pull_function (connection->tls_session,
1266 gnutls_transport_set_push_function (connection->tls_session,
1269 if (daemon->https_mem_trust)
1270 gnutls_certificate_server_set_request (connection->tls_session,
1271 GNUTLS_CERT_REQUEST);
1277 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1286 MHD_PANIC (
"Failed to release cleanup mutex\n");
1293 if (0 != res_thread_create)
1297 MHD_DLOG (daemon,
"Failed to create a thread: %s\n",
1298 STRERROR (res_thread_create));
1304 if ( (
MHD_YES == external_add) &&
1305 (-1 != daemon->
wpipe[1]) &&
1306 (1 != WRITE (daemon->
wpipe[1],
"n", 1)) )
1310 "failed to signal new connection via pipe");
1318 struct epoll_event event;
1320 event.events = EPOLLIN | EPOLLOUT | EPOLLET;
1321 event.data.ptr = connection;
1322 if (0 != epoll_ctl (daemon->epoll_fd,
1330 "Call to epoll_ctl failed: %s\n",
1342 daemon->eready_tail,
1350 if (0 != CLOSE (client_socket))
1355 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1364 MHD_PANIC (
"Failed to release cleanup mutex\n");
1366 free (connection->
addr);
1407 daemon = connection->
daemon;
1409 MHD_PANIC (
"Cannot suspend connections without enabling MHD_USE_SUSPEND_RESUME!\n");
1412 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1433 daemon->eready_tail,
1438 if (0 != epoll_ctl (daemon->epoll_fd,
1442 MHD_PANIC (
"Failed to remove FD from epoll set\n");
1451 MHD_PANIC (
"Failed to release cleanup mutex\n");
1468 daemon = connection->
daemon;
1470 MHD_PANIC (
"Cannot resume connections without enabling MHD_USE_SUSPEND_RESUME!\n");
1473 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1476 if ( (-1 != daemon->
wpipe[1]) &&
1477 (1 != WRITE (daemon->
wpipe[1],
"r", 1)) )
1481 "failed to signal resume via pipe");
1486 MHD_PANIC (
"Failed to release cleanup mutex\n");
1503 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1508 while (
NULL != (pos = next))
1534 daemon->eready_tail,
1539 struct epoll_event event;
1541 event.events = EPOLLIN | EPOLLOUT | EPOLLET;
1542 event.data.ptr = pos;
1543 if (0 != epoll_ctl (daemon->epoll_fd,
1547 MHD_PANIC (
"Failed to add FD to epoll set\n");
1560 MHD_PANIC (
"Failed to release cleanup mutex\n");
1576 #ifdef HAVE_SOCK_NONBLOCK
1577 nonblock = SOCK_NONBLOCK;
1588 unsigned long flags = 1;
1590 if (0 != ioctlsocket (sock, FIONBIO, &flags))
1594 "Failed to make socket non-blocking: %s\n",
1598 if (!GetHandleInformation ((HANDLE) sock, &dwFlags) ||
1599 ((dwFlags != dwFlags & ~HANDLE_FLAG_INHERIT) &&
1600 !SetHandleInformation ((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)))
1603 SetErrnoFromWinError (GetLastError ());
1605 "Failed to make socket non-inheritable: %s\n",
1612 nonblock = O_NONBLOCK;
1617 flags = fcntl (sock, F_GETFD);
1618 if ( ( (-1 == flags) ||
1619 ( (flags != (flags | FD_CLOEXEC)) &&
1620 (0 != fcntl (sock, F_SETFD, flags | nonblock | FD_CLOEXEC)) ) ) )
1624 "Failed to make socket non-inheritable: %s\n",
1664 const struct sockaddr *addr,
1692 struct sockaddr_in6 addrstorage;
1694 struct sockaddr_in addrstorage;
1696 struct sockaddr *addr = (
struct sockaddr *) &addrstorage;
1702 addrlen =
sizeof (addrstorage);
1703 memset (addr, 0,
sizeof (addrstorage));
1706 #ifdef HAVE_SOCK_NONBLOCK
1707 nonblock = SOCK_NONBLOCK;
1716 s = accept4 (fd, addr, &addrlen,
SOCK_CLOEXEC | nonblock);
1718 s = ACCEPT (fd, addr, &addrlen);
1720 if ((-1 == s) || (addrlen <= 0))
1724 if ((EAGAIN != errno) && (EWOULDBLOCK != errno))
1726 "Error accepting connection: %s\n",
1741 MHD_DLOG (daemon,
"Accepted connection on socket %d\n", s);
1767 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1776 if (0 != (rc = pthread_join (pos->
pid, &unused)))
1778 MHD_PANIC (
"Failed to join a thread\n");
1783 if (pos->tls_session !=
NULL)
1784 gnutls_deinit (pos->tls_session);
1787 (
struct sockaddr *) pos->
addr,
1793 daemon->eready_tail,
1798 (-1 != daemon->epoll_fd) &&
1807 if (0 != epoll_ctl (daemon->epoll_fd,
1811 MHD_PANIC (
"Failed to remove FD from epoll set\n");
1835 MHD_PANIC (
"Failed to release cleanup mutex\n");
1857 time_t earliest_deadline;
1865 MHD_DLOG (daemon,
"Illegal call to MHD_get_timeout\n");
1871 if (0 != daemon->num_tls_read_ready)
1885 if ( (! have_timeout) ||
1890 (0 != gnutls_record_check_pending (pos->tls_session)) )
1891 earliest_deadline = 0;
1898 if ( (
NULL != pos) &&
1901 if ( (! have_timeout) ||
1906 (0 != gnutls_record_check_pending (pos->tls_session)) )
1907 earliest_deadline = 0;
1912 if (
MHD_NO == have_timeout)
1915 if (earliest_deadline < now)
1918 *timeout = 1000 * (1 + earliest_deadline - now);
1944 const fd_set *read_fd_set,
1945 const fd_set *write_fd_set,
1946 const fd_set *except_fd_set)
1958 if (daemon->epoll_fd >= FD_SETSIZE)
1960 if (FD_ISSET (daemon->epoll_fd, read_fd_set))
1967 if ( (-1 != (ds = daemon->
socket_fd)) &&
1968 (FD_ISSET (ds, read_fd_set)) )
1971 if ( (-1 != daemon->
wpipe[0]) &&
1972 (FD_ISSET (daemon->
wpipe[0], read_fd_set)) )
1973 (void) read (daemon->
wpipe[0], &tmp, sizeof (tmp));
1979 while (
NULL != (pos = next))
1988 if ( (FD_ISSET (ds, read_fd_set))
1990 || (
MHD_YES == pos->tls_read_ready)
1996 if ( (FD_ISSET (ds, read_fd_set)) &&
1999 if (FD_ISSET (ds, write_fd_set))
2003 if ( (FD_ISSET (ds, read_fd_set)) &&
2036 struct timeval timeout;
2041 timeout.tv_usec = 0;
2072 if (-1 != daemon->
wpipe[0])
2074 FD_SET (daemon->
wpipe[0], &rs);
2076 if (max < daemon->wpipe[0])
2077 max = daemon->
wpipe[0];
2083 timeout.tv_usec = 0;
2091 timeout.tv_usec = (ltimeout % 1000) * 1000;
2092 timeout.tv_sec = ltimeout / 1000;
2097 num_ready = SELECT (max + 1, &rs, &ws, &es, tv);
2105 MHD_DLOG (daemon,
"select failed: %s\n", STRERROR (errno));
2126 unsigned int num_connections;
2134 num_connections = 0;
2138 struct pollfd p[2 + num_connections];
2142 unsigned int poll_server;
2145 memset (p, 0,
sizeof (p));
2153 p[poll_server].events = POLLIN;
2154 p[poll_server].revents = 0;
2155 poll_listen = (int) poll_server;
2158 if (-1 != daemon->
wpipe[0])
2160 p[poll_server].fd = daemon->
wpipe[0];
2161 p[poll_server].events = POLLIN;
2162 p[poll_server].revents = 0;
2171 timeout = (ltimeout > INT_MAX) ? INT_MAX : (
int) ltimeout;
2180 p[poll_server+i].events |= POLLIN;
2183 p[poll_server+i].events |= POLLOUT;
2185 p[poll_server+i].events |= POLLIN;
2189 p[poll_server+i].events |= POLLIN;
2197 if (0 == poll_server + num_connections)
2199 if (poll (p, poll_server + num_connections, timeout) < 0)
2205 "poll failed: %s\n",
2215 while (
NULL != (pos = next))
2222 if (i >= num_connections)
2224 if (p[poll_server+i].fd != pos->
socket_fd)
2227 if (0 != (p[poll_server+i].revents & POLLIN))
2234 if (i >= num_connections)
2236 if (p[poll_server+i].fd != pos->
socket_fd)
2239 if (0 != (p[poll_server+i].revents & POLLIN))
2241 if (0 != (p[poll_server+i].revents & POLLOUT))
2247 if (0 != (p[poll_server+i].revents & POLLIN))
2257 if ( (-1 != poll_listen) &&
2258 (0 != (p[poll_listen].revents & POLLIN)) )
2273 MHD_poll_listen_socket (
struct MHD_Daemon *daemon,
2278 unsigned int poll_count;
2281 memset (&p, 0,
sizeof (p));
2287 p[poll_count].events = POLLIN;
2288 p[poll_count].revents = 0;
2289 poll_listen = poll_count;
2292 if (-1 != daemon->
wpipe[0])
2294 p[poll_count].fd = daemon->
wpipe[0];
2295 p[poll_count].events = POLLIN;
2296 p[poll_count].revents = 0;
2303 if (0 == poll_count)
2305 if (poll (p, poll_count, timeout) < 0)
2310 MHD_DLOG (daemon,
"poll failed: %s\n", STRERROR (errno));
2317 if ( (-1 != poll_listen) &&
2318 (0 != (p[poll_listen].revents & POLLIN)) )
2340 return MHD_poll_all (daemon, may_block);
2342 return MHD_poll_listen_socket (daemon, may_block);
2359 #define MAX_EVENTS 128
2376 struct epoll_event events[MAX_EVENTS];
2377 struct epoll_event event;
2382 unsigned int series_length;
2385 if (-1 == daemon->epoll_fd)
2391 (
MHD_NO == daemon->listen_socket_in_epoll) )
2393 event.events = EPOLLIN;
2394 event.data.ptr = daemon;
2395 if (0 != epoll_ctl (daemon->epoll_fd,
2403 "Call to epoll_ctl failed: %s\n",
2408 daemon->listen_socket_in_epoll =
MHD_YES;
2410 if ( (
MHD_YES == daemon->listen_socket_in_epoll) &&
2415 if (0 != epoll_ctl (daemon->epoll_fd,
2419 MHD_PANIC (
"Failed to remove listen FD from epoll set\n");
2420 daemon->listen_socket_in_epoll =
MHD_NO;
2428 timeout_ms = INT_MAX;
2430 timeout_ms = (int) timeout_ll;
2442 num_events = MAX_EVENTS;
2443 while (MAX_EVENTS == num_events)
2446 num_events = epoll_wait (daemon->epoll_fd,
2447 events, MAX_EVENTS, timeout_ms);
2448 if (-1 == num_events)
2455 "Call to epoll_wait failed: %s\n",
2460 for (i=0;i<num_events;i++)
2462 if (
NULL == events[i].data.ptr)
2464 if ( (-1 != daemon->
wpipe[0]) &&
2465 (daemon->
wpipe[0] == events[i].data.fd) )
2467 (void) read (daemon->
wpipe[0], &tmp, sizeof (tmp));
2470 if (daemon != events[i].data.ptr)
2475 pos = events[i].data.ptr;
2476 if (0 != (events[i].events & EPOLLIN))
2484 daemon->eready_tail,
2489 if (0 != (events[i].events & EPOLLOUT))
2496 daemon->eready_tail,
2509 (series_length < 128) )
2521 while (
NULL != (pos = daemon->eready_tail))
2524 daemon->eready_tail,
2542 while (
NULL != (pos = next))
2552 while (
NULL != (pos = next))
2598 MHD_epoll (daemon,
MHD_NO);
2665 va_start (ap, dh_cls);
2700 if ( (-1 == daemon->
wpipe[1]) &&
2705 "Using MHD_quiesce_daemon in this mode requires MHD_USE_PIPE_FOR_SHUTDOWN\n");
2719 if (0 != epoll_ctl (daemon->
worker_pool[i].epoll_fd,
2723 MHD_PANIC (
"Failed to remove listen FD from epoll set\n");
2731 (-1 != daemon->epoll_fd) &&
2732 (
MHD_YES == daemon->listen_socket_in_epoll) )
2734 if (0 != epoll_ctl (daemon->epoll_fd,
2738 MHD_PANIC (
"Failed to remove listen FD from epoll set\n");
2739 daemon->listen_socket_in_epoll =
MHD_NO;
2768 const struct sockaddr **servaddr,
2782 const struct sockaddr **servaddr,
2788 va_start (ap, servaddr);
2805 const struct sockaddr **servaddr,
2821 daemon->
pool_size = va_arg (ap,
size_t);
2841 *servaddr = va_arg (ap,
const struct sockaddr *);
2854 "Specified thread pool size (%u) too big\n",
2863 daemon->https_mem_key = va_arg (ap,
const char *);
2867 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
2873 daemon->https_mem_cert = va_arg (ap,
const char *);
2877 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
2883 daemon->https_mem_trust = va_arg (ap,
const char *);
2887 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
2892 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
int);
2897 gnutls_priority_deinit (daemon->priority_cache);
2898 ret = gnutls_priority_init (&daemon->priority_cache,
2899 pstr = va_arg (ap,
const char*),
2901 if (ret != GNUTLS_E_SUCCESS)
2905 "Setting priorities to `%s' failed: %s\n",
2907 gnutls_strerror (ret));
2909 daemon->priority_cache =
NULL;
2915 #if GNUTLS_VERSION_MAJOR < 3
2918 "MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n");
2923 daemon->cert_callback = va_arg (ap, gnutls_certificate_retrieve_function2 *);
2927 #ifdef DAUTH_SUPPORT
2929 daemon->digest_auth_rand_size = va_arg (ap,
size_t);
2930 daemon->digest_auth_random = va_arg (ap,
const char *);
2933 daemon->nonce_nc_size = va_arg (ap,
unsigned int);
2941 daemon->custom_error_log =
2943 daemon->custom_error_log_cls = va_arg (ap,
void *);
2946 va_arg (ap,
void *);
2966 (
size_t) oa[i].
value,
2979 (
unsigned int) oa[i].value,
3016 (
void *) oa[i].value,
3026 (
size_t) oa[i].value,
3048 "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
3054 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
3075 int domain,
int type,
int protocol)
3082 fd = SOCKET (domain, ctype, protocol);
3083 if ( (-1 == fd) && (EINVAL == errno) && (0 !=
SOCK_CLOEXEC) )
3086 fd = SOCKET(domain, type, protocol);
3105 setup_epoll_to_listen (
struct MHD_Daemon *daemon)
3107 struct epoll_event event;
3110 if (-1 == daemon->epoll_fd)
3115 "Call to epoll_create1 failed: %s\n",
3125 event.events = EPOLLIN;
3126 event.data.ptr = daemon;
3127 if (0 != epoll_ctl (daemon->epoll_fd,
3135 "Call to epoll_ctl failed: %s\n",
3140 if ( (-1 != daemon->
wpipe[0]) &&
3143 event.events = EPOLLIN | EPOLLET;
3144 event.data.ptr =
NULL;
3145 event.data.fd = daemon->
wpipe[0];
3146 if (0 != epoll_ctl (daemon->epoll_fd,
3154 "Call to epoll_ctl failed: %s\n",
3160 daemon->listen_socket_in_epoll =
MHD_YES;
3194 struct sockaddr_in servaddr4;
3196 struct sockaddr_in6 servaddr6;
3198 const struct sockaddr *servaddr =
NULL;
3201 int res_thread_create;
3220 memset (daemon, 0,
sizeof (
struct MHD_Daemon));
3222 daemon->epoll_fd = -1;
3226 if (0 != (flags & MHD_USE_SSL))
3228 gnutls_priority_init (&daemon->priority_cache,
3240 daemon->
port = port;
3250 daemon->
wpipe[0] = -1;
3251 daemon->
wpipe[1] = -1;
3254 daemon->custom_error_log_cls = stderr;
3256 #ifdef HAVE_LISTEN_SHUTDOWN
3265 (0 != SOCKETPAIR (AF_INET, SOCK_STREAM, IPPROTO_TCP, daemon->
wpipe))
3267 (0 != PIPE (daemon->
wpipe))
3273 "Failed to create control pipe: %s\n",
3280 if ( (0 == (flags & MHD_USE_POLL)) &&
3282 (daemon->
wpipe[0] >= FD_SETSIZE) )
3286 "file descriptor for control pipe exceeds maximum value\n");
3288 if (0 != CLOSE (daemon->
wpipe[0]))
3290 if (0 != CLOSE (daemon->
wpipe[1]))
3296 #ifdef DAUTH_SUPPORT
3297 daemon->digest_auth_rand_size = 0;
3298 daemon->digest_auth_random =
NULL;
3299 daemon->nonce_nc_size = 4;
3302 if (0 != (flags & MHD_USE_SSL))
3304 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
3312 if ( (0 != (flags & MHD_USE_SSL)) &&
3313 (
NULL != daemon->priority_cache) )
3314 gnutls_priority_deinit (daemon->priority_cache);
3319 #ifdef DAUTH_SUPPORT
3320 if (daemon->nonce_nc_size > 0)
3322 if ( ( (
size_t) (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc))) /
3323 sizeof(
struct MHD_NonceNc) != daemon->nonce_nc_size)
3327 "Specified value for NC_SIZE too large\n");
3330 if (0 != (flags & MHD_USE_SSL))
3331 gnutls_priority_deinit (daemon->priority_cache);
3336 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc));
3337 if (
NULL == daemon->nnc)
3341 "Failed to allocate memory for nonce-nc map: %s\n",
3345 if (0 != (flags & MHD_USE_SSL))
3346 gnutls_priority_deinit (daemon->priority_cache);
3353 if (0 != pthread_mutex_init (&daemon->nnc_lock,
NULL))
3357 "MHD failed to initialize nonce-nc mutex\n");
3360 if (0 != (flags & MHD_USE_SSL))
3361 gnutls_priority_deinit (daemon->priority_cache);
3375 "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n");
3385 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_SUSPEND_RESUME is not supported.\n");
3390 #ifdef __SYMBIAN32__
3391 if (0 != (flags & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
3395 "Threaded operations are not supported on Symbian.\n");
3405 if (0 != (flags & MHD_USE_THREAD_PER_CONNECTION))
3409 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL_LINUX_ONLY is not supported.\n");
3413 if (
MHD_YES != setup_epoll_to_listen (daemon))
3417 if (0 != (flags & MHD_USE_EPOLL_LINUX_ONLY))
3421 "epoll is not supported on this platform by this build.\n");
3430 if ((flags & MHD_USE_IPv6) != 0)
3432 PF_INET6, SOCK_STREAM, 0);
3435 PF_INET, SOCK_STREAM, 0);
3436 if (-1 == socket_fd)
3441 "Call to socket failed: %s\n",
3446 if ( (0 > SETSOCKOPT (socket_fd,
3449 &on,
sizeof (on))) &&
3454 "setsockopt failed: %s\n",
3461 if (0 != (flags & MHD_USE_IPv6))
3462 addrlen =
sizeof (
struct sockaddr_in6);
3465 addrlen =
sizeof (
struct sockaddr_in);
3466 if (
NULL == servaddr)
3469 if (0 != (flags & MHD_USE_IPv6))
3471 memset (&servaddr6, 0,
sizeof (
struct sockaddr_in6));
3472 servaddr6.sin6_family = AF_INET6;
3473 servaddr6.sin6_port = htons (port);
3474 #if HAVE_SOCKADDR_IN_SIN_LEN
3475 servaddr6.sin6_len =
sizeof (
struct sockaddr_in6);
3477 servaddr = (
struct sockaddr *) &servaddr6;
3482 memset (&servaddr4, 0,
sizeof (
struct sockaddr_in));
3483 servaddr4.sin_family = AF_INET;
3484 servaddr4.sin_port = htons (port);
3485 #if HAVE_SOCKADDR_IN_SIN_LEN
3486 servaddr4.sin_len =
sizeof (
struct sockaddr_in);
3488 servaddr = (
struct sockaddr *) &servaddr4;
3493 if ( (0 != (flags & MHD_USE_IPv6)) &&
3507 if ( (0 > SETSOCKOPT (socket_fd,
3508 IPPROTO_IPV6, IPV6_V6ONLY,
3509 &on,
sizeof (on))) &&
3514 "setsockopt failed: %s\n",
3521 if (-1 == BIND (socket_fd, servaddr, addrlen))
3524 if (0 != (flags & MHD_USE_DEBUG))
3526 "Failed to bind to port %u: %s\n",
3527 (
unsigned int) port,
3530 if (0 != CLOSE (socket_fd))
3535 if (0 != (flags & MHD_USE_EPOLL_LINUX_ONLY))
3537 int sk_flags = fcntl (socket_fd, F_GETFL);
3538 if (0 != fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK))
3542 "Failed to make listen socket non-blocking: %s\n",
3545 if (0 != CLOSE (socket_fd))
3551 if (LISTEN (socket_fd, 32) < 0)
3554 if (0 != (flags & MHD_USE_DEBUG))
3556 "Failed to listen for connections: %s\n",
3559 if (0 != CLOSE (socket_fd))
3569 if ( (socket_fd >= FD_SETSIZE) &&
3570 (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL_LINUX_ONLY)) ) )
3575 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
3579 if (0 != CLOSE (socket_fd))
3589 "MHD failed to initialize IP connection limit mutex\n");
3591 if ( (-1 != socket_fd) &&
3592 (0 != CLOSE (socket_fd)) )
3600 "MHD failed to initialize IP connection limit mutex\n");
3603 if ( (-1 != socket_fd) &&
3604 (0 != CLOSE (socket_fd)) )
3611 if ((0 != (flags & MHD_USE_SSL)) && (0 != MHD_TLS_init (daemon)))
3615 "Failed to initialize TLS support\n");
3617 if ( (-1 != socket_fd) &&
3618 (0 != CLOSE (socket_fd)) )
3625 if ( ( (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) ||
3626 ( (0 != (flags & MHD_USE_SELECT_INTERNALLY)) &&
3629 (0 != (res_thread_create =
3634 "Failed to create listen thread: %s\n",
3635 STRERROR (res_thread_create));
3639 if ( (-1 != socket_fd) &&
3640 (0 != CLOSE (socket_fd)) )
3650 unsigned long sk_flags;
3667 sk_flags = fcntl (socket_fd, F_GETFL);
3670 if (0 != fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK))
3676 ioctlsocket (plibc_fd_get_handle (socket_fd), FIONBIO, &sk_flags))
3679 if (ioctlsocket (socket_fd, FIONBIO, &sk_flags) == SOCKET_ERROR)
3696 memcpy (d, daemon,
sizeof (
struct MHD_Daemon));
3704 if ( (MHD_USE_SUSPEND_RESUME == (flags & MHD_USE_SUSPEND_RESUME)) &&
3706 (0 != SOCKETPAIR (AF_INET, SOCK_STREAM, IPPROTO_TCP, d->
wpipe))
3708 (0 != PIPE (d->
wpipe))
3714 "Failed to create worker control pipe: %s\n",
3720 if ( (0 == (flags & MHD_USE_POLL)) &&
3721 (MHD_USE_SUSPEND_RESUME == (flags & MHD_USE_SUSPEND_RESUME)) &&
3722 (d->
wpipe[0] >= FD_SETSIZE) )
3726 "file descriptor for worker control pipe exceeds maximum value\n");
3728 if (0 != CLOSE (d->
wpipe[0]))
3730 if (0 != CLOSE (d->
wpipe[1]))
3740 if (i < leftover_conns)
3743 if ( (0 != (daemon->
options & MHD_USE_EPOLL_LINUX_ONLY)) &&
3744 (
MHD_YES != setup_epoll_to_listen (d)) )
3752 "MHD failed to initialize cleanup connection mutex for thread worker %d\n", i);
3758 if (0 != (res_thread_create =
3763 "Failed to create pool thread: %s\n",
3764 STRERROR (res_thread_create));
3782 if ( (-1 != socket_fd) &&
3783 (0 != CLOSE (socket_fd)) )
3804 if (-1 != daemon->epoll_fd)
3805 close (daemon->epoll_fd);
3807 #ifdef DAUTH_SUPPORT
3809 pthread_mutex_destroy (&daemon->nnc_lock);
3812 if (0 != (flags & MHD_USE_SSL))
3813 gnutls_priority_deinit (daemon->priority_cache);
3869 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
3875 MHD_PANIC (
"Failed to release cleanup mutex\n");
3882 if (0 != (rc = pthread_join (pos->
pid, &unused)))
3883 MHD_PANIC (
"Failed to join a thread\n");
3904 struct epoll_event event;
3906 if (-1 == daemon->
wpipe[1])
3911 event.events = EPOLLOUT;
3912 event.data.ptr =
NULL;
3913 if (0 != epoll_ctl (daemon->epoll_fd,
3917 MHD_PANIC (
"Failed to add wpipe to epoll set to signal termination\n");
3957 if (-1 != daemon->
wpipe[1])
3959 if (1 != WRITE (daemon->
wpipe[1],
"e", 1))
3960 MHD_PANIC (
"failed to signal shutdown via pipe");
3962 #ifdef HAVE_LISTEN_SHUTDOWN
3967 (void) SHUTDOWN (fd, SHUT_RDWR);
3972 (-1 != daemon->epoll_fd) &&
3974 epoll_shutdown (daemon);
3979 MHD_DLOG (daemon,
"MHD listen socket shutdown\n");
3993 MHD_PANIC (
"failed to signal shutdown via pipe");
3995 if (0 != (rc = pthread_join (daemon->
worker_pool[i].
pid, &unused)))
3996 MHD_PANIC (
"Failed to join a thread\n");
4024 if (0 != (rc = pthread_join (daemon->
pid, &unused)))
4026 MHD_PANIC (
"Failed to join a thread\n");
4039 gnutls_priority_deinit (daemon->priority_cache);
4040 if (daemon->x509_cred)
4041 gnutls_certificate_free_credentials (daemon->x509_cred);
4046 (-1 != daemon->epoll_fd) &&
4047 (0 != CLOSE (daemon->epoll_fd)) )
4051 #ifdef DAUTH_SUPPORT
4053 pthread_mutex_destroy (&daemon->nnc_lock);
4058 if (-1 != daemon->
wpipe[1])
4060 if (0 != CLOSE (daemon->
wpipe[0]))
4062 if (0 != CLOSE (daemon->
wpipe[1]))
4136 return PACKAGE_VERSION;
4141 #define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor))
4142 #define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor))
4144 #define ATTRIBUTE_CONSTRUCTOR
4145 #define ATTRIBUTE_DESTRUCTOR
4149 #if GCRYPT_VERSION_NUMBER < 0x010600
4150 GCRY_THREAD_OPTION_PTHREAD_IMPL;
4165 plibc_init (
"GNU",
"libmicrohttpd");
4168 #if GCRYPT_VERSION_NUMBER < 0x010600
4169 gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
4171 gcry_check_version (
NULL);
4172 gnutls_global_init ();
4181 gnutls_global_deinit ();
unsigned int per_ip_connection_limit
void * unescape_callback_cls
#define XDLL_insert(head, tail, element)
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
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)
union MHD_DaemonInfo * MHD_get_daemon_info(struct MHD_Daemon *daemon, enum MHD_DaemonInfoType info_type,...)
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.
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)
void MHD_resume_connection(struct MHD_Connection *connection)
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
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
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
static int create_socket(struct MHD_Daemon *daemon, int domain, int type, int protocol)
MHD_AccessHandlerCallback default_handler
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
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.
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
static void add_to_fd_set(int fd, fd_set *set, int *max_fd)
struct MHD_Connection * cleanup_head
static int internal_add_connection(struct MHD_Daemon *daemon, int client_socket, const struct sockaddr *addr, socklen_t addrlen, int external_add)
struct MHD_Connection * cleanup_tail
static void close_connection(struct MHD_Connection *pos)
size_t write_buffer_send_offset
#define ATTRIBUTE_CONSTRUCTOR
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)
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)
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)
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
void MHD_destroy_response(struct MHD_Response *response)
static void make_nonblocking_noninheritable(struct MHD_Daemon *daemon, int sock)
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)
void ATTRIBUTE_DESTRUCTOR MHD_fini()
struct MHD_Connection * normal_timeout_head
void ATTRIBUTE_CONSTRUCTOR MHD_init()
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)
int MHD_quiesce_daemon(struct MHD_Daemon *daemon)
struct MHD_Connection * connections_head
struct MHD_Daemon * master
struct MHD_Connection * next
if((r=(*compar)(vkey,(*rootp) ->key))==0)
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)
static void * MHD_handle_connection(void *data)
size_t write_buffer_append_offset
#define ATTRIBUTE_DESTRUCTOR
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
int MHD_run(struct MHD_Daemon *daemon)
#define XDLL_remove(head, tail, element)
#define DLL_insert(head, tail, element)
int MHD_get_fdset(struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, int *max_fd)
void *(* ThreadStartRoutine)(void *cls)
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)
int MHD_add_connection(struct MHD_Daemon *daemon, int client_socket, const struct sockaddr *addr, socklen_t addrlen)
size_t read_buffer_offset
void * default_handler_cls
unsigned int connection_timeout
void MHD_suspend_connection(struct MHD_Connection *connection)
static int MHD_accept_connection(struct MHD_Daemon *daemon)
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)
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...