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

📄 nth_server.c

📁 this is simple sip stack.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 * *//**@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 <stddef.h>#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <errno.h>#include <assert.h>#include <sofia-sip/string0.h>#if !defined(EALREADY) && defined(_WIN32)#define EALREADY WSAEALREADY#endiftypedef 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>/* We are customer of tport_t */#define TP_STACK_T   server_t#define TP_MAGIC_T   void                                     #ifndef TPORT_H                 #include <sofia-sip/tport.h>#endif#include <sofia-sip/htable.h>enum { 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;  nth_site_t         **site_prev;  nth_site_t          *site_kids;  server_t            *site_server;  url_t               *site_url;  char const          *site_path;  size_t               site_path_len;  nth_request_f       *site_callback;  nth_site_magic_t    *site_magic;  unsigned             site_strict : 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;  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>/**@var NTH_DEBUG * * 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 <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);static inline int server_timer_init(server_t *srv);static void server_timer(su_root_magic_t *rm, su_timer_t *timer, server_t *srv);static 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_directory(nth_site_t **list, 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[], unsigned 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 virtual * http server or a site within a server  */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;  url_t *url;  server_t *srv;  ta_list ta;  su_home_t temphome[1] = { SU_HOME_INIT(temphome) };  char const *path = NULL;  size_t len = 0;  url = url_hdup(temphome, address->us_url);  if (!url || !callback)    return NULL;  if (url->url_host && url->url_path) {    SU_DEBUG_3(("nth_site_create(): virtual host and path simultanously\n"));    su_home_deinit(temphome);    errno = EINVAL;    return NULL;  }  if (!parent && url->url_path) {    SU_DEBUG_3(("nth_site_create(): no virtual host\n"));    su_home_deinit(temphome);    errno = EINVAL;    return NULL;  }  ta_start(ta, tag, value);  if (parent) {    srv = parent->site_server; assert(srv);    if (url->url_host)      prev = site_get_host(&srv->srv_sites, url->url_host, url->url_port);    else {      len = strlen(url->url_path);      if (len > 1 && url->url_path[len - 1] == '/')	((char *)url->url_path)[len - 1] = '\0';      prev = site_get_directory(&parent, url->url_path, &path);    }  }  else {    srv = server_create(url, ta_tags(ta));    prev = &srv->srv_sites;  }  if (url->url_path) {    assert(path);    len = strlen(path);    if (len == 0) {      SU_DEBUG_3(("nth_site_create(): directory \"%s\" already exists\n", 		  url->url_path));      su_home_deinit(temphome);      ta_end(ta);      errno = EALREADY;      return NULL;    }  }  if (srv && (site = su_zalloc(srv->srv_home, sizeof *site))) {    if (*prev) {      /* The existing node should will be kid */      site->site_next = (*prev)->site_next;      site->site_next->site_prev = &site->site_next;      site->site_kids = *prev;      (*prev)->site_prev = NULL;      (*prev)->site_next = NULL;    }    *prev = site, site->site_prev = prev;    site->site_server = srv;    site->site_url = url_hdup(srv->srv_home, url);    if (path) {      site->site_path = site->site_url->url_path + (path - url->url_path);      site->site_path_len = len;    } else {      site->site_path = "";      site->site_path_len = 0;    }    site->site_callback = callback;    site->site_magic = magic;    nth_site_set_params(site, ta_tags(ta));  }  su_home_deinit(temphome);  ta_end(ta);  return site;}void nth_site_destroy(nth_site_t *site){  if (site == NULL) {  }  else if (site->site_server->srv_sites == site) {    server_destroy(site->site_server);  }}nth_site_magic_t *nth_site_magic(nth_site_t const *site){  return site ? site->site_magic : NULL;}void nth_site_bind(nth_site_t *site, 		   nth_request_f *callback, 		   nth_site_magic_t *magic){  if (site) {    site->site_callback = callback;    site->site_magic = magic;  }}char const *nth_site_server_version(void){  return "nth/" NTH_VERSION;}int nth_site_set_params(nth_site_t *site,			tag_type_t tag, tag_value_t value, ...){  int n;  ta_list ta;  server_t *server;  int master;  msg_mclass_t const *mclass;  int mflags;  if (site == NULL)    return (errno = EINVAL), -1;  server = site->site_server;  master = site == server->srv_sites;  mclass = server->srv_mclass;  mflags = server->srv_mflags;  ta_start(ta, tag, value);  n = tl_gets(ta_args(ta),	      TAG_IF(master, NTHTAG_MCLASS_REF(mclass)),	      TAG_IF(master, NTHTAG_MFLAGS_REF(mflags)),	      TAG_END());    if (n > 0) {    if (mclass)      server->srv_mclass = mclass;    else      server->srv_mclass = http_default_mclass();    server->srv_mflags = mflags;  }  ta_end(ta);  return n;}int nth_site_get_params(nth_site_t const *site,			tag_type_t tag, tag_value_t value, ...){  int n;  ta_list ta;  server_t *server;  int master;  msg_mclass_t const *mclass;  if (site == NULL)    return (errno = EINVAL), -1;  server = site->site_server;  master = site == server->srv_sites;  if (master && server->srv_mclass != http_default_mclass())    mclass = server->srv_mclass;  else    mclass = NULL;  ta_start(ta, tag, value);  n = tl_tgets(ta_args(ta),	       TAG_IF(master, NTHTAG_MCLASS(mclass)),	       TAG_IF(master, NTHTAG_MFLAGS(server->srv_mflags)),	       TAG_END());    ta_end(ta);  return n;}int nth_site_get_stats(nth_site_t const *site, 		       tag_type_t tag, tag_value_t value, ...){  int n;  ta_list ta;  if (site == NULL)    return (errno = EINVAL), -1;  ta_start(ta, tag, value);  n = tl_tgets(ta_args(ta),	       TAG_END());    ta_end(ta);  return n;}staticnth_site_t **site_get_host(nth_site_t **list, char const *host, char const *port){  nth_site_t *site;  assert(host);  for (; (site = *list); list = &site->site_next) {    if (strcasecmp(host, site->site_url->url_host) == 0 &&	str0cmp(port, site->site_url->url_port) == 0) {      break;    }  }  return list;}staticnth_site_t **site_get_directory(nth_site_t **list, char const *path, char const **res){  nth_site_t *site, **prev;  assert(path);  if (path[0] == '/')    while (path[1] == '/')      path++;  if (path[0] && (path[0] != '/' || path[1]))    for (prev = &(*list)->site_kids; (site = *prev); prev = &site->site_next) {      size_t len = site->site_path_len;      if (strncmp(path, site->site_path, len) == 0) {	return site_get_directory(prev, path + len, res);      }    }

⌨️ 快捷键说明

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