|
GNU libmicrohttpd
0.9.5
|
00001 /* 00002 This file is part of libmicrohttpd 00003 (C) 2007, 2008, 2009, 2010, 2011, 2012 Daniel Pittman and Christian Grothoff 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Lesser General Public 00007 License as published by the Free Software Foundation; either 00008 version 2.1 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public 00016 License along with this library; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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 /* IPv4 addresses */ 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 /* IPv6 addresses */ 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 /* Some other address */ 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 /* Ignore if no connection limit assigned */ 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 /* Initialize key */ 00283 if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, key)) 00284 { 00285 /* Allow unhandled address types through */ 00286 free (key); 00287 return MHD_YES; 00288 } 00289 MHD_ip_count_lock (daemon); 00290 00291 /* Search for the IP address */ 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 /* If we got an existing node back, free the one we created */ 00306 if (node != key) 00307 free(key); 00308 key = (struct MHD_IPCount *) node; 00309 /* Test if there is room for another connection; if so, 00310 * increment count */ 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 /* Ignore if no connection limit assigned */ 00339 if (0 == daemon->per_ip_connection_limit) 00340 return; 00341 /* Initialize search key */ 00342 if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, &search_key)) 00343 return; 00344 00345 MHD_ip_count_lock (daemon); 00346 00347 /* Search for the IP address */ 00348 if (NULL == (nodep = TFIND (&search_key, 00349 &daemon->per_ip_connection_count, 00350 &MHD_ip_addr_compare))) 00351 { 00352 /* Something's wrong if we couldn't find an IP address 00353 * that was previously added */ 00354 MHD_PANIC ("Failed to find previously-added IP address\n"); 00355 } 00356 found_key = (struct MHD_IPCount *) *nodep; 00357 /* Validate existing count for IP address */ 00358 if (0 == found_key->count) 00359 { 00360 MHD_PANIC ("Previously-added IP address had 0 count\n"); 00361 } 00362 /* Remove the node entirely if count reduces to 0 */ 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 /* Likely 'GNUTLS_E_INVALID_SESSION' (client communication 00399 disrupted); set errno to something caller will interpret 00400 correctly as a hard error*/ 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 /* certificate & key loaded from memory */ 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 /* update max file descriptor */ 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 /* do not block (we're waiting for our callback to succeed) */ 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 /* use select */ 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 /* call appropriate connection handler if necessary */ 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 /* use poll */ 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 /* can use sendfile */ 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; /* cap at return value limit */ 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 /* None of the 'usual' sendfile errors occurred, so we should try 00773 to fall back to 'SEND'; see also this thread for info on 00774 odd libc/Linux behavior with sendfile: 00775 http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */ 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 /* above connection limit - reject */ 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 /* apply connection acceptance policy if present */ 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 /* set default connection handlers */ 00962 MHD_set_http_callbacks_ (connection); 00963 connection->recv_cls = &recv_param_adapter; 00964 connection->send_cls = &send_param_adapter; 00965 /* non-blocking sockets are required on most systems and for GNUtls; 00966 however, they somehow cause serious problems on CYGWIN (#1824) */ 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 /* make socket non-blocking */ 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 /* set needed credentials for certificate authentication. */ 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 /* attempt to create handler thread */ 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 /* This could be a common occurance with multiple worker threads */ 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 /* just in case */ 01146 } 01147 return MHD_NO; 01148 } 01149 if (MHD_YES == need_fcntl) 01150 { 01151 /* make socket non-inheritable */ 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 /* single-threaded, go over everything */ 01328 if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max)) 01329 return MHD_NO; 01330 01331 /* If we're at the connection limit, no need to 01332 accept new connections. */ 01333 if ( (0 == daemon->max_connections) && 01334 (-1 != daemon->socket_fd) ) 01335 FD_CLR (daemon->socket_fd, &rs); 01336 } 01337 else 01338 { 01339 /* accept only, have one thread per connection */ 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 /* update max file descriptor */ 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 /* ltimeout is in ms */ 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 /* select connection thread handling type */ 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 /* do not have a thread per connection, process all connections now */ 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 /* count number of connections and thus determine poll set size */ 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 /* only listen if we are not at the connection limit */ 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 /* handle shutdown */ 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 /* first, sanity checks */ 01499 if (i >= num_connections) 01500 break; /* connection list changed somehow, retry later ... */ 01501 MHD_connection_get_pollfd (pos, &mp); 01502 if (p[poll_server+i].fd != mp.fd) 01503 break; /* fd mismatch, something else happened, retry later ... */ 01504 01505 /* normal handling */ 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 /* handle shutdown */ 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 /* all options taking 'size_t' */ 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 /* all options taking 'unsigned int' */ 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 /* all options taking 'int' or 'enum' */ 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 /* all options taking one pointer */ 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 /* all options taking two pointers */ 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 /* options taking size_t-number followed by pointer */ 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 /* use SOCK_STREAM rather than ai_socktype: some getaddrinfo 02002 * implementations do not set ai_socktype, e.g. RHL6.2. */ 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; /* this is it */ 02013 /* flag was not set during 'socket' call, let's try setting it manually */ 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; /* good luck */ 02025 } 02026 #if !WINDOWS 02027 if (flags == (flags | FD_CLOEXEC)) 02028 return fd; /* already set */ 02029 flags |= FD_CLOEXEC; 02030 if (0 != fcntl (fd, F_SETFD, flags)) 02031 #else 02032 if (dwFlags != (dwFlags | HANDLE_FLAG_INHERIT)) 02033 return fd; /* already unset */ 02034 if (!SetHandleInformation ((HANDLE) fd, HANDLE_FLAG_INHERIT, 0)) 02035 #endif 02036 { 02037 #if WINDOWS 02038 SetErrnoFromWinError (GetLastError ()); 02039 #endif 02040 return fd; /* good luck */ 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; /* no timeout */ 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; /* yes, must use pipe to signal shutdown */ 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; /* tiny */ 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 /* Thread pooling currently works only with internal select thread model */ 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 /* try to open listen socket */ 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 /* check for user supplied sockaddr */ 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 /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options" 02312 (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx); 02313 and may also be missing on older POSIX systems; good luck if you have any of those, 02314 your IPv6 socket may then also bind against IPv4... */ 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 /* initialize HTTPS daemon certificate aspects & send / recv functions */ 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 /* Coarse-grained count of connections per thread (note error 02439 * due to integer division). Also keep track of how many 02440 * connections are leftover after an equal split. */ 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; /* we need this in case fcntl or malloc fails */ 02447 02448 /* Accept must be non-blocking. Multiple children may wake up 02449 * to handle a new connection, but only one will win the race. 02450 * The others must immediately return. */ 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 /* Allocate memory for pooled objects */ 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 /* Start the workers in the pool */ 02475 for (i = 0; i < daemon->worker_pool_size; ++i) 02476 { 02477 /* Create copy of the Daemon object for each worker */ 02478 struct MHD_Daemon *d = &daemon->worker_pool[i]; 02479 memcpy (d, daemon, sizeof (struct MHD_Daemon)); 02480 02481 /* Adjust pooling params for worker daemons; note that memcpy() 02482 has already copied MHD_USE_SELECT_INTERNALLY thread model into 02483 the worker threads. */ 02484 d->master = daemon; 02485 d->worker_pool_size = 0; 02486 d->worker_pool = NULL; 02487 02488 /* Divide available connections evenly amongst the threads. 02489 * Thread indexes in [0, leftover_conns) each get one of the 02490 * leftover connections. */ 02491 d->max_connections = conns_per_thread; 02492 if (i < leftover_conns) 02493 ++d->max_connections; 02494 02495 /* Spawn the worker thread */ 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 /* Free memory for this worker; cleanup below handles 02504 * all previously-created workers. */ 02505 goto thread_failed; 02506 } 02507 } 02508 } 02509 return daemon; 02510 02511 thread_failed: 02512 /* If no worker threads created, then shut down normally. Calling 02513 MHD_stop_daemon (as we do below) doesn't work here since it 02514 assumes a 0-sized thread pool means we had been in the default 02515 MHD_USE_SELECT_INTERNALLY mode. */ 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 /* Shutdown worker threads we've already created. Pretend 02528 as though we had fully initialized our daemon, but 02529 with a smaller number of threads than had been 02530 requested. */ 02531 daemon->worker_pool_size = i - 1; 02532 MHD_stop_daemon (daemon); 02533 return NULL; 02534 02535 free_and_fail: 02536 /* clean up basic memory state in 'daemon' and return NULL to 02537 indicate failure */ 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 /* first, make sure all threads are aware of shutdown; need to 02566 traverse DLLs in peace... */ 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 /* now, collect threads */ 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 /* now that we're alone, move everyone to cleanup */ 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 /* Prepare workers for shutdown */ 02627 if (NULL != daemon->worker_pool) 02628 { 02629 /* MHD_USE_NO_LISTEN_SOCKET disables thread pools, hence we need to check */ 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 /* fd must not be -1 here, otherwise we'd have used the wpipe */ 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 /* Signal workers to stop and clean them up */ 02656 if (NULL != daemon->worker_pool) 02657 { 02658 /* MHD_USE_NO_LISTEN_SOCKET disables thread pools, hence we need to check */ 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 /* clean up master threads */ 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 /* TLS clean up */ 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 /* end of daemon.c */