コード例 #1
0
ファイル: nua_client.c プロジェクト: Deepwalker/FreeSWITCH
/** Restart request.
 *
 * @retval 1 if restarted
 * @retval 0 otherwise
 */
int nua_client_restart(nua_client_request_t *cr,
		       int status, char const *phrase)
{
  nua_handle_t *nh = cr->cr_owner;
  nta_outgoing_t *orq;
  int error = -1, terminated, graceful;

  if (cr->cr_retry_count > NH_PGET(nh, retry_count))
    return 0;

  orq = cr->cr_orq, cr->cr_orq = NULL;  assert(orq);
  terminated = cr->cr_terminated, cr->cr_terminated = 0;
  graceful = cr->cr_graceful, cr->cr_graceful = 0;

  cr->cr_restarting = 1;
  error = nua_client_request_sendmsg(cr);
  cr->cr_restarting = 0;

  if (error) {
    cr->cr_graceful = graceful;
    cr->cr_terminated = terminated;
    assert(cr->cr_orq == NULL);
    cr->cr_orq = orq;
    return 0;
  }

  nua_client_report(cr, status, phrase, NULL, orq, NULL);

  nta_outgoing_destroy(orq);
  nua_client_request_unref(cr);	/* ... reference used by old orq */

  return 1;
}
コード例 #2
0
ファイル: outbound.c プロジェクト: FreeMCU/freemcu
static int response_to_keepalive_options(outbound_t *ob,
					 nta_outgoing_t *orq,
					 sip_t const *sip)
{
  int status = 408;
  char const *phrase = sip_408_Request_timeout;

  if (sip && sip->sip_status) {
    status = sip->sip_status->st_status;
    phrase = sip->sip_status->st_phrase;
  }

  if (status == 100) {
    /* This probably means that we are in trouble. whattodo, whattodo */
  }

  if (status >= 200) {
    if (orq == ob->ob_keepalive.orq)
      ob->ob_keepalive.orq = NULL;
    process_response_to_keepalive_options(ob, orq, sip, status, phrase);
    nta_outgoing_destroy(orq);
  }

  return 0;
}
コード例 #3
0
END_TEST

START_TEST(client_2_0_1)
{
    nta_outgoing_t *orq;
    struct message *request;
    struct event *response;

    S2_CASE("client-2.0.1", "Send MESSAGE",
            "Basic non-INVITE transaction with "
            "numeric per-transaction outbound proxy");

    orq = nta_outgoing_tcreate(s2->default_leg,
                               s2_nta_orq_callback, NULL,
                               (url_string_t *)s2sip->contact->m_url,
                               SIP_METHOD_MESSAGE,
                               URL_STRING_MAKE("sip:test2.0.example.org"),
                               SIPTAG_FROM_STR("<sip:[email protected]>"),
                               TAG_END());
    fail_unless(orq != NULL);
    request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE);
    fail_unless(request != NULL);
    s2_sip_respond_to(request, NULL, 200, "OK 2.0.1", TAG_END());
    response = s2_nta_wait_for(wait_for_orq, orq,
                               wait_for_status, 200,
                               0);
    s2_sip_free_message(request);
    s2_nta_free_event(response);
    nta_outgoing_destroy(orq);
}
コード例 #4
0
ファイル: nua_client.c プロジェクト: Deepwalker/FreeSWITCH
int
nua_client_request_clean(nua_client_request_t *cr)
{
  if (cr->cr_orq) {
    nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL, cr->cr_acked = 0;
    return nua_client_request_unref(cr);
  }
  return 0;
}
コード例 #5
0
ファイル: outbound.c プロジェクト: FreeMCU/freemcu
void outbound_unref(outbound_t *ob)
{
  if (ob->ob_keepalive.timer)
    su_timer_destroy(ob->ob_keepalive.timer), ob->ob_keepalive.timer = NULL;

  if (ob->ob_keepalive.orq)
    nta_outgoing_destroy(ob->ob_keepalive.orq), ob->ob_keepalive.orq = NULL;

  if (ob->ob_keepalive.msg)
    msg_destroy(ob->ob_keepalive.msg), ob->ob_keepalive.msg = NULL;

  su_home_unref(ob->ob_home);
}
コード例 #6
0
ファイル: outbound.c プロジェクト: FreeMCU/freemcu
void outbound_stop_keepalive(outbound_t *ob)
{
  if (!ob)
    return;

  ob->ob_keepalive.interval = 0;

  if (ob->ob_keepalive.timer)
    su_timer_destroy(ob->ob_keepalive.timer), ob->ob_keepalive.timer = NULL;

  if (ob->ob_keepalive.orq)
    nta_outgoing_destroy(ob->ob_keepalive.orq), ob->ob_keepalive.orq = NULL;

  if (ob->ob_keepalive.msg)
    msg_destroy(ob->ob_keepalive.msg), ob->ob_keepalive.msg = NULL;
}
コード例 #7
0
ファイル: nua_client.c プロジェクト: Deepwalker/FreeSWITCH
static void
nua_client_request_destroy(nua_client_request_t *cr)
{
  nua_handle_t *nh;

  if (cr == NULL)
    return;

  /* Possible references: */
  assert(cr->cr_prev == NULL);	/* queue */
  assert(cr->cr_orq == NULL);	/* transaction callback */
  assert(cr->cr_timer == NULL);	/* timer callback */

  nh = cr->cr_owner;

  nua_destroy_signal(cr->cr_signal);

  nua_client_bind(cr, NULL);

#if HAVE_MEMLEAK_LOG
  SU_DEBUG_0(("%p %s for %s\n", cr, __func__, cr->cr_methods->crm_method_name));
#endif

  if (cr->cr_msg)
    msg_destroy(cr->cr_msg);
  cr->cr_msg = NULL, cr->cr_sip = NULL;

  if (cr->cr_orq)
    nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL;

  if (cr->cr_target)
    su_free(nh->nh_home, cr->cr_target);

  su_free(nh->nh_home, cr);

  nua_handle_unref(nh);
}
コード例 #8
0
END_TEST

START_TEST(client_2_0_2)
{
    nta_outgoing_t *orq;
    struct message *request;
    struct event *response;

    char payload[2048];

    S2_CASE("client-2.0.2", "Send MESSAGE",
            "Basic non-INVITE transaction exceeding "
            "default path MTU (1300 bytes)");

    memset(payload, 'x', sizeof payload);
    payload[(sizeof payload) - 1] = '\0';

    orq = nta_outgoing_tcreate(s2->default_leg,
                               s2_nta_orq_callback, NULL, NULL,
                               SIP_METHOD_MESSAGE,
                               URL_STRING_MAKE("sip:test2.0.example.org"),
                               SIPTAG_FROM_STR("<sip:[email protected]>"),
                               SIPTAG_PAYLOAD_STR(payload),
                               TAG_END());
    fail_unless(orq != NULL);
    request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE);
    fail_unless(request != NULL);
    fail_unless(request->sip->sip_via->v_protocol == sip_transport_tcp);

    s2_sip_respond_to(request, NULL, 200, "OK 2.0.2", TAG_END());
    response = s2_nta_wait_for(wait_for_orq, orq,
                               wait_for_status, 200,
                               0);
    s2_nta_free_event(response);
    nta_outgoing_destroy(orq);
}
コード例 #9
0
ファイル: nua_client.c プロジェクト: Deepwalker/FreeSWITCH
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. */
}
コード例 #10
0
END_TEST

START_TEST(client_2_3_2)
{
    nta_outgoing_t *orq, *tagged, *prack;
    struct message *request, *r_prack, *r_ack;
    sip_t *sip;
    struct event *response;

    S2_CASE("client-2.3.2", "INVITE with 100rel",
            "Forked INVITE transaction with 100rel");

    orq = nta_outgoing_tcreate(leg, s2_nta_orq_callback, NULL, NULL,
                               SIP_METHOD_INVITE,
                               (url_string_t *)s2sip->udp.contact->m_url,
                               SIPTAG_SUPPORTED_STR("100rel"),
                               TAG_END());
    fail_unless(orq != NULL);

    request = s2_sip_wait_for_request(SIP_METHOD_INVITE);
    fail_unless(request != NULL);

    s2_sip_respond_to(request, dialog, SIP_183_SESSION_PROGRESS,
                      SIPTAG_RSEQ_STR("1"),
                      SIPTAG_REQUIRE_STR("100rel"),
                      TAG_END());

    response = s2_nta_wait_for(wait_for_orq, orq,
                               wait_for_status, 183,
                               0);

    sip = response->sip;
    tagged = nta_outgoing_tagged(orq, s2_nta_orq_callback, NULL,
                                 sip->sip_to->a_tag, sip->sip_rseq);
    fail_unless(tagged != NULL);

    fail_unless(nta_leg_rtag(leg, sip->sip_to->a_tag) != NULL);

    prack = nta_outgoing_prack(leg, tagged, s2_nta_orq_callback, NULL,
                               NULL, sip, TAG_END());
    r_prack = s2_sip_wait_for_request(SIP_METHOD_PRACK);
    fail_unless(r_prack != NULL);
    s2_sip_respond_to(r_prack, dialog, SIP_200_OK,
                      TAG_END());
    s2_sip_free_message(r_prack);

    response = s2_nta_wait_for(wait_for_orq, prack,
                               wait_for_status, 200,
                               0);
    fail_unless(response != NULL);

    nta_outgoing_destroy(prack);

    s2_sip_respond_to(request, NULL, SIP_480_TEMPORARILY_UNAVAILABLE, TAG_END());
    s2_nta_free_event(response);
    response = s2_nta_wait_for(wait_for_orq, orq,
                               wait_for_status, 480,
                               0);
    fail_unless(response != NULL);
    s2_nta_free_event(response), response = NULL;
    r_ack = s2_sip_wait_for_request(SIP_METHOD_ACK);
    s2_sip_free_message(r_ack);
    nta_outgoing_destroy(orq), orq = NULL;
    s2_sip_free_message(request);

    /* 408 is eventually received by tagged transaction */
    response = s2_nta_wait_for(wait_for_orq, tagged,
                               wait_for_status, 408,
                               0);
    fail_unless(response != NULL);
    nta_outgoing_destroy(tagged);

    s2_nta_free_event(response);
}
コード例 #11
0
END_TEST

