📄 check_session.c
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2008 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * 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 check_session.c * * @brief NUA module tests for SIP session handling * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * * @copyright (C) 2008 Nokia Corporation. */#include "config.h"#include "check_nua.h"#include "test_s2.h"#include <sofia-sip/sip_status.h>#include <sofia-sip/sip_header.h>#include <sofia-sip/soa.h>#include <sofia-sip/su_tagarg.h>#include <sofia-sip/su_tag_io.h>#include <stdlib.h>#include <string.h>#include <assert.h>/* ====================================================================== *//* Call cases */static nua_t *nua;static soa_session_t *soa = NULL;static struct dialog *dialog = NULL;#define CRLF "\r\n"static void call_setup(void){ s2_case("0.1.1", "Setup for Call Tests", ""); nua = s2_nua_setup(TAG_END()); soa = soa_create(NULL, s2->root, NULL); fail_if(!soa); soa_set_params(soa, SOATAG_USER_SDP_STR("m=audio 5008 RTP/AVP 8 0" CRLF "m=video 5010 RTP/AVP 34" CRLF), TAG_END()); dialog = su_home_new(sizeof *dialog); fail_if(!dialog); s2_register_setup();}static void call_teardown(void){ s2_case("0.1.2", "Teardown Call Test Setup", ""); mark_point(); s2_register_teardown(); nua_shutdown(nua); fail_unless(s2_check_event(nua_r_shutdown, 200)); s2_nua_teardown();}static void save_sdp_to_soa(struct message *message){ sip_payload_t *pl; char const *body; isize_t bodylen; fail_if(!message); fail_if(!message->sip->sip_content_length); fail_if(!message->sip->sip_content_type); fail_if(strcmp(message->sip->sip_content_type->c_type, "application/sdp")); fail_if(!message->sip->sip_payload); pl = message->sip->sip_payload; body = pl->pl_data, bodylen = pl->pl_len; fail_if(soa_set_remote_sdp(soa, NULL, body, (issize_t)bodylen) < 0);}static void process_offer(struct message *message){ save_sdp_to_soa(message); fail_if(soa_generate_answer(soa, NULL) < 0);}static void process_answer(struct message *message){ save_sdp_to_soa(message); fail_if(soa_process_answer(soa, NULL) < 0);}static voidrespond_with_sdp(struct message *request, struct dialog *dialog, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...){ ta_list ta; char const *body; isize_t bodylen; fail_if(soa_get_local_sdp(soa, NULL, &body, &bodylen) != 1); ta_start(ta, tag, value); s2_respond_to(request, dialog, status, phrase, SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(body), SIPTAG_CONTENT_DISPOSITION_STR("session"), ta_tags(ta)); ta_end(ta);}static voidrequest_with_sdp(struct dialog *dialog, sip_method_t method, char const *name, tport_t *tport, tag_type_t tag, tag_value_t value, ...){ ta_list ta; char const *body; isize_t bodylen; fail_if(soa_get_local_sdp(soa, NULL, &body, &bodylen) != 1); ta_start(ta, tag, value); fail_if( s2_request_to(dialog, method, name, tport, SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(body), ta_tags(ta))); ta_end(ta);}static struct message *invite_sent_by_nua(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...){ ta_list ta; ta_start(ta, tag, value); nua_invite(nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), ta_tags(ta)); ta_end(ta); fail_unless(s2_check_callstate(nua_callstate_calling)); return s2_wait_for_request(SIP_METHOD_INVITE);}static struct message *respond_with_100rel(struct message *invite, struct dialog *d, int sdp, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...){ struct message *prack; ta_list ta; static uint32_t rseq; sip_rseq_t rs[1]; assert(100 < status && status < 200); sip_rseq_init(rs); rs->rs_response = ++rseq; ta_start(ta, tag, value); if (sdp) { respond_with_sdp( invite, dialog, status, phrase, SIPTAG_REQUIRE_STR("100rel"), SIPTAG_RSEQ(rs), ta_tags(ta)); } else { s2_respond_to( invite, dialog, status, phrase, SIPTAG_REQUIRE_STR("100rel"), SIPTAG_RSEQ(rs), ta_tags(ta)); } ta_end(ta); fail_unless(s2_check_event(nua_r_invite, status)); prack = s2_wait_for_request(SIP_METHOD_PRACK); /* Assumes auto-prack, so there is no offer in prack */ s2_respond_to(prack, dialog, SIP_200_OK, TAG_END()); return prack;}static voidinvite_by_nua(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...){ struct message *invite; ta_list ta; ta_start(ta, tag, value); invite = invite_sent_by_nua( nh, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), ta_tags(ta)); ta_end(ta); process_offer(invite); respond_with_sdp( invite, dialog, SIP_180_RINGING, SIPTAG_CONTENT_DISPOSITION_STR("session;handling=optional"), TAG_END()); fail_unless(s2_check_event(nua_r_invite, 180)); fail_unless(s2_check_callstate(nua_callstate_proceeding)); respond_with_sdp(invite, dialog, SIP_200_OK, TAG_END()); s2_free_message(invite); fail_unless(s2_check_event(nua_r_invite, 200)); fail_unless(s2_check_callstate(nua_callstate_ready)); fail_unless(s2_check_request(SIP_METHOD_ACK));}static nua_handle_t *invite_to_nua(tag_type_t tag, tag_value_t value, ...){ ta_list ta; struct event *invite; struct message *response; nua_handle_t *nh; sip_cseq_t cseq[1]; soa_generate_offer(soa, 1, NULL); ta_start(ta, tag, value); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, ta_tags(ta)); ta_end(ta); invite = s2_wait_for_event(nua_i_invite, 100); fail_unless(invite != NULL); fail_unless(s2_check_callstate(nua_callstate_received)); nh = invite->nh; fail_if(!nh); sip_cseq_init(cseq); cseq->cs_method = sip_method_ack; cseq->cs_method_name = "ACK"; cseq->cs_seq = sip_object(invite->data->e_msg)->sip_cseq->cs_seq; s2_free_event(invite); response = s2_wait_for_response(100, SIP_METHOD_INVITE); fail_if(!response); nua_respond(nh, SIP_180_RINGING, SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_early)); response = s2_wait_for_response(180, SIP_METHOD_INVITE); fail_if(!response); s2_update_dialog(dialog, response); process_answer(response); s2_free_message(response); nua_respond(nh, SIP_200_OK, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_completed)); response = s2_wait_for_response(200, SIP_METHOD_INVITE); fail_if(!response); s2_update_dialog(dialog, response); s2_free_message(response); fail_if(s2_request_to(dialog, SIP_METHOD_ACK, NULL, SIPTAG_CSEQ(cseq), TAG_END())); fail_unless(s2_check_event(nua_i_ack, 200)); fail_unless(s2_check_callstate(nua_callstate_ready)); return nh;}static voidbye_by_nua(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...){ ta_list ta; struct message *bye; ta_start(ta, tag, value); nua_bye(nh, ta_tags(ta)); ta_end(ta); bye = s2_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_free_message(bye); fail_unless(s2_check_event(nua_r_bye, 200)); fail_unless(s2_check_callstate(nua_callstate_terminated));}static void bye_by_nua_challenged(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...){ ta_list ta; struct message *bye; s2_flush_events(); ta_start(ta, tag, value); nua_bye(nh, ta_tags(ta)); ta_end(ta); bye = s2_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_respond_to(bye, dialog, SIP_407_PROXY_AUTH_REQUIRED, SIPTAG_PROXY_AUTHENTICATE_STR(s2_auth_digest_str), TAG_END()); s2_free_message(bye); fail_unless(s2_check_event(nua_r_bye, 407)); nua_authenticate(nh, NUTAG_AUTH("Digest:\"s2test\":abc:abc"), TAG_END()); bye = s2_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); s2_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_free_message(bye); fail_unless(s2_check_event(nua_r_bye, 200)); fail_unless(s2_check_callstate(nua_callstate_terminated)); fail_if(s2->events);}static void cancel_by_nua(nua_handle_t *nh, struct message *invite, struct dialog *dialog, tag_type_t tag, tag_value_t value, ...){ ta_list ta; struct message *cancel; ta_start(ta, tag, value); nua_cancel(nh, ta_tags(ta)); ta_end(ta); cancel = s2_wait_for_request(SIP_METHOD_CANCEL); fail_if(!cancel); s2_respond_to(cancel, dialog, SIP_200_OK, TAG_END()); s2_free_message(cancel); fail_unless(s2_check_event(nua_r_cancel, 200)); s2_respond_to(invite, dialog, SIP_487_REQUEST_CANCELLED, TAG_END()); fail_unless(s2_check_request(SIP_METHOD_ACK)); fail_unless(s2_check_event(nua_r_invite, 487));}static void bye_to_nua(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...){ ta_list ta; ta_start(ta, tag, value); fail_if(s2_request_to(dialog, SIP_METHOD_BYE, NULL, ta_tags(ta))); ta_end(ta); fail_unless(s2_check_event(nua_i_bye, 200)); fail_unless(s2_check_callstate(nua_callstate_terminated)); fail_unless(s2_check_response(200, SIP_METHOD_BYE));}/* ====================================================================== *//* 2 - Call cases *//* 2.1 - Basic call cases */START_TEST(call_2_1_1){ nua_handle_t *nh; s2_case("2.1.1", "Basic call", "NUA sends INVITE, NUA sends BYE"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END()); invite_by_nua(nh, TAG_END()); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh);}END_TESTSTART_TEST(call_2_1_2){ nua_handle_t *nh; s2_case("2.1.2", "Basic call", "NUA sends INVITE, NUA receives BYE"); nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END()); invite_by_nua(nh, TAG_END()); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh);}END_TESTSTART_TEST(call_2_1_3){ nua_handle_t *nh; s2_case("2.1.3", "Incoming call", "NUA receives INVITE and BYE"); nh = invite_to_nua(TAG_END()); bye_to_nua(nh, TAG_END()); nua_handle_destroy(nh);}END_TESTSTART_TEST(call_2_1_4){ nua_handle_t *nh; s2_case("2.1.4", "Incoming call", "NUA receives INVITE and sends BYE"); nh = invite_to_nua(TAG_END()); bye_by_nua(nh, TAG_END()); nua_handle_destroy(nh);}END_TESTSTART_TEST(call_2_1_5){ nua_handle_t *nh; s2_case("2.1.5", "Incoming call", "NUA receives INVITE and sends BYE, BYE is challenged"); nh = invite_to_nua(TAG_END()); bye_by_nua_challenged(nh, TAG_END()); nua_handle_destroy(nh);}END_TESTSTART_TEST(call_2_1_6){ nua_handle_t *nh; struct message *bye; struct event *invite; struct message *response; sip_cseq_t cseq[1]; s2_case("2.1.6", "Basic call", "NUA received INVITE, " "NUA responds (and saves proxy for dialog), " "NUA sends BYE"); soa_generate_offer(soa, 1, NULL); request_with_sdp(dialog, SIP_METHOD_INVITE, NULL, TAG_END()); invite = s2_wait_for_event(nua_i_invite, 100); fail_unless(invite != NULL); fail_unless(s2_check_callstate(nua_callstate_received)); nh = invite->nh; fail_if(!nh); sip_cseq_init(cseq); cseq->cs_method = sip_method_ack; cseq->cs_method_name = "ACK"; cseq->cs_seq = sip_object(invite->data->e_msg)->sip_cseq->cs_seq; s2_free_event(invite); response = s2_wait_for_response(100, SIP_METHOD_INVITE); fail_if(!response); nua_respond(nh, SIP_180_RINGING, /* Dialog-specific proxy is saved */ NUTAG_PROXY(s2->tcp.contact->m_url), SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), TAG_END()); fail_unless(s2_check_callstate(nua_callstate_early)); response = s2_wait_for_response(180, SIP_METHOD_INVITE); fail_if(!response); s2_update_dialog(dialog, response); process_answer(response); s2_free_message(response); nua_respond(nh, SIP_200_OK, TAG_END()); fail_unless(s2_check_callstate(nua_callstate_completed)); response = s2_wait_for_response(200, SIP_METHOD_INVITE); fail_if(!response); s2_update_dialog(dialog, response); s2_free_message(response); fail_if(s2_request_to(dialog, SIP_METHOD_ACK, NULL, SIPTAG_CSEQ(cseq), TAG_END())); fail_unless(s2_check_event(nua_i_ack, 200)); fail_unless(s2_check_callstate(nua_callstate_ready)); nua_bye(nh, TAG_END()); bye = s2_wait_for_request(SIP_METHOD_BYE); fail_if(!bye); /* Check that NUA used dialog-specific proxy with BYE */ fail_unless(tport_is_tcp(bye->tport)); s2_respond_to(bye, dialog, SIP_200_OK, TAG_END()); s2_free_message(bye);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -