From 23ecb71e03d237e45dd02b69d3792d638953b8d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Blin?= <sebastien.blin@savoirfairelinux.com> Date: Tue, 3 Oct 2023 05:40:30 -0400 Subject: [PATCH] jamiaccount: use current media list when answering a swarm call Else, the mute state is ignored, causing the new member to be able to listen from the host even if the host muted itself. https://git.jami.net/savoirfairelinux/jami-client-android/-/issues/1351 Change-Id: Ic0e4f7ac99fd945847f47c9e2e4573fa1d6a1b1a --- src/jamidht/jamiaccount.cpp | 21 +++++---- test/unitTest/conversation/call.cpp | 68 +++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 8 deletions(-) diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp index 6ac8625236..830a6abc9b 100644 --- a/src/jamidht/jamiaccount.cpp +++ b/src/jamidht/jamiaccount.cpp @@ -521,7 +521,18 @@ JamiAccount::handleIncomingConversationCall(const std::string& callId, Manager::instance().hangupCall(getAccountID(), callId); return; } - Manager::instance().answerCall(*call); + + std::shared_ptr<Conference> conf; + std::vector<libjami::MediaMap> currentMediaList; + if (!isNotHosting) { + conf = getConference(confId); + if (!conf) { + JAMI_ERR("Conference %s not found", confId.c_str()); + return; + } + currentMediaList = conf->currentMediaList(); + } + Manager::instance().answerCall(*call, currentMediaList); if (isNotHosting) { // Create conference and host it. @@ -529,12 +540,6 @@ JamiAccount::handleIncomingConversationCall(const std::string& callId, if (auto conf = getConference(confId)) conf->detachLocalParticipant(); } else { - auto conf = getConference(confId); - if (!conf) { - JAMI_ERR("Conference %s not found", confId.c_str()); - return; - } - Manager::instance().addParticipant(*call, *conf); emitSignal<libjami::CallSignal::ConferenceChanged>(getAccountID(), conf->getConfId(), @@ -3860,7 +3865,7 @@ JamiAccount::cacheSIPConnection(std::shared_ptr<dhtnet::ChannelSocket>&& socket, shared->convModule()->syncConversations(peerId, deviceId.toString()); } }); - + // Retry messages messageEngine_.onPeerOnline(peerId); messageEngine_.onPeerOnline(peerId, true, deviceId.toString()); diff --git a/test/unitTest/conversation/call.cpp b/test/unitTest/conversation/call.cpp index 3f03711a9c..79f81843da 100644 --- a/test/unitTest/conversation/call.cpp +++ b/test/unitTest/conversation/call.cpp @@ -30,6 +30,7 @@ #include "conversation/conversationcommon.h" #include "manager.h" #include "media_const.h" +#include "sip/sipcall.h" using namespace std::literals::chrono_literals; @@ -85,6 +86,7 @@ private: void testCallSelfIfDefaultHost(); void testNeedsHost(); void testAudioOnly(); + void testJoinAfterMuteHost(); CPPUNIT_TEST_SUITE(ConversationCallTest); CPPUNIT_TEST(testActiveCalls); @@ -98,6 +100,7 @@ private: CPPUNIT_TEST(testCallSelfIfDefaultHost); CPPUNIT_TEST(testNeedsHost); CPPUNIT_TEST(testAudioOnly); + CPPUNIT_TEST(testJoinAfterMuteHost); CPPUNIT_TEST_SUITE_END(); }; @@ -1009,6 +1012,71 @@ ConversationCallTest::testAudioOnly() CPPUNIT_ASSERT(libjami::getActiveCalls(aliceId, aliceData_.id).size() == 0); } +void +ConversationCallTest::testJoinAfterMuteHost() +{ + connectSignals(); + + auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId); + auto aliceUri = aliceAccount->getUsername(); + auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId); + auto bobUri = bobAccount->getUsername(); + // Start conversation + libjami::startConversation(aliceId); + CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return !aliceData_.id.empty(); })); + + libjami::addConversationMember(aliceId, aliceData_.id, bobUri); + CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&]() { + return bobData_.requestReceived; + })); + + aliceData_.messages.clear(); + libjami::acceptConversationRequest(bobId, aliceData_.id); + CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { + return !bobData_.id.empty() && !aliceData_.messages.empty(); + })); + + // start call + aliceData_.messages.clear(); + bobData_.messages.clear(); + carlaData_.messages.clear(); + auto callId = libjami::placeCallWithMedia(aliceId, "swarm:" + aliceData_.id, {}); + auto lastCommitIsCall = [&](const auto& data) { + return !data.messages.empty() + && data.messages.rbegin()->at("type") == "application/call-history+json"; + }; + // should get message + CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { + return lastCommitIsCall(aliceData_) && lastCommitIsCall(bobData_) && !pInfos_.empty(); + })); + auto confId = bobData_.messages.rbegin()->at("confId"); + + // Mute host + auto call = std::dynamic_pointer_cast<SIPCall>(aliceAccount->getCall(callId)); + auto proposedList = call->currentMediaList(); + for (auto& media : proposedList) + if (media["LABEL"] == "audio_0") + media["MUTED"] = "true"; + libjami::requestMediaChange(aliceId, confId, proposedList); + + // Bob join, alice must stay muted + auto destination = fmt::format("rdv:{}/{}/{}/{}", + bobData_.id, + bobData_.messages.rbegin()->at("uri"), + bobData_.messages.rbegin()->at("device"), + confId); + + aliceData_.conferenceChanged = false; + pInfos_.clear(); + auto bobCall = libjami::placeCallWithMedia(bobId, destination, {}); + CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { + return aliceData_.conferenceChanged && bobData_.hostState == "CURRENT" && bobData_.state == "CURRENT" && pInfos_.size() == 2; + })); + // Audio of the host is still muted + CPPUNIT_ASSERT(pInfos_[0]["audioLocalMuted"] == "true"); + +} + } // namespace test } // namespace jami -- GitLab