/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ /**@CFILE test_register.c * @brief Test registering, outbound, nat traversal. * * @author Pekka Pessi * @author Martti Mela * * @date Created: Wed Aug 17 12:12:12 EEST 2005 ppessi */ #include "config.h" #include "test_nua.h" #include #if HAVE_FUNC #elif HAVE_FUNCTION #define __func__ __FUNCTION__ #else #define __func__ "test_register" #endif /* ======================================================================== */ /* Test REGISTER */ int test_register_to_proxy(struct context *ctx) { BEGIN(); struct endpoint *a = &ctx->a, *b = &ctx->b, *c = &ctx->c, *x; struct call *a_reg = a->reg, *b_reg = b->reg, *c_reg = c->reg; struct event *e; sip_t const *sip; sip_cseq_t cseq[1]; if (ctx->p) test_proxy_set_expiration(ctx->p, 5, 5, 10); if (print_headings) printf("TEST NUA-2.3.0.1: un-REGISTER a\n"); TEST_1(a_reg->nh = nua_handle(a->nua, a_reg, TAG_END())); UNREGISTER(a, a_reg, a_reg->nh, SIPTAG_TO(a->to), SIPTAG_CONTACT_STR("*"), TAG_END()); run_a_until(ctx, -1, until_final_response); AUTHENTICATE(a, a_reg, a_reg->nh, NUTAG_AUTH("Digest:\"test-proxy\":alice:secret"), TAG_END()); run_a_until(ctx, -1, until_final_response); nua_handle_destroy(a_reg->nh); if (print_headings) printf("TEST NUA-2.3.0.1: PASSED\n"); if (print_headings) printf("TEST NUA-2.3.0.2: un-REGISTER b\n"); TEST_1(b_reg->nh = nua_handle(b->nua, b_reg, TAG_END())); UNREGISTER(b, b_reg, b_reg->nh, SIPTAG_TO(b->to), SIPTAG_CONTACT_STR("*"), TAG_END()); run_b_until(ctx, -1, until_final_response); AUTHENTICATE(b, b_reg, b_reg->nh, NUTAG_AUTH("Digest:\"test-proxy\":bob:secret"), TAG_END()); run_b_until(ctx, -1, until_final_response); nua_handle_destroy(b_reg->nh); if (print_headings) printf("TEST NUA-2.3.0.2: PASSED\n"); if (print_headings) printf("TEST NUA-2.3.0.3: un-REGISTER c\n"); TEST_1(c_reg->nh = nua_handle(c->nua, c_reg, TAG_END())); UNREGISTER(c, c_reg, c_reg->nh, SIPTAG_TO(c->to), SIPTAG_CONTACT_STR("*"), TAG_END()); run_c_until(ctx, -1, until_final_response); AUTHENTICATE(c, c_reg, c_reg->nh, NUTAG_AUTH("Digest:\"test-proxy\":charlie:secret"), TAG_END()); run_c_until(ctx, -1, until_final_response); nua_handle_destroy(c_reg->nh); if (print_headings) printf("TEST NUA-2.3.0.3: PASSED\n"); /* REGISTER test A B |------REGISTER----->| |<-------401---------| |------REGISTER----->| |<-------200---------| | | */ if (print_headings) printf("TEST NUA-2.3.1: REGISTER a\n"); TEST_1(a_reg->nh = nua_handle(a->nua, a_reg, TAG_END())); sip_cseq_init(cseq)->cs_seq = 12; cseq->cs_method = sip_method_register; cseq->cs_method_name = sip_method_name_register; REGISTER(a, a_reg, a_reg->nh, SIPTAG_TO(a->to), NUTAG_OUTBOUND("natify options-keepalive validate"), NUTAG_KEEPALIVE(1000), NUTAG_M_DISPLAY("A&A"), NUTAG_M_USERNAME("a"), SIPTAG_CSEQ(cseq), TAG_END()); run_a_until(ctx, -1, save_until_final_response); TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_register); TEST_1(sip = sip_object(e->data->e_msg)); TEST(e->data->e_status, 401); TEST(sip->sip_status->st_status, 401); TEST(sip->sip_cseq->cs_seq, 13); TEST_1(!sip->sip_contact); TEST_1(!e->next); free_events_in_list(ctx, a->events); AUTHENTICATE(a, a_reg, a_reg->nh, NUTAG_AUTH("Digest:\"test-proxy\":alice:secret"), TAG_END()); run_a_until(ctx, -1, save_until_final_response); TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_register); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_contact); { char const *expect_m_display = "\"A&A\""; /* VC does not dig \" with TEST_S() */ TEST_S(sip->sip_contact->m_display, expect_m_display); } TEST_S(sip->sip_contact->m_url->url_user, "a"); TEST(sip->sip_cseq->cs_seq, 14); if (ctx->nat) { TEST_1(e = a->specials->head); } if (print_headings) printf("TEST NUA-2.3.1: PASSED\n"); if (print_headings) printf("TEST NUA-2.3.2: REGISTER b\n"); TEST_1(b_reg->nh = nua_handle(b->nua, b_reg, TAG_END())); REGISTER(b, b_reg, b_reg->nh, SIPTAG_TO(b->to), NUTAG_M_DISPLAY("B"), NUTAG_M_USERNAME("b"), TAG_END()); run_ab_until(ctx, -1, save_events, -1, save_until_final_response); TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_register); TEST_1(sip = sip_object(e->data->e_msg)); TEST(e->data->e_status, 401); TEST(sip->sip_status->st_status, 401); TEST_1(!sip->sip_contact); TEST_1(!e->next); free_events_in_list(ctx, b->events); AUTHENTICATE(b, b_reg, b_reg->nh, NUTAG_AUTH("Digest:\"test-proxy\":bob:secret"), TAG_END()); run_ab_until(ctx, -1, save_events, -1, save_until_final_response); TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_register); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_contact); TEST_S(sip->sip_contact->m_display, "B"); TEST_S(sip->sip_contact->m_url->url_user, "b"); if (print_headings) printf("TEST NUA-2.3.2: PASSED\n"); if (ctx->p) test_proxy_set_expiration(ctx->p, 30, 3600, 36000); if (print_headings) printf("TEST NUA-2.3.3: REGISTER c\n"); TEST_1(c_reg->nh = nua_handle(c->nua, c_reg, TAG_END())); REGISTER(c, c_reg, c_reg->nh, SIPTAG_TO(c->to), NUTAG_M_DISPLAY("C"), NUTAG_M_USERNAME("c"), SIPTAG_EXPIRES_STR("5"), /* Test 423 negotiation */ TAG_END()); run_abc_until(ctx, -1, save_events, -1, save_events, -1, save_until_final_response); TEST_1(e = c->events->head); TEST_E(e->data->e_event, nua_r_register); TEST_1(sip = sip_object(e->data->e_msg)); TEST(e->data->e_status, 401); TEST(sip->sip_status->st_status, 401); TEST_1(!sip->sip_contact); TEST_1(!e->next); free_events_in_list(ctx, c->events); AUTHENTICATE(c, c_reg, c_reg->nh, NUTAG_AUTH("Digest:\"test-proxy\":charlie:secret"), TAG_END()); run_abc_until(ctx, -1, save_events, -1, save_events, -1, save_until_final_response); TEST_1(e = c->events->head); TEST_E(e->data->e_event, nua_r_register); TEST(e->data->e_status, 100); TEST_1(sip = sip_object(e->data->e_msg)); TEST(sip->sip_status->st_status, 423); TEST_1(e = e->next); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_contact); TEST_S(sip->sip_contact->m_display, "C"); TEST_S(sip->sip_contact->m_url->url_user, "c"); TEST_1(!e->next); free_events_in_list(ctx, c->events); if (print_headings) printf("TEST NUA-2.3.3: PASSED\n"); if (!ctx->p) { free_events_in_list(ctx, a->events); free_events_in_list(ctx, b->events); return 0; } if (print_headings) printf("TEST NUA-2.3.4: refresh REGISTER\n"); /* Wait for A and B to refresh their registrations */ /* * Avoid race condition: if X has already refreshed registration * with expiration time of 3600 seconds, do not wait for new refresh */ a->next_condition = save_until_final_response; b->next_condition = save_until_final_response; for (x = a; x; x = x == a ? b : NULL) { for (e = x->events->head; e; e = e->next) { if (e->data->e_event == nua_r_register && e->data->e_status == 200 && (sip = sip_object(e->data->e_msg)) && sip->sip_contact && sip->sip_contact->m_expires && strcmp(sip->sip_contact->m_expires, "3600") == 0) { x->next_condition = NULL; break; } } } run_ab_until(ctx, -1, a->next_condition, -1, b->next_condition); for (e = a->events->head; e; e = e->next) { TEST_E(e->data->e_event, nua_r_register); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_contact); if (!e->next) break; } TEST_1(e); TEST_S(sip->sip_contact->m_expires, "3600"); TEST_1(!e->next); free_events_in_list(ctx, a->events); for (e = b->events->head; e; e = e->next) { TEST_E(e->data->e_event, nua_r_register); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_contact); if (!e->next) break; } TEST_1(e); TEST_S(sip->sip_contact->m_expires, "3600"); TEST_1(!e->next); free_events_in_list(ctx, b->events); if (print_headings) printf("TEST NUA-2.3.4: PASSED\n"); END(); } int registrar_299(CONDITION_PARAMS) { msg_t *request = nua_current_request(nua); save_event_in_list(ctx, event, ep, ep->call); if (event == nua_i_register) { RESPOND(ep, call, nh, 299, "YES", NUTAG_WITH(request), TAG_END()); return 1; } return 0; } int test_register_to_c(struct context *ctx) { BEGIN(); struct endpoint *b = &ctx->b, *c = &ctx->c; struct call *b_call = b->call, *c_call = c->call; struct event *e; sip_t const *sip; if (print_headings) printf("TEST NUA-2.3.2: REGISTER b to c\n"); nua_set_params(ctx->c.nua, NUTAG_ALLOW("REGISTER"), TAG_END()); run_c_until(ctx, nua_r_set_params, until_final_response); TEST_1(b_call->nh = nua_handle(b->nua, b_call, TAG_END())); REGISTER(b, b_call, b_call->nh, NUTAG_REGISTRAR((url_string_t *)c->contact->m_url), SIPTAG_TO(b->to), NUTAG_OUTBOUND(NULL), SIPTAG_CONTACT_STR(NULL), TAG_END()); run_bc_until(ctx, -1, save_until_final_response, -1, registrar_299); TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_register); TEST(e->data->e_status, 299); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(!sip->sip_contact); if (print_headings) printf("TEST NUA-2.6.1: PASSED\n"); free_events_in_list(ctx, b->events); nua_handle_destroy(b_call->nh), b_call->nh = NULL; TEST_1(e = c->events->head); TEST_E(e->data->e_event, nua_i_register); TEST(e->data->e_status, 100); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(!sip->sip_contact); free_events_in_list(ctx, c->events); nua_handle_destroy(c_call->nh), c_call->nh = NULL; if (print_headings) printf("TEST NUA-2.3.4: PASSED\n"); END(); } int test_register(struct context *ctx) { if (test_register_to_c(ctx)) return 1; if (ctx->proxy_tests) if (test_register_to_proxy(ctx)) return 1; return 0; } int test_connectivity(struct context *ctx) { if (!ctx->proxy_tests) return 0; /* No proxy */ BEGIN(); struct endpoint *a = &ctx->a, *b = &ctx->b, *c = &ctx->c; struct call *a_call = a->call, *b_call = b->call, *c_call = c->call; struct event *e; sip_t const *sip; /* Connectivity test using OPTIONS */ if (print_headings) printf("TEST NUA-2.4.1: OPTIONS from A to B\n"); TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END())); OPTIONS(a, a_call, a_call->nh, TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)), NUTAG_ALLOW("OPTIONS"), TAG_END()); run_ab_until(ctx, -1, save_until_final_response, -1, save_until_received); /* Client events: nua_options(), nua_r_options */ TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_options); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_allow); TEST_1(sip->sip_accept); TEST_1(sip->sip_supported); /* TEST_1(sip->sip_content_type); */ /* TEST_1(sip->sip_payload); */ TEST_1(!e->next); free_events_in_list(ctx, a->events); nua_handle_destroy(a_call->nh), a_call->nh = NULL; /* Server events: nua_i_options */ TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_options); TEST(e->data->e_status, 200); TEST_1(!e->next); free_events_in_list(ctx, b->events); nua_handle_destroy(b_call->nh), b_call->nh = NULL; if (print_headings) printf("TEST NUA-2.4.1: PASSED\n"); if (print_headings) printf("TEST NUA-2.4.2: OPTIONS from B to C\n"); TEST_1(b_call->nh = nua_handle(b->nua, b_call, SIPTAG_TO(c->to), TAG_END())); OPTIONS(b, b_call, b_call->nh, TAG_IF(!ctx->proxy_tests, NUTAG_URL(c->contact->m_url)), TAG_END()); run_abc_until(ctx, -1, NULL, -1, save_until_final_response, -1, save_until_received); /* Client events: nua_options(), nua_r_options */ TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_options); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_allow); TEST_1(sip->sip_accept); TEST_1(sip->sip_supported); /* TEST_1(sip->sip_content_type); */ /* TEST_1(sip->sip_payload); */ TEST_1(!e->next); free_events_in_list(ctx, b->events); nua_handle_destroy(b_call->nh), b_call->nh = NULL; /* Server events: nua_i_options */ TEST_1(e = c->events->head); TEST_E(e->data->e_event, nua_i_options); TEST(e->data->e_status, 200); TEST_1(!e->next); free_events_in_list(ctx, c->events); nua_handle_destroy(c_call->nh), c_call->nh = NULL; if (print_headings) printf("TEST NUA-2.4.2: PASSED\n"); if (print_headings) printf("TEST NUA-2.4.3: OPTIONS from C to A\n"); TEST_1(c_call->nh = nua_handle(c->nua, c_call, SIPTAG_TO(a->to), TAG_END())); OPTIONS(c, c_call, c_call->nh, TAG_IF(!ctx->proxy_tests, NUTAG_URL(a->contact->m_url)), TAG_END()); if (ctx->proxy_tests) { run_abc_until(ctx, -1, NULL, -1, NULL, -1, save_until_final_response); /* Client events: nua_options(), nua_r_options */ TEST_1(e = c->events->head); TEST_E(e->data->e_event, nua_r_options); TEST(e->data->e_status, 407); TEST_1(!e->next); free_events_in_list(ctx, c->events); AUTHENTICATE(c, c_call, c_call->nh, NUTAG_AUTH("Digest:\"test-proxy\":charlie:secret"), TAG_END()); } run_abc_until(ctx, -1, save_until_received, -1, NULL, -1, save_until_final_response); /* Client events: nua_options(), nua_r_options */ TEST_1(e = c->events->head); TEST_E(e->data->e_event, nua_r_options); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_allow); TEST_1(sip->sip_accept); TEST_1(sip->sip_supported); /* TEST_1(sip->sip_content_type); */ /* TEST_1(sip->sip_payload); */ TEST_1(!e->next); free_events_in_list(ctx, c->events); nua_handle_destroy(c_call->nh), c_call->nh = NULL; /* Server events: nua_i_options */ TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_options); TEST(e->data->e_status, 200); TEST_1(!e->next); free_events_in_list(ctx, a->events); nua_handle_destroy(a_call->nh), a_call->nh = NULL; if (print_headings) printf("TEST NUA-2.4.3: PASSED\n"); END(); } int test_nat_timeout(struct context *ctx) { if (!ctx->proxy_tests || !ctx->nat) return 0; /* No proxy */ BEGIN(); struct endpoint *a = &ctx->a, *b = &ctx->b, *c = &ctx->c; struct event *e; sip_t const *sip; /* Test what happens when NAT bindings go away */ if (print_headings) printf("TEST NUA-2.5.1: NAT binding change\n"); free_events_in_list(ctx, a->specials); test_nat_flush(ctx->nat); /* Break our connections */ /* Run until we get final response to REGISTER */ run_a_until(ctx, -1, save_until_final_response); TEST_1(e = a->specials->head); TEST_E(e->data->e_event, nua_i_outbound); TEST(e->data->e_status, 102); TEST_S(e->data->e_phrase, "NAT binding changed"); TEST_1(!e->next); free_events_in_list(ctx, a->specials); TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_register); TEST(e->data->e_status, 200); TEST_1(!e->next); free_events_in_list(ctx, a->events); if (print_headings) printf("TEST NUA-2.5.1: PASSED\n"); (void)b; (void)c; (void)sip; END(); } int test_unregister(struct context *ctx) { if (!ctx->proxy_tests) return 0; /* No proxy */ BEGIN(); struct endpoint *a = &ctx->a, *b = &ctx->b, *c = &ctx->c; struct event *e; sip_t const *sip; /* un-REGISTER test A B |----un-REGISTER---->| |<-------200---------| | | */ if (print_headings) printf("TEST NUA-13.1: un-REGISTER a\n"); if (a->reg->nh) { free_events_in_list(ctx, a->events); UNREGISTER(a, NULL, a->reg->nh, TAG_END()); run_a_until(ctx, -1, save_until_final_response); TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_unregister); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(!sip->sip_contact); TEST_1(!e->next); free_events_in_list(ctx, a->events); nua_handle_destroy(a->reg->nh), a->reg->nh = NULL; } if (print_headings) printf("TEST NUA-13.1: PASSED\n"); if (print_headings) printf("TEST NUA-13.2: un-REGISTER b\n"); if (b->reg->nh) { free_events_in_list(ctx, b->events); UNREGISTER(b, NULL, b->reg->nh, TAG_END()); run_b_until(ctx, -1, save_until_final_response); TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_unregister); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(!sip->sip_contact); TEST_1(!e->next); free_events_in_list(ctx, b->events); nua_handle_destroy(b->reg->nh), b->reg->nh = NULL; } if (print_headings) printf("TEST NUA-13.2: PASSED\n"); if (print_headings) printf("TEST NUA-13.3: un-REGISTER c\n"); /* Unregister using another handle */ free_events_in_list(ctx, c->events); TEST_1(c->call->nh = nua_handle(c->nua, c->call, TAG_END())); UNREGISTER(c, c->call, c->call->nh, SIPTAG_TO(c->to), NUTAG_M_DISPLAY("C"), NUTAG_M_USERNAME("c"), TAG_END()); run_c_until(ctx, -1, save_until_final_response); TEST_1(e = c->events->head); TEST_E(e->data->e_event, nua_r_unregister); TEST_1(sip = sip_object(e->data->e_msg)); TEST(e->data->e_status, 401); TEST(sip->sip_status->st_status, 401); TEST_1(!sip->sip_contact); TEST_1(!e->next); free_events_in_list(ctx, c->events); AUTHENTICATE(c, c->call, c->call->nh, NUTAG_AUTH("Digest:\"test-proxy\":charlie:secret"), TAG_END()); run_c_until(ctx, -1, save_until_final_response); TEST_1(e = c->events->head); TEST_E(e->data->e_event, nua_r_unregister); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(!sip->sip_contact); TEST_1(!e->next); free_events_in_list(ctx, c->events); nua_handle_destroy(c->call->nh), c->call->nh = NULL; if (c->reg->nh) { UNREGISTER(c, NULL, c->reg->nh, TAG_END()); run_c_until(ctx, -1, save_until_final_response); TEST_1(e = c->events->head); TEST_E(e->data->e_event, nua_r_unregister); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(!sip->sip_contact); TEST_1(!e->next); free_events_in_list(ctx, c->events); nua_handle_destroy(c->reg->nh), c->reg->nh = NULL; } if (print_headings) printf("TEST NUA-13.3: PASSED\n"); END(); }