Allow retriving N bytes of data without coping using variadic ByteView::Read

dependabot/npm_and_yarn/Src/WebController/UI/websocket-extensions-0.1.4
Pawel Kurowski 2019-09-12 13:37:52 +02:00
parent 17d2604c26
commit ffe0d66fcd
6 changed files with 63 additions and 21 deletions

View File

@ -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) MWR::ByteVector MWR::C3::Interfaces::Connectors::TeamServer::PeripheralCreationCommand(ByteView connectionId, ByteView data, bool isX64)
{ {
auto [pipeName, maxConnectionTrials, delayBetweenConnectionTrials/*, payload*/] = data.Read<std::string, uint16_t, uint16_t/*, ByteVector*/>(); auto [pipeName, maxConnectionTrials, delayBetweenConnectionTrials/*, payload*/] = data.Read<std::string, uint16_t, uint16_t/*, ByteView*/>();
// custom payload is removed from release. // custom payload is removed from release.
//if (!payload.empty()) //if (!payload.empty())

View File

@ -4,7 +4,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MWR::C3::Interfaces::Peripherals::Beacon::Beacon(ByteView arguments) MWR::C3::Interfaces::Peripherals::Beacon::Beacon(ByteView arguments)
{ {
auto [pipeName, maxConnectionTrials, delayBetweenConnectionTrials, payload] = arguments.Read<std::string, uint16_t, uint16_t, ByteVector>(); auto [pipeName, maxConnectionTrials, delayBetweenConnectionTrials, payload] = arguments.Read<std::string, uint16_t, uint16_t, ByteView>();
// Arguments validation. // Arguments validation.
if (payload.empty()) if (payload.empty())

View File

@ -40,6 +40,10 @@ namespace MWR
/// @returns std::vector<std::string> tokenized string. /// @returns std::vector<std::string> tokenized string.
std::vector<std::string> SplitAndCopy(std::string_view stringToBeSplitted, std::string_view delimiter); std::vector<std::string> SplitAndCopy(std::string_view stringToBeSplitted, std::string_view delimiter);
/// Idiom for detecting ByteView::Get.
template <typename X>
constexpr bool IsGetter = false;
/// Non owning container. /// Non owning container.
class ByteView : std::basic_string_view<ByteVector::value_type> class ByteView : std::basic_string_view<ByteVector::value_type>
{ {
@ -136,6 +140,7 @@ namespace MWR
using Super::npos; using Super::npos;
using Super::value_type; using Super::value_type;
/// @returns ByteVector. Owning container with the read bytes. /// @returns ByteVector. Owning container with the read bytes.
/// @param byteCount. How many bytes should be read. /// @param byteCount. How many bytes should be read.
/// @remarks Read is not compatible with Read<ByteVector>. /// @remarks Read is not compatible with Read<ByteVector>.
@ -187,7 +192,7 @@ namespace MWR
/// Read bytes and remove them from ByteView. /// Read bytes and remove them from ByteView.
/// @returns ByteArray. Owning container with the read bytes. /// @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. /// @throws std::out_of_range. If ByteView is too short to hold size of object to return.
template<typename T, typename std::enable_if_t<IsByteArray<T>, int> = 0> template<typename T>
std::enable_if_t<IsByteArray<T>, T> Read() std::enable_if_t<IsByteArray<T>, T> Read()
{ {
if (std::tuple_size<typename T>::value > size()) if (std::tuple_size<typename T>::value > size())
@ -223,6 +228,35 @@ namespace MWR
return TupleGenerator<T>::Generate(*this); return TupleGenerator<T>::Generate(*this);
} }
/// Class allowing reading N bytes without coping data like in ByeView::Read<ByteArray<N>> or ByteView::Reed(size_t).
template <size_t N>
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<typename T>
std::enable_if_t<IsGetter<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. /// 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. /// @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. /// @returns std::tuple. Tuple will store types provided in parameter pack.
@ -273,7 +307,7 @@ namespace MWR
{ {
auto current = std::make_tuple(self.Read<T>()); auto current = std::make_tuple(self.Read<T>());
auto rest = VariadicTupleGenerator<Rest...>::Generate(self); auto rest = VariadicTupleGenerator<Rest...>::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<size_t N>
constexpr bool IsGetter<ByteView::Get<N>> = true;
/// Alias for simpler use of ByteView::Get.
template<size_t N>
using Bytes = ByteView::Get<N>;
namespace Literals namespace Literals
{ {
/// Create ByteView with syntax ""_bvec /// Create ByteView with syntax ""_bvec

View File

@ -47,7 +47,7 @@ void MWR::C3::Core::GateRelay::OnProtocolS2G(ByteView packet0, std::shared_ptr<D
try try
{ {
auto decrypted = MWR::Crypto::DecryptFromAnonymous(packet0.SubString(1), m_AuthenticationKey, m_DecryptionKey); auto decrypted = MWR::Crypto::DecryptFromAnonymous(packet0.SubString(1), m_AuthenticationKey, m_DecryptionKey);
auto [procedure, rid, timestamp] = ByteView{ decrypted }.Read<ProceduresUnderlyingType, ByteArray<RouteId::BinarySize>, int32_t>(); auto [procedure, rid, timestamp] = ByteView{ decrypted }.Read<ProceduresUnderlyingType, Bytes<RouteId::BinarySize>, int32_t>();
if (!m_Profiler->Get().m_Gateway.ConnectionExist(RouteId::FromByteView(rid).GetAgentId())) if (!m_Profiler->Get().m_Gateway.ConnectionExist(RouteId::FromByteView(rid).GetAgentId()))
throw std::runtime_error{ "S2G packet received from not connected source." }; 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 readView = ByteView{ decryptedPacket };
auto newRelayBuildId = BuildId{ readView.Read<BuildId::UnderlyingIntegerType>() }; auto newRelayBuildId = BuildId{ readView.Read<BuildId::UnderlyingIntegerType>() };
// todo prepending fixed-size key with 4 byte length is unnecessary, (remember to change writing, not only reading) // todo prepending fixed-size key with 4 byte length is unnecessary, (remember to change writing, not only reading)
auto newRelayPublicKey = Crypto::PublicKey{ readView.Read<ByteVector>() }; auto newRelayPublicKey = Crypto::PublicKey{ readView.Read<ByteView>() };
auto hash = readView.Read<HashT>(); auto hash = readView.Read<HashT>();
auto lastSeen = readView.Read<int32_t>(); auto lastSeen = readView.Read<int32_t>();
HostInfo hostInfo(ByteView{ readView.Read<ByteVector>() }); HostInfo hostInfo(readView.Read<ByteView>());
auto receivedFrom = query.GetSenderChannel().lock(); auto receivedFrom = query.GetSenderChannel().lock();
if (!receivedFrom) if (!receivedFrom)
@ -299,17 +299,17 @@ void MWR::C3::Core::GateRelay::On(ProceduresS2G::InitializeRouteQuery&& query)
auto readView = ByteView{ decryptedPacket }; auto readView = ByteView{ decryptedPacket };
// part of message created by parent Node // part of message created by parent Node
auto [procedureID, parentRid, timestamp, childRid, childSideDid] = readView.Read<ProceduresUnderlyingType, ByteArray<RouteId::BinarySize>, int32_t, ByteArray<RouteId::BinarySize>, ByteArray<DeviceId::BinarySize>>(); auto [procedureID, parentRid, timestamp, childRid, childSideDid] = readView.Read<ProceduresUnderlyingType, Bytes<RouteId::BinarySize>, int32_t, Bytes<RouteId::BinarySize>, Bytes<DeviceId::BinarySize>>();
// part of message from new relay. encrypted once again because it was blob for parent relay. // 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); auto childPacket = Crypto::DecryptFromAnonymous(readView, m_AuthenticationKey, m_DecryptionKey);
readView = ByteView{ childPacket }; readView = ByteView{ childPacket };
auto newRelayBuildId = BuildId{ readView.Read<BuildId::UnderlyingIntegerType>() }; // todo blocking auto newRelayBuildId = BuildId{ readView.Read<BuildId::UnderlyingIntegerType>() }; // todo blocking
auto newRelayPublicKey = Crypto::PublicKey{ readView.Read<ByteVector>() }; auto newRelayPublicKey = Crypto::PublicKey{ readView.Read<ByteView>() };
auto hash = readView.Read<HashT>(); auto hash = readView.Read<HashT>();
auto lastSeen = readView.Read<int32_t>(); auto lastSeen = readView.Read<int32_t>();
HostInfo hostInfo(ByteView{ readView.Read<ByteVector>() }); HostInfo hostInfo(readView.Read<ByteView>());
auto receivedFrom = query.GetSenderChannel().lock(); auto receivedFrom = query.GetSenderChannel().lock();
if (!receivedFrom) if (!receivedFrom)
@ -337,9 +337,9 @@ void MWR::C3::Core::GateRelay::On(ProceduresS2G::DeliverToBinder query)
auto readView = ByteView{ decryptedPacket }; auto readView = ByteView{ decryptedPacket };
auto unusedProtocolId = readView.Read<int8_t>(); auto unusedProtocolId = readView.Read<int8_t>();
auto senderRid = RouteId::FromByteView(readView.Read<ByteArray<RouteId::BinarySize>>()); auto senderRid = RouteId::FromByteView(readView.Read<Bytes<RouteId::BinarySize>>());
auto timestamp = readView.Read<int32_t>(); auto timestamp = readView.Read<int32_t>();
auto deviceId = readView.Read<ByteArray<DeviceId::BinarySize>>(); auto deviceId = readView.Read<Bytes<DeviceId::BinarySize>>();
auto connectorHash = readView.Read<HashT>(); auto connectorHash = readView.Read<HashT>();
auto connector = m_Connectors.Find([&](auto const& e){ return e->GetNameHash() == connectorHash; }); 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 decryptedPacket = response.GetQueryPacket(m_AuthenticationKey, m_DecryptionKey);
auto readView = ByteView{ decryptedPacket }; auto readView = ByteView{ decryptedPacket };
auto [unsusedProcedureNo, unusedSenderRouteId, timestamp, deviceId, deviceTypeHash, flags] = readView.Read<ProceduresUnderlyingType, ByteArray<RouteId::BinarySize>, int32_t, DeviceId::UnderlyingIntegerType, HashT, std::uint8_t>(); auto [unsusedProcedureNo, unusedSenderRouteId, timestamp, deviceId, deviceTypeHash, flags] = readView.Read<ProceduresUnderlyingType, Bytes<RouteId::BinarySize>, int32_t, DeviceId::UnderlyingIntegerType, HashT, std::uint8_t>();
bool isChannel = flags & 1; bool isChannel = flags & 1;
bool isNegotiationChannel = flags & (1 << 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) void MWR::C3::Core::GateRelay::On(ProceduresN2N::ChannelIdExchangeStep1 query)
{ {
auto readView = ByteView{ query.GetQueryPacket() }; auto readView = ByteView{ query.GetQueryPacket() };
auto newOutputId = readView.Read<ByteVector>(); auto newOutputId = readView.Read<ByteView>();
auto newInputId = MWR::Utils::GenerateRandomString(newOutputId.size()); auto newInputId = MWR::Utils::GenerateRandomString(newOutputId.size());
auto sender = query.GetSenderChannel().lock(); 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 decryptedPacket = query.GetQueryPacket(m_AuthenticationKey, m_DecryptionKey);
auto readView = ByteView{ decryptedPacket }; auto readView = ByteView{ decryptedPacket };
auto [unsusedProcedureNo, unusedSenderRouteId, timestamp, newDeviceId, negotiatorId, inId, outId] = readView.Read<ProceduresUnderlyingType, ByteArray<RouteId::BinarySize>, int32_t, DeviceId::UnderlyingIntegerType, DeviceId::UnderlyingIntegerType, std::string, std::string>(); auto [unsusedProcedureNo, unusedSenderRouteId, timestamp, newDeviceId, negotiatorId, inId, outId] = readView.Read<ProceduresUnderlyingType, Bytes<RouteId::BinarySize>, int32_t, DeviceId::UnderlyingIntegerType, DeviceId::UnderlyingIntegerType, std::string, std::string>();
auto agent = m_Profiler->Get().m_Gateway.m_Agents.Find(query.GetSenderRouteId().GetAgentId()); auto agent = m_Profiler->Get().m_Gateway.m_Agents.Find(query.GetSenderRouteId().GetAgentId());
if (!agent) if (!agent)
@ -448,7 +448,7 @@ void MWR::C3::Core::GateRelay::On(ProceduresS2G::Notification query)
{ {
auto decryptedPacket = query.GetQueryPacket(m_AuthenticationKey, m_DecryptionKey); auto decryptedPacket = query.GetQueryPacket(m_AuthenticationKey, m_DecryptionKey);
auto readView = ByteView{ decryptedPacket }; auto readView = ByteView{ decryptedPacket };
auto [unsusedProcedureNo, unusedSenderRouteId, timestamp, blob] = readView.Read<ProceduresUnderlyingType, ByteArray<RouteId::BinarySize>, int32_t, ByteVector>(); auto [unsusedProcedureNo, unusedSenderRouteId, timestamp, blob] = readView.Read<ProceduresUnderlyingType, Bytes<RouteId::BinarySize>, int32_t, ByteView>();
// blob has not defined structure. Currently Notification is used as ping response. // 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()); auto agent = m_Profiler->Get().m_Gateway.m_Agents.Find(query.GetSenderRouteId().GetAgentId());

View File

@ -247,7 +247,7 @@ void MWR::C3::Core::NodeRelay::On(ProceduresG2X::RunCommandOnAgentQuery query)
void MWR::C3::Core::NodeRelay::On(ProceduresG2X::AddRoute query) void MWR::C3::Core::NodeRelay::On(ProceduresG2X::AddRoute query)
{ {
auto recipient = query.GetRecipientRouteId(); auto recipient = query.GetRecipientRouteId();
auto [newRouteBA, directionDidBA] = ByteView{ query.GetPacketBody() }.Read<ByteArray<RouteId::BinarySize>, ByteArray<DeviceId::BinarySize>>(); auto [newRouteBA, directionDidBA] = ByteView{ query.GetPacketBody() }.Read<Bytes<RouteId::BinarySize>, Bytes<DeviceId::BinarySize>>();
auto newRoute = RouteId::FromByteView(newRouteBA); auto newRoute = RouteId::FromByteView(newRouteBA);
auto directionDid = DeviceId(directionDidBA); auto directionDid = DeviceId(directionDidBA);
std::shared_ptr<DeviceBridge> bridge; std::shared_ptr<DeviceBridge> bridge;
@ -301,7 +301,7 @@ void MWR::C3::Core::NodeRelay::On(ProceduresG2X::DeliverToBinder query)
void MWR::C3::Core::NodeRelay::On(ProceduresN2N::ChannelIdExchangeStep1 query) void MWR::C3::Core::NodeRelay::On(ProceduresN2N::ChannelIdExchangeStep1 query)
{ {
auto readView = ByteView{ query.GetQueryPacket() }; auto readView = ByteView{ query.GetQueryPacket() };
auto newOutputId = readView.Read<ByteVector>(); auto newOutputId = readView.Read<ByteView>();
auto newInputId = MWR::Utils::GenerateRandomString(newOutputId.size()); auto newInputId = MWR::Utils::GenerateRandomString(newOutputId.size());
auto sender = query.GetSenderChannel().lock(); 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) void MWR::C3::Core::NodeRelay::On(ProceduresN2N::ChannelIdExchangeStep2 query)
{ {
auto readView = ByteView{ query.GetQueryPacket() }; auto readView = ByteView{ query.GetQueryPacket() };
auto newOutputId = readView.Read<ByteVector>(); auto newOutputId = readView.Read<ByteView>();
auto sender = query.GetSenderChannel().lock(); auto sender = query.GetSenderChannel().lock();
@ -334,7 +334,7 @@ void MWR::C3::Core::NodeRelay::On(ProceduresN2N::ChannelIdExchangeStep2 query)
ByteVector args = sender->GetChannelParameters(); ByteVector args = sender->GetChannelParameters();
auto hash = sender->GetTypeNameHash(); auto hash = sender->GetTypeNameHash();
auto newInputId = ByteVector{ sender->GetInputId() }; auto newInputId = sender->GetInputId() ;
DetachDevice(sender->GetDid()); DetachDevice(sender->GetDid());
sender.reset(); sender.reset();
// Don't use sender below; // Don't use sender below;

View File

@ -41,7 +41,7 @@ std::shared_ptr<MWR::C3::Core::DeviceBridge> MWR::C3::Core::Relay::CreateAndAtta
if (isNegotiationChannel) if (isNegotiationChannel)
{ {
auto readView = commandLine; auto readView = commandLine;
auto negotiationId = readView.Read<ByteVector>(); auto negotiationId = readView.Read<ByteView>();
helper.reserve(commandLine.size() + negotiationId.size() + sizeof(std::uint32_t)); helper.reserve(commandLine.size() + negotiationId.size() + sizeof(std::uint32_t));
auto generatedId = MWR::Utils::GenerateRandomString(negotiationId.size()); auto generatedId = MWR::Utils::GenerateRandomString(negotiationId.size());
if (negotiationClient) if (negotiationClient)