daemon.c

Go to the documentation of this file.
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, &ltimeout)) )
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, &ltimeout)) )
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 */

Generated on Thu Sep 27 17:58:52 2012 for GNU libmicrohttpd by  doxygen 1.4.7