00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00027 #include "platform.h"
00028 #include "internal.h"
00029 #include "response.h"
00030 #include "connection.h"
00031 #include "memorypool.h"
00032
00033 #if HTTPS_SUPPORT
00034 #include "connection_https.h"
00035 #include "gnutls_int.h"
00036 #include "gnutls_global.h"
00037 #endif
00038
00042 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE -4
00043
00047 #define MHD_POOL_SIZE_DEFAULT (1024 * 1024)
00048
00053 #define DEBUG_CLOSE MHD_NO
00054
00059 #define DEBUG_CONNECT MHD_NO
00060
00061 #ifndef LINUX
00062 #ifndef MSG_NOSIGNAL
00063 #define MSG_NOSIGNAL 0
00064 #endif
00065 #endif
00066
00067 #if HTTPS_SUPPORT
00068 pthread_mutex_t MHD_gnutls_init_mutex;
00069
00075 static int
00076 _set_priority (MHD_gtls_priority_st * st, const int *list)
00077 {
00078 int num = 0;
00079
00080 while ((list[num] != 0) && (num < MAX_ALGOS))
00081 num++;
00082 st->num_algorithms = num;
00083 memcpy (st->priority, list, num * sizeof (int));
00084 return 0;
00085 }
00086
00087
00096 static ssize_t
00097 recv_tls_adapter (struct MHD_Connection *connection, void *other, size_t i)
00098 {
00099 return MHD__gnutls_record_recv (connection->tls_session, other, i);
00100 }
00101
00110 static ssize_t
00111 send_tls_adapter (struct MHD_Connection *connection,
00112 const void *other, size_t i)
00113 {
00114 return MHD__gnutls_record_send (connection->tls_session, other, i);
00115 }
00116
00117
00123 static int
00124 MHD_init_daemon_certificate (struct MHD_Daemon *daemon)
00125 {
00126 MHD_gnutls_datum_t key;
00127 MHD_gnutls_datum_t cert;
00128
00129
00130 if (daemon->https_mem_cert && daemon->https_mem_key)
00131 {
00132 key.data = (unsigned char *) daemon->https_mem_key;
00133 key.size = strlen (daemon->https_mem_key);
00134 cert.data = (unsigned char *) daemon->https_mem_cert;
00135 cert.size = strlen (daemon->https_mem_cert);
00136
00137 return MHD__gnutls_certificate_set_x509_key_mem (daemon->x509_cred,
00138 &cert, &key,
00139 GNUTLS_X509_FMT_PEM);
00140 }
00141 #if HAVE_MESSAGES
00142 MHD_DLOG (daemon, "You need to specify a certificate and key location\n");
00143 #endif
00144 return -1;
00145 }
00146
00152 static int
00153 MHD_TLS_init (struct MHD_Daemon *daemon)
00154 {
00155 switch (daemon->cred_type)
00156 {
00157 case MHD_GNUTLS_CRD_CERTIFICATE:
00158 if (0 !=
00159 MHD__gnutls_certificate_allocate_credentials (&daemon->x509_cred))
00160 return GNUTLS_E_MEMORY_ERROR;
00161 return MHD_init_daemon_certificate (daemon);
00162 default:
00163 #if HAVE_MESSAGES
00164 MHD_DLOG (daemon,
00165 "Error: invalid credentials type %d specified.\n",
00166 daemon->cred_type);
00167 #endif
00168 return -1;
00169 }
00170 }
00171 #endif
00172
00180 int
00181 MHD_get_fdset (struct MHD_Daemon *daemon,
00182 fd_set * read_fd_set,
00183 fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd)
00184 {
00185 struct MHD_Connection *con_itr;
00186 int fd;
00187
00188 if ((daemon == NULL) || (read_fd_set == NULL) || (write_fd_set == NULL)
00189 || (except_fd_set == NULL) || (max_fd == NULL)
00190 || (-1 == (fd = daemon->socket_fd)) || (daemon->shutdown == MHD_YES)
00191 || ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0))
00192 return MHD_NO;
00193
00194 FD_SET (fd, read_fd_set);
00195
00196 if ((*max_fd) < fd)
00197 *max_fd = fd;
00198
00199 con_itr = daemon->connections;
00200 while (con_itr != NULL)
00201 {
00202 if (MHD_YES != MHD_connection_get_fdset (con_itr,
00203 read_fd_set,
00204 write_fd_set,
00205 except_fd_set, max_fd))
00206 return MHD_NO;
00207 con_itr = con_itr->next;
00208 }
00209 #if DEBUG_CONNECT
00210 MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
00211 #endif
00212 return MHD_YES;
00213 }
00214
00219 static void *
00220 MHD_handle_connection (void *data)
00221 {
00222 struct MHD_Connection *con = data;
00223 int num_ready;
00224 fd_set rs;
00225 fd_set ws;
00226 fd_set es;
00227 int max;
00228 struct timeval tv;
00229 unsigned int timeout;
00230 unsigned int now;
00231
00232 if (con == NULL)
00233 abort ();
00234 timeout = con->daemon->connection_timeout;
00235 while ((!con->daemon->shutdown) && (con->socket_fd != -1))
00236 {
00237 FD_ZERO (&rs);
00238 FD_ZERO (&ws);
00239 FD_ZERO (&es);
00240 max = 0;
00241 MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
00242 now = time (NULL);
00243 tv.tv_usec = 0;
00244 if (timeout > (now - con->last_activity))
00245 tv.tv_sec = timeout - (now - con->last_activity);
00246 else
00247 tv.tv_sec = 0;
00248 if ((con->state == MHD_CONNECTION_NORMAL_BODY_UNREADY) ||
00249 (con->state == MHD_CONNECTION_CHUNKED_BODY_UNREADY))
00250 {
00251
00252 timeout = 1;
00253 tv.tv_sec = 0;
00254 }
00255 num_ready = SELECT (max + 1,
00256 &rs, &ws, &es, (timeout != 0) ? &tv : NULL);
00257 if (num_ready < 0)
00258 {
00259 if (errno == EINTR)
00260 continue;
00261 #if HAVE_MESSAGES
00262 MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n", max,
00263 STRERROR (errno));
00264 #endif
00265 break;
00266 }
00267
00268 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &rs)))
00269 con->read_handler (con);
00270 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
00271 con->write_handler (con);
00272 if (con->socket_fd != -1)
00273 con->idle_handler (con);
00274 }
00275 if (con->socket_fd != -1)
00276 {
00277 #if DEBUG_CLOSE
00278 #if HAVE_MESSAGES
00279 MHD_DLOG (con->daemon,
00280 "Processing thread terminating, closing connection\n");
00281 #endif
00282 #endif
00283 MHD_connection_close (con, MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
00284 }
00285 return NULL;
00286 }
00287
00296 static ssize_t
00297 recv_param_adapter (struct MHD_Connection *connection, void *other, size_t i)
00298 {
00299 if (connection->socket_fd == -1)
00300 return -1;
00301 return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
00302 }
00303
00312 static ssize_t
00313 send_param_adapter (struct MHD_Connection *connection,
00314 const void *other, size_t i)
00315 {
00316 if (connection->socket_fd == -1)
00317 return -1;
00318 return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
00319 }
00320
00326 static int
00327 MHD_accept_connection (struct MHD_Daemon *daemon)
00328 {
00329 struct MHD_Connection *pos;
00330 struct MHD_Connection *connection;
00331 #if HAVE_INET6
00332 struct sockaddr_in6 addrstorage;
00333 #else
00334 struct sockaddr_in addrstorage;
00335 #endif
00336 struct sockaddr *addr = (struct sockaddr *) &addrstorage;
00337 socklen_t addrlen;
00338 unsigned int have;
00339 int s, res_thread_create;
00340 #if OSX
00341 static int on = 1;
00342 #endif
00343
00344 #if HAVE_INET6
00345 if (sizeof (struct sockaddr) > sizeof (struct sockaddr_in6))
00346 abort ();
00347 #endif
00348 addrlen = sizeof (addrstorage);
00349 memset (addr, 0, sizeof (addrstorage));
00350
00351 s = ACCEPT (daemon->socket_fd, addr, &addrlen);
00352
00353 if ((s < 0) || (addrlen <= 0))
00354 {
00355 #if HAVE_MESSAGES
00356 MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));
00357 #endif
00358 if (s != -1)
00359 {
00360 SHUTDOWN (s, SHUT_RDWR);
00361 CLOSE (s);
00362
00363 }
00364 return MHD_NO;
00365 }
00366 #if HAVE_MESSAGES
00367 #if DEBUG_CONNECT
00368 MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
00369 #endif
00370 #endif
00371 have = 0;
00372 if ((daemon->per_ip_connection_limit != 0) && (daemon->max_connections > 0))
00373 {
00374 pos = daemon->connections;
00375 while (pos != NULL)
00376 {
00377 if ((pos->addr != NULL) && (pos->addr_len == addrlen))
00378 {
00379 if (addrlen == sizeof (struct sockaddr_in))
00380 {
00381 const struct sockaddr_in *a1 =
00382 (const struct sockaddr_in *) addr;
00383 const struct sockaddr_in *a2 =
00384 (const struct sockaddr_in *) pos->addr;
00385 if (0 == memcmp (&a1->sin_addr, &a2->sin_addr,
00386 sizeof (struct in_addr)))
00387 have++;
00388 }
00389 #if HAVE_INET6
00390 if (addrlen == sizeof (struct sockaddr_in6))
00391 {
00392 const struct sockaddr_in6 *a1 =
00393 (const struct sockaddr_in6 *) addr;
00394 const struct sockaddr_in6 *a2 =
00395 (const struct sockaddr_in6 *) pos->addr;
00396 if (0 == memcmp (&a1->sin6_addr, &a2->sin6_addr,
00397 sizeof (struct in6_addr)))
00398 have++;
00399 }
00400 #endif
00401 }
00402 pos = pos->next;
00403 }
00404 }
00405
00406 if ((daemon->max_connections == 0) || ((daemon->per_ip_connection_limit
00407 != 0)
00408 && (daemon->per_ip_connection_limit
00409 <= have)))
00410 {
00411
00412 #if HAVE_MESSAGES
00413 MHD_DLOG (daemon,
00414 "Server reached connection limit (closing inbound connection)\n");
00415 #endif
00416 SHUTDOWN (s, SHUT_RDWR);
00417 CLOSE (s);
00418 return MHD_NO;
00419 }
00420
00421
00422 if ((daemon->apc != NULL)
00423 && (MHD_NO == daemon->apc (daemon->apc_cls, addr, addrlen)))
00424 {
00425 #if DEBUG_CLOSE
00426 #if HAVE_MESSAGES
00427 MHD_DLOG (daemon, "Connection rejected, closing connection\n");
00428 #endif
00429 #endif
00430 SHUTDOWN (s, SHUT_RDWR);
00431 CLOSE (s);
00432 return MHD_YES;
00433 }
00434 #if OSX
00435 #ifdef SOL_SOCKET
00436 #ifdef SO_NOSIGPIPE
00437 setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof (on));
00438 #endif
00439 #endif
00440 #endif
00441 connection = malloc (sizeof (struct MHD_Connection));
00442 if (connection == NULL)
00443 {
00444 #if HAVE_MESSAGES
00445 MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00446 #endif
00447 SHUTDOWN (s, SHUT_RDWR);
00448 CLOSE (s);
00449 return MHD_NO;
00450 }
00451 memset (connection, 0, sizeof (struct MHD_Connection));
00452 connection->pool = NULL;
00453 connection->addr = malloc (addrlen);
00454 if (connection->addr == NULL)
00455 {
00456 #if HAVE_MESSAGES
00457 MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00458 #endif
00459 SHUTDOWN (s, SHUT_RDWR);
00460 CLOSE (s);
00461 free (connection);
00462 return MHD_NO;
00463 }
00464 memcpy (connection->addr, addr, addrlen);
00465 connection->addr_len = addrlen;
00466 connection->socket_fd = s;
00467 connection->daemon = daemon;
00468 connection->last_activity = time (NULL);
00469
00470
00471 MHD_set_http_calbacks (connection);
00472 connection->recv_cls = &recv_param_adapter;
00473 connection->send_cls = &send_param_adapter;
00474 #if HTTPS_SUPPORT
00475 if (0 != (daemon->options & MHD_USE_SSL))
00476 {
00477 connection->recv_cls = &recv_tls_adapter;
00478 connection->send_cls = &send_tls_adapter;
00479 connection->state = MHD_TLS_CONNECTION_INIT;
00480 MHD_set_https_calbacks (connection);
00481 MHD__gnutls_init (&connection->tls_session, GNUTLS_SERVER);
00482 MHD__gnutls_priority_set (connection->tls_session,
00483 connection->daemon->priority_cache);
00484 switch (connection->daemon->cred_type)
00485 {
00486
00487 case MHD_GNUTLS_CRD_CERTIFICATE:
00488 MHD__gnutls_credentials_set (connection->tls_session,
00489 MHD_GNUTLS_CRD_CERTIFICATE,
00490 connection->daemon->x509_cred);
00491 break;
00492 default:
00493 #if HAVE_MESSAGES
00494 MHD_DLOG (connection->daemon,
00495 "Failed to setup TLS credentials: unknown credential type %d\n",
00496 connection->daemon->cred_type);
00497 #endif
00498 abort ();
00499 }
00500 MHD__gnutls_transport_set_ptr (connection->tls_session,
00501 (MHD_gnutls_transport_ptr_t) connection);
00502 MHD__gnutls_transport_set_pull_function (connection->tls_session,
00503 (MHD_gtls_pull_func) &
00504 recv_param_adapter);
00505 MHD__gnutls_transport_set_push_function (connection->tls_session,
00506 (MHD_gtls_push_func) &
00507 send_param_adapter);
00508 }
00509 #endif
00510
00511
00512 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00513 {
00514 res_thread_create = pthread_create (&connection->pid, NULL,
00515 &MHD_handle_connection, connection);
00516 if (res_thread_create != 0)
00517 {
00518 #if HAVE_MESSAGES
00519 MHD_DLOG (daemon, "Failed to create a thread: %s\n",
00520 STRERROR (errno));
00521 #endif
00522 SHUTDOWN (s, SHUT_RDWR);
00523 CLOSE (s);
00524 free (connection->addr);
00525 free (connection);
00526 return MHD_NO;
00527 }
00528 }
00529 connection->next = daemon->connections;
00530 daemon->connections = connection;
00531 daemon->max_connections--;
00532 return MHD_YES;
00533 }
00534
00540 static void
00541 MHD_cleanup_connections (struct MHD_Daemon *daemon)
00542 {
00543 struct MHD_Connection *pos;
00544 struct MHD_Connection *prev;
00545 void *unused;
00546
00547 pos = daemon->connections;
00548 prev = NULL;
00549 while (pos != NULL)
00550 {
00551 if ((pos->socket_fd == -1) ||
00552 (((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
00553 (daemon->shutdown) && (pos->socket_fd != -1))))
00554 {
00555 if (prev == NULL)
00556 daemon->connections = pos->next;
00557 else
00558 prev->next = pos->next;
00559 if (0 != (pos->daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00560 {
00561 pthread_kill (pos->pid, SIGALRM);
00562 pthread_join (pos->pid, &unused);
00563 }
00564 MHD_destroy_response (pos->response);
00565 MHD_pool_destroy (pos->pool);
00566 #if HTTPS_SUPPORT
00567 if (pos->tls_session != NULL)
00568 MHD__gnutls_deinit (pos->tls_session);
00569 #endif
00570 free (pos->addr);
00571 free (pos);
00572 daemon->max_connections++;
00573 if (prev == NULL)
00574 pos = daemon->connections;
00575 else
00576 pos = prev->next;
00577 continue;
00578 }
00579 prev = pos;
00580 pos = pos->next;
00581 }
00582 }
00583
00595 int
00596 MHD_get_timeout (struct MHD_Daemon *daemon, unsigned long long *timeout)
00597 {
00598 time_t earliest_deadline;
00599 time_t now;
00600 struct MHD_Connection *pos;
00601 unsigned int dto;
00602
00603 dto = daemon->connection_timeout;
00604 if (0 == dto)
00605 return MHD_NO;
00606 pos = daemon->connections;
00607 if (pos == NULL)
00608 return MHD_NO;
00609 now = time (NULL);
00610
00611 earliest_deadline = now + dto;
00612 while (pos != NULL)
00613 {
00614 if (earliest_deadline > pos->last_activity + dto)
00615 earliest_deadline = pos->last_activity + dto;
00616 pos = pos->next;
00617 }
00618 if (earliest_deadline < now)
00619 *timeout = 0;
00620 else
00621 *timeout = (earliest_deadline - now);
00622 return MHD_YES;
00623 }
00624
00631 static int
00632 MHD_select (struct MHD_Daemon *daemon, int may_block)
00633 {
00634 struct MHD_Connection *pos;
00635 int num_ready;
00636 fd_set rs;
00637 fd_set ws;
00638 fd_set es;
00639 int max;
00640 struct timeval timeout;
00641 unsigned long long ltimeout;
00642 int ds;
00643 time_t now;
00644
00645 timeout.tv_sec = 0;
00646 timeout.tv_usec = 0;
00647 if (daemon == NULL)
00648 abort ();
00649 if (daemon->shutdown == MHD_YES)
00650 return MHD_NO;
00651 FD_ZERO (&rs);
00652 FD_ZERO (&ws);
00653 FD_ZERO (&es);
00654 max = 0;
00655
00656 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00657 {
00658
00659 if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
00660 return MHD_NO;
00661 }
00662 else
00663 {
00664
00665 max = daemon->socket_fd;
00666 if (max == -1)
00667 return MHD_NO;
00668 FD_SET (max, &rs);
00669 }
00670
00671 if (may_block == MHD_NO)
00672 {
00673 timeout.tv_usec = 0;
00674 timeout.tv_sec = 0;
00675 }
00676 else
00677 {
00678
00679 if (MHD_YES == MHD_get_timeout (daemon, <imeout))
00680 {
00681 timeout.tv_usec = (ltimeout % 1000) * 1000;
00682 timeout.tv_sec = ltimeout / 1000;
00683 may_block = MHD_NO;
00684 }
00685 }
00686
00687 num_ready = select (max + 1, &rs, &ws, &es, may_block == MHD_NO ? &timeout
00688 : NULL);
00689
00690 if (daemon->shutdown == MHD_YES)
00691 return MHD_NO;
00692 if (num_ready < 0)
00693 {
00694 if (errno == EINTR)
00695 return MHD_YES;
00696 #if HAVE_MESSAGES
00697 MHD_DLOG (daemon, "select failed: %s\n", STRERROR (errno));
00698 #endif
00699 return MHD_NO;
00700 }
00701 ds = daemon->socket_fd;
00702 if (ds == -1)
00703 return MHD_YES;
00704
00705
00706 if (FD_ISSET (ds, &rs))
00707 MHD_accept_connection (daemon);
00708 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00709 {
00710
00711 now = time (NULL);
00712 pos = daemon->connections;
00713 while (pos != NULL)
00714 {
00715 ds = pos->socket_fd;
00716 if (ds != -1)
00717 {
00718
00719 if (FD_ISSET (ds, &rs))
00720 pos->read_handler (pos);
00721 if ((pos->socket_fd != -1) && (FD_ISSET (ds, &ws)))
00722 pos->write_handler (pos);
00723 if (pos->socket_fd != -1)
00724 pos->idle_handler (pos);
00725 }
00726 pos = pos->next;
00727 }
00728 }
00729 return MHD_YES;
00730 }
00731
00742 int
00743 MHD_run (struct MHD_Daemon *daemon)
00744 {
00745 if ((daemon->shutdown != MHD_NO) || (0 != (daemon->options
00746 & MHD_USE_THREAD_PER_CONNECTION))
00747 || (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
00748 return MHD_NO;
00749 MHD_select (daemon, MHD_NO);
00750 MHD_cleanup_connections (daemon);
00751 return MHD_YES;
00752 }
00753
00758 static void *
00759 MHD_select_thread (void *cls)
00760 {
00761 struct MHD_Daemon *daemon = cls;
00762 while (daemon->shutdown == MHD_NO)
00763 {
00764 MHD_select (daemon, MHD_YES);
00765 MHD_cleanup_connections (daemon);
00766 }
00767 return NULL;
00768 }
00769
00781 struct MHD_Daemon *
00782 MHD_start_daemon (unsigned int options,
00783 unsigned short port,
00784 MHD_AcceptPolicyCallback apc,
00785 void *apc_cls,
00786 MHD_AccessHandlerCallback dh, void *dh_cls, ...)
00787 {
00788 struct MHD_Daemon *ret;
00789 va_list ap;
00790
00791 va_start (ap, dh_cls);
00792 ret = MHD_start_daemon_va (options, port, apc, apc_cls, dh, dh_cls, ap);
00793 va_end (ap);
00794 return ret;
00795 }
00796
00808 struct MHD_Daemon *
00809 MHD_start_daemon_va (unsigned int options,
00810 unsigned short port,
00811 MHD_AcceptPolicyCallback apc,
00812 void *apc_cls,
00813 MHD_AccessHandlerCallback dh, void *dh_cls, va_list ap)
00814 {
00815 const int on = 1;
00816 struct MHD_Daemon *retVal;
00817 int socket_fd;
00818 struct sockaddr_in servaddr4;
00819 #if HAVE_INET6
00820 struct sockaddr_in6 servaddr6;
00821 #endif
00822 const struct sockaddr *servaddr = NULL;
00823 socklen_t addrlen;
00824 enum MHD_OPTION opt;
00825
00826 if ((port == 0) || (dh == NULL))
00827 return NULL;
00828 retVal = malloc (sizeof (struct MHD_Daemon));
00829 if (retVal == NULL)
00830 return NULL;
00831 memset (retVal, 0, sizeof (struct MHD_Daemon));
00832 retVal->options = options;
00833 retVal->port = port;
00834 retVal->apc = apc;
00835 retVal->apc_cls = apc_cls;
00836 retVal->default_handler = dh;
00837 retVal->default_handler_cls = dh_cls;
00838 retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
00839 retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
00840 retVal->connection_timeout = 0;
00841 #if HAVE_MESSAGES
00842 retVal->custom_error_log =
00843 (void (*)(void *, const char *, va_list)) &vfprintf;
00844 retVal->custom_error_log_cls = stderr;
00845 #endif
00846 #if HTTPS_SUPPORT
00847 if (options & MHD_USE_SSL)
00848 {
00849
00850 pthread_mutex_lock (&MHD_gnutls_init_mutex);
00851 MHD__gnutls_global_init ();
00852 pthread_mutex_unlock (&MHD_gnutls_init_mutex);
00853
00854 MHD_tls_set_default_priority (&retVal->priority_cache, "", NULL);
00855 retVal->cred_type = MHD_GNUTLS_CRD_CERTIFICATE;
00856 }
00857 #endif
00858
00859 while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
00860 {
00861 switch (opt)
00862 {
00863 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
00864 retVal->pool_size = va_arg (ap, size_t);
00865 break;
00866 case MHD_OPTION_CONNECTION_LIMIT:
00867 retVal->max_connections = va_arg (ap, unsigned int);
00868 break;
00869 case MHD_OPTION_CONNECTION_TIMEOUT:
00870 retVal->connection_timeout = va_arg (ap, unsigned int);
00871 break;
00872 case MHD_OPTION_NOTIFY_COMPLETED:
00873 retVal->notify_completed =
00874 va_arg (ap, MHD_RequestCompletedCallback);
00875 retVal->notify_completed_cls = va_arg (ap, void *);
00876 break;
00877 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
00878 retVal->per_ip_connection_limit = va_arg (ap, unsigned int);
00879 break;
00880 case MHD_OPTION_SOCK_ADDR:
00881 servaddr = va_arg (ap, struct sockaddr *);
00882 break;
00883 case MHD_OPTION_URI_LOG_CALLBACK:
00884 retVal->uri_log_callback =
00885 va_arg (ap, LogCallback);
00886 retVal->uri_log_callback_cls = va_arg (ap, void *);
00887 break;
00888 #if HTTPS_SUPPORT
00889 case MHD_OPTION_PROTOCOL_VERSION:
00890 _set_priority (&retVal->priority_cache->protocol,
00891 va_arg (ap, const int *));
00892 break;
00893 case MHD_OPTION_HTTPS_MEM_KEY:
00894 retVal->https_mem_key = va_arg (ap, const char *);
00895 break;
00896 case MHD_OPTION_HTTPS_MEM_CERT:
00897 retVal->https_mem_cert = va_arg (ap, const char *);
00898 break;
00899 case MHD_OPTION_CIPHER_ALGORITHM:
00900 _set_priority (&retVal->priority_cache->cipher,
00901 va_arg (ap, const int *));
00902 break;
00903 #endif
00904 case MHD_OPTION_EXTERNAL_LOGGER:
00905 #if HAVE_MESSAGES
00906 retVal->custom_error_log =
00907 va_arg (ap, void (*)(void *cls, const char *, va_list));
00908 retVal->custom_error_log_cls = va_arg (ap, void *);
00909 #else
00910 va_arg (ap, void (*)(void *cls, const char *, ...));
00911 va_arg (ap, void *);
00912 #endif
00913 break;
00914 default:
00915 #if HAVE_MESSAGES
00916 if ((opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
00917 (opt <= MHD_OPTION_CIPHER_ALGORITHM))
00918 {
00919 FPRINTF (stderr,
00920 "MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
00921 opt);
00922 }
00923 else
00924 {
00925 FPRINTF (stderr,
00926 "Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
00927 opt);
00928 }
00929 #endif
00930 abort ();
00931 }
00932 }
00933
00934 if ((options & MHD_USE_IPv6) != 0)
00935 #if HAVE_INET6
00936 socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0);
00937 #else
00938 {
00939 #if HAVE_MESSAGES
00940 FPRINTF (stderr, "AF_INET6 not supported\n");
00941 #endif
00942 return NULL;
00943 }
00944 #endif
00945 else
00946 socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0);
00947 if (socket_fd < 0)
00948 {
00949 #if HAVE_MESSAGES
00950 if ((options & MHD_USE_DEBUG) != 0)
00951 FPRINTF (stderr, "Call to socket failed: %s\n", STRERROR (errno));
00952 #endif
00953 free (retVal);
00954 return NULL;
00955 }
00956 if ((SETSOCKOPT (socket_fd,
00957 SOL_SOCKET,
00958 SO_REUSEADDR,
00959 &on, sizeof (on)) < 0) && (options & MHD_USE_DEBUG) != 0)
00960 {
00961 #if HAVE_MESSAGES
00962 FPRINTF (stderr, "setsockopt failed: %s\n", STRERROR (errno));
00963 #endif
00964 }
00965
00966
00967 #if HAVE_INET6
00968 if ((options & MHD_USE_IPv6) != 0)
00969 addrlen = sizeof (struct sockaddr_in6);
00970 else
00971 #endif
00972 addrlen = sizeof (struct sockaddr_in);
00973 if (NULL == servaddr)
00974 {
00975 #if HAVE_INET6
00976 if ((options & MHD_USE_IPv6) != 0)
00977 {
00978 memset (&servaddr6, 0, sizeof (struct sockaddr_in6));
00979 servaddr6.sin6_family = AF_INET6;
00980 servaddr6.sin6_port = htons (port);
00981 servaddr = (struct sockaddr *) &servaddr6;
00982 }
00983 else
00984 #endif
00985 {
00986 memset (&servaddr4, 0, sizeof (struct sockaddr_in));
00987 servaddr4.sin_family = AF_INET;
00988 servaddr4.sin_port = htons (port);
00989 servaddr = (struct sockaddr *) &servaddr4;
00990 }
00991 }
00992 retVal->socket_fd = socket_fd;
00993 if (BIND (socket_fd, servaddr, addrlen) < 0)
00994 {
00995 #if HAVE_MESSAGES
00996 if ((options & MHD_USE_DEBUG) != 0)
00997 FPRINTF (stderr,
00998 "Failed to bind to port %u: %s\n", port, STRERROR (errno));
00999 #endif
01000 CLOSE (socket_fd);
01001 free (retVal);
01002 return NULL;
01003 }
01004
01005
01006 if (LISTEN (socket_fd, 20) < 0)
01007 {
01008 #if HAVE_MESSAGES
01009 if ((options & MHD_USE_DEBUG) != 0)
01010 FPRINTF (stderr,
01011 "Failed to listen for connections: %s\n", STRERROR (errno));
01012 #endif
01013 CLOSE (socket_fd);
01014 free (retVal);
01015 return NULL;
01016 }
01017
01018 #if HTTPS_SUPPORT
01019
01020 if ((0 != (options & MHD_USE_SSL)) && (0 != MHD_TLS_init (retVal)))
01021 {
01022 #if HAVE_MESSAGES
01023 MHD_DLOG (retVal, "Failed to initialize TLS support\n");
01024 #endif
01025 CLOSE (socket_fd);
01026 free (retVal);
01027 return NULL;
01028 }
01029 #endif
01030 if (((0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
01031 (0 != (options & MHD_USE_SELECT_INTERNALLY)))
01032 && (0 !=
01033 pthread_create (&retVal->pid, NULL, &MHD_select_thread, retVal)))
01034 {
01035 #if HAVE_MESSAGES
01036 MHD_DLOG (retVal,
01037 "Failed to create listen thread: %s\n", STRERROR (errno));
01038 #endif
01039 free (retVal);
01040 CLOSE (socket_fd);
01041 return NULL;
01042 }
01043 return retVal;
01044 }
01045
01049 void
01050 MHD_stop_daemon (struct MHD_Daemon *daemon)
01051 {
01052 void *unused;
01053 int fd;
01054
01055 if (daemon == NULL)
01056 return;
01057 daemon->shutdown = MHD_YES;
01058 fd = daemon->socket_fd;
01059 daemon->socket_fd = -1;
01060 #if DEBUG_CLOSE
01061 #if HAVE_MESSAGES
01062 MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
01063 #endif
01064 #endif
01065 CLOSE (fd);
01066 if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
01067 (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
01068 {
01069 pthread_kill (daemon->pid, SIGALRM);
01070 pthread_join (daemon->pid, &unused);
01071 }
01072 while (daemon->connections != NULL)
01073 {
01074 if (-1 != daemon->connections->socket_fd)
01075 {
01076 #if DEBUG_CLOSE
01077 #if HAVE_MESSAGES
01078 MHD_DLOG (daemon, "MHD shutdown, closing active connections\n");
01079 #endif
01080 #endif
01081 MHD_connection_close (daemon->connections,
01082 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
01083 }
01084 MHD_cleanup_connections (daemon);
01085 }
01086
01087
01088 #if HTTPS_SUPPORT
01089 if (daemon->options & MHD_USE_SSL)
01090 {
01091 MHD__gnutls_priority_deinit (daemon->priority_cache);
01092 if (daemon->x509_cred)
01093 MHD__gnutls_certificate_free_credentials (daemon->x509_cred);
01094
01095 pthread_mutex_lock (&MHD_gnutls_init_mutex);
01096 MHD__gnutls_global_deinit ();
01097 pthread_mutex_unlock (&MHD_gnutls_init_mutex);
01098 }
01099 #endif
01100 free (daemon);
01101 }
01102
01113 const union MHD_DaemonInfo *
01114 MHD_get_daemon_info (struct MHD_Daemon *daemon,
01115 enum MHD_DaemonInfoType infoType, ...)
01116 {
01117 return NULL;
01118 }
01119
01120 #ifndef WINDOWS
01121
01122 static struct sigaction sig;
01123
01124 static struct sigaction old;
01125
01126 static void
01127 sigalrmHandler (int sig)
01128 {
01129 }
01130 #endif
01131
01136 void __attribute__ ((constructor)) MHD_init ()
01137 {
01138 #ifndef WINDOWS
01139
01140 memset (&sig, 0, sizeof (struct sigaction));
01141 memset (&old, 0, sizeof (struct sigaction));
01142 sig.sa_flags = SA_NODEFER;
01143 sig.sa_handler = &sigalrmHandler;
01144 sigaction (SIGALRM, &sig, &old);
01145 #else
01146 plibc_init ("CRISP", "libmicrohttpd");
01147 #endif
01148 #if HTTPS_SUPPORT
01149 if (0 != pthread_mutex_init(&MHD_gnutls_init_mutex, NULL))
01150 abort();
01151 #endif
01152 }
01153
01154 void __attribute__ ((destructor)) MHD_fini ()
01155 {
01156 #if HTTPS_SUPPORT
01157 if (0 != pthread_mutex_destroy(&MHD_gnutls_init_mutex))
01158 abort ();
01159 #endif
01160 #ifndef WINDOWS
01161 sigaction (SIGALRM, &old, &sig);
01162 #else
01163 plibc_shutdown ();
01164 #endif
01165 }
01166
01167