daemon.c

Go to the documentation of this file.
00001 /*
00002   This file is part of libmicrohttpd
00003   (C) 2007, 2008, 2009 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 
00033 #if HTTPS_SUPPORT
00034 #include "connection_https.h"
00035 #include "gnutls_int.h"
00036 #include "gnutls_global.h"
00037 #endif
00038 
00039 #ifdef HAVE_POLL_H
00040 #include <poll.h>
00041 #endif
00042 
00046 #ifndef WINDOWS
00047 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE -4
00048 #else
00049 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE
00050 #endif
00051 
00055 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
00056 
00061 #define DEBUG_CLOSE MHD_NO
00062 
00067 #define DEBUG_CONNECT MHD_NO
00068 
00069 #ifndef LINUX
00070 #ifndef MSG_NOSIGNAL
00071 #define MSG_NOSIGNAL 0
00072 #endif
00073 #ifndef MSG_DONTWAIT
00074 #define MSG_DONTWAIT 0
00075 #endif
00076 #endif
00077 
00078 #ifdef __SYMBIAN32__
00079 static void pthread_kill (int, int) {
00080   // Symbian doesn't have signals. The user of the library is required to
00081   // run it in an external select loop.
00082   abort();
00083 }
00084 #endif  // __SYMBIAN32__
00085 
00089 static void 
00090 mhd_panic_std(void *cls,
00091               const char *file,
00092               unsigned int line,
00093               const char *reason)
00094 {
00095   abort ();
00096 }
00097 
00098 
00102 MHD_PanicCallback mhd_panic;
00103 
00107 void *mhd_panic_cls;
00108 
00113 static struct MHD_Daemon*
00114 MHD_get_master (struct MHD_Daemon *daemon)
00115 {
00116   while (NULL != daemon->master)
00117     daemon = daemon->master;
00118   return daemon;
00119 }
00120 
00124 struct MHD_IPCount
00125 {
00126   int family;
00127   union
00128   {
00129     struct in_addr ipv4;
00130 #if HAVE_IPV6
00131     struct in6_addr ipv6;
00132 #endif
00133   } addr;
00134   unsigned int count;
00135 };
00136 
00140 static void
00141 MHD_ip_count_lock(struct MHD_Daemon *daemon)
00142 {
00143   if (0 != pthread_mutex_lock(&daemon->per_ip_connection_mutex))
00144     {
00145 #if HAVE_MESSAGES
00146       MHD_DLOG (daemon, "Failed to acquire IP connection limit mutex\n");
00147 #endif
00148       abort();
00149     }
00150 }
00151 
00155 static void
00156 MHD_ip_count_unlock(struct MHD_Daemon *daemon)
00157 {
00158   if (0 != pthread_mutex_unlock(&daemon->per_ip_connection_mutex))
00159     {
00160 #if HAVE_MESSAGES
00161       MHD_DLOG (daemon, "Failed to release IP connection limit mutex\n");
00162 #endif
00163       abort();
00164     }
00165 }
00166 
00172 static int
00173 MHD_ip_addr_compare(const void *a1, const void *a2)
00174 {
00175   return memcmp (a1, a2, offsetof(struct MHD_IPCount, count));
00176 }
00177 
00182 static int
00183 MHD_ip_addr_to_key(struct sockaddr *addr, socklen_t addrlen,
00184                    struct MHD_IPCount *key)
00185 {
00186   memset(key, 0, sizeof(*key));
00187 
00188   /* IPv4 addresses */
00189   if (addrlen == sizeof(struct sockaddr_in))
00190     {
00191       const struct sockaddr_in *addr4 = (const struct sockaddr_in*)addr;
00192       key->family = AF_INET;
00193       memcpy (&key->addr.ipv4, &addr4->sin_addr, sizeof(addr4->sin_addr));
00194       return MHD_YES;
00195     }
00196 
00197 #if HAVE_IPV6
00198   /* IPv6 addresses */
00199   if (addrlen == sizeof (struct sockaddr_in6))
00200     {
00201       const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)addr;
00202       key->family = AF_INET6;
00203       memcpy (&key->addr.ipv6, &addr6->sin6_addr, sizeof(addr6->sin6_addr));
00204       return MHD_YES;
00205     }
00206 #endif
00207 
00208   /* Some other address */
00209   return MHD_NO;
00210 }
00211 
00218 static int
00219 MHD_ip_limit_add(struct MHD_Daemon *daemon,
00220                  struct sockaddr *addr, socklen_t addrlen)
00221 {
00222   struct MHD_IPCount *key;
00223   void *node;
00224   int result;
00225 
00226   daemon = MHD_get_master (daemon);
00227 
00228   /* Ignore if no connection limit assigned */
00229   if (daemon->per_ip_connection_limit == 0)
00230     return MHD_YES;
00231 
00232   key = malloc (sizeof(*key));
00233   if (NULL == key)
00234     return MHD_NO;
00235 
00236   /* Initialize key */
00237   if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, key))
00238     {
00239       /* Allow unhandled address types through */
00240       free (key);
00241       return MHD_YES;
00242     }
00243 
00244   MHD_ip_count_lock (daemon);
00245 
00246   /* Search for the IP address */
00247   node = (void*)TSEARCH (key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
00248   if (!node)
00249     {
00250 #if HAVE_MESSAGES
00251       MHD_DLOG(daemon,
00252                "Failed to add IP connection count node\n");
00253 #endif
00254       MHD_ip_count_unlock (daemon);
00255       return MHD_NO;
00256     }
00257   node = *(void**)node;
00258 
00259   /* If we got an existing node back, free the one we created */
00260   if (node != key)
00261     free(key);
00262   key = (struct MHD_IPCount*)node;
00263 
00264   /* Test if there is room for another connection; if so,
00265    * increment count */
00266   result = (key->count < daemon->per_ip_connection_limit);
00267   if (result == MHD_YES)
00268     ++key->count;
00269 
00270   MHD_ip_count_unlock (daemon);
00271   return result;
00272 }
00273 
00278 static void
00279 MHD_ip_limit_del(struct MHD_Daemon *daemon,
00280                  struct sockaddr *addr, socklen_t addrlen)
00281 {
00282   struct MHD_IPCount search_key;
00283   struct MHD_IPCount *found_key;
00284   void *node;
00285 
00286   daemon = MHD_get_master (daemon);
00287 
00288   /* Ignore if no connection limit assigned */
00289   if (daemon->per_ip_connection_limit == 0)
00290     return;
00291 
00292   /* Initialize search key */
00293   if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, &search_key))
00294     return;
00295 
00296   MHD_ip_count_lock (daemon);
00297 
00298   /* Search for the IP address */
00299   node = (void*)TFIND (&search_key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
00300 
00301   /* Something's wrong if we couldn't find an IP address
00302    * that was previously added */
00303   if (!node)
00304     {
00305 #if HAVE_MESSAGES
00306       MHD_DLOG (daemon,
00307                 "Failed to find previously-added IP address\n");
00308 #endif
00309       abort();
00310     }
00311   found_key = (struct MHD_IPCount*)*(void**)node;
00312 
00313   /* Validate existing count for IP address */
00314   if (found_key->count == 0)
00315     {
00316 #if HAVE_MESSAGES
00317       MHD_DLOG (daemon,
00318                 "Previously-added IP address had 0 count\n");
00319 #endif
00320       abort();
00321     }
00322 
00323   /* Remove the node entirely if count reduces to 0 */
00324   if (--found_key->count == 0)
00325     {
00326       TDELETE (found_key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
00327       free (found_key);
00328     }
00329 
00330   MHD_ip_count_unlock (daemon);
00331 }
00332 
00333 #if HTTPS_SUPPORT
00334 pthread_mutex_t MHD_gnutls_init_mutex;
00335 
00341 static int
00342 _set_priority (MHD_gtls_priority_st * st, const int *list)
00343 {
00344   int num = 0;
00345 
00346   while ((list[num] != 0) && (num < MAX_ALGOS))
00347     num++;
00348   st->num_algorithms = num;
00349   memcpy (st->priority, list, num * sizeof (int));
00350   return 0;
00351 }
00352 
00353 
00362 static ssize_t
00363 recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i)
00364 {
00365   return MHD__gnutls_record_recv (connection->tls_session, other, i);
00366 }
00367 
00376 static ssize_t
00377 send_tls_adapter (struct MHD_Connection *connection,
00378                   const void *other, size_t i)
00379 {
00380   return MHD__gnutls_record_send (connection->tls_session, other, i);
00381 }
00382 
00383 
00389 static int
00390 MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
00391 {
00392   MHD_gnutls_datum_t key;
00393   MHD_gnutls_datum_t cert;
00394 
00395   /* certificate & key loaded from memory */
00396   if (daemon->https_mem_cert && daemon->https_mem_key)
00397     {
00398       key.data = (unsigned char *) daemon->https_mem_key;
00399       key.size = strlen (daemon->https_mem_key);
00400       cert.data = (unsigned char *) daemon->https_mem_cert;
00401       cert.size = strlen (daemon->https_mem_cert);
00402 
00403       return MHD__gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
00404                                                        &cert, &key,
00405                                                        GNUTLS_X509_FMT_PEM);
00406     }
00407 #if HAVE_MESSAGES
00408   MHD_DLOG (daemon, "You need to specify a certificate and key location\n");
00409 #endif
00410   return -1;
00411 }
00412 
00418 static int
00419 MHD_TLS_init (struct MHD_Daemon *daemon)
00420 {
00421   switch (daemon->cred_type)
00422     {
00423     case MHD_GNUTLS_CRD_CERTIFICATE:
00424       if (0 !=
00425           MHD__gnutls_certificate_allocate_credentials (&daemon->x509_cred))
00426         return GNUTLS_E_MEMORY_ERROR;
00427       return MHD_init_daemon_certificate (daemon);
00428     default:
00429 #if HAVE_MESSAGES
00430       MHD_DLOG (daemon,
00431                 "Error: invalid credentials type %d specified.\n",
00432                 daemon->cred_type);
00433 #endif
00434       return -1;
00435     }
00436 }
00437 #endif
00438 
00446 int
00447 MHD_get_fdset (struct MHD_Daemon *daemon,
00448                fd_set * read_fd_set,
00449                fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd)
00450 {
00451   struct MHD_Connection *con_itr;
00452   int fd;
00453 
00454   if ((daemon == NULL) || (read_fd_set == NULL) || (write_fd_set == NULL)
00455       || (except_fd_set == NULL) || (max_fd == NULL)
00456       || (-1 == (fd = daemon->socket_fd)) || (daemon->shutdown == MHD_YES)
00457       || ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0)
00458       || ((daemon->options & MHD_USE_POLL) != 0))
00459     return MHD_NO;
00460 
00461   FD_SET (fd, read_fd_set);
00462   /* update max file descriptor */
00463   if ((*max_fd) < fd)
00464     *max_fd = fd;
00465 
00466   con_itr = daemon->connections;
00467   while (con_itr != NULL)
00468     {
00469       if (MHD_YES != MHD_connection_get_fdset (con_itr,
00470                                                read_fd_set,
00471                                                write_fd_set,
00472                                                except_fd_set, max_fd))
00473         return MHD_NO;
00474       con_itr = con_itr->next;
00475     }
00476 #if DEBUG_CONNECT
00477   MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
00478 #endif
00479   return MHD_YES;
00480 }
00481 
00486 static void *
00487 MHD_handle_connection (void *data)
00488 {
00489   struct MHD_Connection *con = data;
00490   int num_ready;
00491   fd_set rs;
00492   fd_set ws;
00493   fd_set es;
00494   int max;
00495   struct timeval tv;
00496   unsigned int timeout;
00497   time_t now;
00498 #ifdef HAVE_POLL_H
00499   struct MHD_Pollfd mp;
00500   struct pollfd p;
00501 #endif
00502 
00503   timeout = con->daemon->connection_timeout;
00504   while ((!con->daemon->shutdown) && (con->socket_fd != -1)) {
00505       now = time (NULL);
00506       tv.tv_usec = 0;
00507       if ( (timeout > (now - con->last_activity)) ||
00508            (timeout == 0) )
00509         {
00510           /* in case we are missing the SIGALRM, keep going after
00511              at most 1s; see http://lists.gnu.org/archive/html/libmicrohttpd/2009-10/msg00013.html */
00512           tv.tv_sec = 1;
00513           if ((con->state == MHD_CONNECTION_NORMAL_BODY_UNREADY) ||
00514               (con->state == MHD_CONNECTION_CHUNKED_BODY_UNREADY))
00515             {
00516               /* do not block (we're waiting for our callback to succeed) */
00517               tv.tv_sec = 0;
00518             }
00519         }
00520       else
00521         {
00522           tv.tv_sec = 0;
00523         }
00524 #ifdef HAVE_POLL_H
00525       if (0 == (con->daemon->options & MHD_USE_POLL)) {
00526 #else
00527       {
00528 #endif
00529         /* use select */
00530         FD_ZERO (&rs);
00531         FD_ZERO (&ws);
00532         FD_ZERO (&es);
00533         max = 0;
00534         MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
00535         num_ready = SELECT (max + 1, &rs, &ws, &es, &tv);
00536         if (num_ready < 0) {
00537             if (errno == EINTR)
00538               continue;
00539 #if HAVE_MESSAGES
00540             MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n", max,
00541                       STRERROR (errno));
00542 #endif
00543             break;
00544         }
00545         /* call appropriate connection handler if necessary */
00546         if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &rs)))
00547           con->read_handler (con);
00548         if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
00549           con->write_handler (con);
00550         if (con->socket_fd != -1)
00551           con->idle_handler (con);
00552       }
00553 #ifdef HAVE_POLL_H
00554       else
00555       {
00556         /* use poll */
00557         memset(&mp, 0, sizeof (struct MHD_Pollfd));
00558         MHD_connection_get_pollfd(con, &mp);
00559         memset(&p, 0, sizeof (struct pollfd));
00560         p.fd = mp.fd;
00561         if (mp.events & MHD_POLL_ACTION_IN) 
00562           p.events |= POLLIN;        
00563         if (mp.events & MHD_POLL_ACTION_OUT) 
00564           p.events |= POLLOUT;
00565         /* in case we are missing the SIGALRM, keep going after
00566            at most 1s */
00567         if (poll (&p, 1, 1000) < 0) {
00568           if (errno == EINTR)
00569             continue;
00570 #if HAVE_MESSAGES
00571           MHD_DLOG (con->daemon, "Error during poll: `%s'\n", 
00572                     STRERROR (errno));
00573 #endif
00574           break;
00575         }
00576         if ( (con->socket_fd != -1) && 
00577              (0 != (p.revents & POLLIN)) ) 
00578           con->read_handler (con);        
00579         if ( (con->socket_fd != -1) && 
00580              (0 != (p.revents & POLLOUT)) )
00581           con->write_handler (con);        
00582         if (con->socket_fd != -1)
00583           con->idle_handler (con);
00584         if ( (con->socket_fd != -1) &&
00585              (0 != (p.revents & (POLLERR | POLLHUP))) )
00586           MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR);      
00587       }
00588 #endif
00589     }
00590   if (con->socket_fd != -1)
00591     {
00592 #if DEBUG_CLOSE
00593 #if HAVE_MESSAGES
00594       MHD_DLOG (con->daemon,
00595                 "Processing thread terminating, closing connection\n");
00596 #endif
00597 #endif
00598       MHD_connection_close (con, MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
00599     }
00600   return NULL;
00601 }
00602 
00611 static ssize_t
00612 recv_param_adapter (struct MHD_Connection *connection, void *other, size_t i)
00613 {
00614   if (connection->socket_fd == -1)
00615     return -1;
00616   if (0 != (connection->daemon->options & MHD_USE_SSL))
00617     return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
00618   else
00619     return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT);
00620 }
00621 
00630 static ssize_t
00631 send_param_adapter (struct MHD_Connection *connection,
00632                     const void *other, size_t i)
00633 {
00634   if (connection->socket_fd == -1)
00635     return -1;
00636   if (0 != (connection->daemon->options & MHD_USE_SSL))
00637     return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
00638   else
00639     return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT);
00640 }
00641 
00647 static int
00648 MHD_accept_connection (struct MHD_Daemon *daemon)
00649 {
00650   struct MHD_Connection *connection;
00651 #if HAVE_INET6
00652   struct sockaddr_in6 addrstorage;
00653 #else
00654   struct sockaddr_in addrstorage;
00655 #endif
00656   struct sockaddr *addr = (struct sockaddr *) &addrstorage;
00657   socklen_t addrlen;
00658   int s;
00659   int res_thread_create;
00660 #if OSX
00661   static int on = 1;
00662 #endif
00663 
00664   addrlen = sizeof (addrstorage);
00665   memset (addr, 0, sizeof (addrstorage));
00666 
00667   s = ACCEPT (daemon->socket_fd, addr, &addrlen);
00668   if ((s == -1) || (addrlen <= 0))
00669     {
00670 #if HAVE_MESSAGES
00671       /* This could be a common occurance with multiple worker threads */
00672       if ((EAGAIN != errno) && (EWOULDBLOCK != errno))
00673         MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));
00674 #endif
00675       if (s != -1)
00676         {
00677           SHUTDOWN (s, SHUT_RDWR);
00678           CLOSE (s);
00679           /* just in case */
00680         }
00681       return MHD_NO;
00682     }
00683 #ifndef WINDOWS
00684   if ( (s >= FD_SETSIZE) &&
00685        (0 == (daemon->options & MHD_USE_POLL)) )
00686     {
00687 #if HAVE_MESSAGES
00688       MHD_DLOG (daemon,
00689                 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
00690                 s,
00691                 FD_SETSIZE);
00692 #endif
00693       CLOSE (s);
00694       return MHD_NO;
00695     }
00696 #endif
00697 
00698 
00699 #if HAVE_MESSAGES
00700 #if DEBUG_CONNECT
00701   MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
00702 #endif
00703 #endif
00704   if ((daemon->max_connections == 0)
00705       || (MHD_ip_limit_add (daemon, addr, addrlen) == MHD_NO))
00706     {
00707       /* above connection limit - reject */
00708 #if HAVE_MESSAGES
00709       MHD_DLOG (daemon,
00710                 "Server reached connection limit (closing inbound connection)\n");
00711 #endif
00712       SHUTDOWN (s, SHUT_RDWR);
00713       CLOSE (s);
00714       return MHD_NO;
00715     }
00716 
00717   /* apply connection acceptance policy if present */
00718   if ((daemon->apc != NULL)
00719       && (MHD_NO == daemon->apc (daemon->apc_cls, addr, addrlen)))
00720     {
00721 #if DEBUG_CLOSE
00722 #if HAVE_MESSAGES
00723       MHD_DLOG (daemon, "Connection rejected, closing connection\n");
00724 #endif
00725 #endif
00726       SHUTDOWN (s, SHUT_RDWR);
00727       CLOSE (s);
00728       MHD_ip_limit_del (daemon, addr, addrlen);
00729       return MHD_YES;
00730     }
00731 #if OSX
00732 #ifdef SOL_SOCKET
00733 #ifdef SO_NOSIGPIPE
00734   setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof (on));
00735 #endif
00736 #endif
00737 #endif
00738   connection = malloc (sizeof (struct MHD_Connection));
00739   if (NULL == connection)
00740     {
00741 #if HAVE_MESSAGES
00742       MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00743 #endif
00744       SHUTDOWN (s, SHUT_RDWR);
00745       CLOSE (s);
00746       MHD_ip_limit_del (daemon, addr, addrlen);
00747       return MHD_NO;
00748     }
00749   memset (connection, 0, sizeof (struct MHD_Connection));
00750   connection->pool = NULL;
00751   connection->addr = malloc (addrlen);
00752   if (connection->addr == NULL)
00753     {
00754 #if HAVE_MESSAGES
00755       MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00756 #endif
00757       SHUTDOWN (s, SHUT_RDWR);
00758       CLOSE (s);
00759       MHD_ip_limit_del (daemon, addr, addrlen);
00760       free (connection);
00761       return MHD_NO;
00762     }
00763   memcpy (connection->addr, addr, addrlen);
00764   connection->addr_len = addrlen;
00765   connection->socket_fd = s;
00766   connection->daemon = daemon;
00767   connection->last_activity = time (NULL);
00768 
00769   /* set default connection handlers  */
00770   MHD_set_http_calbacks (connection);
00771   connection->recv_cls = &recv_param_adapter;
00772   connection->send_cls = &send_param_adapter;
00773 #if HTTPS_SUPPORT
00774   if (0 != (daemon->options & MHD_USE_SSL))
00775     {
00776       connection->recv_cls = &recv_tls_adapter;
00777       connection->send_cls = &send_tls_adapter;
00778       connection->state = MHD_TLS_CONNECTION_INIT;
00779       MHD_set_https_calbacks (connection);
00780       MHD__gnutls_init (&connection->tls_session, GNUTLS_SERVER);
00781       MHD__gnutls_priority_set (connection->tls_session,
00782                                 connection->daemon->priority_cache);
00783       switch (connection->daemon->cred_type)
00784         {
00785           /* set needed credentials for certificate authentication. */
00786         case MHD_GNUTLS_CRD_CERTIFICATE:
00787           MHD__gnutls_credentials_set (connection->tls_session,
00788                                        MHD_GNUTLS_CRD_CERTIFICATE,
00789                                        connection->daemon->x509_cred);
00790           break;
00791         default:
00792 #if HAVE_MESSAGES
00793           MHD_DLOG (connection->daemon,
00794                     "Failed to setup TLS credentials: unknown credential type %d\n",
00795                     connection->daemon->cred_type);
00796 #endif
00797           SHUTDOWN (s, SHUT_RDWR);
00798           CLOSE (s);
00799           MHD_ip_limit_del (daemon, addr, addrlen);
00800           free (connection->addr);
00801           free (connection);
00802           mhd_panic (mhd_panic_cls, __FILE__, __LINE__, 
00803 #if HAVE_MESSAGES
00804                      "Unknown credential type"
00805 #else
00806                      NULL
00807 #endif
00808                      );
00809           return MHD_NO;
00810         }
00811       MHD__gnutls_transport_set_ptr (connection->tls_session,
00812                                      (MHD_gnutls_transport_ptr_t) connection);
00813       MHD__gnutls_transport_set_pull_function (connection->tls_session,
00814                                                (MHD_gtls_pull_func) &
00815                                                recv_param_adapter);
00816       MHD__gnutls_transport_set_push_function (connection->tls_session,
00817                                                (MHD_gtls_push_func) &
00818                                                send_param_adapter);
00819     }
00820 #endif
00821 
00822   /* attempt to create handler thread */
00823   if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00824     {
00825       res_thread_create = pthread_create (&connection->pid, NULL,
00826                                           &MHD_handle_connection, connection);
00827       if (res_thread_create != 0)
00828         {
00829 #if HAVE_MESSAGES
00830           MHD_DLOG (daemon, "Failed to create a thread: %s\n",
00831                     STRERROR (res_thread_create));
00832 #endif
00833           SHUTDOWN (s, SHUT_RDWR);
00834           CLOSE (s);
00835           MHD_ip_limit_del (daemon, addr, addrlen);
00836           free (connection->addr);
00837           free (connection);
00838           return MHD_NO;
00839         }
00840     }
00841   connection->next = daemon->connections;
00842   daemon->connections = connection;
00843   daemon->max_connections--;
00844   return MHD_YES;
00845 }
00846 
00852 static void
00853 MHD_cleanup_connections (struct MHD_Daemon *daemon)
00854 {
00855   struct MHD_Connection *pos;
00856   struct MHD_Connection *prev;
00857   void *unused;
00858   int rc;
00859 
00860   pos = daemon->connections;
00861   prev = NULL;
00862   while (pos != NULL)
00863     {
00864       if ((pos->socket_fd == -1) ||
00865           (((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
00866             (daemon->shutdown) && (pos->socket_fd != -1))))
00867         {
00868           if (prev == NULL)
00869             daemon->connections = pos->next;
00870           else
00871             prev->next = pos->next;
00872           if (0 != (pos->daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00873             {
00874               pthread_kill (pos->pid, SIGALRM);
00875               if (0 != (rc = pthread_join (pos->pid, &unused)))
00876                 {
00877 #if HAVE_MESSAGES
00878                   MHD_DLOG (daemon, "Failed to join a thread: %s\n",
00879                             STRERROR (rc));
00880 #endif
00881                   abort();
00882                 }
00883             }
00884           MHD_destroy_response (pos->response);
00885           MHD_pool_destroy (pos->pool);
00886 #if HTTPS_SUPPORT
00887           if (pos->tls_session != NULL)
00888             MHD__gnutls_deinit (pos->tls_session);
00889 #endif
00890           MHD_ip_limit_del (daemon, (struct sockaddr*)pos->addr, pos->addr_len);
00891           free (pos->addr);
00892           free (pos);
00893           daemon->max_connections++;
00894           if (prev == NULL)
00895             pos = daemon->connections;
00896           else
00897             pos = prev->next;
00898           continue;
00899         }
00900       prev = pos;
00901       pos = pos->next;
00902     }
00903 }
00904 
00916 int
00917 MHD_get_timeout (struct MHD_Daemon *daemon, unsigned long long *timeout)
00918 {
00919   time_t earliest_deadline;
00920   time_t now;
00921   struct MHD_Connection *pos;
00922   unsigned int dto;
00923 
00924   dto = daemon->connection_timeout;
00925   if (0 == dto)
00926     return MHD_NO;
00927   pos = daemon->connections;
00928   if (pos == NULL)
00929     return MHD_NO;              /* no connections */
00930   now = time (NULL);
00931   /* start with conservative estimate */
00932   earliest_deadline = now + dto;
00933   while (pos != NULL)
00934     {
00935       if (earliest_deadline > pos->last_activity + dto)
00936         earliest_deadline = pos->last_activity + dto;
00937       pos = pos->next;
00938     }
00939   if (earliest_deadline < now)
00940     *timeout = 0;
00941   else
00942     *timeout = (earliest_deadline - now);
00943   return MHD_YES;
00944 }
00945 
00952 static int
00953 MHD_select (struct MHD_Daemon *daemon, int may_block)
00954 {
00955   struct MHD_Connection *pos;
00956   int num_ready;
00957   fd_set rs;
00958   fd_set ws;
00959   fd_set es;
00960   int max;
00961   struct timeval timeout;
00962   unsigned long long ltimeout;
00963   int ds;
00964   time_t now;
00965 
00966   timeout.tv_sec = 0;
00967   timeout.tv_usec = 0;
00968   if (daemon->shutdown == MHD_YES)
00969     return MHD_NO;
00970   FD_ZERO (&rs);
00971   FD_ZERO (&ws);
00972   FD_ZERO (&es);
00973   max = 0;
00974 
00975   if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00976     {
00977       /* single-threaded, go over everything */
00978       if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
00979         return MHD_NO;
00980 
00981       /* If we're at the connection limit, no need to
00982          accept new connections. */
00983       if ( (daemon->max_connections == 0) && (daemon->socket_fd != -1) )
00984         FD_CLR(daemon->socket_fd, &rs);
00985     }
00986   else
00987     {
00988       /* accept only, have one thread per connection */
00989       max = daemon->socket_fd;
00990       if (max == -1)
00991         return MHD_NO;
00992       FD_SET (max, &rs);
00993     }
00994 
00995   /* in case we are missing the SIGALRM, keep going after
00996      at most 1s; see http://lists.gnu.org/archive/html/libmicrohttpd/2009-10/msg00013.html */
00997   timeout.tv_usec = 0;
00998   timeout.tv_sec = 1;
00999   if (may_block == MHD_NO)
01000     {
01001       timeout.tv_usec = 0;
01002       timeout.tv_sec = 0;
01003     }
01004   else
01005     {
01006       /* ltimeout is in ms */
01007       if ( (MHD_YES == MHD_get_timeout (daemon, &ltimeout)) &&
01008            (ltimeout < 1000) )
01009         {
01010           timeout.tv_usec = ltimeout * 1000;
01011           timeout.tv_sec = 0;
01012         }
01013     }
01014   num_ready = SELECT (max + 1, &rs, &ws, &es, &timeout);
01015 
01016   if (daemon->shutdown == MHD_YES)
01017     return MHD_NO;
01018   if (num_ready < 0)
01019     {
01020       if (errno == EINTR)
01021         return MHD_YES;
01022 #if HAVE_MESSAGES
01023       MHD_DLOG (daemon, "select failed: %s\n", STRERROR (errno));
01024 #endif
01025       return MHD_NO;
01026     }
01027   ds = daemon->socket_fd;
01028   if (ds == -1)
01029     return MHD_YES;
01030 
01031   /* select connection thread handling type */
01032   if (FD_ISSET (ds, &rs))
01033     MHD_accept_connection (daemon);
01034   if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01035     {
01036       /* do not have a thread per connection, process all connections now */
01037       now = time (NULL);
01038       pos = daemon->connections;
01039       while (pos != NULL)
01040         {
01041           ds = pos->socket_fd;
01042           if (ds != -1)
01043             {
01044               /* TODO call con->read handler */
01045               if (FD_ISSET (ds, &rs))
01046                 pos->read_handler (pos);
01047               if ((pos->socket_fd != -1) && (FD_ISSET (ds, &ws)))
01048                 pos->write_handler (pos);
01049               if (pos->socket_fd != -1)
01050                 pos->idle_handler (pos);
01051             }
01052           pos = pos->next;
01053         }
01054     }
01055   return MHD_YES;
01056 }
01057 
01061 static int
01062 MHD_poll (struct MHD_Daemon *daemon)
01063 {
01064 #ifdef HAVE_POLL_H
01065   struct pollfd p;
01066 
01067   if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 
01068     return MHD_NO;
01069   p.fd = daemon->socket_fd;
01070   p.events = POLLIN;
01071   p.revents = 0;
01072 
01073   if (poll(&p, 1, 1000) < 0) {
01074     if (errno == EINTR)
01075       return MHD_YES;
01076 #if HAVE_MESSAGES
01077     MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
01078 #endif
01079     return MHD_NO;
01080   }
01081   /* handle shutdown cases */
01082   if (daemon->shutdown == MHD_YES) 
01083     return MHD_NO;  
01084   if (daemon->socket_fd < 0) 
01085     return MHD_YES; 
01086   if (0 != (p.revents & POLLIN)) 
01087     MHD_accept_connection (daemon);
01088   return MHD_YES;
01089 #else
01090   return MHD_NO;
01091 #endif
01092 }
01093 
01104 int
01105 MHD_run (struct MHD_Daemon *daemon)
01106 {
01107   if ((daemon->shutdown != MHD_NO) || (0 != (daemon->options
01108                                              & MHD_USE_THREAD_PER_CONNECTION))
01109       || (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
01110     return MHD_NO;
01111   MHD_select (daemon, MHD_NO);
01112   MHD_cleanup_connections (daemon);
01113   return MHD_YES;
01114 }
01115 
01120 static void *
01121 MHD_select_thread (void *cls)
01122 {
01123   struct MHD_Daemon *daemon = cls;
01124   while (daemon->shutdown == MHD_NO)
01125     {
01126       if ((daemon->options & MHD_USE_POLL) == 0) 
01127         MHD_select (daemon, MHD_YES);
01128       else 
01129         MHD_poll(daemon);      
01130       MHD_cleanup_connections (daemon);
01131     }
01132   return NULL;
01133 }
01134 
01146 struct MHD_Daemon *
01147 MHD_start_daemon (unsigned int options,
01148                   unsigned short port,
01149                   MHD_AcceptPolicyCallback apc,
01150                   void *apc_cls,
01151                   MHD_AccessHandlerCallback dh, void *dh_cls, ...)
01152 {
01153   struct MHD_Daemon *ret;
01154   va_list ap;
01155 
01156   va_start (ap, dh_cls);
01157   ret = MHD_start_daemon_va (options, port, apc, apc_cls, dh, dh_cls, ap);
01158   va_end (ap);
01159   return ret;
01160 }
01161 
01162 
01163 typedef void (*VfprintfFunctionPointerType)(void *, const char *, va_list);
01164 
01165 
01173 static int
01174 parse_options_va (struct MHD_Daemon *daemon,
01175                   const struct sockaddr **servaddr,
01176                   va_list ap);
01177 
01178 
01186 static int
01187 parse_options (struct MHD_Daemon *daemon,
01188                const struct sockaddr **servaddr,
01189                ...)
01190 {
01191   va_list ap;
01192   int ret;
01193 
01194   va_start (ap, servaddr);
01195   ret = parse_options_va (daemon, servaddr, ap);
01196   va_end (ap);
01197   return ret;
01198 }
01199 
01200 
01208 static int
01209 parse_options_va (struct MHD_Daemon *daemon,
01210                   const struct sockaddr **servaddr,
01211                   va_list ap)
01212 {
01213   enum MHD_OPTION opt;
01214   struct MHD_OptionItem *oa;
01215   unsigned int i;
01216   
01217   while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
01218     {
01219       switch (opt)
01220         {
01221         case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
01222           daemon->pool_size = va_arg (ap, size_t);
01223           break;
01224         case MHD_OPTION_CONNECTION_LIMIT:
01225           daemon->max_connections = va_arg (ap, unsigned int);
01226           break;
01227         case MHD_OPTION_CONNECTION_TIMEOUT:
01228           daemon->connection_timeout = va_arg (ap, unsigned int);
01229           break;
01230         case MHD_OPTION_NOTIFY_COMPLETED:
01231           daemon->notify_completed =
01232             va_arg (ap, MHD_RequestCompletedCallback);
01233           daemon->notify_completed_cls = va_arg (ap, void *);
01234           break;
01235         case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
01236           daemon->per_ip_connection_limit = va_arg (ap, unsigned int);
01237           break;
01238         case MHD_OPTION_SOCK_ADDR:
01239           *servaddr = va_arg (ap, const struct sockaddr *);
01240           break;
01241         case MHD_OPTION_URI_LOG_CALLBACK:
01242           daemon->uri_log_callback =
01243             va_arg (ap, LogCallback);
01244           daemon->uri_log_callback_cls = va_arg (ap, void *);
01245           break;
01246         case MHD_OPTION_THREAD_POOL_SIZE:
01247           daemon->worker_pool_size = va_arg (ap, unsigned int);
01248           break;
01249 #if HTTPS_SUPPORT
01250         case MHD_OPTION_PROTOCOL_VERSION:
01251           if (daemon->options & MHD_USE_SSL)
01252             _set_priority (&daemon->priority_cache->protocol,
01253                            va_arg (ap, const int *));
01254 #if HAVE_MESSAGES
01255           else
01256             FPRINTF (stderr,
01257                      "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01258                      opt);        
01259 #endif
01260           break;
01261         case MHD_OPTION_HTTPS_MEM_KEY:
01262           if (daemon->options & MHD_USE_SSL)
01263             daemon->https_mem_key = va_arg (ap, const char *);
01264 #if HAVE_MESSAGES
01265           else
01266             FPRINTF (stderr,
01267                      "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01268                      opt);        
01269 #endif
01270           break;
01271         case MHD_OPTION_HTTPS_MEM_CERT:
01272           if (daemon->options & MHD_USE_SSL)
01273             daemon->https_mem_cert = va_arg (ap, const char *);
01274 #if HAVE_MESSAGES
01275           else
01276             FPRINTF (stderr,
01277                      "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01278                      opt);        
01279 #endif
01280           break;
01281         case MHD_OPTION_CIPHER_ALGORITHM:
01282           if (daemon->options & MHD_USE_SSL)
01283             _set_priority (&daemon->priority_cache->cipher,
01284                            va_arg (ap, const int *));
01285 #if HAVE_MESSAGES
01286           else
01287             FPRINTF (stderr,
01288                      "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01289                      opt);        
01290 #endif    
01291           break;
01292 #endif
01293         case MHD_OPTION_EXTERNAL_LOGGER:
01294 #if HAVE_MESSAGES
01295           daemon->custom_error_log =
01296             va_arg (ap, VfprintfFunctionPointerType);
01297           daemon->custom_error_log_cls = va_arg (ap, void *);
01298 #else
01299           va_arg (ap, VfprintfFunctionPointerType);
01300           va_arg (ap, void *);
01301 #endif
01302           break;
01303         case MHD_OPTION_ARRAY:
01304           oa = va_arg (ap, struct MHD_OptionItem*);
01305           i = 0;
01306           while (MHD_OPTION_END != (opt = oa[i].option))
01307             {
01308               switch (opt)
01309                 {
01310                   /* all options taking 'size_t' */
01311                 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
01312                   if (MHD_YES != parse_options (daemon,
01313                                                 servaddr,
01314                                                 opt,
01315                                                 (size_t) oa[i].value,
01316                                                 MHD_OPTION_END))
01317                     return MHD_NO;
01318                   break;
01319                   /* all options taking 'unsigned int' */
01320                 case MHD_OPTION_CONNECTION_LIMIT:
01321                 case MHD_OPTION_CONNECTION_TIMEOUT:
01322                 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
01323                 case MHD_OPTION_THREAD_POOL_SIZE:
01324                   if (MHD_YES != parse_options (daemon,
01325                                                 servaddr,
01326                                                 opt,
01327                                                 (unsigned int) oa[i].value,
01328                                                 MHD_OPTION_END))
01329                     return MHD_NO;
01330                   break;
01331                   /* all options taking 'int' or 'enum' */
01332                 case MHD_OPTION_CRED_TYPE:
01333                   if (MHD_YES != parse_options (daemon,
01334                                                 servaddr,
01335                                                 opt,
01336                                                 (int) oa[i].value,
01337                                                 MHD_OPTION_END))
01338                     return MHD_NO;
01339                   break;
01340                   /* all options taking one pointer */
01341                 case MHD_OPTION_SOCK_ADDR:
01342                 case MHD_OPTION_HTTPS_MEM_KEY:
01343                 case MHD_OPTION_HTTPS_MEM_CERT:
01344                 case MHD_OPTION_PROTOCOL_VERSION:
01345                 case MHD_OPTION_CIPHER_ALGORITHM:
01346                 case MHD_OPTION_ARRAY:
01347                   if (MHD_YES != parse_options (daemon,
01348                                                 servaddr,
01349                                                 opt,
01350                                                 oa[i].ptr_value,
01351                                                 MHD_OPTION_END))
01352                     return MHD_NO;
01353                   break;
01354                   /* all options taking two pointers */
01355                 case MHD_OPTION_NOTIFY_COMPLETED:
01356                 case MHD_OPTION_URI_LOG_CALLBACK:
01357                 case MHD_OPTION_EXTERNAL_LOGGER:
01358                   if (MHD_YES != parse_options (daemon,
01359                                                 servaddr,
01360                                                 opt,
01361                                                 (void *) oa[i].value,
01362                                                 oa[i].ptr_value,
01363                                                 MHD_OPTION_END))
01364                     return MHD_NO;
01365                   break;
01366                   
01367                 default:
01368                   return MHD_NO;
01369                 }
01370               i++;
01371             }
01372           break;
01373         default:
01374 #if HAVE_MESSAGES
01375           if ((opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
01376               (opt <= MHD_OPTION_CIPHER_ALGORITHM))
01377             {
01378               FPRINTF (stderr,
01379                        "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
01380                        opt);
01381             }
01382           else
01383             {
01384               FPRINTF (stderr,
01385                        "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
01386                        opt);
01387             }
01388 #endif
01389           return MHD_NO;
01390         }
01391     }  
01392   return MHD_YES;
01393 }
01394 
01395 
01407 struct MHD_Daemon *
01408 MHD_start_daemon_va (unsigned int options,
01409                      unsigned short port,
01410                      MHD_AcceptPolicyCallback apc,
01411                      void *apc_cls,
01412                      MHD_AccessHandlerCallback dh, void *dh_cls, va_list ap)
01413 {
01414   const int on = 1;
01415   struct MHD_Daemon *retVal;
01416   int socket_fd;
01417   struct sockaddr_in servaddr4;
01418 #if HAVE_INET6
01419   struct sockaddr_in6 servaddr6;
01420 #endif
01421   const struct sockaddr *servaddr = NULL;
01422   socklen_t addrlen;
01423   unsigned int i;
01424   int res_thread_create;
01425 
01426   if ((port == 0) || (dh == NULL))
01427     return NULL;
01428   retVal = malloc (sizeof (struct MHD_Daemon));
01429   if (retVal == NULL)
01430     return NULL;
01431   memset (retVal, 0, sizeof (struct MHD_Daemon));
01432   retVal->options = (enum MHD_OPTION)options;
01433   retVal->port = port;
01434   retVal->apc = apc;
01435   retVal->apc_cls = apc_cls;
01436   retVal->default_handler = dh;
01437   retVal->default_handler_cls = dh_cls;
01438   retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
01439   retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
01440   retVal->connection_timeout = 0;       /* no timeout */
01441 #if HAVE_MESSAGES
01442   retVal->custom_error_log =
01443     (void (*)(void *, const char *, va_list)) &vfprintf;
01444   retVal->custom_error_log_cls = stderr;
01445 #endif
01446 #if HTTPS_SUPPORT
01447   if (options & MHD_USE_SSL)
01448     {
01449       /* lock MHD_gnutls_global mutex since it uses reference counting */
01450       if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
01451         {
01452 #if HAVE_MESSAGES
01453           MHD_DLOG (retVal, "Failed to aquire gnutls mutex\n");
01454 #endif
01455           mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01456         }
01457       if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
01458         {
01459 #if HAVE_MESSAGES
01460           MHD_DLOG (retVal, "Failed to release gnutls mutex\n");
01461 #endif
01462           mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01463         }
01464       /* set default priorities */
01465       MHD_tls_set_default_priority (&retVal->priority_cache, "", NULL);
01466       retVal->cred_type = MHD_GNUTLS_CRD_CERTIFICATE;
01467     }
01468 #endif
01469 
01470   if (MHD_YES != parse_options_va (retVal, &servaddr, ap))
01471     {
01472       free (retVal);
01473       return NULL;
01474     }
01475 
01476   /* poll support currently only works with MHD_USE_THREAD_PER_CONNECTION */
01477   if ( (0 != (options & MHD_USE_POLL)) && 
01478        (0 == (options & MHD_USE_THREAD_PER_CONNECTION)) ) {
01479 #if HAVE_MESSAGES
01480       fprintf (stderr,
01481                "MHD poll support only works with MHD_USE_THREAD_PER_CONNECTION\n");
01482 #endif
01483       free (retVal);
01484       return NULL;
01485   }
01486 
01487   /* Thread pooling currently works only with internal select thread model */
01488   if ((0 == (options & MHD_USE_SELECT_INTERNALLY))
01489       && (retVal->worker_pool_size > 0))
01490     {
01491 #if HAVE_MESSAGES
01492       fprintf (stderr,
01493                "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n");
01494 #endif
01495       free (retVal);
01496       return NULL;
01497     }
01498 
01499 #ifdef __SYMBIAN32__
01500   if (0 != (options & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
01501     {
01502 #if HAVE_MESSAGES
01503       fprintf (stderr,
01504                "Threaded operations are not supported on Symbian.\n");
01505 #endif
01506       free (retVal);
01507       return NULL;
01508     }
01509 #endif
01510   if ((options & MHD_USE_IPv6) != 0)
01511 #if HAVE_INET6
01512     socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0);
01513 #else
01514     {
01515 #if HAVE_MESSAGES
01516       fprintf (stderr, "AF_INET6 not supported\n");
01517 #endif
01518       free (retVal);
01519       return NULL;
01520     }
01521 #endif
01522   else
01523     socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0);
01524   if (socket_fd == -1)
01525     {
01526 #if HAVE_MESSAGES
01527       if ((options & MHD_USE_DEBUG) != 0)
01528         FPRINTF (stderr, "Call to socket failed: %s\n", STRERROR (errno));
01529 #endif
01530       free (retVal);
01531       return NULL;
01532     }
01533 #ifndef WINDOWS
01534   if ( (socket_fd >= FD_SETSIZE) &&
01535        (0 == (options & MHD_USE_POLL)) )
01536     {
01537 #if HAVE_MESSAGES
01538       if ((options & MHD_USE_DEBUG) != 0)
01539         FPRINTF (stderr,
01540                  "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
01541                  socket_fd,
01542                  FD_SETSIZE);
01543 #endif
01544       CLOSE (socket_fd);
01545       free (retVal);
01546       return NULL;
01547     }
01548 #endif
01549   if ((SETSOCKOPT (socket_fd,
01550                    SOL_SOCKET,
01551                    SO_REUSEADDR,
01552                    &on, sizeof (on)) < 0) && (options & MHD_USE_DEBUG) != 0)
01553     {
01554 #if HAVE_MESSAGES
01555       FPRINTF (stderr, "setsockopt failed: %s\n", STRERROR (errno));
01556 #endif
01557     }
01558 
01559   /* check for user supplied sockaddr */
01560 #if HAVE_INET6
01561   if ((options & MHD_USE_IPv6) != 0)
01562     addrlen = sizeof (struct sockaddr_in6);
01563   else
01564 #endif
01565     addrlen = sizeof (struct sockaddr_in);
01566   if (NULL == servaddr)
01567     {
01568 #if HAVE_INET6
01569       if ((options & MHD_USE_IPv6) != 0)
01570         {
01571           memset (&servaddr6, 0, sizeof (struct sockaddr_in6));
01572           servaddr6.sin6_family = AF_INET6;
01573           servaddr6.sin6_port = htons (port);
01574           servaddr = (struct sockaddr *) &servaddr6;
01575         }
01576       else
01577 #endif
01578         {
01579           memset (&servaddr4, 0, sizeof (struct sockaddr_in));
01580           servaddr4.sin_family = AF_INET;
01581           servaddr4.sin_port = htons (port);
01582           servaddr = (struct sockaddr *) &servaddr4;
01583         }
01584     }
01585   retVal->socket_fd = socket_fd;
01586   if (BIND (socket_fd, servaddr, addrlen) == -1)
01587     {
01588 #if HAVE_MESSAGES
01589       if ((options & MHD_USE_DEBUG) != 0)
01590         FPRINTF (stderr,
01591                  "Failed to bind to port %u: %s\n", port, STRERROR (errno));
01592 #endif
01593       CLOSE (socket_fd);
01594       free (retVal);
01595       return NULL;
01596     }
01597 
01598   if (LISTEN (socket_fd, 20) < 0)
01599     {
01600 #if HAVE_MESSAGES
01601       if ((options & MHD_USE_DEBUG) != 0)
01602         FPRINTF (stderr,
01603                  "Failed to listen for connections: %s\n", STRERROR (errno));
01604 #endif
01605       CLOSE (socket_fd);
01606       free (retVal);
01607       return NULL;
01608     }
01609 
01610   if (0 != pthread_mutex_init (&retVal->per_ip_connection_mutex, NULL))
01611     {
01612 #if HAVE_MESSAGES
01613       MHD_DLOG (retVal,
01614                "MHD failed to initialize IP connection limit mutex\n");
01615 #endif
01616       CLOSE (socket_fd);
01617       free (retVal);
01618       return NULL;
01619     }
01620 
01621 #if HTTPS_SUPPORT
01622   /* initialize HTTPS daemon certificate aspects & send / recv functions */
01623   if ((0 != (options & MHD_USE_SSL)) && (0 != MHD_TLS_init (retVal)))
01624     {
01625 #if HAVE_MESSAGES
01626       MHD_DLOG (retVal, "Failed to initialize TLS support\n");
01627 #endif
01628       CLOSE (socket_fd);
01629       pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
01630       free (retVal);
01631       return NULL;
01632     }
01633 #endif
01634   if ( ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
01635          ( (0 != (options & MHD_USE_SELECT_INTERNALLY)) &&
01636            (0 == retVal->worker_pool_size)) ) && 
01637        (0 != (res_thread_create =
01638               pthread_create (&retVal->pid, NULL, &MHD_select_thread, retVal))))
01639     {
01640 #if HAVE_MESSAGES
01641       MHD_DLOG (retVal,
01642                 "Failed to create listen thread: %s\n", STRERROR (res_thread_create));
01643 #endif
01644       pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
01645       free (retVal);
01646       CLOSE (socket_fd);
01647       return NULL;
01648     }
01649   else if (retVal->worker_pool_size > 0)
01650     {
01651 #ifndef MINGW
01652       int sk_flags;
01653 #else
01654       unsigned long sk_flags;
01655 #endif
01656 
01657       /* Coarse-grained count of connections per thread (note error
01658        * due to integer division). Also keep track of how many
01659        * connections are leftover after an equal split. */
01660       unsigned int conns_per_thread = retVal->max_connections
01661                                       / retVal->worker_pool_size;
01662       unsigned int leftover_conns = retVal->max_connections
01663                                     % retVal->worker_pool_size;
01664 
01665       i = 0; /* we need this in case fcntl or malloc fails */
01666 
01667       /* Accept must be non-blocking. Multiple children may wake up
01668        * to handle a new connection, but only one will win the race.
01669        * The others must immediately return. */
01670 #ifndef MINGW
01671       sk_flags = fcntl (socket_fd, F_GETFL);
01672       if (sk_flags < 0)
01673         goto thread_failed;
01674       if (fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK) < 0)
01675         goto thread_failed;
01676 #else
01677       sk_flags = 1;
01678 #if HAVE_PLIBC_FD
01679       if (ioctlsocket (plibc_fd_get_handle (socket_fd), FIONBIO, &sk_flags) ==
01680           SOCKET_ERROR)
01681 #else
01682       if (ioctlsocket (socket_fd, FIONBIO, &sk_flags) == SOCKET_ERROR)
01683 #endif // PLIBC_FD
01684         goto thread_failed;
01685 #endif // MINGW
01686 
01687       /* Allocate memory for pooled objects */
01688       retVal->worker_pool = malloc (sizeof (struct MHD_Daemon)
01689                                     * retVal->worker_pool_size);
01690       if (NULL == retVal->worker_pool)
01691         goto thread_failed;
01692 
01693       /* Start the workers in the pool */
01694       for (i = 0; i < retVal->worker_pool_size; ++i)
01695         {
01696           /* Create copy of the Daemon object for each worker */
01697           struct MHD_Daemon *d = &retVal->worker_pool[i];
01698           memcpy (d, retVal, sizeof (struct MHD_Daemon));
01699 
01700           /* Adjust pooling params for worker daemons; note that memcpy()
01701              has already copied MHD_USE_SELECT_INTERNALLY thread model into
01702              the worker threads. */
01703           d->master = retVal;
01704           d->worker_pool_size = 0;
01705           d->worker_pool = NULL;
01706 
01707           /* Divide available connections evenly amongst the threads.
01708            * Thread indexes in [0, leftover_conns) each get one of the
01709            * leftover connections. */
01710           d->max_connections = conns_per_thread;
01711           if (i < leftover_conns)
01712             ++d->max_connections;
01713 
01714           /* Spawn the worker thread */
01715           if (0 != (res_thread_create = pthread_create (&d->pid, NULL, &MHD_select_thread, d)))
01716             {
01717 #if HAVE_MESSAGES
01718               MHD_DLOG (retVal,
01719                         "Failed to create pool thread: %s\n", 
01720                         STRERROR (res_thread_create));
01721 #endif
01722               /* Free memory for this worker; cleanup below handles
01723                * all previously-created workers. */
01724               goto thread_failed;
01725             }
01726         }
01727     }
01728   return retVal;
01729 
01730 thread_failed:
01731   /* If no worker threads created, then shut down normally. Calling
01732      MHD_stop_daemon (as we do below) doesn't work here since it
01733      assumes a 0-sized thread pool means we had been in the default
01734      MHD_USE_SELECT_INTERNALLY mode. */
01735   if (i == 0)
01736     {
01737       CLOSE (socket_fd);
01738       pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
01739       if (NULL != retVal->worker_pool)
01740         free (retVal->worker_pool);
01741       free (retVal);
01742       return NULL;
01743     }
01744 
01745   /* Shutdown worker threads we've already created. Pretend
01746      as though we had fully initialized our daemon, but
01747      with a smaller number of threads than had been
01748      requested. */
01749   retVal->worker_pool_size = i - 1;
01750   MHD_stop_daemon (retVal);
01751   return NULL;
01752 }
01753 
01757 static void
01758 MHD_close_connections (struct MHD_Daemon *daemon)
01759 {
01760   while (daemon->connections != NULL)
01761     {
01762       if (-1 != daemon->connections->socket_fd)
01763         {
01764 #if DEBUG_CLOSE
01765 #if HAVE_MESSAGES
01766           MHD_DLOG (daemon, "MHD shutdown, closing active connections\n");
01767 #endif
01768 #endif
01769           MHD_connection_close (daemon->connections,
01770                                 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
01771         }
01772       MHD_cleanup_connections (daemon);
01773     }
01774 }
01775 
01779 void
01780 MHD_stop_daemon (struct MHD_Daemon *daemon)
01781 {
01782   void *unused;
01783   int fd;
01784   unsigned int i;
01785   int rc;
01786 
01787   if (daemon == NULL)
01788     return;
01789   daemon->shutdown = MHD_YES;
01790   fd = daemon->socket_fd;
01791   daemon->socket_fd = -1;
01792 
01793   /* Prepare workers for shutdown */
01794   for (i = 0; i < daemon->worker_pool_size; ++i)
01795     {
01796       daemon->worker_pool[i].shutdown = MHD_YES;
01797       daemon->worker_pool[i].socket_fd = -1;
01798     }
01799 
01800 #if OSX
01801   /* without this, either (thread pool = 0) threads would get stuck or
01802    * CLOSE would get stuck if attempted before (thread pool > 0)
01803    * threads have ended */
01804   SHUTDOWN (fd, SHUT_RDWR);
01805 #else
01806 #if DEBUG_CLOSE
01807 #if HAVE_MESSAGES
01808   MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
01809 #endif
01810 #endif
01811   CLOSE (fd);
01812 #endif
01813 
01814   /* Signal workers to stop and clean them up */
01815   for (i = 0; i < daemon->worker_pool_size; ++i)
01816     pthread_kill (daemon->worker_pool[i].pid, SIGALRM);
01817   for (i = 0; i < daemon->worker_pool_size; ++i)
01818     {
01819       if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused)))
01820         {
01821 #if HAVE_MESSAGES
01822           MHD_DLOG (daemon, "Failed to join a thread: %s\n",
01823                     STRERROR (rc));
01824 #endif
01825           abort();
01826         }
01827       MHD_close_connections (&daemon->worker_pool[i]);
01828     }
01829   free (daemon->worker_pool);
01830 
01831   if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
01832       ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))
01833         && (0 == daemon->worker_pool_size)))
01834     {
01835       pthread_kill (daemon->pid, SIGALRM);
01836       if (0 != (rc = pthread_join (daemon->pid, &unused)))
01837         {
01838 #if HAVE_MESSAGES
01839           MHD_DLOG (daemon, "Failed to join a thread: %s\n",
01840                     STRERROR (rc));
01841 #endif
01842           abort();
01843         }
01844     }
01845   MHD_close_connections (daemon);
01846 
01847 #if OSX
01848 #if DEBUG_CLOSE
01849 #if HAVE_MESSAGES
01850   MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
01851 #endif
01852 #endif
01853   CLOSE (fd);
01854 #endif
01855 
01856   /* TLS clean up */
01857 #if HTTPS_SUPPORT
01858   if (daemon->options & MHD_USE_SSL)
01859     {
01860       MHD__gnutls_priority_deinit (daemon->priority_cache);
01861       if (daemon->x509_cred)
01862         MHD__gnutls_certificate_free_credentials (daemon->x509_cred);
01863       /* lock MHD_gnutls_global mutex since it uses reference counting */
01864       if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
01865         {
01866 #if HAVE_MESSAGES
01867           MHD_DLOG (daemon, "Failed to aquire gnutls mutex\n");
01868 #endif
01869           abort();
01870         }
01871       if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
01872         {
01873 #if HAVE_MESSAGES
01874           MHD_DLOG (daemon, "Failed to release gnutls mutex\n");
01875 #endif
01876           abort();
01877         }
01878     }
01879 #endif
01880   pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
01881   free (daemon);
01882 }
01883 
01894 const union MHD_DaemonInfo *
01895 MHD_get_daemon_info (struct MHD_Daemon *daemon,
01896                      enum MHD_DaemonInfoType infoType, ...)
01897 {
01898   switch (infoType)
01899     {
01900     case MHD_DAEMON_INFO_LISTEN_FD:
01901       return (const union MHD_DaemonInfo *) &daemon->socket_fd;
01902    default:
01903       return NULL;
01904     };
01905 }
01906 
01922 void MHD_set_panic_func (MHD_PanicCallback cb, void *cls)
01923 {
01924   mhd_panic = cb;
01925   mhd_panic_cls = cls;
01926 }
01927 
01933 const char *
01934 MHD_get_version (void)
01935 {
01936   return PACKAGE_VERSION;
01937 }
01938 
01939 #ifndef WINDOWS
01940 
01941 static struct sigaction sig;
01942 
01943 static struct sigaction old;
01944 
01945 static void
01946 sigalrmHandler (int sig)
01947 {
01948 }
01949 #endif
01950 
01951 #ifdef __GNUC__
01952 #define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor))
01953 #define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor))
01954 #else  // !__GNUC__
01955 #define ATTRIBUTE_CONSTRUCTOR
01956 #define ATTRIBUTE_DESTRUCTOR
01957 #endif  // __GNUC__
01958 
01963 void ATTRIBUTE_CONSTRUCTOR MHD_init ()
01964 {
01965   mhd_panic = &mhd_panic_std;
01966   mhd_panic_cls = NULL;
01967 
01968 #ifndef WINDOWS
01969   /* make sure SIGALRM does not kill us */
01970   memset (&sig, 0, sizeof (struct sigaction));
01971   memset (&old, 0, sizeof (struct sigaction));
01972   sig.sa_flags = SA_NODEFER;
01973   sig.sa_handler = &sigalrmHandler;
01974   sigaction (SIGALRM, &sig, &old);
01975 #else
01976   plibc_init ("GNU", "libmicrohttpd");
01977 #endif
01978 #if HTTPS_SUPPORT
01979   MHD__gnutls_global_init ();
01980   if (0 != pthread_mutex_init(&MHD_gnutls_init_mutex, NULL))
01981     abort();
01982 #endif
01983 }
01984 
01985 void ATTRIBUTE_DESTRUCTOR MHD_fini ()
01986 {
01987 #if HTTPS_SUPPORT
01988   MHD__gnutls_global_deinit ();
01989   if (0 != pthread_mutex_destroy(&MHD_gnutls_init_mutex))
01990     mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01991 #endif
01992 #ifndef WINDOWS
01993   sigaction (SIGALRM, &old, &sig);
01994 #else
01995   plibc_shutdown ();
01996 #endif
01997 }
01998 
01999 /* end of daemon.c */
Generated by  doxygen 1.6.2-20100208