An error occurred while loading the file. Please try again.
-
Marco Paniconi authored
Change-Id: I11aa90be41dd585c9784301f47a9d580fac09260
1076101b
/*
* Copyright (c) 2010-2023 Belledonne Communications SARL.
*
* This file is part of Liblinphone
* (see https://gitlab.linphone.org/BC/public/liblinphone).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "liblinphone_tester.h"
#include "linphone/core.h"
#include "linphone/lpconfig.h"
#include "linphone/utils/utils.h"
#include "sal/sal_media_description.h"
#include "sal/sal_stream_description.h"
#include "shared_tester_functions.h"
#include "tester_utils.h"
#include <sys/stat.h>
#include <sys/types.h>
using namespace LinphonePrivate;
static int get_codec_position(const MSList *l, const char *mime_type, int rate) {
const MSList *elem;
int i;
for (elem = l, i = 0; elem != NULL; elem = elem->next, i++) {
PayloadType *pt = (PayloadType *)elem->data;
if (strcasecmp(pt->mime_type, mime_type) == 0 && pt->clock_rate == rate) return i;
}
return -1;
}
/*check basic things about codecs at startup: order and enablement*/
static void start_with_no_config(void) {
LinphoneCore *lc =
linphone_factory_create_core_3(linphone_factory_get(), NULL, liblinphone_tester_get_empty_rc(), system_context);
const MSList *codecs = linphone_core_get_audio_codecs(lc);
int opus_codec_pos;
int speex_codec_pos = get_codec_position(codecs, "speex", 8000);
int speex16_codec_pos = get_codec_position(codecs, "speex", 16000);
PayloadType *pt;
opus_codec_pos = get_codec_position(codecs, "opus", 48000);
if (opus_codec_pos != -1) BC_ASSERT_EQUAL(opus_codec_pos, 0, int, "%d");
BC_ASSERT_LOWER(speex16_codec_pos, speex_codec_pos, int, "%d");
pt = linphone_core_find_payload_type(lc, "speex", 16000, 1);
BC_ASSERT_PTR_NOT_NULL(pt);
if (pt) {
BC_ASSERT_TRUE(linphone_core_payload_type_enabled(lc, pt));
}
linphone_core_unref(lc);
}
static void check_payload_type_numbers(LinphoneCall *call1, LinphoneCall *call2, int expected_number) {
const LinphoneCallParams *params = linphone_call_get_current_params(call1);
if (!BC_ASSERT_PTR_NOT_NULL(params)) return;
const LinphonePayloadType *pt = linphone_call_params_get_used_audio_payload_type(params);
BC_ASSERT_PTR_NOT_NULL(pt);
if (pt) {
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
BC_ASSERT_EQUAL(linphone_payload_type_get_number(pt), expected_number, int, "%d");
}
params = linphone_call_get_current_params(call2);
pt = linphone_call_params_get_used_audio_payload_type(params);
BC_ASSERT_PTR_NOT_NULL(pt);
if (pt) {
BC_ASSERT_EQUAL(linphone_payload_type_get_number(pt), expected_number, int, "%d");
}
}
static void simple_call_with_different_codec_mappings_and_config_supplied_sdp_addresses(void) {
LinphoneCoreManager *marie;
LinphoneCoreManager *pauline;
LinphoneCall *pauline_call;
const char *marie4 = "10.0.0.56";
const char *marie6 = "fd00:0bad:f00d::56";
marie = linphone_core_manager_new("marie_rc");
pauline = linphone_core_manager_new("pauline_tcp_rc");
disable_all_audio_codecs_except_one(marie->lc, "pcmu", -1);
disable_all_audio_codecs_except_one(pauline->lc, "pcmu", -1);
/*marie set a fantasy number to PCMU*/
payload_type_set_number(linphone_core_find_payload_type(marie->lc, "PCMU", 8000, -1), 104);
LinphoneConfig *cfg = linphone_core_get_config(marie->lc);
linphone_config_set_string(cfg, "rtp", "ipv4_sdp_address", marie4);
linphone_config_set_string(cfg, "rtp", "ipv6_sdp_address", marie6);
cfg = linphone_core_get_config(pauline->lc);
BC_ASSERT_TRUE(call(marie, pauline));
pauline_call = linphone_core_get_current_call(pauline->lc);
BC_ASSERT_PTR_NOT_NULL(pauline_call);
if (pauline_call) {
LinphoneCallParams *params;
check_payload_type_numbers(linphone_core_get_current_call(marie->lc), pauline_call, 104);
std::string sdp_address = _linphone_call_get_remote_desc(pauline_call)->getConnectionAddress();
BC_ASSERT_TRUE(sdp_address == marie4 || sdp_address == marie6);
/*make a reinvite in the other direction*/
linphone_call_update(pauline_call, params = linphone_core_create_call_params(pauline->lc, pauline_call));
linphone_call_params_unref(params);
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneCallUpdating, 1));
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneCallUpdatedByRemote, 1));
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 2));
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 2));
/*payload type numbers shall remain the same*/
check_payload_type_numbers(linphone_core_get_current_call(marie->lc), pauline_call, 104);
}
end_call(marie, pauline);
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void simple_call_with_fmtps(void) {
LinphoneCoreManager *marie;
LinphoneCoreManager *pauline;
LinphoneCall *pauline_call;
marie = linphone_core_manager_new("marie_rc");
pauline = linphone_core_manager_new("pauline_tcp_rc");
disable_all_audio_codecs_except_one(marie->lc, "pcmu", -1);
disable_all_audio_codecs_except_one(pauline->lc, "pcmu", -1);
/*marie set a fantasy fmtp to PCMU*/
LinphonePayloadType *marie_pt = linphone_core_get_payload_type(marie->lc, "PCMU", 8000, -1);
linphone_payload_type_set_recv_fmtp(marie_pt, "parles-plus-fort=1");
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
linphone_payload_type_unref(marie_pt);
BC_ASSERT_TRUE(call(marie, pauline));
pauline_call = linphone_core_get_current_call(pauline->lc);
BC_ASSERT_PTR_NOT_NULL(pauline_call);
if (pauline_call) {
const LinphonePayloadType *pt =
linphone_call_params_get_used_audio_payload_type(linphone_call_get_current_params(pauline_call));
BC_ASSERT_PTR_NOT_NULL(pt);
if (pt) {
BC_ASSERT_STRING_EQUAL(linphone_payload_type_get_send_fmtp(pt), "parles-plus-fort=1");
}
pt = linphone_call_params_get_used_audio_payload_type(
linphone_call_get_current_params(linphone_core_get_current_call(marie->lc)));
BC_ASSERT_PTR_NOT_NULL(pt);
if (pt) {
ms_message("send_fmtp=%s, recv_fmtp=%s", linphone_payload_type_get_send_fmtp(pt),
linphone_payload_type_get_recv_fmtp(pt));
BC_ASSERT_STRING_EQUAL(linphone_payload_type_get_recv_fmtp(pt), "parles-plus-fort=1");
}
}
end_call(marie, pauline);
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
#ifdef VIDEO_ENABLED
static void h264_call_with_fmtps(void) {
LinphoneCoreManager *marie;
LinphoneCoreManager *pauline;
LinphoneCall *pauline_call;
OrtpPayloadType *pt_1 = NULL, *pt_2 = NULL;
marie = linphone_core_manager_new("marie_rc");
pauline = linphone_core_manager_new("pauline_tcp_rc");
bctbx_list_t *video_codecs = NULL;
OrtpPayloadType *origin_h264_pt = NULL;
linphone_core_set_video_device(marie->lc, "Mire: Mire (synthetic moving picture)");
linphone_core_enable_video_capture(marie->lc, TRUE);
linphone_core_enable_video_display(marie->lc, TRUE);
linphone_core_enable_video_capture(pauline->lc, TRUE);
linphone_core_enable_video_display(pauline->lc, TRUE);
LinphoneVideoActivationPolicy *pol = linphone_factory_create_video_activation_policy(linphone_factory_get());
linphone_video_activation_policy_set_automatically_accept(pol, TRUE);
linphone_video_activation_policy_set_automatically_initiate(pol, TRUE);
linphone_core_set_video_activation_policy(marie->lc, pol);
linphone_core_set_video_activation_policy(pauline->lc, pol);
linphone_video_activation_policy_unref(pol);
LinphonePayloadType *marie_pt = linphone_core_get_payload_type(marie->lc, "h264", 90000, -1);
if (!marie_pt) {
ms_warning("H264 not available on this platform, skeeping");
goto end;
}
linphone_payload_type_unref(marie_pt);
disable_all_video_codecs_except_one(marie->lc, "H264");
disable_all_video_codecs_except_one(pauline->lc, "H264");
origin_h264_pt = linphone_core_find_payload_type(pauline->lc, "H264", 90000, -1);
pt_1 = payload_type_clone(origin_h264_pt);
pt_2 = payload_type_clone(pt_1);
payload_type_set_recv_fmtp(pt_1, "profile-level-id=42801F; packetization-mode=0");
payload_type_set_recv_fmtp(pt_2, "profile-level-id=42801F; packetization-mode=1");
video_codecs = bctbx_list_copy(linphone_core_get_video_codecs(marie->lc));
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
for (bctbx_list_t *it = video_codecs; it != NULL; it = bctbx_list_next(it)) {
OrtpPayloadType *pt = (OrtpPayloadType *)bctbx_list_get_data(it);
if (strcasecmp(payload_type_get_mime(pt), "H264") == 0) {
video_codecs = bctbx_list_remove(video_codecs, pt);
break; // one
}
}
video_codecs = bctbx_list_append(video_codecs, pt_1);
video_codecs = bctbx_list_append(video_codecs, pt_2);
linphone_core_set_video_codecs(marie->lc, video_codecs);
/*marie set packetization-mode=1*/
// linphone_payload_type_set_recv_fmtp(linphone_core_get_payload_type(marie->lc, "h264", 90000, -1),
// "profile-level-id=42801F ");
BC_ASSERT_TRUE(call(marie, pauline));
pauline_call = linphone_core_get_current_call(pauline->lc);
BC_ASSERT_PTR_NOT_NULL(pauline_call);
if (pauline_call) {
const LinphonePayloadType *pt =
linphone_call_params_get_used_video_payload_type(linphone_call_get_current_params(pauline_call));
BC_ASSERT_PTR_NOT_NULL(pt);
if (pt) {
BC_ASSERT_PTR_NOT_NULL(strstr(linphone_payload_type_get_recv_fmtp(pt), "packetization-mode=1"));
}
pt = linphone_call_params_get_used_video_payload_type(
linphone_call_get_current_params(linphone_core_get_current_call(marie->lc)));
BC_ASSERT_PTR_NOT_NULL(pt);
if (pt) {
ms_message("send_fmtp=%s, recv_fmtp=%s", linphone_payload_type_get_send_fmtp(pt),
linphone_payload_type_get_recv_fmtp(pt));
BC_ASSERT_PTR_NOT_NULL(strstr(linphone_payload_type_get_recv_fmtp(pt), "packetization-mode=1"));
BC_ASSERT_PTR_NOT_NULL(strstr(linphone_payload_type_get_recv_fmtp(pt), "packetization-mode=1"));
}
}
end_call(marie, pauline);
end:
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
if (pt_1) payload_type_destroy(pt_1);
if (pt_2) payload_type_destroy(pt_2);
}
static void enable_rtp_bundle(LinphoneCore *lc, bool_t enable) {
if (enable == false) {
linphone_config_set_bool(linphone_core_get_config(lc), "rtp", "accept_bundle", FALSE);
}
LinphoneAccount *account = linphone_core_get_default_account(lc);
LinphoneAccountParams *account_params = linphone_account_params_clone(linphone_account_get_params(account));
linphone_account_params_enable_rtp_bundle(account_params, enable);
linphone_account_set_params(account, account_params);
linphone_account_params_unref(account_params);
}
static void enable_video_stream(LinphoneCore *lc, LinphoneVideoActivationPolicy *policy) {
linphone_core_set_video_device(lc, "Mire: Mire (synthetic moving picture)");
linphone_core_enable_video_capture(lc, TRUE);
linphone_core_enable_video_display(lc, TRUE);
linphone_core_set_video_activation_policy(lc, policy);
}
typedef struct flexfec_scenarios_t {
bool_t bundle_proposed;
bool_t fec_proposed;
bool_t bundle_accepted;
bool_t fec_accepted;
} flexfec_scenarios;
static void _base_video_call_for_fec(flexfec_scenarios params) {
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
LinphoneCoreManager *marie;
LinphoneCoreManager *pauline;
LinphoneCall *pauline_call;
marie = linphone_core_manager_new("marie_rc");
pauline = linphone_core_manager_new("pauline_rc");
LinphoneVideoActivationPolicy *pol = linphone_factory_create_video_activation_policy(linphone_factory_get());
linphone_video_activation_policy_set_automatically_accept(pol, TRUE);
linphone_video_activation_policy_set_automatically_initiate(pol, TRUE);
enable_rtp_bundle(marie->lc, params.bundle_proposed);
enable_rtp_bundle(pauline->lc, params.bundle_accepted);
linphone_core_enable_fec(marie->lc, params.fec_proposed);
linphone_core_enable_fec(pauline->lc, params.fec_accepted);
enable_video_stream(marie->lc, pol);
enable_video_stream(pauline->lc, pol);
linphone_video_activation_policy_unref(pol);
BC_ASSERT_TRUE(call(marie, pauline));
pauline_call = linphone_core_get_current_call(pauline->lc);
if (pauline_call) {
const LinphoneCallParams *call_params = linphone_call_get_current_params(pauline_call);
bool_t bundle_enabled = linphone_call_params_rtp_bundle_enabled(call_params);
if (params.bundle_proposed && params.bundle_accepted) BC_ASSERT_TRUE(bundle_enabled);
else {
BC_ASSERT_FALSE(bundle_enabled);
}
}
end_call(marie, pauline);
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
void flexfec_test_both_proposed_both_accepted(void) {
flexfec_scenarios params = {TRUE, TRUE, TRUE, TRUE};
_base_video_call_for_fec(params);
}
void flexfec_test_both_proposed_bundle_accepted(void) {
flexfec_scenarios params = {TRUE, TRUE, TRUE, FALSE};
_base_video_call_for_fec(params);
}
void flexfec_test_both_proposed_nothing_accepted(void) {
flexfec_scenarios params = {TRUE, TRUE, FALSE, FALSE};
_base_video_call_for_fec(params);
}
void flexfec_test_both_poposed_only_fec_accepted(void) {
flexfec_scenarios params = {TRUE, TRUE, FALSE, TRUE};
_base_video_call_for_fec(params);
}
void flexfec_test_only_fec_proposed_and_accepted(void) {
flexfec_scenarios params = {FALSE, TRUE, FALSE, TRUE};
_base_video_call_for_fec(params);
}
static void h264_call_receiver_with_no_h264_support(void) {
LinphoneCoreManager *marie;
LinphoneCoreManager *pauline;
LinphoneCall *pauline_call;
marie = linphone_core_manager_new("marie_rc");
pauline = linphone_core_manager_new("pauline_tcp_rc");
linphone_core_set_video_device(marie->lc, "Mire: Mire (synthetic moving picture)");
linphone_core_enable_video_capture(marie->lc, TRUE);
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
linphone_core_enable_video_display(marie->lc, TRUE);
linphone_core_enable_video_capture(pauline->lc, TRUE);
linphone_core_enable_video_display(pauline->lc, TRUE);
LinphoneVideoActivationPolicy *pol = linphone_factory_create_video_activation_policy(linphone_factory_get());
linphone_video_activation_policy_set_automatically_accept(pol, TRUE);
linphone_video_activation_policy_set_automatically_initiate(pol, TRUE);
linphone_core_set_video_activation_policy(marie->lc, pol);
linphone_core_set_video_activation_policy(pauline->lc, pol);
linphone_video_activation_policy_unref(pol);
LinphonePayloadType *marie_pt = linphone_core_get_payload_type(marie->lc, "h264", 90000, -1);
if (!marie_pt) {
ms_warning("H264 not available on this platform, skeeping");
goto end;
}
linphone_payload_type_unref(marie_pt);
disable_all_video_codecs_except_one(marie->lc, "H264");
disable_all_video_codecs_except_one(pauline->lc, "VP8");
BC_ASSERT_TRUE(call(marie, pauline));
pauline_call = linphone_core_get_current_call(pauline->lc);
BC_ASSERT_PTR_NOT_NULL(pauline_call);
if (pauline_call) {
const LinphonePayloadType *pt =
linphone_call_params_get_used_video_payload_type(linphone_call_get_current_params(pauline_call));
BC_ASSERT_PTR_NULL(pt);
pt = linphone_call_params_get_used_video_payload_type(
linphone_call_get_current_params(linphone_core_get_current_call(marie->lc)));
BC_ASSERT_PTR_NULL(pt);
}
end_call(marie, pauline);
end:
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void h264_call_without_packetization_mode(void) {
LinphoneCoreManager *marie;
LinphoneCoreManager *pauline;
LinphoneCall *pauline_call;
OrtpPayloadType *pt_1 = NULL, *pt_2 = NULL;
marie = linphone_core_manager_new("marie_rc");
pauline = linphone_core_manager_new("pauline_tcp_rc");
linphone_core_set_video_device(marie->lc, "Mire: Mire (synthetic moving picture)");
linphone_core_enable_video_capture(marie->lc, TRUE);
linphone_core_enable_video_display(marie->lc, TRUE);
linphone_core_enable_video_capture(pauline->lc, TRUE);
linphone_core_enable_video_display(pauline->lc, TRUE);
LinphoneVideoActivationPolicy *pol = linphone_factory_create_video_activation_policy(linphone_factory_get());
linphone_video_activation_policy_set_automatically_accept(pol, TRUE);
linphone_video_activation_policy_set_automatically_initiate(pol, TRUE);
linphone_core_set_video_activation_policy(marie->lc, pol);
linphone_core_set_video_activation_policy(pauline->lc, pol);
linphone_video_activation_policy_unref(pol);
LinphonePayloadType *marie_pt = linphone_core_get_payload_type(marie->lc, "h264", 90000, -1);
if (!marie_pt) {
ms_warning("H264 not available on this platform, skeeping");
goto end;
}
linphone_payload_type_unref(marie_pt);
disable_all_video_codecs_except_one(marie->lc, "H264");
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
disable_all_video_codecs_except_one(pauline->lc, "H264");
BC_ASSERT_TRUE(call(marie, pauline));
pauline_call = linphone_core_get_current_call(pauline->lc);
BC_ASSERT_PTR_NOT_NULL(pauline_call);
if (pauline_call) {
const LinphonePayloadType *pt =
linphone_call_params_get_used_video_payload_type(linphone_call_get_current_params(pauline_call));
BC_ASSERT_PTR_NOT_NULL(pt);
if (pt) {
BC_ASSERT_PTR_NULL(strstr(linphone_payload_type_get_recv_fmtp(pt), "packetization-mode"));
}
pt = linphone_call_params_get_used_video_payload_type(
linphone_call_get_current_params(linphone_core_get_current_call(marie->lc)));
BC_ASSERT_PTR_NOT_NULL(pt);
if (pt) {
ms_message("send_fmtp=%s, recv_fmtp=%s", linphone_payload_type_get_send_fmtp(pt),
linphone_payload_type_get_recv_fmtp(pt));
BC_ASSERT_PTR_NULL(strstr(linphone_payload_type_get_recv_fmtp(pt), "packetization-mode"));
BC_ASSERT_PTR_NULL(strstr(linphone_payload_type_get_recv_fmtp(pt), "packetization-mode"));
}
}
end_call(marie, pauline);
end:
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
if (pt_1) payload_type_destroy(pt_1);
if (pt_2) payload_type_destroy(pt_2);
}
#endif
static void call_failed_because_of_codecs(void) {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
LinphoneCall *out_call;
disable_all_audio_codecs_except_one(marie->lc, "pcmu", -1);
disable_all_audio_codecs_except_one(pauline->lc, "pcma", -1);
out_call = linphone_core_invite_address(pauline->lc, marie->identity);
linphone_call_ref(out_call);
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneCallOutgoingInit, 1));
/*flexisip will retain the 488 until the "urgent reply" timeout (I.E 5s) arrives.*/
BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneCallError, 1, 7000));
BC_ASSERT_EQUAL(linphone_call_get_reason(out_call), LinphoneReasonNotAcceptable, int, "%d");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingReceived, 0, int, "%d");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallReleased, 0, int, "%d");
linphone_call_unref(out_call);
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void profile_call_base(bool_t avpf1,
LinphoneMediaEncryption srtp1,
bool_t avpf2,
LinphoneMediaEncryption srtp2,
bool_t encryption_mandatory,
const char *expected_profile,
bool_t enable_video) {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
LinphoneProxyConfig *lpc;
const LinphoneCallParams *params;
if (avpf1) {
lpc = linphone_core_get_default_proxy_config(marie->lc);
linphone_proxy_config_edit(lpc);
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
linphone_proxy_config_set_avpf_mode(lpc, LinphoneAVPFEnabled);
linphone_proxy_config_set_avpf_rr_interval(lpc, 3);
linphone_proxy_config_done(lpc);
}
if (avpf2) {
lpc = linphone_core_get_default_proxy_config(pauline->lc);
linphone_proxy_config_edit(lpc);
linphone_proxy_config_set_avpf_mode(lpc, LinphoneAVPFEnabled);
linphone_proxy_config_set_avpf_rr_interval(lpc, 3);
linphone_proxy_config_done(lpc);
}
if (encryption_mandatory) {
linphone_core_set_media_encryption_mandatory(marie->lc, TRUE);
linphone_core_set_media_encryption_mandatory(pauline->lc, TRUE);
}
if (enable_video && linphone_core_video_supported(marie->lc)) {
LinphoneVideoPolicy policy;
policy.automatically_accept = TRUE;
policy.automatically_initiate = TRUE;
linphone_core_enable_video_capture(marie->lc, TRUE);
linphone_core_enable_video_display(marie->lc, TRUE);
linphone_core_set_video_policy(marie->lc, &policy);
linphone_core_enable_video_capture(pauline->lc, TRUE);
linphone_core_enable_video_display(pauline->lc, TRUE);
linphone_core_set_video_policy(pauline->lc, &policy);
}
if (linphone_core_media_encryption_supported(marie->lc, srtp1)) {
linphone_core_set_media_encryption(marie->lc, srtp1);
} else {
ms_message("Unsupported [%s] encryption type, cannot test", linphone_media_encryption_to_string(srtp1));
goto end;
}
if (linphone_core_media_encryption_supported(pauline->lc, srtp2)) {
linphone_core_set_media_encryption(pauline->lc, srtp2);
} else {
ms_message("Unsupported [%s] encryption type, cannot test", linphone_media_encryption_to_string(srtp2));
goto end;
}
if (!BC_ASSERT_TRUE(call(marie, pauline))) goto end;
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1));
wait_for_until(marie->lc, pauline->lc, NULL, 0, 1000); /*wait 1 second for streams to start flowing*/
if (linphone_core_get_current_call(marie->lc)) {
params = linphone_call_get_current_params(linphone_core_get_current_call(marie->lc));
BC_ASSERT_STRING_EQUAL(linphone_call_params_get_rtp_profile(params), expected_profile);
}
if (linphone_core_get_current_call(pauline->lc)) {
params = linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc));
BC_ASSERT_STRING_EQUAL(linphone_call_params_get_rtp_profile(params), expected_profile);
}
linphone_core_terminate_all_calls(marie->lc);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallReleased, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallReleased, 1));
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallConnected, 1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallConnected, 1, int, "%d");
end:
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(marie);
}
#ifdef VIDEO_ENABLED
/*This test simulates a case where an audio/video call is sent with AVPF only for video, not audio. */
static void avp_avpf_video_call(void) {
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
LinphoneProxyConfig *lpc;
const LinphoneCallParams *params;
const char *expected_profile = "RTP/AVPF";
linphone_config_set_bool(linphone_core_get_config(marie->lc), "misc", "no_avpf_for_audio", TRUE);
lpc = linphone_core_get_default_proxy_config(marie->lc);
linphone_proxy_config_edit(lpc);
linphone_proxy_config_set_avpf_mode(lpc, LinphoneAVPFEnabled);
linphone_proxy_config_set_avpf_rr_interval(lpc, 3);
linphone_proxy_config_done(lpc);
lpc = linphone_core_get_default_proxy_config(pauline->lc);
linphone_proxy_config_edit(lpc);
linphone_proxy_config_set_avpf_mode(lpc, LinphoneAVPFEnabled);
linphone_proxy_config_set_avpf_rr_interval(lpc, 3);
linphone_proxy_config_done(lpc);
if (linphone_core_video_supported(marie->lc)) {
LinphoneVideoPolicy policy;
policy.automatically_accept = TRUE;
policy.automatically_initiate = TRUE;
linphone_core_enable_video_capture(marie->lc, TRUE);
linphone_core_enable_video_display(marie->lc, TRUE);
linphone_core_set_video_policy(marie->lc, &policy);
linphone_core_enable_video_capture(pauline->lc, TRUE);
linphone_core_enable_video_display(pauline->lc, TRUE);
linphone_core_set_video_policy(pauline->lc, &policy);
}
if (!BC_ASSERT_TRUE(call(marie, pauline))) goto end;
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1));
wait_for_until(marie->lc, pauline->lc, NULL, 0, 1000); /*wait 1 second for streams to start flowing*/
if (linphone_core_get_current_call(marie->lc)) {
params = linphone_call_get_current_params(linphone_core_get_current_call(marie->lc));
BC_ASSERT_STRING_EQUAL(linphone_call_params_get_rtp_profile(params), expected_profile);
}
if (linphone_core_get_current_call(pauline->lc)) {
params = linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc));
BC_ASSERT_STRING_EQUAL(linphone_call_params_get_rtp_profile(params), expected_profile);
}
BC_ASSERT_TRUE(linphone_call_params_audio_enabled(
linphone_call_get_current_params(linphone_core_get_current_call(marie->lc))));
BC_ASSERT_TRUE(linphone_call_params_audio_enabled(
linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc))));
linphone_core_terminate_all_calls(marie->lc);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallReleased, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallReleased, 1));
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallConnected, 1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallConnected, 1, int, "%d");
end:
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(marie);
}
#endif
static void profile_call(bool_t avpf1,
LinphoneMediaEncryption srtp1,
bool_t avpf2,
LinphoneMediaEncryption srtp2,
const char *expected_profile,
bool_t enable_video) {
profile_call_base(avpf1, srtp1, avpf2, srtp2, FALSE, expected_profile, enable_video);
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
}
static void avp_to_avp_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionNone, FALSE, LinphoneMediaEncryptionNone, "RTP/AVP", FALSE);
}
#ifdef VIDEO_ENABLED
static void avp_to_avp_video_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionNone, FALSE, LinphoneMediaEncryptionNone, "RTP/AVP", TRUE);
}
#endif
static void avp_to_avpf_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionNone, TRUE, LinphoneMediaEncryptionNone, "RTP/AVP", FALSE);
}
#ifdef VIDEO_ENABLED
static void avp_to_avpf_video_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionNone, TRUE, LinphoneMediaEncryptionNone, "RTP/AVP", TRUE);
}
#endif
static void avp_to_savp_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionNone, FALSE, LinphoneMediaEncryptionSRTP, "RTP/AVP", FALSE);
}
#ifdef VIDEO_ENABLED
static void avp_to_savp_video_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionNone, FALSE, LinphoneMediaEncryptionSRTP, "RTP/AVP", TRUE);
}
#endif
static void avp_to_savpf_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionNone, TRUE, LinphoneMediaEncryptionSRTP, "RTP/AVP", FALSE);
}
#ifdef VIDEO_ENABLED
static void avp_to_savpf_video_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionNone, TRUE, LinphoneMediaEncryptionSRTP, "RTP/AVP", TRUE);
}
#endif
static void avpf_to_avp_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionNone, FALSE, LinphoneMediaEncryptionNone, "RTP/AVPF", FALSE);
}
#ifdef VIDEO_ENABLED
static void avpf_to_avp_video_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionNone, FALSE, LinphoneMediaEncryptionNone, "RTP/AVPF", TRUE);
}
#endif
static void avpf_to_avpf_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionNone, TRUE, LinphoneMediaEncryptionNone, "RTP/AVPF", FALSE);
}
#ifdef VIDEO_ENABLED
static void avpf_to_avpf_video_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionNone, TRUE, LinphoneMediaEncryptionNone, "RTP/AVPF", TRUE);
}
#endif
static void avpf_to_savp_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionNone, FALSE, LinphoneMediaEncryptionSRTP, "RTP/AVPF", FALSE);
}
#ifdef VIDEO_ENABLED
static void avpf_to_savp_video_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionNone, FALSE, LinphoneMediaEncryptionSRTP, "RTP/AVPF", TRUE);
}
#endif
static void avpf_to_savpf_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionNone, TRUE, LinphoneMediaEncryptionSRTP, "RTP/AVPF", FALSE);
}
#ifdef VIDEO_ENABLED
static void avpf_to_savpf_video_call(void) {
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
profile_call(TRUE, LinphoneMediaEncryptionNone, TRUE, LinphoneMediaEncryptionSRTP, "RTP/AVPF", TRUE);
}
#endif
static void savp_to_avp_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionSRTP, FALSE, LinphoneMediaEncryptionNone, "RTP/SAVP", FALSE);
}
#ifdef VIDEO_ENABLED
static void savp_to_avp_video_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionSRTP, FALSE, LinphoneMediaEncryptionNone, "RTP/SAVP", TRUE);
}
#endif
static void savp_to_avpf_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionSRTP, TRUE, LinphoneMediaEncryptionNone, "RTP/SAVP", FALSE);
}
#ifdef VIDEO_ENABLED
static void savp_to_avpf_video_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionSRTP, TRUE, LinphoneMediaEncryptionNone, "RTP/SAVP", TRUE);
}
#endif
static void savp_to_savp_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionSRTP, FALSE, LinphoneMediaEncryptionSRTP, "RTP/SAVP", FALSE);
}
#ifdef VIDEO_ENABLED
static void savp_to_savp_video_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionSRTP, FALSE, LinphoneMediaEncryptionSRTP, "RTP/SAVP", TRUE);
}
#endif
static void savp_to_savpf_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionSRTP, TRUE, LinphoneMediaEncryptionSRTP, "RTP/SAVP", FALSE);
}
#ifdef VIDEO_ENABLED
static void savp_to_savpf_video_call(void) {
profile_call(FALSE, LinphoneMediaEncryptionSRTP, TRUE, LinphoneMediaEncryptionSRTP, "RTP/SAVP", TRUE);
}
#endif
static void savpf_to_avp_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionSRTP, FALSE, LinphoneMediaEncryptionNone, "RTP/SAVPF", FALSE);
}
#ifdef VIDEO_ENABLED
static void savpf_to_avp_video_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionSRTP, FALSE, LinphoneMediaEncryptionNone, "RTP/SAVPF", TRUE);
}
#endif
static void savpf_to_avpf_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionSRTP, TRUE, LinphoneMediaEncryptionNone, "RTP/SAVPF", FALSE);
}
#ifdef VIDEO_ENABLED
static void savpf_to_avpf_video_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionSRTP, TRUE, LinphoneMediaEncryptionNone, "RTP/SAVPF", TRUE);
}
#endif
static void savpf_to_savp_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionSRTP, FALSE, LinphoneMediaEncryptionSRTP, "RTP/SAVPF", FALSE);
}
#ifdef VIDEO_ENABLED
static void savpf_to_savp_video_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionSRTP, FALSE, LinphoneMediaEncryptionSRTP, "RTP/SAVPF", TRUE);
}
#endif
static void savpf_to_savpf_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionSRTP, TRUE, LinphoneMediaEncryptionSRTP, "RTP/SAVPF", FALSE);
}
#ifdef VIDEO_ENABLED
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
static void savpf_to_savpf_video_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionSRTP, TRUE, LinphoneMediaEncryptionSRTP, "RTP/SAVPF", TRUE);
}
#endif
static void savpf_dtls_to_savpf_dtls_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionDTLS, TRUE, LinphoneMediaEncryptionDTLS, "UDP/TLS/RTP/SAVPF", FALSE);
}
#ifdef VIDEO_ENABLED
static void savpf_dtls_to_savpf_dtls_video_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionDTLS, TRUE, LinphoneMediaEncryptionDTLS, "UDP/TLS/RTP/SAVPF", TRUE);
}
#endif
static void savpf_dtls_to_savpf_dtls_encryption_mandatory_call(void) {
profile_call_base(TRUE, LinphoneMediaEncryptionDTLS, TRUE, LinphoneMediaEncryptionDTLS, TRUE, "UDP/TLS/RTP/SAVPF",
FALSE);
}
#ifdef VIDEO_ENABLED
static void savpf_dtls_to_savpf_dtls_encryption_mandatory_video_call(void) {
profile_call_base(TRUE, LinphoneMediaEncryptionDTLS, TRUE, LinphoneMediaEncryptionDTLS, TRUE, "UDP/TLS/RTP/SAVPF",
TRUE);
}
#endif
static void savpf_dtls_to_savpf_encryption_mandatory_call(void) {
/*profile_call_base(TRUE, LinphoneMediaEncryptionDTLS, TRUE, LinphoneMediaEncryptionSRTP, TRUE,
* "UDP/TLS/RTP/SAVPF",FALSE); not sure of result*/
}
#ifdef VIDEO_ENABLED
static void savpf_dtls_to_savpf_encryption_mandatory_video_call(void) {
/*profile_call_base(TRUE, LinphoneMediaEncryptionDTLS, TRUE, LinphoneMediaEncryptionSRTP, TRUE,
* "UDP/TLS/RTP/SAVPF",TRUE); not sure of result*/
}
#endif
static void savpf_dtls_to_savpf_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionDTLS, TRUE, LinphoneMediaEncryptionSRTP, "UDP/TLS/RTP/SAVPF", FALSE);
}
#ifdef VIDEO_ENABLED
static void savpf_dtls_to_savpf_video_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionDTLS, TRUE, LinphoneMediaEncryptionSRTP, "UDP/TLS/RTP/SAVPF", TRUE);
}
#endif
static void savpf_dtls_to_avpf_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionDTLS, TRUE, LinphoneMediaEncryptionNone, "UDP/TLS/RTP/SAVPF", FALSE);
}
#ifdef VIDEO_ENABLED
static void savpf_dtls_to_avpf_video_call(void) {
profile_call(TRUE, LinphoneMediaEncryptionDTLS, TRUE, LinphoneMediaEncryptionNone, "UDP/TLS/RTP/SAVPF", TRUE);
}
#endif
#ifdef VIDEO_ENABLED
static OrtpPayloadType *configure_core_for_avpf_and_video(LinphoneCore *lc) {
LinphoneProxyConfig *lpc;
OrtpPayloadType *pt;
LinphoneVideoPolicy policy = {0};
policy.automatically_initiate = TRUE;
policy.automatically_accept = TRUE;
lpc = linphone_core_get_default_proxy_config(lc);
linphone_proxy_config_edit(lpc);
linphone_proxy_config_set_avpf_mode(lpc, LinphoneAVPFEnabled);
linphone_proxy_config_set_avpf_rr_interval(lpc, 3);
linphone_proxy_config_done(lpc);
linphone_core_set_video_device(lc, "StaticImage: Static picture");
linphone_core_enable_video_capture(lc, TRUE);
linphone_core_enable_video_display(lc, TRUE);
841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
linphone_core_set_video_policy(lc, &policy);
pt = linphone_core_find_payload_type(lc, "VP8", 90000, -1);
if (pt == NULL) {
ms_warning("VP8 codec not available.");
} else {
disable_all_video_codecs_except_one(lc, "VP8");
}
return pt;
}
static void check_avpf_features(LinphoneCore *lc, unsigned char expected_features) {
LinphoneCall *lcall = linphone_core_get_current_call(lc);
BC_ASSERT_PTR_NOT_NULL(lcall);
if (lcall != NULL) {
SalMediaDescription *resultDesc = _linphone_call_get_result_desc(lcall);
const auto &desc = resultDesc->findStream(SalProtoRtpAvpf, SalVideo);
BC_ASSERT_TRUE(desc != Utils::getEmptyConstRefObject<SalStreamDescription>());
if (desc != Utils::getEmptyConstRefObject<SalStreamDescription>()) {
const auto &payloads = desc.getPayloads();
BC_ASSERT_FALSE(payloads.empty());
if (!payloads.empty()) {
PayloadType *pt = payloads.front();
BC_ASSERT_STRING_EQUAL(pt->mime_type, "VP8");
BC_ASSERT_EQUAL(pt->avpf.features, expected_features, int, "%d");
}
}
}
}
static void compatible_avpf_features(void) {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
OrtpPayloadType *pt;
bool_t call_ok;
if (configure_core_for_avpf_and_video(marie->lc) == NULL) goto end;
pt = configure_core_for_avpf_and_video(pauline->lc);
BC_ASSERT_TRUE((call_ok = call(marie, pauline)));
if (!call_ok) goto end;
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1));
wait_for_until(marie->lc, pauline->lc, NULL, 0, 1000); /*wait 1 second for streams to start flowing*/
check_avpf_features(marie->lc, pt->avpf.features);
check_avpf_features(pauline->lc, pt->avpf.features);
end_call(marie, pauline);
end:
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(marie);
}
static void incompatible_avpf_features(void) {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
OrtpPayloadType *pt;
bool_t call_ok;
if (configure_core_for_avpf_and_video(marie->lc) == NULL) goto end;
pt = configure_core_for_avpf_and_video(pauline->lc);
pt->avpf.features = PAYLOAD_TYPE_AVPF_NONE;
BC_ASSERT_TRUE(call_ok = call(marie, pauline));
if (!call_ok) goto end;
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1));
wait_for_until(marie->lc, pauline->lc, NULL, 0, 1000); /*wait 1 second for streams to start flowing*/
911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
check_avpf_features(marie->lc, PAYLOAD_TYPE_AVPF_NONE);
check_avpf_features(pauline->lc, PAYLOAD_TYPE_AVPF_NONE);
end_call(marie, pauline);
end:
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(marie);
}
static void call_with_two_audio_streams(void) {
const char *crashing_invite =
"INVITE sip:631453@212.55.48.36:51230;transport=udp SIP/2.0\r\n"
"Via: SIP/2.0/UDP 212.55.48.2:5060;branch=z9hG4bKac1473882254\r\n"
"Max-Forwards: 19\r\n"
"From: \"Mickey Mouse\" <sip:mickey@example.com;user=phone>;tag=1c849167855\r\n"
"To: \"Bugs Bunny\" <sip:bunny@example.com>\r\n"
"Call-ID: 9771187781832022142418@212.55.48.2\r\n"
"CSeq: 1 INVITE\r\n"
"Contact: <sip:212.55.48.2:5060>\r\n"
"Supported: 100rel,sdp-anat\r\n"
"Allow: ACK,BYE,CANCEL,INFO,INVITE,OPTIONS,PRACK,REFER,NOTIFY,UPDATE\r\n"
"User-Agent: vSBC PROD/v.7.20A.258.459\r\n"
"Accept:application/media_control+xml,application/sdp,multipart/mixed\r\n"
"Recv-Info:x-broadworks-client-session-info\r\n"
"Content-Type: application/sdp\r\n"
"Content-Length: 860\r\n"
"\r\n"
"v=0\r\n"
"o=BroadWorks 1693848685 415741525 IN IP4 212.55.48.2\r\n"
"s=-\r\n"
"c=IN IP4 212.55.48.2\r\n"
"t=0 0\r\n"
"m=audio 15536 RTP/AVP 8 0 18 116\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:116 telephone-event/8000\r\n"
"a=ptime:20\r\n"
"a=3gOoBTC\r\n"
"a=rtpmap:18 G729/8000\r\n"
"a=fmtp:18 annexb=yes\r\n"
"m=audio 15536 RTP/SAVP 8 0 18 116\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:116 telephone-event/8000\r\n"
"a=ptime:20\r\n"
"a=3gOoBTC\r\n"
"a=rtpmap:18 G729/8000\r\n"
"a=fmtp:18 annexb=yes\r\n"
"a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:zc409/eT1JuwUPQAswLkF878WJvn5Rpo+aLUt+SI|2^31\r\n"
"a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:ebHN/WPPcu2E+Jm4kdx9YK58jVFDKD4uRgwFu18k|2^31\r\n"
"a=crypto:3 AES_256_CM_HMAC_SHA1_80 "
"inline:M9UR+6n8F8DZ5mh/V5vh2VKdYZ+5Hb4K3mwepx8oM9aIQYb7RzdfJE42ezOTcQ==|2^31\r\n"
"a=crypto:4 AES_256_CM_HMAC_SHA1_32 "
"inline:AIsXIk2O8tsCefUYXpqP96hNZKJR+nJZcXlCOiXZW6TDEtg/g5HQD7lcj0KJPA==|2^31\r\n";
LinphoneCoreManager *laure = linphone_core_manager_new("laure_rc_udp");
LinphoneTransports *tp = linphone_core_get_transports_used(laure->lc);
BC_ASSERT_TRUE(liblinphone_tester_send_data(crashing_invite, strlen(crashing_invite), "127.0.0.1",
linphone_transports_get_udp_port(tp), SOCK_DGRAM) > 0);
linphone_transports_unref(tp);
BC_ASSERT_TRUE(wait_for(laure->lc, NULL, &laure->stat.number_of_LinphoneCallIncomingReceived, 1));
LinphoneCall *laure_call = linphone_core_get_current_call(laure->lc);
BC_ASSERT_PTR_NOT_NULL(laure_call);
if (laure_call) {
linphone_call_accept(laure_call);
BC_ASSERT_TRUE(wait_for(laure->lc, NULL, &laure->stat.number_of_LinphoneCallStreamsRunning, 1));
const LinphoneCallParams *laure_call_param = linphone_call_get_current_params(laure_call);
981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
const LinphoneMediaEncryption laure_enc = linphone_call_params_get_media_encryption(laure_call_param);
BC_ASSERT_EQUAL(laure_enc, LinphoneMediaEncryptionNone, int, "%d");
linphone_call_terminate(laure_call);
}
BC_ASSERT_TRUE(wait_for(laure->lc, NULL, &laure->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for_until(laure->lc, NULL, &laure->stat.number_of_LinphoneCallReleased, 1, 36000));
linphone_core_manager_destroy(laure);
}
static void _call_with_unknown_stream(bool_t accepted, bool_t unknown_at_end) {
const char *unsupported_invite_base =
"INVITE sip:3827m@192.168.50.222:54989;transport=udp SIP/2.0\r\n"
"Via: SIP/2.0/UDP 5.135.31.160:5060;branch=z9hG4bKsAOMEtSQmuUlZRFV268653\r\n"
"Accept-Language: en\r\n"
"Call-ID: 20220209215755041746-3e68c7f9f40b7da9df92cf4b0e08742e\r\n"
"Contact: <sip:5.135.31.160:5060;transport=udp>\r\n"
"CSeq: 201 INVITE\r\n"
"From: \"Donald duck\" <sip:7956@example.com>;tag=gOobZHXFNJsMD6aT268645\r\n"
"Max-Forwards: 19\r\n"
"To: <sip:mickey@example.com>\r\n"
"Date: Wed, 09 Feb 2022 21:57:58 GMT\r\n"
"Server: unknown server\r\n"
"Allow: INVITE,ACK,BYE,CANCEL,OPTIONS,INFO,MESSAGE,SUBSCRIBE,NOTIFY,PRACK,UPDATE,REFER\r\n"
"Allow-Events: conference,talk,hold\r\n"
"Supported: timer\r\n"
"Content-Type: application/sdp\r\n"
"Content-Length: 908\r\n"
"\r\n"
"v=0\r\n"
"o=PouetPouet_Tra 1644443875 1644443878181 IN IP4 5.135.31.160\r\n"
"s=kokokok IP Phone\r\n"
"c=IN IP4 5.135.31.160\r\n"
"b=AS:2048\r\n"
"t=0 0\r\n"
"a=sendrecv\r\n"
"m=audio 26192 RTP/AVP 0 8 9 18 101\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"a=rtpmap:9 G722/8000\r\n"
"a=rtpmap:18 G729/8000\r\n"
"a=fmtp:18 annexb=no\r\n"
"a=rtpmap:101 telephone-event/8000\r\n";
const char *application_stream_sdp = "m=application 2244 RTP/AVP 124\r\n"
"a=rtpmap:124 H224/4800\r\n";
const char *video_stream_sdp =
"m=video 26592 RTP/AVP 100 113 109 99\r\n"
"a=rtcp-fb:* ccm fir\r\n"
"a=rtpmap:100 H264/90000\r\n"
"a=fmtp:100 profile-level-id=64001f; packetization-mode=1; max-mbps=108000; max-fs=3600\r\n"
"a=rtpmap:113 H264/90000\r\n"
"a=fmtp:113 profile-level-id=64001f; packetization-mode=0; max-mbps=108000; max-fs=3600\r\n"
"a=rtpmap:109 H264/90000\r\n"
"a=fmtp:109 profile-level-id=42801f; packetization-mode=1; max-mbps=108000; max-fs=3600\r\n"
"a=rtpmap:99 H264/90000\r\n"
"a=fmtp:99 profile-level-id=42801f; packetization-mode=0; max-mbps=108000; max-fs=3600\r\n"
"a=rtcp-fb:* ccm fir\r\n";
LinphoneCoreManager *laure = linphone_core_manager_new("laure_rc_udp");
LinphoneTransports *tp = linphone_core_get_transports_used(laure->lc);
char *unsupported_invite;
if (unknown_at_end) {
unsupported_invite =
bctbx_strdup_printf("%s%s%s", unsupported_invite_base, video_stream_sdp, application_stream_sdp);
} else {
unsupported_invite =
bctbx_strdup_printf("%s%s%s", unsupported_invite_base, application_stream_sdp, video_stream_sdp);
1051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
}
BC_ASSERT_TRUE(liblinphone_tester_send_data(unsupported_invite, strlen(unsupported_invite), "127.0.0.1",
linphone_transports_get_udp_port(tp), SOCK_DGRAM) > 0);
linphone_transports_unref(tp);
bctbx_free(unsupported_invite);
BC_ASSERT_TRUE(wait_for(laure->lc, NULL, &laure->stat.number_of_LinphoneCallIncomingReceived, 1));
if (accepted) {
linphone_call_accept(linphone_core_get_current_call(laure->lc));
BC_ASSERT_TRUE(wait_for(laure->lc, NULL, &laure->stat.number_of_LinphoneCallStreamsRunning, 1));
auto resultDesc = _linphone_call_get_result_desc(linphone_core_get_current_call(laure->lc));
std::string streamType = resultDesc->getStreamIdx(unknown_at_end ? 2 : 1).getTypeAsString();
BC_ASSERT_STRING_EQUAL(streamType.c_str(), "application");
linphone_call_terminate(linphone_core_get_current_call(laure->lc));
} else {
linphone_call_decline(linphone_core_get_current_call(laure->lc), LinphoneReasonDeclined);
}
BC_ASSERT_TRUE(wait_for(laure->lc, NULL, &laure->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for_until(laure->lc, NULL, &laure->stat.number_of_LinphoneCallReleased, 1, 36000));
linphone_core_manager_destroy(laure);
}
static void call_with_unknown_stream(void) {
_call_with_unknown_stream(FALSE, FALSE);
}
static void call_with_unknown_stream_accepted(void) {
_call_with_unknown_stream(TRUE, FALSE);
}
static void call_with_unknown_stream_accepted_2(void) {
_call_with_unknown_stream(TRUE, TRUE);
}
static void activate_video_and_ice(LinphoneCoreManager *m) {
LinphoneVideoActivationPolicy *pol = linphone_factory_create_video_activation_policy(linphone_factory_get());
LinphoneNatPolicy *nat_policy;
LinphoneAccountParams *account_params;
LinphoneAccount *account;
linphone_video_activation_policy_set_automatically_initiate(pol, TRUE);
linphone_video_activation_policy_set_automatically_accept(pol, TRUE);
linphone_core_set_video_activation_policy(m->lc, pol);
linphone_video_activation_policy_unref(pol);
linphone_core_enable_video_capture(m->lc, TRUE);
linphone_core_enable_video_display(m->lc, TRUE);
nat_policy = linphone_core_create_nat_policy(m->lc);
linphone_nat_policy_enable_ice(nat_policy, TRUE);
account = linphone_core_get_default_account(m->lc);
account_params = linphone_account_params_clone(linphone_account_get_params(account));
linphone_account_params_set_nat_policy(account_params, nat_policy);
linphone_account_set_params(account, account_params);
linphone_account_params_unref(account_params);
linphone_nat_policy_unref(nat_policy);
linphone_core_set_video_device(m->lc, liblinphone_tester_static_image_id);
}
static bool_t codec_appears_first(LinphoneCore *lc, const char *codec) {
bctbx_list_t *codec_list = linphone_core_get_video_payload_types(lc);
LinphonePayloadType *pt = (LinphonePayloadType *)codec_list->data;
bool_t ret = strcasecmp(codec, linphone_payload_type_get_mime_type(pt)) == 0;
bctbx_list_free_with_data(codec_list, (bctbx_list_free_func)linphone_payload_type_unref);
return ret;
}
1121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
static const char *call_selected_codec(LinphoneCall *call) {
const LinphoneCallParams *current_params = linphone_call_get_current_params(call);
const LinphonePayloadType *pt = linphone_call_params_get_used_video_payload_type(current_params);
if (BC_ASSERT_PTR_NOT_NULL(pt)) {
return linphone_payload_type_get_mime_type(pt);
}
return "";
}
static void check_linphonerc_config(const char *rcfile) {
char *path = bc_tester_res(rcfile);
if (BC_ASSERT_PTR_NOT_NULL(path)) {
LinphoneConfig *config = linphone_factory_create_config(linphone_factory_get(), path);
if (BC_ASSERT_PTR_NOT_NULL(config)) {
BC_ASSERT_STRING_EQUAL(linphone_config_get_string(config, "video", "codec_priority_policy", "unset"),
"unset");
linphone_config_unref(config);
}
bc_free(path);
}
}
static void call_with_video_codec_priority_policy(void) {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
LinphonePayloadType *vp8, *av1;
LinphoneCall *marie_call, *pauline_call;
vp8 = linphone_core_get_payload_type(pauline->lc, "VP8", 90000, -1);
av1 = linphone_core_get_payload_type(pauline->lc, "AV1", 90000, -1);
if (!vp8 || !av1) {
ms_warning("This test requires both VP8 and AV1 video codecs, skipped.");
goto end;
}
activate_video_and_ice(marie);
activate_video_and_ice(pauline);
/* Make sure that configuration files do not mention codec_priority_policy.*/
check_linphonerc_config("rcfiles/marie_rc");
check_linphonerc_config("rcfiles/pauline_tcp_rc");
/* PolicyAuto is the default one. However Marie has a video codec list defined, so in absence of
[video]video_priority_policy item written in its configuration file, we must assume it is using the basic policy.
*/
BC_ASSERT_TRUE(linphone_core_get_video_codec_priority_policy(marie->lc) == LinphoneCodecPriorityPolicyBasic);
BC_ASSERT_TRUE(linphone_core_get_video_codec_priority_policy(pauline->lc) == LinphoneCodecPriorityPolicyAuto);
BC_ASSERT_TRUE(codec_appears_first(marie->lc, "AV1"));
BC_ASSERT_TRUE(codec_appears_first(pauline->lc, "AV1"));
/* this is to force to re-compute the codec list order: */
linphone_core_set_video_codec_priority_policy(pauline->lc, LinphoneCodecPriorityPolicyBasic);
/* AV1 is before VP8 by default. Give an artificial bonus to VP8. Normally this is done at startup*/
linphone_payload_type_set_priority_bonus(vp8, TRUE); // this function is not public, apps should not do this.
linphone_core_set_video_codec_priority_policy(pauline->lc, LinphoneCodecPriorityPolicyAuto);
/* now vp8 shall appear first */
BC_ASSERT_TRUE(codec_appears_first(pauline->lc, "VP8"));
marie_call = linphone_core_invite_address(marie->lc, pauline->identity);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1));
pauline_call = linphone_core_get_current_call(pauline->lc);
if (!BC_ASSERT_PTR_NOT_NULL(pauline_call)) goto end;
linphone_call_accept(pauline_call);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1));
BC_ASSERT_STRING_EQUAL(call_selected_codec(marie_call), "VP8");
BC_ASSERT_STRING_EQUAL(call_selected_codec(pauline_call), "VP8");
1191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
/* Now comes the ICE re-INVITE */
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 2));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 2));
/* Assert that the ICE re-invite did not change the selected codec */
BC_ASSERT_STRING_EQUAL(call_selected_codec(marie_call), "VP8");
BC_ASSERT_STRING_EQUAL(call_selected_codec(pauline_call), "VP8");
wait_for_until(marie->lc, pauline->lc, NULL, 0, 1000);
linphone_call_terminate(pauline_call);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallReleased, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallReleased, 1));
/* Assert the priority policy for pauline is now set */
BC_ASSERT_STRING_EQUAL(
linphone_config_get_string(linphone_core_get_config(pauline->lc), "video", "codec_priority_policy", "unset"),
"1");
end:
if (av1) linphone_payload_type_unref(av1);
if (vp8) linphone_payload_type_unref(vp8);
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
#endif
static test_t offeranswer_tests[] = {
TEST_NO_TAG("Start with no config", start_with_no_config),
TEST_NO_TAG("Call failed because of codecs", call_failed_because_of_codecs),
TEST_NO_TAG("Simple call with different codec mappings and config-supplied sdp address",
simple_call_with_different_codec_mappings_and_config_supplied_sdp_addresses),
TEST_NO_TAG("Simple call with fmtps", simple_call_with_fmtps),
TEST_NO_TAG("AVP to AVP call", avp_to_avp_call),
TEST_NO_TAG("AVP to AVPF call", avp_to_avpf_call),
TEST_NO_TAG("AVP to SAVP call", avp_to_savp_call),
TEST_NO_TAG("AVP to SAVPF call", avp_to_savpf_call),
TEST_NO_TAG("AVPF to AVP call", avpf_to_avp_call),
TEST_NO_TAG("AVPF to AVPF call", avpf_to_avpf_call),
TEST_NO_TAG("AVPF to SAVP call", avpf_to_savp_call),
TEST_NO_TAG("AVPF to SAVPF call", avpf_to_savpf_call),
TEST_NO_TAG("SAVP to AVP call", savp_to_avp_call),
TEST_NO_TAG("SAVP to AVPF call", savp_to_avpf_call),
TEST_NO_TAG("SAVP to SAVP call", savp_to_savp_call),
TEST_NO_TAG("SAVP to SAVPF call", savp_to_savpf_call),
TEST_NO_TAG("SAVPF to AVP call", savpf_to_avp_call),
TEST_NO_TAG("SAVPF to AVPF call", savpf_to_avpf_call),
TEST_NO_TAG("SAVPF to SAVP call", savpf_to_savp_call),
TEST_NO_TAG("SAVPF to SAVPF call", savpf_to_savpf_call),
TEST_ONE_TAG("SAVPF/DTLS to SAVPF/DTLS call", savpf_dtls_to_savpf_dtls_call, "DTLS"),
TEST_ONE_TAG("SAVPF/DTLS to SAVPF/DTLS encryption mandatory call",
savpf_dtls_to_savpf_dtls_encryption_mandatory_call,
"DTLS"),
TEST_ONE_TAG("SAVPF/DTLS to SAVPF call", savpf_dtls_to_savpf_call, "DTLS"),
TEST_ONE_TAG(
"SAVPF/DTLS to SAVPF encryption mandatory call", savpf_dtls_to_savpf_encryption_mandatory_call, "DTLS"),
TEST_ONE_TAG("SAVPF/DTLS to AVPF call", savpf_dtls_to_avpf_call, "DTLS"),
#ifdef VIDEO_ENABLED
TEST_NO_TAG("AVP to AVP video call", avp_to_avp_video_call),
TEST_NO_TAG("AVP to AVPF video call", avp_to_avpf_video_call),
TEST_NO_TAG("AVP to SAVP video call", avp_to_savp_video_call),
TEST_NO_TAG("AVP to SAVPF video call", avp_to_savpf_video_call),
TEST_NO_TAG("AVPF to AVP video call", avpf_to_avp_video_call),
TEST_NO_TAG("AVPF to AVPF video call", avpf_to_avpf_video_call),
TEST_NO_TAG("AVPF to SAVP video call", avpf_to_savp_video_call),
TEST_NO_TAG("AVPF to SAVPF video call", avpf_to_savpf_video_call),
TEST_NO_TAG("SAVP to AVP video call", savp_to_avp_video_call),
TEST_NO_TAG("SAVP to AVPF video call", savp_to_avpf_video_call),
TEST_NO_TAG("SAVP to SAVP video call", savp_to_savp_video_call),
TEST_NO_TAG("SAVP to SAVPF video call", savp_to_savpf_video_call),
126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302
TEST_NO_TAG("SAVPF to AVP video call", savpf_to_avp_video_call),
TEST_NO_TAG("SAVPF to AVPF video call", savpf_to_avpf_video_call),
TEST_NO_TAG("SAVPF to SAVP video call", savpf_to_savp_video_call),
TEST_NO_TAG("SAVPF to SAVPF video call", savpf_to_savpf_video_call),
TEST_ONE_TAG("SAVPF/DTLS to SAVPF/DTLS video call", savpf_dtls_to_savpf_dtls_video_call, "DTLS"),
TEST_ONE_TAG("SAVPF/DTLS to SAVPF/DTLS encryption mandatory video call",
savpf_dtls_to_savpf_dtls_encryption_mandatory_video_call,
"DTLS"),
TEST_ONE_TAG("SAVPF/DTLS to SAVPF video call", savpf_dtls_to_savpf_video_call, "DTLS"),
TEST_ONE_TAG("SAVPF/DTLS to SAVPF encryption mandatory video call",
savpf_dtls_to_savpf_encryption_mandatory_video_call,
"DTLS"),
TEST_ONE_TAG("SAVPF/DTLS to AVPF video call", savpf_dtls_to_avpf_video_call, "DTLS"),
TEST_NO_TAG("Compatible AVPF features", compatible_avpf_features),
TEST_NO_TAG("Incompatible AVPF features", incompatible_avpf_features),
TEST_NO_TAG("H264 packetization-mode set to 1 on sender", h264_call_with_fmtps),
TEST_NO_TAG("H264 on sender, but not on receiver", h264_call_receiver_with_no_h264_support),
TEST_NO_TAG("H264 packetization-mode not set", h264_call_without_packetization_mode),
TEST_NO_TAG("Mixed AVP+AVPF video call", avp_avpf_video_call),
TEST_NO_TAG("flexfec both proposed both accepted", flexfec_test_both_proposed_both_accepted),
TEST_NO_TAG("flexfec both proposed bundle accepted", flexfec_test_both_proposed_bundle_accepted),
TEST_NO_TAG("flexfec both proposed nothing accepted", flexfec_test_both_proposed_nothing_accepted),
TEST_NO_TAG("flexfec both proposed only fec accepted", flexfec_test_both_poposed_only_fec_accepted),
TEST_NO_TAG("flexfec only fec proposed and accepted", flexfec_test_only_fec_proposed_and_accepted),
TEST_NO_TAG("Call with unknown stream", call_with_unknown_stream),
TEST_NO_TAG("Call with unknown stream, accepted", call_with_unknown_stream_accepted),
TEST_NO_TAG("Call with unknown stream, accepted 2", call_with_unknown_stream_accepted_2),
TEST_NO_TAG("Call with 2 audio streams", call_with_two_audio_streams),
TEST_NO_TAG("Call with video codec priority policy auto", call_with_video_codec_priority_policy)
#endif
};
test_suite_t offeranswer_test_suite = {"Offer-answer",
NULL,
NULL,
liblinphone_tester_before_each,
liblinphone_tester_after_each,
sizeof(offeranswer_tests) / sizeof(offeranswer_tests[0]),
offeranswer_tests,
0};