diff --git a/mcc/mcc_generics.h b/mcc/mcc_generics.h index eee3ba1..0d3454a 100644 --- a/mcc/mcc_generics.h +++ b/mcc/mcc_generics.h @@ -78,6 +78,7 @@ concept mcc_logger_c = requires(T t, const T t_const) { { t.logDebug(std::declval()) }; { t.logWarn(std::declval()) }; { t.logInfo(std::declval()) }; + { t.logTrace(std::declval()) }; }; @@ -86,6 +87,7 @@ struct MccNullLogger { void logDebug(const std::string&) {} void logWarn(const std::string&) {} void logInfo(const std::string&) {} + void logTrace(const std::string&) {} }; diff --git a/mcc/mcc_netserver.h b/mcc/mcc_netserver.h index 78920e5..44194f5 100644 --- a/mcc/mcc_netserver.h +++ b/mcc/mcc_netserver.h @@ -30,12 +30,12 @@ -#include "control_proto.h" #include "mcc_generics.h" #include "mcc_netserver_endpoint.h" +#include "mcc_netserver_proto.h" #include "mcc_traits.h" -namespace mcc +namespace mcc::network { @@ -73,6 +73,7 @@ public: using LoggerT::logDebug; using LoggerT::logError; using LoggerT::logInfo; + using LoggerT::logTrace; using LoggerT::logWarn; static constexpr std::chrono::duration DEFAULT_RCV_TIMEOUT = std::chrono::hours(12); @@ -84,7 +85,7 @@ public: std::stringstream st; 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() @@ -92,7 +93,7 @@ public: std::stringstream st; 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(); disconnectClients(); @@ -103,7 +104,8 @@ public: asio::awaitable listen(std::derived_from auto endpoint, CtorArgTs&&... ctor_args) { 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; } @@ -124,7 +126,7 @@ public: s_port.open(pt.string(), 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; } @@ -157,7 +159,7 @@ public: 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; @@ -174,7 +176,8 @@ public: exit_flag = true; break; } 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; } } @@ -185,7 +188,8 @@ public: _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 for (;;) { @@ -195,7 +199,8 @@ public: } } 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; 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); st.str(""); 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) { @@ -251,7 +256,8 @@ public: } 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 { static_assert(false, "INVALID ENDPOINT!!!"); @@ -280,19 +286,19 @@ public: std::error_code ec; if (acc_ptrs.size()) { - logInfo("Close {} acceptors ...", desc); + logInfo(std::format("Close {} acceptors ...", desc)); for (auto& acc : acc_ptrs) { acc->close(ec); if (ec) { - logError("Cannot close {} acceptor! ec = '{}'", desc, ec.message()); + logError(std::format("Cannot close {} acceptor! ec = '{}'", desc, ec.message())); } else { ++M; } ++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 acc_ptrs.clear(); @@ -319,12 +325,12 @@ public: ptr->shutdown(asio::socket_base::shutdown_both, 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); 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::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) { ptr->cancel(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); 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()) { 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); } if (_localSeqpackSockets.size()) { 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); } if (_tcpSockets.size()) { 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); } @@ -406,13 +414,13 @@ public: 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::filesystem::current_path(tmp_path, 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); @@ -451,7 +459,7 @@ public: } _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(); disconnectClients(); @@ -464,7 +472,7 @@ public: } _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(); }); } @@ -474,7 +482,7 @@ public: disconnectClients(); _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(); }); } @@ -522,7 +530,7 @@ private: 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)) { @@ -533,14 +541,15 @@ private: std::vector handleClientCommand(std::string_view command) { - std::vector resp{BM700::CONTROL_PROTO_STR_RESP_ACK.begin(), BM700::CONTROL_PROTO_STR_RESP_ACK.end()}; + std::vector resp{MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR.begin(), + MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR.end()}; return resp; } - template + template asio::awaitable startSession(auto socket, const RCVT& rcv_timeout = DEFAULT_RCV_TIMEOUT, const SNDT& snd_timeout = DEFAULT_SND_TIMEOUT) @@ -551,7 +560,7 @@ private: 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()); }; @@ -576,11 +585,11 @@ private: 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 { if constexpr (!traits::is_serial_proto) { - _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)); } @@ -607,7 +616,7 @@ private: // send buffer sequence // initiate the second element by "stop-sequence" symbols std::vector 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); std::variant op_res; @@ -621,7 +630,7 @@ private: // receive message 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) { nbytes = 1024; @@ -656,7 +665,7 @@ private: } else { 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) { if (!nbytes) { // EOF! @@ -672,8 +681,8 @@ private: auto msg = look_for_whole_msg(std::span(start_ptr, sbuff.size())); if (msg.empty()) { // still not whole message - _serverLogger->trace( - "It seems a partial command message was received, so waiting for remaining part ..."); + logTrace(std::format( + "It seems a partial command message was received, so waiting for remaining part ...")); do_read = true; continue; } @@ -681,13 +690,13 @@ private: // extract command without stop sequence symbols // 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::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, - thr_id); + logDebug(std::format("A command [{}] was received from client (remote endpoint <{}>, thread ID = {})", + comm, r_epn, thr_id)); auto resp = handleClientCommand(comm); @@ -696,8 +705,8 @@ private: do_read = sbuff.size() == 0; - logDebug("Send respond [{}] to client (remote endpoint <{}>, thread ID = {})", - std::string_view(resp.begin(), resp.end()), r_epn, thr_id); + logDebug(std::format("Send respond [{}] to client (remote endpoint <{}>, thread ID = {})", + std::string_view(resp.begin(), resp.end()), r_epn, thr_id)); // send server respond to client 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)); } else { 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) { 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, - thr_id); + logInfo(std::format( + "It seems client or server closed the connection (remote endpoint <{}>, thread ID = {})", r_epn, + thr_id)); } else { - logError("An error '{}' occured in client session (remote endpoint <{}>, thread ID = {})", ex.what(), - r_epn, thr_id); + logError(std::format("An error '{}' occured in client session (remote endpoint <{}>, thread ID = {})", + ex.what(), r_epn, thr_id)); } } catch (const std::exception& ex) { - logError("An unhandled error '{}' occured in client sesssion (remote endpoint <{}>, thread ID = {})", - ex.what(), r_epn, thr_id); + logError( + std::format("An unhandled error '{}' occured in client sesssion (remote endpoint <{}>, thread ID = {})", + ex.what(), r_epn, thr_id)); } catch (...) { - logError("An unhandled error occured in client sesssion (remote endpoint <{}>, thread ID = {})", r_epn, - thr_id); + logError(std::format("An unhandled error occured in client sesssion (remote endpoint <{}>, thread ID = {})", + r_epn, thr_id)); } // remove pointer as it is invalidated here (at the exit of the method) @@ -758,8 +769,8 @@ private: 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 diff --git a/mcc/mcc_netserver_endpoint.h b/mcc/mcc_netserver_endpoint.h index 5b0fa6c..6920f6d 100644 --- a/mcc/mcc_netserver_endpoint.h +++ b/mcc/mcc_netserver_endpoint.h @@ -16,15 +16,15 @@ #include "mcc_traits.h" -namespace mcc +namespace mcc::network { namespace utils { -static constexpr bool mcc_char_subrange_compare(const traits::mcc_char_view auto& what, - const traits::mcc_char_view auto& where, - bool case_insensitive = false) +static constexpr bool mcc_char_range_compare(const traits::mcc_char_view auto& what, + const traits::mcc_char_view auto& where, + bool case_insensitive = false) { if (std::ranges::size(what) == std::ranges::size(where)) { if (case_insensitive) { @@ -201,7 +201,7 @@ public: if (isLocal()) { // check for special values idx = 0; 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) { ++idx; } @@ -398,7 +398,7 @@ protected: // case-insensitive look-up 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) { ++idx; @@ -509,4 +509,4 @@ protected: } }; -} // namespace mcc +} // namespace mcc::network diff --git a/mcc/mcc_netserver_proto.h b/mcc/mcc_netserver_proto.h index 98c5da7..b1c1510 100644 --- a/mcc/mcc_netserver_proto.h +++ b/mcc/mcc_netserver_proto.h @@ -1,38 +1,39 @@ #pragma once #include +#include #include "mcc_angle.h" -namespace mcc +namespace mcc::network { /* * network communication message format: - * keyword[[key-param-delim]param1[param-param-delim][param2]...] + * [[]param1[param-param-delim][param2]...] * e.g. - * "target 12:23:45.56 00:32:21.978\n" + * "TARGET 12:23:45.56 00:32:21.978\n" */ /* message */ 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_PARAMPARAM_DELIM_DEQ = " "; +static constexpr std::string_view MCC_COMMPROTO_KEYPARAM_DELIM_SEQ = " "; +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_SERVER_RESP_ERROR = "ERROR"; // mount operational error +static constexpr std::string_view MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR = "ACK"; // ACK +static constexpr std::string_view MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR = "ERROR"; // mount operational error // 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_RESP_ERROR_INVPAR = "INVPAR"; // invalid parameter +static constexpr std::string_view MCC_COMMPROTO_SERVER_ERROR_INVKEY_STR = "INVKEY"; // invalid keyword +static constexpr std::string_view MCC_COMMPROTO_SERVER_ERROR_INVPAR_STR = "INVPAR"; // invalid parameter /* 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 = "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_AZALT = "AZALT"; 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 SECOND CASE NUMBERS MUST BE INTERPRETATED ACCORDING TO ITS TYPE: // 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' @@ -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_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"; @@ -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" // 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\n" -> "AC 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 AZZD\n" for alt-azimuthal 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_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::hasher{}(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR); +auto MCC_COMMPROTO_KEYWORD_SERVER_ERROR_HASH = + std::unordered_set::hasher{}(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR); + +template +std::string_view mcc_parse_netmsg(IR&& netmsg, OT& parse_res, bool from_server = false) +{ + if (std::ranges::size(std::forward(netmsg)) == 0) { + return ""; + }; + + std::string_view ret; + + auto found = std::ranges::search(std::forward(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(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 diff --git a/mcc/tests/ccte_test.cpp b/mcc/tests/ccte_test.cpp index 750fad4..b6d97fb 100644 --- a/mcc/tests/ccte_test.cpp +++ b/mcc/tests/ccte_test.cpp @@ -2,6 +2,7 @@ #include #include "../mcc_ccte_erfa.h" +#include "../mcc_netserver_proto.h" #include "../mcc_pzone.h" #include "../mcc_pzone_container.h" @@ -155,5 +156,18 @@ int main() 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 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; }