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

📄 daemon.c

📁 一个 http 服务器的框架实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*     This file is part of libmicrohttpd     (C) 2007 Daniel Pittman and Christian Grothoff     libmicrohttpd is free software; you can redistribute it and/or modify     it under the terms of the GNU General Public License as published     by the Free Software Foundation; either version 2, or (at your     option) any later version.     libmicrohttpd is distributed in the hope that it will be useful, but     WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     General Public License for more details.     You should have received a copy of the GNU General Public License     along with libmicrohttpd; see the file COPYING.  If not, write to the     Free Software Foundation, Inc., 59 Temple Place - Suite 330,     Boston, MA 02111-1307, USA.*//** * @file daemon.c * @brief  A minimal-HTTP server library * @author Daniel Pittman * @author Christian Grothoff */#include "internal.h"#include "response.h"#include "connection.h"#include "memorypool.h"/** * Default connection limit. */#define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE -4/** * Default memory allowed per connection. */#define MHD_POOL_SIZE_DEFAULT (1024 * 1024)/** * Register an access handler for all URIs beginning with uri_prefix. * * @param uri_prefix * @return MRI_NO if a handler for this exact prefix *         already exists */intMHD_register_handler (struct MHD_Daemon *daemon,                      const char *uri_prefix,                      MHD_AccessHandlerCallback dh, void *dh_cls){  struct MHD_Access_Handler *ah;  if ((daemon == NULL) || (uri_prefix == NULL) || (dh == NULL))    return MHD_NO;  ah = daemon->handlers;  while (ah != NULL)    {      if (0 == strcmp (uri_prefix, ah->uri_prefix))        return MHD_NO;      ah = ah->next;    }  ah = malloc (sizeof (struct MHD_Access_Handler));  ah->next = daemon->handlers;  ah->uri_prefix = strdup (uri_prefix);  ah->dh = dh;  ah->dh_cls = dh_cls;  daemon->handlers = ah;  return MHD_YES;}/** * Unregister an access handler for the URIs beginning with * uri_prefix. * * @param uri_prefix * @return MHD_NO if a handler for this exact prefix *         is not known for this daemon */intMHD_unregister_handler (struct MHD_Daemon *daemon,                        const char *uri_prefix,                        MHD_AccessHandlerCallback dh, void *dh_cls){  struct MHD_Access_Handler *prev;  struct MHD_Access_Handler *pos;  if ((daemon == NULL) || (uri_prefix == NULL) || (dh == NULL))    return MHD_NO;  pos = daemon->handlers;  prev = NULL;  while (pos != NULL)    {      if ((dh == pos->dh) &&          (dh_cls == pos->dh_cls) &&          (0 == strcmp (uri_prefix, pos->uri_prefix)))        {          if (prev == NULL)            daemon->handlers = pos->next;          else            prev->next = pos->next;          free (pos);          return MHD_YES;        }      prev = pos;      pos = pos->next;    }  return MHD_NO;}/** * Obtain the select sets for this daemon. * * @return MHD_YES on success, MHD_NO if this *         daemon was not started with the right *         options for this call. */intMHD_get_fdset (struct MHD_Daemon *daemon,               fd_set * read_fd_set,               fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd){  struct MHD_Connection *pos;  if ((daemon == NULL) ||      (read_fd_set == NULL) ||      (write_fd_set == NULL) ||      (except_fd_set == NULL) ||      (max_fd == NULL) ||      ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0))    return MHD_NO;  FD_SET (daemon->socket_fd, read_fd_set);  if ((*max_fd) < daemon->socket_fd)    *max_fd = daemon->socket_fd;  pos = daemon->connections;  while (pos != NULL)    {      if (MHD_YES != MHD_connection_get_fdset (pos,                                               read_fd_set,                                               write_fd_set,                                               except_fd_set, max_fd))        return MHD_NO;      pos = pos->next;    }  return MHD_YES;}/** * Main function of the thread that handles an individual * connection. */static void *MHD_handle_connection (void *data){  struct MHD_Connection *con = data;  int num_ready;  fd_set rs;  fd_set ws;  fd_set es;  int max;  if (con == NULL)    abort ();  while ((!con->daemon->shutdown) && (con->socket_fd != -1))    {      FD_ZERO (&rs);      FD_ZERO (&ws);      FD_ZERO (&es);      max = 0;      MHD_connection_get_fdset (con, &rs, &ws, &es, &max);      num_ready = SELECT (max + 1, &rs, &ws, &es, NULL);      if (num_ready <= 0)        {          if (errno == EINTR)            continue;          break;        }      if (((FD_ISSET (con->socket_fd, &rs)) &&           (MHD_YES != MHD_connection_handle_read (con))) ||          ((con->socket_fd != -1) &&           (FD_ISSET (con->socket_fd, &ws)) &&           (MHD_YES != MHD_connection_handle_write (con))))        break;      if ((con->headersReceived == 1) && (con->response == NULL))        MHD_call_connection_handler (con);    }  if (con->socket_fd != -1)    {      CLOSE (con->socket_fd);      con->socket_fd = -1;    }  return NULL;}/** * Accept an incoming connection and create the MHD_Connection object for * it.  This function also enforces policy by way of checking with the * accept policy callback. */static intMHD_accept_connection (struct MHD_Daemon *daemon){  struct MHD_Connection *connection;  struct sockaddr_in6 addr6;  struct sockaddr *addr = (struct sockaddr *) &addr6;  socklen_t addrlen;  int s;  if (sizeof (struct sockaddr) > sizeof (struct sockaddr_in6))    abort ();                   /* fatal, serious error */  addrlen = sizeof (struct sockaddr_in6);  memset (addr, 0, sizeof (struct sockaddr_in6));  s = ACCEPT (daemon->socket_fd, addr, &addrlen);  if ((s < 0) || (addrlen <= 0))    {      MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));      if (s != -1)        CLOSE (s);              /* just in case */      return MHD_NO;    }  if (daemon->max_connections == 0)    {      /* above connection limit - reject */      CLOSE (s);      return MHD_NO;    }  if ((daemon->apc != NULL) &&      (MHD_NO == daemon->apc (daemon->apc_cls, addr, addrlen)))    {      CLOSE (s);      return MHD_YES;    }  connection = malloc (sizeof (struct MHD_Connection));  memset (connection, 0, sizeof (struct MHD_Connection));  connection->pool = NULL;  connection->addr = malloc (addrlen);  if (connection->addr == NULL)    {      CLOSE (s);      free (connection);      return MHD_NO;    }  memcpy (connection->addr, addr, addrlen);  connection->addr_len = addrlen;  connection->socket_fd = s;  connection->daemon = daemon;  if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&      (0 != pthread_create (&connection->pid,                            NULL, &MHD_handle_connection, connection)))    {      MHD_DLOG (daemon, "Failed to create a thread: %s\n", STRERROR (errno));      CLOSE (s);      free (connection->addr);      free (connection);      return MHD_NO;    }  connection->next = daemon->connections;  daemon->connections = connection;  daemon->max_connections--;  return MHD_YES;}/** * Free resources associated with all closed connections. * (destroy responses, free buffers, etc.).  A connection * is known to be closed if the socket_fd is -1. * * Also performs connection actions that need to be run * even if the connection is not selectable (such as * calling the application again with upload data when * the upload data buffer is full). */static voidMHD_cleanup_connections (struct MHD_Daemon *daemon){  struct MHD_Connection *pos;  struct MHD_Connection *prev;  void *unused;  pos = daemon->connections;  prev = NULL;  while (pos != NULL)    {      if (pos->socket_fd == -1)        {          if (prev == NULL)            daemon->connections = pos->next;          else            prev->next = pos->next;          if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))            {              pthread_kill (pos->pid, SIGALRM);              pthread_join (pos->pid, &unused);            }          if (pos->response != NULL)            MHD_destroy_response (pos->response);          MHD_pool_destroy (pos->pool);          free (pos->addr);          free (pos);          daemon->max_connections++;          if (prev == NULL)            pos = daemon->connections;          else            pos = prev->next;          continue;        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -