Skip to content
Snippets Groups Projects
Commit 2f3539bc authored by Amna Snene's avatar Amna Snene
Browse files

tool/dnc: update dnc

Change-Id: I3c790221ed78af80f88a2bb54bf2319b27235be6
parent 4a70f5ce
No related branches found
No related tags found
No related merge requests found
/*
* Copyright (C) 2004-2023 Savoir-faire Linux Inc.
* Copyright (C) 2023 Savoir-faire Linux Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -21,7 +21,6 @@
#include "ice_transport.h"
#include <opendht/crypto.h>
#include <iostream>
#include <string>
#include <filesystem>
#include <unistd.h>
......@@ -40,8 +39,7 @@ loadIdentity(const std::filesystem::path& path)
for (const auto& path : std::filesystem::directory_iterator(path)) {
auto p = path.path();
if (p.extension() == ".pem") {
auto privateKey = std::make_unique<dht::crypto::PrivateKey>(
fileutils::loadFile(p));
auto privateKey = std::make_unique<dht::crypto::PrivateKey>(fileutils::loadFile(p));
auto certificate = std::make_unique<dht::crypto::Certificate>(
fileutils::loadFile(p.replace_extension(".crt")));
return dht::crypto::Identity(std::move(privateKey), std::move(certificate));
......@@ -53,6 +51,7 @@ loadIdentity(const std::filesystem::path& path)
auto ca = dht::crypto::generateIdentity("ca");
auto id = dht::crypto::generateIdentity("dhtnc", ca);
fmt::print("Generated new identity: {}\n", id.first->getPublicKey().getId());
dht::crypto::saveIdentity(id, path / "id");
return id;
}
......@@ -62,9 +61,13 @@ connectionManagerConfig(const std::filesystem::path& path,
dht::crypto::Identity identity,
const std::string& bootstrap,
std::shared_ptr<Logger> logger,
tls::CertificateStore& certStore,
std::shared_ptr<tls::CertificateStore> certStore,
std::shared_ptr<asio::io_context> ioContext,
IceTransportFactory& iceFactory)
std::shared_ptr<IceTransportFactory> iceFactory,
const std::string& turn_host,
const std::string& turn_user,
const std::string& turn_pass,
const std::string& turn_realm)
{
std::filesystem::create_directories(path / "certstore");
......@@ -81,7 +84,7 @@ connectionManagerConfig(const std::filesystem::path& path,
};
dhtContext.certificateStore = [&](const dht::InfoHash& pk_id) {
std::vector<std::shared_ptr<dht::crypto::Certificate>> ret;
if (auto cert = certStore.getCertificate(pk_id.toString()))
if (auto cert = certStore->getCertificate(pk_id.toString()))
ret.emplace_back(std::move(cert));
return ret;
};
......@@ -95,15 +98,23 @@ connectionManagerConfig(const std::filesystem::path& path,
config->dht = runner;
config->id = identity;
config->ioContext = ioContext;
config->certStore = &certStore;
config->factory = &iceFactory;
config->certStore = certStore;
config->factory = iceFactory;
config->cachePath = path;
config->logger = logger;
if (!turn_host.empty())
config->turnEnabled = true;
config->turnServer = turn_host;
config->turnServerUserName = turn_user;
config->turnServerPwd = turn_pass;
config->turnServerRealm = turn_realm;
return std::move(config);
}
template<typename T>
void readFromPipe(std::shared_ptr<ChannelSocket> socket, T input, Buffer buffer)
void
readFromPipe(std::shared_ptr<ChannelSocket> socket, T input, Buffer buffer)
{
asio::async_read(*input,
asio::buffer(*buffer),
......@@ -112,26 +123,28 @@ void readFromPipe(std::shared_ptr<ChannelSocket> socket, T input, Buffer buffer)
if (!error) {
// Process the data received in the buffer
std::error_code ec;
// print the data to stdout
// Write the data to the socket
socket->write(buffer->data(), bytesRead, ec);
if (!ec) {
// Continue reading more data
readFromPipe(socket, input, buffer);
} else {
fmt::print(stderr, "Error writing to socket: {}\n", ec.message());
// logger->error("Error writing to socket: {}", ec.message());
}
} else if(error != asio::error::eof) {
} else if (error == asio::error::eof) {
// Connection closed cleanly by peer.
socket->shutdown();
}else{
fmt::print(stderr, "Error reading from stdin: {}\n", error.message());
// logger->error("Error reading from stdin: {}", error.message());
}
});
}
template void readFromPipe(std::shared_ptr<ChannelSocket> socket, std::shared_ptr<asio::posix::stream_descriptor> input, Buffer buffer);
template void readFromPipe(std::shared_ptr<ChannelSocket> socket, std::shared_ptr<asio::ip::tcp::socket> input, Buffer buffer);
template void readFromPipe(std::shared_ptr<ChannelSocket> socket,
std::shared_ptr<asio::posix::stream_descriptor> input,
Buffer buffer);
template void readFromPipe(std::shared_ptr<ChannelSocket> socket,
std::shared_ptr<asio::ip::tcp::socket> input,
Buffer buffer);
} // namespace dhtnet
\ No newline at end of file
/*
* Copyright (C) 2004-2023 Savoir-faire Linux Inc.
* Copyright (C) 2023 Savoir-faire Linux Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -23,6 +23,7 @@
namespace dhtnet {
using Buffer = std::shared_ptr<std::vector<uint8_t>>;
constexpr size_t BUFFER_SIZE = 64 * 1024;
/**
* Attempt to retrieve the identity from the .ssh directory, and if none is found, generate a new
......@@ -31,13 +32,18 @@ using Buffer = std::shared_ptr<std::vector<uint8_t>>;
*/
dht::crypto::Identity loadIdentity(const std::filesystem::path& path);
// add certstore to the config
std::unique_ptr<ConnectionManager::Config> connectionManagerConfig(const std::filesystem::path& path,
std::unique_ptr<ConnectionManager::Config> connectionManagerConfig(
const std::filesystem::path& path,
dht::crypto::Identity identity,
const std::string& bootstrap,
std::shared_ptr<Logger> logger,
tls::CertificateStore& certStore,
std::shared_ptr<tls::CertificateStore> certStore,
std::shared_ptr<asio::io_context> ioContext,
IceTransportFactory& iceFactory);
std::shared_ptr<dhtnet::IceTransportFactory> iceFactory,
const std::string& turn_host ="",
const std::string& turn_user="",
const std::string& turn_pass="",
const std::string& turn_realm="");
// add ioContext to readFromStdin
template<typename T>
......
/*
* Copyright (C) 2004-2023 Savoir-faire Linux Inc.
* Copyright (C) 2023 Savoir-faire Linux Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -27,7 +27,6 @@
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <chrono>
#include <string>
#include <string_view>
......@@ -53,16 +52,19 @@ Dnc::parseName(const std::string_view name)
return std::make_pair(ip_add, port);
}
// Build a server
Dnc::Dnc(const std::filesystem::path& path,
dht::crypto::Identity identity,
const std::string& bootstrap)
const std::string& bootstrap,
const std::string& turn_host,
const std::string& turn_user,
const std::string& turn_pass,
const std::string& turn_realm)
: logger(dht::log::getStdLogger())
, certStore(path / "certstore", logger)
// , certStore(std::shared_ptr<tls::CertificateStore>(path / "certstore", logger))
, ioContext(std::make_shared<asio::io_context>())
{
ioContext = std::make_shared<asio::io_context>();
auto certStore = std::make_shared<tls::CertificateStore>(path / "certstore", logger);
ioContextRunner = std::thread([context = ioContext, logger = logger] {
try {
auto work = asio::make_work_guard(*context);
......@@ -73,7 +75,17 @@ Dnc::Dnc(const std::filesystem::path& path,
}
});
auto config = connectionManagerConfig(path, identity, bootstrap, logger, certStore, ioContext, iceFactory);
auto config = connectionManagerConfig(path,
identity,
bootstrap,
logger,
certStore,
ioContext,
iceFactory,
turn_host,
turn_user,
turn_pass,
turn_realm);
// create a connection manager
connectionManager = std::make_unique<ConnectionManager>(std::move(config));
......@@ -113,6 +125,8 @@ Dnc::Dnc(const std::filesystem::path& path,
// Create a TCP socket
auto socket = std::make_shared<asio::ip::tcp::socket>(*ioContext);
socket->open(asio::ip::tcp::v4());
socket->set_option(asio::socket_base::keep_alive(true));
asio::async_connect(
*socket,
endpoints,
......@@ -137,8 +151,7 @@ Dnc::Dnc(const std::filesystem::path& path,
return size;
});
// Create a buffer to read data into
auto buffer = std::make_shared<std::vector<uint8_t>>(65536);
auto buffer = std::make_shared<std::vector<uint8_t>>(BUFFER_SIZE);
readFromPipe(mtlxSocket, socket, buffer);
} else {
if (logger)
......@@ -159,41 +172,42 @@ Dnc::Dnc(const std::filesystem::path& path,
const std::string& bootstrap,
dht::InfoHash peer_id,
const std::string& remote_host,
int remote_port)
: Dnc(path, identity, bootstrap)
int remote_port,
const std::string& turn_host,
const std::string& turn_user,
const std::string& turn_pass,
const std::string& turn_realm)
: Dnc(path, identity, bootstrap,turn_host,turn_user,turn_pass, turn_realm)
{
std::condition_variable cv;
auto name = fmt::format("nc://{:s}:{:d}", remote_host, remote_port);
connectionManager->connectDevice(peer_id,
name,
[&](std::shared_ptr<ChannelSocket> socket,
const dht::InfoHash&) {
connectionManager->connectDevice(
peer_id, name, [&](std::shared_ptr<ChannelSocket> socket, const dht::InfoHash&) {
if (socket) {
socket->setOnRecv(
[this, socket](const uint8_t* data, size_t size) {
socket->setOnRecv([this, socket](const uint8_t* data, size_t size) {
std::cout.write((const char*) data, size);
std::cout.flush();
return size;
});
// Create a buffer to read data into
auto buffer = std::make_shared<std::vector<uint8_t>>(65536);
auto buffer = std::make_shared<std::vector<uint8_t>>(BUFFER_SIZE);
// Create a shared_ptr to the stream_descriptor
auto stdinPipe = std::make_shared<asio::posix::stream_descriptor>(*ioContext,
::dup(STDIN_FILENO));
::dup(
STDIN_FILENO));
readFromPipe(socket, stdinPipe, buffer);
socket->onShutdown([this]() {
if (logger)
logger->error("Exit program");
std::exit(EXIT_FAILURE);
logger->debug("Exit program");
ioContext->stop();
});
}
});
connectionManager->onConnectionReady([&](const DeviceId&,
const std::string& name,
std::shared_ptr<ChannelSocket> mtlxSocket) {
connectionManager->onConnectionReady(
[&](const DeviceId&, const std::string& name, std::shared_ptr<ChannelSocket> mtlxSocket) {
if (logger)
logger->debug("Connected!");
});
......@@ -205,7 +219,6 @@ Dnc::run()
ioContext->run();
}
Dnc::~Dnc()
{
ioContext->stop();
......
/*
* Copyright (C) 2004-2023 Savoir-faire Linux Inc.
* Copyright (C) 2023 Savoir-faire Linux Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -34,22 +34,30 @@ public:
// Build a server
Dnc(const std::filesystem::path& path,
dht::crypto::Identity identity,
const std::string& bootstrap);
const std::string& bootstrap,
const std::string& turn_host,
const std::string& turn_user,
const std::string& turn_pass,
const std::string& turn_realm);
// Build a client
Dnc(const std::filesystem::path& path,
dht::crypto::Identity identity,
const std::string& bootstrap,
dht::InfoHash peer_id,
const std::string& remote_host,
int remote_port);
int remote_port,
const std::string& turn_host = "",
const std::string& turn_user = "",
const std::string& turn_pass = "",
const std::string& turn_realm = "");
~Dnc();
void run();
private:
std::unique_ptr<ConnectionManager> connectionManager;
std::shared_ptr<Logger> logger;
tls::CertificateStore certStore;
IceTransportFactory iceFactory;
std::shared_ptr<tls::CertificateStore> certStore;
std::shared_ptr<IceTransportFactory> iceFactory;
std::shared_ptr<asio::io_context> ioContext;
std::thread ioContextRunner;
......
/*
* Copyright (C) 2004-2023 Savoir-faire Linux Inc.
* Copyright (C) 2023 Savoir-faire Linux Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -34,23 +34,28 @@ struct dhtnc_params
bool help {false};
bool version {false};
bool listen {false};
bool verbose {false};
std::filesystem::path path {};
std::string bootstrap {};
std::string remote_host {};
in_port_t remote_port {};
dht::InfoHash peer_id {};
std::string turn_host {};
std::string turn_user {};
std::string turn_pass {};
std::string turn_realm {};
};
static const constexpr struct option long_options[]
= {{"help", no_argument, nullptr, 'h'},
static const constexpr struct option long_options[] = {{"help", no_argument, nullptr, 'h'},
{"version", no_argument, nullptr, 'V'},
{"verbose", no_argument, nullptr, 'v'},
{"port", required_argument, nullptr, 'p'},
{"ip", required_argument, nullptr, 'i'},
{"listen", no_argument, nullptr, 'l'},
{"bootstrap", required_argument, nullptr, 'b'},
{"id_path", required_argument, nullptr, 'I'},
{"turn_host", required_argument, nullptr, 't'},
{"turn_user", required_argument, nullptr, 'u'},
{"turn_pass", required_argument, nullptr, 'w'},
{"turn_realm", required_argument, nullptr, 'r'},
{nullptr, 0, nullptr, 0}};
dhtnc_params
......@@ -58,7 +63,7 @@ parse_args(int argc, char** argv)
{
dhtnc_params params;
int opt;
while ((opt = getopt_long(argc, argv, "hvVlI:b:p:i:", long_options, nullptr)) != -1) {
while ((opt = getopt_long(argc, argv, "hVlw:r:u:t:I:b:p:i:", long_options, nullptr)) != -1) {
// fmt::print("opt: {} {}\n", opt, optarg);
switch (opt) {
case 'h':
......@@ -67,9 +72,6 @@ parse_args(int argc, char** argv)
case 'V':
params.version = true;
break;
case 'v':
params.verbose = true;
break;
case 'p':
params.remote_port = std::stoi(optarg);
break;
......@@ -85,6 +87,18 @@ parse_args(int argc, char** argv)
case 'I':
params.path = optarg;
break;
case 't':
params.turn_host = optarg;
break;
case 'u':
params.turn_user = optarg;
break;
case 'w':
params.turn_pass = optarg;
break;
case 'r':
params.turn_realm = optarg;
break;
default:
std::cerr << "Invalid option" << std::endl;
exit(EXIT_FAILURE);
......@@ -111,6 +125,14 @@ parse_args(int argc, char** argv)
params.bootstrap = "bootstrap.jami.net";
if (params.path.empty())
params.path = std::filesystem::path(getenv("HOME")) / ".dhtnet";
if (params.turn_host.empty())
params.turn_host = "turn.jami.net";
if (params.turn_user.empty())
params.turn_user = "ring";
if (params.turn_pass.empty())
params.turn_pass = "ring";
if (params.turn_realm.empty())
params.turn_realm = "ring";
return params;
}
......@@ -124,8 +146,7 @@ setSipLogLevel()
}
pj_log_set_level(level);
pj_log_set_log_func([](int level, const char* data, int /*len*/) {
});
pj_log_set_log_func([](int level, const char* data, int /*len*/) {});
}
int
......@@ -140,14 +161,20 @@ main(int argc, char** argv)
std::unique_ptr<dhtnet::Dnc> dhtnc;
if (params.listen) {
// create dnc instance
dhtnc = std::make_unique<dhtnet::Dnc>(params.path, identity, params.bootstrap);
dhtnc = std::make_unique<dhtnet::Dnc>(params.path, identity, params.bootstrap, params.turn_host, params.turn_user, params.turn_pass, params.turn_realm);
} else {
dhtnc = std::make_unique<dhtnet::Dnc>(params.path,
identity,
params.bootstrap,
params.peer_id,
params.remote_host,
params.remote_port);
params.remote_port,
params.turn_host,
params.turn_user,
params.turn_pass,
params.turn_realm
);
}
dhtnc->run();
return EXIT_SUCCESS;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment