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

📄 nth_server.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 3 页
字号:
    site->site_access = now;  if (subsite && subsite->site_isdir && subpath == site_nodir_match) {    /* Answer with 301 */    http_location_t loc[1];    http_location_init(loc);    *loc->loc_url = *site->site_url;    if (site->site_wildcard) {      if (http->http_host) {	loc->loc_url->url_host = http->http_host->h_host;	loc->loc_url->url_port = http->http_host->h_port;      }      else {	tp_name_t const *tpn = tport_name(tport); assert(tpn);	loc->loc_url->url_host = tpn->tpn_canon;	if (strcmp(url_port_default(loc->loc_url->url_type), tpn->tpn_port))	  loc->loc_url->url_port = tpn->tpn_port;      }    }    loc->loc_url->url_root = 1;    loc->loc_url->url_path = subsite->site_url->url_path;    msg_header_add_dup(response, NULL, (msg_header_t *)loc);    server_reply(srv, tport, request, response, HTTP_301_MOVED_PERMANENTLY);  }  else if (subsite)    nth_site_request(srv, subsite, tport, request, http, subpath, response);  else if (site)    nth_site_request(srv, site, tport, request, http, path, response);  else    /* Answer with 404 */    server_reply(srv, tport, request, response, HTTP_404_NOT_FOUND);}static void server_tport_error(server_t *srv,				   tport_t *tport,				   int errcode,				   char const *remote){  su_log("\nth: tport: %s%s%s\n",	 remote ? remote : "", remote ? ": " : "",	 su_strerror(errcode));}/** Respond without creating a request structure */static void server_reply(server_t *srv, tport_t *tport, 			 msg_t *request, msg_t *response,			 int status, char const *phrase){  http_t *http;  http_payload_t *pl;  int close;  http_status_t st[1];  char const *req_version = NULL;  if (status < 200 || status >= 600)    status = 500, phrase = http_500_internal_server;  http = http_object(request);    if (http && http->http_request)    req_version = http->http_request->rq_version;  close = status >= 200 &&     (!srv->srv_persistent     || status == 400     || (http && http->http_request && 	 http->http_request->rq_version != http_version_1_1)     || (http && http->http_connection && 	 msg_params_find(http->http_connection->k_items, "close")));  msg_destroy(request);  http = http_object(response);  pl = http_payload_format(msg_home(response), 			   "<html>\n"			   "<head><title>%u %s</title></head>\n"			   "<body><h2>%u %s</h2></body>\n"			   "</html>\n", status, phrase, status, phrase);  msg_header_insert(response, (msg_pub_t *)http, (msg_header_t *)pl);  if (req_version != http_version_0_9) {    http_status_init(st);    st->st_version = http_version_1_1;    st->st_status = status;    st->st_phrase = phrase;        http_add_tl(response, http,		HTTPTAG_STATUS(st),		HTTPTAG_SERVER(srv->srv_server),		HTTPTAG_CONTENT_TYPE_STR("text/html"),		HTTPTAG_SEPARATOR_STR("\r\n"),		TAG_IF(close, HTTPTAG_CONNECTION_STR("close")),		TAG_END());    msg_serialize(response, (msg_pub_t *)http);  } else {    /* Just send the response */    *msg_chain_head(response) = (msg_header_t *)pl;    close = 1;  }  if (tport_tqsend(tport, response, NULL, 		   TPTAG_CLOSE_AFTER(close), 		   TAG_END()) == -1) {    SU_DEBUG_3(("server_reply(): cannot queue response\n"));    tport_shutdown(tport, 2);  }  msg_destroy(response);}/** Create a new message for transport */staticmsg_t *server_msg_create(server_t *srv, int flags, 			 char const data[], usize_t dlen,			 tport_t const *tp, tp_client_t *tpc){  msg_t *msg = msg_create(srv->srv_mclass, srv->srv_mflags | flags);  return msg;}/* ---------------------------------------------------------------------- * 6) Server transactions  */struct auth_info{  nth_site_t *site;  nth_request_t *req;  http_t const *http;  char const *path;};static void nth_authentication_result(void *ai0, auth_status_t *as);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){  auth_mod_t *am = site->site_auth;  nth_request_t *req;  auth_status_t *as;  struct auth_info *ai;  size_t size = (am ? (sizeof *as) + (sizeof *ai) : 0) + (sizeof *req);  int status;  req = su_zalloc(srv->srv_home, size);    if (req == NULL) {    server_reply(srv, tport, request, response, HTTP_500_INTERNAL_SERVER);    return;  }    if (am)    as = auth_status_init(req + 1, sizeof *as), ai = (void *)(as + 1);  else    as = NULL, ai = NULL;  req->req_server = srv;  req->req_method = http->http_request->rq_method;  req->req_method_name = http->http_request->rq_method_name;  req->req_url = http->http_request->rq_url;  req->req_version = http->http_request->rq_version;  req->req_tport = tport_incref(tport);  req->req_request = request;  req->req_response = response;  req->req_status = 100;  req->req_close =     !srv->srv_persistent    || http->http_request->rq_version != http_version_1_1    || (http->http_connection && 	msg_params_find(http->http_connection->k_items, "close"));  if (am) {    static auth_challenger_t const http_server_challenger[] =       {{ HTTP_401_UNAUTHORIZED, http_www_authenticate_class }};    req->req_as = as;    as->as_method = http->http_request->rq_method_name;    as->as_uri = path;        if (http->http_payload) {      as->as_body = http->http_payload->pl_data;      as->as_bodylen = http->http_payload->pl_len;    }    auth_mod_check_client(am, as, 			  http->http_authorization,			  http_server_challenger);    if (as->as_status == 100) {      /* Stall transport - do not read more requests */      if (tport_queuelen(tport) * 2 >= srv->srv_queuesize)	tport_stall(tport);      as->as_callback = nth_authentication_result;      as->as_magic = ai;      ai->site = site;      ai->req = req;      ai->http = http;      ai->path = path;      return;    }    else if (as->as_status) {      assert(as->as_status >= 200);      nth_request_treply(req, as->as_status, as->as_phrase,			 HTTPTAG_HEADER((http_header_t *)as->as_response),			 HTTPTAG_HEADER((http_header_t *)as->as_info),			 TAG_END());      nth_request_destroy(req);      return;    }  }  req->req_in_callback = 1;  status = site->site_callback(site->site_magic, site, req, http, path);  req->req_in_callback = 0;  if (status != 0 && (status < 100 || status >= 600))    status = 500;  if (status != 0 && req->req_status < 200) {    nth_request_treply(req, status, NULL, TAG_END());  }  if (req->req_status < 100) {    /* Stall transport - do not read more requests */    if (tport_queuelen(tport) * 2 >= srv->srv_queuesize)      tport_stall(tport);  }  if (status >= 200 || req->req_destroyed)    nth_request_destroy(req);}static void nth_authentication_result(void *ai0, auth_status_t *as){  struct auth_info *ai = ai0;  nth_request_t *req = ai->req;  int status;  if (as->as_status != 0) {    assert(as->as_status >= 300);    nth_request_treply(req, status = as->as_status, as->as_phrase, 		       HTTPTAG_HEADER((http_header_t *)as->as_response), 		       TAG_END());  }  else {    req->req_in_callback = 1;    status = ai->site->site_callback(ai->site->site_magic, 				     ai->site,				     ai->req,				     ai->http,				     ai->path);    req->req_in_callback = 0;    if (status != 0 && (status < 100 || status >= 600))      status = 500;    if (status != 0 && req->req_status < 200) {      nth_request_treply(req, status, NULL, TAG_END());    }  }  if (status >= 200 || req->req_destroyed)    nth_request_destroy(req);}void nth_request_destroy(nth_request_t *req){  if (req == NULL)    return;  if (req->req_status < 200)    nth_request_treply(req, HTTP_500_INTERNAL_SERVER, TAG_END());  req->req_destroyed = 1;  if (req->req_in_callback)     return;  if (req->req_as)    su_home_deinit(req->req_as->as_home);  tport_decref(&req->req_tport), req->req_tport = NULL;  msg_destroy(req->req_request), req->req_request = NULL;  msg_destroy(req->req_response), req->req_response = NULL;  su_free(req->req_server->srv_home, req);}/** Return request authentication status. * * @param req pointer to HTTP request object *  * @retval Status code * * @since New in @VERSION_1_12_4 */int nth_request_status(nth_request_t const *req){  return req ? req->req_status : 400;}/** Return request authentication status. * * @param req pointer to HTTP request object *  * @retval Pointer to authentication status struct * * @note The authentication status struct is freed when the #nth_request_t * object is destroyed. * * @since New in @VERSION_1_12_4 * * @sa AUTH */auth_status_t *nth_request_auth(nth_request_t const *req){  return req ? req->req_as : NULL;}http_method_t nth_request_method(nth_request_t const *req){  return req ? req->req_method : http_method_invalid;}msg_t *nth_request_message(nth_request_t *req){  msg_t *retval = NULL;  if (req)    retval = msg_ref_create(req->req_request);  return retval;}int nth_request_treply(nth_request_t *req, 		       int status, char const *phrase, 		       tag_type_t tag, tag_value_t value, ...){  msg_t *response, *next = NULL;  http_t *http;  int retval = -1;  int req_close, close;  ta_list ta;  http_header_t const *as_info = NULL;  if (req == NULL || status < 100 || status >= 600) {    return -1;  }  response = req->req_response;  http = http_object(response);  if (status >= 200 && req->req_as)    as_info = (http_header_t const *)req->req_as->as_info;  ta_start(ta, tag, value);  http_add_tl(response, http,	      HTTPTAG_SERVER(req->req_server->srv_server),	      HTTPTAG_HEADER(as_info), 	      ta_tags(ta));  if (http->http_payload && !http->http_content_length) {    http_content_length_t *l;    http_payload_t *pl;    size_t len = 0;        for (pl = http->http_payload; pl; pl = pl->pl_next)      len += pl->pl_len;    if (len > UINT32_MAX)      goto fail;    l = http_content_length_create(msg_home(response), (uint32_t)len);    msg_header_insert(response, (msg_pub_t *)http, (msg_header_t *)l);  }  if (req->req_method == http_method_head && http->http_payload) {    http_payload_t *pl;        for (pl = http->http_payload; pl; pl = pl->pl_next)      msg_header_remove(response, (msg_pub_t *)http, (msg_header_t *)pl);  }  http_complete_response(response, status, phrase, 			 http_object(req->req_request));  if (!http->http_date) {    http_date_t date[1];    http_date_init(date)->d_time = msg_now();    msg_header_add_dup(response, (msg_pub_t *)http, (msg_header_t*)date);  }  if (status < 200) {    close = 0;    next = server_msg_create(req->req_server, 0, NULL, 0, NULL, NULL);  }  else {    req_close = req->req_close;    close = (http->http_connection && 	     msg_params_find(http->http_connection->k_items, "close"));        if (req_close && !close && status >= 200) {      close = 1;      http_add_tl(response, http, HTTPTAG_CONNECTION_STR("close"), TAG_END());    }  }  msg_serialize(response, (msg_pub_t *)http);  retval = tport_tqsend(req->req_tport, response, next, 			TAG_IF(close, TPTAG_CLOSE_AFTER(1)),			ta_tags(ta)); fail:  ta_end(ta);    if (retval == 0)    req->req_status = status;  return retval;}

⌨️ 快捷键说明

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