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 return res;
00403 }
00404
00405
00414 static ssize_t
00415 send_tls_adapter (struct MHD_Connection *connection,
00416 const void *other, size_t i)
00417 {
00418 int res;
00419 res = gnutls_record_send (connection->tls_session, other, i);
00420 if ( (res == GNUTLS_E_AGAIN) ||
00421 (res == GNUTLS_E_INTERRUPTED) )
00422 {
00423 errno = EINTR;
00424 return -1;
00425 }
00426 return res;
00427 }
00428
00429
00436 static int
00437 MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
00438 {
00439 gnutls_datum_t key;
00440 gnutls_datum_t cert;
00441
00442 if (daemon->https_mem_trust) {
00443 cert.data = (unsigned char *) daemon->https_mem_trust;
00444 cert.size = strlen(daemon->https_mem_trust);
00445 if (gnutls_certificate_set_x509_trust_mem(daemon->x509_cred, &cert,
00446 GNUTLS_X509_FMT_PEM) < 0) {
00447 #if HAVE_MESSAGES
00448 MHD_DLOG(daemon,
00449 "Bad trust certificate format\n");
00450 #endif
00451 return -1;
00452 }
00453 }
00454
00455
00456 if (daemon->https_mem_cert && daemon->https_mem_key)
00457 {
00458 key.data = (unsigned char *) daemon->https_mem_key;
00459 key.size = strlen (daemon->https_mem_key);
00460 cert.data = (unsigned char *) daemon->https_mem_cert;
00461 cert.size = strlen (daemon->https_mem_cert);
00462
00463 return gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
00464 &cert, &key,
00465 GNUTLS_X509_FMT_PEM);
00466 }
00467 #if HAVE_MESSAGES
00468 MHD_DLOG (daemon, "You need to specify a certificate and key location\n");
00469 #endif
00470 return -1;
00471 }
00472
00479 static int
00480 MHD_TLS_init (struct MHD_Daemon *daemon)
00481 {
00482 switch (daemon->cred_type)
00483 {
00484 case GNUTLS_CRD_CERTIFICATE:
00485 if (0 !=
00486 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
00487 return GNUTLS_E_MEMORY_ERROR;
00488 return MHD_init_daemon_certificate (daemon);
00489 default:
00490 #if HAVE_MESSAGES
00491 MHD_DLOG (daemon,
00492 "Error: invalid credentials type %d specified.\n",
00493 daemon->cred_type);
00494 #endif
00495 return -1;
00496 }
00497 }
00498 #endif
00499
00513 int
00514 MHD_get_fdset (struct MHD_Daemon *daemon,
00515 fd_set * read_fd_set,
00516 fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd)
00517 {
00518 struct MHD_Connection *con_itr;
00519 int fd;
00520
00521 if ((daemon == NULL) || (read_fd_set == NULL) || (write_fd_set == NULL)
00522 || (except_fd_set == NULL) || (max_fd == NULL)
00523 || (-1 == (fd = daemon->socket_fd)) || (daemon->shutdown == MHD_YES)
00524 || ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0)
00525 || ((daemon->options & MHD_USE_POLL) != 0))
00526 return MHD_NO;
00527
00528 FD_SET (fd, read_fd_set);
00529
00530 if ((*max_fd) < fd)
00531 *max_fd = fd;
00532
00533 con_itr = daemon->connections;
00534 while (con_itr != NULL)
00535 {
00536 if (MHD_YES != MHD_connection_get_fdset (con_itr,
00537 read_fd_set,
00538 write_fd_set,
00539 except_fd_set, max_fd))
00540 return MHD_NO;
00541 con_itr = con_itr->next;
00542 }
00543 #if DEBUG_CONNECT
00544 MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
00545 #endif
00546 return MHD_YES;
00547 }
00548
00556 static void *
00557 MHD_handle_connection (void *data)
00558 {
00559 struct MHD_Connection *con = data;
00560 int num_ready;
00561 fd_set rs;
00562 fd_set ws;
00563 fd_set es;
00564 int max;
00565 struct timeval tv;
00566 unsigned int timeout;
00567 #ifdef HAVE_POLL_H
00568 struct MHD_Pollfd mp;
00569 struct pollfd p;
00570 #endif
00571
00572 timeout = con->daemon->connection_timeout;
00573 while ((!con->daemon->shutdown) && (con->socket_fd != -1)) {
00574 tv.tv_usec = 0;
00575 if ( (timeout > (time (NULL) - con->last_activity)) ||
00576 (timeout == 0) )
00577 {
00578
00579
00580 tv.tv_sec = 1;
00581 if ((con->state == MHD_CONNECTION_NORMAL_BODY_UNREADY) ||
00582 (con->state == MHD_CONNECTION_CHUNKED_BODY_UNREADY))
00583 {
00584
00585 tv.tv_sec = 0;
00586 }
00587 }
00588 else
00589 {
00590 tv.tv_sec = 0;
00591 }
00592 #ifdef HAVE_POLL_H
00593 if (0 == (con->daemon->options & MHD_USE_POLL)) {
00594 #else
00595 {
00596 #endif
00597
00598 FD_ZERO (&rs);
00599 FD_ZERO (&ws);
00600 FD_ZERO (&es);
00601 max = 0;
00602 MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
00603 num_ready = SELECT (max + 1, &rs, &ws, &es, &tv);
00604 if (num_ready < 0) {
00605 if (errno == EINTR)
00606 continue;
00607 #if HAVE_MESSAGES
00608 MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n", max,
00609 STRERROR (errno));
00610 #endif
00611 break;
00612 }
00613
00614 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &rs)))
00615 con->read_handler (con);
00616 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
00617 con->write_handler (con);
00618 if (con->socket_fd != -1)
00619 con->idle_handler (con);
00620 }
00621 #ifdef HAVE_POLL_H
00622 else
00623 {
00624
00625 memset(&mp, 0, sizeof (struct MHD_Pollfd));
00626 MHD_connection_get_pollfd(con, &mp);
00627 memset(&p, 0, sizeof (struct pollfd));
00628 p.fd = mp.fd;
00629 if (mp.events & MHD_POLL_ACTION_IN)
00630 p.events |= POLLIN;
00631 if (mp.events & MHD_POLL_ACTION_OUT)
00632 p.events |= POLLOUT;
00633
00634
00635 if (poll (&p, 1, 1000) < 0) {
00636 if (errno == EINTR)
00637 continue;
00638 #if HAVE_MESSAGES
00639 MHD_DLOG (con->daemon, "Error during poll: `%s'\n",
00640 STRERROR (errno));
00641 #endif
00642 break;
00643 }
00644 if ( (con->socket_fd != -1) &&
00645 (0 != (p.revents & POLLIN)) )
00646 con->read_handler (con);
00647 if ( (con->socket_fd != -1) &&
00648 (0 != (p.revents & POLLOUT)) )
00649 con->write_handler (con);
00650 if (con->socket_fd != -1)
00651 con->idle_handler (con);
00652 if ( (con->socket_fd != -1) &&
00653 (0 != (p.revents & (POLLERR | POLLHUP))) )
00654 MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR);
00655 }
00656 #endif
00657 }
00658 if (con->socket_fd != -1)
00659 {
00660 #if DEBUG_CLOSE
00661 #if HAVE_MESSAGES
00662 MHD_DLOG (con->daemon,
00663 "Processing thread terminating, closing connection\n");
00664 #endif
00665 #endif
00666 MHD_connection_close (con, MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
00667 }
00668 return NULL;
00669 }
00670
00679 static ssize_t
00680 recv_param_adapter (struct MHD_Connection *connection, void *other, size_t i)
00681 {
00682 if (connection->socket_fd == -1)
00683 return -1;
00684 if (0 != (connection->daemon->options & MHD_USE_SSL))
00685 return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
00686 return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT);
00687 }
00688
00697 static ssize_t
00698 send_param_adapter (struct MHD_Connection *connection,
00699 const void *other, size_t i)
00700 {
00701 #if LINUX
00702 int fd;
00703 off_t offset;
00704 int ret;
00705 #endif
00706 if (connection->socket_fd == -1)
00707 return -1;
00708 if (0 != (connection->daemon->options & MHD_USE_SSL))
00709 return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
00710 #if LINUX
00711 if ( (connection->write_buffer_append_offset ==
00712 connection->write_buffer_send_offset) &&
00713 (NULL != connection->response) &&
00714 (-1 != (fd = connection->response->fd)) )
00715 {
00716
00717 offset = (off_t) connection->response_write_position + connection->response->fd_off;
00718 ret = sendfile (connection->socket_fd,
00719 fd,
00720 &offset,
00721 connection->response->total_size - offset);
00722 if ( (ret == -1) &&
00723 (errno == EINTR) )
00724 return 0;
00725 return ret;
00726 }
00727 #endif
00728 return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT);
00729 }
00730
00731
00732 #if HTTPS_SUPPORT
00733
00737 static void
00738 socket_set_nonblocking (int fd)
00739 {
00740 #if MINGW
00741 u_long mode;
00742 mode = 1;
00743 if (ioctlsocket (fd, FIONBIO, &mode) == SOCKET_ERROR)
00744 {
00745 SetErrnoFromWinsockError (WSAGetLastError ());
00746 #if HAVE_MESSAGES
00747 FPRINTF(stderr, "Failed to make socket non-blocking: %s\n",
00748 STRERROR (errno));
00749 #endif
00750 }
00751 #else
00752
00753
00754 int flags = fcntl (fd, F_GETFL);
00755 if ( (flags == -1) ||
00756 (0 != fcntl (fd, F_SETFL, flags | O_NONBLOCK)) )
00757 {
00758 #if HAVE_MESSAGES
00759 FPRINTF(stderr, "Failed to make socket non-blocking: %s\n",
00760 STRERROR (errno));
00761 #endif
00762 }
00763 #endif
00764 }
00765 #endif
00766
00767
00777 static int
00778 create_thread (pthread_t * thread,
00779 const struct MHD_Daemon *daemon,
00780 void *(*start_routine)(void*),
00781 void *arg)
00782 {
00783 pthread_attr_t attr;
00784 pthread_attr_t *pattr;
00785 int ret;
00786
00787 if (daemon->thread_stack_size != 0)
00788 {
00789 if (0 != (ret = pthread_attr_init (&attr)))
00790 goto ERR;
00791 if (0 != (ret = pthread_attr_setstacksize (&attr, daemon->thread_stack_size)))
00792 {
00793 pthread_attr_destroy (&attr);
00794 goto ERR;
00795 }
00796 pattr = &attr;
00797 }
00798 else
00799 {
00800 pattr = NULL;
00801 }
00802 ret = pthread_create (thread, pattr,
00803 start_routine, arg);
00804 if (daemon->thread_stack_size != 0)
00805 pthread_attr_destroy (&attr);
00806 return ret;
00807 ERR:
00808 #if HAVE_MESSAGES
00809 MHD_DLOG (daemon,
00810 "Failed to set thread stack size\n");
00811 #endif
00812 errno = EINVAL;
00813 return ret;
00814 }
00815
00816
00817
00826 static int
00827 MHD_accept_connection (struct MHD_Daemon *daemon)
00828 {
00829 struct MHD_Connection *connection;
00830 #if HAVE_INET6
00831 struct sockaddr_in6 addrstorage;
00832 #else
00833 struct sockaddr_in addrstorage;
00834 #endif
00835 struct sockaddr *addr = (struct sockaddr *) &addrstorage;
00836 socklen_t addrlen;
00837 int s;
00838 int res_thread_create;
00839 #if OSX
00840 static int on = 1;
00841 #endif
00842
00843 addrlen = sizeof (addrstorage);
00844 memset (addr, 0, sizeof (addrstorage));
00845
00846 s = ACCEPT (daemon->socket_fd, addr, &addrlen);
00847 if ((s == -1) || (addrlen <= 0))
00848 {
00849 #if HAVE_MESSAGES
00850
00851 if ((EAGAIN != errno) && (EWOULDBLOCK != errno))
00852 MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));
00853 #endif
00854 if (s != -1)
00855 {
00856 SHUTDOWN (s, SHUT_RDWR);
00857 CLOSE (s);
00858
00859 }
00860 return MHD_NO;
00861 }
00862 #ifndef WINDOWS
00863 if ( (s >= FD_SETSIZE) &&
00864 (0 == (daemon->options & MHD_USE_POLL)) )
00865 {
00866 #if HAVE_MESSAGES
00867 MHD_DLOG (daemon,
00868 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
00869 s,
00870 FD_SETSIZE);
00871 #endif
00872 CLOSE (s);
00873 return MHD_NO;
00874 }
00875 #endif
00876
00877
00878 #if HAVE_MESSAGES
00879 #if DEBUG_CONNECT
00880 MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
00881 #endif
00882 #endif
00883 if ((daemon->max_connections == 0)
00884 || (MHD_ip_limit_add (daemon, addr, addrlen) == MHD_NO))
00885 {
00886
00887 #if HAVE_MESSAGES
00888 MHD_DLOG (daemon,
00889 "Server reached connection limit (closing inbound connection)\n");
00890 #endif
00891 SHUTDOWN (s, SHUT_RDWR);
00892 CLOSE (s);
00893 return MHD_NO;
00894 }
00895
00896
00897 if ((daemon->apc != NULL)
00898 && (MHD_NO == daemon->apc (daemon->apc_cls, addr, addrlen)))
00899 {
00900 #if DEBUG_CLOSE
00901 #if HAVE_MESSAGES
00902 MHD_DLOG (daemon, "Connection rejected, closing connection\n");
00903 #endif
00904 #endif
00905 SHUTDOWN (s, SHUT_RDWR);
00906 CLOSE (s);
00907 MHD_ip_limit_del (daemon, addr, addrlen);
00908 return MHD_YES;
00909 }
00910 #if OSX
00911 #ifdef SOL_SOCKET
00912 #ifdef SO_NOSIGPIPE
00913 setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof (on));
00914 #endif
00915 #endif
00916 #endif
00917 connection = malloc (sizeof (struct MHD_Connection));
00918 if (NULL == connection)
00919 {
00920 #if HAVE_MESSAGES
00921 MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00922 #endif
00923 SHUTDOWN (s, SHUT_RDWR);
00924 CLOSE (s);
00925 MHD_ip_limit_del (daemon, addr, addrlen);
00926 return MHD_NO;
00927 }
00928 memset (connection, 0, sizeof (struct MHD_Connection));
00929 connection->pool = NULL;
00930 connection->addr = malloc (addrlen);
00931 if (connection->addr == NULL)
00932 {
00933 #if HAVE_MESSAGES
00934 MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00935 #endif
00936 SHUTDOWN (s, SHUT_RDWR);
00937 CLOSE (s);
00938 MHD_ip_limit_del (daemon, addr, addrlen);
00939 free (connection);
00940 return MHD_NO;
00941 }
00942 memcpy (connection->addr, addr, addrlen);
00943 connection->addr_len = addrlen;
00944 connection->socket_fd = s;
00945 connection->daemon = daemon;
00946 connection->last_activity = time (NULL);
00947
00948
00949 MHD_set_http_callbacks_ (connection);
00950 connection->recv_cls = &recv_param_adapter;
00951 connection->send_cls = &send_param_adapter;
00952 #if HTTPS_SUPPORT
00953 if (0 != (daemon->options & MHD_USE_SSL))
00954 {
00955 connection->recv_cls = &recv_tls_adapter;
00956 connection->send_cls = &send_tls_adapter;
00957 connection->state = MHD_TLS_CONNECTION_INIT;
00958 MHD_set_https_callbacks (connection);
00959 gnutls_init (&connection->tls_session, GNUTLS_SERVER);
00960 gnutls_priority_set (connection->tls_session,
00961 daemon->priority_cache);
00962 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00963 {
00964
00965 socket_set_nonblocking (connection->socket_fd);
00966 }
00967 switch (connection->daemon->cred_type)
00968 {
00969
00970 case GNUTLS_CRD_CERTIFICATE:
00971 gnutls_credentials_set (connection->tls_session,
00972 GNUTLS_CRD_CERTIFICATE,
00973 connection->daemon->x509_cred);
00974 break;
00975 default:
00976 #if HAVE_MESSAGES
00977 MHD_DLOG (connection->daemon,
00978 "Failed to setup TLS credentials: unknown credential type %d\n",
00979 connection->daemon->cred_type);
00980 #endif
00981 SHUTDOWN (s, SHUT_RDWR);
00982 CLOSE (s);
00983 MHD_ip_limit_del (daemon, addr, addrlen);
00984 free (connection->addr);
00985 free (connection);
00986 mhd_panic (mhd_panic_cls, __FILE__, __LINE__,
00987 #if HAVE_MESSAGES
00988 "Unknown credential type"
00989 #else
00990 NULL
00991 #endif
00992 );
00993 return MHD_NO;
00994 }
00995 gnutls_transport_set_ptr (connection->tls_session,
00996 (gnutls_transport_ptr_t) connection);
00997 gnutls_transport_set_pull_function (connection->tls_session,
00998 (gnutls_pull_func) &
00999 recv_param_adapter);
01000 gnutls_transport_set_push_function (connection->tls_session,
01001 (gnutls_push_func) &
01002 send_param_adapter);
01003
01004 if (daemon->https_mem_trust){
01005 gnutls_certificate_server_set_request(connection->tls_session, GNUTLS_CERT_REQUEST);
01006 }
01007 }
01008 #endif
01009
01010
01011 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01012 {
01013 res_thread_create = create_thread (&connection->pid, daemon,
01014 &MHD_handle_connection, connection);
01015 if (res_thread_create != 0)
01016 {
01017 #if HAVE_MESSAGES
01018 MHD_DLOG (daemon, "Failed to create a thread: %s\n",
01019 STRERROR (res_thread_create));
01020 #endif
01021 SHUTDOWN (s, SHUT_RDWR);
01022 CLOSE (s);
01023 MHD_ip_limit_del (daemon, addr, addrlen);
01024 free (connection->addr);
01025 free (connection);
01026 return MHD_NO;
01027 }
01028 }
01029 connection->next = daemon->connections;
01030 daemon->connections = connection;
01031 daemon->max_connections--;
01032 return MHD_YES;
01033 }
01034
01042 static void
01043 MHD_cleanup_connections (struct MHD_Daemon *daemon)
01044 {
01045 struct MHD_Connection *pos;
01046 struct MHD_Connection *prev;
01047 void *unused;
01048 int rc;
01049
01050 pos = daemon->connections;
01051 prev = NULL;
01052 while (pos != NULL)
01053 {
01054 if ((pos->socket_fd == -1) ||
01055 (((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01056 (daemon->shutdown) && (pos->socket_fd != -1))))
01057 {
01058 if (prev == NULL)
01059 daemon->connections = pos->next;
01060 else
01061 prev->next = pos->next;
01062 if (0 != (pos->daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01063 {
01064 pthread_kill (pos->pid, SIGALRM);
01065 if (0 != (rc = pthread_join (pos->pid, &unused)))
01066 {
01067 #if HAVE_MESSAGES
01068 MHD_DLOG (daemon, "Failed to join a thread: %s\n",
01069 STRERROR (rc));
01070 #endif
01071 abort();
01072 }
01073 }
01074 MHD_pool_destroy (pos->pool);
01075 #if HTTPS_SUPPORT
01076 if (pos->tls_session != NULL)
01077 gnutls_deinit (pos->tls_session);
01078 #endif
01079 MHD_ip_limit_del (daemon, (struct sockaddr*)pos->addr, pos->addr_len);
01080 if (pos->response != NULL)
01081 {
01082 MHD_destroy_response (pos->response);
01083 pos->response = NULL;
01084 }
01085 free (pos->addr);
01086 free (pos);
01087 daemon->max_connections++;
01088 if (prev == NULL)
01089 pos = daemon->connections;
01090 else
01091 pos = prev->next;
01092 continue;
01093 }
01094 prev = pos;
01095 pos = pos->next;
01096 }
01097 }
01098
01111 int
01112 MHD_get_timeout (struct MHD_Daemon *daemon, unsigned MHD_LONG_LONG *timeout)
01113 {
01114 time_t earliest_deadline;
01115 time_t now;
01116 struct MHD_Connection *pos;
01117 unsigned int dto;
01118
01119 dto = daemon->connection_timeout;
01120 if (0 == dto)
01121 return MHD_NO;
01122 pos = daemon->connections;
01123 if (pos == NULL)
01124 return MHD_NO;
01125 now = time (NULL);
01126
01127 earliest_deadline = now + dto;
01128 while (pos != NULL)
01129 {
01130 if (earliest_deadline > pos->last_activity + dto)
01131 earliest_deadline = pos->last_activity + dto;
01132 #if HTTPS_SUPPORT
01133 if ( (0 != (daemon->options & MHD_USE_SSL)) &&
01134 (0 != gnutls_record_check_pending (pos->tls_session)) )
01135 earliest_deadline = now;
01136 #endif
01137 pos = pos->next;
01138 }
01139 if (earliest_deadline < now)
01140 *timeout = 0;
01141 else
01142 *timeout = (earliest_deadline - now);
01143 return MHD_YES;
01144 }
01145
01146
01154 static int
01155 MHD_select (struct MHD_Daemon *daemon, int may_block)
01156 {
01157 struct MHD_Connection *pos;
01158 int num_ready;
01159 fd_set rs;
01160 fd_set ws;
01161 fd_set es;
01162 int max;
01163 struct timeval timeout;
01164 unsigned MHD_LONG_LONG ltimeout;
01165 int ds;
01166
01167 timeout.tv_sec = 0;
01168 timeout.tv_usec = 0;
01169 if (daemon->shutdown == MHD_YES)
01170 return MHD_NO;
01171 FD_ZERO (&rs);
01172 FD_ZERO (&ws);
01173 FD_ZERO (&es);
01174 max = 0;
01175
01176 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01177 {
01178
01179 if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
01180 return MHD_NO;
01181
01182
01183
01184 if ( (daemon->max_connections == 0) && (daemon->socket_fd != -1) )
01185 FD_CLR(daemon->socket_fd, &rs);
01186 }
01187 else
01188 {
01189
01190 max = daemon->socket_fd;
01191 if (max == -1)
01192 return MHD_NO;
01193 FD_SET (max, &rs);
01194 }
01195
01196
01197
01198 timeout.tv_usec = 0;
01199 timeout.tv_sec = 1;
01200 if (may_block == MHD_NO)
01201 {
01202 timeout.tv_usec = 0;
01203 timeout.tv_sec = 0;
01204 }
01205 else
01206 {
01207
01208 if ( (MHD_YES == MHD_get_timeout (daemon, <imeout)) &&
01209 (ltimeout < 1000) )
01210 {
01211 timeout.tv_usec = ltimeout * 1000;
01212 timeout.tv_sec = 0;
01213 }
01214 }
01215 num_ready = SELECT (max + 1, &rs, &ws, &es, &timeout);
01216
01217 if (daemon->shutdown == MHD_YES)
01218 return MHD_NO;
01219 if (num_ready < 0)
01220 {
01221 if (errno == EINTR)
01222 return MHD_YES;
01223 #if HAVE_MESSAGES
01224 MHD_DLOG (daemon, "select failed: %s\n", STRERROR (errno));
01225 #endif
01226 return MHD_NO;
01227 }
01228 ds = daemon->socket_fd;
01229 if (ds == -1)
01230 return MHD_YES;
01231
01232
01233 if (FD_ISSET (ds, &rs))
01234 MHD_accept_connection (daemon);
01235 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01236 {
01237
01238 pos = daemon->connections;
01239 while (pos != NULL)
01240 {
01241 ds = pos->socket_fd;
01242 if (ds != -1)
01243 {
01244
01245 if (FD_ISSET (ds, &rs))
01246 pos->read_handler (pos);
01247 if ((pos->socket_fd != -1) && (FD_ISSET (ds, &ws)))
01248 pos->write_handler (pos);
01249 if (pos->socket_fd != -1)
01250 pos->idle_handler (pos);
01251 }
01252 pos = pos->next;
01253 }
01254 }
01255 return MHD_YES;
01256 }
01257
01263 static int
01264 MHD_poll (struct MHD_Daemon *daemon)
01265 {
01266 #ifdef HAVE_POLL_H
01267 struct pollfd p;
01268
01269 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01270 return MHD_NO;
01271 p.fd = daemon->socket_fd;
01272 p.events = POLLIN;
01273 p.revents = 0;
01274
01275 if (poll(&p, 1, 1000) < 0) {
01276 if (errno == EINTR)
01277 return MHD_YES;
01278 #if HAVE_MESSAGES
01279 MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
01280 #endif
01281 return MHD_NO;
01282 }
01283
01284 if (daemon->shutdown == MHD_YES)
01285 return MHD_NO;
01286 if (daemon->socket_fd < 0)
01287 return MHD_YES;
01288 if (0 != (p.revents & POLLIN))
01289 MHD_accept_connection (daemon);
01290 return MHD_YES;
01291 #else
01292 return MHD_NO;
01293 #endif
01294 }
01295
01296
01307 int
01308 MHD_run (struct MHD_Daemon *daemon)
01309 {
01310 if ((daemon->shutdown != MHD_NO) || (0 != (daemon->options
01311 & MHD_USE_THREAD_PER_CONNECTION))
01312 || (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
01313 return MHD_NO;
01314 MHD_select (daemon, MHD_NO);
01315 MHD_cleanup_connections (daemon);
01316 return MHD_YES;
01317 }
01318
01319
01327 static void *
01328 MHD_select_thread (void *cls)
01329 {
01330 struct MHD_Daemon *daemon = cls;
01331 while (daemon->shutdown == MHD_NO)
01332 {
01333 if ((daemon->options & MHD_USE_POLL) == 0)
01334 MHD_select (daemon, MHD_YES);
01335 else
01336 MHD_poll(daemon);
01337 MHD_cleanup_connections (daemon);
01338 }
01339 return NULL;
01340 }
01341
01342
01354 struct MHD_Daemon *
01355 MHD_start_daemon (unsigned int options,
01356 uint16_t port,
01357 MHD_AcceptPolicyCallback apc,
01358 void *apc_cls,
01359 MHD_AccessHandlerCallback dh, void *dh_cls, ...)
01360 {
01361 struct MHD_Daemon *ret;
01362 va_list ap;
01363
01364 va_start (ap, dh_cls);
01365 ret = MHD_start_daemon_va (options, port, apc, apc_cls, dh, dh_cls, ap);
01366 va_end (ap);
01367 return ret;
01368 }
01369
01370
01371 typedef void (*VfprintfFunctionPointerType)(void *, const char *, va_list);
01372
01373
01382 static int
01383 parse_options_va (struct MHD_Daemon *daemon,
01384 const struct sockaddr **servaddr,
01385 va_list ap);
01386
01387
01396 static int
01397 parse_options (struct MHD_Daemon *daemon,
01398 const struct sockaddr **servaddr,
01399 ...)
01400 {
01401 va_list ap;
01402 int ret;
01403
01404 va_start (ap, servaddr);
01405 ret = parse_options_va (daemon, servaddr, ap);
01406 va_end (ap);
01407 return ret;
01408 }
01409
01410
01419 static int
01420 parse_options_va (struct MHD_Daemon *daemon,
01421 const struct sockaddr **servaddr,
01422 va_list ap)
01423 {
01424 enum MHD_OPTION opt;
01425 struct MHD_OptionItem *oa;
01426 unsigned int i;
01427 #if HTTPS_SUPPORT
01428 int ret;
01429 const char *pstr;
01430 #endif
01431
01432 while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
01433 {
01434 switch (opt)
01435 {
01436 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
01437 daemon->pool_size = va_arg (ap, size_t);
01438 break;
01439 case MHD_OPTION_CONNECTION_LIMIT:
01440 daemon->max_connections = va_arg (ap, unsigned int);
01441 break;
01442 case MHD_OPTION_CONNECTION_TIMEOUT:
01443 daemon->connection_timeout = va_arg (ap, unsigned int);
01444 break;
01445 case MHD_OPTION_NOTIFY_COMPLETED:
01446 daemon->notify_completed =
01447 va_arg (ap, MHD_RequestCompletedCallback);
01448 daemon->notify_completed_cls = va_arg (ap, void *);
01449 break;
01450 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
01451 daemon->per_ip_connection_limit = va_arg (ap, unsigned int);
01452 break;
01453 case MHD_OPTION_SOCK_ADDR:
01454 *servaddr = va_arg (ap, const struct sockaddr *);
01455 break;
01456 case MHD_OPTION_URI_LOG_CALLBACK:
01457 daemon->uri_log_callback =
01458 va_arg (ap, LogCallback);
01459 daemon->uri_log_callback_cls = va_arg (ap, void *);
01460 break;
01461 case MHD_OPTION_THREAD_POOL_SIZE:
01462 daemon->worker_pool_size = va_arg (ap, unsigned int);
01463 if (daemon->worker_pool_size >= SIZE_MAX / sizeof (struct MHD_Daemon))
01464 {
01465 #if HAVE_MESSAGES
01466 FPRINTF (stderr,
01467 "Specified thread pool size (%u) too big\n",
01468 daemon->worker_pool_size);
01469 #endif
01470 return MHD_NO;
01471 }
01472 break;
01473 #if HTTPS_SUPPORT
01474 case MHD_OPTION_HTTPS_MEM_KEY:
01475 if (0 != (daemon->options & MHD_USE_SSL))
01476 daemon->https_mem_key = va_arg (ap, const char *);
01477 #if HAVE_MESSAGES
01478 else
01479 FPRINTF (stderr,
01480 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01481 opt);
01482 #endif
01483 break;
01484 case MHD_OPTION_HTTPS_MEM_CERT:
01485 if (0 != (daemon->options & MHD_USE_SSL))
01486 daemon->https_mem_cert = va_arg (ap, const char *);
01487 #if HAVE_MESSAGES
01488 else
01489 FPRINTF (stderr,
01490 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01491 opt);
01492 #endif
01493 break;
01494 case MHD_OPTION_HTTPS_MEM_TRUST:
01495 if (0 != (daemon->options & MHD_USE_SSL))
01496 daemon->https_mem_trust = va_arg (ap, const char *);
01497 #if HAVE_MESSAGES
01498 else
01499 FPRINTF (stderr,
01500 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01501 opt);
01502 #endif
01503 break;
01504 case MHD_OPTION_HTTPS_CRED_TYPE:
01505 daemon->cred_type = va_arg (ap, gnutls_credentials_type_t);
01506 break;
01507 case MHD_OPTION_HTTPS_PRIORITIES:
01508 ret = gnutls_priority_init (&daemon->priority_cache,
01509 pstr = va_arg (ap, const char*),
01510 NULL);
01511 #if HAVE_MESSAGES
01512 if (ret != GNUTLS_E_SUCCESS)
01513 FPRINTF (stderr,
01514 "Setting priorities to `%s' failed: %s\n",
01515 pstr,
01516 gnutls_strerror (ret));
01517 #endif
01518 if (ret != GNUTLS_E_SUCCESS)
01519 return MHD_NO;
01520 break;
01521 #endif
01522 #ifdef DAUTH_SUPPORT
01523 case MHD_OPTION_DIGEST_AUTH_RANDOM:
01524 daemon->digest_auth_rand_size = va_arg (ap, size_t);
01525 daemon->digest_auth_random = va_arg (ap, const char *);
01526 break;
01527 case MHD_OPTION_NONCE_NC_SIZE:
01528 daemon->nonce_nc_size = va_arg (ap, unsigned int);
01529 break;
01530 #endif
01531 case MHD_OPTION_LISTEN_SOCKET:
01532 daemon->socket_fd = va_arg (ap, int);
01533 break;
01534 case MHD_OPTION_EXTERNAL_LOGGER:
01535 #if HAVE_MESSAGES
01536 daemon->custom_error_log =
01537 va_arg (ap, VfprintfFunctionPointerType);
01538 daemon->custom_error_log_cls = va_arg (ap, void *);
01539 #else
01540 va_arg (ap, VfprintfFunctionPointerType);
01541 va_arg (ap, void *);
01542 #endif
01543 break;
01544 case MHD_OPTION_THREAD_STACK_SIZE:
01545 daemon->thread_stack_size = va_arg (ap, size_t);
01546 break;
01547 case MHD_OPTION_ARRAY:
01548 oa = va_arg (ap, struct MHD_OptionItem*);
01549 i = 0;
01550 while (MHD_OPTION_END != (opt = oa[i].option))
01551 {
01552 switch (opt)
01553 {
01554
01555 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
01556 case MHD_OPTION_THREAD_STACK_SIZE:
01557 if (MHD_YES != parse_options (daemon,
01558 servaddr,
01559 opt,
01560 (size_t) oa[i].value,
01561 MHD_OPTION_END))
01562 return MHD_NO;
01563 break;
01564
01565 case MHD_OPTION_NONCE_NC_SIZE:
01566 case MHD_OPTION_CONNECTION_LIMIT:
01567 case MHD_OPTION_CONNECTION_TIMEOUT:
01568 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
01569 case MHD_OPTION_THREAD_POOL_SIZE:
01570 if (MHD_YES != parse_options (daemon,
01571 servaddr,
01572 opt,
01573 (unsigned int) oa[i].value,
01574 MHD_OPTION_END))
01575 return MHD_NO;
01576 break;
01577
01578 case MHD_OPTION_HTTPS_CRED_TYPE:
01579 case MHD_OPTION_LISTEN_SOCKET:
01580 if (MHD_YES != parse_options (daemon,
01581 servaddr,
01582 opt,
01583 (int) oa[i].value,
01584 MHD_OPTION_END))
01585 return MHD_NO;
01586 break;
01587
01588 case MHD_OPTION_SOCK_ADDR:
01589 case MHD_OPTION_HTTPS_MEM_KEY:
01590 case MHD_OPTION_HTTPS_MEM_CERT:
01591 case MHD_OPTION_HTTPS_MEM_TRUST:
01592 case MHD_OPTION_HTTPS_PRIORITIES:
01593 case MHD_OPTION_ARRAY:
01594 if (MHD_YES != parse_options (daemon,
01595 servaddr,
01596 opt,
01597 oa[i].ptr_value,
01598 MHD_OPTION_END))
01599 return MHD_NO;
01600 break;
01601
01602 case MHD_OPTION_NOTIFY_COMPLETED:
01603 case MHD_OPTION_URI_LOG_CALLBACK:
01604 case MHD_OPTION_EXTERNAL_LOGGER:
01605 case MHD_OPTION_UNESCAPE_CALLBACK:
01606 if (MHD_YES != parse_options (daemon,
01607 servaddr,
01608 opt,
01609 (void *) oa[i].value,
01610 oa[i].ptr_value,
01611 MHD_OPTION_END))
01612 return MHD_NO;
01613 break;
01614
01615 case MHD_OPTION_DIGEST_AUTH_RANDOM:
01616 if (MHD_YES != parse_options (daemon,
01617 servaddr,
01618 opt,
01619 (size_t) oa[i].value,
01620 oa[i].ptr_value,
01621 MHD_OPTION_END))
01622 return MHD_NO;
01623 break;
01624 default:
01625 return MHD_NO;
01626 }
01627 i++;
01628 }
01629 break;
01630 case MHD_OPTION_UNESCAPE_CALLBACK:
01631 daemon->unescape_callback =
01632 va_arg (ap, UnescapeCallback);
01633 daemon->unescape_callback_cls = va_arg (ap, void *);
01634 break;
01635 default:
01636 #if HAVE_MESSAGES
01637 if (((opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
01638 (opt <= MHD_OPTION_HTTPS_PRIORITIES)) || (opt == MHD_OPTION_HTTPS_MEM_TRUST))
01639 {
01640 FPRINTF (stderr,
01641 "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
01642 opt);
01643 }
01644 else
01645 {
01646 FPRINTF (stderr,
01647 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
01648 opt);
01649 }
01650 #endif
01651 return MHD_NO;
01652 }
01653 }
01654 return MHD_YES;
01655 }
01656
01657
01669 struct MHD_Daemon *
01670 MHD_start_daemon_va (unsigned int options,
01671 uint16_t port,
01672 MHD_AcceptPolicyCallback apc,
01673 void *apc_cls,
01674 MHD_AccessHandlerCallback dh, void *dh_cls,
01675 va_list ap)
01676 {
01677 const int on = 1;
01678 struct MHD_Daemon *retVal;
01679 int socket_fd;
01680 struct sockaddr_in servaddr4;
01681 #if HAVE_INET6
01682 struct sockaddr_in6 servaddr6;
01683 #endif
01684 const struct sockaddr *servaddr = NULL;
01685 socklen_t addrlen;
01686 unsigned int i;
01687 int res_thread_create;
01688
01689 if ((port == 0) || (dh == NULL))
01690 return NULL;
01691 retVal = malloc (sizeof (struct MHD_Daemon));
01692 if (retVal == NULL)
01693 return NULL;
01694 memset (retVal, 0, sizeof (struct MHD_Daemon));
01695 #if HTTPS_SUPPORT
01696 if (options & MHD_USE_SSL)
01697 {
01698 gnutls_priority_init (&retVal->priority_cache,
01699 "NORMAL",
01700 NULL);
01701 }
01702 #endif
01703 retVal->socket_fd = -1;
01704 retVal->options = (enum MHD_OPTION)options;
01705 retVal->port = port;
01706 retVal->apc = apc;
01707 retVal->apc_cls = apc_cls;
01708 retVal->default_handler = dh;
01709 retVal->default_handler_cls = dh_cls;
01710 retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
01711 retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
01712 retVal->unescape_callback = &MHD_http_unescape;
01713 retVal->connection_timeout = 0;
01714 #ifdef DAUTH_SUPPORT
01715 retVal->digest_auth_rand_size = 0;
01716 retVal->digest_auth_random = NULL;
01717 retVal->nonce_nc_size = 4;
01718 #endif
01719 #if HAVE_MESSAGES
01720 retVal->custom_error_log =
01721 (void (*)(void *, const char *, va_list)) &vfprintf;
01722 retVal->custom_error_log_cls = stderr;
01723 #endif
01724 #if HTTPS_SUPPORT
01725 if (options & MHD_USE_SSL)
01726 {
01727
01728 if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
01729 {
01730 #if HAVE_MESSAGES
01731 MHD_DLOG (retVal, "Failed to aquire gnutls mutex\n");
01732 #endif
01733 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01734 }
01735 if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
01736 {
01737 #if HAVE_MESSAGES
01738 MHD_DLOG (retVal, "Failed to release gnutls mutex\n");
01739 #endif
01740 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01741 }
01742 retVal->cred_type = GNUTLS_CRD_CERTIFICATE;
01743 }
01744 #endif
01745
01746 if (MHD_YES != parse_options_va (retVal, &servaddr, ap))
01747 {
01748 free (retVal);
01749 return NULL;
01750 }
01751
01752 #ifdef DAUTH_SUPPORT
01753 if (retVal->nonce_nc_size > 0)
01754 {
01755 if ( ( (size_t) (retVal->nonce_nc_size * sizeof(struct MHD_NonceNc))) /
01756 sizeof(struct MHD_NonceNc) != retVal->nonce_nc_size)
01757 {
01758 #if HAVE_MESSAGES
01759 MHD_DLOG (retVal,
01760 "Specified value for NC_SIZE too large\n");
01761 #endif
01762 free (retVal);
01763 return NULL;
01764 }
01765 retVal->nnc = malloc (retVal->nonce_nc_size * sizeof(struct MHD_NonceNc));
01766 if (NULL == retVal->nnc)
01767 {
01768 #if HAVE_MESSAGES
01769 MHD_DLOG (retVal,
01770 "Failed to allocate memory for nonce-nc map: %s\n",
01771 STRERROR (errno));
01772 #endif
01773 free (retVal);
01774 return NULL;
01775 }
01776 }
01777 if (0 != pthread_mutex_init (&retVal->nnc_lock, NULL))
01778 {
01779 #if HAVE_MESSAGES
01780 MHD_DLOG (retVal,
01781 "MHD failed to initialize nonce-nc mutex\n");
01782 #endif
01783 free (retVal);
01784 return NULL;
01785 }
01786 #endif
01787
01788
01789 if ( (0 != (options & MHD_USE_POLL)) &&
01790 (0 == (options & MHD_USE_THREAD_PER_CONNECTION)) )
01791 {
01792 #if HAVE_MESSAGES
01793 MHD_DLOG (retVal,
01794 "MHD poll support only works with MHD_USE_THREAD_PER_CONNECTION\n");
01795 #endif
01796 #if DAUTH_SUPPORT
01797 free (retVal->nnc);
01798 pthread_mutex_destroy (&retVal->nnc_lock);
01799 #endif
01800 free (retVal);
01801 return NULL;
01802 }
01803
01804
01805 if ( (0 == (options & MHD_USE_SELECT_INTERNALLY)) &&
01806 (retVal->worker_pool_size > 0) )
01807 {
01808 #if HAVE_MESSAGES
01809 MHD_DLOG (retVal,
01810 "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n");
01811 #endif
01812 free (retVal);
01813 return NULL;
01814 }
01815
01816 #ifdef __SYMBIAN32__
01817 if (0 != (options & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
01818 {
01819 #if HAVE_MESSAGES
01820 MHD_DLOG (retVal,
01821 "Threaded operations are not supported on Symbian.\n");
01822 #endif
01823 free (retVal);
01824 return NULL;
01825 }
01826 #endif
01827 if (retVal->socket_fd == -1)
01828 {
01829 if ((options & MHD_USE_IPv6) != 0)
01830 #if HAVE_INET6
01831 socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0);
01832 #else
01833 {
01834 #if HAVE_MESSAGES
01835 MHD_DLOG (retVal,
01836 "AF_INET6 not supported\n");
01837 #endif
01838 free (retVal);
01839 return NULL;
01840 }
01841 #endif
01842 else
01843 socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0);
01844 if (socket_fd == -1)
01845 {
01846 #if HAVE_MESSAGES
01847 if ((options & MHD_USE_DEBUG) != 0)
01848 MHD_DLOG (retVal,
01849 "Call to socket failed: %s\n",
01850 STRERROR (errno));
01851 #endif
01852 free (retVal);
01853 return NULL;
01854 }
01855 if ((SETSOCKOPT (socket_fd,
01856 SOL_SOCKET,
01857 SO_REUSEADDR,
01858 &on, sizeof (on)) < 0) && ((options & MHD_USE_DEBUG) != 0))
01859 {
01860 #if HAVE_MESSAGES
01861 MHD_DLOG (retVal,
01862 "setsockopt failed: %s\n",
01863 STRERROR (errno));
01864 #endif
01865 }
01866
01867
01868 #if HAVE_INET6
01869 if ((options & MHD_USE_IPv6) != 0)
01870 addrlen = sizeof (struct sockaddr_in6);
01871 else
01872 #endif
01873 addrlen = sizeof (struct sockaddr_in);
01874 if (NULL == servaddr)
01875 {
01876 #if HAVE_INET6
01877 if ((options & MHD_USE_IPv6) != 0)
01878 {
01879 memset (&servaddr6, 0, sizeof (struct sockaddr_in6));
01880 servaddr6.sin6_family = AF_INET6;
01881 servaddr6.sin6_port = htons (port);
01882 servaddr = (struct sockaddr *) &servaddr6;
01883 }
01884 else
01885 #endif
01886 {
01887 memset (&servaddr4, 0, sizeof (struct sockaddr_in));
01888 servaddr4.sin_family = AF_INET;
01889 servaddr4.sin_port = htons (port);
01890 servaddr = (struct sockaddr *) &servaddr4;
01891 }
01892 }
01893 retVal->socket_fd = socket_fd;
01894
01895 if ((options & MHD_USE_IPv6) != 0)
01896 {
01897 #ifdef IPPROTO_IPV6
01898 #ifdef IPV6_V6ONLY
01899
01900
01901
01902
01903 #ifndef WINDOWS
01904 const int on = 1;
01905 setsockopt (socket_fd,
01906 IPPROTO_IPV6, IPV6_V6ONLY,
01907 &on, sizeof (on));
01908 #else
01909 const char on = 1;
01910 setsockopt (socket_fd,
01911 IPPROTO_IPV6, IPV6_V6ONLY,
01912 &on, sizeof (on));
01913 #endif
01914 #endif
01915 #endif
01916 }
01917 if (BIND (socket_fd, servaddr, addrlen) == -1)
01918 {
01919 #if HAVE_MESSAGES
01920 if ((options & MHD_USE_DEBUG) != 0)
01921 MHD_DLOG (retVal,
01922 "Failed to bind to port %u: %s\n",
01923 (unsigned int) port,
01924 STRERROR (errno));
01925 #endif
01926 CLOSE (socket_fd);
01927 free (retVal);
01928 return NULL;
01929 }
01930
01931 if (LISTEN (socket_fd, 20) < 0)
01932 {
01933 #if HAVE_MESSAGES
01934 if ((options & MHD_USE_DEBUG) != 0)
01935 MHD_DLOG (retVal,
01936 "Failed to listen for connections: %s\n",
01937 STRERROR (errno));
01938 #endif
01939 CLOSE (socket_fd);
01940 free (retVal);
01941 return NULL;
01942 }
01943 }
01944 else
01945 {
01946 socket_fd = retVal->socket_fd;
01947 }
01948 #ifndef WINDOWS
01949 if ( (socket_fd >= FD_SETSIZE) &&
01950 (0 == (options & MHD_USE_POLL)) )
01951 {
01952 #if HAVE_MESSAGES
01953 if ((options & MHD_USE_DEBUG) != 0)
01954 MHD_DLOG (retVal,
01955 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
01956 socket_fd,
01957 FD_SETSIZE);
01958 #endif
01959 CLOSE (socket_fd);
01960 free (retVal);
01961 return NULL;
01962 }
01963 #endif
01964
01965 if (0 != pthread_mutex_init (&retVal->per_ip_connection_mutex, NULL))
01966 {
01967 #if HAVE_MESSAGES
01968 MHD_DLOG (retVal,
01969 "MHD failed to initialize IP connection limit mutex\n");
01970 #endif
01971 CLOSE (socket_fd);
01972 free (retVal);
01973 return NULL;
01974 }
01975
01976 #if HTTPS_SUPPORT
01977
01978 if ((0 != (options & MHD_USE_SSL)) && (0 != MHD_TLS_init (retVal)))
01979 {
01980 #if HAVE_MESSAGES
01981 MHD_DLOG (retVal,
01982 "Failed to initialize TLS support\n");
01983 #endif
01984 CLOSE (socket_fd);
01985 #ifdef DAUTH_SUPPORT
01986 pthread_mutex_destroy (&retVal->nnc_lock);
01987 free (retVal->nnc);
01988 #endif
01989 pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
01990 free (retVal);
01991 return NULL;
01992 }
01993 #endif
01994 if ( ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
01995 ( (0 != (options & MHD_USE_SELECT_INTERNALLY)) &&
01996 (0 == retVal->worker_pool_size)) ) &&
01997 (0 != (res_thread_create =
01998 create_thread (&retVal->pid, retVal, &MHD_select_thread, retVal))))
01999 {
02000 #if HAVE_MESSAGES
02001 MHD_DLOG (retVal,
02002 "Failed to create listen thread: %s\n",
02003 STRERROR (res_thread_create));
02004 #endif
02005 #ifdef DAUTH_SUPPORT
02006 pthread_mutex_destroy (&retVal->nnc_lock);
02007 free (retVal->nnc);
02008 #endif
02009 pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
02010 free (retVal);
02011 CLOSE (socket_fd);
02012 return NULL;
02013 }
02014 if (retVal->worker_pool_size > 0)
02015 {
02016 #ifndef MINGW
02017 int sk_flags;
02018 #else
02019 unsigned long sk_flags;
02020 #endif
02021
02022
02023
02024
02025 unsigned int conns_per_thread = retVal->max_connections
02026 / retVal->worker_pool_size;
02027 unsigned int leftover_conns = retVal->max_connections
02028 % retVal->worker_pool_size;
02029
02030 i = 0;
02031
02032
02033
02034
02035 #ifndef MINGW
02036 sk_flags = fcntl (socket_fd, F_GETFL);
02037 if (sk_flags < 0)
02038 goto thread_failed;
02039 if (fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK) < 0)
02040 goto thread_failed;
02041 #else
02042 sk_flags = 1;
02043 #if HAVE_PLIBC_FD
02044 if (ioctlsocket (plibc_fd_get_handle (socket_fd), FIONBIO, &sk_flags) ==
02045 SOCKET_ERROR)
02046 #else
02047 if (ioctlsocket (socket_fd, FIONBIO, &sk_flags) == SOCKET_ERROR)
02048 #endif // PLIBC_FD
02049 goto thread_failed;
02050 #endif // MINGW
02051
02052
02053 retVal->worker_pool = malloc (sizeof (struct MHD_Daemon)
02054 * retVal->worker_pool_size);
02055 if (NULL == retVal->worker_pool)
02056 goto thread_failed;
02057
02058
02059 for (i = 0; i < retVal->worker_pool_size; ++i)
02060 {
02061
02062 struct MHD_Daemon *d = &retVal->worker_pool[i];
02063 memcpy (d, retVal, sizeof (struct MHD_Daemon));
02064
02065
02066
02067
02068 d->master = retVal;
02069 d->worker_pool_size = 0;
02070 d->worker_pool = NULL;
02071
02072
02073
02074
02075 d->max_connections = conns_per_thread;
02076 if (i < leftover_conns)
02077 ++d->max_connections;
02078
02079
02080 if (0 != (res_thread_create = create_thread (&d->pid, retVal, &MHD_select_thread, d)))
02081 {
02082 #if HAVE_MESSAGES
02083 MHD_DLOG (retVal,
02084 "Failed to create pool thread: %s\n",
02085 STRERROR (res_thread_create));
02086 #endif
02087
02088
02089 goto thread_failed;
02090 }
02091 }
02092 }
02093 return retVal;
02094
02095 thread_failed:
02096
02097
02098
02099
02100 if (i == 0)
02101 {
02102 CLOSE (socket_fd);
02103 pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
02104 if (NULL != retVal->worker_pool)
02105 free (retVal->worker_pool);
02106 free (retVal);
02107 return NULL;
02108 }
02109
02110
02111
02112
02113
02114 retVal->worker_pool_size = i - 1;
02115 MHD_stop_daemon (retVal);
02116 return NULL;
02117 }
02118
02122 static void
02123 MHD_close_connections (struct MHD_Daemon *daemon)
02124 {
02125 while (daemon->connections != NULL)
02126 {
02127 if (-1 != daemon->connections->socket_fd)
02128 {
02129 #if DEBUG_CLOSE
02130 #if HAVE_MESSAGES
02131 MHD_DLOG (daemon, "MHD shutdown, closing active connections\n");
02132 #endif
02133 #endif
02134 MHD_connection_close (daemon->connections,
02135 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
02136 }
02137 MHD_cleanup_connections (daemon);
02138 }
02139 }
02140
02144 void
02145 MHD_stop_daemon (struct MHD_Daemon *daemon)
02146 {
02147 void *unused;
02148 int fd;
02149 unsigned int i;
02150 int rc;
02151
02152 if (daemon == NULL)
02153 return;
02154 daemon->shutdown = MHD_YES;
02155 fd = daemon->socket_fd;
02156 daemon->socket_fd = -1;
02157
02158
02159 for (i = 0; i < daemon->worker_pool_size; ++i)
02160 {
02161 daemon->worker_pool[i].shutdown = MHD_YES;
02162 daemon->worker_pool[i].socket_fd = -1;
02163 }
02164
02165 #if OSX
02166
02167
02168
02169 SHUTDOWN (fd, SHUT_RDWR);
02170 #else
02171 #if DEBUG_CLOSE
02172 #if HAVE_MESSAGES
02173 MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
02174 #endif
02175 #endif
02176 CLOSE (fd);
02177 #endif
02178
02179
02180 for (i = 0; i < daemon->worker_pool_size; ++i)
02181 pthread_kill (daemon->worker_pool[i].pid, SIGALRM);
02182 for (i = 0; i < daemon->worker_pool_size; ++i)
02183 {
02184 if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused)))
02185 {
02186 #if HAVE_MESSAGES
02187 MHD_DLOG (daemon, "Failed to join a thread: %s\n",
02188 STRERROR (rc));
02189 #endif
02190 abort();
02191 }
02192 MHD_close_connections (&daemon->worker_pool[i]);
02193 }
02194 free (daemon->worker_pool);
02195
02196 if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
02197 ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))
02198 && (0 == daemon->worker_pool_size)))
02199 {
02200 pthread_kill (daemon->pid, SIGALRM);
02201 if (0 != (rc = pthread_join (daemon->pid, &unused)))
02202 {
02203 #if HAVE_MESSAGES
02204 MHD_DLOG (daemon, "Failed to join a thread: %s\n",
02205 STRERROR (rc));
02206 #endif
02207 abort();
02208 }
02209 }
02210 MHD_close_connections (daemon);
02211
02212 #if OSX
02213 #if DEBUG_CLOSE
02214 #if HAVE_MESSAGES
02215 MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
02216 #endif
02217 #endif
02218 CLOSE (fd);
02219 #endif
02220
02221
02222 #if HTTPS_SUPPORT
02223 if (daemon->options & MHD_USE_SSL)
02224 {
02225 gnutls_priority_deinit (daemon->priority_cache);
02226 if (daemon->x509_cred)
02227 gnutls_certificate_free_credentials (daemon->x509_cred);
02228
02229 if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
02230 {
02231 #if HAVE_MESSAGES
02232 MHD_DLOG (daemon, "Failed to aquire gnutls mutex\n");
02233 #endif
02234 abort();
02235 }
02236 if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
02237 {
02238 #if HAVE_MESSAGES
02239 MHD_DLOG (daemon, "Failed to release gnutls mutex\n");
02240 #endif
02241 abort();
02242 }
02243 }
02244 #endif
02245
02246 #ifdef DAUTH_SUPPORT
02247 free (daemon->nnc);
02248 pthread_mutex_destroy (&daemon->nnc_lock);
02249 #endif
02250 pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
02251 free (daemon);
02252 }
02253
02264 const union MHD_DaemonInfo *
02265 MHD_get_daemon_info (struct MHD_Daemon *daemon,
02266 enum MHD_DaemonInfoType infoType, ...)
02267 {
02268 switch (infoType)
02269 {
02270 case MHD_DAEMON_INFO_LISTEN_FD:
02271 return (const union MHD_DaemonInfo *) &daemon->socket_fd;
02272 default:
02273 return NULL;
02274 };
02275 }
02276
02292 void MHD_set_panic_func (MHD_PanicCallback cb, void *cls)
02293 {
02294 mhd_panic = cb;
02295 mhd_panic_cls = cls;
02296 }
02297
02303 const char *
02304 MHD_get_version (void)
02305 {
02306 return PACKAGE_VERSION;
02307 }
02308
02309 #ifndef WINDOWS
02310
02311 static struct sigaction sig;
02312
02313 static struct sigaction old;
02314
02315 static void
02316 sigalrmHandler (int sig)
02317 {
02318 }
02319 #endif
02320
02321 #ifdef __GNUC__
02322 #define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor))
02323 #define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor))
02324 #else // !__GNUC__
02325 #define ATTRIBUTE_CONSTRUCTOR
02326 #define ATTRIBUTE_DESTRUCTOR
02327 #endif // __GNUC__
02328
02329 #if HTTPS_SUPPORT
02330 GCRY_THREAD_OPTION_PTHREAD_IMPL;
02331 #endif
02332
02337 void ATTRIBUTE_CONSTRUCTOR MHD_init ()
02338 {
02339 mhd_panic = &mhd_panic_std;
02340 mhd_panic_cls = NULL;
02341
02342 #ifndef WINDOWS
02343
02344 memset (&sig, 0, sizeof (struct sigaction));
02345 memset (&old, 0, sizeof (struct sigaction));
02346 sig.sa_flags = SA_NODEFER;
02347 sig.sa_handler = &sigalrmHandler;
02348 sigaction (SIGALRM, &sig, &old);
02349 #else
02350 plibc_init ("GNU", "libmicrohttpd");
02351 #endif
02352 #if HTTPS_SUPPORT
02353 gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
02354 gnutls_global_init ();
02355 if (0 != pthread_mutex_init(&MHD_gnutls_init_mutex, NULL))
02356 abort();
02357 #endif
02358 }
02359
02360 void ATTRIBUTE_DESTRUCTOR MHD_fini ()
02361 {
02362 #if HTTPS_SUPPORT
02363 gnutls_global_deinit ();
02364 if (0 != pthread_mutex_destroy(&MHD_gnutls_init_mutex))
02365 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
02366 #endif
02367 #ifndef WINDOWS
02368 sigaction (SIGALRM, &old, &sig);
02369 #else
02370 plibc_shutdown ();
02371 #endif
02372 }
02373
02374