⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 daemon.c

📁 一个 http 服务器的框架实现
💻 C
📖 第 1 页 / 共 2 页
字号:
      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 + -