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

Generated on 16 Nov 2010 for GNU libmicrohttpd by  doxygen 1.6.1