📄 nua_register.c
字号:
* fields of dialog-establishing messages, such as INVITE or SUBSCRIBE. * Also, if the registrar has included a Service-Route header in the * response, and the service route feature has not been disabled using * NUTAG_SERVICE_ROUTE_ENABLE(), the route URIs from the Service-Route * header will be used for initial non-REGISTER requests. * * The #nua_r_register message will include the contact header and route * used in with the registration. * * @par Registration Keep-Alive * * After the registration has successfully completed the nua_register() will * validate the registration and initiate the keepalive mechanism, too. The * user-agent validates the registration by sending a OPTIONS requests to * itself. If there is an error, nua_register() will indicate that to the * application using #nua_i_outbound event, and start unregistration * procedure (unless that has been explicitly disabled). * * You can disable validation by inserting "no-validate" into * NUTAG_OUTBOUND() string. * * The keepalive mechanism depends on the network features detected earlier. * If @a outbound extension is used, the STUN keepalives will be used. * Otherwise, NUA stack will repeatedly send OPTIONS requests to itself. In * order to save bandwidth, it will include Max-Forwards: 0 in the * keep-alive requests, however. The keepalive interval is determined by * NUTAG_KEEPALIVE() parameter. If the interval is 0, no keepalive messages * is sent. * * You can disable keepalive OPTIONS by inserting "no-options-keepalive" * into NUTAG_OUTBOUND() string. Currently there are no other keepalive * mechanisms available. * * The value of NUTAG_KEEPALIVE_STREAM(), if specified, is used to indicate * the desired transport-layer keepalive interval for stream-based * transports like TLS and TCP. * * As alternative to OPTIONS/STUN keepalives, the client can propose * a more frequent registration refresh interval with * NUTAG_M_FEATURES() (e.g. NUTAG_M_FEATURES("expires=120") given as * parameter to nua_register()). * * @sa #nua_r_register, nua_unregister(), #nua_r_unregister, * #nua_i_register, * @RFC3261 section 10, * @Expires, @Contact, @CallID, @CSeq, * @Path, @RFC3327, @ServiceRoute, @RFC3608, @RFC3680, * NUTAG_REGISTRAR(), NUTAG_INSTANCE(), NUTAG_OUTBOUND(), * NUTAG_KEEPALIVE(), NUTAG_KEEPALIVE_STREAM(), * SIPTAG_CONTACT(), SIPTAG_CONTACT_STR(), NUTAG_M_USERNAME(), * NUTAG_M_DISPLAY(), NUTAG_M_PARAMS(), NUTAG_M_FEATURES(), *//** @NUA_EVENT nua_r_register * * Response to an outgoing REGISTER. * * The REGISTER may be sent explicitly by nua_register() or implicitly by * NUA state machines. * * When REGISTER request has been restarted the @a status may be 100 even * while the real response status returned is different. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the registration * @param hmagic application context associated with the registration * @param sip response message to REGISTER request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags empty * * @sa nua_register(), nua_unregister(), #nua_r_unregister, * @Contact, @CallID, @CSeq, @RFC3261 section 10, * @Path, @RFC3327, @ServiceRoute, @RFC3608, @RFC3680 * * @END_NUA_EVENT *//**@fn void nua_unregister(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * Unregister. * * Send a REGISTER request with expiration time 0. This removes the * registration from the registrar. If the handle was earlier used * with nua_register() the periodic updates will be terminated. * * If a SIPTAG_CONTACT_STR() with argument "*" is used, all the * registrations will be removed from the registrar otherwise only the * contact address belonging to the NUA stack is removed. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * * @return * nothing * * @par Related tags: * NUTAG_REGISTRAR() \n * Header tags defined in <sofia-sip/sip_tag.h> except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR() * * @par Events: * #nua_r_unregister * * @sa nua_register(), #nua_r_register, nua_handle_destroy(), nua_shutdown(), * #nua_i_register, * @Expires, @Contact, @CallID, @CSeq, @RFC3261 section 10, * @Path, @RFC3327, @ServiceRoute, @RFC3608, @RFC3680, * NUTAG_REGISTRAR(), NUTAG_INSTANCE(), NUTAG_OUTBOUND(), * NUTAG_KEEPALIVE(), NUTAG_KEEPALIVE_STREAM(), * SIPTAG_CONTACT(), SIPTAG_CONTACT_STR(), NUTAG_M_USERNAME(), * NUTAG_M_DISPLAY(), NUTAG_M_PARAMS(), NUTAG_M_FEATURES(), *//** @NUA_EVENT nua_r_unregister * * Answer to outgoing un-REGISTER. * * @param status response status code * (if the request is retried, @a status is 100, the @a * sip->sip_status->st_status contain the real status code * from the response message, e.g., 302, 401, or 407) * @param phrase a short textual description of @a status code * @param nh operation handle associated with the registration * @param hmagic application context associated with the registration * @param sip response message to REGISTER request or NULL upon an error * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags empty * * @sa nua_unregister(), nua_register(), #nua_r_register, * @Contact, @CallID, @CSeq, @RFC3261 section 10, * @Path, @RFC3327, @ServiceRoute, @RFC3608, @RFC3680 * * @END_NUA_EVENT */static int nua_register_client_template(nua_client_request_t *cr, msg_t **return_msg, tagi_t const *tags);static int nua_register_client_init(nua_client_request_t *cr, msg_t *, sip_t *, tagi_t const *tags);static int nua_register_client_request(nua_client_request_t *cr, msg_t *, sip_t *, tagi_t const *tags);static int nua_register_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip);static int nua_register_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip);static nua_client_methods_t const nua_register_client_methods = { SIP_METHOD_REGISTER, /* crm_method, crm_method_name */ 0, /* crm_extra */ { /* crm_flags */ /* create_dialog */ 1, /* in_dialog */ 0, /* target refresh */ 0 }, nua_register_client_template, /* crm_template */ nua_register_client_init, /* crm_init */ nua_register_client_request, /* crm_send */ nua_register_client_check_restart, /* crm_check_restart */ nua_register_client_response, /* crm_recv */ NULL, /* crm_preliminary */ NULL, /* crm_report */ NULL, /* crm_complete */};/**@internal Send REGISTER. */int nua_stack_register(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags){ return nua_client_create(nh, e, &nua_register_client_methods, tags);}static int nua_register_client_template(nua_client_request_t *cr, msg_t **return_msg, tagi_t const *tags){ nua_dialog_usage_t *du; if (cr->cr_event == nua_r_register) return 0; /* Use a copy of REGISTER message as the template for un-REGISTER */ du = nua_dialog_usage_get(cr->cr_owner->nh_ds, nua_register_usage, NULL); if (du && du->du_cr) { if (nua_client_set_target(cr, du->du_cr->cr_target) < 0) return -1; *return_msg = msg_copy(du->du_cr->cr_msg); return 1; } return 0;}static int nua_register_client_init(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags){ nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du; nua_registration_t *nr; sip_to_t const *aor = sip->sip_to; int unreg; /* Explicit empty (NULL) contact - used for CPL store/remove? */ if (!sip->sip_contact && cr->cr_has_contact) /* Do not create any usage */ return 0; unreg = cr->cr_event != nua_r_register || (sip->sip_expires && sip->sip_expires->ex_delta == 0); if (unreg) nua_client_terminating(cr); du = nua_dialog_usage_add(nh, nh->nh_ds, nua_register_usage, NULL); if (du == NULL) return -1; nr = nua_dialog_usage_private(du); if (nua_client_bind(cr, du) < 0) return -1; if (!nr->nr_list) { nua_registration_add(&nh->nh_nua->nua_registrations, nr); if (aor == NULL) aor = sip->sip_from; if (aor == NULL) aor = nh->nh_nua->nua_from; if (nua_registration_set_aor(nh->nh_home, nr, aor) < 0) return -1; } if (nua_registration_set_contact(nh, nr, sip->sip_contact, unreg) < 0) return -1; if (!nr->nr_ob && (NH_PGET(nh, outbound) || NH_PGET(nh, instance))) { nr->nr_ob = outbound_new(nh, &nua_stack_outbound_callbacks, nh->nh_nua->nua_root, nh->nh_nua->nua_nta, NH_PGET(nh, instance)); if (!nr->nr_ob) return nua_client_return(cr, 900, "Cannot create outbound", msg); nua_register_usage_update_params(du, NULL, nh->nh_prefs, nh->nh_dprefs); } if (nr->nr_ob) { outbound_t *ob = nr->nr_ob; sip_contact_t *m; if (!unreg && sip->sip_contact) { for (m = sip->sip_contact; m; m = m->m_next) if (!m->m_expires || strtoul(m->m_expires, NULL, 10) != 0) break; if (m == NULL) unreg = 1; /* All contacts have expires=0 */ } if (outbound_set_contact(ob, sip->sip_contact, nr->nr_via, unreg) < 0) return nua_client_return(cr, 900, "Cannot set outbound contact", msg); } return 0;}staticint nua_register_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags){ nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_registration_t *nr; sip_contact_t *m, *contacts = sip->sip_contact; char const *min_expires = NULL; int unreg; tport_t *tport = NULL; (void)nh; /* Explicit empty (NULL) contact - used for CPL store/remove? */ if (!contacts && cr->cr_has_contact) return nua_base_client_request(cr, msg, sip, tags); if ((du && du->du_shutdown) || (sip->sip_expires && sip->sip_expires->ex_delta == 0)) nua_client_terminating(cr); if (contacts) { if (!cr->cr_terminating) { for (m = contacts; m; m = m->m_next) if (!m->m_expires || strtoul(m->m_expires, NULL, 10) != 0) break; /* All contacts have expires=0 */ if (m == NULL) nua_client_terminating(cr); } } unreg = cr->cr_terminating; nr = nua_dialog_usage_private(du); if (nr) { if (nr->nr_ob) { outbound_stop_keepalive(nr->nr_ob); outbound_start_registering(nr->nr_ob); } if (nr->nr_by_stack) { sip_contact_t *m = nr->nr_contact, *previous = NULL; outbound_get_contacts(nr->nr_ob, &m, &previous); sip_add_dup(msg, sip, (sip_header_t *)m); /* previous is an outdated contact generated by stack * and it is now unregistered */ if (previous) sip_add_dup(msg, sip, (sip_header_t *)previous); } tport = nr->nr_tport; } for (m = sip->sip_contact; m; m = m->m_next) { if (m->m_url->url_type == url_any) { /* If there is a '*' in contact list, remove everything else */ while (m != sip->sip_contact) sip_header_remove(msg, sip, (sip_header_t *)sip->sip_contact); while (m->m_next) sip_header_remove(msg, sip, (sip_header_t *)m->m_next); contacts = m; break; } if (!m->m_expires) continue; if (unreg) { /* Remove the expire parameters from contacts */ msg_header_remove_param(m->m_common, "expires"); } else if (nr && nr->nr_min_expires && strtoul(m->m_expires, 0, 10) < nr->nr_min_expires) { if (min_expires == NULL) min_expires = su_sprintf(msg_home(msg), "expires=%lu", nr->nr_min_expires); msg_header_replace_param(msg_home(msg), m->m_common, min_expires); } } return nua_base_client_trequest(cr, msg, sip, TAG_IF(unreg, SIPTAG_EXPIRES_STR("0")),#if 0 TAG_IF(unreg, NTATAG_SIGCOMP_CLOSE(1)), TAG_IF(!unreg, NTATAG_COMP("sigcomp")),#endif NTATAG_TPORT(tport), TAG_NEXT(tags));}static int nua_register_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip){ nua_registration_t *nr = nua_dialog_usage_private(cr->cr_usage); unsigned short retry_count = cr->cr_retry_count; int restart = 0, retry; if (nr && nr->nr_ob) { msg_t *_reqmsg = nta_outgoing_getrequest(cr->cr_orq); sip_t *req = sip_object(_reqmsg); msg_destroy(_reqmsg); retry = outbound_register_response(nr->nr_ob, cr->cr_terminating, req, sip); restart = retry >= ob_reregister_now; if (retry == ob_reregister) /* outbound restarts REGISTER later */; if (retry < 0) /* XXX - report an error? */; } if (nr && status == 423) { if (sip->sip_min_expires) nr->nr_min_expires = sip->sip_min_expires->me_delta; } /* Check for status-specific reasons to retry */ if (nua_base_client_check_restart(cr, status, phrase, sip)) return 1; /* Restart only if nua_base_client_check_restart() did not try to restart */ if (restart && retry_count == cr->cr_retry_count) return nua_client_restart(cr, 100, "Outbound NAT Detected"); return 0;}static int nua_register_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip){ nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; nua_registration_t *nr = nua_dialog_usage_private(du); int ready;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -