36 #include <gnutls/gnutls.h>
45 #include <sys/sendfile.h>
52 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE - 4
54 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE
60 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
66 #define DEBUG_CLOSE MHD_NO
72 #define DEBUG_CONNECT MHD_NO
76 #define MSG_NOSIGNAL 0
81 #define SOCK_CLOEXEC 0
101 fprintf (stderr,
"Fatal error in GNU libmicrohttpd %s:%u: %s\n",
158 struct in6_addr ipv6;
179 MHD_PANIC (
"Failed to acquire IP connection limit mutex\n");
194 MHD_PANIC (
"Failed to release IP connection limit mutex\n");
211 return memcmp (a1, a2, offsetof (
struct MHD_IPCount, count));
226 struct MHD_IPCount *key)
228 memset(key, 0,
sizeof(*key));
231 if (
sizeof (
struct sockaddr_in) == addrlen)
233 const struct sockaddr_in *addr4 = (
const struct sockaddr_in*) addr;
234 key->family = AF_INET;
235 memcpy (&key->addr.ipv4, &addr4->sin_addr,
sizeof(addr4->sin_addr));
241 if (
sizeof (
struct sockaddr_in6) == addrlen)
243 const struct sockaddr_in6 *addr6 = (
const struct sockaddr_in6*) addr;
244 key->family = AF_INET6;
245 memcpy (&key->addr.ipv6, &addr6->sin6_addr,
sizeof(addr6->sin6_addr));
266 const struct sockaddr *addr,
269 struct MHD_IPCount *key;
279 if (
NULL == (key = malloc (
sizeof(*key))))
298 "Failed to add IP connection count node\n");
308 key = (
struct MHD_IPCount *) node;
330 const struct sockaddr *addr,
333 struct MHD_IPCount search_key;
334 struct MHD_IPCount *found_key;
354 MHD_PANIC (
"Failed to find previously-added IP address\n");
356 found_key = (
struct MHD_IPCount *) *nodep;
358 if (0 == found_key->count)
360 MHD_PANIC (
"Previously-added IP address had 0 count\n");
363 if (0 == --found_key->count)
385 recv_tls_adapter (
struct MHD_Connection *connection,
void *other,
size_t i)
389 res = gnutls_record_recv (connection->tls_session, other, i);
390 if ( (GNUTLS_E_AGAIN == res) ||
391 (GNUTLS_E_INTERRUPTED == res) )
418 const void *other,
size_t i)
422 res = gnutls_record_send (connection->tls_session, other, i);
423 if ( (GNUTLS_E_AGAIN == res) ||
424 (GNUTLS_E_INTERRUPTED == res) )
440 MHD_init_daemon_certificate (
struct MHD_Daemon *daemon)
445 if (
NULL != daemon->https_mem_trust)
447 cert.data = (
unsigned char *) daemon->https_mem_trust;
448 cert.size = strlen (daemon->https_mem_trust);
449 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred, &cert,
450 GNUTLS_X509_FMT_PEM) < 0)
454 "Bad trust certificate format\n");
461 if ( (
NULL != daemon->https_mem_cert) &&
462 (
NULL != daemon->https_mem_key) )
464 key.data = (
unsigned char *) daemon->https_mem_key;
465 key.size = strlen (daemon->https_mem_key);
466 cert.data = (
unsigned char *) daemon->https_mem_cert;
467 cert.size = strlen (daemon->https_mem_cert);
469 return gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
471 GNUTLS_X509_FMT_PEM);
474 MHD_DLOG (daemon,
"You need to specify a certificate and key location\n");
489 switch (daemon->cred_type)
491 case GNUTLS_CRD_CERTIFICATE:
493 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
494 return GNUTLS_E_MEMORY_ERROR;
495 return MHD_init_daemon_certificate (daemon);
499 "Error: invalid credentials type %d specified.\n",
524 fd_set *write_fd_set,
525 fd_set *except_fd_set,
531 if ( (
NULL == daemon)
532 || (
NULL == read_fd_set)
533 || (
NULL == write_fd_set)
534 || (
NULL == except_fd_set)
543 FD_SET (fd, read_fd_set);
552 except_fd_set, max_fd))
555 MHD_DLOG (daemon,
"Maximum socket in select set: %d\n", *max_fd);
579 unsigned int timeout;
621 num_ready =
SELECT (max + 1, &rs, &ws, &es, tvp);
628 "Error during select (%d): `%s'\n",
648 memset(&p, 0,
sizeof (p));
651 p[0].events |= POLLIN;
653 p[0].events |= POLLOUT;
656 (
NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
661 MHD_DLOG (con->
daemon,
"Error during poll: `%s'\n",
666 if (0 != (p[0].revents & POLLIN))
668 if (0 != (p[0].revents & POLLOUT))
670 if (0 != (p[0].revents & (POLLERR | POLLHUP)))
682 "Processing thread terminating, closing connection\n");
761 if (left > SSIZE_MAX)
763 if (-1 != (ret = sendfile (connection->
socket_fd,
768 if ( (EINTR == errno) || (EAGAIN == errno) )
770 if ( (EINVAL == errno) || (EBADF == errno) )
794 void *(*start_routine)(
void*),
798 pthread_attr_t *pattr;
803 if (0 != (ret = pthread_attr_init (&attr)))
807 pthread_attr_destroy (&attr);
816 ret = pthread_create (thread, pattr,
819 pthread_attr_destroy (&attr);
824 "Failed to set thread stack size\n");
857 const struct sockaddr *addr,
861 int res_thread_create;
867 if ( (client_socket >= FD_SETSIZE) &&
872 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
876 SHUTDOWN (client_socket, SHUT_RDWR);
877 CLOSE (client_socket);
885 MHD_DLOG (daemon,
"Accepted connection on socket %d\n", s);
894 "Server reached connection limit (closing inbound connection)\n");
896 SHUTDOWN (client_socket, SHUT_RDWR);
897 CLOSE (client_socket);
908 MHD_DLOG (daemon,
"Connection rejected, closing connection\n");
911 SHUTDOWN (client_socket, SHUT_RDWR);
912 CLOSE (client_socket);
920 setsockopt (client_socket,
921 SOL_SOCKET, SO_NOSIGPIPE,
931 "Error allocating memory: %s\n",
934 SHUTDOWN (client_socket, SHUT_RDWR);
935 CLOSE (client_socket);
942 if (
NULL == (connection->
addr = malloc (addrlen)))
946 "Error allocating memory: %s\n",
949 SHUTDOWN (client_socket, SHUT_RDWR);
950 CLOSE (client_socket);
955 memcpy (connection->
addr, addr, addrlen);
978 int flags = fcntl (connection->
socket_fd, F_GETFL);
979 if ( (-1 == flags) ||
980 (0 != fcntl (connection->
socket_fd, F_SETFL, flags | O_NONBLOCK)) )
984 "Failed to make socket %d non-blocking: %s\n",
990 unsigned long flags = 1;
991 if (0 != ioctlsocket (connection->
socket_fd, FIONBIO, &flags))
995 "Failed to make socket non-blocking: %s\n",
1005 connection->
recv_cls = &recv_tls_adapter;
1006 connection->
send_cls = &send_tls_adapter;
1009 gnutls_init (&connection->tls_session, GNUTLS_SERVER);
1010 gnutls_priority_set (connection->tls_session,
1011 daemon->priority_cache);
1012 switch (daemon->cred_type)
1015 case GNUTLS_CRD_CERTIFICATE:
1016 gnutls_credentials_set (connection->tls_session,
1017 GNUTLS_CRD_CERTIFICATE,
1022 MHD_DLOG (connection->
daemon,
1023 "Failed to setup TLS credentials: unknown credential type %d\n",
1026 SHUTDOWN (client_socket, SHUT_RDWR);
1027 CLOSE (client_socket);
1029 free (connection->
addr);
1034 gnutls_transport_set_ptr (connection->tls_session,
1035 (gnutls_transport_ptr_t) connection);
1036 gnutls_transport_set_pull_function (connection->tls_session,
1037 (gnutls_pull_func) &
1039 gnutls_transport_set_push_function (connection->tls_session,
1040 (gnutls_push_func) &
1043 if (daemon->https_mem_trust){
1044 gnutls_certificate_server_set_request(connection->tls_session, GNUTLS_CERT_REQUEST);
1051 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1058 MHD_PANIC (
"Failed to release cleanup mutex\n");
1066 if (0 != res_thread_create)
1069 MHD_DLOG (daemon,
"Failed to create a thread: %s\n",
1072 SHUTDOWN (client_socket, SHUT_RDWR);
1073 CLOSE (client_socket);
1077 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1084 MHD_PANIC (
"Failed to release cleanup mutex\n");
1086 free (connection->
addr);
1108 struct sockaddr_in6 addrstorage;
1110 struct sockaddr_in addrstorage;
1112 struct sockaddr *addr = (
struct sockaddr *) &addrstorage;
1118 addrlen =
sizeof (addrstorage);
1119 memset (addr, 0,
sizeof (addrstorage));
1132 if ((-1 == s) || (addrlen <= 0))
1136 if ((EAGAIN != errno) && (EWOULDBLOCK != errno))
1138 "Error accepting connection: %s\n",
1153 flags = fcntl (s, F_GETFD);
1154 if ( ( (-1 == flags) ||
1155 ( (flags != (flags | FD_CLOEXEC)) &&
1156 (0 != fcntl (s, F_SETFD, flags | FD_CLOEXEC)) ) ) )
1159 if (!GetHandleInformation ((HANDLE) s, &dwFlags) ||
1160 ((dwFlags != dwFlags & ~HANDLE_FLAG_INHERIT) &&
1161 !SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0)))
1166 SetErrnoFromWinError (GetLastError ());
1169 "Failed to make socket non-inheritable: %s\n",
1176 MHD_DLOG (daemon,
"Accepted connection on socket %d\n", s);
1200 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
1210 if (0 != (rc = pthread_join (pos->
pid, &unused)))
1212 MHD_PANIC (
"Failed to join a thread\n");
1217 if (pos->tls_session !=
NULL)
1218 gnutls_deinit (pos->tls_session);
1235 MHD_PANIC (
"Failed to release cleanup mutex\n");
1256 time_t earliest_deadline;
1264 MHD_DLOG (daemon,
"Illegal call to MHD_get_timeout\n");
1272 if (!have_timeout ||
1277 (0 != gnutls_record_check_pending (pos->tls_session)) )
1278 earliest_deadline = 0;
1283 if (
MHD_NO == have_timeout)
1286 if (earliest_deadline < now)
1289 *timeout = 1000 * (1 + earliest_deadline - now);
1312 struct timeval timeout;
1318 timeout.tv_usec = 0;
1346 if (-1 != daemon->
wpipe[0])
1348 FD_SET (daemon->
wpipe[0], &rs);
1350 if (max < daemon->wpipe[0])
1351 max = daemon->
wpipe[0];
1357 timeout.tv_usec = 0;
1365 timeout.tv_usec = (ltimeout % 1000) * 1000;
1366 timeout.tv_sec = ltimeout / 1000;
1369 num_ready =
SELECT (max + 1, &rs, &ws, &es, tv);
1378 MHD_DLOG (daemon,
"select failed: %s\n",
STRERROR (errno));
1383 if ( (-1 != (ds = daemon->
socket_fd)) &&
1384 (FD_ISSET (ds, &rs)) )
1390 while (
NULL != (pos = next))
1396 if (FD_ISSET (ds, &rs))
1398 if (FD_ISSET (ds, &ws))
1421 unsigned int num_connections;
1426 num_connections = 0;
1431 struct pollfd p[2 + num_connections];
1436 unsigned int poll_server;
1439 memset (p, 0,
sizeof (p));
1447 p[poll_server].events = POLLIN;
1448 p[poll_server].revents = 0;
1449 poll_listen = (int) poll_server;
1452 if (-1 != daemon->
wpipe[0])
1454 p[poll_server].fd = daemon->
wpipe[0];
1455 p[poll_server].events = POLLIN;
1456 p[poll_server].revents = 0;
1465 timeout = (ltimeout > INT_MAX) ? INT_MAX : (
int) ltimeout;
1472 p[poll_server+i].fd = mp.
fd;
1474 p[poll_server+i].events |= POLLIN;
1476 p[poll_server+i].events |= POLLOUT;
1479 if (poll (p, poll_server + num_connections, timeout) < 0)
1485 "poll failed: %s\n",
1495 while (
NULL != (pos = next))
1499 if (i >= num_connections)
1502 if (p[poll_server+i].
fd != mp.
fd)
1506 if (0 != (p[poll_server+i].revents & POLLIN))
1508 if (0 != (p[poll_server+i].revents & POLLOUT))
1513 if ( (-1 != poll_listen) &&
1514 (0 != (p[poll_listen].revents & POLLIN)) )
1529 MHD_poll_listen_socket (
struct MHD_Daemon *daemon,
1534 unsigned int poll_count;
1537 memset (&p, 0,
sizeof (p));
1543 p[poll_count].events = POLLIN;
1544 p[poll_count].revents = 0;
1545 poll_listen = poll_count;
1548 if (-1 != daemon->
wpipe[0])
1550 p[poll_count].fd = daemon->
wpipe[0];
1551 p[poll_count].events = POLLIN;
1552 p[poll_count].revents = 0;
1559 if (poll (p, poll_count, timeout) < 0)
1564 MHD_DLOG (daemon,
"poll failed: %s\n",
STRERROR (errno));
1571 if ( (-1 != poll_listen) &&
1572 (0 != (p[poll_listen].revents & POLLIN)) )
1594 return MHD_poll_all (daemon, may_block);
1596 return MHD_poll_listen_socket (daemon, may_block);
1674 va_start (ap, dh_cls);
1703 const struct sockaddr **servaddr,
1717 const struct sockaddr **servaddr,
1723 va_start (ap, servaddr);
1740 const struct sockaddr **servaddr,
1756 daemon->
pool_size = va_arg (ap,
size_t);
1773 *servaddr = va_arg (ap,
const struct sockaddr *);
1786 "Specified thread pool size (%u) too big\n",
1795 daemon->https_mem_key = va_arg (ap,
const char *);
1799 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
1805 daemon->https_mem_cert = va_arg (ap,
const char *);
1809 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
1815 daemon->https_mem_trust = va_arg (ap,
const char *);
1819 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
1824 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap,
int);
1829 gnutls_priority_deinit (daemon->priority_cache);
1830 ret = gnutls_priority_init (&daemon->priority_cache,
1831 pstr = va_arg (ap,
const char*),
1833 if (ret != GNUTLS_E_SUCCESS)
1837 "Setting priorities to `%s' failed: %s\n",
1839 gnutls_strerror (ret));
1841 daemon->priority_cache =
NULL;
1847 #ifdef DAUTH_SUPPORT
1849 daemon->digest_auth_rand_size = va_arg (ap,
size_t);
1850 daemon->digest_auth_random = va_arg (ap,
const char *);
1853 daemon->nonce_nc_size = va_arg (ap,
unsigned int);
1861 daemon->custom_error_log =
1863 daemon->custom_error_log_cls = va_arg (ap,
void *);
1866 va_arg (ap,
void *);
1885 (
size_t) oa[i].
value,
1898 (
unsigned int) oa[i].value,
1934 (
void *) oa[i].value,
1944 (
size_t) oa[i].value,
1966 "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
1972 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
1994 int ctype = SOCK_STREAM | sock_cloexec;
2003 fd =
SOCKET (domain, ctype, protocol);
2004 if ( (-1 == fd) && (EINVAL == errno) && (0 != sock_cloexec) )
2007 fd =
SOCKET(domain, type, protocol);
2011 if (0 != sock_cloexec)
2015 flags = fcntl (fd, F_GETFD);
2018 if (!GetHandleInformation ((HANDLE) fd, &dwFlags))
2022 SetErrnoFromWinError (GetLastError ());
2027 if (flags == (flags | FD_CLOEXEC))
2029 flags |= FD_CLOEXEC;
2030 if (0 != fcntl (fd, F_SETFD, flags))
2032 if (dwFlags != (dwFlags | HANDLE_FLAG_INHERIT))
2034 if (!SetHandleInformation ((HANDLE) fd, HANDLE_FLAG_INHERIT, 0))
2038 SetErrnoFromWinError (GetLastError ());
2068 struct sockaddr_in servaddr4;
2070 struct sockaddr_in6 servaddr6;
2072 const struct sockaddr *servaddr =
NULL;
2075 int res_thread_create;
2082 memset (daemon, 0,
sizeof (
struct MHD_Daemon));
2086 gnutls_priority_init (&daemon->priority_cache,
2093 daemon->
port = port;
2102 daemon->
wpipe[0] = -1;
2103 daemon->
wpipe[1] = -1;
2105 daemon->custom_error_log =
2106 (void (*)(
void *,
const char *, va_list)) &vfprintf;
2107 daemon->custom_error_log_cls = stderr;
2109 #ifdef HAVE_LISTEN_SHUTDOWN
2119 "Failed to create control pipe: %s\n",
2127 (daemon->
wpipe[0] >= FD_SETSIZE) )
2131 "file descriptor for control pipe exceeds maximum value\n");
2139 #ifdef DAUTH_SUPPORT
2140 daemon->digest_auth_rand_size = 0;
2141 daemon->digest_auth_random =
NULL;
2142 daemon->nonce_nc_size = 4;
2145 if (0 != (options & MHD_USE_SSL))
2147 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
2154 if ( (0 != (options & MHD_USE_SSL)) &&
2155 (
NULL != daemon->priority_cache) )
2156 gnutls_priority_deinit (daemon->priority_cache);
2162 #ifdef DAUTH_SUPPORT
2163 if (daemon->nonce_nc_size > 0)
2165 if ( ( (
size_t) (daemon->nonce_nc_size *
sizeof(
struct MHD_NonceNc))) /
2166 sizeof(
struct MHD_NonceNc) != daemon->nonce_nc_size)
2170 "Specified value for NC_SIZE too large\n");
2173 if (0 != (options & MHD_USE_SSL))
2174 gnutls_priority_deinit (daemon->priority_cache);
2179 daemon->nnc = malloc (daemon->nonce_nc_size *
sizeof(
struct MHD_NonceNc));
2180 if (
NULL == daemon->nnc)
2184 "Failed to allocate memory for nonce-nc map: %s\n",
2188 if (0 != (options & MHD_USE_SSL))
2189 gnutls_priority_deinit (daemon->priority_cache);
2196 if (0 != pthread_mutex_init (&daemon->nnc_lock,
NULL))
2200 "MHD failed to initialize nonce-nc mutex\n");
2203 if (0 != (options & MHD_USE_SSL))
2204 gnutls_priority_deinit (daemon->priority_cache);
2218 "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n");
2223 #ifdef __SYMBIAN32__
2228 "Threaded operations are not supported on Symbian.\n");
2244 "AF_INET6 not supported\n");
2251 if (-1 == socket_fd)
2256 "Call to socket failed: %s\n",
2268 "setsockopt failed: %s\n",
2275 if (0 != (options & MHD_USE_IPv6))
2276 addrlen =
sizeof (
struct sockaddr_in6);
2279 addrlen =
sizeof (
struct sockaddr_in);
2280 if (
NULL == servaddr)
2283 if (0 != (options & MHD_USE_IPv6))
2285 memset (&servaddr6, 0,
sizeof (
struct sockaddr_in6));
2286 servaddr6.sin6_family = AF_INET6;
2287 servaddr6.sin6_port = htons (port);
2288 #if HAVE_SOCKADDR_IN_SIN_LEN
2289 servaddr6.sin6_len =
sizeof (
struct sockaddr_in6);
2291 servaddr = (
struct sockaddr *) &servaddr6;
2296 memset (&servaddr4, 0,
sizeof (
struct sockaddr_in));
2297 servaddr4.sin_family = AF_INET;
2298 servaddr4.sin_port = htons (port);
2299 #if HAVE_SOCKADDR_IN_SIN_LEN
2300 servaddr4.sin_len =
sizeof (
struct sockaddr_in);
2302 servaddr = (
struct sockaddr *) &servaddr4;
2307 if (0 != (options & MHD_USE_IPv6))
2317 setsockopt (socket_fd,
2318 IPPROTO_IPV6, IPV6_V6ONLY,
2322 setsockopt (socket_fd,
2323 IPPROTO_IPV6, IPV6_V6ONLY,
2329 if (-1 ==
BIND (socket_fd, servaddr, addrlen))
2332 if (0 != (options & MHD_USE_DEBUG))
2334 "Failed to bind to port %u: %s\n",
2335 (
unsigned int) port,
2342 if (
LISTEN (socket_fd, 20) < 0)
2345 if (0 != (options & MHD_USE_DEBUG))
2347 "Failed to listen for connections: %s\n",
2359 if ( (socket_fd >= FD_SETSIZE) &&
2360 (0 == (options & MHD_USE_POLL)) )
2365 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
2378 "MHD failed to initialize IP connection limit mutex\n");
2380 if (-1 != socket_fd)
2388 "MHD failed to initialize IP connection limit mutex\n");
2391 if (-1 != socket_fd)
2398 if ((0 != (options & MHD_USE_SSL)) && (0 != MHD_TLS_init (daemon)))
2402 "Failed to initialize TLS support\n");
2404 if (-1 != socket_fd)
2412 ( (0 != (options & MHD_USE_SELECT_INTERNALLY)) &&
2415 (0 != (res_thread_create =
2420 "Failed to create listen thread: %s\n",
2425 if (-1 != socket_fd)
2435 unsigned long sk_flags;
2452 sk_flags = fcntl (socket_fd, F_GETFL);
2455 if (0 != fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK))
2461 ioctlsocket (plibc_fd_get_handle (socket_fd), FIONBIO, &sk_flags))
2463 if (ioctlsocket (socket_fd, FIONBIO, &sk_flags) == SOCKET_ERROR)
2479 memcpy (d, daemon,
sizeof (
struct MHD_Daemon));
2492 if (i < leftover_conns)
2500 "Failed to create pool thread: %s\n",
2518 if (-1 != socket_fd)
2538 #ifdef DAUTH_SUPPORT
2540 pthread_mutex_destroy (&daemon->nnc_lock);
2543 if (0 != (options & MHD_USE_SSL))
2544 gnutls_priority_deinit (daemon->priority_cache);
2569 MHD_PANIC (
"Failed to acquire cleanup mutex\n");
2576 MHD_PANIC (
"Failed to release cleanup mutex\n");
2584 if (0 != (rc = pthread_join (pos->
pid, &unused)))
2586 MHD_PANIC (
"Failed to join a thread\n");
2636 if (-1 != daemon->
wpipe[1])
2639 MHD_PANIC (
"failed to signal shutdownn via pipe");
2641 #ifdef HAVE_LISTEN_SHUTDOWN
2650 MHD_DLOG (daemon,
"MHD listen socket shutdown\n");
2661 if (0 != (rc = pthread_join (daemon->
worker_pool[i].
pid, &unused)))
2663 MHD_PANIC (
"Failed to join a thread\n");
2676 if (0 != (rc = pthread_join (daemon->
pid, &unused)))
2678 MHD_PANIC (
"Failed to join a thread\n");
2690 gnutls_priority_deinit (daemon->priority_cache);
2691 if (daemon->x509_cred)
2692 gnutls_certificate_free_credentials (daemon->x509_cred);
2696 #ifdef DAUTH_SUPPORT
2698 pthread_mutex_destroy (&daemon->nnc_lock);
2703 if (-1 != daemon->
wpipe[1])
2768 return PACKAGE_VERSION;
2773 #define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor))
2774 #define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor))
2776 #define ATTRIBUTE_CONSTRUCTOR
2777 #define ATTRIBUTE_DESTRUCTOR
2781 GCRY_THREAD_OPTION_PTHREAD_IMPL;
2795 plibc_init_utf8 (
"GNU",
"libmicrohttpd", 1);
2798 gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
2799 gnutls_global_init ();
2808 gnutls_global_deinit ();