blob: c22df5e06173d5b9691fdf4207ef25b4f5ea39f0 [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));
62 //h->dht->bootstrap("127.0.0.1:36432");
63 h->dht->bootstrap("bootstrap.jami.net");
64
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éraud6c6a9622023-08-27 12:49:31 -040072
73 std::filesystem::path currentPath = std::filesystem::current_path();
74 std::filesystem::path tempDirPath = currentPath / "temp";
75
76 config->cachePath = tempDirPath.string();
77
78 h->connectionManager = std::make_shared<ConnectionManager>(config);
79 h->connectionManager->onICERequest([](const DeviceId&) { return true; });
Amnab31c3742023-08-28 13:58:31 -040080 return h;
Adrien Béraud6c6a9622023-08-27 12:49:31 -040081}
82
83struct BenchResult {
84 duration connection;
85 duration send;
86 bool success;
87};
88
89BenchResult
90runBench(std::shared_ptr<asio::io_context> ioContext,
91 std::shared_ptr<std::thread> ioContextRunner,
Adrien Béraudcd8fea92023-09-20 14:16:36 -040092 std::shared_ptr<IceTransportFactory>& factory,
Adrien Béraud6c6a9622023-08-27 12:49:31 -040093 std::shared_ptr<Logger> logger)
94{
95 BenchResult ret;
96 std::mutex mtx;
97 std::unique_lock<std::mutex> lock {mtx};
98 std::condition_variable serverConVar;
99
100 //auto boostrap_node = std::make_shared<dht::DhtRunner>();
101 //boostrap_node->run(36432);
102
Amnab31c3742023-08-28 13:58:31 -0400103 fmt::print("Generating identities…\n");
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400104 auto server = setupHandler("server", ioContext, ioContextRunner, factory, logger);
105 auto client = setupHandler("client", ioContext, ioContextRunner, factory, logger);
106
107 client->connectionManager->onDhtConnected(client->id.first->getPublicKey());
108 server->connectionManager->onDhtConnected(server->id.first->getPublicKey());
109
110 server->connectionManager->onChannelRequest(
111 [](const std::shared_ptr<dht::crypto::Certificate>&,
112 const std::string& name) {
113 return name == "channelName";
114 });
115 server->connectionManager->onConnectionReady([&](const DeviceId& device, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
116 if (socket) {
Amnab31c3742023-08-28 13:58:31 -0400117 fmt::print("Server: Connection succeeded\n");
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400118 socket->setOnRecv([s=socket.get()](const uint8_t* data, size_t size) {
119 std::error_code ec;
120 return s->write(data, size, ec);
121 });
122 } else {
Amnab31c3742023-08-28 13:58:31 -0400123 fmt::print("Server: Connection failed\n");
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400124 }
125 });
126
127 std::condition_variable cv;
128 bool completed = false;
129 size_t rx = 0;
130 constexpr size_t TX_SIZE = 64 * 1024;
131 constexpr size_t TX_NUM = 1024;
132 constexpr size_t TX_GOAL = TX_SIZE * TX_NUM;
133 time_point start_connect, start_send;
134
135 std::this_thread::sleep_for(5s);
Adrien Beraudabdbe202023-08-30 12:35:42 -0400136 fmt::print("Connecting…\n");
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400137 start_connect = clock::now();
138 client->connectionManager->connectDevice(server->id.second, "channelName", [&](std::shared_ptr<ChannelSocket> socket, const DeviceId&) {
139 if (socket) {
140 socket->setOnRecv([&](const uint8_t* data, size_t size) {
141 rx += size;
142 if (rx == TX_GOAL) {
143 auto end = clock::now();
144 ret.send = end - start_send;
Amnab31c3742023-08-28 13:58:31 -0400145 fmt::print("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 -0400146 cv.notify_one();
147 }
148 return size;
149 });
150 ret.connection = clock::now() - start_connect;
Amnab31c3742023-08-28 13:58:31 -0400151 fmt::print("Connected in {}\n", dht::print_duration(ret.connection));
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400152 std::vector<uint8_t> data(TX_SIZE, 'y');
153 std::error_code ec;
154 start_send = clock::now();
155 for (unsigned i = 0; i < TX_NUM; ++i) {
156 socket->write(data.data(), data.size(), ec);
157 if (ec)
Amnab31c3742023-08-28 13:58:31 -0400158 fmt::print("error: {}\n", ec.message());
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400159 }
160 } else {
161 completed = true;
162 }
163 });
164 ret.success = cv.wait_for(lock, 60s, [&] { return completed or rx == TX_GOAL; });
165 std::this_thread::sleep_for(500ms);
166 return ret;
167}
168
169
170void
171bench()
172{
173
174 std::shared_ptr<Logger> logger;// = dht::log::getStdLogger();
Adrien Béraudcd8fea92023-09-20 14:16:36 -0400175 auto factory = std::make_shared<IceTransportFactory>(logger);
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400176 auto ioContext = std::make_shared<asio::io_context>();
177 auto ioContextRunner = std::make_shared<std::thread>([context = ioContext]() {
178 try {
179 auto work = asio::make_work_guard(*context);
180 context->run();
181 } catch (const std::exception& ex) {
Amnab31c3742023-08-28 13:58:31 -0400182 fmt::print(stderr, "Exception: {}\n", ex.what());
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400183 }
184 });
Amnab31c3742023-08-28 13:58:31 -0400185
186 BenchResult total = {0s, 0s, false};
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400187 unsigned total_success = 0;
188 constexpr unsigned ITERATIONS = 20;
189 for (unsigned i = 0; i < ITERATIONS; ++i) {
Amnab31c3742023-08-28 13:58:31 -0400190 fmt::print("Iteration {}\n", i);
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400191 auto res = runBench(ioContext, ioContextRunner, factory, logger);
192 if (res.success) {
193 total.connection += res.connection;
194 total.send += res.send;
195 total_success++;
196 }
197 }
Amnab31c3742023-08-28 13:58:31 -0400198 fmt::print("Average connection time: {}\n", dht::print_duration(total.connection / total_success));
199 fmt::print("Average send time: {}\n", dht::print_duration(total.send / total_success));
200 fmt::print("Total success: {}\n", total_success);
201
Adrien Béraud6c6a9622023-08-27 12:49:31 -0400202 std::this_thread::sleep_for(500ms);
203 ioContext->stop();
204 ioContextRunner->join();
205}
206
207}
208
209static void
210setSipLogLevel()
211{
212 int level = 0;
213 if (char* envvar = getenv("SIPLOGLEVEL")) {
214 // From 0 (min) to 6 (max)
215 level = std::clamp(std::stoi(envvar), 0, 6);
216 }
217
218 pj_log_set_level(level);
219 pj_log_set_log_func([](int level, const char* data, int /*len*/) {
220 });
221}
222
223int
224main(int argc, char** argv)
225{
226 setSipLogLevel();
227 dhtnet::bench();
228 return 0;
229}