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

📄 nth_server.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@internal @file nth_server.c * @brief HTTP server. *  * @author Pekka Pessi <Pekka.Pessi@nokia.com> *  * @date Created: Sat Oct 19 01:37:36 2002 ppessi */#include "config.h"#include <sofia-sip/string0.h>#include <sofia-sip/su.h>typedef struct server_s server_t;/** @internal SU timer argument pointer type */#define SU_TIMER_ARG_T server_t#include <sofia-sip/http_header.h>#include <sofia-sip/http_status.h>#include <sofia-sip/http_tag.h>#include "sofia-sip/nth.h"#include <sofia-sip/msg_date.h>#include <sofia-sip/msg_addr.h>#include <sofia-sip/su_tagarg.h>#include <sofia-sip/hostdomain.h>/* We are customer of tport_t */#define TP_STACK_T   server_t#define TP_MAGIC_T   void                                     #include <sofia-sip/tport.h>#include <sofia-sip/htable.h>#include <sofia-sip/auth_module.h>#include <stddef.h>#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <errno.h>#include <assert.h>#ifndef UINT32_MAX#define UINT32_MAX (0xffffffffU)#endifenum { SERVER_TICK = 1000 };#define SERVER_VERSION "nth/" NTH_VERSIONHTABLE_DECLARE(hc_htable, hct, nth_client_t);struct server_s {  su_home_t          srv_home[1];  su_root_t         *srv_root;  su_timer_t        *srv_timer;  unsigned           srv_now;  msg_mclass_t const*srv_mclass;  int                srv_mflags;	/**< Message flags */  tport_t           *srv_tports;  unsigned           srv_queuesize;	/**< Maximum number of queued responses */  size_t             srv_max_bodylen;	/**< Maximum accepted length */  unsigned           srv_persistent:1;	/**< Allow persistent connections */  /** Sites */  nth_site_t        *srv_sites;  /* Statistics */  struct {    uint32_t           st_requests;     /**< Received requests */    uint32_t           st_responses;    /**< Sent responses */    uint32_t           st_bad;		/**< Bad requests */  }                  srv_stats[1];  http_server_t     *srv_server;      /**< Server header */};struct nth_site_s {  nth_site_t          *site_next, **site_prev;  nth_site_t          *site_kids;  server_t            *site_server;  auth_mod_t          *site_auth;  url_t               *site_url;  char const          *site_path;  size_t               site_path_len;  nth_request_f       *site_callback;  nth_site_magic_t    *site_magic;  su_time_t            site_access; /**< Last request served */  /** Host header must match with server name */  unsigned             site_strict : 1;  /** Site can have kids */  unsigned             site_isdir : 1;  /** Site does not have domain name */  unsigned             site_wildcard : 1;};struct nth_request_s{  server_t              *req_server;  http_method_t        	req_method;  char const           *req_method_name;  url_t const          *req_url;         /**< RequestURI  */  char const           *req_version;    tport_t              *req_tport;  msg_t		       *req_request;  msg_t                *req_response;  auth_status_t        *req_as;  unsigned short      	req_status;  unsigned              req_close : 1; /**< Client asked for close */  unsigned              req_in_callback : 1;  unsigned              req_destroyed : 1;};/* ====================================================================== *//* Debug log settings */#define SU_LOG   nth_server_log#ifdef SU_DEBUG_H#error <su_debug.h> included directly.#endif#include <sofia-sip/su_debug.h>/**Environment variable determining the debug log level for @b nth * module. * * The NTH_DEBUG environment variable is used to determine the debug * logging level for @b nth module. The default level is 1. *  * @sa <sofia-sip/su_debug.h>, nth_server_log, SOFIA_DEBUG */extern char const NTH_DEBUG[];#ifndef SU_DEBUG#define SU_DEBUG 1#endif/**Debug log for @b nth module.  *  * The nth_server_log is the log object used by @b nth module. The level of * #nth_server_log is set using #NTH_DEBUG environment variable. */su_log_t nth_server_log[] = { SU_LOG_INIT("nth", "NTH_DEBUG", SU_DEBUG) };#if HAVE_FUNC#elif HAVE_FUNCTION#define __func__ __FUNCTION__#elsestatic char const __func__[] = "nth";#endif/* ====================================================================== *//** Server side */static server_t *server_create(url_t const *url,			       tag_type_t tag, tag_value_t value, ...);void server_destroy(server_t *srv);su_inline int server_timer_init(server_t *srv);static void server_timer(su_root_magic_t *rm, su_timer_t *timer, server_t *srv);su_inline uint32_t server_now(server_t const *srv);static void server_request(server_t *srv, tport_t *tport, msg_t *msg,				    void *arg, su_time_t now);static nth_site_t **site_get_host(nth_site_t **, char const *host, char const *port);static nth_site_t **site_get_rslot(nth_site_t *parent, char *path,				   char **return_rest);static nth_site_t *site_get_subdir(nth_site_t *parent, char const *path, char const **res);static void server_tport_error(server_t *srv, tport_t *tport,			       int errcode, char const *remote);static msg_t *server_msg_create(server_t *srv, int flags, 				char const data[], usize_t dlen,				tport_t const *tp, tp_client_t *tpc);static void server_reply(server_t *srv, tport_t *tport, 			 msg_t *request, msg_t *response,			 int status, char const *phrase);staticvoid nth_site_request(server_t *srv,		      nth_site_t *site,		      tport_t *tport,		      msg_t *request,		      http_t *http,		      char const *path,		      msg_t *response);/* ---------------------------------------------------------------------- * 5) Site functions *//** Create a http site object.  * * The function nth_site_create() allocates and initializes a web site * object. A web site object can be either  * - a primary http server (@a parent is NULL), * - a virtual http server (@a address contains hostpart), or  * - a site within a server  *   (@a address does not have hostpart, only path part). * * @param parent pointer to parent site *               (NULL when creating a primary server object) * @param callback pointer to callback function called when *                 a request is received * @param magic    application context included in callback parameters * @param address  absolute or relative URI specifying the address of *                 site * @param tag, value, ... list of tagged parameters * * @TAGS * If the @a parent is NULL, the list of tagged parameters must contain * NTHTAG_ROOT() used to create the server engine. Tags supported when @a * parent is NULL are NTHTAG_ROOT(), NTHTAG_MCLASS(), TPTAG_REUSE(), * HTTPTAG_SERVER(), and HTTPTAG_SERVER_STR(). All the tags are passed to * tport_tcreate() and tport_tbind(), too. * * @since Support for multiple sites was added to @VERSION_1_12_4 */nth_site_t *nth_site_create(nth_site_t *parent,  			    nth_request_f *callback,			    nth_site_magic_t *magic,			    url_string_t const *address,			    tag_type_t tag, tag_value_t value,			    ...){  nth_site_t *site = NULL, **prev = NULL;  su_home_t home[SU_HOME_AUTO_SIZE(256)];  url_t *url, url0[1];  server_t *srv = NULL;  ta_list ta;  char *path = NULL;  size_t usize;  int is_host, is_path, wildcard = 0;  su_home_auto(home, sizeof home);  if (parent && url_is_string(address)) {    char const *s = (char const *)address;    size_t sep = strcspn(s, "/:");    if (parent->site_path) {      /* subpath */      url_init(url0, parent->site_url->url_type);      url0->url_path = s;      address = (url_string_t*)url0;    }    else if (s[sep] == ':')      /* absolute URL with scheme */;    else if (s[sep] == '\0' && strchr(s, '.') && host_is_valid(s)) {      /* looks like a domain name */;      url_init(url0, parent->site_url->url_type);      url0->url_host = s;      address = (url_string_t*)url0;    }    else {      /* looks like a path */      url_init(url0, parent->site_url->url_type);      url0->url_path = s;      address = (url_string_t*)url0;    }  }  url = url_hdup(home, address->us_url);  if (!url || !callback)    return NULL;    is_host = url->url_host != NULL;  is_path = url->url_path != NULL;  if (is_host && is_path) {    SU_DEBUG_3(("nth_site_create(): virtual host and path simultanously\n"));    errno = EINVAL;    goto error;  }  if (!parent && !is_host) {    SU_DEBUG_3(("nth_site_create(): host is required\n"));    errno = EINVAL;    goto error;  }  if (parent) {    if (!parent->site_isdir) {      SU_DEBUG_3(("nth_site_create(): invalid parent resource \n"));      errno = EINVAL;      goto error;    }          srv = parent->site_server; assert(srv);    if (is_host) {      prev = site_get_host(&srv->srv_sites, url->url_host, url->url_port);      if (prev == NULL) {	SU_DEBUG_3(("nth_site_create(): host %s:%s already exists\n",		    url->url_host, url->url_port ? url->url_port : ""));	errno = EEXIST;	goto error;      }    }     else {      size_t i, j;      path = (char *)url->url_path;      while (path[0] == '/')	path++;      /* Remove duplicate // */      for (i = j = 0; path[i];) {	while (path[i] == '/' && path[i + 1] == '/')	  i++;	path[j++] = path[i++];      }      path[j] = path[i];      url = url0, *url = *parent->site_url;      if (url->url_path) {	url->url_path = su_strcat(home, url->url_path, path);	if (!url->url_path)	  goto error;	path = (char *)url->url_path + strlen(parent->site_url->url_path);      }      else	url->url_path = path;      prev = site_get_rslot(parent, path, &path);      if (!prev || path[0] == '\0') {	SU_DEBUG_3(("nth_site_create(): directory \"%s\" already exists\n", 		    url->url_path));	errno = EEXIST;	goto error;      }    }  }  if (!parent) {    if (strcmp(url->url_host, "*") == 0 ||	host_cmp(url->url_host, "0.0.0.0") == 0 ||	host_cmp(url->url_host, "::") == 0)      wildcard = 1, url->url_host = "*";  }  usize = sizeof(*url) + url_xtra(url);  ta_start(ta, tag, value);  if (!parent) {    srv = server_create(url, ta_tags(ta));    prev = &srv->srv_sites;  }  if (srv && (site = su_zalloc(srv->srv_home, (sizeof *site) + usize))) {    site->site_url = (url_t *)(site + 1);    url_dup((void *)(site->site_url + 1), usize - sizeof(*url), 	    site->site_url, url);    assert(prev);    if ((site->site_next = *prev))      site->site_next->site_prev = &site->site_next;    *prev = site, site->site_prev = prev;    site->site_server = srv;    if (path) {      size_t path_len;      site->site_path = site->site_url->url_path + (path - url->url_path);      path_len = strlen(site->site_path); assert(path_len > 0);      if (path_len > 0 && site->site_path[path_len - 1] == '/')	path_len--, site->site_isdir = 1;      site->site_path_len = path_len;    }    else {      site->site_isdir = is_host;      site->site_path = "";      site->site_path_len = 0;    }    site->site_wildcard = wildcard;    site->site_callback = callback;    site->site_magic = magic;        if (parent)      site->site_auth = parent->site_auth;    nth_site_set_params(site, ta_tags(ta));  }  ta_end(ta); error:  su_home_deinit(home);  return site;}void nth_site_destroy(nth_site_t *site){  if (site == NULL)    return;

⌨️ 快捷键说明

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