00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00028 #include "internal.h"
00029 #include "response.h"
00030 #include "connection.h"
00031 #include "memorypool.h"
00032
00036 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE -4
00037
00041 #define MHD_POOL_SIZE_DEFAULT (1024 * 1024)
00042
00047 #define DEBUG_CLOSE MHD_NO
00048
00053 #define DEBUG_CONNECT MHD_NO
00054
00055
00063 int
00064 MHD_get_fdset (struct MHD_Daemon *daemon,
00065 fd_set * read_fd_set,
00066 fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd)
00067 {
00068 struct MHD_Connection *pos;
00069 int fd;
00070
00071 if ((daemon == NULL) ||
00072 (read_fd_set == NULL) ||
00073 (write_fd_set == NULL) ||
00074 (except_fd_set == NULL) ||
00075 (max_fd == NULL) ||
00076 (-1 == (fd = daemon->socket_fd)) ||
00077 (daemon->shutdown == MHD_YES) ||
00078 ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0))
00079 return MHD_NO;
00080 FD_SET (fd, read_fd_set);
00081 if ((*max_fd) < fd)
00082 *max_fd = fd;
00083 pos = daemon->connections;
00084 while (pos != NULL)
00085 {
00086 if (MHD_YES != MHD_connection_get_fdset (pos,
00087 read_fd_set,
00088 write_fd_set,
00089 except_fd_set, max_fd))
00090 return MHD_NO;
00091 pos = pos->next;
00092 }
00093 #if DEBUG_CONNECT
00094 MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
00095 #endif
00096 return MHD_YES;
00097 }
00098
00103 static void *
00104 MHD_handle_connection (void *data)
00105 {
00106 struct MHD_Connection *con = data;
00107 int num_ready;
00108 fd_set rs;
00109 fd_set ws;
00110 fd_set es;
00111 int max;
00112 struct timeval tv;
00113 unsigned int timeout;
00114 unsigned int now;
00115
00116 if (con == NULL)
00117 abort ();
00118 timeout = con->daemon->connection_timeout;
00119 while ((!con->daemon->shutdown) && (con->socket_fd != -1))
00120 {
00121 FD_ZERO (&rs);
00122 FD_ZERO (&ws);
00123 FD_ZERO (&es);
00124 max = 0;
00125 MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
00126 now = time (NULL);
00127 tv.tv_usec = 0;
00128 if (timeout > (now - con->last_activity))
00129 tv.tv_sec = timeout - (now - con->last_activity);
00130 else
00131 tv.tv_sec = 0;
00132 num_ready = SELECT (max + 1,
00133 &rs, &ws, &es, (timeout != 0) ? &tv : NULL);
00134 if (num_ready < 0)
00135 {
00136 if (errno == EINTR)
00137 continue;
00138 #if HAVE_MESSAGES
00139 MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n",
00140 max, STRERROR (errno));
00141 #endif
00142 break;
00143 }
00144 if (FD_ISSET (con->socket_fd, &rs))
00145 MHD_connection_handle_read (con);
00146 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
00147 MHD_connection_handle_write (con);
00148 if (con->socket_fd != -1)
00149 MHD_connection_handle_idle (con);
00150 }
00151 if (con->socket_fd != -1)
00152 {
00153 #if DEBUG_CLOSE
00154 #if HAVE_MESSAGES
00155 MHD_DLOG (con->daemon,
00156 "Processing thread terminating, closing connection\n");
00157 #endif
00158 #endif
00159 SHUTDOWN (con->socket_fd, SHUT_RDWR);
00160 CLOSE (con->socket_fd);
00161 con->socket_fd = -1;
00162 }
00163 return NULL;
00164 }
00165
00166
00172 static int
00173 MHD_accept_connection (struct MHD_Daemon *daemon)
00174 {
00175 struct MHD_Connection *pos;
00176 struct MHD_Connection *connection;
00177 struct sockaddr_in6 addr6;
00178 struct sockaddr *addr = (struct sockaddr *) &addr6;
00179 socklen_t addrlen;
00180 unsigned int have;
00181 int s;
00182 #if OSX
00183 static int on = 1;
00184 #endif
00185
00186
00187 if (sizeof (struct sockaddr) > sizeof (struct sockaddr_in6))
00188 abort ();
00189 addrlen = sizeof (struct sockaddr_in6);
00190 memset (addr, 0, sizeof (struct sockaddr_in6));
00191 s = ACCEPT (daemon->socket_fd, addr, &addrlen);
00192 if ((s < 0) || (addrlen <= 0))
00193 {
00194 #if HAVE_MESSAGES
00195 MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));
00196 #endif
00197 if (s != -1)
00198 {
00199 SHUTDOWN (s, SHUT_RDWR);
00200 CLOSE (s);
00201 }
00202 return MHD_NO;
00203 }
00204 #if DEBUG_CONNECT
00205 MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
00206 #endif
00207 have = 0;
00208 if ((daemon->per_ip_connection_limit != 0) && (daemon->max_connections > 0))
00209 {
00210 pos = daemon->connections;
00211 while (pos != NULL)
00212 {
00213 if ((pos->addr != NULL) && (pos->addr_len == addrlen))
00214 {
00215 if (addrlen == sizeof (struct sockaddr_in))
00216 {
00217 const struct sockaddr_in *a1 =
00218 (const struct sockaddr_in *) &addr;
00219 const struct sockaddr_in *a2 =
00220 (const struct sockaddr_in *) pos->addr;
00221 if (0 ==
00222 memcmp (&a1->sin_addr, &a2->sin_addr,
00223 sizeof (struct in_addr)))
00224 have++;
00225 }
00226 if (addrlen == sizeof (struct sockaddr_in6))
00227 {
00228 const struct sockaddr_in6 *a1 =
00229 (const struct sockaddr_in6 *) &addr;
00230 const struct sockaddr_in6 *a2 =
00231 (const struct sockaddr_in6 *) pos->addr;
00232 if (0 ==
00233 memcmp (&a1->sin6_addr, &a2->sin6_addr,
00234 sizeof (struct in6_addr)))
00235 have++;
00236 }
00237 }
00238 pos = pos->next;
00239 }
00240 }
00241
00242 if ((daemon->max_connections == 0) ||
00243 ((daemon->per_ip_connection_limit != 0) &&
00244 (daemon->per_ip_connection_limit <= have)))
00245 {
00246
00247 #if HAVE_MESSAGES
00248 MHD_DLOG (daemon,
00249 "Server reached connection limit (closing inbound connection)\n");
00250 #endif
00251 SHUTDOWN (s, SHUT_RDWR);
00252 CLOSE (s);
00253 return MHD_NO;
00254 }
00255 if ((daemon->apc != NULL) &&
00256 (MHD_NO == daemon->apc (daemon->apc_cls, addr, addrlen)))
00257 {
00258 #if DEBUG_CLOSE
00259 #if HAVE_MESSAGES
00260 MHD_DLOG (daemon, "Connection rejected, closing connection\n");
00261 #endif
00262 #endif
00263 SHUTDOWN (s, SHUT_RDWR);
00264 CLOSE (s);
00265 return MHD_YES;
00266 }
00267 #if OSX
00268 #ifdef SOL_SOCKET
00269 #ifdef SO_NOSIGPIPE
00270 setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof (on));
00271 #endif
00272 #endif
00273 #endif
00274 connection = malloc (sizeof (struct MHD_Connection));
00275 if (connection == NULL)
00276 {
00277 #if HAVE_MESSAGES
00278 MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00279 #endif
00280 SHUTDOWN (s, SHUT_RDWR);
00281 CLOSE (s);
00282 return MHD_NO;
00283 }
00284 memset (connection, 0, sizeof (struct MHD_Connection));
00285 connection->pool = NULL;
00286 connection->addr = malloc (addrlen);
00287 if (connection->addr == NULL)
00288 {
00289 #if HAVE_MESSAGES
00290 MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00291 #endif
00292 SHUTDOWN (s, SHUT_RDWR);
00293 CLOSE (s);
00294 free (connection);
00295 return MHD_NO;
00296 }
00297 memcpy (connection->addr, addr, addrlen);
00298 connection->addr_len = addrlen;
00299 connection->socket_fd = s;
00300 connection->daemon = daemon;
00301 if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
00302 (0 != pthread_create (&connection->pid,
00303 NULL, &MHD_handle_connection, connection)))
00304 {
00305 #if HAVE_MESSAGES
00306 MHD_DLOG (daemon, "Failed to create a thread: %s\n", STRERROR (errno));
00307 #endif
00308 SHUTDOWN (s, SHUT_RDWR);
00309 CLOSE (s);
00310 free (connection->addr);
00311 free (connection);
00312 return MHD_NO;
00313 }
00314 connection->last_activity = time (NULL);
00315 connection->next = daemon->connections;
00316 daemon->connections = connection;
00317 daemon->max_connections--;
00318 return MHD_YES;
00319 }
00320
00321
00327 static void
00328 MHD_cleanup_connections (struct MHD_Daemon *daemon)
00329 {
00330 struct MHD_Connection *pos;
00331 struct MHD_Connection *prev;
00332 void *unused;
00333
00334 pos = daemon->connections;
00335 prev = NULL;
00336 while (pos != NULL)
00337 {
00338 if (pos->socket_fd == -1)
00339 {
00340 if (prev == NULL)
00341 daemon->connections = pos->next;
00342 else
00343 prev->next = pos->next;
00344 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00345 {
00346 pthread_kill (pos->pid, SIGALRM);
00347 pthread_join (pos->pid, &unused);
00348 }
00349 MHD_destroy_response (pos->response);
00350 MHD_pool_destroy (pos->pool);
00351 free (pos->addr);
00352 free (pos);
00353 daemon->max_connections++;
00354 if (prev == NULL)
00355 pos = daemon->connections;
00356 else
00357 pos = prev->next;
00358 continue;
00359 }
00360 prev = pos;
00361 pos = pos->next;
00362 }
00363 }
00364
00376 int
00377 MHD_get_timeout (struct MHD_Daemon *daemon, unsigned long long *timeout)
00378 {
00379 time_t earliest_deadline;
00380 time_t now;
00381 struct MHD_Connection *pos;
00382 unsigned int dto;
00383
00384 dto = daemon->connection_timeout;
00385 if (0 == dto)
00386 return MHD_NO;
00387 pos = daemon->connections;
00388 if (pos == NULL)
00389 return MHD_NO;
00390 now = time (NULL);
00391
00392 earliest_deadline = now + dto;
00393 while (pos != NULL)
00394 {
00395 if (earliest_deadline > pos->last_activity + dto)
00396 earliest_deadline = pos->last_activity + dto;
00397 pos = pos->next;
00398 }
00399 if (earliest_deadline < now)
00400 *timeout = 0;
00401 else
00402 *timeout = (earliest_deadline - now);
00403 return MHD_YES;
00404 }
00405
00412 static int
00413 MHD_select (struct MHD_Daemon *daemon, int may_block)
00414 {
00415 struct MHD_Connection *pos;
00416 int num_ready;
00417 fd_set rs;
00418 fd_set ws;
00419 fd_set es;
00420 int max;
00421 struct timeval timeout;
00422 unsigned long long ltimeout;
00423 int ds;
00424 time_t now;
00425
00426 timeout.tv_sec = 0;
00427 timeout.tv_usec = 0;
00428 if (daemon == NULL)
00429 abort ();
00430 if (daemon->shutdown == MHD_YES)
00431 return MHD_NO;
00432 FD_ZERO (&rs);
00433 FD_ZERO (&ws);
00434 FD_ZERO (&es);
00435 max = 0;
00436
00437 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00438 {
00439
00440 if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
00441 return MHD_NO;
00442 }
00443 else
00444 {
00445
00446 max = daemon->socket_fd;
00447 if (max == -1)
00448 return MHD_NO;
00449 FD_SET (max, &rs);
00450 }
00451 if (may_block == MHD_NO)
00452 {
00453 timeout.tv_usec = 0;
00454 timeout.tv_sec = 0;
00455 }
00456 else
00457 {
00458
00459 if (MHD_YES == MHD_get_timeout (daemon, <imeout))
00460 {
00461 timeout.tv_usec = (ltimeout % 1000) * 1000;
00462 timeout.tv_sec = ltimeout / 1000;
00463 may_block = MHD_NO;
00464 }
00465 }
00466 num_ready = SELECT (max + 1,
00467 &rs, &ws, &es, may_block == MHD_NO ? &timeout : NULL);
00468 if (daemon->shutdown == MHD_YES)
00469 return MHD_NO;
00470 if (num_ready < 0)
00471 {
00472 if (errno == EINTR)
00473 return MHD_YES;
00474 #if HAVE_MESSAGES
00475 MHD_DLOG (daemon, "Select failed: %s\n", STRERROR (errno));
00476 #endif
00477 return MHD_NO;
00478 }
00479 ds = daemon->socket_fd;
00480 if (ds == -1)
00481 return MHD_YES;
00482 if (FD_ISSET (ds, &rs))
00483 MHD_accept_connection (daemon);
00484 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00485 {
00486
00487 now = time (NULL);
00488 pos = daemon->connections;
00489 while (pos != NULL)
00490 {
00491 ds = pos->socket_fd;
00492 if (ds != -1)
00493 {
00494 if (FD_ISSET (ds, &rs))
00495 MHD_connection_handle_read (pos);
00496 if ((pos->socket_fd != -1) && (FD_ISSET (ds, &ws)))
00497 MHD_connection_handle_write (pos);
00498 if (pos->socket_fd != -1)
00499 MHD_connection_handle_idle (pos);
00500 }
00501 pos = pos->next;
00502 }
00503 }
00504 return MHD_YES;
00505 }
00506
00507
00518 int
00519 MHD_run (struct MHD_Daemon *daemon)
00520 {
00521 if ((daemon->shutdown != MHD_NO) ||
00522 (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
00523 (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
00524 return MHD_NO;
00525 MHD_select (daemon, MHD_NO);
00526 MHD_cleanup_connections (daemon);
00527 return MHD_YES;
00528 }
00529
00530
00535 static void *
00536 MHD_select_thread (void *cls)
00537 {
00538 struct MHD_Daemon *daemon = cls;
00539 while (daemon->shutdown == MHD_NO)
00540 {
00541 MHD_select (daemon, MHD_YES);
00542 MHD_cleanup_connections (daemon);
00543 }
00544 return NULL;
00545 }
00546
00547
00559 struct MHD_Daemon *
00560 MHD_start_daemon (unsigned int options,
00561 unsigned short port,
00562 MHD_AcceptPolicyCallback apc,
00563 void *apc_cls,
00564 MHD_AccessHandlerCallback dh, void *dh_cls, ...)
00565 {
00566 const int on = 1;
00567 struct MHD_Daemon *retVal;
00568 int socket_fd;
00569 struct sockaddr_in servaddr4;
00570 struct sockaddr_in6 servaddr6;
00571 const struct sockaddr *servaddr;
00572 socklen_t addrlen;
00573 va_list ap;
00574 enum MHD_OPTION opt;
00575
00576 if ((options & MHD_USE_SSL) != 0)
00577 return NULL;
00578 if ((port == 0) || (dh == NULL))
00579 return NULL;
00580 if ((options & MHD_USE_IPv6) != 0)
00581 socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0);
00582 else
00583 socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0);
00584 if (socket_fd < 0)
00585 {
00586 #if HAVE_MESSAGES
00587 if ((options & MHD_USE_DEBUG) != 0)
00588 fprintf (stderr, "Call to socket failed: %s\n", STRERROR (errno));
00589 #endif
00590 return NULL;
00591 }
00592 if ((SETSOCKOPT (socket_fd,
00593 SOL_SOCKET,
00594 SO_REUSEADDR,
00595 &on, sizeof (on)) < 0) && (options & MHD_USE_DEBUG) != 0)
00596 {
00597 #if HAVE_MESSAGES
00598 fprintf (stderr, "setsockopt failed: %s\n", STRERROR (errno));
00599 #endif
00600 }
00601 if ((options & MHD_USE_IPv6) != 0)
00602 {
00603 memset (&servaddr6, 0, sizeof (struct sockaddr_in6));
00604 servaddr6.sin6_family = AF_INET6;
00605 servaddr6.sin6_port = htons (port);
00606 servaddr = (struct sockaddr *) &servaddr6;
00607 addrlen = sizeof (struct sockaddr_in6);
00608 }
00609 else
00610 {
00611 memset (&servaddr4, 0, sizeof (struct sockaddr_in));
00612 servaddr4.sin_family = AF_INET;
00613 servaddr4.sin_port = htons (port);
00614 servaddr = (struct sockaddr *) &servaddr4;
00615 addrlen = sizeof (struct sockaddr_in);
00616 }
00617 if (BIND (socket_fd, servaddr, addrlen) < 0)
00618 {
00619 #if HAVE_MESSAGES
00620 if ((options & MHD_USE_DEBUG) != 0)
00621 fprintf (stderr,
00622 "Failed to bind to port %u: %s\n", port, STRERROR (errno));
00623 #endif
00624 CLOSE (socket_fd);
00625 return NULL;
00626 }
00627 if (LISTEN (socket_fd, 20) < 0)
00628 {
00629 #if HAVE_MESSAGES
00630 if ((options & MHD_USE_DEBUG) != 0)
00631 fprintf (stderr,
00632 "Failed to listen for connections: %s\n", STRERROR (errno));
00633 #endif
00634 CLOSE (socket_fd);
00635 return NULL;
00636 }
00637 retVal = malloc (sizeof (struct MHD_Daemon));
00638 if (retVal == NULL)
00639 {
00640 CLOSE (socket_fd);
00641 return NULL;
00642 }
00643 memset (retVal, 0, sizeof (struct MHD_Daemon));
00644 retVal->options = options;
00645 retVal->port = port;
00646 retVal->apc = apc;
00647 retVal->apc_cls = apc_cls;
00648 retVal->socket_fd = socket_fd;
00649 retVal->default_handler = dh;
00650 retVal->default_handler_cls = dh_cls;
00651 retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
00652 retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
00653 retVal->connection_timeout = 0;
00654 va_start (ap, dh_cls);
00655 while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
00656 {
00657 switch (opt)
00658 {
00659 case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
00660 retVal->pool_size = va_arg (ap, unsigned int);
00661 break;
00662 case MHD_OPTION_CONNECTION_LIMIT:
00663 retVal->max_connections = va_arg (ap, unsigned int);
00664 break;
00665 case MHD_OPTION_CONNECTION_TIMEOUT:
00666 retVal->connection_timeout = va_arg (ap, unsigned int);
00667 break;
00668 case MHD_OPTION_NOTIFY_COMPLETED:
00669 retVal->notify_completed =
00670 va_arg (ap, MHD_RequestCompletedCallback);
00671 retVal->notify_completed_cls = va_arg (ap, void *);
00672 break;
00673 case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
00674 retVal->per_ip_connection_limit = va_arg (ap, unsigned int);
00675 break;
00676 default:
00677 #if HAVE_MESSAGES
00678 fprintf (stderr,
00679 "Invalid MHD_OPTION argument! (Did you terminate the list with MHD_OPTION_END?)\n");
00680 #endif
00681 abort ();
00682 }
00683 }
00684 va_end (ap);
00685 if (((0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
00686 (0 != (options & MHD_USE_SELECT_INTERNALLY))) &&
00687 (0 != pthread_create (&retVal->pid, NULL, &MHD_select_thread, retVal)))
00688 {
00689 #if HAVE_MESSAGES
00690 MHD_DLOG (retVal,
00691 "Failed to create listen thread: %s\n", STRERROR (errno));
00692 #endif
00693 free (retVal);
00694 CLOSE (socket_fd);
00695 return NULL;
00696 }
00697 return retVal;
00698 }
00699
00703 void
00704 MHD_stop_daemon (struct MHD_Daemon *daemon)
00705 {
00706 void *unused;
00707 int fd;
00708
00709 if (daemon == NULL)
00710 return;
00711 daemon->shutdown = MHD_YES;
00712 fd = daemon->socket_fd;
00713 daemon->socket_fd = -1;
00714 #if DEBUG_CLOSE
00715 #if HAVE_MESSAGES
00716 MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
00717 #endif
00718 #endif
00719 CLOSE (fd);
00720 if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
00721 (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
00722 {
00723 pthread_kill (daemon->pid, SIGALRM);
00724 pthread_join (daemon->pid, &unused);
00725 }
00726 while (daemon->connections != NULL)
00727 {
00728 if (-1 != daemon->connections->socket_fd)
00729 {
00730 #if DEBUG_CLOSE
00731 #if HAVE_MESSAGES
00732 MHD_DLOG (daemon, "MHD shutdown, closing active connections\n");
00733 #endif
00734 #endif
00735 if (daemon->notify_completed != NULL)
00736 daemon->notify_completed (daemon->notify_completed_cls,
00737 daemon->connections,
00738 &daemon->connections->client_context,
00739 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
00740 SHUTDOWN (daemon->connections->socket_fd, SHUT_RDWR);
00741 CLOSE (daemon->connections->socket_fd);
00742 daemon->connections->socket_fd = -1;
00743 }
00744 MHD_cleanup_connections (daemon);
00745 }
00746 free (daemon);
00747 }
00748
00749 #ifndef WINDOWS
00750
00751 static struct sigaction sig;
00752
00753 static struct sigaction old;
00754
00755 static void
00756 sigalrmHandler (int sig)
00757 {
00758 }
00759
00763 void __attribute__ ((constructor)) MHD_pthread_handlers_ltdl_init ()
00764 {
00765
00766 memset (&sig, 0, sizeof (struct sigaction));
00767 memset (&old, 0, sizeof (struct sigaction));
00768 sig.sa_flags = SA_NODEFER;
00769 sig.sa_handler = &sigalrmHandler;
00770 sigaction (SIGALRM, &sig, &old);
00771 }
00772
00773 void __attribute__ ((destructor)) MHD_pthread_handlers_ltdl_fini ()
00774 {
00775 sigaction (SIGALRM, &old, &sig);
00776 }
00777 #else
00778 void __attribute__ ((constructor)) MHD_win_ltdl_init ()
00779 {
00780 plibc_init ("CRISP", "libmicrohttpd");
00781 }
00782
00783 void __attribute__ ((destructor)) MHD_win_ltdl_fini ()
00784 {
00785 plibc_shutdown ();
00786 }
00787 #endif
00788
00789