#pragma once #include #include #include #include #include #include #include "comm_server_endpoint.h" #include "mount.h" namespace mcc { namespace traits { template concept mcc_endpoint_c = std::derived_from || std::derived_from || std::derived_from || std::derived_from; template static constexpr bool is_serial_proto = std::derived_from; template static constexpr bool is_tcp_proto = std::derived_from; template static constexpr bool is_local_stream_proto = std::derived_from; template static constexpr bool is_local_seqpack_proto = std::derived_from; } // namespace traits class MccMountServer { public: MccMountServer(asio::io_context& ctx, std::shared_ptr logger) : _asioContext(ctx), _serverLogger(std::move(logger)) { } ~MccMountServer() {} void listen(traits::mcc_endpoint_c auto endpoint) { using epn_t = std::decay_t; std::error_code ec; if constexpr (traits::is_serial_proto) { // first, check if port is openned if (!endpoint.is_open()) { if (ec) { // ?????????? _serverLogger->error("Serial port was not open!"); return; } } _serialPorts.emplace_back(std::move(endpoint)); } else if constexpr (traits::is_tcp_proto) { } else if constexpr (traits::is_local_stream_proto) { } else if constexpr (traits::is_local_seqpack_proto) { } else { static_assert(false, "INVALID ENDPOINT!!!"); } } // close listening on all endpoints void stop() { std::error_code ec; size_t N = 0, M = 0; _serverLogger->info("Close all listening endpoints ..."); auto num = _serialPorts.size() + _tcpAcceptors.size() + _localStreamAcceptors.size() + _localSeqpackAcceptors.size(); if (!num) { _serverLogger->info("There are no listening ports/sockets!"); return; } if (_serialPorts.size()) { _serverLogger->debug("Close serial ports ..."); for (auto& s_port : _serialPorts) { s_port.close(ec); if (ec) { _serverLogger->error("Cannot close serial port! ec = '{}'", ec.message()); ++M; } ++N; } _serverLogger->debug("{} from {} serial ports were closed!", M, N); _serialPorts.clear(); } if (_tcpAcceptors.size()) { _serverLogger->debug("Close TCP listening sockets ..."); N = 0; M = 0; for (auto& acc : _tcpAcceptors) { acc.close(ec); if (ec) { _serverLogger->error("Cannot close TCP socket! ec = '{}'", ec.message()); ++M; } ++N; } _serverLogger->debug("{} from {} TCP sockets were closed!", M, N); _tcpAcceptors.clear(); } if (_localStreamAcceptors.size()) { _serverLogger->debug("Close local stream listening sockets ..."); N = 0; M = 0; for (auto& acc : _localStreamAcceptors) { acc.close(ec); if (ec) { _serverLogger->error("Cannot close local stream socket! ec = '{}'", ec.message()); ++M; } ++N; } _serverLogger->debug("{} from {} local stream sockets were closed!", M, N); _localStreamAcceptors.clear(); } if (_localSeqpackAcceptors.size()) { _serverLogger->debug("Close local seqpack listening sockets ..."); N = 0; M = 0; for (auto& acc : _localSeqpackAcceptors) { acc.close(ec); if (ec) { _serverLogger->error("Cannot close local seqpack socket! ec = '{}'", ec.message()); ++M; } ++N; } _serverLogger->debug("{} from {} local seqpack sockets were closed!", M, N); _localSeqpackAcceptors.clear(); } _serverLogger->info("The all server listening endpoints were closed!"); } private: asio::io_context& _asioContext; std::shared_ptr _serverLogger; std::vector _serialPorts; std::vector _tcpAcceptors; std::vector _localStreamAcceptors; std::vector _localSeqpackAcceptors; void startAccept(traits::mcc_endpoint_c auto endpoint) { using epn_t = std::decay_t; try { std::stringstream st; auto acc = epn_t::protocol_type::endpoint(_asioContext, endpoint); st << acc.local_endpoint(); _serverLogger->info("Try to start listening at <{}> endpoint ...", st.str()); if constexpr (traits::is_tcp_proto) { _tcpAcceptors.emplace_back(std::move(acc)); } else if constexpr (traits::is_local_stream_proto) { _localStreamAcceptors.emplace_back(std::move(acc)); } else if constexpr (traits::is_local_seqpack_proto) { _localSeqpackAcceptors.emplace_back(std::move(acc)); } else { static_assert(false, "INVALID ENDPOINT!!!"); } } catch (const std::system_error& err) { _serverLogger->error("An error occured while creating of connection acceptor! ec = '{}'", err.what()); } } template void doAccept() { } }; } // namespace mcc