start network/serial communications developing
This commit is contained in:
211
cxx/comm_server.h
Normal file
211
cxx/comm_server.h
Normal file
@@ -0,0 +1,211 @@
|
||||
#pragma once
|
||||
|
||||
#include <asio/awaitable.hpp>
|
||||
#include <asio/ip/tcp.hpp>
|
||||
#include <asio/local/seq_packet_protocol.hpp>
|
||||
#include <asio/local/stream_protocol.hpp>
|
||||
#include <asio/serial_port.hpp>
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "comm_server_endpoint.h"
|
||||
#include "mount.h"
|
||||
|
||||
namespace mcc
|
||||
{
|
||||
|
||||
|
||||
namespace traits
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
concept mcc_endpoint_c = std::derived_from<T, asio::serial_port> || std::derived_from<T, asio::ip::tcp::endpoint> ||
|
||||
std::derived_from<T, asio::local::stream_protocol::endpoint> ||
|
||||
std::derived_from<T, asio::local::seq_packet_protocol::endpoint>;
|
||||
|
||||
template <typename T>
|
||||
static constexpr bool is_serial_proto = std::derived_from<T, asio::serial_port>;
|
||||
|
||||
template <typename T>
|
||||
static constexpr bool is_tcp_proto = std::derived_from<T, asio::ip::tcp::endpoint>;
|
||||
|
||||
template <typename T>
|
||||
static constexpr bool is_local_stream_proto = std::derived_from<T, asio::local::stream_protocol::endpoint>;
|
||||
|
||||
template <typename T>
|
||||
static constexpr bool is_local_seqpack_proto = std::derived_from<T, asio::local::seq_packet_protocol::endpoint>;
|
||||
|
||||
} // namespace traits
|
||||
|
||||
|
||||
class MccMountServer
|
||||
{
|
||||
public:
|
||||
MccMountServer(asio::io_context& ctx, std::shared_ptr<spdlog::logger> logger)
|
||||
: _asioContext(ctx), _serverLogger(std::move(logger))
|
||||
{
|
||||
}
|
||||
|
||||
~MccMountServer() {}
|
||||
|
||||
void listen(traits::mcc_endpoint_c auto endpoint)
|
||||
{
|
||||
using epn_t = std::decay_t<decltype(endpoint)>;
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
if constexpr (traits::is_serial_proto<epn_t>) {
|
||||
// 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<epn_t>) {
|
||||
} else if constexpr (traits::is_local_stream_proto<epn_t>) {
|
||||
} else if constexpr (traits::is_local_seqpack_proto<epn_t>) {
|
||||
} 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<spdlog::logger> _serverLogger;
|
||||
|
||||
std::vector<asio::serial_port> _serialPorts;
|
||||
std::vector<asio::ip::tcp::acceptor> _tcpAcceptors;
|
||||
std::vector<asio::local::stream_protocol::acceptor> _localStreamAcceptors;
|
||||
std::vector<asio::local::seq_packet_protocol::acceptor> _localSeqpackAcceptors;
|
||||
|
||||
void startAccept(traits::mcc_endpoint_c auto endpoint)
|
||||
{
|
||||
using epn_t = std::decay_t<decltype(endpoint)>;
|
||||
|
||||
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<epn_t>) {
|
||||
_tcpAcceptors.emplace_back(std::move(acc));
|
||||
} else if constexpr (traits::is_local_stream_proto<epn_t>) {
|
||||
_localStreamAcceptors.emplace_back(std::move(acc));
|
||||
} else if constexpr (traits::is_local_seqpack_proto<epn_t>) {
|
||||
_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 <typename AccT>
|
||||
void doAccept()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mcc
|
||||
Reference in New Issue
Block a user