Commit af3c5f89 authored by Pekka Pessi's avatar Pekka Pessi

test_nua: added a few tests for 200 OK timeout / ACK failing.

darcs-hash:20070201194306-65a35-dd94b1659b7836715bb9ae265b4aeca9927aefe6.gz
parent 3e418f2b
......@@ -945,3 +945,312 @@ int test_mime_negotiation(struct context *ctx)
END();
}
/* ---------------------------------------------------------------------- */
int filter_200_OK(void const *message, size_t len)
{
return len >= 11 && strncasecmp(message, "SIP/2.0 200", 11) == 0;
}
int filter_ACK(void const *message, size_t len)
{
return len >= 7 && strncasecmp(message, "ACK sip", 7) == 0;
}
int call_with_bad_ack(CONDITION_PARAMS);
int accept_call_with_bad_contact(CONDITION_PARAMS);
int test_call_timeouts(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call, *b_call = b->call;
struct event *e;
struct nat_filter *f;
if (print_headings)
printf("TEST NUA-4.7: check for error and timeout handling\n");
a_call->sdp = "m=audio 5008 RTP/AVP 8";
b_call->sdp = "m=audio 5010 RTP/AVP 0 8";
if (!ctx->nat)
goto completed_4_7_1;
if (print_headings)
printf("TEST NUA-4.7.1: ACK timeout (200 OK filtered)\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
TEST_1(f = test_nat_add_filter(ctx->nat, filter_200_OK, nat_inbound));
INVITE(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
SIPTAG_SUBJECT_STR("NUA-4.7.1"),
SOATAG_USER_SDP_STR(a_call->sdp),
TAG_END());
run_ab_until(ctx, -1, until_terminated, -1, accept_call);
/*
A accept_call B
| |
|-------INVITE------>|
|<----100 Trying-----|
| |
|<----180 Ringing----|
| |
| X-----200--------|
| X-----200--------|
| X-----200--------|
| |
|<--------BYE--------|
|--------200 OK----->|
*/
/*
Client transitions:
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
TEST(e->data->e_status, 180);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_proceeding); /* PROCEEDING */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_bye);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */
TEST_1(!e->next);
/*
Server transitions:
-(S1)-> RECEIVED -(S2a)-> EARLY -(S3b)-> COMPLETED -(S5)-> TERMINATING
-(S10)-> TERMINATED -X
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_invite);
TEST(e->data->e_status, 100);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */
TEST_1(is_offer_recv(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_early); /* EARLY */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_completed); /* COMPLETED */
TEST_1(is_answer_sent(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_error);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminating); /* TERMINATING */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_bye);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
free_events_in_list(ctx, b->events);
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
TEST_1(test_nat_remove_filter(ctx->nat, f) == 0);
if (print_headings)
printf("TEST NUA-4.7.1: PASSED\n");
completed_4_7_1:
if (!ctx->nat)
goto completed_4_7_2;
if (print_headings)
printf("TEST NUA-4.7.2: ACK timeout (ACK filtered)\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
TEST_1(f = test_nat_add_filter(ctx->nat, filter_ACK, nat_outbound));
INVITE(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
SIPTAG_SUBJECT_STR("NUA-4.7.2"),
SOATAG_USER_SDP_STR(a_call->sdp),
TAG_END());
run_ab_until(ctx, -1, until_terminated, -1, accept_call);
/*
A accept_call B
| |
|-------INVITE------>|
|<----100 Trying-----|
| |
|<----180 Ringing----|
| |
|<--------200--------|
|--------ACK-----X |
| |
|<--------200--------|
|--------ACK-----X |
| |
|<--------200--------|
|--------ACK-----X |
| |
|<--------BYE--------|
|--------200 OK----->|
*/
/*
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
TEST(e->data->e_status, 180);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_proceeding);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
TEST(e->data->e_status, 200);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_bye);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminated);
TEST_1(!e->next);
/*
Server transitions:
-(S1)-> RECEIVED -(S2a)-> EARLY -(S3b)-> COMPLETED -(S5)-> TERMINATING
-(S10)-> TERMINATED -X
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_invite);
TEST(e->data->e_status, 100);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */
TEST_1(is_offer_recv(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_early); /* EARLY */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_completed); /* COMPLETED */
TEST_1(is_answer_sent(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_error);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminating); /* TERMINATING */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_bye);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
free_events_in_list(ctx, b->events);
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
TEST_1(test_nat_remove_filter(ctx->nat, f) == 0);
if (print_headings)
printf("TEST NUA-4.7.2: PASSED\n");
completed_4_7_2:
if (print_headings)
printf("TEST NUA-4.7.3: sending ACK fails\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
INVITE(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
SIPTAG_SUBJECT_STR("NUA-4.7.3"),
SOATAG_USER_SDP_STR(a_call->sdp),
NUTAG_AUTOACK(0),
TAG_END());
run_ab_until(ctx, -1, call_with_bad_ack, -1, accept_call);
/*
A accept_call B
| |
|-------INVITE------>|
|<----100 Trying-----|
| |
|<----180 Ringing----|
| |
|<--------200--------|
|--ACK-X |
| |
|---------BYE------->|
|<-------200 OK------|
*/
/*
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
TEST(e->data->e_status, 180);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_proceeding);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
TEST(e->data->e_status, 200);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_completing); /* COMPLETING */
/* try to send ACK */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminating);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_bye);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminated);
TEST_1(!e->next);
/*
Server transitions:
-(S1)-> RECEIVED -(S2a)-> EARLY -(S3b)-> COMPLETED -(S5)-> TERMINATING
-(S10)-> TERMINATED -X
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_invite);
TEST(e->data->e_status, 100);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */
TEST_1(is_offer_recv(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_early); /* EARLY */
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_completed); /* COMPLETED */
TEST_1(is_answer_sent(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_bye);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
free_events_in_list(ctx, b->events);
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
if (print_headings)
printf("TEST NUA-4.7.3: PASSED\n");
/* XXX - PRACK timeout, PRACK failing, media failing, re-INVITEs */
if (print_headings)
printf("TEST NUA-4.7: PASSED\n");
END();
}
int call_with_bad_ack(CONDITION_PARAMS)
{
if (!check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR))
return 0;
save_event_in_list(ctx, event, ep, call);
if (event == nua_r_invite && 200 <= status && status < 300) {
ACK(ep, call, nh,
/* Syntax error - sending ACK fails, we send BYE */
SIPTAG_MAX_FORWARDS_STR("blue"),
TAG_END());
}
return event == nua_i_state && callstate(tags) == nua_callstate_terminated;
}
......@@ -224,7 +224,7 @@ int test_nua_init(struct context *ctx,
NUTAG_URL(a_bind),
TAG_IF(a_bind != a_bind2, NUTAG_SIPS_URL(a_bind2)),
SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"),
NTATAG_SIP_T1X64(4000),
NTATAG_SIP_T1X64(2000),
NUTAG_INSTANCE(ctx->a.instance),
TAG_IF(ctx->a.logging, TPTAG_LOG(1)),
TAG_END());
......@@ -262,6 +262,8 @@ int test_nua_init(struct context *ctx,
NUTAG_URL("sip:0.0.0.0:*"),
SOATAG_USER_SDP_STR("m=audio 5006 RTP/AVP 8 0"),
NUTAG_INSTANCE(ctx->b.instance),
/* Quicker timeout */
NTATAG_SIP_T1X64(2000),
TAG_IF(ctx->b.logging, TPTAG_LOG(1)),
TAG_END());
TEST_1(ctx->b.nua);
......
......@@ -91,6 +91,8 @@ struct nat {
struct binding *bindings;
struct nat_filter *in_filters, *out_filters;
/* True if we act in symmetric way */
int symmetric;
/* True if we do logging */
......@@ -153,6 +155,14 @@ static int tcp_out_to_in(struct nat *, su_wait_t *wait, struct binding *);
static int invalidate_binding(struct binding *b);
LIST_PROTOS(static, nat_filter, struct nat_filter);
struct nat_filter
{
struct nat_filter *next, **prev;
int (*condition)(void const *message, size_t len);
};
/* nat entry point */
static int
test_nat_init(su_root_t *root, struct nat *nat)
......@@ -670,6 +680,7 @@ static int udp_in_to_out(struct nat *nat, su_wait_t *wait, struct binding *b)
{
int events;
ssize_t n, m;
struct nat_filter *f;
events = su_wait_events(wait, b->in_socket);
......@@ -679,6 +690,15 @@ static int udp_in_to_out(struct nat *nat, su_wait_t *wait, struct binding *b)
return 0;
}
for (f = nat->out_filters; f; f = f->next) {
if (f->condition(nat->buffer, (size_t)n)) {
if (nat->logging)
printf("nat: udp filtered %d %s => %s\n",
(int)n, b->in_name, b->out_name);
return 0;
}
}
if (nat->symmetric)
m = su_send(b->out_socket, nat->buffer, n, 0);
else
......@@ -696,6 +716,7 @@ static int udp_out_to_in(struct nat *nat, su_wait_t *wait, struct binding *b)
{
int events;
ssize_t n, m;
struct nat_filter *f;
events = su_wait_events(wait, b->out_socket);
......@@ -705,6 +726,15 @@ static int udp_out_to_in(struct nat *nat, su_wait_t *wait, struct binding *b)
return 0;
}
for (f = nat->in_filters; f; f = f->next) {
if (f->condition(nat->buffer, (size_t)n)) {
if (nat->logging)
printf("nat: udp filtered %d %s => %s\n",
(int)n, b->out_name, b->in_name);
return 0;
}
}
m = su_send(b->in_socket, nat->buffer, n, 0);
if (nat->logging)
......@@ -882,3 +912,72 @@ static int invalidate_binding(struct binding *b)
return 0;
}
LIST_BODIES(static, nat_filter, struct nat_filter, next, prev);
struct args {
struct nat *nat;
struct nat_filter *f;
int outbound;
};
int execute_nat_filter_insert(void *_args)
{
struct args *a = (struct args *)_args;
if (a->outbound)
nat_filter_insert(&a->nat->out_filters, a->f);
else
nat_filter_insert(&a->nat->in_filters, a->f);
return 0;
}
int execute_nat_filter_remove(void *_args)
{
struct args *a = (struct args *)_args;
nat_filter_remove(a->f);
return 0;
}
struct nat_filter *test_nat_add_filter(struct nat *nat,
int (*condition)(void const *message,
size_t len),
int outbound)
{
struct args a[1];
if (nat == NULL)
return su_seterrno(EFAULT), NULL;
a->nat = nat;
a->f = su_zalloc(nat->home, sizeof *a->f);
a->outbound = outbound;
if (a->f) {
a->f->condition = condition;
if (su_task_execute(su_clone_task(nat->clone),
execute_nat_filter_insert, a, NULL) < 0)
su_free(nat->home, a->f), a->f = NULL;
}
return a->f;
}
int test_nat_remove_filter(struct nat *nat,
struct nat_filter *filter)
{
struct args a[1];
if (nat == NULL)
return su_seterrno(EFAULT);
a->nat = nat;
a->f = filter;
if (su_task_execute(su_clone_task(nat->clone),
execute_nat_filter_remove, a, NULL) < 0)
return -1;
su_free(nat->home, filter);
return 0;
}
......@@ -31,6 +31,7 @@
SOFIA_BEGIN_DECLS
struct nat;
struct nat_filter;
struct nat *test_nat_create(su_root_t *, int family,
tag_type_t, tag_value_t, ...);
......@@ -42,6 +43,16 @@ int test_nat_public(struct nat *nat, void const *address, int addrlen);
int test_nat_flush(struct nat *nat);
struct nat_filter *test_nat_add_filter(struct nat *nat,
int (*condition)(void const *message,
size_t len),
int outbound);
enum { nat_inbound, nat_outbound };
int test_nat_remove_filter(struct nat *nat,
struct nat_filter *filter);
/* Tags */
/** If true, act as symmetric nat. */
......
......@@ -231,8 +231,10 @@ int main(int argc, char *argv[])
else if (argv[i][0] != '-') {
break;
}
else
else {
fprintf(stderr, "test_nua: unknown argument \"%s\"\n\n", argv[i]);
usage(1);
}
}
if (o_attach) {
......@@ -301,13 +303,13 @@ int main(int argc, char *argv[])
retval |= test_nat_timeout(ctx);
while (retval == 0) {
retval |= test_extension(ctx); SINGLE_FAILURE_CHECK();
retval |= test_basic_call(ctx); SINGLE_FAILURE_CHECK();
retval |= test_reject_a(ctx); SINGLE_FAILURE_CHECK();
retval |= test_reject_b(ctx); SINGLE_FAILURE_CHECK();
retval |= test_reject_302(ctx); SINGLE_FAILURE_CHECK();
retval |= test_reject_401(ctx); SINGLE_FAILURE_CHECK();
retval |= test_mime_negotiation(ctx); SINGLE_FAILURE_CHECK();
retval |= test_call_timeouts(ctx); SINGLE_FAILURE_CHECK();
retval |= test_reject_401_aka(ctx); SINGLE_FAILURE_CHECK();
retval |= test_call_cancel(ctx); SINGLE_FAILURE_CHECK();
retval |= test_call_destroy(ctx); SINGLE_FAILURE_CHECK();
......@@ -318,6 +320,7 @@ int main(int argc, char *argv[])
retval |= test_100rel(ctx); SINGLE_FAILURE_CHECK();
retval |= test_events(ctx); SINGLE_FAILURE_CHECK();
retval |= test_simple(ctx); SINGLE_FAILURE_CHECK();
retval |= test_extension(ctx); SINGLE_FAILURE_CHECK();
if (!o_loop)
break;
}
......
......@@ -332,6 +332,7 @@ int test_reject_b(struct context *ctx);
int test_reject_302(struct context *ctx);
int test_reject_401(struct context *ctx);
int test_mime_negotiation(struct context *ctx);
int test_call_timeouts(struct context *ctx);
int test_reject_401_aka(struct context *ctx);
int test_call_cancel(struct context *ctx);
int test_call_destroy(struct context *ctx);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment