GNU libmicrohttpd 0.9.5

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   return res;
00403 }
00404 
00405 
00414 static ssize_t
00415 send_tls_adapter (struct MHD_Connection *connection,
00416                   const void *other, size_t i)
00417 {
00418   int res;
00419   res = gnutls_record_send (connection->tls_session, other, i);
00420   if ( (res == GNUTLS_E_AGAIN) ||
00421        (res == GNUTLS_E_INTERRUPTED) )
00422     {
00423       errno = EINTR;
00424       return -1;
00425     }
00426   return res;
00427 }
00428 
00429 
00436 static int
00437 MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
00438 {
00439   gnutls_datum_t key;
00440   gnutls_datum_t cert;
00441 
00442   if (daemon->https_mem_trust) {
00443                 cert.data = (unsigned char *) daemon->https_mem_trust;
00444                 cert.size = strlen(daemon->https_mem_trust);
00445                 if (gnutls_certificate_set_x509_trust_mem(daemon->x509_cred, &cert,
00446                                 GNUTLS_X509_FMT_PEM) < 0) {
00447 #if HAVE_MESSAGES
00448                         MHD_DLOG(daemon,
00449                                         "Bad trust certificate format\n");
00450 #endif
00451                         return -1;
00452                 }
00453         }
00454 
00455   /* certificate & key loaded from memory */
00456   if (daemon->https_mem_cert && daemon->https_mem_key)
00457     {
00458       key.data = (unsigned char *) daemon->https_mem_key;
00459       key.size = strlen (daemon->https_mem_key);
00460       cert.data = (unsigned char *) daemon->https_mem_cert;
00461       cert.size = strlen (daemon->https_mem_cert);
00462 
00463       return gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
00464                                                   &cert, &key,
00465                                                   GNUTLS_X509_FMT_PEM);
00466     }
00467 #if HAVE_MESSAGES
00468   MHD_DLOG (daemon, "You need to specify a certificate and key location\n");
00469 #endif
00470   return -1;
00471 }
00472 
00479 static int
00480 MHD_TLS_init (struct MHD_Daemon *daemon)
00481 {
00482   switch (daemon->cred_type)
00483     {
00484     case GNUTLS_CRD_CERTIFICATE:
00485       if (0 !=
00486           gnutls_certificate_allocate_credentials (&daemon->x509_cred))
00487         return GNUTLS_E_MEMORY_ERROR;
00488       return MHD_init_daemon_certificate (daemon);
00489     default:
00490 #if HAVE_MESSAGES
00491       MHD_DLOG (daemon,
00492                 "Error: invalid credentials type %d specified.\n",
00493                 daemon->cred_type);
00494 #endif
00495       return -1;
00496     }
00497 }
00498 #endif
00499 
00513 int
00514 MHD_get_fdset (struct MHD_Daemon *daemon,
00515                fd_set * read_fd_set,
00516                fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd)
00517 {
00518   struct MHD_Connection *con_itr;
00519   int fd;
00520 
00521   if ((daemon == NULL) || (read_fd_set == NULL) || (write_fd_set == NULL)
00522       || (except_fd_set == NULL) || (max_fd == NULL)
00523       || (-1 == (fd = daemon->socket_fd)) || (daemon->shutdown == MHD_YES)
00524       || ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0)
00525       || ((daemon->options & MHD_USE_POLL) != 0))
00526     return MHD_NO;
00527 
00528   FD_SET (fd, read_fd_set);
00529   /* update max file descriptor */
00530   if ((*max_fd) < fd) 
00531     *max_fd = fd;
00532 
00533   con_itr = daemon->connections;
00534   while (con_itr != NULL)
00535     {
00536       if (MHD_YES != MHD_connection_get_fdset (con_itr,
00537                                                read_fd_set,
00538                                                write_fd_set,
00539                                                except_fd_set, max_fd))
00540         return MHD_NO;
00541       con_itr = con_itr->next;
00542     }
00543 #if DEBUG_CONNECT
00544   MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
00545 #endif
00546   return MHD_YES;
00547 }
00548 
00556 static void *
00557 MHD_handle_connection (void *data)
00558 {
00559   struct MHD_Connection *con = data;
00560   int num_ready;
00561   fd_set rs;
00562   fd_set ws;
00563   fd_set es;
00564   int max;
00565   struct timeval tv;
00566   unsigned int timeout;
00567 #ifdef HAVE_POLL_H
00568   struct MHD_Pollfd mp;
00569   struct pollfd p;
00570 #endif
00571 
00572   timeout = con->daemon->connection_timeout;
00573   while ((!con->daemon->shutdown) && (con->socket_fd != -1)) {
00574       tv.tv_usec = 0;
00575       if ( (timeout > (time (NULL) - con->last_activity)) ||
00576            (timeout == 0) )
00577         {
00578           /* in case we are missing the SIGALRM, keep going after
00579              at most 1s; see http://lists.gnu.org/archive/html/libmicrohttpd/2009-10/msg00013.html */
00580           tv.tv_sec = 1;
00581           if ((con->state == MHD_CONNECTION_NORMAL_BODY_UNREADY) ||
00582               (con->state == MHD_CONNECTION_CHUNKED_BODY_UNREADY))
00583             {
00584               /* do not block (we're waiting for our callback to succeed) */
00585               tv.tv_sec = 0;
00586             }
00587         }
00588       else
00589         {
00590           tv.tv_sec = 0;
00591         }
00592 #ifdef HAVE_POLL_H
00593       if (0 == (con->daemon->options & MHD_USE_POLL)) {
00594 #else
00595       {
00596 #endif
00597         /* use select */
00598         FD_ZERO (&rs);
00599         FD_ZERO (&ws);
00600         FD_ZERO (&es);
00601         max = 0;
00602         MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
00603         num_ready = SELECT (max + 1, &rs, &ws, &es, &tv);
00604         if (num_ready < 0) {
00605             if (errno == EINTR)
00606               continue;
00607 #if HAVE_MESSAGES
00608             MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n", max,
00609                       STRERROR (errno));
00610 #endif
00611             break;
00612         }
00613         /* call appropriate connection handler if necessary */
00614         if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &rs)))
00615           con->read_handler (con);
00616         if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
00617           con->write_handler (con);
00618         if (con->socket_fd != -1)
00619           con->idle_handler (con);
00620       }
00621 #ifdef HAVE_POLL_H
00622       else
00623       {
00624         /* use poll */
00625         memset(&mp, 0, sizeof (struct MHD_Pollfd));
00626         MHD_connection_get_pollfd(con, &mp);
00627         memset(&p, 0, sizeof (struct pollfd));
00628         p.fd = mp.fd;
00629         if (mp.events & MHD_POLL_ACTION_IN) 
00630           p.events |= POLLIN;        
00631         if (mp.events & MHD_POLL_ACTION_OUT) 
00632           p.events |= POLLOUT;
00633         /* in case we are missing the SIGALRM, keep going after
00634            at most 1s */
00635         if (poll (&p, 1, 1000) < 0) {
00636           if (errno == EINTR)
00637             continue;
00638 #if HAVE_MESSAGES
00639           MHD_DLOG (con->daemon, "Error during poll: `%s'\n", 
00640                     STRERROR (errno));
00641 #endif
00642           break;
00643         }
00644         if ( (con->socket_fd != -1) && 
00645              (0 != (p.revents & POLLIN)) ) 
00646           con->read_handler (con);        
00647         if ( (con->socket_fd != -1) && 
00648              (0 != (p.revents & POLLOUT)) )
00649           con->write_handler (con);        
00650         if (con->socket_fd != -1)
00651           con->idle_handler (con);
00652         if ( (con->socket_fd != -1) &&
00653              (0 != (p.revents & (POLLERR | POLLHUP))) )
00654           MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR);      
00655       }
00656 #endif
00657     }
00658   if (con->socket_fd != -1)
00659     {
00660 #if DEBUG_CLOSE
00661 #if HAVE_MESSAGES
00662       MHD_DLOG (con->daemon,
00663                 "Processing thread terminating, closing connection\n");
00664 #endif
00665 #endif
00666       MHD_connection_close (con, MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
00667     }
00668   return NULL;
00669 }
00670 
00679 static ssize_t
00680 recv_param_adapter (struct MHD_Connection *connection, void *other, size_t i)
00681 {
00682   if (connection->socket_fd == -1)
00683     return -1;
00684   if (0 != (connection->daemon->options & MHD_USE_SSL))
00685     return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
00686   return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT);
00687 }
00688 
00697 static ssize_t
00698 send_param_adapter (struct MHD_Connection *connection,
00699                     const void *other, size_t i)
00700 {
00701 #if LINUX
00702   int fd;
00703   off_t offset;
00704   int ret;
00705 #endif
00706   if (connection->socket_fd == -1)
00707     return -1;
00708   if (0 != (connection->daemon->options & MHD_USE_SSL))
00709     return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
00710 #if LINUX
00711   if ( (connection->write_buffer_append_offset ==
00712         connection->write_buffer_send_offset) &&
00713        (NULL != connection->response) &&
00714        (-1 != (fd = connection->response->fd)) )
00715     {
00716       /* can use sendfile */
00717       offset = (off_t) connection->response_write_position + connection->response->fd_off;
00718       ret = sendfile (connection->socket_fd, 
00719                       fd,
00720                       &offset,
00721                       connection->response->total_size - offset);
00722       if ( (ret == -1) &&
00723            (errno == EINTR) )
00724         return 0;
00725       return ret;
00726     }
00727 #endif
00728   return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL | MSG_DONTWAIT);
00729 }
00730 
00731 
00732 #if HTTPS_SUPPORT
00733 
00737 static void
00738 socket_set_nonblocking (int fd)
00739 {
00740 #if MINGW
00741   u_long mode;
00742   mode = 1;
00743   if (ioctlsocket (fd, FIONBIO, &mode) == SOCKET_ERROR)
00744     {
00745       SetErrnoFromWinsockError (WSAGetLastError ());
00746 #if HAVE_MESSAGES
00747       FPRINTF(stderr, "Failed to make socket non-blocking: %s\n", 
00748               STRERROR (errno));
00749 #endif
00750     }
00751 #else
00752 
00753   /* not MINGW */
00754   int flags = fcntl (fd, F_GETFL);
00755   if ( (flags == -1) ||
00756        (0 != fcntl (fd, F_SETFL, flags | O_NONBLOCK)) )
00757     {
00758 #if HAVE_MESSAGES
00759       FPRINTF(stderr, "Failed to make socket non-blocking: %s\n", 
00760               STRERROR (errno));
00761 #endif
00762     }
00763 #endif
00764 }
00765 #endif
00766 
00767 
00777 static int
00778 create_thread (pthread_t * thread,
00779                const struct MHD_Daemon *daemon,
00780                void *(*start_routine)(void*),
00781                void *arg)
00782 {
00783   pthread_attr_t attr;
00784   pthread_attr_t *pattr;
00785   int ret;
00786   
00787   if (daemon->thread_stack_size != 0) 
00788     {
00789       if (0 != (ret = pthread_attr_init (&attr))) 
00790         goto ERR;
00791       if (0 != (ret = pthread_attr_setstacksize (&attr, daemon->thread_stack_size)))
00792         {
00793           pthread_attr_destroy (&attr);
00794           goto ERR;
00795         }
00796       pattr = &attr;
00797     }
00798   else
00799     {
00800       pattr = NULL;
00801     }
00802   ret = pthread_create (thread, pattr,
00803                         start_routine, arg);
00804   if (daemon->thread_stack_size != 0) 
00805     pthread_attr_destroy (&attr);
00806   return ret;
00807  ERR:
00808 #if HAVE_MESSAGES
00809   MHD_DLOG (daemon,
00810             "Failed to set thread stack size\n");
00811 #endif
00812   errno = EINVAL;
00813   return ret;
00814 }
00815 
00816 
00817 
00826 static int
00827 MHD_accept_connection (struct MHD_Daemon *daemon)
00828 {
00829   struct MHD_Connection *connection;
00830 #if HAVE_INET6
00831   struct sockaddr_in6 addrstorage;
00832 #else
00833   struct sockaddr_in addrstorage;
00834 #endif
00835   struct sockaddr *addr = (struct sockaddr *) &addrstorage;
00836   socklen_t addrlen;
00837   int s;
00838   int res_thread_create;
00839 #if OSX
00840   static int on = 1;
00841 #endif
00842 
00843   addrlen = sizeof (addrstorage);
00844   memset (addr, 0, sizeof (addrstorage));
00845 
00846   s = ACCEPT (daemon->socket_fd, addr, &addrlen);
00847   if ((s == -1) || (addrlen <= 0))
00848     {
00849 #if HAVE_MESSAGES
00850       /* This could be a common occurance with multiple worker threads */
00851       if ((EAGAIN != errno) && (EWOULDBLOCK != errno))
00852         MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));
00853 #endif
00854       if (s != -1)
00855         {
00856           SHUTDOWN (s, SHUT_RDWR);
00857           CLOSE (s);
00858           /* just in case */
00859         }
00860       return MHD_NO;
00861     }
00862 #ifndef WINDOWS
00863   if ( (s >= FD_SETSIZE) &&
00864        (0 == (daemon->options & MHD_USE_POLL)) )
00865     {
00866 #if HAVE_MESSAGES
00867       MHD_DLOG (daemon,
00868                 "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
00869                 s,
00870                 FD_SETSIZE);
00871 #endif
00872       CLOSE (s);
00873       return MHD_NO;
00874     }
00875 #endif
00876 
00877 
00878 #if HAVE_MESSAGES
00879 #if DEBUG_CONNECT
00880   MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
00881 #endif
00882 #endif
00883   if ((daemon->max_connections == 0)
00884       || (MHD_ip_limit_add (daemon, addr, addrlen) == MHD_NO))
00885     {
00886       /* above connection limit - reject */
00887 #if HAVE_MESSAGES
00888       MHD_DLOG (daemon,
00889                 "Server reached connection limit (closing inbound connection)\n");
00890 #endif
00891       SHUTDOWN (s, SHUT_RDWR);
00892       CLOSE (s);
00893       return MHD_NO;
00894     }
00895 
00896   /* apply connection acceptance policy if present */
00897   if ((daemon->apc != NULL)
00898       && (MHD_NO == daemon->apc (daemon->apc_cls, addr, addrlen)))
00899     {
00900 #if DEBUG_CLOSE
00901 #if HAVE_MESSAGES
00902       MHD_DLOG (daemon, "Connection rejected, closing connection\n");
00903 #endif
00904 #endif
00905       SHUTDOWN (s, SHUT_RDWR);
00906       CLOSE (s);
00907       MHD_ip_limit_del (daemon, addr, addrlen);
00908       return MHD_YES;
00909     }
00910 #if OSX
00911 #ifdef SOL_SOCKET
00912 #ifdef SO_NOSIGPIPE
00913   setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof (on));
00914 #endif
00915 #endif
00916 #endif
00917   connection = malloc (sizeof (struct MHD_Connection));
00918   if (NULL == connection)
00919     {
00920 #if HAVE_MESSAGES
00921       MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00922 #endif
00923       SHUTDOWN (s, SHUT_RDWR);
00924       CLOSE (s);
00925       MHD_ip_limit_del (daemon, addr, addrlen);
00926       return MHD_NO;
00927     }
00928   memset (connection, 0, sizeof (struct MHD_Connection));
00929   connection->pool = NULL;
00930   connection->addr = malloc (addrlen);
00931   if (connection->addr == NULL)
00932     {
00933 #if HAVE_MESSAGES
00934       MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00935 #endif
00936       SHUTDOWN (s, SHUT_RDWR);
00937       CLOSE (s);
00938       MHD_ip_limit_del (daemon, addr, addrlen);
00939       free (connection);
00940       return MHD_NO;
00941     }
00942   memcpy (connection->addr, addr, addrlen);
00943   connection->addr_len = addrlen;
00944   connection->socket_fd = s;
00945   connection->daemon = daemon;
00946   connection->last_activity = time (NULL);
00947 
00948   /* set default connection handlers  */
00949   MHD_set_http_callbacks_ (connection);
00950   connection->recv_cls = &recv_param_adapter;
00951   connection->send_cls = &send_param_adapter;
00952 #if HTTPS_SUPPORT
00953   if (0 != (daemon->options & MHD_USE_SSL))
00954     {
00955       connection->recv_cls = &recv_tls_adapter;
00956       connection->send_cls = &send_tls_adapter;
00957       connection->state = MHD_TLS_CONNECTION_INIT;
00958       MHD_set_https_callbacks (connection);
00959       gnutls_init (&connection->tls_session, GNUTLS_SERVER);
00960       gnutls_priority_set (connection->tls_session,
00961                            daemon->priority_cache);
00962       if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00963         {
00964           /* use non-blocking IO for gnutls */
00965           socket_set_nonblocking (connection->socket_fd);
00966         }
00967       switch (connection->daemon->cred_type)
00968         {
00969           /* set needed credentials for certificate authentication. */
00970         case GNUTLS_CRD_CERTIFICATE:
00971           gnutls_credentials_set (connection->tls_session,
00972                                   GNUTLS_CRD_CERTIFICATE,
00973                                   connection->daemon->x509_cred);
00974           break;
00975         default:
00976 #if HAVE_MESSAGES
00977           MHD_DLOG (connection->daemon,
00978                     "Failed to setup TLS credentials: unknown credential type %d\n",
00979                     connection->daemon->cred_type);
00980 #endif
00981           SHUTDOWN (s, SHUT_RDWR);
00982           CLOSE (s);
00983           MHD_ip_limit_del (daemon, addr, addrlen);
00984           free (connection->addr);
00985           free (connection);
00986           mhd_panic (mhd_panic_cls, __FILE__, __LINE__, 
00987 #if HAVE_MESSAGES
00988                      "Unknown credential type"
00989 #else
00990                      NULL
00991 #endif
00992                      );
00993           return MHD_NO;
00994         }
00995       gnutls_transport_set_ptr (connection->tls_session,
00996                                 (gnutls_transport_ptr_t) connection);
00997       gnutls_transport_set_pull_function (connection->tls_session,
00998                                           (gnutls_pull_func) &
00999                                                recv_param_adapter);
01000       gnutls_transport_set_push_function (connection->tls_session,
01001                                           (gnutls_push_func) &
01002                                                send_param_adapter);
01003 
01004       if (daemon->https_mem_trust){
01005       gnutls_certificate_server_set_request(connection->tls_session, GNUTLS_CERT_REQUEST);
01006       }
01007     }
01008 #endif
01009 
01010   /* attempt to create handler thread */
01011   if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01012     {
01013       res_thread_create = create_thread (&connection->pid, daemon,
01014                                          &MHD_handle_connection, connection);
01015       if (res_thread_create != 0)
01016         {
01017 #if HAVE_MESSAGES
01018           MHD_DLOG (daemon, "Failed to create a thread: %s\n",
01019                     STRERROR (res_thread_create));
01020 #endif
01021           SHUTDOWN (s, SHUT_RDWR);
01022           CLOSE (s);
01023           MHD_ip_limit_del (daemon, addr, addrlen);
01024           free (connection->addr);
01025           free (connection);
01026           return MHD_NO;
01027         }
01028     }
01029   connection->next = daemon->connections;
01030   daemon->connections = connection;
01031   daemon->max_connections--;
01032   return MHD_YES;
01033 }
01034 
01042 static void
01043 MHD_cleanup_connections (struct MHD_Daemon *daemon)
01044 {
01045   struct MHD_Connection *pos;
01046   struct MHD_Connection *prev;
01047   void *unused;
01048   int rc;
01049 
01050   pos = daemon->connections;
01051   prev = NULL;
01052   while (pos != NULL)
01053     {
01054       if ((pos->socket_fd == -1) ||
01055           (((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
01056             (daemon->shutdown) && (pos->socket_fd != -1))))
01057         {
01058           if (prev == NULL)
01059             daemon->connections = pos->next;
01060           else
01061             prev->next = pos->next;
01062           if (0 != (pos->daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01063             {
01064               pthread_kill (pos->pid, SIGALRM);
01065               if (0 != (rc = pthread_join (pos->pid, &unused)))
01066                 {
01067 #if HAVE_MESSAGES
01068                   MHD_DLOG (daemon, "Failed to join a thread: %s\n",
01069                             STRERROR (rc));
01070 #endif
01071                   abort();
01072                 }
01073             }
01074           MHD_pool_destroy (pos->pool);
01075 #if HTTPS_SUPPORT
01076           if (pos->tls_session != NULL)
01077             gnutls_deinit (pos->tls_session);
01078 #endif
01079           MHD_ip_limit_del (daemon, (struct sockaddr*)pos->addr, pos->addr_len);
01080           if (pos->response != NULL)
01081             {
01082               MHD_destroy_response (pos->response);
01083               pos->response = NULL;
01084             }
01085           free (pos->addr);
01086           free (pos);
01087           daemon->max_connections++;
01088           if (prev == NULL)
01089             pos = daemon->connections;
01090           else
01091             pos = prev->next;
01092           continue;
01093         }
01094       prev = pos;
01095       pos = pos->next;
01096     }
01097 }
01098 
01111 int
01112 MHD_get_timeout (struct MHD_Daemon *daemon, unsigned MHD_LONG_LONG *timeout)
01113 {
01114   time_t earliest_deadline;
01115   time_t now;
01116   struct MHD_Connection *pos;
01117   unsigned int dto;
01118 
01119   dto = daemon->connection_timeout;
01120   if (0 == dto)
01121     return MHD_NO;
01122   pos = daemon->connections;
01123   if (pos == NULL)
01124     return MHD_NO;              /* no connections */
01125   now = time (NULL);
01126   /* start with conservative estimate */
01127   earliest_deadline = now + dto;
01128   while (pos != NULL)
01129     {
01130       if (earliest_deadline > pos->last_activity + dto)
01131         earliest_deadline = pos->last_activity + dto;
01132 #if HTTPS_SUPPORT
01133       if (  (0 != (daemon->options & MHD_USE_SSL)) &&
01134             (0 != gnutls_record_check_pending (pos->tls_session)) )
01135         earliest_deadline = now;
01136 #endif
01137       pos = pos->next;
01138     }
01139   if (earliest_deadline < now)
01140     *timeout = 0;
01141   else
01142     *timeout = (earliest_deadline - now);
01143   return MHD_YES;
01144 }
01145 
01146 
01154 static int
01155 MHD_select (struct MHD_Daemon *daemon, int may_block)
01156 {
01157   struct MHD_Connection *pos;
01158   int num_ready;
01159   fd_set rs;
01160   fd_set ws;
01161   fd_set es;
01162   int max;
01163   struct timeval timeout;
01164   unsigned MHD_LONG_LONG ltimeout;
01165   int ds;
01166 
01167   timeout.tv_sec = 0;
01168   timeout.tv_usec = 0;
01169   if (daemon->shutdown == MHD_YES)
01170     return MHD_NO;
01171   FD_ZERO (&rs);
01172   FD_ZERO (&ws);
01173   FD_ZERO (&es);
01174   max = 0;
01175 
01176   if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01177     {
01178       /* single-threaded, go over everything */
01179       if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
01180         return MHD_NO;
01181 
01182       /* If we're at the connection limit, no need to
01183          accept new connections. */
01184       if ( (daemon->max_connections == 0) && (daemon->socket_fd != -1) )
01185         FD_CLR(daemon->socket_fd, &rs);
01186     }
01187   else
01188     {
01189       /* accept only, have one thread per connection */
01190       max = daemon->socket_fd;
01191       if (max == -1)
01192         return MHD_NO;
01193       FD_SET (max, &rs);
01194     }
01195 
01196   /* in case we are missing the SIGALRM, keep going after
01197      at most 1s; see http://lists.gnu.org/archive/html/libmicrohttpd/2009-10/msg00013.html */
01198   timeout.tv_usec = 0;
01199   timeout.tv_sec = 1;
01200   if (may_block == MHD_NO)
01201     {
01202       timeout.tv_usec = 0;
01203       timeout.tv_sec = 0;
01204     }
01205   else
01206     {
01207       /* ltimeout is in ms */
01208       if ( (MHD_YES == MHD_get_timeout (daemon, &ltimeout)) &&
01209            (ltimeout < 1000) )
01210         {
01211           timeout.tv_usec = ltimeout * 1000;
01212           timeout.tv_sec = 0;
01213         }
01214     }
01215   num_ready = SELECT (max + 1, &rs, &ws, &es, &timeout);
01216 
01217   if (daemon->shutdown == MHD_YES)
01218     return MHD_NO;
01219   if (num_ready < 0)
01220     {
01221       if (errno == EINTR)
01222         return MHD_YES;
01223 #if HAVE_MESSAGES
01224       MHD_DLOG (daemon, "select failed: %s\n", STRERROR (errno));
01225 #endif
01226       return MHD_NO;
01227     }
01228   ds = daemon->socket_fd;
01229   if (ds == -1)
01230     return MHD_YES;
01231 
01232   /* select connection thread handling type */
01233   if (FD_ISSET (ds, &rs))
01234     MHD_accept_connection (daemon);
01235   if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
01236     {
01237       /* do not have a thread per connection, process all connections now */
01238       pos = daemon->connections;
01239       while (pos != NULL)
01240         {
01241           ds = pos->socket_fd;
01242           if (ds != -1)
01243             {
01244               /* TODO call con->read handler */
01245               if (FD_ISSET (ds, &rs))
01246                 pos->read_handler (pos);
01247               if ((pos->socket_fd != -1) && (FD_ISSET (ds, &ws)))
01248                 pos->write_handler (pos);
01249               if (pos->socket_fd != -1)
01250                 pos->idle_handler (pos);
01251             }
01252           pos = pos->next;
01253         }
01254     }
01255   return MHD_YES;
01256 }
01257 
01263 static int
01264 MHD_poll (struct MHD_Daemon *daemon)
01265 {
01266 #ifdef HAVE_POLL_H
01267   struct pollfd p;
01268 
01269   if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 
01270     return MHD_NO;
01271   p.fd = daemon->socket_fd;
01272   p.events = POLLIN;
01273   p.revents = 0;
01274 
01275   if (poll(&p, 1, 1000) < 0) {
01276     if (errno == EINTR)
01277       return MHD_YES;
01278 #if HAVE_MESSAGES
01279     MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
01280 #endif
01281     return MHD_NO;
01282   }
01283   /* handle shutdown cases */
01284   if (daemon->shutdown == MHD_YES) 
01285     return MHD_NO;  
01286   if (daemon->socket_fd < 0) 
01287     return MHD_YES; 
01288   if (0 != (p.revents & POLLIN)) 
01289     MHD_accept_connection (daemon);
01290   return MHD_YES;
01291 #else
01292   return MHD_NO;
01293 #endif
01294 }
01295 
01296 
01307 int
01308 MHD_run (struct MHD_Daemon *daemon)
01309 {
01310   if ((daemon->shutdown != MHD_NO) || (0 != (daemon->options
01311                                              & MHD_USE_THREAD_PER_CONNECTION))
01312       || (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
01313     return MHD_NO;
01314   MHD_select (daemon, MHD_NO);
01315   MHD_cleanup_connections (daemon);
01316   return MHD_YES;
01317 }
01318 
01319 
01327 static void *
01328 MHD_select_thread (void *cls)
01329 {
01330   struct MHD_Daemon *daemon = cls;
01331   while (daemon->shutdown == MHD_NO)
01332     {
01333       if ((daemon->options & MHD_USE_POLL) == 0) 
01334         MHD_select (daemon, MHD_YES);
01335       else 
01336         MHD_poll(daemon);      
01337       MHD_cleanup_connections (daemon);
01338     }
01339   return NULL;
01340 }
01341 
01342 
01354 struct MHD_Daemon *
01355 MHD_start_daemon (unsigned int options,
01356                   uint16_t port,
01357                   MHD_AcceptPolicyCallback apc,
01358                   void *apc_cls,
01359                   MHD_AccessHandlerCallback dh, void *dh_cls, ...)
01360 {
01361   struct MHD_Daemon *ret;
01362   va_list ap;
01363 
01364   va_start (ap, dh_cls);
01365   ret = MHD_start_daemon_va (options, port, apc, apc_cls, dh, dh_cls, ap);
01366   va_end (ap);
01367   return ret;
01368 }
01369 
01370 
01371 typedef void (*VfprintfFunctionPointerType)(void *, const char *, va_list);
01372 
01373 
01382 static int
01383 parse_options_va (struct MHD_Daemon *daemon,
01384                   const struct sockaddr **servaddr,
01385                   va_list ap);
01386 
01387 
01396 static int
01397 parse_options (struct MHD_Daemon *daemon,
01398                const struct sockaddr **servaddr,
01399                ...)
01400 {
01401   va_list ap;
01402   int ret;
01403 
01404   va_start (ap, servaddr);
01405   ret = parse_options_va (daemon, servaddr, ap);
01406   va_end (ap);
01407   return ret;
01408 }
01409 
01410 
01419 static int
01420 parse_options_va (struct MHD_Daemon *daemon,
01421                   const struct sockaddr **servaddr,
01422                   va_list ap)
01423 {
01424   enum MHD_OPTION opt;
01425   struct MHD_OptionItem *oa;
01426   unsigned int i;
01427 #if HTTPS_SUPPORT
01428   int ret;
01429   const char *pstr;
01430 #endif
01431   
01432   while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
01433     {
01434       switch (opt)
01435         {
01436         case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
01437           daemon->pool_size = va_arg (ap, size_t);
01438           break;
01439         case MHD_OPTION_CONNECTION_LIMIT:
01440           daemon->max_connections = va_arg (ap, unsigned int);
01441           break;
01442         case MHD_OPTION_CONNECTION_TIMEOUT:
01443           daemon->connection_timeout = va_arg (ap, unsigned int);
01444           break;
01445         case MHD_OPTION_NOTIFY_COMPLETED:
01446           daemon->notify_completed =
01447             va_arg (ap, MHD_RequestCompletedCallback);
01448           daemon->notify_completed_cls = va_arg (ap, void *);
01449           break;
01450         case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
01451           daemon->per_ip_connection_limit = va_arg (ap, unsigned int);
01452           break;
01453         case MHD_OPTION_SOCK_ADDR:
01454           *servaddr = va_arg (ap, const struct sockaddr *);
01455           break;
01456         case MHD_OPTION_URI_LOG_CALLBACK:
01457           daemon->uri_log_callback =
01458             va_arg (ap, LogCallback);
01459           daemon->uri_log_callback_cls = va_arg (ap, void *);
01460           break;
01461         case MHD_OPTION_THREAD_POOL_SIZE:
01462           daemon->worker_pool_size = va_arg (ap, unsigned int);
01463           if (daemon->worker_pool_size >= SIZE_MAX / sizeof (struct MHD_Daemon))
01464             {
01465 #if HAVE_MESSAGES
01466               FPRINTF (stderr,
01467                        "Specified thread pool size (%u) too big\n",
01468                        daemon->worker_pool_size);
01469 #endif
01470               return MHD_NO;
01471             }
01472           break;
01473 #if HTTPS_SUPPORT
01474         case MHD_OPTION_HTTPS_MEM_KEY:
01475           if (0 != (daemon->options & MHD_USE_SSL))
01476             daemon->https_mem_key = va_arg (ap, const char *);
01477 #if HAVE_MESSAGES
01478           else
01479             FPRINTF (stderr,
01480                      "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01481                      opt);        
01482 #endif
01483           break;
01484         case MHD_OPTION_HTTPS_MEM_CERT:
01485           if (0 != (daemon->options & MHD_USE_SSL))
01486             daemon->https_mem_cert = va_arg (ap, const char *);
01487 #if HAVE_MESSAGES
01488           else
01489             FPRINTF (stderr,
01490                      "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01491                      opt);        
01492 #endif
01493           break;
01494         case MHD_OPTION_HTTPS_MEM_TRUST:
01495           if (0 != (daemon->options & MHD_USE_SSL))
01496             daemon->https_mem_trust = va_arg (ap, const char *);
01497 #if HAVE_MESSAGES
01498           else
01499             FPRINTF (stderr,
01500                      "MHD HTTPS option %d passed to MHD but MHD_USE_SSL not set\n",
01501                      opt);
01502 #endif
01503           break;
01504         case MHD_OPTION_HTTPS_CRED_TYPE:
01505           daemon->cred_type = va_arg (ap, gnutls_credentials_type_t);
01506           break;
01507         case MHD_OPTION_HTTPS_PRIORITIES:
01508           ret = gnutls_priority_init (&daemon->priority_cache,
01509                                       pstr = va_arg (ap, const char*),
01510                                       NULL);
01511 #if HAVE_MESSAGES
01512           if (ret != GNUTLS_E_SUCCESS)
01513             FPRINTF (stderr,
01514                      "Setting priorities to `%s' failed: %s\n",
01515                      pstr,
01516                      gnutls_strerror (ret));
01517 #endif    
01518           if (ret != GNUTLS_E_SUCCESS)
01519             return MHD_NO;
01520           break;
01521 #endif
01522 #ifdef DAUTH_SUPPORT
01523         case MHD_OPTION_DIGEST_AUTH_RANDOM:
01524           daemon->digest_auth_rand_size = va_arg (ap, size_t);
01525           daemon->digest_auth_random = va_arg (ap, const char *);
01526           break;
01527         case MHD_OPTION_NONCE_NC_SIZE:
01528           daemon->nonce_nc_size = va_arg (ap, unsigned int);
01529           break;
01530 #endif
01531         case MHD_OPTION_LISTEN_SOCKET:
01532           daemon->socket_fd = va_arg (ap, int);   
01533           break;
01534         case MHD_OPTION_EXTERNAL_LOGGER:
01535 #if HAVE_MESSAGES
01536           daemon->custom_error_log =
01537             va_arg (ap, VfprintfFunctionPointerType);
01538           daemon->custom_error_log_cls = va_arg (ap, void *);
01539 #else
01540           va_arg (ap, VfprintfFunctionPointerType);
01541           va_arg (ap, void *);
01542 #endif
01543           break;
01544         case MHD_OPTION_THREAD_STACK_SIZE:
01545           daemon->thread_stack_size = va_arg (ap, size_t);
01546           break;
01547         case MHD_OPTION_ARRAY:
01548           oa = va_arg (ap, struct MHD_OptionItem*);
01549           i = 0;
01550           while (MHD_OPTION_END != (opt = oa[i].option))
01551             {
01552               switch (opt)
01553                 {
01554                   /* all options taking 'size_t' */
01555                 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
01556                 case MHD_OPTION_THREAD_STACK_SIZE:
01557                   if (MHD_YES != parse_options (daemon,
01558                                                 servaddr,
01559                                                 opt,
01560                                                 (size_t) oa[i].value,
01561                                                 MHD_OPTION_END))
01562                     return MHD_NO;
01563                   break;
01564                   /* all options taking 'unsigned int' */
01565                 case MHD_OPTION_NONCE_NC_SIZE:
01566                 case MHD_OPTION_CONNECTION_LIMIT:
01567                 case MHD_OPTION_CONNECTION_TIMEOUT:
01568                 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
01569                 case MHD_OPTION_THREAD_POOL_SIZE:
01570                   if (MHD_YES != parse_options (daemon,
01571                                                 servaddr,
01572                                                 opt,
01573                                                 (unsigned int) oa[i].value,
01574                                                 MHD_OPTION_END))
01575                     return MHD_NO;
01576                   break;
01577                   /* all options taking 'int' or 'enum' */
01578                 case MHD_OPTION_HTTPS_CRED_TYPE:
01579                 case MHD_OPTION_LISTEN_SOCKET:
01580                   if (MHD_YES != parse_options (daemon,
01581                                                 servaddr,
01582                                                 opt,
01583                                                 (int) oa[i].value,
01584                                                 MHD_OPTION_END))
01585                     return MHD_NO;
01586                   break;
01587                   /* all options taking one pointer */
01588                 case MHD_OPTION_SOCK_ADDR:
01589                 case MHD_OPTION_HTTPS_MEM_KEY:
01590                 case MHD_OPTION_HTTPS_MEM_CERT:
01591                 case MHD_OPTION_HTTPS_MEM_TRUST:
01592                 case MHD_OPTION_HTTPS_PRIORITIES:
01593                 case MHD_OPTION_ARRAY:
01594                   if (MHD_YES != parse_options (daemon,
01595                                                 servaddr,
01596                                                 opt,
01597                                                 oa[i].ptr_value,
01598                                                 MHD_OPTION_END))
01599                     return MHD_NO;
01600                   break;
01601                   /* all options taking two pointers */
01602                 case MHD_OPTION_NOTIFY_COMPLETED:
01603                 case MHD_OPTION_URI_LOG_CALLBACK:
01604                 case MHD_OPTION_EXTERNAL_LOGGER:
01605                 case MHD_OPTION_UNESCAPE_CALLBACK:
01606                   if (MHD_YES != parse_options (daemon,
01607                                                 servaddr,
01608                                                 opt,
01609                                                 (void *) oa[i].value,
01610                                                 oa[i].ptr_value,
01611                                                 MHD_OPTION_END))
01612                     return MHD_NO;
01613                   break;
01614                   /* options taking size_t-number followed by pointer */
01615                 case MHD_OPTION_DIGEST_AUTH_RANDOM:
01616                   if (MHD_YES != parse_options (daemon,
01617                                                 servaddr,
01618                                                 opt,
01619                                                 (size_t) oa[i].value,
01620                                                 oa[i].ptr_value,
01621                                                 MHD_OPTION_END))
01622                     return MHD_NO;
01623                   break;
01624                 default:
01625                   return MHD_NO;
01626                 }
01627               i++;
01628             }
01629           break;
01630         case MHD_OPTION_UNESCAPE_CALLBACK:
01631           daemon->unescape_callback =
01632             va_arg (ap, UnescapeCallback);
01633           daemon->unescape_callback_cls = va_arg (ap, void *);
01634           break;
01635         default:
01636 #if HAVE_MESSAGES
01637           if (((opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
01638               (opt <= MHD_OPTION_HTTPS_PRIORITIES)) || (opt == MHD_OPTION_HTTPS_MEM_TRUST))
01639             {
01640               FPRINTF (stderr,
01641                        "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
01642                        opt);
01643             }
01644           else
01645             {
01646               FPRINTF (stderr,
01647                        "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
01648                        opt);
01649             }
01650 #endif
01651           return MHD_NO;
01652         }
01653     }  
01654   return MHD_YES;
01655 }
01656 
01657 
01669 struct MHD_Daemon *
01670 MHD_start_daemon_va (unsigned int options,
01671                      uint16_t port,
01672                      MHD_AcceptPolicyCallback apc,
01673                      void *apc_cls,
01674                      MHD_AccessHandlerCallback dh, void *dh_cls,
01675                      va_list ap)
01676 {
01677   const int on = 1;
01678   struct MHD_Daemon *retVal;
01679   int socket_fd;
01680   struct sockaddr_in servaddr4;
01681 #if HAVE_INET6
01682   struct sockaddr_in6 servaddr6;
01683 #endif
01684   const struct sockaddr *servaddr = NULL;
01685   socklen_t addrlen;
01686   unsigned int i;
01687   int res_thread_create;
01688 
01689   if ((port == 0) || (dh == NULL))
01690     return NULL;
01691   retVal = malloc (sizeof (struct MHD_Daemon));
01692   if (retVal == NULL)
01693     return NULL;
01694   memset (retVal, 0, sizeof (struct MHD_Daemon));
01695 #if HTTPS_SUPPORT
01696   if (options & MHD_USE_SSL)
01697     {
01698       gnutls_priority_init (&retVal->priority_cache,
01699                             "NORMAL",
01700                             NULL);
01701     }
01702 #endif
01703   retVal->socket_fd = -1;
01704   retVal->options = (enum MHD_OPTION)options;
01705   retVal->port = port;
01706   retVal->apc = apc;
01707   retVal->apc_cls = apc_cls;
01708   retVal->default_handler = dh;
01709   retVal->default_handler_cls = dh_cls;
01710   retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
01711   retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
01712   retVal->unescape_callback = &MHD_http_unescape;
01713   retVal->connection_timeout = 0;       /* no timeout */
01714 #ifdef DAUTH_SUPPORT
01715   retVal->digest_auth_rand_size = 0;
01716   retVal->digest_auth_random = NULL;
01717   retVal->nonce_nc_size = 4; /* tiny */
01718 #endif
01719 #if HAVE_MESSAGES
01720   retVal->custom_error_log =
01721     (void (*)(void *, const char *, va_list)) &vfprintf;
01722   retVal->custom_error_log_cls = stderr;
01723 #endif
01724 #if HTTPS_SUPPORT
01725   if (options & MHD_USE_SSL)
01726     {
01727       /* lock MHD_gnutls_global mutex since it uses reference counting */
01728       if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
01729         {
01730 #if HAVE_MESSAGES
01731           MHD_DLOG (retVal, "Failed to aquire gnutls mutex\n");
01732 #endif
01733           mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01734         }
01735       if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
01736         {
01737 #if HAVE_MESSAGES
01738           MHD_DLOG (retVal, "Failed to release gnutls mutex\n");
01739 #endif
01740           mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
01741         }
01742       retVal->cred_type = GNUTLS_CRD_CERTIFICATE;
01743     }
01744 #endif
01745 
01746   if (MHD_YES != parse_options_va (retVal, &servaddr, ap))
01747     {
01748       free (retVal);
01749       return NULL;
01750     }
01751 
01752 #ifdef DAUTH_SUPPORT
01753   if (retVal->nonce_nc_size > 0) 
01754     {
01755       if ( ( (size_t) (retVal->nonce_nc_size * sizeof(struct MHD_NonceNc))) / 
01756            sizeof(struct MHD_NonceNc) != retVal->nonce_nc_size)
01757         {
01758 #if HAVE_MESSAGES
01759           MHD_DLOG (retVal,
01760                     "Specified value for NC_SIZE too large\n");
01761 #endif
01762           free (retVal);
01763           return NULL;    
01764         }
01765       retVal->nnc = malloc (retVal->nonce_nc_size * sizeof(struct MHD_NonceNc));
01766       if (NULL == retVal->nnc)
01767             {
01768 #if HAVE_MESSAGES
01769               MHD_DLOG (retVal,
01770                         "Failed to allocate memory for nonce-nc map: %s\n",
01771                         STRERROR (errno));
01772 #endif
01773               free (retVal);
01774               return NULL;
01775             }
01776     }
01777   if (0 != pthread_mutex_init (&retVal->nnc_lock, NULL))
01778     {
01779 #if HAVE_MESSAGES
01780       MHD_DLOG (retVal,
01781                 "MHD failed to initialize nonce-nc mutex\n");
01782 #endif
01783       free (retVal);
01784       return NULL;
01785     }
01786 #endif
01787 
01788   /* poll support currently only works with MHD_USE_THREAD_PER_CONNECTION */
01789   if ( (0 != (options & MHD_USE_POLL)) && 
01790        (0 == (options & MHD_USE_THREAD_PER_CONNECTION)) ) 
01791     {
01792 #if HAVE_MESSAGES
01793       MHD_DLOG (retVal,
01794                 "MHD poll support only works with MHD_USE_THREAD_PER_CONNECTION\n");
01795 #endif
01796 #if DAUTH_SUPPORT
01797       free (retVal->nnc);
01798       pthread_mutex_destroy (&retVal->nnc_lock);
01799 #endif
01800       free (retVal);
01801       return NULL;
01802     }
01803 
01804   /* Thread pooling currently works only with internal select thread model */
01805   if ( (0 == (options & MHD_USE_SELECT_INTERNALLY)) && 
01806        (retVal->worker_pool_size > 0) )
01807     {
01808 #if HAVE_MESSAGES
01809       MHD_DLOG (retVal,
01810                 "MHD thread pooling only works with MHD_USE_SELECT_INTERNALLY\n");
01811 #endif
01812       free (retVal);
01813       return NULL;
01814     }
01815 
01816 #ifdef __SYMBIAN32__
01817   if (0 != (options & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
01818     {
01819 #if HAVE_MESSAGES
01820       MHD_DLOG (retVal,
01821                 "Threaded operations are not supported on Symbian.\n");
01822 #endif
01823       free (retVal);
01824       return NULL;
01825     }
01826 #endif
01827   if (retVal->socket_fd == -1)
01828     {
01829       if ((options & MHD_USE_IPv6) != 0)
01830 #if HAVE_INET6
01831         socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0);
01832 #else
01833       {
01834 #if HAVE_MESSAGES
01835         MHD_DLOG (retVal, 
01836                   "AF_INET6 not supported\n");
01837 #endif
01838         free (retVal);
01839         return NULL;
01840       }
01841 #endif
01842       else
01843         socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0);
01844       if (socket_fd == -1)
01845         {
01846 #if HAVE_MESSAGES
01847           if ((options & MHD_USE_DEBUG) != 0)
01848             MHD_DLOG (retVal, 
01849                       "Call to socket failed: %s\n", 
01850                       STRERROR (errno));
01851 #endif
01852           free (retVal);
01853           return NULL;
01854         }
01855       if ((SETSOCKOPT (socket_fd,
01856                        SOL_SOCKET,
01857                        SO_REUSEADDR,
01858                        &on, sizeof (on)) < 0) && ((options & MHD_USE_DEBUG) != 0))
01859         {
01860 #if HAVE_MESSAGES
01861           MHD_DLOG (retVal, 
01862                     "setsockopt failed: %s\n", 
01863                     STRERROR (errno));
01864 #endif
01865         }
01866       
01867       /* check for user supplied sockaddr */
01868 #if HAVE_INET6
01869       if ((options & MHD_USE_IPv6) != 0)
01870         addrlen = sizeof (struct sockaddr_in6);
01871       else
01872 #endif
01873         addrlen = sizeof (struct sockaddr_in);
01874       if (NULL == servaddr)
01875         {
01876 #if HAVE_INET6
01877           if ((options & MHD_USE_IPv6) != 0)
01878             {
01879               memset (&servaddr6, 0, sizeof (struct sockaddr_in6));
01880               servaddr6.sin6_family = AF_INET6;
01881               servaddr6.sin6_port = htons (port);
01882               servaddr = (struct sockaddr *) &servaddr6;
01883             }
01884           else
01885 #endif
01886             {
01887               memset (&servaddr4, 0, sizeof (struct sockaddr_in));
01888               servaddr4.sin_family = AF_INET;
01889               servaddr4.sin_port = htons (port);
01890               servaddr = (struct sockaddr *) &servaddr4;
01891             }
01892         }
01893       retVal->socket_fd = socket_fd;
01894 
01895       if ((options & MHD_USE_IPv6) != 0)
01896         {
01897 #ifdef IPPROTO_IPV6
01898 #ifdef IPV6_V6ONLY
01899           /* Note: "IPV6_V6ONLY" is declared by Windows Vista ff., see "IPPROTO_IPV6 Socket Options" 
01900              (http://msdn.microsoft.com/en-us/library/ms738574%28v=VS.85%29.aspx); 
01901              and may also be missing on older POSIX systems; good luck if you have any of those,
01902              your IPv6 socket may then also bind against IPv4... */
01903 #ifndef WINDOWS
01904           const int on = 1;
01905           setsockopt (socket_fd, 
01906                       IPPROTO_IPV6, IPV6_V6ONLY, 
01907                       &on, sizeof (on));
01908 #else
01909           const char on = 1;
01910           setsockopt (socket_fd, 
01911                       IPPROTO_IPV6, IPV6_V6ONLY, 
01912                       &on, sizeof (on));
01913 #endif
01914 #endif
01915 #endif
01916         }
01917       if (BIND (socket_fd, servaddr, addrlen) == -1)
01918         {
01919 #if HAVE_MESSAGES
01920           if ((options & MHD_USE_DEBUG) != 0)
01921             MHD_DLOG (retVal,
01922                       "Failed to bind to port %u: %s\n", 
01923                       (unsigned int) port, 
01924                       STRERROR (errno));
01925 #endif
01926           CLOSE (socket_fd);
01927           free (retVal);
01928           return NULL;
01929         }
01930       
01931       if (LISTEN (socket_fd, 20) < 0)
01932         {
01933 #if HAVE_MESSAGES
01934           if ((options & MHD_USE_DEBUG) != 0)
01935             MHD_DLOG (retVal,
01936                       "Failed to listen for connections: %s\n", 
01937                       STRERROR (errno));
01938 #endif
01939           CLOSE (socket_fd);
01940           free (retVal);
01941           return NULL;
01942         }      
01943     }
01944   else
01945     {
01946       socket_fd = retVal->socket_fd;
01947     }
01948 #ifndef WINDOWS
01949   if ( (socket_fd >= FD_SETSIZE) &&
01950        (0 == (options & MHD_USE_POLL)) )
01951     {
01952 #if HAVE_MESSAGES
01953       if ((options & MHD_USE_DEBUG) != 0)
01954         MHD_DLOG (retVal,
01955                   "Socket descriptor larger than FD_SETSIZE: %d > %d\n",
01956                   socket_fd,
01957                   FD_SETSIZE);
01958 #endif
01959       CLOSE (socket_fd);
01960       free (retVal);
01961       return NULL;
01962     }
01963 #endif
01964 
01965   if (0 != pthread_mutex_init (&retVal->per_ip_connection_mutex, NULL))
01966     {
01967 #if HAVE_MESSAGES
01968       MHD_DLOG (retVal,
01969                "MHD failed to initialize IP connection limit mutex\n");
01970 #endif
01971       CLOSE (socket_fd);
01972       free (retVal);
01973       return NULL;
01974     }
01975 
01976 #if HTTPS_SUPPORT
01977   /* initialize HTTPS daemon certificate aspects & send / recv functions */
01978   if ((0 != (options & MHD_USE_SSL)) && (0 != MHD_TLS_init (retVal)))
01979     {
01980 #if HAVE_MESSAGES
01981       MHD_DLOG (retVal, 
01982                 "Failed to initialize TLS support\n");
01983 #endif
01984       CLOSE (socket_fd);
01985 #ifdef DAUTH_SUPPORT
01986       pthread_mutex_destroy (&retVal->nnc_lock);
01987       free (retVal->nnc);
01988 #endif
01989       pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
01990       free (retVal);
01991       return NULL;
01992     }
01993 #endif
01994   if ( ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
01995          ( (0 != (options & MHD_USE_SELECT_INTERNALLY)) &&
01996            (0 == retVal->worker_pool_size)) ) && 
01997        (0 != (res_thread_create =
01998               create_thread (&retVal->pid, retVal, &MHD_select_thread, retVal))))
01999     {
02000 #if HAVE_MESSAGES
02001       MHD_DLOG (retVal,
02002                 "Failed to create listen thread: %s\n", 
02003                 STRERROR (res_thread_create));
02004 #endif
02005 #ifdef DAUTH_SUPPORT
02006       pthread_mutex_destroy (&retVal->nnc_lock);
02007       free (retVal->nnc);
02008 #endif
02009       pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
02010       free (retVal);
02011       CLOSE (socket_fd);
02012       return NULL;
02013     }
02014   if (retVal->worker_pool_size > 0)
02015     {
02016 #ifndef MINGW
02017       int sk_flags;
02018 #else
02019       unsigned long sk_flags;
02020 #endif
02021 
02022       /* Coarse-grained count of connections per thread (note error
02023        * due to integer division). Also keep track of how many
02024        * connections are leftover after an equal split. */
02025       unsigned int conns_per_thread = retVal->max_connections
02026                                       / retVal->worker_pool_size;
02027       unsigned int leftover_conns = retVal->max_connections
02028                                     % retVal->worker_pool_size;
02029 
02030       i = 0; /* we need this in case fcntl or malloc fails */
02031 
02032       /* Accept must be non-blocking. Multiple children may wake up
02033        * to handle a new connection, but only one will win the race.
02034        * The others must immediately return. */
02035 #ifndef MINGW
02036       sk_flags = fcntl (socket_fd, F_GETFL);
02037       if (sk_flags < 0)
02038         goto thread_failed;
02039       if (fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK) < 0)
02040         goto thread_failed;
02041 #else
02042       sk_flags = 1;
02043 #if HAVE_PLIBC_FD
02044       if (ioctlsocket (plibc_fd_get_handle (socket_fd), FIONBIO, &sk_flags) ==
02045           SOCKET_ERROR)
02046 #else
02047       if (ioctlsocket (socket_fd, FIONBIO, &sk_flags) == SOCKET_ERROR)
02048 #endif // PLIBC_FD
02049         goto thread_failed;
02050 #endif // MINGW
02051 
02052       /* Allocate memory for pooled objects */
02053       retVal->worker_pool = malloc (sizeof (struct MHD_Daemon)
02054                                     * retVal->worker_pool_size);
02055       if (NULL == retVal->worker_pool)
02056         goto thread_failed;
02057 
02058       /* Start the workers in the pool */
02059       for (i = 0; i < retVal->worker_pool_size; ++i)
02060         {
02061           /* Create copy of the Daemon object for each worker */
02062           struct MHD_Daemon *d = &retVal->worker_pool[i];
02063           memcpy (d, retVal, sizeof (struct MHD_Daemon));
02064 
02065           /* Adjust pooling params for worker daemons; note that memcpy()
02066              has already copied MHD_USE_SELECT_INTERNALLY thread model into
02067              the worker threads. */
02068           d->master = retVal;
02069           d->worker_pool_size = 0;
02070           d->worker_pool = NULL;
02071 
02072           /* Divide available connections evenly amongst the threads.
02073            * Thread indexes in [0, leftover_conns) each get one of the
02074            * leftover connections. */
02075           d->max_connections = conns_per_thread;
02076           if (i < leftover_conns)
02077             ++d->max_connections;
02078 
02079           /* Spawn the worker thread */
02080           if (0 != (res_thread_create = create_thread (&d->pid, retVal, &MHD_select_thread, d)))
02081             {
02082 #if HAVE_MESSAGES
02083               MHD_DLOG (retVal,
02084                         "Failed to create pool thread: %s\n", 
02085                         STRERROR (res_thread_create));
02086 #endif
02087               /* Free memory for this worker; cleanup below handles
02088                * all previously-created workers. */
02089               goto thread_failed;
02090             }
02091         }
02092     }
02093   return retVal;
02094 
02095 thread_failed:
02096   /* If no worker threads created, then shut down normally. Calling
02097      MHD_stop_daemon (as we do below) doesn't work here since it
02098      assumes a 0-sized thread pool means we had been in the default
02099      MHD_USE_SELECT_INTERNALLY mode. */
02100   if (i == 0)
02101     {
02102       CLOSE (socket_fd);
02103       pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
02104       if (NULL != retVal->worker_pool)
02105         free (retVal->worker_pool);
02106       free (retVal);
02107       return NULL;
02108     }
02109 
02110   /* Shutdown worker threads we've already created. Pretend
02111      as though we had fully initialized our daemon, but
02112      with a smaller number of threads than had been
02113      requested. */
02114   retVal->worker_pool_size = i - 1;
02115   MHD_stop_daemon (retVal);
02116   return NULL;
02117 }
02118 
02122 static void
02123 MHD_close_connections (struct MHD_Daemon *daemon)
02124 {
02125   while (daemon->connections != NULL)
02126     {
02127       if (-1 != daemon->connections->socket_fd)
02128         {
02129 #if DEBUG_CLOSE
02130 #if HAVE_MESSAGES
02131           MHD_DLOG (daemon, "MHD shutdown, closing active connections\n");
02132 #endif
02133 #endif
02134           MHD_connection_close (daemon->connections,
02135                                 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
02136         }
02137       MHD_cleanup_connections (daemon);
02138     }
02139 }
02140 
02144 void
02145 MHD_stop_daemon (struct MHD_Daemon *daemon)
02146 {
02147   void *unused;
02148   int fd;
02149   unsigned int i;
02150   int rc;
02151 
02152   if (daemon == NULL)
02153     return;
02154   daemon->shutdown = MHD_YES;
02155   fd = daemon->socket_fd;
02156   daemon->socket_fd = -1;
02157 
02158   /* Prepare workers for shutdown */
02159   for (i = 0; i < daemon->worker_pool_size; ++i)
02160     {
02161       daemon->worker_pool[i].shutdown = MHD_YES;
02162       daemon->worker_pool[i].socket_fd = -1;
02163     }
02164 
02165 #if OSX
02166   /* without this, either (thread pool = 0) threads would get stuck or
02167    * CLOSE would get stuck if attempted before (thread pool > 0)
02168    * threads have ended */
02169   SHUTDOWN (fd, SHUT_RDWR);
02170 #else
02171 #if DEBUG_CLOSE
02172 #if HAVE_MESSAGES
02173   MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
02174 #endif
02175 #endif
02176   CLOSE (fd);
02177 #endif
02178 
02179   /* Signal workers to stop and clean them up */
02180   for (i = 0; i < daemon->worker_pool_size; ++i)
02181     pthread_kill (daemon->worker_pool[i].pid, SIGALRM);
02182   for (i = 0; i < daemon->worker_pool_size; ++i)
02183     {
02184       if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused)))
02185         {
02186 #if HAVE_MESSAGES
02187           MHD_DLOG (daemon, "Failed to join a thread: %s\n",
02188                     STRERROR (rc));
02189 #endif
02190           abort();
02191         }
02192       MHD_close_connections (&daemon->worker_pool[i]);
02193     }
02194   free (daemon->worker_pool);
02195 
02196   if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
02197       ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))
02198         && (0 == daemon->worker_pool_size)))
02199     {
02200       pthread_kill (daemon->pid, SIGALRM);
02201       if (0 != (rc = pthread_join (daemon->pid, &unused)))
02202         {
02203 #if HAVE_MESSAGES
02204           MHD_DLOG (daemon, "Failed to join a thread: %s\n",
02205                     STRERROR (rc));
02206 #endif
02207           abort();
02208         }
02209     }
02210   MHD_close_connections (daemon);
02211 
02212 #if OSX
02213 #if DEBUG_CLOSE
02214 #if HAVE_MESSAGES
02215   MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
02216 #endif
02217 #endif
02218   CLOSE (fd);
02219 #endif
02220 
02221   /* TLS clean up */
02222 #if HTTPS_SUPPORT
02223   if (daemon->options & MHD_USE_SSL)
02224     {
02225       gnutls_priority_deinit (daemon->priority_cache);
02226       if (daemon->x509_cred)
02227         gnutls_certificate_free_credentials (daemon->x509_cred);
02228       /* lock MHD_gnutls_global mutex since it uses reference counting */
02229       if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex))
02230         {
02231 #if HAVE_MESSAGES
02232           MHD_DLOG (daemon, "Failed to aquire gnutls mutex\n");
02233 #endif
02234           abort();
02235         }
02236       if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex))
02237         {
02238 #if HAVE_MESSAGES
02239           MHD_DLOG (daemon, "Failed to release gnutls mutex\n");
02240 #endif
02241           abort();
02242         }
02243     }
02244 #endif
02245 
02246 #ifdef DAUTH_SUPPORT
02247   free (daemon->nnc);
02248   pthread_mutex_destroy (&daemon->nnc_lock);
02249 #endif
02250   pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
02251   free (daemon);
02252 }
02253 
02264 const union MHD_DaemonInfo *
02265 MHD_get_daemon_info (struct MHD_Daemon *daemon,
02266                      enum MHD_DaemonInfoType infoType, ...)
02267 {
02268   switch (infoType)
02269     {
02270     case MHD_DAEMON_INFO_LISTEN_FD:
02271       return (const union MHD_DaemonInfo *) &daemon->socket_fd;
02272    default:
02273       return NULL;
02274     };
02275 }
02276 
02292 void MHD_set_panic_func (MHD_PanicCallback cb, void *cls)
02293 {
02294   mhd_panic = cb;
02295   mhd_panic_cls = cls;
02296 }
02297 
02303 const char *
02304 MHD_get_version (void)
02305 {
02306   return PACKAGE_VERSION;
02307 }
02308 
02309 #ifndef WINDOWS
02310 
02311 static struct sigaction sig;
02312 
02313 static struct sigaction old;
02314 
02315 static void
02316 sigalrmHandler (int sig)
02317 {
02318 }
02319 #endif
02320 
02321 #ifdef __GNUC__
02322 #define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor))
02323 #define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor))
02324 #else  // !__GNUC__
02325 #define ATTRIBUTE_CONSTRUCTOR
02326 #define ATTRIBUTE_DESTRUCTOR
02327 #endif  // __GNUC__
02328 
02329 #if HTTPS_SUPPORT
02330 GCRY_THREAD_OPTION_PTHREAD_IMPL;
02331 #endif
02332 
02337 void ATTRIBUTE_CONSTRUCTOR MHD_init ()
02338 {
02339   mhd_panic = &mhd_panic_std;
02340   mhd_panic_cls = NULL;
02341 
02342 #ifndef WINDOWS
02343   /* make sure SIGALRM does not kill us */
02344   memset (&sig, 0, sizeof (struct sigaction));
02345   memset (&old, 0, sizeof (struct sigaction));
02346   sig.sa_flags = SA_NODEFER;
02347   sig.sa_handler = &sigalrmHandler;
02348   sigaction (SIGALRM, &sig, &old);
02349 #else
02350   plibc_init ("GNU", "libmicrohttpd");
02351 #endif
02352 #if HTTPS_SUPPORT
02353   gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
02354   gnutls_global_init ();
02355   if (0 != pthread_mutex_init(&MHD_gnutls_init_mutex, NULL))
02356     abort();
02357 #endif
02358 }
02359 
02360 void ATTRIBUTE_DESTRUCTOR MHD_fini ()
02361 {
02362 #if HTTPS_SUPPORT
02363   gnutls_global_deinit ();
02364   if (0 != pthread_mutex_destroy(&MHD_gnutls_init_mutex))
02365     mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
02366 #endif
02367 #ifndef WINDOWS
02368   sigaction (SIGALRM, &old, &sig);
02369 #else
02370   plibc_shutdown ();
02371 #endif
02372 }
02373 
02374 /* end of daemon.c */