📄 nua_register.c
字号:
ready = du && !cr->cr_terminated && status < 300; if (ready) { sip_time_t mindelta = 0; sip_time_t now = sip_now(), delta, reqdelta, mdelta; sip_contact_t const *m, *sent; msg_t *_reqmsg = nta_outgoing_getrequest(cr->cr_orq); sip_t *req = sip_object(_reqmsg); tport_t *tport; msg_destroy(_reqmsg); assert(nr); assert(sip); assert(req);#if HAVE_SIGCOMP { struct sigcomp_compartment *cc; cc = nta_outgoing_compartment(cr->cr_orq); sigcomp_compartment_unref(nr->nr_compartment); nr->nr_compartment = cc; }#endif /* XXX - if store/remove, remove Content-Disposition Content-Type body */ /** Search for lowest delta of SIP contacts we tried to register */ mindelta = SIP_TIME_MAX; reqdelta = req->sip_expires ? req->sip_expires->ex_delta : 0; for (m = sip->sip_contact; m; m = m->m_next) { if (m->m_url->url_type != url_sip && m->m_url->url_type != url_sips) continue; for (sent = req->sip_contact; sent; sent = sent->m_next) { if (url_cmp(m->m_url, sent->m_url)) continue; if (sent->m_expires) mdelta = strtoul(sent->m_expires, NULL, 10); else mdelta = reqdelta; if (mdelta == 0) mdelta = 3600; delta = sip_contact_expires(m, sip->sip_expires, sip->sip_date, mdelta, now); if (delta > 0 && delta < mindelta) mindelta = delta; if (url_cmp_all(m->m_url, sent->m_url) == 0) break; } } if (mindelta == SIP_TIME_MAX) mindelta = 3600; nua_dialog_usage_set_refresh(du, mindelta); /* RFC 3608 Section 6.1 Procedures at the UA The UA performs a registration as usual. The REGISTER response may contain a Service-Route header field. If so, the UA MAY store the value of the Service-Route header field in an association with the address-of-record for which the REGISTER transaction had registered a contact. If the UA supports multiple addresses-of-record, it may be able to store multiple service routes, one per address-of-record. If the UA refreshes the registration, the stored value of the Service- Route is updated according to the Service-Route header field of the latest 200 class response. If there is no Service-Route header field in the response, the UA clears any service route for that address- of-record previously stored by the UA. If the re-registration request is refused or if an existing registration expires and the UA chooses not to re-register, the UA SHOULD discard any stored service route for that address-of-record. */ su_free(nh->nh_home, nr->nr_route); nr->nr_route = sip_route_dup(nh->nh_home, sip->sip_service_route); { /* RFC 3327 */ /* Store last URI in Path header */ sip_path_t *path = sip->sip_path; while (path && path->r_next) path = path->r_next; if (!nr->nr_path || !path || url_cmp_all(nr->nr_path->r_url, path->r_url)) { su_free(nh->nh_home, nr->nr_path); nr->nr_path = sip_path_dup(nh->nh_home, path); } } if (sip->sip_to->a_url->url_type == url_sips) nr->nr_secure = 1; if (nr->nr_ob) { outbound_gruuize(nr->nr_ob, sip); outbound_start_keepalive(nr->nr_ob, cr->cr_orq); } tport = nta_outgoing_transport (cr->cr_orq); /* cache persistant connection for registration */ if (tport && tport != nr->nr_tport) { if (nr->nr_error_report_id) { if (tport_release(nr->nr_tport, nr->nr_error_report_id, NULL, NULL, nr, 0) < 0) SU_DEBUG_1(("nua_register: tport_release() failed\n")); nr->nr_error_report_id = 0; } tport_unref(nr->nr_tport); nr->nr_tport = tport; if (tport_is_secondary(tport)) { tport_set_params(tport, TPTAG_SDWN_ERROR(1), TAG_END()); nr->nr_error_report_id = tport_pend(tport, NULL, nua_register_connection_closed, nr); } } else tport_unref(tport); /* note: nta_outgoing_transport() makes a ref */ nua_registration_set_ready(nr, 1); } else if (du) { nua_dialog_usage_reset_refresh(du); su_free(nh->nh_home, nr->nr_route); nr->nr_route = NULL; outbound_stop_keepalive(nr->nr_ob); /* release the persistant transport for registration */ if (nr->nr_tport) { if (nr->nr_error_report_id) { if (tport_release(nr->nr_tport, nr->nr_error_report_id, NULL, NULL, nr, 0) < 0) SU_DEBUG_1(("nua_register: tport_release() failed\n")); nr->nr_error_report_id = 0; } tport_unref(nr->nr_tport), nr->nr_tport = NULL; } nua_registration_set_ready(nr, 0); } return nua_base_client_response(cr, status, phrase, sip, NULL);}staticvoid nua_register_connection_closed(tp_stack_t *sip_stack, nua_registration_t *nr, tport_t *tport, msg_t *msg, int error){ nua_dialog_usage_t *du; tp_name_t const *tpn; int pending; assert(nr && tport == nr->nr_tport); if (nr == NULL || tport != nr->nr_tport) return; du = NUA_DIALOG_USAGE_PUBLIC(nr); pending = nr->nr_error_report_id; if (tport_release(tport, pending, NULL, NULL, nr, 0) < 0) SU_DEBUG_1(("nua_register: tport_release() failed\n")); nr->nr_error_report_id = 0; tpn = tport_name(nr->nr_tport); SU_DEBUG_5(("nua_register(%p): tport to %s/%s:%s%s%s closed %s\n", du->du_dialog->ds_owner, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, tpn->tpn_comp ? ";comp=" : "", tpn->tpn_comp ? tpn->tpn_comp : "", error != 0 ? su_strerror(error) : "")); tport_unref(nr->nr_tport), nr->nr_tport = NULL; /* Schedule re-REGISTER immediately */ nua_dialog_usage_set_refresh_range(du, 0, 0);}static voidnua_register_usage_update_params(nua_dialog_usage_t const *du, nua_handle_preferences_t const *changed, nua_handle_preferences_t const *nhp, nua_handle_preferences_t const *dnhp){ nua_registration_t *nr = nua_dialog_usage_private(du); outbound_t *ob = nr->nr_ob; if (!ob) return; if (!changed || NHP_ISSET(changed, outbound) || NHP_ISSET(changed, keepalive) || NHP_ISSET(changed, keepalive_stream)) { char const *outbound = NHP_ISSET(nhp, outbound) ? nhp->nhp_outbound : dnhp->nhp_outbound; unsigned keepalive = NHP_ISSET(nhp, keepalive) ? nhp->nhp_keepalive : dnhp->nhp_keepalive; unsigned keepalive_stream = NHP_ISSET(nhp, keepalive_stream) ? nhp->nhp_keepalive_stream : NHP_ISSET(dnhp, keepalive_stream) ? nhp->nhp_keepalive_stream : keepalive; outbound_set_options(ob, outbound, keepalive, keepalive_stream); } if (!changed || NHP_ISSET(changed, proxy)) { if (NHP_ISSET(nhp, proxy)) outbound_set_proxy(ob, nhp->nhp_proxy); }}static void nua_register_usage_refresh(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du, sip_time_t now){ nua_t *nua = nh->nh_nua; nua_client_request_t *cr = du->du_cr; if (cr) { if (nua_client_resend_request(cr, 0) >= 0) return; } /* Report that we have de-registered */ nua_stack_event(nua, nh, NULL, nua_r_register, NUA_ERROR_AT(__FILE__, __LINE__), NULL); nua_dialog_usage_remove(nh, ds, du, NULL, NULL);}/** @interal Shut down REGISTER usage. * * @retval >0 shutdown done * @retval 0 shutdown in progress * @retval <0 try again later */static int nua_register_usage_shutdown(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du){ nua_client_request_t *cr = du->du_cr; nua_registration_t *nr = NUA_DIALOG_USAGE_PRIVATE(du); if (cr) { if (nua_client_is_queued(cr)) /* Already registering. */ return -1; cr->cr_event = nua_r_unregister; if (nua_client_resend_request(cr, 1) >= 0) return 0; } /* release the persistant transport for registration */ if (nr->nr_tport) tport_decref(&nr->nr_tport), nr->nr_tport = NULL; nua_dialog_usage_remove(nh, ds, du, NULL, NULL); return 200;}/* ---------------------------------------------------------------------- *//* nua_registration_t interface */#if HAVE_SOFIA_STUN#include <sofia-sip/stun.h>#endifstatic void nua_stack_tport_update(nua_t *nua, nta_agent_t *nta);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);intnua_stack_init_transport(nua_t *nua, tagi_t const *tags){ url_string_t const *contact1 = NULL, *contact2 = NULL; char const *name1 = "sip", *name2 = "sip"; char const *certificate_dir = NULL; tl_gets(tags, NUTAG_URL_REF(contact1), NUTAG_SIPS_URL_REF(contact2), NUTAG_CERTIFICATE_DIR_REF(certificate_dir), TAG_END()); if (!contact1 && contact2) contact1 = contact2, contact2 = NULL; if (contact1 && (url_is_string(contact1) ? strncasecmp(contact1->us_str, "sips:", 5) == 0 : contact1->us_url->url_type == url_sips)) name1 = "sips"; if (contact2 && (url_is_string(contact2) ? strncasecmp(contact2->us_str, "sips:", 5) == 0 : contact2->us_url->url_type == url_sips)) name2 = "sips"; if (!contact1 /* && !contact2 */) { if (nta_agent_add_tport(nua->nua_nta, NULL, TPTAG_IDENT("sip"), TPTAG_CERTIFICATE(certificate_dir), TAG_NEXT(nua->nua_args)) < 0 && nta_agent_add_tport(nua->nua_nta, URL_STRING_MAKE("sip:*:*"), TPTAG_IDENT("sip"), TPTAG_CERTIFICATE(certificate_dir), TAG_NEXT(nua->nua_args)) < 0) return -1;#if HAVE_SOFIA_STUN if (stun_is_requested(TAG_NEXT(nua->nua_args)) && nta_agent_add_tport(nua->nua_nta, URL_STRING_MAKE("sip:0.0.0.0:*"), TPTAG_IDENT("stun"), TPTAG_PUBLIC(tport_type_stun), /* use stun */ TPTAG_CERTIFICATE(certificate_dir), TAG_NEXT(nua->nua_args)) < 0) { SU_DEBUG_0(("nua: error initializing STUN transport\n")); }#endif } else { if (nta_agent_add_tport(nua->nua_nta, contact1, TPTAG_IDENT(name1), TPTAG_CERTIFICATE(certificate_dir), TAG_NEXT(nua->nua_args)) < 0) return -1; if (contact2 && nta_agent_add_tport(nua->nua_nta, contact2, TPTAG_IDENT(name2), TPTAG_CERTIFICATE(certificate_dir), TAG_NEXT(nua->nua_args)) < 0) return -1; } if (nua_stack_init_registrations(nua) < 0) return -1; return 0;}#if 0 /* Store network detector param value */ if (agent->sa_nw_updates == 0) agent->sa_nw_updates = nw_updates; NTATAG_DETECT_NETWORK_UPDATES_REF(nw_updates), unsigned nw_updates = 0; unsigned nw_updates = 0; su_network_changed_t *sa_nw_changed;#endifstaticvoid nua_network_changed_cb(nua_t *nua, su_root_t *root){ uint32_t nw_updates = NUA_NW_DETECT_TRY_FULL; switch (nw_updates) { case NUA_NW_DETECT_ONLY_INFO: nua_stack_event(nua, NULL, NULL, nua_i_network_changed, SIP_200_OK, NULL); break; case NUA_NW_DETECT_TRY_FULL: /* 1) Shutdown all tports */ nta_agent_close_tports(nua->nua_nta); /* 2) Create new tports */ if (nua_stack_init_transport(nua, nua->nua_args) < 0) /* We are hosed */ nua_stack_event(nua, NULL, NULL, nua_i_network_changed, 900, "Internal Error", NULL); else nua_stack_event(nua, NULL, NULL, nua_i_network_changed, SIP_200_OK, NULL); break; default: break; } return;}int nua_stack_launch_network_change_detector(nua_t *nua){ su_network_changed_t *snc = NULL; snc = su_root_add_network_changed(nua->nua_home, nua->nua_api_root, nua_network_changed_cb, nua); if (!snc) return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -