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

📄 nta.c

📁 Internet Phone, Chat, Conferencing
💻 C
📖 第 1 页 / 共 5 页
字号:
 * ;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;  }  if (url->url_type == url_sip) {    tpn->tpn_proto = "*";    tports = tports_sip;  }  else {    assert(url->url_type == url_sips);    tpn->tpn_proto = "tls";    tports = tports_sips;  }  tpn->tpn_canon = url->url_host;  tpn->tpn_host = url->url_host;  tpn->tpn_port = url_port(url);  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 !HAVE_SIGCOMP    if (str0casecmp(tpn->tpn_comp, "sigcomp") == 0) {      SU_DEBUG_1(("nta(%p): sigcomp not supported for UA " 		  URL_PRINT_FORMAT "\n",		  self, URL_PRINT_ARGS(url)));    }#endif  }  ta_start(ta, tag, value);  if (self->sa_tports == NULL) {    /* Create master transport */#if HAVE_SIGCOMP    struct sigcomp_algorithm const *algorithm = self->sa_algorithm;    if (algorithm == NULL)      algorithm = sigcomp_algorithm_by_name(getenv("SIGCOMP_ALGORITHM"));    self->sa_state_handler = sigcomp_state_handler_create();    if (self->sa_state_handler)      self->sa_compartment = 	sigcomp_compartment_create(algorithm, self->sa_state_handler, 0,				   "", 0, NULL, 0);    if (self->sa_compartment) {      agent_sigcomp_options(self, self->sa_compartment);      sigcomp_compartment_option(self->sa_compartment, "stateless");    }    else      SU_DEBUG_1(("nta: initializing SigComp: %s\n", strerror(errno)));#endif    if (!(self->sa_tports = 	  tport_tcreate(self, nta_agent_class, self->sa_root,			TPTAG_SDWN_ERROR(0),			TPTAG_IDLE(1800000),			TPTAG_DEBUG_DROP(self->sa_drop_prob),			IF_SIGCOMP_TPTAG_COMPARTMENT(self->sa_compartment)			ta_tags(ta)))) {      error = su_errno();      SU_DEBUG_9(("nta: cannot create master transport: %s\n",		  su_strerror(error)));      goto error;    }    else      SU_DEBUG_9(("nta: master transport created\n"));  }  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",		tpn->tpn_canon, tpn->tpn_port, tpn->tpn_proto,		tpn->tpn_canon != tpn->tpn_host ? ";maddr=" : "",		tpn->tpn_canon != tpn->tpn_host ? tpn->tpn_host : "",		tpn->tpn_comp ? ";comp=" : "",		tpn->tpn_comp ? tpn->tpn_comp : "",		su_strerror(error)));    goto error;  }  else    SU_DEBUG_5(("nta: bound to (%s:%s;transport=%s%s%s%s%s)\n",		tpn->tpn_canon, tpn->tpn_port, tpn->tpn_proto,		tpn->tpn_canon != tpn->tpn_host ? ";maddr=" : "",		tpn->tpn_canon != tpn->tpn_host ? tpn->tpn_host : "",		tpn->tpn_comp ? ";comp=" : "",		tpn->tpn_comp ? tpn->tpn_comp : ""));  /* XXX - when to use maddr? */  if ((agent_init_via(self, 0)) < 0) {    error = su_errno();    SU_DEBUG_1(("nta: cannot create Via headers\n"));    goto error;  }  else    SU_DEBUG_9(("nta: Via fields initialized\n"));  if ((agent_init_contact(self)) < 0) {    error = su_errno();    SU_DEBUG_1(("nta: cannot create Contact header\n"));    goto error;  }  else    SU_DEBUG_9(("nta: Contact header created\n"));  su_free(self->sa_home, url);  ta_end(ta);  return 0; error:  ta_end(ta);  su_seterrno(error);  return -1;}/** Initialize Via headers. */staticint agent_init_via(nta_agent_t *self, int use_maddr){  sip_via_t *v, **vv;  tport_t *tp;  for (vv = &self->sa_vias; *vv; vv = &(*vv)->v_next)    ;  self->sa_tport_ip4 = 0;  self->sa_tport_ip6 = 0;  self->sa_tport_udp = 0;  self->sa_tport_tcp = 0;  self->sa_tport_sctp = 0;  self->sa_tport_tls = 0;  /* Set via fields for the tports */  for (tp = tport_primaries(self->sa_tports); tp; tp = tport_next(tp)) {    int maddr;    tp_name_t tpn[1];    char const *comp = NULL;    *tpn = *tport_name(tp);    assert(tpn->tpn_proto);    assert(tpn->tpn_canon);    assert(tpn->tpn_host);    assert(tpn->tpn_port);#if 0    if (getenv("SIP_UDP_CONNECT")	&& strcmp(tpn->tpn_proto, "udp") == 0)      tport_set_params(tp, TPTAG_CONNECT(1), TAG_END());#endif    if (tport_has_ip4(tp)) self->sa_tport_ip4 = 1;#if SU_HAVE_IN6    if (tport_has_ip6(tp)) self->sa_tport_ip6 = 1;#endif    if (strcasecmp(tpn->tpn_proto, "udp") == 0)      self->sa_tport_udp = 1;    else if (strcasecmp(tpn->tpn_proto, "tcp") == 0)      self->sa_tport_tcp = 1;    else if (strcasecmp(tpn->tpn_proto, "sctp") == 0)      self->sa_tport_sctp = 1;    if (tport_has_tls(tp)) self->sa_tport_tls = 1;    if (tport_magic(tp))      continue;    if (strcmp(tpn->tpn_port, SIP_DEFAULT_SERV) == 0)      tpn->tpn_port = NULL;    maddr = use_maddr && strcasecmp(tpn->tpn_canon, tpn->tpn_host) != 0;    comp = tpn->tpn_comp;    v = sip_via_format(self->sa_home,		       "%s/%s %s%s%s%s%s%s%s",		       SIP_VERSION_CURRENT, tpn->tpn_proto,		       tpn->tpn_canon,		       tpn->tpn_port ? ":" : "",		       tpn->tpn_port ? tpn->tpn_port : "",		       maddr ? ";maddr=" : "", maddr ? tpn->tpn_host : "",		       comp ? ";comp=" : "", comp ? comp : "");    if (v == NULL)      return -1;    tport_set_magic(tp, v);    /** Add a duplicate to the list shown to application */    *vv = sip_via_dup(self->sa_home, v);    if (*vv == NULL)      return -1;    vv = &(*vv)->v_next;  }  if (self->sa_tport_udp)    agent_set_udp_params(self, self->sa_udp_mtu);  return 0;}/** Initialize main contact header. */staticint agent_init_contact(nta_agent_t *self){  sip_via_t const *v1 = self->sa_vias, *v2;  char const *tp;  if (self->sa_contact)    return 0;  if (!v1) return -1;  tp = strrchr(v1->v_protocol, '/');  if (!tp++)    return -1;  v2 = v1->v_next;  if (v2 &&       strcasecmp(v1->v_host, v2->v_host) == 0 &&      strcasecmp(v1->v_port, v2->v_port) == 0) {    char const *p1 = v1->v_protocol, *p2 = v2->v_protocol;    if (strcasecmp(p1, sip_transport_udp))      p1 = v2->v_protocol, p2 = v1->v_protocol;    if (strcasecmp(p1, sip_transport_udp) == 0 &&	strcasecmp(p2, sip_transport_tcp) == 0)      /* Do not include transport if we have both UDP and TCP */      tp = NULL;  }  self->sa_contact =     sip_contact_create_from_via_with_transport(self->sa_home, v1, NULL, tp);  if (!self->sa_contact)    return -1;  return 0;}/** Return Via line corresponging to tport. */staticsip_via_t const *agent_tport_via(tport_t *tport){  return tport_magic(tport);}/** Insert Via to a request message */staticint outgoing_insert_via(nta_outgoing_t *orq, 			sip_via_t const *via){  nta_agent_t *self = orq->orq_agent;  msg_t *msg = orq->orq_request;  sip_t *sip = sip_object(msg);  char const *branch = orq->orq_via_branch;  int user_via = orq->orq_user_via;  sip_via_t *v;  int clear = 0;  assert(sip); assert(via);  if (user_via && sip->sip_via) {    /* Use existing Via provided by application */    v = sip->sip_via;  }  else if (msg && via && sip->sip_request &&	   (v = sip_via_copy(msg_home(msg), via))) {    msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)v);  }  else    return -1;  if (orq->orq_method != sip_method_ack) {    if (!v->v_rport && 	((self->sa_rport && v->v_protocol == sip_transport_udp) ||	 (self->sa_tcp_rport && v->v_protocol == sip_transport_tcp)))      msg_header_add_param(msg_home(msg), v->v_common, "rport");  }  else {    /* msg_header_remove_param(v->v_common, "comp"); */  }  if (!orq->orq_tpn->tpn_comp)    msg_header_remove_param(v->v_common, "comp");  if (branch && branch != v->v_branch)    msg_header_add_param(msg_home(msg), v->v_common, branch);  if (via->v_protocol != v->v_protocol &&      strcasecmp(via->v_protocol, v->v_protocol))    clear = 1, v->v_protocol = via->v_protocol;  /* XXX - should we do this? */  if (via->v_host != v->v_host &&      str0cmp(via->v_host, v->v_host))    clear = 1, v->v_host = via->v_host;  if (via->v_port != v->v_port &&      str0cmp(via->v_port, v->v_port))    clear = 1, v->v_port = via->v_port;  if (clear)    msg_fragment_clear(v->v_common);  return 0;}/** Get destination name from Via.  * * If @a using_rport is non-null, try rport. * If *using_rport is non-zero, try rport even if <protocol> is not UDP. * If <protocol> is UDP, set *using_rport to zero. */staticint nta_tpn_by_via(tp_name_t *tpn, sip_via_t const *v, int *using_rport){  if (!v)    return -1;  tpn->tpn_proto = sip_via_transport(v);  tpn->tpn_canon = v->v_host;  if (v->v_maddr)    tpn->tpn_host = v->v_maddr;  else if (v->v_received)    tpn->tpn_host = v->v_received;  else    tpn->tpn_host = v->v_host;  tpn->tpn_port = sip_via_port(v, using_rport);  tpn->tpn_comp = v->v_comp;  tpn->tpn_ident = NULL;  return 0;}/** Get transport name from URL. */int nta_tpn_by_url(su_home_t *home,

⌨️ 快捷键说明

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