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
00033 #if HTTPS_SUPPORT
00034 #include "connection_https.h"
00035 #include "gnutls_int.h"
00036 #include "gnutls_global.h"
00037 #endif
00038
00039 #ifdef HAVE_POLL_H
00040 #include <poll.h>
00041 #endif
00042
00046 #ifndef WINDOWS
00047 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE -4
00048 #else
00049 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE
00050 #endif
00051
00055 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
00056
00061 #define DEBUG_CLOSE MHD_NO
00062
00067 #define DEBUG_CONNECT MHD_NO
00068
00069 #ifndef LINUX
00070 #ifndef MSG_NOSIGNAL
00071 #define MSG_NOSIGNAL 0
00072 #endif
00073 #ifndef MSG_DONTWAIT
00074 #define MSG_DONTWAIT 0
00075 #endif
00076 #endif
00077
00078 #ifdef __SYMBIAN32__
00079 static void pthread_kill (int, int) {
00080
00081
00082 abort();
00083 }
00084 #endif // __SYMBIAN32__
00085
00089 static void
00090 mhd_panic_std(void *cls,
00091 const char *file,
00092 unsigned int line,
00093 const char *reason)
00094 {
00095 abort ();
00096 }
00097
00098
00102 MHD_PanicCallback mhd_panic;
00103
00107 void *mhd_panic_cls;
00108
00113 static struct MHD_Daemon*
00114 MHD_get_master (struct MHD_Daemon *daemon)
00115 {
00116 while (NULL != daemon->master)
00117 daemon = daemon->master;
00118 return daemon;
00119 }
00120
00124 struct MHD_IPCount
00125 {
00126 int family;
00127 union
00128 {
00129 struct in_addr ipv4;
00130 #if HAVE_IPV6
00131 struct in6_addr ipv6;
00132 #endif
00133 } addr;
00134 unsigned int count;
00135 };
00136
00140 static void
00141 MHD_ip_count_lock(struct MHD_Daemon *daemon)
00142 {
00143 if (0 != pthread_mutex_lock(&daemon->per_ip_connection_mutex))
00144 {
00145 #if HAVE_MESSAGES
00146 MHD_DLOG (daemon, "Failed to acquire IP connection limit mutex\n");
00147 #endif
00148 abort();
00149 }
00150 }
00151
00155 static void
00156 MHD_ip_count_unlock(struct MHD_Daemon *daemon)
00157 {
00158 if (0 != pthread_mutex_unlock(&daemon->per_ip_connection_mutex))
00159 {
00160 #if HAVE_MESSAGES
00161 MHD_DLOG (daemon, "Failed to release IP connection limit mutex\n");
00162 #endif
00163 abort();
00164 }
00165 }
00166
00172 static int
00173 MHD_ip_addr_compare(const void *a1, const void *a2)
00174 {
00175 return memcmp (a1, a2, offsetof(struct MHD_IPCount, count));
00176 }
00177
00182 static int
00183 MHD_ip_addr_to_key(struct sockaddr *addr, socklen_t addrlen,
00184 struct MHD_IPCount *key)
00185 {
00186 memset(key, 0, sizeof(*key));
00187
00188
00189 if (addrlen == sizeof(struct sockaddr_in))
00190 {
00191 const struct sockaddr_in *addr4 = (const struct sockaddr_in*)addr;
00192 key->family = AF_INET;
00193 memcpy (&key->addr.ipv4, &addr4->sin_addr, sizeof(addr4->sin_addr));
00194 return MHD_YES;
00195 }
00196
00197 #if HAVE_IPV6
00198
00199 if (addrlen == sizeof (struct sockaddr_in6))
00200 {
00201 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)addr;
00202 key->family = AF_INET6;
00203 memcpy (&key->addr.ipv6, &addr6->sin6_addr, sizeof(addr6->sin6_addr));
00204 return MHD_YES;
00205 }
00206 #endif
00207
00208
00209 return MHD_NO;
00210 }
00211
00218 static int
00219 MHD_ip_limit_add(struct MHD_Daemon *daemon,
00220 struct sockaddr *addr, socklen_t addrlen)
00221 {
00222 struct MHD_IPCount *key;
00223 void *node;
00224 int result;
00225
00226 daemon = MHD_get_master (daemon);
00227
00228
00229 if (daemon->per_ip_connection_limit == 0)
00230 return MHD_YES;
00231
00232 key = malloc (sizeof(*key));
00233 if (NULL == key)
00234 return MHD_NO;
00235
00236
00237 if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, key))
00238 {
00239
00240 free (key);
00241 return MHD_YES;
00242 }
00243
00244 MHD_ip_count_lock (daemon);
00245
00246
00247 node = (void*)TSEARCH (key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
00248 if (!node)
00249 {
00250 #if HAVE_MESSAGES
00251 MHD_DLOG(daemon,
00252 "Failed to add IP connection count node\n");
00253 #endif
00254 MHD_ip_count_unlock (daemon);
00255 return MHD_NO;
00256 }
00257 node = *(void**)node;
00258
00259
00260 if (node != key)
00261 free(key);
00262 key = (struct MHD_IPCount*)node;
00263
00264
00265
00266 result = (key->count < daemon->per_ip_connection_limit);
00267 if (result == MHD_YES)
00268 ++key->count;
00269
00270 MHD_ip_count_unlock (daemon);
00271 return result;
00272 }
00273
00278 static void
00279 MHD_ip_limit_del(struct MHD_Daemon *daemon,
00280 struct sockaddr *addr, socklen_t addrlen)
00281 {
00282 struct MHD_IPCount search_key;
00283 struct MHD_IPCount *found_key;
00284 void *node;
00285
00286 daemon = MHD_get_master (daemon);
00287
00288
00289 if (daemon->per_ip_connection_limit == 0)
00290 return;
00291
00292
00293 if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, &search_key))
00294 return;
00295
00296 MHD_ip_count_lock (daemon);
00297
00298
00299 node = (void*)TFIND (&search_key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
00300
00301
00302
00303 if (!node)
00304 {
00305 #if HAVE_MESSAGES
00306 MHD_DLOG (daemon,
00307 "Failed to find previously-added IP address\n");
00308 #endif
00309 abort();
00310 }
00311 found_key = (struct MHD_IPCount*)*(void**)node;
00312
00313
00314 if (found_key->count == 0)
00315 {
00316 #if HAVE_MESSAGES
00317 MHD_DLOG (daemon,
00318 "Previously-added IP address had 0 count\n");
00319 #endif
00320 abort();
00321 }
00322
00323
00324 if (--found_key->count == 0)
00325 {
00326 TDELETE (found_key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
00327 free (found_key);
00328 }
00329
00330 MHD_ip_count_unlock (daemon);
00331 }
00332
00333 #if HTTPS_SUPPORT
00334 pthread_mutex_t MHD_gnutls_init_mutex;
00335
00341 static int
00342 _set_priority (MHD_gtls_priority_st * st, const int *list)
00343 {
00344 int num = 0;
00345
00346 while ((list[num] != 0) && (num < MAX_ALGOS))
00347 num++;
00348 st->num_algorithms = num;
00349 memcpy (st->priority, list, num * sizeof (int));
00350 return 0;
00351 }
00352
00353
00362 static ssize_t
00363 recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i)
00364 {
00365 return MHD__gnutls_record_recv (connection->tls_session, other, i);
00366 }
00367
00376 static ssize_t
00377 send_tls_adapter (struct MHD_Connection *connection,
00378 const void *other, size_t i)
00379 {
00380 return MHD__gnutls_record_send (connection->tls_session, other, i);
00381 }
00382
00383
00389 static int
00390 MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
00391 {
00392 MHD_gnutls_datum_t key;
00393 MHD_gnutls_datum_t cert;
00394
00395
00396 if (daemon->https_mem_cert && daemon->https_mem_key)
00397 {
00398 key.data = (unsigned char *) daemon->https_mem_key;
00399 key.size = strlen (daemon->https_mem_key);
00400 cert.data = (unsigned char *) daemon->https_mem_cert;
00401 cert.size = strlen (daemon->https_mem_cert);
00402
00403 return MHD__gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
00404 &cert, &key,
00405 GNUTLS_X509_FMT_PEM);
00406 }
00407 #if HAVE_MESSAGES
00408 MHD_DLOG (daemon, "You need to specify a certificate and key location\n");
00409 #endif
00410 return -1;
00411 }
00412
00418 static int
00419 MHD_TLS_init (struct MHD_Daemon *daemon)
00420 {
00421 switch (daemon->cred_type)
00422 {
00423 case MHD_GNUTLS_CRD_CERTIFICATE:
00424 if (0 !=
00425 MHD__gnutls_certificate_allocate_credentials (&daemon->x509_cred))
00426 return GNUTLS_E_MEMORY_ERROR;
00427 return MHD_init_daemon_certificate (daemon);
00428 default:
00429 #if HAVE_MESSAGES
00430 MHD_DLOG (daemon,
00431 "Error: invalid credentials type %d specified.\n",
00432 daemon->cred_type);
00433 #endif
00434 return -1;
00435 }
00436 }
00437 #endif
00438
00446 int
00447 MHD_get_fdset (struct MHD_Daemon *daemon,
00448 fd_set * read_fd_set,
00449 fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd)
00450 {
00451 struct MHD_Connection *con_itr;
00452 int fd;
00453
00454 if ((daemon == NULL) || (read_fd_set == NULL) || (write_fd_set == NULL)
00455 || (except_fd_set == NULL) || (max_fd == NULL)
00456 || (-1 == (fd = daemon->socket_fd)) || (daemon->shutdown == MHD_YES)
00457 || ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0)
00458 || ((daemon->options & MHD_USE_POLL) != 0))
00459 return MHD_NO;
00460
00461 FD_SET (fd, read_fd_set);
00462
00463 if ((*max_fd) < fd)
00464 *max_fd = fd;
00465
00466 con_itr = daemon->connections;
00467 while (con_itr != NULL)
00468 {
00469 if (MHD_YES != MHD_connection_get_fdset (con_itr,
00470 read_fd_set,
00471 write_fd_set,
00472 except_fd_set, max_fd))
00473 return MHD_NO;
00474 con_itr = con_itr->next;
00475 }
00476 #if DEBUG_CONNECT
00477 MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
00478 #endif
00479 return MHD_YES;
00480 }
00481
00486 static void *
00487 MHD_handle_connection (void *data)
00488 {
00489 struct MHD_Connection *con = data;
00490 int num_ready;
00491 fd_set rs;
00492 fd_set ws;
00493 fd_set es;
00494 int max;
00495 struct timeval tv;
00496 unsigned int timeout;
00497 time_t now;
00498 #ifdef HAVE_POLL_H
00499 struct MHD_Pollfd mp;
00500 struct pollfd p;
00501 #endif
00502
00503 timeout = con->daemon->connection_timeout;
00504 while ((!con->daemon->shutdown) && (con->socket_fd != -1)) {
00505 now = time (NULL);
00506 tv.tv_usec = 0;
00507 if ( (timeout > (now - con->last_activity)) ||
00508 (timeout == 0) )
00509 {
00510
00511
00512 tv.tv_sec = 1;
00513 if ((con->state == MHD_CONNECTION_NORMAL_BODY_UNREADY) ||
00514 (con->state == MHD_CONNECTION_CHUNKED_BODY_UNREADY))
00515 {
00516
00517 tv.tv_sec = 0;
00518 }
00519 }
00520 else
00521 {
00522 tv.tv_sec = 0;
00523 }
00524 #ifdef HAVE_POLL_H
00525 if (0 == (con->daemon->options & MHD_USE_POLL)) {
00526 #else
00527 {
00528 #endif
00529
00530 FD_ZERO (&rs);
00531 FD_ZERO (&ws);
00532 FD_ZERO (&es);
00533 max = 0;
00534 MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
00535 num_ready = SELECT (max + 1, &rs, &ws, &es, &tv);
00536 if (num_ready < 0) {
00537 if (errno == EINTR)
00538 continue;
00539 #if HAVE_MESSAGES
00540 MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n", max,
00541 STRERROR (errno));
00542 #endif
00543 break;
00544 }
00545
00546 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &rs)))
00547 con->read_handler (con);
00548 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
00549 con->write_handler (con);
00550 if (con->socket_fd != -1)
00551 con->idle_handler (con);
00552 }
00553 #ifdef HAVE_POLL_H
00554 else
00555 {
00556
00557 memset(&mp, 0, sizeof (struct MHD_Pollfd));
00558 MHD_connection_get_pollfd(con, &mp);
00559 memset(&p, 0, sizeof (struct pollfd));
00560 p.fd = mp.fd;
00561 if (mp.events & MHD_POLL_ACTION_IN)
00562 p.events |= POLLIN;
00563 if (mp.events & MHD_POLL_ACTION_OUT)
00564 p.events |= POLLOUT;
00565
00566
00567 if (poll (&p, 1, 1000) < 0) {
00568 if (errno == EINTR)
00569 continue;
00570 #if HAVE_MESSAGES
00571 MHD_DLOG (con->daemon, "Error during poll: `%s'\n",
00572 STRERROR (errno));
00573 #endif
00574 break;
00575 }
00576 if ( (con->socket_fd != -1) &&
00577 (0 != (p.revents & POLLIN)) )
00578 con->read_handler (con);
00579 if ( (con->socket_fd != -1) &&
00580 (0 != (p.revents & POLLOUT)) )
00581 con->write_handler (con);
00582 if (con->socket_fd != -1)
00583 con->idle_handler (con);
00584 if ( (con->socket_fd != -1) &&
00585 (0 != (p.revents & (POLLERR | POLLHUP))) )
00586 MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR);
00587 }
00588 #endif
00589 }
00590 if (con->socket_fd != -1)
00591 {
00592 #if DEBUG_CLOSE
00593 #if HAVE_MESSAGES
00594 MHD_DLOG (con->daemon,
00595 "Processing thread terminating, closing connection\n");
00596 #endif
00597 #endif
00598 MHD_connection_close (con, MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
00599 }
00600 return NULL;
00601 }
00602
00611 static ssize_t
00612 recv_param_adapter (struct MHD_Connection *connection, void *other, size_t i)
00613 {
00614 if (connection->socket_fd == -1)
00615 return -1;
00616 if (0 != (connection->daemon->options & MHD_USE_SSL))
00617 return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
00618 else
00619 return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT);
00620 }
00621
00630 static ssize_t
00631 send_param_adapter (struct MHD_Connection *connection,
00632 const void *other, size_t i)
00633 {
00634 if (connection->socket_fd == -1)
00635 return -1;
00636 if (0 != (connection->daemon->options & MHD_USE_SSL))
00637 return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
00638 else
00639 return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT);
00640 }
00641
00647 static int
00648 MHD_accept_connection (struct MHD_Daemon *daemon)
00649 {
00650 struct MHD_Connection *connection;
00651 #if HAVE_INET6
00652 struct sockaddr_in6 addrstorage;
00653 #else
00654 struct sockaddr_in addrstorage;
00655 #endif
00656 struct sockaddr *addr = (struct sockaddr *) &addrstorage;
00657 socklen_t addrlen;
00658 int s;
00659 int res_thread_create;
00660 #if OSX
00661 static int on = 1;
00662 #endif
00663
00664 addrlen = sizeof (addrstorage);
00665 memset (addr, 0, sizeof (addrstorage));
00666
00667 s = ACCEPT (daemon->socket_fd, addr, &addrlen);
00668 if ((s == -1) || (addrlen <= 0))
00669 {
00670 #if HAVE_MESSAGES
00671
00672 if ((EAGAIN != errno) && (EWOULDBLOCK != errno))
00673 MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));
00674 #endif
00675 if (s != -1)
00676 {
00677 SHUTDOWN (s, SHUT_RDWR);
00678 CLOSE (s);
00679
00680 }
00681 return MHD_NO;
00682 }
00683 #ifndef WINDOWS
00684 if ( (s >= FD_SETSIZE) &&
00685 (0 == (daemon->options & MHD_USE_POLL)) )
00686 {
00687 #if HAVE_MESSAGES
00688 MHD_DLOG (daemon,
00689 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
00690 s,
00691 FD_SETSIZE);
00692 #endif
00693 CLOSE (s);
00694 return MHD_NO;
00695 }
00696 #endif
00697
00698
00699 #if HAVE_MESSAGES
00700 #if DEBUG_CONNECT
00701 MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
00702 #endif
00703 #endif
00704 if ((daemon->max_connections == 0)
00705 || (MHD_ip_limit_add (daemon, addr, addrlen) == MHD_NO))
00706 {
00707
00708 #if HAVE_MESSAGES
00709 MHD_DLOG (daemon,
00710 "Server reached connection limit (closing inbound connection)\n");
00711 #endif
00712 SHUTDOWN (s, SHUT_RDWR);
00713 CLOSE (s);
00714 return MHD_NO;
00715 }
00716
00717
00718 if ((daemon->apc != NULL)
00719 && (MHD_NO == daemon->apc (daemon->apc_cls, addr, addrlen)))
00720 {
00721 #if DEBUG_CLOSE
00722 #if HAVE_MESSAGES
00723 MHD_DLOG (daemon, "Connection rejected, closing connection\n");
00724 #endif
00725 #endif
00726 SHUTDOWN (s, SHUT_RDWR);
00727 CLOSE (s);
00728 MHD_ip_limit_del (daemon, addr, addrlen);
00729 return MHD_YES;
00730 }
00731 #if OSX
00732 #ifdef SOL_SOCKET
00733 #ifdef SO_NOSIGPIPE
00734 setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof (on));
00735 #endif
00736 #endif
00737 #endif
00738 connection = malloc (sizeof (struct MHD_Connection));
00739 if (NULL == connection)
00740 {
00741 #if HAVE_MESSAGES
00742 MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00743 #endif
00744 SHUTDOWN (s, SHUT_RDWR);
00745 CLOSE (s);
00746 MHD_ip_limit_del (daemon, addr, addrlen);
00747 return MHD_NO;
00748 }
00749 memset (connection, 0, sizeof (struct MHD_Connection));
00750 connection->pool = NULL;
00751 connection->addr = malloc (addrlen);
00752 if (connection->addr == NULL)
00753 {
00754 #if HAVE_MESSAGES
00755 MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00756 #endif
00757 SHUTDOWN (s, SHUT_RDWR);
00758 CLOSE (s);
00759 MHD_ip_limit_del (daemon, addr, addrlen);
00760 free (connection);
00761 return MHD_NO;
00762 }
00763 memcpy (connection->addr, addr, addrlen);
00764 connection->addr_len = addrlen;
00765 connection->socket_fd = s;
00766 connection->daemon = daemon;
00767 connection->last_activity = time (NULL);
00768
00769
00770 MHD_set_http_calbacks (connection);
00771 connection->recv_cls = &recv_param_adapter;
00772 connection->send_cls = &send_param_adapter;
00773 #if HTTPS_SUPPORT
00774 if (0 != (daemon->options & MHD_USE_SSL))
00775 {
00776 connection->recv_cls = &recv_tls_adapter;
00777 connection->send_cls = &send_tls_adapter;
00778 connection->state = MHD_TLS_CONNECTION_INIT;
00779 MHD_set_https_calbacks (connection);
00780 MHD__gnutls_init (&connection->tls_session, GNUTLS_SERVER);
00781 MHD__gnutls_priority_set (connection->tls_session,
00782 connection->daemon->priority_cache);
00783 switch (connection->daemon->cred_type)
00784 {
00785
00786 case MHD_GNUTLS_CRD_CERTIFICATE:
00787 MHD__gnutls_credentials_set (connection->tls_session,
00788 MHD_GNUTLS_CRD_CERTIFICATE,
00789 connection->daemon->x509_cred);
00790 break;
00791 default:
00792 #if HAVE_MESSAGES
00793 MHD_DLOG (connection->daemon,
00794 "Failed to setup TLS credentials: unknown credential type %d\n",
00795 connection->daemon->cred_type);
00796 #endif
00797 SHUTDOWN (s, SHUT_RDWR);
00798 CLOSE (s);
00799 MHD_ip_limit_del (daemon, addr, addrlen);
00800 free (connection->addr);
00801 free (connection);
00802 mhd_panic (mhd_panic_cls, __FILE__, __LINE__,
00803 #if HAVE_MESSAGES
00804 "Unknown credential type"
00805 #else
00806 NULL
00807 #endif
00808 );
00809 return MHD_NO;
00810 }
00811 MHD__gnutls_transport_set_ptr (connection->tls_session,
00812 (MHD_gnutls_transport_ptr_t) connection);
00813 MHD__gnutls_transport_set_pull_function (connection->tls_session,
00814 (MHD_gtls_pull_func) &
00815 recv_param_adapter);
00816 MHD__gnutls_transport_set_push_function (connection->tls_session,
00817 (MHD_gtls_push_func) &
00818 send_param_adapter);
00819 }
00820 #endif
00821
00822
00823 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00824 {
00825 res_thread_create = pthread_create (&connection->pid, NULL,
00826 &MHD_handle_connection, connection);
00827 if (res_thread_create != 0)
00828 {
00829 #if HAVE_MESSAGES
00830 MHD_DLOG (daemon, "Failed to create a thread: %s\n",
00831 STRERROR (res_thread_create));
00832 #endif
00833 SHUTDOWN (s, SHUT_RDWR);
00834 CLOSE (s);
00835 MHD_ip_limit_del (daemon, addr, addrlen);
00836 free (connection->addr);
00837 free (connection);
00838 return MHD_NO;
00839 }
00840 }
00841 connection->next = daemon->connections;
00842 daemon->connections = connection;
00843 daemon->max_connections--;
00844 return MHD_YES;
00845 }
00846
00852 static void
00853 MHD_cleanup_connections (struct MHD_Daemon *daemon)
00854 {
00855 struct MHD_Connection *pos;
00856 struct MHD_Connection *prev;
00857 void *unused;
00858 int rc;
00859
00860 pos = daemon->connections;
00861 prev = NULL;
00862 while (pos != NULL)
00863 {
00864 if ((pos->socket_fd == -1) ||
00865 (((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
00866 (daemon->shutdown) && (pos->socket_fd != -1))))
00867 {
00868 if (prev == NULL)
00869 daemon->connections = pos->next;
00870 else
00871 prev->next = pos->next;
00872 if (0 != (pos->daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00873 {
00874 pthread_kill (pos->pid, SIGALRM);
00875 if (0 != (rc = pthread_join (pos->pid, &unused)))
00876 {
00877 #if HAVE_MESSAGES
00878 MHD_DLOG (daemon, "Failed to join a thread: %s\n",
00879 STRERROR (rc));
00880 #endif
00881 abort();
00882 }
00883 }
00884 MHD_destroy_response (pos->response);
00885 MHD_pool_destroy (pos->pool);
00886 #if HTTPS_SUPPORT
00887 if (pos->tls_session != NULL)
00888 MHD__gnutls_deinit (pos->tls_session);
00889 #endif
00890 MHD_ip_limit_del (daemon, (struct sockaddr*)pos->addr, pos->addr_len);
00891 free (pos->addr);
00892 free (pos);
00893 daemon->max_connections++;
00894 if (prev == NULL)
00895 pos = daemon->connections;
00896 else
00897 pos = prev->next;
00898 continue;
00899 }
00900 prev = pos;
00901 pos = pos->next;
00902 }
00903 }
00904
00916 int
00917 MHD_get_timeout (struct MHD_Daemon *daemon, unsigned long long *timeout)
00918 {
00919 time_t earliest_deadline;
00920 time_t now;
00921 struct MHD_Connection *pos;
00922 unsigned int dto;
00923
00924 dto = daemon->connection_timeout;
00925 if (0 == dto)
00926 return MHD_NO;
00927 pos = daemon->connections;
00928 if (pos == NULL)
00929 return MHD_NO;
00930 now = time (NULL);
00931
00932 earliest_deadline = now + dto;
00933 while (pos != NULL)
00934 {
00935 if (earliest_deadline > pos->last_activity + dto)
00936 earliest_deadline = pos->last_activity + dto;
00937 pos = pos->next;
00938 }
00939 if (earliest_deadline < now)
00940 *timeout = 0;
00941 else
00942 *timeout = (earliest_deadline - now);
00943 return MHD_YES;
00944 }
00945
00952 static int
00953 MHD_select (struct MHD_Daemon *daemon, int may_block)
00954 {
00955 struct MHD_Connection *pos;
00956 int num_ready;
00957 fd_set rs;
00958 fd_set ws;
00959 fd_set es;
00960 int max;
00961 struct timeval timeout;
00962 unsigned long long ltimeout;
00963 int ds;
00964 time_t now;
00965
00966 timeout.tv_sec = 0;
00967 timeout.tv_usec = 0;
00968 if (daemon->shutdown == MHD_YES)
00969 return MHD_NO;
00970 FD_ZERO (&rs);
00971 FD_ZERO (&ws);
00972 FD_ZERO (&es);
00973 max = 0;
00974
00975 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00976 {
00977
00978 if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
00979 return MHD_NO;
00980
00981
00982
00983 if ( (daemon->max_connections == 0) && (daemon->socket_fd != -1) )
00984 FD_CLR(daemon->socket_fd, &rs);
00985 }
00986 else
00987 {
00988
00989 max = daemon->socket_fd;
00990 if (max == -1)
00991 return MHD_NO;
00992 FD_SET (max, &rs);
00993 }
00994
00995
00996
00997 timeout.tv_usec = 0;
00998 timeout.tv_sec = 1;
00999 if (may_block == MHD_NO)
01000 {
01001 timeout.tv_usec = 0;
01002 timeout.tv_sec = 0;
01003 }
01004 else
01005 {
01006
01007 if ( (MHD_YES == MHD_get_timeout (daemon, <imeout)) &&
01008 (ltimeout < 1000) )
01009 {
01010 timeout.tv_usec = ltimeout * 1000;
01011 timeout.tv_sec = 0;
01012 }
01013 }
01014 num_ready = SELECT (max + 1, &rs, &ws, &es, &timeout);
01015
01016 if (daemon->shutdown == MHD_YES)
01017 return MHD_NO;
01018 if (num_ready < 0)
01019 {
01020 if (errno == EINTR)
01021 return MHD_YES;
01022 #if HAVE_MESSAGES
01023 MHD_DLOG (daemon, "select failed: %s\n", STRERROR (errno));
01024 #endif
01025 return MHD_NO;
01026 }
01027 ds = daemon->socket_fd;
01028 if (ds == -1)
01029 return MHD_YES;
01030
01031
01032 if (FD_ISSET (ds, &rs))
01033 MHD_accept_connection (daemon);
01034 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01035 {
01036
01037 now = time (NULL);
01038 pos = daemon->connections;
01039 while (pos != NULL)
01040 {
01041 ds = pos->socket_fd;
01042 if (ds != -1)
01043 {
01044
01045 if (FD_ISSET (ds, &rs))
01046 pos->read_handler (pos);
01047 if ((pos->socket_fd != -1) && (FD_ISSET (ds, &ws)))
01048 pos->write_handler (pos);
01049 if (pos->socket_fd != -1)
01050 pos->idle_handler (pos);
01051 }
01052 pos = pos->next;
01053 }
01054 }
01055 return MHD_YES;
01056 }
01057
01061 static int
01062 MHD_poll (struct MHD_Daemon *daemon)
01063 {
01064 #ifdef HAVE_POLL_H
01065 struct pollfd p;
01066
01067 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01068 return MHD_NO;
01069 p.fd = daemon->socket_fd;
01070 p.events = POLLIN;
01071 p.revents = 0;
01072
01073 if (poll(&p, 1, 1000) < 0) {
01074 if (errno == EINTR)
01075 return MHD_YES;
01076 #if HAVE_MESSAGES
01077 MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
01078 #endif
01079 return MHD_NO;
01080 }
01081
01082 if (daemon->shutdown == MHD_YES)
01083 return MHD_NO;
01084 if (daemon->socket_fd < 0)
01085 return MHD_YES;
01086 if (0 != (p.revents & POLLIN))
01087 MHD_accept_connection (daemon);
01088 return MHD_YES;
01089 #else
01090 return MHD_NO;
01091 #endif
01092 }
01093
01104 int
01105 MHD_run (struct MHD_Daemon *daemon)
01106 {
01107 if ((daemon->shutdown != MHD_NO) || (0 != (daemon->options
01108 & MHD_USE_THREAD_PER_CONNECTION))
01109 || (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
01110 return MHD_NO;
01111 MHD_select (daemon, MHD_NO);
01112 MHD_cleanup_connections (daemon);
01113 return MHD_YES;
01114 }
01115
01120 static void *
01121 MHD_select_thread (void *cls)
01122 {
01123 struct MHD_Daemon *daemon = cls;
01124 while (daemon->shutdown == MHD_NO)
01125 {
01126 if ((daemon->options & MHD_USE_POLL) == 0)
01127 MHD_select (daemon, MHD_YES);
01128 else
01129 MHD_poll(daemon);
01130 MHD_cleanup_connections (daemon);
01131 }
01132 return NULL;
01133 }
01134
01146 struct MHD_Daemon *
01147 MHD_start_daemon (unsigned int options,
01148 unsigned short port,
01149 MHD_AcceptPolicyCallback apc,
01150 void *apc_cls,
01151 MHD_AccessHandlerCallback dh, void *dh_cls, ...)
01152 {
01153 struct MHD_Daemon *ret;
01154 va_list ap;
01155
01156 va_start (ap, dh_cls);
01157 ret = MHD_start_daemon_va (options, port, apc, apc_cls, dh, dh_cls, ap);
01158 va_end (ap);
01159 return ret;
01160 }
01161
01162
01163 typedef void (*VfprintfFunctionPointerType)(void *, const char *, va_list);
01164
01165
01173 static int
01174 parse_options_va (struct MHD_Daemon *daemon,
01175 const struct sockaddr **servaddr,
01176 va_list ap);
01177
01178
01186 static int
01187 parse_options (struct MHD_Daemon *daemon,
01188 const struct sockaddr **servaddr,
01189 ...)
01190 {
01191 va_list ap;
01192 int ret;
01193
01194 va_start (ap, servaddr);
01195 ret = parse_options_va (daemon, servaddr, ap);
01196 va_end (ap);
01197 return ret;
01198 }
01199
01200
01208 static int
01209 parse_options_va (struct MHD_Daemon *daemon,
01210 const struct sockaddr **servaddr,
01211 va_list ap)
01212 {
01213 enum MHD_OPTION opt;
01214 struct MHD_OptionItem *oa;
01215 unsigned int i;
01216
01217 while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
01218 {
01219 switch (opt)
01220 {
01221 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
01222 daemon->pool_size = va_arg (ap, size_t);
01223 break;
01224 case MHD_OPTION_CONNECTION_LIMIT:
01225 daemon->max_connections = va_arg (ap, unsigned int);
01226 break;
01227 case MHD_OPTION_CONNECTION_TIMEOUT:
01228 daemon->connection_timeout = va_arg (ap, unsigned int);
01229 break;
01230 case MHD_OPTION_NOTIFY_COMPLETED:
01231 daemon->notify_completed =
01232 va_arg (ap, MHD_RequestCompletedCallback);
01233 daemon->notify_completed_cls = va_arg (ap, void *);
01234 break;
01235 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
01236 daemon->per_ip_connection_limit = va_arg (ap, unsigned int);
01237 break;
01238 case MHD_OPTION_SOCK_ADDR:
01239 *servaddr = va_arg (ap, const struct sockaddr *);
01240 break;
01241 case MHD_OPTION_URI_LOG_CALLBACK:
01242 daemon->uri_log_callback =
01243 va_arg (ap, LogCallback);
01244 daemon->uri_log_callback_cls = va_arg (ap, void *);
01245 break;
01246 case MHD_OPTION_THREAD_POOL_SIZE:
01247 daemon->worker_pool_size = va_arg (ap, unsigned int);
01248 break;
01249 #if HTTPS_SUPPORT
01250 case MHD_OPTION_PROTOCOL_VERSION:
01251 if (daemon->options & MHD_USE_SSL)
01252 _set_priority (&daemon->priority_cache->protocol,
01253 va_arg (ap, const int *));
01254 #if HAVE_MESSAGES
01255 else
01256 FPRINTF (stderr,
01257 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01258 opt);
01259 #endif
01260 break;
01261 case MHD_OPTION_HTTPS_MEM_KEY:
01262 if (daemon->options & MHD_USE_SSL)
01263 daemon->https_mem_key = va_arg (ap, const char *);
01264 #if HAVE_MESSAGES
01265 else
01266 FPRINTF (stderr,
01267 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01268 opt);
01269 #endif
01270 break;
01271 case MHD_OPTION_HTTPS_MEM_CERT:
01272 if (daemon->options & MHD_USE_SSL)
01273 daemon->https_mem_cert = va_arg (ap, const char *);
01274 #if HAVE_MESSAGES
01275 else
01276 FPRINTF (stderr,
01277 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01278 opt);
01279 #endif
01280 break;
01281 case MHD_OPTION_CIPHER_ALGORITHM:
01282 if (daemon->options & MHD_USE_SSL)
01283 _set_priority (&daemon->priority_cache->cipher,
01284 va_arg (ap, const int *));
01285 #if HAVE_MESSAGES
01286 else
01287 FPRINTF (stderr,
01288 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01289 opt);
01290 #endif
01291 break;
01292 #endif
01293 case MHD_OPTION_EXTERNAL_LOGGER:
01294 #if HAVE_MESSAGES
01295 daemon->custom_error_log =
01296 va_arg (ap, VfprintfFunctionPointerType);
01297 daemon->custom_error_log_cls = va_arg (ap, void *);
01298 #else
01299 va_arg (ap, VfprintfFunctionPointerType);
01300 va_arg (ap, void *);
01301 #endif
01302 break;
01303 case MHD_OPTION_ARRAY:
01304 oa = va_arg (ap, struct MHD_OptionItem*);
01305 i = 0;
01306 while (MHD_OPTION_END != (opt = oa[i].option))
01307 {
01308 switch (opt)
01309 {
01310
01311 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
01312 if (MHD_YES != parse_options (daemon,
01313 servaddr,
01314 opt,
01315 (size_t) oa[i].value,
01316 MHD_OPTION_END))
01317 return MHD_NO;
01318 break;
01319
01320 case MHD_OPTION_CONNECTION_LIMIT:
01321 case MHD_OPTION_CONNECTION_TIMEOUT:
01322 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
01323 case MHD_OPTION_THREAD_POOL_SIZE:
01324 if (MHD_YES != parse_options (daemon,
01325 servaddr,
01326 opt,
01327 (unsigned int) oa[i].value,
01328 MHD_OPTION_END))
01329 return MHD_NO;
01330 break;
01331
01332 case MHD_OPTION_CRED_TYPE:
01333 if (MHD_YES != parse_options (daemon,
01334 servaddr,
01335 opt,
01336 (int) oa[i].value,
01337 MHD_OPTION_END))
01338 return MHD_NO;
01339 break;
01340
01341 case MHD_OPTION_SOCK_ADDR:
01342 case MHD_OPTION_HTTPS_MEM_KEY:
01343 case MHD_OPTION_HTTPS_MEM_CERT:
01344 case MHD_OPTION_PROTOCOL_VERSION:
01345 case MHD_OPTION_CIPHER_ALGORITHM:
01346 case MHD_OPTION_ARRAY:
01347 if (MHD_YES != parse_options (daemon,
01348 servaddr,
01349 opt,
01350 oa[i].ptr_value,
01351 MHD_OPTION_END))
01352 return MHD_NO;
01353 break;
01354
01355 case MHD_OPTION_NOTIFY_COMPLETED:
01356 case MHD_OPTION_URI_LOG_CALLBACK:
01357 case MHD_OPTION_EXTERNAL_LOGGER:
01358 if (MHD_YES != parse_options (daemon,
01359 servaddr,
01360 opt,
01361 (void *) oa[i].value,
01362 oa[i].ptr_value,
01363 MHD_OPTION_END))
01364 return MHD_NO;
01365 break;
01366
01367 default:
01368 return MHD_NO;
01369 }
01370 i++;
01371 }
01372 break;
01373 default:
01374 #if HAVE_MESSAGES
01375 if ((opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
01376 (opt <= MHD_OPTION_CIPHER_ALGORITHM))
01377 {
01378 FPRINTF (stderr,
01379 "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
01380 opt);
01381 }
01382 else
01383 {
01384 FPRINTF (stderr,
01385 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
01386 opt);
01387 }
01388 #endif
01389 return MHD_NO;
01390 }
01391 }
01392 return MHD_YES;
01393 }
01394
01395
01407 struct MHD_Daemon *
01408 MHD_start_daemon_va (unsigned int options,
01409 unsigned short port,
01410 MHD_AcceptPolicyCallback apc,
01411 void *apc_cls,
01412 MHD_AccessHandlerCallback dh, void *dh_cls, va_list ap)
01413 {
01414 const int on = 1;
01415 struct MHD_Daemon *retVal;
01416 int socket_fd;
01417 struct sockaddr_in servaddr4;
01418 #if HAVE_INET6
01419 struct sockaddr_in6 servaddr6;
01420 #endif
01421 const struct sockaddr *servaddr = NULL;
01422 socklen_t addrlen;
01423 unsigned int i;
01424 int res_thread_create;
01425
01426 if ((port == 0) || (dh == NULL))
01427 return NULL;
01428 retVal = malloc (sizeof (struct MHD_Daemon));
01429 if (retVal == NULL)
01430 return NULL;
01431 memset (retVal, 0, sizeof (struct MHD_Daemon));
01432 retVal->options = (enum MHD_OPTION)options;
01433 retVal->port = port;
01434 retVal->apc = apc;
01435 retVal->apc_cls = apc_cls;
01436 retVal->default_handler = dh;
01437 retVal->default_handler_cls = dh_cls;
01438 retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
01439 retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
01440 retVal->connection_timeout = 0;
01441 #if HAVE_MESSAGES
01442 retVal->custom_error_log =
01443 (void (*)(void *, const char *, va_list)) &vfprintf;
01444 retVal->custom_error_log_cls = stderr;
01445 #endif
01446 #if HTTPS_SUPPORT
01447 if (options & MHD_USE_SSL)
01448 {
01449
01450 if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
01451 {
01452 #if HAVE_MESSAGES
01453 MHD_DLOG (retVal, "Failed to aquire gnutls mutex\n");
01454 #endif
01455 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01456 }
01457 if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
01458 {
01459 #if HAVE_MESSAGES
01460 MHD_DLOG (retVal, "Failed to release gnutls mutex\n");
01461 #endif
01462 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01463 }
01464
01465 MHD_tls_set_default_priority (&retVal->priority_cache, "", NULL);
01466 retVal->cred_type = MHD_GNUTLS_CRD_CERTIFICATE;
01467 }
01468 #endif
01469
01470 if (MHD_YES != parse_options_va (retVal, &servaddr, ap))
01471 {
01472 free (retVal);
01473 return NULL;
01474 }
01475
01476
01477 if ( (0 != (options & MHD_USE_POLL)) &&
01478 (0 == (options & MHD_USE_THREAD_PER_CONNECTION)) ) {
01479 #if HAVE_MESSAGES
01480 fprintf (stderr,
01481 "MHD poll support only works with MHD_USE_THREAD_PER_CONNECTION\n");
01482 #endif
01483 free (retVal);
01484 return NULL;
01485 }
01486
01487
01488 if ((0 == (options & MHD_USE_SELECT_INTERNALLY))
01489 && (retVal->worker_pool_size > 0))
01490 {
01491 #if HAVE_MESSAGES
01492 fprintf (stderr,
01493 "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n");
01494 #endif
01495 free (retVal);
01496 return NULL;
01497 }
01498
01499 #ifdef __SYMBIAN32__
01500 if (0 != (options & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
01501 {
01502 #if HAVE_MESSAGES
01503 fprintf (stderr,
01504 "Threaded operations are not supported on Symbian.\n");
01505 #endif
01506 free (retVal);
01507 return NULL;
01508 }
01509 #endif
01510 if ((options & MHD_USE_IPv6) != 0)
01511 #if HAVE_INET6
01512 socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0);
01513 #else
01514 {
01515 #if HAVE_MESSAGES
01516 fprintf (stderr, "AF_INET6 not supported\n");
01517 #endif
01518 free (retVal);
01519 return NULL;
01520 }
01521 #endif
01522 else
01523 socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0);
01524 if (socket_fd == -1)
01525 {
01526 #if HAVE_MESSAGES
01527 if ((options & MHD_USE_DEBUG) != 0)
01528 FPRINTF (stderr, "Call to socket failed: %s\n", STRERROR (errno));
01529 #endif
01530 free (retVal);
01531 return NULL;
01532 }
01533 #ifndef WINDOWS
01534 if ( (socket_fd >= FD_SETSIZE) &&
01535 (0 == (options & MHD_USE_POLL)) )
01536 {
01537 #if HAVE_MESSAGES
01538 if ((options & MHD_USE_DEBUG) != 0)
01539 FPRINTF (stderr,
01540 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
01541 socket_fd,
01542 FD_SETSIZE);
01543 #endif
01544 CLOSE (socket_fd);
01545 free (retVal);
01546 return NULL;
01547 }
01548 #endif
01549 if ((SETSOCKOPT (socket_fd,
01550 SOL_SOCKET,
01551 SO_REUSEADDR,
01552 &on, sizeof (on)) < 0) && (options & MHD_USE_DEBUG) != 0)
01553 {
01554 #if HAVE_MESSAGES
01555 FPRINTF (stderr, "setsockopt failed: %s\n", STRERROR (errno));
01556 #endif
01557 }
01558
01559
01560 #if HAVE_INET6
01561 if ((options & MHD_USE_IPv6) != 0)
01562 addrlen = sizeof (struct sockaddr_in6);
01563 else
01564 #endif
01565 addrlen = sizeof (struct sockaddr_in);
01566 if (NULL == servaddr)
01567 {
01568 #if HAVE_INET6
01569 if ((options & MHD_USE_IPv6) != 0)
01570 {
01571 memset (&servaddr6, 0, sizeof (struct sockaddr_in6));
01572 servaddr6.sin6_family = AF_INET6;
01573 servaddr6.sin6_port = htons (port);
01574 servaddr = (struct sockaddr *) &servaddr6;
01575 }
01576 else
01577 #endif
01578 {
01579 memset (&servaddr4, 0, sizeof (struct sockaddr_in));
01580 servaddr4.sin_family = AF_INET;
01581 servaddr4.sin_port = htons (port);
01582 servaddr = (struct sockaddr *) &servaddr4;
01583 }
01584 }
01585 retVal->socket_fd = socket_fd;
01586 if (BIND (socket_fd, servaddr, addrlen) == -1)
01587 {
01588 #if HAVE_MESSAGES
01589 if ((options & MHD_USE_DEBUG) != 0)
01590 FPRINTF (stderr,
01591 "Failed to bind to port %u: %s\n", port, STRERROR (errno));
01592 #endif
01593 CLOSE (socket_fd);
01594 free (retVal);
01595 return NULL;
01596 }
01597
01598 if (LISTEN (socket_fd, 20) < 0)
01599 {
01600 #if HAVE_MESSAGES
01601 if ((options & MHD_USE_DEBUG) != 0)
01602 FPRINTF (stderr,
01603 "Failed to listen for connections: %s\n", STRERROR (errno));
01604 #endif
01605 CLOSE (socket_fd);
01606 free (retVal);
01607 return NULL;
01608 }
01609
01610 if (0 != pthread_mutex_init (&retVal->per_ip_connection_mutex, NULL))
01611 {
01612 #if HAVE_MESSAGES
01613 MHD_DLOG (retVal,
01614 "MHD failed to initialize IP connection limit mutex\n");
01615 #endif
01616 CLOSE (socket_fd);
01617 free (retVal);
01618 return NULL;
01619 }
01620
01621 #if HTTPS_SUPPORT
01622
01623 if ((0 != (options & MHD_USE_SSL)) && (0 != MHD_TLS_init (retVal)))
01624 {
01625 #if HAVE_MESSAGES
01626 MHD_DLOG (retVal, "Failed to initialize TLS support\n");
01627 #endif
01628 CLOSE (socket_fd);
01629 pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
01630 free (retVal);
01631 return NULL;
01632 }
01633 #endif
01634 if ( ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
01635 ( (0 != (options & MHD_USE_SELECT_INTERNALLY)) &&
01636 (0 == retVal->worker_pool_size)) ) &&
01637 (0 != (res_thread_create =
01638 pthread_create (&retVal->pid, NULL, &MHD_select_thread, retVal))))
01639 {
01640 #if HAVE_MESSAGES
01641 MHD_DLOG (retVal,
01642 "Failed to create listen thread: %s\n", STRERROR (res_thread_create));
01643 #endif
01644 pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
01645 free (retVal);
01646 CLOSE (socket_fd);
01647 return NULL;
01648 }
01649 else if (retVal->worker_pool_size > 0)
01650 {
01651 #ifndef MINGW
01652 int sk_flags;
01653 #else
01654 unsigned long sk_flags;
01655 #endif
01656
01657
01658
01659
01660 unsigned int conns_per_thread = retVal->max_connections
01661 / retVal->worker_pool_size;
01662 unsigned int leftover_conns = retVal->max_connections
01663 % retVal->worker_pool_size;
01664
01665 i = 0;
01666
01667
01668
01669
01670 #ifndef MINGW
01671 sk_flags = fcntl (socket_fd, F_GETFL);
01672 if (sk_flags < 0)
01673 goto thread_failed;
01674 if (fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK) < 0)
01675 goto thread_failed;
01676 #else
01677 sk_flags = 1;
01678 #if HAVE_PLIBC_FD
01679 if (ioctlsocket (plibc_fd_get_handle (socket_fd), FIONBIO, &sk_flags) ==
01680 SOCKET_ERROR)
01681 #else
01682 if (ioctlsocket (socket_fd, FIONBIO, &sk_flags) == SOCKET_ERROR)
01683 #endif // PLIBC_FD
01684 goto thread_failed;
01685 #endif // MINGW
01686
01687
01688 retVal->worker_pool = malloc (sizeof (struct MHD_Daemon)
01689 * retVal->worker_pool_size);
01690 if (NULL == retVal->worker_pool)
01691 goto thread_failed;
01692
01693
01694 for (i = 0; i < retVal->worker_pool_size; ++i)
01695 {
01696
01697 struct MHD_Daemon *d = &retVal->worker_pool[i];
01698 memcpy (d, retVal, sizeof (struct MHD_Daemon));
01699
01700
01701
01702
01703 d->master = retVal;
01704 d->worker_pool_size = 0;
01705 d->worker_pool = NULL;
01706
01707
01708
01709
01710 d->max_connections = conns_per_thread;
01711 if (i < leftover_conns)
01712 ++d->max_connections;
01713
01714
01715 if (0 != (res_thread_create = pthread_create (&d->pid, NULL, &MHD_select_thread, d)))
01716 {
01717 #if HAVE_MESSAGES
01718 MHD_DLOG (retVal,
01719 "Failed to create pool thread: %s\n",
01720 STRERROR (res_thread_create));
01721 #endif
01722
01723
01724 goto thread_failed;
01725 }
01726 }
01727 }
01728 return retVal;
01729
01730 thread_failed:
01731
01732
01733
01734
01735 if (i == 0)
01736 {
01737 CLOSE (socket_fd);
01738 pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
01739 if (NULL != retVal->worker_pool)
01740 free (retVal->worker_pool);
01741 free (retVal);
01742 return NULL;
01743 }
01744
01745
01746
01747
01748
01749 retVal->worker_pool_size = i - 1;
01750 MHD_stop_daemon (retVal);
01751 return NULL;
01752 }
01753
01757 static void
01758 MHD_close_connections (struct MHD_Daemon *daemon)
01759 {
01760 while (daemon->connections != NULL)
01761 {
01762 if (-1 != daemon->connections->socket_fd)
01763 {
01764 #if DEBUG_CLOSE
01765 #if HAVE_MESSAGES
01766 MHD_DLOG (daemon, "MHD shutdown, closing active connections\n");
01767 #endif
01768 #endif
01769 MHD_connection_close (daemon->connections,
01770 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
01771 }
01772 MHD_cleanup_connections (daemon);
01773 }
01774 }
01775
01779 void
01780 MHD_stop_daemon (struct MHD_Daemon *daemon)
01781 {
01782 void *unused;
01783 int fd;
01784 unsigned int i;
01785 int rc;
01786
01787 if (daemon == NULL)
01788 return;
01789 daemon->shutdown = MHD_YES;
01790 fd = daemon->socket_fd;
01791 daemon->socket_fd = -1;
01792
01793
01794 for (i = 0; i < daemon->worker_pool_size; ++i)
01795 {
01796 daemon->worker_pool[i].shutdown = MHD_YES;
01797 daemon->worker_pool[i].socket_fd = -1;
01798 }
01799
01800 #if OSX
01801
01802
01803
01804 SHUTDOWN (fd, SHUT_RDWR);
01805 #else
01806 #if DEBUG_CLOSE
01807 #if HAVE_MESSAGES
01808 MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
01809 #endif
01810 #endif
01811 CLOSE (fd);
01812 #endif
01813
01814
01815 for (i = 0; i < daemon->worker_pool_size; ++i)
01816 pthread_kill (daemon->worker_pool[i].pid, SIGALRM);
01817 for (i = 0; i < daemon->worker_pool_size; ++i)
01818 {
01819 if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused)))
01820 {
01821 #if HAVE_MESSAGES
01822 MHD_DLOG (daemon, "Failed to join a thread: %s\n",
01823 STRERROR (rc));
01824 #endif
01825 abort();
01826 }
01827 MHD_close_connections (&daemon->worker_pool[i]);
01828 }
01829 free (daemon->worker_pool);
01830
01831 if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
01832 ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))
01833 && (0 == daemon->worker_pool_size)))
01834 {
01835 pthread_kill (daemon->pid, SIGALRM);
01836 if (0 != (rc = pthread_join (daemon->pid, &unused)))
01837 {
01838 #if HAVE_MESSAGES
01839 MHD_DLOG (daemon, "Failed to join a thread: %s\n",
01840 STRERROR (rc));
01841 #endif
01842 abort();
01843 }
01844 }
01845 MHD_close_connections (daemon);
01846
01847 #if OSX
01848 #if DEBUG_CLOSE
01849 #if HAVE_MESSAGES
01850 MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
01851 #endif
01852 #endif
01853 CLOSE (fd);
01854 #endif
01855
01856
01857 #if HTTPS_SUPPORT
01858 if (daemon->options & MHD_USE_SSL)
01859 {
01860 MHD__gnutls_priority_deinit (daemon->priority_cache);
01861 if (daemon->x509_cred)
01862 MHD__gnutls_certificate_free_credentials (daemon->x509_cred);
01863
01864 if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
01865 {
01866 #if HAVE_MESSAGES
01867 MHD_DLOG (daemon, "Failed to aquire gnutls mutex\n");
01868 #endif
01869 abort();
01870 }
01871 if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
01872 {
01873 #if HAVE_MESSAGES
01874 MHD_DLOG (daemon, "Failed to release gnutls mutex\n");
01875 #endif
01876 abort();
01877 }
01878 }
01879 #endif
01880 pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
01881 free (daemon);
01882 }
01883
01894 const union MHD_DaemonInfo *
01895 MHD_get_daemon_info (struct MHD_Daemon *daemon,
01896 enum MHD_DaemonInfoType infoType, ...)
01897 {
01898 switch (infoType)
01899 {
01900 case MHD_DAEMON_INFO_LISTEN_FD:
01901 return (const union MHD_DaemonInfo *) &daemon->socket_fd;
01902 default:
01903 return NULL;
01904 };
01905 }
01906
01922 void MHD_set_panic_func (MHD_PanicCallback cb, void *cls)
01923 {
01924 mhd_panic = cb;
01925 mhd_panic_cls = cls;
01926 }
01927
01933 const char *
01934 MHD_get_version (void)
01935 {
01936 return PACKAGE_VERSION;
01937 }
01938
01939 #ifndef WINDOWS
01940
01941 static struct sigaction sig;
01942
01943 static struct sigaction old;
01944
01945 static void
01946 sigalrmHandler (int sig)
01947 {
01948 }
01949 #endif
01950
01951 #ifdef __GNUC__
01952 #define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor))
01953 #define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor))
01954 #else // !__GNUC__
01955 #define ATTRIBUTE_CONSTRUCTOR
01956 #define ATTRIBUTE_DESTRUCTOR
01957 #endif // __GNUC__
01958
01963 void ATTRIBUTE_CONSTRUCTOR MHD_init ()
01964 {
01965 mhd_panic = &mhd_panic_std;
01966 mhd_panic_cls = NULL;
01967
01968 #ifndef WINDOWS
01969
01970 memset (&sig, 0, sizeof (struct sigaction));
01971 memset (&old, 0, sizeof (struct sigaction));
01972 sig.sa_flags = SA_NODEFER;
01973 sig.sa_handler = &sigalrmHandler;
01974 sigaction (SIGALRM, &sig, &old);
01975 #else
01976 plibc_init ("GNU", "libmicrohttpd");
01977 #endif
01978 #if HTTPS_SUPPORT
01979 MHD__gnutls_global_init ();
01980 if (0 != pthread_mutex_init(&MHD_gnutls_init_mutex, NULL))
01981 abort();
01982 #endif
01983 }
01984
01985 void ATTRIBUTE_DESTRUCTOR MHD_fini ()
01986 {
01987 #if HTTPS_SUPPORT
01988 MHD__gnutls_global_deinit ();
01989 if (0 != pthread_mutex_destroy(&MHD_gnutls_init_mutex))
01990 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01991 #endif
01992 #ifndef WINDOWS
01993 sigaction (SIGALRM, &old, &sig);
01994 #else
01995 plibc_shutdown ();
01996 #endif
01997 }
01998
01999