mirror of https://github.com/infosecn1nja/C3.git
Add QualityOfService PacketSplitter
parent
69282372d6
commit
8fee6a5fe2
|
@ -92,22 +92,14 @@ namespace FSecure::C3::Linter
|
||||||
|
|
||||||
void MockDeviceBridge::Send(ByteView blob)
|
void MockDeviceBridge::Send(ByteView blob)
|
||||||
{
|
{
|
||||||
auto oryginalSize = static_cast<uint32_t>(blob.size());
|
auto packetSplitter = m_QoS.GetPacketSplitter(blob);
|
||||||
auto messageId = m_QoS.GetOutgouingPacketId();
|
|
||||||
auto chunkId = uint32_t{ 0 };
|
|
||||||
for (auto noProgressCounter = 0; noProgressCounter < 10; ++noProgressCounter)
|
for (auto noProgressCounter = 0; noProgressCounter < 10; ++noProgressCounter)
|
||||||
{
|
{
|
||||||
auto data = ByteVector{}.Write(messageId, chunkId, oryginalSize).Concat(blob);
|
auto sent = GetDevice()->OnSendToChannelInternal(packetSplitter.NextChunk());
|
||||||
auto sent = GetDevice()->OnSendToChannelInternal(data);
|
if (packetSplitter.Update(sent))
|
||||||
|
|
||||||
if (sent >= QualityOfService::s_MinFrameSize || sent == data.size())
|
|
||||||
{
|
|
||||||
chunkId++;
|
|
||||||
noProgressCounter = 0;
|
noProgressCounter = 0;
|
||||||
blob.remove_prefix(sent - QualityOfService::s_HeaderSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blob.empty())
|
if (!packetSplitter.HasMore())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,21 +70,9 @@ void FSecure::C3::Core::DeviceBridge::OnPassNetworkPacket(ByteView packet)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto oryginalSize = static_cast<uint32_t>(packet.size());
|
auto packetSplitter = m_QoS.GetPacketSplitter(packet);
|
||||||
auto messageId = m_QoS.GetOutgouingPacketId();
|
while (packetSplitter.HasMore())
|
||||||
uint32_t chunkId = 0u;
|
packetSplitter.Update(GetDevice()->OnSendToChannelInternal(packetSplitter.NextChunk()));
|
||||||
while (!packet.empty())
|
|
||||||
{
|
|
||||||
auto data = ByteVector{}.Write(messageId, chunkId, oryginalSize).Concat(packet);
|
|
||||||
auto sent = GetDevice()->OnSendToChannelInternal(data);
|
|
||||||
|
|
||||||
if (sent >= QualityOfService::s_MinFrameSize || sent == data.size()) // if this condition were not channel must resend data.
|
|
||||||
{
|
|
||||||
chunkId++;
|
|
||||||
packet.remove_prefix(sent - QualityOfService::s_HeaderSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -24,7 +24,7 @@ FSecure::ByteVector FSecure::C3::QualityOfService::GetNextPacket()
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
void FSecure::C3::QualityOfService::PushReceivedChunk(ByteView chunkWithHeader)
|
void FSecure::C3::QualityOfService::PushReceivedChunk(ByteView chunkWithHeader)
|
||||||
{
|
{
|
||||||
if (chunkWithHeader.size() < QualityOfService::s_HeaderSize) // Data is to short to even be chunk of packet.
|
if (chunkWithHeader.size() <= QualityOfService::s_HeaderSize) // Data is to short to even be chunk of packet.
|
||||||
return; // skip this chunk. there is nothing that can be done with it. If sender knows it pushed chunk to short it will retransmit it.
|
return; // skip this chunk. there is nothing that can be done with it. If sender knows it pushed chunk to short it will retransmit it.
|
||||||
|
|
||||||
auto [mId, cId, expectedSize] = chunkWithHeader.Read<uint32_t, uint32_t, uint32_t>();
|
auto [mId, cId, expectedSize] = chunkWithHeader.Read<uint32_t, uint32_t, uint32_t>();
|
||||||
|
@ -41,6 +41,11 @@ void FSecure::C3::QualityOfService::PushReceivedChunk(uint32_t packetId, uint32_
|
||||||
it->second.PushNextChunk(chunkId, expectedSize, ByteVector{ chunk });
|
it->second.PushNextChunk(chunkId, expectedSize, ByteVector{ chunk });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSecure::C3::PacketSplitter FSecure::C3::QualityOfService::GetPacketSplitter(ByteView data)
|
||||||
|
{
|
||||||
|
return { data, GetOutgouingPacketId() };
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
FSecure::C3::QualityOfService::Packet::Packet(uint32_t chunkId, uint32_t expectedSize, ByteVector chunk)
|
FSecure::C3::QualityOfService::Packet::Packet(uint32_t chunkId, uint32_t expectedSize, ByteVector chunk)
|
||||||
: m_ExpectedSize(expectedSize)
|
: m_ExpectedSize(expectedSize)
|
||||||
|
@ -96,3 +101,30 @@ bool FSecure::C3::QualityOfService::Packet::IsReady()
|
||||||
|
|
||||||
return m_Size == m_ExpectedSize;
|
return m_Size == m_ExpectedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSecure::C3::PacketSplitter::PacketSplitter(ByteView data, uint32_t id)
|
||||||
|
: m_Data{ data }, m_OryginalDataSize{ static_cast<uint32_t>(data.size()) }, m_PacketId{ id }, m_ChunkId{ 0 }
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FSecure::C3::PacketSplitter::Update(size_t sent)
|
||||||
|
{
|
||||||
|
auto dataSent = sent - QualityOfService::s_HeaderSize;
|
||||||
|
if (sent < QualityOfService::s_MinFrameSize && dataSent != m_Data.size() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
++m_ChunkId;
|
||||||
|
m_Data.remove_prefix(dataSent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSecure::ByteVector FSecure::C3::PacketSplitter::NextChunk() const
|
||||||
|
{
|
||||||
|
return ByteVector::Create(m_PacketId, m_ChunkId, m_OryginalDataSize).Concat(m_Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FSecure::C3::PacketSplitter::HasMore() const
|
||||||
|
{
|
||||||
|
return !m_Data.empty();
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,22 @@
|
||||||
|
|
||||||
namespace FSecure::C3
|
namespace FSecure::C3
|
||||||
{
|
{
|
||||||
|
class PacketSplitter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PacketSplitter(ByteView data, uint32_t id);
|
||||||
|
bool Update(size_t sent);
|
||||||
|
ByteVector NextChunk() const;
|
||||||
|
bool HasMore() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ByteView m_Data;
|
||||||
|
uint32_t m_OryginalDataSize;
|
||||||
|
uint32_t m_PacketId;
|
||||||
|
uint32_t m_ChunkId;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// A structure that handles Quality of Service of C3 protocols.
|
/// A structure that handles Quality of Service of C3 protocols.
|
||||||
class QualityOfService
|
class QualityOfService
|
||||||
{
|
{
|
||||||
|
@ -45,6 +61,12 @@ namespace FSecure::C3
|
||||||
/// Used to mark order to outgoing packets.
|
/// Used to mark order to outgoing packets.
|
||||||
uint32_t m_OutgouingPacketId = 0u;
|
uint32_t m_OutgouingPacketId = 0u;
|
||||||
|
|
||||||
|
/// Map of received packets. Packets could be not complete, or there could be packet missing.
|
||||||
|
std::map<uint32_t, Packet> m_ReciveQueue;
|
||||||
|
|
||||||
|
/// Returns next ids for packets.
|
||||||
|
uint32_t GetOutgouingPacketId();
|
||||||
|
|
||||||
/// Used to find order in incoming packets. GetNextPacket will hold ready packets if there was gap in numbering.
|
/// Used to find order in incoming packets. GetNextPacket will hold ready packets if there was gap in numbering.
|
||||||
// removed, manual route table management means that channels should not wait for missing packets. It will be introduced at the edges of network
|
// removed, manual route table management means that channels should not wait for missing packets. It will be introduced at the edges of network
|
||||||
//uint32_t m_IncomigPacketId = 0u;
|
//uint32_t m_IncomigPacketId = 0u;
|
||||||
|
@ -57,9 +79,6 @@ namespace FSecure::C3
|
||||||
static constexpr size_t s_MinFrameSize = 64U;
|
static constexpr size_t s_MinFrameSize = 64U;
|
||||||
static constexpr size_t s_MinBodySize = s_MinFrameSize - s_HeaderSize;
|
static constexpr size_t s_MinBodySize = s_MinFrameSize - s_HeaderSize;
|
||||||
|
|
||||||
/// Map of received packets. Packets could be not complete, or there could be packet missing.
|
|
||||||
std::map<uint32_t, Packet> m_ReciveQueue;
|
|
||||||
|
|
||||||
/// Get next packet.
|
/// Get next packet.
|
||||||
/// @returns ByteVector whole packet when it's ready or empty buffer otherwise.
|
/// @returns ByteVector whole packet when it's ready or empty buffer otherwise.
|
||||||
ByteVector GetNextPacket();
|
ByteVector GetNextPacket();
|
||||||
|
@ -75,8 +94,7 @@ namespace FSecure::C3
|
||||||
/// @param chunk chunk of packet.
|
/// @param chunk chunk of packet.
|
||||||
void PushReceivedChunk(uint32_t packetId, uint32_t chunkId, uint32_t expectedSize, ByteView chunk);
|
void PushReceivedChunk(uint32_t packetId, uint32_t chunkId, uint32_t expectedSize, ByteView chunk);
|
||||||
|
|
||||||
/// Returns next ids for packets.
|
PacketSplitter GetPacketSplitter(ByteView data);
|
||||||
uint32_t GetOutgouingPacketId();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue