📄 nta.c
字号:
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 + -