📄 nua_register.c
字号:
nua->nua_nw_changed = snc; return 0;}intnua_stack_init_registrations(nua_t *nua){ /* Create initial identities: peer-to-peer, public, sips */ nua_registration_t **nr_list = &nua->nua_registrations, **nr_next; nua_handle_t **nh_list; nua_handle_t *dnh = nua->nua_dhandle; sip_via_t const *v; /* Remove existing, local address based registrations and count the rest */ while (nr_list && *nr_list) { nr_next = &(*nr_list)->nr_next; if ((*nr_list)->nr_default == 1) { nua_registration_remove(*nr_list); /* memset(*nr_list, 170, sizeof(**nr_list)); */ /* XXX - free, too */ } nr_list = nr_next; } nr_list = &nua->nua_registrations; v = nta_agent_public_via(nua->nua_nta); if (v) { nua_registration_from_via(nr_list, dnh, v, 1); } v = nta_agent_via(nua->nua_nta); if (v) { nua_registration_from_via(nr_list, dnh, v, 0); } else { sip_via_t v[2]; sip_via_init(v)->v_next = v + 1; v[0].v_protocol = sip_transport_udp; v[0].v_host = "addr.is.invalid."; sip_via_init(v + 1); v[1].v_protocol = sip_transport_tcp; v[1].v_host = "addr.is.invalid."; nua_registration_from_via(nr_list, dnh, v, 0); } /* Go through all the registrations and set to refresh almost immediately */ nh_list = &nua->nua_handles; for (; *nh_list; nh_list = &(*nh_list)->nh_next) { nua_dialog_state_t *ds; nua_dialog_usage_t *du; ds = (*nh_list)->nh_ds; du = ds->ds_usage; if (ds->ds_has_register == 1 && du->du_class->usage_refresh) { nua_dialog_usage_refresh(*nh_list, ds, du, 1); } } nta_agent_bind_tport_update(nua->nua_nta, (nta_update_magic_t *)nua, nua_stack_tport_update); return 0;}int nua_registration_from_via(nua_registration_t **list, nua_handle_t *nh, sip_via_t const *via, int public){ su_home_t *home = nh->nh_home; sip_via_t *v, *pair, /* v2[2], */ *vias, **vv, **prev; nua_registration_t *nr = NULL, **next; su_home_t autohome[SU_HOME_AUTO_SIZE(1024)]; int nr_items = 0; vias = sip_via_copy(su_home_auto(autohome, sizeof autohome), via); for (; *list; list = &(*list)->nr_next) ++nr_items; next = list; for (vv = &vias; (v = *vv);) { char const *protocol; sip_contact_t *contact; sip_via_t v2[2]; *vv = v->v_next, v->v_next = NULL, pair = NULL; if (v->v_protocol == sip_transport_tcp) protocol = sip_transport_udp; else if (v->v_protocol == sip_transport_udp) protocol = sip_transport_tcp; else protocol = NULL; if (protocol) { /* Try to pair vias if we have both udp and tcp */ for (prev = vv; *prev; prev = &(*prev)->v_next) { if (strcasecmp(protocol, (*prev)->v_protocol)) continue; if (strcasecmp(v->v_host, (*prev)->v_host)) continue; if (str0cmp(v->v_port, (*prev)->v_port)) continue; break; } if (*prev) { pair = *prev; *prev = pair->v_next; pair->v_next = NULL; } } /* if more than one candidate, ignore local entries */ if (v && (*vv || nr_items > 0) && host_is_local(v->v_host)) { SU_DEBUG_9(("nua_register: ignoring contact candidate %s:%s.\n", v->v_host, v->v_port ? v->v_port : "")); continue; } nr = su_zalloc(home, sizeof *nr); if (!nr) break; v2[0] = *v; if (pair) /* Don't use protocol if we have both udp and tcp */ protocol = NULL, v2[0].v_next = &v2[1], v2[1] = *pair; else protocol = via->v_protocol, v2[0].v_next = NULL; v2[1].v_next = NULL; contact = nua_handle_contact_by_via(nh, home, 0, v2, protocol, NULL); v = sip_via_dup(home, v2); if (!contact || !v) { su_free(home, nr); break; } nr->nr_ready = 1, nr->nr_default = 1, nr->nr_public = public; nr->nr_secure = contact->m_url->url_type == url_sips; nr->nr_contact = contact; *nr->nr_dcontact = *contact, nr->nr_dcontact->m_params = NULL; nr->nr_via = v; nr->nr_ip4 = host_is_ip4_address(contact->m_url->url_host); nr->nr_ip6 = !nr->nr_ip4 && host_is_ip6_reference(contact->m_url->url_host); SU_DEBUG_9(("nua_register: Adding contact URL '%s' to list.\n", contact->m_url->url_host)); ++nr_items; nr->nr_next = *next, nr->nr_prev = next; *next = nr, next = &nr->nr_next; nr->nr_list = list; } su_home_deinit(autohome); return 0;}staticvoid nua_stack_tport_update(nua_t *nua, nta_agent_t *nta){#if 0 nua_registration_t *default_oc; nua_registration_t const *defaults = nua->nua_registrations; sip_via_t *via = nta_agent_via(nta); default_oc = outbound_by_aor(defaults, NULL, 1); if (default_oc) { assert(default_oc->nr_via); outbound_contacts_from_via(default_oc, via, via->v_next); /* refresh_register(nua_handle_t *nh, nua_dialog_usage_t *du, sip_time_t now); */ }#endif return;}nua_registration_t *nua_registration_by_aor(nua_registration_t const *list, sip_from_t const *aor, url_t const *remote_uri, int only_default){ sip_from_t *alt_aor = NULL, _alt_aor[1]; int sips_aor = aor && aor->a_url->url_type == url_sips; int sips_uri = remote_uri && remote_uri->url_type == url_sips; nua_registration_t const *nr, *public = NULL, *any = NULL; nua_registration_t const *registered = NULL; nua_registration_t const *namewise = NULL, *sipswise = NULL; int ip4 = remote_uri && host_is_ip4_address(remote_uri->url_host); int ip6 = remote_uri && host_is_ip6_reference(remote_uri->url_host); if (only_default || aor == NULL) { /* Ignore AoR, select only by remote_uri */ for (nr = list; nr; nr = nr->nr_next) { if (!nr->nr_ready) continue; if (only_default && !nr->nr_default) continue; if (nr->nr_ip4 && ip6) continue; if (nr->nr_ip6 && ip4) continue; if (sips_uri ? nr->nr_secure : !nr->nr_secure) return (nua_registration_t *)nr; if (!registered && nr->nr_aor) registered = nr; if (!public && nr->nr_public) public = nr; if (!any) any = nr; } if (registered) return (nua_registration_t *)registered; if (public) return (nua_registration_t *)public; if (any) return (nua_registration_t *)any; return NULL; } if (!sips_aor && aor) { alt_aor = memcpy(_alt_aor, aor, sizeof _alt_aor); alt_aor->a_url->url_type = url_sips; alt_aor->a_url->url_scheme = "sips"; } for (nr = list; nr; nr = nr->nr_next) { if (!nr->nr_ready || !nr->nr_contact) continue; if (nr->nr_aor) { if (aor && url_cmp(nr->nr_aor->a_url, aor->a_url) == 0) return (nua_registration_t *)nr; if (!namewise && alt_aor && url_cmp(nr->nr_aor->a_url, aor->a_url) == 0) namewise = nr; } if (!sipswise && ((sips_aor || sips_uri) ? nr->nr_secure : !nr->nr_secure)) sipswise = nr; if (!registered) registered = nr; if (!public && nr->nr_public) public = nr; if (!any) any = nr; } if (namewise) return (nua_registration_t *)namewise; if (sipswise) return (nua_registration_t *)sipswise; if (registered) return (nua_registration_t *)registered; /* XXX - should we do some policing whether sips_aor or sips_uri can be used with sip contact? */ if (public) return (nua_registration_t *)public; if (any) return (nua_registration_t *)any; return NULL;}nua_registration_t *nua_registration_for_request(nua_registration_t const *list, sip_t const *sip){ sip_from_t const *aor; url_t *uri; aor = sip->sip_from; uri = sip->sip_request->rq_url; return nua_registration_by_aor(list, aor, uri, 0);}nua_registration_t *nua_registration_for_response(nua_registration_t const *list, sip_t const *sip, sip_record_route_t const *record_route, sip_contact_t const *remote_contact){ nua_registration_t *nr; sip_to_t const *aor = NULL; url_t const *uri = NULL; if (sip) aor = sip->sip_to; if (record_route) uri = record_route->r_url; else if (sip && sip->sip_record_route) uri = sip->sip_record_route->r_url; else if (remote_contact) uri = remote_contact->m_url; else if (sip && sip->sip_from) uri = sip->sip_from->a_url; nr = nua_registration_by_aor(list, aor, uri, 0); return nr;}/** Return Contact usable in dialogs */sip_contact_t const *nua_registration_contact(nua_registration_t const *nr){ if (nr->nr_by_stack && nr->nr_ob) { sip_contact_t const *m = outbound_dialog_contact(nr->nr_ob); if (m) return m; } if (nr->nr_contact) return nr->nr_dcontact; else return NULL;}/** Return initial route. */sip_route_t const *nua_registration_route(nua_registration_t const *nr){ return nr ? nr->nr_route : NULL;}sip_contact_t const *nua_stack_get_contact(nua_registration_t const *nr){ nr = nua_registration_by_aor(nr, NULL, NULL, 1); return nr && nr->nr_contact ? nr->nr_dcontact : NULL;}/** Add a Contact (and Route) header to request */int nua_registration_add_contact_to_request(nua_handle_t *nh, msg_t *msg, sip_t *sip, int add_contact, int add_service_route){ nua_registration_t *nr = NULL; if (!add_contact && !add_service_route) return 0; if (nh == NULL || msg == NULL) return -1; if (sip == NULL) sip = sip_object(msg); if (nr == NULL) nr = nua_registration_for_request(nh->nh_nua->nua_registrations, sip); return nua_registration_add_contact_and_route(nh, nr, msg, sip, add_contact, add_service_route);}/** Add a Contact header to response. * * @param nh * @param msg response message * @param sip headers in response message * @param record_route record-route from request * @param remote_contact Contact from request */int nua_registration_add_contact_to_response(nua_handle_t *nh, msg_t *msg, sip_t *sip, sip_record_route_t const *record_route, sip_contact_t const *remote_contact){ nua_registration_t *nr = NULL; if (sip == NULL) sip = sip_object(msg); if (nh == NULL || msg == NULL || sip == NULL) return -1; if (nr == NULL) nr = nua_registration_for_response(nh->nh_nua->nua_registrations, sip, record_route, remote_contact); return nua_registration_add_contact_and_route(nh, nr, msg, sip, 1, 0);}/** Add a Contact (and Route) header to request */static int nua_registration_add_contact_and_route(nua_handle_t *nh, nua_registration_t *nr, msg_t *msg, sip_t *sip, int add_contact, int add_service_route){ if (nr == NULL) return -1; if (add_contact) { sip_contact_t const *m = NULL; char const *m_display;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -