示例#1
0
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;
}
示例#2
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. */
}