From b7fcb0970c1891a194ad1600c05bebcd7b229291 Mon Sep 17 00:00:00 2001 From: giskard Date: Sun, 6 Oct 2024 17:18:43 +0800 Subject: [PATCH] udp2p: basic setup --- src/udp2p/peer.cc | 25 ++++++++++++++++++ src/udp2p/peer.h | 54 ++++++++++++++++++++++++++++++++++++++ src/udp2p/server.cc | 44 +++++++++++++++++++++++++++++++ src/udp2p/server.h | 33 ++++++++++++++++++++++++ src/udp2p/udp2p.cc | 63 +++++++++++++++++++++++++++++++++++++++++++++ src/udp2p/udp2p.h | 53 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 272 insertions(+) create mode 100644 src/udp2p/peer.cc create mode 100644 src/udp2p/peer.h create mode 100644 src/udp2p/server.cc create mode 100644 src/udp2p/server.h create mode 100644 src/udp2p/udp2p.cc create mode 100644 src/udp2p/udp2p.h diff --git a/src/udp2p/peer.cc b/src/udp2p/peer.cc new file mode 100644 index 0000000..5f9aa87 --- /dev/null +++ b/src/udp2p/peer.cc @@ -0,0 +1,25 @@ +#include + +#include "peer.h" + +namespace mtrx { +namespace udp2p { + +void Peer::run() { + logger_->info("run .."); + + // TODO: do_sth() + asio::steady_timer t(ctx_, asio::chrono::seconds(2)); + t.async_wait([&](const std::error_code &) { logger_->info("timer done"); }); + + ctx_.run(); +}; + +uint64_t Peer::connectServer() { + return 0; +}; + +void Peer::disconnectServer() {}; + +}; // namespace udp2p +}; // namespace mtrx diff --git a/src/udp2p/peer.h b/src/udp2p/peer.h new file mode 100644 index 0000000..c02e1f0 --- /dev/null +++ b/src/udp2p/peer.h @@ -0,0 +1,54 @@ +#ifndef INCLUDE_UDP2P_PEER_H +#define INCLUDE_UDP2P_PEER_H + +#include + +#include +#include + +#include + +namespace mtrx { +namespace udp2p { + +struct PeerInfo { + uint64_t id; // peer id generated by server + + int localPort; // local port to send and to accept packets +}; + +class Peer { + public: + Peer(asio::io_context & ctx) : ctx_(ctx) { + logger_ = spdlog::default_logger()->clone("peer"); + }; + + ~Peer(){}; + + void run(); + void stop(); + + uint64_t connectServer(); + void disconnectServer(); + + bool scanInfo(); + bool reportInfo(); + + bool getPeerInfo(); + void connectPeer(); + void disconnectPeer(); + + bool connectPeerByHP(); // hole punching, luky? + bool connectPeerByLocalAddr(); + bool connectPeerByRelay(); + + private: + PeerInfo info; + asio::io_context & ctx_; + std::shared_ptr logger_; +}; + +}; // namespace udp2p +}; // namespace mtrx + +#endif diff --git a/src/udp2p/server.cc b/src/udp2p/server.cc new file mode 100644 index 0000000..44c25e9 --- /dev/null +++ b/src/udp2p/server.cc @@ -0,0 +1,44 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "server.h" +#include "utils/misc.h" + +namespace mtrx { +namespace udp2p { + +void Server::serv(const std::string & addr, uint port) { + logger_->info("serv .."); + + auto endpoint = asio::ip::udp::endpoint(asio::ip::make_address(addr), port); + auto socket = asio::ip::udp::socket(ctx_, endpoint); + + asio::co_spawn( + ctx_, + [&socket, this]() -> asio::awaitable { + char buffer[1024]; + asio::ip::udp::endpoint remote_endpoint; + while (true) { + size_t n = co_await socket.async_receive_from( + asio::buffer(buffer), remote_endpoint, asio::use_awaitable); + + logger_->debug("get: {}", utils::hexFromBytes(buffer, n)); + + co_await socket.async_send_to(asio::buffer(buffer, n), remote_endpoint, + asio::use_awaitable); + } + }, + asio::detached); + + ctx_.run(); +} + +}; // namespace udp2p +}; // namespace mtrx diff --git a/src/udp2p/server.h b/src/udp2p/server.h new file mode 100644 index 0000000..c774a80 --- /dev/null +++ b/src/udp2p/server.h @@ -0,0 +1,33 @@ +#ifndef INCLUDE_UDP2P_SERVER_H +#define INCLUDE_UDP2P_SERVER_H + +#include +#include + +#include "udp2p/manager.h" + +namespace mtrx { +namespace udp2p { + +class Server { + public: + Server(asio::io_context & ctx) : ctx_(ctx) { + logger_ = spdlog::default_logger()->clone("server"); + }; + + void serv(const std::string & addr, uint port); + + private: + asio::io_context & ctx_; + AuthManager authKeeper_; + std::shared_ptr logger_; +}; + +class Relay { + public: + void serv(); +}; + +}; // namespace udp2p +}; // namespace mtrx +#endif diff --git a/src/udp2p/udp2p.cc b/src/udp2p/udp2p.cc new file mode 100644 index 0000000..ae610a6 --- /dev/null +++ b/src/udp2p/udp2p.cc @@ -0,0 +1,63 @@ +#include +#include +#include + +#include +#include +#include + +#include "udp2p.h" + +namespace mtrx { +namespace udp2p { + +void Udp2p::run() { + logger_->info("run mode: {}", static_cast(config_.mode)); + + switch (config_.mode) { + case Udp2p_Mode::UDP2P_MODE_PEER: + peer_ptr_ = std::make_unique(ctx_); + break; + case Udp2p_Mode::UDP2P_MODE_SERVER: + server_ptr_ = std::make_unique(ctx_); + break; + case Udp2p_Mode::UDP2P_MODE_HYBRID: + peer_ptr_ = std::make_unique(ctx_); + server_ptr_ = std::make_unique(ctx_); + break; + } + + // hold sub threads to join at the end + std::vector threads; + if (peer_ptr_) + threads.push_back(std::thread([this]() { peer_ptr_->run(); })); + if (server_ptr_) + threads.push_back(std::thread( + [this]() { server_ptr_->serv(config_.server_addr, config_.server_port); })); + + // handle signals + asio::signal_set signals(ctx_, SIGINT, SIGTERM); + signals.async_wait([&](const asio::error_code & ec, int sig_num) { + if (!ec) { + logger_->warn("get signal: {}({})", sig_num, strsignal(sig_num)); + stop(); + } else + logger_->warn("signal ec: {}, {}", ec.value(), ec.message()); + }); + + // run the event loop + ctx_.run(); + + // wait sub threads + for (auto & t : threads) + t.join(); +} + +void Udp2p::stop() { + logger_->info("stop .."); + // notify peer/server via the stop + ctx_.stop(); +} + +}; // namespace udp2p +}; // namespace mtrx diff --git a/src/udp2p/udp2p.h b/src/udp2p/udp2p.h new file mode 100644 index 0000000..a66f3e2 --- /dev/null +++ b/src/udp2p/udp2p.h @@ -0,0 +1,53 @@ +#ifndef INCLUDE_UDP2P_UDP2P_H +#define INCLUDE_UDP2P_UDP2P_H + +#include +#include +#include + +#include +#include + +#include "udp2p/peer.h" +#include "udp2p/server.h" + +namespace mtrx { +namespace udp2p { + +enum class Udp2p_Mode { + UDP2P_MODE_PEER, // peer only + UDP2P_MODE_SERVER, // server only + UDP2P_MODE_HYBRID // peer + server +}; + +class Config { + public: + Udp2p_Mode mode; + std::string server_addr; + int server_port; + uint64_t peer_id; // peer to connect +}; + +class Udp2p { + public: + Udp2p(Config & config) : config_(config) { + logger_ = spdlog::default_logger()->clone("udp2p"); + } + + void run(); + void stop(); + + private: + Config & config_; + asio::io_context ctx_; + + std::unique_ptr server_ptr_ = nullptr; + std::unique_ptr peer_ptr_ = nullptr; + + std::shared_ptr logger_; +}; + +}; // namespace udp2p +}; // namespace mtrx + +#endif