📄 nta.c
字号:
NTATAG_PASS_408(agent->sa_pass_408), NTATAG_PRELOAD(agent->sa_preload), NTATAG_PROGRESS(agent->sa_progress), NTATAG_REL100(agent->sa_invite_100rel), NTATAG_SERVER_RPORT(agent->sa_server_rport), NTATAG_SIGCOMP_ALGORITHM(agent->sa_algorithm), NTATAG_SIGCOMP_OPTIONS(agent->sa_sigcomp_options ? agent->sa_sigcomp_options : "sip"), NTATAG_SIPFLAGS(agent->sa_flags), NTATAG_SIP_T1(agent->sa_t1), NTATAG_SIP_T1X64(agent->sa_t1x64), NTATAG_SIP_T2(agent->sa_t2), NTATAG_SIP_T4(agent->sa_t4),#if HAVE_SOFIA_SMIME NTATAG_SMIME(agent->sa_smime),#else NTATAG_SMIME(NULL),#endif NTATAG_STATELESS(agent->sa_is_stateless), NTATAG_TAG_3261(1), NTATAG_TIMEOUT_408(agent->sa_timeout_408), NTATAG_TIMER_C(agent->sa_timer_c), NTATAG_UA(agent->sa_is_a_uas), NTATAG_UDP_MTU(agent->sa_udp_mtu), NTATAG_USER_VIA(agent->sa_user_via), NTATAG_USE_NAPTR(agent->sa_use_naptr), NTATAG_USE_SRV(agent->sa_use_srv), NTATAG_USE_TIMESTAMP(agent->sa_timestamp), TAG_END());}/**Get NTA statistics. * * The nta_agent_get_stats() function retrieves the stack statistics. * * @TAGS * NTATAG_S_ACKED_TR_REF(), * NTATAG_S_BAD_MESSAGE_REF(), * NTATAG_S_BAD_REQUEST_REF(), * NTATAG_S_BAD_RESPONSE_REF(), * NTATAG_S_CANCELED_TR_REF(), * NTATAG_S_CLIENT_TR_REF(), * NTATAG_S_DIALOG_TR_REF(), * NTATAG_S_DROP_REQUEST_REF(), * NTATAG_S_DROP_RESPONSE_REF(), * NTATAG_S_IRQ_HASH_REF(), * NTATAG_S_IRQ_HASH_USED_REF(), * NTATAG_S_LEG_HASH_REF(), * NTATAG_S_LEG_HASH_USED_REF(), * NTATAG_S_MERGED_REQUEST_REF(), * NTATAG_S_ORQ_HASH_REF(), * NTATAG_S_ORQ_HASH_USED_REF(), * NTATAG_S_RECV_MSG_REF(), * NTATAG_S_RECV_REQUEST_REF(), * NTATAG_S_RECV_RESPONSE_REF(), * NTATAG_S_RECV_RETRY_REF(), * NTATAG_S_RETRY_REQUEST_REF(), * NTATAG_S_RETRY_RESPONSE_REF(), * NTATAG_S_SENT_MSG_REF(), * NTATAG_S_SENT_REQUEST_REF(), * NTATAG_S_SENT_RESPONSE_REF(), * NTATAG_S_SERVER_TR_REF(), * NTATAG_S_TOUT_REQUEST_REF(), * NTATAG_S_TOUT_RESPONSE_REF(), * NTATAG_S_TRLESS_200_REF(), * NTATAG_S_TRLESS_REQUEST_REF(), * NTATAG_S_TRLESS_RESPONSE_REF(), and * NTATAG_S_TRLESS_TO_TR_REF(), */int nta_agent_get_stats(nta_agent_t *agent, tag_type_t tag, tag_value_t value, ...){ int n; ta_list ta; if (!agent) return su_seterrno(EINVAL), -1; ta_start(ta, tag, value); n = tl_tgets(ta_args(ta), NTATAG_S_IRQ_HASH(agent->sa_incoming->iht_size), NTATAG_S_ORQ_HASH(agent->sa_outgoing->oht_size), NTATAG_S_LEG_HASH(agent->sa_dialogs->lht_size), NTATAG_S_IRQ_HASH_USED(agent->sa_incoming->iht_used), NTATAG_S_ORQ_HASH_USED(agent->sa_outgoing->oht_used), NTATAG_S_LEG_HASH_USED(agent->sa_dialogs->lht_used), NTATAG_S_RECV_MSG(agent->sa_stats->as_recv_msg), NTATAG_S_RECV_REQUEST(agent->sa_stats->as_recv_request), NTATAG_S_RECV_RESPONSE(agent->sa_stats->as_recv_response), NTATAG_S_BAD_MESSAGE(agent->sa_stats->as_bad_message), NTATAG_S_BAD_REQUEST(agent->sa_stats->as_bad_request), NTATAG_S_BAD_RESPONSE(agent->sa_stats->as_bad_response), NTATAG_S_DROP_REQUEST(agent->sa_stats->as_drop_request), NTATAG_S_DROP_RESPONSE(agent->sa_stats->as_drop_response), NTATAG_S_CLIENT_TR(agent->sa_stats->as_client_tr), NTATAG_S_SERVER_TR(agent->sa_stats->as_server_tr), NTATAG_S_DIALOG_TR(agent->sa_stats->as_dialog_tr), NTATAG_S_ACKED_TR(agent->sa_stats->as_acked_tr), NTATAG_S_CANCELED_TR(agent->sa_stats->as_canceled_tr), NTATAG_S_TRLESS_REQUEST(agent->sa_stats->as_trless_request), NTATAG_S_TRLESS_TO_TR(agent->sa_stats->as_trless_to_tr), NTATAG_S_TRLESS_RESPONSE(agent->sa_stats->as_trless_response), NTATAG_S_TRLESS_200(agent->sa_stats->as_trless_200), NTATAG_S_MERGED_REQUEST(agent->sa_stats->as_merged_request), NTATAG_S_SENT_MSG(agent->sa_stats->as_sent_msg), NTATAG_S_SENT_REQUEST(agent->sa_stats->as_sent_request), NTATAG_S_SENT_RESPONSE(agent->sa_stats->as_sent_response), NTATAG_S_RETRY_REQUEST(agent->sa_stats->as_retry_request), NTATAG_S_RETRY_RESPONSE(agent->sa_stats->as_retry_response), NTATAG_S_RECV_RETRY(agent->sa_stats->as_recv_retry), NTATAG_S_TOUT_REQUEST(agent->sa_stats->as_tout_request), NTATAG_S_TOUT_RESPONSE(agent->sa_stats->as_tout_response), TAG_END()); ta_end(ta); return n;}/**Calculate a new unique tag. * * This function generates a series of 2**64 unique tags for @From or @To * headers. The start of the tag series is derived from the NTP time the NTA * agent was initialized. * */char const *nta_agent_newtag(su_home_t *home, char const *fmt, nta_agent_t *sa){ char tag[(8 * 8 + 4)/ 5 + 1]; if (sa == NULL) return su_seterrno(EINVAL), NULL; /* XXX - use a cryptographically safe func here? */ sa->sa_tags += NTA_TAG_PRIME; msg_random_token(tag, sizeof(tag) - 1, &sa->sa_tags, sizeof(sa->sa_tags)); if (fmt && fmt[0]) return su_sprintf(home, fmt, tag); else return su_strdup(home, tag);}/** * Calculate branch value. */static char const *stateful_branch(su_home_t *home, nta_agent_t *sa){ char branch[(8 * 8 + 4)/ 5 + 1]; /* XXX - use a cryptographically safe func here? */ sa->sa_branch += NTA_BRANCH_PRIME; msg_random_token(branch, sizeof(branch) - 1, &sa->sa_branch, sizeof(sa->sa_branch)); return su_sprintf(home, "branch=z9hG4bK%s", branch);}#include <sofia-sip/su_md5.h>/** * Calculate branch value for stateless operation. * * XXX - should include HMAC of previous @Via line. */staticchar const *stateless_branch(nta_agent_t *sa, msg_t *msg, sip_t const *sip, tp_name_t const *tpn){ su_md5_t md5[1]; uint8_t digest[SU_MD5_DIGEST_SIZE]; char branch[(SU_MD5_DIGEST_SIZE * 8 + 4)/ 5 + 1]; sip_route_t const *r; assert(sip->sip_request); if (!sip->sip_via) return stateful_branch(msg_home(msg), sa); su_md5_init(md5); su_md5_str0update(md5, tpn->tpn_host); su_md5_str0update(md5, tpn->tpn_port); url_update(md5, sip->sip_request->rq_url); if (sip->sip_call_id) { su_md5_str0update(md5, sip->sip_call_id->i_id); } if (sip->sip_from) { url_update(md5, sip->sip_from->a_url); su_md5_stri0update(md5, sip->sip_from->a_tag); } if (sip->sip_to) { url_update(md5, sip->sip_to->a_url); /* XXX - some broken implementations include To tag in CANCEL */ /* su_md5_str0update(md5, sip->sip_to->a_tag); */ } if (sip->sip_cseq) { uint32_t cseq = htonl(sip->sip_cseq->cs_seq); su_md5_update(md5, &cseq, sizeof(cseq)); } for (r = sip->sip_route; r; r = r->r_next) url_update(md5, r->r_url); su_md5_digest(md5, digest); msg_random_token(branch, sizeof(branch) - 1, digest, sizeof(digest)); return su_sprintf(msg_home(msg), "branch=z9hG4bK.%s", branch);}/* ====================================================================== *//* 2) Transport interface *//* Local prototypes */static int agent_create_master_transport(nta_agent_t *self, tagi_t *tags);static int agent_init_via(nta_agent_t *self, tport_t *primaries, int use_maddr);static int agent_init_contact(nta_agent_t *self);static void agent_recv_message(nta_agent_t *agent, tport_t *tport, msg_t *msg, sip_via_t *tport_via, su_time_t now);static void agent_tp_error(nta_agent_t *agent, tport_t *tport, int errcode, char const *remote);static void agent_update_tport(nta_agent_t *agent, tport_t *);/**For each transport, we have name used by tport module, SRV prefixes used * for resolving, and NAPTR service/conversion. */static struct sipdns_tport { char name[6]; /**< Named used by tport module */ char port[6]; /**< Default port number */ char prefix[14]; /**< Prefix for SRV domains */ char service[10]; /**< NAPTR service */}#define SIPDNS_TRANSPORTS (4)const sipdns_tports[SIPDNS_TRANSPORTS] = { { "udp", "5060", "_sip._udp.", "SIP+D2U" }, { "tcp", "5060", "_sip._tcp.", "SIP+D2T" }, { "sctp", "5060", "_sip._sctp.", "SIP+D2S" }, { "tls", "5061", "_sips._tcp.", "SIPS+D2T" },};static char const * const tports_sip[] = { "udp", "tcp", "sctp", NULL };static char const * const tports_sips[] = { "tls", NULL };static tport_stack_class_t nta_agent_class[1] = {{ sizeof(nta_agent_class), agent_recv_message, agent_tp_error, nta_msg_create_for_transport, agent_update_tport, }};/** Add a transport to the agent. * * Creates a new transport and binds it * to the port specified by the @a uri. The @a uri must have sip: or sips: * scheme or be a wildcard uri ("*"). The @a uri syntax allowed is as * follows: * * @code url <scheme>:<host>[:<port>]<url-params> @endcode * where <url-params> may be * @code * ;transport=<xxx> * ;maddr=<actual addr> * ;comp=sigcomp * @endcode * * The scheme part determines which transports are used. "sip" implies UDP * and TCP, "sips" TLS over TCP. In the future, more transports can be * supported, for instance, "sip" can use SCTP or DCCP, "sips" DTLS or TLS * over SCTP. * * The "host" part determines what address/domain name is used in @Contact. * An "*" in "host" part is shorthand for any local IP address. 0.0.0.0 * means that the only the IPv4 addresses are used. [::] means that only * the IPv6 addresses are used. If a domain name or a specific IP address * is given as "host" part, an additional "maddr" parameter can be used to * control which addresses are used by the stack when binding listen * sockets for incoming requests. * * The "port" determines what port is used in contact, and to which port the * stack binds in order to listen for incoming requests. Empty or missing * port means that default port should be used (5060 for sip, 5061 for * sips). An "*" in "port" part means any port, i.e., the stack binds to an * ephemeral port. * * The "transport" parameter determines the transport protocol that is used * and how they are preferred. If no protocol is specified, both UDP and TCP * are used for SIP URL and TLS for SIPS URL. The preference can be * indicated with a comma-separated list of transports, for instance, * parameter @code transport=tcp,udp @endocde indicates that TCP is * preferred to UDP. * * The "maddr" parameter determines to which address the stack binds in * order to listen for incoming requests. An "*" in "maddr" parameter is * shorthand for any local IP address. 0.0.0.0 means that only IPv4 sockets * are created. [::] means that only IPv6 sockets are created. * * The "comp" parameter determines the supported compression protocol. * Currently only sigcomp is supported (with suitable library. * * @par Examples: * @code sip:172.21.40.24;maddr=* @endcode \n * @code sip:172.21.40.24:50600;transport=TCP,UDP;comp=sigcomp @endcode \n * @code sips:* @endcode * * @return * On success, zero is returned. On error, -1 is returned, and @a errno is * set appropriately. */int nta_agent_add_tport(nta_agent_t *self, url_string_t const *uri, tag_type_t tag, tag_value_t value, ...){ url_t *url; char tp[32]; char maddr[256]; char comp[32]; tp_name_t tpn[1] = {{ NULL }}; char const * const * tports = tports_sip; int error; ta_list ta; if (self == NULL) { su_seterrno(EINVAL); return -1; } if (uri == NULL) uri = (url_string_t *)"sip:*"; else if (url_string_p(uri) ? strcmp(uri->us_str, "*") == 0 : uri->us_url->url_type == url_any) { uri = (url_string_t *)"sip:*:*"; } if (!(url = url_hdup(self->sa_home, uri->us_url)) || (url->url_type != url_sip && url->url_type != url_sips)) { if (url_string_p(uri)) SU_DEBUG_1(("nta: %s: invalid bind URL\n", uri->us_str)); else SU_DEBUG_1(("nta: invalid bind URL\n")); su_seterrno(EINVAL); return -1; } tpn->tpn_canon = url->url_host; tpn->tpn_host = url->url_host; tpn->tpn_port = url_port(url); if (url->url_type == url_sip) { tpn->tpn_proto = "*"; tports = tports_sip; if (!tpn->tpn_port || !tpn->tpn_port[0]) tpn->tpn_port = SIP_DEFAULT_SERV; } else { assert(url->url_type == url_sips); tpn->tpn_proto = "*"; tports = tports_sips; if (!tpn->tpn_port || !tpn->tpn_port[0]) tpn->tpn_port = SIPS_DEFAULT_SERV; } if (url->url_params) { if (url_param(url->url_params, "transport", tp, sizeof(tp)) > 0) { if (strchr(tp, ',')) { int i; char *t, *tps[9]; /* Split tp into transports */ for (i = 0, t = tp; t && i < 8; i++) { tps[i] = t; if ((t = strchr(t, ','))) *t++ = '\0'; } tps[i] = NULL; tports = (char const * const *)tps; } else { tpn->tpn_proto = tp; } } if (url_param(url->url_params, "maddr", maddr, sizeof(maddr)) > 0) tpn->tpn_host = maddr; if (url_param(url->url_params, "comp", comp, sizeof(comp)) > 0) tpn->tpn_comp = comp; if (tpn->tpn_comp && (nta_compressor_vtable == NULL || strcasecmp(tpn->tpn_comp, nta_compressor_vtable->ncv_name) != 0)) { SU_DEBUG_1(("nta(%p): comp=%s not supported for " URL_PRINT_FORMAT "\n", (void *)self, tpn->tpn_comp, URL_PRINT_ARGS(url))); } } ta_start(ta, tag, value); if (self->sa_tports == NULL) { if (agent_create_master_transport(self, ta_args(ta)) < 0) { error = su_errno(); SU_DEBUG_1(("nta: cannot create master transport: %s\n", su_strerror(error))); goto error; } } if (tport_tbind(self->sa_tports, tpn, tports, ta_tags(ta)) < 0) { error = su_errno(); SU_DEBUG_1(("nta: bind(%s:%s;transport=%s%s%s%s%s): %s\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -