Example #1
0
END_TEST

START_TEST(notify_6_3_5)
{
    nua_handle_t *nh;
    struct message *notify;
    struct event *response;
    sip_t *sip;

    S2_CASE("6.3.4", "NOTIFY server - terminate with error response to NOTIFY",
            "NUA receives SUBSCRIBE, sends 202 and NOTIFY. "
            "The subscription terminates when watcher "
            "returns 481 to NOTIFY.");

    nh = subscribe_to_nua("presence", SIPTAG_EXPIRES_STR("300"), TAG_END());

    nua_notify(nh,
               SIPTAG_SUBSCRIPTION_STATE_STR("active"),
               SIPTAG_PAYLOAD_STR(presence_closed),
               TAG_END());
    notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY);
    fail_unless(notify != NULL);
    sip = notify->sip;
    fail_unless(sip->sip_subscription_state != NULL);
    fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate,
                            "active"));
    s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END());
    fail_unless_event(nua_r_notify, 200);

    nua_notify(nh,
               SIPTAG_SUBSCRIPTION_STATE_STR("active"),
               SIPTAG_PAYLOAD_STR(presence_open),
               TAG_END());
    notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY);
    fail_unless(notify != NULL);
    sip = notify->sip;
    fail_unless(sip->sip_subscription_state != NULL);
    fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate,
                            "active"));

    nua_notify(nh,
               NUTAG_NEWSUB(1),
               SIPTAG_SUBSCRIPTION_STATE_STR("active"),
               SIPTAG_PAYLOAD_STR(presence_open),
               TAG_END());

    s2_sip_respond_to(notify, dialog, SIP_481_NO_TRANSACTION, TAG_END());
    response = s2_wait_for_event(nua_r_notify, 481);
    fail_unless(s2_event_substate(response) == nua_substate_terminated);

    notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY);
    s2_sip_respond_to(notify, dialog, SIP_481_NO_TRANSACTION, TAG_END());
    response = s2_wait_for_event(nua_r_notify, 481);
    fail_unless(s2_event_substate(response) == nua_substate_terminated);

    nua_handle_destroy(nh);
}
Example #2
0
/**Compare two SIP addresses ( @From or @To headers).
 *
 * @retval nonzero if matching.
 * @retval zero if not matching.
 */
int sip_addr_match(sip_addr_t const *a, sip_addr_t const *b)
{
  return
    (a->a_tag == NULL || b->a_tag == NULL ||
     su_casematch(a->a_tag, b->a_tag))
    &&
    su_casematch(a->a_host, b->a_host)
    &&
    su_strmatch(a->a_user, b->a_user)
    &&
    su_strmatch(a->a_url->url_scheme, b->a_url->url_scheme);
}
Example #3
0
int nua_subscribe_server_preprocess(nua_server_request_t *sr)
{
  nua_handle_t *nh = sr->sr_owner;
  nua_dialog_state_t *ds = nh->nh_ds;
  nua_dialog_usage_t *du;
  struct notifier_usage *nu;
  sip_t const *sip = sr->sr_request.sip;
  sip_event_t *o = sip->sip_event;
  char const *event = o ? o->o_type : NULL;
  /* Maximum expiration time */
  unsigned long expires = sip->sip_expires ? sip->sip_expires->ex_delta : 3600;
  sip_time_t now = sip_now();
  sip_allow_events_t *appl_event = NH_PGET(nh, appl_event);

  assert(nh && nh->nh_nua->nua_dhandle != nh);

  du = nua_dialog_usage_get(ds, nua_notify_usage, o);

  if (du == NULL) {
    /* Create a new subscription */
    du = nua_dialog_usage_add(nh, ds, nua_notify_usage, o);
    if (du == NULL)
      return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR);
  }
  else if (!msg_header_find_param((void *)appl_event, event)) {
    unsigned max_expires;

    /* Refresh existing subscription */
    if (su_strmatch(event, "refer"))
      max_expires = NH_PGET(nh, refer_expires);
    else
      max_expires = NH_PGET(nh, sub_expires);

    if (expires >= max_expires)
      expires = max_expires;

    SR_STATUS1(sr, SIP_200_OK);
  }

  nu = nua_dialog_usage_private(du);

  if (now + expires >= now)
    nu->nu_requested = now + expires;
  else
    nu->nu_requested = SIP_TIME_MAX - 1;

#if SU_HAVE_EXPERIMENTAL
  nu->nu_etags =
    sip_suppress_body_if_match(sip) ||
    sip_suppress_notify_if_match(sip) ||
    sip_has_feature(sr->sr_request.sip->sip_supported, "etags");
#endif

  sr->sr_usage = du;

  return sr->sr_status <= 100 ? 0 : sr->sr_status;
}
Example #4
0
END_TEST

START_TEST(notify_6_3_2)
{
    nua_handle_t *nh;
    struct message *notify;
    sip_t *sip;

    S2_CASE("6.3.2", "NOTIFY server - automatic subscription termination",
            "NUA receives SUBSCRIBE, sends 202 and NOTIFY. "
            "The subscription terminates with timeout. ");

    nh = subscribe_to_nua("presence", SIPTAG_EXPIRES_STR("300"), TAG_END());

    nua_notify(nh,
               NUTAG_SUBSTATE(nua_substate_active),
               SIPTAG_PAYLOAD_STR(presence_closed),
               TAG_END());
    notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY);
    fail_unless(notify != NULL);
    sip = notify->sip;
    fail_unless(sip->sip_subscription_state != NULL);
    fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate,
                            "active"));
    s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END());
    fail_unless_event(nua_r_notify, 200);

    s2_nua_fast_forward(300, s2base->root);

    notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY);
    fail_unless(notify != NULL);
    sip = notify->sip;
    fail_unless(sip->sip_subscription_state != NULL);
    fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate,
                            "terminated"));
    s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END());
    fail_unless_event(nua_r_notify, 200);

    nua_handle_destroy(nh);
}
Example #5
0
/** Select best mechanism from @SecurityClient header.
 *
 * @note We assume that @SecurityServer header in @a s is sorted by
 * preference.
 */
sip_security_client_t const *
sip_security_client_select(sip_security_client_t const *client,
			   sip_security_server_t const *server)
{
  sip_security_server_t const *c, *s;

  if (server == NULL || client == NULL)
    return NULL;

  for (s = server; s; s = s->sa_next) {
    for (c = client; c; c = c->sa_next) {
      if (su_strmatch(s->sa_mec, c->sa_mec))
	return c;
    }
  }

  return NULL;
}
Example #6
0
/**Perform sanity check on a SIP message
 *
 * Check that the SIP message has all the mandatory fields.
 *
 * @param sip SIP message to be checked
 *
 * @return
 * When the SIP message fulfills the minimum requirements, return zero,
 * otherwise a negative status code.
 */
int
sip_sanity_check(sip_t const *sip)
{
  if (!sip ||
      !((sip->sip_request != NULL) ^ (sip->sip_status != NULL)) ||
      !sip->sip_to ||
      !sip->sip_from ||
      !sip->sip_call_id ||
      !sip->sip_cseq ||
      !sip->sip_via ||
      (sip->sip_flags & MSG_FLG_TRUNC))
    return -1;  /* Bad request */

  if (sip->sip_request) {
    url_t const *ruri = sip->sip_request->rq_url;

    switch (ruri->url_type) {
    case url_invalid:
      return -1;

    case url_sip: case url_sips: case url_im: case url_pres:
      if (!ruri->url_host || strlen(ruri->url_host) == 0)
	return -1;
      break;

    case url_tel:
      if (!ruri->url_user || strlen(ruri->url_user) == 0)
	return -1;
      break;
    }

    if (sip->sip_request->rq_method != sip->sip_cseq->cs_method)
      return -1;

    if (sip->sip_request->rq_method == sip_method_unknown &&
	!su_strmatch(sip->sip_request->rq_method_name,
		     sip->sip_cseq->cs_method_name))
      return -1;
  }

  return 0;
}
Example #7
0
int nua_subscribe_server_init(nua_server_request_t *sr)
{
  nua_handle_t *nh = sr->sr_owner;
  nua_dialog_state_t *ds = nh->nh_ds;
  sip_allow_events_t const *allow_events = NH_PGET(nh, allow_events);
  sip_t const *sip = sr->sr_request.sip;
  sip_event_t *o = sip->sip_event;
  char const *event = o ? o->o_type : NULL;

  if (sr->sr_initial || !nua_dialog_usage_get(ds, nua_notify_usage, o)) {
    if (su_strmatch(event, "refer"))
      /* refer event subscription should be initiated with REFER */
      return SR_STATUS1(sr, SIP_403_FORBIDDEN);

    /* XXX - event is case-sensitive, should use msg_header_find_item() */
    if (!event || !msg_header_find_param(allow_events->k_common, event))
      return SR_STATUS1(sr, SIP_489_BAD_EVENT);
  }

  return 0;
}
Example #8
0
END_TEST

START_TEST(message_6_4_3)
{
    nua_handle_t *nh;
    struct message *message;
    struct event *response;
    sip_call_id_t *i;

    S2_CASE("6.4.1", "SIMPLE MESSAGE",
            "Send MESSAGE");

    nh = nua_handle(nua, NULL, SIPTAG_TO(s2sip->aor), TAG_END());
    nua_message(nh,
                SIPTAG_CONTENT_TYPE_STR("text/plain"),
                SIPTAG_PAYLOAD_STR("hello"),
                TAG_END());
    message = s2_sip_wait_for_request(SIP_METHOD_MESSAGE);
    s2_sip_respond_to(message, NULL,
                      SIP_407_PROXY_AUTH_REQUIRED,
                      SIPTAG_PROXY_AUTHENTICATE_STR(s2_auth_digest_str),
                      TAG_END());
    i = sip_call_id_dup(NULL, message->sip->sip_call_id);
    fail_unless(i != NULL);
    s2_sip_free_message(message);
    fail_unless_event(nua_r_message, 407);

    nua_authenticate(nh, NUTAG_AUTH(s2_auth_credentials), TAG_END());

    message = s2_sip_wait_for_request(SIP_METHOD_MESSAGE);
    s2_sip_respond_to(message, NULL, SIP_202_ACCEPTED, TAG_END());
    fail_unless(su_strmatch(i->i_id, message->sip->sip_call_id->i_id));
    s2_sip_free_message(message);
    response = s2_wait_for_event(nua_r_message, 202);
    s2_free_event(response);

    nua_handle_destroy(nh);
}
Example #9
0
static int test_strmatch(void)
{
  BEGIN();

  TEST_1(!su_strmatch(NULL, ""));
  TEST_1(su_strmatch(NULL, NULL));
  TEST_1(!su_strmatch("", NULL));

  TEST_1(!su_strnmatch(NULL, "", 1));
  TEST_1(su_strnmatch(NULL, NULL, 1));
  TEST_1(!su_strnmatch("", NULL, 1));

  TEST_1(su_strnmatch(NULL, "", 0));
  TEST_1(su_strnmatch(NULL, NULL, 0));
  TEST_1(su_strnmatch("", NULL, 0));

  TEST_1(su_strnmatch("foo", "foo", 3));
  TEST_1(!su_strnmatch("FOO", "foo", 3));
  TEST_1(!su_strnmatch("foo", "FOO", 3));

  TEST_1(su_strnmatch("foo", "foo", 4));
  TEST_1(!su_strnmatch("FOO", "foo", 4));
  TEST_1(!su_strnmatch("foo", "FOO", 4));

  TEST_1(su_strmatch("foo", "foo"));
  TEST_1(!su_strmatch("FOO", "foo"));
  TEST_1(!su_strmatch("foo", "FOO"));

  TEST_1(!su_strmatch("foo_", "foo"));

  TEST_1(su_strnmatch("foo\0X", "foo\0z", 5));
  TEST_1(!su_strnmatch("FOO\0X", "foo\0z", 5));
  TEST_1(!su_strnmatch("foo\0X", "FOO\0z", 5));

  END();
}
Example #10
0
/** Update mode within session.
 *
 * @sa soatag_hold
 *
 * @retval 1 if session was changed (or to be changed, if @a dryrun is nonzero)
 */
static
int soa_sdp_mode_set(sdp_session_t const *user,
		     int const *s2u,
		     sdp_session_t *session,
		     sdp_session_t const *remote,
		     char const *hold,
		     int dryrun)
{
  sdp_media_t *sm;
  sdp_media_t const *rm, *rm_next, *um;
  int retval = 0, i, j;
  int hold_all;
  int inactive_all;
  char const *hold_media = NULL;
  sdp_mode_t send_mode, recv_mode;

  SU_DEBUG_7(("soa_sdp_mode_set(%p, %p, \"%s\"): called\n",
	      (void *)session, (void *)remote, hold ? hold : ""));

  if (!session || !session->sdp_media)
    return 0;

  rm = remote ? remote->sdp_media : NULL, rm_next = NULL;

  hold_all = su_strmatch(hold, "*");
  inactive_all = su_strmatch(hold, "#");

  i = 0;

  for (sm = session->sdp_media; sm; sm = sm->m_next, rm = rm_next, i++) {
    rm_next = rm ? rm->m_next : NULL;

    if (sm->m_rejected)
      continue;

    assert(s2u);

    for (j = 0, um = user->sdp_media; j != s2u[i]; um = um->m_next, j++) {
		if (!um) break;
	}

    if (um == NULL) {
      if (dryrun)
		  return 1;
      else
		  retval = 1;
      sm->m_rejected = 1;
      sm->m_mode = sdp_inactive;
      sm->m_port = 0;
      continue;
    }

    send_mode = (sdp_mode_t)(um->m_mode & sdp_sendonly);
    if (rm)
      send_mode = (rm->m_mode & sdp_recvonly) ? sdp_sendonly : 0;

    recv_mode = (sdp_mode_t)(um->m_mode & sdp_recvonly);

    if (rm && rm->m_mode == sdp_inactive) {
      send_mode = recv_mode = (sdp_mode_t)0;
    }
    else if (inactive_all) {
      send_mode = recv_mode = (sdp_mode_t)0;
    }
    else if (hold_all) {
      recv_mode = (sdp_mode_t)0;
    }
    else if (hold && (hold_media = su_strcasestr(hold, sm->m_type_name))) {
      recv_mode = (sdp_mode_t)0;
      hold_media += strlen(sm->m_type_name);
      hold_media += strspn(hold_media, " \t");
      if (hold_media[0] == '=') {
	hold_media += strspn(hold, " \t");
	if (su_casenmatch(hold_media, "inactive", strlen("inactive")))
	  recv_mode = send_mode = (sdp_mode_t)0;
      }
    }

    if (sm->m_mode != (unsigned)(recv_mode | send_mode)) {
      if (dryrun)
	return 1;
      else
	retval = 1;
      sm->m_mode = recv_mode | send_mode;
    }
  }

  return retval;
}
Example #11
0
END_TEST

START_TEST(notify_6_3_6)
{
    nua_handle_t *nh;
    struct event *subscribe;
    struct message *notify, *response;
    sip_t *sip;

    S2_CASE("6.3.6", "Explicit refresh with NUTAG_APPL_EVENT()",
            "Process subscription refresh by application");

    nua_set_params(nua,
                   NUTAG_APPL_METHOD("SUBSCRIBE"),
                   NUTAG_APPL_EVENT("presence"),
                   SIPTAG_ALLOW_EVENTS_STR("presence"),
                   TAG_END());
    fail_unless_event(nua_r_set_params, 200);

    s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL,
                      SIPTAG_EVENT_STR("presence"),
                      TAG_END());
    subscribe = s2_wait_for_event(nua_i_subscribe, 100);
    nh = subscribe->nh;
    nua_respond(nh, SIP_202_ACCEPTED,
                NUTAG_WITH_SAVED(subscribe->event),
                TAG_END());
    s2_free_event(subscribe);

    response = s2_sip_wait_for_response(202, SIP_METHOD_SUBSCRIBE);
    s2_sip_update_dialog(dialog, response);
    fail_unless(response->sip->sip_expires != NULL);
    s2_sip_free_message(response);

    nua_notify(nh,
               NUTAG_SUBSTATE(nua_substate_active),
               SIPTAG_PAYLOAD_STR(presence_closed),
               TAG_END());
    notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY);
    fail_unless(notify != NULL);
    sip = notify->sip;
    fail_unless(sip->sip_subscription_state != NULL);
    fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate,
                            "active"));
    s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END());

    fail_unless_event(nua_r_notify, 200);

    s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL,
                      SIPTAG_EVENT_STR("presence"),
                      TAG_END());
    subscribe = s2_wait_for_event(nua_i_subscribe, 100);
    nh = subscribe->nh;
    nua_respond(nh, SIP_202_ACCEPTED,
                NUTAG_WITH_SAVED(subscribe->event),
                TAG_END());
    s2_free_event(subscribe);

    response = s2_sip_wait_for_response(202, SIP_METHOD_SUBSCRIBE);
    s2_sip_update_dialog(dialog, response);
    fail_unless(response->sip->sip_expires != NULL);
    s2_sip_free_message(response);

    notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY);
    fail_unless(notify != NULL);
    sip = notify->sip;
    fail_unless(sip->sip_subscription_state != NULL);
    fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate,
                            "active"));
    s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END());

    fail_unless_event(nua_r_notify, 200);

    /* Now clear list of application events */
    nua_set_params(nua,
                   NUTAG_APPL_EVENT(NULL),
                   NUTAG_SUB_EXPIRES(360),
                   TAG_END());
    fail_unless_event(nua_r_set_params, 200);

    s2_sip_request_to(dialog, SIP_METHOD_SUBSCRIBE, NULL,
                      SIPTAG_EVENT_STR("presence"),
                      TAG_END());
    /* Automatically responded && refreshed */
    subscribe = s2_wait_for_event(nua_i_subscribe, 200);
    s2_free_event(subscribe);

    response = s2_sip_wait_for_response(200, SIP_METHOD_SUBSCRIBE);
    s2_sip_update_dialog(dialog, response);
    fail_unless(response->sip->sip_expires != NULL);
    fail_unless(response->sip->sip_expires->ex_delta == 360);
    s2_sip_free_message(response);

    notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY);
    fail_unless(notify != NULL);
    sip = notify->sip;
    fail_unless(sip->sip_subscription_state != NULL);
    fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate,
                            "active"));
    s2_sip_respond_to(notify, dialog, SIP_200_OK, TAG_END());

    fail_unless_event(nua_r_notify, 200);

    nua_handle_destroy(nh);

    notify = s2_sip_wait_for_request(SIP_METHOD_NOTIFY);
    sip = notify->sip;
    fail_unless(sip->sip_subscription_state != NULL);
    fail_unless(su_strmatch(sip->sip_subscription_state->ss_substate,
                            "terminated"));
    s2_sip_respond_to(notify, dialog, SIP_481_NO_TRANSACTION, TAG_END());
}
Example #12
0
int main(int argc, char *argv[])
{
  int i, failed = 0, selected = 0;
  int threading, single_thread, multi_thread;
  char const *xml = NULL;
  Suite *suite = suite_create("Unit tests for Sofia-SIP UA Engine");
  SRunner *runner;

  s2_tester = "check_nua";

  s2_suite("N2");

  if (getenv("CHECK_NUA_VERBOSE"))
    s2_start_stop = strtoul(getenv("CHECK_NUA_VERBOSE"), NULL, 10);

  for (i = 1; argv[i]; i++) {
    if (su_strnmatch(argv[i], "--xml=", strlen("--xml="))) {
      xml = argv[i] + strlen("--xml=");
    }
    else if (su_strmatch(argv[i], "--xml")) {
      if (!(xml = argv[++i]))
	usage(2);
    }
    else if (su_strmatch(argv[i], "-v")) {
      s2_start_stop = 1;
    }
    else if (su_strmatch(argv[i], "-?") ||
	     su_strmatch(argv[i], "-h") ||
	     su_strmatch(argv[i], "--help"))
      usage(0);
    else {
      s2_select_tests(argv[i]);
      selected = 1;
    }
  }

  if (!selected)
    s2_select_tests(getenv("CHECK_NUA_CASES"));

  if (getenv("CHECK_NUA_THREADING")) {
    single_thread = strcmp(getenv("CHECK_NUA_THREADING"), "no");
    multi_thread = !single_thread;
  }
  else {
    single_thread = multi_thread = 1;
  }

  if (single_thread) {
    check_register_cases(suite, threading = 0);
    check_simple_cases(suite, threading = 0);
    check_session_cases(suite, threading = 0);
    check_etsi_cases(suite, threading = 0);
  }

  if (multi_thread) {
    check_register_cases(suite, threading = 1);
    check_session_cases(suite, threading = 1);
    check_etsi_cases(suite, threading = 1);
    check_simple_cases(suite, threading = 1);
  }

  runner = srunner_create(suite);

  if (xml)
    srunner_set_xml(runner, argv[1]);

  srunner_run_all(runner, CK_ENV);
  failed = srunner_ntests_failed(runner);
  srunner_free(runner);

  exit(failed ? EXIT_FAILURE : EXIT_SUCCESS);
}