53 #include <sys/sendfile.h> 57 #ifndef WIN32_LEAN_AND_MEAN 58 #define WIN32_LEAN_AND_MEAN 1 66 #ifdef MHD_POSIX_SOCKETS 67 #define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 4) 69 #define MHD_MAX_CONNECTIONS_DEFAULT (FD_SETSIZE - 2) 75 #define MHD_POOL_SIZE_DEFAULT (32 * 1024) 81 #define DEBUG_CLOSE MHD_NO 87 #define DEBUG_CONNECT MHD_NO 107 _(
"Fatal error in GNU libmicrohttpd %s:%u: %s\n"),
130 static int mhd_winsock_inited_ = 0;
173 struct in6_addr ipv6;
223 offsetof (
struct MHD_IPCount,
239 struct MHD_IPCount *key)
246 if (
sizeof (
struct sockaddr_in) == addrlen)
248 const struct sockaddr_in *addr4 = (
const struct sockaddr_in*) addr;
250 key->family = AF_INET;
251 memcpy (&key->addr.ipv4,
253 sizeof(addr4->sin_addr));
259 if (
sizeof (
struct sockaddr_in6) == addrlen)
261 const struct sockaddr_in6 *addr6 = (
const struct sockaddr_in6*) addr;
263 key->family = AF_INET6;
264 memcpy (&key->addr.ipv6,
266 sizeof(addr6->sin6_addr));
289 const struct sockaddr *addr,
292 struct MHD_IPCount *key;
302 if (
NULL == (key = malloc (
sizeof(*key))))
323 _(
"Failed to add IP connection count node\n"));
333 key = (
struct MHD_IPCount *) node;
355 const struct sockaddr *addr,
358 struct MHD_IPCount search_key;
359 struct MHD_IPCount *found_key;
381 MHD_PANIC (
_(
"Failed to find previously-added IP address\n"));
383 found_key = (
struct MHD_IPCount *) *nodep;
385 if (0 == found_key->count)
387 MHD_PANIC (
_(
"Previously-added IP address had counter of zero\n"));
390 if (0 == --found_key->count)
418 if (
MHD_YES == connection->tls_read_ready)
420 connection->
daemon->num_tls_read_ready--;
421 connection->tls_read_ready =
MHD_NO;
423 res = gnutls_record_recv (connection->tls_session,
426 if ( (GNUTLS_E_AGAIN == res) ||
427 (GNUTLS_E_INTERRUPTED == res) )
443 if ((
size_t)res == i)
445 connection->tls_read_ready =
MHD_YES;
446 connection->
daemon->num_tls_read_ready++;
467 res = gnutls_record_send (connection->tls_session,
470 if ( (GNUTLS_E_AGAIN == res) ||
471 (GNUTLS_E_INTERRUPTED == res) )
499 MHD_init_daemon_certificate (
struct MHD_Daemon *daemon)
505 #if GNUTLS_VERSION_MAJOR >= 3 506 if (
NULL != daemon->cert_callback)
508 gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
509 daemon->cert_callback);
512 if (
NULL != daemon->https_mem_trust)
514 cert.data = (
unsigned char *) daemon->https_mem_trust;
515 cert.size = strlen (daemon->https_mem_trust);
516 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred,
518 GNUTLS_X509_FMT_PEM) < 0)
522 "Bad trust certificate format\n");
528 if (
MHD_YES == daemon->have_dhparams)
530 gnutls_certificate_set_dh_params (daemon->x509_cred,
531 daemon->https_mem_dhparams);
534 if ( (
NULL != daemon->https_mem_cert) &&
535 (
NULL != daemon->https_mem_key) )
537 key.data = (
unsigned char *) daemon->https_mem_key;
538 key.size = strlen (daemon->https_mem_key);
539 cert.data = (
unsigned char *) daemon->https_mem_cert;
540 cert.size = strlen (daemon->https_mem_cert);
542 if (
NULL != daemon->https_key_password) {
543 #if GNUTLS_VERSION_NUMBER >= 0x030111 544 ret = gnutls_certificate_set_x509_key_mem2 (daemon->x509_cred,
548 daemon->https_key_password,
553 _(
"Failed to setup x509 certificate/key: pre 3.X.X version " \
554 "of GnuTLS does not support setting key password"));
560 ret = gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
563 GNUTLS_X509_FMT_PEM);
567 "GnuTLS failed to setup x509 certificate/key: %s\n",
568 gnutls_strerror (ret));
572 #if GNUTLS_VERSION_MAJOR >= 3 573 if (
NULL != daemon->cert_callback)
578 "You need to specify a certificate and key location\n");
593 switch (daemon->cred_type)
595 case GNUTLS_CRD_CERTIFICATE:
597 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
598 return GNUTLS_E_MEMORY_ERROR;
599 return MHD_init_daemon_certificate (daemon);
603 _(
"Error: invalid credentials type %d specified.\n"),
636 fd_set *write_fd_set,
637 fd_set *except_fd_set,
666 unsigned int fd_setsize)
668 if ( (urh->out_buffer_off < urh->out_buffer_size) &&
682 if ( (urh->in_buffer_off < urh->in_buffer_size) &&
716 FD_ISSET (conn_sckt, rs))
719 FD_ISSET (conn_sckt, ws))
722 FD_ISSET (mhd_sckt, rs))
725 FD_ISSET (mhd_sckt, ws))
755 fd_set *write_fd_set,
756 fd_set *except_fd_set,
758 unsigned int fd_setsize)
764 if ( (
NULL == daemon) ||
765 (
NULL == read_fd_set) ||
766 (
NULL == write_fd_set) ||
833 for (urh = daemon->urh_head;
NULL != urh; urh = urh->next)
849 _(
"Maximum socket in select set: %d\n"),
877 int had_response_before_idle;
881 if (
MHD_YES == con->tls_read_ready)
895 if ( (! force_close) &&
899 (
MHD_NO == had_response_before_idle) )
941 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
945 MHD_PANIC (
_(
"Failed to remove FD from epoll set\n"));
958 (0 != epoll_ctl (daemon->epoll_upgrade_fd,
962 MHD_PANIC (
_(
"Failed to remove FD from epoll set\n"));
977 gnutls_bye (connection->tls_session,
1009 (urh->in_buffer_off < urh->in_buffer_size) )
1013 res = gnutls_record_recv (urh->
connection->tls_session,
1014 &urh->in_buffer[urh->in_buffer_off],
1015 urh->in_buffer_size - urh->in_buffer_off);
1016 if ( (GNUTLS_E_AGAIN == res) ||
1017 (GNUTLS_E_INTERRUPTED == res) )
1023 urh->in_buffer_off += res;
1029 urh->in_buffer_size = urh->in_buffer_off;
1033 (urh->in_buffer_off > 0) )
1039 urh->in_buffer_off);
1051 urh->in_buffer_size = 0;
1052 urh->in_buffer_off = 0;
1057 if (urh->in_buffer_off != res)
1059 memmove (urh->in_buffer,
1060 &urh->in_buffer[res],
1061 urh->in_buffer_off - res);
1062 urh->in_buffer_off -= res;
1066 urh->in_buffer_off = 0;
1073 (urh->out_buffer_off < urh->out_buffer_size) )
1078 &urh->out_buffer[urh->out_buffer_off],
1079 urh->out_buffer_size - urh->out_buffer_off);
1087 urh->out_buffer_off += res;
1093 urh->out_buffer_size = urh->out_buffer_off;
1095 fin_read = (0 == res);
1100 (urh->out_buffer_off > 0) )
1104 res = gnutls_record_send (urh->
connection->tls_session,
1106 urh->out_buffer_off);
1107 if ( (GNUTLS_E_AGAIN == res) ||
1108 (GNUTLS_E_INTERRUPTED == res) )
1114 if (urh->out_buffer_off != res)
1116 memmove (urh->out_buffer,
1117 &urh->out_buffer[res],
1118 urh->out_buffer_off - res);
1119 urh->out_buffer_off -= res;
1123 urh->out_buffer_off = 0;
1130 urh->out_buffer_size = 0;
1131 urh->out_buffer_off = 0;
1136 (0 == urh->out_buffer_off) &&
1176 result = urh_to_fdset (urh,
1183 #ifdef HAVE_MESSAGES 1185 _(
"Error preparing select\n"));
1203 #ifdef HAVE_MESSAGES 1205 _(
"Error during select (%d): `%s'\n"),
1211 urh_from_fdset (urh,
1215 if ( (0 == urh->out_buffer_size) &&
1216 (0 == urh->in_buffer_size) )
1224 const unsigned int timeout =
UINT_MAX;
1232 sizeof (
struct pollfd) * 2);
1234 p[1].fd = urh->mhd.socket;
1235 if (urh->in_buffer_off < urh->in_buffer_size)
1236 p[0].events |= POLLIN;
1238 p[0].events |= POLLOUT;
1239 if (urh->out_buffer_off < urh->out_buffer_size)
1240 p[1].events |= POLLIN;
1242 p[1].events |= POLLOUT;
1244 if ( (0 != (p[0].events | p[1].events)) &&
1253 #ifdef HAVE_MESSAGES 1255 _(
"Error during poll: `%s'\n"),
1260 if (0 != (p[0].revents & POLLIN))
1262 if (0 != (p[0].revents & POLLOUT))
1264 if (0 != (p[1].revents & POLLIN))
1266 if (0 != (p[1].revents & POLLOUT))
1269 if ( (0 == urh->out_buffer_size) &&
1270 (0 == urh->in_buffer_size) )
1288 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
1298 struct timeval *tvp;
1304 #define EXTRA_SLOTS 1 1306 #define EXTRA_SLOTS 0 1309 struct pollfd p[1 + EXTRA_SLOTS];
1320 if (
MHD_YES == con->tls_read_ready)
1328 if ( (
NULL == tvp) &&
1336 const time_t seconds_left = timeout - (now - con->
last_activity);
1338 tv.tv_sec = seconds_left;
1395 if (MHD_ITC_IS_VALID_(daemon->
itc) )
1406 #ifdef HAVE_MESSAGES 1408 _(
"Failed to add FD to fd_set\n"));
1424 #ifdef HAVE_MESSAGES 1426 _(
"Error during select (%d): `%s'\n"),
1435 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
1436 (FD_ISSET (MHD_itc_r_fd_ (daemon->
itc),
1438 MHD_itc_clear_ (daemon->
itc);
1460 p[0].events |= POLLIN;
1463 p[0].events |= POLLOUT;
1465 p[0].events |= POLLIN;
1469 p[0].events |= POLLIN;
1480 if (MHD_ITC_IS_VALID_(daemon->
itc))
1482 p[1].events |= POLLIN;
1483 p[1].fd = MHD_itc_r_fd_ (daemon->
itc);
1488 if (MHD_sys_poll_ (p,
1494 (
NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
1498 #ifdef HAVE_MESSAGES 1500 _(
"Error during poll: `%s'\n"),
1508 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
1509 (0 != (p[1].revents & (POLLERR | POLLHUP | POLLIN))) )
1510 MHD_itc_clear_ (daemon->
itc);
1514 0 != (p[0].revents & POLLIN),
1515 0 != (p[0].revents & POLLOUT),
1516 0 != (p[0].revents & (POLLERR | POLLHUP))))
1538 return (MHD_THRD_RTRN_TYPE_) 0;
1544 #ifdef HAVE_MESSAGES 1546 _(
"Processing thread terminating. Closing connection\n"));
1568 return (MHD_THRD_RTRN_TYPE_) 0;
1593 #ifdef MHD_POSIX_SOCKETS 1604 #ifdef EPOLL_SUPPORT 1657 #ifndef HAVE_SENDFILE64 1666 #ifndef HAVE_SENDFILE64 1667 offset = (off_t) offsetu64;
1668 if ( (offsetu64 <= (uint64_t)
OFF_T_MAX) &&
1669 (0 < (ret = sendfile (connection->
socket_fd,
1674 offset = (off64_t) offsetu64;
1675 if ( (offsetu64 <= (uint64_t) OFF64_T_MAX) &&
1676 (0 < (ret = sendfile64 (connection->
socket_fd,
1686 #ifdef EPOLL_SUPPORT 1710 #ifdef EPOLL_SUPPORT 1768 const struct sockaddr *addr,
1807 #ifdef HAVE_MESSAGES 1809 _(
"Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
1810 (
int) client_socket,
1821 #ifdef HAVE_MESSAGES 1824 _(
"Accepted connection on socket %d\n"),
1834 #ifdef HAVE_MESSAGES 1836 _(
"Server reached connection limit. Closing inbound connection.\n"));
1852 #ifdef HAVE_MESSAGES 1854 _(
"Connection rejected by application. Closing connection.\n"));
1870 setsockopt (client_socket,
1882 #ifdef HAVE_MESSAGES 1884 "Error allocating memory: %s\n",
1900 #ifdef HAVE_MESSAGES 1902 _(
"Error allocating memory: %s\n"),
1917 if (
NULL == (connection->
addr = malloc (addrlen)))
1920 #ifdef HAVE_MESSAGES 1922 _(
"Error allocating memory: %s\n"),
1934 memcpy (connection->
addr,
1939 connection->
daemon = daemon;
1953 #ifdef HAVE_MESSAGES 1954 MHD_DLOG (connection->
daemon,
1955 _(
"Failed to set nonblocking mode on connection socket: %s\n"),
1964 connection->
recv_cls = &recv_tls_adapter;
1965 connection->
send_cls = &send_tls_adapter;
1968 gnutls_init (&connection->tls_session,
1970 gnutls_priority_set (connection->tls_session,
1971 daemon->priority_cache);
1972 switch (daemon->cred_type)
1975 case GNUTLS_CRD_CERTIFICATE:
1976 gnutls_credentials_set (connection->tls_session,
1977 GNUTLS_CRD_CERTIFICATE,
1981 #ifdef HAVE_MESSAGES 1982 MHD_DLOG (connection->
daemon,
1983 _(
"Failed to setup TLS credentials: unknown credential type %d\n"),
1990 free (connection->
addr);
1998 gnutls_transport_set_ptr (connection->tls_session,
1999 (gnutls_transport_ptr_t) connection);
2000 gnutls_transport_set_pull_function (connection->tls_session,
2002 gnutls_transport_set_push_function (connection->tls_session,
2005 if (daemon->https_mem_trust)
2006 gnutls_certificate_server_set_request (connection->tls_session,
2007 GNUTLS_CERT_REQUEST);
2043 #ifdef HAVE_MESSAGES 2045 "Failed to create a thread: %s\n",
2052 if ( (
MHD_YES == external_add) &&
2053 (MHD_ITC_IS_VALID_(daemon->
itc)) &&
2054 (! MHD_itc_activate_ (daemon->
itc,
"n")) )
2056 #ifdef HAVE_MESSAGES 2058 _(
"Failed to signal new connection via inter-thread communication channel."));
2061 #ifdef EPOLL_SUPPORT 2066 struct epoll_event event;
2068 event.events = EPOLLIN | EPOLLOUT | EPOLLET;
2069 event.data.ptr = connection;
2070 if (0 != epoll_ctl (daemon->epoll_fd,
2076 #ifdef HAVE_MESSAGES 2078 _(
"Call to epoll_ctl failed: %s\n"),
2090 daemon->eready_tail,
2123 free (connection->
addr);
2162 daemon = connection->
daemon;
2164 MHD_PANIC (
_(
"Cannot suspend connections without enabling MHD_USE_SUSPEND_RESUME!\n"));
2186 #ifdef EPOLL_SUPPORT 2192 daemon->eready_tail,
2198 if (0 != epoll_ctl (daemon->epoll_fd,
2202 MHD_PANIC (
_(
"Failed to remove FD from epoll set\n"));
2227 daemon = connection->
daemon;
2229 MHD_PANIC (
_(
"Cannot resume connections without enabling MHD_USE_SUSPEND_RESUME!\n"));
2234 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
2235 (! MHD_itc_activate_ (daemon->
itc,
"r")) )
2237 #ifdef HAVE_MESSAGES 2239 _(
"Failed to signal resume via inter-thread communication channel."));
2277 while (
NULL != (pos = next))
2300 #ifdef EPOLL_SUPPORT 2304 MHD_PANIC (
"Resumed connection was already in EREADY set\n");
2308 daemon->eready_tail,
2355 const struct sockaddr *
addr,
2364 #ifdef HAVE_MESSAGES 2366 _(
"Failed to set nonblocking mode on new client socket: %s\n"),
2372 #ifdef HAVE_MESSAGES 2374 _(
"Failed to set noninheritable mode on new client socket.\n"));
2402 struct sockaddr_in6 addrstorage;
2404 struct sockaddr_in addrstorage;
2406 struct sockaddr *addr = (
struct sockaddr *) &addrstorage;
2411 addrlen =
sizeof (addrstorage);
2414 sizeof (addrstorage));
2439 #ifdef HAVE_MESSAGES 2442 _(
"Error accepting connection: %s\n"),
2454 #ifdef HAVE_MESSAGES 2459 _(
"Hit process or system resource limit at FIRST connection. This is really bad as there is no sane way to proceed. Will try busy waiting for system resources to become magically available.\n"));
2465 #ifdef HAVE_MESSAGES 2467 _(
"Hit process or system resource limit at %u connections, temporarily suspending accept(). Consider setting a lower MHD_OPTION_CONNECTION_LIMIT.\n"),
2474 #if !defined(USE_ACCEPT4) || !defined(HAVE_SOCK_NONBLOCK) 2477 #ifdef HAVE_MESSAGES 2479 _(
"Failed to set nonblocking mode on incoming connection socket: %s\n"),
2484 #if !defined(USE_ACCEPT4) || !defined(SOCK_CLOEXEC) 2487 #ifdef HAVE_MESSAGES 2489 _(
"Failed to set noninheritable mode on incoming connection socket.\n"));
2493 #ifdef HAVE_MESSAGES 2496 _(
"Accepted connection on socket %d\n"),
2534 (! MHD_join_thread_ (pos->
pid)) )
2538 if (
NULL != pos->tls_session)
2539 gnutls_deinit (pos->tls_session);
2553 #ifdef EPOLL_SUPPORT 2559 daemon->eready_tail,
2563 if ( (-1 != daemon->epoll_fd) &&
2572 if (0 != epoll_ctl (daemon->epoll_fd,
2576 MHD_PANIC (
_(
"Failed to remove FD from epoll set\n"));
2618 time_t earliest_deadline;
2625 #ifdef HAVE_MESSAGES 2627 _(
"Illegal call to MHD_get_timeout\n"));
2633 if (0 != daemon->num_tls_read_ready)
2643 earliest_deadline = 0;
2648 if ( (! have_timeout) ||
2653 (0 != gnutls_record_check_pending (pos->tls_session)) )
2654 earliest_deadline = 0;
2661 if ( (
NULL != pos) &&
2664 if ( (! have_timeout) ||
2669 (0 != gnutls_record_check_pending (pos->tls_session)) )
2670 earliest_deadline = 0;
2675 if (
MHD_NO == have_timeout)
2678 if (earliest_deadline < now)
2682 const time_t second_left = earliest_deadline - now;
2686 *timeout = 1000 * second_left;
2713 const fd_set *read_fd_set,
2714 const fd_set *write_fd_set,
2715 const fd_set *except_fd_set)
2730 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
2731 (FD_ISSET (MHD_itc_r_fd_ (daemon->
itc),
2733 MHD_itc_clear_ (daemon->
itc);
2739 #ifdef EPOLL_SUPPORT 2747 if (FD_ISSET (daemon->epoll_fd,
2764 while (
NULL != (pos = next))
2781 for (urh = daemon->urh_head;
NULL != urh; urh = urhn)
2785 urh_from_fdset (urh,
2814 struct timeval timeout;
2820 timeout.tv_usec = 0;
2843 #ifdef HAVE_MESSAGES 2845 _(
"Could not obtain daemon fdsets"));
2859 #ifdef HAVE_MESSAGES 2861 _(
"Could not add listen socket to fdset"));
2866 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
2872 #if defined(MHD_WINSOCK_SOCKETS) 2886 #ifdef HAVE_MESSAGES 2888 _(
"Could not add control inter-thread communication channel FD to fdset"));
2891 #if defined(MHD_WINSOCK_SOCKETS) 2903 (MHD_ITC_IS_VALID_(daemon->
itc)) &&
2916 timeout.tv_usec = 0;
2924 timeout.tv_usec = (ltimeout % 1000) * 1000;
2943 #ifdef HAVE_MESSAGES 2945 _(
"select failed: %s\n"),
2972 unsigned int num_connections;
2985 num_connections = 0;
2989 for (urh = daemon->urh_head;
NULL != urh; urh = urh->next)
2990 num_connections += 2;
2996 unsigned int poll_server;
3001 p = malloc (
sizeof (
struct pollfd) * (2 + num_connections));
3004 #ifdef HAVE_MESSAGES 3006 _(
"Error allocating memory: %s\n"),
3013 sizeof (
struct pollfd) * (2 + num_connections));
3022 p[poll_server].events = POLLIN;
3023 p[poll_server].revents = 0;
3024 poll_listen = (int) poll_server;
3028 if (MHD_ITC_IS_VALID_(daemon->
itc))
3030 p[poll_server].fd = MHD_itc_r_fd_ (daemon->
itc);
3031 p[poll_server].events = POLLIN;
3032 p[poll_server].revents = 0;
3033 poll_itc_idx = (int) poll_server;
3043 timeout = (ltimeout > INT_MAX) ? INT_MAX : (
int) ltimeout;
3052 p[poll_server+i].events |= POLLIN;
3055 p[poll_server+i].events |= POLLOUT;
3057 p[poll_server+i].events |= POLLIN;
3061 p[poll_server+i].events |= POLLIN;
3070 for (urh = daemon->urh_head;
NULL != urh; urh = urh->next)
3073 if (urh->in_buffer_off < urh->in_buffer_size)
3074 p[poll_server+i].events |= POLLIN;
3076 p[poll_server+i].events |= POLLOUT;
3078 p[poll_server+i].fd = urh->mhd.socket;
3079 if (urh->out_buffer_off < urh->out_buffer_size)
3080 p[poll_server+i].events |= POLLIN;
3082 p[poll_server+i].events |= POLLOUT;
3086 if (0 == poll_server + num_connections)
3091 if (MHD_sys_poll_(p,
3092 poll_server + num_connections,
3101 #ifdef HAVE_MESSAGES 3103 _(
"poll failed: %s\n"),
3112 if ( (-1 != poll_itc_idx) &&
3113 (0 != (p[poll_itc_idx].revents & POLLIN)) )
3114 MHD_itc_clear_ (daemon->
itc);
3124 while (
NULL != (pos = next))
3128 if (i >= num_connections)
3133 0 != (p[poll_server+i].revents & POLLIN),
3134 0 != (p[poll_server+i].revents & POLLOUT),
3139 for (urh = daemon->urh_head;
NULL != urh; urh = urhn)
3141 if (i >= num_connections)
3146 if (0 != (p[poll_server+i].revents & POLLIN))
3148 if (0 != (p[poll_server+i].revents & POLLOUT))
3151 if (p[poll_server+i].
fd != urh->mhd.socket)
3159 if (0 != (p[poll_server+i].revents & POLLIN))
3161 if (0 != (p[poll_server+i].revents & POLLOUT))
3168 if ( (-1 != poll_listen) &&
3169 (0 != (p[poll_listen].revents & POLLIN)) )
3186 MHD_poll_listen_socket (
struct MHD_Daemon *daemon,
3191 unsigned int poll_count;
3204 p[poll_count].events = POLLIN;
3205 p[poll_count].revents = 0;
3206 poll_listen = poll_count;
3209 if (MHD_ITC_IS_VALID_(daemon->
itc))
3211 p[poll_count].fd = MHD_itc_r_fd_ (daemon->
itc);
3212 p[poll_count].events = POLLIN;
3213 p[poll_count].revents = 0;
3214 poll_itc_idx = poll_count;
3221 if (0 == poll_count)
3223 if (MHD_sys_poll_(p,
3231 #ifdef HAVE_MESSAGES 3233 _(
"poll failed: %s\n"),
3238 if ( (-1 != poll_itc_idx) &&
3239 (0 != (p[poll_itc_idx].revents & POLLIN)) )
3240 MHD_itc_clear_ (daemon->
itc);
3245 if ( (-1 != poll_listen) &&
3246 (0 != (p[poll_listen].revents & POLLIN)) )
3268 return MHD_poll_all (daemon,
3270 return MHD_poll_listen_socket (daemon,
3278 #ifdef EPOLL_SUPPORT 3288 #define MAX_EVENTS 128 3300 run_epoll_for_upgrade (
struct MHD_Daemon *daemon)
3302 struct epoll_event events[MAX_EVENTS];
3307 num_events = MAX_EVENTS;
3308 while (MAX_EVENTS == num_events)
3311 num_events = epoll_wait (daemon->epoll_upgrade_fd,
3315 if (-1 == num_events)
3320 #ifdef HAVE_MESSAGES 3322 _(
"Call to epoll_wait failed: %s\n"),
3327 for (i=0;i<(
unsigned int) num_events;i++)
3340 for (j=i+1;j< (
unsigned int) num_events;j++)
3351 if (0 != (events[j].events & EPOLLIN))
3353 if (0 != (events[j].events & EPOLLOUT))
3356 events[j].data.ptr =
NULL;
3360 if (0 != (events[i].events & EPOLLIN))
3362 if (0 != (events[i].events & EPOLLOUT))
3387 static const char *upgrade_marker =
"upgrade_ptr";
3391 struct epoll_event events[MAX_EVENTS];
3392 struct epoll_event event;
3397 unsigned int series_length;
3399 if (-1 == daemon->epoll_fd)
3405 (
MHD_NO == daemon->listen_socket_in_epoll) &&
3408 event.events = EPOLLIN;
3409 event.data.ptr = daemon;
3410 if (0 != epoll_ctl (daemon->epoll_fd,
3415 #ifdef HAVE_MESSAGES 3417 _(
"Call to epoll_ctl failed: %s\n"),
3422 daemon->listen_socket_in_epoll =
MHD_YES;
3425 if ( (
MHD_NO == daemon->upgrade_fd_in_epoll) &&
3426 (-1 != daemon->epoll_upgrade_fd) )
3428 event.events = EPOLLIN | EPOLLOUT;
3429 event.data.ptr = (
void *) upgrade_marker;
3430 if (0 != epoll_ctl (daemon->epoll_fd,
3432 daemon->epoll_upgrade_fd,
3435 #ifdef HAVE_MESSAGES 3437 _(
"Call to epoll_ctl failed: %s\n"),
3442 daemon->upgrade_fd_in_epoll =
MHD_YES;
3445 if ( ( (
MHD_YES == daemon->listen_socket_in_epoll) &&
3451 if (0 != epoll_ctl (daemon->epoll_fd,
3455 MHD_PANIC (
_(
"Failed to remove listen FD from epoll set\n"));
3456 daemon->listen_socket_in_epoll =
MHD_NO;
3464 timeout_ms = INT_MAX;
3466 timeout_ms = (int) timeout_ll;
3478 num_events = MAX_EVENTS;
3479 while (MAX_EVENTS == num_events)
3482 num_events = epoll_wait (daemon->epoll_fd,
3486 if (-1 == num_events)
3491 #ifdef HAVE_MESSAGES 3493 _(
"Call to epoll_wait failed: %s\n"),
3498 for (i=0;i<(
unsigned int) num_events;i++)
3505 if (upgrade_marker == events[i].
data.ptr)
3509 run_epoll_for_upgrade (daemon);
3518 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
3519 (MHD_itc_r_fd_ (daemon->
itc) == events[i].data.fd) )
3523 MHD_itc_clear_ (daemon->
itc);
3526 if (daemon == events[i].
data.ptr)
3533 (series_length < 128) &&
3541 pos = events[i].data.ptr;
3543 if (0 != (events[i].events & EPOLLIN))
3551 daemon->eready_tail,
3556 if (0 != (events[i].events & EPOLLOUT))
3563 daemon->eready_tail,
3577 while (
NULL != (pos = daemon->eready_tail))
3580 daemon->eready_tail,
3598 while (
NULL != (pos = next))
3608 while (
NULL != (pos = next))
3651 #ifdef EPOLL_SUPPORT 3654 MHD_epoll (daemon,
MHD_NO);
3707 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
3717 #ifdef EPOLL_SUPPORT 3736 return (MHD_THRD_RTRN_TYPE_)0;
3833 #ifdef HAVE_MESSAGES 3835 "Using MHD_quiesce_daemon in this mode requires MHD_USE_ITC\n");
3844 #ifdef EPOLL_SUPPORT 3849 if (0 != epoll_ctl (daemon->
worker_pool[i].epoll_fd,
3853 MHD_PANIC (
_(
"Failed to remove listen FD from epoll set\n"));
3861 MHD_PANIC (
_(
"Failed to signal quiesce via inter-thread communication channel"));
3865 #ifdef EPOLL_SUPPORT 3867 (-1 != daemon->epoll_fd) &&
3868 (
MHD_YES == daemon->listen_socket_in_epoll) )
3870 if (0 != epoll_ctl (daemon->epoll_fd,
3874 MHD_PANIC (
"Failed to remove listen FD from epoll set\n");
3875 daemon->listen_socket_in_epoll =
MHD_NO;
3879 if (MHD_ITC_IS_VALID_(daemon->
itc))
3881 if (! MHD_itc_activate_ (daemon->
itc,
"q"))
3882 MHD_PANIC (
_(
"failed to signal quiesce via inter-thread communication channel"));
3912 const struct sockaddr **servaddr,
3926 const struct sockaddr **servaddr,
3932 va_start (ap, servaddr);
3951 const struct sockaddr **servaddr,
3999 *servaddr = va_arg (ap,
4000 const struct sockaddr *);
4013 #ifdef HAVE_MESSAGES 4015 _(
"Specified thread pool size (%u) too big\n"),
4024 daemon->https_mem_key = va_arg (ap,
4026 #ifdef HAVE_MESSAGES 4029 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4035 daemon->https_key_password = va_arg (ap,
4037 #ifdef HAVE_MESSAGES 4040 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4046 daemon->https_mem_cert = va_arg (ap,
4048 #ifdef HAVE_MESSAGES 4051 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4057 daemon->https_mem_trust = va_arg (ap,
4059 #ifdef HAVE_MESSAGES 4062 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4067 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
4073 const char *arg = va_arg (ap,
4075 gnutls_datum_t dhpar;
4077 if (gnutls_dh_params_init (&daemon->https_mem_dhparams) < 0)
4079 #ifdef HAVE_MESSAGES 4081 _(
"Error initializing DH parameters\n"));
4085 dhpar.data = (
unsigned char *) arg;
4086 dhpar.size = strlen (arg);
4087 if (gnutls_dh_params_import_pkcs3 (daemon->https_mem_dhparams,
4089 GNUTLS_X509_FMT_PEM) < 0)
4091 #ifdef HAVE_MESSAGES 4093 _(
"Bad Diffie-Hellman parameters format\n"));
4095 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
4098 daemon->have_dhparams =
MHD_YES;
4102 #ifdef HAVE_MESSAGES 4104 _(
"MHD HTTPS option %d passed to MHD but MHD_USE_TLS not set\n"),
4113 gnutls_priority_deinit (daemon->priority_cache);
4114 ret = gnutls_priority_init (&daemon->priority_cache,
4115 pstr = va_arg (ap,
const char*),
4117 if (GNUTLS_E_SUCCESS != ret)
4119 #ifdef HAVE_MESSAGES 4121 _(
"Setting priorities to `%s' failed: %s\n"),
4123 gnutls_strerror (ret));
4125 daemon->priority_cache =
NULL;
4131 #if GNUTLS_VERSION_MAJOR < 3 4132 #ifdef HAVE_MESSAGES 4134 _(
"MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n"));
4139 daemon->cert_callback = va_arg (ap,
4140 gnutls_certificate_retrieve_function2 *);
4144 #ifdef DAUTH_SUPPORT 4146 daemon->digest_auth_rand_size = va_arg (ap,
4148 daemon->digest_auth_random = va_arg (ap,
4152 daemon->nonce_nc_size = va_arg (ap,
4161 #ifdef HAVE_MESSAGES 4162 daemon->custom_error_log = va_arg (ap,
4164 daemon->custom_error_log_cls = va_arg (ap,
4179 daemon->fastopen_queue_size = va_arg (ap,
4185 unsigned int) ? 1 : -1;
4205 (
size_t) oa[i].
value,
4221 (
unsigned int) oa[i].value,
4269 (
void *) oa[i].value,
4279 (
size_t) oa[i].value,
4297 #ifdef HAVE_MESSAGES 4303 _(
"MHD HTTPS option %d passed to MHD compiled without HTTPS support\n"),
4309 _(
"Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n"),
4320 #ifdef EPOLL_SUPPORT 4326 #ifdef USE_EPOLL_CREATE1 4327 fd = epoll_create1 (EPOLL_CLOEXEC);
4329 fd = epoll_create (MAX_EVENTS);
4333 #ifdef HAVE_MESSAGES 4335 _(
"Call to epoll_create1 failed: %s\n"),
4340 #if !defined(USE_EPOLL_CREATE1) 4343 #ifdef HAVE_MESSAGES 4345 _(
"Failed to set noninheritable mode on epoll FD.\n"));
4361 setup_epoll_to_listen (
struct MHD_Daemon *daemon)
4363 struct epoll_event event;
4365 daemon->epoll_fd = setup_epoll_fd (daemon);
4366 if (-1 == daemon->epoll_fd)
4371 daemon->epoll_upgrade_fd = setup_epoll_fd (daemon);
4378 event.events = EPOLLIN;
4379 event.data.ptr = daemon;
4380 if (0 != epoll_ctl (daemon->epoll_fd,
4385 #ifdef HAVE_MESSAGES 4387 _(
"Call to epoll_ctl failed: %s\n"),
4392 if ( (MHD_ITC_IS_VALID_(daemon->
itc)) &&
4395 event.events = EPOLLIN | EPOLLET;
4396 event.data.ptr =
NULL;
4397 event.data.fd = MHD_itc_r_fd_ (daemon->
itc);
4398 if (0 != epoll_ctl (daemon->epoll_fd,
4400 MHD_itc_r_fd_ (daemon->
itc),
4403 #ifdef HAVE_MESSAGES 4405 _(
"Call to epoll_ctl failed: %s\n"),
4411 daemon->listen_socket_in_epoll =
MHD_YES;
4446 struct sockaddr_in servaddr4;
4448 struct sockaddr_in6 servaddr6;
4450 const struct sockaddr *servaddr =
NULL;
4467 #ifndef TCP_FASTOPEN 4478 #ifdef EPOLL_SUPPORT 4479 daemon->epoll_fd = -1;
4481 daemon->epoll_upgrade_fd = -1;
4486 if (0 != (flags & MHD_USE_TLS))
4488 gnutls_priority_init (&daemon->priority_cache,
4496 daemon->
port = port;
4507 MHD_itc_set_invalid_ (daemon->
itc);
4513 #ifdef HAVE_MESSAGES 4515 daemon->custom_error_log_cls = stderr;
4517 #ifdef HAVE_LISTEN_SHUTDOWN 4526 if (! MHD_itc_init_ (daemon->
itc))
4528 #ifdef HAVE_MESSAGES 4530 _(
"Failed to create inter-thread communication channel: %s\n"),
4531 MHD_itc_last_strerror_ ());
4542 #ifdef HAVE_MESSAGES 4544 _(
"file descriptor for inter-thread communication channel exceeds maximum value\n"));
4550 #ifdef DAUTH_SUPPORT 4551 daemon->digest_auth_rand_size = 0;
4552 daemon->digest_auth_random =
NULL;
4553 daemon->nonce_nc_size = 4;
4556 if (0 != (flags & MHD_USE_TLS))
4558 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
4568 if ( (0 != (flags & MHD_USE_TLS)) &&
4569 (
NULL != daemon->priority_cache) )
4570 gnutls_priority_deinit (daemon->priority_cache);
4575 #ifdef DAUTH_SUPPORT 4576 if (daemon->nonce_nc_size > 0)
4578 if ( ( (
size_t) (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc))) /
4579 sizeof(
struct MHD_NonceNc) != daemon->nonce_nc_size)
4581 #ifdef HAVE_MESSAGES 4583 _(
"Specified value for NC_SIZE too large\n"));
4586 if (0 != (flags & MHD_USE_TLS))
4587 gnutls_priority_deinit (daemon->priority_cache);
4592 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (
struct MHD_NonceNc));
4593 if (
NULL == daemon->nnc)
4595 #ifdef HAVE_MESSAGES 4597 _(
"Failed to allocate memory for nonce-nc map: %s\n"),
4601 if (0 != (flags & MHD_USE_TLS))
4602 gnutls_priority_deinit (daemon->priority_cache);
4609 if (! MHD_mutex_init_ (&daemon->nnc_lock))
4611 #ifdef HAVE_MESSAGES 4613 _(
"MHD failed to initialize nonce-nc mutex\n"));
4616 if (0 != (flags & MHD_USE_TLS))
4617 gnutls_priority_deinit (daemon->priority_cache);
4629 #ifdef HAVE_MESSAGES 4631 _(
"MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n"));
4639 #ifdef HAVE_MESSAGES 4641 _(
"Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_SUSPEND_RESUME is not supported.\n"));
4646 #ifdef __SYMBIAN32__ 4647 if (0 != (flags & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
4649 #ifdef HAVE_MESSAGES 4651 _(
"Threaded operations are not supported on Symbian.\n"));
4663 #ifdef HAVE_MESSAGES 4665 _(
"Failed to create socket for listening: %s\n"),
4676 if (0 > setsockopt (socket_fd,
4679 (
void*)&on,
sizeof (on)))
4681 #ifdef HAVE_MESSAGES 4683 _(
"setsockopt failed: %s\n"),
4697 if (0 > setsockopt (socket_fd,
4700 (
void*)&on,
sizeof (on)))
4702 #ifdef HAVE_MESSAGES 4704 "setsockopt failed: %s\n",
4710 #ifndef SO_REUSEPORT 4715 #define SO_REUSEPORT 15 4719 if (0 > setsockopt (socket_fd,
4725 #ifdef HAVE_MESSAGES 4727 _(
"setsockopt failed: %s\n"),
4735 #ifdef HAVE_MESSAGES 4737 _(
"Cannot allow listening address reuse: SO_REUSEPORT not defined\n"));
4750 #ifdef SO_EXCLUSIVEADDRUSE 4751 if (0 > setsockopt (socket_fd,
4753 SO_EXCLUSIVEADDRUSE,
4757 #ifdef HAVE_MESSAGES 4759 _(
"setsockopt failed: %s\n"),
4765 #ifdef HAVE_MESSAGES 4767 _(
"Cannot disallow listening address reuse: SO_EXCLUSIVEADDRUSE not defined\n"));
4776 if (0 != (flags & MHD_USE_IPv6))
4777 addrlen =
sizeof (
struct sockaddr_in6);
4780 addrlen =
sizeof (
struct sockaddr_in);
4781 if (
NULL == servaddr)
4784 if (0 != (flags & MHD_USE_IPv6))
4788 sizeof (
struct sockaddr_in6));
4789 servaddr6.sin6_family = AF_INET6;
4790 servaddr6.sin6_port = htons (port);
4791 #if HAVE_SOCKADDR_IN_SIN_LEN 4792 servaddr6.sin6_len =
sizeof (
struct sockaddr_in6);
4794 servaddr = (
struct sockaddr *) &servaddr6;
4801 sizeof (
struct sockaddr_in));
4802 servaddr4.sin_family = AF_INET;
4803 servaddr4.sin_port = htons (port);
4804 #if HAVE_SOCKADDR_IN_SIN_LEN 4805 servaddr4.sin_len =
sizeof (
struct sockaddr_in);
4807 servaddr = (
struct sockaddr *) &servaddr4;
4812 if (0 != (flags & MHD_USE_IPv6))
4822 if (0 > setsockopt (socket_fd,
4823 IPPROTO_IPV6, IPV6_V6ONLY,
4824 (
const void *) &v6_only,
4827 #ifdef HAVE_MESSAGES 4829 _(
"setsockopt failed: %s\n"),
4836 if (-1 == bind (socket_fd, servaddr, addrlen))
4838 #ifdef HAVE_MESSAGES 4840 _(
"Failed to bind to port %u: %s\n"),
4841 (
unsigned int) port,
4848 if (0 != (flags & MHD_USE_TCP_FASTOPEN))
4850 if (0 == daemon->fastopen_queue_size)
4851 daemon->fastopen_queue_size = MHD_TCP_FASTOPEN_QUEUE_SIZE_DEFAULT;
4852 if (0 != setsockopt (socket_fd,
4855 &daemon->fastopen_queue_size,
4856 sizeof (daemon->fastopen_queue_size)))
4858 #ifdef HAVE_MESSAGES 4860 _(
"setsockopt failed: %s\n"),
4866 if (listen (socket_fd,
4869 #ifdef HAVE_MESSAGES 4871 _(
"Failed to listen for connections: %s\n"),
4885 #ifdef HAVE_MESSAGES 4887 _(
"Failed to set nonblocking mode on listening socket: %s\n"),
4904 #ifdef HAVE_MESSAGES 4906 _(
"Socket descriptor larger than FD_SETSIZE: %d > %d\n"),
4914 #ifdef EPOLL_SUPPORT 4919 if (0 != (flags & MHD_USE_THREAD_PER_CONNECTION))
4921 #ifdef HAVE_MESSAGES 4923 _(
"Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL is not supported.\n"));
4927 if (
MHD_YES != setup_epoll_to_listen (daemon))
4931 if (0 != (flags & MHD_USE_EPOLL))
4933 #ifdef HAVE_MESSAGES 4935 _(
"epoll is not supported on this platform by this build.\n"));
4943 #ifdef HAVE_MESSAGES 4945 _(
"MHD failed to initialize IP connection limit mutex\n"));
4953 #ifdef HAVE_MESSAGES 4955 _(
"MHD failed to initialize IP connection limit mutex\n"));
4965 if ( (0 != (flags & MHD_USE_TLS)) &&
4966 (0 != MHD_TLS_init (daemon)) )
4968 #ifdef HAVE_MESSAGES 4970 _(
"Failed to initialize TLS support\n"));
4979 if ( ( (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) ||
4980 ( (0 != (flags & MHD_USE_SELECT_INTERNALLY)) &&
4984 (flags & MHD_USE_THREAD_PER_CONNECTION) ?
4985 "MHD-listen" :
"MHD-single",
4990 #ifdef HAVE_MESSAGES 4992 _(
"Failed to create listen thread: %s\n"),
5026 memcpy (d, daemon,
sizeof (
struct MHD_Daemon));
5037 if (! MHD_itc_init_ (d->
itc))
5039 #ifdef HAVE_MESSAGES 5041 _(
"Failed to create worker inter-thread communication channel: %s\n"),
5042 MHD_itc_last_strerror_() );
5047 if ( (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL))) &&
5051 #ifdef HAVE_MESSAGES 5053 _(
"File descriptor for worker inter-thread communication channel exceeds maximum value\n"));
5063 if (i < leftover_conns)
5065 #ifdef EPOLL_SUPPORT 5066 if ( (0 != (daemon->
options & MHD_USE_EPOLL)) &&
5067 (
MHD_YES != setup_epoll_to_listen (d)) )
5073 #ifdef HAVE_MESSAGES 5075 _(
"MHD failed to initialize cleanup connection mutex\n"));
5087 #ifdef HAVE_MESSAGES 5089 _(
"Failed to create pool thread: %s\n"),
5102 daemon->https_key_password =
NULL;
5135 #ifdef EPOLL_SUPPORT 5136 if (
MHD_YES == daemon->upgrade_fd_in_epoll)
5138 if (0 != epoll_ctl (daemon->epoll_fd,
5140 daemon->epoll_upgrade_fd,
5142 MHD_PANIC (
_(
"Failed to remove FD from epoll set\n"));
5143 daemon->upgrade_fd_in_epoll =
MHD_NO;
5145 if (-1 != daemon->epoll_fd)
5146 close (daemon->epoll_fd);
5148 if (-1 != daemon->epoll_upgrade_fd)
5149 close (daemon->epoll_upgrade_fd);
5153 #ifdef DAUTH_SUPPORT 5158 if (0 != (flags & MHD_USE_TLS))
5159 gnutls_priority_deinit (daemon->priority_cache);
5161 if (MHD_ITC_IS_VALID_(daemon->
itc))
5190 MHD_PANIC (
_(
"MHD_stop_daemon() called while we have suspended connections.\n"));
5194 #if MHD_WINSOCK_SOCKETS 5196 (MHD_ITC_IS_VALID_(daemon->
itc)) &&
5197 (! MHD_itc_activate_ (daemon->
itc,
"e")) )
5198 MHD_PANIC (
_(
"Failed to signal shutdown via inter-thread communication channel"));
5212 if (! MHD_join_thread_ (pos->
pid))
5235 #ifdef EPOLL_SUPPORT 5244 struct epoll_event event;
5251 event.events = EPOLLOUT;
5252 event.data.ptr =
NULL;
5253 if (0 != epoll_ctl (daemon->epoll_fd,
5255 MHD_itc_w_fd_ (daemon->
itc),
5257 MHD_PANIC (
_(
"Failed to add inter-thread communication channel FD to epoll set to signal termination\n"));
5283 for (urh = daemon->urh_head;
NULL != urh; urh = urhn)
5306 #ifdef EPOLL_SUPPORT 5314 if (MHD_ITC_IS_VALID_(daemon->
itc))
5316 if (! MHD_itc_activate_ (daemon->
itc,
"e"))
5317 MHD_PANIC (
_(
"Failed to signal shutdown via inter-thread communication channel"));
5319 #ifdef HAVE_LISTEN_SHUTDOWN 5325 (void) shutdown (fd,
5329 #ifdef EPOLL_SUPPORT 5331 (-1 != daemon->epoll_fd) &&
5333 epoll_shutdown (daemon);
5337 #ifdef HAVE_MESSAGES 5339 _(
"MHD listen socket shutdown\n"));
5353 MHD_PANIC (
_(
"Failed to signal shutdown via inter-thread communication channel."));
5359 #ifdef EPOLL_SUPPORT 5363 if (-1 != daemon->
worker_pool[i].epoll_upgrade_fd)
5385 if (! MHD_join_thread_ (daemon->
pid))
5397 if (
MHD_YES == daemon->have_dhparams)
5399 gnutls_dh_params_deinit (daemon->https_mem_dhparams);
5400 daemon->have_dhparams =
MHD_NO;
5404 gnutls_priority_deinit (daemon->priority_cache);
5405 if (daemon->x509_cred)
5406 gnutls_certificate_free_credentials (daemon->x509_cred);
5409 #ifdef EPOLL_SUPPORT 5411 (-1 != daemon->epoll_fd) )
5415 (-1 != daemon->epoll_upgrade_fd) )
5420 #ifdef DAUTH_SUPPORT 5427 if (MHD_ITC_IS_VALID_(daemon->
itc))
5457 #ifdef EPOLL_SUPPORT 5516 #ifdef PACKAGE_VERSION 5517 return PACKAGE_VERSION;
5519 static char ver[12] =
"\0\0\0\0\0\0\0\0\0\0\0";
5522 int res = MHD_snprintf_(ver,
5528 if (0 >= res ||
sizeof(ver) <= res)
5553 #ifdef HAVE_MESSAGES 5565 #if HTTPS_SUPPORT && GNUTLS_VERSION_MAJOR >= 3 5577 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) 5589 #ifdef EPOLL_SUPPORT 5595 #ifdef HAVE_LISTEN_SHUTDOWN 5601 #ifdef _MHD_ITC_SOCKETPAIR 5613 #ifdef BAUTH_SUPPORT 5619 #ifdef DAUTH_SUPPORT 5625 #ifdef HAVE_POSTPROCESSOR 5631 #if HTTPS_SUPPORT && GNUTLS_VERSION_NUMBER >= 0x030111 5637 #if defined(HAVE___LSEEKI64) || defined(HAVE_LSEEK64) 5640 return (
sizeof(uint64_t) >
sizeof(off_t)) ?
MHD_NO :
MHD_YES;
5643 #if defined(MHD_USE_THREAD_NAME_) 5653 #if HTTPS_SUPPORT && GCRYPT_VERSION_NUMBER < 0x010600 5654 #if defined(MHD_USE_POSIX_THREADS) 5655 GCRY_THREAD_OPTION_PTHREAD_IMPL;
5656 #elif defined(MHD_W32_MUTEX_) 5659 gcry_w32_mutex_init (
void **ppmtx)
5661 *ppmtx = malloc (
sizeof (MHD_mutex_));
5665 if (!MHD_mutex_init_ ((MHD_mutex_*)*ppmtx))
5677 gcry_w32_mutex_destroy (
void **ppmtx)
5686 gcry_w32_mutex_lock (
void **ppmtx)
5694 gcry_w32_mutex_unlock (
void **ppmtx)
5701 static struct gcry_thread_cbs gcry_threads_w32 = {
5702 (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
5703 NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
5704 gcry_w32_mutex_lock, gcry_w32_mutex_unlock,
5724 if (0 != WSAStartup(MAKEWORD(2, 2), &wsd))
5725 MHD_PANIC (
_(
"Failed to initialize winsock\n"));
5726 mhd_winsock_inited_ = 1;
5727 if (2 != LOBYTE(wsd.wVersion) && 2 != HIBYTE(wsd.wVersion))
5728 MHD_PANIC (
_(
"Winsock version 2.2 is not available\n"));
5731 #if GCRYPT_VERSION_NUMBER < 0x010600 5732 #if defined(MHD_USE_POSIX_THREADS) 5733 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
5734 &gcry_threads_pthread))
5735 MHD_PANIC (
_(
"Failed to initialise multithreading in libgcrypt\n"));
5736 #elif defined(MHD_W32_MUTEX_) 5737 if (0 != gcry_control (GCRYCTL_SET_THREAD_CBS,
5739 MHD_PANIC (
_(
"Failed to initialise multithreading in libgcrypt\n"));
5741 gcry_check_version (NULL);
5743 if (NULL == gcry_check_version (
"1.6.0"))
5744 MHD_PANIC (
_(
"libgcrypt is too old. MHD was compiled for libgcrypt 1.6.0 or newer\n"));
5746 gnutls_global_init ();
5756 gnutls_global_deinit ();
5759 if (mhd_winsock_inited_)
unsigned int per_ip_connection_limit
int MHD_socket_nonblocking_(MHD_socket sock)
void * unescape_callback_cls
#define MHD_send_(s, b, l)
_MHD_EXTERN struct MHD_Daemon * MHD_start_daemon_va(unsigned int flags, uint16_t port, MHD_AcceptPolicyCallback apc, void *apc_cls, MHD_AccessHandlerCallback dh, void *dh_cls, va_list ap)
void MHD_cleanup_upgraded_connection_(struct MHD_Connection *connection)
static int parse_options(struct MHD_Daemon *daemon, const struct sockaddr **servaddr,...)
_MHD_EXTERN const char * MHD_get_version(void)
#define DLL_insert(head, tail, element)
size_t(* UnescapeCallback)(void *cls, struct MHD_Connection *conn, char *uri)
enum MHD_CONNECTION_STATE state
struct MHD_UpgradeResponseHandle * urh
uint64_t response_write_position
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ MHD_select_thread(void *cls)
void MHD_pool_destroy(struct MemoryPool *pool)
#define MHD_SCKT_SEND_MAX_SIZE_
enum MHD_ConnectionEventLoopInfo event_loop_info
void(* VfprintfFunctionPointerType)(void *cls, const char *format, va_list va)
#define MHD_ITC_IS_INVALID_(itc)
Methods for managing connections.
_MHD_EXTERN int MHD_get_timeout(struct MHD_Daemon *daemon, MHD_UNSIGNED_LONG_LONG *timeout)
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
#define MHD_socket_set_error_(err)
_MHD_EXTERN int MHD_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen)
struct MHD_Response * response
#define MHD_socket_get_error_()
struct MHD_Connection * normal_timeout_tail
Header for platform missing functions.
#define MHD_MAX_CONNECTIONS_DEFAULT
static void mhd_panic_std(void *cls, const char *file, unsigned int line, const char *reason)
MHD_AccessHandlerCallback default_handler
static ssize_t send_param_adapter(struct MHD_Connection *connection, const void *other, size_t i)
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
void MHD_suspend_connection(struct MHD_Connection *connection)
static size_t unescape_wrapper(void *cls, struct MHD_Connection *connection, char *val)
_MHD_EXTERN struct MHD_Daemon * MHD_start_daemon(unsigned int flags, uint16_t port, MHD_AcceptPolicyCallback apc, void *apc_cls, MHD_AccessHandlerCallback dh, void *dh_cls,...)
#define MHD_mutex_destroy_chk_(pmutex)
#define EDLL_insert(head, tail, element)
#define MHD_SCKT_ERR_IS_(err, code)
static int parse_options_va(struct MHD_Daemon *daemon, const struct sockaddr **servaddr, va_list ap)
#define MHD_strerror_(errnum)
#define MHD_itc_destroy_chk_(itc)
struct MHD_UpgradeResponseHandle * urh
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
static struct MHD_Daemon * MHD_get_master(struct MHD_Daemon *daemon)
void(* MHD_PanicCallback)(void *cls, const char *file, unsigned int line, const char *reason)
void(* MHD_LogCallback)(void *cls, const char *fm, va_list ap)
struct MHD_Daemon * daemon
int(* idle_handler)(struct MHD_Connection *connection)
int listening_address_reuse
MHD_mutex_ per_ip_connection_mutex
struct MHD_Connection * manual_timeout_head
MHD_NotifyConnectionCallback notify_connection
struct MHD_Connection * cleanup_head
#define MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)
#define XDLL_remove(head, tail, element)
#define MHD_mutex_unlock_chk_(pmutex)
#define XDLL_insert(head, tail, element)
MHD_socket MHD_socket_create_listen_(int use_ipv6)
struct MHD_Connection * cleanup_tail
Header for platform-independent inter-thread communication.
static int MHD_ip_addr_compare(const void *a1, const void *a2)
size_t write_buffer_send_offset
struct MHD_Daemon * worker_pool
#define MAYBE_SOCK_CLOEXEC
_MHD_EXTERN void MHD_stop_daemon(struct MHD_Daemon *daemon)
struct MHD_Connection * nextX
#define MHD_socket_close_chk_(fd)
struct MHD_Connection * manual_timeout_tail
static int MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen, struct MHD_IPCount *key)
#define MHD_INVALID_SOCKET
static int MHD_select(struct MHD_Daemon *daemon, int may_block)
#define MHD_POOL_SIZE_DEFAULT
void MHD_set_https_callbacks(struct MHD_Connection *connection)
#define MHD_create_named_thread_(t, n, s, r, a)
int MHD_add_to_fd_set_(MHD_socket fd, fd_set *set, MHD_socket *max_fd, unsigned int fd_setsize)
unsigned int connection_limit
#define MHD_recv_(s, b, l)
unsigned int worker_pool_size
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
_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
#define MHD_SYS_select_(n, r, w, e, t)
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
struct MHD_Connection * connection
static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_ thread_main_handle_connection(void *data)
static int MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
Methods for managing connections.
int(* read_handler)(struct MHD_Connection *connection)
struct MHD_Connection * normal_timeout_head
void * tdelete(const void *__restrict vkey, void **__restrict vrootp, int(*compar)(const void *, const void *))
static void MHD_ip_limit_del(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
_SET_INIT_AND_DEINIT_FUNCS(MHD_init, MHD_fini)
static int call_handlers(struct MHD_Connection *con, int read_ready, int write_ready, int force_close)
int MHD_socket_noninheritable_(MHD_socket sock)
void * tfind(const void *vkey, void *const *vrootp, int(*compar)(const void *, const void *))
#define MAYBE_SOCK_NONBLOCK
limits values definitions
Header for platform-independent threads abstraction.
void MHD_monotonic_sec_counter_init(void)
#define MHD_SCKT_ENOTCONN_
internal shared structures
UnescapeCallback unescape_callback
#define MHD_socket_last_strerr_()
#define MHD_SCKT_LAST_ERR_IS_(code)
internal monotonic clock functions implementations
int(* write_handler)(struct MHD_Connection *connection)
unsigned int listen_backlog_size
#define MHD_fd_close_chk_(fd)
struct MHD_Connection * connections_head
struct MHD_Daemon * master
struct MHD_Connection * next
MHD_AcceptPolicyCallback apc
void *(* LogCallback)(void *cls, const char *uri, struct MHD_Connection *con)
static int resume_suspended_connections(struct MHD_Daemon *daemon)
#define MHD_socket_strerr_(err)
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)
static int MHD_poll(struct MHD_Daemon *daemon, int may_block)
static void MHD_cleanup_connections(struct MHD_Daemon *daemon)
static int MHD_accept_connection(struct MHD_Daemon *daemon)
_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_ip_count_unlock(struct MHD_Daemon *daemon)
time_t MHD_monotonic_sec_counter(void)
void(* MHD_RequestCompletedCallback)(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
size_t write_buffer_append_offset
#define MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)
MHD_RequestCompletedCallback notify_completed
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
struct MHD_Connection * prevX
static void close_connection(struct MHD_Connection *pos)
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
#define DLL_remove(head, tail, element)
void * notify_completed_cls
struct MemoryPool * MHD_pool_create(size_t max)
TransmitCallback send_cls
#define EDLL_remove(head, tail, element)
_MHD_EXTERN int MHD_run(struct MHD_Daemon *daemon)
#define TIMEVAL_TV_SEC_MAX
void * notify_connection_cls
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
MHD_PanicCallback mhd_panic
struct MHD_Connection * suspended_connections_tail
void MHD_resume_connection(struct MHD_Connection *connection)
void * per_ip_connection_count
_MHD_EXTERN int MHD_is_feature_supported(enum MHD_FEATURE feature)
#define MHD_SCKT_ECONNRESET_
size_t read_buffer_offset
_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
static void thread_main_connection_upgrade(struct MHD_Connection *con)
unsigned int connection_timeout
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
#define MHD_SCKT_ERR_IS_EINTR_(err)
MHD_mutex_ cleanup_connection_mutex
_MHD_EXTERN MHD_socket MHD_quiesce_daemon(struct MHD_Daemon *daemon)
Header for platform-independent locks abstraction.
int(* MHD_AcceptPolicyCallback)(void *cls, const struct sockaddr *addr, socklen_t addrlen)
void(* MHD_NotifyConnectionCallback)(void *cls, struct MHD_Connection *connection, void **socket_context, enum MHD_ConnectionNotificationCode toe)
_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)
static void close_all_connections(struct MHD_Daemon *daemon)
struct MHD_Connection * connections_tail
#define MHD_socket_set_error_to_ENOMEM()
void MHD_monotonic_sec_counter_finish(void)
#define MHD_mutex_lock_chk_(pmutex)
static int internal_add_connection(struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, socklen_t addrlen, int external_add)
struct MHD_Connection * suspended_connections_head
#define _MHD_SYS_DEFAULT_FD_SETSIZE
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...