START_TEST(client_2_1_2)
{
    nta_outgoing_t *orq;
    struct message *request;
    struct event *response;
    url_t udpurl[1];

    S2_CASE("client-2.1.2", "Send MESSAGE",
            "Non-INVITE transaction to TCP-only server");

    client_setup_tcp_only_server();

    *udpurl = *s2sip->tcp.contact->m_url;
    udpurl->url_params = "transport=udp";

    /* Create DNS records for both UDP and TCP, resolver matches UDP */
    s2_dns_domain("udptcp.org", 1,
                  "s2", 1, udpurl,
                  "s2", 2, s2sip->tcp.contact->m_url,
                  NULL);

    /* Sent to tport selected by resolver */
    orq = nta_outgoing_tcreate(s2->default_leg,
                               s2_nta_orq_callback, NULL,
                               URL_STRING_MAKE("sip:udptcp.org"),
                               SIP_METHOD_MESSAGE,
                               URL_STRING_MAKE("sip:test2.0.example.org"),
                               SIPTAG_FROM_STR("<sip:[email protected]>"),
                               TAG_END());
    fail_unless(orq != NULL);
    response = s2_nta_wait_for(wait_for_orq, orq,
                               wait_for_status, 503,
                               0);
    s2_nta_free_event(response);
    nta_outgoing_destroy(orq);

    /* Message size exceeds 1300, tries to use TCP even if NAPTR points to UDP */
    orq = nta_outgoing_tcreate(s2->default_leg,
                               s2_nta_orq_callback, NULL,
                               URL_STRING_MAKE("sip:udptcp.org"),
                               SIP_METHOD_MESSAGE,
                               URL_STRING_MAKE("sip:test2.0.example.org"),
                               SIPTAG_FROM_STR("<sip:[email protected]>"),
#define ROW "012345678901234567890123456789012345678901234\n"
                               SIPTAG_PAYLOAD_STR( /* > 1300 bytes */
                                   "0000 " ROW "0050 " ROW
                                   "0100 " ROW "0150 " ROW
                                   "0200 " ROW "0250 " ROW
                                   "0300 " ROW "0350 " ROW
                                   "0400 " ROW "0450 " ROW
                                   "0500 " ROW "0550 " ROW
                                   "0600 " ROW "0650 " ROW
                                   "0700 " ROW "0750 " ROW
                                   "0800 " ROW "0850 " ROW
                                   "0900 " ROW "0950 " ROW
                                   "1000 " ROW "1050 " ROW
                                   "1100 " ROW "1150 " ROW
                                   "1200 " ROW "1250 " ROW
                               ),
#undef ROW
                               TAG_END());
    fail_unless(orq != NULL);
    request = s2_sip_wait_for_request(SIP_METHOD_MESSAGE);
    fail_unless(request != NULL);
    fail_unless(request->sip->sip_via->v_protocol == sip_transport_tcp);
    s2_sip_respond_to(request, NULL, 200, "2.1.2", TAG_END());
    s2_sip_free_message(request);
    response = s2_nta_wait_for(wait_for_orq, orq,
                               wait_for_status, 200,
                               0);
    s2_nta_free_event(response);
    nta_outgoing_destroy(orq);
}