blob: 06b92080254251457559b7fbe4981d5f6d057439 [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,
Amna45db7762024-07-24 18:33:48 -040056 const std::string& turn_realm,
57 const bool enable_upnp)
Amna38768302023-08-21 11:51:56 -040058{
Amna38768302023-08-21 11:51:56 -040059 // DHT node creation: To make a connection manager at first a DHT node should be created
Amna38768302023-08-21 11:51:56 -040060 dht::DhtRunner::Config dhtConfig;
61 dhtConfig.dht_config.id = identity;
62 dhtConfig.threaded = true;
63 dhtConfig.peer_discovery = false;
64 dhtConfig.peer_publish = false;
65 dht::DhtRunner::Context dhtContext;
66 dhtContext.identityAnnouncedCb = [logger](bool ok) {
67 if (logger)
68 logger->debug("Identity announced {}\n", ok);
69 };
Amna7c973d52023-09-25 14:12:29 -040070 dhtContext.certificateStore = [certStore](const dht::InfoHash& pk_id) {
Amna38768302023-08-21 11:51:56 -040071 std::vector<std::shared_ptr<dht::crypto::Certificate>> ret;
Amna2f3539b2023-09-18 13:59:22 -040072 if (auto cert = certStore->getCertificate(pk_id.toString()))
Amna38768302023-08-21 11:51:56 -040073 ret.emplace_back(std::move(cert));
74 return ret;
75 };
76 auto runner = std::make_shared<dht::DhtRunner>();
77 runner->run(dhtConfig, std::move(dhtContext));
Adrien Béraudecde63f2023-08-26 18:11:21 -040078 runner->bootstrap(bootstrap);
Amna38768302023-08-21 11:51:56 -040079
80 // DHT node creation end:
81 // ConnectionManager creation:
82 auto config = std::make_unique<ConnectionManager::Config>();
83 config->dht = runner;
84 config->id = identity;
85 config->ioContext = ioContext;
Amna2f3539b2023-09-18 13:59:22 -040086 config->certStore = certStore;
Amna0e5f0762024-05-06 15:40:14 -040087 config->cachePath = cachePath();
Amna2f3539b2023-09-18 13:59:22 -040088 config->factory = iceFactory;
Adrien Béraudecde63f2023-08-26 18:11:21 -040089 config->logger = logger;
Amna41848a22024-01-22 16:22:57 -050090 if (!turn_host.empty()){
Amna2f3539b2023-09-18 13:59:22 -040091 config->turnEnabled = true;
Amna41848a22024-01-22 16:22:57 -050092 config->turnServer = turn_host;
93 config->turnServerUserName = turn_user;
94 config->turnServerPwd = turn_pass;
95 config->turnServerRealm = turn_realm;
96 }
Amna45db7762024-07-24 18:33:48 -040097
98 if (enable_upnp) {
99 // UPnP configuration
100 auto upnpContext = std::make_shared<dhtnet::upnp::UPnPContext>(ioContext, logger);
101 auto controller = std::make_shared<dhtnet::upnp::Controller>(upnpContext);
102 config->upnpEnabled = true;
103 config->upnpCtrl = controller;
104 }
105
Amna38768302023-08-21 11:51:56 -0400106 return std::move(config);
107}
Amna2f3539b2023-09-18 13:59:22 -0400108template<typename T>
109void
110readFromPipe(std::shared_ptr<ChannelSocket> socket, T input, Buffer buffer)
Amna38768302023-08-21 11:51:56 -0400111{
112 asio::async_read(*input,
113 asio::buffer(*buffer),
114 asio::transfer_at_least(1),
115 [socket, input, buffer](const asio::error_code& error, size_t bytesRead) {
116 if (!error) {
117 // Process the data received in the buffer
118 std::error_code ec;
Amna2f3539b2023-09-18 13:59:22 -0400119 // Write the data to the socket
Amna38768302023-08-21 11:51:56 -0400120 socket->write(buffer->data(), bytesRead, ec);
121 if (!ec) {
122 // Continue reading more data
123 readFromPipe(socket, input, buffer);
124 } else {
Amna2f3539b2023-09-18 13:59:22 -0400125 fmt::print(stderr, "Error writing to socket: {}\n", ec.message());
Amna38768302023-08-21 11:51:56 -0400126 }
Amna2f3539b2023-09-18 13:59:22 -0400127 } else if (error == asio::error::eof) {
128 // Connection closed cleanly by peer.
129 socket->shutdown();
130 }else{
Amna38768302023-08-21 11:51:56 -0400131 fmt::print(stderr, "Error reading from stdin: {}\n", error.message());
Amna38768302023-08-21 11:51:56 -0400132 }
133 });
134}
135
Amna2f3539b2023-09-18 13:59:22 -0400136template void readFromPipe(std::shared_ptr<ChannelSocket> socket,
137 std::shared_ptr<asio::posix::stream_descriptor> input,
138 Buffer buffer);
139template void readFromPipe(std::shared_ptr<ChannelSocket> socket,
140 std::shared_ptr<asio::ip::tcp::socket> input,
141 Buffer buffer);
Amna38768302023-08-21 11:51:56 -0400142
143} // namespace dhtnet