This commit is contained in:
Timur A. Fatkhullin 2024-10-22 00:44:43 +03:00
parent 0d62c9defc
commit 0e937bb2d7
2 changed files with 129 additions and 4 deletions

View File

@ -46,6 +46,7 @@ if (ASIO_LIBRARY)
set(ADC_NETWORK_HEADERS ${ADC_NETWORK_HEADERS}
net/asio/adc_netservice_asio.h
net/asio/adc_netsession_asio.h
net/asio/adc_device_netserver_asio.h
)
add_compile_definitions(PUBLIC USE_ASIO_LIBRARY)

View File

@ -1,6 +1,7 @@
#pragma once
#include "../common/adc_traits.h"
#include "../common/adc_utils.h"
namespace adc
{
@ -38,10 +39,7 @@ struct AdcStopSeqSessionProto {
typedef std::string proto_ident_t;
proto_ident_t ident() const
{
return "STOP SEQUENCE PROTO";
}
proto_ident_t ident() const { return "STOP SEQUENCE PROTO"; }
// template <traits::adc_input_char_range R>
// auto search(const R& r)
@ -143,6 +141,132 @@ struct AdcStopSeqSessionProto {
}
};
// session protocol for datagram-kind message (e.g. UDP, seqpacket)
// The protocol does not contain any special characters, so to/fromProto methods
// return just a copy/one-element-array-of-vew/view of input byte
// sequence.
struct AdcDatagramSessionProto {
typedef std::string proto_ident_t;
proto_ident_t ident() const { return "DATAGRAM PROTO"; }
template <traits::adc_input_char_range R>
auto search(const R& r)
{
if constexpr (std::ranges::viewable_range<R>) {
return std::ranges::subrange(r.begin(), r.end());
} else {
R res;
std::ranges::copy(r, std::back_inserter(res));
return res;
}
}
template <traits::adc_input_char_range R>
auto toProto(const R& r)
{
if constexpr (std::ranges::viewable_range<R>) {
return std::array{std::ranges::subrange(r.begin(), r.end())};
} else {
R res;
std::ranges::copy(r, std::back_inserter(res));
return res;
}
}
template <traits::adc_input_char_range R>
auto fromProto(const R& r)
{
if constexpr (std::ranges::viewable_range<R>) {
return std::ranges::subrange(r.begin(), r.end());
} else {
R res;
std::ranges::copy(r, std::back_inserter(res));
return res;
}
}
};
template <const char* START_MARK = constants::ADC_DEFAULT_NETPROTO_STARTMARK, size_t SIZE_FIELD_LEN = 8>
struct AdcBinaryBlobSessionProto {
static constexpr size_t startMarkSize = utils::AdcCharArrSize(START_MARK);
static constexpr std::span<const char> startMark{START_MARK, startMarkSize};
static_assert(startMarkSize, "START MARK SEQUENCE MUST NOT BE AN EMPTY ONE!");
static_assert(SIZE_FIELD_LEN > 0, "LENGTH OF SIZE FILED MUST BE GREATER THAN 0!");
static constexpr size_t headerSize = startMarkSize + SIZE_FIELD_LEN;
typedef std::string proto_ident_t;
proto_ident_t ident() const { return "BINARY BLOB PROTO"; }
template <traits::adc_input_char_range R>
auto search(const R& r)
{
size_t r_size = std::ranges::size(r);
if (r_size < headerSize) {
return std::ranges::subrange(r.begin(), r.begin());
}
auto found = std::ranges::search(r, startMark);
if (found.empty()) {
return std::ranges::subrange(r.begin(), r.begin());
}
std::string len;
std::ranges::copy(found.end(), found.end() + SIZE_FIELD_LEN, std::back_inserter(len));
// NOTE: HERE ONE EXPECTS A HEXIMAL NUMBER!!!
size_t blob_size;
auto end_ptr = len.c_str() + len.size();
auto [ptr, ec] = std::from_chars(len.c_str(), end_ptr, blob_size, 16);
if (ec != std::errc{} || ptr != end_ptr) {
return std::ranges::subrange(r.begin(), r.begin());
}
if (blob_size == 0) { // just start mark and size field (zero-length blob)
return std::ranges::subrange(r.begin(), found.end() + SIZE_FIELD_LEN);
}
if ((r_size - headerSize) < blob_size) { // not enough of data
return std::ranges::subrange(r.begin(), r.begin());
}
return std::ranges::subrange(r.begin(), r.begin() + headerSize + blob_size);
}
template <traits::adc_input_char_range R>
auto toProto(const R& r)
{
static const std::string fmt = std::string{"{:0"} + std::to_string(SIZE_FIELD_LEN) + std::string{"X}"};
if constexpr (std::ranges::viewable_range<R>) {
// return
} else {
R res;
std::ranges::copy(startMark, std::back_inserter(res));
std::format_to(std::back_inserter(res), fmt, std::ranges::size(r));
std::ranges::copy(r, std::back_inserter(res));
}
}
template <traits::adc_input_char_range R>
auto fromProto(const R& r)
{
if constexpr (std::ranges::viewable_range<R>) {
return std::ranges::subrange(r.begin() + headerSize, r.end());
} else {
R res;
std::ranges::copy(r | std::views::drop(headerSize), std::back_inserter(res));
return res;
}
}
};
template <typename InetT, const char* STOPSEQ = constants::ADC_DEFAULT_NETPROTO_STOPSEQ>
struct AdcNetProtoStopSeq : InetT {
static constexpr std::string_view stopSeq{STOPSEQ};