blob: ff4ed72ba889cf08367392c780b34e22609f6729 [file] [log] [blame]
Adrien Béraud6c6a9622023-08-27 12:49:31 -04001#include "../common.h"
2
3#include "connectionmanager.h"
4#include "multiplexed_socket.h"
5#include "certstore.h"
6
7#include <opendht/log.h>
8#include <opendht/utils.h>
9#include <opendht/thread_pool.h>
10
11#include <asio/executor_work_guard.hpp>
12#include <asio/io_context.hpp>
13
14namespace dhtnet {
15using namespace std::literals::chrono_literals;
16using clock = std::chrono::high_resolution_clock;
17using time_point = clock::time_point;
18using duration = clock::duration;
19
20struct ConnectionHandler
21{
22 dht::crypto::Identity id;
23 std::shared_ptr<Logger> logger;
24 std::shared_ptr<tls::CertificateStore> certStore;
25 std::shared_ptr<dht::DhtRunner> dht;
26 std::shared_ptr<ConnectionManager> connectionManager;
27 std::shared_ptr<asio::io_context> ioContext;
28 std::shared_ptr<std::thread> ioContextRunner;
29};
30
31std::unique_ptr<ConnectionHandler>
32setupHandler(const std::string& name,
33 std::shared_ptr<asio::io_context> ioContext,
34 std::shared_ptr<std::thread> ioContextRunner,
Adrien Béraudcd8fea92023-09-20 14:16:36 -040035 std::shared_ptr<IceTransportFactory> factory,
Adrien Béraud6c6a9622023-08-27 12:49:31 -040036 std::shared_ptr<Logger> logger)
37{
38 auto h = std::make_unique<ConnectionHandler>();
39 auto ca = dht::crypto::generateIdentity("ca");
40 h->id = dht::crypto::generateIdentity(name, ca);
41 h->logger = logger;
42 h->certStore = std::make_shared<tls::CertificateStore>(name, h->logger);
43 h->ioContext = std::make_shared<asio::io_context>();
44 h->ioContext = ioContext;
45 h->ioContextRunner = ioContextRunner;
46
47 dht::DhtRunner::Config dhtConfig;
48 dhtConfig.dht_config.id = h->id;
49 dhtConfig.threaded = true;
50
51 dht::DhtRunner::Context dhtContext;
52 dhtContext.certificateStore = [c = h->certStore](const dht::InfoHash& pk_id) {
53 std::vector<std::shared_ptr<dht::crypto::Certificate>> ret;
54 if (auto cert = c->getCertificate(pk_id.toString()))
55 ret.emplace_back(std::move(cert));
56 return ret;
57 };
58 // dhtContext.logger = h->logger;
59
60 h->dht = std::make_shared<dht::DhtRunner>();
61 h->dht->run(dhtConfig, std::move(dhtContext));
Adrien Béraudf8b33b22023-11-05 12:29:13 -050062 h->dht->bootstrap("127.0.0.1:36432");
63 //h->dht->bootstrap("bootstrap.jami.net");
Adrien Béraud6c6a9622023-08-27 12:49:31 -040064
65 auto config = std::make_shared<ConnectionManager::Config>();
66 config->dht = h->dht;
67 config->id = h->id;
68 config->ioContext = h->ioContext;
Adrien Béraudcd8fea92023-09-20 14:16:36 -040069 config->factory = factory;
Adrien Béraud6c6a9622023-08-27 12:49:31 -040070 config->logger = logger;
Adrien Béraudcd8fea92023-09-20 14:16:36 -040071 config->certStore = h->certStore;
Adrien Béraud9deadef2024-02-18 14:53:07 -050072 config->cachePath = std::filesystem::current_path() / "temp";
Adrien Béraud6c6a9622023-08-27 12:49:31 -040073
74 h->connectionManager = std::make_shared<ConnectionManager>(config);
75 h->connectionManager->onICERequest([](const DeviceId&) { return true; });
Amnab31c3742023-08-28 13:58:31 -040076 return h;
Adrien Béraud6c6a9622023-08-27 12:49:31 -040077}
78
79struct BenchResult {
80 duration connection;
81 duration send;
82 bool success;
83};
84
85BenchResult
86runBench(std::shared_ptr<asio::io_context> ioContext,
87 std::shared_ptr<std::thread> ioContextRunner,
Adrien Béraudcd8fea92023-09-20 14:16:36 -040088 std::shared_ptr<IceTransportFactory>& factory,
Adrien Béraud6c6a9622023-08-27 12:49:31 -040089 std::shared_ptr<Logger> logger)
90{
91 BenchResult ret;
92 std::mutex mtx;
Adrien Béraud024c46f2024-03-02 23:53:18 -050093 std::unique_lock lock {mtx};
Adrien Béraud6c6a9622023-08-27 12:49:31 -040094 std::condition_variable serverConVar;
95
Adrien Béraudf8b33b22023-11-05 12:29:13 -050096 auto boostrap_node = std::make_shared<dht::DhtRunner>();
97 boostrap_node->run(36432);
Adrien Béraud6c6a9622023-08-27 12:49:31 -040098
Amnac03c4b52024-07-24 17:57:25 -040099 Log("Generating identities…\n");
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400100 auto server = setupHandler("server", ioContext, ioContextRunner, factory, logger);
101 auto client = setupHandler("client", ioContext, ioContextRunner, factory, logger);
102
103 client->connectionManager->onDhtConnected(client->id.first->getPublicKey());
104 server->connectionManager->onDhtConnected(server->id.first->getPublicKey());
105
106 server->connectionManager->onChannelRequest(
107 [](const std::shared_ptr<dht::crypto::Certificate>&,
108 const std::string& name) {
109 return name == "channelName";
110 });
111 server->connectionManager->onConnectionReady([&](const DeviceId& device, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
112 if (socket) {
Amnac03c4b52024-07-24 17:57:25 -0400113 Log("Server: Connection succeeded\n");
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400114 socket->setOnRecv([s=socket.get()](const uint8_t* data, size_t size) {
115 std::error_code ec;
116 return s->write(data, size, ec);
117 });
118 } else {
Amnac03c4b52024-07-24 17:57:25 -0400119 Log("Server: Connection failed\n");
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400120 }
121 });
122
123 std::condition_variable cv;
124 bool completed = false;
125 size_t rx = 0;
126 constexpr size_t TX_SIZE = 64 * 1024;
127 constexpr size_t TX_NUM = 1024;
128 constexpr size_t TX_GOAL = TX_SIZE * TX_NUM;
129 time_point start_connect, start_send;
130
Adrien Béraudf8b33b22023-11-05 12:29:13 -0500131 std::this_thread::sleep_for(3s);
Amnac03c4b52024-07-24 17:57:25 -0400132 Log("Connecting…\n");
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400133 start_connect = clock::now();
134 client->connectionManager->connectDevice(server->id.second, "channelName", [&](std::shared_ptr<ChannelSocket> socket, const DeviceId&) {
135 if (socket) {
136 socket->setOnRecv([&](const uint8_t* data, size_t size) {
137 rx += size;
138 if (rx == TX_GOAL) {
139 auto end = clock::now();
140 ret.send = end - start_send;
Amnac03c4b52024-07-24 17:57:25 -0400141 Log("Streamed {} bytes back and forth in {} ({} kBps)\n", rx, dht::print_duration(ret.send), (unsigned)(rx / (1000 * std::chrono::duration<double>(ret.send).count())));
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400142 cv.notify_one();
143 }
144 return size;
145 });
146 ret.connection = clock::now() - start_connect;
Amnac03c4b52024-07-24 17:57:25 -0400147 Log("Connected in {}\n", dht::print_duration(ret.connection));
Adrien Béraudf8b33b22023-11-05 12:29:13 -0500148 std::vector<uint8_t> data(TX_SIZE, (uint8_t)'y');
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400149 std::error_code ec;
150 start_send = clock::now();
151 for (unsigned i = 0; i < TX_NUM; ++i) {
152 socket->write(data.data(), data.size(), ec);
153 if (ec)
Amnac03c4b52024-07-24 17:57:25 -0400154 fmt::print(stderr, "error: {}\n", ec.message());
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400155 }
156 } else {
157 completed = true;
158 }
159 });
160 ret.success = cv.wait_for(lock, 60s, [&] { return completed or rx == TX_GOAL; });
161 std::this_thread::sleep_for(500ms);
162 return ret;
163}
164
165
166void
167bench()
168{
169
170 std::shared_ptr<Logger> logger;// = dht::log::getStdLogger();
Adrien Béraudcd8fea92023-09-20 14:16:36 -0400171 auto factory = std::make_shared<IceTransportFactory>(logger);
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400172 auto ioContext = std::make_shared<asio::io_context>();
173 auto ioContextRunner = std::make_shared<std::thread>([context = ioContext]() {
174 try {
175 auto work = asio::make_work_guard(*context);
176 context->run();
177 } catch (const std::exception& ex) {
Amnab31c3742023-08-28 13:58:31 -0400178 fmt::print(stderr, "Exception: {}\n", ex.what());
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400179 }
180 });
Amnab31c3742023-08-28 13:58:31 -0400181
182 BenchResult total = {0s, 0s, false};
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400183 unsigned total_success = 0;
184 constexpr unsigned ITERATIONS = 20;
185 for (unsigned i = 0; i < ITERATIONS; ++i) {
Amnac03c4b52024-07-24 17:57:25 -0400186 Log("Iteration {}\n", i);
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400187 auto res = runBench(ioContext, ioContextRunner, factory, logger);
188 if (res.success) {
189 total.connection += res.connection;
190 total.send += res.send;
191 total_success++;
192 }
193 }
Amnac03c4b52024-07-24 17:57:25 -0400194 Log("Average connection time: {}\n", dht::print_duration(total.connection / total_success));
195 Log("Average send time: {}\n", dht::print_duration(total.send / total_success));
196 Log("Total success: {}\n", total_success);
Amnab31c3742023-08-28 13:58:31 -0400197
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400198 std::this_thread::sleep_for(500ms);
199 ioContext->stop();
200 ioContextRunner->join();
201}
202
203}
204
205static void
206setSipLogLevel()
207{
208 int level = 0;
209 if (char* envvar = getenv("SIPLOGLEVEL")) {
210 // From 0 (min) to 6 (max)
211 level = std::clamp(std::stoi(envvar), 0, 6);
212 }
213
214 pj_log_set_level(level);
215 pj_log_set_log_func([](int level, const char* data, int /*len*/) {
216 });
217}
218
219int
220main(int argc, char** argv)
221{
222 setSipLogLevel();
223 dhtnet::bench();
224 return 0;
225}