diff --git a/Src/Common/MWR/C3/Interfaces/Connectors/TeamServer.cpp b/Src/Common/MWR/C3/Interfaces/Connectors/TeamServer.cpp
index b1c1938..b056f5c 100644
--- a/Src/Common/MWR/C3/Interfaces/Connectors/TeamServer.cpp
+++ b/Src/Common/MWR/C3/Interfaces/Connectors/TeamServer.cpp
@@ -385,7 +385,7 @@ bool MWR::C3::Interfaces::Connectors::TeamServer::Connection::SecondThreadStarte
MWR::ByteVector MWR::C3::Interfaces::Connectors::TeamServer::PeripheralCreationCommand(ByteView connectionId, ByteView data, bool isX64)
{
- auto [pipeName, maxConnectionTrials, delayBetweenConnectionTrials/*, payload*/] = data.Read();
+ auto [pipeName, maxConnectionTrials, delayBetweenConnectionTrials/*, payload*/] = data.Read();
// custom payload is removed from release.
//if (!payload.empty())
diff --git a/Src/Common/MWR/C3/Interfaces/Peripherals/Beacon.cpp b/Src/Common/MWR/C3/Interfaces/Peripherals/Beacon.cpp
index 16c6bbd..e5882da 100644
--- a/Src/Common/MWR/C3/Interfaces/Peripherals/Beacon.cpp
+++ b/Src/Common/MWR/C3/Interfaces/Peripherals/Beacon.cpp
@@ -4,7 +4,7 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MWR::C3::Interfaces::Peripherals::Beacon::Beacon(ByteView arguments)
{
- auto [pipeName, maxConnectionTrials, delayBetweenConnectionTrials, payload] = arguments.Read();
+ auto [pipeName, maxConnectionTrials, delayBetweenConnectionTrials, payload] = arguments.Read();
// Arguments validation.
if (payload.empty())
diff --git a/Src/Common/MWR/CppTools/ByteView.h b/Src/Common/MWR/CppTools/ByteView.h
index 7d4f201..0f17626 100644
--- a/Src/Common/MWR/CppTools/ByteView.h
+++ b/Src/Common/MWR/CppTools/ByteView.h
@@ -40,6 +40,10 @@ namespace MWR
/// @returns std::vector tokenized string.
std::vector SplitAndCopy(std::string_view stringToBeSplitted, std::string_view delimiter);
+ /// Idiom for detecting ByteView::Get.
+ template
+ constexpr bool IsGetter = false;
+
/// Non owning container.
class ByteView : std::basic_string_view
{
@@ -136,6 +140,7 @@ namespace MWR
using Super::npos;
using Super::value_type;
+
/// @returns ByteVector. Owning container with the read bytes.
/// @param byteCount. How many bytes should be read.
/// @remarks Read is not compatible with Read.
@@ -187,7 +192,7 @@ namespace MWR
/// Read bytes and remove them from ByteView.
/// @returns ByteArray. Owning container with the read bytes.
/// @throws std::out_of_range. If ByteView is too short to hold size of object to return.
- template, int> = 0>
+ template
std::enable_if_t, T> Read()
{
if (std::tuple_size::value > size())
@@ -223,6 +228,35 @@ namespace MWR
return TupleGenerator::Generate(*this);
}
+ /// Class allowing reading N bytes without coping data like in ByeView::Read> or ByteView::Reed(size_t).
+ template
+ class Get
+ {
+ public:
+ /// Define size marker.
+ static constexpr size_t size = N;
+ static constexpr size_t Size = size;
+
+ private:
+ /// Private constructor.
+ /// This class should never be instantiated.
+ Get() = default;
+ };
+
+ /// Read bytes and remove them from ByteView.
+ /// @returns ByteView. Non owning container with the read bytes.
+ /// @throws std::out_of_range. If ByteView is too short to hold size of object to return.
+ template
+ std::enable_if_t, ByteView> Read()
+ {
+ if (T::Size > size())
+ throw std::out_of_range{ OBF(": Cannot read data from ByteView") };
+
+ auto retVal = SubString(0, T::Size);
+ remove_prefix(T::Size);
+ return retVal;
+ }
+
/// Read tuple and remove bytes from ByteView.
/// @tparam T. Parameter pack of types to be stored in tuple. Must consist more then one type. Each of types must be parsable by Reed template for one type.
/// @returns std::tuple. Tuple will store types provided in parameter pack.
@@ -273,7 +307,7 @@ namespace MWR
{
auto current = std::make_tuple(self.Read());
auto rest = VariadicTupleGenerator::Generate(self);
- return std::tuple_cat(current, rest);
+ return std::tuple_cat(std::move(current), std::move(rest));
}
};
@@ -325,6 +359,14 @@ namespace MWR
};
};
+ /// Specialization of idiom for detecting ByteView::Get.
+ template
+ constexpr bool IsGetter> = true;
+
+ /// Alias for simpler use of ByteView::Get.
+ template
+ using Bytes = ByteView::Get;
+
namespace Literals
{
/// Create ByteView with syntax ""_bvec
diff --git a/Src/Core/GateRelay.cpp b/Src/Core/GateRelay.cpp
index 0ae470e..91dae24 100644
--- a/Src/Core/GateRelay.cpp
+++ b/Src/Core/GateRelay.cpp
@@ -47,7 +47,7 @@ void MWR::C3::Core::GateRelay::OnProtocolS2G(ByteView packet0, std::shared_ptr, int32_t>();
+ auto [procedure, rid, timestamp] = ByteView{ decrypted }.Read, int32_t>();
if (!m_Profiler->Get().m_Gateway.ConnectionExist(RouteId::FromByteView(rid).GetAgentId()))
throw std::runtime_error{ "S2G packet received from not connected source." };
@@ -274,10 +274,10 @@ void MWR::C3::Core::GateRelay::On(ProceduresN2N::InitializeRouteQuery&& query)
auto readView = ByteView{ decryptedPacket };
auto newRelayBuildId = BuildId{ readView.Read() };
// todo prepending fixed-size key with 4 byte length is unnecessary, (remember to change writing, not only reading)
- auto newRelayPublicKey = Crypto::PublicKey{ readView.Read() };
+ auto newRelayPublicKey = Crypto::PublicKey{ readView.Read() };
auto hash = readView.Read();
auto lastSeen = readView.Read();
- HostInfo hostInfo(ByteView{ readView.Read() });
+ HostInfo hostInfo(readView.Read());
auto receivedFrom = query.GetSenderChannel().lock();
if (!receivedFrom)
@@ -299,17 +299,17 @@ void MWR::C3::Core::GateRelay::On(ProceduresS2G::InitializeRouteQuery&& query)
auto readView = ByteView{ decryptedPacket };
// part of message created by parent Node
- auto [procedureID, parentRid, timestamp, childRid, childSideDid] = readView.Read, int32_t, ByteArray, ByteArray>();
+ auto [procedureID, parentRid, timestamp, childRid, childSideDid] = readView.Read, int32_t, Bytes, Bytes>();
// part of message from new relay. encrypted once again because it was blob for parent relay.
auto childPacket = Crypto::DecryptFromAnonymous(readView, m_AuthenticationKey, m_DecryptionKey);
readView = ByteView{ childPacket };
auto newRelayBuildId = BuildId{ readView.Read() }; // todo blocking
- auto newRelayPublicKey = Crypto::PublicKey{ readView.Read() };
+ auto newRelayPublicKey = Crypto::PublicKey{ readView.Read() };
auto hash = readView.Read();
auto lastSeen = readView.Read();
- HostInfo hostInfo(ByteView{ readView.Read() });
+ HostInfo hostInfo(readView.Read());
auto receivedFrom = query.GetSenderChannel().lock();
if (!receivedFrom)
@@ -337,9 +337,9 @@ void MWR::C3::Core::GateRelay::On(ProceduresS2G::DeliverToBinder query)
auto readView = ByteView{ decryptedPacket };
auto unusedProtocolId = readView.Read();
- auto senderRid = RouteId::FromByteView(readView.Read>());
+ auto senderRid = RouteId::FromByteView(readView.Read>());
auto timestamp = readView.Read();
- auto deviceId = readView.Read>();
+ auto deviceId = readView.Read>();
auto connectorHash = readView.Read();
auto connector = m_Connectors.Find([&](auto const& e){ return e->GetNameHash() == connectorHash; });
@@ -372,7 +372,7 @@ void MWR::C3::Core::GateRelay::On(ProceduresS2G::AddDeviceResponse response)
{
auto decryptedPacket = response.GetQueryPacket(m_AuthenticationKey, m_DecryptionKey);
auto readView = ByteView{ decryptedPacket };
- auto [unsusedProcedureNo, unusedSenderRouteId, timestamp, deviceId, deviceTypeHash, flags] = readView.Read, int32_t, DeviceId::UnderlyingIntegerType, HashT, std::uint8_t>();
+ auto [unsusedProcedureNo, unusedSenderRouteId, timestamp, deviceId, deviceTypeHash, flags] = readView.Read, int32_t, DeviceId::UnderlyingIntegerType, HashT, std::uint8_t>();
bool isChannel = flags & 1;
bool isNegotiationChannel = flags & (1 << 1);
@@ -393,7 +393,7 @@ void MWR::C3::Core::GateRelay::On(ProceduresS2G::AddDeviceResponse response)
void MWR::C3::Core::GateRelay::On(ProceduresN2N::ChannelIdExchangeStep1 query)
{
auto readView = ByteView{ query.GetQueryPacket() };
- auto newOutputId = readView.Read();
+ auto newOutputId = readView.Read();
auto newInputId = MWR::Utils::GenerateRandomString(newOutputId.size());
auto sender = query.GetSenderChannel().lock();
@@ -426,7 +426,7 @@ void MWR::C3::Core::GateRelay::On(ProceduresS2G::NewNegotiatedChannelNotificatio
{
auto decryptedPacket = query.GetQueryPacket(m_AuthenticationKey, m_DecryptionKey);
auto readView = ByteView{ decryptedPacket };
- auto [unsusedProcedureNo, unusedSenderRouteId, timestamp, newDeviceId, negotiatorId, inId, outId] = readView.Read, int32_t, DeviceId::UnderlyingIntegerType, DeviceId::UnderlyingIntegerType, std::string, std::string>();
+ auto [unsusedProcedureNo, unusedSenderRouteId, timestamp, newDeviceId, negotiatorId, inId, outId] = readView.Read, int32_t, DeviceId::UnderlyingIntegerType, DeviceId::UnderlyingIntegerType, std::string, std::string>();
auto agent = m_Profiler->Get().m_Gateway.m_Agents.Find(query.GetSenderRouteId().GetAgentId());
if (!agent)
@@ -448,7 +448,7 @@ void MWR::C3::Core::GateRelay::On(ProceduresS2G::Notification query)
{
auto decryptedPacket = query.GetQueryPacket(m_AuthenticationKey, m_DecryptionKey);
auto readView = ByteView{ decryptedPacket };
- auto [unsusedProcedureNo, unusedSenderRouteId, timestamp, blob] = readView.Read, int32_t, ByteVector>();
+ auto [unsusedProcedureNo, unusedSenderRouteId, timestamp, blob] = readView.Read, int32_t, ByteView>();
// blob has not defined structure. Currently Notification is used as ping response.
auto agent = m_Profiler->Get().m_Gateway.m_Agents.Find(query.GetSenderRouteId().GetAgentId());
diff --git a/Src/Core/NodeRelay.cpp b/Src/Core/NodeRelay.cpp
index beb0522..b3b7802 100644
--- a/Src/Core/NodeRelay.cpp
+++ b/Src/Core/NodeRelay.cpp
@@ -247,7 +247,7 @@ void MWR::C3::Core::NodeRelay::On(ProceduresG2X::RunCommandOnAgentQuery query)
void MWR::C3::Core::NodeRelay::On(ProceduresG2X::AddRoute query)
{
auto recipient = query.GetRecipientRouteId();
- auto [newRouteBA, directionDidBA] = ByteView{ query.GetPacketBody() }.Read, ByteArray>();
+ auto [newRouteBA, directionDidBA] = ByteView{ query.GetPacketBody() }.Read, Bytes>();
auto newRoute = RouteId::FromByteView(newRouteBA);
auto directionDid = DeviceId(directionDidBA);
std::shared_ptr bridge;
@@ -301,7 +301,7 @@ void MWR::C3::Core::NodeRelay::On(ProceduresG2X::DeliverToBinder query)
void MWR::C3::Core::NodeRelay::On(ProceduresN2N::ChannelIdExchangeStep1 query)
{
auto readView = ByteView{ query.GetQueryPacket() };
- auto newOutputId = readView.Read();
+ auto newOutputId = readView.Read();
auto newInputId = MWR::Utils::GenerateRandomString(newOutputId.size());
auto sender = query.GetSenderChannel().lock();
@@ -324,7 +324,7 @@ void MWR::C3::Core::NodeRelay::On(ProceduresN2N::ChannelIdExchangeStep1 query)
void MWR::C3::Core::NodeRelay::On(ProceduresN2N::ChannelIdExchangeStep2 query)
{
auto readView = ByteView{ query.GetQueryPacket() };
- auto newOutputId = readView.Read();
+ auto newOutputId = readView.Read();
auto sender = query.GetSenderChannel().lock();
@@ -334,7 +334,7 @@ void MWR::C3::Core::NodeRelay::On(ProceduresN2N::ChannelIdExchangeStep2 query)
ByteVector args = sender->GetChannelParameters();
auto hash = sender->GetTypeNameHash();
- auto newInputId = ByteVector{ sender->GetInputId() };
+ auto newInputId = sender->GetInputId() ;
DetachDevice(sender->GetDid());
sender.reset();
// Don't use sender below;
diff --git a/Src/Core/Relay.cpp b/Src/Core/Relay.cpp
index 7df9a82..ab6774c 100644
--- a/Src/Core/Relay.cpp
+++ b/Src/Core/Relay.cpp
@@ -41,7 +41,7 @@ std::shared_ptr MWR::C3::Core::Relay::CreateAndAtta
if (isNegotiationChannel)
{
auto readView = commandLine;
- auto negotiationId = readView.Read();
+ auto negotiationId = readView.Read();
helper.reserve(commandLine.size() + negotiationId.size() + sizeof(std::uint32_t));
auto generatedId = MWR::Utils::GenerateRandomString(negotiationId.size());
if (negotiationClient)