From eba7ac39c94fde91283f7f491eb89aaffd714943 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Thu, 20 Feb 2025 18:29:09 +0300 Subject: [PATCH] ... --- cxx/CMakeLists.txt | 4 ++ cxx/comm_server.h | 87 ++++++++++++++++++++++++++++++-------------- cxx/mount_server.cpp | 14 +++++++ 3 files changed, 78 insertions(+), 27 deletions(-) create mode 100644 cxx/mount_server.cpp diff --git a/cxx/CMakeLists.txt b/cxx/CMakeLists.txt index 63f6b67..ab66677 100644 --- a/cxx/CMakeLists.txt +++ b/cxx/CMakeLists.txt @@ -85,6 +85,10 @@ set(CNTR_PROTO_LIB_SRC set(CNTR_PROTO_LIB comm_proto) add_library(${CNTR_PROTO_LIB} STATIC ${CNTR_PROTO_LIB_SRC}) +set(MOUNT_SERVER_APP_SRC mount.h mount_server.cpp comm_server.h) +set(MOUNT_SERVER_APP mount_server) +add_executable(${MOUNT_SERVER_APP} ${MOUNT_SERVER_APP_SRC}) +target_link_libraries(${MOUNT_SERVER_APP} ${CNTR_PROTO_LIB} spdlog::spdlog_header_only) if (WITH_TESTS) set(CNTR_PROTO_TEST_APP cntr_proto_test) diff --git a/cxx/comm_server.h b/cxx/comm_server.h index 6c0ae52..08d17b7 100644 --- a/cxx/comm_server.h +++ b/cxx/comm_server.h @@ -16,6 +16,7 @@ #include #include +#include #include #include "comm_server_endpoint.h" @@ -75,7 +76,7 @@ public: static constexpr std::chrono::duration DEFAULT_RCV_TIMEOUT = std::chrono::hours(12); static constexpr std::chrono::duration DEFAULT_SND_TIMEOUT = std::chrono::milliseconds(2000); - MccMountServer(asio::io_context& ctx, std::shared_ptr logger) + MccMountServer(asio::io_context& ctx, std::shared_ptr logger = spdlog::null_logger_mt("NULL")) : _asioContext(ctx), _serverLogger(std::move(logger)) { } @@ -84,21 +85,18 @@ public: template - asio::awaitable listen(std::derived_from auto endpoint, CtorArgTs&&... ctor_args) + asio::awaitable listen(std::derived_from auto endpoint, CtorArgTs&&... ctor_args) { - bool exit_flag = false; - if (!endpoint.isValid()) { _serverLogger->error("Cannot start listening! Invalid endpoint string representation ('{}')!", endpoint.endpoint()); - co_return exit_flag; + co_return; } // add root path to endpoint one std::filesystem::path pt("/"); pt += endpoint.path(); - auto args = std::make_tuple(std::forward(ctor_args)...); if (endpoint.isLocalSerial()) { asio::serial_port s_port(_asioContext); @@ -112,26 +110,26 @@ public: s_port.open(pt.string(), ec); if (ec) { _serverLogger->error("Cannot open serial device '{}' (Error = '{}')!", pt.string(), ec.message()); - co_return exit_flag; + co_return; } // asio::co_spawn(_asioContext, listen(std::move(s_port)), asio::detached); - co_return listen(std::move(s_port)); + co_await listen(std::move(s_port)); } else if (endpoint.isLocal()) { // create abstract namespace socket endpoint if its path starts from '@' symbol endpoint.makeAbstract('@'); if (endpoint.isLocalStream()) { - co_return listen(asio::local::stream_protocol::endpoint(pt.string())); + co_await listen(asio::local::stream_protocol::endpoint(pt.string())); // asio::co_spawn(_asioContext, listen(asio::local::stream_protocol::endpoint(pt.string())), // asio::detached); } else if (endpoint.isLocalSeqpacket()) { - co_return listen(asio::local::seq_packet_protocol::endpoint(pt.string())); + co_await listen(asio::local::seq_packet_protocol::endpoint(pt.string())); // asio::co_spawn(_asioContext, listen(asio::local::seq_packet_protocol::endpoint(pt.string())), // asio::detached); } else { - co_return exit_flag; // ???!!!! + co_return; // it must not be!!!! } } else if (endpoint.isTCP()) { // resolve hostname @@ -140,27 +138,49 @@ public: auto r_result = co_await res.async_resolve(endpoint.host(), endpoint.portView(), asio::use_awaitable); + _serverLogger->info("Resolve hostname <{}> to {} IP-addresses", endpoint.host(), r_result.size()); + + + bool exit_flag = false; + asio::ip::tcp::acceptor acc(_asioContext); + for (auto const& epn : r_result) { - exit_flag = co_await listen(epn); - if (exit_flag) { + try { + // std::stringstream st; + + _serverLogger->debug("Create connection acceptor for endpoint <{}> ...", + epn.address().to_string()); + acc = asio::ip::tcp::acceptor(_asioContext, epn); + // st << acc.local_endpoint(); + exit_flag = true; break; + } catch (const std::system_error& err) { + _serverLogger->error("An error occuring while creating connection acceptor (ec = {})", + err.what()); + continue; } } if (!exit_flag) { _serverLogger->error("Cannot start listening on any resolved endpoints!"); - co_return exit_flag; + co_return; } - // listen(std::move(*r_result.begin())); + _tcpAcceptors.emplace_back(&acc); + + _serverLogger->info("Start listening at <{}> endpoint ...", acc.local_endpoint().address().to_string()); + + // start accepting connections + for (;;) { + auto sock = co_await acc.async_accept(asio::use_awaitable); + // start new client session + asio::co_spawn(_asioContext, startSession(std::move(sock)), asio::detached); + } } catch (const std::system_error& err) { - _serverLogger->error("An error occured while resolving '{}' hostname (Error = '{}')", endpoint.host(), - err.code().message()); - co_return exit_flag; + _serverLogger->error("An error occured while trying to start accepting connections! ec = '{}'", + err.what()); } } - - co_return true; } template @@ -186,10 +206,14 @@ public: try { std::stringstream st; - _serverLogger->debug("Create connection acceptor ..."); + st << endpoint; + _serverLogger->debug("Create connection acceptor for endpoint <{}> ...", st.str()); auto acc = epn_t::protocol_type::acceptor(_asioContext, endpoint); + + st.str(""); st << acc.local_endpoint(); - _serverLogger->info("Try to start listening at <{}> endpoint ...", st.str()); + _serverLogger->info("Start listening at <{}> endpoint ...", st.str()); + if constexpr (traits::is_tcp_proto) { _tcpAcceptors.emplace_back(&acc); @@ -315,7 +339,7 @@ private: std::vector handleClientCommand(std::string_view command) { - std::vector resp; + std::vector resp{BM700::CONTROL_PROTO_STR_RESP_ACK.begin(), BM700::CONTROL_PROTO_STR_RESP_ACK.end()}; return resp; } @@ -353,13 +377,22 @@ private: asio::streambuf sbuff; size_t nbytes; std::stringstream st; + std::string r_epn; - st << socket.remote_endpoint(); - std::string r_epn = st.str(); - - st.str() = ""; st << std::this_thread::get_id(); std::string thr_id = st.str(); + st.str(""); + + if constexpr (traits::is_serial_proto) { + st << "serial port: " << socket.native_handle(); + } else { // network sockets + st << socket.remote_endpoint(); + } + + r_epn = st.str(); + if (r_epn.empty()) { // UNIX domain sockets + r_epn = "local"; + } _serverLogger->info("Start client session: remote endpoint <{}> (session thread ID = {})", r_epn, thr_id); diff --git a/cxx/mount_server.cpp b/cxx/mount_server.cpp new file mode 100644 index 0000000..04b4e27 --- /dev/null +++ b/cxx/mount_server.cpp @@ -0,0 +1,14 @@ +#include "comm_server.h" + +#include +#include + +int main() +{ + asio::io_context ctx; + + mcc::MccMountServer server(ctx, spdlog::stdout_color_mt("STDOUT_LOGGER")); + + + ctx.run(); +}