📄 nth_client.c
字号:
/* * 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 * *//**@CFILE nth_client.c * @brief HTTP Client implementhtion * * Copyright (c) 2002 Nokia Research Center. All rights reserved. * * This source file has been divided into following sections: * 1) engine * 2) tport handling * 3) client transactions * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * * @date Created: Tue Jun 13 02:57:51 2000 ppessi */#include "config.h"#include <stddef.h>#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <assert.h>#include <errno.h>#include <sofia-sip/string0.h>/** @internal SU message argument structure type */#define SU_MSG_ARG_T union sm_arg_u/** @internal SU timer argument pointer type */#define SU_TIMER_ARG_T struct nth_engine_s#define MSG_HDR_T union http_header_u#define MSG_PUB_T struct http_s#include "sofia-sip/nth.h"#include <sofia-sip/http_header.h>#include <sofia-sip/http_tag.h>#include <sofia-sip/http_status.h>#include <sofia-sip/hostdomain.h>#include <sofia-sip/msg_addr.h>#include <sofia-sip/su_tagarg.h>#include <sofia-sip/auth_client.h>/* We are customer of tport_t */#define TP_STACK_T nth_engine_t#define TP_MAGIC_T void#define TP_CLIENT_T nth_client_t#ifndef TPORT_H#include <sofia-sip/tport.h>#endif#include <sofia-sip/htable.h>#define HE_TIMER HE_TIMERenum { HE_TIMER = 1000 };/** @c http_flag telling that this message is internally generated. */#define NTH_INTERNAL_MSG (1<<16)HTABLE_DECLARE_WITH(hc_htable, hct, nth_client_t, uintptr_t, size_t);struct nth_engine_s { su_home_t he_home[1]; su_root_t *he_root; su_timer_t *he_timer; int he_mflags; /**< Message flags */ msg_mclass_t const *he_mclass; tport_t *he_tports; url_t *he_default_proxy; unsigned he_now; unsigned he_expires; /* Attributes */ unsigned he_streaming:1; /**< Enable streaming */ unsigned he_error_msg:1; unsigned:0; /* Statistics */ struct { uint32_t st_requests; /**< Sent requests */ uint32_t st_1xxresponses; /**< Received 1XX responses */ uint32_t st_responses; /**< Received responses */ uint32_t st_tp_errors; /**< Transport errors */ uint32_t st_timeouts; /**< Timeouts */ uint32_t st_bad; /**< Bad responses*/ } he_stats[1]; /** Table for client transactions */ hc_htable_t he_clients[1];};struct nth_client_s { nth_engine_t *hc_engine; nth_response_f *hc_callback; nth_client_magic_t *hc_magic; http_method_t hc_method; char const *hc_method_name; url_t const *hc_url; /**< Original RequestURI */ unsigned hc_timeout; /**< Client timeout */ unsigned hc_expires; /**< Client expires */ /* Request state */ unsigned short hc_status; unsigned hc_destroyed:1; unsigned hc_completed:1; unsigned hc_inserted:1; unsigned hc_is_streaming:1; /**< Currently streaming response */ /* Attributes */ unsigned hc_streaming:1; /**< Enable streaming */ unsigned hc_error_msg:1; unsigned /* pad */:0; url_string_t const *hc_route_url; tp_name_t hc_tpn[1]; /**< Where to send requests */ tport_t *hc_tport; int hc_pending; /**< Request is pending in tport */ tagi_t *hc_tags; /**< Transport tags */ auth_client_t **hc_auc; /**< List of authenticators */ msg_t *hc_request; msg_t *hc_response;};/* ====================================================================== *//* Debug log settings */#define SU_LOG nth_client_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 <sofia-sip/su_debug.h>, nth_client_log, #SOFIA_DEBUG */extern char const NTH_DEBUG[];#ifndef SU_DEBUG#define SU_DEBUG 1#endif/**Debug log for @b nth module. * * The nth_client_log is the log object used by @b nth client. The level of * #nth_client_log is set using #NTH_DEBUG environment variable. */su_log_t nth_client_log[] = { SU_LOG_INIT("nth", "NTH_DEBUG", SU_DEBUG) };#if HAVE_FUNC#elif HAVE_FUNCTION#define __func__ __FUNCTION__#elsestatic char const __func__[] = "nth";#endif/* ====================================================================== *//* Internal message passing */union sm_arg_u { struct hc_recv_s { nth_client_t *hc; msg_t *msg; http_t *http; } hc_recv[1];};/* ====================================================================== *//* Internal prototypes */tagi_t nth_client_tags[] = { {nthtag_mclass, 0}, {nthtag_message, 0}, {nthtag_mflags, 0}, {nthtag_proxy, 0}, {nthtag_error_msg, 0}, {nthtag_template, 0}, {nthtag_authentication, 0}, {TAG_NEXT(tport_tags)}};/* ====================================================================== *//* Internal prototypes */static int he_create_tports(nth_engine_t * he, tagi_t *tags);static int he_timer_init(nth_engine_t * he);static void he_timer(su_root_magic_t *, su_timer_t *, nth_engine_t * he);static void hc_timer(nth_engine_t * he, nth_client_t * hc, uint32_t now);static uint32_t he_now(nth_engine_t const *he);static void he_recv_message(nth_engine_t * he, tport_t * tport, msg_t *msg, void *arg, su_time_t now);static msg_t *he_msg_create(nth_engine_t * he, int flags, char const data[], usize_t dlen, tport_t const *tport, nth_client_t * hc);static void he_tp_error(nth_engine_t * he, tport_t * tport, int errcode, char const *remote);static int hc_recv(nth_client_t * hc, msg_t *msg, http_t * http);HTABLE_PROTOS_WITH(hc_htable, hct, nth_client_t, uintptr_t, size_t);#define HTABLE_HASH_CLIENT(hc) ((uintptr_t)(hc)->hc_tport)HTABLE_BODIES_WITH(hc_htable, hct, nth_client_t, HTABLE_HASH_CLIENT, uintptr_t, size_t);static url_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 *url, char const *version, url_t const *parent);staticint hc_request_authenticate(nth_client_t * hc, msg_t *msg, http_t * http, url_string_t const *uri, auth_client_t **auc);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, ...);static int hc_resolve_and_send(nth_client_t * hc);static nth_client_t *hc_send(nth_client_t * hc);static void hc_insert(nth_engine_t * he, nth_client_t * hc);static void hc_free(nth_client_t * hc);static void hc_tport_error(nth_engine_t *, nth_client_t * hc, tport_t * tp, msg_t *msg, int error);static int hc_reply(nth_client_t * hc, int status, char const *phrase);static int hc_default_cb(nth_client_magic_t * magic, nth_client_t * request, http_t const *http);/* ---------------------------------------------------------------------- */char const *nth_engine_version(void){ return "sofia-http-client/" NTH_CLIENT_VERSION;}/* ---------------------------------------------------------------------- */nth_engine_t *nth_engine_create(su_root_t *root, tag_type_t tag, tag_value_t value, ...){ nth_engine_t *he; ta_list ta; if ((he = su_home_new(sizeof(*he)))) { he->he_root = root; he->he_mflags = MSG_DO_CANONIC; he->he_mclass = http_default_mclass(); he->he_expires = 32000; ta_start(ta, tag, value); if (hc_htable_resize(he->he_home, he->he_clients, 0) < 0 || he_create_tports(he, ta_args(ta)) < 0 || he_timer_init(he) < 0 || nth_engine_set_params(he, ta_tags(ta)) < 0) { nth_engine_destroy(he), he = NULL; } ta_end(ta); } return he;}void nth_engine_destroy(nth_engine_t * he){ if (he) { size_t i; hc_htable_t *hct = he->he_clients; for (i = 0; i < hct->hct_size; i++) hc_free(hct->hct_table[i]); tport_destroy(he->he_tports); su_timer_destroy(he->he_timer), he->he_timer = NULL; su_home_unref(he->he_home); }}int nth_engine_set_params(nth_engine_t * he, tag_type_t tag, tag_value_t value, ...){ int n; ta_list ta; unsigned expires; int error_msg; msg_mclass_t const *mclass; int mflags; int streaming; url_string_t const *proxy; if (he == NULL) return (errno = EINVAL), -1; ta_start(ta, tag, value); expires = he->he_expires; error_msg = he->he_error_msg; mclass = he->he_mclass; mflags = he->he_mflags; streaming = he->he_streaming; proxy = (void *) he->he_default_proxy; n = tl_gets(ta_args(ta), NTHTAG_EXPIRES_REF(expires), NTHTAG_ERROR_MSG_REF(error_msg), NTHTAG_MCLASS_REF(mclass), NTHTAG_MFLAGS_REF(mflags), NTHTAG_STREAMING_REF(streaming), NTHTAG_PROXY_REF(proxy), TAG_END()); if (n > 0) { if (proxy->us_url != he->he_default_proxy) { url_t *copy = url_hdup(he->he_home, proxy->us_url); if (proxy && !copy) { n = -1; } else { su_free(he->he_home, (void *) he->he_default_proxy); he->he_default_proxy = copy; } } } if (n > 0) { he->he_expires = expires; he->he_error_msg = error_msg != 0; if (mclass) he->he_mclass = mclass; else he->he_mclass = http_default_mclass(); he->he_mflags = mflags; he->he_streaming = streaming != 0; } ta_end(ta); return n;}int nth_engine_get_params(nth_engine_t const *he, tag_type_t tag, tag_value_t value, ...){ int n; ta_list ta; msg_mclass_t const *mclass; if (he == NULL) return (errno = EINVAL), -1; if (he->he_mclass != http_default_mclass()) mclass = he->he_mclass; else mclass = NULL; ta_start(ta, tag, value); n = tl_tgets(ta_args(ta), NTHTAG_ERROR_MSG(he->he_error_msg), NTHTAG_MCLASS(mclass), NTHTAG_MFLAGS(he->he_mflags), NTHTAG_EXPIRES(he->he_expires), NTHTAG_STREAMING(he->he_streaming), NTHTAG_PROXY((url_string_t *) he->he_default_proxy), TAG_END()); ta_end(ta); return n;}int nth_engine_get_stats(nth_engine_t const *he, tag_type_t tag, tag_value_t value, ...){ int n; ta_list ta; if (he == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -