blob: 7b10bfd817cb77cc31e6fd9341fda3e7674d94bb [file] [log] [blame]
Amna38768302023-08-21 11:51:56 -04001/*
Amna2f3539b2023-09-18 13:59:22 -04002 * Copyright (C) 2023 Savoir-faire Linux Inc.
Amna38768302023-08-21 11:51:56 -04003 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (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
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * 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 */
17#include "certstore.h"
Amna38768302023-08-21 11:51:56 -040018#include "connectionmanager.h"
19#include "common.h"
20#include "fileutils.h"
21#include "ice_transport.h"
22
Adrien Béraudc1cac452023-08-22 20:32:36 -040023#include <opendht/crypto.h>
Amna38768302023-08-21 11:51:56 -040024#include <string>
25#include <filesystem>
26#include <unistd.h>
27#include <fcntl.h>
28#include <asio.hpp>
29
30namespace dhtnet {
31
Amna0e5f0762024-05-06 15:40:14 -040032std::filesystem::path cachePath()
33{
34 auto* cache_path = getenv("DHTNET_CACHE_DIR");
35 if (cache_path) {
36 return std::filesystem::path(cache_path);
37 }
38 auto* home = getenv("HOME");
39 if (home) {
40 return std::filesystem::path(home) / ".cache" / "dhtnet";
41 }
42 // If user got no HOME and no DHTNET_CACHE_DIR set, use /tmp
43 return std::filesystem::path("/tmp");
44}
45
Amna38768302023-08-21 11:51:56 -040046std::unique_ptr<ConnectionManager::Config>
Amnac75ffe92024-02-08 17:23:29 -050047connectionManagerConfig(dht::crypto::Identity identity,
Amna2f3539b2023-09-18 13:59:22 -040048 const std::string& bootstrap,
49 std::shared_ptr<Logger> logger,
50 std::shared_ptr<tls::CertificateStore> certStore,
51 std::shared_ptr<asio::io_context> ioContext,
52 std::shared_ptr<IceTransportFactory> iceFactory,
53 const std::string& turn_host,
54 const std::string& turn_user,
55 const std::string& turn_pass,
56 const std::string& turn_realm)
Amna38768302023-08-21 11:51:56 -040057{
Amna38768302023-08-21 11:51:56 -040058 // DHT node creation: To make a connection manager at first a DHT node should be created
Amna38768302023-08-21 11:51:56 -040059 dht::DhtRunner::Config dhtConfig;
60 dhtConfig.dht_config.id = identity;
61 dhtConfig.threaded = true;
62 dhtConfig.peer_discovery = false;
63 dhtConfig.peer_publish = false;
64 dht::DhtRunner::Context dhtContext;
65 dhtContext.identityAnnouncedCb = [logger](bool ok) {
66 if (logger)
67 logger->debug("Identity announced {}\n", ok);
68 };
Amna7c973d52023-09-25 14:12:29 -040069 dhtContext.certificateStore = [certStore](const dht::InfoHash& pk_id) {
Amna38768302023-08-21 11:51:56 -040070 std::vector<std::shared_ptr<dht::crypto::Certificate>> ret;
Amna2f3539b2023-09-18 13:59:22 -040071 if (auto cert = certStore->getCertificate(pk_id.toString()))
Amna38768302023-08-21 11:51:56 -040072 ret.emplace_back(std::move(cert));
73 return ret;
74 };
75 auto runner = std::make_shared<dht::DhtRunner>();
76 runner->run(dhtConfig, std::move(dhtContext));
Adrien Béraudecde63f2023-08-26 18:11:21 -040077 runner->bootstrap(bootstrap);
Amna38768302023-08-21 11:51:56 -040078
79 // DHT node creation end:
80 // ConnectionManager creation:
81 auto config = std::make_unique<ConnectionManager::Config>();
82 config->dht = runner;
83 config->id = identity;
84 config->ioContext = ioContext;
Amna2f3539b2023-09-18 13:59:22 -040085 config->certStore = certStore;
Amna0e5f0762024-05-06 15:40:14 -040086 config->cachePath = cachePath();
Amna2f3539b2023-09-18 13:59:22 -040087 config->factory = iceFactory;
Adrien Béraudecde63f2023-08-26 18:11:21 -040088 config->logger = logger;
Amna41848a22024-01-22 16:22:57 -050089 if (!turn_host.empty()){
Amna2f3539b2023-09-18 13:59:22 -040090 config->turnEnabled = true;
Amna41848a22024-01-22 16:22:57 -050091 config->turnServer = turn_host;
92 config->turnServerUserName = turn_user;
93 config->turnServerPwd = turn_pass;
94 config->turnServerRealm = turn_realm;
95 }
Amna38768302023-08-21 11:51:56 -040096 return std::move(config);
97}
Amna2f3539b2023-09-18 13:59:22 -040098template<typename T>
99void
100readFromPipe(std::shared_ptr<ChannelSocket> socket, T input, Buffer buffer)
Amna38768302023-08-21 11:51:56 -0400101{
102 asio::async_read(*input,
103 asio::buffer(*buffer),
104 asio::transfer_at_least(1),
105 [socket, input, buffer](const asio::error_code& error, size_t bytesRead) {
106 if (!error) {
107 // Process the data received in the buffer
108 std::error_code ec;
Amna2f3539b2023-09-18 13:59:22 -0400109 // Write the data to the socket
Amna38768302023-08-21 11:51:56 -0400110 socket->write(buffer->data(), bytesRead, ec);
111 if (!ec) {
112 // Continue reading more data
113 readFromPipe(socket, input, buffer);
114 } else {
Amna2f3539b2023-09-18 13:59:22 -0400115 fmt::print(stderr, "Error writing to socket: {}\n", ec.message());
Amna38768302023-08-21 11:51:56 -0400116 }
Amna2f3539b2023-09-18 13:59:22 -0400117 } else if (error == asio::error::eof) {
118 // Connection closed cleanly by peer.
119 socket->shutdown();
120 }else{
Amna38768302023-08-21 11:51:56 -0400121 fmt::print(stderr, "Error reading from stdin: {}\n", error.message());
Amna38768302023-08-21 11:51:56 -0400122 }
123 });
124}
125
Amna2f3539b2023-09-18 13:59:22 -0400126template void readFromPipe(std::shared_ptr<ChannelSocket> socket,
127 std::shared_ptr<asio::posix::stream_descriptor> input,
128 Buffer buffer);
129template void readFromPipe(std::shared_ptr<ChannelSocket> socket,
130 std::shared_ptr<asio::ip::tcp::socket> input,
131 Buffer buffer);
Amna38768302023-08-21 11:51:56 -0400132
133} // namespace dhtnet