LCOV - code coverage report
Current view: top level - test/unitTest/sip_account - sip_srtp.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 230 249 92.4 %
Date: 2024-05-03 08:04:07 Functions: 25 25 100.0 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2021-2024 Savoir-faire Linux Inc.
       3             :  *
       4             :  *  Author: Mohamed Chibani <mohamed.chibani@savoirfairelinux.com>
       5             :  *
       6             :  *  This program is free software; you can redistribute it and/or modify
       7             :  *  it under the terms of the GNU General Public License as published by
       8             :  *  the Free Software Foundation; either version 3 of the License, or
       9             :  *  (at your option) any later version.
      10             :  *
      11             :  *  This program is distributed in the hope that it will be useful,
      12             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  *  GNU General Public License for more details.
      15             :  *
      16             :  *  You should have received a copy of the GNU General Public License
      17             :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include <cppunit/TestAssert.h>
      21             : #include <cppunit/TestFixture.h>
      22             : #include <cppunit/extensions/HelperMacros.h>
      23             : 
      24             : #include <condition_variable>
      25             : #include <string>
      26             : 
      27             : #include "callmanager_interface.h"
      28             : #include "manager.h"
      29             : #include "sip/sipaccount.h"
      30             : #include "../../test_runner.h"
      31             : #include "jami.h"
      32             : #include "jami/media_const.h"
      33             : #include "call_const.h"
      34             : #include "account_const.h"
      35             : #include "sip/sipcall.h"
      36             : #include "sip/sdp.h"
      37             : using namespace libjami::Account;
      38             : using namespace libjami::Call;
      39             : 
      40             : namespace jami {
      41             : namespace test {
      42             : 
      43             : struct CallData
      44             : {
      45             :     struct Signal
      46             :     {
      47          12 :         Signal(const std::string& name, const std::string& event = {})
      48          12 :             : name_(std::move(name))
      49          12 :             , event_(std::move(event)) {};
      50             : 
      51             :         std::string name_ {};
      52             :         std::string event_ {};
      53             :     };
      54             : 
      55             :     std::string accountId_ {};
      56             :     uint16_t listeningPort_ {0};
      57             :     std::string userName_ {};
      58             :     std::string alias_ {};
      59             :     std::string callId_ {};
      60             :     std::vector<Signal> signals_;
      61             :     std::condition_variable cv_ {};
      62             :     std::mutex mtx_;
      63             : };
      64             : 
      65             : /**
      66             :  * Call tests for SIP accounts.
      67             :  */
      68             : class SipSrtpTest : public CppUnit::TestFixture
      69             : {
      70             : public:
      71           1 :     SipSrtpTest()
      72           1 :     {
      73             :         // Init daemon
      74           1 :         libjami::init(libjami::InitFlag(libjami::LIBJAMI_FLAG_DEBUG | libjami::LIBJAMI_FLAG_CONSOLE_LOG));
      75           1 :         if (not Manager::instance().initialized)
      76           1 :             CPPUNIT_ASSERT(libjami::start("dring-sample.yml"));
      77           1 :     }
      78           2 :     ~SipSrtpTest() { libjami::fini(); }
      79             : 
      80           2 :     static std::string name() { return "SipSrtpTest"; }
      81             :     void setUp();
      82             :     void tearDown();
      83             : 
      84             : private:
      85             :     // Test cases.
      86             :     void audio_video_srtp_enabled_test();
      87             : 
      88           2 :     CPPUNIT_TEST_SUITE(SipSrtpTest);
      89           1 :     CPPUNIT_TEST(audio_video_srtp_enabled_test);
      90             : 
      91           4 :     CPPUNIT_TEST_SUITE_END();
      92             : 
      93             :     // Event/Signal handlers
      94             :     static void onCallStateChange(const std::string& accountId,
      95             :                                   const std::string& callId,
      96             :                                   const std::string& state,
      97             :                                   CallData& callData);
      98             :     static void onIncomingCallWithMedia(const std::string& accountId,
      99             :                                         const std::string& callId,
     100             :                                         const std::vector<libjami::MediaMap> mediaList,
     101             :                                         CallData& callData);
     102             :     static void onMediaNegotiationStatus(const std::string& callId,
     103             :                                          const std::string& event,
     104             :                                          CallData& callData);
     105             : 
     106             :     // Helpers
     107             :     void audio_video_call(std::vector<MediaAttribute> offer,
     108             :                           std::vector<MediaAttribute> answer,
     109             :                           bool validateMedia = true);
     110             :     static void configureTest(CallData& bob, CallData& alice);
     111             :     static std::string getUserAlias(const std::string& callId);
     112             :     // Wait for a signal from the callbacks. Some signals also report the event that
     113             :     // triggered the signal a like the StateChange signal.
     114             :     static bool waitForSignal(CallData& callData,
     115             :                               const std::string& signal,
     116             :                               const std::string& expectedEvent = {});
     117             : 
     118             : private:
     119             :     CallData aliceData_;
     120             :     CallData bobData_;
     121             : };
     122             : 
     123             : CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(SipSrtpTest, SipSrtpTest::name());
     124             : 
     125             : void
     126           1 : SipSrtpTest::setUp()
     127             : {
     128           1 :     aliceData_.listeningPort_ = 5080;
     129           2 :     std::map<std::string, std::string> details = libjami::getAccountTemplate("SIP");
     130           1 :     details[ConfProperties::TYPE] = "SIP";
     131           1 :     details[ConfProperties::DISPLAYNAME] = "ALICE";
     132           1 :     details[ConfProperties::ALIAS] = "ALICE";
     133           1 :     details[ConfProperties::LOCAL_PORT] = std::to_string(aliceData_.listeningPort_);
     134           1 :     details[ConfProperties::UPNP_ENABLED] = "false";
     135           1 :     details[ConfProperties::SRTP::KEY_EXCHANGE] = "sdes";
     136           1 :     aliceData_.accountId_ = Manager::instance().addAccount(details);
     137             : 
     138           1 :     bobData_.listeningPort_ = 5082;
     139           1 :     details = libjami::getAccountTemplate("SIP");
     140           1 :     details[ConfProperties::TYPE] = "SIP";
     141           1 :     details[ConfProperties::DISPLAYNAME] = "BOB";
     142           1 :     details[ConfProperties::ALIAS] = "BOB";
     143           1 :     details[ConfProperties::LOCAL_PORT] = std::to_string(bobData_.listeningPort_);
     144           1 :     details[ConfProperties::UPNP_ENABLED] = "false";
     145           1 :     details[ConfProperties::SRTP::KEY_EXCHANGE] = "sdes";
     146           1 :     bobData_.accountId_ = Manager::instance().addAccount(details);
     147             : 
     148           1 :     JAMI_INFO("Initialize accounts ...");
     149           1 :     auto aliceAccount = Manager::instance().getAccount<SIPAccount>(aliceData_.accountId_);
     150           1 :     auto bobAccount = Manager::instance().getAccount<SIPAccount>(bobData_.accountId_);
     151           1 : }
     152             : 
     153             : void
     154           1 : SipSrtpTest::tearDown()
     155             : {
     156           1 :     JAMI_INFO("Remove created accounts...");
     157             : 
     158           1 :     std::map<std::string, std::shared_ptr<libjami::CallbackWrapperBase>> confHandlers;
     159           1 :     std::mutex mtx;
     160           1 :     std::unique_lock lk {mtx};
     161           1 :     std::condition_variable cv;
     162           1 :     auto currentAccSize = Manager::instance().getAccountList().size();
     163           1 :     std::atomic_bool accountsRemoved {false};
     164           1 :     confHandlers.insert(
     165           2 :         libjami::exportable_callback<libjami::ConfigurationSignal::AccountsChanged>([&]() {
     166           2 :             if (Manager::instance().getAccountList().size() <= currentAccSize - 2) {
     167           1 :                 accountsRemoved = true;
     168           1 :                 cv.notify_one();
     169             :             }
     170           2 :         }));
     171           1 :     libjami::registerSignalHandlers(confHandlers);
     172             : 
     173           1 :     Manager::instance().removeAccount(aliceData_.accountId_, true);
     174           1 :     Manager::instance().removeAccount(bobData_.accountId_, true);
     175             :     // Because cppunit is not linked with dbus, just poll if removed
     176           2 :     CPPUNIT_ASSERT(
     177             :         cv.wait_for(lk, std::chrono::seconds(30), [&] { return accountsRemoved.load(); }));
     178             : 
     179           1 :     libjami::unregisterSignalHandlers();
     180           1 : }
     181             : 
     182             : std::string
     183          14 : SipSrtpTest::getUserAlias(const std::string& callId)
     184             : {
     185          14 :     auto call = Manager::instance().getCallFromCallID(callId);
     186             : 
     187          14 :     if (not call) {
     188           2 :         JAMI_WARN("Call with ID [%s] does not exist anymore!", callId.c_str());
     189           2 :         return {};
     190             :     }
     191             : 
     192          12 :     auto const& account = call->getAccount().lock();
     193          12 :     if (not account) {
     194           0 :         return {};
     195             :     }
     196             : 
     197          12 :     return account->getAccountDetails()[ConfProperties::ALIAS];
     198          14 : }
     199             : 
     200             : void
     201           1 : SipSrtpTest::onIncomingCallWithMedia(const std::string& accountId,
     202             :                                      const std::string& callId,
     203             :                                      const std::vector<libjami::MediaMap> mediaList,
     204             :                                      CallData& callData)
     205             : {
     206           1 :     CPPUNIT_ASSERT_EQUAL(callData.accountId_, accountId);
     207             : 
     208           1 :     JAMI_INFO("Signal [%s] - user [%s] - call [%s] - media count [%lu]",
     209             :               libjami::CallSignal::IncomingCallWithMedia::name,
     210             :               callData.alias_.c_str(),
     211             :               callId.c_str(),
     212             :               mediaList.size());
     213             : 
     214             :     // NOTE.
     215             :     // We shouldn't access shared_ptr<Call> as this event is supposed to mimic
     216             :     // the client, and the client have no access to this type. But here, we only
     217             :     // needed to check if the call exists. This is the most straightforward and
     218             :     // reliable way to do it until we add a new API (like hasCall(id)).
     219           1 :     if (not Manager::instance().getCallFromCallID(callId)) {
     220           0 :         JAMI_WARN("Call with ID [%s] does not exist!", callId.c_str());
     221           0 :         callData.callId_ = {};
     222           0 :         return;
     223             :     }
     224             : 
     225           1 :     std::unique_lock lock {callData.mtx_};
     226           1 :     callData.callId_ = callId;
     227           1 :     callData.signals_.emplace_back(CallData::Signal(libjami::CallSignal::IncomingCallWithMedia::name));
     228             : 
     229           1 :     callData.cv_.notify_one();
     230           1 : }
     231             : 
     232             : void
     233           9 : SipSrtpTest::onCallStateChange(const std::string&,
     234             :                                const std::string& callId,
     235             :                                const std::string& state,
     236             :                                CallData& callData)
     237             : {
     238           9 :     auto call = Manager::instance().getCallFromCallID(callId);
     239           9 :     if (not call) {
     240           0 :         JAMI_WARN("Call with ID [%s] does not exist anymore!", callId.c_str());
     241           0 :         return;
     242             :     }
     243             : 
     244           9 :     auto account = call->getAccount().lock();
     245           9 :     if (not account) {
     246           0 :         JAMI_WARN("Account owning the call [%s] does not exist!", callId.c_str());
     247           0 :         return;
     248             :     }
     249             : 
     250           9 :     JAMI_INFO("Signal [%s] - user [%s] - call [%s] - state [%s]",
     251             :               libjami::CallSignal::StateChange::name,
     252             :               callData.alias_.c_str(),
     253             :               callId.c_str(),
     254             :               state.c_str());
     255             : 
     256           9 :     if (account->getAccountID() != callData.accountId_)
     257           0 :         return;
     258             : 
     259             :     {
     260           9 :         std::unique_lock lock {callData.mtx_};
     261           9 :         callData.signals_.emplace_back(
     262          18 :             CallData::Signal(libjami::CallSignal::StateChange::name, state));
     263           9 :     }
     264             :     // NOTE. Only states that we are interested on will notify the CV. If this
     265             :     // unit test is modified to process other states, they must be added here.
     266           9 :     if (state == "CURRENT" or state == "OVER" or state == "HUNGUP" or state == "RINGING") {
     267           5 :         callData.cv_.notify_one();
     268             :     }
     269           9 : }
     270             : 
     271             : void
     272           2 : SipSrtpTest::onMediaNegotiationStatus(const std::string& callId,
     273             :                                       const std::string& event,
     274             :                                       CallData& callData)
     275             : {
     276           2 :     auto call = Manager::instance().getCallFromCallID(callId);
     277           2 :     if (not call) {
     278           0 :         JAMI_WARN("Call with ID [%s] does not exist!", callId.c_str());
     279           0 :         return;
     280             :     }
     281             : 
     282           2 :     auto account = call->getAccount().lock();
     283           2 :     if (not account) {
     284           0 :         JAMI_WARN("Account owning the call [%s] does not exist!", callId.c_str());
     285           0 :         return;
     286             :     }
     287             : 
     288           2 :     JAMI_INFO("Signal [%s] - user [%s] - call [%s] - state [%s]",
     289             :               libjami::CallSignal::MediaNegotiationStatus::name,
     290             :               account->getAccountDetails()[ConfProperties::ALIAS].c_str(),
     291             :               call->getCallId().c_str(),
     292             :               event.c_str());
     293             : 
     294           2 :     if (account->getAccountID() != callData.accountId_)
     295           0 :         return;
     296             : 
     297             :     {
     298           2 :         std::unique_lock lock {callData.mtx_};
     299           2 :         callData.signals_.emplace_back(
     300           4 :             CallData::Signal(libjami::CallSignal::MediaNegotiationStatus::name, event));
     301           2 :     }
     302             : 
     303           2 :     callData.cv_.notify_one();
     304           2 : }
     305             : 
     306             : bool
     307           6 : SipSrtpTest::waitForSignal(CallData& callData,
     308             :                            const std::string& expectedSignal,
     309             :                            const std::string& expectedEvent)
     310             : {
     311           6 :     const std::chrono::seconds TIME_OUT {30};
     312           6 :     std::unique_lock lock {callData.mtx_};
     313             : 
     314             :     // Combined signal + event (if any).
     315           6 :     std::string sigEvent(expectedSignal);
     316           6 :     if (not expectedEvent.empty())
     317           5 :         sigEvent += "::" + expectedEvent;
     318             : 
     319           6 :     JAMI_INFO("[%s] is waiting for [%s] signal/event", callData.alias_.c_str(), sigEvent.c_str());
     320             : 
     321           6 :     auto res = callData.cv_.wait_for(lock, TIME_OUT, [&] {
     322             :         // Search for the expected signal in list of received signals.
     323           9 :         bool pred = false;
     324          32 :         for (auto it = callData.signals_.begin(); it != callData.signals_.end(); it++) {
     325             :             // The predicate is true if the signal names match, and if the
     326             :             // expectedEvent is not empty, the events must also match.
     327          29 :             if (it->name_ == expectedSignal
     328          29 :                 and (expectedEvent.empty() or it->event_ == expectedEvent)) {
     329           6 :                 pred = true;
     330             :                 // Done with this signal.
     331           6 :                 callData.signals_.erase(it);
     332           6 :                 break;
     333             :             }
     334             :         }
     335             : 
     336           9 :         return pred;
     337             :     });
     338             : 
     339           6 :     if (not res) {
     340           0 :         JAMI_ERR("[%s] waiting for signal/event [%s] timed-out!",
     341             :                  callData.alias_.c_str(),
     342             :                  sigEvent.c_str());
     343             : 
     344           0 :         JAMI_INFO("[%s] currently has the following signals:", callData.alias_.c_str());
     345             : 
     346           0 :         for (auto const& sig : callData.signals_) {
     347           0 :             JAMI_INFO() << "Signal [" << sig.name_
     348           0 :                         << (sig.event_.empty() ? "" : ("::" + sig.event_)) << "]";
     349             :         }
     350             :     }
     351             : 
     352           6 :     return res;
     353           6 : }
     354             : 
     355             : void
     356           1 : SipSrtpTest::configureTest(CallData& aliceData, CallData& bobData)
     357             : {
     358             :     {
     359           1 :         CPPUNIT_ASSERT(not aliceData.accountId_.empty());
     360           1 :         auto const& account = Manager::instance().getAccount<SIPAccount>(aliceData.accountId_);
     361           1 :         aliceData.userName_ = account->getAccountDetails()[ConfProperties::USERNAME];
     362           1 :         aliceData.alias_ = account->getAccountDetails()[ConfProperties::ALIAS];
     363           1 :         account->setLocalPort(aliceData.listeningPort_);
     364           1 :     }
     365             : 
     366             :     {
     367           1 :         CPPUNIT_ASSERT(not bobData.accountId_.empty());
     368           1 :         auto const& account = Manager::instance().getAccount<SIPAccount>(bobData.accountId_);
     369           1 :         bobData.userName_ = account->getAccountDetails()[ConfProperties::USERNAME];
     370           1 :         bobData.alias_ = account->getAccountDetails()[ConfProperties::ALIAS];
     371           1 :         account->setLocalPort(bobData.listeningPort_);
     372           1 :     }
     373             : 
     374           1 :     std::map<std::string, std::shared_ptr<libjami::CallbackWrapperBase>> signalHandlers;
     375             : 
     376             :     // Insert needed signal handlers.
     377           1 :     signalHandlers.insert(libjami::exportable_callback<libjami::CallSignal::IncomingCallWithMedia>(
     378           1 :         [&](const std::string& accountId,
     379             :             const std::string& callId,
     380             :             const std::string&,
     381             :             const std::vector<libjami::MediaMap> mediaList) {
     382           1 :             auto user = getUserAlias(callId);
     383           1 :             if (not user.empty())
     384           1 :                 onIncomingCallWithMedia(accountId,
     385             :                                         callId,
     386             :                                         mediaList,
     387           1 :                                         user == aliceData.alias_ ? aliceData : bobData);
     388           1 :         }));
     389             : 
     390           1 :     signalHandlers.insert(
     391           2 :         libjami::exportable_callback<libjami::CallSignal::StateChange>([&](const std::string& accountId,
     392             :                                                                        const std::string& callId,
     393             :                                                                        const std::string& state,
     394             :                                                                        signed) {
     395          11 :             auto user = getUserAlias(callId);
     396          11 :             if (not user.empty())
     397           9 :                 onCallStateChange(accountId,
     398             :                                   callId,
     399             :                                   state,
     400           9 :                                   user == aliceData.alias_ ? aliceData : bobData);
     401          11 :         }));
     402             : 
     403           1 :     signalHandlers.insert(libjami::exportable_callback<libjami::CallSignal::MediaNegotiationStatus>(
     404           2 :         [&](const std::string& callId,
     405             :             const std::string& event,
     406             :             const std::vector<std::map<std::string, std::string>>& /* mediaList */) {
     407           2 :             auto user = getUserAlias(callId);
     408           2 :             if (not user.empty())
     409           2 :                 onMediaNegotiationStatus(callId,
     410             :                                          event,
     411           2 :                                          user == aliceData.alias_ ? aliceData : bobData);
     412           2 :         }));
     413             : 
     414           1 :     libjami::registerSignalHandlers(signalHandlers);
     415           1 : }
     416             : 
     417             : void
     418           1 : SipSrtpTest::audio_video_call(std::vector<MediaAttribute> offer,
     419             :                               std::vector<MediaAttribute> answer,
     420             :                               bool validateMedia)
     421             : {
     422           1 :     JAMI_INFO("=== Begin test %s ===", __FUNCTION__);
     423             : 
     424           1 :     configureTest(aliceData_, bobData_);
     425             : 
     426           1 :     JAMI_INFO("=== Start a call and validate ===");
     427             : 
     428           1 :     std::string bobUri = "127.0.0.1:" + std::to_string(bobData_.listeningPort_);
     429             : 
     430           2 :     aliceData_.callId_ = libjami::placeCallWithMedia(aliceData_.accountId_,
     431             :                                                    bobUri,
     432           2 :                                                    MediaAttribute::mediaAttributesToMediaMaps(
     433           1 :                                                        offer));
     434             : 
     435           1 :     CPPUNIT_ASSERT(not aliceData_.callId_.empty());
     436             : 
     437           1 :     JAMI_INFO("ALICE [%s] started a call with BOB [%s] and wait for answer",
     438             :               aliceData_.accountId_.c_str(),
     439             :               bobData_.accountId_.c_str());
     440             : 
     441             :     // Give it some time to ring
     442           1 :     std::this_thread::sleep_for(std::chrono::seconds(2));
     443             : 
     444             :     // Wait for call to be processed.
     445           1 :     CPPUNIT_ASSERT(
     446             :         waitForSignal(aliceData_, libjami::CallSignal::StateChange::name, StateEvent::RINGING));
     447             : 
     448             :     // Wait for incoming call signal.
     449           1 :     CPPUNIT_ASSERT(waitForSignal(bobData_, libjami::CallSignal::IncomingCallWithMedia::name));
     450             : 
     451             :     // Answer the call.
     452           1 :     libjami::acceptWithMedia(bobData_.accountId_,
     453           1 :                            bobData_.callId_,
     454           2 :                            MediaAttribute::mediaAttributesToMediaMaps(answer));
     455             : 
     456             :     // Wait for media negotiation complete signal.
     457           1 :     CPPUNIT_ASSERT(waitForSignal(bobData_,
     458             :                                  libjami::CallSignal::MediaNegotiationStatus::name,
     459             :                                  libjami::Media::MediaNegotiationStatusEvents::NEGOTIATION_SUCCESS));
     460             : 
     461             :     // Wait for the StateChange signal.
     462           1 :     CPPUNIT_ASSERT(
     463             :         waitForSignal(bobData_, libjami::CallSignal::StateChange::name, StateEvent::CURRENT));
     464             : 
     465           1 :     JAMI_INFO("BOB answered the call [%s]", bobData_.callId_.c_str());
     466             : 
     467             :     // Wait for media negotiation complete signal.
     468           1 :     CPPUNIT_ASSERT(waitForSignal(aliceData_,
     469             :                                  libjami::CallSignal::MediaNegotiationStatus::name,
     470             :                                  libjami::Media::MediaNegotiationStatusEvents::NEGOTIATION_SUCCESS));
     471             : 
     472             :     // Validate Alice's media
     473           1 :     if (validateMedia) {
     474           1 :         auto call = Manager::instance().getCallFromCallID(aliceData_.callId_);
     475           1 :         auto activeMediaList = call->getMediaAttributeList();
     476           1 :         CPPUNIT_ASSERT_EQUAL(offer.size(), activeMediaList.size());
     477             :         // Audio
     478           1 :         CPPUNIT_ASSERT_EQUAL(MediaType::MEDIA_AUDIO, activeMediaList[0].type_);
     479           1 :         CPPUNIT_ASSERT_EQUAL(offer[0].enabled_, activeMediaList[0].enabled_);
     480             : 
     481             :         // Video
     482           1 :         if (offer.size() > 1) {
     483           1 :             CPPUNIT_ASSERT_EQUAL(MediaType::MEDIA_VIDEO, activeMediaList[1].type_);
     484           1 :             CPPUNIT_ASSERT_EQUAL(offer[1].enabled_, activeMediaList[1].enabled_);
     485             :         }
     486           1 :     }
     487             : 
     488             :     // Validate Bob's media
     489           1 :     if (validateMedia) {
     490           1 :         auto call = Manager::instance().getCallFromCallID(bobData_.callId_);
     491           1 :         auto activeMediaList = call->getMediaAttributeList();
     492           1 :         CPPUNIT_ASSERT_EQUAL(answer.size(), activeMediaList.size());
     493             :         // Audio
     494           1 :         CPPUNIT_ASSERT_EQUAL(MediaType::MEDIA_AUDIO, activeMediaList[0].type_);
     495           1 :         CPPUNIT_ASSERT_EQUAL(answer[0].enabled_, activeMediaList[0].enabled_);
     496             : 
     497             :         // Video
     498           1 :         if (offer.size() > 1) {
     499           1 :             CPPUNIT_ASSERT_EQUAL(MediaType::MEDIA_VIDEO, activeMediaList[1].type_);
     500           1 :             CPPUNIT_ASSERT_EQUAL(answer[1].enabled_, activeMediaList[1].enabled_);
     501             :         }
     502           1 :     }
     503             : 
     504             :     // Give some time to media to start and flow
     505           1 :     std::this_thread::sleep_for(std::chrono::seconds(3));
     506             : 
     507             :     // Bob hang-up.
     508           1 :     JAMI_INFO("Hang up BOB's call and wait for ALICE to hang up");
     509           1 :     libjami::hangUp(bobData_.accountId_, bobData_.callId_);
     510             : 
     511           1 :     CPPUNIT_ASSERT(
     512             :         waitForSignal(aliceData_, libjami::CallSignal::StateChange::name, StateEvent::HUNGUP));
     513             : 
     514           1 :     JAMI_INFO("Call terminated on both sides");
     515           1 : }
     516             : 
     517             : void
     518           1 : SipSrtpTest::audio_video_srtp_enabled_test()
     519             : {
     520             :     // Test with video enabled on Alice's side and disabled
     521             :     // on Bob's side.
     522             : 
     523           1 :     auto const aliceAcc = Manager::instance().getAccount<SIPAccount>(aliceData_.accountId_);
     524           1 :     CPPUNIT_ASSERT(aliceAcc->isSrtpEnabled());
     525             : 
     526           1 :     auto const bobAcc = Manager::instance().getAccount<SIPAccount>(bobData_.accountId_);
     527           1 :     CPPUNIT_ASSERT(bobAcc->isSrtpEnabled());
     528             : 
     529           1 :     std::vector<MediaAttribute> offer;
     530           1 :     std::vector<MediaAttribute> answer;
     531             : 
     532           1 :     MediaAttribute audio(MediaType::MEDIA_AUDIO);
     533           1 :     MediaAttribute video(MediaType::MEDIA_VIDEO);
     534             : 
     535             :     // Configure Alice
     536           1 :     audio.enabled_ = true;
     537           1 :     audio.label_ = "audio_0";
     538           1 :     offer.emplace_back(audio);
     539             : 
     540           1 :     video.enabled_ = true;
     541           1 :     video.label_ = "video_0";
     542           1 :     aliceAcc->enableVideo(true);
     543           1 :     offer.emplace_back(video);
     544             : 
     545             :     // Configure Bob
     546           1 :     audio.enabled_ = true;
     547           1 :     audio.label_ = "audio_0";
     548           1 :     answer.emplace_back(audio);
     549             : 
     550           1 :     video.enabled_ = false;
     551           1 :     video.label_ = "video_0";
     552           1 :     bobAcc->enableVideo(false);
     553           1 :     answer.emplace_back(video);
     554             : 
     555             :     // Run the scenario
     556           1 :     audio_video_call(offer, answer);
     557           1 : }
     558             : 
     559             : } // namespace test
     560             : } // namespace jami
     561             : 
     562           1 : RING_TEST_RUNNER(jami::test::SipSrtpTest::name())

Generated by: LCOV version 1.14