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

📄 nth_server.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 3 页
字号:
  if (site->site_auth)    auth_mod_unref(site->site_auth), site->site_auth = NULL;  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;  }}/** Get the site URL. @NEW_1_12_4. */url_t const *nth_site_url(nth_site_t const *site){  return site ? site->site_url : NULL;}/** Return server name and version */char const *nth_site_server_version(void){  return "nth/" NTH_VERSION;}/** Get the time last time served. @NEW_1_12_4. */su_time_t nth_site_access_time(nth_site_t const *site){  su_time_t const never = { 0, 0 };  return site ? site->site_access : never;}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;  auth_mod_t *am;  if (site == NULL)    return (errno = EINVAL), -1;  server = site->site_server;  master = site == server->srv_sites;  am = site->site_auth;  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)),	      NTHTAG_AUTH_MODULE_REF(am),	      TAG_END());    if (n > 0) {    if (mclass)      server->srv_mclass = mclass;    else      server->srv_mclass = http_default_mclass();    server->srv_mflags = mflags;    auth_mod_ref(am), auth_mod_unref(site->site_auth), site->site_auth = am;  }  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 (host_cmp(host, site->site_url->url_host) == 0 &&	str0cmp(port, site->site_url->url_port) == 0) {      break;    }  }  return list;}/** Find a place to insert site from the hierarchy. * * A resource can be either a 'dir' (name ends with '/') or 'file'. * When a resource */staticnth_site_t **site_get_rslot(nth_site_t *parent, char *path, 			    char **return_rest){  nth_site_t *site, **prev;  size_t len;  int cmp;  assert(path);  if (path[0] == '\0')    return errno = EEXIST, NULL;  for (prev = &parent->site_kids; (site = *prev); prev = &site->site_next) {    cmp = strncmp(path, site->site_path, len = site->site_path_len);    if (cmp > 0)      break;    if (cmp < 0)      continue;    if (path[len] == '\0') {      if (site->site_isdir)	return *return_rest = path, prev;       return errno = EEXIST, NULL;    }    if (path[len] != '/' || site->site_path[len] != '/')      continue;    while (path[++len] == '/')      ;    return site_get_rslot(site, path + len, return_rest);  }  *return_rest = path;  return prev;}static char const site_nodir_match[] = "";/** Find a subdir from site hierarchy */staticnth_site_t *site_get_subdir(nth_site_t *parent,			    char const *path,			    char const **return_rest){  nth_site_t *site;  size_t len;  int cmp;  assert(path);  while (path[0] == '/')	/* Skip multiple slashes */    path++;  if (path[0] == '\0')    return *return_rest = path, parent;    for (site = parent->site_kids; site; site = site->site_next) {    cmp = strncmp(path, site->site_path, len = site->site_path_len);    if (cmp > 0)      break;    if (cmp < 0)      continue;    if (path[len] == '\0')      return *return_rest = site_nodir_match, site;    if (site->site_path[len] == '/' && path[len] == '/')      return site_get_subdir(site, path + len + 1, return_rest);  }  return *return_rest = path, parent;}/* ---------------------------------------------------------------------- * Server functions */static char const * const http_tports[] =  {    "tcp", "tls", NULL  };static char const * const http_no_tls_tports[] = { "tcp", NULL };static tp_stack_class_t nth_server_class[1] =  {{    sizeof(nth_server_class),    server_request,    server_tport_error,    server_msg_create  }};server_t *server_create(url_t const *url,			tag_type_t tag, tag_value_t value, ...){  server_t *srv;  msg_mclass_t const *mclass = NULL;  tp_name_t tpn[1] = {{ NULL }};  su_root_t *root = NULL;  http_server_t const *server = NULL;  int persistent = 0;  char const *server_str = SERVER_VERSION;  ta_list ta;  ta_start(ta, tag, value);  tl_gets(ta_args(ta), 	  NTHTAG_ROOT_REF(root),	  NTHTAG_MCLASS_REF(mclass),	  TPTAG_REUSE_REF(persistent),	  HTTPTAG_SERVER_REF(server),	  HTTPTAG_SERVER_STR_REF(server_str),	  TAG_END());  if (!root || !url ||       (url->url_type != url_http && url->url_type != url_https)      || !(srv = su_home_new(sizeof(*srv)))) {    ta_end(ta);    return NULL;  }  tpn->tpn_proto = url_tport_default(url->url_type);  tpn->tpn_canon = url->url_host;  tpn->tpn_host =  url->url_host;  tpn->tpn_port = url_port(url);  srv->srv_tports = tport_tcreate(srv, nth_server_class, root, 				  TPTAG_IDLE(600000),				  TPTAG_TIMEOUT(300000),				  ta_tags(ta));  srv->srv_persistent = persistent;  srv->srv_max_bodylen = 1 << 30; /* 1 GB */  if (tport_tbind(srv->srv_tports, tpn, http_tports,		  TAG_END()) >= 0 ||      tport_tbind(srv->srv_tports, tpn, http_no_tls_tports,		  TAG_END()) >= 0) {    srv->srv_root = root;    srv->srv_mclass = mclass ? mclass : http_default_mclass();    srv->srv_mflags = MSG_DO_CANONIC;    if (server)      srv->srv_server = http_server_dup(srv->srv_home, server);    else      srv->srv_server = http_server_make(srv->srv_home, server_str);    tport_get_params(srv->srv_tports,		     TPTAG_QUEUESIZE_REF(srv->srv_queuesize),		     TAG_END());  }  else {    SU_DEBUG_1(("nth_server_create: cannot bind transports " 		URL_FORMAT_STRING "\n",		URL_PRINT_ARGS(url)));     server_destroy(srv), srv = NULL;  }  ta_end(ta);  return srv;}void server_destroy(server_t *srv){  tport_destroy(srv->srv_tports);  su_timer_destroy(srv->srv_timer);  su_home_unref(srv->srv_home);}/** Initialize server timer. */su_inlineint server_timer_init(server_t *srv){  if (0) {    srv->srv_timer = su_timer_create(su_root_task(srv->srv_root), SERVER_TICK);    return su_timer_set(srv->srv_timer, server_timer, srv);  }  return 0;}/** * Server timer routine. */staticvoid server_timer(su_root_magic_t *rm, su_timer_t *timer, server_t *srv){  uint32_t now;  su_timer_set(timer, server_timer, srv);  now = su_time_ms(su_now()); now += now == 0; srv->srv_now = now;  /* Xyzzy */  srv->srv_now = 0;}/** Get current timestamp in milliseconds */su_inlineuint32_t server_now(server_t const *srv){  if (srv->srv_now)    return srv->srv_now;  else    return su_time_ms(su_now());}/** Process incoming request message */staticvoid server_request(server_t *srv,		    tport_t *tport,		    msg_t *request,		    void *arg,		    su_time_t now){  nth_site_t *site = NULL, *subsite = NULL;  msg_t *response;  http_t *http = http_object(request);  http_host_t *h;  char const *host, *port, *path, *subpath = NULL;  /* Disable streaming */  if (msg_is_streaming(request)) {    msg_set_streaming(request, 0);    return;  }  /* Create a response message */  response = server_msg_create(srv, 0, NULL, 0, NULL, NULL);  tport_tqueue(tport, response, TAG_END());  if (http && http->http_flags & MSG_FLG_TIMEOUT) {    server_reply(srv, tport, request, response, 400, "Request timeout");    return;  } else if (http && http->http_flags & MSG_FLG_TOOLARGE) {    server_reply(srv, tport, request, response, HTTP_413_ENTITY_TOO_LARGE);    return;  } else if (!http || !http->http_request || 	     (http->http_flags & MSG_FLG_ERROR)) {    server_reply(srv, tport, request, response, HTTP_400_BAD_REQUEST);    return;  }  if (http->http_request->rq_version != http_version_1_0 &&      http->http_request->rq_version != http_version_1_1) {    server_reply(srv, tport, request, response, HTTP_505_HTTP_VERSION);    return;  }  h = http->http_host;  if (h) {    host = h->h_host, port = h->h_port;  }  else if (http->http_request->rq_url->url_host) {    host = http->http_request->rq_url->url_host;    port = http->http_request->rq_url->url_port;  }  else    host = NULL, port = NULL;  path = http->http_request->rq_url->url_path;  if (host)    site = *site_get_host(&srv->srv_sites, host, port);  if (site == NULL && !srv->srv_sites->site_strict)    site = srv->srv_sites;  if (path == NULL)    path = "";  if (path[0])    subsite = site_get_subdir(site, path, &subpath);  if (subsite)    subsite->site_access = now;  else

⌨️ 快捷键说明

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