-
Andrea Gianarda authored4526065f
/*
* Copyright (c) 2010-2019 Belledonne Communications SARL.
*
* This file is part of Liblinphone.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <bctoolbox/tester.h>
#include "tester_utils.h"
#include "call/call.h"
#include "sal/call-op.h"
#include "sal/sal_media_description.h"
#include "shared_tester_functions.h"
#include "c-wrapper/internal/c-tools.h"
using namespace LinphonePrivate;
static void check_ice_from_rtp(LinphoneCall *c1, LinphoneCall *c2, LinphoneStreamType stream_type) {
MediaStream *ms;
LinphoneCallStats *stats;
switch (stream_type) {
case LinphoneStreamTypeAudio:
ms=linphone_call_get_stream(c1, LinphoneStreamTypeAudio);
break;
case LinphoneStreamTypeVideo:
ms=linphone_call_get_stream(c1, LinphoneStreamTypeVideo);
break;
case LinphoneStreamTypeText:
ms=linphone_call_get_stream(c1, LinphoneStreamTypeText);
break;
default:
lError() << "Unknown stream type [" << linphone_stream_type_to_string(stream_type) << "]";
BC_ASSERT_FALSE(stream_type >= LinphoneStreamTypeUnknown);
return;
}
stats = linphone_call_get_audio_stats(c1);
if (linphone_call_stats_get_ice_state(stats) == LinphoneIceStateHostConnection && media_stream_started(ms)) {
struct sockaddr_storage remaddr;
socklen_t remaddrlen = sizeof(remaddr);
char ip[NI_MAXHOST] = { 0 };
int port = 0;
std::string expected_addr;
AudioStream *astream;
const LinphoneCallParams *cp1 = linphone_call_get_current_params(c1);
const LinphoneCallParams *cp2 = linphone_call_get_current_params(c2);
if (linphone_call_params_get_update_call_when_ice_completed(cp1) && linphone_call_params_get_update_call_when_ice_completed(cp2)) {
memset(&remaddr, 0, remaddrlen);
LinphonePrivate::SalCallOp * op = LinphonePrivate::Call::toCpp(c2)->getOp();
const std::shared_ptr<SalMediaDescription> & result_desc = op->getFinalMediaDescription();
const auto & result_stream = result_desc->getStreamIdx(0);
if (result_stream != Utils::getEmptyConstRefObject<SalStreamDescription>()) {
expected_addr = result_stream.getRtpAddress();
}
if (expected_addr.empty()) {
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
expected_addr = result_desc->getAddress();
}
astream = (AudioStream *)linphone_call_get_stream(c1, LinphoneStreamTypeAudio);
if ((expected_addr.find(':') == std::string::npos) && (astream->ms.sessions.rtp_session->rtp.gs.rem_addr.ss_family == AF_INET6)) {
bctbx_sockaddr_ipv6_to_ipv4((struct sockaddr *)&astream->ms.sessions.rtp_session->rtp.gs.rem_addr, (struct sockaddr *)&remaddr, &remaddrlen);
} else {
memcpy(&remaddr, &astream->ms.sessions.rtp_session->rtp.gs.rem_addr, astream->ms.sessions.rtp_session->rtp.gs.rem_addrlen);
}
bctbx_sockaddr_to_ip_address((struct sockaddr *)&remaddr, remaddrlen, ip, sizeof(ip), &port);
BC_ASSERT_STRING_EQUAL(ip, expected_addr.c_str());
}
}
linphone_call_stats_unref(stats);
}
bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, LinphoneIceState state) {
LinphoneCall *c1,*c2;
bool_t global_success = TRUE;
bool_t audio_success=FALSE;
bool_t video_success=FALSE;
bool_t text_success=FALSE;
bool_t audio_enabled, video_enabled, realtime_text_enabled;
MSTimeSpec ts;
c1=linphone_core_get_current_call(caller->lc);
c2=linphone_core_get_current_call(callee->lc);
BC_ASSERT_PTR_NOT_NULL(c1);
BC_ASSERT_PTR_NOT_NULL(c2);
if (!c1 || !c2) return FALSE;
linphone_call_ref(c1);
linphone_call_ref(c2);
BC_ASSERT_EQUAL(linphone_call_params_video_enabled(linphone_call_get_current_params(c1)),linphone_call_params_video_enabled(linphone_call_get_current_params(c2)), int, "%d");
BC_ASSERT_EQUAL(linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(c1)),linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(c2)), int, "%d");
audio_enabled=linphone_call_params_audio_enabled(linphone_call_get_current_params(c1));
video_enabled=linphone_call_params_video_enabled(linphone_call_get_current_params(c1));
realtime_text_enabled=linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(c1));
if (audio_enabled) {
liblinphone_tester_clock_start(&ts);
LinphoneCallStats *stats1 = NULL;
LinphoneCallStats *stats2 = NULL;
do {
if ((c1 != NULL) && (c2 != NULL)) {
stats1 = linphone_call_get_audio_stats(c1);
stats2 = linphone_call_get_audio_stats(c2);
if (linphone_call_stats_get_ice_state(stats1)==state &&
linphone_call_stats_get_ice_state(stats2)==state){
audio_success=TRUE;
check_ice_from_rtp(c1,c2,LinphoneStreamTypeAudio);
check_ice_from_rtp(c2,c1,LinphoneStreamTypeAudio);
break;
}
linphone_core_iterate(caller->lc);
linphone_core_iterate(callee->lc);
linphone_call_stats_unref(stats1);
linphone_call_stats_unref(stats2);
stats1 = stats2 = NULL;
}
ms_usleep(20000);
} while (!liblinphone_tester_clock_elapsed(&ts,10000));
if (stats1)
linphone_call_stats_unref(stats1);
if (stats2)
linphone_call_stats_unref(stats2);
}
if (video_enabled){
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
liblinphone_tester_clock_start(&ts);
LinphoneCallStats *stats1 = NULL;
LinphoneCallStats *stats2 = NULL;
do {
if ((c1 != NULL) && (c2 != NULL)) {
stats1 = linphone_call_get_video_stats(c1);
stats2 = linphone_call_get_video_stats(c2);
if (linphone_call_stats_get_ice_state(stats1)==state &&
linphone_call_stats_get_ice_state(stats2)==state){
video_success=TRUE;
check_ice_from_rtp(c1,c2,LinphoneStreamTypeVideo);
check_ice_from_rtp(c2,c1,LinphoneStreamTypeVideo);
break;
}
linphone_core_iterate(caller->lc);
linphone_core_iterate(callee->lc);
linphone_call_stats_unref(stats1);
linphone_call_stats_unref(stats2);
stats1 = stats2 = NULL;
}
ms_usleep(20000);
} while (!liblinphone_tester_clock_elapsed(&ts,10000));
if (stats1)
linphone_call_stats_unref(stats1);
if (stats2)
linphone_call_stats_unref(stats2);
}
if (realtime_text_enabled){
liblinphone_tester_clock_start(&ts);
LinphoneCallStats *stats1 = NULL;
LinphoneCallStats *stats2 = NULL;
do {
if ((c1 != NULL) && (c2 != NULL)) {
stats1 = linphone_call_get_text_stats(c1);
stats2 = linphone_call_get_text_stats(c2);
if (linphone_call_stats_get_ice_state(stats1)==state &&
linphone_call_stats_get_ice_state(stats2)==state){
text_success=TRUE;
check_ice_from_rtp(c1,c2,LinphoneStreamTypeText);
check_ice_from_rtp(c2,c1,LinphoneStreamTypeText);
break;
}
linphone_core_iterate(caller->lc);
linphone_core_iterate(callee->lc);
linphone_call_stats_unref(stats1);
linphone_call_stats_unref(stats2);
stats1 = stats2 = NULL;
}
ms_usleep(20000);
} while (!liblinphone_tester_clock_elapsed(&ts,10000));
if (stats1)
linphone_call_stats_unref(stats1);
if (stats2)
linphone_call_stats_unref(stats2);
}
linphone_call_unref(c1);
linphone_call_unref(c2);
if (audio_enabled) global_success = global_success && audio_success;
if (video_enabled) global_success = global_success && video_success;
if (realtime_text_enabled) global_success = global_success && text_success;
return global_success;
}
bool_t check_ice_sdp (LinphoneCall *call) {
SalMediaDescription *desc = _linphone_call_get_local_desc(call);
belle_sdp_session_description_t *sdp = desc->toSdp();
const char *value=belle_sdp_session_description_get_attribute_value(sdp,"ice-ufrag");
if (value) return TRUE;
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
return FALSE;
}
bool_t is_srtp_secured (LinphoneCall *call, LinphoneStreamType ctype) {
SalStreamType type = SalOther;
switch(ctype){
case LinphoneStreamTypeAudio:
type = SalAudio;
break;
case LinphoneStreamTypeVideo:
type = SalVideo;
break;
case LinphoneStreamTypeText:
type = SalText;
break;
default:
type = SalOther;
break;
}
SalMediaDescription *desc = _linphone_call_get_result_desc(call);
const SalStreamDescription & stream = desc->findBestStream(type);
if (stream == Utils::getEmptyConstRefObject<SalStreamDescription>()) return FALSE;
if (stream.hasSrtp()) {
const auto & streamCryptos = stream.getCryptos();
for (const auto & crypto : streamCryptos) {
const auto & algo = crypto.algo;
//return (!ms_crypto_suite_is_unencrypted(algo) && !ms_crypto_suite_is_unauthenticated(algo));
return (!ms_crypto_suite_is_unencrypted(algo));
}
}
return FALSE;
}
void check_media_stream(LinphoneCall *call, bool_t is_null) {
LinphonePrivate::Call * c = LinphonePrivate::Call::toCpp(call);
if (is_null || !linphone_call_params_audio_enabled(linphone_call_get_current_params(call))) {
BC_ASSERT_PTR_NULL(c->getMediaStream(LinphoneStreamTypeAudio));
} else {
BC_ASSERT_PTR_NOT_NULL(c->getMediaStream(LinphoneStreamTypeAudio));
}
if (is_null || !linphone_call_params_video_enabled(linphone_call_get_current_params(call))) {
BC_ASSERT_PTR_NULL(c->getMediaStream(LinphoneStreamTypeVideo));
} else {
BC_ASSERT_PTR_NOT_NULL(c->getMediaStream(LinphoneStreamTypeVideo));
}
if (is_null || !linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) {
BC_ASSERT_PTR_NULL(c->getMediaStream(LinphoneStreamTypeText));
} else {
BC_ASSERT_PTR_NOT_NULL(c->getMediaStream(LinphoneStreamTypeText));
}
}