📄 daemon.c
字号:
if ((pos->headersReceived == 1) && (pos->response == NULL)) MHD_call_connection_handler (pos); prev = pos; pos = pos->next; }}/** * Main select call. * * @param may_block YES if blocking, NO if non-blocking * @return MHD_NO on serious errors, MHD_YES on success */static intMHD_select (struct MHD_Daemon *daemon, int may_block){ struct MHD_Connection *pos; int num_ready; fd_set rs; fd_set ws; fd_set es; int max; struct timeval timeout; int ds; timeout.tv_sec = 0; timeout.tv_usec = 0; if (daemon == NULL) abort (); FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); max = 0; if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) { /* single-threaded, go over everything */ if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max)) return MHD_NO; } else { /* accept only, have one thread per connection */ max = daemon->socket_fd; FD_SET (daemon->socket_fd, &rs); } num_ready = SELECT (max + 1, &rs, &ws, &es, may_block == MHD_NO ? &timeout : NULL); if (num_ready < 0) { if (errno == EINTR) return MHD_YES; MHD_DLOG (daemon, "Select failed: %s\n", STRERROR (errno)); return MHD_NO; } ds = daemon->socket_fd; if (ds == -1) return MHD_YES; if (FD_ISSET (ds, &rs)) MHD_accept_connection (daemon); if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) { /* do not have a thread per connection, process all connections now */ pos = daemon->connections; while (pos != NULL) { ds = pos->socket_fd; if (ds == -1) { pos = pos->next; continue; } if (FD_ISSET (ds, &rs)) MHD_connection_handle_read (pos); if (FD_ISSET (ds, &ws)) MHD_connection_handle_write (pos); pos = pos->next; } } return MHD_YES;}/** * Run webserver operations (without blocking unless * in client callbacks). This method should be called * by clients in combination with MHD_get_fdset * if the client-controlled select method is used. * * @return MHD_YES on success, MHD_NO if this * daemon was not started with the right * options for this call. */intMHD_run (struct MHD_Daemon *daemon){ if ((daemon->shutdown != 0) || (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))) return MHD_NO; MHD_select (daemon, MHD_NO); MHD_cleanup_connections (daemon); return MHD_YES;}/** * Thread that runs the select loop until the daemon * is explicitly shut down. */static void *MHD_select_thread (void *cls){ struct MHD_Daemon *daemon = cls; while (daemon->shutdown == 0) { MHD_select (daemon, MHD_YES); MHD_cleanup_connections (daemon); } return NULL;}/** * Start a webserver on the given port. * * @param port port to bind to * @param apc callback to call to check which clients * will be allowed to connect * @param apc_cls extra argument to apc * @param dh default handler for all URIs * @param dh_cls extra argument to dh * @return NULL on error, handle to daemon on success */struct MHD_Daemon *MHD_start_daemon (unsigned int options, unsigned short port, MHD_AcceptPolicyCallback apc, void *apc_cls, MHD_AccessHandlerCallback dh, void *dh_cls, ...){ const int on = 1; struct MHD_Daemon *retVal; int socket_fd; struct sockaddr_in servaddr4; struct sockaddr_in6 servaddr6; const struct sockaddr *servaddr; socklen_t addrlen; va_list ap; enum MHD_OPTION opt; if ((options & MHD_USE_SSL) != 0) return NULL; if ((port == 0) || (dh == NULL)) return NULL; if ((options & MHD_USE_IPv6) != 0) socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0); else socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0); if (socket_fd < 0) { if ((options & MHD_USE_DEBUG) != 0) fprintf (stderr, "Call to socket failed: %s\n", STRERROR (errno)); return NULL; } if ((SETSOCKOPT (socket_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) && (options & MHD_USE_DEBUG) != 0) fprintf (stderr, "setsockopt failed: %s\n", STRERROR (errno)); if ((options & MHD_USE_IPv6) != 0) { memset (&servaddr6, 0, sizeof (struct sockaddr_in6)); servaddr6.sin6_family = AF_INET6; servaddr6.sin6_port = htons (port); servaddr = (struct sockaddr *) &servaddr6; addrlen = sizeof (struct sockaddr_in6); } else { memset (&servaddr4, 0, sizeof (struct sockaddr_in)); servaddr4.sin_family = AF_INET; servaddr4.sin_port = htons (port); servaddr = (struct sockaddr *) &servaddr4; addrlen = sizeof (struct sockaddr_in); } if (BIND (socket_fd, servaddr, addrlen) < 0) { if ((options & MHD_USE_DEBUG) != 0) fprintf (stderr, "Failed to bind to port %u: %s\n", port, STRERROR (errno)); CLOSE (socket_fd); return NULL; } if (LISTEN (socket_fd, 20) < 0) { if ((options & MHD_USE_DEBUG) != 0) fprintf (stderr, "Failed to listen for connections: %s\n", STRERROR (errno)); CLOSE (socket_fd); return NULL; } retVal = malloc (sizeof (struct MHD_Daemon)); memset (retVal, 0, sizeof (struct MHD_Daemon)); retVal->options = options; retVal->port = port; retVal->apc = apc; retVal->apc_cls = apc_cls; retVal->socket_fd = socket_fd; retVal->default_handler.dh = dh; retVal->default_handler.dh_cls = dh_cls; retVal->default_handler.uri_prefix = ""; retVal->default_handler.next = NULL; retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT; retVal->pool_size = MHD_POOL_SIZE_DEFAULT; va_start (ap, dh_cls); while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION))) { switch (opt) { case MHD_OPTION_CONNECTION_MEMORY_LIMIT: retVal->pool_size = va_arg (ap, unsigned int); break; case MHD_OPTION_CONNECTION_LIMIT: retVal->max_connections = va_arg (ap, unsigned int); break; default: fprintf (stderr, "Invalid MHD_OPTION argument! (Did you terminate the list with MHD_OPTION_END?)\n"); abort (); } } va_end (ap); if (((0 != (options & MHD_USE_THREAD_PER_CONNECTION)) || (0 != (options & MHD_USE_SELECT_INTERNALLY))) && (0 != pthread_create (&retVal->pid, NULL, &MHD_select_thread, retVal))) { MHD_DLOG (retVal, "Failed to create listen thread: %s\n", STRERROR (errno)); free (retVal); CLOSE (socket_fd); return NULL; } return retVal;}/** * Shutdown an http daemon. */voidMHD_stop_daemon (struct MHD_Daemon *daemon){ void *unused; if (daemon == NULL) return; daemon->shutdown = 1; CLOSE (daemon->socket_fd); daemon->socket_fd = -1; if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))) { pthread_kill (daemon->pid, SIGALRM); pthread_join (daemon->pid, &unused); } while (daemon->connections != NULL) { if (-1 != daemon->connections->socket_fd) { CLOSE (daemon->connections->socket_fd); daemon->connections->socket_fd = -1; } MHD_cleanup_connections (daemon); } free (daemon);}#ifndef WINDOWSstatic struct sigaction sig;static struct sigaction old;static voidsigalrmHandler (int sig){}/** * Initialize the signal handler for SIGALRM. */void __attribute__ ((constructor)) MHD_pthread_handlers_ltdl_init (){ /* make sure SIGALRM does not kill us */ memset (&sig, 0, sizeof (struct sigaction)); memset (&old, 0, sizeof (struct sigaction)); sig.sa_flags = SA_NODEFER; sig.sa_handler = &sigalrmHandler; sigaction (SIGALRM, &sig, &old);}void __attribute__ ((destructor)) MHD_pthread_handlers_ltdl_fini (){ sigaction (SIGALRM, &old, &sig);}#endif/* end of daemon.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -