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

📄 nta.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
		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, tport_primaries(self->sa_tports), 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;}staticint agent_create_master_transport(nta_agent_t *self, tagi_t *tags){  self->sa_tports =     tport_tcreate(self, nta_agent_class, self->sa_root,		  TPTAG_SDWN_ERROR(0),		  TPTAG_IDLE(1800000),		  TAG_NEXT(tags));  if (!self->sa_tports)    return -1;  SU_DEBUG_9(("nta: master transport created\n"));  return 0;}/** Initialize @Via headers. */staticint agent_init_via(nta_agent_t *self, tport_t *primaries, int use_maddr){  sip_via_t *via = NULL, *new_via, *dup_via, *v, **vv = &via;  sip_via_t *new_vias, **next_new_via, *new_publics, **next_new_public;  tport_t *tp;  su_addrinfo_t const *ai;  su_home_t autohome[SU_HOME_AUTO_SIZE(2048)];  su_home_auto(autohome, sizeof autohome);  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 = primaries; tp; tp = tport_next(tp)) {    int maddr, first_via;    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;    first_via = 1;    ai = tport_get_address(tp);    for (; ai; ai = ai->ai_next) {      char host[TPORT_HOSTPORTSIZE] = "";      char sport[8];      char const *canon = ai->ai_canonname;      su_sockaddr_t *su = (void *)ai->ai_addr;      int port;      if (su) {	su_inet_ntop(su->su_family, SU_ADDR(su), host, sizeof host);	maddr = use_maddr && strcasecmp(canon, host) != 0;	port = ntohs(su->su_port);      }      else {	msg_random_token(host, 16, NULL, 0);	canon = strcat(host, ".is.invalid");	maddr = 0;	port = 0;      }	      if (strncasecmp(tpn->tpn_proto, "tls", 3)	  ? port == SIP_DEFAULT_PORT	  : port == SIPS_DEFAULT_PORT)	port = 0;      snprintf(sport, sizeof sport, ":%u", port);            comp = tpn->tpn_comp;      SU_DEBUG_9(("nta: agent_init_via: "		  "%s/%s %s%s%s%s%s%s (%s)\n",		  SIP_VERSION_CURRENT, tpn->tpn_proto,		  canon, port ? sport : "",		  maddr ? ";maddr=" : "", maddr ? host : "",		  comp ? ";comp=" : "", comp ? comp : "",		  tpn->tpn_ident ? tpn->tpn_ident : "*"));      v = sip_via_format(autohome,			 "%s/%s %s%s%s%s%s%s",			 SIP_VERSION_CURRENT, tpn->tpn_proto,			 canon, port ? sport : "",			 maddr ? ";maddr=" : "", maddr ? host : "",			 comp ? ";comp=" : "", comp ? comp : "");      if (v == NULL)	goto error;      v->v_comment = tpn->tpn_ident;      v->v_common->h_data = tp;	/* Nasty trick */      *vv = v; vv = &(*vv)->v_next;    }  }  /* Duplicate the list bind to the transports */  new_via = sip_via_dup(self->sa_home, via);  /* Duplicate the complete list shown to the application */  dup_via = sip_via_dup(self->sa_home, via);  if (via && (!new_via || !dup_via)) {    msg_header_free(self->sa_home, (void *)new_via);    msg_header_free(self->sa_home, (void *)dup_via);    goto error;  }  new_vias = NULL, next_new_via = &new_vias;  new_publics = NULL, next_new_public = &new_publics;  /* Set via field magic for the tports */  for (tp = primaries; tp; tp = tport_next(tp)) {    assert(via->v_common->h_data == tp);    v = tport_magic(tp);    tport_set_magic(tp, new_via);    msg_header_free(self->sa_home, (void *)v);    if (tport_is_public(tp))      *next_new_public = dup_via;    else      *next_new_via = dup_via;    while (via->v_next && via->v_next->v_common->h_data == tp)      via = via->v_next, new_via = new_via->v_next, dup_via = dup_via->v_next;        via = via->v_next;    /* Break the link in via list between transports */    vv = &new_via->v_next, new_via = *vv, *vv = NULL;    vv = &dup_via->v_next, dup_via = *vv, *vv = NULL;    if (tport_is_public(tp))      while (*next_new_public) next_new_public = &(*next_new_public)->v_next;    else      while (*next_new_via) next_new_via = &(*next_new_via)->v_next;  }  assert(dup_via == NULL);  assert(new_via == NULL);  if (self->sa_tport_udp)    agent_set_udp_params(self, self->sa_udp_mtu);  v = self->sa_vias;  self->sa_vias = new_vias;   msg_header_free(self->sa_home, (void *)v);  v = self->sa_public_vias;  self->sa_public_vias = new_publics;  msg_header_free(self->sa_home, (void *)v);  su_home_deinit(autohome);  return 0; error:  su_home_deinit(autohome);  return -1;}/** Initialize main contact header. */staticint agent_init_contact(nta_agent_t *self){  sip_via_t const *v1, *v2;  char const *tp;  if (self->sa_contact)    return 0;  for (v1 = self->sa_vias ? self->sa_vias : self->sa_public_vias;       v1;       v1 = v1->v_next) {    if (host_is_ip_address(v1->v_host)) {      if (!host_is_local(v1->v_host))	break;    }    else if (!host_has_domain_invalid(v1->v_host)) {      break;    }  }  if (v1 == NULL)    v1 = self->sa_vias ? self->sa_vias : self->sa_public_vias;  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 &&      str0casecmp(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){  sip_via_t *v = tport_magic(tport);  while (v && v->v_next)    v = v->v_next;  return v;}/** 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 (!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");  if (!orq->orq_tpn->tpn_comp)    msg_header_remove_param(v->v_common, "comp");  if (branch && branch != v->v_branch) {    char const *bvalue = branch + strcspn(branch, "=");    if (*bvalue) bvalue++;    if (!v->v_branch || strcasecmp(bvalue, v->v_branch))      msg_header_replace_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 (!user_via &&      via->v_host != v->v_host &&      str0cmp(via->v_host, v->v_host))    clear = 1, v->v_host = via->v_host;  if ((!user_via ||       /* Replace port in user Via only if we use udp and no rport */       (v->v_protocol == sip_transport_udp && !v->v_rport && 	!orq->orq_stateless)) &&      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,		   tp_name_t *tpn,		   char const **scheme,		   char const **port,		   url_string_t const *us){  url_t url[1];  isize_t n;  char *b;  n = url_xtra(us->us_url);  b = su_alloc(home, n);  if (b == NULL || url_dup(b, n, url, us->us_url) < 0) {    su_free(home, b);    return -1;  }  if (url->url_type != url_sip &&       url->url_type != url_sips &&      url->url_type != url_im &&      url->url_type != url_pres) {    su_free(home, b);    return -1;  }  SU_DEBUG_7(("nta: selecting scheme %s\n", url->url_scheme));  *scheme = url->url_scheme;  if (strcasecmp(url->url_scheme, "sips") == 0)    tpn->tpn_proto = "tls

⌨️ 快捷键说明

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