00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00027 #include "platform.h"
00028 #include "internal.h"
00029 #include "response.h"
00030 #include "connection.h"
00031 #include "memorypool.h"
00032 #include <limits.h>
00033
00034 #if HAVE_SEARCH_H
00035 #include <search.h>
00036 #else
00037 #include "tsearch.h"
00038 #endif
00039
00040 #if HTTPS_SUPPORT
00041 #include "connection_https.h"
00042 #include <gcrypt.h>
00043 #endif
00044
00045 #ifdef HAVE_POLL_H
00046 #include <poll.h>
00047 #endif
00048
00049 #ifdef LINUX
00050 #include <sys/sendfile.h>
00051 #endif
00052
00053 #ifndef HAVE_ACCEPT4
00054 #define HAVE_ACCEPT4 0
00055 #endif
00056
00060 #ifndef WINDOWS
00061 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE - 4
00062 #else
00063 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE
00064 #endif
00065
00069 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
00070
00075 #define DEBUG_CLOSE MHD_NO
00076
00081 #define DEBUG_CONNECT MHD_NO
00082
00083 #ifndef LINUX
00084 #ifndef MSG_NOSIGNAL
00085 #define MSG_NOSIGNAL 0
00086 #endif
00087 #endif
00088
00089 #ifndef SOCK_CLOEXEC
00090 #define SOCK_CLOEXEC 0
00091 #endif
00092
00093 #ifndef EPOLL_CLOEXEC
00094 #define EPOLL_CLOEXEC 0
00095 #endif
00096
00097
00107 static void
00108 mhd_panic_std (void *cls,
00109 const char *file,
00110 unsigned int line,
00111 const char *reason)
00112 {
00113 #if HAVE_MESSAGES
00114 fprintf (stderr, "Fatal error in GNU libmicrohttpd %s:%u: %s\n",
00115 file, line, reason);
00116 #endif
00117 abort ();
00118 }
00119
00120
00124 MHD_PanicCallback mhd_panic;
00125
00129 void *mhd_panic_cls;
00130
00131
00139 static struct MHD_Daemon*
00140 MHD_get_master (struct MHD_Daemon *daemon)
00141 {
00142 while (NULL != daemon->master)
00143 daemon = daemon->master;
00144 return daemon;
00145 }
00146
00147
00151 struct MHD_IPCount
00152 {
00156 int family;
00157
00161 union
00162 {
00166 struct in_addr ipv4;
00167 #if HAVE_IPV6
00168
00171 struct in6_addr ipv6;
00172 #endif
00173 } addr;
00174
00178 unsigned int count;
00179 };
00180
00181
00187 static void
00188 MHD_ip_count_lock (struct MHD_Daemon *daemon)
00189 {
00190 if (0 != pthread_mutex_lock(&daemon->per_ip_connection_mutex))
00191 {
00192 MHD_PANIC ("Failed to acquire IP connection limit mutex\n");
00193 }
00194 }
00195
00196
00202 static void
00203 MHD_ip_count_unlock (struct MHD_Daemon *daemon)
00204 {
00205 if (0 != pthread_mutex_unlock(&daemon->per_ip_connection_mutex))
00206 {
00207 MHD_PANIC ("Failed to release IP connection limit mutex\n");
00208 }
00209 }
00210
00211
00221 static int
00222 MHD_ip_addr_compare (const void *a1, const void *a2)
00223 {
00224 return memcmp (a1, a2, offsetof (struct MHD_IPCount, count));
00225 }
00226
00227
00236 static int
00237 MHD_ip_addr_to_key (const struct sockaddr *addr,
00238 socklen_t addrlen,
00239 struct MHD_IPCount *key)
00240 {
00241 memset(key, 0, sizeof(*key));
00242
00243
00244 if (sizeof (struct sockaddr_in) == addrlen)
00245 {
00246 const struct sockaddr_in *addr4 = (const struct sockaddr_in*) addr;
00247 key->family = AF_INET;
00248 memcpy (&key->addr.ipv4, &addr4->sin_addr, sizeof(addr4->sin_addr));
00249 return MHD_YES;
00250 }
00251
00252 #if HAVE_IPV6
00253
00254 if (sizeof (struct sockaddr_in6) == addrlen)
00255 {
00256 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*) addr;
00257 key->family = AF_INET6;
00258 memcpy (&key->addr.ipv6, &addr6->sin6_addr, sizeof(addr6->sin6_addr));
00259 return MHD_YES;
00260 }
00261 #endif
00262
00263
00264 return MHD_NO;
00265 }
00266
00267
00277 static int
00278 MHD_ip_limit_add (struct MHD_Daemon *daemon,
00279 const struct sockaddr *addr,
00280 socklen_t addrlen)
00281 {
00282 struct MHD_IPCount *key;
00283 void **nodep;
00284 void *node;
00285 int result;
00286
00287 daemon = MHD_get_master (daemon);
00288
00289 if (0 == daemon->per_ip_connection_limit)
00290 return MHD_YES;
00291
00292 if (NULL == (key = malloc (sizeof(*key))))
00293 return MHD_NO;
00294
00295
00296 if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, key))
00297 {
00298
00299 free (key);
00300 return MHD_YES;
00301 }
00302 MHD_ip_count_lock (daemon);
00303
00304
00305 if (NULL == (nodep = TSEARCH (key,
00306 &daemon->per_ip_connection_count,
00307 &MHD_ip_addr_compare)))
00308 {
00309 #if HAVE_MESSAGES
00310 MHD_DLOG (daemon,
00311 "Failed to add IP connection count node\n");
00312 #endif
00313 MHD_ip_count_unlock (daemon);
00314 free (key);
00315 return MHD_NO;
00316 }
00317 node = *nodep;
00318
00319 if (node != key)
00320 free(key);
00321 key = (struct MHD_IPCount *) node;
00322
00323
00324 result = (key->count < daemon->per_ip_connection_limit);
00325 if (MHD_YES == result)
00326 ++key->count;
00327
00328 MHD_ip_count_unlock (daemon);
00329 return result;
00330 }
00331
00332
00341 static void
00342 MHD_ip_limit_del (struct MHD_Daemon *daemon,
00343 const struct sockaddr *addr,
00344 socklen_t addrlen)
00345 {
00346 struct MHD_IPCount search_key;
00347 struct MHD_IPCount *found_key;
00348 void **nodep;
00349
00350 daemon = MHD_get_master (daemon);
00351
00352 if (0 == daemon->per_ip_connection_limit)
00353 return;
00354
00355 if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, &search_key))
00356 return;
00357
00358 MHD_ip_count_lock (daemon);
00359
00360
00361 if (NULL == (nodep = TFIND (&search_key,
00362 &daemon->per_ip_connection_count,
00363 &MHD_ip_addr_compare)))
00364 {
00365
00366
00367 MHD_PANIC ("Failed to find previously-added IP address\n");
00368 }
00369 found_key = (struct MHD_IPCount *) *nodep;
00370
00371 if (0 == found_key->count)
00372 {
00373 MHD_PANIC ("Previously-added IP address had 0 count\n");
00374 }
00375
00376 if (0 == --found_key->count)
00377 {
00378 TDELETE (found_key,
00379 &daemon->per_ip_connection_count,
00380 &MHD_ip_addr_compare);
00381 free (found_key);
00382 }
00383
00384 MHD_ip_count_unlock (daemon);
00385 }
00386
00387
00388 #if HTTPS_SUPPORT
00389
00397 static ssize_t
00398 recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i)
00399 {
00400 int res;
00401
00402 if (MHD_YES == connection->tls_read_ready)
00403 {
00404 connection->daemon->num_tls_read_ready--;
00405 connection->tls_read_ready = MHD_NO;
00406 }
00407 res = gnutls_record_recv (connection->tls_session, other, i);
00408 if ( (GNUTLS_E_AGAIN == res) ||
00409 (GNUTLS_E_INTERRUPTED == res) )
00410 {
00411 errno = EINTR;
00412 #if EPOLL_SUPPORT
00413 connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
00414 #endif
00415 return -1;
00416 }
00417 if (res < 0)
00418 {
00419
00420
00421
00422 errno = EPIPE;
00423 return res;
00424 }
00425 if (res == i)
00426 {
00427 connection->tls_read_ready = MHD_YES;
00428 connection->daemon->num_tls_read_ready++;
00429 }
00430 return res;
00431 }
00432
00433
00442 static ssize_t
00443 send_tls_adapter (struct MHD_Connection *connection,
00444 const void *other, size_t i)
00445 {
00446 int res;
00447
00448 res = gnutls_record_send (connection->tls_session, other, i);
00449 if ( (GNUTLS_E_AGAIN == res) ||
00450 (GNUTLS_E_INTERRUPTED == res) )
00451 {
00452 errno = EINTR;
00453 #if EPOLL_SUPPORT
00454 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
00455 #endif
00456 return -1;
00457 }
00458 return res;
00459 }
00460
00461
00468 static int
00469 MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
00470 {
00471 gnutls_datum_t key;
00472 gnutls_datum_t cert;
00473
00474 #if GNUTLS_VERSION_MAJOR >= 3
00475 if (NULL != daemon->cert_callback)
00476 {
00477 gnutls_certificate_set_retrieve_function2 (daemon->x509_cred,
00478 daemon->cert_callback);
00479 }
00480 #endif
00481 if (NULL != daemon->https_mem_trust)
00482 {
00483 cert.data = (unsigned char *) daemon->https_mem_trust;
00484 cert.size = strlen (daemon->https_mem_trust);
00485 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred, &cert,
00486 GNUTLS_X509_FMT_PEM) < 0)
00487 {
00488 #if HAVE_MESSAGES
00489 MHD_DLOG(daemon,
00490 "Bad trust certificate format\n");
00491 #endif
00492 return -1;
00493 }
00494 }
00495
00496
00497 if ( (NULL != daemon->https_mem_cert) &&
00498 (NULL != daemon->https_mem_key) )
00499 {
00500 key.data = (unsigned char *) daemon->https_mem_key;
00501 key.size = strlen (daemon->https_mem_key);
00502 cert.data = (unsigned char *) daemon->https_mem_cert;
00503 cert.size = strlen (daemon->https_mem_cert);
00504
00505 return gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
00506 &cert, &key,
00507 GNUTLS_X509_FMT_PEM);
00508 }
00509 #if GNUTLS_VERSION_MAJOR >= 3
00510 if (NULL != daemon->cert_callback)
00511 return 0;
00512 #endif
00513 #if HAVE_MESSAGES
00514 MHD_DLOG (daemon, "You need to specify a certificate and key location\n");
00515 #endif
00516 return -1;
00517 }
00518
00519
00526 static int
00527 MHD_TLS_init (struct MHD_Daemon *daemon)
00528 {
00529 switch (daemon->cred_type)
00530 {
00531 case GNUTLS_CRD_CERTIFICATE:
00532 if (0 !=
00533 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
00534 return GNUTLS_E_MEMORY_ERROR;
00535 return MHD_init_daemon_certificate (daemon);
00536 default:
00537 #if HAVE_MESSAGES
00538 MHD_DLOG (daemon,
00539 "Error: invalid credentials type %d specified.\n",
00540 daemon->cred_type);
00541 #endif
00542 return -1;
00543 }
00544 }
00545 #endif
00546
00547
00556 static void
00557 add_to_fd_set (int fd,
00558 fd_set *set,
00559 int *max_fd)
00560 {
00561 FD_SET (fd, set);
00562 if ( (NULL != max_fd) &&
00563 (fd > *max_fd) )
00564 *max_fd = fd;
00565 }
00566
00567
00582 int
00583 MHD_get_fdset (struct MHD_Daemon *daemon,
00584 fd_set *read_fd_set,
00585 fd_set *write_fd_set,
00586 fd_set *except_fd_set,
00587 int *max_fd)
00588 {
00589 struct MHD_Connection *pos;
00590 int fd;
00591
00592 if ( (NULL == daemon)
00593 || (NULL == read_fd_set)
00594 || (NULL == write_fd_set)
00595 || (NULL == except_fd_set)
00596 || (NULL == max_fd)
00597 || (MHD_YES == daemon->shutdown)
00598 || (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00599 || (0 != (daemon->options & MHD_USE_POLL)))
00600 return MHD_NO;
00601 #if EPOLL_SUPPORT
00602 if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY))
00603 {
00604
00605
00606
00607 if (daemon->epoll_fd >= FD_SETSIZE)
00608 return MHD_NO;
00609 FD_SET (daemon->epoll_fd, read_fd_set);
00610 if ((*max_fd) < daemon->epoll_fd)
00611 *max_fd = daemon->epoll_fd;
00612 return MHD_YES;
00613 }
00614 #endif
00615 fd = daemon->socket_fd;
00616 if (-1 != fd)
00617 {
00618 FD_SET (fd, read_fd_set);
00619
00620 if ((*max_fd) < fd)
00621 *max_fd = fd;
00622 }
00623 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
00624 {
00625 switch (pos->event_loop_info)
00626 {
00627 case MHD_EVENT_LOOP_INFO_READ:
00628 add_to_fd_set (pos->socket_fd, read_fd_set, max_fd);
00629 break;
00630 case MHD_EVENT_LOOP_INFO_WRITE:
00631 add_to_fd_set (pos->socket_fd, write_fd_set, max_fd);
00632 if (pos->read_buffer_size > pos->read_buffer_offset)
00633 add_to_fd_set (pos->socket_fd, read_fd_set, max_fd);
00634 break;
00635 case MHD_EVENT_LOOP_INFO_BLOCK:
00636 if (pos->read_buffer_size > pos->read_buffer_offset)
00637 add_to_fd_set (pos->socket_fd, read_fd_set, max_fd);
00638 break;
00639 case MHD_EVENT_LOOP_INFO_CLEANUP:
00640
00641 break;
00642 }
00643 }
00644 #if DEBUG_CONNECT
00645 #if HAVE_MESSAGES
00646 MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
00647 #endif
00648 #endif
00649 return MHD_YES;
00650 }
00651
00652
00660 static void *
00661 MHD_handle_connection (void *data)
00662 {
00663 struct MHD_Connection *con = data;
00664 int num_ready;
00665 fd_set rs;
00666 fd_set ws;
00667 int max;
00668 struct timeval tv;
00669 struct timeval *tvp;
00670 unsigned int timeout;
00671 time_t now;
00672 #ifdef HAVE_POLL_H
00673 struct pollfd p[1];
00674 #endif
00675
00676 timeout = con->daemon->connection_timeout;
00677 while ( (MHD_YES != con->daemon->shutdown) &&
00678 (MHD_CONNECTION_CLOSED != con->state) )
00679 {
00680 tvp = NULL;
00681 if (timeout > 0)
00682 {
00683 now = MHD_monotonic_time();
00684 if (now - con->last_activity > timeout)
00685 tv.tv_sec = 0;
00686 else
00687 tv.tv_sec = timeout - (now - con->last_activity);
00688 tv.tv_usec = 0;
00689 tvp = &tv;
00690 }
00691 #if HTTPS_SUPPORT
00692 if (MHD_YES == con->tls_read_ready)
00693 {
00694
00695 tv.tv_sec = 0;
00696 tv.tv_usec = 0;
00697 tvp = &tv;
00698 }
00699 #endif
00700 if (0 == (con->daemon->options & MHD_USE_POLL))
00701 {
00702
00703 FD_ZERO (&rs);
00704 FD_ZERO (&ws);
00705 max = 0;
00706 switch (con->event_loop_info)
00707 {
00708 case MHD_EVENT_LOOP_INFO_READ:
00709 add_to_fd_set (con->socket_fd, &rs, &max);
00710 break;
00711 case MHD_EVENT_LOOP_INFO_WRITE:
00712 add_to_fd_set (con->socket_fd, &ws, &max);
00713 if (con->read_buffer_size > con->read_buffer_offset)
00714 add_to_fd_set (con->socket_fd, &rs, &max);
00715 break;
00716 case MHD_EVENT_LOOP_INFO_BLOCK:
00717 if (con->read_buffer_size > con->read_buffer_offset)
00718 add_to_fd_set (con->socket_fd, &rs, &max);
00719 tv.tv_sec = 0;
00720 tv.tv_usec = 0;
00721 tvp = &tv;
00722 break;
00723 case MHD_EVENT_LOOP_INFO_CLEANUP:
00724
00725 goto exit;
00726 }
00727 num_ready = SELECT (max + 1, &rs, &ws, NULL, tvp);
00728 if (num_ready < 0)
00729 {
00730 if (EINTR == errno)
00731 continue;
00732 #if HAVE_MESSAGES
00733 MHD_DLOG (con->daemon,
00734 "Error during select (%d): `%s'\n",
00735 max,
00736 STRERROR (errno));
00737 #endif
00738 break;
00739 }
00740
00741 if ( (FD_ISSET (con->socket_fd, &rs))
00742 #if HTTPS_SUPPORT
00743 || (MHD_YES == con->tls_read_ready)
00744 #endif
00745 )
00746 con->read_handler (con);
00747 if (FD_ISSET (con->socket_fd, &ws))
00748 con->write_handler (con);
00749 if (MHD_NO == con->idle_handler (con))
00750 goto exit;
00751 }
00752 #ifdef HAVE_POLL_H
00753 else
00754 {
00755
00756 memset (&p, 0, sizeof (p));
00757 p[0].fd = con->socket_fd;
00758 switch (con->event_loop_info)
00759 {
00760 case MHD_EVENT_LOOP_INFO_READ:
00761 p[0].events |= POLLIN;
00762 break;
00763 case MHD_EVENT_LOOP_INFO_WRITE:
00764 p[0].events |= POLLOUT;
00765 if (con->read_buffer_size > con->read_buffer_offset)
00766 p[0].events |= POLLIN;
00767 break;
00768 case MHD_EVENT_LOOP_INFO_BLOCK:
00769 if (con->read_buffer_size > con->read_buffer_offset)
00770 p[0].events |= POLLIN;
00771 tv.tv_sec = 0;
00772 tv.tv_usec = 0;
00773 tvp = &tv;
00774 break;
00775 case MHD_EVENT_LOOP_INFO_CLEANUP:
00776
00777 goto exit;
00778 }
00779 if (poll (p, 1,
00780 (NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
00781 {
00782 if (EINTR == errno)
00783 continue;
00784 #if HAVE_MESSAGES
00785 MHD_DLOG (con->daemon, "Error during poll: `%s'\n",
00786 STRERROR (errno));
00787 #endif
00788 break;
00789 }
00790 if ( (0 != (p[0].revents & POLLIN))
00791 #if HTTPS_SUPPORT
00792 || (MHD_YES == con->tls_read_ready)
00793 #endif
00794 )
00795 con->read_handler (con);
00796 if (0 != (p[0].revents & POLLOUT))
00797 con->write_handler (con);
00798 if (0 != (p[0].revents & (POLLERR | POLLHUP)))
00799 MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR);
00800 if (MHD_NO == con->idle_handler (con))
00801 goto exit;
00802 }
00803 #endif
00804 }
00805 if (MHD_CONNECTION_IN_CLEANUP != con->state)
00806 {
00807 #if DEBUG_CLOSE
00808 #if HAVE_MESSAGES
00809 MHD_DLOG (con->daemon,
00810 "Processing thread terminating, closing connection\n");
00811 #endif
00812 #endif
00813 if (MHD_CONNECTION_CLOSED != con->state)
00814 MHD_connection_close (con,
00815 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
00816 con->idle_handler (con);
00817 }
00818 exit:
00819 if (NULL != con->response)
00820 {
00821 MHD_destroy_response (con->response);
00822 con->response = NULL;
00823 }
00824 return NULL;
00825 }
00826
00827
00836 static ssize_t
00837 recv_param_adapter (struct MHD_Connection *connection,
00838 void *other,
00839 size_t i)
00840 {
00841 ssize_t ret;
00842
00843 if ( (-1 == connection->socket_fd) ||
00844 (MHD_CONNECTION_CLOSED == connection->state) )
00845 {
00846 errno = ENOTCONN;
00847 return -1;
00848 }
00849 ret = RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
00850 #if EPOLL_SUPPORT
00851 if (ret < (ssize_t) i)
00852 {
00853
00854 connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
00855 }
00856 #endif
00857 return ret;
00858 }
00859
00860
00869 static ssize_t
00870 send_param_adapter (struct MHD_Connection *connection,
00871 const void *other,
00872 size_t i)
00873 {
00874 ssize_t ret;
00875 #if LINUX
00876 int fd;
00877 off_t offset;
00878 off_t left;
00879 #endif
00880
00881 if ( (-1 == connection->socket_fd) ||
00882 (MHD_CONNECTION_CLOSED == connection->state) )
00883 {
00884 errno = ENOTCONN;
00885 return -1;
00886 }
00887 if (0 != (connection->daemon->options & MHD_USE_SSL))
00888 return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
00889 #if LINUX
00890 if ( (connection->write_buffer_append_offset ==
00891 connection->write_buffer_send_offset) &&
00892 (NULL != connection->response) &&
00893 (-1 != (fd = connection->response->fd)) )
00894 {
00895
00896 offset = (off_t) connection->response_write_position + connection->response->fd_off;
00897 left = connection->response->total_size - connection->response_write_position;
00898 if (left > SSIZE_MAX)
00899 left = SSIZE_MAX;
00900 if (-1 != (ret = sendfile (connection->socket_fd,
00901 fd,
00902 &offset,
00903 (size_t) left)))
00904 {
00905 #if EPOLL_SUPPORT
00906 if (ret < left)
00907 {
00908
00909 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
00910 }
00911 #endif
00912 return ret;
00913 }
00914 if ( (EINTR == errno) || (EAGAIN == errno) )
00915 return 0;
00916 if ( (EINVAL == errno) || (EBADF == errno) )
00917 return -1;
00918
00919
00920
00921
00922 }
00923 #endif
00924 ret = SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
00925 #if EPOLL_SUPPORT
00926 if (ret < (ssize_t) i)
00927 {
00928
00929 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
00930 }
00931 #endif
00932 return ret;
00933 }
00934
00935
00942 typedef void *(*ThreadStartRoutine)(void *cls);
00943
00944
00954 static int
00955 create_thread (pthread_t *thread,
00956 const struct MHD_Daemon *daemon,
00957 ThreadStartRoutine start_routine,
00958 void *arg)
00959 {
00960 pthread_attr_t attr;
00961 pthread_attr_t *pattr;
00962 int ret;
00963
00964 if (0 != daemon->thread_stack_size)
00965 {
00966 if (0 != (ret = pthread_attr_init (&attr)))
00967 goto ERR;
00968 if (0 != (ret = pthread_attr_setstacksize (&attr, daemon->thread_stack_size)))
00969 {
00970 pthread_attr_destroy (&attr);
00971 goto ERR;
00972 }
00973 pattr = &attr;
00974 }
00975 else
00976 {
00977 pattr = NULL;
00978 }
00979 ret = pthread_create (thread, pattr,
00980 start_routine, arg);
00981 #if (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)
00982 #if LINUX
00983 (void) pthread_setname_np (*thread, "libmicrohttpd");
00984 #endif
00985 #endif
00986 if (0 != daemon->thread_stack_size)
00987 pthread_attr_destroy (&attr);
00988 return ret;
00989 ERR:
00990 #if HAVE_MESSAGES
00991 MHD_DLOG (daemon,
00992 "Failed to set thread stack size\n");
00993 #endif
00994 errno = EINVAL;
00995 return ret;
00996 }
00997
00998
01025 static int
01026 internal_add_connection (struct MHD_Daemon *daemon,
01027 int client_socket,
01028 const struct sockaddr *addr,
01029 socklen_t addrlen,
01030 int external_add)
01031 {
01032 struct MHD_Connection *connection;
01033 int res_thread_create;
01034 unsigned int i;
01035 int eno;
01036 #if OSX
01037 static int on = 1;
01038 #endif
01039 if (NULL != daemon->worker_pool)
01040 {
01041
01042
01043
01044 for (i=0;i<daemon->worker_pool_size;i++)
01045 if (0 < daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size].max_connections)
01046 return internal_add_connection (&daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size],
01047 client_socket,
01048 addr, addrlen,
01049 external_add);
01050
01051 if (0 != CLOSE (client_socket))
01052 MHD_PANIC ("close failed\n");
01053 #if ENFILE
01054 errno = ENFILE;
01055 #endif
01056 return MHD_NO;
01057 }
01058
01059 #ifndef WINDOWS
01060 if ( (client_socket >= FD_SETSIZE) &&
01061 (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL_LINUX_ONLY))) )
01062 {
01063 #if HAVE_MESSAGES
01064 MHD_DLOG (daemon,
01065 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
01066 client_socket,
01067 FD_SETSIZE);
01068 #endif
01069 if (0 != CLOSE (client_socket))
01070 MHD_PANIC ("close failed\n");
01071 #if EINVAL
01072 errno = EINVAL;
01073 #endif
01074 return MHD_NO;
01075 }
01076 #endif
01077
01078
01079 #if HAVE_MESSAGES
01080 #if DEBUG_CONNECT
01081 MHD_DLOG (daemon, "Accepted connection on socket %d\n", client_socket);
01082 #endif
01083 #endif
01084 if ( (0 == daemon->max_connections) ||
01085 (MHD_NO == MHD_ip_limit_add (daemon, addr, addrlen)) )
01086 {
01087
01088 #if HAVE_MESSAGES
01089 MHD_DLOG (daemon,
01090 "Server reached connection limit (closing inbound connection)\n");
01091 #endif
01092 if (0 != CLOSE (client_socket))
01093 MHD_PANIC ("close failed\n");
01094 #if ENFILE
01095 errno = ENFILE;
01096 #endif
01097 return MHD_NO;
01098 }
01099
01100
01101 if ( (NULL != daemon->apc) &&
01102 (MHD_NO == daemon->apc (daemon->apc_cls,
01103 addr, addrlen)) )
01104 {
01105 #if DEBUG_CLOSE
01106 #if HAVE_MESSAGES
01107 MHD_DLOG (daemon, "Connection rejected, closing connection\n");
01108 #endif
01109 #endif
01110 if (0 != CLOSE (client_socket))
01111 MHD_PANIC ("close failed\n");
01112 MHD_ip_limit_del (daemon, addr, addrlen);
01113 #if EACCESS
01114 errno = EACCESS;
01115 #endif
01116 return MHD_NO;
01117 }
01118
01119 #if OSX
01120 #ifdef SOL_SOCKET
01121 #ifdef SO_NOSIGPIPE
01122 setsockopt (client_socket,
01123 SOL_SOCKET, SO_NOSIGPIPE,
01124 &on, sizeof (on));
01125 #endif
01126 #endif
01127 #endif
01128
01129 if (NULL == (connection = malloc (sizeof (struct MHD_Connection))))
01130 {
01131 eno = errno;
01132 #if HAVE_MESSAGES
01133 MHD_DLOG (daemon,
01134 "Error allocating memory: %s\n",
01135 STRERROR (errno));
01136 #endif
01137 if (0 != CLOSE (client_socket))
01138 MHD_PANIC ("close failed\n");
01139 MHD_ip_limit_del (daemon, addr, addrlen);
01140 errno = eno;
01141 return MHD_NO;
01142 }
01143 memset (connection, 0, sizeof (struct MHD_Connection));
01144 connection->pool = MHD_pool_create (daemon->pool_size);
01145 if (NULL == connection->pool)
01146 {
01147 #if HAVE_MESSAGES
01148 MHD_DLOG (daemon,
01149 "Error allocating memory: %s\n",
01150 STRERROR (errno));
01151 #endif
01152 if (0 != CLOSE (client_socket))
01153 MHD_PANIC ("close failed\n");
01154 MHD_ip_limit_del (daemon, addr, addrlen);
01155 free (connection);
01156 #if ENOMEM
01157 errno = ENOMEM;
01158 #endif
01159 return MHD_NO;
01160 }
01161
01162 connection->connection_timeout = daemon->connection_timeout;
01163 if (NULL == (connection->addr = malloc (addrlen)))
01164 {
01165 eno = errno;
01166 #if HAVE_MESSAGES
01167 MHD_DLOG (daemon,
01168 "Error allocating memory: %s\n",
01169 STRERROR (errno));
01170 #endif
01171 if (0 != CLOSE (client_socket))
01172 MHD_PANIC ("close failed\n");
01173 MHD_ip_limit_del (daemon, addr, addrlen);
01174 MHD_pool_destroy (connection->pool);
01175 free (connection);
01176 errno = eno;
01177 return MHD_NO;
01178 }
01179 memcpy (connection->addr, addr, addrlen);
01180 connection->addr_len = addrlen;
01181 connection->socket_fd = client_socket;
01182 connection->daemon = daemon;
01183 connection->last_activity = MHD_monotonic_time();
01184
01185
01186 MHD_set_http_callbacks_ (connection);
01187 connection->recv_cls = &recv_param_adapter;
01188 connection->send_cls = &send_param_adapter;
01189
01190 if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO))
01191 {
01192
01193
01194
01195
01196 #ifdef CYGWIN
01197 if (0 != (daemon->options & MHD_USE_SSL))
01198 #endif
01199 {
01200
01201 #ifndef MINGW
01202 int flags = fcntl (connection->socket_fd, F_GETFL);
01203 if ( (-1 == flags) ||
01204 (0 != fcntl (connection->socket_fd, F_SETFL, flags | O_NONBLOCK)) )
01205 {
01206 #if HAVE_MESSAGES
01207 MHD_DLOG (daemon,
01208 "Failed to make socket %d non-blocking: %s\n",
01209 connection->socket_fd,
01210 STRERROR (errno));
01211 #endif
01212 }
01213 #else
01214 unsigned long flags = 1;
01215 if (0 != ioctlsocket (connection->socket_fd, FIONBIO, &flags))
01216 {
01217 #if HAVE_MESSAGES
01218 MHD_DLOG (daemon,
01219 "Failed to make socket non-blocking: %s\n",
01220 STRERROR (errno));
01221 #endif
01222 }
01223 #endif
01224 }
01225 }
01226
01227 #if HTTPS_SUPPORT
01228 if (0 != (daemon->options & MHD_USE_SSL))
01229 {
01230 connection->recv_cls = &recv_tls_adapter;
01231 connection->send_cls = &send_tls_adapter;
01232 connection->state = MHD_TLS_CONNECTION_INIT;
01233 MHD_set_https_callbacks (connection);
01234 gnutls_init (&connection->tls_session, GNUTLS_SERVER);
01235 gnutls_priority_set (connection->tls_session,
01236 daemon->priority_cache);
01237 switch (daemon->cred_type)
01238 {
01239
01240 case GNUTLS_CRD_CERTIFICATE:
01241 gnutls_credentials_set (connection->tls_session,
01242 GNUTLS_CRD_CERTIFICATE,
01243 daemon->x509_cred);
01244 break;
01245 default:
01246 #if HAVE_MESSAGES
01247 MHD_DLOG (connection->daemon,
01248 "Failed to setup TLS credentials: unknown credential type %d\n",
01249 daemon->cred_type);
01250 #endif
01251 if (0 != CLOSE (client_socket))
01252 MHD_PANIC ("close failed\n");
01253 MHD_ip_limit_del (daemon, addr, addrlen);
01254 free (connection->addr);
01255 free (connection);
01256 MHD_PANIC ("Unknown credential type");
01257 #if EINVAL
01258 errno = EINVAL;
01259 #endif
01260 return MHD_NO;
01261 }
01262 gnutls_transport_set_ptr (connection->tls_session,
01263 (gnutls_transport_ptr_t) connection);
01264 gnutls_transport_set_pull_function (connection->tls_session,
01265 (gnutls_pull_func) &recv_param_adapter);
01266 gnutls_transport_set_push_function (connection->tls_session,
01267 (gnutls_push_func) &send_param_adapter);
01268
01269 if (daemon->https_mem_trust)
01270 gnutls_certificate_server_set_request (connection->tls_session,
01271 GNUTLS_CERT_REQUEST);
01272 }
01273 #endif
01274
01275 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01276 (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
01277 MHD_PANIC ("Failed to acquire cleanup mutex\n");
01278 XDLL_insert (daemon->normal_timeout_head,
01279 daemon->normal_timeout_tail,
01280 connection);
01281 DLL_insert (daemon->connections_head,
01282 daemon->connections_tail,
01283 connection);
01284 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01285 (0 != pthread_mutex_unlock (&daemon->cleanup_connection_mutex)) )
01286 MHD_PANIC ("Failed to release cleanup mutex\n");
01287
01288
01289 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01290 {
01291 res_thread_create = create_thread (&connection->pid, daemon,
01292 &MHD_handle_connection, connection);
01293 if (0 != res_thread_create)
01294 {
01295 eno = errno;
01296 #if HAVE_MESSAGES
01297 MHD_DLOG (daemon, "Failed to create a thread: %s\n",
01298 STRERROR (res_thread_create));
01299 #endif
01300 goto cleanup;
01301 }
01302 }
01303 else
01304 if ( (MHD_YES == external_add) &&
01305 (-1 != daemon->wpipe[1]) &&
01306 (1 != WRITE (daemon->wpipe[1], "n", 1)) )
01307 {
01308 #if HAVE_MESSAGES
01309 MHD_DLOG (daemon,
01310 "failed to signal new connection via pipe");
01311 #endif
01312 }
01313 #if EPOLL_SUPPORT
01314 if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY))
01315 {
01316 if (0 == (daemon->options & MHD_USE_EPOLL_TURBO))
01317 {
01318 struct epoll_event event;
01319
01320 event.events = EPOLLIN | EPOLLOUT | EPOLLET;
01321 event.data.ptr = connection;
01322 if (0 != epoll_ctl (daemon->epoll_fd,
01323 EPOLL_CTL_ADD,
01324 client_socket,
01325 &event))
01326 {
01327 eno = errno;
01328 #if HAVE_MESSAGES
01329 MHD_DLOG (daemon,
01330 "Call to epoll_ctl failed: %s\n",
01331 STRERROR (errno));
01332 #endif
01333 goto cleanup;
01334 }
01335 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
01336 }
01337 else
01338 {
01339 connection->epoll_state |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY
01340 | MHD_EPOLL_STATE_IN_EREADY_EDLL;
01341 EDLL_insert (daemon->eready_head,
01342 daemon->eready_tail,
01343 connection);
01344 }
01345 }
01346 #endif
01347 daemon->max_connections--;
01348 return MHD_YES;
01349 cleanup:
01350 if (0 != CLOSE (client_socket))
01351 MHD_PANIC ("close failed\n");
01352 MHD_ip_limit_del (daemon, addr, addrlen);
01353 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01354 (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
01355 MHD_PANIC ("Failed to acquire cleanup mutex\n");
01356 DLL_remove (daemon->connections_head,
01357 daemon->connections_tail,
01358 connection);
01359 XDLL_remove (daemon->normal_timeout_head,
01360 daemon->normal_timeout_tail,
01361 connection);
01362 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01363 (0 != pthread_mutex_unlock (&daemon->cleanup_connection_mutex)) )
01364 MHD_PANIC ("Failed to release cleanup mutex\n");
01365 MHD_pool_destroy (connection->pool);
01366 free (connection->addr);
01367 free (connection);
01368 #if EINVAL
01369 errno = eno;
01370 #endif
01371 return MHD_NO;
01372 }
01373
01374
01402 void
01403 MHD_suspend_connection (struct MHD_Connection *connection)
01404 {
01405 struct MHD_Daemon *daemon;
01406
01407 daemon = connection->daemon;
01408 if (MHD_USE_SUSPEND_RESUME != (daemon->options & MHD_USE_SUSPEND_RESUME))
01409 MHD_PANIC ("Cannot suspend connections without enabling MHD_USE_SUSPEND_RESUME!\n");
01410 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01411 (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
01412 MHD_PANIC ("Failed to acquire cleanup mutex\n");
01413 DLL_remove (daemon->connections_head,
01414 daemon->connections_tail,
01415 connection);
01416 DLL_insert (daemon->suspended_connections_head,
01417 daemon->suspended_connections_tail,
01418 connection);
01419 if (connection->connection_timeout == daemon->connection_timeout)
01420 XDLL_remove (daemon->normal_timeout_head,
01421 daemon->normal_timeout_tail,
01422 connection);
01423 else
01424 XDLL_remove (daemon->manual_timeout_head,
01425 daemon->manual_timeout_tail,
01426 connection);
01427 #if EPOLL_SUPPORT
01428 if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY))
01429 {
01430 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
01431 {
01432 EDLL_remove (daemon->eready_head,
01433 daemon->eready_tail,
01434 connection);
01435 }
01436 if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
01437 {
01438 if (0 != epoll_ctl (daemon->epoll_fd,
01439 EPOLL_CTL_DEL,
01440 connection->socket_fd,
01441 NULL))
01442 MHD_PANIC ("Failed to remove FD from epoll set\n");
01443 connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
01444 }
01445 connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
01446 }
01447 #endif
01448 connection->suspended = MHD_YES;
01449 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01450 (0 != pthread_mutex_unlock (&daemon->cleanup_connection_mutex)) )
01451 MHD_PANIC ("Failed to release cleanup mutex\n");
01452 }
01453
01454
01463 void
01464 MHD_resume_connection (struct MHD_Connection *connection)
01465 {
01466 struct MHD_Daemon *daemon;
01467
01468 daemon = connection->daemon;
01469 if (MHD_USE_SUSPEND_RESUME != (daemon->options & MHD_USE_SUSPEND_RESUME))
01470 MHD_PANIC ("Cannot resume connections without enabling MHD_USE_SUSPEND_RESUME!\n");
01471 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01472 (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
01473 MHD_PANIC ("Failed to acquire cleanup mutex\n");
01474 connection->resuming = MHD_YES;
01475 daemon->resuming = MHD_YES;
01476 if ( (-1 != daemon->wpipe[1]) &&
01477 (1 != WRITE (daemon->wpipe[1], "r", 1)) )
01478 {
01479 #if HAVE_MESSAGES
01480 MHD_DLOG (daemon,
01481 "failed to signal resume via pipe");
01482 #endif
01483 }
01484 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01485 (0 != pthread_mutex_unlock (&daemon->cleanup_connection_mutex)) )
01486 MHD_PANIC ("Failed to release cleanup mutex\n");
01487 }
01488
01495 static void
01496 resume_suspended_connections (struct MHD_Daemon *daemon)
01497 {
01498 struct MHD_Connection *pos;
01499 struct MHD_Connection *next = NULL;
01500
01501 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01502 (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
01503 MHD_PANIC ("Failed to acquire cleanup mutex\n");
01504
01505 if (MHD_YES == daemon->resuming)
01506 next = daemon->suspended_connections_head;
01507
01508 while (NULL != (pos = next))
01509 {
01510 next = pos->next;
01511 if (MHD_NO == pos->resuming)
01512 continue;
01513
01514 DLL_remove (daemon->suspended_connections_head,
01515 daemon->suspended_connections_tail,
01516 pos);
01517 DLL_insert (daemon->connections_head,
01518 daemon->connections_tail,
01519 pos);
01520 if (pos->connection_timeout == daemon->connection_timeout)
01521 XDLL_insert (daemon->normal_timeout_head,
01522 daemon->normal_timeout_tail,
01523 pos);
01524 else
01525 XDLL_insert (daemon->manual_timeout_head,
01526 daemon->manual_timeout_tail,
01527 pos);
01528 #if EPOLL_SUPPORT
01529 if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY))
01530 {
01531 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
01532 {
01533 EDLL_insert (daemon->eready_head,
01534 daemon->eready_tail,
01535 pos);
01536 }
01537 else
01538 {
01539 struct epoll_event event;
01540
01541 event.events = EPOLLIN | EPOLLOUT | EPOLLET;
01542 event.data.ptr = pos;
01543 if (0 != epoll_ctl (daemon->epoll_fd,
01544 EPOLL_CTL_ADD,
01545 pos->socket_fd,
01546 &event))
01547 MHD_PANIC ("Failed to add FD to epoll set\n");
01548 else
01549 pos->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
01550 }
01551 pos->epoll_state &= ~MHD_EPOLL_STATE_SUSPENDED;
01552 }
01553 #endif
01554 pos->suspended = MHD_NO;
01555 pos->resuming = MHD_NO;
01556 }
01557 daemon->resuming = MHD_NO;
01558 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01559 (0 != pthread_mutex_unlock (&daemon->cleanup_connection_mutex)) )
01560 MHD_PANIC ("Failed to release cleanup mutex\n");
01561 }
01562
01563
01570 static void
01571 make_nonblocking_noninheritable (struct MHD_Daemon *daemon,
01572 int sock)
01573 {
01574 int nonblock;
01575
01576 #ifdef HAVE_SOCK_NONBLOCK
01577 nonblock = SOCK_NONBLOCK;
01578 #else
01579 nonblock = 0;
01580 #endif
01581 #ifdef CYGWIN
01582 if (0 == (daemon->options & MHD_USE_SSL))
01583 nonblock = 0;
01584 #endif
01585
01586 #ifdef WINDOWS
01587 DWORD dwFlags;
01588 unsigned long flags = 1;
01589
01590 if (0 != ioctlsocket (sock, FIONBIO, &flags))
01591 {
01592 #if HAVE_MESSAGES
01593 MHD_DLOG (daemon,
01594 "Failed to make socket non-blocking: %s\n",
01595 STRERROR (errno));
01596 #endif
01597 }
01598 if (!GetHandleInformation ((HANDLE) sock, &dwFlags) ||
01599 ((dwFlags != dwFlags & ~HANDLE_FLAG_INHERIT) &&
01600 !SetHandleInformation ((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)))
01601 {
01602 #if HAVE_MESSAGES
01603 SetErrnoFromWinError (GetLastError ());
01604 MHD_DLOG (daemon,
01605 "Failed to make socket non-inheritable: %s\n",
01606 STRERROR (errno));
01607 #endif
01608 }
01609 #else
01610 int flags;
01611
01612 nonblock = O_NONBLOCK;
01613 #ifdef CYGWIN
01614 if (0 == (daemon->options & MHD_USE_SSL))
01615 nonblock = 0;
01616 #endif
01617 flags = fcntl (sock, F_GETFD);
01618 if ( ( (-1 == flags) ||
01619 ( (flags != (flags | FD_CLOEXEC)) &&
01620 (0 != fcntl (sock, F_SETFD, flags | nonblock | FD_CLOEXEC)) ) ) )
01621 {
01622 #if HAVE_MESSAGES
01623 MHD_DLOG (daemon,
01624 "Failed to make socket non-inheritable: %s\n",
01625 STRERROR (errno));
01626 #endif
01627 }
01628 #endif
01629 }
01630
01631
01661 int
01662 MHD_add_connection (struct MHD_Daemon *daemon,
01663 int client_socket,
01664 const struct sockaddr *addr,
01665 socklen_t addrlen)
01666 {
01667 make_nonblocking_noninheritable (daemon,
01668 client_socket);
01669 return internal_add_connection (daemon,
01670 client_socket,
01671 addr, addrlen,
01672 MHD_YES);
01673 }
01674
01675
01688 static int
01689 MHD_accept_connection (struct MHD_Daemon *daemon)
01690 {
01691 #if HAVE_INET6
01692 struct sockaddr_in6 addrstorage;
01693 #else
01694 struct sockaddr_in addrstorage;
01695 #endif
01696 struct sockaddr *addr = (struct sockaddr *) &addrstorage;
01697 socklen_t addrlen;
01698 int s;
01699 int fd;
01700 int nonblock;
01701
01702 addrlen = sizeof (addrstorage);
01703 memset (addr, 0, sizeof (addrstorage));
01704 if (-1 == (fd = daemon->socket_fd))
01705 return MHD_NO;
01706 #ifdef HAVE_SOCK_NONBLOCK
01707 nonblock = SOCK_NONBLOCK;
01708 #else
01709 nonblock = 0;
01710 #endif
01711 #ifdef CYGWIN
01712 if (0 == (daemon->options & MHD_USE_SSL))
01713 nonblock = 0;
01714 #endif
01715 #if HAVE_ACCEPT4
01716 s = accept4 (fd, addr, &addrlen, SOCK_CLOEXEC | nonblock);
01717 #else
01718 s = ACCEPT (fd, addr, &addrlen);
01719 #endif
01720 if ((-1 == s) || (addrlen <= 0))
01721 {
01722 #if HAVE_MESSAGES
01723
01724 if ((EAGAIN != errno) && (EWOULDBLOCK != errno))
01725 MHD_DLOG (daemon,
01726 "Error accepting connection: %s\n",
01727 STRERROR (errno));
01728 #endif
01729 if (-1 != s)
01730 {
01731 if (0 != CLOSE (s))
01732 MHD_PANIC ("close failed\n");
01733
01734 }
01735 return MHD_NO;
01736 }
01737 if ( (! HAVE_ACCEPT4) || (0 == SOCK_CLOEXEC) )
01738 make_nonblocking_noninheritable (daemon, s);
01739 #if HAVE_MESSAGES
01740 #if DEBUG_CONNECT
01741 MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
01742 #endif
01743 #endif
01744 (void) internal_add_connection (daemon, s,
01745 addr, addrlen,
01746 MHD_NO);
01747 return MHD_YES;
01748 }
01749
01750
01758 static void
01759 MHD_cleanup_connections (struct MHD_Daemon *daemon)
01760 {
01761 struct MHD_Connection *pos;
01762 void *unused;
01763 int rc;
01764
01765 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01766 (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
01767 MHD_PANIC ("Failed to acquire cleanup mutex\n");
01768 while (NULL != (pos = daemon->cleanup_head))
01769 {
01770 DLL_remove (daemon->cleanup_head,
01771 daemon->cleanup_tail,
01772 pos);
01773 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01774 (MHD_NO == pos->thread_joined) )
01775 {
01776 if (0 != (rc = pthread_join (pos->pid, &unused)))
01777 {
01778 MHD_PANIC ("Failed to join a thread\n");
01779 }
01780 }
01781 MHD_pool_destroy (pos->pool);
01782 #if HTTPS_SUPPORT
01783 if (pos->tls_session != NULL)
01784 gnutls_deinit (pos->tls_session);
01785 #endif
01786 MHD_ip_limit_del (daemon,
01787 (struct sockaddr *) pos->addr,
01788 pos->addr_len);
01789 #if EPOLL_SUPPORT
01790 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
01791 {
01792 EDLL_remove (daemon->eready_head,
01793 daemon->eready_tail,
01794 pos);
01795 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
01796 }
01797 if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) &&
01798 (-1 != daemon->epoll_fd) &&
01799 (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
01800 {
01801
01802
01803
01804
01805
01806
01807 if (0 != epoll_ctl (daemon->epoll_fd,
01808 EPOLL_CTL_DEL,
01809 pos->socket_fd,
01810 NULL))
01811 MHD_PANIC ("Failed to remove FD from epoll set\n");
01812 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
01813 }
01814 #endif
01815 if (NULL != pos->response)
01816 {
01817 MHD_destroy_response (pos->response);
01818 pos->response = NULL;
01819 }
01820 if (-1 != pos->socket_fd)
01821 {
01822 #ifdef WINDOWS
01823 SHUTDOWN (pos->socket_fd, SHUT_WR);
01824 #endif
01825 if (0 != CLOSE (pos->socket_fd))
01826 MHD_PANIC ("close failed\n");
01827 }
01828 if (NULL != pos->addr)
01829 free (pos->addr);
01830 free (pos);
01831 daemon->max_connections++;
01832 }
01833 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01834 (0 != pthread_mutex_unlock (&daemon->cleanup_connection_mutex)) )
01835 MHD_PANIC ("Failed to release cleanup mutex\n");
01836 }
01837
01838
01853 int
01854 MHD_get_timeout (struct MHD_Daemon *daemon,
01855 MHD_UNSIGNED_LONG_LONG *timeout)
01856 {
01857 time_t earliest_deadline;
01858 time_t now;
01859 struct MHD_Connection *pos;
01860 int have_timeout;
01861
01862 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01863 {
01864 #if HAVE_MESSAGES
01865 MHD_DLOG (daemon, "Illegal call to MHD_get_timeout\n");
01866 #endif
01867 return MHD_NO;
01868 }
01869
01870 #if HTTPS_SUPPORT
01871 if (0 != daemon->num_tls_read_ready)
01872 {
01873
01874
01875 *timeout = 0;
01876 return MHD_YES;
01877 }
01878 #endif
01879
01880 have_timeout = MHD_NO;
01881 for (pos = daemon->manual_timeout_head; NULL != pos; pos = pos->nextX)
01882 {
01883 if (0 != pos->connection_timeout)
01884 {
01885 if ( (! have_timeout) ||
01886 (earliest_deadline > pos->last_activity + pos->connection_timeout) )
01887 earliest_deadline = pos->last_activity + pos->connection_timeout;
01888 #if HTTPS_SUPPORT
01889 if ( (0 != (daemon->options & MHD_USE_SSL)) &&
01890 (0 != gnutls_record_check_pending (pos->tls_session)) )
01891 earliest_deadline = 0;
01892 #endif
01893 have_timeout = MHD_YES;
01894 }
01895 }
01896
01897 pos = daemon->normal_timeout_head;
01898 if ( (NULL != pos) &&
01899 (0 != pos->connection_timeout) )
01900 {
01901 if ( (! have_timeout) ||
01902 (earliest_deadline > pos->last_activity + pos->connection_timeout) )
01903 earliest_deadline = pos->last_activity + pos->connection_timeout;
01904 #if HTTPS_SUPPORT
01905 if ( (0 != (daemon->options & MHD_USE_SSL)) &&
01906 (0 != gnutls_record_check_pending (pos->tls_session)) )
01907 earliest_deadline = 0;
01908 #endif
01909 have_timeout = MHD_YES;
01910 }
01911
01912 if (MHD_NO == have_timeout)
01913 return MHD_NO;
01914 now = MHD_monotonic_time();
01915 if (earliest_deadline < now)
01916 *timeout = 0;
01917 else
01918 *timeout = 1000 * (1 + earliest_deadline - now);
01919 return MHD_YES;
01920 }
01921
01922
01942 int
01943 MHD_run_from_select (struct MHD_Daemon *daemon,
01944 const fd_set *read_fd_set,
01945 const fd_set *write_fd_set,
01946 const fd_set *except_fd_set)
01947 {
01948 int ds;
01949 char tmp;
01950 struct MHD_Connection *pos;
01951 struct MHD_Connection *next;
01952
01953 #if EPOLL_SUPPORT
01954 if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY))
01955 {
01956
01957
01958 if (daemon->epoll_fd >= FD_SETSIZE)
01959 return MHD_NO;
01960 if (FD_ISSET (daemon->epoll_fd, read_fd_set))
01961 return MHD_run (daemon);
01962 return MHD_YES;
01963 }
01964 #endif
01965
01966
01967 if ( (-1 != (ds = daemon->socket_fd)) &&
01968 (FD_ISSET (ds, read_fd_set)) )
01969 (void) MHD_accept_connection (daemon);
01970
01971 if ( (-1 != daemon->wpipe[0]) &&
01972 (FD_ISSET (daemon->wpipe[0], read_fd_set)) )
01973 (void) read (daemon->wpipe[0], &tmp, sizeof (tmp));
01974
01975 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01976 {
01977
01978 next = daemon->connections_head;
01979 while (NULL != (pos = next))
01980 {
01981 next = pos->next;
01982 ds = pos->socket_fd;
01983 if (-1 == ds)
01984 continue;
01985 switch (pos->event_loop_info)
01986 {
01987 case MHD_EVENT_LOOP_INFO_READ:
01988 if ( (FD_ISSET (ds, read_fd_set))
01989 #if HTTPS_SUPPORT
01990 || (MHD_YES == pos->tls_read_ready)
01991 #endif
01992 )
01993 pos->read_handler (pos);
01994 break;
01995 case MHD_EVENT_LOOP_INFO_WRITE:
01996 if ( (FD_ISSET (ds, read_fd_set)) &&
01997 (pos->read_buffer_size > pos->read_buffer_offset) )
01998 pos->read_handler (pos);
01999 if (FD_ISSET (ds, write_fd_set))
02000 pos->write_handler (pos);
02001 break;
02002 case MHD_EVENT_LOOP_INFO_BLOCK:
02003 if ( (FD_ISSET (ds, read_fd_set)) &&
02004 (pos->read_buffer_size > pos->read_buffer_offset) )
02005 pos->read_handler (pos);
02006 break;
02007 case MHD_EVENT_LOOP_INFO_CLEANUP:
02008
02009 break;
02010 }
02011 pos->idle_handler (pos);
02012 }
02013 }
02014 MHD_cleanup_connections (daemon);
02015 return MHD_YES;
02016 }
02017
02018
02027 static int
02028 MHD_select (struct MHD_Daemon *daemon,
02029 int may_block)
02030 {
02031 int num_ready;
02032 fd_set rs;
02033 fd_set ws;
02034 fd_set es;
02035 int max;
02036 struct timeval timeout;
02037 struct timeval *tv;
02038 MHD_UNSIGNED_LONG_LONG ltimeout;
02039
02040 timeout.tv_sec = 0;
02041 timeout.tv_usec = 0;
02042 if (MHD_YES == daemon->shutdown)
02043 return MHD_NO;
02044 FD_ZERO (&rs);
02045 FD_ZERO (&ws);
02046 FD_ZERO (&es);
02047 max = -1;
02048 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
02049 {
02050 if (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME))
02051 resume_suspended_connections (daemon);
02052
02053
02054 if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
02055 return MHD_NO;
02056
02057
02058
02059 if ( (0 == daemon->max_connections) &&
02060 (-1 != daemon->socket_fd) )
02061 FD_CLR (daemon->socket_fd, &rs);
02062 }
02063 else
02064 {
02065
02066 if (-1 != daemon->socket_fd)
02067 {
02068 max = daemon->socket_fd;
02069 FD_SET (daemon->socket_fd, &rs);
02070 }
02071 }
02072 if (-1 != daemon->wpipe[0])
02073 {
02074 FD_SET (daemon->wpipe[0], &rs);
02075
02076 if (max < daemon->wpipe[0])
02077 max = daemon->wpipe[0];
02078 }
02079
02080 tv = NULL;
02081 if (MHD_NO == may_block)
02082 {
02083 timeout.tv_usec = 0;
02084 timeout.tv_sec = 0;
02085 tv = &timeout;
02086 }
02087 else if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
02088 (MHD_YES == MHD_get_timeout (daemon, <imeout)) )
02089 {
02090
02091 timeout.tv_usec = (ltimeout % 1000) * 1000;
02092 timeout.tv_sec = ltimeout / 1000;
02093 tv = &timeout;
02094 }
02095 if (-1 == max)
02096 return MHD_YES;
02097 num_ready = SELECT (max + 1, &rs, &ws, &es, tv);
02098 if (MHD_YES == daemon->shutdown)
02099 return MHD_NO;
02100 if (num_ready < 0)
02101 {
02102 if (EINTR == errno)
02103 return MHD_YES;
02104 #if HAVE_MESSAGES
02105 MHD_DLOG (daemon, "select failed: %s\n", STRERROR (errno));
02106 #endif
02107 return MHD_NO;
02108 }
02109 return MHD_run_from_select (daemon, &rs, &ws, &es);
02110 }
02111
02112
02113 #ifdef HAVE_POLL_H
02114
02122 static int
02123 MHD_poll_all (struct MHD_Daemon *daemon,
02124 int may_block)
02125 {
02126 unsigned int num_connections;
02127 struct MHD_Connection *pos;
02128 struct MHD_Connection *next;
02129
02130 if (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME))
02131 resume_suspended_connections (daemon);
02132
02133
02134 num_connections = 0;
02135 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
02136 num_connections++;
02137 {
02138 struct pollfd p[2 + num_connections];
02139 MHD_UNSIGNED_LONG_LONG ltimeout;
02140 unsigned int i;
02141 int timeout;
02142 unsigned int poll_server;
02143 int poll_listen;
02144
02145 memset (p, 0, sizeof (p));
02146 poll_server = 0;
02147 poll_listen = -1;
02148 if ( (-1 != daemon->socket_fd) &&
02149 (0 != daemon->max_connections) )
02150 {
02151
02152 p[poll_server].fd = daemon->socket_fd;
02153 p[poll_server].events = POLLIN;
02154 p[poll_server].revents = 0;
02155 poll_listen = (int) poll_server;
02156 poll_server++;
02157 }
02158 if (-1 != daemon->wpipe[0])
02159 {
02160 p[poll_server].fd = daemon->wpipe[0];
02161 p[poll_server].events = POLLIN;
02162 p[poll_server].revents = 0;
02163 poll_server++;
02164 }
02165 if (may_block == MHD_NO)
02166 timeout = 0;
02167 else if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
02168 (MHD_YES != MHD_get_timeout (daemon, <imeout)) )
02169 timeout = -1;
02170 else
02171 timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
02172
02173 i = 0;
02174 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
02175 {
02176 p[poll_server+i].fd = pos->socket_fd;
02177 switch (pos->event_loop_info)
02178 {
02179 case MHD_EVENT_LOOP_INFO_READ:
02180 p[poll_server+i].events |= POLLIN;
02181 break;
02182 case MHD_EVENT_LOOP_INFO_WRITE:
02183 p[poll_server+i].events |= POLLOUT;
02184 if (pos->read_buffer_size > pos->read_buffer_offset)
02185 p[poll_server+i].events |= POLLIN;
02186 break;
02187 case MHD_EVENT_LOOP_INFO_BLOCK:
02188 if (pos->read_buffer_size > pos->read_buffer_offset)
02189 p[poll_server+i].events |= POLLIN;
02190 break;
02191 case MHD_EVENT_LOOP_INFO_CLEANUP:
02192
02193 break;
02194 }
02195 i++;
02196 }
02197 if (0 == poll_server + num_connections)
02198 return MHD_YES;
02199 if (poll (p, poll_server + num_connections, timeout) < 0)
02200 {
02201 if (EINTR == errno)
02202 return MHD_YES;
02203 #if HAVE_MESSAGES
02204 MHD_DLOG (daemon,
02205 "poll failed: %s\n",
02206 STRERROR (errno));
02207 #endif
02208 return MHD_NO;
02209 }
02210
02211 if (MHD_YES == daemon->shutdown)
02212 return MHD_NO;
02213 i = 0;
02214 next = daemon->connections_head;
02215 while (NULL != (pos = next))
02216 {
02217 next = pos->next;
02218 switch (pos->event_loop_info)
02219 {
02220 case MHD_EVENT_LOOP_INFO_READ:
02221
02222 if (i >= num_connections)
02223 break;
02224 if (p[poll_server+i].fd != pos->socket_fd)
02225 break;
02226
02227 if (0 != (p[poll_server+i].revents & POLLIN))
02228 pos->read_handler (pos);
02229 pos->idle_handler (pos);
02230 i++;
02231 break;
02232 case MHD_EVENT_LOOP_INFO_WRITE:
02233
02234 if (i >= num_connections)
02235 break;
02236 if (p[poll_server+i].fd != pos->socket_fd)
02237 break;
02238
02239 if (0 != (p[poll_server+i].revents & POLLIN))
02240 pos->read_handler (pos);
02241 if (0 != (p[poll_server+i].revents & POLLOUT))
02242 pos->write_handler (pos);
02243 pos->idle_handler (pos);
02244 i++;
02245 break;
02246 case MHD_EVENT_LOOP_INFO_BLOCK:
02247 if (0 != (p[poll_server+i].revents & POLLIN))
02248 pos->read_handler (pos);
02249 pos->idle_handler (pos);
02250 break;
02251 case MHD_EVENT_LOOP_INFO_CLEANUP:
02252
02253 break;
02254 }
02255 }
02256
02257 if ( (-1 != poll_listen) &&
02258 (0 != (p[poll_listen].revents & POLLIN)) )
02259 (void) MHD_accept_connection (daemon);
02260 }
02261 return MHD_YES;
02262 }
02263
02264
02272 static int
02273 MHD_poll_listen_socket (struct MHD_Daemon *daemon,
02274 int may_block)
02275 {
02276 struct pollfd p[2];
02277 int timeout;
02278 unsigned int poll_count;
02279 int poll_listen;
02280
02281 memset (&p, 0, sizeof (p));
02282 poll_count = 0;
02283 poll_listen = -1;
02284 if (-1 != daemon->socket_fd)
02285 {
02286 p[poll_count].fd = daemon->socket_fd;
02287 p[poll_count].events = POLLIN;
02288 p[poll_count].revents = 0;
02289 poll_listen = poll_count;
02290 poll_count++;
02291 }
02292 if (-1 != daemon->wpipe[0])
02293 {
02294 p[poll_count].fd = daemon->wpipe[0];
02295 p[poll_count].events = POLLIN;
02296 p[poll_count].revents = 0;
02297 poll_count++;
02298 }
02299 if (MHD_NO == may_block)
02300 timeout = 0;
02301 else
02302 timeout = -1;
02303 if (0 == poll_count)
02304 return MHD_YES;
02305 if (poll (p, poll_count, timeout) < 0)
02306 {
02307 if (EINTR == errno)
02308 return MHD_YES;
02309 #if HAVE_MESSAGES
02310 MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
02311 #endif
02312 return MHD_NO;
02313 }
02314
02315 if (MHD_YES == daemon->shutdown)
02316 return MHD_NO;
02317 if ( (-1 != poll_listen) &&
02318 (0 != (p[poll_listen].revents & POLLIN)) )
02319 (void) MHD_accept_connection (daemon);
02320 return MHD_YES;
02321 }
02322 #endif
02323
02324
02332 static int
02333 MHD_poll (struct MHD_Daemon *daemon,
02334 int may_block)
02335 {
02336 #ifdef HAVE_POLL_H
02337 if (MHD_YES == daemon->shutdown)
02338 return MHD_NO;
02339 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
02340 return MHD_poll_all (daemon, may_block);
02341 else
02342 return MHD_poll_listen_socket (daemon, may_block);
02343 #else
02344 return MHD_NO;
02345 #endif
02346 }
02347
02348
02349 #if EPOLL_SUPPORT
02350
02359 #define MAX_EVENTS 128
02360
02361
02370 static int
02371 MHD_epoll (struct MHD_Daemon *daemon,
02372 int may_block)
02373 {
02374 struct MHD_Connection *pos;
02375 struct MHD_Connection *next;
02376 struct epoll_event events[MAX_EVENTS];
02377 struct epoll_event event;
02378 int timeout_ms;
02379 MHD_UNSIGNED_LONG_LONG timeout_ll;
02380 int num_events;
02381 unsigned int i;
02382 unsigned int series_length;
02383 char tmp;
02384
02385 if (-1 == daemon->epoll_fd)
02386 return MHD_NO;
02387 if (MHD_YES == daemon->shutdown)
02388 return MHD_NO;
02389 if ( (-1 != daemon->socket_fd) &&
02390 (0 != daemon->max_connections) &&
02391 (MHD_NO == daemon->listen_socket_in_epoll) )
02392 {
02393 event.events = EPOLLIN;
02394 event.data.ptr = daemon;
02395 if (0 != epoll_ctl (daemon->epoll_fd,
02396 EPOLL_CTL_ADD,
02397 daemon->socket_fd,
02398 &event))
02399 {
02400 #if HAVE_MESSAGES
02401 if (0 != (daemon->options & MHD_USE_DEBUG))
02402 MHD_DLOG (daemon,
02403 "Call to epoll_ctl failed: %s\n",
02404 STRERROR (errno));
02405 #endif
02406 return MHD_NO;
02407 }
02408 daemon->listen_socket_in_epoll = MHD_YES;
02409 }
02410 if ( (MHD_YES == daemon->listen_socket_in_epoll) &&
02411 (0 == daemon->max_connections) )
02412 {
02413
02414
02415 if (0 != epoll_ctl (daemon->epoll_fd,
02416 EPOLL_CTL_DEL,
02417 daemon->socket_fd,
02418 NULL))
02419 MHD_PANIC ("Failed to remove listen FD from epoll set\n");
02420 daemon->listen_socket_in_epoll = MHD_NO;
02421 }
02422 if (MHD_YES == may_block)
02423 {
02424 if (MHD_YES == MHD_get_timeout (daemon,
02425 &timeout_ll))
02426 {
02427 if (timeout_ll >= (MHD_UNSIGNED_LONG_LONG) INT_MAX)
02428 timeout_ms = INT_MAX;
02429 else
02430 timeout_ms = (int) timeout_ll;
02431 }
02432 else
02433 timeout_ms = -1;
02434 }
02435 else
02436 timeout_ms = 0;
02437
02438
02439
02440
02441
02442 num_events = MAX_EVENTS;
02443 while (MAX_EVENTS == num_events)
02444 {
02445
02446 num_events = epoll_wait (daemon->epoll_fd,
02447 events, MAX_EVENTS, timeout_ms);
02448 if (-1 == num_events)
02449 {
02450 if (EINTR == errno)
02451 return MHD_YES;
02452 #if HAVE_MESSAGES
02453 if (0 != (daemon->options & MHD_USE_DEBUG))
02454 MHD_DLOG (daemon,
02455 "Call to epoll_wait failed: %s\n",
02456 STRERROR (errno));
02457 #endif
02458 return MHD_NO;
02459 }
02460 for (i=0;i<num_events;i++)
02461 {
02462 if (NULL == events[i].data.ptr)
02463 continue;
02464 if ( (-1 != daemon->wpipe[0]) &&
02465 (daemon->wpipe[0] == events[i].data.fd) )
02466 {
02467 (void) read (daemon->wpipe[0], &tmp, sizeof (tmp));
02468 continue;
02469 }
02470 if (daemon != events[i].data.ptr)
02471 {
02472
02473
02474
02475 pos = events[i].data.ptr;
02476 if (0 != (events[i].events & EPOLLIN))
02477 {
02478 pos->epoll_state |= MHD_EPOLL_STATE_READ_READY;
02479 if ( ( (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) ||
02480 (pos->read_buffer_size > pos->read_buffer_offset) ) &&
02481 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
02482 {
02483 EDLL_insert (daemon->eready_head,
02484 daemon->eready_tail,
02485 pos);
02486 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
02487 }
02488 }
02489 if (0 != (events[i].events & EPOLLOUT))
02490 {
02491 pos->epoll_state |= MHD_EPOLL_STATE_WRITE_READY;
02492 if ( (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info) &&
02493 (0 == (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) ) )
02494 {
02495 EDLL_insert (daemon->eready_head,
02496 daemon->eready_tail,
02497 pos);
02498 pos->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
02499 }
02500 }
02501 }
02502 else
02503 {
02504
02505
02506 series_length = 0;
02507 while ( (MHD_YES == MHD_accept_connection (daemon)) &&
02508 (0 != daemon->max_connections) &&
02509 (series_length < 128) )
02510 series_length++;
02511 }
02512 }
02513 }
02514
02515
02516
02517 if (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME))
02518 resume_suspended_connections (daemon);
02519
02520
02521 while (NULL != (pos = daemon->eready_tail))
02522 {
02523 EDLL_remove (daemon->eready_head,
02524 daemon->eready_tail,
02525 pos);
02526 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
02527 if (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info)
02528 pos->read_handler (pos);
02529 if (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info)
02530 pos->write_handler (pos);
02531 pos->idle_handler (pos);
02532 }
02533
02534
02535
02536
02537
02538
02539
02540
02541 next = daemon->manual_timeout_head;
02542 while (NULL != (pos = next))
02543 {
02544 next = pos->nextX;
02545 pos->idle_handler (pos);
02546 }
02547
02548
02549
02550
02551 next = daemon->normal_timeout_tail;
02552 while (NULL != (pos = next))
02553 {
02554 next = pos->prevX;
02555 pos->idle_handler (pos);
02556 if (MHD_CONNECTION_CLOSED != pos->state)
02557 break;
02558 }
02559 return MHD_YES;
02560 }
02561 #endif
02562
02563
02583 int
02584 MHD_run (struct MHD_Daemon *daemon)
02585 {
02586 if ( (MHD_YES == daemon->shutdown) ||
02587 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
02588 (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) )
02589 return MHD_NO;
02590 if (0 != (daemon->options & MHD_USE_POLL))
02591 {
02592 MHD_poll (daemon, MHD_NO);
02593 MHD_cleanup_connections (daemon);
02594 }
02595 #if EPOLL_SUPPORT
02596 else if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY))
02597 {
02598 MHD_epoll (daemon, MHD_NO);
02599 MHD_cleanup_connections (daemon);
02600 }
02601 #endif
02602 else
02603 {
02604 MHD_select (daemon, MHD_NO);
02605
02606 }
02607 return MHD_YES;
02608 }
02609
02610
02618 static void *
02619 MHD_select_thread (void *cls)
02620 {
02621 struct MHD_Daemon *daemon = cls;
02622
02623 while (MHD_YES != daemon->shutdown)
02624 {
02625 if (0 != (daemon->options & MHD_USE_POLL))
02626 MHD_poll (daemon, MHD_YES);
02627 #if EPOLL_SUPPORT
02628 else if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY))
02629 MHD_epoll (daemon, MHD_YES);
02630 #endif
02631 else
02632 MHD_select (daemon, MHD_YES);
02633 MHD_cleanup_connections (daemon);
02634 }
02635 return NULL;
02636 }
02637
02638
02655 struct MHD_Daemon *
02656 MHD_start_daemon (unsigned int flags,
02657 uint16_t port,
02658 MHD_AcceptPolicyCallback apc,
02659 void *apc_cls,
02660 MHD_AccessHandlerCallback dh, void *dh_cls, ...)
02661 {
02662 struct MHD_Daemon *daemon;
02663 va_list ap;
02664
02665 va_start (ap, dh_cls);
02666 daemon = MHD_start_daemon_va (flags, port, apc, apc_cls, dh, dh_cls, ap);
02667 va_end (ap);
02668 return daemon;
02669 }
02670
02671
02691 int
02692 MHD_quiesce_daemon (struct MHD_Daemon *daemon)
02693 {
02694 unsigned int i;
02695 int ret;
02696
02697 ret = daemon->socket_fd;
02698 if (-1 == ret)
02699 return -1;
02700 if ( (-1 == daemon->wpipe[1]) &&
02701 (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) )
02702 {
02703 #if HAVE_MESSAGES
02704 MHD_DLOG (daemon,
02705 "Using MHD_quiesce_daemon in this mode requires MHD_USE_PIPE_FOR_SHUTDOWN\n");
02706 #endif
02707 return -1;
02708 }
02709
02710 if (NULL != daemon->worker_pool)
02711 for (i = 0; i < daemon->worker_pool_size; i++)
02712 {
02713 daemon->worker_pool[i].socket_fd = -1;
02714 #if EPOLL_SUPPORT
02715 if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) &&
02716 (-1 != daemon->worker_pool[i].epoll_fd) &&
02717 (MHD_YES == daemon->worker_pool[i].listen_socket_in_epoll) )
02718 {
02719 if (0 != epoll_ctl (daemon->worker_pool[i].epoll_fd,
02720 EPOLL_CTL_DEL,
02721 ret,
02722 NULL))
02723 MHD_PANIC ("Failed to remove listen FD from epoll set\n");
02724 daemon->worker_pool[i].listen_socket_in_epoll = MHD_NO;
02725 }
02726 #endif
02727 }
02728 daemon->socket_fd = -1;
02729 #if EPOLL_SUPPORT
02730 if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) &&
02731 (-1 != daemon->epoll_fd) &&
02732 (MHD_YES == daemon->listen_socket_in_epoll) )
02733 {
02734 if (0 != epoll_ctl (daemon->epoll_fd,
02735 EPOLL_CTL_DEL,
02736 ret,
02737 NULL))
02738 MHD_PANIC ("Failed to remove listen FD from epoll set\n");
02739 daemon->listen_socket_in_epoll = MHD_NO;
02740 }
02741 #endif
02742 return ret;
02743 }
02744
02745
02753 typedef void (*VfprintfFunctionPointerType)(void *cls,
02754 const char *format,
02755 va_list va);
02756
02757
02766 static int
02767 parse_options_va (struct MHD_Daemon *daemon,
02768 const struct sockaddr **servaddr,
02769 va_list ap);
02770
02771
02780 static int
02781 parse_options (struct MHD_Daemon *daemon,
02782 const struct sockaddr **servaddr,
02783 ...)
02784 {
02785 va_list ap;
02786 int ret;
02787
02788 va_start (ap, servaddr);
02789 ret = parse_options_va (daemon, servaddr, ap);
02790 va_end (ap);
02791 return ret;
02792 }
02793
02794
02803 static int
02804 parse_options_va (struct MHD_Daemon *daemon,
02805 const struct sockaddr **servaddr,
02806 va_list ap)
02807 {
02808 enum MHD_OPTION opt;
02809 struct MHD_OptionItem *oa;
02810 unsigned int i;
02811 #if HTTPS_SUPPORT
02812 int ret;
02813 const char *pstr;
02814 #endif
02815
02816 while (MHD_OPTION_END != (opt = (enum MHD_OPTION) va_arg (ap, int)))
02817 {
02818 switch (opt)
02819 {
02820 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
02821 daemon->pool_size = va_arg (ap, size_t);
02822 break;
02823 case MHD_OPTION_CONNECTION_MEMORY_INCREMENT:
02824 daemon->pool_increment= va_arg (ap, size_t);
02825 break;
02826 case MHD_OPTION_CONNECTION_LIMIT:
02827 daemon->max_connections = va_arg (ap, unsigned int);
02828 break;
02829 case MHD_OPTION_CONNECTION_TIMEOUT:
02830 daemon->connection_timeout = va_arg (ap, unsigned int);
02831 break;
02832 case MHD_OPTION_NOTIFY_COMPLETED:
02833 daemon->notify_completed =
02834 va_arg (ap, MHD_RequestCompletedCallback);
02835 daemon->notify_completed_cls = va_arg (ap, void *);
02836 break;
02837 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
02838 daemon->per_ip_connection_limit = va_arg (ap, unsigned int);
02839 break;
02840 case MHD_OPTION_SOCK_ADDR:
02841 *servaddr = va_arg (ap, const struct sockaddr *);
02842 break;
02843 case MHD_OPTION_URI_LOG_CALLBACK:
02844 daemon->uri_log_callback =
02845 va_arg (ap, LogCallback);
02846 daemon->uri_log_callback_cls = va_arg (ap, void *);
02847 break;
02848 case MHD_OPTION_THREAD_POOL_SIZE:
02849 daemon->worker_pool_size = va_arg (ap, unsigned int);
02850 if (daemon->worker_pool_size >= (SIZE_MAX / sizeof (struct MHD_Daemon)))
02851 {
02852 #if HAVE_MESSAGES
02853 MHD_DLOG (daemon,
02854 "Specified thread pool size (%u) too big\n",
02855 daemon->worker_pool_size);
02856 #endif
02857 return MHD_NO;
02858 }
02859 break;
02860 #if HTTPS_SUPPORT
02861 case MHD_OPTION_HTTPS_MEM_KEY:
02862 if (0 != (daemon->options & MHD_USE_SSL))
02863 daemon->https_mem_key = va_arg (ap, const char *);
02864 #if HAVE_MESSAGES
02865 else
02866 MHD_DLOG (daemon,
02867 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
02868 opt);
02869 #endif
02870 break;
02871 case MHD_OPTION_HTTPS_MEM_CERT:
02872 if (0 != (daemon->options & MHD_USE_SSL))
02873 daemon->https_mem_cert = va_arg (ap, const char *);
02874 #if HAVE_MESSAGES
02875 else
02876 MHD_DLOG (daemon,
02877 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
02878 opt);
02879 #endif
02880 break;
02881 case MHD_OPTION_HTTPS_MEM_TRUST:
02882 if (0 != (daemon->options & MHD_USE_SSL))
02883 daemon->https_mem_trust = va_arg (ap, const char *);
02884 #if HAVE_MESSAGES
02885 else
02886 MHD_DLOG (daemon,
02887 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
02888 opt);
02889 #endif
02890 break;
02891 case MHD_OPTION_HTTPS_CRED_TYPE:
02892 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap, int);
02893 break;
02894 case MHD_OPTION_HTTPS_PRIORITIES:
02895 if (0 != (daemon->options & MHD_USE_SSL))
02896 {
02897 gnutls_priority_deinit (daemon->priority_cache);
02898 ret = gnutls_priority_init (&daemon->priority_cache,
02899 pstr = va_arg (ap, const char*),
02900 NULL);
02901 if (ret != GNUTLS_E_SUCCESS)
02902 {
02903 #if HAVE_MESSAGES
02904 MHD_DLOG (daemon,
02905 "Setting priorities to `%s' failed: %s\n",
02906 pstr,
02907 gnutls_strerror (ret));
02908 #endif
02909 daemon->priority_cache = NULL;
02910 return MHD_NO;
02911 }
02912 }
02913 break;
02914 case MHD_OPTION_HTTPS_CERT_CALLBACK:
02915 #if GNUTLS_VERSION_MAJOR < 3
02916 #if HAVE_MESSAGES
02917 MHD_DLOG (daemon,
02918 "MHD_OPTION_HTTPS_CERT_CALLBACK requires building MHD with GnuTLS >= 3.0\n");
02919 #endif
02920 return MHD_NO;
02921 #else
02922 if (0 != (daemon->options & MHD_USE_SSL))
02923 daemon->cert_callback = va_arg (ap, gnutls_certificate_retrieve_function2 *);
02924 break;
02925 #endif
02926 #endif
02927 #ifdef DAUTH_SUPPORT
02928 case MHD_OPTION_DIGEST_AUTH_RANDOM:
02929 daemon->digest_auth_rand_size = va_arg (ap, size_t);
02930 daemon->digest_auth_random = va_arg (ap, const char *);
02931 break;
02932 case MHD_OPTION_NONCE_NC_SIZE:
02933 daemon->nonce_nc_size = va_arg (ap, unsigned int);
02934 break;
02935 #endif
02936 case MHD_OPTION_LISTEN_SOCKET:
02937 daemon->socket_fd = va_arg (ap, int);
02938 break;
02939 case MHD_OPTION_EXTERNAL_LOGGER:
02940 #if HAVE_MESSAGES
02941 daemon->custom_error_log =
02942 va_arg (ap, VfprintfFunctionPointerType);
02943 daemon->custom_error_log_cls = va_arg (ap, void *);
02944 #else
02945 va_arg (ap, VfprintfFunctionPointerType);
02946 va_arg (ap, void *);
02947 #endif
02948 break;
02949 case MHD_OPTION_THREAD_STACK_SIZE:
02950 daemon->thread_stack_size = va_arg (ap, size_t);
02951 break;
02952 case MHD_OPTION_ARRAY:
02953 oa = va_arg (ap, struct MHD_OptionItem*);
02954 i = 0;
02955 while (MHD_OPTION_END != (opt = oa[i].option))
02956 {
02957 switch (opt)
02958 {
02959
02960 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
02961 case MHD_OPTION_CONNECTION_MEMORY_INCREMENT:
02962 case MHD_OPTION_THREAD_STACK_SIZE:
02963 if (MHD_YES != parse_options (daemon,
02964 servaddr,
02965 opt,
02966 (size_t) oa[i].value,
02967 MHD_OPTION_END))
02968 return MHD_NO;
02969 break;
02970
02971 case MHD_OPTION_NONCE_NC_SIZE:
02972 case MHD_OPTION_CONNECTION_LIMIT:
02973 case MHD_OPTION_CONNECTION_TIMEOUT:
02974 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
02975 case MHD_OPTION_THREAD_POOL_SIZE:
02976 if (MHD_YES != parse_options (daemon,
02977 servaddr,
02978 opt,
02979 (unsigned int) oa[i].value,
02980 MHD_OPTION_END))
02981 return MHD_NO;
02982 break;
02983
02984 case MHD_OPTION_HTTPS_CRED_TYPE:
02985 case MHD_OPTION_LISTEN_SOCKET:
02986 if (MHD_YES != parse_options (daemon,
02987 servaddr,
02988 opt,
02989 (int) oa[i].value,
02990 MHD_OPTION_END))
02991 return MHD_NO;
02992 break;
02993
02994 case MHD_OPTION_SOCK_ADDR:
02995 case MHD_OPTION_HTTPS_MEM_KEY:
02996 case MHD_OPTION_HTTPS_MEM_CERT:
02997 case MHD_OPTION_HTTPS_MEM_TRUST:
02998 case MHD_OPTION_HTTPS_PRIORITIES:
02999 case MHD_OPTION_ARRAY:
03000 case MHD_OPTION_HTTPS_CERT_CALLBACK:
03001 if (MHD_YES != parse_options (daemon,
03002 servaddr,
03003 opt,
03004 oa[i].ptr_value,
03005 MHD_OPTION_END))
03006 return MHD_NO;
03007 break;
03008
03009 case MHD_OPTION_NOTIFY_COMPLETED:
03010 case MHD_OPTION_URI_LOG_CALLBACK:
03011 case MHD_OPTION_EXTERNAL_LOGGER:
03012 case MHD_OPTION_UNESCAPE_CALLBACK:
03013 if (MHD_YES != parse_options (daemon,
03014 servaddr,
03015 opt,
03016 (void *) oa[i].value,
03017 oa[i].ptr_value,
03018 MHD_OPTION_END))
03019 return MHD_NO;
03020 break;
03021
03022 case MHD_OPTION_DIGEST_AUTH_RANDOM:
03023 if (MHD_YES != parse_options (daemon,
03024 servaddr,
03025 opt,
03026 (size_t) oa[i].value,
03027 oa[i].ptr_value,
03028 MHD_OPTION_END))
03029 return MHD_NO;
03030 break;
03031 default:
03032 return MHD_NO;
03033 }
03034 i++;
03035 }
03036 break;
03037 case MHD_OPTION_UNESCAPE_CALLBACK:
03038 daemon->unescape_callback =
03039 va_arg (ap, UnescapeCallback);
03040 daemon->unescape_callback_cls = va_arg (ap, void *);
03041 break;
03042 default:
03043 #if HAVE_MESSAGES
03044 if (((opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
03045 (opt <= MHD_OPTION_HTTPS_PRIORITIES)) || (opt == MHD_OPTION_HTTPS_MEM_TRUST))
03046 {
03047 MHD_DLOG (daemon,
03048 "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
03049 opt);
03050 }
03051 else
03052 {
03053 MHD_DLOG (daemon,
03054 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
03055 opt);
03056 }
03057 #endif
03058 return MHD_NO;
03059 }
03060 }
03061 return MHD_YES;
03062 }
03063
03064
03073 static int
03074 create_socket (struct MHD_Daemon *daemon,
03075 int domain, int type, int protocol)
03076 {
03077 int ctype = type | SOCK_CLOEXEC;
03078 int fd;
03079
03080
03081
03082 fd = SOCKET (domain, ctype, protocol);
03083 if ( (-1 == fd) && (EINVAL == errno) && (0 != SOCK_CLOEXEC) )
03084 {
03085 ctype = type;
03086 fd = SOCKET(domain, type, protocol);
03087 }
03088 if (-1 == fd)
03089 return -1;
03090 if (type == ctype)
03091 make_nonblocking_noninheritable (daemon, fd);
03092 return fd;
03093 }
03094
03095
03096 #if EPOLL_SUPPORT
03097
03104 static int
03105 setup_epoll_to_listen (struct MHD_Daemon *daemon)
03106 {
03107 struct epoll_event event;
03108
03109 daemon->epoll_fd = epoll_create1 (EPOLL_CLOEXEC);
03110 if (-1 == daemon->epoll_fd)
03111 {
03112 #if HAVE_MESSAGES
03113 if (0 != (daemon->options & MHD_USE_DEBUG))
03114 MHD_DLOG (daemon,
03115 "Call to epoll_create1 failed: %s\n",
03116 STRERROR (errno));
03117 #endif
03118 return MHD_NO;
03119 }
03120 if (0 == EPOLL_CLOEXEC)
03121 make_nonblocking_noninheritable (daemon,
03122 daemon->epoll_fd);
03123 if (-1 == daemon->socket_fd)
03124 return MHD_YES;
03125 event.events = EPOLLIN;
03126 event.data.ptr = daemon;
03127 if (0 != epoll_ctl (daemon->epoll_fd,
03128 EPOLL_CTL_ADD,
03129 daemon->socket_fd,
03130 &event))
03131 {
03132 #if HAVE_MESSAGES
03133 if (0 != (daemon->options & MHD_USE_DEBUG))
03134 MHD_DLOG (daemon,
03135 "Call to epoll_ctl failed: %s\n",
03136 STRERROR (errno));
03137 #endif
03138 return MHD_NO;
03139 }
03140 if ( (-1 != daemon->wpipe[0]) &&
03141 (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME)) )
03142 {
03143 event.events = EPOLLIN | EPOLLET;
03144 event.data.ptr = NULL;
03145 event.data.fd = daemon->wpipe[0];
03146 if (0 != epoll_ctl (daemon->epoll_fd,
03147 EPOLL_CTL_ADD,
03148 daemon->wpipe[0],
03149 &event))
03150 {
03151 #if HAVE_MESSAGES
03152 if (0 != (daemon->options & MHD_USE_DEBUG))
03153 MHD_DLOG (daemon,
03154 "Call to epoll_ctl failed: %s\n",
03155 STRERROR (errno));
03156 #endif
03157 return MHD_NO;
03158 }
03159 }
03160 daemon->listen_socket_in_epoll = MHD_YES;
03161 return MHD_YES;
03162 }
03163 #endif
03164
03165
03183 struct MHD_Daemon *
03184 MHD_start_daemon_va (unsigned int flags,
03185 uint16_t port,
03186 MHD_AcceptPolicyCallback apc,
03187 void *apc_cls,
03188 MHD_AccessHandlerCallback dh, void *dh_cls,
03189 va_list ap)
03190 {
03191 const int on = 1;
03192 struct MHD_Daemon *daemon;
03193 int socket_fd;
03194 struct sockaddr_in servaddr4;
03195 #if HAVE_INET6
03196 struct sockaddr_in6 servaddr6;
03197 #endif
03198 const struct sockaddr *servaddr = NULL;
03199 socklen_t addrlen;
03200 unsigned int i;
03201 int res_thread_create;
03202 int use_pipe;
03203
03204 #ifndef HAVE_INET6
03205 if (0 != (flags & MHD_USE_IPv6))
03206 return NULL;
03207 #endif
03208 #ifndef HAVE_POLL_H
03209 if (0 != (flags & MHD_USE_POLL))
03210 return NULL;
03211 #endif
03212 #if ! HTTPS_SUPPORT
03213 if (0 != (flags & MHD_USE_SSL))
03214 return NULL;
03215 #endif
03216 if (NULL == dh)
03217 return NULL;
03218 if (NULL == (daemon = malloc (sizeof (struct MHD_Daemon))))
03219 return NULL;
03220 memset (daemon, 0, sizeof (struct MHD_Daemon));
03221 #if EPOLL_SUPPORT
03222 daemon->epoll_fd = -1;
03223 #endif
03224
03225 #if HTTPS_SUPPORT
03226 if (0 != (flags & MHD_USE_SSL))
03227 {
03228 gnutls_priority_init (&daemon->priority_cache,
03229 "NORMAL",
03230 NULL);
03231 }
03232 #endif
03233 daemon->socket_fd = -1;
03234 daemon->options = (enum MHD_OPTION) flags;
03235 #if WINDOWS
03236
03237
03238 daemon->options |= MHD_USE_EPOLL_TURBO;
03239 #endif
03240 daemon->port = port;
03241 daemon->apc = apc;
03242 daemon->apc_cls = apc_cls;
03243 daemon->default_handler = dh;
03244 daemon->default_handler_cls = dh_cls;
03245 daemon->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
03246 daemon->pool_size = MHD_POOL_SIZE_DEFAULT;
03247 daemon->pool_increment = MHD_BUF_INC_SIZE;
03248 daemon->unescape_callback = &MHD_http_unescape;
03249 daemon->connection_timeout = 0;
03250 daemon->wpipe[0] = -1;
03251 daemon->wpipe[1] = -1;
03252 #if HAVE_MESSAGES
03253 daemon->custom_error_log = (MHD_LogCallback) &vfprintf;
03254 daemon->custom_error_log_cls = stderr;
03255 #endif
03256 #ifdef HAVE_LISTEN_SHUTDOWN
03257 use_pipe = (0 != (daemon->options & (MHD_USE_NO_LISTEN_SOCKET | MHD_USE_PIPE_FOR_SHUTDOWN)));
03258 #else
03259 use_pipe = 1;
03260 #endif
03261 if (0 == (flags & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
03262 use_pipe = 0;
03263 if ( (use_pipe) &&
03264 #ifdef WINDOWS
03265 (0 != SOCKETPAIR (AF_INET, SOCK_STREAM, IPPROTO_TCP, daemon->wpipe))
03266 #else
03267 (0 != PIPE (daemon->wpipe))
03268 #endif
03269 )
03270 {
03271 #if HAVE_MESSAGES
03272 MHD_DLOG (daemon,
03273 "Failed to create control pipe: %s\n",
03274 STRERROR (errno));
03275 #endif
03276 free (daemon);
03277 return NULL;
03278 }
03279 #ifndef WINDOWS
03280 if ( (0 == (flags & MHD_USE_POLL)) &&
03281 (1 == use_pipe) &&
03282 (daemon->wpipe[0] >= FD_SETSIZE) )
03283 {
03284 #if HAVE_MESSAGES
03285 MHD_DLOG (daemon,
03286 "file descriptor for control pipe exceeds maximum value\n");
03287 #endif
03288 if (0 != CLOSE (daemon->wpipe[0]))
03289 MHD_PANIC ("close failed\n");
03290 if (0 != CLOSE (daemon->wpipe[1]))
03291 MHD_PANIC ("close failed\n");
03292 free (daemon);
03293 return NULL;
03294 }
03295 #endif
03296 #ifdef DAUTH_SUPPORT
03297 daemon->digest_auth_rand_size = 0;
03298 daemon->digest_auth_random = NULL;
03299 daemon->nonce_nc_size = 4;
03300 #endif
03301 #if HTTPS_SUPPORT
03302 if (0 != (flags & MHD_USE_SSL))
03303 {
03304 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
03305 }
03306 #endif
03307
03308
03309 if (MHD_YES != parse_options_va (daemon, &servaddr, ap))
03310 {
03311 #if HTTPS_SUPPORT
03312 if ( (0 != (flags & MHD_USE_SSL)) &&
03313 (NULL != daemon->priority_cache) )
03314 gnutls_priority_deinit (daemon->priority_cache);
03315 #endif
03316 free (daemon);
03317 return NULL;
03318 }
03319 #ifdef DAUTH_SUPPORT
03320 if (daemon->nonce_nc_size > 0)
03321 {
03322 if ( ( (size_t) (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc))) /
03323 sizeof(struct MHD_NonceNc) != daemon->nonce_nc_size)
03324 {
03325 #if HAVE_MESSAGES
03326 MHD_DLOG (daemon,
03327 "Specified value for NC_SIZE too large\n");
03328 #endif
03329 #if HTTPS_SUPPORT
03330 if (0 != (flags & MHD_USE_SSL))
03331 gnutls_priority_deinit (daemon->priority_cache);
03332 #endif
03333 free (daemon);
03334 return NULL;
03335 }
03336 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof (struct MHD_NonceNc));
03337 if (NULL == daemon->nnc)
03338 {
03339 #if HAVE_MESSAGES
03340 MHD_DLOG (daemon,
03341 "Failed to allocate memory for nonce-nc map: %s\n",
03342 STRERROR (errno));
03343 #endif
03344 #if HTTPS_SUPPORT
03345 if (0 != (flags & MHD_USE_SSL))
03346 gnutls_priority_deinit (daemon->priority_cache);
03347 #endif
03348 free (daemon);
03349 return NULL;
03350 }
03351 }
03352
03353 if (0 != pthread_mutex_init (&daemon->nnc_lock, NULL))
03354 {
03355 #if HAVE_MESSAGES
03356 MHD_DLOG (daemon,
03357 "MHD failed to initialize nonce-nc mutex\n");
03358 #endif
03359 #if HTTPS_SUPPORT
03360 if (0 != (flags & MHD_USE_SSL))
03361 gnutls_priority_deinit (daemon->priority_cache);
03362 #endif
03363 free (daemon->nnc);
03364 free (daemon);
03365 return NULL;
03366 }
03367 #endif
03368
03369
03370 if ( (0 == (flags & MHD_USE_SELECT_INTERNALLY)) &&
03371 (daemon->worker_pool_size > 0) )
03372 {
03373 #if HAVE_MESSAGES
03374 MHD_DLOG (daemon,
03375 "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n");
03376 #endif
03377 goto free_and_fail;
03378 }
03379
03380 if ( (MHD_USE_SUSPEND_RESUME == (flags & MHD_USE_SUSPEND_RESUME)) &&
03381 (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) )
03382 {
03383 #if HAVE_MESSAGES
03384 MHD_DLOG (daemon,
03385 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_SUSPEND_RESUME is not supported.\n");
03386 #endif
03387 goto free_and_fail;
03388 }
03389
03390 #ifdef __SYMBIAN32__
03391 if (0 != (flags & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
03392 {
03393 #if HAVE_MESSAGES
03394 MHD_DLOG (daemon,
03395 "Threaded operations are not supported on Symbian.\n");
03396 #endif
03397 goto free_and_fail;
03398 }
03399 #endif
03400 #if EPOLL_SUPPORT
03401 if ( (0 != (flags & MHD_USE_EPOLL_LINUX_ONLY)) &&
03402 (0 == daemon->worker_pool_size) &&
03403 (0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) )
03404 {
03405 if (0 != (flags & MHD_USE_THREAD_PER_CONNECTION))
03406 {
03407 #if HAVE_MESSAGES
03408 MHD_DLOG (daemon,
03409 "Combining MHD_USE_THREAD_PER_CONNECTION and MHD_USE_EPOLL_LINUX_ONLY is not supported.\n");
03410 #endif
03411 goto free_and_fail;
03412 }
03413 if (MHD_YES != setup_epoll_to_listen (daemon))
03414 goto free_and_fail;
03415 }
03416 #else
03417 if (0 != (flags & MHD_USE_EPOLL_LINUX_ONLY))
03418 {
03419 #if HAVE_MESSAGES
03420 MHD_DLOG (daemon,
03421 "epoll is not supported on this platform by this build.\n");
03422 #endif
03423 goto free_and_fail;
03424 }
03425 #endif
03426 if ( (-1 == daemon->socket_fd) &&
03427 (0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) )
03428 {
03429
03430 if ((flags & MHD_USE_IPv6) != 0)
03431 socket_fd = create_socket (daemon,
03432 PF_INET6, SOCK_STREAM, 0);
03433 else
03434 socket_fd = create_socket (daemon,
03435 PF_INET, SOCK_STREAM, 0);
03436 if (-1 == socket_fd)
03437 {
03438 #if HAVE_MESSAGES
03439 if (0 != (flags & MHD_USE_DEBUG))
03440 MHD_DLOG (daemon,
03441 "Call to socket failed: %s\n",
03442 STRERROR (errno));
03443 #endif
03444 goto free_and_fail;
03445 }
03446 if ( (0 > SETSOCKOPT (socket_fd,
03447 SOL_SOCKET,
03448 SO_REUSEADDR,
03449 &on, sizeof (on))) &&
03450 (0 != (flags & MHD_USE_DEBUG)) )
03451 {
03452 #if HAVE_MESSAGES
03453 MHD_DLOG (daemon,
03454 "setsockopt failed: %s\n",
03455 STRERROR (errno));
03456 #endif
03457 }
03458
03459
03460 #if HAVE_INET6
03461 if (0 != (flags & MHD_USE_IPv6))
03462 addrlen = sizeof (struct sockaddr_in6);
03463 else
03464 #endif
03465 addrlen = sizeof (struct sockaddr_in);
03466 if (NULL == servaddr)
03467 {
03468 #if HAVE_INET6
03469 if (0 != (flags & MHD_USE_IPv6))
03470 {
03471 memset (&servaddr6, 0, sizeof (struct sockaddr_in6));
03472 servaddr6.sin6_family = AF_INET6;
03473 servaddr6.sin6_port = htons (port);
03474 #if HAVE_SOCKADDR_IN_SIN_LEN
03475 servaddr6.sin6_len = sizeof (struct sockaddr_in6);
03476 #endif
03477 servaddr = (struct sockaddr *) &servaddr6;
03478 }
03479 else
03480 #endif
03481 {
03482 memset (&servaddr4, 0, sizeof (struct sockaddr_in));
03483 servaddr4.sin_family = AF_INET;
03484 servaddr4.sin_port = htons (port);
03485 #if HAVE_SOCKADDR_IN_SIN_LEN
03486 servaddr4.sin_len = sizeof (struct sockaddr_in);
03487 #endif
03488 servaddr = (struct sockaddr *) &servaddr4;
03489 }
03490 }
03491 daemon->socket_fd = socket_fd;
03492
03493 if ( (0 != (flags & MHD_USE_IPv6)) &&
03494 (MHD_USE_DUAL_STACK != (flags & MHD_USE_DUAL_STACK)) )
03495 {
03496 #ifdef IPPROTO_IPV6
03497 #ifdef IPV6_V6ONLY
03498
03499
03500
03501
03502 #ifndef WINDOWS
03503 const int on = 1;
03504 #else
03505 const char on = 1;
03506 #endif
03507 if ( (0 > SETSOCKOPT (socket_fd,
03508 IPPROTO_IPV6, IPV6_V6ONLY,
03509 &on, sizeof (on))) &&
03510 (0 != (flags & MHD_USE_DEBUG)) )
03511 {
03512 #if HAVE_MESSAGES
03513 MHD_DLOG (daemon,
03514 "setsockopt failed: %s\n",
03515 STRERROR (errno));
03516 #endif
03517 }
03518 #endif
03519 #endif
03520 }
03521 if (-1 == BIND (socket_fd, servaddr, addrlen))
03522 {
03523 #if HAVE_MESSAGES
03524 if (0 != (flags & MHD_USE_DEBUG))
03525 MHD_DLOG (daemon,
03526 "Failed to bind to port %u: %s\n",
03527 (unsigned int) port,
03528 STRERROR (errno));
03529 #endif
03530 if (0 != CLOSE (socket_fd))
03531 MHD_PANIC ("close failed\n");
03532 goto free_and_fail;
03533 }
03534 #if EPOLL_SUPPORT
03535 if (0 != (flags & MHD_USE_EPOLL_LINUX_ONLY))
03536 {
03537 int sk_flags = fcntl (socket_fd, F_GETFL);
03538 if (0 != fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK))
03539 {
03540 #if HAVE_MESSAGES
03541 MHD_DLOG (daemon,
03542 "Failed to make listen socket non-blocking: %s\n",
03543 STRERROR (errno));
03544 #endif
03545 if (0 != CLOSE (socket_fd))
03546 MHD_PANIC ("close failed\n");
03547 goto free_and_fail;
03548 }
03549 }
03550 #endif
03551 if (LISTEN (socket_fd, 32) < 0)
03552 {
03553 #if HAVE_MESSAGES
03554 if (0 != (flags & MHD_USE_DEBUG))
03555 MHD_DLOG (daemon,
03556 "Failed to listen for connections: %s\n",
03557 STRERROR (errno));
03558 #endif
03559 if (0 != CLOSE (socket_fd))
03560 MHD_PANIC ("close failed\n");
03561 goto free_and_fail;
03562 }
03563 }
03564 else
03565 {
03566 socket_fd = daemon->socket_fd;
03567 }
03568 #ifndef WINDOWS
03569 if ( (socket_fd >= FD_SETSIZE) &&
03570 (0 == (flags & (MHD_USE_POLL | MHD_USE_EPOLL_LINUX_ONLY)) ) )
03571 {
03572 #if HAVE_MESSAGES
03573 if ((flags & MHD_USE_DEBUG) != 0)
03574 MHD_DLOG (daemon,
03575 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
03576 socket_fd,
03577 FD_SETSIZE);
03578 #endif
03579 if (0 != CLOSE (socket_fd))
03580 MHD_PANIC ("close failed\n");
03581 goto free_and_fail;
03582 }
03583 #endif
03584
03585 if (0 != pthread_mutex_init (&daemon->per_ip_connection_mutex, NULL))
03586 {
03587 #if HAVE_MESSAGES
03588 MHD_DLOG (daemon,
03589 "MHD failed to initialize IP connection limit mutex\n");
03590 #endif
03591 if ( (-1 != socket_fd) &&
03592 (0 != CLOSE (socket_fd)) )
03593 MHD_PANIC ("close failed\n");
03594 goto free_and_fail;
03595 }
03596 if (0 != pthread_mutex_init (&daemon->cleanup_connection_mutex, NULL))
03597 {
03598 #if HAVE_MESSAGES
03599 MHD_DLOG (daemon,
03600 "MHD failed to initialize IP connection limit mutex\n");
03601 #endif
03602 pthread_mutex_destroy (&daemon->cleanup_connection_mutex);
03603 if ( (-1 != socket_fd) &&
03604 (0 != CLOSE (socket_fd)) )
03605 MHD_PANIC ("close failed\n");
03606 goto free_and_fail;
03607 }
03608
03609 #if HTTPS_SUPPORT
03610
03611 if ((0 != (flags & MHD_USE_SSL)) && (0 != MHD_TLS_init (daemon)))
03612 {
03613 #if HAVE_MESSAGES
03614 MHD_DLOG (daemon,
03615 "Failed to initialize TLS support\n");
03616 #endif
03617 if ( (-1 != socket_fd) &&
03618 (0 != CLOSE (socket_fd)) )
03619 MHD_PANIC ("close failed\n");
03620 pthread_mutex_destroy (&daemon->cleanup_connection_mutex);
03621 pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
03622 goto free_and_fail;
03623 }
03624 #endif
03625 if ( ( (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) ||
03626 ( (0 != (flags & MHD_USE_SELECT_INTERNALLY)) &&
03627 (0 == daemon->worker_pool_size)) ) &&
03628 (0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) &&
03629 (0 != (res_thread_create =
03630 create_thread (&daemon->pid, daemon, &MHD_select_thread, daemon))))
03631 {
03632 #if HAVE_MESSAGES
03633 MHD_DLOG (daemon,
03634 "Failed to create listen thread: %s\n",
03635 STRERROR (res_thread_create));
03636 #endif
03637 pthread_mutex_destroy (&daemon->cleanup_connection_mutex);
03638 pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
03639 if ( (-1 != socket_fd) &&
03640 (0 != CLOSE (socket_fd)) )
03641 MHD_PANIC ("close failed\n");
03642 goto free_and_fail;
03643 }
03644 if ( (daemon->worker_pool_size > 0) &&
03645 (0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) )
03646 {
03647 #ifndef MINGW
03648 int sk_flags;
03649 #else
03650 unsigned long sk_flags;
03651 #endif
03652
03653
03654
03655
03656 unsigned int conns_per_thread = daemon->max_connections
03657 / daemon->worker_pool_size;
03658 unsigned int leftover_conns = daemon->max_connections
03659 % daemon->worker_pool_size;
03660
03661 i = 0;
03662
03663
03664
03665
03666 #ifndef MINGW
03667 sk_flags = fcntl (socket_fd, F_GETFL);
03668 if (sk_flags < 0)
03669 goto thread_failed;
03670 if (0 != fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK))
03671 goto thread_failed;
03672 #else
03673 sk_flags = 1;
03674 #if HAVE_PLIBC_FD
03675 if (SOCKET_ERROR ==
03676 ioctlsocket (plibc_fd_get_handle (socket_fd), FIONBIO, &sk_flags))
03677 goto thread_failed;
03678 #else
03679 if (ioctlsocket (socket_fd, FIONBIO, &sk_flags) == SOCKET_ERROR)
03680 goto thread_failed;
03681 #endif // PLIBC_FD
03682 #endif // MINGW
03683
03684
03685 daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
03686 * daemon->worker_pool_size);
03687 if (NULL == daemon->worker_pool)
03688 goto thread_failed;
03689
03690
03691 for (i = 0; i < daemon->worker_pool_size; ++i)
03692 {
03693
03694 struct MHD_Daemon *d = &daemon->worker_pool[i];
03695
03696 memcpy (d, daemon, sizeof (struct MHD_Daemon));
03697
03698
03699
03700 d->master = daemon;
03701 d->worker_pool_size = 0;
03702 d->worker_pool = NULL;
03703
03704 if ( (MHD_USE_SUSPEND_RESUME == (flags & MHD_USE_SUSPEND_RESUME)) &&
03705 #ifdef WINDOWS
03706 (0 != SOCKETPAIR (AF_INET, SOCK_STREAM, IPPROTO_TCP, d->wpipe))
03707 #else
03708 (0 != PIPE (d->wpipe))
03709 #endif
03710 )
03711 {
03712 #if HAVE_MESSAGES
03713 MHD_DLOG (daemon,
03714 "Failed to create worker control pipe: %s\n",
03715 STRERROR (errno));
03716 #endif
03717 goto thread_failed;
03718 }
03719 #ifndef WINDOWS
03720 if ( (0 == (flags & MHD_USE_POLL)) &&
03721 (MHD_USE_SUSPEND_RESUME == (flags & MHD_USE_SUSPEND_RESUME)) &&
03722 (d->wpipe[0] >= FD_SETSIZE) )
03723 {
03724 #if HAVE_MESSAGES
03725 MHD_DLOG (daemon,
03726 "file descriptor for worker control pipe exceeds maximum value\n");
03727 #endif
03728 if (0 != CLOSE (d->wpipe[0]))
03729 MHD_PANIC ("close failed\n");
03730 if (0 != CLOSE (d->wpipe[1]))
03731 MHD_PANIC ("close failed\n");
03732 goto thread_failed;
03733 }
03734 #endif
03735
03736
03737
03738
03739 d->max_connections = conns_per_thread;
03740 if (i < leftover_conns)
03741 ++d->max_connections;
03742 #if EPOLL_SUPPORT
03743 if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) &&
03744 (MHD_YES != setup_epoll_to_listen (d)) )
03745 goto thread_failed;
03746 #endif
03747
03748 if (0 != pthread_mutex_init (&d->cleanup_connection_mutex, NULL))
03749 {
03750 #if HAVE_MESSAGES
03751 MHD_DLOG (daemon,
03752 "MHD failed to initialize cleanup connection mutex for thread worker %d\n", i);
03753 #endif
03754 goto thread_failed;
03755 }
03756
03757
03758 if (0 != (res_thread_create =
03759 create_thread (&d->pid, daemon, &MHD_select_thread, d)))
03760 {
03761 #if HAVE_MESSAGES
03762 MHD_DLOG (daemon,
03763 "Failed to create pool thread: %s\n",
03764 STRERROR (res_thread_create));
03765 #endif
03766
03767
03768 pthread_mutex_destroy (&d->cleanup_connection_mutex);
03769 goto thread_failed;
03770 }
03771 }
03772 }
03773 return daemon;
03774
03775 thread_failed:
03776
03777
03778
03779
03780 if (0 == i)
03781 {
03782 if ( (-1 != socket_fd) &&
03783 (0 != CLOSE (socket_fd)) )
03784 MHD_PANIC ("close failed\n");
03785 pthread_mutex_destroy (&daemon->cleanup_connection_mutex);
03786 pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
03787 if (NULL != daemon->worker_pool)
03788 free (daemon->worker_pool);
03789 goto free_and_fail;
03790 }
03791
03792
03793
03794
03795
03796 daemon->worker_pool_size = i - 1;
03797 MHD_stop_daemon (daemon);
03798 return NULL;
03799
03800 free_and_fail:
03801
03802
03803 #if EPOLL_SUPPORT
03804 if (-1 != daemon->epoll_fd)
03805 close (daemon->epoll_fd);
03806 #endif
03807 #ifdef DAUTH_SUPPORT
03808 free (daemon->nnc);
03809 pthread_mutex_destroy (&daemon->nnc_lock);
03810 #endif
03811 #if HTTPS_SUPPORT
03812 if (0 != (flags & MHD_USE_SSL))
03813 gnutls_priority_deinit (daemon->priority_cache);
03814 #endif
03815 free (daemon);
03816 return NULL;
03817 }
03818
03819
03826 static void
03827 close_connection (struct MHD_Connection *pos)
03828 {
03829 struct MHD_Daemon *daemon = pos->daemon;
03830
03831 MHD_connection_close (pos,
03832 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
03833 if (pos->connection_timeout == pos->daemon->connection_timeout)
03834 XDLL_remove (daemon->normal_timeout_head,
03835 daemon->normal_timeout_tail,
03836 pos);
03837 else
03838 XDLL_remove (daemon->manual_timeout_head,
03839 daemon->manual_timeout_tail,
03840 pos);
03841 DLL_remove (daemon->connections_head,
03842 daemon->connections_tail,
03843 pos);
03844 pos->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
03845 DLL_insert (daemon->cleanup_head,
03846 daemon->cleanup_tail,
03847 pos);
03848 }
03849
03850
03858 static void
03859 close_all_connections (struct MHD_Daemon *daemon)
03860 {
03861 struct MHD_Connection *pos;
03862 void *unused;
03863 int rc;
03864
03865
03866
03867 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
03868 (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
03869 MHD_PANIC ("Failed to acquire cleanup mutex\n");
03870 for (pos = daemon->connections_head; NULL != pos; pos = pos->nextX)
03871 SHUTDOWN (pos->socket_fd,
03872 (pos->read_closed == MHD_YES) ? SHUT_WR : SHUT_RDWR);
03873 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
03874 (0 != pthread_mutex_unlock (&daemon->cleanup_connection_mutex)) )
03875 MHD_PANIC ("Failed to release cleanup mutex\n");
03876
03877
03878 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
03879 {
03880 while (NULL != (pos = daemon->connections_head))
03881 {
03882 if (0 != (rc = pthread_join (pos->pid, &unused)))
03883 MHD_PANIC ("Failed to join a thread\n");
03884 pos->thread_joined = MHD_YES;
03885 }
03886 }
03887
03888
03889 while (NULL != (pos = daemon->connections_head))
03890 close_connection (pos);
03891 MHD_cleanup_connections (daemon);
03892 }
03893
03894
03895 #if EPOLL_SUPPORT
03896
03901 static void
03902 epoll_shutdown (struct MHD_Daemon *daemon)
03903 {
03904 struct epoll_event event;
03905
03906 if (-1 == daemon->wpipe[1])
03907 {
03908
03909 MHD_PANIC ("Internal error\n");
03910 }
03911 event.events = EPOLLOUT;
03912 event.data.ptr = NULL;
03913 if (0 != epoll_ctl (daemon->epoll_fd,
03914 EPOLL_CTL_ADD,
03915 daemon->wpipe[1],
03916 &event))
03917 MHD_PANIC ("Failed to add wpipe to epoll set to signal termination\n");
03918 }
03919 #endif
03920
03921
03928 void
03929 MHD_stop_daemon (struct MHD_Daemon *daemon)
03930 {
03931 void *unused;
03932 int fd;
03933 unsigned int i;
03934 int rc;
03935
03936 if (NULL == daemon)
03937 return;
03938 daemon->shutdown = MHD_YES;
03939 fd = daemon->socket_fd;
03940 daemon->socket_fd = -1;
03941
03942 if (NULL != daemon->worker_pool)
03943 {
03944
03945 for (i = 0; i < daemon->worker_pool_size; ++i)
03946 {
03947 daemon->worker_pool[i].shutdown = MHD_YES;
03948 daemon->worker_pool[i].socket_fd = -1;
03949 #if EPOLL_SUPPORT
03950 if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) &&
03951 (-1 != daemon->worker_pool[i].epoll_fd) &&
03952 (-1 == fd) )
03953 epoll_shutdown (&daemon->worker_pool[i]);
03954 #endif
03955 }
03956 }
03957 if (-1 != daemon->wpipe[1])
03958 {
03959 if (1 != WRITE (daemon->wpipe[1], "e", 1))
03960 MHD_PANIC ("failed to signal shutdown via pipe");
03961 }
03962 #ifdef HAVE_LISTEN_SHUTDOWN
03963 else
03964 {
03965
03966 if (-1 != fd)
03967 (void) SHUTDOWN (fd, SHUT_RDWR);
03968 }
03969 #endif
03970 #if EPOLL_SUPPORT
03971 if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) &&
03972 (-1 != daemon->epoll_fd) &&
03973 (-1 == fd) )
03974 epoll_shutdown (daemon);
03975 #endif
03976
03977 #if DEBUG_CLOSE
03978 #if HAVE_MESSAGES
03979 MHD_DLOG (daemon, "MHD listen socket shutdown\n");
03980 #endif
03981 #endif
03982
03983
03984
03985 if (NULL != daemon->worker_pool)
03986 {
03987
03988 for (i = 0; i < daemon->worker_pool_size; ++i)
03989 {
03990 if (-1 != daemon->worker_pool[i].wpipe[1])
03991 {
03992 if (1 != WRITE (daemon->worker_pool[i].wpipe[1], "e", 1))
03993 MHD_PANIC ("failed to signal shutdown via pipe");
03994 }
03995 if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused)))
03996 MHD_PANIC ("Failed to join a thread\n");
03997 close_all_connections (&daemon->worker_pool[i]);
03998 pthread_mutex_destroy (&daemon->worker_pool[i].cleanup_connection_mutex);
03999 #if EPOLL_SUPPORT
04000 if ( (-1 != daemon->worker_pool[i].epoll_fd) &&
04001 (0 != CLOSE (daemon->worker_pool[i].epoll_fd)) )
04002 MHD_PANIC ("close failed\n");
04003 #endif
04004 if ( (MHD_USE_SUSPEND_RESUME == (daemon->options & MHD_USE_SUSPEND_RESUME)) )
04005 {
04006 if (-1 != daemon->worker_pool[i].wpipe[1])
04007 {
04008 if (0 != CLOSE (daemon->worker_pool[i].wpipe[0]))
04009 MHD_PANIC ("close failed\n");
04010 if (0 != CLOSE (daemon->worker_pool[i].wpipe[1]))
04011 MHD_PANIC ("close failed\n");
04012 }
04013 }
04014 }
04015 free (daemon->worker_pool);
04016 }
04017 else
04018 {
04019
04020 if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
04021 ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))
04022 && (0 == daemon->worker_pool_size)))
04023 {
04024 if (0 != (rc = pthread_join (daemon->pid, &unused)))
04025 {
04026 MHD_PANIC ("Failed to join a thread\n");
04027 }
04028 }
04029 }
04030 close_all_connections (daemon);
04031 if ( (-1 != fd) &&
04032 (0 != CLOSE (fd)) )
04033 MHD_PANIC ("close failed\n");
04034
04035
04036 #if HTTPS_SUPPORT
04037 if (0 != (daemon->options & MHD_USE_SSL))
04038 {
04039 gnutls_priority_deinit (daemon->priority_cache);
04040 if (daemon->x509_cred)
04041 gnutls_certificate_free_credentials (daemon->x509_cred);
04042 }
04043 #endif
04044 #if EPOLL_SUPPORT
04045 if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) &&
04046 (-1 != daemon->epoll_fd) &&
04047 (0 != CLOSE (daemon->epoll_fd)) )
04048 MHD_PANIC ("close failed\n");
04049 #endif
04050
04051 #ifdef DAUTH_SUPPORT
04052 free (daemon->nnc);
04053 pthread_mutex_destroy (&daemon->nnc_lock);
04054 #endif
04055 pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
04056 pthread_mutex_destroy (&daemon->cleanup_connection_mutex);
04057
04058 if (-1 != daemon->wpipe[1])
04059 {
04060 if (0 != CLOSE (daemon->wpipe[0]))
04061 MHD_PANIC ("close failed\n");
04062 if (0 != CLOSE (daemon->wpipe[1]))
04063 MHD_PANIC ("close failed\n");
04064 }
04065 free (daemon);
04066 }
04067
04068
04080 const union MHD_DaemonInfo *
04081 MHD_get_daemon_info (struct MHD_Daemon *daemon,
04082 enum MHD_DaemonInfoType info_type,
04083 ...)
04084 {
04085 switch (info_type)
04086 {
04087 case MHD_DAEMON_INFO_KEY_SIZE:
04088 return NULL;
04089 case MHD_DAEMON_INFO_MAC_KEY_SIZE:
04090 return NULL;
04091 case MHD_DAEMON_INFO_LISTEN_FD:
04092 return (const union MHD_DaemonInfo *) &daemon->socket_fd;
04093 #if EPOLL_SUPPORT
04094 case MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY:
04095 return (const union MHD_DaemonInfo *) &daemon->epoll_fd;
04096 #endif
04097 default:
04098 return NULL;
04099 };
04100 }
04101
04102
04119 void
04120 MHD_set_panic_func (MHD_PanicCallback cb, void *cls)
04121 {
04122 mhd_panic = cb;
04123 mhd_panic_cls = cls;
04124 }
04125
04126
04133 const char *
04134 MHD_get_version (void)
04135 {
04136 return PACKAGE_VERSION;
04137 }
04138
04139
04140 #ifdef __GNUC__
04141 #define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor))
04142 #define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor))
04143 #else // !__GNUC__
04144 #define ATTRIBUTE_CONSTRUCTOR
04145 #define ATTRIBUTE_DESTRUCTOR
04146 #endif // __GNUC__
04147
04148 #if HTTPS_SUPPORT
04149 #if GCRYPT_VERSION_NUMBER < 0x010600
04150 GCRY_THREAD_OPTION_PTHREAD_IMPL;
04151 #endif
04152 #endif
04153
04154
04158 void ATTRIBUTE_CONSTRUCTOR
04159 MHD_init ()
04160 {
04161 mhd_panic = &mhd_panic_std;
04162 mhd_panic_cls = NULL;
04163
04164 #ifdef WINDOWS
04165 plibc_init ("GNU", "libmicrohttpd");
04166 #endif
04167 #if HTTPS_SUPPORT
04168 #if GCRYPT_VERSION_NUMBER < 0x010600
04169 gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
04170 #endif
04171 gcry_check_version (NULL);
04172 gnutls_global_init ();
04173 #endif
04174 }
04175
04176
04177 void ATTRIBUTE_DESTRUCTOR
04178 MHD_fini ()
04179 {
04180 #if HTTPS_SUPPORT
04181 gnutls_global_deinit ();
04182 #endif
04183 #ifdef WINDOWS
04184 plibc_shutdown ();
04185 #endif
04186 }
04187
04188
04189