daemon.c

Go to the documentation of this file.
00001 /*
00002   This file is part of libmicrohttpd
00003   (C) 2007, 2008, 2009, 2010 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/gnutls.h>
00036 #include <gcrypt.h>
00037 #endif
00038 
00039 #ifdef HAVE_POLL_H
00040 #include <poll.h>
00041 #endif
00042 
00043 #ifdef LINUX
00044 #include <sys/sendfile.h>
00045 #endif
00046 
00050 #ifndef WINDOWS
00051 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE -4
00052 #else
00053 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE
00054 #endif
00055 
00059 #define MHD_POOL_SIZE_DEFAULT (32 * 1024)
00060 
00065 #define DEBUG_CLOSE MHD_NO
00066 
00071 #define DEBUG_CONNECT MHD_NO
00072 
00073 #ifndef LINUX
00074 #ifndef MSG_NOSIGNAL
00075 #define MSG_NOSIGNAL 0
00076 #endif
00077 #ifndef MSG_DONTWAIT
00078 #define MSG_DONTWAIT 0
00079 #endif
00080 #endif
00081 
00082 #ifdef __SYMBIAN32__
00083 static void pthread_kill (int, int) {
00084   // Symbian doesn't have signals. The user of the library is required to
00085   // run it in an external select loop.
00086   abort();
00087 }
00088 #endif  // __SYMBIAN32__
00089 
00093 static void 
00094 mhd_panic_std(void *cls,
00095               const char *file,
00096               unsigned int line,
00097               const char *reason)
00098 {
00099   abort ();
00100 }
00101 
00102 
00106 MHD_PanicCallback mhd_panic;
00107 
00111 void *mhd_panic_cls;
00112 
00113 
00121 static struct MHD_Daemon*
00122 MHD_get_master (struct MHD_Daemon *daemon)
00123 {
00124   while (NULL != daemon->master)
00125     daemon = daemon->master;
00126   return daemon;
00127 }
00128 
00132 struct MHD_IPCount
00133 {
00137   int family;
00138 
00142   union
00143   {
00147     struct in_addr ipv4;
00148 #if HAVE_IPV6
00149 
00152     struct in6_addr ipv6;
00153 #endif
00154   } addr;
00155 
00159   unsigned int count;
00160 };
00161 
00167 static void
00168 MHD_ip_count_lock(struct MHD_Daemon *daemon)
00169 {
00170   if (0 != pthread_mutex_lock(&daemon->per_ip_connection_mutex))
00171     {
00172 #if HAVE_MESSAGES
00173       MHD_DLOG (daemon, "Failed to acquire IP connection limit mutex\n");
00174 #endif
00175       abort();
00176     }
00177 }
00178 
00184 static void
00185 MHD_ip_count_unlock(struct MHD_Daemon *daemon)
00186 {
00187   if (0 != pthread_mutex_unlock(&daemon->per_ip_connection_mutex))
00188     {
00189 #if HAVE_MESSAGES
00190       MHD_DLOG (daemon, "Failed to release IP connection limit mutex\n");
00191 #endif
00192       abort();
00193     }
00194 }
00195 
00205 static int
00206 MHD_ip_addr_compare(const void *a1, const void *a2)
00207 {
00208   return memcmp (a1, a2, offsetof(struct MHD_IPCount, count));
00209 }
00210 
00219 static int
00220 MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen,
00221                    struct MHD_IPCount *key)
00222 {
00223   memset(key, 0, sizeof(*key));
00224 
00225   /* IPv4 addresses */
00226   if (addrlen == sizeof(struct sockaddr_in))
00227     {
00228       const struct sockaddr_in *addr4 = (const struct sockaddr_in*)addr;
00229       key->family = AF_INET;
00230       memcpy (&key->addr.ipv4, &addr4->sin_addr, sizeof(addr4->sin_addr));
00231       return MHD_YES;
00232     }
00233 
00234 #if HAVE_IPV6
00235   /* IPv6 addresses */
00236   if (addrlen == sizeof (struct sockaddr_in6))
00237     {
00238       const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)addr;
00239       key->family = AF_INET6;
00240       memcpy (&key->addr.ipv6, &addr6->sin6_addr, sizeof(addr6->sin6_addr));
00241       return MHD_YES;
00242     }
00243 #endif
00244 
00245   /* Some other address */
00246   return MHD_NO;
00247 }
00248 
00258 static int
00259 MHD_ip_limit_add(struct MHD_Daemon *daemon,
00260                  const struct sockaddr *addr,
00261                  socklen_t addrlen)
00262 {
00263   struct MHD_IPCount *key;
00264   void *node;
00265   int result;
00266 
00267   daemon = MHD_get_master (daemon);
00268 
00269   /* Ignore if no connection limit assigned */
00270   if (daemon->per_ip_connection_limit == 0)
00271     return MHD_YES;
00272 
00273   key = malloc (sizeof(*key));
00274   if (NULL == key)
00275     return MHD_NO;
00276 
00277   /* Initialize key */
00278   if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, key))
00279     {
00280       /* Allow unhandled address types through */
00281       free (key);
00282       return MHD_YES;
00283     }
00284 
00285   MHD_ip_count_lock (daemon);
00286 
00287   /* Search for the IP address */
00288   node = (void*)TSEARCH (key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
00289   if (!node)
00290     {
00291 #if HAVE_MESSAGES
00292       MHD_DLOG(daemon,
00293                "Failed to add IP connection count node\n");
00294 #endif      
00295       MHD_ip_count_unlock (daemon);
00296       free (key);
00297       return MHD_NO;
00298     }
00299   node = *(void**)node;
00300 
00301   /* If we got an existing node back, free the one we created */
00302   if (node != key)
00303     free(key);
00304   key = (struct MHD_IPCount*)node;
00305 
00306   /* Test if there is room for another connection; if so,
00307    * increment count */
00308   result = (key->count < daemon->per_ip_connection_limit);
00309   if (result == MHD_YES)
00310     ++key->count;
00311 
00312   MHD_ip_count_unlock (daemon);
00313   return result;
00314 }
00315 
00324 static void
00325 MHD_ip_limit_del(struct MHD_Daemon *daemon,
00326                  const struct sockaddr *addr,
00327                  socklen_t addrlen)
00328 {
00329   struct MHD_IPCount search_key;
00330   struct MHD_IPCount *found_key;
00331   void *node;
00332 
00333   daemon = MHD_get_master (daemon);
00334 
00335   /* Ignore if no connection limit assigned */
00336   if (daemon->per_ip_connection_limit == 0)
00337     return;
00338 
00339   /* Initialize search key */
00340   if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, &search_key))
00341     return;
00342 
00343   MHD_ip_count_lock (daemon);
00344 
00345   /* Search for the IP address */
00346   node = (void*)TFIND (&search_key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
00347 
00348   /* Something's wrong if we couldn't find an IP address
00349    * that was previously added */
00350   if (!node)
00351     {
00352 #if HAVE_MESSAGES
00353       MHD_DLOG (daemon,
00354                 "Failed to find previously-added IP address\n");
00355 #endif
00356       abort();
00357     }
00358   found_key = (struct MHD_IPCount*)*(void**)node;
00359 
00360   /* Validate existing count for IP address */
00361   if (found_key->count == 0)
00362     {
00363 #if HAVE_MESSAGES
00364       MHD_DLOG (daemon,
00365                 "Previously-added IP address had 0 count\n");
00366 #endif
00367       abort();
00368     }
00369 
00370   /* Remove the node entirely if count reduces to 0 */
00371   if (--found_key->count == 0)
00372     {
00373       TDELETE (found_key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
00374       free (found_key);
00375     }
00376 
00377   MHD_ip_count_unlock (daemon);
00378 }
00379 
00380 #if HTTPS_SUPPORT
00381 static pthread_mutex_t MHD_gnutls_init_mutex;
00382 
00391 static ssize_t
00392 recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i)
00393 {
00394   int res;
00395   res = gnutls_record_recv (connection->tls_session, other, i);
00396   if ( (res == GNUTLS_E_AGAIN) ||
00397        (res == GNUTLS_E_INTERRUPTED) )
00398     {
00399       errno = EINTR;
00400       return -1;
00401     }
00402   if (res < 0)
00403     {
00404       /* Likely 'GNUTLS_E_INVALID_SESSION' (client communication
00405          disrupted); set errno to something caller will interpret
00406          correctly as a hard error*/
00407       errno = EPIPE;
00408       return res;
00409     }
00410   return res;
00411 }
00412 
00413 
00422 static ssize_t
00423 send_tls_adapter (struct MHD_Connection *connection,
00424                   const void *other, size_t i)
00425 {
00426   int res;
00427   res = gnutls_record_send (connection->tls_session, other, i);
00428   if ( (res == GNUTLS_E_AGAIN) ||
00429        (res == GNUTLS_E_INTERRUPTED) )
00430     {
00431       errno = EINTR;
00432       return -1;
00433     }
00434   return res;
00435 }
00436 
00437 
00444 static int
00445 MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
00446 {
00447   gnutls_datum_t key;
00448   gnutls_datum_t cert;
00449 
00450   if (daemon->https_mem_trust) {
00451                 cert.data = (unsigned char *) daemon->https_mem_trust;
00452                 cert.size = strlen(daemon->https_mem_trust);
00453                 if (gnutls_certificate_set_x509_trust_mem(daemon->x509_cred, &cert,
00454                                 GNUTLS_X509_FMT_PEM) < 0) {
00455 #if HAVE_MESSAGES
00456                         MHD_DLOG(daemon,
00457                                         "Bad trust certificate format\n");
00458 #endif
00459                         return -1;
00460                 }
00461         }
00462 
00463   /* certificate & key loaded from memory */
00464   if (daemon->https_mem_cert && daemon->https_mem_key)
00465     {
00466       key.data = (unsigned char *) daemon->https_mem_key;
00467       key.size = strlen (daemon->https_mem_key);
00468       cert.data = (unsigned char *) daemon->https_mem_cert;
00469       cert.size = strlen (daemon->https_mem_cert);
00470 
00471       return gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
00472                                                   &cert, &key,
00473                                                   GNUTLS_X509_FMT_PEM);
00474     }
00475 #if HAVE_MESSAGES
00476   MHD_DLOG (daemon, "You need to specify a certificate and key location\n");
00477 #endif
00478   return -1;
00479 }
00480 
00487 static int
00488 MHD_TLS_init (struct MHD_Daemon *daemon)
00489 {
00490   switch (daemon->cred_type)
00491     {
00492     case GNUTLS_CRD_CERTIFICATE:
00493       if (0 !=
00494           gnutls_certificate_allocate_credentials (&daemon->x509_cred))
00495         return GNUTLS_E_MEMORY_ERROR;
00496       return MHD_init_daemon_certificate (daemon);
00497     default:
00498 #if HAVE_MESSAGES
00499       MHD_DLOG (daemon,
00500                 "Error: invalid credentials type %d specified.\n",
00501                 daemon->cred_type);
00502 #endif
00503       return -1;
00504     }
00505 }
00506 #endif
00507 
00521 int
00522 MHD_get_fdset (struct MHD_Daemon *daemon,
00523                fd_set * read_fd_set,
00524                fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd)
00525 {
00526   struct MHD_Connection *con_itr;
00527   int fd;
00528 
00529   if ((daemon == NULL) || (read_fd_set == NULL) || (write_fd_set == NULL)
00530       || (except_fd_set == NULL) || (max_fd == NULL)
00531       || (-1 == (fd = daemon->socket_fd)) || (daemon->shutdown == MHD_YES)
00532       || ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0)
00533       || ((daemon->options & MHD_USE_POLL) != 0))
00534     return MHD_NO;
00535 
00536   FD_SET (fd, read_fd_set);
00537   /* update max file descriptor */
00538   if ((*max_fd) < fd) 
00539     *max_fd = fd;
00540 
00541   con_itr = daemon->connections;
00542   while (con_itr != NULL)
00543     {
00544       if (MHD_YES != MHD_connection_get_fdset (con_itr,
00545                                                read_fd_set,
00546                                                write_fd_set,
00547                                                except_fd_set, max_fd))
00548         return MHD_NO;
00549       con_itr = con_itr->next;
00550     }
00551 #if DEBUG_CONNECT
00552   MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
00553 #endif
00554   return MHD_YES;
00555 }
00556 
00564 static void *
00565 MHD_handle_connection (void *data)
00566 {
00567   struct MHD_Connection *con = data;
00568   int num_ready;
00569   fd_set rs;
00570   fd_set ws;
00571   fd_set es;
00572   int max;
00573   struct timeval tv;
00574   unsigned int timeout;
00575 #ifdef HAVE_POLL_H
00576   struct MHD_Pollfd mp;
00577   struct pollfd p;
00578 #endif
00579 
00580   timeout = con->daemon->connection_timeout;
00581   while ((!con->daemon->shutdown) && (con->socket_fd != -1)) {
00582       tv.tv_usec = 0;
00583       if ( (timeout > (time (NULL) - con->last_activity)) ||
00584            (timeout == 0) )
00585         {
00586           /* in case we are missing the SIGALRM, keep going after
00587              at most 1s; see http://lists.gnu.org/archive/html/libmicrohttpd/2009-10/msg00013.html */
00588           tv.tv_sec = 1;
00589           if ((con->state == MHD_CONNECTION_NORMAL_BODY_UNREADY) ||
00590               (con->state == MHD_CONNECTION_CHUNKED_BODY_UNREADY))
00591             {
00592               /* do not block (we're waiting for our callback to succeed) */
00593               tv.tv_sec = 0;
00594             }
00595         }
00596       else
00597         {
00598           tv.tv_sec = 0;
00599         }
00600 #ifdef HAVE_POLL_H
00601       if (0 == (con->daemon->options & MHD_USE_POLL)) {
00602 #else
00603       {
00604 #endif
00605         /* use select */
00606         FD_ZERO (&rs);
00607         FD_ZERO (&ws);
00608         FD_ZERO (&es);
00609         max = 0;
00610         MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
00611         num_ready = SELECT (max + 1, &rs, &ws, &es, &tv);
00612         if (num_ready < 0) {
00613             if (errno == EINTR)
00614               continue;
00615 #if HAVE_MESSAGES
00616             MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n", max,
00617                       STRERROR (errno));
00618 #endif
00619             break;
00620         }
00621         /* call appropriate connection handler if necessary */
00622         if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &rs)))
00623           con->read_handler (con);
00624         if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
00625           con->write_handler (con);
00626         if (con->socket_fd != -1)
00627           con->idle_handler (con);
00628       }
00629 #ifdef HAVE_POLL_H
00630       else
00631       {
00632         /* use poll */
00633         memset(&mp, 0, sizeof (struct MHD_Pollfd));
00634         MHD_connection_get_pollfd(con, &mp);
00635         memset(&p, 0, sizeof (struct pollfd));
00636         p.fd = mp.fd;
00637         if (mp.events & MHD_POLL_ACTION_IN) 
00638           p.events |= POLLIN;        
00639         if (mp.events & MHD_POLL_ACTION_OUT) 
00640           p.events |= POLLOUT;
00641         /* in case we are missing the SIGALRM, keep going after
00642            at most 1s */
00643         if (poll (&p, 1, 1000) < 0) {
00644           if (errno == EINTR)
00645             continue;
00646 #if HAVE_MESSAGES
00647           MHD_DLOG (con->daemon, "Error during poll: `%s'\n", 
00648                     STRERROR (errno));
00649 #endif
00650           break;
00651         }
00652         if ( (con->socket_fd != -1) && 
00653              (0 != (p.revents & POLLIN)) ) 
00654           con->read_handler (con);        
00655         if ( (con->socket_fd != -1) && 
00656              (0 != (p.revents & POLLOUT)) )
00657           con->write_handler (con);        
00658         if (con->socket_fd != -1)
00659           con->idle_handler (con);
00660         if ( (con->socket_fd != -1) &&
00661              (0 != (p.revents & (POLLERR | POLLHUP))) )
00662           MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR);      
00663       }
00664 #endif
00665     }
00666   if (con->socket_fd != -1)
00667     {
00668 #if DEBUG_CLOSE
00669 #if HAVE_MESSAGES
00670       MHD_DLOG (con->daemon,
00671                 "Processing thread terminating, closing connection\n");
00672 #endif
00673 #endif
00674       MHD_connection_close (con, MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
00675     }
00676   return NULL;
00677 }
00678 
00687 static ssize_t
00688 recv_param_adapter (struct MHD_Connection *connection, void *other, size_t i)
00689 {
00690   if (connection->socket_fd == -1)
00691     return -1;
00692   if (0 != (connection->daemon->options & MHD_USE_SSL))
00693     return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
00694   return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT);
00695 }
00696 
00705 static ssize_t
00706 send_param_adapter (struct MHD_Connection *connection,
00707                     const void *other, size_t i)
00708 {
00709 #if LINUX
00710   int fd;
00711   off_t offset;
00712   int ret;
00713 #endif
00714   if (connection->socket_fd == -1)
00715     return -1;
00716   if (0 != (connection->daemon->options & MHD_USE_SSL))
00717     return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
00718 #if LINUX
00719   if ( (connection->write_buffer_append_offset ==
00720         connection->write_buffer_send_offset) &&
00721        (NULL != connection->response) &&
00722        (-1 != (fd = connection->response->fd)) )
00723     {
00724       /* can use sendfile */
00725       offset = (off_t) connection->response_write_position + connection->response->fd_off;
00726       ret = sendfile (connection->socket_fd, 
00727                       fd,
00728                       &offset,
00729                       connection->response->total_size - offset);
00730       if ( (ret == -1) &&
00731            (errno == EINTR) )
00732         return 0;
00733       return ret;
00734     }
00735 #endif
00736   return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT);
00737 }
00738 
00739 
00740 #if HTTPS_SUPPORT
00741 
00745 static void
00746 socket_set_nonblocking (int fd)
00747 {
00748 #if MINGW
00749   u_long mode;
00750   mode = 1;
00751   if (ioctlsocket (fd, FIONBIO, &mode) == SOCKET_ERROR)
00752     {
00753       SetErrnoFromWinsockError (WSAGetLastError ());
00754 #if HAVE_MESSAGES
00755       FPRINTF(stderr, "Failed to make socket non-blocking: %s\n", 
00756               STRERROR (errno));
00757 #endif
00758     }
00759 #else
00760 
00761   /* not MINGW */
00762   int flags = fcntl (fd, F_GETFL);
00763   if ( (flags == -1) ||
00764        (0 != fcntl (fd, F_SETFL, flags | O_NONBLOCK)) )
00765     {
00766 #if HAVE_MESSAGES
00767       FPRINTF(stderr, "Failed to make socket non-blocking: %s\n", 
00768               STRERROR (errno));
00769 #endif
00770     }
00771 #endif
00772 }
00773 #endif
00774 
00775 
00785 static int
00786 create_thread (pthread_t * thread,
00787                const struct MHD_Daemon *daemon,
00788                void *(*start_routine)(void*),
00789                void *arg)
00790 {
00791   pthread_attr_t attr;
00792   pthread_attr_t *pattr;
00793   int ret;
00794   
00795   if (daemon->thread_stack_size != 0) 
00796     {
00797       if (0 != (ret = pthread_attr_init (&attr))) 
00798         goto ERR;
00799       if (0 != (ret = pthread_attr_setstacksize (&attr, daemon->thread_stack_size)))
00800         {
00801           pthread_attr_destroy (&attr);
00802           goto ERR;
00803         }
00804       pattr = &attr;
00805     }
00806   else
00807     {
00808       pattr = NULL;
00809     }
00810   ret = pthread_create (thread, pattr,
00811                         start_routine, arg);
00812   if (daemon->thread_stack_size != 0) 
00813     pthread_attr_destroy (&attr);
00814   return ret;
00815  ERR:
00816 #if HAVE_MESSAGES
00817   MHD_DLOG (daemon,
00818             "Failed to set thread stack size\n");
00819 #endif
00820   errno = EINVAL;
00821   return ret;
00822 }
00823 
00824 
00825 
00834 static int
00835 MHD_accept_connection (struct MHD_Daemon *daemon)
00836 {
00837   struct MHD_Connection *connection;
00838 #if HAVE_INET6
00839   struct sockaddr_in6 addrstorage;
00840 #else
00841   struct sockaddr_in addrstorage;
00842 #endif
00843   struct sockaddr *addr = (struct sockaddr *) &addrstorage;
00844   socklen_t addrlen;
00845   int s;
00846   int res_thread_create;
00847 #if OSX
00848   static int on = 1;
00849 #endif
00850 
00851   addrlen = sizeof (addrstorage);
00852   memset (addr, 0, sizeof (addrstorage));
00853 
00854   s = ACCEPT (daemon->socket_fd, addr, &addrlen);
00855   if ((s == -1) || (addrlen <= 0))
00856     {
00857 #if HAVE_MESSAGES
00858       /* This could be a common occurance with multiple worker threads */
00859       if ((EAGAIN != errno) && (EWOULDBLOCK != errno))
00860         MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));
00861 #endif
00862       if (s != -1)
00863         {
00864           SHUTDOWN (s, SHUT_RDWR);
00865           CLOSE (s);
00866           /* just in case */
00867         }
00868       return MHD_NO;
00869     }
00870 #ifndef WINDOWS
00871   if ( (s >= FD_SETSIZE) &&
00872        (0 == (daemon->options & MHD_USE_POLL)) )
00873     {
00874 #if HAVE_MESSAGES
00875       MHD_DLOG (daemon,
00876                 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
00877                 s,
00878                 FD_SETSIZE);
00879 #endif
00880       CLOSE (s);
00881       return MHD_NO;
00882     }
00883 #endif
00884 
00885 
00886 #if HAVE_MESSAGES
00887 #if DEBUG_CONNECT
00888   MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
00889 #endif
00890 #endif
00891   if ((daemon->max_connections == 0)
00892       || (MHD_ip_limit_add (daemon, addr, addrlen) == MHD_NO))
00893     {
00894       /* above connection limit - reject */
00895 #if HAVE_MESSAGES
00896       MHD_DLOG (daemon,
00897                 "Server reached connection limit (closing inbound connection)\n");
00898 #endif
00899       SHUTDOWN (s, SHUT_RDWR);
00900       CLOSE (s);
00901       return MHD_NO;
00902     }
00903 
00904   /* apply connection acceptance policy if present */
00905   if ((daemon->apc != NULL)
00906       && (MHD_NO == daemon->apc (daemon->apc_cls, addr, addrlen)))
00907     {
00908 #if DEBUG_CLOSE
00909 #if HAVE_MESSAGES
00910       MHD_DLOG (daemon, "Connection rejected, closing connection\n");
00911 #endif
00912 #endif
00913       SHUTDOWN (s, SHUT_RDWR);
00914       CLOSE (s);
00915       MHD_ip_limit_del (daemon, addr, addrlen);
00916       return MHD_YES;
00917     }
00918 #if OSX
00919 #ifdef SOL_SOCKET
00920 #ifdef SO_NOSIGPIPE
00921   setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof (on));
00922 #endif
00923 #endif
00924 #endif
00925   connection = malloc (sizeof (struct MHD_Connection));
00926   if (NULL == connection)
00927     {
00928 #if HAVE_MESSAGES
00929       MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00930 #endif
00931       SHUTDOWN (s, SHUT_RDWR);
00932       CLOSE (s);
00933       MHD_ip_limit_del (daemon, addr, addrlen);
00934       return MHD_NO;
00935     }
00936   memset (connection, 0, sizeof (struct MHD_Connection));
00937   connection->pool = NULL;
00938   connection->addr = malloc (addrlen);
00939   if (connection->addr == NULL)
00940     {
00941 #if HAVE_MESSAGES
00942       MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00943 #endif
00944       SHUTDOWN (s, SHUT_RDWR);
00945       CLOSE (s);
00946       MHD_ip_limit_del (daemon, addr, addrlen);
00947       free (connection);
00948       return MHD_NO;
00949     }
00950   memcpy (connection->addr, addr, addrlen);
00951   connection->addr_len = addrlen;
00952   connection->socket_fd = s;
00953   connection->daemon = daemon;
00954   connection->last_activity = time (NULL);
00955 
00956   /* set default connection handlers  */
00957   MHD_set_http_callbacks_ (connection);
00958   connection->recv_cls = &recv_param_adapter;
00959   connection->send_cls = &send_param_adapter;
00960 #if HTTPS_SUPPORT
00961   if (0 != (daemon->options & MHD_USE_SSL))
00962     {
00963       connection->recv_cls = &recv_tls_adapter;
00964       connection->send_cls = &send_tls_adapter;
00965       connection->state = MHD_TLS_CONNECTION_INIT;
00966       MHD_set_https_callbacks (connection);
00967       gnutls_init (&connection->tls_session, GNUTLS_SERVER);
00968       gnutls_priority_set (connection->tls_session,
00969                            daemon->priority_cache);
00970       if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00971         {
00972           /* use non-blocking IO for gnutls */
00973           socket_set_nonblocking (connection->socket_fd);
00974         }
00975       switch (connection->daemon->cred_type)
00976         {
00977           /* set needed credentials for certificate authentication. */
00978         case GNUTLS_CRD_CERTIFICATE:
00979           gnutls_credentials_set (connection->tls_session,
00980                                   GNUTLS_CRD_CERTIFICATE,
00981                                   connection->daemon->x509_cred);
00982           break;
00983         default:
00984 #if HAVE_MESSAGES
00985           MHD_DLOG (connection->daemon,
00986                     "Failed to setup TLS credentials: unknown credential type %d\n",
00987                     connection->daemon->cred_type);
00988 #endif
00989           SHUTDOWN (s, SHUT_RDWR);
00990           CLOSE (s);
00991           MHD_ip_limit_del (daemon, addr, addrlen);
00992           free (connection->addr);
00993           free (connection);
00994           mhd_panic (mhd_panic_cls, __FILE__, __LINE__, 
00995 #if HAVE_MESSAGES
00996                      "Unknown credential type"
00997 #else
00998                      NULL
00999 #endif
01000                      );
01001           return MHD_NO;
01002         }
01003       gnutls_transport_set_ptr (connection->tls_session,
01004                                 (gnutls_transport_ptr_t) connection);
01005       gnutls_transport_set_pull_function (connection->tls_session,
01006                                           (gnutls_pull_func) &
01007                                                recv_param_adapter);
01008       gnutls_transport_set_push_function (connection->tls_session,
01009                                           (gnutls_push_func) &
01010                                                send_param_adapter);
01011 
01012       if (daemon->https_mem_trust){
01013       gnutls_certificate_server_set_request(connection->tls_session, GNUTLS_CERT_REQUEST);
01014       }
01015     }
01016 #endif
01017 
01018   /* attempt to create handler thread */
01019   if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01020     {
01021       res_thread_create = create_thread (&connection->pid, daemon,
01022                                          &MHD_handle_connection, connection);
01023       if (res_thread_create != 0)
01024         {
01025 #if HAVE_MESSAGES
01026           MHD_DLOG (daemon, "Failed to create a thread: %s\n",
01027                     STRERROR (res_thread_create));
01028 #endif
01029           SHUTDOWN (s, SHUT_RDWR);
01030           CLOSE (s);
01031           MHD_ip_limit_del (daemon, addr, addrlen);
01032           free (connection->addr);
01033           free (connection);
01034           return MHD_NO;
01035         }
01036     }
01037   connection->next = daemon->connections;
01038   daemon->connections = connection;
01039   daemon->max_connections--;
01040   return MHD_YES;
01041 }
01042 
01050 static void
01051 MHD_cleanup_connections (struct MHD_Daemon *daemon)
01052 {
01053   struct MHD_Connection *pos;
01054   struct MHD_Connection *prev;
01055   void *unused;
01056   int rc;
01057 
01058   pos = daemon->connections;
01059   prev = NULL;
01060   while (pos != NULL)
01061     {
01062       if ((pos->socket_fd == -1) ||
01063           (((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01064             (daemon->shutdown) && (pos->socket_fd != -1))))
01065         {
01066           if (prev == NULL)
01067             daemon->connections = pos->next;
01068           else
01069             prev->next = pos->next;
01070           if (0 != (pos->daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01071             {
01072               pthread_kill (pos->pid, SIGALRM);
01073               if (0 != (rc = pthread_join (pos->pid, &unused)))
01074                 {
01075 #if HAVE_MESSAGES
01076                   MHD_DLOG (daemon, "Failed to join a thread: %s\n",
01077                             STRERROR (rc));
01078 #endif
01079                   abort();
01080                 }
01081             }
01082           MHD_pool_destroy (pos->pool);
01083 #if HTTPS_SUPPORT
01084           if (pos->tls_session != NULL)
01085             gnutls_deinit (pos->tls_session);
01086 #endif
01087           MHD_ip_limit_del (daemon, (struct sockaddr*)pos->addr, pos->addr_len);
01088           if (pos->response != NULL)
01089             {
01090               MHD_destroy_response (pos->response);
01091               pos->response = NULL;
01092             }
01093           free (pos->addr);
01094           free (pos);
01095           daemon->max_connections++;
01096           if (prev == NULL)
01097             pos = daemon->connections;
01098           else
01099             pos = prev->next;
01100           continue;
01101         }
01102       prev = pos;
01103       pos = pos->next;
01104     }
01105 }
01106 
01119 int
01120 MHD_get_timeout (struct MHD_Daemon *daemon, unsigned MHD_LONG_LONG *timeout)
01121 {
01122   time_t earliest_deadline;
01123   time_t now;
01124   struct MHD_Connection *pos;
01125   unsigned int dto;
01126 
01127   dto = daemon->connection_timeout;
01128   if (0 == dto)
01129     return MHD_NO;
01130   pos = daemon->connections;
01131   if (pos == NULL)
01132     return MHD_NO;              /* no connections */
01133   now = time (NULL);
01134   /* start with conservative estimate */
01135   earliest_deadline = now + dto;
01136   while (pos != NULL)
01137     {
01138       if (earliest_deadline > pos->last_activity + dto)
01139         earliest_deadline = pos->last_activity + dto;
01140 #if HTTPS_SUPPORT
01141       if (  (0 != (daemon->options & MHD_USE_SSL)) &&
01142             (0 != gnutls_record_check_pending (pos->tls_session)) )
01143         earliest_deadline = now;
01144 #endif
01145       pos = pos->next;
01146     }
01147   if (earliest_deadline < now)
01148     *timeout = 0;
01149   else
01150     *timeout = (earliest_deadline - now);
01151   return MHD_YES;
01152 }
01153 
01154 
01162 static int
01163 MHD_select (struct MHD_Daemon *daemon, int may_block)
01164 {
01165   struct MHD_Connection *pos;
01166   int num_ready;
01167   fd_set rs;
01168   fd_set ws;
01169   fd_set es;
01170   int max;
01171   struct timeval timeout;
01172   unsigned MHD_LONG_LONG ltimeout;
01173   int ds;
01174 
01175   timeout.tv_sec = 0;
01176   timeout.tv_usec = 0;
01177   if (daemon->shutdown == MHD_YES)
01178     return MHD_NO;
01179   FD_ZERO (&rs);
01180   FD_ZERO (&ws);
01181   FD_ZERO (&es);
01182   max = 0;
01183 
01184   if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01185     {
01186       /* single-threaded, go over everything */
01187       if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
01188         return MHD_NO;
01189 
01190       /* If we're at the connection limit, no need to
01191          accept new connections. */
01192       if ( (daemon->max_connections == 0) && (daemon->socket_fd != -1) )
01193         FD_CLR(daemon->socket_fd, &rs);
01194     }
01195   else
01196     {
01197       /* accept only, have one thread per connection */
01198       max = daemon->socket_fd;
01199       if (max == -1)
01200         return MHD_NO;
01201       FD_SET (max, &rs);
01202     }
01203 
01204   /* in case we are missing the SIGALRM, keep going after
01205      at most 1s; see http://lists.gnu.org/archive/html/libmicrohttpd/2009-10/msg00013.html */
01206   timeout.tv_usec = 0;
01207   timeout.tv_sec = 1;
01208   if (may_block == MHD_NO)
01209     {
01210       timeout.tv_usec = 0;
01211       timeout.tv_sec = 0;
01212     }
01213   else
01214     {
01215       /* ltimeout is in ms */
01216       if ( (MHD_YES == MHD_get_timeout (daemon, &ltimeout)) &&
01217            (ltimeout < 1000) )
01218         {
01219           timeout.tv_usec = ltimeout * 1000;
01220           timeout.tv_sec = 0;
01221         }
01222     }
01223   num_ready = SELECT (max + 1, &rs, &ws, &es, &timeout);
01224 
01225   if (daemon->shutdown == MHD_YES)
01226     return MHD_NO;
01227   if (num_ready < 0)
01228     {
01229       if (errno == EINTR)
01230         return MHD_YES;
01231 #if HAVE_MESSAGES
01232       MHD_DLOG (daemon, "select failed: %s\n", STRERROR (errno));
01233 #endif
01234       return MHD_NO;
01235     }
01236   ds = daemon->socket_fd;
01237   if (ds == -1)
01238     return MHD_YES;
01239 
01240   /* select connection thread handling type */
01241   if (FD_ISSET (ds, &rs))
01242     MHD_accept_connection (daemon);
01243   if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01244     {
01245       /* do not have a thread per connection, process all connections now */
01246       pos = daemon->connections;
01247       while (pos != NULL)
01248         {
01249           ds = pos->socket_fd;
01250           if (ds != -1)
01251             {
01252               /* TODO call con->read handler */
01253               if (FD_ISSET (ds, &rs))
01254                 pos->read_handler (pos);
01255               if ((pos->socket_fd != -1) && (FD_ISSET (ds, &ws)))
01256                 pos->write_handler (pos);
01257               if (pos->socket_fd != -1)
01258                 pos->idle_handler (pos);
01259             }
01260           pos = pos->next;
01261         }
01262     }
01263   return MHD_YES;
01264 }
01265 
01271 static int
01272 MHD_poll (struct MHD_Daemon *daemon)
01273 {
01274 #ifdef HAVE_POLL_H
01275   struct pollfd p;
01276 
01277   if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 
01278     return MHD_NO;
01279   p.fd = daemon->socket_fd;
01280   p.events = POLLIN;
01281   p.revents = 0;
01282 
01283   if (poll(&p, 1, 1000) < 0) {
01284     if (errno == EINTR)
01285       return MHD_YES;
01286 #if HAVE_MESSAGES
01287     MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
01288 #endif
01289     return MHD_NO;
01290   }
01291   /* handle shutdown cases */
01292   if (daemon->shutdown == MHD_YES) 
01293     return MHD_NO;  
01294   if (daemon->socket_fd < 0) 
01295     return MHD_YES; 
01296   if (0 != (p.revents & POLLIN)) 
01297     MHD_accept_connection (daemon);
01298   return MHD_YES;
01299 #else
01300   return MHD_NO;
01301 #endif
01302 }
01303 
01304 
01315 int
01316 MHD_run (struct MHD_Daemon *daemon)
01317 {
01318   if ((daemon->shutdown != MHD_NO) || (0 != (daemon->options
01319                                              & MHD_USE_THREAD_PER_CONNECTION))
01320       || (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
01321     return MHD_NO;
01322   MHD_select (daemon, MHD_NO);
01323   MHD_cleanup_connections (daemon);
01324   return MHD_YES;
01325 }
01326 
01327 
01335 static void *
01336 MHD_select_thread (void *cls)
01337 {
01338   struct MHD_Daemon *daemon = cls;
01339   while (daemon->shutdown == MHD_NO)
01340     {
01341       if ((daemon->options & MHD_USE_POLL) == 0) 
01342         MHD_select (daemon, MHD_YES);
01343       else 
01344         MHD_poll(daemon);      
01345       MHD_cleanup_connections (daemon);
01346     }
01347   return NULL;
01348 }
01349 
01350 
01362 struct MHD_Daemon *
01363 MHD_start_daemon (unsigned int options,
01364                   uint16_t port,
01365                   MHD_AcceptPolicyCallback apc,
01366                   void *apc_cls,
01367                   MHD_AccessHandlerCallback dh, void *dh_cls, ...)
01368 {
01369   struct MHD_Daemon *ret;
01370   va_list ap;
01371 
01372   va_start (ap, dh_cls);
01373   ret = MHD_start_daemon_va (options, port, apc, apc_cls, dh, dh_cls, ap);
01374   va_end (ap);
01375   return ret;
01376 }
01377 
01378 
01379 typedef void (*VfprintfFunctionPointerType)(void *, const char *, va_list);
01380 
01381 
01390 static int
01391 parse_options_va (struct MHD_Daemon *daemon,
01392                   const struct sockaddr **servaddr,
01393                   va_list ap);
01394 
01395 
01404 static int
01405 parse_options (struct MHD_Daemon *daemon,
01406                const struct sockaddr **servaddr,
01407                ...)
01408 {
01409   va_list ap;
01410   int ret;
01411 
01412   va_start (ap, servaddr);
01413   ret = parse_options_va (daemon, servaddr, ap);
01414   va_end (ap);
01415   return ret;
01416 }
01417 
01418 
01427 static int
01428 parse_options_va (struct MHD_Daemon *daemon,
01429                   const struct sockaddr **servaddr,
01430                   va_list ap)
01431 {
01432   enum MHD_OPTION opt;
01433   struct MHD_OptionItem *oa;
01434   unsigned int i;
01435 #if HTTPS_SUPPORT
01436   int ret;
01437   const char *pstr;
01438 #endif
01439   
01440   while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
01441     {
01442       switch (opt)
01443         {
01444         case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
01445           daemon->pool_size = va_arg (ap, size_t);
01446           break;
01447         case MHD_OPTION_CONNECTION_LIMIT:
01448           daemon->max_connections = va_arg (ap, unsigned int);
01449           break;
01450         case MHD_OPTION_CONNECTION_TIMEOUT:
01451           daemon->connection_timeout = va_arg (ap, unsigned int);
01452           break;
01453         case MHD_OPTION_NOTIFY_COMPLETED:
01454           daemon->notify_completed =
01455             va_arg (ap, MHD_RequestCompletedCallback);
01456           daemon->notify_completed_cls = va_arg (ap, void *);
01457           break;
01458         case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
01459           daemon->per_ip_connection_limit = va_arg (ap, unsigned int);
01460           break;
01461         case MHD_OPTION_SOCK_ADDR:
01462           *servaddr = va_arg (ap, const struct sockaddr *);
01463           break;
01464         case MHD_OPTION_URI_LOG_CALLBACK:
01465           daemon->uri_log_callback =
01466             va_arg (ap, LogCallback);
01467           daemon->uri_log_callback_cls = va_arg (ap, void *);
01468           break;
01469         case MHD_OPTION_THREAD_POOL_SIZE:
01470           daemon->worker_pool_size = va_arg (ap, unsigned int);
01471           if (daemon->worker_pool_size >= SIZE_MAX / sizeof (struct MHD_Daemon))
01472             {
01473 #if HAVE_MESSAGES
01474               FPRINTF (stderr,
01475                        "Specified thread pool size (%u) too big\n",
01476                        daemon->worker_pool_size);
01477 #endif
01478               return MHD_NO;
01479             }
01480           break;
01481 #if HTTPS_SUPPORT
01482         case MHD_OPTION_HTTPS_MEM_KEY:
01483           if (0 != (daemon->options & MHD_USE_SSL))
01484             daemon->https_mem_key = va_arg (ap, const char *);
01485 #if HAVE_MESSAGES
01486           else
01487             FPRINTF (stderr,
01488                      "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01489                      opt);        
01490 #endif
01491           break;
01492         case MHD_OPTION_HTTPS_MEM_CERT:
01493           if (0 != (daemon->options & MHD_USE_SSL))
01494             daemon->https_mem_cert = va_arg (ap, const char *);
01495 #if HAVE_MESSAGES
01496           else
01497             FPRINTF (stderr,
01498                      "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01499                      opt);        
01500 #endif
01501           break;
01502         case MHD_OPTION_HTTPS_MEM_TRUST:
01503           if (0 != (daemon->options & MHD_USE_SSL))
01504             daemon->https_mem_trust = va_arg (ap, const char *);
01505 #if HAVE_MESSAGES
01506           else
01507             FPRINTF (stderr,
01508                      "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01509                      opt);
01510 #endif
01511           break;
01512         case MHD_OPTION_HTTPS_CRED_TYPE:
01513           daemon->cred_type = va_arg (ap, gnutls_credentials_type_t);
01514           break;
01515         case MHD_OPTION_HTTPS_PRIORITIES:
01516           ret = gnutls_priority_init (&daemon->priority_cache,
01517                                       pstr = va_arg (ap, const char*),
01518                                       NULL);
01519 #if HAVE_MESSAGES
01520           if (ret != GNUTLS_E_SUCCESS)
01521             FPRINTF (stderr,
01522                      "Setting priorities to `%s' failed: %s\n",
01523                      pstr,
01524                      gnutls_strerror (ret));
01525 #endif    
01526           if (ret != GNUTLS_E_SUCCESS)
01527             return MHD_NO;
01528           break;
01529 #endif
01530 #ifdef DAUTH_SUPPORT
01531         case MHD_OPTION_DIGEST_AUTH_RANDOM:
01532           daemon->digest_auth_rand_size = va_arg (ap, size_t);
01533           daemon->digest_auth_random = va_arg (ap, const char *);
01534           break;
01535         case MHD_OPTION_NONCE_NC_SIZE:
01536           daemon->nonce_nc_size = va_arg (ap, unsigned int);
01537           break;
01538 #endif
01539         case MHD_OPTION_LISTEN_SOCKET:
01540           daemon->socket_fd = va_arg (ap, int);   
01541           break;
01542         case MHD_OPTION_EXTERNAL_LOGGER:
01543 #if HAVE_MESSAGES
01544           daemon->custom_error_log =
01545             va_arg (ap, VfprintfFunctionPointerType);
01546           daemon->custom_error_log_cls = va_arg (ap, void *);
01547 #else
01548           va_arg (ap, VfprintfFunctionPointerType);
01549           va_arg (ap, void *);
01550 #endif
01551           break;
01552         case MHD_OPTION_THREAD_STACK_SIZE:
01553           daemon->thread_stack_size = va_arg (ap, size_t);
01554           break;
01555         case MHD_OPTION_ARRAY:
01556           oa = va_arg (ap, struct MHD_OptionItem*);
01557           i = 0;
01558           while (MHD_OPTION_END != (opt = oa[i].option))
01559             {
01560               switch (opt)
01561                 {
01562                   /* all options taking 'size_t' */
01563                 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
01564                 case MHD_OPTION_THREAD_STACK_SIZE:
01565                   if (MHD_YES != parse_options (daemon,
01566                                                 servaddr,
01567                                                 opt,
01568                                                 (size_t) oa[i].value,
01569                                                 MHD_OPTION_END))
01570                     return MHD_NO;
01571                   break;
01572                   /* all options taking 'unsigned int' */
01573                 case MHD_OPTION_NONCE_NC_SIZE:
01574                 case MHD_OPTION_CONNECTION_LIMIT:
01575                 case MHD_OPTION_CONNECTION_TIMEOUT:
01576                 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
01577                 case MHD_OPTION_THREAD_POOL_SIZE:
01578                   if (MHD_YES != parse_options (daemon,
01579                                                 servaddr,
01580                                                 opt,
01581                                                 (unsigned int) oa[i].value,
01582                                                 MHD_OPTION_END))
01583                     return MHD_NO;
01584                   break;
01585                   /* all options taking 'int' or 'enum' */
01586                 case MHD_OPTION_HTTPS_CRED_TYPE:
01587                 case MHD_OPTION_LISTEN_SOCKET:
01588                   if (MHD_YES != parse_options (daemon,
01589                                                 servaddr,
01590                                                 opt,
01591                                                 (int) oa[i].value,
01592                                                 MHD_OPTION_END))
01593                     return MHD_NO;
01594                   break;
01595                   /* all options taking one pointer */
01596                 case MHD_OPTION_SOCK_ADDR:
01597                 case MHD_OPTION_HTTPS_MEM_KEY:
01598                 case MHD_OPTION_HTTPS_MEM_CERT:
01599                 case MHD_OPTION_HTTPS_MEM_TRUST:
01600                 case MHD_OPTION_HTTPS_PRIORITIES:
01601                 case MHD_OPTION_ARRAY:
01602                   if (MHD_YES != parse_options (daemon,
01603                                                 servaddr,
01604                                                 opt,
01605                                                 oa[i].ptr_value,
01606                                                 MHD_OPTION_END))
01607                     return MHD_NO;
01608                   break;
01609                   /* all options taking two pointers */
01610                 case MHD_OPTION_NOTIFY_COMPLETED:
01611                 case MHD_OPTION_URI_LOG_CALLBACK:
01612                 case MHD_OPTION_EXTERNAL_LOGGER:
01613                 case MHD_OPTION_UNESCAPE_CALLBACK:
01614                   if (MHD_YES != parse_options (daemon,
01615                                                 servaddr,
01616                                                 opt,
01617                                                 (void *) oa[i].value,
01618                                                 oa[i].ptr_value,
01619                                                 MHD_OPTION_END))
01620                     return MHD_NO;
01621                   break;
01622                   /* options taking size_t-number followed by pointer */
01623                 case MHD_OPTION_DIGEST_AUTH_RANDOM:
01624                   if (MHD_YES != parse_options (daemon,
01625                                                 servaddr,
01626                                                 opt,
01627                                                 (size_t) oa[i].value,
01628                                                 oa[i].ptr_value,
01629                                                 MHD_OPTION_END))
01630                     return MHD_NO;
01631                   break;
01632                 default:
01633                   return MHD_NO;
01634                 }
01635               i++;
01636             }
01637           break;
01638         case MHD_OPTION_UNESCAPE_CALLBACK:
01639           daemon->unescape_callback =
01640             va_arg (ap, UnescapeCallback);
01641           daemon->unescape_callback_cls = va_arg (ap, void *);
01642           break;
01643         default:
01644 #if HAVE_MESSAGES
01645           if (((opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
01646               (opt <= MHD_OPTION_HTTPS_PRIORITIES)) || (opt == MHD_OPTION_HTTPS_MEM_TRUST))
01647             {
01648               FPRINTF (stderr,
01649                        "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
01650                        opt);
01651             }
01652           else
01653             {
01654               FPRINTF (stderr,
01655                        "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
01656                        opt);
01657             }
01658 #endif
01659           return MHD_NO;
01660         }
01661     }  
01662   return MHD_YES;
01663 }
01664 
01665 
01677 struct MHD_Daemon *
01678 MHD_start_daemon_va (unsigned int options,
01679                      uint16_t port,
01680                      MHD_AcceptPolicyCallback apc,
01681                      void *apc_cls,
01682                      MHD_AccessHandlerCallback dh, void *dh_cls,
01683                      va_list ap)
01684 {
01685   const int on = 1;
01686   struct MHD_Daemon *retVal;
01687   int socket_fd;
01688   struct sockaddr_in servaddr4;
01689 #if HAVE_INET6
01690   struct sockaddr_in6 servaddr6;
01691 #endif
01692   const struct sockaddr *servaddr = NULL;
01693   socklen_t addrlen;
01694   unsigned int i;
01695   int res_thread_create;
01696 
01697   if ((port == 0) || (dh == NULL))
01698     return NULL;
01699   retVal = malloc (sizeof (struct MHD_Daemon));
01700   if (retVal == NULL)
01701     return NULL;
01702   memset (retVal, 0, sizeof (struct MHD_Daemon));
01703 #if HTTPS_SUPPORT
01704   if (options & MHD_USE_SSL)
01705     {
01706       gnutls_priority_init (&retVal->priority_cache,
01707                             "NORMAL",
01708                             NULL);
01709     }
01710 #endif
01711   retVal->socket_fd = -1;
01712   retVal->options = (enum MHD_OPTION)options;
01713   retVal->port = port;
01714   retVal->apc = apc;
01715   retVal->apc_cls = apc_cls;
01716   retVal->default_handler = dh;
01717   retVal->default_handler_cls = dh_cls;
01718   retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
01719   retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
01720   retVal->unescape_callback = &MHD_http_unescape;
01721   retVal->connection_timeout = 0;       /* no timeout */
01722 #ifdef DAUTH_SUPPORT
01723   retVal->digest_auth_rand_size = 0;
01724   retVal->digest_auth_random = NULL;
01725   retVal->nonce_nc_size = 4; /* tiny */
01726 #endif
01727 #if HAVE_MESSAGES
01728   retVal->custom_error_log =
01729     (void (*)(void *, const char *, va_list)) &vfprintf;
01730   retVal->custom_error_log_cls = stderr;
01731 #endif
01732 #if HTTPS_SUPPORT
01733   if (options & MHD_USE_SSL)
01734     {
01735       /* lock MHD_gnutls_global mutex since it uses reference counting */
01736       if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
01737         {
01738 #if HAVE_MESSAGES
01739           MHD_DLOG (retVal, "Failed to aquire gnutls mutex\n");
01740 #endif
01741           mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01742         }
01743       if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
01744         {
01745 #if HAVE_MESSAGES
01746           MHD_DLOG (retVal, "Failed to release gnutls mutex\n");
01747 #endif
01748           mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01749         }
01750       retVal->cred_type = GNUTLS_CRD_CERTIFICATE;
01751     }
01752 #endif
01753 
01754   if (MHD_YES != parse_options_va (retVal, &servaddr, ap))
01755     {
01756       free (retVal);
01757       return NULL;
01758     }
01759 
01760 #ifdef DAUTH_SUPPORT
01761   if (retVal->nonce_nc_size > 0) 
01762     {
01763       if ( ( (size_t) (retVal->nonce_nc_size * sizeof(struct MHD_NonceNc))) / 
01764            sizeof(struct MHD_NonceNc) != retVal->nonce_nc_size)
01765         {
01766 #if HAVE_MESSAGES
01767           MHD_DLOG (retVal,
01768                     "Specified value for NC_SIZE too large\n");
01769 #endif
01770           free (retVal);
01771           return NULL;    
01772         }
01773       retVal->nnc = malloc (retVal->nonce_nc_size * sizeof(struct MHD_NonceNc));
01774       if (NULL == retVal->nnc)
01775             {
01776 #if HAVE_MESSAGES
01777               MHD_DLOG (retVal,
01778                         "Failed to allocate memory for nonce-nc map: %s\n",
01779                         STRERROR (errno));
01780 #endif
01781               free (retVal);
01782               return NULL;
01783             }
01784     }
01785   if (0 != pthread_mutex_init (&retVal->nnc_lock, NULL))
01786     {
01787 #if HAVE_MESSAGES
01788       MHD_DLOG (retVal,
01789                 "MHD failed to initialize nonce-nc mutex\n");
01790 #endif
01791       free (retVal);
01792       return NULL;
01793     }
01794 #endif
01795 
01796   /* poll support currently only works with MHD_USE_THREAD_PER_CONNECTION */
01797   if ( (0 != (options & MHD_USE_POLL)) && 
01798        (0 == (options & MHD_USE_THREAD_PER_CONNECTION)) ) 
01799     {
01800 #if HAVE_MESSAGES
01801       MHD_DLOG (retVal,
01802                 "MHD poll support only works with MHD_USE_THREAD_PER_CONNECTION\n");
01803 #endif
01804 #if DAUTH_SUPPORT
01805       free (retVal->nnc);
01806       pthread_mutex_destroy (&retVal->nnc_lock);
01807 #endif
01808       free (retVal);
01809       return NULL;
01810     }
01811 
01812   /* Thread pooling currently works only with internal select thread model */
01813   if ( (0 == (options & MHD_USE_SELECT_INTERNALLY)) && 
01814        (retVal->worker_pool_size > 0) )
01815     {
01816 #if HAVE_MESSAGES
01817       MHD_DLOG (retVal,
01818                 "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n");
01819 #endif
01820       free (retVal);
01821       return NULL;
01822     }
01823 
01824 #ifdef __SYMBIAN32__
01825   if (0 != (options & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
01826     {
01827 #if HAVE_MESSAGES
01828       MHD_DLOG (retVal,
01829                 "Threaded operations are not supported on Symbian.\n");
01830 #endif
01831       free (retVal);
01832       return NULL;
01833     }
01834 #endif
01835   if (retVal->socket_fd == -1)
01836     {
01837       if ((options & MHD_USE_IPv6) != 0)
01838 #if HAVE_INET6
01839         socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0);
01840 #else
01841       {
01842 #if HAVE_MESSAGES
01843         MHD_DLOG (retVal, 
01844                   "AF_INET6 not supported\n");
01845 #endif
01846         free (retVal);
01847         return NULL;
01848       }
01849 #endif
01850       else
01851         socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0);
01852       if (socket_fd == -1)
01853         {
01854 #if HAVE_MESSAGES
01855           if ((options & MHD_USE_DEBUG) != 0)
01856             MHD_DLOG (retVal, 
01857                       "Call to socket failed: %s\n", 
01858                       STRERROR (errno));
01859 #endif
01860           free (retVal);
01861           return NULL;
01862         }
01863       if ((SETSOCKOPT (socket_fd,
01864                        SOL_SOCKET,
01865                        SO_REUSEADDR,
01866                        &on, sizeof (on)) < 0) && ((options & MHD_USE_DEBUG) != 0))
01867         {
01868 #if HAVE_MESSAGES
01869           MHD_DLOG (retVal, 
01870                     "setsockopt failed: %s\n", 
01871                     STRERROR (errno));
01872 #endif
01873         }
01874       
01875       /* check for user supplied sockaddr */
01876 #if HAVE_INET6
01877       if ((options & MHD_USE_IPv6) != 0)
01878         addrlen = sizeof (struct sockaddr_in6);
01879       else
01880 #endif
01881         addrlen = sizeof (struct sockaddr_in);
01882       if (NULL == servaddr)
01883         {
01884 #if HAVE_INET6
01885           if ((options & MHD_USE_IPv6) != 0)
01886             {
01887               memset (&servaddr6, 0, sizeof (struct sockaddr_in6));
01888               servaddr6.sin6_family = AF_INET6;
01889               servaddr6.sin6_port = htons (port);
01890               servaddr = (struct sockaddr *) &servaddr6;
01891             }
01892           else
01893 #endif
01894             {
01895               memset (&servaddr4, 0, sizeof (struct sockaddr_in));
01896               servaddr4.sin_family = AF_INET;
01897               servaddr4.sin_port = htons (port);
01898               servaddr = (struct sockaddr *) &servaddr4;
01899             }
01900         }
01901       retVal->socket_fd = socket_fd;
01902 
01903       if ((options & MHD_USE_IPv6) != 0)
01904         {
01905 #ifdef IPPROTO_IPV6
01906 #ifdef IPV6_V6ONLY
01907           /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options" 
01908              (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx); 
01909              and may also be missing on older POSIX systems; good luck if you have any of those,
01910              your IPv6 socket may then also bind against IPv4... */
01911 #ifndef WINDOWS
01912           const int on = 1;
01913           setsockopt (socket_fd, 
01914                       IPPROTO_IPV6, IPV6_V6ONLY, 
01915                       &on, sizeof (on));
01916 #else
01917           const char on = 1;
01918           setsockopt (socket_fd, 
01919                       IPPROTO_IPV6, IPV6_V6ONLY, 
01920                       &on, sizeof (on));
01921 #endif
01922 #endif
01923 #endif
01924         }
01925       if (BIND (socket_fd, servaddr, addrlen) == -1)
01926         {
01927 #if HAVE_MESSAGES
01928           if ((options & MHD_USE_DEBUG) != 0)
01929             MHD_DLOG (retVal,
01930                       "Failed to bind to port %u: %s\n", 
01931                       (unsigned int) port, 
01932                       STRERROR (errno));
01933 #endif
01934           CLOSE (socket_fd);
01935           free (retVal);
01936           return NULL;
01937         }
01938       
01939       if (LISTEN (socket_fd, 20) < 0)
01940         {
01941 #if HAVE_MESSAGES
01942           if ((options & MHD_USE_DEBUG) != 0)
01943             MHD_DLOG (retVal,
01944                       "Failed to listen for connections: %s\n", 
01945                       STRERROR (errno));
01946 #endif
01947           CLOSE (socket_fd);
01948           free (retVal);
01949           return NULL;
01950         }      
01951     }
01952   else
01953     {
01954       socket_fd = retVal->socket_fd;
01955     }
01956 #ifndef WINDOWS
01957   if ( (socket_fd >= FD_SETSIZE) &&
01958        (0 == (options & MHD_USE_POLL)) )
01959     {
01960 #if HAVE_MESSAGES
01961       if ((options & MHD_USE_DEBUG) != 0)
01962         MHD_DLOG (retVal,
01963                   "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
01964                   socket_fd,
01965                   FD_SETSIZE);
01966 #endif
01967       CLOSE (socket_fd);
01968       free (retVal);
01969       return NULL;
01970     }
01971 #endif
01972 
01973   if (0 != pthread_mutex_init (&retVal->per_ip_connection_mutex, NULL))
01974     {
01975 #if HAVE_MESSAGES
01976       MHD_DLOG (retVal,
01977                "MHD failed to initialize IP connection limit mutex\n");
01978 #endif
01979       CLOSE (socket_fd);
01980       free (retVal);
01981       return NULL;
01982     }
01983 
01984 #if HTTPS_SUPPORT
01985   /* initialize HTTPS daemon certificate aspects & send / recv functions */
01986   if ((0 != (options & MHD_USE_SSL)) && (0 != MHD_TLS_init (retVal)))
01987     {
01988 #if HAVE_MESSAGES
01989       MHD_DLOG (retVal, 
01990                 "Failed to initialize TLS support\n");
01991 #endif
01992       CLOSE (socket_fd);
01993 #ifdef DAUTH_SUPPORT
01994       pthread_mutex_destroy (&retVal->nnc_lock);
01995       free (retVal->nnc);
01996 #endif
01997       pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
01998       free (retVal);
01999       return NULL;
02000     }
02001 #endif
02002   if ( ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
02003          ( (0 != (options & MHD_USE_SELECT_INTERNALLY)) &&
02004            (0 == retVal->worker_pool_size)) ) && 
02005        (0 != (res_thread_create =
02006               create_thread (&retVal->pid, retVal, &MHD_select_thread, retVal))))
02007     {
02008 #if HAVE_MESSAGES
02009       MHD_DLOG (retVal,
02010                 "Failed to create listen thread: %s\n", 
02011                 STRERROR (res_thread_create));
02012 #endif
02013 #ifdef DAUTH_SUPPORT
02014       pthread_mutex_destroy (&retVal->nnc_lock);
02015       free (retVal->nnc);
02016 #endif
02017       pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
02018       free (retVal);
02019       CLOSE (socket_fd);
02020       return NULL;
02021     }
02022   if (retVal->worker_pool_size > 0)
02023     {
02024 #ifndef MINGW
02025       int sk_flags;
02026 #else
02027       unsigned long sk_flags;
02028 #endif
02029 
02030       /* Coarse-grained count of connections per thread (note error
02031        * due to integer division). Also keep track of how many
02032        * connections are leftover after an equal split. */
02033       unsigned int conns_per_thread = retVal->max_connections
02034                                       / retVal->worker_pool_size;
02035       unsigned int leftover_conns = retVal->max_connections
02036                                     % retVal->worker_pool_size;
02037 
02038       i = 0; /* we need this in case fcntl or malloc fails */
02039 
02040       /* Accept must be non-blocking. Multiple children may wake up
02041        * to handle a new connection, but only one will win the race.
02042        * The others must immediately return. */
02043 #ifndef MINGW
02044       sk_flags = fcntl (socket_fd, F_GETFL);
02045       if (sk_flags < 0)
02046         goto thread_failed;
02047       if (fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK) < 0)
02048         goto thread_failed;
02049 #else
02050       sk_flags = 1;
02051 #if HAVE_PLIBC_FD
02052       if (ioctlsocket (plibc_fd_get_handle (socket_fd), FIONBIO, &sk_flags) ==
02053           SOCKET_ERROR)
02054 #else
02055       if (ioctlsocket (socket_fd, FIONBIO, &sk_flags) == SOCKET_ERROR)
02056 #endif // PLIBC_FD
02057         goto thread_failed;
02058 #endif // MINGW
02059 
02060       /* Allocate memory for pooled objects */
02061       retVal->worker_pool = malloc (sizeof (struct MHD_Daemon)
02062                                     * retVal->worker_pool_size);
02063       if (NULL == retVal->worker_pool)
02064         goto thread_failed;
02065 
02066       /* Start the workers in the pool */
02067       for (i = 0; i < retVal->worker_pool_size; ++i)
02068         {
02069           /* Create copy of the Daemon object for each worker */
02070           struct MHD_Daemon *d = &retVal->worker_pool[i];
02071           memcpy (d, retVal, sizeof (struct MHD_Daemon));
02072 
02073           /* Adjust pooling params for worker daemons; note that memcpy()
02074              has already copied MHD_USE_SELECT_INTERNALLY thread model into
02075              the worker threads. */
02076           d->master = retVal;
02077           d->worker_pool_size = 0;
02078           d->worker_pool = NULL;
02079 
02080           /* Divide available connections evenly amongst the threads.
02081            * Thread indexes in [0, leftover_conns) each get one of the
02082            * leftover connections. */
02083           d->max_connections = conns_per_thread;
02084           if (i < leftover_conns)
02085             ++d->max_connections;
02086 
02087           /* Spawn the worker thread */
02088           if (0 != (res_thread_create = create_thread (&d->pid, retVal, &MHD_select_thread, d)))
02089             {
02090 #if HAVE_MESSAGES
02091               MHD_DLOG (retVal,
02092                         "Failed to create pool thread: %s\n", 
02093                         STRERROR (res_thread_create));
02094 #endif
02095               /* Free memory for this worker; cleanup below handles
02096                * all previously-created workers. */
02097               goto thread_failed;
02098             }
02099         }
02100     }
02101   return retVal;
02102 
02103 thread_failed:
02104   /* If no worker threads created, then shut down normally. Calling
02105      MHD_stop_daemon (as we do below) doesn't work here since it
02106      assumes a 0-sized thread pool means we had been in the default
02107      MHD_USE_SELECT_INTERNALLY mode. */
02108   if (i == 0)
02109     {
02110       CLOSE (socket_fd);
02111       pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
02112       if (NULL != retVal->worker_pool)
02113         free (retVal->worker_pool);
02114       free (retVal);
02115       return NULL;
02116     }
02117 
02118   /* Shutdown worker threads we've already created. Pretend
02119      as though we had fully initialized our daemon, but
02120      with a smaller number of threads than had been
02121      requested. */
02122   retVal->worker_pool_size = i - 1;
02123   MHD_stop_daemon (retVal);
02124   return NULL;
02125 }
02126 
02130 static void
02131 MHD_close_connections (struct MHD_Daemon *daemon)
02132 {
02133   while (daemon->connections != NULL)
02134     {
02135       if (-1 != daemon->connections->socket_fd)
02136         {
02137 #if DEBUG_CLOSE
02138 #if HAVE_MESSAGES
02139           MHD_DLOG (daemon, "MHD shutdown, closing active connections\n");
02140 #endif
02141 #endif
02142           MHD_connection_close (daemon->connections,
02143                                 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
02144         }
02145       MHD_cleanup_connections (daemon);
02146     }
02147 }
02148 
02152 void
02153 MHD_stop_daemon (struct MHD_Daemon *daemon)
02154 {
02155   void *unused;
02156   int fd;
02157   unsigned int i;
02158   int rc;
02159 
02160   if (daemon == NULL)
02161     return;
02162   daemon->shutdown = MHD_YES;
02163   fd = daemon->socket_fd;
02164   daemon->socket_fd = -1;
02165 
02166   /* Prepare workers for shutdown */
02167   for (i = 0; i < daemon->worker_pool_size; ++i)
02168     {
02169       daemon->worker_pool[i].shutdown = MHD_YES;
02170       daemon->worker_pool[i].socket_fd = -1;
02171     }
02172 
02173 #if OSX
02174   /* without this, either (thread pool = 0) threads would get stuck or
02175    * CLOSE would get stuck if attempted before (thread pool > 0)
02176    * threads have ended */
02177   SHUTDOWN (fd, SHUT_RDWR);
02178 #else
02179 #if DEBUG_CLOSE
02180 #if HAVE_MESSAGES
02181   MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
02182 #endif
02183 #endif
02184   CLOSE (fd);
02185 #endif
02186 
02187   /* Signal workers to stop and clean them up */
02188   for (i = 0; i < daemon->worker_pool_size; ++i)
02189     pthread_kill (daemon->worker_pool[i].pid, SIGALRM);
02190   for (i = 0; i < daemon->worker_pool_size; ++i)
02191     {
02192       if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused)))
02193         {
02194 #if HAVE_MESSAGES
02195           MHD_DLOG (daemon, "Failed to join a thread: %s\n",
02196                     STRERROR (rc));
02197 #endif
02198           abort();
02199         }
02200       MHD_close_connections (&daemon->worker_pool[i]);
02201     }
02202   free (daemon->worker_pool);
02203 
02204   if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
02205       ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))
02206         && (0 == daemon->worker_pool_size)))
02207     {
02208       pthread_kill (daemon->pid, SIGALRM);
02209       if (0 != (rc = pthread_join (daemon->pid, &unused)))
02210         {
02211 #if HAVE_MESSAGES
02212           MHD_DLOG (daemon, "Failed to join a thread: %s\n",
02213                     STRERROR (rc));
02214 #endif
02215           abort();
02216         }
02217     }
02218   MHD_close_connections (daemon);
02219 
02220 #if OSX
02221 #if DEBUG_CLOSE
02222 #if HAVE_MESSAGES
02223   MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
02224 #endif
02225 #endif
02226   CLOSE (fd);
02227 #endif
02228 
02229   /* TLS clean up */
02230 #if HTTPS_SUPPORT
02231   if (daemon->options & MHD_USE_SSL)
02232     {
02233       gnutls_priority_deinit (daemon->priority_cache);
02234       if (daemon->x509_cred)
02235         gnutls_certificate_free_credentials (daemon->x509_cred);
02236       /* lock MHD_gnutls_global mutex since it uses reference counting */
02237       if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
02238         {
02239 #if HAVE_MESSAGES
02240           MHD_DLOG (daemon, "Failed to aquire gnutls mutex\n");
02241 #endif
02242           abort();
02243         }
02244       if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
02245         {
02246 #if HAVE_MESSAGES
02247           MHD_DLOG (daemon, "Failed to release gnutls mutex\n");
02248 #endif
02249           abort();
02250         }
02251     }
02252 #endif
02253 
02254 #ifdef DAUTH_SUPPORT
02255   free (daemon->nnc);
02256   pthread_mutex_destroy (&daemon->nnc_lock);
02257 #endif
02258   pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
02259   free (daemon);
02260 }
02261 
02272 const union MHD_DaemonInfo *
02273 MHD_get_daemon_info (struct MHD_Daemon *daemon,
02274                      enum MHD_DaemonInfoType infoType, ...)
02275 {
02276   switch (infoType)
02277     {
02278     case MHD_DAEMON_INFO_LISTEN_FD:
02279       return (const union MHD_DaemonInfo *) &daemon->socket_fd;
02280    default:
02281       return NULL;
02282     };
02283 }
02284 
02300 void MHD_set_panic_func (MHD_PanicCallback cb, void *cls)
02301 {
02302   mhd_panic = cb;
02303   mhd_panic_cls = cls;
02304 }
02305 
02311 const char *
02312 MHD_get_version (void)
02313 {
02314   return PACKAGE_VERSION;
02315 }
02316 
02317 #ifndef WINDOWS
02318 
02319 static struct sigaction sig;
02320 
02321 static struct sigaction old;
02322 
02323 static void
02324 sigalrmHandler (int sig)
02325 {
02326 }
02327 #endif
02328 
02329 #ifdef __GNUC__
02330 #define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor))
02331 #define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor))
02332 #else  // !__GNUC__
02333 #define ATTRIBUTE_CONSTRUCTOR
02334 #define ATTRIBUTE_DESTRUCTOR
02335 #endif  // __GNUC__
02336 
02337 #if HTTPS_SUPPORT
02338 GCRY_THREAD_OPTION_PTHREAD_IMPL;
02339 #endif
02340 
02345 void ATTRIBUTE_CONSTRUCTOR MHD_init ()
02346 {
02347   mhd_panic = &mhd_panic_std;
02348   mhd_panic_cls = NULL;
02349 
02350 #ifndef WINDOWS
02351   /* make sure SIGALRM does not kill us */
02352   memset (&sig, 0, sizeof (struct sigaction));
02353   memset (&old, 0, sizeof (struct sigaction));
02354   sig.sa_flags = SA_NODEFER;
02355   sig.sa_handler = &sigalrmHandler;
02356   sigaction (SIGALRM, &sig, &old);
02357 #else
02358   plibc_init ("GNU", "libmicrohttpd");
02359 #endif
02360 #if HTTPS_SUPPORT
02361   gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
02362   gnutls_global_init ();
02363   if (0 != pthread_mutex_init(&MHD_gnutls_init_mutex, NULL))
02364     abort();
02365 #endif
02366 }
02367 
02368 void ATTRIBUTE_DESTRUCTOR MHD_fini ()
02369 {
02370 #if HTTPS_SUPPORT
02371   gnutls_global_deinit ();
02372   if (0 != pthread_mutex_destroy(&MHD_gnutls_init_mutex))
02373     mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
02374 #endif
02375 #ifndef WINDOWS
02376   sigaction (SIGALRM, &old, &sig);
02377 #else
02378   plibc_shutdown ();
02379 #endif
02380 }
02381 
02382 /* end of daemon.c */

Generated on Thu May 10 14:38:01 2012 for GNU libmicrohttpd by  doxygen 1.4.7