35 #include <gnutls/gnutls.h>
44 #include <sys/sendfile.h>
51 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE -4
53 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE
59 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
65 #define DEBUG_CLOSE MHD_NO
71 #define DEBUG_CONNECT MHD_NO
75 #define MSG_NOSIGNAL 0
78 #define MSG_DONTWAIT 0
83 static void pthread_kill (
int,
int) {
88 #endif // __SYMBIAN32__
152 struct in6_addr ipv6;
173 MHD_DLOG (daemon,
"Failed to acquire IP connection limit mutex\n");
190 MHD_DLOG (daemon,
"Failed to release IP connection limit mutex\n");
208 return memcmp (a1, a2, offsetof(
struct MHD_IPCount, count));
221 struct MHD_IPCount *key)
223 memset(key, 0,
sizeof(*key));
226 if (addrlen ==
sizeof(
struct sockaddr_in))
228 const struct sockaddr_in *addr4 = (
const struct sockaddr_in*)addr;
229 key->family = AF_INET;
230 memcpy (&key->addr.ipv4, &addr4->sin_addr,
sizeof(addr4->sin_addr));
236 if (addrlen ==
sizeof (
struct sockaddr_in6))
238 const struct sockaddr_in6 *addr6 = (
const struct sockaddr_in6*)addr;
239 key->family = AF_INET6;
240 memcpy (&key->addr.ipv6, &addr6->sin6_addr,
sizeof(addr6->sin6_addr));
260 const struct sockaddr *addr,
263 struct MHD_IPCount *key;
273 key = malloc (
sizeof(*key));
293 "Failed to add IP connection count node\n");
299 node = *(
void**)node;
304 key = (
struct MHD_IPCount*)node;
326 const struct sockaddr *addr,
329 struct MHD_IPCount search_key;
330 struct MHD_IPCount *found_key;
354 "Failed to find previously-added IP address\n");
358 found_key = (
struct MHD_IPCount*)*(
void**)node;
361 if (found_key->count == 0)
365 "Previously-added IP address had 0 count\n");
371 if (--found_key->count == 0)
381 static pthread_mutex_t MHD_gnutls_init_mutex;
392 recv_tls_adapter (
struct MHD_Connection *connection,
void *other,
size_t i)
395 res = gnutls_record_recv (connection->tls_session, other, i);
396 if ( (res == GNUTLS_E_AGAIN) ||
397 (res == GNUTLS_E_INTERRUPTED) )
424 const void *other,
size_t i)
427 res = gnutls_record_send (connection->tls_session, other, i);
428 if ( (res == GNUTLS_E_AGAIN) ||
429 (res == GNUTLS_E_INTERRUPTED) )
445 MHD_init_daemon_certificate (
struct MHD_Daemon *daemon)
450 if (daemon->https_mem_trust) {
451 cert.data = (
unsigned char *) daemon->https_mem_trust;
452 cert.size = strlen(daemon->https_mem_trust);
453 if (gnutls_certificate_set_x509_trust_mem(daemon->x509_cred, &cert,
454 GNUTLS_X509_FMT_PEM) < 0) {
457 "Bad trust certificate format\n");
464 if (daemon->https_mem_cert && daemon->https_mem_key)
466 key.data = (
unsigned char *) daemon->https_mem_key;
467 key.size = strlen (daemon->https_mem_key);
468 cert.data = (
unsigned char *) daemon->https_mem_cert;
469 cert.size = strlen (daemon->https_mem_cert);
471 return gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
473 GNUTLS_X509_FMT_PEM);
476 MHD_DLOG (daemon,
"You need to specify a certificate and key location\n");
490 switch (daemon->cred_type)
492 case GNUTLS_CRD_CERTIFICATE:
494 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
495 return GNUTLS_E_MEMORY_ERROR;
496 return MHD_init_daemon_certificate (daemon);
500 "Error: invalid credentials type %d specified.\n",
523 fd_set * read_fd_set,
524 fd_set * write_fd_set, fd_set * except_fd_set,
int *max_fd)
529 if ((daemon ==
NULL) || (read_fd_set ==
NULL) || (write_fd_set ==
NULL)
530 || (except_fd_set ==
NULL) || (max_fd ==
NULL)
536 FD_SET (fd, read_fd_set);
542 while (con_itr !=
NULL)
547 except_fd_set, max_fd))
549 con_itr = con_itr->
next;
552 MHD_DLOG (daemon,
"Maximum socket in select set: %d\n", *max_fd);
574 unsigned int timeout;
611 num_ready =
SELECT (max + 1, &rs, &ws, &es, &tv);
616 MHD_DLOG (con->
daemon,
"Error during select (%d): `%s'\n", max,
635 memset(&p, 0,
sizeof (
struct pollfd));
643 if (poll (&p, 1, 1000) < 0) {
647 MHD_DLOG (con->
daemon,
"Error during poll: `%s'\n",
653 (0 != (p.revents & POLLIN)) )
656 (0 != (p.revents & POLLOUT)) )
661 (0 != (p.revents & (POLLERR | POLLHUP))) )
671 "Processing thread terminating, closing connection\n");
707 const void *other,
size_t i)
746 socket_set_nonblocking (
int fd)
751 if (ioctlsocket (fd, FIONBIO, &mode) == SOCKET_ERROR)
753 SetErrnoFromWinsockError (WSAGetLastError ());
755 FPRINTF(stderr,
"Failed to make socket non-blocking: %s\n",
762 int flags = fcntl (fd, F_GETFL);
763 if ( (flags == -1) ||
764 (0 != fcntl (fd, F_SETFL, flags | O_NONBLOCK)) )
767 FPRINTF(stderr,
"Failed to make socket non-blocking: %s\n",
788 void *(*start_routine)(
void*),
792 pthread_attr_t *pattr;
797 if (0 != (ret = pthread_attr_init (&attr)))
801 pthread_attr_destroy (&attr);
810 ret = pthread_create (thread, pattr,
813 pthread_attr_destroy (&attr);
818 "Failed to set thread stack size\n");
839 struct sockaddr_in6 addrstorage;
841 struct sockaddr_in addrstorage;
843 struct sockaddr *addr = (
struct sockaddr *) &addrstorage;
846 int res_thread_create;
851 addrlen =
sizeof (addrstorage);
852 memset (addr, 0,
sizeof (addrstorage));
855 if ((s == -1) || (addrlen <= 0))
859 if ((EAGAIN != errno) && (EWOULDBLOCK != errno))
860 MHD_DLOG (daemon,
"Error accepting connection: %s\n",
STRERROR (errno));
871 if ( (s >= FD_SETSIZE) &&
876 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
888 MHD_DLOG (daemon,
"Accepted connection on socket %d\n", s);
897 "Server reached connection limit (closing inbound connection)\n");
910 MHD_DLOG (daemon,
"Connection rejected, closing connection\n");
921 setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &on,
sizeof (on));
926 if (
NULL == connection)
929 MHD_DLOG (daemon,
"Error allocating memory: %s\n",
STRERROR (errno));
938 connection->
addr = malloc (addrlen);
942 MHD_DLOG (daemon,
"Error allocating memory: %s\n",
STRERROR (errno));
950 memcpy (connection->
addr, addr, addrlen);
953 connection->
daemon = daemon;
963 connection->
recv_cls = &recv_tls_adapter;
964 connection->
send_cls = &send_tls_adapter;
967 gnutls_init (&connection->tls_session, GNUTLS_SERVER);
968 gnutls_priority_set (connection->tls_session,
969 daemon->priority_cache);
973 socket_set_nonblocking (connection->
socket_fd);
975 switch (connection->
daemon->cred_type)
978 case GNUTLS_CRD_CERTIFICATE:
979 gnutls_credentials_set (connection->tls_session,
980 GNUTLS_CRD_CERTIFICATE,
981 connection->
daemon->x509_cred);
985 MHD_DLOG (connection->
daemon,
986 "Failed to setup TLS credentials: unknown credential type %d\n",
987 connection->
daemon->cred_type);
992 free (connection->
addr);
996 "Unknown credential type"
1003 gnutls_transport_set_ptr (connection->tls_session,
1004 (gnutls_transport_ptr_t) connection);
1005 gnutls_transport_set_pull_function (connection->tls_session,
1006 (gnutls_pull_func) &
1008 gnutls_transport_set_push_function (connection->tls_session,
1009 (gnutls_push_func) &
1012 if (daemon->https_mem_trust){
1013 gnutls_certificate_server_set_request(connection->tls_session, GNUTLS_CERT_REQUEST);
1023 if (res_thread_create != 0)
1026 MHD_DLOG (daemon,
"Failed to create a thread: %s\n",
1032 free (connection->
addr);
1073 if (0 != (rc = pthread_join (pos->
pid, &unused)))
1076 MHD_DLOG (daemon,
"Failed to join a thread: %s\n",
1084 if (pos->tls_session !=
NULL)
1085 gnutls_deinit (pos->tls_session);
1122 time_t earliest_deadline;
1135 earliest_deadline = now + dto;
1142 (0 != gnutls_record_check_pending (pos->tls_session)) )
1143 earliest_deadline = now;
1147 if (earliest_deadline < now)
1150 *timeout = (earliest_deadline - now);
1171 struct timeval timeout;
1176 timeout.tv_usec = 0;
1206 timeout.tv_usec = 0;
1210 timeout.tv_usec = 0;
1219 timeout.tv_usec = ltimeout * 1000;
1223 num_ready =
SELECT (max + 1, &rs, &ws, &es, &timeout);
1232 MHD_DLOG (daemon,
"select failed: %s\n",
STRERROR (errno));
1241 if (FD_ISSET (ds, &rs))
1253 if (FD_ISSET (ds, &rs))
1255 if ((pos->
socket_fd != -1) && (FD_ISSET (ds, &ws)))
1283 if (poll(&p, 1, 1000) < 0) {
1287 MHD_DLOG (daemon,
"poll failed: %s\n",
STRERROR (errno));
1296 if (0 != (p.revents & POLLIN))
1372 va_start (ap, dh_cls);
1392 const struct sockaddr **servaddr,
1406 const struct sockaddr **servaddr,
1412 va_start (ap, servaddr);
1429 const struct sockaddr **servaddr,
1445 daemon->
pool_size = va_arg (ap,
size_t);
1462 *servaddr = va_arg (ap,
const struct sockaddr *);
1475 "Specified thread pool size (%u) too big\n",
1484 daemon->https_mem_key = va_arg (ap,
const char *);
1488 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
1494 daemon->https_mem_cert = va_arg (ap,
const char *);
1498 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
1504 daemon->https_mem_trust = va_arg (ap,
const char *);
1508 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
1513 daemon->cred_type = va_arg (ap, gnutls_credentials_type_t);
1516 ret = gnutls_priority_init (&daemon->priority_cache,
1517 pstr = va_arg (ap,
const char*),
1520 if (ret != GNUTLS_E_SUCCESS)
1522 "Setting priorities to `%s' failed: %s\n",
1524 gnutls_strerror (ret));
1526 if (ret != GNUTLS_E_SUCCESS)
1530 #ifdef DAUTH_SUPPORT
1532 daemon->digest_auth_rand_size = va_arg (ap,
size_t);
1533 daemon->digest_auth_random = va_arg (ap,
const char *);
1536 daemon->nonce_nc_size = va_arg (ap,
unsigned int);
1544 daemon->custom_error_log =
1546 daemon->custom_error_log_cls = va_arg (ap,
void *);
1549 va_arg (ap,
void *);
1568 (
size_t) oa[i].
value,
1581 (
unsigned int) oa[i].value,
1617 (
void *) oa[i].value,
1627 (
size_t) oa[i].value,
1649 "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
1655 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
1688 struct sockaddr_in servaddr4;
1690 struct sockaddr_in6 servaddr6;
1692 const struct sockaddr *servaddr =
NULL;
1695 int res_thread_create;
1697 if ((port == 0) || (dh ==
NULL))
1699 retVal = malloc (
sizeof (
struct MHD_Daemon));
1702 memset (retVal, 0,
sizeof (
struct MHD_Daemon));
1706 gnutls_priority_init (&retVal->priority_cache,
1713 retVal->
port = port;
1722 #ifdef DAUTH_SUPPORT
1723 retVal->digest_auth_rand_size = 0;
1724 retVal->digest_auth_random =
NULL;
1725 retVal->nonce_nc_size = 4;
1728 retVal->custom_error_log =
1729 (void (*)(
void *,
const char *, va_list)) &vfprintf;
1730 retVal->custom_error_log_cls = stderr;
1733 if (options & MHD_USE_SSL)
1736 if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
1739 MHD_DLOG (retVal,
"Failed to aquire gnutls mutex\n");
1743 if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
1746 MHD_DLOG (retVal,
"Failed to release gnutls mutex\n");
1750 retVal->cred_type = GNUTLS_CRD_CERTIFICATE;
1760 #ifdef DAUTH_SUPPORT
1761 if (retVal->nonce_nc_size > 0)
1763 if ( ( (
size_t) (retVal->nonce_nc_size *
sizeof(
struct MHD_NonceNc))) /
1764 sizeof(
struct MHD_NonceNc) != retVal->nonce_nc_size)
1768 "Specified value for NC_SIZE too large\n");
1773 retVal->nnc = malloc (retVal->nonce_nc_size *
sizeof(
struct MHD_NonceNc));
1774 if (
NULL == retVal->nnc)
1778 "Failed to allocate memory for nonce-nc map: %s\n",
1785 if (0 != pthread_mutex_init (&retVal->nnc_lock,
NULL))
1789 "MHD failed to initialize nonce-nc mutex\n");
1802 "MHD poll support only works with MHD_USE_THREAD_PER_CONNECTION\n");
1806 pthread_mutex_destroy (&retVal->nnc_lock);
1818 "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n");
1824 #ifdef __SYMBIAN32__
1825 if (0 != (options & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
1829 "Threaded operations are not supported on Symbian.\n");
1839 socket_fd =
SOCKET (PF_INET6, SOCK_STREAM, 0);
1844 "AF_INET6 not supported\n");
1851 socket_fd =
SOCKET (PF_INET, SOCK_STREAM, 0);
1852 if (socket_fd == -1)
1857 "Call to socket failed: %s\n",
1870 "setsockopt failed: %s\n",
1877 if ((options & MHD_USE_IPv6) != 0)
1878 addrlen =
sizeof (
struct sockaddr_in6);
1881 addrlen =
sizeof (
struct sockaddr_in);
1882 if (
NULL == servaddr)
1885 if ((options & MHD_USE_IPv6) != 0)
1887 memset (&servaddr6, 0,
sizeof (
struct sockaddr_in6));
1888 servaddr6.sin6_family = AF_INET6;
1889 servaddr6.sin6_port = htons (port);
1890 servaddr = (
struct sockaddr *) &servaddr6;
1895 memset (&servaddr4, 0,
sizeof (
struct sockaddr_in));
1896 servaddr4.sin_family = AF_INET;
1897 servaddr4.sin_port = htons (port);
1898 servaddr = (
struct sockaddr *) &servaddr4;
1903 if ((options & MHD_USE_IPv6) != 0)
1913 setsockopt (socket_fd,
1914 IPPROTO_IPV6, IPV6_V6ONLY,
1918 setsockopt (socket_fd,
1919 IPPROTO_IPV6, IPV6_V6ONLY,
1925 if (
BIND (socket_fd, servaddr, addrlen) == -1)
1928 if ((options & MHD_USE_DEBUG) != 0)
1930 "Failed to bind to port %u: %s\n",
1931 (
unsigned int) port,
1939 if (
LISTEN (socket_fd, 20) < 0)
1942 if ((options & MHD_USE_DEBUG) != 0)
1944 "Failed to listen for connections: %s\n",
1957 if ( (socket_fd >= FD_SETSIZE) &&
1958 (0 == (options & MHD_USE_POLL)) )
1963 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
1977 "MHD failed to initialize IP connection limit mutex\n");
1986 if ((0 != (options & MHD_USE_SSL)) && (0 != MHD_TLS_init (retVal)))
1990 "Failed to initialize TLS support\n");
1993 #ifdef DAUTH_SUPPORT
1994 pthread_mutex_destroy (&retVal->nnc_lock);
2002 if ( ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
2003 ( (0 != (options & MHD_USE_SELECT_INTERNALLY)) &&
2005 (0 != (res_thread_create =
2010 "Failed to create listen thread: %s\n",
2013 #ifdef DAUTH_SUPPORT
2014 pthread_mutex_destroy (&retVal->nnc_lock);
2027 unsigned long sk_flags;
2044 sk_flags = fcntl (socket_fd, F_GETFL);
2047 if (fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK) < 0)
2052 if (ioctlsocket (plibc_fd_get_handle (socket_fd), FIONBIO, &sk_flags) ==
2055 if (ioctlsocket (socket_fd, FIONBIO, &sk_flags) == SOCKET_ERROR)
2071 memcpy (d, retVal,
sizeof (
struct MHD_Daemon));
2084 if (i < leftover_conns)
2092 "Failed to create pool thread: %s\n",
2139 MHD_DLOG (daemon,
"MHD shutdown, closing active connections\n");
2181 MHD_DLOG (daemon,
"MHD shutdown, closing listen socket\n");
2192 if (0 != (rc = pthread_join (daemon->
worker_pool[i].
pid, &unused)))
2195 MHD_DLOG (daemon,
"Failed to join a thread: %s\n",
2209 if (0 != (rc = pthread_join (daemon->
pid, &unused)))
2212 MHD_DLOG (daemon,
"Failed to join a thread: %s\n",
2223 MHD_DLOG (daemon,
"MHD shutdown, closing listen socket\n");
2233 gnutls_priority_deinit (daemon->priority_cache);
2234 if (daemon->x509_cred)
2235 gnutls_certificate_free_credentials (daemon->x509_cred);
2237 if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
2240 MHD_DLOG (daemon,
"Failed to aquire gnutls mutex\n");
2244 if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
2247 MHD_DLOG (daemon,
"Failed to release gnutls mutex\n");
2254 #ifdef DAUTH_SUPPORT
2256 pthread_mutex_destroy (&daemon->nnc_lock);
2314 return PACKAGE_VERSION;
2330 #define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor))
2331 #define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor))
2333 #define ATTRIBUTE_CONSTRUCTOR
2334 #define ATTRIBUTE_DESTRUCTOR
2338 GCRY_THREAD_OPTION_PTHREAD_IMPL;
2352 memset (&
sig, 0,
sizeof (
struct sigaction));
2353 memset (&
old, 0,
sizeof (
struct sigaction));
2354 sig.sa_flags = SA_NODEFER;
2358 plibc_init (
"GNU",
"libmicrohttpd");
2361 gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
2362 gnutls_global_init ();
2363 if (0 != pthread_mutex_init(&MHD_gnutls_init_mutex,
NULL))
2371 gnutls_global_deinit ();
2372 if (0 != pthread_mutex_destroy(&MHD_gnutls_init_mutex))