correct packetbuffer issues;

pull/129/head
Bryan Biedenkapp 2 weeks ago
parent fc23017cf2
commit cb390aa0cd

@ -22,7 +22,7 @@ using namespace compress;
// ---------------------------------------------------------------------------
#define MAX_FRAGMENT_SIZE 8192 * 1024 // 8MB max
#define MAX_BLOCK_CNT 254
// ---------------------------------------------------------------------------
// Public Class Members
@ -164,6 +164,13 @@ bool PacketBuffer::decode(const uint8_t* data, uint8_t** message, uint32_t* outL
if (m_compression) {
uint32_t decompressedLen = 0U;
UInt8Array decompressed = Compression::decompress(buffer, compressedLen, &decompressedLen);
if (decompressed == nullptr || decompressedLen == 0U) {
LogError(LOG_NET, "%s, Packet Fragment, error decompressing packet data", m_name);
fragments.unlock();
clear();
return false;
}
*message = new uint8_t[decompressedLen];
::memset(*message, 0x00U, decompressedLen);
::memcpy(*message, decompressed.get(), decompressedLen);
@ -202,7 +209,7 @@ bool PacketBuffer::decode(const uint8_t* data, uint8_t** message, uint32_t* outL
/* Encode a network packet fragment. */
void PacketBuffer::encode(uint8_t* data, uint32_t length)
bool PacketBuffer::encode(uint8_t* data, uint32_t length)
{
assert(data != nullptr);
assert(length > 0U);
@ -224,6 +231,11 @@ void PacketBuffer::encode(uint8_t* data, uint32_t length)
// create packet fragments
uint8_t blockCnt = (compressedLen / FRAG_BLOCK_SIZE) + (compressedLen % FRAG_BLOCK_SIZE ? 1U : 0U);
if (blockCnt > MAX_BLOCK_CNT) {
LogError(LOG_NET, "%s, Outbound Packet Fragment, too many packet fragments, %u (max %u)", m_name, blockCnt, MAX_BLOCK_CNT);
return false;
}
uint32_t offs = 0U;
for (uint8_t i = 0U; i < blockCnt; i++) {
// build dataset
@ -256,6 +268,8 @@ void PacketBuffer::encode(uint8_t* data, uint32_t length)
fragments.insert(i, frag);
LogInfoEx(LOG_NET, "%s, Outbound Packet Fragment, block %u of %u, txFragments = %u", m_name, i, blockCnt - 1U, fragments.size());
}
return true;
}
/* Helper to clear currently buffered fragments. */

@ -82,8 +82,9 @@ namespace network
* @brief Encode a network packet fragment.
* @param[out] data Message to encode.
* @param length Length of message.
* @returns bool True if encoding was successful, false otherwise.
*/
void encode(uint8_t* data, uint32_t length);
bool encode(uint8_t* data, uint32_t length);
/**
* @brief Helper to clear currently buffered fragments.

@ -146,7 +146,11 @@ bool PeerNetwork::writePeerLinkPeers(json::array* peerList)
::snprintf(buffer + 8U, json.length() + 1U, "%s", json.c_str());
PacketBuffer pkt(true, "Peer Replication, Active Peer List");
pkt.encode((uint8_t*)buffer, len);
bool success = pkt.encode((uint8_t*)buffer, len);
if (!success) {
LogError(LOG_REPL, "PEER %u Peer Replication, Active Peer List, failed to encode packet", m_peerId);
return false;
}
uint32_t streamId = createStreamId();
LogInfoEx(LOG_REPL, "PEER %u Peer Replication, Active Peer List, blocks %u, streamId = %u", m_peerId, pkt.fragments.size(), streamId);
@ -188,7 +192,11 @@ bool PeerNetwork::writeSpanningTree(SpanningTree* treeRoot)
::snprintf(buffer + 8U, json.length() + 1U, "%s", json.c_str());
PacketBuffer pkt(true, "Network Tree, Tree List");
pkt.encode((uint8_t*)buffer, len);
bool success = pkt.encode((uint8_t*)buffer, len);
if (!success) {
LogError(LOG_STP, "PEER %u Network Tree, Tree List, failed to encode packet", m_peerId);
return false;
}
uint32_t streamId = createStreamId();
LogInfoEx(LOG_STP, "PEER %u Network Tree, Tree List, blocks %u, streamId = %u", m_peerId, pkt.fragments.size(), streamId);

@ -1914,7 +1914,11 @@ void TrafficNetwork::writeWhitelistRIDs(uint32_t peerId, uint32_t streamId, bool
::memcpy(buffer, b.str().data(), len);
PacketBuffer pkt(true, "Peer Replication, RID List");
pkt.encode((uint8_t*)buffer, len);
bool success = pkt.encode((uint8_t*)buffer, len);
if (!success) {
LogError(LOG_REPL, "PEER %u (%s) Peer Replication, RID List, failed to encode packet", peerId, connection->identWithQualifier().c_str());
return;
}
LogInfoEx(LOG_REPL, "PEER %u (%s) Peer Replication, RID List, blocks %u, streamId = %u", peerId, connection->identWithQualifier().c_str(),
pkt.fragments.size(), streamId);
@ -2115,7 +2119,11 @@ void TrafficNetwork::writeTGIDs(uint32_t peerId, uint32_t streamId, bool sendRep
::memcpy(buffer, b.str().data(), len);
PacketBuffer pkt(true, "Peer Replication, TGID List");
pkt.encode((uint8_t*)buffer, len);
bool success = pkt.encode((uint8_t*)buffer, len);
if (!success) {
LogError(LOG_REPL, "PEER %u (%s) Peer Replication, TGID List, failed to encode packet", peerId, connection->identWithQualifier().c_str());
return;
}
LogInfoEx(LOG_REPL, "PEER %u (%s) Peer Replication, TGID List, blocks %u, streamId = %u", peerId, connection->identWithQualifier().c_str(),
pkt.fragments.size(), streamId);
@ -2317,7 +2325,11 @@ void TrafficNetwork::writeRadioAliasList(uint32_t peerId, uint32_t streamId)
::memcpy(buffer, b.str().data(), len);
PacketBuffer pkt(true, "Peer Replication, RID Alias List");
pkt.encode((uint8_t*)buffer, len);
bool success = pkt.encode((uint8_t*)buffer, len);
if (!success) {
LogError(LOG_REPL, "PEER %u (%s) Peer Replication, RID Alias List, failed to encode packet", peerId, connection->identWithQualifier().c_str());
return;
}
LogInfoEx(LOG_REPL, "PEER %u (%s) Peer Replication, RID Alias List, blocks %u, streamId = %u", peerId, connection->identWithQualifier().c_str(),
pkt.fragments.size(), streamId);
@ -2379,7 +2391,11 @@ void TrafficNetwork::writePeerList(uint32_t peerId, uint32_t streamId)
::memcpy(buffer, b.str().data(), len);
PacketBuffer pkt(true, "Peer Replication, PID List");
pkt.encode((uint8_t*)buffer, len);
bool success = pkt.encode((uint8_t*)buffer, len);
if (!success) {
LogError(LOG_REPL, "PEER %u (%s) Peer Replication, PID List, failed to encode packet", peerId, connection->identWithQualifier().c_str());
return;
}
LogInfoEx(LOG_REPL, "PEER %u (%s) Peer Replication, PID List, blocks %u, streamId = %u", peerId, connection->identWithQualifier().c_str(),
pkt.fragments.size(), streamId);

@ -194,7 +194,11 @@ void MetadataNetwork::PacketHandler::keysInventory(TrafficNetwork* network, Meta
}
PacketBuffer pkt(true, "Remote EKC, Key Inventory");
pkt.encode((uint8_t*)buffer, len);
bool success = pkt.encode((uint8_t*)buffer, len);
if (!success) {
LogError(LOG_REPL, "PEER %u Remote EKC, Key Inventory, failed to encode packet", peerId);
return;
}
LogInfoEx(LOG_REPL, "PEER %u Remote EKC, Key Inventory, blocks %u, streamId = %u", peerId, pkt.fragments.size(), streamId);
if (pkt.fragments.size() > 0U) {

@ -61,7 +61,11 @@ void MetadataNetwork::PacketHandler::radioAliasSync(TrafficNetwork* network, Met
}
PacketBuffer pkt(true, "Radio Alias Sync");
pkt.encode((uint8_t*)buffer, len);
bool success = pkt.encode((uint8_t*)buffer, len);
if (!success) {
LogError(LOG_REPL, "PEER %u Radio Alias Sync, failed to encode packet", peerId);
return;
}
LogInfoEx(LOG_REPL, "PEER %u Radio Alias Sync, blocks %u, streamId = %u", peerId, pkt.fragments.size(), streamId);
if (pkt.fragments.size() > 0U) {

@ -141,3 +141,47 @@ TEST_CASE("PacketBuffer rejects oversized packet metadata", "[network][packetbuf
REQUIRE(messageLength == 0U);
REQUIRE(buffer.fragments.size() == 0U);
}
TEST_CASE("PacketBuffer rejects invalid ZLIB data", "[network][packetbuffer]")
{
PacketBuffer buffer(true, "packetbuffer-invalid-zlib");
std::array<uint8_t, FRAG_SIZE> fragment = {};
constexpr uint32_t invalidCompressedSize = 8U;
setFragmentHeader(fragment.data(), 64U, invalidCompressedSize, 0U, 0U);
std::fill_n(fragment.data() + FRAG_HDR_SIZE, invalidCompressedSize, 0xFFU);
uint8_t* message = nullptr;
uint32_t messageLength = 0U;
REQUIRE_FALSE(buffer.decode(fragment.data(), &message, &messageLength));
REQUIRE(message == nullptr);
REQUIRE(messageLength == 0U);
REQUIRE(buffer.fragments.empty());
}
TEST_CASE("PacketBuffer enforces the maximum block count", "[network][packetbuffer]")
{
constexpr uint32_t maxBlockCount = 254U;
SECTION("accepts exactly the maximum number of blocks") {
PacketBuffer buffer(false, "packetbuffer-max-blocks");
std::vector<uint8_t> payload(FRAG_BLOCK_SIZE * maxBlockCount, 0x5AU);
REQUIRE(buffer.encode(payload.data(), (uint32_t)payload.size()));
REQUIRE(buffer.fragments.size() == maxBlockCount);
auto last = buffer.fragments.find((uint8_t)(maxBlockCount - 1U));
REQUIRE(last != buffer.fragments.end());
REQUIRE(last->second != nullptr);
REQUIRE(last->second->data[8U] == maxBlockCount - 1U);
REQUIRE(last->second->data[9U] == maxBlockCount - 1U);
}
SECTION("rejects one block over the maximum") {
PacketBuffer buffer(false, "packetbuffer-too-many-blocks");
std::vector<uint8_t> payload(FRAG_BLOCK_SIZE * maxBlockCount + 1U, 0xA5U);
REQUIRE_FALSE(buffer.encode(payload.data(), (uint32_t)payload.size()));
REQUIRE(buffer.fragments.empty());
}
}

Loading…
Cancel
Save

Powered by TurnKey Linux.