blob: 60e6197a21dbe2d01bf59ef84937d621601b0631 [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 */
Morteza Namvar82960b32023-07-04 17:08:22 -040017#include <iostream>
18#include <filesystem>
19
20#include <opendht/log.h>
21
Adrien Béraudefe27372023-05-27 18:56:29 -040022#include <cppunit/TestAssert.h>
23#include <cppunit/TestFixture.h>
24#include <cppunit/extensions/HelperMacros.h>
25
Morteza Namvar82960b32023-07-04 17:08:22 -040026#include <asio/executor_work_guard.hpp>
27#include <asio/io_context.hpp>
28
Adrien Béraudefe27372023-05-27 18:56:29 -040029#include <condition_variable>
30
31#include "connectionmanager.h"
32#include "multiplexed_socket.h"
33#include "test_runner.h"
Morteza Namvar82960b32023-07-04 17:08:22 -040034#include "certstore.h"
Adrien Béraudefe27372023-05-27 18:56:29 -040035
36using namespace std::literals::chrono_literals;
37
Adrien Béraud1ae60aa2023-07-07 09:55:09 -040038namespace dhtnet {
Adrien Béraudefe27372023-05-27 18:56:29 -040039namespace test {
40
Amnab8c33bb2023-08-03 14:40:01 -040041struct ConnectionHandler
42{
Morteza Namvar82960b32023-07-04 17:08:22 -040043 dht::crypto::Identity id;
44 std::shared_ptr<Logger> logger;
45 std::shared_ptr<tls::CertificateStore> certStore;
46 std::shared_ptr<dht::DhtRunner> dht;
47 std::shared_ptr<ConnectionManager> connectionManager;
48 std::shared_ptr<asio::io_context> ioContext;
Amnab8c33bb2023-08-03 14:40:01 -040049 std::shared_ptr<std::thread> ioContextRunner;
Morteza Namvar82960b32023-07-04 17:08:22 -040050};
51
Adrien Béraudefe27372023-05-27 18:56:29 -040052class ConnectionManagerTest : public CppUnit::TestFixture
53{
54public:
55 ConnectionManagerTest() {}
Amnab8c33bb2023-08-03 14:40:01 -040056 ~ConnectionManagerTest() {}
Adrien Béraudefe27372023-05-27 18:56:29 -040057 static std::string name() { return "ConnectionManager"; }
58 void setUp();
59 void tearDown();
60
Morteza Namvar82960b32023-07-04 17:08:22 -040061 std::unique_ptr<ConnectionHandler> alice;
62 std::unique_ptr<ConnectionHandler> bob;
Adrien Béraudefe27372023-05-27 18:56:29 -040063
Amnab8c33bb2023-08-03 14:40:01 -040064 // Create a lock to be used in the test units
Morteza Namvar82960b32023-07-04 17:08:22 -040065 std::mutex mtx;
66 std::shared_ptr<asio::io_context> ioContext;
Amnab8c33bb2023-08-03 14:40:01 -040067 std::shared_ptr<std::thread> ioContextRunner;
68 // std::thread ioContextRunner;
Morteza Namvar82960b32023-07-04 17:08:22 -040069 std::shared_ptr<Logger> logger;
70 std::unique_ptr<IceTransportFactory> factory;
Morteza Namvar82960b32023-07-04 17:08:22 -040071
Amnab8c33bb2023-08-03 14:40:01 -040072private:
Morteza Namvar82960b32023-07-04 17:08:22 -040073 std::unique_ptr<ConnectionHandler> setupHandler(const std::string& name);
74
Amnab8c33bb2023-08-03 14:40:01 -040075 void testConnectDevice();
76 void testAcceptConnection();
77 void testMultipleChannels();
78 void testMultipleChannelsOneDeclined();
79 void testMultipleChannelsSameName();
80 void testDeclineConnection();
81 void testSendReceiveData();
82 void testAcceptsICERequest();
83 void testDeclineICERequest();
84 void testChannelRcvShutdown();
85 void testChannelSenderShutdown();
86 void testCloseConnectionWith();
87 void testShutdownCallbacks();
88 void testFloodSocket();
89 void testDestroyWhileSending();
90 void testIsConnecting();
91 void testCanSendBeacon();
92 void testCannotSendBeacon();
93 void testConnectivityChangeTriggerBeacon();
94 void testOnNoBeaconTriggersShutdown();
95 void testShutdownWhileNegotiating();
96 void testGetChannelList();
Adrien Béraudefe27372023-05-27 18:56:29 -040097 CPPUNIT_TEST_SUITE(ConnectionManagerTest);
Amnab8c33bb2023-08-03 14:40:01 -040098 CPPUNIT_TEST(testDeclineICERequest);
99 CPPUNIT_TEST(testConnectDevice);
100 CPPUNIT_TEST(testIsConnecting);
101 CPPUNIT_TEST(testAcceptConnection);
102 CPPUNIT_TEST(testDeclineConnection);
103 CPPUNIT_TEST(testMultipleChannels);
104 CPPUNIT_TEST(testMultipleChannelsOneDeclined);
105 CPPUNIT_TEST(testMultipleChannelsSameName);
106 CPPUNIT_TEST(testSendReceiveData);
107 CPPUNIT_TEST(testAcceptsICERequest);
108 CPPUNIT_TEST(testChannelRcvShutdown);
109 CPPUNIT_TEST(testChannelSenderShutdown);
110 CPPUNIT_TEST(testCloseConnectionWith);
111 CPPUNIT_TEST(testShutdownCallbacks);
112 CPPUNIT_TEST(testFloodSocket);
113 CPPUNIT_TEST(testDestroyWhileSending);
114 CPPUNIT_TEST(testCanSendBeacon);
115 CPPUNIT_TEST(testCannotSendBeacon);
116 CPPUNIT_TEST(testConnectivityChangeTriggerBeacon);
117 CPPUNIT_TEST(testOnNoBeaconTriggersShutdown);
118 CPPUNIT_TEST(testShutdownWhileNegotiating);
119 CPPUNIT_TEST(testGetChannelList);
Adrien Béraudefe27372023-05-27 18:56:29 -0400120 CPPUNIT_TEST_SUITE_END();
121};
122
123CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ConnectionManagerTest, ConnectionManagerTest::name());
124
Morteza Namvar82960b32023-07-04 17:08:22 -0400125std::unique_ptr<ConnectionHandler>
Amnab8c33bb2023-08-03 14:40:01 -0400126ConnectionManagerTest::setupHandler(const std::string& name)
127{
Morteza Namvar82960b32023-07-04 17:08:22 -0400128 auto h = std::make_unique<ConnectionHandler>();
Adrien Béraudc631a832023-07-26 22:19:00 -0400129 auto ca = dht::crypto::generateIdentity("ca");
130 h->id = dht::crypto::generateIdentity(name, ca);
Morteza Namvar82960b32023-07-04 17:08:22 -0400131 h->logger = logger;
132 h->certStore = std::make_shared<tls::CertificateStore>(name, h->logger);
133 h->ioContext = std::make_shared<asio::io_context>();
Amnab8c33bb2023-08-03 14:40:01 -0400134 h->ioContext = ioContext;
135
136 h->ioContextRunner = ioContextRunner;
Morteza Namvar82960b32023-07-04 17:08:22 -0400137
138 dht::DhtRunner::Config dhtConfig;
139 dhtConfig.dht_config.id = h->id;
140 dhtConfig.threaded = true;
141
142 dht::DhtRunner::Context dhtContext;
Amnab8c33bb2023-08-03 14:40:01 -0400143 dhtContext.certificateStore = [c = h->certStore](const dht::InfoHash& pk_id) {
Morteza Namvar82960b32023-07-04 17:08:22 -0400144 std::vector<std::shared_ptr<dht::crypto::Certificate>> ret;
145 if (auto cert = c->getCertificate(pk_id.toString()))
146 ret.emplace_back(std::move(cert));
147 return ret;
148 };
Amnab8c33bb2023-08-03 14:40:01 -0400149 // dhtContext.logger = h->logger;
Morteza Namvar82960b32023-07-04 17:08:22 -0400150
151 h->dht = std::make_shared<dht::DhtRunner>();
152 h->dht->run(dhtConfig, std::move(dhtContext));
Adrien Béraude8541392023-07-27 15:48:04 -0400153 h->dht->bootstrap("bootstrap.jami.net");
Morteza Namvar82960b32023-07-04 17:08:22 -0400154
155 auto config = std::make_shared<ConnectionManager::Config>();
156 config->dht = h->dht;
157 config->id = h->id;
158 config->ioContext = h->ioContext;
159 config->factory = factory.get();
160 config->logger = logger;
161 config->certStore = h->certStore.get();
162
163 std::filesystem::path currentPath = std::filesystem::current_path();
164 std::filesystem::path tempDirPath = currentPath / "temp";
165
166 config->cachePath = tempDirPath.string();
167
168 h->connectionManager = std::make_shared<ConnectionManager>(config);
Amnab8c33bb2023-08-03 14:40:01 -0400169 h->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400170 return h;
171}
172
Adrien Béraudefe27372023-05-27 18:56:29 -0400173void
174ConnectionManagerTest::setUp()
175{
Morteza Namvar82960b32023-07-04 17:08:22 -0400176 logger = dht::log::getStdLogger();
Adrien Béraudc631a832023-07-26 22:19:00 -0400177
178 logger->debug("Using PJSIP version {} for {}", pj_get_version(), PJ_OS_NAME);
179 logger->debug("Using GnuTLS version {}", gnutls_check_version(nullptr));
180 logger->debug("Using OpenDHT version {}", dht::version());
181
Morteza Namvar82960b32023-07-04 17:08:22 -0400182 ioContext = std::make_shared<asio::io_context>();
Amnab8c33bb2023-08-03 14:40:01 -0400183 ioContextRunner = std::make_shared<std::thread>([context = ioContext]() {
Morteza Namvar82960b32023-07-04 17:08:22 -0400184 try {
185 auto work = asio::make_work_guard(*context);
186 context->run();
187 } catch (const std::exception& ex) {
Amnab8c33bb2023-08-03 14:40:01 -0400188 // print the error;
Morteza Namvar82960b32023-07-04 17:08:22 -0400189 }
190 });
Amnab8c33bb2023-08-03 14:40:01 -0400191 // ioContextRunner = std::thread([context = ioContext]() {
192 // try {
193 // auto work = asio::make_work_guard(*context);
194 // context->run();
195 // } catch (const std::exception& ex) {
196 // // print the error;
197 // }
198 // });
Adrien Béraud89933c12023-07-26 14:53:30 -0400199 factory = std::make_unique<IceTransportFactory>(logger);
Morteza Namvar82960b32023-07-04 17:08:22 -0400200 alice = setupHandler("alice");
201 bob = setupHandler("bob");
Adrien Béraudefe27372023-05-27 18:56:29 -0400202}
203
Morteza Namvar82960b32023-07-04 17:08:22 -0400204
Adrien Béraudefe27372023-05-27 18:56:29 -0400205void
206ConnectionManagerTest::tearDown()
207{
Amnab8c33bb2023-08-03 14:40:01 -0400208 // wait_for_removal_of({aliceId, bobId});
209 // Stop the io_context and join the ioContextRunner thread
Morteza Namvar82960b32023-07-04 17:08:22 -0400210 ioContext->stop();
Amnab8c33bb2023-08-03 14:40:01 -0400211
212 if (ioContextRunner && ioContextRunner->joinable()) {
213 ioContextRunner->join();
214 }
Adrien Béraudefe27372023-05-27 18:56:29 -0400215}
Adrien Béraudefe27372023-05-27 18:56:29 -0400216void
Morteza Namvar82960b32023-07-04 17:08:22 -0400217ConnectionManagerTest::testConnectDevice()
Adrien Béraudefe27372023-05-27 18:56:29 -0400218{
Morteza Namvar82960b32023-07-04 17:08:22 -0400219 std::unique_lock<std::mutex> lock {mtx};
220 std::condition_variable bobConVar;
221 bool isBobRecvChanlReq = false;
Adrien Béraudefe27372023-05-27 18:56:29 -0400222
Morteza Namvar82960b32023-07-04 17:08:22 -0400223 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
224 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Adrien Béraudefe27372023-05-27 18:56:29 -0400225
Amnab8c33bb2023-08-03 14:40:01 -0400226 bob->connectionManager->onChannelRequest(
227 [&isBobRecvChanlReq, &bobConVar](const std::shared_ptr<dht::crypto::Certificate>&,
228 const std::string& name) {
229 isBobRecvChanlReq = name == "dumyName";
230 bobConVar.notify_one();
231 return true;
232 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400233
Morteza Namvar82960b32023-07-04 17:08:22 -0400234 std::condition_variable alicConVar;
235 bool isAlicConnected = false;
236 auto conctDevicCalBack = [&](std::shared_ptr<ChannelSocket> socket, const DeviceId&) {
Amnab8c33bb2023-08-03 14:40:01 -0400237 if (socket) {
238 isAlicConnected = true;
239 }
Morteza Namvar82960b32023-07-04 17:08:22 -0400240 alicConVar.notify_one();
241 };
Adrien Béraudefe27372023-05-27 18:56:29 -0400242
Morteza Namvar82960b32023-07-04 17:08:22 -0400243 alice->connectionManager->connectDevice(bob->id.second, "dumyName", conctDevicCalBack);
Adrien Béraudefe27372023-05-27 18:56:29 -0400244
Amnab8c33bb2023-08-03 14:40:01 -0400245 // Step 4: to check if Alice connected to Bob?
Morteza Namvar82960b32023-07-04 17:08:22 -0400246 CPPUNIT_ASSERT(alicConVar.wait_for(lock, 60s, [&] { return isAlicConnected; }));
Adrien Béraudefe27372023-05-27 18:56:29 -0400247}
248
Amnab8c33bb2023-08-03 14:40:01 -0400249void
250ConnectionManagerTest::testAcceptConnection()
251{
252 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
253 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Adrien Béraudefe27372023-05-27 18:56:29 -0400254
Amnab8c33bb2023-08-03 14:40:01 -0400255 std::mutex mtx;
256 std::unique_lock<std::mutex> lk {mtx};
257 std::condition_variable cv;
258 bool successfullyConnected = false;
259 bool successfullyReceive = false;
260 bool receiverConnected = false;
Adrien Béraudefe27372023-05-27 18:56:29 -0400261
Amnab8c33bb2023-08-03 14:40:01 -0400262 bob->connectionManager->onChannelRequest(
263 [&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
264 const std::string& name) {
265 successfullyReceive = name == "git://*";
266 return true;
267 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400268
Amnab8c33bb2023-08-03 14:40:01 -0400269 bob->connectionManager->onConnectionReady(
270 [&receiverConnected](const DeviceId&,
271 const std::string& name,
272 std::shared_ptr<ChannelSocket> socket) {
273 receiverConnected = socket && (name == "git://*");
274 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400275
Amnab8c33bb2023-08-03 14:40:01 -0400276 alice->connectionManager->connectDevice(bob->id.second,
277 "git://*",
278 [&](std::shared_ptr<ChannelSocket> socket,
279 const DeviceId&) {
280 if (socket) {
281 successfullyConnected = true;
282 }
283 cv.notify_one();
284 });
285 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
286 return successfullyReceive && successfullyConnected && receiverConnected;
287 }));
288}
Adrien Béraudefe27372023-05-27 18:56:29 -0400289
Amnab8c33bb2023-08-03 14:40:01 -0400290void
291ConnectionManagerTest::testDeclineConnection()
292{
293 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
294 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Adrien Béraudefe27372023-05-27 18:56:29 -0400295
Amnab8c33bb2023-08-03 14:40:01 -0400296 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
297 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Adrien Béraudefe27372023-05-27 18:56:29 -0400298
Amnab8c33bb2023-08-03 14:40:01 -0400299 std::mutex mtx;
300 std::unique_lock<std::mutex> lk {mtx};
301 std::condition_variable cv;
302 bool successfullyConnected = false;
303 bool successfullyReceive = false;
304 bool receiverConnected = false;
Adrien Béraudefe27372023-05-27 18:56:29 -0400305
Amnab8c33bb2023-08-03 14:40:01 -0400306 bob->connectionManager->onChannelRequest(
307 [&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
308 const std::string&) {
309 successfullyReceive = true;
310 return false;
311 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400312
Amnab8c33bb2023-08-03 14:40:01 -0400313 bob->connectionManager->onConnectionReady(
314 [&receiverConnected](const DeviceId&,
315 const std::string&,
316 std::shared_ptr<ChannelSocket> socket) {
317 if (socket)
318 receiverConnected = true;
319 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400320
Amnab8c33bb2023-08-03 14:40:01 -0400321 alice->connectionManager->connectDevice(bob->id.second,
322 "git://*",
323 [&](std::shared_ptr<ChannelSocket> socket,
324 const DeviceId&) {
325 if (socket) {
326 successfullyConnected = true;
327 }
328 cv.notify_one();
329 });
330 cv.wait_for(lk, 30s);
331 CPPUNIT_ASSERT(successfullyReceive);
332 CPPUNIT_ASSERT(!successfullyConnected);
333 CPPUNIT_ASSERT(!receiverConnected);
334}
Adrien Béraudefe27372023-05-27 18:56:29 -0400335
Amnab8c33bb2023-08-03 14:40:01 -0400336void
337ConnectionManagerTest::testMultipleChannels()
338{
339 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
340 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Adrien Béraudefe27372023-05-27 18:56:29 -0400341
Amnab8c33bb2023-08-03 14:40:01 -0400342 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
343 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Adrien Béraudefe27372023-05-27 18:56:29 -0400344
Amnab8c33bb2023-08-03 14:40:01 -0400345 std::mutex mtx;
346 std::unique_lock<std::mutex> lk {mtx};
347 std::condition_variable cv;
348 bool successfullyConnected = false;
349 bool successfullyConnected2 = false;
350 int receiverConnected = 0;
Adrien Béraudefe27372023-05-27 18:56:29 -0400351
Amnab8c33bb2023-08-03 14:40:01 -0400352 bob->connectionManager->onChannelRequest(
353 [](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
Adrien Béraudefe27372023-05-27 18:56:29 -0400354
Amnab8c33bb2023-08-03 14:40:01 -0400355 bob->connectionManager->onConnectionReady(
356 [&receiverConnected](const DeviceId&,
357 const std::string&,
358 std::shared_ptr<ChannelSocket> socket) {
359 if (socket)
360 receiverConnected += 1;
361 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400362
Amnab8c33bb2023-08-03 14:40:01 -0400363 alice->connectionManager->connectDevice(bob->id.second,
364 "git://*",
365 [&](std::shared_ptr<ChannelSocket> socket,
366 const DeviceId&) {
367 if (socket) {
368 successfullyConnected = true;
369 }
370 cv.notify_one();
371 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400372
Amnab8c33bb2023-08-03 14:40:01 -0400373 alice->connectionManager->connectDevice(bob->id.second,
374 "sip://*",
375 [&](std::shared_ptr<ChannelSocket> socket,
376 const DeviceId&) {
377 if (socket) {
378 successfullyConnected2 = true;
379 }
380 cv.notify_one();
381 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400382
Amnab8c33bb2023-08-03 14:40:01 -0400383 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
384 return successfullyConnected && successfullyConnected2 && receiverConnected == 2;
385 }));
386 CPPUNIT_ASSERT(alice->connectionManager->activeSockets() == 1);
387}
Adrien Béraudefe27372023-05-27 18:56:29 -0400388
Amnab8c33bb2023-08-03 14:40:01 -0400389void
390ConnectionManagerTest::testMultipleChannelsOneDeclined()
391{
392 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
393 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Adrien Béraudefe27372023-05-27 18:56:29 -0400394
Amnab8c33bb2023-08-03 14:40:01 -0400395 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
396 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Adrien Béraudefe27372023-05-27 18:56:29 -0400397
Amnab8c33bb2023-08-03 14:40:01 -0400398 std::mutex mtx;
399 std::unique_lock<std::mutex> lk {mtx};
400 std::condition_variable cv;
401 bool successfullyNotConnected = false;
402 bool successfullyConnected2 = false;
403 int receiverConnected = 0;
Adrien Béraudefe27372023-05-27 18:56:29 -0400404
Amnab8c33bb2023-08-03 14:40:01 -0400405 bob->connectionManager->onChannelRequest(
406 [](const std::shared_ptr<dht::crypto::Certificate>&, const std::string& name) {
407 if (name == "git://*")
408 return false;
409 return true;
410 });
Adrien Béraudefe27372023-05-27 18:56:29 -0400411
Amnab8c33bb2023-08-03 14:40:01 -0400412 bob->connectionManager->onConnectionReady(
413 [&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
414 if (socket)
415 receiverConnected += 1;
416 cv.notify_one();
417 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400418
Amnab8c33bb2023-08-03 14:40:01 -0400419 alice->connectionManager->connectDevice(bob->id.second,
420 "git://*",
421 [&](std::shared_ptr<ChannelSocket> socket,
422 const DeviceId&) {
423 if (!socket)
424 successfullyNotConnected = true;
425 cv.notify_one();
426 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400427
Amnab8c33bb2023-08-03 14:40:01 -0400428 alice->connectionManager->connectDevice(bob->id.second,
429 "sip://*",
430 [&](std::shared_ptr<ChannelSocket> socket,
431 const DeviceId&) {
432 if (socket)
433 successfullyConnected2 = true;
434 cv.notify_one();
435 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400436
Amnab8c33bb2023-08-03 14:40:01 -0400437 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
438 return successfullyNotConnected && successfullyConnected2 && receiverConnected == 1;
439 }));
440 CPPUNIT_ASSERT(alice->connectionManager->activeSockets() == 1);
441}
Morteza Namvar82960b32023-07-04 17:08:22 -0400442
Amnab8c33bb2023-08-03 14:40:01 -0400443void
444ConnectionManagerTest::testMultipleChannelsSameName()
445{
446 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
447 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -0400448
Amnab8c33bb2023-08-03 14:40:01 -0400449 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
450 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400451
Amnab8c33bb2023-08-03 14:40:01 -0400452 std::mutex mtx;
453 std::unique_lock<std::mutex> lk {mtx};
454 std::condition_variable cv;
455 bool successfullyConnected = false;
456 bool successfullyConnected2 = false;
457 int receiverConnected = 0;
Morteza Namvar82960b32023-07-04 17:08:22 -0400458
Amnab8c33bb2023-08-03 14:40:01 -0400459 bob->connectionManager->onChannelRequest(
460 [](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400461
Amnab8c33bb2023-08-03 14:40:01 -0400462 bob->connectionManager->onConnectionReady(
463 [&receiverConnected](const DeviceId&,
464 const std::string&,
465 std::shared_ptr<ChannelSocket> socket) {
466 if (socket)
467 receiverConnected += 1;
468 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400469
Amnab8c33bb2023-08-03 14:40:01 -0400470 alice->connectionManager->connectDevice(bob->id.second,
471 "git://*",
472 [&](std::shared_ptr<ChannelSocket> socket,
473 const DeviceId&) {
474 if (socket) {
475 successfullyConnected = true;
476 }
477 cv.notify_one();
478 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400479
Amnab8c33bb2023-08-03 14:40:01 -0400480 // We can open two sockets with the same name, it will be two different channel
481 alice->connectionManager->connectDevice(bob->id.second,
482 "git://*",
483 [&](std::shared_ptr<ChannelSocket> socket,
484 const DeviceId&) {
485 if (socket) {
486 successfullyConnected2 = true;
487 }
488 cv.notify_one();
489 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400490
Amnab8c33bb2023-08-03 14:40:01 -0400491 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
492 return successfullyConnected && successfullyConnected2 && receiverConnected == 2;
493 }));
494}
Morteza Namvar82960b32023-07-04 17:08:22 -0400495
Amnab8c33bb2023-08-03 14:40:01 -0400496void
497ConnectionManagerTest::testSendReceiveData()
498{
499 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
500 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -0400501
Amnab8c33bb2023-08-03 14:40:01 -0400502 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
503 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400504
Amnab8c33bb2023-08-03 14:40:01 -0400505 std::mutex mtx;
506 std::unique_lock<std::mutex> lk {mtx};
507 std::condition_variable cv;
508 std::atomic_int events(0);
509 bool successfullyConnected = false, successfullyConnected2 = false, successfullyReceive = false,
510 receiverConnected = false;
511 const uint8_t buf_other[] = {0x64, 0x65, 0x66, 0x67};
512 const uint8_t buf_test[] = {0x68, 0x69, 0x70, 0x71};
513 bool dataOk = false, dataOk2 = false;
Morteza Namvar82960b32023-07-04 17:08:22 -0400514
Amnab8c33bb2023-08-03 14:40:01 -0400515 bob->connectionManager->onChannelRequest(
516 [&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
517 const std::string&) {
518 successfullyReceive = true;
519 return true;
520 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400521
Amnab8c33bb2023-08-03 14:40:01 -0400522 bob->connectionManager->onConnectionReady(
523 [&](const DeviceId&, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
524 if (socket && (name == "test" || name == "other")) {
525 receiverConnected = true;
526 std::error_code ec;
527 auto res = socket->waitForData(std::chrono::milliseconds(5000), ec);
528 if (res == 4) {
529 uint8_t buf[4];
530 socket->read(&buf[0], 4, ec);
531 if (name == "test")
532 dataOk = std::equal(std::begin(buf), std::end(buf), std::begin(buf_test));
533 else
534 dataOk2 = std::equal(std::begin(buf), std::end(buf), std::begin(buf_other));
535 events++;
536 cv.notify_one();
537 }
538 }
539 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400540
Amnab8c33bb2023-08-03 14:40:01 -0400541 alice->connectionManager->connectDevice(bob->id.second,
542 "test",
543 [&](std::shared_ptr<ChannelSocket> socket,
544 const DeviceId&) {
545 if (socket) {
546 successfullyConnected = true;
547 std::error_code ec;
548 socket->write(&buf_test[0], 4, ec);
549 }
550 events++;
551 cv.notify_one();
552 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400553
Amnab8c33bb2023-08-03 14:40:01 -0400554 alice->connectionManager->connectDevice(bob->id.second,
555 "other",
556 [&](std::shared_ptr<ChannelSocket> socket,
557 const DeviceId&) {
558 if (socket) {
559 successfullyConnected2 = true;
560 std::error_code ec;
561 socket->write(&buf_other[0], 4, ec);
562 }
563 events++;
564 cv.notify_one();
565 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400566
Amnab8c33bb2023-08-03 14:40:01 -0400567 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
568 return events == 4 && successfullyReceive && successfullyConnected && successfullyConnected2
569 && dataOk && dataOk2;
570 }));
571}
Morteza Namvar82960b32023-07-04 17:08:22 -0400572
Amnab8c33bb2023-08-03 14:40:01 -0400573void
574ConnectionManagerTest::testAcceptsICERequest()
575{
576 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
577 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -0400578
Amnab8c33bb2023-08-03 14:40:01 -0400579 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400580
Amnab8c33bb2023-08-03 14:40:01 -0400581 std::mutex mtx;
582 std::unique_lock<std::mutex> lk {mtx};
583 std::condition_variable cv;
584 bool successfullyConnected = false;
585 bool successfullyReceive = false;
586 bool receiverConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -0400587
Amnab8c33bb2023-08-03 14:40:01 -0400588 bob->connectionManager->onChannelRequest(
589 [](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
590 bob->connectionManager->onICERequest([&](const DeviceId&) {
591 successfullyReceive = true;
592 return true;
593 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400594
Amnab8c33bb2023-08-03 14:40:01 -0400595 bob->connectionManager->onConnectionReady(
596 [&receiverConnected](const DeviceId&,
597 const std::string& name,
598 std::shared_ptr<ChannelSocket> socket) {
599 receiverConnected = socket && (name == "git://*");
600 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400601
Amnab8c33bb2023-08-03 14:40:01 -0400602 alice->connectionManager->connectDevice(bob->id.second,
603 "git://*",
604 [&](std::shared_ptr<ChannelSocket> socket,
605 const DeviceId&) {
606 if (socket) {
607 successfullyConnected = true;
608 }
609 cv.notify_one();
610 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400611
Amnab8c33bb2023-08-03 14:40:01 -0400612 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] {
613 return successfullyReceive && successfullyConnected && receiverConnected;
614 }));
615}
Morteza Namvar82960b32023-07-04 17:08:22 -0400616
Amnab8c33bb2023-08-03 14:40:01 -0400617void
618ConnectionManagerTest::testDeclineICERequest()
619{
620 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
621 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
Morteza Namvar82960b32023-07-04 17:08:22 -0400622
Amnab8c33bb2023-08-03 14:40:01 -0400623 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400624
Amnab8c33bb2023-08-03 14:40:01 -0400625 std::mutex mtx;
626 std::unique_lock<std::mutex> lk {mtx};
627 std::condition_variable cv;
628 bool successfullyConnected = false;
629 bool successfullyReceive = false;
630 bool receiverConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -0400631
Amnab8c33bb2023-08-03 14:40:01 -0400632 bob->connectionManager->onChannelRequest(
633 [](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
634 bob->connectionManager->onICERequest([&](const DeviceId&) {
635 successfullyReceive = true;
636 return false;
637 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400638
Amnab8c33bb2023-08-03 14:40:01 -0400639 bob->connectionManager->onConnectionReady(
640 [&receiverConnected](const DeviceId&,
641 const std::string& name,
642 std::shared_ptr<ChannelSocket> socket) {
643 receiverConnected = socket && (name == "git://*");
644 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400645
Amnab8c33bb2023-08-03 14:40:01 -0400646 alice->connectionManager->connectDevice(bob->id.second,
647 "git://*",
648 [&](std::shared_ptr<ChannelSocket> socket,
649 const DeviceId&) {
650 if (socket) {
651 successfullyConnected = true;
652 }
653 cv.notify_one();
654 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400655
Amnab8c33bb2023-08-03 14:40:01 -0400656 cv.wait_for(lk, 30s);
657 CPPUNIT_ASSERT(successfullyReceive);
658 CPPUNIT_ASSERT(!receiverConnected);
659 CPPUNIT_ASSERT(!successfullyConnected);
660}
Morteza Namvar82960b32023-07-04 17:08:22 -0400661
Amnab8c33bb2023-08-03 14:40:01 -0400662void
663ConnectionManagerTest::testChannelRcvShutdown()
664{
665 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
666 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -0400667
Amnab8c33bb2023-08-03 14:40:01 -0400668 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
669 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400670
Amnab8c33bb2023-08-03 14:40:01 -0400671 std::mutex mtx;
672 std::unique_lock<std::mutex> lk {mtx};
673 std::condition_variable cv;
674 bool successfullyConnected = false;
675 bool shutdownReceived = false;
Morteza Namvar82960b32023-07-04 17:08:22 -0400676
Amnab8c33bb2023-08-03 14:40:01 -0400677 std::shared_ptr<ChannelSocket> bobSock;
Morteza Namvar82960b32023-07-04 17:08:22 -0400678
Amnab8c33bb2023-08-03 14:40:01 -0400679 bob->connectionManager->onChannelRequest(
680 [](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400681
Amnab8c33bb2023-08-03 14:40:01 -0400682 bob->connectionManager->onConnectionReady(
683 [&](const DeviceId& did, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
684 if (socket && name == "git://*" && did != bob->id.second->getLongId()) {
685 bobSock = socket;
686 cv.notify_one();
687 }
688 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400689
Amnab8c33bb2023-08-03 14:40:01 -0400690 alice->connectionManager->connectDevice(bob->id.second,
691 "git://*",
692 [&](std::shared_ptr<ChannelSocket> socket,
693 const DeviceId&) {
694 if (socket) {
695 socket->onShutdown([&] {
696 shutdownReceived = true;
697 cv.notify_one();
698 });
699 successfullyConnected = true;
700 cv.notify_one();
701 }
702 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400703
Amnab8c33bb2023-08-03 14:40:01 -0400704 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return bobSock && successfullyConnected; }));
Morteza Namvar82960b32023-07-04 17:08:22 -0400705
Amnab8c33bb2023-08-03 14:40:01 -0400706 bobSock->shutdown();
Morteza Namvar82960b32023-07-04 17:08:22 -0400707
Amnab8c33bb2023-08-03 14:40:01 -0400708 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return shutdownReceived; }));
709}
Morteza Namvar82960b32023-07-04 17:08:22 -0400710
Amnab8c33bb2023-08-03 14:40:01 -0400711void
712ConnectionManagerTest::testChannelSenderShutdown()
713{
714 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
715 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
Morteza Namvar82960b32023-07-04 17:08:22 -0400716
Amnab8c33bb2023-08-03 14:40:01 -0400717 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
718 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400719
Amnab8c33bb2023-08-03 14:40:01 -0400720 std::mutex mtx;
721 std::unique_lock<std::mutex> lk {mtx};
722 std::condition_variable rcv, scv;
723 bool successfullyConnected = false;
724 bool successfullyReceive = false;
725 bool receiverConnected = false;
726 bool shutdownReceived = false;
Morteza Namvar82960b32023-07-04 17:08:22 -0400727
Amnab8c33bb2023-08-03 14:40:01 -0400728 bob->connectionManager->onChannelRequest(
729 [&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
730 const std::string& name) {
731 successfullyReceive = name == "git://*";
732 return true;
733 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400734
Amnab8c33bb2023-08-03 14:40:01 -0400735 bob->connectionManager->onConnectionReady(
736 [&](const DeviceId&, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
737 if (socket) {
738 socket->onShutdown([&] {
739 shutdownReceived = true;
740 scv.notify_one();
741 });
742 }
743 receiverConnected = socket && (name == "git://*");
744 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400745
Amnab8c33bb2023-08-03 14:40:01 -0400746 alice->connectionManager->connectDevice(bob->id.second,
747 "git://*",
748 [&](std::shared_ptr<ChannelSocket> socket,
749 const DeviceId&) {
750 if (socket) {
751 successfullyConnected = true;
752 rcv.notify_one();
753 socket->shutdown();
754 }
755 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400756
Amnab8c33bb2023-08-03 14:40:01 -0400757 rcv.wait_for(lk, 30s);
758 scv.wait_for(lk, 30s);
759 CPPUNIT_ASSERT(shutdownReceived);
760 CPPUNIT_ASSERT(successfullyReceive);
761 CPPUNIT_ASSERT(successfullyConnected);
762 CPPUNIT_ASSERT(receiverConnected);
763}
Morteza Namvar82960b32023-07-04 17:08:22 -0400764
Amnab8c33bb2023-08-03 14:40:01 -0400765void
766ConnectionManagerTest::testCloseConnectionWith()
767{
768 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
769 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -0400770
Amnab8c33bb2023-08-03 14:40:01 -0400771 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
772 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400773
Amnab8c33bb2023-08-03 14:40:01 -0400774 auto bobUri = bob->id.second->issuer->getId().toString();
775 std::mutex mtx;
776 std::unique_lock<std::mutex> lk {mtx};
777 std::condition_variable rcv, scv;
778 std::atomic_int events(0);
779 bool successfullyConnected = false;
780 bool successfullyReceive = false;
781 bool receiverConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -0400782
Amnab8c33bb2023-08-03 14:40:01 -0400783 bob->connectionManager->onChannelRequest(
784 [&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
785 const std::string& name) {
786 successfullyReceive = name == "git://*";
787 return true;
788 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400789
Amnab8c33bb2023-08-03 14:40:01 -0400790 bob->connectionManager->onConnectionReady([&](const DeviceId&,
791 const std::string& name,
792 std::shared_ptr<dhtnet::ChannelSocket> socket) {
793 if (socket) {
794 socket->onShutdown([&] {
795 events += 1;
796 scv.notify_one();
797 });
798 }
799 receiverConnected = socket && (name == "git://*");
800 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400801
Amnab8c33bb2023-08-03 14:40:01 -0400802 alice->connectionManager->connectDevice(bob->id.second->getId(),
803 "git://*",
804 [&](std::shared_ptr<dhtnet::ChannelSocket> socket,
805 const dht::InfoHash&) {
806 if (socket) {
807 socket->onShutdown([&] {
808 events += 1;
809 scv.notify_one();
810 });
811 successfullyConnected = true;
812 rcv.notify_one();
813 }
814 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400815
Amnab8c33bb2023-08-03 14:40:01 -0400816 rcv.wait_for(lk, 30s);
817 // This should trigger onShutdown
818 alice->connectionManager->closeConnectionsWith(bobUri);
819 CPPUNIT_ASSERT(scv.wait_for(lk, 60s, [&] {
820 return events == 2 && successfullyReceive && successfullyConnected && receiverConnected;
821 }));
822}
Morteza Namvar82960b32023-07-04 17:08:22 -0400823
Amnab8c33bb2023-08-03 14:40:01 -0400824// explain algorithm
825void
826ConnectionManagerTest::testShutdownCallbacks()
827{
828 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
829 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -0400830
Amnab8c33bb2023-08-03 14:40:01 -0400831 auto aliceUri = alice->id.second->issuer->getId().toString();
Morteza Namvar82960b32023-07-04 17:08:22 -0400832
Amnab8c33bb2023-08-03 14:40:01 -0400833 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
834 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400835
Amnab8c33bb2023-08-03 14:40:01 -0400836 std::mutex mtx;
837 std::unique_lock<std::mutex> lk {mtx};
838 std::condition_variable rcv, chan2cv;
839 bool successfullyConnected = false;
840 bool successfullyReceive = false;
841 bool receiverConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -0400842
Amnab8c33bb2023-08-03 14:40:01 -0400843 bob->connectionManager->onChannelRequest(
844 [&successfullyReceive, &chan2cv](const std::shared_ptr<dht::crypto::Certificate>&,
845 const std::string& name) {
846 if (name == "1") {
847 successfullyReceive = true;
848 } else {
849 chan2cv.notify_one();
850 // Do not return directly. Let the connection be closed
851 std::this_thread::sleep_for(10s);
852 }
853 return true;
854 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400855
Amnab8c33bb2023-08-03 14:40:01 -0400856 bob->connectionManager->onConnectionReady([&](const DeviceId&,
857 const std::string& name,
858 std::shared_ptr<dhtnet::ChannelSocket> socket) {
859 receiverConnected = socket && (name == "1");
860 });
Morteza Namvar82960b32023-07-04 17:08:22 -0400861
Amnab8c33bb2023-08-03 14:40:01 -0400862 alice->connectionManager->connectDevice(bob->id.second->getId(),
863 "1",
864 [&](std::shared_ptr<dhtnet::ChannelSocket> socket,
865 const dht::InfoHash&) {
866 if (socket) {
867 successfullyConnected = true;
868 rcv.notify_one();
869 }
870 });
871 // Connect first channel. This will initiate a mx sock
872 CPPUNIT_ASSERT(rcv.wait_for(lk, 30s, [&] {
873 fmt::print("successfullyReceive: {}\n", successfullyReceive);
874 fmt::print("successfullyConnected: {}\n", successfullyConnected);
875 fmt::print("receiverConnected: {}\n", receiverConnected);
876 return successfullyReceive && successfullyConnected && receiverConnected;
877 }));
Morteza Namvar82960b32023-07-04 17:08:22 -0400878
Amnab8c33bb2023-08-03 14:40:01 -0400879 // Connect another channel, but close the connection
880 bool channel2NotConnected = false;
881 alice->connectionManager->connectDevice(bob->id.second->getId(),
882 "2",
883 [&](std::shared_ptr<dhtnet::ChannelSocket> socket,
884 const dht::InfoHash&) {
885 channel2NotConnected = !socket;
886 rcv.notify_one();
887 });
888 chan2cv.wait_for(lk, 30s);
Morteza Namvar82960b32023-07-04 17:08:22 -0400889
Amnab8c33bb2023-08-03 14:40:01 -0400890 // This should trigger onShutdown for second callback
891 bob->connectionManager->closeConnectionsWith(aliceUri);
892 CPPUNIT_ASSERT(rcv.wait_for(lk, 30s, [&] { return channel2NotConnected; }));
893}
Morteza Namvar82960b32023-07-04 17:08:22 -0400894
Amnab8c33bb2023-08-03 14:40:01 -0400895void
896ConnectionManagerTest::testFloodSocket()
897{
898 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
899 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -0400900
Amnab8c33bb2023-08-03 14:40:01 -0400901 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
902 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -0400903
Amnab8c33bb2023-08-03 14:40:01 -0400904 std::mutex mtx;
905 std::unique_lock<std::mutex> lk {mtx};
906 std::condition_variable cv;
907 bool successfullyConnected = false;
908 bool successfullyReceive = false;
909 bool receiverConnected = false;
910 std::shared_ptr<dhtnet::ChannelSocket> rcvSock1, rcvSock2, rcvSock3, sendSock, sendSock2,
911 sendSock3;
912 bob->connectionManager->onChannelRequest(
913 [&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
914 const std::string& name) {
915 successfullyReceive = name == "1";
916 return true;
917 });
918 bob->connectionManager->onConnectionReady([&](const DeviceId&,
919 const std::string& name,
920 std::shared_ptr<dhtnet::ChannelSocket> socket) {
921 receiverConnected = socket != nullptr;
922 if (name == "1")
923 rcvSock1 = socket;
924 else if (name == "2")
925 rcvSock2 = socket;
926 else if (name == "3")
927 rcvSock3 = socket;
928 });
929 alice->connectionManager->connectDevice(bob->id.second,
930 "1",
931 [&](std::shared_ptr<dhtnet::ChannelSocket> socket,
932 const DeviceId&) {
933 if (socket) {
934 sendSock = socket;
935 successfullyConnected = true;
936 }
937 cv.notify_one();
938 });
939 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] {
940 return successfullyReceive && successfullyConnected && receiverConnected;
941 }));
942 CPPUNIT_ASSERT(receiverConnected);
943 successfullyConnected = false;
944 receiverConnected = false;
945 alice->connectionManager->connectDevice(bob->id.second,
946 "2",
947 [&](std::shared_ptr<dhtnet::ChannelSocket> socket,
948 const DeviceId&) {
949 if (socket) {
950 sendSock2 = socket;
951 successfullyConnected = true;
952 }
953 cv.notify_one();
954 });
955 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyConnected && receiverConnected; }));
956 successfullyConnected = false;
957 receiverConnected = false;
958 alice->connectionManager->connectDevice(bob->id.second,
959 "3",
960 [&](std::shared_ptr<dhtnet::ChannelSocket> socket,
961 const DeviceId&) {
962 if (socket) {
963 sendSock3 = socket;
964 successfullyConnected = true;
965 }
966 cv.notify_one();
967 });
968 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyConnected && receiverConnected; }));
969 std::mutex mtxRcv {};
970 std::string alphabet, shouldRcv, rcv1, rcv2, rcv3;
971 for (int i = 0; i < 100; ++i)
972 alphabet += "QWERTYUIOPASDFGHJKLZXCVBNM";
973 rcvSock1->setOnRecv([&](const uint8_t* buf, size_t len) {
974 rcv1 += std::string(buf, buf + len);
975 return len;
976 });
977 rcvSock2->setOnRecv([&](const uint8_t* buf, size_t len) {
978 rcv2 += std::string(buf, buf + len);
979 return len;
980 });
981 rcvSock3->setOnRecv([&](const uint8_t* buf, size_t len) {
982 rcv3 += std::string(buf, buf + len);
983 return len;
984 });
985 for (uint64_t i = 0; i < alphabet.size(); ++i) {
986 auto send = std::string(8000, alphabet[i]);
987 shouldRcv += send;
988 std::error_code ec;
989 sendSock->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
990 sendSock2->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
991 sendSock3->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
992 CPPUNIT_ASSERT(!ec);
993 }
994 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
995 return shouldRcv == rcv1 && shouldRcv == rcv2 && shouldRcv == rcv3;
996 }));
997}
Morteza Namvar82960b32023-07-04 17:08:22 -0400998
Amnab8c33bb2023-08-03 14:40:01 -0400999void
1000ConnectionManagerTest::testDestroyWhileSending()
1001{
1002 // Same as test before, but destroy the accounts while sending.
1003 // This test if a segfault occurs
1004 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1005 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
1006 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
1007 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
1008 std::mutex mtx;
1009 std::unique_lock<std::mutex> lk {mtx};
1010 std::condition_variable cv;
1011 bool successfullyConnected = false;
1012 bool successfullyReceive = false;
1013 bool receiverConnected = false;
1014 std::shared_ptr<ChannelSocket> rcvSock1, rcvSock2, rcvSock3, sendSock, sendSock2, sendSock3;
1015 bob->connectionManager->onChannelRequest(
1016 [&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
1017 const std::string& name) {
1018 successfullyReceive = name == "1";
1019 return true;
1020 });
1021 bob->connectionManager->onConnectionReady(
1022 [&](const DeviceId&, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
1023 receiverConnected = socket != nullptr;
1024 if (name == "1")
1025 rcvSock1 = socket;
1026 else if (name == "2")
1027 rcvSock2 = socket;
1028 else if (name == "3")
1029 rcvSock3 = socket;
1030 });
1031 alice->connectionManager->connectDevice(bob->id.second,
1032 "1",
1033 [&](std::shared_ptr<ChannelSocket> socket,
1034 const DeviceId&) {
1035 if (socket) {
1036 sendSock = socket;
1037 successfullyConnected = true;
1038 }
1039 cv.notify_one();
1040 });
1041 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] {
1042 return successfullyReceive && successfullyConnected && receiverConnected;
1043 }));
1044 successfullyConnected = false;
1045 receiverConnected = false;
1046 alice->connectionManager->connectDevice(bob->id.second,
1047 "2",
1048 [&](std::shared_ptr<ChannelSocket> socket,
1049 const DeviceId&) {
1050 if (socket) {
1051 sendSock2 = socket;
1052 successfullyConnected = true;
1053 }
1054 cv.notify_one();
1055 });
1056 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyConnected && receiverConnected; }));
1057 successfullyConnected = false;
1058 receiverConnected = false;
1059 alice->connectionManager->connectDevice(bob->id.second,
1060 "3",
1061 [&](std::shared_ptr<ChannelSocket> socket,
1062 const DeviceId&) {
1063 if (socket) {
1064 sendSock3 = socket;
1065 successfullyConnected = true;
1066 }
1067 cv.notify_one();
1068 });
1069 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyConnected && receiverConnected; }));
1070 std::mutex mtxRcv {};
1071 std::string alphabet;
1072 for (int i = 0; i < 100; ++i)
1073 alphabet += "QWERTYUIOPASDFGHJKLZXCVBNM";
1074 rcvSock1->setOnRecv([&](const uint8_t*, size_t len) { return len; });
1075 rcvSock2->setOnRecv([&](const uint8_t*, size_t len) { return len; });
1076 rcvSock3->setOnRecv([&](const uint8_t*, size_t len) { return len; });
1077 for (uint64_t i = 0; i < alphabet.size(); ++i) {
1078 auto send = std::string(8000, alphabet[i]);
1079 std::error_code ec;
1080 sendSock->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
1081 sendSock2->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
1082 sendSock3->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
1083 CPPUNIT_ASSERT(!ec);
1084 }
Morteza Namvar82960b32023-07-04 17:08:22 -04001085
Amnab8c33bb2023-08-03 14:40:01 -04001086 // No need to wait, immediately destroy, no segfault must occurs
1087}
Morteza Namvar82960b32023-07-04 17:08:22 -04001088
Amnab8c33bb2023-08-03 14:40:01 -04001089void
1090ConnectionManagerTest::testIsConnecting()
1091{
1092 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1093 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
Morteza Namvar82960b32023-07-04 17:08:22 -04001094
Amnab8c33bb2023-08-03 14:40:01 -04001095 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
1096 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -04001097
Amnab8c33bb2023-08-03 14:40:01 -04001098 std::mutex mtx;
1099 std::unique_lock<std::mutex> lk {mtx};
1100 std::condition_variable cv;
1101 bool successfullyConnected = false, successfullyReceive = false;
Morteza Namvar82960b32023-07-04 17:08:22 -04001102
Amnab8c33bb2023-08-03 14:40:01 -04001103 bob->connectionManager->onChannelRequest(
1104 [&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) {
1105 successfullyReceive = true;
1106 cv.notify_one();
1107 std::this_thread::sleep_for(2s);
1108 return true;
1109 });
Morteza Namvar82960b32023-07-04 17:08:22 -04001110
Amnab8c33bb2023-08-03 14:40:01 -04001111 CPPUNIT_ASSERT(!alice->connectionManager->isConnecting(bob->id.second->getLongId(), "sip"));
Morteza Namvar82960b32023-07-04 17:08:22 -04001112
Amnab8c33bb2023-08-03 14:40:01 -04001113 alice->connectionManager->connectDevice(bob->id.second,
1114 "sip",
1115 [&](std::shared_ptr<ChannelSocket> socket,
1116 const DeviceId&) {
1117 if (socket) {
1118 successfullyConnected = true;
1119 }
1120 cv.notify_one();
1121 });
1122 // connectDevice is full async, so isConnecting will be true after a few ms.
1123 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] { return successfullyReceive; }));
1124 CPPUNIT_ASSERT(alice->connectionManager->isConnecting(bob->id.second->getLongId(), "sip"));
1125 CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] { return successfullyConnected; }));
1126 std::this_thread::sleep_for(
1127 std::chrono::milliseconds(100)); // Just to wait for the callback to finish
1128 CPPUNIT_ASSERT(!alice->connectionManager->isConnecting(bob->id.second->getLongId(), "sip"));
1129}
Morteza Namvar82960b32023-07-04 17:08:22 -04001130
Amnab8c33bb2023-08-03 14:40:01 -04001131void
1132ConnectionManagerTest::testCanSendBeacon()
1133{
1134 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1135 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
Morteza Namvar82960b32023-07-04 17:08:22 -04001136
Amnab8c33bb2023-08-03 14:40:01 -04001137 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
1138 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -04001139
Amnab8c33bb2023-08-03 14:40:01 -04001140 std::mutex mtx;
1141 std::unique_lock<std::mutex> lk {mtx};
1142 std::condition_variable cv;
1143 bool successfullyConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -04001144
Amnab8c33bb2023-08-03 14:40:01 -04001145 std::shared_ptr<MultiplexedSocket> aliceSocket, bobSocket;
1146 bob->connectionManager->onChannelRequest(
1147 [&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
1148 bob->connectionManager->onConnectionReady(
1149 [&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
1150 if (socket && socket->name() == "sip")
1151 bobSocket = socket->underlyingSocket();
1152 cv.notify_one();
1153 });
Morteza Namvar82960b32023-07-04 17:08:22 -04001154
Amnab8c33bb2023-08-03 14:40:01 -04001155 alice->connectionManager->connectDevice(bob->id.second,
1156 "sip",
1157 [&](std::shared_ptr<ChannelSocket> socket,
1158 const DeviceId&) {
1159 if (socket) {
1160 aliceSocket = socket->underlyingSocket();
1161 successfullyConnected = true;
1162 }
1163 cv.notify_one();
1164 });
1165 // connectDevice is full async, so isConnecting will be true after a few ms.
1166 CPPUNIT_ASSERT(
1167 cv.wait_for(lk, 30s, [&] { return aliceSocket && bobSocket && successfullyConnected; }));
1168 CPPUNIT_ASSERT(aliceSocket->canSendBeacon());
Morteza Namvar82960b32023-07-04 17:08:22 -04001169
Amnab8c33bb2023-08-03 14:40:01 -04001170 // Because onConnectionReady is true before version is sent, we can wait a bit
1171 // before canSendBeacon is true.
1172 auto start = std::chrono::steady_clock::now();
1173 auto aliceCanSendBeacon = false;
1174 auto bobCanSendBeacon = false;
1175 do {
1176 aliceCanSendBeacon = aliceSocket->canSendBeacon();
1177 bobCanSendBeacon = bobSocket->canSendBeacon();
1178 if (!bobCanSendBeacon || !aliceCanSendBeacon)
1179 std::this_thread::sleep_for(1s);
1180 } while ((not bobCanSendBeacon or not aliceCanSendBeacon)
1181 and std::chrono::steady_clock::now() - start < 5s);
Morteza Namvar82960b32023-07-04 17:08:22 -04001182
Amnab8c33bb2023-08-03 14:40:01 -04001183 CPPUNIT_ASSERT(bobCanSendBeacon && aliceCanSendBeacon);
1184}
Morteza Namvar82960b32023-07-04 17:08:22 -04001185
Amnab8c33bb2023-08-03 14:40:01 -04001186void
1187ConnectionManagerTest::testCannotSendBeacon()
1188{
1189 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1190 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
Morteza Namvar82960b32023-07-04 17:08:22 -04001191
Amnab8c33bb2023-08-03 14:40:01 -04001192 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
1193 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -04001194
Amnab8c33bb2023-08-03 14:40:01 -04001195 std::mutex mtx;
1196 std::unique_lock<std::mutex> lk {mtx};
1197 std::condition_variable cv;
1198 bool successfullyConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -04001199
Amnab8c33bb2023-08-03 14:40:01 -04001200 std::shared_ptr<MultiplexedSocket> aliceSocket, bobSocket;
1201 bob->connectionManager->onChannelRequest(
1202 [&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
1203 bob->connectionManager->onConnectionReady(
1204 [&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
1205 if (socket && socket->name() == "sip")
1206 bobSocket = socket->underlyingSocket();
1207 cv.notify_one();
1208 });
Morteza Namvar82960b32023-07-04 17:08:22 -04001209
Amnab8c33bb2023-08-03 14:40:01 -04001210 alice->connectionManager->connectDevice(bob->id.second,
1211 "sip",
1212 [&](std::shared_ptr<ChannelSocket> socket,
1213 const DeviceId&) {
1214 if (socket) {
1215 aliceSocket = socket->underlyingSocket();
1216 successfullyConnected = true;
1217 }
1218 cv.notify_one();
1219 });
1220 // connectDevice is full async, so isConnecting will be true after a few ms.
1221 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return aliceSocket && bobSocket; }));
Morteza Namvar82960b32023-07-04 17:08:22 -04001222
Amnab8c33bb2023-08-03 14:40:01 -04001223 int version = 1412;
1224 bobSocket->setOnVersionCb([&](auto v) {
1225 version = v;
1226 cv.notify_one();
1227 });
1228 aliceSocket->setVersion(0);
1229 aliceSocket->sendVersion();
1230 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return version == 0; }));
1231 CPPUNIT_ASSERT(!bobSocket->canSendBeacon());
1232}
Morteza Namvar82960b32023-07-04 17:08:22 -04001233
Amnab8c33bb2023-08-03 14:40:01 -04001234void
1235ConnectionManagerTest::testConnectivityChangeTriggerBeacon()
1236{
1237 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1238 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
Morteza Namvar82960b32023-07-04 17:08:22 -04001239
Amnab8c33bb2023-08-03 14:40:01 -04001240 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
1241 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -04001242
Amnab8c33bb2023-08-03 14:40:01 -04001243 std::mutex mtx;
1244 std::unique_lock<std::mutex> lk {mtx};
1245 std::condition_variable cv;
1246 bool successfullyConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -04001247
Amnab8c33bb2023-08-03 14:40:01 -04001248 std::shared_ptr<MultiplexedSocket> aliceSocket, bobSocket;
1249 bob->connectionManager->onChannelRequest(
1250 [&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
1251 bob->connectionManager->onConnectionReady(
1252 [&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
1253 if (socket && socket->name() == "sip")
1254 bobSocket = socket->underlyingSocket();
1255 cv.notify_one();
1256 });
Morteza Namvar82960b32023-07-04 17:08:22 -04001257
Amnab8c33bb2023-08-03 14:40:01 -04001258 alice->connectionManager->connectDevice(bob->id.second,
1259 "sip",
1260 [&](std::shared_ptr<ChannelSocket> socket,
1261 const DeviceId&) {
1262 if (socket) {
1263 aliceSocket = socket->underlyingSocket();
1264 successfullyConnected = true;
1265 }
1266 cv.notify_one();
1267 });
1268 // connectDevice is full async, so isConnecting will be true after a few ms.
1269 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return aliceSocket && bobSocket; }));
Morteza Namvar82960b32023-07-04 17:08:22 -04001270
Amnab8c33bb2023-08-03 14:40:01 -04001271 bool hasRequest = false;
1272 bobSocket->setOnBeaconCb([&](auto p) {
1273 if (p)
1274 hasRequest = true;
1275 cv.notify_one();
1276 });
1277 alice->connectionManager->connectivityChanged();
1278 CPPUNIT_ASSERT(cv.wait_for(lk, 10s, [&] { return hasRequest; }));
1279}
Morteza Namvar82960b32023-07-04 17:08:22 -04001280
Amnab8c33bb2023-08-03 14:40:01 -04001281void
1282ConnectionManagerTest::testOnNoBeaconTriggersShutdown()
1283{
1284 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1285 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey()); //
Morteza Namvar82960b32023-07-04 17:08:22 -04001286
Amnab8c33bb2023-08-03 14:40:01 -04001287 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
1288 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -04001289
Amnab8c33bb2023-08-03 14:40:01 -04001290 std::mutex mtx;
1291 std::unique_lock<std::mutex> lk {mtx};
1292 std::condition_variable cv;
1293 bool successfullyConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -04001294
Amnab8c33bb2023-08-03 14:40:01 -04001295 std::shared_ptr<MultiplexedSocket> aliceSocket, bobSocket;
1296 bob->connectionManager->onChannelRequest(
1297 [&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
1298 bob->connectionManager->onConnectionReady(
1299 [&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
1300 if (socket && socket->name() == "sip")
1301 bobSocket = socket->underlyingSocket();
1302 cv.notify_one();
1303 });
Morteza Namvar82960b32023-07-04 17:08:22 -04001304
Amnab8c33bb2023-08-03 14:40:01 -04001305 alice->connectionManager->connectDevice(bob->id.second,
1306 "sip",
1307 [&](std::shared_ptr<ChannelSocket> socket,
1308 const DeviceId&) {
1309 if (socket) {
1310 aliceSocket = socket->underlyingSocket();
1311 successfullyConnected = true;
1312 }
1313 cv.notify_one();
1314 });
1315 // connectDevice is full async, so isConnecting will be true after a few ms.
1316 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return aliceSocket && bobSocket; }));
Morteza Namvar82960b32023-07-04 17:08:22 -04001317
Amnab8c33bb2023-08-03 14:40:01 -04001318 bool isClosed = false;
1319 aliceSocket->onShutdown([&] {
1320 isClosed = true;
1321 cv.notify_one();
1322 });
1323 bobSocket->answerToBeacon(false);
1324 alice->connectionManager->connectivityChanged();
1325 CPPUNIT_ASSERT(cv.wait_for(lk, 10s, [&] { return isClosed; }));
1326}
Morteza Namvar82960b32023-07-04 17:08:22 -04001327
Amnab8c33bb2023-08-03 14:40:01 -04001328void
1329ConnectionManagerTest::testShutdownWhileNegotiating()
1330{
1331 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1332 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -04001333
Amnab8c33bb2023-08-03 14:40:01 -04001334 alice->connectionManager->onICERequest([](const DeviceId&) { return true; });
Morteza Namvar82960b32023-07-04 17:08:22 -04001335
Amnab8c33bb2023-08-03 14:40:01 -04001336 std::mutex mtx;
1337 std::unique_lock<std::mutex> lk {mtx};
1338 std::condition_variable cv;
1339 bool successfullyReceive = false;
1340 bool notConnected = false;
Morteza Namvar82960b32023-07-04 17:08:22 -04001341
Amnab8c33bb2023-08-03 14:40:01 -04001342 bob->connectionManager->onICERequest([&](const DeviceId&) {
1343 successfullyReceive = true;
1344 cv.notify_one();
1345 return true;
1346 });
Morteza Namvar82960b32023-07-04 17:08:22 -04001347
Amnab8c33bb2023-08-03 14:40:01 -04001348 alice->connectionManager->connectDevice(bob->id.second,
1349 "git://*",
1350 [&](std::shared_ptr<ChannelSocket> socket,
1351 const DeviceId&) {
1352 notConnected = !socket;
1353 cv.notify_one();
1354 });
Morteza Namvar82960b32023-07-04 17:08:22 -04001355
Amnab8c33bb2023-08-03 14:40:01 -04001356 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyReceive; }));
1357 // Manager::instance().setAccountActive(alice->id.second, false, true);
Morteza Namvar82960b32023-07-04 17:08:22 -04001358
Amnab8c33bb2023-08-03 14:40:01 -04001359 // Just move destruction on another thread.
1360 // dht::threadpool::io().run([conMgr =std::move(alice->connectionManager)] {});
1361 alice->connectionManager.reset();
Morteza Namvar82960b32023-07-04 17:08:22 -04001362
Amnab8c33bb2023-08-03 14:40:01 -04001363 CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return notConnected; }));
1364}
1365void
1366ConnectionManagerTest::testGetChannelList()
1367{
1368 alice->connectionManager->onDhtConnected(alice->id.first->getPublicKey());
1369 bob->connectionManager->onDhtConnected(bob->id.first->getPublicKey());
Morteza Namvar82960b32023-07-04 17:08:22 -04001370
Amnab8c33bb2023-08-03 14:40:01 -04001371 bob->connectionManager->onICERequest([](const DeviceId&) { return true; });
1372 std::mutex mtx;
1373 std::condition_variable cv;
1374 std::unique_lock<std::mutex> lk {mtx};
1375 bool successfullyConnected = false;
1376 int receiverConnected = 0;
1377 bob->connectionManager->onChannelRequest(
1378 [](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
1379 bob->connectionManager->onConnectionReady(
1380 [&receiverConnected,
1381 &cv](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
1382 if (socket)
1383 receiverConnected += 1;
Morteza Namvar82960b32023-07-04 17:08:22 -04001384
Amnab8c33bb2023-08-03 14:40:01 -04001385 cv.notify_one();
1386 });
1387 std::string channelId;
1388 alice->connectionManager->connectDevice(bob->id.second,
1389 "git://*",
1390 [&](std::shared_ptr<ChannelSocket> socket,
1391 const DeviceId&) {
1392 if (socket) {
1393 channelId = std::to_string(socket->channel());
1394 successfullyConnected = true;
1395 }
Morteza Namvar82960b32023-07-04 17:08:22 -04001396
Amnab8c33bb2023-08-03 14:40:01 -04001397 cv.notify_one();
1398 });
1399 CPPUNIT_ASSERT(
1400 cv.wait_for(lk, 60s, [&] { return successfullyConnected && receiverConnected == 1; }));
1401 std::vector<std::map<std::string, std::string>> expectedList = {
1402 {{"channel", channelId}, {"channelName", "git://*"}}};
1403 auto connectionList = alice->connectionManager->getConnectionList();
1404 CPPUNIT_ASSERT(!connectionList.empty());
1405 const auto& connectionInfo = connectionList[0];
1406 auto it = connectionInfo.find("id");
1407 CPPUNIT_ASSERT(it != connectionInfo.end());
1408 std::string connectionId = it->second;
1409 auto actualList = alice->connectionManager->getChannelList(connectionId);
1410 CPPUNIT_ASSERT(expectedList.size() == actualList.size());
1411 CPPUNIT_ASSERT(std::equal(expectedList.begin(), expectedList.end(), actualList.begin()));
1412 for (const auto& expectedMap : expectedList) {
1413 auto it = std::find_if(actualList.begin(),
1414 actualList.end(),
1415 [&](const std::map<std::string, std::string>& actualMap) {
1416 return expectedMap.size() == actualMap.size()
1417 && std::equal(expectedMap.begin(),
1418 expectedMap.end(),
1419 actualMap.begin());
1420 });
1421 CPPUNIT_ASSERT(it != actualList.end());
1422 }
1423}
Adrien Béraudefe27372023-05-27 18:56:29 -04001424
1425} // namespace test
Sébastien Blin464bdff2023-07-19 08:02:53 -04001426} // namespace dhtnet
Adrien Béraudefe27372023-05-27 18:56:29 -04001427
Adrien Béraud1ae60aa2023-07-07 09:55:09 -04001428JAMI_TEST_RUNNER(dhtnet::test::ConnectionManagerTest::name())