...
This commit is contained in:
parent
b1a48d2b77
commit
f729799335
@ -78,6 +78,7 @@ concept mcc_logger_c = requires(T t, const T t_const) {
|
|||||||
{ t.logDebug(std::declval<const std::string&>()) };
|
{ t.logDebug(std::declval<const std::string&>()) };
|
||||||
{ t.logWarn(std::declval<const std::string&>()) };
|
{ t.logWarn(std::declval<const std::string&>()) };
|
||||||
{ t.logInfo(std::declval<const std::string&>()) };
|
{ t.logInfo(std::declval<const std::string&>()) };
|
||||||
|
{ t.logTrace(std::declval<const std::string&>()) };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -86,6 +87,7 @@ struct MccNullLogger {
|
|||||||
void logDebug(const std::string&) {}
|
void logDebug(const std::string&) {}
|
||||||
void logWarn(const std::string&) {}
|
void logWarn(const std::string&) {}
|
||||||
void logInfo(const std::string&) {}
|
void logInfo(const std::string&) {}
|
||||||
|
void logTrace(const std::string&) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -30,12 +30,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "control_proto.h"
|
|
||||||
#include "mcc_generics.h"
|
#include "mcc_generics.h"
|
||||||
#include "mcc_netserver_endpoint.h"
|
#include "mcc_netserver_endpoint.h"
|
||||||
|
#include "mcc_netserver_proto.h"
|
||||||
#include "mcc_traits.h"
|
#include "mcc_traits.h"
|
||||||
|
|
||||||
namespace mcc
|
namespace mcc::network
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
@ -73,6 +73,7 @@ public:
|
|||||||
using LoggerT::logDebug;
|
using LoggerT::logDebug;
|
||||||
using LoggerT::logError;
|
using LoggerT::logError;
|
||||||
using LoggerT::logInfo;
|
using LoggerT::logInfo;
|
||||||
|
using LoggerT::logTrace;
|
||||||
using LoggerT::logWarn;
|
using LoggerT::logWarn;
|
||||||
|
|
||||||
static constexpr std::chrono::duration DEFAULT_RCV_TIMEOUT = std::chrono::hours(12);
|
static constexpr std::chrono::duration DEFAULT_RCV_TIMEOUT = std::chrono::hours(12);
|
||||||
@ -84,7 +85,7 @@ public:
|
|||||||
std::stringstream st;
|
std::stringstream st;
|
||||||
st << std::this_thread::get_id();
|
st << std::this_thread::get_id();
|
||||||
|
|
||||||
logInfo("Create mount server instance (thread ID = {})", st.str());
|
logInfo(std::format("Create mount server instance (thread ID = {})", st.str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
~MccNetworkServer()
|
~MccNetworkServer()
|
||||||
@ -92,7 +93,7 @@ public:
|
|||||||
std::stringstream st;
|
std::stringstream st;
|
||||||
st << std::this_thread::get_id();
|
st << std::this_thread::get_id();
|
||||||
|
|
||||||
logInfo("Delete mount server instance (thread ID = {}) ...", st.str());
|
logInfo(std::format("Delete mount server instance (thread ID = {}) ...", st.str()));
|
||||||
|
|
||||||
stopListening();
|
stopListening();
|
||||||
disconnectClients();
|
disconnectClients();
|
||||||
@ -103,7 +104,8 @@ public:
|
|||||||
asio::awaitable<void> listen(std::derived_from<MccServerEndpoint> auto endpoint, CtorArgTs&&... ctor_args)
|
asio::awaitable<void> listen(std::derived_from<MccServerEndpoint> auto endpoint, CtorArgTs&&... ctor_args)
|
||||||
{
|
{
|
||||||
if (!endpoint.isValid()) {
|
if (!endpoint.isValid()) {
|
||||||
logError("Cannot start listening! Invalid endpoint string representation ('{}')!", endpoint.endpoint());
|
logError(std::format("Cannot start listening! Invalid endpoint string representation ('{}')!",
|
||||||
|
endpoint.endpoint()));
|
||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +126,7 @@ public:
|
|||||||
|
|
||||||
s_port.open(pt.string(), ec);
|
s_port.open(pt.string(), ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
logError("Cannot open serial device '{}' (Error = '{}')!", pt.string(), ec.message());
|
logError(std::format("Cannot open serial device '{}' (Error = '{}')!", pt.string(), ec.message()));
|
||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +159,7 @@ public:
|
|||||||
|
|
||||||
auto r_result = co_await res.async_resolve(endpoint.host(), endpoint.portView(), asio::use_awaitable);
|
auto r_result = co_await res.async_resolve(endpoint.host(), endpoint.portView(), asio::use_awaitable);
|
||||||
|
|
||||||
logInfo("Resolve hostname <{}> to {} IP-addresses", endpoint.host(), r_result.size());
|
logInfo(std::format("Resolve hostname <{}> to {} IP-addresses", endpoint.host(), r_result.size()));
|
||||||
|
|
||||||
|
|
||||||
bool exit_flag = false;
|
bool exit_flag = false;
|
||||||
@ -174,7 +176,8 @@ public:
|
|||||||
exit_flag = true;
|
exit_flag = true;
|
||||||
break;
|
break;
|
||||||
} catch (const std::system_error& err) {
|
} catch (const std::system_error& err) {
|
||||||
logError("An error occuring while creating connection acceptor (ec = {})", err.what());
|
logError(
|
||||||
|
std::format("An error occuring while creating connection acceptor (ec = {})", err.what()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,7 +188,8 @@ public:
|
|||||||
|
|
||||||
_tcpAcceptors.emplace_back(&acc);
|
_tcpAcceptors.emplace_back(&acc);
|
||||||
|
|
||||||
logInfo("Start listening at <{}> endpoint ...", acc.local_endpoint().address().to_string());
|
logInfo(
|
||||||
|
std::format("Start listening at <{}> endpoint ...", acc.local_endpoint().address().to_string()));
|
||||||
|
|
||||||
// start accepting connections
|
// start accepting connections
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -195,7 +199,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (const std::system_error& err) {
|
} catch (const std::system_error& err) {
|
||||||
logError("An error occured while trying to start accepting connections! ec = '{}'", err.what());
|
logError(
|
||||||
|
std::format("An error occured while trying to start accepting connections! ec = '{}'", err.what()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,12 +229,12 @@ public:
|
|||||||
std::stringstream st;
|
std::stringstream st;
|
||||||
|
|
||||||
st << endpoint;
|
st << endpoint;
|
||||||
logDebug("Create connection acceptor for endpoint <{}> ...", st.str());
|
logDebug(std::format("Create connection acceptor for endpoint <{}> ...", st.str()));
|
||||||
auto acc = typename epn_t::protocol_type::acceptor(_asioContext, endpoint);
|
auto acc = typename epn_t::protocol_type::acceptor(_asioContext, endpoint);
|
||||||
|
|
||||||
st.str("");
|
st.str("");
|
||||||
st << acc.local_endpoint();
|
st << acc.local_endpoint();
|
||||||
logInfo("Start listening at <{}> endpoint ...", st.str());
|
logInfo(std::format("Start listening at <{}> endpoint ...", st.str()));
|
||||||
|
|
||||||
|
|
||||||
if constexpr (traits::is_tcp_proto<epn_t>) {
|
if constexpr (traits::is_tcp_proto<epn_t>) {
|
||||||
@ -251,7 +256,8 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
} catch (const std::system_error& err) {
|
} catch (const std::system_error& err) {
|
||||||
logError("An error occured while trying to start accepting connections! ec = '{}'", err.what());
|
logError(
|
||||||
|
std::format("An error occured while trying to start accepting connections! ec = '{}'", err.what()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
static_assert(false, "INVALID ENDPOINT!!!");
|
static_assert(false, "INVALID ENDPOINT!!!");
|
||||||
@ -280,19 +286,19 @@ public:
|
|||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
|
|
||||||
if (acc_ptrs.size()) {
|
if (acc_ptrs.size()) {
|
||||||
logInfo("Close {} acceptors ...", desc);
|
logInfo(std::format("Close {} acceptors ...", desc));
|
||||||
|
|
||||||
for (auto& acc : acc_ptrs) {
|
for (auto& acc : acc_ptrs) {
|
||||||
acc->close(ec);
|
acc->close(ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
logError("Cannot close {} acceptor! ec = '{}'", desc, ec.message());
|
logError(std::format("Cannot close {} acceptor! ec = '{}'", desc, ec.message()));
|
||||||
} else {
|
} else {
|
||||||
++M;
|
++M;
|
||||||
}
|
}
|
||||||
++N;
|
++N;
|
||||||
}
|
}
|
||||||
|
|
||||||
logDebug("{} from {} {} acceptors were closed!", M, N, desc);
|
logDebug(std::format("{} from {} {} acceptors were closed!", M, N, desc));
|
||||||
|
|
||||||
// pointers are invalidated here, so clear its container
|
// pointers are invalidated here, so clear its container
|
||||||
acc_ptrs.clear();
|
acc_ptrs.clear();
|
||||||
@ -319,12 +325,12 @@ public:
|
|||||||
|
|
||||||
ptr->shutdown(asio::socket_base::shutdown_both, ec);
|
ptr->shutdown(asio::socket_base::shutdown_both, ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
logWarn("socket_base::shutdown: an error occured (ec = {})", ec.message());
|
logWarn(std::format("socket_base::shutdown: an error occured (ec = {})", ec.message()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr->close(ec);
|
ptr->close(ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
logWarn("socket_base::close: an error occured (ec = {})", ec.message());
|
logWarn(std::format("socket_base::close: an error occured (ec = {})", ec.message()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -340,15 +346,15 @@ public:
|
|||||||
std::lock_guard lock_g(_serialPortsMutex);
|
std::lock_guard lock_g(_serialPortsMutex);
|
||||||
|
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
logInfo("Close serial port clients ({} in total) ...", _serialPorts.size());
|
logInfo(std::format("Close serial port clients ({} in total) ...", _serialPorts.size()));
|
||||||
for (auto& ptr : _serialPorts) {
|
for (auto& ptr : _serialPorts) {
|
||||||
ptr->cancel(ec);
|
ptr->cancel(ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
logWarn("serial_port::cancel: an error occured (ec = {})", ec.message());
|
logWarn(std::format("serial_port::cancel: an error occured (ec = {})", ec.message()));
|
||||||
}
|
}
|
||||||
ptr->close(ec);
|
ptr->close(ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
logWarn("serial_port::close: an error occured (ec = {})", ec.message());
|
logWarn(std::format("serial_port::close: an error occured (ec = {})", ec.message()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -356,21 +362,23 @@ public:
|
|||||||
if (_localStreamSockets.size()) {
|
if (_localStreamSockets.size()) {
|
||||||
std::lock_guard lock_g(_localStreamSocketsMutex);
|
std::lock_guard lock_g(_localStreamSocketsMutex);
|
||||||
|
|
||||||
logInfo("Close local stream socket-type clients ({} in total) ...", _localStreamSockets.size());
|
logInfo(
|
||||||
|
std::format("Close local stream socket-type clients ({} in total) ...", _localStreamSockets.size()));
|
||||||
disconn_func(_localStreamSockets);
|
disconn_func(_localStreamSockets);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_localSeqpackSockets.size()) {
|
if (_localSeqpackSockets.size()) {
|
||||||
std::lock_guard lock_g(_localSeqpackSocketsMutex);
|
std::lock_guard lock_g(_localSeqpackSocketsMutex);
|
||||||
|
|
||||||
logInfo("Close local seqpack socket-type clients ({} in total) ...", _localSeqpackSockets.size());
|
logInfo(
|
||||||
|
std::format("Close local seqpack socket-type clients ({} in total) ...", _localSeqpackSockets.size()));
|
||||||
disconn_func(_localSeqpackSockets);
|
disconn_func(_localSeqpackSockets);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_tcpSockets.size()) {
|
if (_tcpSockets.size()) {
|
||||||
std::lock_guard lock_g(_tcpSocketsMutex);
|
std::lock_guard lock_g(_tcpSocketsMutex);
|
||||||
|
|
||||||
logInfo("Close TCP socket-type clients ({} in total) ...", _tcpSockets.size());
|
logInfo(std::format("Close TCP socket-type clients ({} in total) ...", _tcpSockets.size()));
|
||||||
disconn_func(_tcpSockets);
|
disconn_func(_tcpSockets);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,13 +414,13 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logInfo("Try to set the daemon current path to '{}' ...", tmp_path.string());
|
logInfo(std::format("Try to set the daemon current path to '{}' ...", tmp_path.string()));
|
||||||
|
|
||||||
std::error_code ec{};
|
std::error_code ec{};
|
||||||
|
|
||||||
std::filesystem::current_path(tmp_path, ec);
|
std::filesystem::current_path(tmp_path, ec);
|
||||||
if (!ec) {
|
if (!ec) {
|
||||||
logWarn("Cannot change current path to '{}'! Ignore!", tmp_path.string());
|
logWarn(std::format("Cannot change current path to '{}'! Ignore!", tmp_path.string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
umask(0);
|
umask(0);
|
||||||
@ -451,7 +459,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
_stopSignal.async_wait([this](std::error_code, int signo) {
|
_stopSignal.async_wait([this](std::error_code, int signo) {
|
||||||
logInfo("Stop signal was received (signo = {})", signo);
|
logInfo(std::format("Stop signal was received (signo = {})", signo));
|
||||||
|
|
||||||
stopListening();
|
stopListening();
|
||||||
disconnectClients();
|
disconnectClients();
|
||||||
@ -464,7 +472,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
_restartSignal.async_wait([this](std::error_code, int signo) {
|
_restartSignal.async_wait([this](std::error_code, int signo) {
|
||||||
logInfo("Restart signal was received (signo = {})", signo);
|
logInfo(std::format("Restart signal was received (signo = {})", signo));
|
||||||
restart();
|
restart();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -474,7 +482,7 @@ public:
|
|||||||
disconnectClients();
|
disconnectClients();
|
||||||
|
|
||||||
_restartSignal.async_wait([this](std::error_code, int signo) {
|
_restartSignal.async_wait([this](std::error_code, int signo) {
|
||||||
logInfo("Restart signal was received (signo = {})", signo);
|
logInfo(std::format("Restart signal was received (signo = {})", signo));
|
||||||
restart();
|
restart();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -522,7 +530,7 @@ private:
|
|||||||
opt_name = "char size";
|
opt_name = "char size";
|
||||||
}
|
}
|
||||||
|
|
||||||
logError("Cannot set serial port '{}' option! Just skip!", opt_name);
|
logError(std::format("Cannot set serial port '{}' option! Just skip!", opt_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (sizeof...(OptTs)) {
|
if constexpr (sizeof...(OptTs)) {
|
||||||
@ -533,14 +541,15 @@ private:
|
|||||||
|
|
||||||
std::vector<char> handleClientCommand(std::string_view command)
|
std::vector<char> handleClientCommand(std::string_view command)
|
||||||
{
|
{
|
||||||
std::vector<char> resp{BM700::CONTROL_PROTO_STR_RESP_ACK.begin(), BM700::CONTROL_PROTO_STR_RESP_ACK.end()};
|
std::vector<char> resp{MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR.begin(),
|
||||||
|
MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR.end()};
|
||||||
|
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <traits::mcc_time_duration_c RCVT = decltype(DEFAULT_RCV_TIMEOUT),
|
template <mcc::traits::mcc_time_duration_c RCVT = decltype(DEFAULT_RCV_TIMEOUT),
|
||||||
traits::mcc_time_duration_c SNDT = decltype(DEFAULT_SND_TIMEOUT)>
|
mcc::traits::mcc_time_duration_c SNDT = decltype(DEFAULT_SND_TIMEOUT)>
|
||||||
asio::awaitable<void> startSession(auto socket,
|
asio::awaitable<void> startSession(auto socket,
|
||||||
const RCVT& rcv_timeout = DEFAULT_RCV_TIMEOUT,
|
const RCVT& rcv_timeout = DEFAULT_RCV_TIMEOUT,
|
||||||
const SNDT& snd_timeout = DEFAULT_SND_TIMEOUT)
|
const SNDT& snd_timeout = DEFAULT_SND_TIMEOUT)
|
||||||
@ -551,7 +560,7 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
auto look_for_whole_msg = [](auto const& bytes) {
|
auto look_for_whole_msg = [](auto const& bytes) {
|
||||||
auto found = std::ranges::search(bytes, BM700::CONTROL_PROTO_STOP_SEQ);
|
auto found = std::ranges::search(bytes, MCC_COMMPROTO_STOP_SEQ);
|
||||||
return found.empty() ? std::span(bytes.begin(), bytes.begin()) : std::span(bytes.begin(), found.end());
|
return found.empty() ? std::span(bytes.begin(), bytes.begin()) : std::span(bytes.begin(), found.end());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -576,11 +585,11 @@ private:
|
|||||||
r_epn = "local";
|
r_epn = "local";
|
||||||
}
|
}
|
||||||
|
|
||||||
logInfo("Start client session: remote endpoint <{}> (session thread ID = {})", r_epn, thr_id);
|
logInfo(std::format("Start client session: remote endpoint <{}> (session thread ID = {})", r_epn, thr_id));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if constexpr (!traits::is_serial_proto<sock_t>) {
|
if constexpr (!traits::is_serial_proto<sock_t>) {
|
||||||
_serverLogger->trace("Set socket option KEEP_ALIVE to TRUE");
|
logTrace("Set socket option KEEP_ALIVE to TRUE");
|
||||||
socket.set_option(asio::socket_base::keep_alive(true));
|
socket.set_option(asio::socket_base::keep_alive(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -607,7 +616,7 @@ private:
|
|||||||
// send buffer sequence
|
// send buffer sequence
|
||||||
// initiate the second element by "stop-sequence" symbols
|
// initiate the second element by "stop-sequence" symbols
|
||||||
std::vector<asio::const_buffer> snd_buff_seq{
|
std::vector<asio::const_buffer> snd_buff_seq{
|
||||||
{}, {BM700::CONTROL_PROTO_STOP_SEQ.data(), BM700::CONTROL_PROTO_STOP_SEQ.size()}};
|
{}, {MCC_COMMPROTO_STOP_SEQ.data(), MCC_COMMPROTO_STOP_SEQ.size()}};
|
||||||
|
|
||||||
asio::steady_timer timeout_timer(_asioContext);
|
asio::steady_timer timeout_timer(_asioContext);
|
||||||
std::variant<size_t, std::monostate> op_res;
|
std::variant<size_t, std::monostate> op_res;
|
||||||
@ -621,7 +630,7 @@ private:
|
|||||||
// receive message
|
// receive message
|
||||||
|
|
||||||
if (do_read) {
|
if (do_read) {
|
||||||
_serverLogger->trace("Start socket/port reading operation with timeout {} ...", rcv_timeout);
|
logTrace(std::format("Start socket/port reading operation with timeout {} ...", rcv_timeout));
|
||||||
|
|
||||||
if constexpr (traits::is_serial_proto<sock_t>) {
|
if constexpr (traits::is_serial_proto<sock_t>) {
|
||||||
nbytes = 1024;
|
nbytes = 1024;
|
||||||
@ -656,7 +665,7 @@ private:
|
|||||||
} else {
|
} else {
|
||||||
nbytes = std::get<0>(op_res);
|
nbytes = std::get<0>(op_res);
|
||||||
|
|
||||||
_serverLogger->trace("{} bytes were received", nbytes);
|
logTrace(std::format("{} bytes were received", nbytes));
|
||||||
|
|
||||||
if constexpr (traits::is_local_seqpack_proto<sock_t>) {
|
if constexpr (traits::is_local_seqpack_proto<sock_t>) {
|
||||||
if (!nbytes) { // EOF!
|
if (!nbytes) { // EOF!
|
||||||
@ -672,8 +681,8 @@ private:
|
|||||||
|
|
||||||
auto msg = look_for_whole_msg(std::span(start_ptr, sbuff.size()));
|
auto msg = look_for_whole_msg(std::span(start_ptr, sbuff.size()));
|
||||||
if (msg.empty()) { // still not whole message
|
if (msg.empty()) { // still not whole message
|
||||||
_serverLogger->trace(
|
logTrace(std::format(
|
||||||
"It seems a partial command message was received, so waiting for remaining part ...");
|
"It seems a partial command message was received, so waiting for remaining part ..."));
|
||||||
do_read = true;
|
do_read = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -681,13 +690,13 @@ private:
|
|||||||
|
|
||||||
// extract command without stop sequence symbols
|
// extract command without stop sequence symbols
|
||||||
// std::string comm;
|
// std::string comm;
|
||||||
// std::ranges::copy(msg | std::views::take(msg.size() - BM700::CONTROL_PROTO_STOP_SEQ.size()),
|
// std::ranges::copy(msg | std::views::take(msg.size() - MCC_COMMPROTO_STOP_SEQ.size()),
|
||||||
// std::back_inserter(comm));
|
// std::back_inserter(comm));
|
||||||
|
|
||||||
std::string_view comm{msg.begin(), msg.end() - BM700::CONTROL_PROTO_STOP_SEQ.size()};
|
std::string_view comm{msg.begin(), msg.end() - MCC_COMMPROTO_STOP_SEQ.size()};
|
||||||
|
|
||||||
logDebug("A command [{}] was received from client (remote endpoint <{}>, thread ID = {})", comm, r_epn,
|
logDebug(std::format("A command [{}] was received from client (remote endpoint <{}>, thread ID = {})",
|
||||||
thr_id);
|
comm, r_epn, thr_id));
|
||||||
|
|
||||||
auto resp = handleClientCommand(comm);
|
auto resp = handleClientCommand(comm);
|
||||||
|
|
||||||
@ -696,8 +705,8 @@ private:
|
|||||||
do_read = sbuff.size() == 0;
|
do_read = sbuff.size() == 0;
|
||||||
|
|
||||||
|
|
||||||
logDebug("Send respond [{}] to client (remote endpoint <{}>, thread ID = {})",
|
logDebug(std::format("Send respond [{}] to client (remote endpoint <{}>, thread ID = {})",
|
||||||
std::string_view(resp.begin(), resp.end()), r_epn, thr_id);
|
std::string_view(resp.begin(), resp.end()), r_epn, thr_id));
|
||||||
|
|
||||||
// send server respond to client
|
// send server respond to client
|
||||||
snd_buff_seq[0] = {resp.data(), resp.size()};
|
snd_buff_seq[0] = {resp.data(), resp.size()};
|
||||||
@ -722,27 +731,29 @@ private:
|
|||||||
throw std::system_error(std::make_error_code(std::errc::timed_out));
|
throw std::system_error(std::make_error_code(std::errc::timed_out));
|
||||||
} else {
|
} else {
|
||||||
nbytes = std::get<0>(op_res);
|
nbytes = std::get<0>(op_res);
|
||||||
_serverLogger->trace("{} bytes were sent", nbytes);
|
logTrace(std::format("{} bytes were sent", nbytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbytes != (resp.size() + BM700::CONTROL_PROTO_STOP_SEQ.size())) { // !!!!!!!!!!
|
if (nbytes != (resp.size() + MCC_COMMPROTO_STOP_SEQ.size())) { // !!!!!!!!!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (const std::system_error& ex) {
|
} catch (const std::system_error& ex) {
|
||||||
if (ex.code() == std::error_code(asio::error::misc_errors::eof)) {
|
if (ex.code() == std::error_code(asio::error::misc_errors::eof)) {
|
||||||
logInfo("It seems client or server closed the connection (remote endpoint <{}>, thread ID = {})", r_epn,
|
logInfo(std::format(
|
||||||
thr_id);
|
"It seems client or server closed the connection (remote endpoint <{}>, thread ID = {})", r_epn,
|
||||||
|
thr_id));
|
||||||
} else {
|
} else {
|
||||||
logError("An error '{}' occured in client session (remote endpoint <{}>, thread ID = {})", ex.what(),
|
logError(std::format("An error '{}' occured in client session (remote endpoint <{}>, thread ID = {})",
|
||||||
r_epn, thr_id);
|
ex.what(), r_epn, thr_id));
|
||||||
}
|
}
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
logError("An unhandled error '{}' occured in client sesssion (remote endpoint <{}>, thread ID = {})",
|
logError(
|
||||||
ex.what(), r_epn, thr_id);
|
std::format("An unhandled error '{}' occured in client sesssion (remote endpoint <{}>, thread ID = {})",
|
||||||
|
ex.what(), r_epn, thr_id));
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
logError("An unhandled error occured in client sesssion (remote endpoint <{}>, thread ID = {})", r_epn,
|
logError(std::format("An unhandled error occured in client sesssion (remote endpoint <{}>, thread ID = {})",
|
||||||
thr_id);
|
r_epn, thr_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove pointer as it is invalidated here (at the exit of the method)
|
// remove pointer as it is invalidated here (at the exit of the method)
|
||||||
@ -758,8 +769,8 @@ private:
|
|||||||
static_assert(false, "INVALID SOCKET TTYPE!!!");
|
static_assert(false, "INVALID SOCKET TTYPE!!!");
|
||||||
}
|
}
|
||||||
|
|
||||||
logInfo("Close client session: remote endpoint <{}> (thread ID = {})", r_epn, thr_id);
|
logInfo(std::format("Close client session: remote endpoint <{}> (thread ID = {})", r_epn, thr_id));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mcc
|
} // namespace mcc::network
|
||||||
|
|||||||
@ -16,13 +16,13 @@
|
|||||||
|
|
||||||
#include "mcc_traits.h"
|
#include "mcc_traits.h"
|
||||||
|
|
||||||
namespace mcc
|
namespace mcc::network
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace utils
|
namespace utils
|
||||||
{
|
{
|
||||||
|
|
||||||
static constexpr bool mcc_char_subrange_compare(const traits::mcc_char_view auto& what,
|
static constexpr bool mcc_char_range_compare(const traits::mcc_char_view auto& what,
|
||||||
const traits::mcc_char_view auto& where,
|
const traits::mcc_char_view auto& where,
|
||||||
bool case_insensitive = false)
|
bool case_insensitive = false)
|
||||||
{
|
{
|
||||||
@ -201,7 +201,7 @@ public:
|
|||||||
if (isLocal()) { // check for special values
|
if (isLocal()) { // check for special values
|
||||||
idx = 0;
|
idx = 0;
|
||||||
if (std::ranges::any_of(validLocalProtoTypes, [&idx, this](const auto& el) {
|
if (std::ranges::any_of(validLocalProtoTypes, [&idx, this](const auto& el) {
|
||||||
bool ok = utils::mcc_char_subrange_compare(_host, el, true);
|
bool ok = utils::mcc_char_range_compare(_host, el, true);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
++idx;
|
++idx;
|
||||||
}
|
}
|
||||||
@ -398,7 +398,7 @@ protected:
|
|||||||
|
|
||||||
// case-insensitive look-up
|
// case-insensitive look-up
|
||||||
bool found = std::ranges::any_of(MccServerEndpoint::validProtoMarks, [&idx, &proto_mark](const auto& el) {
|
bool found = std::ranges::any_of(MccServerEndpoint::validProtoMarks, [&idx, &proto_mark](const auto& el) {
|
||||||
bool ok = utils::mcc_char_subrange_compare(proto_mark, el, true);
|
bool ok = utils::mcc_char_range_compare(proto_mark, el, true);
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
++idx;
|
++idx;
|
||||||
@ -509,4 +509,4 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mcc
|
} // namespace mcc::network
|
||||||
|
|||||||
@ -1,38 +1,39 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <unordered_set>
|
||||||
#include "mcc_angle.h"
|
#include "mcc_angle.h"
|
||||||
|
|
||||||
namespace mcc
|
namespace mcc::network
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* network communication message format:
|
* network communication message format:
|
||||||
* keyword[[key-param-delim]param1[param-param-delim][param2]...]<stop-seq>
|
* <keyword>[[<key-param-delim>]param1[param-param-delim][param2]...]<stop-seq>
|
||||||
* e.g.
|
* e.g.
|
||||||
* "target 12:23:45.56 00:32:21.978\n"
|
* "TARGET 12:23:45.56 00:32:21.978\n"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* message */
|
/* message */
|
||||||
static constexpr std::string_view MCC_COMMPROTO_STOP_SEQ = "\n";
|
static constexpr std::string_view MCC_COMMPROTO_STOP_SEQ = "\n";
|
||||||
static constexpr std::string_view MCC_COMMPROTO_KEYPARAM_DELIM_DEQ = " ";
|
static constexpr std::string_view MCC_COMMPROTO_KEYPARAM_DELIM_SEQ = " ";
|
||||||
static constexpr std::string_view MCC_COMMPROTO_PARAMPARAM_DELIM_DEQ = " ";
|
static constexpr std::string_view MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ = " ";
|
||||||
|
|
||||||
|
|
||||||
/* server special response keywords */
|
/* server special keywords */
|
||||||
|
|
||||||
static constexpr std::string_view MCC_COMMPROTO_SERVER_RESP_ACK = "ACK"; // ACK
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR = "ACK"; // ACK
|
||||||
static constexpr std::string_view MCC_COMMPROTO_SERVER_RESP_ERROR = "ERROR"; // mount operational error
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR = "ERROR"; // mount operational error
|
||||||
// pre-defined errors
|
// pre-defined errors
|
||||||
static constexpr std::string_view MCC_COMMPROTO_SERVER_RESP_ERROR_INVKEY = "INVKEY"; // invalid keyword
|
static constexpr std::string_view MCC_COMMPROTO_SERVER_ERROR_INVKEY_STR = "INVKEY"; // invalid keyword
|
||||||
static constexpr std::string_view MCC_COMMPROTO_SERVER_RESP_ERROR_INVPAR = "INVPAR"; // invalid parameter
|
static constexpr std::string_view MCC_COMMPROTO_SERVER_ERROR_INVPAR_STR = "INVPAR"; // invalid parameter
|
||||||
|
|
||||||
/* predefined parameters */
|
/* predefined parameters */
|
||||||
|
|
||||||
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_RADEC_ICRS = "RADEC_ICRS";
|
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_RADEC_ICRS = "RADEC_ICRS";
|
||||||
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_RADEC = "RADEC"; // apparent RA and DEC
|
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_RADEC = "RADEC"; // apparent RA and DEC
|
||||||
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_HADEC = "HADEC";
|
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_HADEC = "HADEC"; // apparent HA and DEC
|
||||||
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_AZZD = "AZZD";
|
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_AZZD = "AZZD";
|
||||||
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_AZALT = "AZALT";
|
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_AZALT = "AZALT";
|
||||||
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_XY = "XY";
|
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_XY = "XY";
|
||||||
@ -58,7 +59,7 @@ static constexpr MccCoordPairKind mcc_str2pairkind(std::string_view spair)
|
|||||||
// IN THE FIRST CASE ALL NUMBERS MUST BE INTERPRETATED AS DEGREES,
|
// IN THE FIRST CASE ALL NUMBERS MUST BE INTERPRETATED AS DEGREES,
|
||||||
// IN THE SECOND CASE NUMBERS MUST BE INTERPRETATED ACCORDING TO ITS TYPE:
|
// IN THE SECOND CASE NUMBERS MUST BE INTERPRETATED ACCORDING TO ITS TYPE:
|
||||||
// ALL TIME-RELATED QUANTITIES AND RA/HA COORDINATES MUST BE EXPRESSED
|
// ALL TIME-RELATED QUANTITIES AND RA/HA COORDINATES MUST BE EXPRESSED
|
||||||
// IN FORMAT 'HOURS:MINUTES:SECONDS' WHILE DEC/ALT/AZ/ZD COORDINATES MUST
|
// IN FORMAT 'HOURS:MINUTES:SECONDS', WHILE DEC/ALT/AZ/ZD COORDINATES MUST
|
||||||
// BE EXPRESSED AS '+/-DEGREES:ARCMINUTES:ARCSECONDS'
|
// BE EXPRESSED AS '+/-DEGREES:ARCMINUTES:ARCSECONDS'
|
||||||
|
|
||||||
|
|
||||||
@ -80,7 +81,14 @@ static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDFMT_STR = "COORDFMT
|
|||||||
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDFMT_SEXGM_STR = "SGM"; // sexagesimal
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDFMT_SEXGM_STR = "SGM"; // sexagesimal
|
||||||
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDFMT_FIXED_STR = "FIX"; // fixed point
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDFMT_FIXED_STR = "FIX"; // fixed point
|
||||||
|
|
||||||
// precision of returned coordinates
|
// precision (number of decimal places) of returned coordinates:
|
||||||
|
// "COORDPREC seconds-prec arcseconds-prec\n"
|
||||||
|
// seconds-prec - precision of hour-based coordinates (RA and HA) or time-related quantities
|
||||||
|
// arcseconds-prec - precision of degree-based coordinates (DEC, AZ, ZD, ALT)
|
||||||
|
// precision must be given as non-negative integer number
|
||||||
|
// e.g.
|
||||||
|
// "COORDPREC 2 1\n" (output sexagesimal RA=12:34:56.67, DEC=32:54:21.9)
|
||||||
|
//
|
||||||
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDPREC_STR = "COORDPREC";
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDPREC_STR = "COORDPREC";
|
||||||
|
|
||||||
|
|
||||||
@ -111,14 +119,99 @@ static constexpr std::string_view MCC_COMMPROTO_KEYWORD_TARGET_STR = "TARGET";
|
|||||||
//
|
//
|
||||||
// server must return "ACK MOUNT X-coord Y-coord XY-kind" or "ERROR INVPAR"
|
// server must return "ACK MOUNT X-coord Y-coord XY-kind" or "ERROR INVPAR"
|
||||||
// e.g.
|
// e.g.
|
||||||
// "MOUNT AZALT\n" -> "AC MOUNT 1.2332325 54.23321312 AZALT\n"
|
// "MOUNT AZALT\n" -> "ACK MOUNT 1.2332325 54.23321312 AZALT\n"
|
||||||
// "MOUNT AZAL\n" -> "ERROR INVPAR\n" (invalid parameter of coordinates pair kind)
|
// "MOUNT AZAL\n" -> "ERROR INVPAR\n" (invalid parameter of coordinates pair kind)
|
||||||
// "MOUNT\n" -> "AC MOUNT 1.2332325 54.23321312 AZZD\n" for alt-azimuthal mount
|
// "MOUNT\n" -> "ACK MOUNT 1.2332325 54.23321312 AZZD\n" for alt-azimuthal mount
|
||||||
// "MOUNT\n" -> "AC MOUNT 1.2332325 54.23321312 HADEC\n" for equathorial mount
|
// "MOUNT\n" -> "ACK MOUNT 1.2332325 54.23321312 HADEC\n" for equathorial mount
|
||||||
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_MOUNT_STR = "MOUNT";
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_MOUNT_STR = "MOUNT";
|
||||||
|
|
||||||
|
|
||||||
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_TELEMTRY_STR = "TELEMETRY";
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_TELEMTRY_STR = "TELEMETRY";
|
||||||
|
|
||||||
|
|
||||||
} // namespace mcc
|
static const std::unordered_set MCC_COMMPROTO_VALID_KEYS = {
|
||||||
|
MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, MCC_COMMPROTO_KEYWORD_COORDFMT_STR,
|
||||||
|
MCC_COMMPROTO_KEYWORD_COORDPREC_STR, MCC_COMMPROTO_KEYWORD_TARGET_STR, MCC_COMMPROTO_KEYWORD_MOUNT_STR,
|
||||||
|
MCC_COMMPROTO_KEYWORD_TELEMTRY_STR};
|
||||||
|
|
||||||
|
auto MCC_COMMPROTO_KEYWORD_SERVER_ACK_HASH =
|
||||||
|
std::unordered_set<std::string_view>::hasher{}(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR);
|
||||||
|
auto MCC_COMMPROTO_KEYWORD_SERVER_ERROR_HASH =
|
||||||
|
std::unordered_set<std::string_view>::hasher{}(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR);
|
||||||
|
|
||||||
|
template <traits::mcc_input_char_range IR, traits::mcc_range_of_output_char_range OT>
|
||||||
|
std::string_view mcc_parse_netmsg(IR&& netmsg, OT& parse_res, bool from_server = false)
|
||||||
|
{
|
||||||
|
if (std::ranges::size(std::forward<IR>(netmsg)) == 0) {
|
||||||
|
return "";
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string_view ret;
|
||||||
|
|
||||||
|
auto found = std::ranges::search(std::forward<IR>(netmsg), MCC_COMMPROTO_KEYPARAM_DELIM_SEQ);
|
||||||
|
|
||||||
|
auto it = MCC_COMMPROTO_VALID_KEYS.find({netmsg.begin(), found.begin()});
|
||||||
|
if (it == MCC_COMMPROTO_VALID_KEYS.end()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = *it;
|
||||||
|
|
||||||
|
if (from_server) { // only ACK and ERROR
|
||||||
|
auto ok = std::ranges::search(netmsg.begin(), found.begin(), MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR.begin(),
|
||||||
|
MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR.end());
|
||||||
|
if (ok) {
|
||||||
|
ret = MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = std::ranges::search(netmsg.begin(), found.begin(), MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR.begin(),
|
||||||
|
MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR.end());
|
||||||
|
if (ok) {
|
||||||
|
ret = MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (found.empty()) { // no parameters?
|
||||||
|
// if (from_server) {
|
||||||
|
// auto ok = std::ranges::search(netmsg.begin(), found.begin(),
|
||||||
|
// MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR.begin(),
|
||||||
|
// MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR.end());
|
||||||
|
// if (ok) {
|
||||||
|
// ret = MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ok = std::ranges::search(netmsg.begin(), found.begin(), MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR.begin(),
|
||||||
|
// MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR.end());
|
||||||
|
// if (ok) {
|
||||||
|
// ret = MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR;
|
||||||
|
// } else {
|
||||||
|
// return "";
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// if (!MCC_COMMPROTO_VALID_KEYS.contains({netmsg.begin(), found.begin()})) {
|
||||||
|
// return "";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// if (std::distance(netmsg.begin(), found.begin()) == 0) { // an empty keyword
|
||||||
|
// return "";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
auto pars = std::forward<IR>(netmsg) | std::views::drop(std::distance(netmsg.begin(), found.end())) |
|
||||||
|
std::views::split(MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ);
|
||||||
|
|
||||||
|
OT res;
|
||||||
|
for (auto const& el : pars) {
|
||||||
|
std::back_inserter(res) = {el.begin(), el.end()};
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_res = std::move(res);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mcc::network
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#include "../mcc_ccte_erfa.h"
|
#include "../mcc_ccte_erfa.h"
|
||||||
|
#include "../mcc_netserver_proto.h"
|
||||||
#include "../mcc_pzone.h"
|
#include "../mcc_pzone.h"
|
||||||
#include "../mcc_pzone_container.h"
|
#include "../mcc_pzone_container.h"
|
||||||
|
|
||||||
@ -155,5 +156,18 @@ int main()
|
|||||||
|
|
||||||
std::cout << a1.sexagesimal() << "\n" << a2.sexagesimal() << "\n";
|
std::cout << a1.sexagesimal() << "\n" << a2.sexagesimal() << "\n";
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << "\n\n";
|
||||||
|
|
||||||
|
std::string sm{"ACK TARGET 12:23:45.13 -09.23423525 RADEC"};
|
||||||
|
std::vector<std::string> sv;
|
||||||
|
|
||||||
|
auto mr = mcc::network::mcc_parse_netmsg(sm, sv);
|
||||||
|
|
||||||
|
std::cout << "MSG RET = <" << mr << ">\n";
|
||||||
|
for (auto const& pr : sv) {
|
||||||
|
std::cout << "\t[" << pr << "]\n";
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user