...
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "../common/adc_utils.h"
|
||||
|
||||
|
||||
/*
|
||||
|
||||
ABSTRACT DEVICE COMPONENTS LIBRARY
|
||||
@@ -19,13 +22,18 @@ namespace adc
|
||||
* Very simple various protocols endpoint parser and holder class
|
||||
*
|
||||
* endpoint: proto_mark://host_name:port_num/path
|
||||
* where "part" is optional for all protocol kinds;
|
||||
* where "part" is optional for all non-local protocol kinds;
|
||||
*
|
||||
* for the "local" kind protocol the endpoint string must consists of
|
||||
* only "proto_mark" and "host_name" fields
|
||||
* (e.g.: local://APP_UNIX_SOCKET)
|
||||
* for local kind of protocols the endpoint must be given as:
|
||||
* local://stream/PATH
|
||||
* local://datagram/PATH
|
||||
* local://seqpacket/PATH
|
||||
* where 'stream', 'datagram' and 'seqpacket' "host_name"-field marks the
|
||||
* stream-type, datagram-type and seqpacket-type UNIX domain sockets protocols.
|
||||
* here, possible "port_num" field is allowed but ignored.
|
||||
*
|
||||
* NOTE: "proto_mark" and "host_name" (for local kind) fields are parsed in case-insensitive manner!
|
||||
*
|
||||
* NOTE: "proto_mark" field is parsed as case-insensitive string!
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -39,6 +47,7 @@ public:
|
||||
|
||||
enum proto_id_t : uint8_t {
|
||||
PROTO_ID_LOCAL,
|
||||
PROTO_ID_SEQLOCAL,
|
||||
PROTO_ID_TCP,
|
||||
PROTO_ID_TLS,
|
||||
PROTO_ID_UDP,
|
||||
@@ -58,6 +67,14 @@ public:
|
||||
protoMarkUDP, protoMarkWS, protoMarkWSS};
|
||||
|
||||
|
||||
static constexpr std::string_view localProtoTypeStream{"stream"}; // UNIX domain stream
|
||||
static constexpr std::string_view localProtoTypeDatagram{"datagram"}; // UNIX domain datagram
|
||||
static constexpr std::string_view localProtoTypeSeqpacket{"seqpacket"}; // UNIX domain seqpacket
|
||||
|
||||
static constexpr std::array validLocalProtoTypes{localProtoTypeStream, localProtoTypeDatagram,
|
||||
localProtoTypeSeqpacket};
|
||||
|
||||
|
||||
template <traits::adc_input_char_range R>
|
||||
AdcEndpointParser(const R& ept)
|
||||
{
|
||||
@@ -81,7 +98,8 @@ public:
|
||||
if constexpr (std::is_array_v<std::remove_cvref_t<R>>) {
|
||||
_endpoint = ept;
|
||||
} else {
|
||||
std::ranges::copy(ept, _endpoint);
|
||||
_endpoint.clear();
|
||||
std::ranges::copy(ept, std::back_inserter(_endpoint));
|
||||
}
|
||||
|
||||
auto found = std::ranges::search(_endpoint, protoHostDelim);
|
||||
@@ -90,53 +108,59 @@ public:
|
||||
}
|
||||
|
||||
|
||||
|
||||
_proto = std::string_view{_endpoint.begin(), found.begin()};
|
||||
// for (auto& valid_proto : validProtoMarks) {
|
||||
// _isValid = _proto == valid_proto;
|
||||
// if (_isValid) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (!_isValid) {
|
||||
// return _isValid;
|
||||
// }
|
||||
|
||||
// _isValid = false;
|
||||
|
||||
if (!checkProtoMark(_proto)) {
|
||||
ssize_t idx;
|
||||
if ((idx = checkProtoMark(std::string_view{_endpoint.begin(), found.begin()})) < 0) {
|
||||
return _isValid;
|
||||
}
|
||||
|
||||
_proto = validProtoMarks[idx];
|
||||
|
||||
_host = std::string_view{found.end(), _endpoint.end()};
|
||||
if (_proto == protoMarkLocal) { // local proto allows only hostname
|
||||
_path = std::string_view();
|
||||
_port = -1;
|
||||
|
||||
auto f1 = std::ranges::search(_host, portPathDelim);
|
||||
std::string_view port_sv;
|
||||
if (f1.empty() && isLocal()) { // no path, but it is mandatory for 'local'!
|
||||
return _isValid;
|
||||
} else {
|
||||
auto f1 = std::ranges::search(_host, hostPortDelim);
|
||||
std::string_view port_sv;
|
||||
if (f1.empty()) { // no port, but is must be!
|
||||
_host = std::string_view(_host.begin(), f1.begin());
|
||||
|
||||
_path = std::string_view(f1.end(), &*_endpoint.end());
|
||||
|
||||
f1 = std::ranges::search(_host, hostPortDelim);
|
||||
if (f1.empty() && !isLocal()) { // no port, but it is mandatory for non-local!
|
||||
return _isValid;
|
||||
} else {
|
||||
}
|
||||
|
||||
port_sv = std::string_view(f1.end(), _host.end());
|
||||
if (port_sv.size()) {
|
||||
_host = std::string_view(_host.begin(), f1.begin());
|
||||
// port_sv = std::string_view(f1.end(), _endpoint.end());
|
||||
port_sv = std::string_view(f1.end(), &*_endpoint.end());
|
||||
|
||||
f1 = std::ranges::search(port_sv, portPathDelim);
|
||||
if (f1.empty()) {
|
||||
_path = std::string_view();
|
||||
} else {
|
||||
port_sv = std::string_view(port_sv.begin(), f1.begin());
|
||||
if (!isLocal()) {
|
||||
// convert port string to int
|
||||
auto end_ptr = port_sv.data() + port_sv.size();
|
||||
|
||||
_path = std::string_view(f1.end(), &*_endpoint.end());
|
||||
auto [ptr, ec] = std::from_chars(port_sv.data(), end_ptr, _port);
|
||||
if (ec != std::errc() || ptr != end_ptr) {
|
||||
return _isValid;
|
||||
}
|
||||
} else { // ignore for local
|
||||
_port = -1;
|
||||
}
|
||||
} else {
|
||||
_port = -1;
|
||||
}
|
||||
|
||||
// convert port string to int
|
||||
auto end_ptr = port_sv.data() + port_sv.size();
|
||||
|
||||
auto [ptr, ec] = std::from_chars(port_sv.data(), end_ptr, _port);
|
||||
if (ec != std::errc() || ptr != end_ptr) {
|
||||
if (isLocal()) { // check for special values
|
||||
idx = 0;
|
||||
if (std::ranges::any_of(validLocalProtoTypes, [&idx, this](const auto& el) {
|
||||
bool ok = utils::AdcCharRangeCompare(_host, el, true);
|
||||
if (!ok) {
|
||||
++idx;
|
||||
}
|
||||
return ok;
|
||||
})) {
|
||||
_host = validLocalProtoTypes[idx];
|
||||
} else {
|
||||
return _isValid;
|
||||
}
|
||||
}
|
||||
@@ -197,6 +221,22 @@ public:
|
||||
return proto() == protoMarkLocal;
|
||||
}
|
||||
|
||||
bool isLocalStream() const
|
||||
{
|
||||
return host() == localProtoTypeStream;
|
||||
}
|
||||
|
||||
bool isLocalDatagram() const
|
||||
{
|
||||
return host() == localProtoTypeDatagram;
|
||||
}
|
||||
|
||||
bool isLocalSeqpacket() const
|
||||
{
|
||||
return host() == localProtoTypeSeqpacket;
|
||||
}
|
||||
|
||||
|
||||
bool isTCP() const
|
||||
{
|
||||
return proto() == protoMarkTCP;
|
||||
@@ -229,10 +269,22 @@ protected:
|
||||
bool _isValid;
|
||||
|
||||
|
||||
virtual bool checkProtoMark(std::string_view proto_mark)
|
||||
virtual ssize_t checkProtoMark(std::string_view proto_mark)
|
||||
{
|
||||
return std::ranges::any_of(AdcEndpointParser::validProtoMarks,
|
||||
[proto_mark](const auto& el) { return el == proto_mark; });
|
||||
ssize_t idx = 0;
|
||||
|
||||
// case-insensitive look-up
|
||||
bool found = std::ranges::any_of(AdcEndpointParser::validProtoMarks, [&idx, &proto_mark, this](const auto& el) {
|
||||
bool ok = utils::AdcCharRangeCompare(proto_mark, el, true);
|
||||
|
||||
if (!ok) {
|
||||
++idx;
|
||||
}
|
||||
|
||||
return ok;
|
||||
});
|
||||
|
||||
return found ? idx : -1;
|
||||
}
|
||||
|
||||
enum EndpointPart { PROTO_PART, HOST_PART, PATH_PART };
|
||||
@@ -242,9 +294,9 @@ protected:
|
||||
{
|
||||
R res;
|
||||
|
||||
if (!_isValid) {
|
||||
return res;
|
||||
}
|
||||
// if (!_isValid) {
|
||||
// return res;
|
||||
// }
|
||||
|
||||
auto part = _proto;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user