Skip to content
Snippets Groups Projects
Commit 78e3c5e8 authored by Sébastien Blin's avatar Sébastien Blin
Browse files

test: remove ice_media_cand_exchange

There were no useful test as it duplicates test for ICE connectivity
and doesn't test media

Change-Id: Ifde558bf44bbd60911385760c209eb4ccab9dc12
parent c9bb7b12
Branches
No related tags found
No related merge requests found
......@@ -216,18 +216,6 @@ test('ice', ut_ice,
workdir: ut_workdir, is_parallel: false, timeout: 1800
)
ut_ice_media_candidates_exchange = executable('ut_ice_media_candidates_exchange',
sources: files('unitTest/ice/ice_media_cand_exchange.cpp'),
include_directories: ut_includedirs,
dependencies: ut_dependencies,
link_with: ut_library
)
test('ice_media_candidates_exchange', ut_ice_media_candidates_exchange,
workdir: ut_workdir, is_parallel: false, timeout: 1800
)
ut_ice_sdp_parser = executable('ut_ice_sdp_parser',
sources: files('unitTest/ice/ice_sdp_parser.cpp'),
include_directories: ut_includedirs,
......
......@@ -225,9 +225,6 @@ ut_revoke_SOURCES = revoke/revoke.cpp common.cpp
check_PROGRAMS += ut_ice_sdp_parser
ut_ice_sdp_parser_SOURCES = ice/ice_sdp_parser.cpp common.cpp
check_PROGRAMS += ut_ice_media_cand_exchange
ut_ice_media_cand_exchange_SOURCES = ice/ice_media_cand_exchange.cpp common.cpp
#
# Calls using SIP accounts
#
......
/*
* Copyright (C) 2021-2024 Savoir-faire Linux Inc.
*
* Author: Mohamed Chibani <mohamed.chibani@savoirfairelinux.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "manager.h"
#include "jamidht/jamiaccount.h"
#include "sip/sipaccount.h"
#include "../../test_runner.h"
#include "jami.h"
#include "media_const.h"
#include "call_const.h"
#include "account_const.h"
#include "sip/sipcall.h"
#include "common.h"
#include <dhtnet/upnp/upnp_control.h>
#include <cppunit/TestAssert.h>
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <condition_variable>
#include <string>
using namespace libjami::Account;
using namespace libjami::Call;
namespace jami {
namespace test {
struct CallData
{
struct Signal
{
Signal(const std::string& callId, const std::string& name, const std::string& event = {})
: callId_(std::move(callId))
, name_(std::move(name))
, event_(std::move(event)) {};
std::string callId_ {};
std::string name_ {};
std::string event_ {};
};
std::string accountId_ {};
std::string displayName_ {};
std::string userName_ {};
std::string alias_ {};
std::string callId_ {};
std::vector<Signal> signals_;
std::condition_variable cv_ {};
std::mutex mtx_;
bool deviceAnnounced_ {false};
bool upnpEnabled_ {false};
bool turnEnabled_ {false};
dhtnet::IpAddr dest_ {};
// SIP accounts only
uint16_t listeningPort_ {0};
};
class IceMediaCandExchangeTest : public CppUnit::TestFixture
{
public:
IceMediaCandExchangeTest()
{
// Init daemon
libjami::init(libjami::InitFlag(libjami::LIBJAMI_FLAG_DEBUG | libjami::LIBJAMI_FLAG_CONSOLE_LOG));
if (not Manager::instance().initialized)
CPPUNIT_ASSERT(libjami::start("jami-sample.yml"));
}
~IceMediaCandExchangeTest() { libjami::fini(); }
static std::string name() { return "IceMediaCandExchangeTest"; }
void setUp();
void tearDown();
private:
// Test cases.
// This is not actual test, it only checks if upnp is
// functional. This information is needed to validate
// generated ICE srflx candidates.
void check_upnp();
void jami_account_no_turn();
void jami_account_with_turn();
void sip_account_no_turn();
void sip_account_with_turn();
CPPUNIT_TEST_SUITE(IceMediaCandExchangeTest);
CPPUNIT_TEST(check_upnp);
CPPUNIT_TEST(jami_account_no_turn);
CPPUNIT_TEST(jami_account_with_turn);
CPPUNIT_TEST_SUITE_END();
// Event/Signal handlers
static void onCallStateChange(const std::string& accountId,
const std::string& callId,
const std::string& state,
CallData& callData);
static void onIncomingCallWithMedia(const std::string& accountId,
const std::string& callId,
const std::vector<libjami::MediaMap> mediaList,
CallData& callData);
static void onMediaNegotiationStatus(const std::string& callId,
const std::string& event,
CallData& callData);
// Helpers
void test_call(const char* accountType);
static void validate_ice_candidates(CallData& user,
const char* accountType,
bool hasUpnp,
bool upnpSameAsPublished);
static void setupJamiAccount(CallData& user);
static void setupSipAccount(CallData& user);
static void setupAccounts(CallData& bob, CallData& alice, const char* accountType);
static void configureAccount(CallData& user, const char* accountType);
static std::string getUserAlias(const std::string& callId);
// Wait for a signal from the callbacks. Some signals also report the event that
// triggered the signal a like the StateChange signal.
static bool waitForSignal(CallData& callData,
const std::string& signal,
const std::string& expectedEvent = {});
private:
CallData aliceData_;
CallData bobData_;
const size_t MEDIA_COUNT {2};
std::condition_variable upnpCv_ {};
std::mutex upnpMtx_;
bool hasUpnp_ {false};
bool upnpAddrSameAsPublished_ {false};
};
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(IceMediaCandExchangeTest, IceMediaCandExchangeTest::name());
void
IceMediaCandExchangeTest::setUp()
{
// Everything is done in ConfigureTest()
}
void
IceMediaCandExchangeTest::tearDown()
{
JAMI_INFO("Remove created accounts...");
wait_for_removal_of({aliceData_.accountId_, bobData_.accountId_});
}
std::string
IceMediaCandExchangeTest::getUserAlias(const std::string& callId)
{
auto call = Manager::instance().getCallFromCallID(callId);
if (call) {
auto const& account = call->getAccount().lock();
if (not account) {
return {};
}
return account->getAccountDetails()[ConfProperties::ALIAS];
}
JAMI_WARN("Call [%s] does not exist!", callId.c_str());
return {};
}
void
IceMediaCandExchangeTest::onIncomingCallWithMedia(const std::string& accountId,
const std::string& callId,
const std::vector<libjami::MediaMap> mediaList,
CallData& callData)
{
CPPUNIT_ASSERT_EQUAL(callData.accountId_, accountId);
JAMI_INFO("Signal [%s] - user [%s] - call [%s] - media count [%lu]",
libjami::CallSignal::IncomingCallWithMedia::name,
callData.alias_.c_str(),
callId.c_str(),
mediaList.size());
if (not Manager::instance().getCallFromCallID(callId)) {
JAMI_WARN("Call [%s] does not exist!", callId.c_str());
callData.callId_ = {};
return;
}
std::unique_lock<std::mutex> lock {callData.mtx_};
callData.callId_ = callId;
callData.signals_.emplace_back(
CallData::Signal(callId, libjami::CallSignal::IncomingCallWithMedia::name));
callData.cv_.notify_one();
}
void
IceMediaCandExchangeTest::onCallStateChange(const std::string&,
const std::string& callId,
const std::string& state,
CallData& callData)
{
JAMI_INFO("Signal [%s] - user [%s] - call [%s] - state [%s]",
libjami::CallSignal::StateChange::name,
callData.alias_.c_str(),
callId.c_str(),
state.c_str());
{
std::unique_lock<std::mutex> lock {callData.mtx_};
callData.signals_.emplace_back(
CallData::Signal(callId, libjami::CallSignal::StateChange::name, state));
}
if (state == "RINGING" or state == "CURRENT" or state == "HUNGUP" or state == "OVER") {
callData.cv_.notify_one();
}
}
void
IceMediaCandExchangeTest::onMediaNegotiationStatus(const std::string& callId,
const std::string& event,
CallData& callData)
{
auto call = Manager::instance().getCallFromCallID(callId);
if (not call) {
JAMI_WARN("Call [%s] does not exist!", callId.c_str());
return;
}
auto account = call->getAccount().lock();
if (not account) {
JAMI_WARN("Account owning the call [%s] does not exist!", callId.c_str());
return;
}
JAMI_INFO("Signal [%s] - user [%s] - call [%s] - state [%s]",
libjami::CallSignal::MediaNegotiationStatus::name,
account->getAccountDetails()[ConfProperties::ALIAS].c_str(),
call->getCallId().c_str(),
event.c_str());
if (account->getAccountID() != callData.accountId_)
return;
{
std::unique_lock<std::mutex> lock {callData.mtx_};
callData.signals_.emplace_back(
CallData::Signal(callId, libjami::CallSignal::MediaNegotiationStatus::name, event));
}
callData.cv_.notify_one();
}
bool
IceMediaCandExchangeTest::waitForSignal(CallData& callData,
const std::string& expectedSignal,
const std::string& expectedEvent)
{
const std::chrono::seconds TIME_OUT {45};
std::unique_lock<std::mutex> lock {callData.mtx_};
// Combined signal + event (if any).
std::string sigEvent(expectedSignal);
if (not expectedEvent.empty())
sigEvent += "::" + expectedEvent;
JAMI_INFO("[%s] is waiting for [%s] signal/event", callData.alias_.c_str(), sigEvent.c_str());
auto res = callData.cv_.wait_for(lock, TIME_OUT, [&] {
// Search for the expected signal in list of received signals.
for (auto it = callData.signals_.begin(); it != callData.signals_.end(); it++) {
// The predicate is true if the signal names match, and if the
// expectedEvent is not empty, the events must also match.
if (it->name_ == expectedSignal
and (expectedEvent.empty() or it->event_ == expectedEvent)) {
// Done with this signal.
callData.signals_.erase(it);
return true;
}
}
// Signal/event not found.
return false;
});
if (not res) {
JAMI_ERR("[%s] waiting for signal/event [%s] [call:%s] timed-out!",
callData.alias_.c_str(),
sigEvent.c_str(),
callData.callId_.c_str());
JAMI_INFO("[%s] currently has the following signals:", callData.alias_.c_str());
for (auto const& sig : callData.signals_) {
JAMI_INFO() << "Signal [" << sig.name_
<< (sig.event_.empty() ? "" : ("::" + sig.event_)) << "] "
<< "call [" << sig.callId_ << "]";
}
}
return res;
}
void
IceMediaCandExchangeTest::setupJamiAccount(CallData& user)
{
auto account = Manager::instance().getAccount<JamiAccount>(user.accountId_);
auto details = account->getAccountDetails();
user.userName_ = details[ConfProperties::USERNAME];
user.alias_ = details[ConfProperties::ALIAS];
// Apply the settings according to the test case
details[ConfProperties::UPNP_ENABLED] = user.upnpEnabled_ ? "true" : "false";
details[ConfProperties::TURN::ENABLED] = user.turnEnabled_ ? "true" : "false";
libjami::setAccountDetails(user.accountId_, details);
}
void
IceMediaCandExchangeTest::setupSipAccount(CallData& user)
{
CPPUNIT_ASSERT_GREATER(0, static_cast<int>(user.listeningPort_));
auto details = libjami::getAccountTemplate(libjami::Account::ProtocolNames::SIP);
details[ConfProperties::TYPE] = libjami::Account::ProtocolNames::SIP;
details[ConfProperties::DISPLAYNAME] = user.displayName_.c_str();
details[ConfProperties::ALIAS] = user.displayName_.c_str();
details[ConfProperties::LOCAL_PORT] = std::to_string(user.listeningPort_);
details[ConfProperties::PUBLISHED_PORT] = std::to_string(user.listeningPort_);
details[ConfProperties::PUBLISHED_SAMEAS_LOCAL] = "true";
details[ConfProperties::SRTP::ENABLED] = "false";
details[ConfProperties::SRTP::KEY_EXCHANGE] = "NONE";
// Apply the settings according to the test case
details[ConfProperties::UPNP_ENABLED] = user.upnpEnabled_ ? "true" : "false";
details[ConfProperties::TURN::ENABLED] = user.turnEnabled_ ? "true" : "false";
user.accountId_ = Manager::instance().addAccount(details);
CPPUNIT_ASSERT(not user.accountId_.empty());
auto const& account = Manager::instance().getAccount<Account>(user.accountId_);
details = account->getAccountDetails();
user.userName_ = details[ConfProperties::USERNAME];
user.alias_ = details[ConfProperties::ALIAS];
user.dest_ = dhtnet::ip_utils::getLocalAddr(AF_INET);
user.dest_.setPort(user.listeningPort_);
}
void
IceMediaCandExchangeTest::setupAccounts(CallData& aliceData,
CallData& bobData,
const char* accountType)
{
if (strcmp(accountType, libjami::Account::ProtocolNames::SIP) == 0) {
JAMI_INFO("Setup SIP accounts and configure test case ...");
aliceData.displayName_ = "ALICE";
aliceData.listeningPort_ = 5080;
setupSipAccount(aliceData);
bobData.displayName_ = "BOB";
bobData.listeningPort_ = 5082;
setupSipAccount(bobData);
} else {
JAMI_INFO("Setup JAMI accounts and configure test case ...");
auto actors = load_actors("actors/alice-bob-no-upnp.yml");
aliceData.accountId_ = actors["alice"];
auto const& aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceData.accountId_);
bobData.accountId_ = actors["bob"];
auto const& bobAccount = Manager::instance().getAccount<JamiAccount>(bobData.accountId_);
wait_for_announcement_of({aliceAccount->getAccountID(), bobAccount->getAccountID()});
setupJamiAccount(bobData);
setupJamiAccount(aliceData);
}
// Setup signal handlers.
std::map<std::string, std::shared_ptr<libjami::CallbackWrapperBase>> signalHandlers;
signalHandlers.insert(libjami::exportable_callback<libjami::CallSignal::IncomingCallWithMedia>(
[&](const std::string& accountId,
const std::string& callId,
const std::string&,
const std::vector<libjami::MediaMap> mediaList) {
auto user = getUserAlias(callId);
if (user.empty()) {
// The call was probably already removed, in this case, just
// check callId against current calls.
if (callId == aliceData.callId_)
user = aliceData.alias_;
if (callId == bobData.callId_)
user = bobData.alias_;
}
if (not user.empty()) {
onIncomingCallWithMedia(accountId,
callId,
mediaList,
user == aliceData.alias_ ? aliceData : bobData);
} else {
JAMI_WARN("Received [CallSignal::IncomingCallWithMedia] for a removed call [%s]",
callId.c_str());
}
}));
signalHandlers.insert(
libjami::exportable_callback<libjami::CallSignal::StateChange>([&](const std::string& accountId,
const std::string& callId,
const std::string& state,
signed) {
auto user = getUserAlias(callId);
if (user.empty()) {
// The call was probably already removed, in this case, just
// check callId against current calls.
if (callId == aliceData.callId_)
user = aliceData.alias_;
if (callId == bobData.callId_)
user = bobData.alias_;
}
if (not user.empty()) {
onCallStateChange(accountId,
callId,
state,
user == aliceData.alias_ ? aliceData : bobData);
} else {
JAMI_WARN("Received [StateChange::%s] for a removed call [%s]",
state.c_str(),
callId.c_str());
}
}));
signalHandlers.insert(libjami::exportable_callback<libjami::CallSignal::MediaNegotiationStatus>(
[&](const std::string& callId,
const std::string& event,
const std::vector<std::map<std::string, std::string>>& /* mediaList */) {
auto user = getUserAlias(callId);
if (user.empty()) {
// The call was probably already removed, in this case, just
// check callId against current calls.
if (callId == aliceData.callId_)
user = aliceData.alias_;
if (callId == bobData.callId_)
user = bobData.alias_;
}
if (not user.empty()) {
onMediaNegotiationStatus(callId,
event,
user == aliceData.alias_ ? aliceData : bobData);
} else {
JAMI_WARN("Received [CallSignal::MediaNegotiationStatus] for a removed call [%s]",
callId.c_str());
}
}));
signalHandlers.insert(
libjami::exportable_callback<libjami::ConfigurationSignal::VolatileDetailsChanged>(
[&](const std::string& accountId, const std::map<std::string, std::string>&) {
auto account = Manager::instance().getAccount(accountId);
if (not account) {
JAMI_ERR("No account with ID [%s]", accountId.c_str());
return;
}
auto details = account->getVolatileAccountDetails();
auto deviceAnnounced = details[libjami::Account::VolatileProperties::DEVICE_ANNOUNCED];
if (accountId == aliceData.accountId_) {
aliceData.deviceAnnounced_ = deviceAnnounced == "true";
aliceData.cv_.notify_one();
} else if (accountId == bobData.accountId_) {
bobData.deviceAnnounced_ = deviceAnnounced == "true";
bobData.cv_.notify_one();
} else {
JAMI_ERR("Account with ID [%s] is unknown", accountId.c_str());
}
}));
libjami::registerSignalHandlers(signalHandlers);
}
void
IceMediaCandExchangeTest::configureAccount(CallData& user, const char* accountType)
{
auto details
= strcmp(accountType, libjami::Account::ProtocolNames::RING) == 0
? Manager::instance().getAccount<JamiAccount>(user.accountId_)->getAccountDetails()
: Manager::instance().getAccount<SIPAccount>(user.accountId_)->getAccountDetails();
// Apply the settings according to the test case
details[ConfProperties::UPNP_ENABLED] = user.upnpEnabled_ ? "true" : "false";
details[ConfProperties::TURN::ENABLED] = user.turnEnabled_ ? "true" : "false";
libjami::setAccountDetails(user.accountId_, details);
// Note: setAccountDetails will trigger a re-register of the account, so
// we need to wait for the registration to proceed.
// Only done for JAMI accounts.
if (strcmp(accountType, libjami::Account::ProtocolNames::RING) != 0)
return;
auto account = Manager::instance().getAccount<JamiAccount>(user.accountId_);
CPPUNIT_ASSERT(account);
JAMI_INFO("Waiting for [%s] account [%s] to register ...",
user.alias_.c_str(),
user.accountId_.c_str());
std::unique_lock<std::mutex> lock {user.mtx_};
CPPUNIT_ASSERT(
user.cv_.wait_for(lock, std::chrono::seconds(60), [&] { return user.deviceAnnounced_; }));
}
void
IceMediaCandExchangeTest::validate_ice_candidates(CallData& user,
const char* accountType,
bool hasUpnp,
bool upnpSameAsPublished)
{
auto sipCall = std::dynamic_pointer_cast<SIPCall>(
Manager::instance().getCallFromCallID(user.callId_));
CPPUNIT_ASSERT(sipCall);
// Only check the first component for now.
auto localCand = sipCall->getLocalIceCandidates(1);
// Should not be empty.
CPPUNIT_ASSERT(not localCand.empty());
int srflxCandCount = 0;
int relayCandCount = 0;
for (auto const& cand : localCand) {
JAMI_INFO("[%s] ICE cand: [%s]", user.alias_.c_str(), cand.c_str());
if (cand.find("srflx") != std::string::npos) {
srflxCandCount++;
} else if (cand.find("relay") != std::string::npos) {
relayCandCount++;
}
}
// Note:
// Enabling UPNP does not guarantee that we have valid UPNP srflx
// candidate. However, for RING accounts, we must have at least one
// srflx candidate generated using the public address discovered
// after connecting to the DHT.
// For SIP accounts, we use un-registered (P2P) mode), so srflx
// candidates are only added if UPNP is enabled and the mapping is
// successful.
int expectedSrflxCandCount = 0;
if (strcmp(accountType, libjami::Account::ProtocolNames::RING) == 0) {
if (hasUpnp) {
if (upnpSameAsPublished) {
// UPNP and published are the same, published wont be added.
expectedSrflxCandCount = 1;
} else {
// Both UPNP and published will be added.
expectedSrflxCandCount = 2;
}
} else {
// No UPNP, only published address.
expectedSrflxCandCount = 1;
}
} else {
// SIP accounts in un-registered mode will have only UPNP srflx
// candidates if available
if (hasUpnp) {
expectedSrflxCandCount = 1;
}
}
// Validate srflx
CPPUNIT_ASSERT_EQUAL(expectedSrflxCandCount, srflxCandCount);
// Validate relay
CPPUNIT_ASSERT_EQUAL(user.turnEnabled_ ? 1 : 0, relayCandCount);
}
void
IceMediaCandExchangeTest::test_call(const char* accountType)
{
JAMI_INFO("=== Start a call and validate ICE for account type [%s] ===", accountType);
MediaAttribute media_0(MediaType::MEDIA_AUDIO);
media_0.label_ = "audio_0";
media_0.enabled_ = true;
MediaAttribute media_1(MediaType::MEDIA_VIDEO);
media_1.label_ = "video_0";
media_1.enabled_ = true;
std::vector<MediaAttribute> offer;
offer.emplace_back(media_0);
offer.emplace_back(media_1);
std::vector<MediaAttribute> answer;
answer.emplace_back(media_0);
answer.emplace_back(media_1);
CPPUNIT_ASSERT_EQUAL(MEDIA_COUNT, offer.size());
CPPUNIT_ASSERT_EQUAL(MEDIA_COUNT, answer.size());
// Set the destination according to account type.
auto dest = strcmp(accountType, libjami::Account::ProtocolNames::SIP) == 0
? bobData_.dest_.toString(true)
: bobData_.userName_;
CPPUNIT_ASSERT(not dest.empty());
aliceData_.callId_ = libjami::placeCallWithMedia(aliceData_.accountId_,
dest,
MediaAttribute::mediaAttributesToMediaMaps(
offer));
CPPUNIT_ASSERT(not aliceData_.callId_.empty());
JAMI_INFO("ALICE [%s] started a call with BOB [%s:%s] and wait for answer",
aliceData_.accountId_.c_str(),
bobData_.accountId_.c_str(),
dest.c_str());
// Give it some time to ring
std::this_thread::sleep_for(std::chrono::seconds(2));
// Wait for call to be processed.
CPPUNIT_ASSERT(
waitForSignal(aliceData_, libjami::CallSignal::StateChange::name, StateEvent::RINGING));
// Wait for incoming call signal.
CPPUNIT_ASSERT(waitForSignal(bobData_, libjami::CallSignal::IncomingCallWithMedia::name));
// Answer the call.
libjami::acceptWithMedia(bobData_.accountId_,
bobData_.callId_,
MediaAttribute::mediaAttributesToMediaMaps(answer));
// Wait for media negotiation complete signal.
CPPUNIT_ASSERT(waitForSignal(bobData_,
libjami::CallSignal::MediaNegotiationStatus::name,
libjami::Media::MediaNegotiationStatusEvents::NEGOTIATION_SUCCESS));
// Wait for the StateChange signal.
CPPUNIT_ASSERT(
waitForSignal(bobData_, libjami::CallSignal::StateChange::name, StateEvent::CURRENT));
JAMI_INFO("BOB answered the call [%s]", bobData_.callId_.c_str());
// Wait for media negotiation complete signal.
CPPUNIT_ASSERT(waitForSignal(aliceData_,
libjami::CallSignal::MediaNegotiationStatus::name,
libjami::Media::MediaNegotiationStatusEvents::NEGOTIATION_SUCCESS));
// Validate ICE candidates
validate_ice_candidates(aliceData_, accountType, hasUpnp_, upnpAddrSameAsPublished_);
validate_ice_candidates(bobData_, accountType, hasUpnp_, upnpAddrSameAsPublished_);
// Give some time to media to start.
std::this_thread::sleep_for(std::chrono::seconds(2));
// Bob hang-up.
JAMI_INFO("Hang up BOB's call and wait for ALICE to hang up");
Manager::instance().hangupCall(bobData_.accountId_, bobData_.callId_);
CPPUNIT_ASSERT(
waitForSignal(bobData_, libjami::CallSignal::StateChange::name, StateEvent::HUNGUP));
CPPUNIT_ASSERT(
waitForSignal(aliceData_, libjami::CallSignal::StateChange::name, StateEvent::HUNGUP));
CPPUNIT_ASSERT(waitForSignal(bobData_, libjami::CallSignal::StateChange::name, StateEvent::OVER));
CPPUNIT_ASSERT(
waitForSignal(aliceData_, libjami::CallSignal::StateChange::name, StateEvent::OVER));
JAMI_INFO("Call terminated on both sides");
// Reset signals
aliceData_.signals_.clear();
aliceData_.callId_.clear();
bobData_.signals_.clear();
bobData_.callId_.clear();
}
void
IceMediaCandExchangeTest::check_upnp()
{
auto accountType = libjami::Account::ProtocolNames::RING;
setupAccounts(aliceData_, bobData_, accountType);
auto const& account = Manager::instance().getAccount<JamiAccount>(aliceData_.accountId_);
auto publishedAddr = account->getPublishedIpAddress(AF_INET);
const std::chrono::seconds TIME_OUT {15};
auto upnpCtrl = std::make_shared<dhtnet::upnp::Controller>(Manager::instance().upnpContext());
dhtnet::upnp::Mapping map {dhtnet::upnp::PortType::UDP};
std::string upnpAddr {};
map.setNotifyCallback([this_ = this, &publishedAddr, &upnpAddr](
dhtnet::upnp::Mapping::sharedPtr_t mapRes) {
if (mapRes->getState() == dhtnet::upnp::MappingState::OPEN) {
upnpAddr = mapRes->getExternalAddress();
this_->upnpAddrSameAsPublished_ = publishedAddr.toString(false).compare(upnpAddr) == 0;
this_->hasUpnp_ = true;
this_->upnpCv_.notify_one();
} else {
this_->upnpAddrSameAsPublished_ = false;
this_->hasUpnp_ = false;
}
});
upnpCtrl->reserveMapping(map);
JAMI_INFO("Waiting for upnp request response ...");
std::unique_lock<std::mutex> lock(upnpMtx_);
auto res = upnpCv_.wait_for(lock, TIME_OUT, [this_ = this] { return this_->hasUpnp_; });
if (res) {
JAMI_INFO("UPNP is available");
if (upnpAddrSameAsPublished_) {
JAMI_INFO("UPNP address [%s] same as published address: expect only one srflx cand per "
"component",
upnpAddr.c_str());
} else {
JAMI_INFO("UPNP [%s] and published [%s] addresses differ: expect two srflx cand per "
"component",
upnpAddr.c_str(),
publishedAddr.toString().c_str());
}
} else {
JAMI_WARN("UPNP is not available (timeout!)");
}
}
void
IceMediaCandExchangeTest::jami_account_no_turn()
{
JAMI_INFO("=== Begin test %s ===", __FUNCTION__);
auto accountType = libjami::Account::ProtocolNames::RING;
setupAccounts(aliceData_, bobData_, accountType);
bobData_.turnEnabled_ = false;
aliceData_.turnEnabled_ = false;
{
aliceData_.upnpEnabled_ = false;
bobData_.upnpEnabled_ = false;
configureAccount(aliceData_, accountType);
configureAccount(bobData_, accountType);
test_call(accountType);
}
{
aliceData_.upnpEnabled_ = true;
bobData_.upnpEnabled_ = false;
configureAccount(aliceData_, accountType);
configureAccount(bobData_, accountType);
test_call(accountType);
}
{
aliceData_.upnpEnabled_ = false;
bobData_.upnpEnabled_ = true;
configureAccount(aliceData_, accountType);
configureAccount(bobData_, accountType);
test_call(accountType);
}
{
aliceData_.upnpEnabled_ = true;
bobData_.upnpEnabled_ = true;
configureAccount(aliceData_, accountType);
configureAccount(bobData_, accountType);
test_call(accountType);
}
}
void
IceMediaCandExchangeTest::jami_account_with_turn()
{
JAMI_INFO("=== Begin test %s ===", __FUNCTION__);
auto accountType = libjami::Account::ProtocolNames::RING;
setupAccounts(aliceData_, bobData_, accountType);
bobData_.turnEnabled_ = true;
aliceData_.turnEnabled_ = true;
{
aliceData_.upnpEnabled_ = false;
bobData_.upnpEnabled_ = false;
configureAccount(aliceData_, accountType);
configureAccount(bobData_, accountType);
test_call(accountType);
}
{
aliceData_.upnpEnabled_ = true;
bobData_.upnpEnabled_ = false;
configureAccount(aliceData_, accountType);
configureAccount(bobData_, accountType);
test_call(accountType);
}
{
aliceData_.upnpEnabled_ = false;
bobData_.upnpEnabled_ = true;
configureAccount(aliceData_, accountType);
configureAccount(bobData_, accountType);
test_call(accountType);
}
{
aliceData_.upnpEnabled_ = true;
bobData_.upnpEnabled_ = true;
configureAccount(aliceData_, accountType);
configureAccount(bobData_, accountType);
test_call(accountType);
}
}
} // namespace test
} // namespace jami
RING_TEST_RUNNER(jami::test::IceMediaCandExchangeTest::name())
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment