diff --git a/CMakeLists.txt b/CMakeLists.txt index a35f8329594c25c0eefd7a0c2e62f1a5118909b8..b0f95f6c900924a7b90e4d351573e9fa9c11dff4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -712,10 +712,6 @@ else() target_link_libraries(ut_base64 ut_library) add_test(NAME base64 COMMAND ut_base64) - add_executable(ut_ice test/unitTest/ice/ice.cpp) - target_link_libraries(ut_ice ut_library) - add_test(NAME ice COMMAND ut_ice) - add_executable(ut_ice_sdp_parser test/unitTest/ice/ice_sdp_parser.cpp) target_link_libraries(ut_ice_sdp_parser ut_library) add_test(NAME ice_sdp_parser COMMAND ut_ice_sdp_parser) @@ -788,10 +784,6 @@ else() target_link_libraries(ut_utf8_utils ut_library) add_test(NAME utf8_utils COMMAND ut_utf8_utils) - add_executable(ut_certstore test/unitTest/certstore.cpp) - target_link_libraries(ut_certstore ut_library) - add_test(NAME certstore COMMAND ut_certstore) - add_executable(ut_presence test/unitTest/presence/presence.cpp) target_link_libraries(ut_presence ut_library) add_test(NAME presence COMMAND ut_presence) diff --git a/test/meson.build b/test/meson.build index 56fa582ec6a51b2b4ded535ea5aeb3f68e58be05..b52568b8d6ada26da9bc0619c68971327b2a4e17 100644 --- a/test/meson.build +++ b/test/meson.build @@ -77,17 +77,6 @@ test('call', ut_call, ) -ut_certificate_store = executable('ut_certificate_store', - sources: files('unitTest/certstore.cpp'), - include_directories: ut_includedirs, - dependencies: ut_dependencies, - link_with: ut_library -) -test('certificate_store', ut_certificate_store, - workdir: ut_workdir, is_parallel: false, timeout: 1800 -) - - ut_conference = executable('ut_conference', sources: files('unitTest/call/conference.cpp'), include_directories: ut_includedirs, @@ -206,16 +195,6 @@ test('hold_resume', ut_hold_resume, ) -ut_ice = executable('ut_ice', - sources: files('unitTest/ice/ice.cpp'), - include_directories: ut_includedirs, - dependencies: ut_dependencies, - link_with: ut_library -) -test('ice', ut_ice, - 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, diff --git a/test/unitTest/Makefile.am b/test/unitTest/Makefile.am index df3777f0f5cb2be98e9c472d24cd9b007181bc12..4abefc2c010ad0003f742f94428bffe0d5f4964c 100644 --- a/test/unitTest/Makefile.am +++ b/test/unitTest/Makefile.am @@ -31,12 +31,6 @@ ut_account_archive_SOURCES = account_archive/account_archive.cpp common.cpp check_PROGRAMS += ut_migration ut_migration_SOURCES = account_archive/migration.cpp common.cpp -# -# certstore -# -check_PROGRAMS += ut_certstore -ut_certstore_SOURCES = certstore.cpp common.cpp - # # scheduler # @@ -216,11 +210,6 @@ ut_typers_SOURCES = conversation/typers.cpp conversation/conversationcommon.cpp check_PROGRAMS += ut_syncHistory ut_syncHistory_SOURCES = syncHistory/syncHistory.cpp common.cpp -# -# ice -# -check_PROGRAMS += ut_ice -ut_ice_SOURCES = ice/ice.cpp common.cpp # # revoke diff --git a/test/unitTest/certstore.cpp b/test/unitTest/certstore.cpp deleted file mode 100644 index 722cdf68c475531eb9951ba854f7c68b1132a8bf..0000000000000000000000000000000000000000 --- a/test/unitTest/certstore.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2004-2024 Savoir-faire Linux Inc. - * - * Author: florian Wiesweg <florian.wiesweg@campus.tu-berlin.de> - * - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include <cppunit/TestAssert.h> -#include <cppunit/TestFixture.h> -#include <cppunit/extensions/HelperMacros.h> - -#include "common.h" -#include "test_runner.h" -#include "manager.h" -#include "jami.h" -#include "jamidht/jamiaccount.h" -#include "logger.h" - -#include <dhtnet/certstore.h> - -namespace jami { -namespace test { - -class CertStoreTest : public CppUnit::TestFixture -{ -public: - CertStoreTest() - { - // 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")); - } - ~CertStoreTest() { libjami::fini(); } - static std::string name() { return "certstore"; } - void setUp(); - void tearDown(); - - std::string aliceId; - std::string bobId; - -private: - void trustStoreTest(); - void getCertificateWithSplitted(); - void testBannedParent(); - - CPPUNIT_TEST_SUITE(CertStoreTest); - CPPUNIT_TEST(trustStoreTest); - CPPUNIT_TEST(getCertificateWithSplitted); - CPPUNIT_TEST(testBannedParent); - CPPUNIT_TEST_SUITE_END(); -}; - -CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CertStoreTest, CertStoreTest::name()); - -void -CertStoreTest::setUp() -{ - auto actors = load_actors_and_wait_for_announcement("actors/alice-bob.yml"); - aliceId = actors["alice"]; - bobId = actors["bob"]; -} - -void -CertStoreTest::tearDown() -{ - wait_for_removal_of({aliceId, bobId}); -} - -void -CertStoreTest::trustStoreTest() -{ - auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId); - - auto ca = dht::crypto::generateIdentity("test CA"); - auto account = dht::crypto::generateIdentity("test account", ca, 4096, true); - auto device = dht::crypto::generateIdentity("test device", account); - auto device2 = dht::crypto::generateIdentity("test device 2", account); - auto storeSize = aliceAccount->certStore().getPinnedCertificates().size(); - auto id = ca.second->getId().toString(); - auto pinned = aliceAccount->certStore().getPinnedCertificates(); - CPPUNIT_ASSERT(std::find_if(pinned.begin(), pinned.end(), [&](auto v) { return v == id; }) - == pinned.end()); - - // Test certificate status - auto certAllowed = aliceAccount->accountManager()->getCertificatesByStatus( - dhtnet::tls::TrustStore::PermissionStatus::ALLOWED); - CPPUNIT_ASSERT( - std::find_if(certAllowed.begin(), certAllowed.end(), [&](auto v) { return v == id; }) - == certAllowed.end()); - CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(id) - == dhtnet::tls::TrustStore::PermissionStatus::UNDEFINED); - aliceAccount->setCertificateStatus(ca.second, dhtnet::tls::TrustStore::PermissionStatus::ALLOWED); - certAllowed = aliceAccount->accountManager()->getCertificatesByStatus( - dhtnet::tls::TrustStore::PermissionStatus::ALLOWED); - CPPUNIT_ASSERT( - std::find_if(certAllowed.begin(), certAllowed.end(), [&](auto v) { return v == id; }) - != certAllowed.end()); - CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(id) - == dhtnet::tls::TrustStore::PermissionStatus::ALLOWED); - aliceAccount->setCertificateStatus(ca.second, dhtnet::tls::TrustStore::PermissionStatus::UNDEFINED); - CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(id) - == dhtnet::tls::TrustStore::PermissionStatus::UNDEFINED); - aliceAccount->setCertificateStatus(ca.second, dhtnet::tls::TrustStore::PermissionStatus::ALLOWED); - CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(id) - == dhtnet::tls::TrustStore::PermissionStatus::ALLOWED); - - // Test getPinnedCertificates - pinned = aliceAccount->certStore().getPinnedCertificates(); - CPPUNIT_ASSERT(pinned.size() == storeSize + 2 /* account + device */); - CPPUNIT_ASSERT(std::find_if(pinned.begin(), pinned.end(), [&](auto v) { return v == id; }) - != pinned.end()); - - // Test findCertificateByUID & findIssuer - CPPUNIT_ASSERT(!aliceAccount->certStore().findCertificateByUID("NON_EXISTING_ID")); - auto cert = aliceAccount->certStore().findCertificateByUID(id); - CPPUNIT_ASSERT(cert); - auto issuer = aliceAccount->certStore().findIssuer(cert); - CPPUNIT_ASSERT(issuer); - CPPUNIT_ASSERT(issuer->getId().toString() == id); - - // Test is allowed - CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*ca.second)); - CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*account.second)); - CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*device.second)); - - // Ban device - aliceAccount->setCertificateStatus(device.second, dhtnet::tls::TrustStore::PermissionStatus::BANNED); - CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(device.second->getId().toString()) - == dhtnet::tls::TrustStore::PermissionStatus::BANNED); - CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(id) - == dhtnet::tls::TrustStore::PermissionStatus::ALLOWED); - - CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*ca.second)); - CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*account.second)); - CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*device.second)); - - // Ban account - aliceAccount->setCertificateStatus(account.second, dhtnet::tls::TrustStore::PermissionStatus::BANNED); - CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(account.second->getId().toString()) - == dhtnet::tls::TrustStore::PermissionStatus::BANNED); - CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*ca.second)); - CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*account.second)); - CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*device2.second)); - - // Unban account - aliceAccount->setCertificateStatus(account.second, - dhtnet::tls::TrustStore::PermissionStatus::ALLOWED); - CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(account.second->getId().toString()) - == dhtnet::tls::TrustStore::PermissionStatus::ALLOWED); - CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*ca.second)); - CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*account.second)); - CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*device2.second)); - - // Ban CA - aliceAccount->setCertificateStatus(ca.second, dhtnet::tls::TrustStore::PermissionStatus::BANNED); - CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(ca.second->getId().toString()) - == dhtnet::tls::TrustStore::PermissionStatus::BANNED); - CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*ca.second)); - CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*account.second)); - CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*device2.second)); - - aliceAccount->setCertificateStatus(ca.second, dhtnet::tls::TrustStore::PermissionStatus::BANNED); - CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(ca.second->getId().toString()) - == dhtnet::tls::TrustStore::PermissionStatus::BANNED); - - // Test unpin - aliceAccount->certStore().unpinCertificate(id); - pinned = aliceAccount->certStore().getPinnedCertificates(); - CPPUNIT_ASSERT(std::find_if(pinned.begin(), pinned.end(), [&](auto v) { return v == id; }) - == pinned.end()); - - // Test statusToStr - /*CPPUNIT_ASSERT(strcmp(dhtnet::tls::statusToStr(dhtnet::tls::TrustStatus::TRUSTED), - libdhtnet::Certificate::TrustStatus::TRUSTED) - == 0); - CPPUNIT_ASSERT(strcmp(dhtnet::tls::statusToStr(dhtnet::tls::TrustStatus::UNTRUSTED), - libdhtnet::Certificate::TrustStatus::UNTRUSTED) - == 0);*/ -} - -void -CertStoreTest::getCertificateWithSplitted() -{ - auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId); - auto ca = dht::crypto::generateIdentity("test CA"); - auto account = dht::crypto::generateIdentity("test account", ca, 4096, true); - auto device = dht::crypto::generateIdentity("test device", account); - - auto caCert = std::make_shared<dht::crypto::Certificate>(ca.second->toString(false)); - auto accountCert = std::make_shared<dht::crypto::Certificate>(account.second->toString(false)); - auto devicePartialCert = std::make_shared<dht::crypto::Certificate>( - device.second->toString(false)); - - aliceAccount->certStore().pinCertificate(caCert); - aliceAccount->certStore().pinCertificate(accountCert); - aliceAccount->certStore().pinCertificate(devicePartialCert); - - auto fullCert = aliceAccount->certStore().getCertificate(device.second->getId().toString()); - CPPUNIT_ASSERT(fullCert->issuer && fullCert->issuer->getUID() == accountCert->getUID()); - CPPUNIT_ASSERT(fullCert->issuer->issuer - && fullCert->issuer->issuer->getUID() == caCert->getUID()); -} - -void -CertStoreTest::testBannedParent() -{ - auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId); - - auto ca = dht::crypto::generateIdentity("test CA"); - auto account = dht::crypto::generateIdentity("test account", ca, 4096, true); - auto device = dht::crypto::generateIdentity("test device", account); - auto device2 = dht::crypto::generateIdentity("test device 2", account); - auto id = ca.second->getId().toString(); - auto pinned = aliceAccount->certStore().getPinnedCertificates(); - CPPUNIT_ASSERT(std::find_if(pinned.begin(), pinned.end(), [&](auto v) { return v == id; }) - == pinned.end()); - - // Ban account - aliceAccount->setCertificateStatus(account.second, dhtnet::tls::TrustStore::PermissionStatus::BANNED); - CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(account.second->getId().toString()) - == dhtnet::tls::TrustStore::PermissionStatus::BANNED); - CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*account.second)); - CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*device2.second)); - CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*device.second)); -} - -} // namespace test -} // namespace jami - -RING_TEST_RUNNER(jami::test::CertStoreTest::name()); diff --git a/test/unitTest/ice/ice.cpp b/test/unitTest/ice/ice.cpp deleted file mode 100644 index a89d12b34e3a74150d01daa946e7a31926f377d8..0000000000000000000000000000000000000000 --- a/test/unitTest/ice/ice.cpp +++ /dev/null @@ -1,659 +0,0 @@ -/* - * Copyright (C) 2021-2024 Savoir-faire Linux Inc. - * Author: Sébastien Blin <sebastien.blin@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 <cppunit/TestAssert.h> -#include <cppunit/TestFixture.h> -#include <cppunit/extensions/HelperMacros.h> - -#include <condition_variable> - -#include "manager.h" -#include "opendht/dhtrunner.h" -#include "opendht/thread_pool.h" -#include "../../test_runner.h" -#include "jami.h" -#include "account_const.h" - -#include <dhtnet/ice_transport.h> -#include <dhtnet/ice_transport_factory.h> - -using namespace libjami::Account; - -namespace jami { -namespace test { - -class IceTest : public CppUnit::TestFixture -{ -public: - IceTest() - { - // 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")); - } - ~IceTest() { libjami::fini(); } - static std::string name() { return "Ice"; } - void setUp(); - void tearDown(); - - // For future tests with publicIp - std::shared_ptr<dht::DhtRunner> dht_ {}; - std::unique_ptr<dhtnet::IpAddr> turnV4_ {}; - -private: - void testRawIceConnection(); - void testTurnMasterIceConnection(); - void testTurnSlaveIceConnection(); - void testReceiveTooManyCandidates(); - void testCompleteOnFailure(); - - CPPUNIT_TEST_SUITE(IceTest); - CPPUNIT_TEST(testRawIceConnection); - CPPUNIT_TEST(testTurnMasterIceConnection); - CPPUNIT_TEST(testTurnSlaveIceConnection); - CPPUNIT_TEST(testReceiveTooManyCandidates); - CPPUNIT_TEST(testCompleteOnFailure); - CPPUNIT_TEST_SUITE_END(); -}; - -CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(IceTest, IceTest::name()); - -void -IceTest::setUp() -{ - if (!dht_) { - dht_ = std::make_shared<dht::DhtRunner>(); - dht::DhtRunner::Config config {}; - dht::DhtRunner::Context context {}; - dht_->run(0, config, std::move(context)); - dht_->bootstrap("bootstrap.jami.net:4222"); - std::this_thread::sleep_for(std::chrono::seconds(5)); - } - if (!turnV4_) { - turnV4_ = std::make_unique<dhtnet::IpAddr>("turn.jami.net", AF_INET); - } -} - -void -IceTest::tearDown() -{} - -void -IceTest::testRawIceConnection() -{ - dhtnet::IceTransportOptions ice_config; - ice_config.upnpEnable = true; - ice_config.tcpEnable = true; - std::shared_ptr<dhtnet::IceTransport> ice_master, ice_slave; - std::mutex mtx, mtx_create, mtx_resp, mtx_init; - std::unique_lock lk {mtx}, lk_create {mtx_create}, lk_resp {mtx_resp}, - lk_init {mtx_init}; - std::condition_variable cv, cv_create, cv_resp, cv_init; - std::string init = {}; - std::string response = {}; - bool iceMasterReady = false, iceSlaveReady = false; - ice_config.onInitDone = [&](bool ok) { - CPPUNIT_ASSERT(ok); - dht::ThreadPool::io().run([&] { - CPPUNIT_ASSERT(cv_create.wait_for(lk_create, std::chrono::seconds(10), [&] { - return ice_master != nullptr; - })); - auto iceAttributes = ice_master->getLocalAttributes(); - std::stringstream icemsg; - icemsg << iceAttributes.ufrag << "\n"; - icemsg << iceAttributes.pwd << "\n"; - for (const auto& addr : ice_master->getLocalCandidates(1)) { - icemsg << addr << "\n"; - JAMI_DBG() << "Added local ICE candidate " << addr; - } - init = icemsg.str(); - cv_init.notify_one(); - CPPUNIT_ASSERT(cv_resp.wait_for(lk_resp, std::chrono::seconds(10), [&] { - return !response.empty(); - })); - auto sdp = ice_master->parseIceCandidates(response); - CPPUNIT_ASSERT( - ice_master->startIce({sdp.rem_ufrag, sdp.rem_pwd}, std::move(sdp.rem_candidates))); - }); - }; - ice_config.onNegoDone = [&](bool ok) { - iceMasterReady = ok; - cv.notify_one(); - }; - ice_config.master = true; - ice_config.streamsCount = 1; - ice_config.compCountPerStream = 1; - ice_config.upnpContext = Manager::instance().upnpContext(); - ice_config.factory = Manager::instance().getIceTransportFactory(); - - ice_master = Manager::instance().getIceTransportFactory()->createTransport("master ICE"); - ice_master->initIceInstance(ice_config); - cv_create.notify_all(); - ice_config.onInitDone = [&](bool ok) { - CPPUNIT_ASSERT(ok); - dht::ThreadPool::io().run([&] { - CPPUNIT_ASSERT(cv_create.wait_for(lk_create, std::chrono::seconds(10), [&] { - return ice_slave != nullptr; - })); - auto iceAttributes = ice_slave->getLocalAttributes(); - std::stringstream icemsg; - icemsg << iceAttributes.ufrag << "\n"; - icemsg << iceAttributes.pwd << "\n"; - for (const auto& addr : ice_slave->getLocalCandidates(1)) { - icemsg << addr << "\n"; - JAMI_DBG() << "Added local ICE candidate " << addr; - } - response = icemsg.str(); - cv_resp.notify_one(); - CPPUNIT_ASSERT( - cv_init.wait_for(lk_resp, std::chrono::seconds(10), [&] { return !init.empty(); })); - auto sdp = ice_slave->parseIceCandidates(init); - CPPUNIT_ASSERT( - ice_slave->startIce({sdp.rem_ufrag, sdp.rem_pwd}, std::move(sdp.rem_candidates))); - }); - }; - ice_config.onNegoDone = [&](bool ok) { - iceSlaveReady = ok; - cv.notify_one(); - }; - ice_config.master = false; - ice_config.streamsCount = 1; - ice_config.compCountPerStream = 1; - ice_config.upnpContext = Manager::instance().upnpContext(); - ice_config.factory = Manager::instance().getIceTransportFactory(); - - ice_slave = Manager::instance().getIceTransportFactory()->createTransport("slave ICE"); - ice_slave->initIceInstance(ice_config); - - cv_create.notify_all(); - CPPUNIT_ASSERT( - cv.wait_for(lk, std::chrono::seconds(10), [&] { return iceMasterReady && iceSlaveReady; })); -} - -void -IceTest::testTurnMasterIceConnection() -{ - const auto& addr4 = dht_->getPublicAddress(AF_INET); - CPPUNIT_ASSERT(addr4.size() != 0); - CPPUNIT_ASSERT(turnV4_); - dhtnet::IceTransportOptions ice_config; - ice_config.upnpEnable = true; - ice_config.tcpEnable = true; - std::shared_ptr<dhtnet::IceTransport> ice_master, ice_slave; - std::mutex mtx, mtx_create, mtx_resp, mtx_init; - std::unique_lock lk {mtx}, lk_create {mtx_create}, lk_resp {mtx_resp}, - lk_init {mtx_init}; - std::condition_variable cv, cv_create, cv_resp, cv_init; - std::string init = {}; - std::string response = {}; - bool iceMasterReady = false, iceSlaveReady = false; - ice_config.onInitDone = [&](bool ok) { - CPPUNIT_ASSERT(ok); - dht::ThreadPool::io().run([&] { - CPPUNIT_ASSERT(cv_create.wait_for(lk_create, std::chrono::seconds(10), [&] { - return ice_master != nullptr; - })); - auto iceAttributes = ice_master->getLocalAttributes(); - std::stringstream icemsg; - icemsg << iceAttributes.ufrag << "\n"; - icemsg << iceAttributes.pwd << "\n"; - for (const auto& addr : ice_master->getLocalCandidates(1)) { - if (addr.find("host") == std::string::npos) { - // We only want to add relayed + public ip - icemsg << addr << "\n"; - JAMI_DBG() << "Added local ICE candidate " << addr; - } else { - // Replace host by non existing IP (we still need host to not fail the start) - std::regex e("((?:[0-9]{1,3}\\.){3}[0-9]{1,3})"); - auto newaddr = std::regex_replace(addr, e, "100.100.100.100"); - if (newaddr != addr) - icemsg << newaddr << "\n"; - } - } - init = icemsg.str(); - cv_init.notify_one(); - CPPUNIT_ASSERT(cv_resp.wait_for(lk_resp, std::chrono::seconds(10), [&] { - return !response.empty(); - })); - - auto sdp = ice_master->parseIceCandidates(response); - CPPUNIT_ASSERT( - ice_master->startIce({sdp.rem_ufrag, sdp.rem_pwd}, std::move(sdp.rem_candidates))); - }); - }; - ice_config.onNegoDone = [&](bool ok) { - iceMasterReady = ok; - cv.notify_one(); - }; - ice_config.accountPublicAddr = dhtnet::IpAddr(*addr4[0].get()); - ice_config.accountLocalAddr = dhtnet::ip_utils::getLocalAddr(AF_INET); - ice_config.turnServers.emplace_back(dhtnet::TurnServerInfo() - .setUri(turnV4_->toString(true)) - .setUsername("ring") - .setPassword("ring") - .setRealm("ring")); - ice_config.master = true; - ice_config.streamsCount = 1; - ice_config.compCountPerStream = 1; - ice_config.upnpContext = Manager::instance().upnpContext(); - ice_config.factory = Manager::instance().getIceTransportFactory(); - ice_master = Manager::instance().getIceTransportFactory()->createTransport("master ICE"); - ice_master->initIceInstance(ice_config); - cv_create.notify_all(); - ice_config.turnServers = {}; - ice_config.onInitDone = [&](bool ok) { - CPPUNIT_ASSERT(ok); - dht::ThreadPool::io().run([&] { - CPPUNIT_ASSERT(cv_create.wait_for(lk_create, std::chrono::seconds(10), [&] { - return ice_slave != nullptr; - })); - auto iceAttributes = ice_slave->getLocalAttributes(); - std::stringstream icemsg; - icemsg << iceAttributes.ufrag << "\n"; - icemsg << iceAttributes.pwd << "\n"; - for (const auto& addr : ice_slave->getLocalCandidates(1)) { - if (addr.find("host") == std::string::npos) { - // We only want to add relayed + public ip - icemsg << addr << "\n"; - JAMI_DBG() << "Added local ICE candidate " << addr; - } else { - // Replace host by non existing IP (we still need host to not fail the start) - std::regex e("((?:[0-9]{1,3}\\.){3}[0-9]{1,3})"); - auto newaddr = std::regex_replace(addr, e, "100.100.100.100"); - if (newaddr != addr) - icemsg << newaddr << "\n"; - } - } - response = icemsg.str(); - cv_resp.notify_one(); - CPPUNIT_ASSERT( - cv_init.wait_for(lk_resp, std::chrono::seconds(10), [&] { return !init.empty(); })); - auto sdp = ice_slave->parseIceCandidates(init); - CPPUNIT_ASSERT( - ice_slave->startIce({sdp.rem_ufrag, sdp.rem_pwd}, std::move(sdp.rem_candidates))); - }); - }; - ice_config.onNegoDone = [&](bool ok) { - iceSlaveReady = ok; - cv.notify_one(); - }; - ice_config.master = false; - ice_config.streamsCount = 1; - ice_config.compCountPerStream = 1; - ice_config.upnpContext = Manager::instance().upnpContext(); - ice_config.factory = Manager::instance().getIceTransportFactory(); - ice_slave = Manager::instance().getIceTransportFactory()->createTransport("slave ICE"); - ice_slave->initIceInstance(ice_config); - - cv_create.notify_all(); - CPPUNIT_ASSERT( - cv.wait_for(lk, std::chrono::seconds(10), [&] { return iceMasterReady && iceSlaveReady; })); - CPPUNIT_ASSERT(ice_master->getLocalAddress(1).toString(false) == turnV4_->toString(false)); -} - -void -IceTest::testTurnSlaveIceConnection() -{ - const auto& addr4 = dht_->getPublicAddress(AF_INET); - CPPUNIT_ASSERT(addr4.size() != 0); - CPPUNIT_ASSERT(turnV4_); - dhtnet::IceTransportOptions ice_config; - ice_config.upnpEnable = true; - ice_config.tcpEnable = true; - std::shared_ptr<dhtnet::IceTransport> ice_master, ice_slave; - std::mutex mtx, mtx_create, mtx_resp, mtx_init; - std::unique_lock lk {mtx}, lk_create {mtx_create}, lk_resp {mtx_resp}, - lk_init {mtx_init}; - std::condition_variable cv, cv_create, cv_resp, cv_init; - std::string init = {}; - std::string response = {}; - bool iceMasterReady = false, iceSlaveReady = false; - ice_config.onInitDone = [&](bool ok) { - CPPUNIT_ASSERT(ok); - dht::ThreadPool::io().run([&] { - CPPUNIT_ASSERT(cv_create.wait_for(lk_create, std::chrono::seconds(10), [&] { - return ice_master != nullptr; - })); - auto iceAttributes = ice_master->getLocalAttributes(); - std::stringstream icemsg; - icemsg << iceAttributes.ufrag << "\n"; - icemsg << iceAttributes.pwd << "\n"; - for (const auto& addr : ice_master->getLocalCandidates(1)) { - if (addr.find("host") == std::string::npos) { - // We only want to add relayed + public ip - icemsg << addr << "\n"; - JAMI_DBG() << "Added local ICE candidate " << addr; - } else { - // Replace host by non existing IP (we still need host to not fail the start) - std::regex e("((?:[0-9]{1,3}\\.){3}[0-9]{1,3})"); - auto newaddr = std::regex_replace(addr, e, "100.100.100.100"); - if (newaddr != addr) - icemsg << newaddr << "\n"; - } - } - init = icemsg.str(); - cv_init.notify_one(); - CPPUNIT_ASSERT(cv_resp.wait_for(lk_resp, std::chrono::seconds(10), [&] { - return !response.empty(); - })); - auto sdp = ice_master->parseIceCandidates(response); - CPPUNIT_ASSERT( - ice_master->startIce({sdp.rem_ufrag, sdp.rem_pwd}, std::move(sdp.rem_candidates))); - }); - }; - ice_config.onNegoDone = [&](bool ok) { - iceMasterReady = ok; - cv.notify_one(); - }; - ice_config.accountPublicAddr = dhtnet::IpAddr(*addr4[0].get()); - ice_config.accountLocalAddr = dhtnet::ip_utils::getLocalAddr(AF_INET); - ice_config.master = true; - ice_config.streamsCount = 1; - ice_config.compCountPerStream = 1; - ice_config.upnpContext = Manager::instance().upnpContext(); - ice_config.factory = Manager::instance().getIceTransportFactory(); - ice_master = Manager::instance().getIceTransportFactory()->createTransport("master ICE"); - ice_master->initIceInstance(ice_config); - cv_create.notify_all(); - ice_config.onInitDone = [&](bool ok) { - CPPUNIT_ASSERT(ok); - dht::ThreadPool::io().run([&] { - CPPUNIT_ASSERT(cv_create.wait_for(lk_create, std::chrono::seconds(10), [&] { - return ice_slave != nullptr; - })); - auto iceAttributes = ice_slave->getLocalAttributes(); - std::stringstream icemsg; - icemsg << iceAttributes.ufrag << "\n"; - icemsg << iceAttributes.pwd << "\n"; - for (const auto& addr : ice_slave->getLocalCandidates(1)) { - if (addr.find("host") == std::string::npos) { - // We only want to add relayed + public ip - icemsg << addr << "\n"; - JAMI_DBG() << "Added local ICE candidate " << addr; - } else { - // Replace host by non existing IP (we still need host to not fail the start) - std::regex e("((?:[0-9]{1,3}\\.){3}[0-9]{1,3})"); - auto newaddr = std::regex_replace(addr, e, "100.100.100.100"); - if (newaddr != addr) - icemsg << newaddr << "\n"; - } - } - response = icemsg.str(); - cv_resp.notify_one(); - CPPUNIT_ASSERT( - cv_init.wait_for(lk_resp, std::chrono::seconds(10), [&] { return !init.empty(); })); - auto sdp = ice_slave->parseIceCandidates(init); - CPPUNIT_ASSERT( - ice_slave->startIce({sdp.rem_ufrag, sdp.rem_pwd}, std::move(sdp.rem_candidates))); - }); - }; - ice_config.onNegoDone = [&](bool ok) { - iceSlaveReady = ok; - cv.notify_one(); - }; - ice_config.turnServers.emplace_back(dhtnet::TurnServerInfo() - .setUri(turnV4_->toString(true)) - .setUsername("ring") - .setPassword("ring") - .setRealm("ring")); - ice_config.master = false; - ice_config.streamsCount = 1; - ice_config.compCountPerStream = 1; - ice_config.upnpContext = Manager::instance().upnpContext(); - ice_config.factory = Manager::instance().getIceTransportFactory(); - ice_slave = Manager::instance().getIceTransportFactory()->createTransport("slave ICE"); - ice_slave->initIceInstance(ice_config); - cv_create.notify_all(); - CPPUNIT_ASSERT( - cv.wait_for(lk, std::chrono::seconds(10), [&] { return iceMasterReady && iceSlaveReady; })); - CPPUNIT_ASSERT(ice_slave->getLocalAddress(1).toString(false) == turnV4_->toString(false)); -} - -void -IceTest::testReceiveTooManyCandidates() -{ - const auto& addr4 = dht_->getPublicAddress(AF_INET); - CPPUNIT_ASSERT(addr4.size() != 0); - CPPUNIT_ASSERT(turnV4_); - dhtnet::IceTransportOptions ice_config; - ice_config.upnpEnable = true; - ice_config.tcpEnable = true; - std::shared_ptr<dhtnet::IceTransport> ice_master, ice_slave; - std::mutex mtx, mtx_create, mtx_resp, mtx_init; - std::unique_lock lk {mtx}, lk_create {mtx_create}, lk_resp {mtx_resp}, - lk_init {mtx_init}; - std::condition_variable cv, cv_create, cv_resp, cv_init; - std::string init = {}; - std::string response = {}; - bool iceMasterReady = false, iceSlaveReady = false; - ice_config.onInitDone = [&](bool ok) { - CPPUNIT_ASSERT(ok); - dht::ThreadPool::io().run([&] { - CPPUNIT_ASSERT(cv_create.wait_for(lk_create, std::chrono::seconds(10), [&] { - return ice_master != nullptr; - })); - auto iceAttributes = ice_master->getLocalAttributes(); - std::stringstream icemsg; - icemsg << iceAttributes.ufrag << "\n"; - icemsg << iceAttributes.pwd << "\n"; - for (const auto& addr : ice_master->getLocalCandidates(1)) { - icemsg << addr << "\n"; - JAMI_DBG() << "Added local ICE candidate " << addr; - } - init = icemsg.str(); - cv_init.notify_one(); - CPPUNIT_ASSERT(cv_resp.wait_for(lk_resp, std::chrono::seconds(10), [&] { - return !response.empty(); - })); - auto sdp = ice_master->parseIceCandidates(response); - CPPUNIT_ASSERT( - ice_master->startIce({sdp.rem_ufrag, sdp.rem_pwd}, std::move(sdp.rem_candidates))); - }); - }; - ice_config.onNegoDone = [&](bool ok) { - iceMasterReady = ok; - cv.notify_one(); - }; - ice_config.accountPublicAddr = dhtnet::IpAddr(*addr4[0].get()); - ice_config.accountLocalAddr = dhtnet::ip_utils::getLocalAddr(AF_INET); - ice_config.turnServers.emplace_back(dhtnet::TurnServerInfo() - .setUri(turnV4_->toString(true)) - .setUsername("ring") - .setPassword("ring") - .setRealm("ring")); - ice_config.master = true; - ice_config.streamsCount = 1; - ice_config.compCountPerStream = 1; - ice_config.upnpContext = Manager::instance().upnpContext(); - ice_config.factory = Manager::instance().getIceTransportFactory(); - - ice_master = Manager::instance().getIceTransportFactory()->createTransport("master ICE"); - ice_master->initIceInstance(ice_config); - cv_create.notify_all(); - ice_config.onInitDone = [&](bool ok) { - CPPUNIT_ASSERT(ok); - dht::ThreadPool::io().run([&] { - CPPUNIT_ASSERT(cv_create.wait_for(lk_create, std::chrono::seconds(10), [&] { - return ice_slave != nullptr; - })); - auto iceAttributes = ice_slave->getLocalAttributes(); - std::stringstream icemsg; - icemsg << iceAttributes.ufrag << "\n"; - icemsg << iceAttributes.pwd << "\n"; - for (const auto& addr : ice_master->getLocalCandidates(1)) { - icemsg << addr << "\n"; - JAMI_DBG() << "Added local ICE candidate " << addr; - } - for (auto i = 0; i < std::min(256, PJ_ICE_ST_MAX_CAND); ++i) { - icemsg << "Hc0a800a5 1 TCP 2130706431 192.168.0." << i - << " 43613 typ host tcptype passive" - << "\n"; - icemsg << "Hc0a800a5 1 TCP 2130706431 192.168.0." << i - << " 9 typ host tcptype active" - << "\n"; - } - response = icemsg.str(); - cv_resp.notify_one(); - CPPUNIT_ASSERT( - cv_init.wait_for(lk_resp, std::chrono::seconds(10), [&] { return !init.empty(); })); - auto sdp = ice_slave->parseIceCandidates(init); - CPPUNIT_ASSERT( - ice_slave->startIce({sdp.rem_ufrag, sdp.rem_pwd}, std::move(sdp.rem_candidates))); - }); - }; - ice_config.onNegoDone = [&](bool ok) { - iceSlaveReady = ok; - cv.notify_one(); - }; - ice_config.master = false; - ice_config.streamsCount = 1; - ice_config.compCountPerStream = 1; - ice_config.upnpContext = Manager::instance().upnpContext(); - ice_config.factory = Manager::instance().getIceTransportFactory(); - - ice_slave = Manager::instance().getIceTransportFactory()->createTransport("slave ICE"); - ice_slave->initIceInstance(ice_config); - cv_create.notify_all(); - CPPUNIT_ASSERT( - cv.wait_for(lk, std::chrono::seconds(10), [&] { return iceMasterReady && iceSlaveReady; })); -} - -void -IceTest::testCompleteOnFailure() -{ - const auto& addr4 = dht_->getPublicAddress(AF_INET); - CPPUNIT_ASSERT(addr4.size() != 0); - CPPUNIT_ASSERT(turnV4_); - dhtnet::IceTransportOptions ice_config; - ice_config.upnpEnable = true; - ice_config.tcpEnable = true; - std::shared_ptr<dhtnet::IceTransport> ice_master, ice_slave; - std::mutex mtx, mtx_create, mtx_resp, mtx_init; - std::unique_lock lk {mtx}, lk_create {mtx_create}, lk_resp {mtx_resp}, - lk_init {mtx_init}; - std::condition_variable cv, cv_create, cv_resp, cv_init; - std::string init = {}; - std::string response = {}; - bool iceMasterNotReady = false, iceSlaveNotReady = false; - ice_config.onInitDone = [&](bool ok) { - CPPUNIT_ASSERT(ok); - dht::ThreadPool::io().run([&] { - CPPUNIT_ASSERT(cv_create.wait_for(lk_create, std::chrono::seconds(10), [&] { - return ice_master != nullptr; - })); - auto iceAttributes = ice_master->getLocalAttributes(); - std::stringstream icemsg; - icemsg << iceAttributes.ufrag << "\n"; - icemsg << iceAttributes.pwd << "\n"; - for (const auto& addr : ice_master->getLocalCandidates(1)) { - if (addr.find("relay") != std::string::npos) { - // We only want to relayed and modify the rest (to have CONNREFUSED) - icemsg << addr << "\n"; - JAMI_DBG() << "Added local ICE candidate " << addr; - } else { - // Replace host by non existing IP (we still need host to not fail the start) - std::regex e("((?:[0-9]{1,3}\\.){3}[0-9]{1,3})"); - auto newaddr = std::regex_replace(addr, e, "100.100.100.100"); - if (newaddr != addr) - icemsg << newaddr << "\n"; - } - } - init = icemsg.str(); - cv_init.notify_one(); - CPPUNIT_ASSERT(cv_resp.wait_for(lk_resp, std::chrono::seconds(10), [&] { - return !response.empty(); - })); - auto sdp = ice_master->parseIceCandidates(response); - CPPUNIT_ASSERT( - ice_master->startIce({sdp.rem_ufrag, sdp.rem_pwd}, std::move(sdp.rem_candidates))); - }); - }; - ice_config.onNegoDone = [&](bool ok) { - iceMasterNotReady = !ok; - cv.notify_one(); - }; - ice_config.accountPublicAddr = dhtnet::IpAddr(*addr4[0].get()); - ice_config.accountLocalAddr = dhtnet::ip_utils::getLocalAddr(AF_INET); - ice_config.master = true; - ice_config.streamsCount = 1; - ice_config.compCountPerStream = 1; - ice_config.upnpContext = Manager::instance().upnpContext(); - ice_config.factory = Manager::instance().getIceTransportFactory(); - ice_master = Manager::instance().getIceTransportFactory()->createTransport("master ICE"); - ice_master->initIceInstance(ice_config); - cv_create.notify_all(); - ice_config.onInitDone = [&](bool ok) { - CPPUNIT_ASSERT(ok); - dht::ThreadPool::io().run([&] { - CPPUNIT_ASSERT(cv_create.wait_for(lk_create, std::chrono::seconds(10), [&] { - return ice_slave != nullptr; - })); - auto iceAttributes = ice_slave->getLocalAttributes(); - std::stringstream icemsg; - icemsg << iceAttributes.ufrag << "\n"; - icemsg << iceAttributes.pwd << "\n"; - for (const auto& addr : ice_slave->getLocalCandidates(1)) { - if (addr.find("relay") != std::string::npos) { - // We only want to relayed and modify the rest (to have CONNREFUSED) - icemsg << addr << "\n"; - JAMI_DBG() << "Added local ICE candidate " << addr; - } else { - // Replace host by non existing IP (we still need host to not fail the start) - std::regex e("((?:[0-9]{1,3}\\.){3}[0-9]{1,3})"); - auto newaddr = std::regex_replace(addr, e, "100.100.100.100"); - if (newaddr != addr) - icemsg << newaddr << "\n"; - } - } - response = icemsg.str(); - cv_resp.notify_one(); - CPPUNIT_ASSERT( - cv_init.wait_for(lk_resp, std::chrono::seconds(10), [&] { return !init.empty(); })); - auto sdp = ice_slave->parseIceCandidates(init); - CPPUNIT_ASSERT( - ice_slave->startIce({sdp.rem_ufrag, sdp.rem_pwd}, std::move(sdp.rem_candidates))); - }); - }; - ice_config.onNegoDone = [&](bool ok) { - iceSlaveNotReady = !ok; - cv.notify_one(); - }; - ice_config.turnServers.emplace_back(dhtnet::TurnServerInfo() - .setUri(turnV4_->toString(true)) - .setUsername("ring") - .setPassword("ring") - .setRealm("ring")); - ice_config.master = false; - ice_config.streamsCount = 1; - ice_config.compCountPerStream = 1; - ice_config.upnpContext = Manager::instance().upnpContext(); - ice_config.factory = Manager::instance().getIceTransportFactory(); - ice_slave = Manager::instance().getIceTransportFactory()->createTransport("slave ICE"); - ice_slave->initIceInstance(ice_config); - cv_create.notify_all(); - // Check that nego failed and callback called - CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(120), [&] { - return iceMasterNotReady && iceSlaveNotReady; - })); -} - -} // namespace test -} // namespace jami - -RING_TEST_RUNNER(jami::test::IceTest::name())