📄 nth_server.c
字号:
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 + -