diff --git a/src/jamidht/connectionmanager.cpp b/src/jamidht/connectionmanager.cpp index 684b0ccd8f7703982219a536e026d97d0f102c50..79c04473969db970ed00cac5ecc0c080f854de11 100644 --- a/src/jamidht/connectionmanager.cpp +++ b/src/jamidht/connectionmanager.cpp @@ -73,7 +73,7 @@ public: for (auto it = infos_.begin(); it != infos_.end();) { auto& [key, info] = *it; bool erased = false; - if (info) { + if (info && (!deviceId || key.first == deviceId)) { if (info->tls_) info->tls_->shutdown(); if (info->socket_) @@ -83,10 +83,8 @@ public: info->ice_->stop(); } info->responseCv_.notify_all(); - if (deviceId && key.first == deviceId) { - erased = true; - it = infos_.erase(it); - } + erased = true; + it = infos_.erase(it); } if (!erased) ++it; @@ -1071,24 +1069,32 @@ ConnectionManager::isConnecting(const DeviceId& deviceId, const std::string& nam } void -ConnectionManager::closeConnectionsWith(const DeviceId& deviceId) +ConnectionManager::closeConnectionsWith(const std::string& peerUri) { - for (const auto& pending : pimpl_->extractPendingCallbacks(deviceId)) - pending.cb(nullptr, deviceId); - std::vector<std::shared_ptr<ConnectionInfo>> connInfos; + std::set<DeviceId> peersDevices; { std::lock_guard<std::mutex> lk(pimpl_->infosMtx_); for (auto iter = pimpl_->infos_.begin(); iter != pimpl_->infos_.end();) { auto const& [key, value] = *iter; - if (key.first == deviceId) { + auto deviceId = key.first; + auto cert = tls::CertificateStore::instance().getCertificate(deviceId.toString()); + if (cert && cert->issuer && peerUri == cert->issuer->getId().toString()) { connInfos.emplace_back(value); + peersDevices.emplace(deviceId); iter = pimpl_->infos_.erase(iter); } else { iter++; } } } + // Stop connections to all peers devices + for (const auto& deviceId : peersDevices) { + for (const auto& pending : pimpl_->extractPendingCallbacks(deviceId)) + pending.cb(nullptr, deviceId); + // This will close the TLS Session + pimpl_->removeUnusedConnections(deviceId); + } for (auto& info : connInfos) { if (info->ice_) { info->ice_->cancelOperations(); @@ -1103,8 +1109,6 @@ ConnectionManager::closeConnectionsWith(const DeviceId& deviceId) [ice = std::shared_ptr<IceTransport>(std::move(info->ice_))] {}); } } - // This will close the TLS Session - pimpl_->removeUnusedConnections(deviceId); } void diff --git a/src/jamidht/connectionmanager.h b/src/jamidht/connectionmanager.h index 19f6c92f775ef1bde46ea0da5294f23296c18f1e..3d396dd414dffca0ca247b153022571c7c0cf0de 100644 --- a/src/jamidht/connectionmanager.h +++ b/src/jamidht/connectionmanager.h @@ -115,9 +115,9 @@ public: /** * Close all connections with a current device - * @param deviceId Remote device + * @param peerUri Peer URI */ - void closeConnectionsWith(const DeviceId& deviceId); + void closeConnectionsWith(const std::string& peerUri); /** * Method to call to listen to incoming requests diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp index 37af0244d229dbf3b0a829a208d1ab611cc08b7a..5b9a64c03b0f3d8070fdefb5fd8a40c299e67a1b 100644 --- a/src/jamidht/jamiaccount.cpp +++ b/src/jamidht/jamiaccount.cpp @@ -1128,16 +1128,8 @@ JamiAccount::loadAccount(const std::string& archive_password, // Erase linked conversation's requests if (auto convModule = shared->convModule()) convModule->removeContact(uri, banned); - // Remove current connections with contact - std::unique_lock<std::mutex> lk(shared->sipConnsMtx_); - for (auto it = shared->sipConns_.begin(); it != shared->sipConns_.end();) { - const auto& [key, value] = *it; - if (key.first == uri) - it = shared->sipConns_.erase(it); - else - ++it; - } + shared->connectionManager_->closeConnectionsWith(uri); // Update client. emitSignal<DRing::ConfigurationSignal::ContactRemoved>(shared->getAccountID(), uri, diff --git a/test/unitTest/connectionManager/connectionManager.cpp b/test/unitTest/connectionManager/connectionManager.cpp index 603ed56292d2034c32ec2e666c9822aacb9c41fb..3861ef9925b41cd3ca303e733773a6950f5bd164 100644 --- a/test/unitTest/connectionManager/connectionManager.cpp +++ b/test/unitTest/connectionManager/connectionManager.cpp @@ -67,7 +67,7 @@ private: void testDeclineICERequest(); void testChannelRcvShutdown(); void testChannelSenderShutdown(); - void testCloseConnectionWithDevice(); + void testCloseConnectionWith(); void testShutdownCallbacks(); void testFloodSocket(); void testDestroyWhileSending(); @@ -90,7 +90,7 @@ private: CPPUNIT_TEST(testDeclineICERequest); CPPUNIT_TEST(testChannelRcvShutdown); CPPUNIT_TEST(testChannelSenderShutdown); - CPPUNIT_TEST(testCloseConnectionWithDevice); + CPPUNIT_TEST(testCloseConnectionWith); CPPUNIT_TEST(testShutdownCallbacks); CPPUNIT_TEST(testFloodSocket); CPPUNIT_TEST(testDestroyWhileSending); @@ -685,11 +685,12 @@ ConnectionManagerTest::testChannelSenderShutdown() } void -ConnectionManagerTest::testCloseConnectionWithDevice() +ConnectionManagerTest::testCloseConnectionWith() { auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId); auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId); auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId())); + auto bobUri = bobAccount->getUsername(); bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; }); aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; }); @@ -736,7 +737,7 @@ ConnectionManagerTest::testCloseConnectionWithDevice() rcv.wait_for(lk, 30s); // This should trigger onShutdown - aliceAccount->connectionManager().closeConnectionsWith(bobDeviceId); + aliceAccount->connectionManager().closeConnectionsWith(bobUri); CPPUNIT_ASSERT(scv.wait_for(lk, 60s, [&] { return events == 2 && successfullyReceive && successfullyConnected && receiverConnected; })); @@ -748,6 +749,7 @@ ConnectionManagerTest::testShutdownCallbacks() auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId); auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId); auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId())); + auto aliceUri = aliceAccount->getUsername(); auto aliceDeviceId = DeviceId(std::string(aliceAccount->currentDeviceId())); bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; }); @@ -804,7 +806,7 @@ ConnectionManagerTest::testShutdownCallbacks() chan2cv.wait_for(lk, 30s); // This should trigger onShutdown for second callback - bobAccount->connectionManager().closeConnectionsWith(aliceDeviceId); + bobAccount->connectionManager().closeConnectionsWith(aliceUri); CPPUNIT_ASSERT(rcv.wait_for(lk, 30s, [&] { return channel2NotConnected; })); } diff --git a/test/unitTest/conversation/conversation.cpp b/test/unitTest/conversation/conversation.cpp index 900cc8992a1a6983f39a610d0fb80a42e4fa4315..49b89f32b2b2489fa5536949b8a2ebe6739a720e 100644 --- a/test/unitTest/conversation/conversation.cpp +++ b/test/unitTest/conversation/conversation.cpp @@ -2876,7 +2876,7 @@ ConversationTest::testRemoveReaddMultipleDevice() CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bob2Started; })); // Alice adds bob - requestReceived = false; + requestReceived = false, requestReceivedBob2 = false; aliceAccount->addContact(bobUri); aliceAccount->sendTrustRequest(bobUri, {}); CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return requestReceived && requestReceivedBob2; })); @@ -2893,9 +2893,9 @@ ConversationTest::testRemoveReaddMultipleDevice() std::this_thread::sleep_for(10s); // Alice send a message - requestReceived = false; + requestReceived = false, requestReceivedBob2 = false; DRing::sendMessage(aliceId, convId, "hi"s, ""); - CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return requestReceived; })); + CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return requestReceived && requestReceivedBob2; })); // Re-Add contact should accept and clone the conversation on all devices conversationReadyBob = false;