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

📄 nta.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
	     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 + -