multi-stream - remove legacy code

Remove obsolete code kept for backward compatibility.
Add call transfer test case

Gitlab: #470

Change-Id: I81472b8308ec402911670e8658308a184b97206c
This commit is contained in:
Mohamed Chibani
2021-11-02 16:50:55 -04:00
committed by Sébastien Blin
parent db0726465c
commit df9dba9bba
30 changed files with 348 additions and 652 deletions

View File

@ -28,22 +28,9 @@
#include "utils.h"
static SCM
place_call_binding(SCM accountID_str, SCM contact_str, SCM call_details_alist_optional)
{
LOG_BINDING();
if (SCM_UNBNDP(call_details_alist_optional)) {
return to_guile(DRing::placeCall(from_guile(accountID_str),
from_guile(contact_str)));
}
return to_guile(DRing::placeCall(from_guile(accountID_str),
from_guile(contact_str),
static_cast<std::map<std::string, std::string>>(from_guile(call_details_alist_optional))));
}
static SCM
place_call_with_media_binding(SCM accountID_str, SCM contact_str, SCM call_media_vector_alist_optional)
place_call_with_media_binding(SCM accountID_str,
SCM contact_str,
SCM call_media_vector_alist_optional)
{
LOG_BINDING();
@ -61,8 +48,7 @@ hang_up_binding(SCM accountID_str, SCM callID_str)
{
LOG_BINDING();
return to_guile(DRing::hangUp(from_guile(accountID_str),
from_guile(callID_str)));
return to_guile(DRing::hangUp(from_guile(accountID_str), from_guile(callID_str)));
}
static SCM
@ -71,8 +57,7 @@ accept_binding(SCM accountID_str, SCM callID_str, SCM call_media_vector_alist_op
LOG_BINDING();
if (SCM_UNBNDP(call_media_vector_alist_optional)) {
return to_guile(DRing::accept(from_guile(accountID_str),
from_guile(callID_str)));
return to_guile(DRing::accept(from_guile(accountID_str), from_guile(callID_str)));
}
return to_guile(DRing::acceptWithMedia(from_guile(accountID_str),
@ -85,8 +70,7 @@ refuse_binding(SCM accountID_str, SCM callID_str)
{
LOG_BINDING();
return to_guile(DRing::refuse(from_guile(accountID_str),
from_guile(callID_str)));
return to_guile(DRing::refuse(from_guile(accountID_str), from_guile(callID_str)));
}
static SCM
@ -94,8 +78,7 @@ hold_binding(SCM accountID_str, SCM callID_str)
{
LOG_BINDING();
return to_guile(DRing::hold(from_guile(accountID_str),
from_guile(callID_str)));
return to_guile(DRing::hold(from_guile(accountID_str), from_guile(callID_str)));
}
static SCM
@ -103,14 +86,12 @@ unhold_binding(SCM accountID_str, SCM callID_str)
{
LOG_BINDING();
return to_guile(DRing::unhold(from_guile(accountID_str),
from_guile(callID_str)));
return to_guile(DRing::unhold(from_guile(accountID_str), from_guile(callID_str)));
}
static void
install_call_primitives(void *)
install_call_primitives(void*)
{
define_primitive("place-call", 2, 1, 0, (void*) place_call_binding);
define_primitive("place-call/media", 2, 1, 0, (void*) place_call_with_media_binding);
define_primitive("hang-up", 2, 0, 0, (void*) hang_up_binding);
define_primitive("accept", 2, 1, 0, (void*) accept_binding);

View File

@ -144,7 +144,7 @@ test_SIP::testSimpleOutgoingIpCall()
CPPUNIT_ASSERT(!Manager::instance().hasCurrentCall());
// start a new call sending INVITE message to sipp instance
testcallid = Manager::instance().outgoingCall(testaccount, testcallnumber);
testcallid = DRing::placeCallWithMedia(testaccount, testcallnumber, {});
// wait for receiving 180 and 200 message from peer
std::this_thread::sleep_for(std::chrono::seconds(1)); // should be enough
@ -256,7 +256,7 @@ test_SIP::testMultipleOutgoingIpCall()
// start a user agent server waiting for a call
sippThread("sipp -sn uas -i 127.0.0.1 -p 5061 -m " + std::to_string(numberOfCall) + " -bg");
callID[i] = Manager::instance().outgoingCall(testaccount, callNumber);
callID[i] = DRing::placeCallWithMedia(testaccount, callNumber, {});
auto newCall = Manager::instance().getCallFromCallID(callID[i]);
CPPUNIT_ASSERT(newCall);
@ -302,7 +302,7 @@ test_SIP::testHoldIpCall()
auto callThread = sippThread("sipp -sf sippxml/test_3.xml -i 127.0.0.1 -p 5062 -m 1 -bg");
auto testCallId = Manager::instance().outgoingCall(testAccount, testCallNumber);
auto testCallId = DRing::placeCallWithMedia(testAccount, testCallNumber, {});
auto call = Manager::instance().getCallFromCallID(testCallId);
std::this_thread::sleep_for(std::chrono::seconds(2));

View File

@ -128,13 +128,13 @@ CallTest::testCall()
DRing::registerSignalHandlers(confHandlers);
JAMI_INFO("Start call between alice and Bob");
auto call = aliceAccount->newOutgoingCall(bobUri);
auto call = DRing::placeCallWithMedia(aliceId, bobUri, {});
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return callReceived.load(); }));
JAMI_INFO("Stop call between alice and Bob");
callStopped = 0;
Manager::instance().hangupCall(aliceId, call->getCallId());
Manager::instance().hangupCall(aliceId, call);
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return callStopped == 2; }));
}
@ -186,12 +186,12 @@ CallTest::testCachedCall()
cv.wait_for(lk, std::chrono::seconds(30), [&] { return successfullyConnected.load(); }));
JAMI_INFO("Start call between alice and Bob");
auto call = aliceAccount->newOutgoingCall(bobUri);
auto call = DRing::placeCallWithMedia(aliceId, bobUri, {});
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return callReceived.load(); }));
callStopped = 0;
JAMI_INFO("Stop call between alice and Bob");
Manager::instance().hangupCall(aliceId, call->getCallId());
Manager::instance().hangupCall(aliceId, call);
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return callStopped == 2; }));
}
@ -221,7 +221,7 @@ CallTest::testStopSearching()
DRing::registerSignalHandlers(confHandlers);
JAMI_INFO("Start call between alice and Bob");
auto call = aliceAccount->newOutgoingCall(bobUri);
auto call = DRing::placeCallWithMedia(aliceId, bobUri, {});
// Bob not there, so we should get a SEARCHING STATUS
JAMI_INFO("Wait OVER state");
@ -282,7 +282,7 @@ CallTest::testDeclineMultiDevice()
DRing::registerSignalHandlers(confHandlers);
JAMI_INFO("Start call between alice and Bob");
auto call = aliceAccount->newOutgoingCall(bobUri);
auto call = DRing::placeCallWithMedia(aliceId, bobUri, {});
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] {
return callReceived == 2 && !callIdBob.empty();

View File

@ -165,8 +165,11 @@ ConferenceTest::registerSignalHandlers()
}
cv.notify_one();
}));
confHandlers.insert(DRing::exportable_callback<DRing::CallSignal::StateChange>(
[=](const std::string& accountId, const std::string& callId, const std::string& state, signed) {
confHandlers.insert(
DRing::exportable_callback<DRing::CallSignal::StateChange>([=](const std::string& accountId,
const std::string& callId,
const std::string& state,
signed) {
if (accountId == aliceId) {
auto details = DRing::getCallDetails(aliceId, callId);
if (details["PEER_NUMBER"].find(bobUri) != std::string::npos)
@ -231,7 +234,7 @@ ConferenceTest::startConference()
auto carlaUri = carlaAccount->getUsername();
JAMI_INFO("Start call between Alice and Bob");
auto call1 = aliceAccount->newOutgoingCall(bobUri);
auto call1 = DRing::placeCallWithMedia(aliceId, bobUri, {});
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return !bobCall.callId.empty(); }));
Manager::instance().answerCall(bobId, bobCall.callId);
@ -239,18 +242,20 @@ ConferenceTest::startConference()
cv.wait_for(lk, std::chrono::seconds(20), [&] { return bobCall.hostState == "CURRENT"; }));
JAMI_INFO("Start call between Alice and Carla");
auto call2 = aliceAccount->newOutgoingCall(carlaUri);
auto call2 = DRing::placeCallWithMedia(aliceId, carlaUri, {});
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return !carlaCall.callId.empty(); }));
Manager::instance().answerCall(carlaId, carlaCall.callId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return carlaCall.hostState == "CURRENT"; }));
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(20), [&] {
return carlaCall.hostState == "CURRENT";
}));
JAMI_INFO("Start conference");
confChanged = false;
Manager::instance().joinParticipant(aliceId, call1->getCallId(), aliceId, call2->getCallId());
Manager::instance().joinParticipant(aliceId, call1, aliceId, call2);
// ConfChanged is the signal emitted when the 2 calls will be added to the conference
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(20), [&] { return !confId.empty() && confChanged; }));
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return !confId.empty() && confChanged; }));
}
void
@ -318,29 +323,31 @@ ConferenceTest::testAudioVideoMutedStates()
auto carlaUri = carlaAccount->getUsername();
JAMI_INFO("Start call between Alice and Bob");
auto call1 = aliceAccount->newOutgoingCall(bobUri);
auto call1Id = DRing::placeCallWithMedia(aliceId, bobUri, {});
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return !bobCall.callId.empty(); }));
Manager::instance().answerCall(bobId, bobCall.callId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return bobCall.hostState == "CURRENT"; }));
auto call1 = aliceAccount->getCall(call1Id);
call1->muteMedia(DRing::Media::MediaAttributeValue::AUDIO, true);
call1->muteMedia(DRing::Media::MediaAttributeValue::VIDEO, true);
JAMI_INFO("Start call between Alice and Carla");
auto call2 = aliceAccount->newOutgoingCall(carlaUri);
auto call2Id = DRing::placeCallWithMedia(aliceId, carlaUri, {});
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return !carlaCall.callId.empty(); }));
Manager::instance().answerCall(carlaId, carlaCall.callId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return carlaCall.hostState == "CURRENT"; }));
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(20), [&] {
return carlaCall.hostState == "CURRENT";
}));
auto call2 = aliceAccount->getCall(call2Id);
call2->muteMedia(DRing::Media::MediaAttributeValue::AUDIO, true);
call2->muteMedia(DRing::Media::MediaAttributeValue::VIDEO, true);
JAMI_INFO("Start conference");
Manager::instance().joinParticipant(aliceId, call1->getCallId(), aliceId, call2->getCallId());
Manager::instance().joinParticipant(aliceId, call1Id, aliceId, call2Id);
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(20), [&] { return !confId.empty(); }));
auto conf = aliceAccount->getConference(confId);
@ -401,13 +408,13 @@ ConferenceTest::testMuteStatusAfterRemove()
startConference();
JAMI_INFO("Start call between Alice and Davi");
auto call1 = aliceAccount->newOutgoingCall(daviUri);
auto call1 = DRing::placeCallWithMedia(aliceId, daviUri, {});
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return !daviCall.callId.empty(); }));
Manager::instance().answerCall(daviId, daviCall.callId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.hostState == "CURRENT"; }));
Manager::instance().addParticipant(aliceId, call1->getCallId(), aliceId, confId);
Manager::instance().addParticipant(aliceId, call1, aliceId, confId);
DRing::muteParticipant(aliceId, confId, daviUri, true);
CPPUNIT_ASSERT(
@ -418,13 +425,13 @@ ConferenceTest::testMuteStatusAfterRemove()
cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.state == "OVER"; }));
daviCall.reset();
auto call2 = aliceAccount->newOutgoingCall(daviUri);
auto call2 = DRing::placeCallWithMedia(aliceId, daviUri, {});
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return !daviCall.callId.empty(); }));
Manager::instance().answerCall(daviId, daviCall.callId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.hostState == "CURRENT"; }));
Manager::instance().addParticipant(aliceId, call2->getCallId(), aliceId, confId);
Manager::instance().addParticipant(aliceId, call2, aliceId, confId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(5), [&] { return !daviCall.moderatorMuted.load(); }));
@ -460,13 +467,13 @@ ConferenceTest::testHandsUp()
cv.wait_for(lk, std::chrono::seconds(5), [&] { return !bobCall.raisedHand.load(); }));
JAMI_INFO("Start call between Alice and Davi");
auto call1 = aliceAccount->newOutgoingCall(daviUri);
auto call1 = DRing::placeCallWithMedia(aliceId, daviUri, {});
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return !daviCall.callId.empty(); }));
Manager::instance().answerCall(daviId, daviCall.callId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.hostState == "CURRENT"; }));
Manager::instance().addParticipant(aliceId, call1->getCallId(), aliceId, confId);
Manager::instance().addParticipant(aliceId, call1, aliceId, confId);
DRing::raiseParticipantHand(aliceId, confId, daviUri, true);
CPPUNIT_ASSERT(
@ -477,13 +484,13 @@ ConferenceTest::testHandsUp()
cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.state == "OVER"; }));
daviCall.reset();
auto call2 = aliceAccount->newOutgoingCall(daviUri);
auto call2 = DRing::placeCallWithMedia(aliceId, daviUri, {});
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return !daviCall.callId.empty(); }));
Manager::instance().answerCall(daviId, daviCall.callId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.hostState == "CURRENT"; }));
Manager::instance().addParticipant(aliceId, call2->getCallId(), aliceId, confId);
Manager::instance().addParticipant(aliceId, call2, aliceId, confId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(5), [&] { return !daviCall.raisedHand.load(); }));
@ -537,7 +544,7 @@ ConferenceTest::testJoinCallFromOtherAccount()
cv.wait_for(lk, std::chrono::seconds(5), [&] { return !bobCall.raisedHand.load(); }));
JAMI_INFO("Start call between Alice and Davi");
auto call1 = aliceAccount->newOutgoingCall(daviUri);
auto call1 = DRing::placeCallWithMedia(aliceId, daviUri, {});
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(20), [&] { return !daviCall.callId.empty(); }));
Manager::instance().answerCall(daviId, daviCall.callId);

