📄 nth_client.c
字号:
return (errno = EINVAL), -1; ta_start(ta, tag, value); n = tl_tgets(ta_args(ta), TAG_END()); ta_end(ta); return n;}static tp_name_t he_name[1] = { {"*", "*", "*", "*"} };static char const *const he_tports[] = { "tcp", "tls", NULL};static char const *const he_no_tls_tports[] = { "tcp", NULL };static tp_stack_class_t http_client_class[1] = { { sizeof(http_client_class), he_recv_message, he_tp_error, he_msg_create}};/** Create transports for client engine */staticint he_create_tports(nth_engine_t * he, tagi_t *tags){ he->he_tports = tport_tcreate(he, http_client_class, he->he_root, TAG_END()); if (!he->he_tports) return -1; if (tport_tbind(he->he_tports, he_name, he_tports, TPTAG_SERVER(0), TAG_NEXT(tags)) >= 0) return 0; return tport_tbind(he->he_tports, he_name, he_no_tls_tports, TPTAG_SERVER(0), TAG_NEXT(tags));}/** Initialize engine timer. */staticint he_timer_init(nth_engine_t * he){ he->he_timer = su_timer_create(su_root_task(he->he_root), HE_TIMER); return su_timer_set(he->he_timer, he_timer, he);}/** * Engine timer routine. */staticvoid he_timer(su_root_magic_t *rm, su_timer_t *timer, nth_engine_t * he){ unsigned i; uint32_t now; hc_htable_t *hct = he->he_clients; now = su_time_ms(su_now()); now += now == 0; he->he_now = now; if (hct) for (i = hct->hct_size; i > 0;) if (hct->hct_table[--i]) hc_timer(he, hct->hct_table[i], now); su_timer_set(timer, he_timer, he); he->he_now = 0;}/** Get current timestamp in milliseconds */staticuint32_t he_now(nth_engine_t const *he){ if (he->he_now) return he->he_now; else return su_time_ms(su_now());}staticvoid he_recv_message(nth_engine_t * he, tport_t * tport, msg_t *msg, void *arg, su_time_t now){ nth_client_t *hc, **hcp; tp_name_t const *tpn; for (hcp = hc_htable_hash(he->he_clients, (hash_value_t)(uintptr_t) tport); (hc = *hcp); hcp = hc_htable_next(he->he_clients, hcp)) { if (hc->hc_tport == tport) { if (hc_recv(hc, msg, http_object(msg)) < 0) msg_destroy(msg); return; } } /* Extra response? Framing error? */ tpn = tport_name(tport); if (msg_size(msg)) SU_DEBUG_3(("nth client: received extra data ("MOD_ZU" bytes) " "from %s/%s:%s\n", (size_t)msg_size(msg), tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port)); else SU_DEBUG_3(("nth client: received extra data from %s/%s:%s\n", tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port)); msg_destroy(msg); tport_shutdown(tport, 2);}/** Report error from transport */static void he_tp_error(nth_engine_t * he, tport_t * tport, int errcode, char const *remote){ su_log("\nth: tport: %s%s%s\n", remote ? remote : "", remote ? ": " : "", su_strerror(errcode));}/** Create a new message. */msg_t *nth_engine_msg_create(nth_engine_t * he, int flags){ if (he == NULL) { errno = EINVAL; return NULL; } flags |= he->he_mflags; if (he->he_streaming) flags |= MSG_FLG_STREAMING; else flags &= ~MSG_FLG_STREAMING; return msg_create(he->he_mclass, flags);}/** Create a new message for transport */staticmsg_t *he_msg_create(nth_engine_t * he, int flags, char const data[], usize_t dlen, tport_t const *tport, nth_client_t * hc){ flags |= he->he_mflags; if (he->he_streaming) flags |= MSG_FLG_STREAMING; else flags &= ~MSG_FLG_STREAMING; if (hc == NULL) { nth_client_t **slot; for (slot = hc_htable_hash(he->he_clients, (hash_value_t)(uintptr_t) tport); (hc = *slot); slot = hc_htable_next(he->he_clients, slot)) if (hc->hc_tport == tport) break; } if (hc) { if (hc->hc_method == http_method_head) { flags &= ~MSG_FLG_STREAMING; flags |= HTTP_FLG_NO_BODY; } } return msg_create(he->he_mclass, flags);}/** Get destination name from Host header and request URI. */staticint tpn_by_host(tp_name_t * tpn, http_host_t const *h, url_t const *url){ if (!h || !url) return -1; tpn->tpn_proto = url_tport_default(url->url_type); tpn->tpn_canon = h->h_host; tpn->tpn_host = h->h_host; if (h->h_port) tpn->tpn_port = h->h_port; else tpn->tpn_port = url_port_default(url->url_type); return 0;}/* ---------------------------------------------------------------------- */nth_client_t *nth_client_tcreate(nth_engine_t * engine, nth_response_f * callback, nth_client_magic_t * magic, http_method_t method, char const *name, url_string_t const *uri, tag_type_t tag, tag_value_t value, ...){ nth_client_t *hc = NULL; ta_list ta; if (engine) { void *none = &none; msg_t *msg = none; http_t *http; char const *version = http_version_1_1; nth_client_t const *template = NULL; auth_client_t **auc = none; unsigned expires = engine->he_expires; int ok = 0; ta_start(ta, tag, value); tl_gets(ta_args(ta), NTHTAG_TEMPLATE_REF(template), NTHTAG_AUTHENTICATION_REF(auc), NTHTAG_MESSAGE_REF(msg), NTHTAG_EXPIRES_REF(expires), HTTPTAG_VERSION_REF(version), TAG_END()); if (msg == none) { if (template && template->hc_request) msg = msg_copy(template->hc_request); else msg = msg_create(engine->he_mclass, engine->he_mflags); } http = http_object(msg); if (template) { if (callback == NULL) callback = template->hc_callback; if (magic == NULL) magic = template->hc_magic; if (name == NULL) method = template->hc_method, name = template->hc_method_name; if (uri == NULL) uri = (url_string_t *) template->hc_url; if (auc == none) auc = template->hc_auc; } else if (auc == none) { auc = NULL; } hc = hc_create(engine, callback, magic, msg, ta_tags(ta)); if (hc) hc->hc_expires = expires; if (hc == NULL) ; else if (http_add_tl(msg, http, ta_tags(ta)) < 0) ; else if (!(uri = hc_request_complete(hc, msg, http, method, name, uri, version, nth_client_url(template)))) ; else if (auc && hc_request_authenticate(hc, msg, http, uri, auc) <= 0) ; else if (hc_resolve_and_send(hc) < 0) ; else ok = 1; if (!ok) { if (hc) hc_free(hc); else msg_destroy(msg); hc = NULL; } ta_end(ta); } return hc;}staticurl_string_t const *hc_request_complete(nth_client_t * hc, msg_t *msg, http_t * http, http_method_t method, char const *name, url_string_t const *uri, char const *version, url_t const *parent){ su_home_t *home = msg_home(msg); http_host_t *host = http->http_host; void *tbf = NULL; url_t const *url; url_t u[1]; if (uri == NULL && http->http_request) uri = (url_string_t *) http->http_request->rq_url; if (uri == NULL) uri = (url_string_t *) parent; url = url_string_p(uri) ? (tbf = url_hdup(NULL, uri->us_url)) : uri->us_url; if (!url) return NULL; *u = *url; if (u->url_type == url_unknown && u->url_path && !u->url_host) { if (parent) { *u = *parent; u->url_path = url->url_path; /* XXX - relative URLs! */ u->url_params = url->url_params; u->url_headers = url->url_headers; /* Query */ } } if (!hc->hc_route_url && u->url_type != url_http && u->url_type != url_https) hc->hc_route_url = (url_string_t *) u; if (host && (host_cmp(host->h_host, u->url_host) || str0cmp(host->h_port, u->url_port))) host = NULL; if (host == NULL && u->url_host) { host = http_host_create(home, u->url_host, u->url_port); msg_header_insert(msg, http, (http_header_t *) host); } if (u->url_host || hc->hc_route_url || host) hc->hc_url = url_hdup(home, u); if (hc->hc_route_url == (url_string_t *) u) hc->hc_route_url = (url_string_t *) hc->hc_url; if (hc->hc_url) { http_request_t *rq = http->http_request; if (rq && !method && !name) method = rq->rq_method, name = rq->rq_method_name; else if (rq && method && method != rq->rq_method) rq = NULL; else if (rq && name && strcmp(name, rq->rq_method_name)) rq = NULL; if (rq && version && strcasecmp(version, rq->rq_version)) rq = NULL; if (!hc->hc_route_url) { u->url_type = url_unknown, u->url_scheme = NULL; u->url_user = NULL, u->url_password = NULL; u->url_host = NULL, u->url_port = NULL; u->url_root = '/'; if (!u->url_path) u->url_path = ""; u->url_fragment = NULL; } if (rq && http_url_cmp(u, rq->rq_url)) rq = NULL; if (!rq) { if (http->http_request) msg_header_remove(msg, http, (msg_header_t *) http->http_request); http->http_request = http_request_create(home, method, name, (url_string_t *) u, version); if (!http->http_request) uri = NULL; } } else { uri = NULL; } if (http_message_complete(msg, http) < 0) uri = NULL; if (tbf) su_free(NULL, tbf); if (uri) { hc->hc_method = http->http_request->rq_method; hc->hc_method_name = http->http_request->rq_method_name; } return uri;}staticint hc_request_authenticate(nth_client_t * hc, msg_t *msg, http_t * http, url_string_t const *uri, auth_client_t **auc){ return auc_authorization(auc, msg, http, http->http_request->rq_method_name, uri->us_url, http->http_payload);}staticnth_client_t *hc_create(nth_engine_t * he, nth_response_f * callback, nth_client_magic_t * magic, msg_t *msg, tag_type_t tag, tag_value_t value, ...){ nth_client_t *hc; su_home_t *home = msg_home(msg); if (!(hc = su_zalloc(he->he_home, sizeof(*hc)))) return NULL; if (!callback) callback = hc_default_cb; {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -