static int process_response_to_keepalive_options(outbound_t *ob, nta_outgoing_t *orq, sip_t const *sip, int status, char const *phrase) { int binding_check; int challenged = 0, credentials = 0; msg_t *_reqmsg = nta_outgoing_getrequest(orq); sip_t *request = sip_object(_reqmsg); msg_destroy(_reqmsg); if (sip == NULL) { SU_DEBUG_3(("outbound(%p): keepalive %u %s\n", (void *)ob->ob_owner, status, phrase)); ob->ob_oo->oo_keepalive_error(ob->ob_owner, ob, status, phrase, TAG_END()); return 0; } if (status == 401 || status == 407) { if (sip->sip_www_authenticate) challenged += auc_challenge(ob->ob_keepalive.auc, ob->ob_home, sip->sip_www_authenticate, sip_authorization_class) > 0; if (sip->sip_proxy_authenticate) challenged += auc_challenge(ob->ob_keepalive.auc, ob->ob_home, sip->sip_proxy_authenticate, sip_proxy_authorization_class) > 0; if (ob->ob_oo->oo_credentials) credentials = ob->ob_oo->oo_credentials(ob->ob_owner, ob->ob_keepalive.auc); } binding_check = outbound_nat_detect(ob, request, sip); if (binding_check > 1) { /* Bindings have changed */ if (outbound_contacts_from_via(ob, sip->sip_via) == 0) { /* XXX - Destroy old keepalive template message */ /* re-REGISTER */ ob->ob_oo->oo_refresh(ob->ob_owner, ob); return 0; } } if (binding_check <= 1 && ob->ob_registered && ob->ob_keepalive.validating) { int failed = 0; unsigned loglevel = 3; if (challenged > 0 && credentials > 0) { keepalive_options_with_registration_probe(ob); return 0; } if (status < 300 && ob->ob_keepalive.validated) { loglevel = 5; if (ob->ob_validated) loglevel = 99; /* only once */ ob->ob_validated = ob->ob_once_validated = 1; } else if (status == 401 || status == 407 || status == 403) loglevel = 5, failed = 1; else loglevel = 3, failed = 1; if (loglevel >= SU_LOG->log_level) { sip_contact_t const *m = ob->ob_rcontact; if (m) su_llog(SU_LOG, loglevel, "outbound(%p): %s <" URL_PRINT_FORMAT ">\n", (void *)ob->ob_owner, failed ? "FAILED to validate" : "validated", URL_PRINT_ARGS(m->m_url)); else su_llog(SU_LOG, loglevel, "outbound(%p): %s registration\n", (void *)ob->ob_owner, failed ? "FAILED to validate" : "validated"); if (failed) su_llog(SU_LOG, loglevel, "outbound(%p): FAILED with %u %s\n", (void *)ob->ob_owner, status, phrase); } if (failed) ob->ob_oo->oo_probe_error(ob->ob_owner, ob, status, phrase, TAG_END()); } else if (status == 408) { SU_DEBUG_3(("outbound(%p): keepalive timeout\n", (void *)ob->ob_owner)); ob->ob_oo->oo_keepalive_error(ob->ob_owner, ob, status, phrase, TAG_END()); return 0; } ob->ob_keepalive.validating = 0; if (ob->ob_keepalive.timer) su_timer_set(ob->ob_keepalive.timer, keepalive_timer, ob); return 0; }
int nua_base_client_check_restart(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_handle_t *nh = cr->cr_owner; nta_outgoing_t *orq; #if 0 if (status == 302 || status == 305) { sip_route_t r[1]; if (!can_redirect(sip->sip_contact, cr->cr_method)) return 0; switch (status) { case 302: if (nua_dialog_zap(nh, nh->nh_ds) == 0 && nua_client_set_target(cr, sip->sip_contact->m_url) >= 0) return nua_client_restart(cr, 100, "Redirected"); break; case 305: sip_route_init(r); *r->r_url = *sip->sip_contact->m_url; if (nua_dialog_zap(nh, nh->nh_ds) == 0 && sip_add_dup(cr->cr_msg, cr->cr_sip, (sip_header_t *)r) >= 0) return nua_client_restart(cr, 100, "Redirected via a proxy"); break; default: break; } } #endif if (status == 423) { unsigned my_expires = 0; if (cr->cr_sip->sip_expires) my_expires = cr->cr_sip->sip_expires->ex_delta; if (sip->sip_min_expires && sip->sip_min_expires->me_delta > my_expires) { sip_expires_t ex[1]; sip_expires_init(ex); ex->ex_delta = sip->sip_min_expires->me_delta; if (sip_add_dup(cr->cr_msg, NULL, (sip_header_t *)ex) < 0) return 0; return nua_client_restart(cr, 100, "Re-Negotiating Expiration"); } } if ((status == 401 && sip->sip_www_authenticate) || (status == 407 && sip->sip_proxy_authenticate)) { int server = 0, proxy = 0; if (sip->sip_www_authenticate) server = auc_challenge(&nh->nh_auth, nh->nh_home, sip->sip_www_authenticate, sip_authorization_class); if (sip->sip_proxy_authenticate) proxy = auc_challenge(&nh->nh_auth, nh->nh_home, sip->sip_proxy_authenticate, sip_proxy_authorization_class); if (server >= 0 && proxy >= 0) { int invalid = cr->cr_challenged && server + proxy == 0; cr->cr_challenged = 1; if (invalid) { /* Bad username/password */ SU_DEBUG_7(("nua(%p): bad credentials, clearing them\n", (void *)nh)); auc_clear_credentials(&nh->nh_auth, NULL, NULL); } else if (auc_has_authorization(&nh->nh_auth)) return nua_client_restart(cr, 100, "Request Authorized by Cache"); orq = cr->cr_orq, cr->cr_orq = NULL; cr->cr_waiting = cr->cr_wait_for_cred = 1; nua_client_report(cr, status, phrase, NULL, orq, NULL); nta_outgoing_destroy(orq); cr->cr_status = 0, cr->cr_phrase = NULL; nua_client_request_unref(cr); return 1; } } if (0 && 500 <= status && status < 600 && sip->sip_retry_after && sip->sip_retry_after->af_delta < 32) { su_timer_t *timer; char phrase[18]; /* Retry After XXXX\0 */ timer = su_timer_create(su_root_task(nh->nh_nua->nua_root), 0); if (su_timer_set_interval(timer, nua_client_restart_after, cr, sip->sip_retry_after->af_delta * 1000) < 0) { su_timer_destroy(timer); return 0; /* Too bad */ } cr->cr_timer = timer; /* This takes over cr reference from orq */ snprintf(phrase, sizeof phrase, "Retry After %u", (unsigned)sip->sip_retry_after->af_delta); orq = cr->cr_orq, cr->cr_orq = NULL; cr->cr_waiting = 1; nua_client_report(cr, 100, phrase, NULL, orq, NULL); nta_outgoing_destroy(orq); cr->cr_status = 0, cr->cr_phrase = NULL; return 1; } return 0; /* This was a final response that cannot be restarted. */ }