/* * 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_offer_answer.c * @brief Test offer/answer failures. * * @author Pekka Pessi * * @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_offer_answer" #endif /* ======================================================================== */ /* Send offer in INVITE, no answer: A B --nua_invite()-->| | |-------INVITE------>| <--nua_i_state---| | |<----100 Trying-----| | | |<--------180--------| <--nua_r_invite--| | <--nua_i_state---| | |<------200 OK-------| <--nua_r_invite--| | |--------ACK-------->| |--------BYE-------->| <--nua_i_state---| | |<-------200 OK------| <--nua_r_bye-----| | <--nua_i_state---| | Client transitions: INIT -(C1)-> CALLING -(C2a)-> PROCEEDING -(C3+C4)-> TERMINATING -> TERMINATED Server transitions: INIT -(S1)-> RECEIVED -(S2a)-> EARLY -(S3b)-> COMPLETED -(S4)-> READY -> TERMINATED */ int no_media_terminated(CONDITION_PARAMS); int test_no_answer_1(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; sip_t *sip; if (print_headings) printf("TEST NUA-6.5: No SDP answer from callee\n"); a_call->sdp = "m=audio 5008 RTP/AVP 8"; b_call->sdp = NULL; TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END())); TEST_1(!nua_handle_has_active_call(a_call->nh)); TEST_1(!nua_handle_has_call_on_hold(a_call->nh)); INVITE(a, a_call, a_call->nh, TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)), SOATAG_USER_SDP_STR(a_call->sdp), NUTAG_M_USERNAME("a+a"), NUTAG_M_DISPLAY("Alice"), TAG_END()); run_ab_until(ctx, -1, until_terminated, -1, no_media_terminated); TEST_1(!nua_handle_has_active_call(a_call->nh)); TEST_1(!nua_handle_has_call_on_hold(a_call->nh)); TEST_1(!nua_handle_has_active_call(b_call->nh)); TEST_1(!nua_handle_has_call_on_hold(b_call->nh)); /* Client transitions: INIT -(C1)-> CALLING: nua_invite(), nua_i_state CALLING -(C3)-> PROCEEDING: nua_r_invite, nua_i_state PROCEEDING -(C3a+C5)-> TERMINATING: nua_r_invite, nua_i_state TERMINATING -(C12)-> TERMINATED: nua_r_bye, nua_i_state */ 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(is_offer_sent(e->data->e_tags)); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); TEST(e->data->e_status, 180); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(!sip->sip_payload); 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(!is_answer_recv(e->data->e_tags)); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(!sip->sip_payload); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_media_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); /* Server transitions: INIT -(S1)-> RECEIVED: nua_i_invite, nua_i_state RECEIVED -(S2a)-> EARLY: nua_respond(), nua_i_state EARLY -(S3b)-> COMPLETED: nua_respond(), nua_i_state COMPLETED -(S4)-> READY: nua_i_ack, nua_i_state READY -(T1)-> TERMINATED: nua_i_bye, nua_i_state */ TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_invite); TEST(e->data->e_status, 100); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_contact); TEST_S(sip->sip_contact->m_display, "Alice"); TEST_S(sip->sip_contact->m_url->url_user, "a+a"); 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(!is_answer_sent(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_completed); /* COMPLETED */ TEST_1(!is_answer_sent(e->data->e_tags)); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_ack); TEST_1(sip = sip_object(e->data->e_msg)); 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(!is_answer_recv(e->data->e_tags)); TEST_1(!is_offer_recv(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); free_events_in_list(ctx, b->events); TEST_1(!nua_handle_has_active_call(a_call->nh)); TEST_1(!nua_handle_has_active_call(b_call->nh)); nua_handle_destroy(a_call->nh), a_call->nh = NULL; nua_handle_destroy(b_call->nh), b_call->nh = NULL; if (print_headings) printf("TEST NUA-6.5: PASSED\n"); END(); } int no_media_terminated(CONDITION_PARAMS) { if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR))) return 0; save_event_in_list(ctx, event, ep, call); switch (callstate(tags)) { case nua_callstate_received: RESPOND(ep, call, nh, SIP_180_RINGING, NUTAG_MEDIA_ENABLE(0), TAG_END()); return 0; case nua_callstate_early: RESPOND(ep, call, nh, SIP_200_OK, NUTAG_MEDIA_ENABLE(0), TAG_END()); return 0; case nua_callstate_terminated: if (call) nua_handle_destroy(call->nh), call->nh = NULL; return 1; default: return 0; } } int accept_call_until_terminated(CONDITION_PARAMS); /* No offer in INVITE, offer in 200 OK, no answer in ACK */ int test_no_answer_2(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; sip_t const *sip; if (print_headings) printf("TEST NUA-6.6: No SDP offer from caller\n"); a_call->sdp = "v=0\r\n" "o=- 1 1 IN IP4 127.0.0.1\r\n" "s=-\r\n" "c=IN IP4 127.0.0.1\r\n" "t=0 0\r\n" "m=audio 5008 RTP/AVP 8\r\n"; b_call->sdp = "v=0\r\n" "o=- 2 1 IN IP4 127.0.0.1\r\n" "s=-\r\n" "c=IN IP4 127.0.0.1\r\n" "t=0 0\r\n" "m=audio 5010 RTP/AVP 0 8\r\n"; TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO_STR(""), TAG_END())); TEST_1(!nua_handle_has_active_call(a_call->nh)); TEST_1(!nua_handle_has_call_on_hold(a_call->nh)); INVITE(a, a_call, a_call->nh, NUTAG_MEDIA_ENABLE(0), NUTAG_URL(b->contact->m_url), NUTAG_AUTOACK(1), TAG_END()); run_ab_until(ctx, -1, until_terminated, -1, accept_call_until_terminated); /* Client transitions: INIT -(C1)-> CALLING: nua_invite(), nua_i_state CALLING -(C2)-> PROCEEDING: nua_r_invite, nua_i_state PROCEEDING -(C3+C4)-> READY: nua_r_invite, nua_i_state */ 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(!is_offer_sent(e->data->e_tags)); 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(!is_answer_recv(e->data->e_tags)); TEST_1(!is_offer_recv(e->data->e_tags)); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_content_type); TEST_S(sip->sip_content_type->c_type, "application/sdp"); TEST_1(sip->sip_payload); /* there is sdp in 200 OK */ TEST_1(sip->sip_contact); 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(!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); /* READY */ TEST_1(!e->next); free_events_in_list(ctx, a->events); TEST_1(!nua_handle_has_active_call(a_call->nh)); TEST_1(!nua_handle_has_call_on_hold(a_call->nh)); /* Server transitions: INIT -(S1)-> RECEIVED: nua_i_invite, nua_i_state RECEIVED -(S2a)-> EARLY: nua_respond(), nua_i_state EARLY -(S3b)-> COMPLETED: nua_respond(), nua_i_state COMPLETED -(S4)-> READY: nua_i_ack, nua_i_state */ 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(!is_answer_sent(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_completed); /* COMPLETED */ TEST_1(is_offer_sent(e->data->e_tags)); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_ack); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_media_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, b->events); TEST_1(!nua_handle_has_active_call(b_call->nh)); TEST_1(!nua_handle_has_call_on_hold(b_call->nh)); nua_handle_destroy(a_call->nh), a_call->nh = NULL; nua_handle_destroy(b_call->nh), b_call->nh = NULL; if (print_headings) printf("TEST NUA-6.6: PASSED\n"); END(); } int accept_call_until_terminated(CONDITION_PARAMS) { if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR))) return 0; save_event_in_list(ctx, event, ep, call); switch (callstate(tags)) { case nua_callstate_received: RESPOND(ep, call, nh, SIP_180_RINGING, TAG_END()); return 0; case nua_callstate_early: RESPOND(ep, call, nh, SIP_200_OK, NUTAG_MEDIA_ENABLE(1), TAG_IF(call->sdp, SOATAG_USER_SDP_STR(call->sdp)), TAG_END()); return 0; case nua_callstate_terminated: if (call) nua_handle_destroy(call->nh), call->nh = NULL; return 1; default: return 0; } } /* No offer in INVITE, no user SDP in 200 OK */ int test_missing_user_sdp(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; if (print_headings) printf("TEST NUA-6.6.2: No SDP offer from caller\n"); a_call->sdp = "v=0\r\n" "o=- 1 1 IN IP4 127.0.0.1\r\n" "s=-\r\n" "c=IN IP4 127.0.0.1\r\n" "t=0 0\r\n" "m=audio 5008 RTP/AVP 8\r\n"; b_call->sdp = NULL; nua_set_params(b->nua, NUTAG_MEDIA_ENABLE(0), TAG_END()); run_b_until(ctx, nua_r_set_params, until_final_response); TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO_STR(""), TAG_END())); TEST_1(!nua_handle_has_active_call(a_call->nh)); TEST_1(!nua_handle_has_call_on_hold(a_call->nh)); INVITE(a, a_call, a_call->nh, NUTAG_MEDIA_ENABLE(0), NUTAG_URL(b->contact->m_url), NUTAG_AUTOACK(1), TAG_END()); run_ab_until(ctx, -1, until_terminated, -1, accept_call_until_terminated); /* Client transitions: INIT -(C1)-> CALLING: nua_invite(), nua_i_state CALLING -(C2)-> PROCEEDING: nua_r_invite, nua_i_state PROCEEDING -(C3+C4)-> READY: nua_r_invite, nua_i_state */ 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(!is_offer_sent(e->data->e_tags)); 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(!is_answer_recv(e->data->e_tags)); TEST_1(!is_offer_recv(e->data->e_tags)); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); TEST(e->data->e_status, 500); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* READY */ TEST_1(!e->next); free_events_in_list(ctx, a->events); TEST_1(!nua_handle_has_active_call(a_call->nh)); TEST_1(!nua_handle_has_call_on_hold(a_call->nh)); /* Server transitions: INIT -(S1)-> RECEIVED: nua_i_invite, nua_i_state RECEIVED -(S2a)-> EARLY: nua_respond(), nua_i_state EARLY -(S3b)-> COMPLETED: nua_respond(), nua_i_state COMPLETED -(S4)-> READY: nua_i_ack, nua_i_state */ 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(!is_answer_sent(e->data->e_tags)); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_error); TEST(e->data->e_status, 500); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* COMPLETED */ TEST_1(!e->next); free_events_in_list(ctx, b->events); TEST_1(!nua_handle_has_active_call(b_call->nh)); TEST_1(!nua_handle_has_call_on_hold(b_call->nh)); nua_handle_destroy(a_call->nh), a_call->nh = NULL; nua_handle_destroy(b_call->nh), b_call->nh = NULL; nua_set_params(b->nua, NUTAG_MEDIA_ENABLE(1), SOATAG_USER_SDP_STR("m=audio 5006 RTP/AVP 8 0"), TAG_END()); run_b_until(ctx, nua_r_set_params, until_final_response); if (print_headings) printf("TEST NUA-6.6.2: PASSED\n"); END(); } int test_offer_answer(struct context *ctx) { return test_no_answer_1(ctx) || test_no_answer_2(ctx) || test_missing_user_sdp(ctx) || 0; }