blob: 4cd62daec96cf2091240669645134764cc93b13b [file] [log] [blame]
Adrien Béraudefe27372023-05-27 18:56:29 -04001/*
Adrien Béraudcb753622023-07-17 22:32:49 -04002 * Copyright (C) 2004-2023 Savoir-faire Linux Inc.
Adrien Béraudefe27372023-05-27 18:56:29 -04003 *
Adrien Béraudcb753622023-07-17 22:32:49 -04004 * This program is free software: you can redistribute it and/or modify
Adrien Béraudefe27372023-05-27 18:56:29 -04005 * it under the terms of the GNU General Public License as published by
Adrien Béraudcb753622023-07-17 22:32:49 -04006 * the Free Software Foundation, either version 3 of the License, or
Adrien Béraudefe27372023-05-27 18:56:29 -04007 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Adrien Béraudcb753622023-07-17 22:32:49 -040011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Adrien Béraudefe27372023-05-27 18:56:29 -040012 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
Adrien Béraudefe27372023-05-27 18:56:29 -040017
18#include "connectionmanager.h"
19#include "multiplexed_socket.h"
20#include "test_runner.h"
Morteza Namvar82960b32023-07-04 17:08:22 -040021#include "certstore.h"
Adrien Béraudefe27372023-05-27 18:56:29 -040022
Adrien Béraud027af2a2023-08-27 12:08:50 -040023#include <opendht/log.h>
24#include <asio/executor_work_guard.hpp>
25#include <asio/io_context.hpp>
26
27#include <cppunit/TestAssert.h>
28#include <cppunit/TestFixture.h>
29#include <cppunit/extensions/HelperMacros.h>
30
31#include <condition_variable>
32#include <iostream>
33#include <filesystem>
34
Adrien Béraudefe27372023-05-27 18:56:29 -040035using namespace std::literals::chrono_literals;
36
Adrien Béraud1ae60aa2023-07-07 09:55:09 -040037namespace dhtnet {
Adrien Béraudefe27372023-05-27 18:56:29 -040038namespace test {
39
Amnab8c33bb2023-08-03 14:40:01 -040040struct ConnectionHandler
41{
Morteza Namvar82960b32023-07-04 17:08:22 -040042 dht::crypto::Identity id;
43 std::shared_ptr<Logger> logger;
44 std::shared_ptr<tls::CertificateStore> certStore;
45 std::shared_ptr<dht::DhtRunner> dht;
46 std::shared_ptr<ConnectionManager> connectionManager;
47 std::shared_ptr<asio::io_context> ioContext;
Amnab8c33bb2023-08-03 14:40:01 -040048 std::shared_ptr<std::thread> ioContextRunner;
Morteza Namvar82960b32023-07-04 17:08:22 -040049};
50
Adrien Béraudefe27372023-05-27 18:56:29 -040051class ConnectionManagerTest : public CppUnit::TestFixture
52{
53public:
54 ConnectionManagerTest() {}
Amnab8c33bb2023-08-03 14:40:01 -040055 ~ConnectionManagerTest() {}
Adrien Béraudefe27372023-05-27 18:56:29 -040056 static std::string name() { return "ConnectionManager"; }
57 void setUp();
58 void tearDown();
59
Morteza Namvar82960b32023-07-04 17:08:22 -040060 std::unique_ptr<ConnectionHandler> alice;
61 std::unique_ptr<ConnectionHandler> bob;
Adrien Béraudefe27372023-05-27 18:56:29 -040062
Amnab8c33bb2023-08-03 14:40:01 -040063 // Create a lock to be used in the test units
Morteza Namvar82960b32023-07-04 17:08:22 -040064 std::mutex mtx;
65 std::shared_ptr<asio::io_context> ioContext;
Amnab8c33bb2023-08-03 14:40:01 -040066 std::shared_ptr<std::thread> ioContextRunner;
67 // std::thread ioContextRunner;
Morteza Namvar82960b32023-07-04 17:08:22 -040068 std::shared_ptr<Logger> logger;
Amna81221ad2023-09-14 17:33:26 -040069 std::shared_ptr<IceTransportFactory> factory;
Morteza Namvar82960b32023-07-04 17:08:22 -040070
Amnab8c33bb2023-08-03 14:40:01 -040071private:
Morteza Namvar82960b32023-07-04 17:08:22 -040072 std::unique_ptr<ConnectionHandler> setupHandler(const std::string& name);
73
Amnab8c33bb2023-08-03 14:40:01 -040074 void testConnectDevice();
75 void testAcceptConnection();
76 void testMultipleChannels();
77 void testMultipleChannelsOneDeclined();
78 void testMultipleChannelsSameName();
79 void testDeclineConnection();
80 void testSendReceiveData();
81 void testAcceptsICERequest();
82 void testDeclineICERequest();
83 void testChannelRcvShutdown();
84 void testChannelSenderShutdown();
85 void testCloseConnectionWith();
86 void testShutdownCallbacks();
87 void testFloodSocket();
88 void testDestroyWhileSending();
89 void testIsConnecting();
90 void testCanSendBeacon();
91 void testCannotSendBeacon();
92 void testConnectivityChangeTriggerBeacon();
93 void testOnNoBeaconTriggersShutdown();
94 void testShutdownWhileNegotiating();
95 void testGetChannelList();
Adrien Béraudefe27372023-05-27 18:56:29 -040096 CPPUNIT_TEST_SUITE(ConnectionManagerTest);
Amnab8c33bb2023-08-03 14:40:01 -040097 CPPUNIT_TEST(testDeclineICERequest);
98 CPPUNIT_TEST(testConnectDevice);
99 CPPUNIT_TEST(testIsConnecting);
100 CPPUNIT_TEST(testAcceptConnection);
101 CPPUNIT_TEST(testDeclineConnection);
102 CPPUNIT_TEST(testMultipleChannels);
103 CPPUNIT_TEST(testMultipleChannelsOneDeclined);
104 CPPUNIT_TEST(testMultipleChannelsSameName);
105 CPPUNIT_TEST(testSendReceiveData);
106 CPPUNIT_TEST(testAcceptsICERequest);
107 CPPUNIT_TEST(testChannelRcvShutdown);
108 CPPUNIT_TEST(testChannelSenderShutdown);
109 CPPUNIT_TEST(testCloseConnectionWith);
110 CPPUNIT_TEST(testShutdownCallbacks);
111 CPPUNIT_TEST(testFloodSocket);
112 CPPUNIT_TEST(testDestroyWhileSending);
113 CPPUNIT_TEST(testCanSendBeacon);
114 CPPUNIT_TEST(testCannotSendBeacon);
115 CPPUNIT_TEST(testConnectivityChangeTriggerBeacon);
116 CPPUNIT_TEST(testOnNoBeaconTriggersShutdown);
117 CPPUNIT_TEST(testShutdownWhileNegotiating);
118 CPPUNIT_TEST(testGetChannelList);
Adrien Béraudefe27372023-05-27 18:56:29 -0400119 CPPUNIT_TEST_SUITE_END();
120};
121
122CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ConnectionManagerTest, ConnectionManagerTest::name());
123
Morteza Namvar82960b32023-07-04 17:08:22 -0400124std::unique_ptr<ConnectionHandler>
Amnab8c33bb2023-08-03 14:40:01 -0400125ConnectionManagerTest::setupHandler(const std::string& name)
126{
Morteza Namvar82960b32023-07-04 17:08:22 -0400127 auto h = std::make_unique<ConnectionHandler>();
Adrien Béraudc631a832023-07-26 22:19:00 -0400128 auto ca = dht::crypto::generateIdentity("ca");
129 h->id = dht::crypto::generateIdentity(name, ca);
Morteza Namvar82960b32023-07-04 17:08:22 -0400130 h->logger = logger;
131 h->certStore = std::make_shared<tls::CertificateStore>(name, h->logger);
132 h->ioContext = std::make_shared<asio::io_context>();
Amnab8c33bb2023-08-03 14:40:01 -0400133 h->ioContext = ioContext;
134
135 h->ioContextRunner = ioContextRunner;
Morteza Namvar82960b32023-07-04 17:08:22 -0400136
137 dht::DhtRunner::Config dhtConfig;
138 dhtConfig.dht_config.id = h->id;
139 dhtConfig.threaded = true;
140
141 dht::DhtRunner::Context dhtContext;
Amnab8c33bb2023-08-03 14:40:01 -0400142 dhtContext.certificateStore = [c = h->certStore](const dht::InfoHash& pk_id) {
Morteza Namvar82960b32023-07-04 17:08:22 -0400143 std::vector<std::shared_ptr<dht::crypto::Certificate>> ret;
144 if (auto cert = c->getCertificate(pk_id.toString()))
145 ret.emplace_back(std::move(cert));
146 return ret;
147 };
Amnab8c33bb2023-08-03 14:40:01 -0400148 // dhtContext.logger = h->logger;
Morteza Namvar82960b32023-07-04 17:08:22 -0400149
150 h->dht = std::make_shared<dht::DhtRunner>();
151 h->dht->run(dhtConfig, std::move(dhtContext));
Adrien Béraude8541392023-07-27 15:48:04 -0400152 h->dht->bootstrap("bootstrap.jami.net");
Morteza Namvar82960b32023-07-04 17:08:22 -0400153
154 auto config = std::make_shared<ConnectionManager::Config>();
155 config->dht = h->dht;
156 config->id = h->id;
157 config->ioContext = h->ioContext;
Amna81221ad2023-09-14 17:33:26 -0400158 config->factory = factory;
Morteza Namvar82960b32023-07-04 17:08:22 -0400159 config->logger = logger;
Amna81221ad2023-09-14 17:33:26 -0400160 config->certStore = h->certStore;
Morteza Namvar82960b32023-07-04 17:08:22 -0400161
162 std::filesystem::path currentPath = std::filesystem::current_path();
163 std::filesystem::path tempDirPath = currentPath / "temp";
164
165 config->cachePath = tempDirPath.string();
166
167 h->connectionManager = std::make_shared<ConnectionManager>(config);
Amnab8c33bb2023-08-03 14:40:01 -0400168 h->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400169 return h;
170}
171
Adrien Béraudefe27372023-05-27 18:56:29 -0400172void
173ConnectionManagerTest::setUp()
174{
Morteza Namvar82960b32023-07-04 17:08:22 -0400175 logger = dht::log::getStdLogger();
Adrien Béraudc631a832023-07-26 22:19:00 -0400176
177 logger->debug("Using PJSIP version {} for {}", pj_get_version(), PJ_OS_NAME);
178 logger->debug("Using GnuTLS version {}", gnutls_check_version(nullptr));
179 logger->debug("Using OpenDHT version {}", dht::version());
180
Morteza Namvar82960b32023-07-04 17:08:22 -0400181 ioContext = std::make_shared<asio::io_context>();
Amnab8c33bb2023-08-03 14:40:01 -0400182 ioContextRunner = std::make_shared<std::thread>([context = ioContext]() {
Morteza Namvar82960b32023-07-04 17:08:22 -0400183 try {
184 auto work = asio::make_work_guard(*context);
185 context->run();
186 } catch (const std::exception& ex) {
Amnab8c33bb2023-08-03 14:40:01 -0400187 // print the error;
Morteza Namvar82960b32023-07-04 17:08:22 -0400188 }
189 });
Amnab8c33bb2023-08-03 14:40:01 -0400190 // ioContextRunner = std::thread([context = ioContext]() {
191 // try {
192 // auto work = asio::make_work_guard(*context);
193 // context->run();
194 // } catch (const std::exception& ex) {
195 // // print the error;
196 // }
197 // });
Adrien Béraud89933c12023-07-26 14:53:30 -0400198 factory = std::make_unique<IceTransportFactory>(logger);
Morteza Namvar82960b32023-07-04 17:08:22 -0400199 alice = setupHandler("alice");
200 bob = setupHandler("bob");
Adrien Béraudefe27372023-05-27 18:56:29 -0400201}
202
Morteza Namvar82960b32023-07-04 17:08:22 -0400203
Adrien Béraudefe27372023-05-27 18:56:29 -0400204void
205ConnectionManagerTest::tearDown()
206{
Amnab8c33bb2023-08-03 14:40:01 -0400207 // wait_for_removal_of({aliceId, bobId});
208 // Stop the io_context and join the ioContextRunner thread
Morteza Namvar82960b32023-07-04 17:08:22 -0400209 ioContext->stop();
Amnab8c33bb2023-08-03 14:40:01 -0400210
211 if (ioContextRunner && ioContextRunner->joinable()) {
212 ioContextRunner->join();
213 }
Adrien Béraudefe27372023-05-27 18:56:29 -0400214}
Adrien Béraudefe27372023-05-27 18:56:29 -0400215void
Morteza Namvar82960b32023-07-04 17:08:22 -0400216ConnectionManagerTest::testConnectDevice()
Adrien Béraudefe27372023-05-27 18:56:29 -0400217{
Morteza Namvar82960b32023-07-04 17:08:22 -0400218 std::unique_lock<std::mutex> lock {mtx};
219 std::condition_variable bobConVar;
220 bool isBobRecvChanlReq = false;
Adrien Béraudefe27372023-05-27 18:56:29 -0400221
Morteza Namvar82960b32023-07-04 17:08:22 -0400222 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
223 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Adrien Béraudefe27372023-05-27 18:56:29 -0400224
Amnab8c33bb2023-08-03 14:40:01 -0400225 bob->connectionManager->onChannelRequest(
226 [&isBobRecvChanlReq, &bobConVar](const std::shared_ptr<dht::crypto::Certificate>&,
227 const std::string& name) {
228 isBobRecvChanlReq = name == "dumyName";
229 bobConVar.notify_one();
230 return true;
231 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400232
Morteza Namvar82960b32023-07-04 17:08:22 -0400233 std::condition_variable alicConVar;
234 bool isAlicConnected = false;
235 auto conctDevicCalBack = [&](std::shared_ptr<ChannelSocket> socket, const DeviceId&) {
Amnab8c33bb2023-08-03 14:40:01 -0400236 if (socket) {
237 isAlicConnected = true;
238 }
Morteza Namvar82960b32023-07-04 17:08:22 -0400239 alicConVar.notify_one();
240 };
Adrien Béraudefe27372023-05-27 18:56:29 -0400241
Morteza Namvar82960b32023-07-04 17:08:22 -0400242 alice->connectionManager->connectDevice(bob->id.second, "dumyName", conctDevicCalBack);
Adrien Béraudefe27372023-05-27 18:56:29 -0400243
Amnab8c33bb2023-08-03 14:40:01 -0400244 // Step 4: to check if Alice connected to Bob?
Morteza Namvar82960b32023-07-04 17:08:22 -0400245 CPPUNIT_ASSERT(alicConVar.wait_for(lock, 60s, [&] { return isAlicConnected; }));
Adrien Béraudefe27372023-05-27 18:56:29 -0400246}
247
Amnab8c33bb2023-08-03 14:40:01 -0400248void
249ConnectionManagerTest::testAcceptConnection()
250{
251 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
252 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Adrien Béraudefe27372023-05-27 18:56:29 -0400253
Amnab8c33bb2023-08-03 14:40:01 -0400254 std::mutex mtx;
255 std::unique_lock<std::mutex> lk {mtx};
256 std::condition_variable cv;
257 bool successfullyConnected = false;
258 bool successfullyReceive = false;
259 bool receiverConnected = false;
Adrien Béraudefe27372023-05-27 18:56:29 -0400260
Amnab8c33bb2023-08-03 14:40:01 -0400261 bob->connectionManager->onChannelRequest(
262 [&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
263 const std::string& name) {
264 successfullyReceive = name == "git://*";
265 return true;
266 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400267
Amnab8c33bb2023-08-03 14:40:01 -0400268 bob->connectionManager->onConnectionReady(
269 [&receiverConnected](const DeviceId&,
270 const std::string& name,
271 std::shared_ptr<ChannelSocket> socket) {
272 receiverConnected = socket && (name == "git://*");
273 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400274
Amnab8c33bb2023-08-03 14:40:01 -0400275 alice->connectionManager->connectDevice(bob->id.second,
276 "git://*",
277 [&](std::shared_ptr<ChannelSocket> socket,
278 const DeviceId&) {
279 if (socket) {
280 successfullyConnected = true;
281 }
282 cv.notify_one();
283 });
284 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
285 return successfullyReceive && successfullyConnected && receiverConnected;
286 }));
287}
Adrien Béraudefe27372023-05-27 18:56:29 -0400288
Amnab8c33bb2023-08-03 14:40:01 -0400289void
290ConnectionManagerTest::testDeclineConnection()
291{
292 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
293 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Adrien Béraudefe27372023-05-27 18:56:29 -0400294
Amnab8c33bb2023-08-03 14:40:01 -0400295 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
296 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Adrien Béraudefe27372023-05-27 18:56:29 -0400297
Amnab8c33bb2023-08-03 14:40:01 -0400298 std::mutex mtx;
299 std::unique_lock<std::mutex> lk {mtx};
300 std::condition_variable cv;
301 bool successfullyConnected = false;
302 bool successfullyReceive = false;
303 bool receiverConnected = false;
Adrien Béraudefe27372023-05-27 18:56:29 -0400304
Amnab8c33bb2023-08-03 14:40:01 -0400305 bob->connectionManager->onChannelRequest(
306 [&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
307 const std::string&) {
308 successfullyReceive = true;
309 return false;
310 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400311
Amnab8c33bb2023-08-03 14:40:01 -0400312 bob->connectionManager->onConnectionReady(
313 [&receiverConnected](const DeviceId&,
314 const std::string&,
315 std::shared_ptr<ChannelSocket> socket) {
316 if (socket)
317 receiverConnected = true;
318 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400319
Amnab8c33bb2023-08-03 14:40:01 -0400320 alice->connectionManager->connectDevice(bob->id.second,
321 "git://*",
322 [&](std::shared_ptr<ChannelSocket> socket,
323 const DeviceId&) {
324 if (socket) {
325 successfullyConnected = true;
326 }
327 cv.notify_one();
328 });
329 cv.wait_for(lk, 30s);
330 CPPUNIT_ASSERT(successfullyReceive);
331 CPPUNIT_ASSERT(!successfullyConnected);
332 CPPUNIT_ASSERT(!receiverConnected);
333}
Adrien Béraudefe27372023-05-27 18:56:29 -0400334
Amnab8c33bb2023-08-03 14:40:01 -0400335void
336ConnectionManagerTest::testMultipleChannels()
337{
338 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
339 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Adrien Béraudefe27372023-05-27 18:56:29 -0400340
Amnab8c33bb2023-08-03 14:40:01 -0400341 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
342 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Adrien Béraudefe27372023-05-27 18:56:29 -0400343
Amnab8c33bb2023-08-03 14:40:01 -0400344 std::mutex mtx;
345 std::unique_lock<std::mutex> lk {mtx};
346 std::condition_variable cv;
347 bool successfullyConnected = false;
348 bool successfullyConnected2 = false;
349 int receiverConnected = 0;
Adrien Béraudefe27372023-05-27 18:56:29 -0400350
Amnab8c33bb2023-08-03 14:40:01 -0400351 bob->connectionManager->onChannelRequest(
352 [](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
Adrien Béraudefe27372023-05-27 18:56:29 -0400353
Amnab8c33bb2023-08-03 14:40:01 -0400354 bob->connectionManager->onConnectionReady(
355 [&receiverConnected](const DeviceId&,
356 const std::string&,
357 std::shared_ptr<ChannelSocket> socket) {
358 if (socket)
359 receiverConnected += 1;
360 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400361
Amnab8c33bb2023-08-03 14:40:01 -0400362 alice->connectionManager->connectDevice(bob->id.second,
363 "git://*",
364 [&](std::shared_ptr<ChannelSocket> socket,
365 const DeviceId&) {
366 if (socket) {
367 successfullyConnected = true;
368 }
369 cv.notify_one();
370 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400371
Amnab8c33bb2023-08-03 14:40:01 -0400372 alice->connectionManager->connectDevice(bob->id.second,
373 "sip://*",
374 [&](std::shared_ptr<ChannelSocket> socket,
375 const DeviceId&) {
376 if (socket) {
377 successfullyConnected2 = true;
378 }
379 cv.notify_one();
380 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400381
Amnab8c33bb2023-08-03 14:40:01 -0400382 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
383 return successfullyConnected && successfullyConnected2 && receiverConnected == 2;
384 }));
385 CPPUNIT_ASSERT(alice->connectionManager->activeSockets() == 1);
386}
Adrien Béraudefe27372023-05-27 18:56:29 -0400387
Amnab8c33bb2023-08-03 14:40:01 -0400388void
389ConnectionManagerTest::testMultipleChannelsOneDeclined()
390{
391 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
392 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Adrien Béraudefe27372023-05-27 18:56:29 -0400393
Amnab8c33bb2023-08-03 14:40:01 -0400394 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
395 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Adrien Béraudefe27372023-05-27 18:56:29 -0400396
Amnab8c33bb2023-08-03 14:40:01 -0400397 std::mutex mtx;
398 std::unique_lock<std::mutex> lk {mtx};
399 std::condition_variable cv;
400 bool successfullyNotConnected = false;
401 bool successfullyConnected2 = false;
402 int receiverConnected = 0;
Adrien Béraudefe27372023-05-27 18:56:29 -0400403
Amnab8c33bb2023-08-03 14:40:01 -0400404 bob->connectionManager->onChannelRequest(
405 [](const std::shared_ptr<dht::crypto::Certificate>&, const std::string& name) {
406 if (name == "git://*")
407 return false;
408 return true;
409 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400410
Amnab8c33bb2023-08-03 14:40:01 -0400411 bob->connectionManager->onConnectionReady(
412 [&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
413 if (socket)
414 receiverConnected += 1;
415 cv.notify_one();
416 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400417
Amnab8c33bb2023-08-03 14:40:01 -0400418 alice->connectionManager->connectDevice(bob->id.second,
419 "git://*",
420 [&](std::shared_ptr<ChannelSocket> socket,
421 const DeviceId&) {
422 if (!socket)
423 successfullyNotConnected = true;
424 cv.notify_one();
425 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400426
Amnab8c33bb2023-08-03 14:40:01 -0400427 alice->connectionManager->connectDevice(bob->id.second,
428 "sip://*",
429 [&](std::shared_ptr<ChannelSocket> socket,
430 const DeviceId&) {
431 if (socket)
432 successfullyConnected2 = true;
433 cv.notify_one();
434 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400435
Amnab8c33bb2023-08-03 14:40:01 -0400436 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
437 return successfullyNotConnected && successfullyConnected2 && receiverConnected == 1;
438 }));
439 CPPUNIT_ASSERT(alice->connectionManager->activeSockets() == 1);
440}
Morteza Namvar82960b32023-07-04 17:08:22 -0400441
Amnab8c33bb2023-08-03 14:40:01 -0400442void
443ConnectionManagerTest::testMultipleChannelsSameName()
444{
445 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
446 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -0400447
Amnab8c33bb2023-08-03 14:40:01 -0400448 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
449 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400450
Amnab8c33bb2023-08-03 14:40:01 -0400451 std::mutex mtx;
452 std::unique_lock<std::mutex> lk {mtx};
453 std::condition_variable cv;
454 bool successfullyConnected = false;
455 bool successfullyConnected2 = false;
456 int receiverConnected = 0;
Morteza Namvar82960b32023-07-04 17:08:22 -0400457
Amnab8c33bb2023-08-03 14:40:01 -0400458 bob->connectionManager->onChannelRequest(
459 [](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400460
Amnab8c33bb2023-08-03 14:40:01 -0400461 bob->connectionManager->onConnectionReady(
462 [&receiverConnected](const DeviceId&,
463 const std::string&,
464 std::shared_ptr<ChannelSocket> socket) {
465 if (socket)
466 receiverConnected += 1;
467 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400468
Amnab8c33bb2023-08-03 14:40:01 -0400469 alice->connectionManager->connectDevice(bob->id.second,
470 "git://*",
471 [&](std::shared_ptr<ChannelSocket> socket,
472 const DeviceId&) {
473 if (socket) {
474 successfullyConnected = true;
475 }
476 cv.notify_one();
477 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400478
Amnab8c33bb2023-08-03 14:40:01 -0400479 // We can open two sockets with the same name, it will be two different channel
480 alice->connectionManager->connectDevice(bob->id.second,
481 "git://*",
482 [&](std::shared_ptr<ChannelSocket> socket,
483 const DeviceId&) {
484 if (socket) {
485 successfullyConnected2 = true;
486 }
487 cv.notify_one();
488 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400489
Amnab8c33bb2023-08-03 14:40:01 -0400490 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
491 return successfullyConnected && successfullyConnected2 && receiverConnected == 2;
492 }));
493}
Morteza Namvar82960b32023-07-04 17:08:22 -0400494
Amnab8c33bb2023-08-03 14:40:01 -0400495void
496ConnectionManagerTest::testSendReceiveData()
497{
498 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
499 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -0400500
Amnab8c33bb2023-08-03 14:40:01 -0400501 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
502 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400503
Amnab8c33bb2023-08-03 14:40:01 -0400504 std::mutex mtx;
505 std::unique_lock<std::mutex> lk {mtx};
506 std::condition_variable cv;
507 std::atomic_int events(0);
508 bool successfullyConnected = false, successfullyConnected2 = false, successfullyReceive = false,
509 receiverConnected = false;
510 const uint8_t buf_other[] = {0x64, 0x65, 0x66, 0x67};
511 const uint8_t buf_test[] = {0x68, 0x69, 0x70, 0x71};
512 bool dataOk = false, dataOk2 = false;
Morteza Namvar82960b32023-07-04 17:08:22 -0400513
Amnab8c33bb2023-08-03 14:40:01 -0400514 bob->connectionManager->onChannelRequest(
515 [&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
516 const std::string&) {
517 successfullyReceive = true;
518 return true;
519 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400520
Amnab8c33bb2023-08-03 14:40:01 -0400521 bob->connectionManager->onConnectionReady(
522 [&](const DeviceId&, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
523 if (socket && (name == "test" || name == "other")) {
524 receiverConnected = true;
525 std::error_code ec;
526 auto res = socket->waitForData(std::chrono::milliseconds(5000), ec);
527 if (res == 4) {
528 uint8_t buf[4];
529 socket->read(&buf[0], 4, ec);
530 if (name == "test")
531 dataOk = std::equal(std::begin(buf), std::end(buf), std::begin(buf_test));
532 else
533 dataOk2 = std::equal(std::begin(buf), std::end(buf), std::begin(buf_other));
534 events++;
535 cv.notify_one();
536 }
537 }
538 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400539
Amnab8c33bb2023-08-03 14:40:01 -0400540 alice->connectionManager->connectDevice(bob->id.second,
541 "test",
542 [&](std::shared_ptr<ChannelSocket> socket,
543 const DeviceId&) {
544 if (socket) {
545 successfullyConnected = true;
546 std::error_code ec;
547 socket->write(&buf_test[0], 4, ec);
548 }
549 events++;
550 cv.notify_one();
551 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400552
Amnab8c33bb2023-08-03 14:40:01 -0400553 alice->connectionManager->connectDevice(bob->id.second,
554 "other",
555 [&](std::shared_ptr<ChannelSocket> socket,
556 const DeviceId&) {
557 if (socket) {
558 successfullyConnected2 = true;
559 std::error_code ec;
560 socket->write(&buf_other[0], 4, ec);
561 }
562 events++;
563 cv.notify_one();
564 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400565
Amnab8c33bb2023-08-03 14:40:01 -0400566 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
567 return events == 4 && successfullyReceive && successfullyConnected && successfullyConnected2
568 && dataOk && dataOk2;
569 }));
570}
Morteza Namvar82960b32023-07-04 17:08:22 -0400571
Amnab8c33bb2023-08-03 14:40:01 -0400572void
573ConnectionManagerTest::testAcceptsICERequest()
574{
575 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
576 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -0400577
Amnab8c33bb2023-08-03 14:40:01 -0400578 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400579
Amnab8c33bb2023-08-03 14:40:01 -0400580 std::mutex mtx;
581 std::unique_lock<std::mutex> lk {mtx};
582 std::condition_variable cv;
583 bool successfullyConnected = false;
584 bool successfullyReceive = false;
585 bool receiverConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -0400586
Amnab8c33bb2023-08-03 14:40:01 -0400587 bob->connectionManager->onChannelRequest(
588 [](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
589 bob->connectionManager->onICERequest([&](const DeviceId&) {
590 successfullyReceive = true;
591 return true;
592 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400593
Amnab8c33bb2023-08-03 14:40:01 -0400594 bob->connectionManager->onConnectionReady(
595 [&receiverConnected](const DeviceId&,
596 const std::string& name,
597 std::shared_ptr<ChannelSocket> socket) {
598 receiverConnected = socket && (name == "git://*");
599 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400600
Amnab8c33bb2023-08-03 14:40:01 -0400601 alice->connectionManager->connectDevice(bob->id.second,
602 "git://*",
603 [&](std::shared_ptr<ChannelSocket> socket,
604 const DeviceId&) {
605 if (socket) {
606 successfullyConnected = true;
607 }
608 cv.notify_one();
609 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400610
Amnab8c33bb2023-08-03 14:40:01 -0400611 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] {
612 return successfullyReceive && successfullyConnected && receiverConnected;
613 }));
614}
Morteza Namvar82960b32023-07-04 17:08:22 -0400615
Amnab8c33bb2023-08-03 14:40:01 -0400616void
617ConnectionManagerTest::testDeclineICERequest()
618{
619 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
620 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
Morteza Namvar82960b32023-07-04 17:08:22 -0400621
Amnab8c33bb2023-08-03 14:40:01 -0400622 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400623
Amnab8c33bb2023-08-03 14:40:01 -0400624 std::mutex mtx;
625 std::unique_lock<std::mutex> lk {mtx};
626 std::condition_variable cv;
627 bool successfullyConnected = false;
628 bool successfullyReceive = false;
629 bool receiverConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -0400630
Amnab8c33bb2023-08-03 14:40:01 -0400631 bob->connectionManager->onChannelRequest(
632 [](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
633 bob->connectionManager->onICERequest([&](const DeviceId&) {
634 successfullyReceive = true;
635 return false;
636 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400637
Amnab8c33bb2023-08-03 14:40:01 -0400638 bob->connectionManager->onConnectionReady(
639 [&receiverConnected](const DeviceId&,
640 const std::string& name,
641 std::shared_ptr<ChannelSocket> socket) {
642 receiverConnected = socket && (name == "git://*");
643 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400644
Amnab8c33bb2023-08-03 14:40:01 -0400645 alice->connectionManager->connectDevice(bob->id.second,
646 "git://*",
647 [&](std::shared_ptr<ChannelSocket> socket,
648 const DeviceId&) {
649 if (socket) {
650 successfullyConnected = true;
651 }
652 cv.notify_one();
653 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400654
Amnab8c33bb2023-08-03 14:40:01 -0400655 cv.wait_for(lk, 30s);
656 CPPUNIT_ASSERT(successfullyReceive);
657 CPPUNIT_ASSERT(!receiverConnected);
658 CPPUNIT_ASSERT(!successfullyConnected);
659}
Morteza Namvar82960b32023-07-04 17:08:22 -0400660
Amnab8c33bb2023-08-03 14:40:01 -0400661void
662ConnectionManagerTest::testChannelRcvShutdown()
663{
664 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
665 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -0400666
Amnab8c33bb2023-08-03 14:40:01 -0400667 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
668 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400669
Amnab8c33bb2023-08-03 14:40:01 -0400670 std::mutex mtx;
671 std::unique_lock<std::mutex> lk {mtx};
672 std::condition_variable cv;
673 bool successfullyConnected = false;
674 bool shutdownReceived = false;
Morteza Namvar82960b32023-07-04 17:08:22 -0400675
Amnab8c33bb2023-08-03 14:40:01 -0400676 std::shared_ptr<ChannelSocket> bobSock;
Morteza Namvar82960b32023-07-04 17:08:22 -0400677
Amnab8c33bb2023-08-03 14:40:01 -0400678 bob->connectionManager->onChannelRequest(
679 [](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400680
Amnab8c33bb2023-08-03 14:40:01 -0400681 bob->connectionManager->onConnectionReady(
682 [&](const DeviceId& did, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
683 if (socket && name == "git://*" && did != bob->id.second->getLongId()) {
684 bobSock = socket;
685 cv.notify_one();
686 }
687 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400688
Amnab8c33bb2023-08-03 14:40:01 -0400689 alice->connectionManager->connectDevice(bob->id.second,
690 "git://*",
691 [&](std::shared_ptr<ChannelSocket> socket,
692 const DeviceId&) {
693 if (socket) {
694 socket->onShutdown([&] {
695 shutdownReceived = true;
696 cv.notify_one();
697 });
698 successfullyConnected = true;
699 cv.notify_one();
700 }
701 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400702
Amnab8c33bb2023-08-03 14:40:01 -0400703 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return bobSock && successfullyConnected; }));
Morteza Namvar82960b32023-07-04 17:08:22 -0400704
Amnab8c33bb2023-08-03 14:40:01 -0400705 bobSock->shutdown();
Morteza Namvar82960b32023-07-04 17:08:22 -0400706
Amnab8c33bb2023-08-03 14:40:01 -0400707 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return shutdownReceived; }));
708}
Morteza Namvar82960b32023-07-04 17:08:22 -0400709
Amnab8c33bb2023-08-03 14:40:01 -0400710void
711ConnectionManagerTest::testChannelSenderShutdown()
712{
713 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
714 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
Morteza Namvar82960b32023-07-04 17:08:22 -0400715
Amnab8c33bb2023-08-03 14:40:01 -0400716 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
717 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400718
Amnab8c33bb2023-08-03 14:40:01 -0400719 std::mutex mtx;
720 std::unique_lock<std::mutex> lk {mtx};
721 std::condition_variable rcv, scv;
722 bool successfullyConnected = false;
723 bool successfullyReceive = false;
724 bool receiverConnected = false;
725 bool shutdownReceived = false;
Morteza Namvar82960b32023-07-04 17:08:22 -0400726
Amnab8c33bb2023-08-03 14:40:01 -0400727 bob->connectionManager->onChannelRequest(
728 [&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
729 const std::string& name) {
730 successfullyReceive = name == "git://*";
731 return true;
732 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400733
Amnab8c33bb2023-08-03 14:40:01 -0400734 bob->connectionManager->onConnectionReady(
735 [&](const DeviceId&, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
736 if (socket) {
737 socket->onShutdown([&] {
738 shutdownReceived = true;
739 scv.notify_one();
740 });
741 }
742 receiverConnected = socket && (name == "git://*");
743 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400744
Amnab8c33bb2023-08-03 14:40:01 -0400745 alice->connectionManager->connectDevice(bob->id.second,
746 "git://*",
747 [&](std::shared_ptr<ChannelSocket> socket,
748 const DeviceId&) {
749 if (socket) {
750 successfullyConnected = true;
751 rcv.notify_one();
752 socket->shutdown();
753 }
754 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400755
Amnab8c33bb2023-08-03 14:40:01 -0400756 rcv.wait_for(lk, 30s);
757 scv.wait_for(lk, 30s);
758 CPPUNIT_ASSERT(shutdownReceived);
759 CPPUNIT_ASSERT(successfullyReceive);
760 CPPUNIT_ASSERT(successfullyConnected);
761 CPPUNIT_ASSERT(receiverConnected);
762}
Morteza Namvar82960b32023-07-04 17:08:22 -0400763
Amnab8c33bb2023-08-03 14:40:01 -0400764void
765ConnectionManagerTest::testCloseConnectionWith()
766{
767 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
768 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -0400769
Amnab8c33bb2023-08-03 14:40:01 -0400770 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
771 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400772
Amnab8c33bb2023-08-03 14:40:01 -0400773 auto bobUri = bob->id.second->issuer->getId().toString();
774 std::mutex mtx;
775 std::unique_lock<std::mutex> lk {mtx};
776 std::condition_variable rcv, scv;
777 std::atomic_int events(0);
778 bool successfullyConnected = false;
779 bool successfullyReceive = false;
780 bool receiverConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -0400781
Amnab8c33bb2023-08-03 14:40:01 -0400782 bob->connectionManager->onChannelRequest(
783 [&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
784 const std::string& name) {
785 successfullyReceive = name == "git://*";
786 return true;
787 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400788
Amnab8c33bb2023-08-03 14:40:01 -0400789 bob->connectionManager->onConnectionReady([&](const DeviceId&,
790 const std::string& name,
791 std::shared_ptr<dhtnet::ChannelSocket> socket) {
792 if (socket) {
793 socket->onShutdown([&] {
794 events += 1;
795 scv.notify_one();
796 });
797 }
798 receiverConnected = socket && (name == "git://*");
799 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400800
Amnab8c33bb2023-08-03 14:40:01 -0400801 alice->connectionManager->connectDevice(bob->id.second->getId(),
802 "git://*",
803 [&](std::shared_ptr<dhtnet::ChannelSocket> socket,
804 const dht::InfoHash&) {
805 if (socket) {
806 socket->onShutdown([&] {
807 events += 1;
808 scv.notify_one();
809 });
810 successfullyConnected = true;
811 rcv.notify_one();
812 }
813 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400814
Amnab8c33bb2023-08-03 14:40:01 -0400815 rcv.wait_for(lk, 30s);
816 // This should trigger onShutdown
817 alice->connectionManager->closeConnectionsWith(bobUri);
818 CPPUNIT_ASSERT(scv.wait_for(lk, 60s, [&] {
819 return events == 2 && successfullyReceive && successfullyConnected && receiverConnected;
820 }));
821}
Morteza Namvar82960b32023-07-04 17:08:22 -0400822
Amnab8c33bb2023-08-03 14:40:01 -0400823// explain algorithm
824void
825ConnectionManagerTest::testShutdownCallbacks()
826{
827 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
828 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -0400829
Amnab8c33bb2023-08-03 14:40:01 -0400830 auto aliceUri = alice->id.second->issuer->getId().toString();
Morteza Namvar82960b32023-07-04 17:08:22 -0400831
Amnab8c33bb2023-08-03 14:40:01 -0400832 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
833 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400834
Amnab8c33bb2023-08-03 14:40:01 -0400835 std::mutex mtx;
836 std::unique_lock<std::mutex> lk {mtx};
837 std::condition_variable rcv, chan2cv;
838 bool successfullyConnected = false;
839 bool successfullyReceive = false;
840 bool receiverConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -0400841
Amnab8c33bb2023-08-03 14:40:01 -0400842 bob->connectionManager->onChannelRequest(
843 [&successfullyReceive, &chan2cv](const std::shared_ptr<dht::crypto::Certificate>&,
844 const std::string& name) {
845 if (name == "1") {
846 successfullyReceive = true;
847 } else {
848 chan2cv.notify_one();
849 // Do not return directly. Let the connection be closed
850 std::this_thread::sleep_for(10s);
851 }
852 return true;
853 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400854
Amnab8c33bb2023-08-03 14:40:01 -0400855 bob->connectionManager->onConnectionReady([&](const DeviceId&,
856 const std::string& name,
857 std::shared_ptr<dhtnet::ChannelSocket> socket) {
858 receiverConnected = socket && (name == "1");
859 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400860
Amnab8c33bb2023-08-03 14:40:01 -0400861 alice->connectionManager->connectDevice(bob->id.second->getId(),
862 "1",
863 [&](std::shared_ptr<dhtnet::ChannelSocket> socket,
864 const dht::InfoHash&) {
865 if (socket) {
866 successfullyConnected = true;
867 rcv.notify_one();
868 }
869 });
870 // Connect first channel. This will initiate a mx sock
871 CPPUNIT_ASSERT(rcv.wait_for(lk, 30s, [&] {
872 fmt::print("successfullyReceive: {}\n", successfullyReceive);
873 fmt::print("successfullyConnected: {}\n", successfullyConnected);
874 fmt::print("receiverConnected: {}\n", receiverConnected);
875 return successfullyReceive && successfullyConnected && receiverConnected;
876 }));
Morteza Namvar82960b32023-07-04 17:08:22 -0400877
Amnab8c33bb2023-08-03 14:40:01 -0400878 // Connect another channel, but close the connection
879 bool channel2NotConnected = false;
880 alice->connectionManager->connectDevice(bob->id.second->getId(),
881 "2",
882 [&](std::shared_ptr<dhtnet::ChannelSocket> socket,
883 const dht::InfoHash&) {
884 channel2NotConnected = !socket;
885 rcv.notify_one();
886 });
887 chan2cv.wait_for(lk, 30s);
Morteza Namvar82960b32023-07-04 17:08:22 -0400888
Amnab8c33bb2023-08-03 14:40:01 -0400889 // This should trigger onShutdown for second callback
890 bob->connectionManager->closeConnectionsWith(aliceUri);
891 CPPUNIT_ASSERT(rcv.wait_for(lk, 30s, [&] { return channel2NotConnected; }));
892}
Morteza Namvar82960b32023-07-04 17:08:22 -0400893
Amnab8c33bb2023-08-03 14:40:01 -0400894void
895ConnectionManagerTest::testFloodSocket()
896{
897 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
898 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -0400899
Amnab8c33bb2023-08-03 14:40:01 -0400900 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
901 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400902
Amnab8c33bb2023-08-03 14:40:01 -0400903 std::mutex mtx;
904 std::unique_lock<std::mutex> lk {mtx};
905 std::condition_variable cv;
906 bool successfullyConnected = false;
907 bool successfullyReceive = false;
908 bool receiverConnected = false;
909 std::shared_ptr<dhtnet::ChannelSocket> rcvSock1, rcvSock2, rcvSock3, sendSock, sendSock2,
910 sendSock3;
911 bob->connectionManager->onChannelRequest(
912 [&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
913 const std::string& name) {
914 successfullyReceive = name == "1";
915 return true;
916 });
917 bob->connectionManager->onConnectionReady([&](const DeviceId&,
918 const std::string& name,
919 std::shared_ptr<dhtnet::ChannelSocket> socket) {
920 receiverConnected = socket != nullptr;
921 if (name == "1")
922 rcvSock1 = socket;
923 else if (name == "2")
924 rcvSock2 = socket;
925 else if (name == "3")
926 rcvSock3 = socket;
927 });
928 alice->connectionManager->connectDevice(bob->id.second,
929 "1",
930 [&](std::shared_ptr<dhtnet::ChannelSocket> socket,
931 const DeviceId&) {
932 if (socket) {
933 sendSock = socket;
934 successfullyConnected = true;
935 }
936 cv.notify_one();
937 });
938 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] {
939 return successfullyReceive && successfullyConnected && receiverConnected;
940 }));
941 CPPUNIT_ASSERT(receiverConnected);
942 successfullyConnected = false;
943 receiverConnected = false;
944 alice->connectionManager->connectDevice(bob->id.second,
945 "2",
946 [&](std::shared_ptr<dhtnet::ChannelSocket> socket,
947 const DeviceId&) {
948 if (socket) {
949 sendSock2 = socket;
950 successfullyConnected = true;
951 }
952 cv.notify_one();
953 });
954 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyConnected && receiverConnected; }));
955 successfullyConnected = false;
956 receiverConnected = false;
957 alice->connectionManager->connectDevice(bob->id.second,
958 "3",
959 [&](std::shared_ptr<dhtnet::ChannelSocket> socket,
960 const DeviceId&) {
961 if (socket) {
962 sendSock3 = socket;
963 successfullyConnected = true;
964 }
965 cv.notify_one();
966 });
967 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyConnected && receiverConnected; }));
968 std::mutex mtxRcv {};
969 std::string alphabet, shouldRcv, rcv1, rcv2, rcv3;
970 for (int i = 0; i < 100; ++i)
971 alphabet += "QWERTYUIOPASDFGHJKLZXCVBNM";
972 rcvSock1->setOnRecv([&](const uint8_t* buf, size_t len) {
973 rcv1 += std::string(buf, buf + len);
974 return len;
975 });
976 rcvSock2->setOnRecv([&](const uint8_t* buf, size_t len) {
977 rcv2 += std::string(buf, buf + len);
978 return len;
979 });
980 rcvSock3->setOnRecv([&](const uint8_t* buf, size_t len) {
981 rcv3 += std::string(buf, buf + len);
982 return len;
983 });
984 for (uint64_t i = 0; i < alphabet.size(); ++i) {
985 auto send = std::string(8000, alphabet[i]);
986 shouldRcv += send;
987 std::error_code ec;
988 sendSock->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
989 sendSock2->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
990 sendSock3->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
991 CPPUNIT_ASSERT(!ec);
992 }
993 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
994 return shouldRcv == rcv1 && shouldRcv == rcv2 && shouldRcv == rcv3;
995 }));
996}
Morteza Namvar82960b32023-07-04 17:08:22 -0400997
Amnab8c33bb2023-08-03 14:40:01 -0400998void
999ConnectionManagerTest::testDestroyWhileSending()
1000{
1001 // Same as test before, but destroy the accounts while sending.
1002 // This test if a segfault occurs
1003 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1004 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
1005 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
1006 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
1007 std::mutex mtx;
1008 std::unique_lock<std::mutex> lk {mtx};
1009 std::condition_variable cv;
1010 bool successfullyConnected = false;
1011 bool successfullyReceive = false;
1012 bool receiverConnected = false;
1013 std::shared_ptr<ChannelSocket> rcvSock1, rcvSock2, rcvSock3, sendSock, sendSock2, sendSock3;
1014 bob->connectionManager->onChannelRequest(
1015 [&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
1016 const std::string& name) {
1017 successfullyReceive = name == "1";
1018 return true;
1019 });
1020 bob->connectionManager->onConnectionReady(
1021 [&](const DeviceId&, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
1022 receiverConnected = socket != nullptr;
1023 if (name == "1")
1024 rcvSock1 = socket;
1025 else if (name == "2")
1026 rcvSock2 = socket;
1027 else if (name == "3")
1028 rcvSock3 = socket;
1029 });
1030 alice->connectionManager->connectDevice(bob->id.second,
1031 "1",
1032 [&](std::shared_ptr<ChannelSocket> socket,
1033 const DeviceId&) {
1034 if (socket) {
1035 sendSock = socket;
1036 successfullyConnected = true;
1037 }
1038 cv.notify_one();
1039 });
1040 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] {
1041 return successfullyReceive && successfullyConnected && receiverConnected;
1042 }));
1043 successfullyConnected = false;
1044 receiverConnected = false;
1045 alice->connectionManager->connectDevice(bob->id.second,
1046 "2",
1047 [&](std::shared_ptr<ChannelSocket> socket,
1048 const DeviceId&) {
1049 if (socket) {
1050 sendSock2 = socket;
1051 successfullyConnected = true;
1052 }
1053 cv.notify_one();
1054 });
1055 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyConnected && receiverConnected; }));
1056 successfullyConnected = false;
1057 receiverConnected = false;
1058 alice->connectionManager->connectDevice(bob->id.second,
1059 "3",
1060 [&](std::shared_ptr<ChannelSocket> socket,
1061 const DeviceId&) {
1062 if (socket) {
1063 sendSock3 = socket;
1064 successfullyConnected = true;
1065 }
1066 cv.notify_one();
1067 });
1068 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyConnected && receiverConnected; }));
1069 std::mutex mtxRcv {};
1070 std::string alphabet;
1071 for (int i = 0; i < 100; ++i)
1072 alphabet += "QWERTYUIOPASDFGHJKLZXCVBNM";
1073 rcvSock1->setOnRecv([&](const uint8_t*, size_t len) { return len; });
1074 rcvSock2->setOnRecv([&](const uint8_t*, size_t len) { return len; });
1075 rcvSock3->setOnRecv([&](const uint8_t*, size_t len) { return len; });
1076 for (uint64_t i = 0; i < alphabet.size(); ++i) {
1077 auto send = std::string(8000, alphabet[i]);
1078 std::error_code ec;
1079 sendSock->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
1080 sendSock2->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
1081 sendSock3->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
1082 CPPUNIT_ASSERT(!ec);
1083 }
Morteza Namvar82960b32023-07-04 17:08:22 -04001084
Amnab8c33bb2023-08-03 14:40:01 -04001085 // No need to wait, immediately destroy, no segfault must occurs
1086}
Morteza Namvar82960b32023-07-04 17:08:22 -04001087
Amnab8c33bb2023-08-03 14:40:01 -04001088void
1089ConnectionManagerTest::testIsConnecting()
1090{
1091 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1092 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
Morteza Namvar82960b32023-07-04 17:08:22 -04001093
Amnab8c33bb2023-08-03 14:40:01 -04001094 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
1095 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -04001096
Amnab8c33bb2023-08-03 14:40:01 -04001097 std::mutex mtx;
1098 std::unique_lock<std::mutex> lk {mtx};
1099 std::condition_variable cv;
1100 bool successfullyConnected = false, successfullyReceive = false;
Morteza Namvar82960b32023-07-04 17:08:22 -04001101
Amnab8c33bb2023-08-03 14:40:01 -04001102 bob->connectionManager->onChannelRequest(
1103 [&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) {
1104 successfullyReceive = true;
1105 cv.notify_one();
1106 std::this_thread::sleep_for(2s);
1107 return true;
1108 });
Morteza Namvar82960b32023-07-04 17:08:22 -04001109
Amnab8c33bb2023-08-03 14:40:01 -04001110 CPPUNIT_ASSERT(!alice->connectionManager->isConnecting(bob->id.second->getLongId(), "sip"));
Morteza Namvar82960b32023-07-04 17:08:22 -04001111
Amnab8c33bb2023-08-03 14:40:01 -04001112 alice->connectionManager->connectDevice(bob->id.second,
1113 "sip",
1114 [&](std::shared_ptr<ChannelSocket> socket,
1115 const DeviceId&) {
1116 if (socket) {
1117 successfullyConnected = true;
1118 }
1119 cv.notify_one();
1120 });
1121 // connectDevice is full async, so isConnecting will be true after a few ms.
1122 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] { return successfullyReceive; }));
1123 CPPUNIT_ASSERT(alice->connectionManager->isConnecting(bob->id.second->getLongId(), "sip"));
1124 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] { return successfullyConnected; }));
1125 std::this_thread::sleep_for(
1126 std::chrono::milliseconds(100)); // Just to wait for the callback to finish
1127 CPPUNIT_ASSERT(!alice->connectionManager->isConnecting(bob->id.second->getLongId(), "sip"));
1128}
Morteza Namvar82960b32023-07-04 17:08:22 -04001129
Amnab8c33bb2023-08-03 14:40:01 -04001130void
1131ConnectionManagerTest::testCanSendBeacon()
1132{
1133 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1134 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
Morteza Namvar82960b32023-07-04 17:08:22 -04001135
Amnab8c33bb2023-08-03 14:40:01 -04001136 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
1137 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -04001138
Amnab8c33bb2023-08-03 14:40:01 -04001139 std::mutex mtx;
1140 std::unique_lock<std::mutex> lk {mtx};
1141 std::condition_variable cv;
1142 bool successfullyConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -04001143
Amnab8c33bb2023-08-03 14:40:01 -04001144 std::shared_ptr<MultiplexedSocket> aliceSocket, bobSocket;
1145 bob->connectionManager->onChannelRequest(
1146 [&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
1147 bob->connectionManager->onConnectionReady(
1148 [&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
1149 if (socket && socket->name() == "sip")
1150 bobSocket = socket->underlyingSocket();
1151 cv.notify_one();
1152 });
Morteza Namvar82960b32023-07-04 17:08:22 -04001153
Amnab8c33bb2023-08-03 14:40:01 -04001154 alice->connectionManager->connectDevice(bob->id.second,
1155 "sip",
1156 [&](std::shared_ptr<ChannelSocket> socket,
1157 const DeviceId&) {
1158 if (socket) {
1159 aliceSocket = socket->underlyingSocket();
1160 successfullyConnected = true;
1161 }
1162 cv.notify_one();
1163 });
1164 // connectDevice is full async, so isConnecting will be true after a few ms.
1165 CPPUNIT_ASSERT(
1166 cv.wait_for(lk, 30s, [&] { return aliceSocket && bobSocket && successfullyConnected; }));
1167 CPPUNIT_ASSERT(aliceSocket->canSendBeacon());
Morteza Namvar82960b32023-07-04 17:08:22 -04001168
Amnab8c33bb2023-08-03 14:40:01 -04001169 // Because onConnectionReady is true before version is sent, we can wait a bit
1170 // before canSendBeacon is true.
1171 auto start = std::chrono::steady_clock::now();
1172 auto aliceCanSendBeacon = false;
1173 auto bobCanSendBeacon = false;
1174 do {
1175 aliceCanSendBeacon = aliceSocket->canSendBeacon();
1176 bobCanSendBeacon = bobSocket->canSendBeacon();
1177 if (!bobCanSendBeacon || !aliceCanSendBeacon)
1178 std::this_thread::sleep_for(1s);
1179 } while ((not bobCanSendBeacon or not aliceCanSendBeacon)
1180 and std::chrono::steady_clock::now() - start < 5s);
Morteza Namvar82960b32023-07-04 17:08:22 -04001181
Amnab8c33bb2023-08-03 14:40:01 -04001182 CPPUNIT_ASSERT(bobCanSendBeacon && aliceCanSendBeacon);
1183}
Morteza Namvar82960b32023-07-04 17:08:22 -04001184
Amnab8c33bb2023-08-03 14:40:01 -04001185void
1186ConnectionManagerTest::testCannotSendBeacon()
1187{
1188 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1189 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
Morteza Namvar82960b32023-07-04 17:08:22 -04001190
Amnab8c33bb2023-08-03 14:40:01 -04001191 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
1192 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -04001193
Amnab8c33bb2023-08-03 14:40:01 -04001194 std::mutex mtx;
1195 std::unique_lock<std::mutex> lk {mtx};
1196 std::condition_variable cv;
1197 bool successfullyConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -04001198
Amnab8c33bb2023-08-03 14:40:01 -04001199 std::shared_ptr<MultiplexedSocket> aliceSocket, bobSocket;
1200 bob->connectionManager->onChannelRequest(
1201 [&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
1202 bob->connectionManager->onConnectionReady(
1203 [&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
1204 if (socket && socket->name() == "sip")
1205 bobSocket = socket->underlyingSocket();
1206 cv.notify_one();
1207 });
Morteza Namvar82960b32023-07-04 17:08:22 -04001208
Amnab8c33bb2023-08-03 14:40:01 -04001209 alice->connectionManager->connectDevice(bob->id.second,
1210 "sip",
1211 [&](std::shared_ptr<ChannelSocket> socket,
1212 const DeviceId&) {
1213 if (socket) {
1214 aliceSocket = socket->underlyingSocket();
1215 successfullyConnected = true;
1216 }
1217 cv.notify_one();
1218 });
1219 // connectDevice is full async, so isConnecting will be true after a few ms.
1220 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return aliceSocket && bobSocket; }));
Morteza Namvar82960b32023-07-04 17:08:22 -04001221
Amnab8c33bb2023-08-03 14:40:01 -04001222 int version = 1412;
1223 bobSocket->setOnVersionCb([&](auto v) {
1224 version = v;
1225 cv.notify_one();
1226 });
1227 aliceSocket->setVersion(0);
1228 aliceSocket->sendVersion();
1229 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return version == 0; }));
1230 CPPUNIT_ASSERT(!bobSocket->canSendBeacon());
1231}
Morteza Namvar82960b32023-07-04 17:08:22 -04001232
Amnab8c33bb2023-08-03 14:40:01 -04001233void
1234ConnectionManagerTest::testConnectivityChangeTriggerBeacon()
1235{
1236 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1237 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
Morteza Namvar82960b32023-07-04 17:08:22 -04001238
Amnab8c33bb2023-08-03 14:40:01 -04001239 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
1240 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -04001241
Amnab8c33bb2023-08-03 14:40:01 -04001242 std::mutex mtx;
1243 std::unique_lock<std::mutex> lk {mtx};
1244 std::condition_variable cv;
1245 bool successfullyConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -04001246
Amnab8c33bb2023-08-03 14:40:01 -04001247 std::shared_ptr<MultiplexedSocket> aliceSocket, bobSocket;
1248 bob->connectionManager->onChannelRequest(
1249 [&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
1250 bob->connectionManager->onConnectionReady(
1251 [&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
1252 if (socket && socket->name() == "sip")
1253 bobSocket = socket->underlyingSocket();
1254 cv.notify_one();
1255 });
Morteza Namvar82960b32023-07-04 17:08:22 -04001256
Amnab8c33bb2023-08-03 14:40:01 -04001257 alice->connectionManager->connectDevice(bob->id.second,
1258 "sip",
1259 [&](std::shared_ptr<ChannelSocket> socket,
1260 const DeviceId&) {
1261 if (socket) {
1262 aliceSocket = socket->underlyingSocket();
1263 successfullyConnected = true;
1264 }
1265 cv.notify_one();
1266 });
1267 // connectDevice is full async, so isConnecting will be true after a few ms.
1268 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return aliceSocket && bobSocket; }));
Morteza Namvar82960b32023-07-04 17:08:22 -04001269
Amnab8c33bb2023-08-03 14:40:01 -04001270 bool hasRequest = false;
1271 bobSocket->setOnBeaconCb([&](auto p) {
1272 if (p)
1273 hasRequest = true;
1274 cv.notify_one();
1275 });
1276 alice->connectionManager->connectivityChanged();
1277 CPPUNIT_ASSERT(cv.wait_for(lk, 10s, [&] { return hasRequest; }));
1278}
Morteza Namvar82960b32023-07-04 17:08:22 -04001279
Amnab8c33bb2023-08-03 14:40:01 -04001280void
1281ConnectionManagerTest::testOnNoBeaconTriggersShutdown()
1282{
1283 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1284 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
Morteza Namvar82960b32023-07-04 17:08:22 -04001285
Amnab8c33bb2023-08-03 14:40:01 -04001286 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
1287 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -04001288
Amnab8c33bb2023-08-03 14:40:01 -04001289 std::mutex mtx;
1290 std::unique_lock<std::mutex> lk {mtx};
1291 std::condition_variable cv;
1292 bool successfullyConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -04001293
Amnab8c33bb2023-08-03 14:40:01 -04001294 std::shared_ptr<MultiplexedSocket> aliceSocket, bobSocket;
1295 bob->connectionManager->onChannelRequest(
1296 [&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
1297 bob->connectionManager->onConnectionReady(
1298 [&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
1299 if (socket && socket->name() == "sip")
1300 bobSocket = socket->underlyingSocket();
1301 cv.notify_one();
1302 });
Morteza Namvar82960b32023-07-04 17:08:22 -04001303
Amnab8c33bb2023-08-03 14:40:01 -04001304 alice->connectionManager->connectDevice(bob->id.second,
1305 "sip",
1306 [&](std::shared_ptr<ChannelSocket> socket,
1307 const DeviceId&) {
1308 if (socket) {
1309 aliceSocket = socket->underlyingSocket();
1310 successfullyConnected = true;
1311 }
1312 cv.notify_one();
1313 });
1314 // connectDevice is full async, so isConnecting will be true after a few ms.
1315 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return aliceSocket && bobSocket; }));
Morteza Namvar82960b32023-07-04 17:08:22 -04001316
Amnab8c33bb2023-08-03 14:40:01 -04001317 bool isClosed = false;
1318 aliceSocket->onShutdown([&] {
1319 isClosed = true;
1320 cv.notify_one();
1321 });
1322 bobSocket->answerToBeacon(false);
1323 alice->connectionManager->connectivityChanged();
1324 CPPUNIT_ASSERT(cv.wait_for(lk, 10s, [&] { return isClosed; }));
1325}
Morteza Namvar82960b32023-07-04 17:08:22 -04001326
Amnab8c33bb2023-08-03 14:40:01 -04001327void
1328ConnectionManagerTest::testShutdownWhileNegotiating()
1329{
1330 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1331 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -04001332
Amnab8c33bb2023-08-03 14:40:01 -04001333 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -04001334
Amnab8c33bb2023-08-03 14:40:01 -04001335 std::mutex mtx;
1336 std::unique_lock<std::mutex> lk {mtx};
1337 std::condition_variable cv;
1338 bool successfullyReceive = false;
1339 bool notConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -04001340
Amnab8c33bb2023-08-03 14:40:01 -04001341 bob->connectionManager->onICERequest([&](const DeviceId&) {
1342 successfullyReceive = true;
1343 cv.notify_one();
1344 return true;
1345 });
Morteza Namvar82960b32023-07-04 17:08:22 -04001346
Amnab8c33bb2023-08-03 14:40:01 -04001347 alice->connectionManager->connectDevice(bob->id.second,
1348 "git://*",
1349 [&](std::shared_ptr<ChannelSocket> socket,
1350 const DeviceId&) {
1351 notConnected = !socket;
1352 cv.notify_one();
1353 });
Morteza Namvar82960b32023-07-04 17:08:22 -04001354
Amnab8c33bb2023-08-03 14:40:01 -04001355 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyReceive; }));
1356 // Manager::instance().setAccountActive(alice->id.second, false, true);
Morteza Namvar82960b32023-07-04 17:08:22 -04001357
Amnab8c33bb2023-08-03 14:40:01 -04001358 // Just move destruction on another thread.
1359 // dht::threadpool::io().run([conMgr =std::move(alice->connectionManager)] {});
1360 alice->connectionManager.reset();
Morteza Namvar82960b32023-07-04 17:08:22 -04001361
Amnab8c33bb2023-08-03 14:40:01 -04001362 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return notConnected; }));
1363}
1364void
1365ConnectionManagerTest::testGetChannelList()
1366{
1367 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1368 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -04001369
Amnab8c33bb2023-08-03 14:40:01 -04001370 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
1371 std::mutex mtx;
1372 std::condition_variable cv;
1373 std::unique_lock<std::mutex> lk {mtx};
1374 bool successfullyConnected = false;
1375 int receiverConnected = 0;
1376 bob->connectionManager->onChannelRequest(
1377 [](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
1378 bob->connectionManager->onConnectionReady(
1379 [&receiverConnected,
1380 &cv](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
1381 if (socket)
1382 receiverConnected += 1;
Morteza Namvar82960b32023-07-04 17:08:22 -04001383
Amnab8c33bb2023-08-03 14:40:01 -04001384 cv.notify_one();
1385 });
1386 std::string channelId;
1387 alice->connectionManager->connectDevice(bob->id.second,
1388 "git://*",
1389 [&](std::shared_ptr<ChannelSocket> socket,
1390 const DeviceId&) {
1391 if (socket) {
1392 channelId = std::to_string(socket->channel());
1393 successfullyConnected = true;
1394 }
Morteza Namvar82960b32023-07-04 17:08:22 -04001395
Amnab8c33bb2023-08-03 14:40:01 -04001396 cv.notify_one();
1397 });
1398 CPPUNIT_ASSERT(
1399 cv.wait_for(lk, 60s, [&] { return successfullyConnected && receiverConnected == 1; }));
1400 std::vector<std::map<std::string, std::string>> expectedList = {
1401 {{"channel", channelId}, {"channelName", "git://*"}}};
1402 auto connectionList = alice->connectionManager->getConnectionList();
1403 CPPUNIT_ASSERT(!connectionList.empty());
1404 const auto& connectionInfo = connectionList[0];
1405 auto it = connectionInfo.find("id");
1406 CPPUNIT_ASSERT(it != connectionInfo.end());
1407 std::string connectionId = it->second;
1408 auto actualList = alice->connectionManager->getChannelList(connectionId);
1409 CPPUNIT_ASSERT(expectedList.size() == actualList.size());
1410 CPPUNIT_ASSERT(std::equal(expectedList.begin(), expectedList.end(), actualList.begin()));
1411 for (const auto& expectedMap : expectedList) {
1412 auto it = std::find_if(actualList.begin(),
1413 actualList.end(),
1414 [&](const std::map<std::string, std::string>& actualMap) {
1415 return expectedMap.size() == actualMap.size()
1416 && std::equal(expectedMap.begin(),
1417 expectedMap.end(),
1418 actualMap.begin());
1419 });
1420 CPPUNIT_ASSERT(it != actualList.end());
1421 }
1422}
Adrien Béraudefe27372023-05-27 18:56:29 -04001423
1424} // namespace test
Sébastien Blin464bdff2023-07-19 08:02:53 -04001425} // namespace dhtnet
Adrien Béraudefe27372023-05-27 18:56:29 -04001426
Adrien Béraud1ae60aa2023-07-07 09:55:09 -04001427JAMI_TEST_RUNNER(dhtnet::test::ConnectionManagerTest::name())