📄 nua_register.c
字号:
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 */; contact = sip_contact_create_from_via_with_transport(home, v, NULL, protocol); /* v = sip_via_dup(home, v2); */ if (!contact) { 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_via = v; */ 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 *namewise = NULL, *sipswise = NULL; 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 (sips_uri ? nr->nr_secure : !nr->nr_secure) return (nua_registration_t *)nr; if (!public && nr->nr_public) public = nr; if (!any) any = nr; } 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); for (nr = list; nr; nr = nr->nr_next) { if (!nr->nr_ready) 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 (!public && nr->nr_public) public = nr; if (!any) any = nr; } if (namewise) return (nua_registration_t *)namewise; if (sipswise) return (nua_registration_t *)sipswise; /* 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_msg(nua_registration_t const *list, sip_t const *sip){ sip_from_t const *aor; url_t *uri; if (sip == NULL) return NULL; if (sip->sip_request) { aor = sip->sip_from; uri = sip->sip_request->rq_url; } else { /* This is much hairier! */ aor = sip->sip_to; if (sip->sip_record_route) uri = sip->sip_record_route->r_url; else if (sip->sip_contact) uri = sip->sip_contact->m_url; else uri = sip->sip_from->a_url; assert(uri != ((sip_contact_t *)NULL)->m_url); } return nua_registration_by_aor(list, aor, uri, 0);}/** 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; } return nr->nr_contact;}/** 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 : NULL;}/** Add a Contact (and Route) header to request (or response) */int nua_registration_add_contact(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_msg(nh->nh_nua->nua_registrations, sip); if (nr == NULL) return -1; if (add_contact) { sip_contact_t const *m = nua_registration_contact(nr); if (!m || msg_header_add_dup(msg, (msg_pub_t *)sip, (void const *)m) < 0) return -1; } if (add_service_route && !sip->sip_status) { sip_route_t const *sr = nua_registration_route(nr); if (msg_header_add_dup(msg, (msg_pub_t *)sip, (void const *)sr) < 0) return -1; } return 0;}/** Add a registration to list of contacts */int nua_registration_add(nua_registration_t **list, nua_registration_t *nr){ assert(list && nr); if (nr->nr_list == NULL) { nua_registration_t *next = *list; if (next) next->nr_prev = &nr->nr_next; nr->nr_next = next, nr->nr_prev = list, nr->nr_list = list; *list = nr; } return 0;}/** Remove from list of registrations */void nua_registration_remove(nua_registration_t *nr){ if ((*nr->nr_prev = nr->nr_next)) nr->nr_next->nr_prev = nr->nr_prev; nr->nr_next = NULL, nr->nr_prev = NULL, nr->nr_list = NULL;}/** Set address-of-record. */int nua_registration_set_aor(su_home_t *home, nua_registration_t *nr, sip_from_t const *aor){ sip_from_t *new_aor, *old_aor; if (!home || !nr || !aor) return -1; new_aor = sip_from_dup(home, aor); if (!new_aor) return -1; old_aor = nr->nr_aor; nr->nr_aor = new_aor; msg_header_free(home, (void *)old_aor); return 0;}/** Set contact. */int nua_registration_set_contact(su_home_t *home, nua_registration_t *nr, sip_contact_t const *application_contact, int terminating){ sip_contact_t *m = NULL, *previous; url_t *uri; if (!home || !nr) return -1; uri = nr->nr_aor ? nr->nr_aor->a_url : NULL; previous = nr->nr_contact; if (application_contact) { m = sip_contact_dup(home, application_contact); } else if (terminating && nr->nr_contact) { return 0; } else { nua_registration_t *nr0; nr0 = nua_registration_by_aor(*nr->nr_list, NULL, uri, 1); if (nr0) m = sip_contact_dup(home, nr0->nr_contact); } if (!m) return -1; nr->nr_contact = m; nr->nr_by_stack = !application_contact; msg_header_free(home, (void *)previous); return 0;}/** Mark registration as ready */void nua_registration_set_ready(nua_registration_t *nr, int ready){ nr->nr_ready = ready;}/** @internal Hook for processing incoming request by registration. * * This is used for keepalive/validate OPTIONS. */int nua_registration_process_request(nua_registration_t *list, nta_incoming_t *irq, sip_t const *sip){ sip_call_id_t *i; nua_registration_t *nr; if (!outbound_targeted_request(sip)) return 0; /* Process by outbound... */ i = sip->sip_call_id; for (nr = list; nr; nr = nr->nr_next) { outbound_t *ob = nr->nr_ob; if (ob) if (outbound_process_request(ob, irq, sip)) return 501; /* Just in case */ } return 481; /* Call/Transaction does not exist */}/**@internal * Fix contacts for un-REGISTER. * * Remove (possible non-zero) "expires" parameters from contacts and extra * contacts, add Expire: 0. */staticvoid unregister_expires_contacts(msg_t *msg, sip_t *sip){ sip_contact_t *m; int unregister_all; if (msg == NULL || sip == NULL) return; /* Remove payload */ while (sip->sip_payload) sip_header_remove(msg, sip, (sip_header_t *)sip->sip_payload); while (sip->sip_content_type) sip_header_remove(msg, sip, (sip_header_t *)sip->sip_content_type); for (m = sip->sip_contact; m; m = m->m_next) { if (m->m_url->url_type == url_any) break; msg_header_remove_param(m->m_common, "expires");#if 0 msg_header_add_param(msg_home(msg), m->m_common, "expires=0");#endif } unregister_all = m && (m != sip->sip_contact || m->m_next); sip_add_tl(msg, sip, /* Remove existing contacts */ TAG_IF(unregister_all, SIPTAG_CONTACT(NONE)), /* Add '*' contact: 0 */ TAG_IF(unregister_all, SIPTAG_CONTACT_STR("*")), SIPTAG_EXPIRES_STR("0"), TAG_END());}/** Outbound requests us to refres registration */static int nua_stack_outbound_refresh(nua_handle_t *nh, outbound_t *ob){ nua_dialog_usage_t *du = nua_dialog_usage_get(nh->nh_ds, nua_register_usage, NULL); if (du) nua_dialog_usage_refresh(nh, du, 1); return 0;}/** @internal Callback from outbound_t */static int nua_stack_outbound_status(nua_handle_t *nh, outbound_t *ob, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...){ ta_list ta; ta_start(ta, tag, value); nua_stack_event(nh->nh_nua, nh, NULL, nua_i_outbound, status, phrase, ta_tags(ta)); ta_end(ta); return 0;}/** @internal Callback from outbound_t */static int nua_stack_outbound_failed(nua_handle_t *nh, outbound_t *ob, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...){ ta_list ta; ta_start(ta, tag, value); nua_stack_event(nh->nh_nua, nh, NULL, nua_i_outbound, status, phrase, ta_tags(ta)); ta_end(ta); return 0;}/** @internal Callback for obtaining credentials for keepalive */static int nua_stack_outbound_credentials(nua_handle_t *nh, auth_client_t **auc){ return auc_copy_credentials(auc, nh->nh_auth);}/** @internal Return a string describing our features. */static char *nua_handle_features(nua_handle_t *nh){ char *retval = NULL; su_strlst_t *l = su_strlst_create(NULL); su_home_t *home = su_strlst_home(l); if (!l) return NULL; if (NH_PGET(nh, callee_caps)) { sip_allow_t const *allow = NH_PGET(nh, allow); if (allow) { /* Skip ";" if this is first one */ su_strlst_append(l, ";methods=\"" + (su_strlst_len(l) == 0)); if (allow->k_items) { int i; for (i = 0; allow->k_items[i]; i++) { su_strlst_append(l, allow->k_items[i]); if (allow->k_items[i + 1]) su_strlst_append(l, ","); } } su_strlst_append(l, "\""); } if (nh->nh_soa) { char **media = soa_media_features(nh->nh_soa, 0, home); while (*media) { if (su_strlst_len(l)) su_strlst_append(l, ";"); su_strlst_append(l, *media++); } } } if (su_strlst_len(l)) retval = su_strlst_join(l, nh->nh_home, ""); su_strlst_destroy(l); return retval;}static int nua_stack_outbound_features(nua_handle_t *nh, outbound_t *ob){ char *features; int retval; if (!nh) return -1; if (!ob) return 0; features = nua_handle_features(nh); retval = outbound_set_features(ob, features); su_free(nh->nh_home, features); return retval;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -