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/gnutls.h>
00036 #include <gcrypt.h>
00037 #endif
00038
00039 #ifdef HAVE_POLL_H
00040 #include <poll.h>
00041 #endif
00042
00043 #ifdef LINUX
00044 #include <sys/sendfile.h>
00045 #endif
00046
00050 #ifndef WINDOWS
00051 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE -4
00052 #else
00053 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE
00054 #endif
00055
00059 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
00060
00065 #define DEBUG_CLOSE MHD_NO
00066
00071 #define DEBUG_CONNECT MHD_NO
00072
00073 #ifndef LINUX
00074 #ifndef MSG_NOSIGNAL
00075 #define MSG_NOSIGNAL 0
00076 #endif
00077 #ifndef MSG_DONTWAIT
00078 #define MSG_DONTWAIT 0
00079 #endif
00080 #endif
00081
00082 #ifdef __SYMBIAN32__
00083 static void pthread_kill (int, int) {
00084
00085
00086 abort();
00087 }
00088 #endif // __SYMBIAN32__
00089
00093 static void
00094 mhd_panic_std(void *cls,
00095 const char *file,
00096 unsigned int line,
00097 const char *reason)
00098 {
00099 abort ();
00100 }
00101
00102
00106 MHD_PanicCallback mhd_panic;
00107
00111 void *mhd_panic_cls;
00112
00113
00121 static struct MHD_Daemon*
00122 MHD_get_master (struct MHD_Daemon *daemon)
00123 {
00124 while (NULL != daemon->master)
00125 daemon = daemon->master;
00126 return daemon;
00127 }
00128
00132 struct MHD_IPCount
00133 {
00137 int family;
00138
00142 union
00143 {
00147 struct in_addr ipv4;
00148 #if HAVE_IPV6
00149
00152 struct in6_addr ipv6;
00153 #endif
00154 } addr;
00155
00159 unsigned int count;
00160 };
00161
00167 static void
00168 MHD_ip_count_lock(struct MHD_Daemon *daemon)
00169 {
00170 if (0 != pthread_mutex_lock(&daemon->per_ip_connection_mutex))
00171 {
00172 #if HAVE_MESSAGES
00173 MHD_DLOG (daemon, "Failed to acquire IP connection limit mutex\n");
00174 #endif
00175 abort();
00176 }
00177 }
00178
00184 static void
00185 MHD_ip_count_unlock(struct MHD_Daemon *daemon)
00186 {
00187 if (0 != pthread_mutex_unlock(&daemon->per_ip_connection_mutex))
00188 {
00189 #if HAVE_MESSAGES
00190 MHD_DLOG (daemon, "Failed to release IP connection limit mutex\n");
00191 #endif
00192 abort();
00193 }
00194 }
00195
00205 static int
00206 MHD_ip_addr_compare(const void *a1, const void *a2)
00207 {
00208 return memcmp (a1, a2, offsetof(struct MHD_IPCount, count));
00209 }
00210
00219 static int
00220 MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen,
00221 struct MHD_IPCount *key)
00222 {
00223 memset(key, 0, sizeof(*key));
00224
00225
00226 if (addrlen == sizeof(struct sockaddr_in))
00227 {
00228 const struct sockaddr_in *addr4 = (const struct sockaddr_in*)addr;
00229 key->family = AF_INET;
00230 memcpy (&key->addr.ipv4, &addr4->sin_addr, sizeof(addr4->sin_addr));
00231 return MHD_YES;
00232 }
00233
00234 #if HAVE_IPV6
00235
00236 if (addrlen == sizeof (struct sockaddr_in6))
00237 {
00238 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)addr;
00239 key->family = AF_INET6;
00240 memcpy (&key->addr.ipv6, &addr6->sin6_addr, sizeof(addr6->sin6_addr));
00241 return MHD_YES;
00242 }
00243 #endif
00244
00245
00246 return MHD_NO;
00247 }
00248
00258 static int
00259 MHD_ip_limit_add(struct MHD_Daemon *daemon,
00260 const struct sockaddr *addr,
00261 socklen_t addrlen)
00262 {
00263 struct MHD_IPCount *key;
00264 void *node;
00265 int result;
00266
00267 daemon = MHD_get_master (daemon);
00268
00269
00270 if (daemon->per_ip_connection_limit == 0)
00271 return MHD_YES;
00272
00273 key = malloc (sizeof(*key));
00274 if (NULL == key)
00275 return MHD_NO;
00276
00277
00278 if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, key))
00279 {
00280
00281 free (key);
00282 return MHD_YES;
00283 }
00284
00285 MHD_ip_count_lock (daemon);
00286
00287
00288 node = (void*)TSEARCH (key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
00289 if (!node)
00290 {
00291 #if HAVE_MESSAGES
00292 MHD_DLOG(daemon,
00293 "Failed to add IP connection count node\n");
00294 #endif
00295 MHD_ip_count_unlock (daemon);
00296 free (key);
00297 return MHD_NO;
00298 }
00299 node = *(void**)node;
00300
00301
00302 if (node != key)
00303 free(key);
00304 key = (struct MHD_IPCount*)node;
00305
00306
00307
00308 result = (key->count < daemon->per_ip_connection_limit);
00309 if (result == MHD_YES)
00310 ++key->count;
00311
00312 MHD_ip_count_unlock (daemon);
00313 return result;
00314 }
00315
00324 static void
00325 MHD_ip_limit_del(struct MHD_Daemon *daemon,
00326 const struct sockaddr *addr,
00327 socklen_t addrlen)
00328 {
00329 struct MHD_IPCount search_key;
00330 struct MHD_IPCount *found_key;
00331 void *node;
00332
00333 daemon = MHD_get_master (daemon);
00334
00335
00336 if (daemon->per_ip_connection_limit == 0)
00337 return;
00338
00339
00340 if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, &search_key))
00341 return;
00342
00343 MHD_ip_count_lock (daemon);
00344
00345
00346 node = (void*)TFIND (&search_key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
00347
00348
00349
00350 if (!node)
00351 {
00352 #if HAVE_MESSAGES
00353 MHD_DLOG (daemon,
00354 "Failed to find previously-added IP address\n");
00355 #endif
00356 abort();
00357 }
00358 found_key = (struct MHD_IPCount*)*(void**)node;
00359
00360
00361 if (found_key->count == 0)
00362 {
00363 #if HAVE_MESSAGES
00364 MHD_DLOG (daemon,
00365 "Previously-added IP address had 0 count\n");
00366 #endif
00367 abort();
00368 }
00369
00370
00371 if (--found_key->count == 0)
00372 {
00373 TDELETE (found_key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
00374 free (found_key);
00375 }
00376
00377 MHD_ip_count_unlock (daemon);
00378 }
00379
00380 #if HTTPS_SUPPORT
00381 static pthread_mutex_t MHD_gnutls_init_mutex;
00382
00391 static ssize_t
00392 recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i)
00393 {
00394 int res;
00395 res = gnutls_record_recv (connection->tls_session, other, i);
00396 if ( (res == GNUTLS_E_AGAIN) ||
00397 (res == GNUTLS_E_INTERRUPTED) )
00398 {
00399 errno = EINTR;
00400 return -1;
00401 }
00402 if (res < 0)
00403 {
00404
00405
00406
00407 errno = EPIPE;
00408 return res;
00409 }
00410 return res;
00411 }
00412
00413
00422 static ssize_t
00423 send_tls_adapter (struct MHD_Connection *connection,
00424 const void *other, size_t i)
00425 {
00426 int res;
00427 res = gnutls_record_send (connection->tls_session, other, i);
00428 if ( (res == GNUTLS_E_AGAIN) ||
00429 (res == GNUTLS_E_INTERRUPTED) )
00430 {
00431 errno = EINTR;
00432 return -1;
00433 }
00434 return res;
00435 }
00436
00437
00444 static int
00445 MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
00446 {
00447 gnutls_datum_t key;
00448 gnutls_datum_t cert;
00449
00450 if (daemon->https_mem_trust) {
00451 cert.data = (unsigned char *) daemon->https_mem_trust;
00452 cert.size = strlen(daemon->https_mem_trust);
00453 if (gnutls_certificate_set_x509_trust_mem(daemon->x509_cred, &cert,
00454 GNUTLS_X509_FMT_PEM) < 0) {
00455 #if HAVE_MESSAGES
00456 MHD_DLOG(daemon,
00457 "Bad trust certificate format\n");
00458 #endif
00459 return -1;
00460 }
00461 }
00462
00463
00464 if (daemon->https_mem_cert && daemon->https_mem_key)
00465 {
00466 key.data = (unsigned char *) daemon->https_mem_key;
00467 key.size = strlen (daemon->https_mem_key);
00468 cert.data = (unsigned char *) daemon->https_mem_cert;
00469 cert.size = strlen (daemon->https_mem_cert);
00470
00471 return gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
00472 &cert, &key,
00473 GNUTLS_X509_FMT_PEM);
00474 }
00475 #if HAVE_MESSAGES
00476 MHD_DLOG (daemon, "You need to specify a certificate and key location\n");
00477 #endif
00478 return -1;
00479 }
00480
00487 static int
00488 MHD_TLS_init (struct MHD_Daemon *daemon)
00489 {
00490 switch (daemon->cred_type)
00491 {
00492 case GNUTLS_CRD_CERTIFICATE:
00493 if (0 !=
00494 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
00495 return GNUTLS_E_MEMORY_ERROR;
00496 return MHD_init_daemon_certificate (daemon);
00497 default:
00498 #if HAVE_MESSAGES
00499 MHD_DLOG (daemon,
00500 "Error: invalid credentials type %d specified.\n",
00501 daemon->cred_type);
00502 #endif
00503 return -1;
00504 }
00505 }
00506 #endif
00507
00521 int
00522 MHD_get_fdset (struct MHD_Daemon *daemon,
00523 fd_set * read_fd_set,
00524 fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd)
00525 {
00526 struct MHD_Connection *con_itr;
00527 int fd;
00528
00529 if ((daemon == NULL) || (read_fd_set == NULL) || (write_fd_set == NULL)
00530 || (except_fd_set == NULL) || (max_fd == NULL)
00531 || (-1 == (fd = daemon->socket_fd)) || (daemon->shutdown == MHD_YES)
00532 || ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0)
00533 || ((daemon->options & MHD_USE_POLL) != 0))
00534 return MHD_NO;
00535
00536 FD_SET (fd, read_fd_set);
00537
00538 if ((*max_fd) < fd)
00539 *max_fd = fd;
00540
00541 con_itr = daemon->connections;
00542 while (con_itr != NULL)
00543 {
00544 if (MHD_YES != MHD_connection_get_fdset (con_itr,
00545 read_fd_set,
00546 write_fd_set,
00547 except_fd_set, max_fd))
00548 return MHD_NO;
00549 con_itr = con_itr->next;
00550 }
00551 #if DEBUG_CONNECT
00552 MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
00553 #endif
00554 return MHD_YES;
00555 }
00556
00564 static void *
00565 MHD_handle_connection (void *data)
00566 {
00567 struct MHD_Connection *con = data;
00568 int num_ready;
00569 fd_set rs;
00570 fd_set ws;
00571 fd_set es;
00572 int max;
00573 struct timeval tv;
00574 unsigned int timeout;
00575 #ifdef HAVE_POLL_H
00576 struct MHD_Pollfd mp;
00577 struct pollfd p;
00578 #endif
00579
00580 timeout = con->daemon->connection_timeout;
00581 while ((!con->daemon->shutdown) && (con->socket_fd != -1)) {
00582 tv.tv_usec = 0;
00583 if ( (timeout > (time (NULL) - con->last_activity)) ||
00584 (timeout == 0) )
00585 {
00586
00587
00588 tv.tv_sec = 1;
00589 if ((con->state == MHD_CONNECTION_NORMAL_BODY_UNREADY) ||
00590 (con->state == MHD_CONNECTION_CHUNKED_BODY_UNREADY))
00591 {
00592
00593 tv.tv_sec = 0;
00594 }
00595 }
00596 else
00597 {
00598 tv.tv_sec = 0;
00599 }
00600 #ifdef HAVE_POLL_H
00601 if (0 == (con->daemon->options & MHD_USE_POLL)) {
00602 #else
00603 {
00604 #endif
00605
00606 FD_ZERO (&rs);
00607 FD_ZERO (&ws);
00608 FD_ZERO (&es);
00609 max = 0;
00610 MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
00611 num_ready = SELECT (max + 1, &rs, &ws, &es, &tv);
00612 if (num_ready < 0) {
00613 if (errno == EINTR)
00614 continue;
00615 #if HAVE_MESSAGES
00616 MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n", max,
00617 STRERROR (errno));
00618 #endif
00619 break;
00620 }
00621
00622 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &rs)))
00623 con->read_handler (con);
00624 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
00625 con->write_handler (con);
00626 if (con->socket_fd != -1)
00627 con->idle_handler (con);
00628 }
00629 #ifdef HAVE_POLL_H
00630 else
00631 {
00632
00633 memset(&mp, 0, sizeof (struct MHD_Pollfd));
00634 MHD_connection_get_pollfd(con, &mp);
00635 memset(&p, 0, sizeof (struct pollfd));
00636 p.fd = mp.fd;
00637 if (mp.events & MHD_POLL_ACTION_IN)
00638 p.events |= POLLIN;
00639 if (mp.events & MHD_POLL_ACTION_OUT)
00640 p.events |= POLLOUT;
00641
00642
00643 if (poll (&p, 1, 1000) < 0) {
00644 if (errno == EINTR)
00645 continue;
00646 #if HAVE_MESSAGES
00647 MHD_DLOG (con->daemon, "Error during poll: `%s'\n",
00648 STRERROR (errno));
00649 #endif
00650 break;
00651 }
00652 if ( (con->socket_fd != -1) &&
00653 (0 != (p.revents & POLLIN)) )
00654 con->read_handler (con);
00655 if ( (con->socket_fd != -1) &&
00656 (0 != (p.revents & POLLOUT)) )
00657 con->write_handler (con);
00658 if (con->socket_fd != -1)
00659 con->idle_handler (con);
00660 if ( (con->socket_fd != -1) &&
00661 (0 != (p.revents & (POLLERR | POLLHUP))) )
00662 MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR);
00663 }
00664 #endif
00665 }
00666 if (con->socket_fd != -1)
00667 {
00668 #if DEBUG_CLOSE
00669 #if HAVE_MESSAGES
00670 MHD_DLOG (con->daemon,
00671 "Processing thread terminating, closing connection\n");
00672 #endif
00673 #endif
00674 MHD_connection_close (con, MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
00675 }
00676 return NULL;
00677 }
00678
00687 static ssize_t
00688 recv_param_adapter (struct MHD_Connection *connection, void *other, size_t i)
00689 {
00690 if (connection->socket_fd == -1)
00691 return -1;
00692 if (0 != (connection->daemon->options & MHD_USE_SSL))
00693 return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
00694 return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT);
00695 }
00696
00705 static ssize_t
00706 send_param_adapter (struct MHD_Connection *connection,
00707 const void *other, size_t i)
00708 {
00709 #if LINUX
00710 int fd;
00711 off_t offset;
00712 int ret;
00713 #endif
00714 if (connection->socket_fd == -1)
00715 return -1;
00716 if (0 != (connection->daemon->options & MHD_USE_SSL))
00717 return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
00718 #if LINUX
00719 if ( (connection->write_buffer_append_offset ==
00720 connection->write_buffer_send_offset) &&
00721 (NULL != connection->response) &&
00722 (-1 != (fd = connection->response->fd)) )
00723 {
00724
00725 offset = (off_t) connection->response_write_position + connection->response->fd_off;
00726 ret = sendfile (connection->socket_fd,
00727 fd,
00728 &offset,
00729 connection->response->total_size - offset);
00730 if ( (ret == -1) &&
00731 (errno == EINTR) )
00732 return 0;
00733 return ret;
00734 }
00735 #endif
00736 return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT);
00737 }
00738
00739
00740 #if HTTPS_SUPPORT
00741
00745 static void
00746 socket_set_nonblocking (int fd)
00747 {
00748 #if MINGW
00749 u_long mode;
00750 mode = 1;
00751 if (ioctlsocket (fd, FIONBIO, &mode) == SOCKET_ERROR)
00752 {
00753 SetErrnoFromWinsockError (WSAGetLastError ());
00754 #if HAVE_MESSAGES
00755 FPRINTF(stderr, "Failed to make socket non-blocking: %s\n",
00756 STRERROR (errno));
00757 #endif
00758 }
00759 #else
00760
00761
00762 int flags = fcntl (fd, F_GETFL);
00763 if ( (flags == -1) ||
00764 (0 != fcntl (fd, F_SETFL, flags | O_NONBLOCK)) )
00765 {
00766 #if HAVE_MESSAGES
00767 FPRINTF(stderr, "Failed to make socket non-blocking: %s\n",
00768 STRERROR (errno));
00769 #endif
00770 }
00771 #endif
00772 }
00773 #endif
00774
00775
00785 static int
00786 create_thread (pthread_t * thread,
00787 const struct MHD_Daemon *daemon,
00788 void *(*start_routine)(void*),
00789 void *arg)
00790 {
00791 pthread_attr_t attr;
00792 pthread_attr_t *pattr;
00793 int ret;
00794
00795 if (daemon->thread_stack_size != 0)
00796 {
00797 if (0 != (ret = pthread_attr_init (&attr)))
00798 goto ERR;
00799 if (0 != (ret = pthread_attr_setstacksize (&attr, daemon->thread_stack_size)))
00800 {
00801 pthread_attr_destroy (&attr);
00802 goto ERR;
00803 }
00804 pattr = &attr;
00805 }
00806 else
00807 {
00808 pattr = NULL;
00809 }
00810 ret = pthread_create (thread, pattr,
00811 start_routine, arg);
00812 if (daemon->thread_stack_size != 0)
00813 pthread_attr_destroy (&attr);
00814 return ret;
00815 ERR:
00816 #if HAVE_MESSAGES
00817 MHD_DLOG (daemon,
00818 "Failed to set thread stack size\n");
00819 #endif
00820 errno = EINVAL;
00821 return ret;
00822 }
00823
00824
00825
00834 static int
00835 MHD_accept_connection (struct MHD_Daemon *daemon)
00836 {
00837 struct MHD_Connection *connection;
00838 #if HAVE_INET6
00839 struct sockaddr_in6 addrstorage;
00840 #else
00841 struct sockaddr_in addrstorage;
00842 #endif
00843 struct sockaddr *addr = (struct sockaddr *) &addrstorage;
00844 socklen_t addrlen;
00845 int s;
00846 int res_thread_create;
00847 #if OSX
00848 static int on = 1;
00849 #endif
00850
00851 addrlen = sizeof (addrstorage);
00852 memset (addr, 0, sizeof (addrstorage));
00853
00854 s = ACCEPT (daemon->socket_fd, addr, &addrlen);
00855 if ((s == -1) || (addrlen <= 0))
00856 {
00857 #if HAVE_MESSAGES
00858
00859 if ((EAGAIN != errno) && (EWOULDBLOCK != errno))
00860 MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));
00861 #endif
00862 if (s != -1)
00863 {
00864 SHUTDOWN (s, SHUT_RDWR);
00865 CLOSE (s);
00866
00867 }
00868 return MHD_NO;
00869 }
00870 #ifndef WINDOWS
00871 if ( (s >= FD_SETSIZE) &&
00872 (0 == (daemon->options & MHD_USE_POLL)) )
00873 {
00874 #if HAVE_MESSAGES
00875 MHD_DLOG (daemon,
00876 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
00877 s,
00878 FD_SETSIZE);
00879 #endif
00880 CLOSE (s);
00881 return MHD_NO;
00882 }
00883 #endif
00884
00885
00886 #if HAVE_MESSAGES
00887 #if DEBUG_CONNECT
00888 MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
00889 #endif
00890 #endif
00891 if ((daemon->max_connections == 0)
00892 || (MHD_ip_limit_add (daemon, addr, addrlen) == MHD_NO))
00893 {
00894
00895 #if HAVE_MESSAGES
00896 MHD_DLOG (daemon,
00897 "Server reached connection limit (closing inbound connection)\n");
00898 #endif
00899 SHUTDOWN (s, SHUT_RDWR);
00900 CLOSE (s);
00901 return MHD_NO;
00902 }
00903
00904
00905 if ((daemon->apc != NULL)
00906 && (MHD_NO == daemon->apc (daemon->apc_cls, addr, addrlen)))
00907 {
00908 #if DEBUG_CLOSE
00909 #if HAVE_MESSAGES
00910 MHD_DLOG (daemon, "Connection rejected, closing connection\n");
00911 #endif
00912 #endif
00913 SHUTDOWN (s, SHUT_RDWR);
00914 CLOSE (s);
00915 MHD_ip_limit_del (daemon, addr, addrlen);
00916 return MHD_YES;
00917 }
00918 #if OSX
00919 #ifdef SOL_SOCKET
00920 #ifdef SO_NOSIGPIPE
00921 setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof (on));
00922 #endif
00923 #endif
00924 #endif
00925 connection = malloc (sizeof (struct MHD_Connection));
00926 if (NULL == connection)
00927 {
00928 #if HAVE_MESSAGES
00929 MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00930 #endif
00931 SHUTDOWN (s, SHUT_RDWR);
00932 CLOSE (s);
00933 MHD_ip_limit_del (daemon, addr, addrlen);
00934 return MHD_NO;
00935 }
00936 memset (connection, 0, sizeof (struct MHD_Connection));
00937 connection->pool = NULL;
00938 connection->addr = malloc (addrlen);
00939 if (connection->addr == NULL)
00940 {
00941 #if HAVE_MESSAGES
00942 MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00943 #endif
00944 SHUTDOWN (s, SHUT_RDWR);
00945 CLOSE (s);
00946 MHD_ip_limit_del (daemon, addr, addrlen);
00947 free (connection);
00948 return MHD_NO;
00949 }
00950 memcpy (connection->addr, addr, addrlen);
00951 connection->addr_len = addrlen;
00952 connection->socket_fd = s;
00953 connection->daemon = daemon;
00954 connection->last_activity = time (NULL);
00955
00956
00957 MHD_set_http_callbacks_ (connection);
00958 connection->recv_cls = &recv_param_adapter;
00959 connection->send_cls = &send_param_adapter;
00960 #if HTTPS_SUPPORT
00961 if (0 != (daemon->options & MHD_USE_SSL))
00962 {
00963 connection->recv_cls = &recv_tls_adapter;
00964 connection->send_cls = &send_tls_adapter;
00965 connection->state = MHD_TLS_CONNECTION_INIT;
00966 MHD_set_https_callbacks (connection);
00967 gnutls_init (&connection->tls_session, GNUTLS_SERVER);
00968 gnutls_priority_set (connection->tls_session,
00969 daemon->priority_cache);
00970 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00971 {
00972
00973 socket_set_nonblocking (connection->socket_fd);
00974 }
00975 switch (connection->daemon->cred_type)
00976 {
00977
00978 case GNUTLS_CRD_CERTIFICATE:
00979 gnutls_credentials_set (connection->tls_session,
00980 GNUTLS_CRD_CERTIFICATE,
00981 connection->daemon->x509_cred);
00982 break;
00983 default:
00984 #if HAVE_MESSAGES
00985 MHD_DLOG (connection->daemon,
00986 "Failed to setup TLS credentials: unknown credential type %d\n",
00987 connection->daemon->cred_type);
00988 #endif
00989 SHUTDOWN (s, SHUT_RDWR);
00990 CLOSE (s);
00991 MHD_ip_limit_del (daemon, addr, addrlen);
00992 free (connection->addr);
00993 free (connection);
00994 mhd_panic (mhd_panic_cls, __FILE__, __LINE__,
00995 #if HAVE_MESSAGES
00996 "Unknown credential type"
00997 #else
00998 NULL
00999 #endif
01000 );
01001 return MHD_NO;
01002 }
01003 gnutls_transport_set_ptr (connection->tls_session,
01004 (gnutls_transport_ptr_t) connection);
01005 gnutls_transport_set_pull_function (connection->tls_session,
01006 (gnutls_pull_func) &
01007 recv_param_adapter);
01008 gnutls_transport_set_push_function (connection->tls_session,
01009 (gnutls_push_func) &
01010 send_param_adapter);
01011
01012 if (daemon->https_mem_trust){
01013 gnutls_certificate_server_set_request(connection->tls_session, GNUTLS_CERT_REQUEST);
01014 }
01015 }
01016 #endif
01017
01018
01019 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01020 {
01021 res_thread_create = create_thread (&connection->pid, daemon,
01022 &MHD_handle_connection, connection);
01023 if (res_thread_create != 0)
01024 {
01025 #if HAVE_MESSAGES
01026 MHD_DLOG (daemon, "Failed to create a thread: %s\n",
01027 STRERROR (res_thread_create));
01028 #endif
01029 SHUTDOWN (s, SHUT_RDWR);
01030 CLOSE (s);
01031 MHD_ip_limit_del (daemon, addr, addrlen);
01032 free (connection->addr);
01033 free (connection);
01034 return MHD_NO;
01035 }
01036 }
01037 connection->next = daemon->connections;
01038 daemon->connections = connection;
01039 daemon->max_connections--;
01040 return MHD_YES;
01041 }
01042
01050 static void
01051 MHD_cleanup_connections (struct MHD_Daemon *daemon)
01052 {
01053 struct MHD_Connection *pos;
01054 struct MHD_Connection *prev;
01055 void *unused;
01056 int rc;
01057
01058 pos = daemon->connections;
01059 prev = NULL;
01060 while (pos != NULL)
01061 {
01062 if ((pos->socket_fd == -1) ||
01063 (((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01064 (daemon->shutdown) && (pos->socket_fd != -1))))
01065 {
01066 if (prev == NULL)
01067 daemon->connections = pos->next;
01068 else
01069 prev->next = pos->next;
01070 if (0 != (pos->daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01071 {
01072 pthread_kill (pos->pid, SIGALRM);
01073 if (0 != (rc = pthread_join (pos->pid, &unused)))
01074 {
01075 #if HAVE_MESSAGES
01076 MHD_DLOG (daemon, "Failed to join a thread: %s\n",
01077 STRERROR (rc));
01078 #endif
01079 abort();
01080 }
01081 }
01082 MHD_pool_destroy (pos->pool);
01083 #if HTTPS_SUPPORT
01084 if (pos->tls_session != NULL)
01085 gnutls_deinit (pos->tls_session);
01086 #endif
01087 MHD_ip_limit_del (daemon, (struct sockaddr*)pos->addr, pos->addr_len);
01088 if (pos->response != NULL)
01089 {
01090 MHD_destroy_response (pos->response);
01091 pos->response = NULL;
01092 }
01093 free (pos->addr);
01094 free (pos);
01095 daemon->max_connections++;
01096 if (prev == NULL)
01097 pos = daemon->connections;
01098 else
01099 pos = prev->next;
01100 continue;
01101 }
01102 prev = pos;
01103 pos = pos->next;
01104 }
01105 }
01106
01119 int
01120 MHD_get_timeout (struct MHD_Daemon *daemon, unsigned MHD_LONG_LONG *timeout)
01121 {
01122 time_t earliest_deadline;
01123 time_t now;
01124 struct MHD_Connection *pos;
01125 unsigned int dto;
01126
01127 dto = daemon->connection_timeout;
01128 if (0 == dto)
01129 return MHD_NO;
01130 pos = daemon->connections;
01131 if (pos == NULL)
01132 return MHD_NO;
01133 now = time (NULL);
01134
01135 earliest_deadline = now + dto;
01136 while (pos != NULL)
01137 {
01138 if (earliest_deadline > pos->last_activity + dto)
01139 earliest_deadline = pos->last_activity + dto;
01140 #if HTTPS_SUPPORT
01141 if ( (0 != (daemon->options & MHD_USE_SSL)) &&
01142 (0 != gnutls_record_check_pending (pos->tls_session)) )
01143 earliest_deadline = now;
01144 #endif
01145 pos = pos->next;
01146 }
01147 if (earliest_deadline < now)
01148 *timeout = 0;
01149 else
01150 *timeout = (earliest_deadline - now);
01151 return MHD_YES;
01152 }
01153
01154
01162 static int
01163 MHD_select (struct MHD_Daemon *daemon, int may_block)
01164 {
01165 struct MHD_Connection *pos;
01166 int num_ready;
01167 fd_set rs;
01168 fd_set ws;
01169 fd_set es;
01170 int max;
01171 struct timeval timeout;
01172 unsigned MHD_LONG_LONG ltimeout;
01173 int ds;
01174
01175 timeout.tv_sec = 0;
01176 timeout.tv_usec = 0;
01177 if (daemon->shutdown == MHD_YES)
01178 return MHD_NO;
01179 FD_ZERO (&rs);
01180 FD_ZERO (&ws);
01181 FD_ZERO (&es);
01182 max = 0;
01183
01184 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01185 {
01186
01187 if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
01188 return MHD_NO;
01189
01190
01191
01192 if ( (daemon->max_connections == 0) && (daemon->socket_fd != -1) )
01193 FD_CLR(daemon->socket_fd, &rs);
01194 }
01195 else
01196 {
01197
01198 max = daemon->socket_fd;
01199 if (max == -1)
01200 return MHD_NO;
01201 FD_SET (max, &rs);
01202 }
01203
01204
01205
01206 timeout.tv_usec = 0;
01207 timeout.tv_sec = 1;
01208 if (may_block == MHD_NO)
01209 {
01210 timeout.tv_usec = 0;
01211 timeout.tv_sec = 0;
01212 }
01213 else
01214 {
01215
01216 if ( (MHD_YES == MHD_get_timeout (daemon, <imeout)) &&
01217 (ltimeout < 1000) )
01218 {
01219 timeout.tv_usec = ltimeout * 1000;
01220 timeout.tv_sec = 0;
01221 }
01222 }
01223 num_ready = SELECT (max + 1, &rs, &ws, &es, &timeout);
01224
01225 if (daemon->shutdown == MHD_YES)
01226 return MHD_NO;
01227 if (num_ready < 0)
01228 {
01229 if (errno == EINTR)
01230 return MHD_YES;
01231 #if HAVE_MESSAGES
01232 MHD_DLOG (daemon, "select failed: %s\n", STRERROR (errno));
01233 #endif
01234 return MHD_NO;
01235 }
01236 ds = daemon->socket_fd;
01237 if (ds == -1)
01238 return MHD_YES;
01239
01240
01241 if (FD_ISSET (ds, &rs))
01242 MHD_accept_connection (daemon);
01243 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01244 {
01245
01246 pos = daemon->connections;
01247 while (pos != NULL)
01248 {
01249 ds = pos->socket_fd;
01250 if (ds != -1)
01251 {
01252
01253 if (FD_ISSET (ds, &rs))
01254 pos->read_handler (pos);
01255 if ((pos->socket_fd != -1) && (FD_ISSET (ds, &ws)))
01256 pos->write_handler (pos);
01257 if (pos->socket_fd != -1)
01258 pos->idle_handler (pos);
01259 }
01260 pos = pos->next;
01261 }
01262 }
01263 return MHD_YES;
01264 }
01265
01271 static int
01272 MHD_poll (struct MHD_Daemon *daemon)
01273 {
01274 #ifdef HAVE_POLL_H
01275 struct pollfd p;
01276
01277 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01278 return MHD_NO;
01279 p.fd = daemon->socket_fd;
01280 p.events = POLLIN;
01281 p.revents = 0;
01282
01283 if (poll(&p, 1, 1000) < 0) {
01284 if (errno == EINTR)
01285 return MHD_YES;
01286 #if HAVE_MESSAGES
01287 MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
01288 #endif
01289 return MHD_NO;
01290 }
01291
01292 if (daemon->shutdown == MHD_YES)
01293 return MHD_NO;
01294 if (daemon->socket_fd < 0)
01295 return MHD_YES;
01296 if (0 != (p.revents & POLLIN))
01297 MHD_accept_connection (daemon);
01298 return MHD_YES;
01299 #else
01300 return MHD_NO;
01301 #endif
01302 }
01303
01304
01315 int
01316 MHD_run (struct MHD_Daemon *daemon)
01317 {
01318 if ((daemon->shutdown != MHD_NO) || (0 != (daemon->options
01319 & MHD_USE_THREAD_PER_CONNECTION))
01320 || (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
01321 return MHD_NO;
01322 MHD_select (daemon, MHD_NO);
01323 MHD_cleanup_connections (daemon);
01324 return MHD_YES;
01325 }
01326
01327
01335 static void *
01336 MHD_select_thread (void *cls)
01337 {
01338 struct MHD_Daemon *daemon = cls;
01339 while (daemon->shutdown == MHD_NO)
01340 {
01341 if ((daemon->options & MHD_USE_POLL) == 0)
01342 MHD_select (daemon, MHD_YES);
01343 else
01344 MHD_poll(daemon);
01345 MHD_cleanup_connections (daemon);
01346 }
01347 return NULL;
01348 }
01349
01350
01362 struct MHD_Daemon *
01363 MHD_start_daemon (unsigned int options,
01364 uint16_t port,
01365 MHD_AcceptPolicyCallback apc,
01366 void *apc_cls,
01367 MHD_AccessHandlerCallback dh, void *dh_cls, ...)
01368 {
01369 struct MHD_Daemon *ret;
01370 va_list ap;
01371
01372 va_start (ap, dh_cls);
01373 ret = MHD_start_daemon_va (options, port, apc, apc_cls, dh, dh_cls, ap);
01374 va_end (ap);
01375 return ret;
01376 }
01377
01378
01379 typedef void (*VfprintfFunctionPointerType)(void *, const char *, va_list);
01380
01381
01390 static int
01391 parse_options_va (struct MHD_Daemon *daemon,
01392 const struct sockaddr **servaddr,
01393 va_list ap);
01394
01395
01404 static int
01405 parse_options (struct MHD_Daemon *daemon,
01406 const struct sockaddr **servaddr,
01407 ...)
01408 {
01409 va_list ap;
01410 int ret;
01411
01412 va_start (ap, servaddr);
01413 ret = parse_options_va (daemon, servaddr, ap);
01414 va_end (ap);
01415 return ret;
01416 }
01417
01418
01427 static int
01428 parse_options_va (struct MHD_Daemon *daemon,
01429 const struct sockaddr **servaddr,
01430 va_list ap)
01431 {
01432 enum MHD_OPTION opt;
01433 struct MHD_OptionItem *oa;
01434 unsigned int i;
01435 #if HTTPS_SUPPORT
01436 int ret;
01437 const char *pstr;
01438 #endif
01439
01440 while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
01441 {
01442 switch (opt)
01443 {
01444 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
01445 daemon->pool_size = va_arg (ap, size_t);
01446 break;
01447 case MHD_OPTION_CONNECTION_LIMIT:
01448 daemon->max_connections = va_arg (ap, unsigned int);
01449 break;
01450 case MHD_OPTION_CONNECTION_TIMEOUT:
01451 daemon->connection_timeout = va_arg (ap, unsigned int);
01452 break;
01453 case MHD_OPTION_NOTIFY_COMPLETED:
01454 daemon->notify_completed =
01455 va_arg (ap, MHD_RequestCompletedCallback);
01456 daemon->notify_completed_cls = va_arg (ap, void *);
01457 break;
01458 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
01459 daemon->per_ip_connection_limit = va_arg (ap, unsigned int);
01460 break;
01461 case MHD_OPTION_SOCK_ADDR:
01462 *servaddr = va_arg (ap, const struct sockaddr *);
01463 break;
01464 case MHD_OPTION_URI_LOG_CALLBACK:
01465 daemon->uri_log_callback =
01466 va_arg (ap, LogCallback);
01467 daemon->uri_log_callback_cls = va_arg (ap, void *);
01468 break;
01469 case MHD_OPTION_THREAD_POOL_SIZE:
01470 daemon->worker_pool_size = va_arg (ap, unsigned int);
01471 if (daemon->worker_pool_size >= SIZE_MAX / sizeof (struct MHD_Daemon))
01472 {
01473 #if HAVE_MESSAGES
01474 FPRINTF (stderr,
01475 "Specified thread pool size (%u) too big\n",
01476 daemon->worker_pool_size);
01477 #endif
01478 return MHD_NO;
01479 }
01480 break;
01481 #if HTTPS_SUPPORT
01482 case MHD_OPTION_HTTPS_MEM_KEY:
01483 if (0 != (daemon->options & MHD_USE_SSL))
01484 daemon->https_mem_key = va_arg (ap, const char *);
01485 #if HAVE_MESSAGES
01486 else
01487 FPRINTF (stderr,
01488 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01489 opt);
01490 #endif
01491 break;
01492 case MHD_OPTION_HTTPS_MEM_CERT:
01493 if (0 != (daemon->options & MHD_USE_SSL))
01494 daemon->https_mem_cert = va_arg (ap, const char *);
01495 #if HAVE_MESSAGES
01496 else
01497 FPRINTF (stderr,
01498 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01499 opt);
01500 #endif
01501 break;
01502 case MHD_OPTION_HTTPS_MEM_TRUST:
01503 if (0 != (daemon->options & MHD_USE_SSL))
01504 daemon->https_mem_trust = va_arg (ap, const char *);
01505 #if HAVE_MESSAGES
01506 else
01507 FPRINTF (stderr,
01508 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01509 opt);
01510 #endif
01511 break;
01512 case MHD_OPTION_HTTPS_CRED_TYPE:
01513 daemon->cred_type = va_arg (ap, gnutls_credentials_type_t);
01514 break;
01515 case MHD_OPTION_HTTPS_PRIORITIES:
01516 ret = gnutls_priority_init (&daemon->priority_cache,
01517 pstr = va_arg (ap, const char*),
01518 NULL);
01519 #if HAVE_MESSAGES
01520 if (ret != GNUTLS_E_SUCCESS)
01521 FPRINTF (stderr,
01522 "Setting priorities to `%s' failed: %s\n",
01523 pstr,
01524 gnutls_strerror (ret));
01525 #endif
01526 if (ret != GNUTLS_E_SUCCESS)
01527 return MHD_NO;
01528 break;
01529 #endif
01530 #ifdef DAUTH_SUPPORT
01531 case MHD_OPTION_DIGEST_AUTH_RANDOM:
01532 daemon->digest_auth_rand_size = va_arg (ap, size_t);
01533 daemon->digest_auth_random = va_arg (ap, const char *);
01534 break;
01535 case MHD_OPTION_NONCE_NC_SIZE:
01536 daemon->nonce_nc_size = va_arg (ap, unsigned int);
01537 break;
01538 #endif
01539 case MHD_OPTION_LISTEN_SOCKET:
01540 daemon->socket_fd = va_arg (ap, int);
01541 break;
01542 case MHD_OPTION_EXTERNAL_LOGGER:
01543 #if HAVE_MESSAGES
01544 daemon->custom_error_log =
01545 va_arg (ap, VfprintfFunctionPointerType);
01546 daemon->custom_error_log_cls = va_arg (ap, void *);
01547 #else
01548 va_arg (ap, VfprintfFunctionPointerType);
01549 va_arg (ap, void *);
01550 #endif
01551 break;
01552 case MHD_OPTION_THREAD_STACK_SIZE:
01553 daemon->thread_stack_size = va_arg (ap, size_t);
01554 break;
01555 case MHD_OPTION_ARRAY:
01556 oa = va_arg (ap, struct MHD_OptionItem*);
01557 i = 0;
01558 while (MHD_OPTION_END != (opt = oa[i].option))
01559 {
01560 switch (opt)
01561 {
01562
01563 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
01564 case MHD_OPTION_THREAD_STACK_SIZE:
01565 if (MHD_YES != parse_options (daemon,
01566 servaddr,
01567 opt,
01568 (size_t) oa[i].value,
01569 MHD_OPTION_END))
01570 return MHD_NO;
01571 break;
01572
01573 case MHD_OPTION_NONCE_NC_SIZE:
01574 case MHD_OPTION_CONNECTION_LIMIT:
01575 case MHD_OPTION_CONNECTION_TIMEOUT:
01576 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
01577 case MHD_OPTION_THREAD_POOL_SIZE:
01578 if (MHD_YES != parse_options (daemon,
01579 servaddr,
01580 opt,
01581 (unsigned int) oa[i].value,
01582 MHD_OPTION_END))
01583 return MHD_NO;
01584 break;
01585
01586 case MHD_OPTION_HTTPS_CRED_TYPE:
01587 case MHD_OPTION_LISTEN_SOCKET:
01588 if (MHD_YES != parse_options (daemon,
01589 servaddr,
01590 opt,
01591 (int) oa[i].value,
01592 MHD_OPTION_END))
01593 return MHD_NO;
01594 break;
01595
01596 case MHD_OPTION_SOCK_ADDR:
01597 case MHD_OPTION_HTTPS_MEM_KEY:
01598 case MHD_OPTION_HTTPS_MEM_CERT:
01599 case MHD_OPTION_HTTPS_MEM_TRUST:
01600 case MHD_OPTION_HTTPS_PRIORITIES:
01601 case MHD_OPTION_ARRAY:
01602 if (MHD_YES != parse_options (daemon,
01603 servaddr,
01604 opt,
01605 oa[i].ptr_value,
01606 MHD_OPTION_END))
01607 return MHD_NO;
01608 break;
01609
01610 case MHD_OPTION_NOTIFY_COMPLETED:
01611 case MHD_OPTION_URI_LOG_CALLBACK:
01612 case MHD_OPTION_EXTERNAL_LOGGER:
01613 case MHD_OPTION_UNESCAPE_CALLBACK:
01614 if (MHD_YES != parse_options (daemon,
01615 servaddr,
01616 opt,
01617 (void *) oa[i].value,
01618 oa[i].ptr_value,
01619 MHD_OPTION_END))
01620 return MHD_NO;
01621 break;
01622
01623 case MHD_OPTION_DIGEST_AUTH_RANDOM:
01624 if (MHD_YES != parse_options (daemon,
01625 servaddr,
01626 opt,
01627 (size_t) oa[i].value,
01628 oa[i].ptr_value,
01629 MHD_OPTION_END))
01630 return MHD_NO;
01631 break;
01632 default:
01633 return MHD_NO;
01634 }
01635 i++;
01636 }
01637 break;
01638 case MHD_OPTION_UNESCAPE_CALLBACK:
01639 daemon->unescape_callback =
01640 va_arg (ap, UnescapeCallback);
01641 daemon->unescape_callback_cls = va_arg (ap, void *);
01642 break;
01643 default:
01644 #if HAVE_MESSAGES
01645 if (((opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
01646 (opt <= MHD_OPTION_HTTPS_PRIORITIES)) || (opt == MHD_OPTION_HTTPS_MEM_TRUST))
01647 {
01648 FPRINTF (stderr,
01649 "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
01650 opt);
01651 }
01652 else
01653 {
01654 FPRINTF (stderr,
01655 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
01656 opt);
01657 }
01658 #endif
01659 return MHD_NO;
01660 }
01661 }
01662 return MHD_YES;
01663 }
01664
01665
01677 struct MHD_Daemon *
01678 MHD_start_daemon_va (unsigned int options,
01679 uint16_t port,
01680 MHD_AcceptPolicyCallback apc,
01681 void *apc_cls,
01682 MHD_AccessHandlerCallback dh, void *dh_cls,
01683 va_list ap)
01684 {
01685 const int on = 1;
01686 struct MHD_Daemon *retVal;
01687 int socket_fd;
01688 struct sockaddr_in servaddr4;
01689 #if HAVE_INET6
01690 struct sockaddr_in6 servaddr6;
01691 #endif
01692 const struct sockaddr *servaddr = NULL;
01693 socklen_t addrlen;
01694 unsigned int i;
01695 int res_thread_create;
01696
01697 if ((port == 0) || (dh == NULL))
01698 return NULL;
01699 retVal = malloc (sizeof (struct MHD_Daemon));
01700 if (retVal == NULL)
01701 return NULL;
01702 memset (retVal, 0, sizeof (struct MHD_Daemon));
01703 #if HTTPS_SUPPORT
01704 if (options & MHD_USE_SSL)
01705 {
01706 gnutls_priority_init (&retVal->priority_cache,
01707 "NORMAL",
01708 NULL);
01709 }
01710 #endif
01711 retVal->socket_fd = -1;
01712 retVal->options = (enum MHD_OPTION)options;
01713 retVal->port = port;
01714 retVal->apc = apc;
01715 retVal->apc_cls = apc_cls;
01716 retVal->default_handler = dh;
01717 retVal->default_handler_cls = dh_cls;
01718 retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
01719 retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
01720 retVal->unescape_callback = &MHD_http_unescape;
01721 retVal->connection_timeout = 0;
01722 #ifdef DAUTH_SUPPORT
01723 retVal->digest_auth_rand_size = 0;
01724 retVal->digest_auth_random = NULL;
01725 retVal->nonce_nc_size = 4;
01726 #endif
01727 #if HAVE_MESSAGES
01728 retVal->custom_error_log =
01729 (void (*)(void *, const char *, va_list)) &vfprintf;
01730 retVal->custom_error_log_cls = stderr;
01731 #endif
01732 #if HTTPS_SUPPORT
01733 if (options & MHD_USE_SSL)
01734 {
01735
01736 if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
01737 {
01738 #if HAVE_MESSAGES
01739 MHD_DLOG (retVal, "Failed to aquire gnutls mutex\n");
01740 #endif
01741 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01742 }
01743 if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
01744 {
01745 #if HAVE_MESSAGES
01746 MHD_DLOG (retVal, "Failed to release gnutls mutex\n");
01747 #endif
01748 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01749 }
01750 retVal->cred_type = GNUTLS_CRD_CERTIFICATE;
01751 }
01752 #endif
01753
01754 if (MHD_YES != parse_options_va (retVal, &servaddr, ap))
01755 {
01756 free (retVal);
01757 return NULL;
01758 }
01759
01760 #ifdef DAUTH_SUPPORT
01761 if (retVal->nonce_nc_size > 0)
01762 {
01763 if ( ( (size_t) (retVal->nonce_nc_size * sizeof(struct MHD_NonceNc))) /
01764 sizeof(struct MHD_NonceNc) != retVal->nonce_nc_size)
01765 {
01766 #if HAVE_MESSAGES
01767 MHD_DLOG (retVal,
01768 "Specified value for NC_SIZE too large\n");
01769 #endif
01770 free (retVal);
01771 return NULL;
01772 }
01773 retVal->nnc = malloc (retVal->nonce_nc_size * sizeof(struct MHD_NonceNc));
01774 if (NULL == retVal->nnc)
01775 {
01776 #if HAVE_MESSAGES
01777 MHD_DLOG (retVal,
01778 "Failed to allocate memory for nonce-nc map: %s\n",
01779 STRERROR (errno));
01780 #endif
01781 free (retVal);
01782 return NULL;
01783 }
01784 }
01785 if (0 != pthread_mutex_init (&retVal->nnc_lock, NULL))
01786 {
01787 #if HAVE_MESSAGES
01788 MHD_DLOG (retVal,
01789 "MHD failed to initialize nonce-nc mutex\n");
01790 #endif
01791 free (retVal);
01792 return NULL;
01793 }
01794 #endif
01795
01796
01797 if ( (0 != (options & MHD_USE_POLL)) &&
01798 (0 == (options & MHD_USE_THREAD_PER_CONNECTION)) )
01799 {
01800 #if HAVE_MESSAGES
01801 MHD_DLOG (retVal,
01802 "MHD poll support only works with MHD_USE_THREAD_PER_CONNECTION\n");
01803 #endif
01804 #if DAUTH_SUPPORT
01805 free (retVal->nnc);
01806 pthread_mutex_destroy (&retVal->nnc_lock);
01807 #endif
01808 free (retVal);
01809 return NULL;
01810 }
01811
01812
01813 if ( (0 == (options & MHD_USE_SELECT_INTERNALLY)) &&
01814 (retVal->worker_pool_size > 0) )
01815 {
01816 #if HAVE_MESSAGES
01817 MHD_DLOG (retVal,
01818 "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n");
01819 #endif
01820 free (retVal);
01821 return NULL;
01822 }
01823
01824 #ifdef __SYMBIAN32__
01825 if (0 != (options & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
01826 {
01827 #if HAVE_MESSAGES
01828 MHD_DLOG (retVal,
01829 "Threaded operations are not supported on Symbian.\n");
01830 #endif
01831 free (retVal);
01832 return NULL;
01833 }
01834 #endif
01835 if (retVal->socket_fd == -1)
01836 {
01837 if ((options & MHD_USE_IPv6) != 0)
01838 #if HAVE_INET6
01839 socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0);
01840 #else
01841 {
01842 #if HAVE_MESSAGES
01843 MHD_DLOG (retVal,
01844 "AF_INET6 not supported\n");
01845 #endif
01846 free (retVal);
01847 return NULL;
01848 }
01849 #endif
01850 else
01851 socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0);
01852 if (socket_fd == -1)
01853 {
01854 #if HAVE_MESSAGES
01855 if ((options & MHD_USE_DEBUG) != 0)
01856 MHD_DLOG (retVal,
01857 "Call to socket failed: %s\n",
01858 STRERROR (errno));
01859 #endif
01860 free (retVal);
01861 return NULL;
01862 }
01863 if ((SETSOCKOPT (socket_fd,
01864 SOL_SOCKET,
01865 SO_REUSEADDR,
01866 &on, sizeof (on)) < 0) && ((options & MHD_USE_DEBUG) != 0))
01867 {
01868 #if HAVE_MESSAGES
01869 MHD_DLOG (retVal,
01870 "setsockopt failed: %s\n",
01871 STRERROR (errno));
01872 #endif
01873 }
01874
01875
01876 #if HAVE_INET6
01877 if ((options & MHD_USE_IPv6) != 0)
01878 addrlen = sizeof (struct sockaddr_in6);
01879 else
01880 #endif
01881 addrlen = sizeof (struct sockaddr_in);
01882 if (NULL == servaddr)
01883 {
01884 #if HAVE_INET6
01885 if ((options & MHD_USE_IPv6) != 0)
01886 {
01887 memset (&servaddr6, 0, sizeof (struct sockaddr_in6));
01888 servaddr6.sin6_family = AF_INET6;
01889 servaddr6.sin6_port = htons (port);
01890 servaddr = (struct sockaddr *) &servaddr6;
01891 }
01892 else
01893 #endif
01894 {
01895 memset (&servaddr4, 0, sizeof (struct sockaddr_in));
01896 servaddr4.sin_family = AF_INET;
01897 servaddr4.sin_port = htons (port);
01898 servaddr = (struct sockaddr *) &servaddr4;
01899 }
01900 }
01901 retVal->socket_fd = socket_fd;
01902
01903 if ((options & MHD_USE_IPv6) != 0)
01904 {
01905 #ifdef IPPROTO_IPV6
01906 #ifdef IPV6_V6ONLY
01907
01908
01909
01910
01911 #ifndef WINDOWS
01912 const int on = 1;
01913 setsockopt (socket_fd,
01914 IPPROTO_IPV6, IPV6_V6ONLY,
01915 &on, sizeof (on));
01916 #else
01917 const char on = 1;
01918 setsockopt (socket_fd,
01919 IPPROTO_IPV6, IPV6_V6ONLY,
01920 &on, sizeof (on));
01921 #endif
01922 #endif
01923 #endif
01924 }
01925 if (BIND (socket_fd, servaddr, addrlen) == -1)
01926 {
01927 #if HAVE_MESSAGES
01928 if ((options & MHD_USE_DEBUG) != 0)
01929 MHD_DLOG (retVal,
01930 "Failed to bind to port %u: %s\n",
01931 (unsigned int) port,
01932 STRERROR (errno));
01933 #endif
01934 CLOSE (socket_fd);
01935 free (retVal);
01936 return NULL;
01937 }
01938
01939 if (LISTEN (socket_fd, 20) < 0)
01940 {
01941 #if HAVE_MESSAGES
01942 if ((options & MHD_USE_DEBUG) != 0)
01943 MHD_DLOG (retVal,
01944 "Failed to listen for connections: %s\n",
01945 STRERROR (errno));
01946 #endif
01947 CLOSE (socket_fd);
01948 free (retVal);
01949 return NULL;
01950 }
01951 }
01952 else
01953 {
01954 socket_fd = retVal->socket_fd;
01955 }
01956 #ifndef WINDOWS
01957 if ( (socket_fd >= FD_SETSIZE) &&
01958 (0 == (options & MHD_USE_POLL)) )
01959 {
01960 #if HAVE_MESSAGES
01961 if ((options & MHD_USE_DEBUG) != 0)
01962 MHD_DLOG (retVal,
01963 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
01964 socket_fd,
01965 FD_SETSIZE);
01966 #endif
01967 CLOSE (socket_fd);
01968 free (retVal);
01969 return NULL;
01970 }
01971 #endif
01972
01973 if (0 != pthread_mutex_init (&retVal->per_ip_connection_mutex, NULL))
01974 {
01975 #if HAVE_MESSAGES
01976 MHD_DLOG (retVal,
01977 "MHD failed to initialize IP connection limit mutex\n");
01978 #endif
01979 CLOSE (socket_fd);
01980 free (retVal);
01981 return NULL;
01982 }
01983
01984 #if HTTPS_SUPPORT
01985
01986 if ((0 != (options & MHD_USE_SSL)) && (0 != MHD_TLS_init (retVal)))
01987 {
01988 #if HAVE_MESSAGES
01989 MHD_DLOG (retVal,
01990 "Failed to initialize TLS support\n");
01991 #endif
01992 CLOSE (socket_fd);
01993 #ifdef DAUTH_SUPPORT
01994 pthread_mutex_destroy (&retVal->nnc_lock);
01995 free (retVal->nnc);
01996 #endif
01997 pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
01998 free (retVal);
01999 return NULL;
02000 }
02001 #endif
02002 if ( ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
02003 ( (0 != (options & MHD_USE_SELECT_INTERNALLY)) &&
02004 (0 == retVal->worker_pool_size)) ) &&
02005 (0 != (res_thread_create =
02006 create_thread (&retVal->pid, retVal, &MHD_select_thread, retVal))))
02007 {
02008 #if HAVE_MESSAGES
02009 MHD_DLOG (retVal,
02010 "Failed to create listen thread: %s\n",
02011 STRERROR (res_thread_create));
02012 #endif
02013 #ifdef DAUTH_SUPPORT
02014 pthread_mutex_destroy (&retVal->nnc_lock);
02015 free (retVal->nnc);
02016 #endif
02017 pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
02018 free (retVal);
02019 CLOSE (socket_fd);
02020 return NULL;
02021 }
02022 if (retVal->worker_pool_size > 0)
02023 {
02024 #ifndef MINGW
02025 int sk_flags;
02026 #else
02027 unsigned long sk_flags;
02028 #endif
02029
02030
02031
02032
02033 unsigned int conns_per_thread = retVal->max_connections
02034 / retVal->worker_pool_size;
02035 unsigned int leftover_conns = retVal->max_connections
02036 % retVal->worker_pool_size;
02037
02038 i = 0;
02039
02040
02041
02042
02043 #ifndef MINGW
02044 sk_flags = fcntl (socket_fd, F_GETFL);
02045 if (sk_flags < 0)
02046 goto thread_failed;
02047 if (fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK) < 0)
02048 goto thread_failed;
02049 #else
02050 sk_flags = 1;
02051 #if HAVE_PLIBC_FD
02052 if (ioctlsocket (plibc_fd_get_handle (socket_fd), FIONBIO, &sk_flags) ==
02053 SOCKET_ERROR)
02054 #else
02055 if (ioctlsocket (socket_fd, FIONBIO, &sk_flags) == SOCKET_ERROR)
02056 #endif // PLIBC_FD
02057 goto thread_failed;
02058 #endif // MINGW
02059
02060
02061 retVal->worker_pool = malloc (sizeof (struct MHD_Daemon)
02062 * retVal->worker_pool_size);
02063 if (NULL == retVal->worker_pool)
02064 goto thread_failed;
02065
02066
02067 for (i = 0; i < retVal->worker_pool_size; ++i)
02068 {
02069
02070 struct MHD_Daemon *d = &retVal->worker_pool[i];
02071 memcpy (d, retVal, sizeof (struct MHD_Daemon));
02072
02073
02074
02075
02076 d->master = retVal;
02077 d->worker_pool_size = 0;
02078 d->worker_pool = NULL;
02079
02080
02081
02082
02083 d->max_connections = conns_per_thread;
02084 if (i < leftover_conns)
02085 ++d->max_connections;
02086
02087
02088 if (0 != (res_thread_create = create_thread (&d->pid, retVal, &MHD_select_thread, d)))
02089 {
02090 #if HAVE_MESSAGES
02091 MHD_DLOG (retVal,
02092 "Failed to create pool thread: %s\n",
02093 STRERROR (res_thread_create));
02094 #endif
02095
02096
02097 goto thread_failed;
02098 }
02099 }
02100 }
02101 return retVal;
02102
02103 thread_failed:
02104
02105
02106
02107
02108 if (i == 0)
02109 {
02110 CLOSE (socket_fd);
02111 pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
02112 if (NULL != retVal->worker_pool)
02113 free (retVal->worker_pool);
02114 free (retVal);
02115 return NULL;
02116 }
02117
02118
02119
02120
02121
02122 retVal->worker_pool_size = i - 1;
02123 MHD_stop_daemon (retVal);
02124 return NULL;
02125 }
02126
02130 static void
02131 MHD_close_connections (struct MHD_Daemon *daemon)
02132 {
02133 while (daemon->connections != NULL)
02134 {
02135 if (-1 != daemon->connections->socket_fd)
02136 {
02137 #if DEBUG_CLOSE
02138 #if HAVE_MESSAGES
02139 MHD_DLOG (daemon, "MHD shutdown, closing active connections\n");
02140 #endif
02141 #endif
02142 MHD_connection_close (daemon->connections,
02143 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
02144 }
02145 MHD_cleanup_connections (daemon);
02146 }
02147 }
02148
02152 void
02153 MHD_stop_daemon (struct MHD_Daemon *daemon)
02154 {
02155 void *unused;
02156 int fd;
02157 unsigned int i;
02158 int rc;
02159
02160 if (daemon == NULL)
02161 return;
02162 daemon->shutdown = MHD_YES;
02163 fd = daemon->socket_fd;
02164 daemon->socket_fd = -1;
02165
02166
02167 for (i = 0; i < daemon->worker_pool_size; ++i)
02168 {
02169 daemon->worker_pool[i].shutdown = MHD_YES;
02170 daemon->worker_pool[i].socket_fd = -1;
02171 }
02172
02173 #if OSX
02174
02175
02176
02177 SHUTDOWN (fd, SHUT_RDWR);
02178 #else
02179 #if DEBUG_CLOSE
02180 #if HAVE_MESSAGES
02181 MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
02182 #endif
02183 #endif
02184 CLOSE (fd);
02185 #endif
02186
02187
02188 for (i = 0; i < daemon->worker_pool_size; ++i)
02189 pthread_kill (daemon->worker_pool[i].pid, SIGALRM);
02190 for (i = 0; i < daemon->worker_pool_size; ++i)
02191 {
02192 if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused)))
02193 {
02194 #if HAVE_MESSAGES
02195 MHD_DLOG (daemon, "Failed to join a thread: %s\n",
02196 STRERROR (rc));
02197 #endif
02198 abort();
02199 }
02200 MHD_close_connections (&daemon->worker_pool[i]);
02201 }
02202 free (daemon->worker_pool);
02203
02204 if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
02205 ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))
02206 && (0 == daemon->worker_pool_size)))
02207 {
02208 pthread_kill (daemon->pid, SIGALRM);
02209 if (0 != (rc = pthread_join (daemon->pid, &unused)))
02210 {
02211 #if HAVE_MESSAGES
02212 MHD_DLOG (daemon, "Failed to join a thread: %s\n",
02213 STRERROR (rc));
02214 #endif
02215 abort();
02216 }
02217 }
02218 MHD_close_connections (daemon);
02219
02220 #if OSX
02221 #if DEBUG_CLOSE
02222 #if HAVE_MESSAGES
02223 MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
02224 #endif
02225 #endif
02226 CLOSE (fd);
02227 #endif
02228
02229
02230 #if HTTPS_SUPPORT
02231 if (daemon->options & MHD_USE_SSL)
02232 {
02233 gnutls_priority_deinit (daemon->priority_cache);
02234 if (daemon->x509_cred)
02235 gnutls_certificate_free_credentials (daemon->x509_cred);
02236
02237 if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
02238 {
02239 #if HAVE_MESSAGES
02240 MHD_DLOG (daemon, "Failed to aquire gnutls mutex\n");
02241 #endif
02242 abort();
02243 }
02244 if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
02245 {
02246 #if HAVE_MESSAGES
02247 MHD_DLOG (daemon, "Failed to release gnutls mutex\n");
02248 #endif
02249 abort();
02250 }
02251 }
02252 #endif
02253
02254 #ifdef DAUTH_SUPPORT
02255 free (daemon->nnc);
02256 pthread_mutex_destroy (&daemon->nnc_lock);
02257 #endif
02258 pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
02259 free (daemon);
02260 }
02261
02272 const union MHD_DaemonInfo *
02273 MHD_get_daemon_info (struct MHD_Daemon *daemon,
02274 enum MHD_DaemonInfoType infoType, ...)
02275 {
02276 switch (infoType)
02277 {
02278 case MHD_DAEMON_INFO_LISTEN_FD:
02279 return (const union MHD_DaemonInfo *) &daemon->socket_fd;
02280 default:
02281 return NULL;
02282 };
02283 }
02284
02300 void MHD_set_panic_func (MHD_PanicCallback cb, void *cls)
02301 {
02302 mhd_panic = cb;
02303 mhd_panic_cls = cls;
02304 }
02305
02311 const char *
02312 MHD_get_version (void)
02313 {
02314 return PACKAGE_VERSION;
02315 }
02316
02317 #ifndef WINDOWS
02318
02319 static struct sigaction sig;
02320
02321 static struct sigaction old;
02322
02323 static void
02324 sigalrmHandler (int sig)
02325 {
02326 }
02327 #endif
02328
02329 #ifdef __GNUC__
02330 #define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor))
02331 #define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor))
02332 #else // !__GNUC__
02333 #define ATTRIBUTE_CONSTRUCTOR
02334 #define ATTRIBUTE_DESTRUCTOR
02335 #endif // __GNUC__
02336
02337 #if HTTPS_SUPPORT
02338 GCRY_THREAD_OPTION_PTHREAD_IMPL;
02339 #endif
02340
02345 void ATTRIBUTE_CONSTRUCTOR MHD_init ()
02346 {
02347 mhd_panic = &mhd_panic_std;
02348 mhd_panic_cls = NULL;
02349
02350 #ifndef WINDOWS
02351
02352 memset (&sig, 0, sizeof (struct sigaction));
02353 memset (&old, 0, sizeof (struct sigaction));
02354 sig.sa_flags = SA_NODEFER;
02355 sig.sa_handler = &sigalrmHandler;
02356 sigaction (SIGALRM, &sig, &old);
02357 #else
02358 plibc_init ("GNU", "libmicrohttpd");
02359 #endif
02360 #if HTTPS_SUPPORT
02361 gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
02362 gnutls_global_init ();
02363 if (0 != pthread_mutex_init(&MHD_gnutls_init_mutex, NULL))
02364 abort();
02365 #endif
02366 }
02367
02368 void ATTRIBUTE_DESTRUCTOR MHD_fini ()
02369 {
02370 #if HTTPS_SUPPORT
02371 gnutls_global_deinit ();
02372 if (0 != pthread_mutex_destroy(&MHD_gnutls_init_mutex))
02373 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
02374 #endif
02375 #ifndef WINDOWS
02376 sigaction (SIGALRM, &old, &sig);
02377 #else
02378 plibc_shutdown ();
02379 #endif
02380 }
02381
02382