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