View File

@ -328,8 +328,6 @@ IceMediaCandExchangeTest::setupJamiAccount(CallData& user)
details[ConfProperties::UPNP_ENABLED] = user.upnpEnabled_ ? "true" : "false";
details[ConfProperties::TURN::ENABLED] = user.turnEnabled_ ? "true" : "false";
DRing::setAccountDetails(user.accountId_, details);
account->enableMultiStream(true);
}
void
@ -359,7 +357,6 @@ IceMediaCandExchangeTest::setupSipAccount(CallData& user)
user.alias_ = details[ConfProperties::ALIAS];
account->enableIceForMedia(true);
account->enableMultiStream(true);
user.dest_ = ip_utils::getLocalAddr(AF_INET);
user.dest_.setPort(user.listeningPort_);

View File

@ -206,9 +206,7 @@ IceSdpParsingTest::setUp()
JAMI_INFO("Initialize accounts ...");
auto aliceAccount = Manager::instance().getAccount<SIPAccount>(aliceData_.accountId_);
aliceAccount->enableMultiStream(true);
auto bobAccount = Manager::instance().getAccount<SIPAccount>(bobData_.accountId_);
bobAccount->enableMultiStream(true);
}
void

View File

@ -81,7 +81,6 @@ struct CallData
std::string userName_ {};
std::string alias_ {};
std::string callId_ {};
bool enableMultiStream_ {true};
std::vector<Signal> signals_;
std::condition_variable cv_ {};
std::mutex mtx_;
@ -163,9 +162,7 @@ HoldResumeTest::setUp()
JAMI_INFO("Initialize account...");
auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceData_.accountId_);
aliceAccount->enableMultiStream(true);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobData_.accountId_);
bobAccount->enableMultiStream(true);
wait_for_announcement_of({aliceAccount->getAccountID(), bobAccount->getAccountID()});
}
@ -402,7 +399,6 @@ HoldResumeTest::configureScenario(CallData& aliceData, CallData& bobData)
auto const& account = Manager::instance().getAccount<JamiAccount>(aliceData.accountId_);
aliceData.userName_ = account->getAccountDetails()[ConfProperties::USERNAME];
aliceData.alias_ = account->getAccountDetails()[ConfProperties::ALIAS];
account->enableMultiStream(aliceData.enableMultiStream_);
}
{
@ -410,7 +406,6 @@ HoldResumeTest::configureScenario(CallData& aliceData, CallData& bobData)
auto const& account = Manager::instance().getAccount<JamiAccount>(bobData.accountId_);
bobData.userName_ = account->getAccountDetails()[ConfProperties::USERNAME];
bobData.alias_ = account->getAccountDetails()[ConfProperties::ALIAS];
account->enableMultiStream(bobData.enableMultiStream_);
}
std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> signalHandlers;
@ -493,11 +488,7 @@ HoldResumeTest::testWithScenario(CallData& aliceData,
bobData.accountId_.c_str());
// Wait for incoming call signal.
if (bobData.enableMultiStream_) {
CPPUNIT_ASSERT(waitForSignal(bobData, DRing::CallSignal::IncomingCallWithMedia::name));
} else {
CPPUNIT_ASSERT(waitForSignal(bobData, DRing::CallSignal::IncomingCall::name));
}
CPPUNIT_ASSERT(waitForSignal(bobData, DRing::CallSignal::IncomingCallWithMedia::name));
// Answer the call.
{

View File

@ -83,7 +83,6 @@ struct CallData
std::string userName_ {};
std::string alias_ {};
std::string callId_ {};
bool enableMultiStream_ {true};
std::vector<Signal> signals_;
std::condition_variable cv_ {};
std::mutex mtx_;
@ -114,14 +113,12 @@ private:
void audio_only_then_add_video();
void audio_and_video_then_mute_audio();
void audio_and_video_then_change_video_source();
void audio_only_then_add_video_but_peer_disabled_multistream();
CPPUNIT_TEST_SUITE(MediaNegotiationTest);
CPPUNIT_TEST(audio_and_video_then_mute_video);
CPPUNIT_TEST(audio_only_then_add_video);
CPPUNIT_TEST(audio_and_video_then_mute_audio);
CPPUNIT_TEST(audio_and_video_then_change_video_source);
CPPUNIT_TEST(audio_only_then_add_video_but_peer_disabled_multistream);
CPPUNIT_TEST_SUITE_END();
// Event/Signal handlers
@ -178,9 +175,7 @@ MediaNegotiationTest::setUp()
JAMI_INFO("Initialize account...");
auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceData_.accountId_);
aliceAccount->enableMultiStream(true);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobData_.accountId_);
bobAccount->enableMultiStream(true);
wait_for_announcement_of({aliceAccount->getAccountID(), bobAccount->getAccountID()});
}
@ -490,7 +485,6 @@ MediaNegotiationTest::configureScenario(CallData& aliceData, CallData& bobData)
auto const& account = Manager::instance().getAccount<JamiAccount>(aliceData.accountId_);
aliceData.userName_ = account->getAccountDetails()[ConfProperties::USERNAME];
aliceData.alias_ = account->getAccountDetails()[ConfProperties::ALIAS];
account->enableMultiStream(aliceData.enableMultiStream_);
}
{
@ -498,7 +492,6 @@ MediaNegotiationTest::configureScenario(CallData& aliceData, CallData& bobData)
auto const& account = Manager::instance().getAccount<JamiAccount>(bobData.accountId_);
bobData.userName_ = account->getAccountDetails()[ConfProperties::USERNAME];
bobData.alias_ = account->getAccountDetails()[ConfProperties::ALIAS];
account->enableMultiStream(bobData.enableMultiStream_);
}
std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> signalHandlers;
@ -594,11 +587,7 @@ MediaNegotiationTest::testWithScenario(CallData& aliceData,
bobData.accountId_.c_str());
// Wait for incoming call signal.
if (bobData.enableMultiStream_) {
CPPUNIT_ASSERT(waitForSignal(bobData, DRing::CallSignal::IncomingCallWithMedia::name));
} else {
CPPUNIT_ASSERT(waitForSignal(bobData, DRing::CallSignal::IncomingCall::name));
}
CPPUNIT_ASSERT(waitForSignal(bobData, DRing::CallSignal::IncomingCallWithMedia::name));
// Answer the call.
{
@ -899,49 +888,6 @@ MediaNegotiationTest::audio_and_video_then_change_video_source()
JAMI_INFO("=== End test %s ===", __FUNCTION__);
}
void
MediaNegotiationTest::audio_only_then_add_video_but_peer_disabled_multistream()
{
JAMI_INFO("=== Begin test %s ===", __FUNCTION__);
// Disable multi-stream on Bob's side
bobData_.enableMultiStream_ = false;
configureScenario(aliceData_, bobData_);
MediaAttribute defaultAudio(MediaType::MEDIA_AUDIO);
defaultAudio.label_ = "audio_0";
defaultAudio.enabled_ = true;
MediaAttribute defaultVideo(MediaType::MEDIA_VIDEO);
defaultVideo.label_ = "video_0";
defaultVideo.enabled_ = true;
{
MediaAttribute audio(defaultAudio);
MediaAttribute video(defaultVideo);
TestScenario scenario;
// First offer/answer
scenario.offer_.emplace_back(audio);
scenario.answer_.emplace_back(audio);
// Updated offer/answer
scenario.offerUpdate_.emplace_back(audio);
scenario.offerUpdate_.emplace_back(video);
scenario.answerUpdate_.emplace_back(audio);
scenario.answerUpdate_.emplace_back(video);
scenario.expectMediaRenegotiation_ = false;
scenario.expectMediaChangeRequest_ = false;
testWithScenario(aliceData_, bobData_, scenario);
}
DRing::unregisterSignalHandlers();
JAMI_INFO("=== End test %s ===", __FUNCTION__);
}
} // namespace test
} // namespace jami

