00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00027 #include "platform.h"
00028 #include "internal.h"
00029 #include "response.h"
00030 #include "connection.h"
00031 #include "memorypool.h"
00032 #include <limits.h>
00033
00034 #if HTTPS_SUPPORT
00035 #include "connection_https.h"
00036 #include <gnutls/gnutls.h>
00037 #include <gcrypt.h>
00038 #endif
00039
00040 #ifdef HAVE_POLL_H
00041 #include <poll.h>
00042 #endif
00043
00044 #ifdef LINUX
00045 #include <sys/sendfile.h>
00046 #endif
00047
00051 #ifndef WINDOWS
00052 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE - 4
00053 #else
00054 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE
00055 #endif
00056
00060 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
00061
00066 #define DEBUG_CLOSE MHD_NO
00067
00072 #define DEBUG_CONNECT MHD_NO
00073
00074 #ifndef LINUX
00075 #ifndef MSG_NOSIGNAL
00076 #define MSG_NOSIGNAL 0
00077 #endif
00078 #endif
00079
00080 #ifndef SOCK_CLOEXEC
00081 #define SOCK_CLOEXEC 0
00082 #endif
00083
00084
00094 static void
00095 mhd_panic_std (void *cls,
00096 const char *file,
00097 unsigned int line,
00098 const char *reason)
00099 {
00100 #if HAVE_MESSAGES
00101 fprintf (stderr, "Fatal error in GNU libmicrohttpd %s:%u: %s\n",
00102 file, line, reason);
00103 #endif
00104 abort ();
00105 }
00106
00107
00111 MHD_PanicCallback mhd_panic;
00112
00116 void *mhd_panic_cls;
00117
00118
00126 static struct MHD_Daemon*
00127 MHD_get_master (struct MHD_Daemon *daemon)
00128 {
00129 while (NULL != daemon->master)
00130 daemon = daemon->master;
00131 return daemon;
00132 }
00133
00134
00138 struct MHD_IPCount
00139 {
00143 int family;
00144
00148 union
00149 {
00153 struct in_addr ipv4;
00154 #if HAVE_IPV6
00155
00158 struct in6_addr ipv6;
00159 #endif
00160 } addr;
00161
00165 unsigned int count;
00166 };
00167
00168
00174 static void
00175 MHD_ip_count_lock(struct MHD_Daemon *daemon)
00176 {
00177 if (0 != pthread_mutex_lock(&daemon->per_ip_connection_mutex))
00178 {
00179 MHD_PANIC ("Failed to acquire IP connection limit mutex\n");
00180 }
00181 }
00182
00183
00189 static void
00190 MHD_ip_count_unlock(struct MHD_Daemon *daemon)
00191 {
00192 if (0 != pthread_mutex_unlock(&daemon->per_ip_connection_mutex))
00193 {
00194 MHD_PANIC ("Failed to release IP connection limit mutex\n");
00195 }
00196 }
00197
00198
00208 static int
00209 MHD_ip_addr_compare(const void *a1, const void *a2)
00210 {
00211 return memcmp (a1, a2, offsetof (struct MHD_IPCount, count));
00212 }
00213
00214
00223 static int
00224 MHD_ip_addr_to_key(const struct sockaddr *addr,
00225 socklen_t addrlen,
00226 struct MHD_IPCount *key)
00227 {
00228 memset(key, 0, sizeof(*key));
00229
00230
00231 if (sizeof (struct sockaddr_in) == addrlen)
00232 {
00233 const struct sockaddr_in *addr4 = (const struct sockaddr_in*) addr;
00234 key->family = AF_INET;
00235 memcpy (&key->addr.ipv4, &addr4->sin_addr, sizeof(addr4->sin_addr));
00236 return MHD_YES;
00237 }
00238
00239 #if HAVE_IPV6
00240
00241 if (sizeof (struct sockaddr_in6) == addrlen)
00242 {
00243 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*) addr;
00244 key->family = AF_INET6;
00245 memcpy (&key->addr.ipv6, &addr6->sin6_addr, sizeof(addr6->sin6_addr));
00246 return MHD_YES;
00247 }
00248 #endif
00249
00250
00251 return MHD_NO;
00252 }
00253
00254
00264 static int
00265 MHD_ip_limit_add(struct MHD_Daemon *daemon,
00266 const struct sockaddr *addr,
00267 socklen_t addrlen)
00268 {
00269 struct MHD_IPCount *key;
00270 void **nodep;
00271 void *node;
00272 int result;
00273
00274 daemon = MHD_get_master (daemon);
00275
00276 if (0 == daemon->per_ip_connection_limit)
00277 return MHD_YES;
00278
00279 if (NULL == (key = malloc (sizeof(*key))))
00280 return MHD_NO;
00281
00282
00283 if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, key))
00284 {
00285
00286 free (key);
00287 return MHD_YES;
00288 }
00289 MHD_ip_count_lock (daemon);
00290
00291
00292 if (NULL == (nodep = TSEARCH (key,
00293 &daemon->per_ip_connection_count,
00294 &MHD_ip_addr_compare)))
00295 {
00296 #if HAVE_MESSAGES
00297 MHD_DLOG (daemon,
00298 "Failed to add IP connection count node\n");
00299 #endif
00300 MHD_ip_count_unlock (daemon);
00301 free (key);
00302 return MHD_NO;
00303 }
00304 node = *nodep;
00305
00306 if (node != key)
00307 free(key);
00308 key = (struct MHD_IPCount *) node;
00309
00310
00311 result = (key->count < daemon->per_ip_connection_limit);
00312 if (MHD_YES == result)
00313 ++key->count;
00314
00315 MHD_ip_count_unlock (daemon);
00316 return result;
00317 }
00318
00319
00328 static void
00329 MHD_ip_limit_del(struct MHD_Daemon *daemon,
00330 const struct sockaddr *addr,
00331 socklen_t addrlen)
00332 {
00333 struct MHD_IPCount search_key;
00334 struct MHD_IPCount *found_key;
00335 void **nodep;
00336
00337 daemon = MHD_get_master (daemon);
00338
00339 if (0 == daemon->per_ip_connection_limit)
00340 return;
00341
00342 if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, &search_key))
00343 return;
00344
00345 MHD_ip_count_lock (daemon);
00346
00347
00348 if (NULL == (nodep = TFIND (&search_key,
00349 &daemon->per_ip_connection_count,
00350 &MHD_ip_addr_compare)))
00351 {
00352
00353
00354 MHD_PANIC ("Failed to find previously-added IP address\n");
00355 }
00356 found_key = (struct MHD_IPCount *) *nodep;
00357
00358 if (0 == found_key->count)
00359 {
00360 MHD_PANIC ("Previously-added IP address had 0 count\n");
00361 }
00362
00363 if (0 == --found_key->count)
00364 {
00365 TDELETE (found_key,
00366 &daemon->per_ip_connection_count,
00367 &MHD_ip_addr_compare);
00368 free (found_key);
00369 }
00370
00371 MHD_ip_count_unlock (daemon);
00372 }
00373
00374
00375 #if HTTPS_SUPPORT
00376
00384 static ssize_t
00385 recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i)
00386 {
00387 int res;
00388
00389 res = gnutls_record_recv (connection->tls_session, other, i);
00390 if ( (GNUTLS_E_AGAIN == res) ||
00391 (GNUTLS_E_INTERRUPTED == res) )
00392 {
00393 errno = EINTR;
00394 return -1;
00395 }
00396 if (res < 0)
00397 {
00398
00399
00400
00401 errno = EPIPE;
00402 return res;
00403 }
00404 return res;
00405 }
00406
00407
00416 static ssize_t
00417 send_tls_adapter (struct MHD_Connection *connection,
00418 const void *other, size_t i)
00419 {
00420 int res;
00421
00422 res = gnutls_record_send (connection->tls_session, other, i);
00423 if ( (GNUTLS_E_AGAIN == res) ||
00424 (GNUTLS_E_INTERRUPTED == res) )
00425 {
00426 errno = EINTR;
00427 return -1;
00428 }
00429 return res;
00430 }
00431
00432
00439 static int
00440 MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
00441 {
00442 gnutls_datum_t key;
00443 gnutls_datum_t cert;
00444
00445 if (NULL != daemon->https_mem_trust)
00446 {
00447 cert.data = (unsigned char *) daemon->https_mem_trust;
00448 cert.size = strlen (daemon->https_mem_trust);
00449 if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred, &cert,
00450 GNUTLS_X509_FMT_PEM) < 0)
00451 {
00452 #if HAVE_MESSAGES
00453 MHD_DLOG(daemon,
00454 "Bad trust certificate format\n");
00455 #endif
00456 return -1;
00457 }
00458 }
00459
00460
00461 if ( (NULL != daemon->https_mem_cert) &&
00462 (NULL != daemon->https_mem_key) )
00463 {
00464 key.data = (unsigned char *) daemon->https_mem_key;
00465 key.size = strlen (daemon->https_mem_key);
00466 cert.data = (unsigned char *) daemon->https_mem_cert;
00467 cert.size = strlen (daemon->https_mem_cert);
00468
00469 return gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
00470 &cert, &key,
00471 GNUTLS_X509_FMT_PEM);
00472 }
00473 #if HAVE_MESSAGES
00474 MHD_DLOG (daemon, "You need to specify a certificate and key location\n");
00475 #endif
00476 return -1;
00477 }
00478
00479
00486 static int
00487 MHD_TLS_init (struct MHD_Daemon *daemon)
00488 {
00489 switch (daemon->cred_type)
00490 {
00491 case GNUTLS_CRD_CERTIFICATE:
00492 if (0 !=
00493 gnutls_certificate_allocate_credentials (&daemon->x509_cred))
00494 return GNUTLS_E_MEMORY_ERROR;
00495 return MHD_init_daemon_certificate (daemon);
00496 default:
00497 #if HAVE_MESSAGES
00498 MHD_DLOG (daemon,
00499 "Error: invalid credentials type %d specified.\n",
00500 daemon->cred_type);
00501 #endif
00502 return -1;
00503 }
00504 }
00505 #endif
00506
00507
00521 int
00522 MHD_get_fdset (struct MHD_Daemon *daemon,
00523 fd_set *read_fd_set,
00524 fd_set *write_fd_set,
00525 fd_set *except_fd_set,
00526 int *max_fd)
00527 {
00528 struct MHD_Connection *pos;
00529 int fd;
00530
00531 if ( (NULL == daemon)
00532 || (NULL == read_fd_set)
00533 || (NULL == write_fd_set)
00534 || (NULL == except_fd_set)
00535 || (NULL == max_fd)
00536 || (MHD_YES == daemon->shutdown)
00537 || (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00538 || (0 != (daemon->options & MHD_USE_POLL)))
00539 return MHD_NO;
00540 fd = daemon->socket_fd;
00541 if (-1 != fd)
00542 {
00543 FD_SET (fd, read_fd_set);
00544
00545 if ((*max_fd) < fd)
00546 *max_fd = fd;
00547 }
00548 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
00549 if (MHD_YES != MHD_connection_get_fdset (pos,
00550 read_fd_set,
00551 write_fd_set,
00552 except_fd_set, max_fd))
00553 return MHD_NO;
00554 #if DEBUG_CONNECT
00555 MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
00556 #endif
00557 return MHD_YES;
00558 }
00559
00560
00568 static void *
00569 MHD_handle_connection (void *data)
00570 {
00571 struct MHD_Connection *con = data;
00572 int num_ready;
00573 fd_set rs;
00574 fd_set ws;
00575 fd_set es;
00576 int max;
00577 struct timeval tv;
00578 struct timeval *tvp;
00579 unsigned int timeout;
00580 time_t now;
00581 #ifdef HAVE_POLL_H
00582 struct MHD_Pollfd mp;
00583 struct pollfd p[1];
00584 #endif
00585
00586 timeout = con->daemon->connection_timeout;
00587 while ( (MHD_YES != con->daemon->shutdown) &&
00588 (MHD_CONNECTION_CLOSED != con->state) )
00589 {
00590 tvp = NULL;
00591 if (timeout > 0)
00592 {
00593 now = MHD_monotonic_time();
00594 if (now - con->last_activity > timeout)
00595 tv.tv_sec = 0;
00596 else
00597 tv.tv_sec = timeout - (now - con->last_activity);
00598 tv.tv_usec = 0;
00599 tvp = &tv;
00600 }
00601 if ( (MHD_CONNECTION_NORMAL_BODY_UNREADY == con->state) ||
00602 (MHD_CONNECTION_CHUNKED_BODY_UNREADY == con->state) )
00603 {
00604
00605 tv.tv_sec = 0;
00606 tv.tv_usec = 0;
00607 tvp = &tv;
00608 }
00609 #ifdef HAVE_POLL_H
00610 if (0 == (con->daemon->options & MHD_USE_POLL))
00611 {
00612 #else
00613 {
00614 #endif
00615
00616 FD_ZERO (&rs);
00617 FD_ZERO (&ws);
00618 FD_ZERO (&es);
00619 max = 0;
00620 MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
00621 num_ready = SELECT (max + 1, &rs, &ws, &es, tvp);
00622 if (num_ready < 0)
00623 {
00624 if (EINTR == errno)
00625 continue;
00626 #if HAVE_MESSAGES
00627 MHD_DLOG (con->daemon,
00628 "Error during select (%d): `%s'\n",
00629 max,
00630 STRERROR (errno));
00631 #endif
00632 break;
00633 }
00634
00635 if (FD_ISSET (con->socket_fd, &rs))
00636 con->read_handler (con);
00637 if (FD_ISSET (con->socket_fd, &ws))
00638 con->write_handler (con);
00639 if (MHD_NO == con->idle_handler (con))
00640 goto exit;
00641 }
00642 #ifdef HAVE_POLL_H
00643 else
00644 {
00645
00646 memset(&mp, 0, sizeof (struct MHD_Pollfd));
00647 MHD_connection_get_pollfd(con, &mp);
00648 memset(&p, 0, sizeof (p));
00649 p[0].fd = mp.fd;
00650 if (mp.events & MHD_POLL_ACTION_IN)
00651 p[0].events |= POLLIN;
00652 if (mp.events & MHD_POLL_ACTION_OUT)
00653 p[0].events |= POLLOUT;
00654 if (poll (p,
00655 1,
00656 (NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
00657 {
00658 if (EINTR == errno)
00659 continue;
00660 #if HAVE_MESSAGES
00661 MHD_DLOG (con->daemon, "Error during poll: `%s'\n",
00662 STRERROR (errno));
00663 #endif
00664 break;
00665 }
00666 if (0 != (p[0].revents & POLLIN))
00667 con->read_handler (con);
00668 if (0 != (p[0].revents & POLLOUT))
00669 con->write_handler (con);
00670 if (0 != (p[0].revents & (POLLERR | POLLHUP)))
00671 MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR);
00672 if (MHD_NO == con->idle_handler (con))
00673 goto exit;
00674 }
00675 #endif
00676 }
00677 if (MHD_CONNECTION_IN_CLEANUP != con->state)
00678 {
00679 #if DEBUG_CLOSE
00680 #if HAVE_MESSAGES
00681 MHD_DLOG (con->daemon,
00682 "Processing thread terminating, closing connection\n");
00683 #endif
00684 #endif
00685 if (MHD_CONNECTION_CLOSED != con->state)
00686 MHD_connection_close (con,
00687 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
00688 con->idle_handler (con);
00689 }
00690 exit:
00691 if (NULL != con->response)
00692 {
00693 MHD_destroy_response (con->response);
00694 con->response = NULL;
00695 }
00696 return NULL;
00697 }
00698
00699
00708 static ssize_t
00709 recv_param_adapter (struct MHD_Connection *connection,
00710 void *other,
00711 size_t i)
00712 {
00713 if ( (-1 == connection->socket_fd) ||
00714 (MHD_CONNECTION_CLOSED == connection->state) )
00715 {
00716 errno = ENOTCONN;
00717 return -1;
00718 }
00719 if (0 != (connection->daemon->options & MHD_USE_SSL))
00720 return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
00721 return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
00722 }
00723
00724
00733 static ssize_t
00734 send_param_adapter (struct MHD_Connection *connection,
00735 const void *other,
00736 size_t i)
00737 {
00738 #if LINUX
00739 int fd;
00740 off_t offset;
00741 off_t left;
00742 ssize_t ret;
00743 #endif
00744 if ( (-1 == connection->socket_fd) ||
00745 (MHD_CONNECTION_CLOSED == connection->state) )
00746 {
00747 errno = ENOTCONN;
00748 return -1;
00749 }
00750 if (0 != (connection->daemon->options & MHD_USE_SSL))
00751 return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
00752 #if LINUX
00753 if ( (connection->write_buffer_append_offset ==
00754 connection->write_buffer_send_offset) &&
00755 (NULL != connection->response) &&
00756 (-1 != (fd = connection->response->fd)) )
00757 {
00758
00759 offset = (off_t) connection->response_write_position + connection->response->fd_off;
00760 left = connection->response->total_size - connection->response_write_position;
00761 if (left > SSIZE_MAX)
00762 left = SSIZE_MAX;
00763 if (-1 != (ret = sendfile (connection->socket_fd,
00764 fd,
00765 &offset,
00766 (size_t) left)))
00767 return ret;
00768 if ( (EINTR == errno) || (EAGAIN == errno) )
00769 return 0;
00770 if ( (EINVAL == errno) || (EBADF == errno) )
00771 return -1;
00772
00773
00774
00775
00776 }
00777 #endif
00778 return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
00779 }
00780
00781
00791 static int
00792 create_thread (pthread_t * thread,
00793 const struct MHD_Daemon *daemon,
00794 void *(*start_routine)(void*),
00795 void *arg)
00796 {
00797 pthread_attr_t attr;
00798 pthread_attr_t *pattr;
00799 int ret;
00800
00801 if (0 != daemon->thread_stack_size)
00802 {
00803 if (0 != (ret = pthread_attr_init (&attr)))
00804 goto ERR;
00805 if (0 != (ret = pthread_attr_setstacksize (&attr, daemon->thread_stack_size)))
00806 {
00807 pthread_attr_destroy (&attr);
00808 goto ERR;
00809 }
00810 pattr = &attr;
00811 }
00812 else
00813 {
00814 pattr = NULL;
00815 }
00816 ret = pthread_create (thread, pattr,
00817 start_routine, arg);
00818 if (0 != daemon->thread_stack_size)
00819 pthread_attr_destroy (&attr);
00820 return ret;
00821 ERR:
00822 #if HAVE_MESSAGES
00823 MHD_DLOG (daemon,
00824 "Failed to set thread stack size\n");
00825 #endif
00826 errno = EINVAL;
00827 return ret;
00828 }
00829
00830
00854 int
00855 MHD_add_connection (struct MHD_Daemon *daemon,
00856 int client_socket,
00857 const struct sockaddr *addr,
00858 socklen_t addrlen)
00859 {
00860 struct MHD_Connection *connection;
00861 int res_thread_create;
00862 #if OSX
00863 static int on = 1;
00864 #endif
00865
00866 #ifndef WINDOWS
00867 if ( (client_socket >= FD_SETSIZE) &&
00868 (0 == (daemon->options & MHD_USE_POLL)) )
00869 {
00870 #if HAVE_MESSAGES
00871 MHD_DLOG (daemon,
00872 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
00873 client_socket,
00874 FD_SETSIZE);
00875 #endif
00876 SHUTDOWN (client_socket, SHUT_RDWR);
00877 CLOSE (client_socket);
00878 return MHD_NO;
00879 }
00880 #endif
00881
00882
00883 #if HAVE_MESSAGES
00884 #if DEBUG_CONNECT
00885 MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
00886 #endif
00887 #endif
00888 if ( (0 == daemon->max_connections) ||
00889 (MHD_NO == MHD_ip_limit_add (daemon, addr, addrlen)) )
00890 {
00891
00892 #if HAVE_MESSAGES
00893 MHD_DLOG (daemon,
00894 "Server reached connection limit (closing inbound connection)\n");
00895 #endif
00896 SHUTDOWN (client_socket, SHUT_RDWR);
00897 CLOSE (client_socket);
00898 return MHD_NO;
00899 }
00900
00901
00902 if ( (NULL != daemon->apc) &&
00903 (MHD_NO == daemon->apc (daemon->apc_cls,
00904 addr, addrlen)) )
00905 {
00906 #if DEBUG_CLOSE
00907 #if HAVE_MESSAGES
00908 MHD_DLOG (daemon, "Connection rejected, closing connection\n");
00909 #endif
00910 #endif
00911 SHUTDOWN (client_socket, SHUT_RDWR);
00912 CLOSE (client_socket);
00913 MHD_ip_limit_del (daemon, addr, addrlen);
00914 return MHD_YES;
00915 }
00916
00917 #if OSX
00918 #ifdef SOL_SOCKET
00919 #ifdef SO_NOSIGPIPE
00920 setsockopt (client_socket,
00921 SOL_SOCKET, SO_NOSIGPIPE,
00922 &on, sizeof (on));
00923 #endif
00924 #endif
00925 #endif
00926
00927 if (NULL == (connection = malloc (sizeof (struct MHD_Connection))))
00928 {
00929 #if HAVE_MESSAGES
00930 MHD_DLOG (daemon,
00931 "Error allocating memory: %s\n",
00932 STRERROR (errno));
00933 #endif
00934 SHUTDOWN (client_socket, SHUT_RDWR);
00935 CLOSE (client_socket);
00936 MHD_ip_limit_del (daemon, addr, addrlen);
00937 return MHD_NO;
00938 }
00939 memset (connection, 0, sizeof (struct MHD_Connection));
00940 connection->connection_timeout = daemon->connection_timeout;
00941 connection->pool = NULL;
00942 if (NULL == (connection->addr = malloc (addrlen)))
00943 {
00944 #if HAVE_MESSAGES
00945 MHD_DLOG (daemon,
00946 "Error allocating memory: %s\n",
00947 STRERROR (errno));
00948 #endif
00949 SHUTDOWN (client_socket, SHUT_RDWR);
00950 CLOSE (client_socket);
00951 MHD_ip_limit_del (daemon, addr, addrlen);
00952 free (connection);
00953 return MHD_NO;
00954 }
00955 memcpy (connection->addr, addr, addrlen);
00956 connection->addr_len = addrlen;
00957 connection->socket_fd = client_socket;
00958 connection->daemon = daemon;
00959 connection->last_activity = MHD_monotonic_time();
00960
00961
00962 MHD_set_http_callbacks_ (connection);
00963 connection->recv_cls = &recv_param_adapter;
00964 connection->send_cls = &send_param_adapter;
00965
00966
00967 #ifdef CYGWIN
00968 if
00969 #if HTTPS_SUPPORT
00970 (0 != (daemon->options & MHD_USE_SSL))
00971 #else
00972 (0)
00973 #endif
00974 #endif
00975 {
00976
00977 #ifndef MINGW
00978 int flags = fcntl (connection->socket_fd, F_GETFL);
00979 if ( (-1 == flags) ||
00980 (0 != fcntl (connection->socket_fd, F_SETFL, flags | O_NONBLOCK)) )
00981 {
00982 #if HAVE_MESSAGES
00983 MHD_DLOG (daemon,
00984 "Failed to make socket %d non-blocking: %s\n",
00985 connection->socket_fd,
00986 STRERROR (errno));
00987 #endif
00988 }
00989 #else
00990 unsigned long flags = 1;
00991 if (0 != ioctlsocket (connection->socket_fd, FIONBIO, &flags))
00992 {
00993 #if HAVE_MESSAGES
00994 MHD_DLOG (daemon,
00995 "Failed to make socket non-blocking: %s\n",
00996 STRERROR (errno));
00997 #endif
00998 }
00999 #endif
01000 }
01001
01002 #if HTTPS_SUPPORT
01003 if (0 != (daemon->options & MHD_USE_SSL))
01004 {
01005 connection->recv_cls = &recv_tls_adapter;
01006 connection->send_cls = &send_tls_adapter;
01007 connection->state = MHD_TLS_CONNECTION_INIT;
01008 MHD_set_https_callbacks (connection);
01009 gnutls_init (&connection->tls_session, GNUTLS_SERVER);
01010 gnutls_priority_set (connection->tls_session,
01011 daemon->priority_cache);
01012 switch (daemon->cred_type)
01013 {
01014
01015 case GNUTLS_CRD_CERTIFICATE:
01016 gnutls_credentials_set (connection->tls_session,
01017 GNUTLS_CRD_CERTIFICATE,
01018 daemon->x509_cred);
01019 break;
01020 default:
01021 #if HAVE_MESSAGES
01022 MHD_DLOG (connection->daemon,
01023 "Failed to setup TLS credentials: unknown credential type %d\n",
01024 daemon->cred_type);
01025 #endif
01026 SHUTDOWN (client_socket, SHUT_RDWR);
01027 CLOSE (client_socket);
01028 MHD_ip_limit_del (daemon, addr, addrlen);
01029 free (connection->addr);
01030 free (connection);
01031 MHD_PANIC ("Unknown credential type");
01032 return MHD_NO;
01033 }
01034 gnutls_transport_set_ptr (connection->tls_session,
01035 (gnutls_transport_ptr_t) connection);
01036 gnutls_transport_set_pull_function (connection->tls_session,
01037 (gnutls_pull_func) &
01038 recv_param_adapter);
01039 gnutls_transport_set_push_function (connection->tls_session,
01040 (gnutls_push_func) &
01041 send_param_adapter);
01042
01043 if (daemon->https_mem_trust){
01044 gnutls_certificate_server_set_request(connection->tls_session, GNUTLS_CERT_REQUEST);
01045 }
01046 }
01047 #endif
01048
01049 if (0 != pthread_mutex_lock(&daemon->cleanup_connection_mutex))
01050 {
01051 MHD_PANIC ("Failed to acquire cleanup mutex\n");
01052 }
01053 DLL_insert (daemon->connections_head,
01054 daemon->connections_tail,
01055 connection);
01056 if (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex))
01057 {
01058 MHD_PANIC ("Failed to release cleanup mutex\n");
01059 }
01060
01061
01062 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01063 {
01064 res_thread_create = create_thread (&connection->pid, daemon,
01065 &MHD_handle_connection, connection);
01066 if (0 != res_thread_create)
01067 {
01068 #if HAVE_MESSAGES
01069 MHD_DLOG (daemon, "Failed to create a thread: %s\n",
01070 STRERROR (res_thread_create));
01071 #endif
01072 SHUTDOWN (client_socket, SHUT_RDWR);
01073 CLOSE (client_socket);
01074 MHD_ip_limit_del (daemon, addr, addrlen);
01075 if (0 != pthread_mutex_lock(&daemon->cleanup_connection_mutex))
01076 {
01077 MHD_PANIC ("Failed to acquire cleanup mutex\n");
01078 }
01079 DLL_remove (daemon->connections_head,
01080 daemon->connections_tail,
01081 connection);
01082 if (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex))
01083 {
01084 MHD_PANIC ("Failed to release cleanup mutex\n");
01085 }
01086 free (connection->addr);
01087 free (connection);
01088 return MHD_NO;
01089 }
01090 }
01091 daemon->max_connections--;
01092 return MHD_YES;
01093 }
01094
01095
01104 static int
01105 MHD_accept_connection (struct MHD_Daemon *daemon)
01106 {
01107 #if HAVE_INET6
01108 struct sockaddr_in6 addrstorage;
01109 #else
01110 struct sockaddr_in addrstorage;
01111 #endif
01112 struct sockaddr *addr = (struct sockaddr *) &addrstorage;
01113 socklen_t addrlen;
01114 int s;
01115 int flags;
01116 int need_fcntl;
01117
01118 addrlen = sizeof (addrstorage);
01119 memset (addr, 0, sizeof (addrstorage));
01120 #if HAVE_ACCEPT4
01121 s = accept4 (daemon->socket_fd, addr, &addrlen, SOCK_CLOEXEC);
01122 need_fcntl = MHD_NO;
01123 #else
01124 s = -1;
01125 need_fcntl = MHD_YES;
01126 #endif
01127 if (-1 == s)
01128 {
01129 s = ACCEPT (daemon->socket_fd, addr, &addrlen);
01130 need_fcntl = MHD_YES;
01131 }
01132 if ((-1 == s) || (addrlen <= 0))
01133 {
01134 #if HAVE_MESSAGES
01135
01136 if ((EAGAIN != errno) && (EWOULDBLOCK != errno))
01137 MHD_DLOG (daemon,
01138 "Error accepting connection: %s\n",
01139 STRERROR (errno));
01140 #endif
01141 if (-1 != s)
01142 {
01143 SHUTDOWN (s, SHUT_RDWR);
01144 CLOSE (s);
01145
01146 }
01147 return MHD_NO;
01148 }
01149 if (MHD_YES == need_fcntl)
01150 {
01151
01152 #if !WINDOWS
01153 flags = fcntl (s, F_GETFD);
01154 if ( ( (-1 == flags) ||
01155 ( (flags != (flags | FD_CLOEXEC)) &&
01156 (0 != fcntl (s, F_SETFD, flags | FD_CLOEXEC)) ) ) )
01157 #else
01158 DWORD dwFlags;
01159 if (!GetHandleInformation ((HANDLE) s, &dwFlags) ||
01160 ((dwFlags != dwFlags & ~HANDLE_FLAG_INHERIT) &&
01161 !SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0)))
01162 #endif
01163 {
01164 #if HAVE_MESSAGES
01165 #if WINDOWS
01166 SetErrnoFromWinError (GetLastError ());
01167 #endif
01168 MHD_DLOG (daemon,
01169 "Failed to make socket non-inheritable: %s\n",
01170 STRERROR (errno));
01171 #endif
01172 }
01173 }
01174 #if HAVE_MESSAGES
01175 #if DEBUG_CONNECT
01176 MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
01177 #endif
01178 #endif
01179 return MHD_add_connection (daemon, s,
01180 addr, addrlen);
01181 }
01182
01183
01191 static void
01192 MHD_cleanup_connections (struct MHD_Daemon *daemon)
01193 {
01194 struct MHD_Connection *pos;
01195 void *unused;
01196 int rc;
01197
01198 if (0 != pthread_mutex_lock(&daemon->cleanup_connection_mutex))
01199 {
01200 MHD_PANIC ("Failed to acquire cleanup mutex\n");
01201 }
01202 while (NULL != (pos = daemon->cleanup_head))
01203 {
01204 DLL_remove (daemon->cleanup_head,
01205 daemon->cleanup_tail,
01206 pos);
01207 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01208 (MHD_NO == pos->thread_joined) )
01209 {
01210 if (0 != (rc = pthread_join (pos->pid, &unused)))
01211 {
01212 MHD_PANIC ("Failed to join a thread\n");
01213 }
01214 }
01215 MHD_pool_destroy (pos->pool);
01216 #if HTTPS_SUPPORT
01217 if (pos->tls_session != NULL)
01218 gnutls_deinit (pos->tls_session);
01219 #endif
01220 MHD_ip_limit_del (daemon, (struct sockaddr*)pos->addr, pos->addr_len);
01221 if (NULL != pos->response)
01222 {
01223 MHD_destroy_response (pos->response);
01224 pos->response = NULL;
01225 }
01226 if (-1 != pos->socket_fd)
01227 CLOSE (pos->socket_fd);
01228 if (NULL != pos->addr)
01229 free (pos->addr);
01230 free (pos);
01231 daemon->max_connections++;
01232 }
01233 if (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex))
01234 {
01235 MHD_PANIC ("Failed to release cleanup mutex\n");
01236 }
01237 }
01238
01239
01252 int
01253 MHD_get_timeout (struct MHD_Daemon *daemon,
01254 unsigned MHD_LONG_LONG *timeout)
01255 {
01256 time_t earliest_deadline;
01257 time_t now;
01258 struct MHD_Connection *pos;
01259 int have_timeout;
01260
01261 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01262 {
01263 #if HAVE_MESSAGES
01264 MHD_DLOG (daemon, "Illegal call to MHD_get_timeout\n");
01265 #endif
01266 return MHD_NO;
01267 }
01268 have_timeout = MHD_NO;
01269 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
01270 {
01271 if (0 != pos->connection_timeout) {
01272 if (!have_timeout ||
01273 earliest_deadline > pos->last_activity + pos->connection_timeout)
01274 earliest_deadline = pos->last_activity + pos->connection_timeout;
01275 #if HTTPS_SUPPORT
01276 if ( (0 != (daemon->options & MHD_USE_SSL)) &&
01277 (0 != gnutls_record_check_pending (pos->tls_session)) )
01278 earliest_deadline = 0;
01279 #endif
01280 have_timeout = MHD_YES;
01281 }
01282 }
01283 if (MHD_NO == have_timeout)
01284 return MHD_NO;
01285 now = MHD_monotonic_time();
01286 if (earliest_deadline < now)
01287 *timeout = 0;
01288 else
01289 *timeout = 1000 * (1 + earliest_deadline - now);
01290 return MHD_YES;
01291 }
01292
01293
01301 static int
01302 MHD_select (struct MHD_Daemon *daemon,
01303 int may_block)
01304 {
01305 struct MHD_Connection *pos;
01306 struct MHD_Connection *next;
01307 int num_ready;
01308 fd_set rs;
01309 fd_set ws;
01310 fd_set es;
01311 int max;
01312 struct timeval timeout;
01313 struct timeval *tv;
01314 unsigned MHD_LONG_LONG ltimeout;
01315 int ds;
01316
01317 timeout.tv_sec = 0;
01318 timeout.tv_usec = 0;
01319 if (MHD_YES == daemon->shutdown)
01320 return MHD_NO;
01321 FD_ZERO (&rs);
01322 FD_ZERO (&ws);
01323 FD_ZERO (&es);
01324 max = -1;
01325 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01326 {
01327
01328 if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
01329 return MHD_NO;
01330
01331
01332
01333 if ( (0 == daemon->max_connections) &&
01334 (-1 != daemon->socket_fd) )
01335 FD_CLR (daemon->socket_fd, &rs);
01336 }
01337 else
01338 {
01339
01340 if (-1 != daemon->socket_fd)
01341 {
01342 max = daemon->socket_fd;
01343 FD_SET (daemon->socket_fd, &rs);
01344 }
01345 }
01346 if (-1 != daemon->wpipe[0])
01347 {
01348 FD_SET (daemon->wpipe[0], &rs);
01349
01350 if (max < daemon->wpipe[0])
01351 max = daemon->wpipe[0];
01352 }
01353
01354 tv = NULL;
01355 if (MHD_NO == may_block)
01356 {
01357 timeout.tv_usec = 0;
01358 timeout.tv_sec = 0;
01359 tv = &timeout;
01360 }
01361 else if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01362 (MHD_YES == MHD_get_timeout (daemon, <imeout)) )
01363 {
01364
01365 timeout.tv_usec = (ltimeout % 1000) * 1000;
01366 timeout.tv_sec = ltimeout / 1000;
01367 tv = &timeout;
01368 }
01369 num_ready = SELECT (max + 1, &rs, &ws, &es, tv);
01370
01371 if (MHD_YES == daemon->shutdown)
01372 return MHD_NO;
01373 if (num_ready < 0)
01374 {
01375 if (EINTR == errno)
01376 return MHD_YES;
01377 #if HAVE_MESSAGES
01378 MHD_DLOG (daemon, "select failed: %s\n", STRERROR (errno));
01379 #endif
01380 return MHD_NO;
01381 }
01382
01383 if ( (-1 != (ds = daemon->socket_fd)) &&
01384 (FD_ISSET (ds, &rs)) )
01385 MHD_accept_connection (daemon);
01386 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01387 {
01388
01389 next = daemon->connections_head;
01390 while (NULL != (pos = next))
01391 {
01392 next = pos->next;
01393 ds = pos->socket_fd;
01394 if (ds != -1)
01395 {
01396 if (FD_ISSET (ds, &rs))
01397 pos->read_handler (pos);
01398 if (FD_ISSET (ds, &ws))
01399 pos->write_handler (pos);
01400 pos->idle_handler (pos);
01401 }
01402 }
01403 }
01404 return MHD_YES;
01405 }
01406
01407
01408 #ifdef HAVE_POLL_H
01409
01417 static int
01418 MHD_poll_all (struct MHD_Daemon *daemon,
01419 int may_block)
01420 {
01421 unsigned int num_connections;
01422 struct MHD_Connection *pos;
01423 struct MHD_Connection *next;
01424
01425
01426 num_connections = 0;
01427 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
01428 num_connections++;
01429
01430 {
01431 struct pollfd p[2 + num_connections];
01432 struct MHD_Pollfd mp;
01433 unsigned MHD_LONG_LONG ltimeout;
01434 unsigned int i;
01435 int timeout;
01436 unsigned int poll_server;
01437 int poll_listen;
01438
01439 memset (p, 0, sizeof (p));
01440 poll_server = 0;
01441 poll_listen = -1;
01442 if ( (-1 != daemon->socket_fd) &&
01443 (0 != daemon->max_connections) )
01444 {
01445
01446 p[poll_server].fd = daemon->socket_fd;
01447 p[poll_server].events = POLLIN;
01448 p[poll_server].revents = 0;
01449 poll_listen = (int) poll_server;
01450 poll_server++;
01451 }
01452 if (-1 != daemon->wpipe[0])
01453 {
01454 p[poll_server].fd = daemon->wpipe[0];
01455 p[poll_server].events = POLLIN;
01456 p[poll_server].revents = 0;
01457 poll_server++;
01458 }
01459 if (may_block == MHD_NO)
01460 timeout = 0;
01461 else if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
01462 (MHD_YES != MHD_get_timeout (daemon, <imeout)) )
01463 timeout = -1;
01464 else
01465 timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
01466
01467 i = 0;
01468 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
01469 {
01470 memset(&mp, 0, sizeof (struct MHD_Pollfd));
01471 MHD_connection_get_pollfd (pos, &mp);
01472 p[poll_server+i].fd = mp.fd;
01473 if (mp.events & MHD_POLL_ACTION_IN)
01474 p[poll_server+i].events |= POLLIN;
01475 if (mp.events & MHD_POLL_ACTION_OUT)
01476 p[poll_server+i].events |= POLLOUT;
01477 i++;
01478 }
01479 if (poll (p, poll_server + num_connections, timeout) < 0)
01480 {
01481 if (EINTR == errno)
01482 return MHD_YES;
01483 #if HAVE_MESSAGES
01484 MHD_DLOG (daemon,
01485 "poll failed: %s\n",
01486 STRERROR (errno));
01487 #endif
01488 return MHD_NO;
01489 }
01490
01491 if (MHD_YES == daemon->shutdown)
01492 return MHD_NO;
01493 i = 0;
01494 next = daemon->connections_head;
01495 while (NULL != (pos = next))
01496 {
01497 next = pos->next;
01498
01499 if (i >= num_connections)
01500 break;
01501 MHD_connection_get_pollfd (pos, &mp);
01502 if (p[poll_server+i].fd != mp.fd)
01503 break;
01504
01505
01506 if (0 != (p[poll_server+i].revents & POLLIN))
01507 pos->read_handler (pos);
01508 if (0 != (p[poll_server+i].revents & POLLOUT))
01509 pos->write_handler (pos);
01510 pos->idle_handler (pos);
01511 i++;
01512 }
01513 if ( (-1 != poll_listen) &&
01514 (0 != (p[poll_listen].revents & POLLIN)) )
01515 MHD_accept_connection (daemon);
01516 }
01517 return MHD_YES;
01518 }
01519
01520
01528 static int
01529 MHD_poll_listen_socket (struct MHD_Daemon *daemon,
01530 int may_block)
01531 {
01532 struct pollfd p[2];
01533 int timeout;
01534 unsigned int poll_count;
01535 int poll_listen;
01536
01537 memset (&p, 0, sizeof (p));
01538 poll_count = 0;
01539 poll_listen = -1;
01540 if (-1 != daemon->socket_fd)
01541 {
01542 p[poll_count].fd = daemon->socket_fd;
01543 p[poll_count].events = POLLIN;
01544 p[poll_count].revents = 0;
01545 poll_listen = poll_count;
01546 poll_count++;
01547 }
01548 if (-1 != daemon->wpipe[0])
01549 {
01550 p[poll_count].fd = daemon->wpipe[0];
01551 p[poll_count].events = POLLIN;
01552 p[poll_count].revents = 0;
01553 poll_count++;
01554 }
01555 if (MHD_NO == may_block)
01556 timeout = 0;
01557 else
01558 timeout = -1;
01559 if (poll (p, poll_count, timeout) < 0)
01560 {
01561 if (EINTR == errno)
01562 return MHD_YES;
01563 #if HAVE_MESSAGES
01564 MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
01565 #endif
01566 return MHD_NO;
01567 }
01568
01569 if (MHD_YES == daemon->shutdown)
01570 return MHD_NO;
01571 if ( (-1 != poll_listen) &&
01572 (0 != (p[poll_listen].revents & POLLIN)) )
01573 MHD_accept_connection (daemon);
01574 return MHD_YES;
01575 }
01576 #endif
01577
01578
01586 static int
01587 MHD_poll (struct MHD_Daemon *daemon,
01588 int may_block)
01589 {
01590 #ifdef HAVE_POLL_H
01591 if (MHD_YES == daemon->shutdown)
01592 return MHD_NO;
01593 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01594 return MHD_poll_all (daemon, may_block);
01595 else
01596 return MHD_poll_listen_socket (daemon, may_block);
01597 #else
01598 return MHD_NO;
01599 #endif
01600 }
01601
01602
01613 int
01614 MHD_run (struct MHD_Daemon *daemon)
01615 {
01616 if ( (MHD_YES == daemon->shutdown) ||
01617 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
01618 (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) )
01619 return MHD_NO;
01620 if (0 == (daemon->options & MHD_USE_POLL))
01621 MHD_select (daemon, MHD_NO);
01622 else
01623 MHD_poll (daemon, MHD_NO);
01624 MHD_cleanup_connections (daemon);
01625 return MHD_YES;
01626 }
01627
01628
01636 static void *
01637 MHD_select_thread (void *cls)
01638 {
01639 struct MHD_Daemon *daemon = cls;
01640
01641 while (MHD_YES != daemon->shutdown)
01642 {
01643 if (0 == (daemon->options & MHD_USE_POLL))
01644 MHD_select (daemon, MHD_YES);
01645 else
01646 MHD_poll (daemon, MHD_YES);
01647 MHD_cleanup_connections (daemon);
01648 }
01649 return NULL;
01650 }
01651
01652
01664 struct MHD_Daemon *
01665 MHD_start_daemon (unsigned int options,
01666 uint16_t port,
01667 MHD_AcceptPolicyCallback apc,
01668 void *apc_cls,
01669 MHD_AccessHandlerCallback dh, void *dh_cls, ...)
01670 {
01671 struct MHD_Daemon *daemon;
01672 va_list ap;
01673
01674 va_start (ap, dh_cls);
01675 daemon = MHD_start_daemon_va (options, port, apc, apc_cls, dh, dh_cls, ap);
01676 va_end (ap);
01677 return daemon;
01678 }
01679
01680
01688 typedef void (*VfprintfFunctionPointerType)(void *cls,
01689 const char *format,
01690 va_list va);
01691
01692
01701 static int
01702 parse_options_va (struct MHD_Daemon *daemon,
01703 const struct sockaddr **servaddr,
01704 va_list ap);
01705
01706
01715 static int
01716 parse_options (struct MHD_Daemon *daemon,
01717 const struct sockaddr **servaddr,
01718 ...)
01719 {
01720 va_list ap;
01721 int ret;
01722
01723 va_start (ap, servaddr);
01724 ret = parse_options_va (daemon, servaddr, ap);
01725 va_end (ap);
01726 return ret;
01727 }
01728
01729
01738 static int
01739 parse_options_va (struct MHD_Daemon *daemon,
01740 const struct sockaddr **servaddr,
01741 va_list ap)
01742 {
01743 enum MHD_OPTION opt;
01744 struct MHD_OptionItem *oa;
01745 unsigned int i;
01746 #if HTTPS_SUPPORT
01747 int ret;
01748 const char *pstr;
01749 #endif
01750
01751 while (MHD_OPTION_END != (opt = (enum MHD_OPTION) va_arg (ap, int)))
01752 {
01753 switch (opt)
01754 {
01755 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
01756 daemon->pool_size = va_arg (ap, size_t);
01757 break;
01758 case MHD_OPTION_CONNECTION_LIMIT:
01759 daemon->max_connections = va_arg (ap, unsigned int);
01760 break;
01761 case MHD_OPTION_CONNECTION_TIMEOUT:
01762 daemon->connection_timeout = va_arg (ap, unsigned int);
01763 break;
01764 case MHD_OPTION_NOTIFY_COMPLETED:
01765 daemon->notify_completed =
01766 va_arg (ap, MHD_RequestCompletedCallback);
01767 daemon->notify_completed_cls = va_arg (ap, void *);
01768 break;
01769 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
01770 daemon->per_ip_connection_limit = va_arg (ap, unsigned int);
01771 break;
01772 case MHD_OPTION_SOCK_ADDR:
01773 *servaddr = va_arg (ap, const struct sockaddr *);
01774 break;
01775 case MHD_OPTION_URI_LOG_CALLBACK:
01776 daemon->uri_log_callback =
01777 va_arg (ap, LogCallback);
01778 daemon->uri_log_callback_cls = va_arg (ap, void *);
01779 break;
01780 case MHD_OPTION_THREAD_POOL_SIZE:
01781 daemon->worker_pool_size = va_arg (ap, unsigned int);
01782 if (daemon->worker_pool_size >= SIZE_MAX / sizeof (struct MHD_Daemon))
01783 {
01784 #if HAVE_MESSAGES
01785 MHD_DLOG (daemon,
01786 "Specified thread pool size (%u) too big\n",
01787 daemon->worker_pool_size);
01788 #endif
01789 return MHD_NO;
01790 }
01791 break;
01792 #if HTTPS_SUPPORT
01793 case MHD_OPTION_HTTPS_MEM_KEY:
01794 if (0 != (daemon->options & MHD_USE_SSL))
01795 daemon->https_mem_key = va_arg (ap, const char *);
01796 #if HAVE_MESSAGES
01797 else
01798 MHD_DLOG (daemon,
01799 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01800 opt);
01801 #endif
01802 break;
01803 case MHD_OPTION_HTTPS_MEM_CERT:
01804 if (0 != (daemon->options & MHD_USE_SSL))
01805 daemon->https_mem_cert = va_arg (ap, const char *);
01806 #if HAVE_MESSAGES
01807 else
01808 MHD_DLOG (daemon,
01809 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01810 opt);
01811 #endif
01812 break;
01813 case MHD_OPTION_HTTPS_MEM_TRUST:
01814 if (0 != (daemon->options & MHD_USE_SSL))
01815 daemon->https_mem_trust = va_arg (ap, const char *);
01816 #if HAVE_MESSAGES
01817 else
01818 MHD_DLOG (daemon,
01819 "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01820 opt);
01821 #endif
01822 break;
01823 case MHD_OPTION_HTTPS_CRED_TYPE:
01824 daemon->cred_type = (gnutls_credentials_type_t) va_arg (ap, int);
01825 break;
01826 case MHD_OPTION_HTTPS_PRIORITIES:
01827 if (0 != (daemon->options & MHD_USE_SSL))
01828 {
01829 gnutls_priority_deinit (daemon->priority_cache);
01830 ret = gnutls_priority_init (&daemon->priority_cache,
01831 pstr = va_arg (ap, const char*),
01832 NULL);
01833 if (ret != GNUTLS_E_SUCCESS)
01834 {
01835 #if HAVE_MESSAGES
01836 MHD_DLOG (daemon,
01837 "Setting priorities to `%s' failed: %s\n",
01838 pstr,
01839 gnutls_strerror (ret));
01840 #endif
01841 daemon->priority_cache = NULL;
01842 return MHD_NO;
01843 }
01844 }
01845 break;
01846 #endif
01847 #ifdef DAUTH_SUPPORT
01848 case MHD_OPTION_DIGEST_AUTH_RANDOM:
01849 daemon->digest_auth_rand_size = va_arg (ap, size_t);
01850 daemon->digest_auth_random = va_arg (ap, const char *);
01851 break;
01852 case MHD_OPTION_NONCE_NC_SIZE:
01853 daemon->nonce_nc_size = va_arg (ap, unsigned int);
01854 break;
01855 #endif
01856 case MHD_OPTION_LISTEN_SOCKET:
01857 daemon->socket_fd = va_arg (ap, int);
01858 break;
01859 case MHD_OPTION_EXTERNAL_LOGGER:
01860 #if HAVE_MESSAGES
01861 daemon->custom_error_log =
01862 va_arg (ap, VfprintfFunctionPointerType);
01863 daemon->custom_error_log_cls = va_arg (ap, void *);
01864 #else
01865 va_arg (ap, VfprintfFunctionPointerType);
01866 va_arg (ap, void *);
01867 #endif
01868 break;
01869 case MHD_OPTION_THREAD_STACK_SIZE:
01870 daemon->thread_stack_size = va_arg (ap, size_t);
01871 break;
01872 case MHD_OPTION_ARRAY:
01873 oa = va_arg (ap, struct MHD_OptionItem*);
01874 i = 0;
01875 while (MHD_OPTION_END != (opt = oa[i].option))
01876 {
01877 switch (opt)
01878 {
01879
01880 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
01881 case MHD_OPTION_THREAD_STACK_SIZE:
01882 if (MHD_YES != parse_options (daemon,
01883 servaddr,
01884 opt,
01885 (size_t) oa[i].value,
01886 MHD_OPTION_END))
01887 return MHD_NO;
01888 break;
01889
01890 case MHD_OPTION_NONCE_NC_SIZE:
01891 case MHD_OPTION_CONNECTION_LIMIT:
01892 case MHD_OPTION_CONNECTION_TIMEOUT:
01893 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
01894 case MHD_OPTION_THREAD_POOL_SIZE:
01895 if (MHD_YES != parse_options (daemon,
01896 servaddr,
01897 opt,
01898 (unsigned int) oa[i].value,
01899 MHD_OPTION_END))
01900 return MHD_NO;
01901 break;
01902
01903 case MHD_OPTION_HTTPS_CRED_TYPE:
01904 case MHD_OPTION_LISTEN_SOCKET:
01905 if (MHD_YES != parse_options (daemon,
01906 servaddr,
01907 opt,
01908 (int) oa[i].value,
01909 MHD_OPTION_END))
01910 return MHD_NO;
01911 break;
01912
01913 case MHD_OPTION_SOCK_ADDR:
01914 case MHD_OPTION_HTTPS_MEM_KEY:
01915 case MHD_OPTION_HTTPS_MEM_CERT:
01916 case MHD_OPTION_HTTPS_MEM_TRUST:
01917 case MHD_OPTION_HTTPS_PRIORITIES:
01918 case MHD_OPTION_ARRAY:
01919 if (MHD_YES != parse_options (daemon,
01920 servaddr,
01921 opt,
01922 oa[i].ptr_value,
01923 MHD_OPTION_END))
01924 return MHD_NO;
01925 break;
01926
01927 case MHD_OPTION_NOTIFY_COMPLETED:
01928 case MHD_OPTION_URI_LOG_CALLBACK:
01929 case MHD_OPTION_EXTERNAL_LOGGER:
01930 case MHD_OPTION_UNESCAPE_CALLBACK:
01931 if (MHD_YES != parse_options (daemon,
01932 servaddr,
01933 opt,
01934 (void *) oa[i].value,
01935 oa[i].ptr_value,
01936 MHD_OPTION_END))
01937 return MHD_NO;
01938 break;
01939
01940 case MHD_OPTION_DIGEST_AUTH_RANDOM:
01941 if (MHD_YES != parse_options (daemon,
01942 servaddr,
01943 opt,
01944 (size_t) oa[i].value,
01945 oa[i].ptr_value,
01946 MHD_OPTION_END))
01947 return MHD_NO;
01948 break;
01949 default:
01950 return MHD_NO;
01951 }
01952 i++;
01953 }
01954 break;
01955 case MHD_OPTION_UNESCAPE_CALLBACK:
01956 daemon->unescape_callback =
01957 va_arg (ap, UnescapeCallback);
01958 daemon->unescape_callback_cls = va_arg (ap, void *);
01959 break;
01960 default:
01961 #if HAVE_MESSAGES
01962 if (((opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
01963 (opt <= MHD_OPTION_HTTPS_PRIORITIES)) || (opt == MHD_OPTION_HTTPS_MEM_TRUST))
01964 {
01965 MHD_DLOG (daemon,
01966 "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
01967 opt);
01968 }
01969 else
01970 {
01971 MHD_DLOG (daemon,
01972 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
01973 opt);
01974 }
01975 #endif
01976 return MHD_NO;
01977 }
01978 }
01979 return MHD_YES;
01980 }
01981
01982
01990 static int
01991 create_socket (int domain, int type, int protocol)
01992 {
01993 static int sock_cloexec = SOCK_CLOEXEC;
01994 int ctype = SOCK_STREAM | sock_cloexec;
01995 int fd;
01996 int flags;
01997 #if WINDOWS
01998 DWORD dwFlags;
01999 #endif
02000
02001
02002
02003 fd = SOCKET (domain, ctype, protocol);
02004 if ( (-1 == fd) && (EINVAL == errno) && (0 != sock_cloexec) )
02005 {
02006 sock_cloexec = 0;
02007 fd = SOCKET(domain, type, protocol);
02008 }
02009 if (-1 == fd)
02010 return -1;
02011 if (0 != sock_cloexec)
02012 return fd;
02013
02014 #if !WINDOWS
02015 flags = fcntl (fd, F_GETFD);
02016 if (flags < 0)
02017 #else
02018 if (!GetHandleInformation ((HANDLE) fd, &dwFlags))
02019 #endif
02020 {
02021 #if WINDOWS
02022 SetErrnoFromWinError (GetLastError ());
02023 #endif
02024 return fd;
02025 }
02026 #if !WINDOWS
02027 if (flags == (flags | FD_CLOEXEC))
02028 return fd;
02029 flags |= FD_CLOEXEC;
02030 if (0 != fcntl (fd, F_SETFD, flags))
02031 #else
02032 if (dwFlags != (dwFlags | HANDLE_FLAG_INHERIT))
02033 return fd;
02034 if (!SetHandleInformation ((HANDLE) fd, HANDLE_FLAG_INHERIT, 0))
02035 #endif
02036 {
02037 #if WINDOWS
02038 SetErrnoFromWinError (GetLastError ());
02039 #endif
02040 return fd;
02041 }
02042 return fd;
02043 }
02044
02045
02057 struct MHD_Daemon *
02058 MHD_start_daemon_va (unsigned int options,
02059 uint16_t port,
02060 MHD_AcceptPolicyCallback apc,
02061 void *apc_cls,
02062 MHD_AccessHandlerCallback dh, void *dh_cls,
02063 va_list ap)
02064 {
02065 const int on = 1;
02066 struct MHD_Daemon *daemon;
02067 int socket_fd;
02068 struct sockaddr_in servaddr4;
02069 #if HAVE_INET6
02070 struct sockaddr_in6 servaddr6;
02071 #endif
02072 const struct sockaddr *servaddr = NULL;
02073 socklen_t addrlen;
02074 unsigned int i;
02075 int res_thread_create;
02076 int use_pipe;
02077
02078 if (NULL == dh)
02079 return NULL;
02080 if (NULL == (daemon = malloc (sizeof (struct MHD_Daemon))))
02081 return NULL;
02082 memset (daemon, 0, sizeof (struct MHD_Daemon));
02083 #if HTTPS_SUPPORT
02084 if (0 != (options & MHD_USE_SSL))
02085 {
02086 gnutls_priority_init (&daemon->priority_cache,
02087 "NORMAL",
02088 NULL);
02089 }
02090 #endif
02091 daemon->socket_fd = -1;
02092 daemon->options = (enum MHD_OPTION) options;
02093 daemon->port = port;
02094 daemon->apc = apc;
02095 daemon->apc_cls = apc_cls;
02096 daemon->default_handler = dh;
02097 daemon->default_handler_cls = dh_cls;
02098 daemon->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
02099 daemon->pool_size = MHD_POOL_SIZE_DEFAULT;
02100 daemon->unescape_callback = &MHD_http_unescape;
02101 daemon->connection_timeout = 0;
02102 daemon->wpipe[0] = -1;
02103 daemon->wpipe[1] = -1;
02104 #if HAVE_MESSAGES
02105 daemon->custom_error_log =
02106 (void (*)(void *, const char *, va_list)) &vfprintf;
02107 daemon->custom_error_log_cls = stderr;
02108 #endif
02109 #ifdef HAVE_LISTEN_SHUTDOWN
02110 use_pipe = (0 != (daemon->options & MHD_USE_NO_LISTEN_SOCKET));
02111 #else
02112 use_pipe = 1;
02113 #endif
02114 if ( (use_pipe) &&
02115 (0 != PIPE (daemon->wpipe)) )
02116 {
02117 #if HAVE_MESSAGES
02118 MHD_DLOG (daemon,
02119 "Failed to create control pipe: %s\n",
02120 STRERROR (errno));
02121 #endif
02122 free (daemon);
02123 return NULL;
02124 }
02125 #ifndef WINDOWS
02126 if ( (0 == (options & MHD_USE_POLL)) &&
02127 (daemon->wpipe[0] >= FD_SETSIZE) )
02128 {
02129 #if HAVE_MESSAGES
02130 MHD_DLOG (daemon,
02131 "file descriptor for control pipe exceeds maximum value\n");
02132 #endif
02133 CLOSE (daemon->wpipe[0]);
02134 CLOSE (daemon->wpipe[1]);
02135 free (daemon);
02136 return NULL;
02137 }
02138 #endif
02139 #ifdef DAUTH_SUPPORT
02140 daemon->digest_auth_rand_size = 0;
02141 daemon->digest_auth_random = NULL;
02142 daemon->nonce_nc_size = 4;
02143 #endif
02144 #if HTTPS_SUPPORT
02145 if (0 != (options & MHD_USE_SSL))
02146 {
02147 daemon->cred_type = GNUTLS_CRD_CERTIFICATE;
02148 }
02149 #endif
02150
02151 if (MHD_YES != parse_options_va (daemon, &servaddr, ap))
02152 {
02153 #if HTTPS_SUPPORT
02154 if ( (0 != (options & MHD_USE_SSL)) &&
02155 (NULL != daemon->priority_cache) )
02156 gnutls_priority_deinit (daemon->priority_cache);
02157 #endif
02158 free (daemon);
02159 return NULL;
02160 }
02161
02162 #ifdef DAUTH_SUPPORT
02163 if (daemon->nonce_nc_size > 0)
02164 {
02165 if ( ( (size_t) (daemon->nonce_nc_size * sizeof(struct MHD_NonceNc))) /
02166 sizeof(struct MHD_NonceNc) != daemon->nonce_nc_size)
02167 {
02168 #if HAVE_MESSAGES
02169 MHD_DLOG (daemon,
02170 "Specified value for NC_SIZE too large\n");
02171 #endif
02172 #if HTTPS_SUPPORT
02173 if (0 != (options & MHD_USE_SSL))
02174 gnutls_priority_deinit (daemon->priority_cache);
02175 #endif
02176 free (daemon);
02177 return NULL;
02178 }
02179 daemon->nnc = malloc (daemon->nonce_nc_size * sizeof(struct MHD_NonceNc));
02180 if (NULL == daemon->nnc)
02181 {
02182 #if HAVE_MESSAGES
02183 MHD_DLOG (daemon,
02184 "Failed to allocate memory for nonce-nc map: %s\n",
02185 STRERROR (errno));
02186 #endif
02187 #if HTTPS_SUPPORT
02188 if (0 != (options & MHD_USE_SSL))
02189 gnutls_priority_deinit (daemon->priority_cache);
02190 #endif
02191 free (daemon);
02192 return NULL;
02193 }
02194 }
02195
02196 if (0 != pthread_mutex_init (&daemon->nnc_lock, NULL))
02197 {
02198 #if HAVE_MESSAGES
02199 MHD_DLOG (daemon,
02200 "MHD failed to initialize nonce-nc mutex\n");
02201 #endif
02202 #if HTTPS_SUPPORT
02203 if (0 != (options & MHD_USE_SSL))
02204 gnutls_priority_deinit (daemon->priority_cache);
02205 #endif
02206 free (daemon->nnc);
02207 free (daemon);
02208 return NULL;
02209 }
02210 #endif
02211
02212
02213 if ( (0 == (options & MHD_USE_SELECT_INTERNALLY)) &&
02214 (daemon->worker_pool_size > 0) )
02215 {
02216 #if HAVE_MESSAGES
02217 MHD_DLOG (daemon,
02218 "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n");
02219 #endif
02220 goto free_and_fail;
02221 }
02222
02223 #ifdef __SYMBIAN32__
02224 if (0 != (options & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
02225 {
02226 #if HAVE_MESSAGES
02227 MHD_DLOG (daemon,
02228 "Threaded operations are not supported on Symbian.\n");
02229 #endif
02230 goto free_and_fail;
02231 }
02232 #endif
02233 if ( (-1 == daemon->socket_fd) &&
02234 (0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) )
02235 {
02236
02237 if ((options & MHD_USE_IPv6) != 0)
02238 #if HAVE_INET6
02239 socket_fd = create_socket (PF_INET6, SOCK_STREAM, 0);
02240 #else
02241 {
02242 #if HAVE_MESSAGES
02243 MHD_DLOG (daemon,
02244 "AF_INET6 not supported\n");
02245 #endif
02246 goto free_and_fail;
02247 }
02248 #endif
02249 else
02250 socket_fd = create_socket (PF_INET, SOCK_STREAM, 0);
02251 if (-1 == socket_fd)
02252 {
02253 #if HAVE_MESSAGES
02254 if (0 != (options & MHD_USE_DEBUG))
02255 MHD_DLOG (daemon,
02256 "Call to socket failed: %s\n",
02257 STRERROR (errno));
02258 #endif
02259 goto free_and_fail;
02260 }
02261 if ((SETSOCKOPT (socket_fd,
02262 SOL_SOCKET,
02263 SO_REUSEADDR,
02264 &on, sizeof (on)) < 0) && ((options & MHD_USE_DEBUG) != 0))
02265 {
02266 #if HAVE_MESSAGES
02267 MHD_DLOG (daemon,
02268 "setsockopt failed: %s\n",
02269 STRERROR (errno));
02270 #endif
02271 }
02272
02273
02274 #if HAVE_INET6
02275 if (0 != (options & MHD_USE_IPv6))
02276 addrlen = sizeof (struct sockaddr_in6);
02277 else
02278 #endif
02279 addrlen = sizeof (struct sockaddr_in);
02280 if (NULL == servaddr)
02281 {
02282 #if HAVE_INET6
02283 if (0 != (options & MHD_USE_IPv6))
02284 {
02285 memset (&servaddr6, 0, sizeof (struct sockaddr_in6));
02286 servaddr6.sin6_family = AF_INET6;
02287 servaddr6.sin6_port = htons (port);
02288 #if HAVE_SOCKADDR_IN_SIN_LEN
02289 servaddr6.sin6_len = sizeof (struct sockaddr_in6);
02290 #endif
02291 servaddr = (struct sockaddr *) &servaddr6;
02292 }
02293 else
02294 #endif
02295 {
02296 memset (&servaddr4, 0, sizeof (struct sockaddr_in));
02297 servaddr4.sin_family = AF_INET;
02298 servaddr4.sin_port = htons (port);
02299 #if HAVE_SOCKADDR_IN_SIN_LEN
02300 servaddr4.sin_len = sizeof (struct sockaddr_in);
02301 #endif
02302 servaddr = (struct sockaddr *) &servaddr4;
02303 }
02304 }
02305 daemon->socket_fd = socket_fd;
02306
02307 if (0 != (options & MHD_USE_IPv6))
02308 {
02309 #ifdef IPPROTO_IPV6
02310 #ifdef IPV6_V6ONLY
02311
02312
02313
02314
02315 #ifndef WINDOWS
02316 const int on = 1;
02317 setsockopt (socket_fd,
02318 IPPROTO_IPV6, IPV6_V6ONLY,
02319 &on, sizeof (on));
02320 #else
02321 const char on = 1;
02322 setsockopt (socket_fd,
02323 IPPROTO_IPV6, IPV6_V6ONLY,
02324 &on, sizeof (on));
02325 #endif
02326 #endif
02327 #endif
02328 }
02329 if (-1 == BIND (socket_fd, servaddr, addrlen))
02330 {
02331 #if HAVE_MESSAGES
02332 if (0 != (options & MHD_USE_DEBUG))
02333 MHD_DLOG (daemon,
02334 "Failed to bind to port %u: %s\n",
02335 (unsigned int) port,
02336 STRERROR (errno));
02337 #endif
02338 CLOSE (socket_fd);
02339 goto free_and_fail;
02340 }
02341
02342 if (LISTEN (socket_fd, 20) < 0)
02343 {
02344 #if HAVE_MESSAGES
02345 if (0 != (options & MHD_USE_DEBUG))
02346 MHD_DLOG (daemon,
02347 "Failed to listen for connections: %s\n",
02348 STRERROR (errno));
02349 #endif
02350 CLOSE (socket_fd);
02351 goto free_and_fail;
02352 }
02353 }
02354 else
02355 {
02356 socket_fd = daemon->socket_fd;
02357 }
02358 #ifndef WINDOWS
02359 if ( (socket_fd >= FD_SETSIZE) &&
02360 (0 == (options & MHD_USE_POLL)) )
02361 {
02362 #if HAVE_MESSAGES
02363 if ((options & MHD_USE_DEBUG) != 0)
02364 MHD_DLOG (daemon,
02365 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
02366 socket_fd,
02367 FD_SETSIZE);
02368 #endif
02369 CLOSE (socket_fd);
02370 goto free_and_fail;
02371 }
02372 #endif
02373
02374 if (0 != pthread_mutex_init (&daemon->per_ip_connection_mutex, NULL))
02375 {
02376 #if HAVE_MESSAGES
02377 MHD_DLOG (daemon,
02378 "MHD failed to initialize IP connection limit mutex\n");
02379 #endif
02380 if (-1 != socket_fd)
02381 CLOSE (socket_fd);
02382 goto free_and_fail;
02383 }
02384 if (0 != pthread_mutex_init (&daemon->cleanup_connection_mutex, NULL))
02385 {
02386 #if HAVE_MESSAGES
02387 MHD_DLOG (daemon,
02388 "MHD failed to initialize IP connection limit mutex\n");
02389 #endif
02390 pthread_mutex_destroy (&daemon->cleanup_connection_mutex);
02391 if (-1 != socket_fd)
02392 CLOSE (socket_fd);
02393 goto free_and_fail;
02394 }
02395
02396 #if HTTPS_SUPPORT
02397
02398 if ((0 != (options & MHD_USE_SSL)) && (0 != MHD_TLS_init (daemon)))
02399 {
02400 #if HAVE_MESSAGES
02401 MHD_DLOG (daemon,
02402 "Failed to initialize TLS support\n");
02403 #endif
02404 if (-1 != socket_fd)
02405 CLOSE (socket_fd);
02406 pthread_mutex_destroy (&daemon->cleanup_connection_mutex);
02407 pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
02408 goto free_and_fail;
02409 }
02410 #endif
02411 if ( ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
02412 ( (0 != (options & MHD_USE_SELECT_INTERNALLY)) &&
02413 (0 == daemon->worker_pool_size)) ) &&
02414 (0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) &&
02415 (0 != (res_thread_create =
02416 create_thread (&daemon->pid, daemon, &MHD_select_thread, daemon))))
02417 {
02418 #if HAVE_MESSAGES
02419 MHD_DLOG (daemon,
02420 "Failed to create listen thread: %s\n",
02421 STRERROR (res_thread_create));
02422 #endif
02423 pthread_mutex_destroy (&daemon->cleanup_connection_mutex);
02424 pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
02425 if (-1 != socket_fd)
02426 CLOSE (socket_fd);
02427 goto free_and_fail;
02428 }
02429 if ( (daemon->worker_pool_size > 0) &&
02430 (0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) )
02431 {
02432 #ifndef MINGW
02433 int sk_flags;
02434 #else
02435 unsigned long sk_flags;
02436 #endif
02437
02438
02439
02440
02441 unsigned int conns_per_thread = daemon->max_connections
02442 / daemon->worker_pool_size;
02443 unsigned int leftover_conns = daemon->max_connections
02444 % daemon->worker_pool_size;
02445
02446 i = 0;
02447
02448
02449
02450
02451 #ifndef MINGW
02452 sk_flags = fcntl (socket_fd, F_GETFL);
02453 if (sk_flags < 0)
02454 goto thread_failed;
02455 if (0 != fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK))
02456 goto thread_failed;
02457 #else
02458 sk_flags = 1;
02459 #if HAVE_PLIBC_FD
02460 if (SOCKET_ERROR ==
02461 ioctlsocket (plibc_fd_get_handle (socket_fd), FIONBIO, &sk_flags))
02462 #else
02463 if (ioctlsocket (socket_fd, FIONBIO, &sk_flags) == SOCKET_ERROR)
02464 #endif // PLIBC_FD
02465 goto thread_failed;
02466 #endif // MINGW
02467
02468
02469 daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
02470 * daemon->worker_pool_size);
02471 if (NULL == daemon->worker_pool)
02472 goto thread_failed;
02473
02474
02475 for (i = 0; i < daemon->worker_pool_size; ++i)
02476 {
02477
02478 struct MHD_Daemon *d = &daemon->worker_pool[i];
02479 memcpy (d, daemon, sizeof (struct MHD_Daemon));
02480
02481
02482
02483
02484 d->master = daemon;
02485 d->worker_pool_size = 0;
02486 d->worker_pool = NULL;
02487
02488
02489
02490
02491 d->max_connections = conns_per_thread;
02492 if (i < leftover_conns)
02493 ++d->max_connections;
02494
02495
02496 if (0 != (res_thread_create = create_thread (&d->pid, daemon, &MHD_select_thread, d)))
02497 {
02498 #if HAVE_MESSAGES
02499 MHD_DLOG (daemon,
02500 "Failed to create pool thread: %s\n",
02501 STRERROR (res_thread_create));
02502 #endif
02503
02504
02505 goto thread_failed;
02506 }
02507 }
02508 }
02509 return daemon;
02510
02511 thread_failed:
02512
02513
02514
02515
02516 if (0 == i)
02517 {
02518 if (-1 != socket_fd)
02519 CLOSE (socket_fd);
02520 pthread_mutex_destroy (&daemon->cleanup_connection_mutex);
02521 pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
02522 if (NULL != daemon->worker_pool)
02523 free (daemon->worker_pool);
02524 goto free_and_fail;
02525 }
02526
02527
02528
02529
02530
02531 daemon->worker_pool_size = i - 1;
02532 MHD_stop_daemon (daemon);
02533 return NULL;
02534
02535 free_and_fail:
02536
02537
02538 #ifdef DAUTH_SUPPORT
02539 free (daemon->nnc);
02540 pthread_mutex_destroy (&daemon->nnc_lock);
02541 #endif
02542 #if HTTPS_SUPPORT
02543 if (0 != (options & MHD_USE_SSL))
02544 gnutls_priority_deinit (daemon->priority_cache);
02545 #endif
02546 free (daemon);
02547 return NULL;
02548 }
02549
02550
02558 static void
02559 close_all_connections (struct MHD_Daemon *daemon)
02560 {
02561 struct MHD_Connection *pos;
02562 void *unused;
02563 int rc;
02564
02565
02566
02567 if (0 != pthread_mutex_lock(&daemon->cleanup_connection_mutex))
02568 {
02569 MHD_PANIC ("Failed to acquire cleanup mutex\n");
02570 }
02571 for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
02572 SHUTDOWN (pos->socket_fd,
02573 (pos->read_closed == MHD_YES) ? SHUT_WR : SHUT_RDWR);
02574 if (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex))
02575 {
02576 MHD_PANIC ("Failed to release cleanup mutex\n");
02577 }
02578
02579
02580 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
02581 {
02582 while (NULL != (pos = daemon->connections_head))
02583 {
02584 if (0 != (rc = pthread_join (pos->pid, &unused)))
02585 {
02586 MHD_PANIC ("Failed to join a thread\n");
02587 }
02588 pos->thread_joined = MHD_YES;
02589 }
02590 }
02591
02592
02593 while (NULL != (pos = daemon->connections_head))
02594 {
02595 MHD_connection_close (pos,
02596 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
02597 DLL_remove (daemon->connections_head,
02598 daemon->connections_tail,
02599 pos);
02600 DLL_insert (daemon->cleanup_head,
02601 daemon->cleanup_tail,
02602 pos);
02603 }
02604 MHD_cleanup_connections (daemon);
02605 }
02606
02607
02613 void
02614 MHD_stop_daemon (struct MHD_Daemon *daemon)
02615 {
02616 void *unused;
02617 int fd;
02618 unsigned int i;
02619 int rc;
02620
02621 if (NULL == daemon)
02622 return;
02623 daemon->shutdown = MHD_YES;
02624 fd = daemon->socket_fd;
02625 daemon->socket_fd = -1;
02626
02627 if (NULL != daemon->worker_pool)
02628 {
02629
02630 for (i = 0; i < daemon->worker_pool_size; ++i)
02631 {
02632 daemon->worker_pool[i].shutdown = MHD_YES;
02633 daemon->worker_pool[i].socket_fd = -1;
02634 }
02635 }
02636 if (-1 != daemon->wpipe[1])
02637 {
02638 if (1 != WRITE (daemon->wpipe[1], "e", 1))
02639 MHD_PANIC ("failed to signal shutdownn via pipe");
02640 }
02641 #ifdef HAVE_LISTEN_SHUTDOWN
02642 else
02643 {
02644
02645 SHUTDOWN (fd, SHUT_RDWR);
02646 }
02647 #endif
02648 #if DEBUG_CLOSE
02649 #if HAVE_MESSAGES
02650 MHD_DLOG (daemon, "MHD listen socket shutdown\n");
02651 #endif
02652 #endif
02653
02654
02655
02656 if (NULL != daemon->worker_pool)
02657 {
02658
02659 for (i = 0; i < daemon->worker_pool_size; ++i)
02660 {
02661 if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused)))
02662 {
02663 MHD_PANIC ("Failed to join a thread\n");
02664 }
02665 close_all_connections (&daemon->worker_pool[i]);
02666 }
02667 free (daemon->worker_pool);
02668 }
02669 else
02670 {
02671
02672 if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
02673 ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))
02674 && (0 == daemon->worker_pool_size)))
02675 {
02676 if (0 != (rc = pthread_join (daemon->pid, &unused)))
02677 {
02678 MHD_PANIC ("Failed to join a thread\n");
02679 }
02680 }
02681 }
02682 close_all_connections (daemon);
02683 if (-1 != fd)
02684 CLOSE (fd);
02685
02686
02687 #if HTTPS_SUPPORT
02688 if (0 != (daemon->options & MHD_USE_SSL))
02689 {
02690 gnutls_priority_deinit (daemon->priority_cache);
02691 if (daemon->x509_cred)
02692 gnutls_certificate_free_credentials (daemon->x509_cred);
02693 }
02694 #endif
02695
02696 #ifdef DAUTH_SUPPORT
02697 free (daemon->nnc);
02698 pthread_mutex_destroy (&daemon->nnc_lock);
02699 #endif
02700 pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
02701 pthread_mutex_destroy (&daemon->cleanup_connection_mutex);
02702
02703 if (-1 != daemon->wpipe[1])
02704 {
02705 CLOSE (daemon->wpipe[0]);
02706 CLOSE (daemon->wpipe[1]);
02707 }
02708
02709 free (daemon);
02710 }
02711
02712
02723 const union MHD_DaemonInfo *
02724 MHD_get_daemon_info (struct MHD_Daemon *daemon,
02725 enum MHD_DaemonInfoType infoType, ...)
02726 {
02727 switch (infoType)
02728 {
02729 case MHD_DAEMON_INFO_LISTEN_FD:
02730 return (const union MHD_DaemonInfo *) &daemon->socket_fd;
02731 default:
02732 return NULL;
02733 };
02734 }
02735
02736
02752 void
02753 MHD_set_panic_func (MHD_PanicCallback cb, void *cls)
02754 {
02755 mhd_panic = cb;
02756 mhd_panic_cls = cls;
02757 }
02758
02759
02765 const char *
02766 MHD_get_version (void)
02767 {
02768 return PACKAGE_VERSION;
02769 }
02770
02771
02772 #ifdef __GNUC__
02773 #define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor))
02774 #define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor))
02775 #else // !__GNUC__
02776 #define ATTRIBUTE_CONSTRUCTOR
02777 #define ATTRIBUTE_DESTRUCTOR
02778 #endif // __GNUC__
02779
02780 #if HTTPS_SUPPORT
02781 GCRY_THREAD_OPTION_PTHREAD_IMPL;
02782 #endif
02783
02784
02788 void ATTRIBUTE_CONSTRUCTOR
02789 MHD_init ()
02790 {
02791 mhd_panic = &mhd_panic_std;
02792 mhd_panic_cls = NULL;
02793
02794 #ifdef WINDOWS
02795 plibc_init_utf8 ("GNU", "libmicrohttpd", 1);
02796 #endif
02797 #if HTTPS_SUPPORT
02798 gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
02799 gnutls_global_init ();
02800 #endif
02801 }
02802
02803
02804 void ATTRIBUTE_DESTRUCTOR
02805 MHD_fini ()
02806 {
02807 #if HTTPS_SUPPORT
02808 gnutls_global_deinit ();
02809 #endif
02810 #ifdef WINDOWS
02811 plibc_shutdown ();
02812 #endif
02813 }
02814
02815