View File

@ -88,6 +88,7 @@ private:
void audio_video_test();
void peer_answer_with_all_media_disabled();
void hold_resume_test();
void blind_transfer_test();
CPPUNIT_TEST_SUITE(SipBasicCallTest);
CPPUNIT_TEST(audio_only_test);
@ -95,6 +96,7 @@ private:
// Test when the peer answers with all the media disabled (RTP port = 0)
CPPUNIT_TEST(peer_answer_with_all_media_disabled);
CPPUNIT_TEST(hold_resume_test);
CPPUNIT_TEST(blind_transfer_test);
CPPUNIT_TEST_SUITE_END();
// Event/Signal handlers
@ -115,7 +117,7 @@ private:
std::vector<MediaAttribute> answer,
bool expectedToSucceed = true,
bool validateMedia = true);
static void configureTest(CallData& bob, CallData& alice);
static void configureTest(CallData& bob, CallData& alice, CallData& carla);
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.
@ -126,6 +128,7 @@ private:
private:
CallData aliceData_;
CallData bobData_;
CallData carlaData_;
};
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(SipBasicCallTest, SipBasicCallTest::name());
@ -136,6 +139,7 @@ SipBasicCallTest::setUp()
aliceData_.listeningPort_ = 5080;
std::map<std::string, std::string> details = DRing::getAccountTemplate("SIP");
details[ConfProperties::TYPE] = "SIP";
details[ConfProperties::USERNAME] = "ALICE";
details[ConfProperties::DISPLAYNAME] = "ALICE";
details[ConfProperties::ALIAS] = "ALICE";
details[ConfProperties::LOCAL_PORT] = std::to_string(aliceData_.listeningPort_);
@ -145,17 +149,27 @@ SipBasicCallTest::setUp()
bobData_.listeningPort_ = 5082;
details = DRing::getAccountTemplate("SIP");
details[ConfProperties::TYPE] = "SIP";
details[ConfProperties::USERNAME] = "BOB";
details[ConfProperties::DISPLAYNAME] = "BOB";
details[ConfProperties::ALIAS] = "BOB";
details[ConfProperties::LOCAL_PORT] = std::to_string(bobData_.listeningPort_);
details[ConfProperties::UPNP_ENABLED] = "false";
bobData_.accountId_ = Manager::instance().addAccount(details);
carlaData_.listeningPort_ = 5084;
details = DRing::getAccountTemplate("SIP");
details[ConfProperties::TYPE] = "SIP";
details[ConfProperties::USERNAME] = "CARLA";
details[ConfProperties::DISPLAYNAME] = "CARLA";
details[ConfProperties::ALIAS] = "CARLA";
details[ConfProperties::LOCAL_PORT] = std::to_string(carlaData_.listeningPort_);
details[ConfProperties::UPNP_ENABLED] = "false";
carlaData_.accountId_ = Manager::instance().addAccount(details);
JAMI_INFO("Initialize accounts ...");
auto aliceAccount = Manager::instance().getAccount<SIPAccount>(aliceData_.accountId_);
aliceAccount->enableMultiStream(true);
auto bobAccount = Manager::instance().getAccount<SIPAccount>(bobData_.accountId_);
bobAccount->enableMultiStream(true);
auto carlaAccount = Manager::instance().getAccount<SIPAccount>(carlaData_.accountId_);
}
void
@ -180,7 +194,8 @@ SipBasicCallTest::tearDown()
Manager::instance().removeAccount(aliceData_.accountId_, true);
Manager::instance().removeAccount(bobData_.accountId_, true);
// Because cppunit is not linked with dbus, just poll if removed
Manager::instance().removeAccount(carlaData_.accountId_, true);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(30), [&] { return accountsRemoved.load(); }));
@ -356,7 +371,7 @@ SipBasicCallTest::waitForSignal(CallData& callData,
}
void
SipBasicCallTest::configureTest(CallData& aliceData, CallData& bobData)
SipBasicCallTest::configureTest(CallData& aliceData, CallData& bobData, CallData& carlaData)
{
{
CPPUNIT_ASSERT(not aliceData.accountId_.empty());
@ -374,6 +389,15 @@ SipBasicCallTest::configureTest(CallData& aliceData, CallData& bobData)
bobData.alias_ = account->getAccountDetails()[ConfProperties::ALIAS];
account->setLocalPort(bobData.listeningPort_);
}
#if 1
{
CPPUNIT_ASSERT(not carlaData.accountId_.empty());
auto const& account = Manager::instance().getAccount<SIPAccount>(carlaData.accountId_);
carlaData.userName_ = account->getAccountDetails()[ConfProperties::USERNAME];
carlaData.alias_ = account->getAccountDetails()[ConfProperties::ALIAS];
account->setLocalPort(carlaData.listeningPort_);
}
#endif
std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> signalHandlers;
@ -388,7 +412,9 @@ SipBasicCallTest::configureTest(CallData& aliceData, CallData& bobData)
onIncomingCallWithMedia(accountId,
callId,
mediaList,
user == aliceData.alias_ ? aliceData : bobData);
user == aliceData.alias_
? aliceData
: (user == bobData.alias_ ? bobData : carlaData));
}));
signalHandlers.insert(
@ -401,7 +427,9 @@ SipBasicCallTest::configureTest(CallData& aliceData, CallData& bobData)
onCallStateChange(accountId,
callId,
state,
user == aliceData.alias_ ? aliceData : bobData);
user == aliceData.alias_
? aliceData
: (user == bobData.alias_ ? bobData : carlaData));
}));
signalHandlers.insert(DRing::exportable_callback<DRing::CallSignal::MediaNegotiationStatus>(
@ -412,7 +440,9 @@ SipBasicCallTest::configureTest(CallData& aliceData, CallData& bobData)
if (not user.empty())
onMediaNegotiationStatus(callId,
event,
user == aliceData.alias_ ? aliceData : bobData);
user == aliceData.alias_
? aliceData
: (user == bobData.alias_ ? bobData : carlaData));
}));
DRing::registerSignalHandlers(signalHandlers);
@ -424,11 +454,12 @@ SipBasicCallTest::audio_video_call(std::vector<MediaAttribute> offer,
bool expectedToSucceed,
bool validateMedia)
{
configureTest(aliceData_, bobData_);
configureTest(aliceData_, bobData_, carlaData_);
JAMI_INFO("=== Start a call and validate ===");
std::string bobUri = "127.0.0.1:" + std::to_string(bobData_.listeningPort_);
std::string bobUri = bobData_.userName_
+ "@127.0.0.1:" + std::to_string(bobData_.listeningPort_);
aliceData_.callId_ = DRing::placeCallWithMedia(aliceData_.accountId_,
bobUri,
@ -660,11 +691,12 @@ SipBasicCallTest::hold_resume_test()
answer.emplace_back(audio);
{
configureTest(aliceData_, bobData_);
configureTest(aliceData_, bobData_, carlaData_);
JAMI_INFO("=== Start a call and validate ===");
std::string bobUri = "127.0.0.1:" + std::to_string(bobData_.listeningPort_);
std::string bobUri = bobData_.userName_
+ "@127.0.0.1:" + std::to_string(bobData_.listeningPort_);
aliceData_.callId_ = DRing::placeCallWithMedia(aliceData_.accountId_,
bobUri,
@ -821,6 +853,195 @@ SipBasicCallTest::hold_resume_test()
}
}
void
SipBasicCallTest::blind_transfer_test()
{
// Test a "blind" (a.k.a. unattended) transfer as described in
// https://datatracker.ietf.org/doc/html/rfc5589
/** Call transfer scenario:
*
* Alice and Bob are in an active call
* Alice performs a call transfer (SIP REFER method) to Carla
* Bob automatically accepts the transfer request
* Alice ends the call with Bob
* Bob send a new call invite to Carla
* Carla accepts the call
* Carl ends the call
*
* Here is a simplified version of a call flow from
* rfc5589
*
*
Alice Bob Carla
| REFER | |
|----------------------->| |
| 202 Accepted | |
|<-----------------------| |
| BYE | |
|<-----------------------| |
| 200 OK | |
|----------------------->| |
| | INVITE |
| |----------------------->|
| | 200 OK |
| |<-----------------------|
*/
JAMI_INFO("=== Begin test %s ===", __FUNCTION__);
auto const aliceAcc = Manager::instance().getAccount<SIPAccount>(aliceData_.accountId_);
auto const bobAcc = Manager::instance().getAccount<SIPAccount>(bobData_.accountId_);
auto const carlaAcc = Manager::instance().getAccount<SIPAccount>(carlaData_.accountId_);
aliceAcc->enableIceForMedia(false);
bobAcc->enableIceForMedia(false);
carlaAcc->enableIceForMedia(false);
std::vector<MediaAttribute> offer;
std::vector<MediaAttribute> answer;
MediaAttribute audio(MediaType::MEDIA_AUDIO);
MediaAttribute video(MediaType::MEDIA_VIDEO);
audio.enabled_ = true;
audio.label_ = "audio_0";
// Alice's media
offer.emplace_back(audio);
// Bob's media
answer.emplace_back(audio);
configureTest(aliceData_, bobData_, carlaData_);
JAMI_INFO("=== Start a call and validate ===");
std::string bobUri = bobData_.userName_
+ "@127.0.0.1:" + std::to_string(bobData_.listeningPort_);
aliceData_.callId_ = DRing::placeCallWithMedia(aliceData_.accountId_,
bobUri,
MediaAttribute::mediaAttributesToMediaMaps(
offer));
CPPUNIT_ASSERT(not aliceData_.callId_.empty());
JAMI_INFO("ALICE [%s] started a call with BOB [%s] and wait for answer",
aliceData_.accountId_.c_str(),
bobData_.accountId_.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_, DRing::CallSignal::StateChange::name, StateEvent::RINGING));
// Wait for incoming call signal.
CPPUNIT_ASSERT(waitForSignal(bobData_, DRing::CallSignal::IncomingCallWithMedia::name));
// Answer the call.
DRing::acceptWithMedia(bobData_.accountId_,
bobData_.callId_,
MediaAttribute::mediaAttributesToMediaMaps(answer));
// Wait for media negotiation complete signal.
CPPUNIT_ASSERT(waitForSignal(bobData_,
DRing::CallSignal::MediaNegotiationStatus::name,
DRing::Media::MediaNegotiationStatusEvents::NEGOTIATION_SUCCESS));
// Wait for the StateChange signal.
CPPUNIT_ASSERT(
waitForSignal(bobData_, DRing::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_,
DRing::CallSignal::MediaNegotiationStatus::name,
DRing::Media::MediaNegotiationStatusEvents::NEGOTIATION_SUCCESS));
// Give some time to media to start and flow
std::this_thread::sleep_for(std::chrono::seconds(2));
// Transfer the call to Carla
std::string carlaUri = carlaAcc->getUsername()
+ "@127.0.0.1:" + std::to_string(carlaData_.listeningPort_);
DRing::transfer(aliceData_.accountId_, aliceData_.callId_, carlaUri); // TODO. Check trim
// Expect Alice's call to end.
CPPUNIT_ASSERT(
waitForSignal(aliceData_, DRing::CallSignal::StateChange::name, StateEvent::HUNGUP));
// Wait for the new call to be processed.
CPPUNIT_ASSERT(
waitForSignal(bobData_, DRing::CallSignal::StateChange::name, StateEvent::RINGING));
// Wait for incoming call signal.
CPPUNIT_ASSERT(waitForSignal(carlaData_, DRing::CallSignal::IncomingCallWithMedia::name));
// Let it ring
std::this_thread::sleep_for(std::chrono::seconds(2));
// Carla answers the call.
DRing::acceptWithMedia(carlaData_.accountId_,
carlaData_.callId_,
MediaAttribute::mediaAttributesToMediaMaps(answer));
// Wait for media negotiation complete signal.
CPPUNIT_ASSERT(waitForSignal(carlaData_,
DRing::CallSignal::MediaNegotiationStatus::name,
DRing::Media::MediaNegotiationStatusEvents::NEGOTIATION_SUCCESS));
// Wait for the StateChange signal.
CPPUNIT_ASSERT(
waitForSignal(carlaData_, DRing::CallSignal::StateChange::name, StateEvent::CURRENT));
JAMI_INFO("CARLA answered the call [%s]", bobData_.callId_.c_str());
// Wait for media negotiation complete signal.
CPPUNIT_ASSERT(waitForSignal(bobData_,
DRing::CallSignal::MediaNegotiationStatus::name,
DRing::Media::MediaNegotiationStatusEvents::NEGOTIATION_SUCCESS));
// Wait for the StateChange signal.
CPPUNIT_ASSERT(
waitForSignal(bobData_, DRing::CallSignal::StateChange::name, StateEvent::CURRENT));
// Validate Carla's side of media direction
{
auto call = std::static_pointer_cast<SIPCall>(
Manager::instance().getCallFromCallID(carlaData_.callId_));
auto& sdp = call->getSDP();
auto mediaStreams = sdp.getMediaSlots();
for (auto const& media : mediaStreams) {
CPPUNIT_ASSERT_EQUAL(media.first.direction_, MediaDirection::SENDRECV);
CPPUNIT_ASSERT_EQUAL(media.second.direction_, MediaDirection::SENDRECV);
}
}
// NOTE:
// For now, we dont validate Bob's media because currently
// test does not update BOB's call ID (bobData_.callId_
// still point to the first call).
// It seems there is no easy way to get the ID of the new call
// made by Bob to Carla.
// Give some time to media to start and flow
std::this_thread::sleep_for(std::chrono::seconds(2));
// Bob hang-up.
JAMI_INFO("Hang up CARLA's call and wait for CARLA to hang up");
DRing::hangUp(carlaData_.accountId_, carlaData_.callId_);
// Expect end call on Carla's side.
CPPUNIT_ASSERT(
waitForSignal(carlaData_, DRing::CallSignal::StateChange::name, StateEvent::HUNGUP));
JAMI_INFO("Calls normally ended on both sides");
}
} // namespace test
} // namespace jami

View File

@ -142,9 +142,7 @@ SipEmptyOfferTest::setUp()
JAMI_INFO("Initialize accounts ...");
auto aliceAccount = Manager::instance().getAccount<SIPAccount>(aliceData_.accountId_);
aliceAccount->enableMultiStream(true);
auto bobAccount = Manager::instance().getAccount<SIPAccount>(bobData_.accountId_);
bobAccount->enableMultiStream(true);
}
void

View File

@ -147,9 +147,7 @@ SipSrtpTest::setUp()
JAMI_INFO("Initialize accounts ...");
auto aliceAccount = Manager::instance().getAccount<SIPAccount>(aliceData_.accountId_);
aliceAccount->enableMultiStream(true);
auto bobAccount = Manager::instance().getAccount<SIPAccount>(bobData_.accountId_);
bobAccount->enableMultiStream(true);
}
void