From 6dd1c8e2eebd3ee51a6736c3a34c4b97715f5a81 Mon Sep 17 00:00:00 2001 From: Pradip De Date: Sat, 20 Apr 2024 00:47:19 +0000 Subject: [PATCH] Changes for large Packetbuffer allocation to support TCP payloads Changes to internal checks in SystemPacketBuffer. Update the length encoding for TCP payloads during send and receive. Max size config for large packetbuffer size limit in SystemPacketBuffer.h. Test modifications for chainedbuffer receives for TCP. - Add test for Buffer length greater than MRP max size. Fixes Issues #31779, #33307. --- src/inet/TCPEndPointImplSockets.cpp | 6 +-- src/system/SystemPacketBuffer.cpp | 31 +++++++++--- src/system/SystemPacketBuffer.h | 13 +++++ src/system/tests/TestSystemPacketBuffer.cpp | 27 +++++++++-- src/transport/raw/TCP.cpp | 18 +++---- src/transport/raw/TCP.h | 2 +- src/transport/raw/TCPConfig.h | 2 +- src/transport/raw/tests/TestTCP.cpp | 54 ++++++++++++--------- 8 files changed, 105 insertions(+), 48 deletions(-) diff --git a/src/inet/TCPEndPointImplSockets.cpp b/src/inet/TCPEndPointImplSockets.cpp index d21c11b6a42865..cade58c7480377 100644 --- a/src/inet/TCPEndPointImplSockets.cpp +++ b/src/inet/TCPEndPointImplSockets.cpp @@ -947,10 +947,10 @@ void TCPEndPointImplSockets::ReceiveData() { VerifyOrDie(rcvLen > 0); size_t newDataLength = rcvBuf->DataLength() + static_cast(rcvLen); - VerifyOrDie(CanCastTo(newDataLength)); + VerifyOrDie(newDataLength <= UINT32_MAX); if (isNewBuf) { - rcvBuf->SetDataLength(static_cast(newDataLength)); + rcvBuf->SetDataLength(newDataLength); rcvBuf.RightSize(); if (mRcvQueue.IsNull()) { @@ -963,7 +963,7 @@ void TCPEndPointImplSockets::ReceiveData() } else { - rcvBuf->SetDataLength(static_cast(newDataLength), mRcvQueue); + rcvBuf->SetDataLength(newDataLength, mRcvQueue); } } } diff --git a/src/system/SystemPacketBuffer.cpp b/src/system/SystemPacketBuffer.cpp index 59e1e822901db0..c82625c3aa6158 100644 --- a/src/system/SystemPacketBuffer.cpp +++ b/src/system/SystemPacketBuffer.cpp @@ -530,12 +530,19 @@ PacketBufferHandle PacketBufferHandle::New(size_t aAvailableSize, uint16_t aRese CHIP_SYSTEM_FAULT_INJECT(FaultInjection::kFault_PacketBufferNew, return PacketBufferHandle()); - // TODO: Change the max to a lower value - if (aAvailableSize > UINT32_MAX || lAllocSize > PacketBuffer::kMaxSizeWithoutReserve || lBlockSize > UINT32_MAX) +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + if (lAllocSize > CHIP_CONFIG_MAX_LARGE_PAYLOAD_SIZE_BYTES || lBlockSize > UINT32_MAX) + { + ChipLogError(chipSystemLayer, "PacketBuffer: allocation exceeds limit for large payload size."); + return PacketBufferHandle(); + } +#else + if (lAllocSize > PacketBuffer::kMaxSizeWithoutReserve || lBlockSize > UINT16_MAX) { ChipLogError(chipSystemLayer, "PacketBuffer: allocation too large."); return PacketBufferHandle(); } +#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT #if CHIP_SYSTEM_CONFIG_USE_LWIP @@ -593,7 +600,11 @@ PacketBufferHandle PacketBufferHandle::New(size_t aAvailableSize, uint16_t aRese PacketBufferHandle PacketBufferHandle::NewWithData(const void * aData, size_t aDataSize, size_t aAdditionalSize, uint16_t aReservedSize) { +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + if (aDataSize > UINT32_MAX) +#else if (aDataSize > UINT16_MAX) +#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT { ChipLogError(chipSystemLayer, "PacketBuffer: allocation too large."); return PacketBufferHandle(); @@ -605,6 +616,8 @@ PacketBufferHandle PacketBufferHandle::NewWithData(const void * aData, size_t aD { memcpy(buffer.mBuffer->payload, aData, aDataSize); #if CHIP_SYSTEM_CONFIG_USE_LWIP + // The VerifyOrDie() in the New() call catches buffer allocations greater + // than UINT16_MAX for LwIP based platforms. buffer.mBuffer->len = buffer.mBuffer->tot_len = static_cast(aDataSize); #else buffer.mBuffer->len = buffer.mBuffer->tot_len = aDataSize; @@ -727,18 +740,24 @@ PacketBufferHandle PacketBufferHandle::CloneData() const size_t originalDataSize = original->MaxDataLength(); uint16_t originalReservedSize = original->ReservedSize(); - if (originalDataSize + originalReservedSize > PacketBuffer::kMaxSizeWithoutReserve) +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + uint32_t maxSize = CHIP_CONFIG_MAX_LARGE_PAYLOAD_SIZE_BYTES; +#else + uint32_t maxSize = PacketBuffer::kMaxSizeWithoutReserve; +#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT + + if (originalDataSize + originalReservedSize > maxSize) { // The original memory allocation may have provided a larger block than requested (e.g. when using a shared pool), // and in particular may have provided a larger block than we are able to request from PackBufferHandle::New(). // It is a genuine error if that extra space has been used. - if (originalReservedSize + original->DataLength() > PacketBuffer::kMaxSizeWithoutReserve) + if (originalReservedSize + original->DataLength() > maxSize) { return PacketBufferHandle(); } // Otherwise, reduce the requested data size. This subtraction can not underflow because the above test - // guarantees originalReservedSize <= PacketBuffer::kMaxSizeWithoutReserve. - originalDataSize = PacketBuffer::kMaxSizeWithoutReserve - originalReservedSize; + // guarantees originalReservedSize <= maxSize. + originalDataSize = maxSize - originalReservedSize; } PacketBufferHandle clone = PacketBufferHandle::New(originalDataSize, originalReservedSize); diff --git a/src/system/SystemPacketBuffer.h b/src/system/SystemPacketBuffer.h index 41eaef6d9e305c..6d3a82bd0d3d21 100644 --- a/src/system/SystemPacketBuffer.h +++ b/src/system/SystemPacketBuffer.h @@ -44,6 +44,19 @@ #include #endif // CHIP_SYSTEM_CONFIG_USE_LWIP +/** + * @def CHIP_CONFIG_MAX_LARGE_PAYLOAD_SIZE_BYTES + * + * @brief Maximum payload size of a 'Large' message + */ +#ifndef CHIP_CONFIG_MAX_LARGE_PAYLOAD_SIZE_BYTES +#define CHIP_CONFIG_MAX_LARGE_PAYLOAD_SIZE_BYTES (64000) +#endif + +#if CHIP_CONFIG_MAX_LARGE_PAYLOAD_SIZE_BYTES > UINT32_MAX +#error "The maximum Large payload size cannot exceed UINT32_MAX" +#endif + namespace chip { namespace System { diff --git a/src/system/tests/TestSystemPacketBuffer.cpp b/src/system/tests/TestSystemPacketBuffer.cpp index c71ad542d6225a..7b89cc3473e546 100644 --- a/src/system/tests/TestSystemPacketBuffer.cpp +++ b/src/system/tests/TestSystemPacketBuffer.cpp @@ -309,7 +309,11 @@ TEST_F_FROM_FIXTURE(TestSystemPacketBuffer, CheckNew) { const PacketBufferHandle buffer = PacketBufferHandle::New(0, config.reserved_size); +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + if (config.reserved_size > CHIP_CONFIG_MAX_LARGE_PAYLOAD_SIZE_BYTES) +#else if (config.reserved_size > PacketBuffer::kMaxSizeWithoutReserve) +#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT { EXPECT_TRUE(buffer.IsNull()); continue; @@ -1605,7 +1609,11 @@ TEST_F_FROM_FIXTURE(TestSystemPacketBuffer, CheckHandleRightSize) TEST_F_FROM_FIXTURE(TestSystemPacketBuffer, CheckHandleCloneData) { +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + uint8_t lPayload[2 * CHIP_CONFIG_MAX_LARGE_PAYLOAD_SIZE_BYTES]; +#else uint8_t lPayload[2 * PacketBuffer::kMaxSizeWithoutReserve]; +#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT for (uint8_t & payload : lPayload) { payload = static_cast(random()); @@ -1684,7 +1692,11 @@ TEST_F_FROM_FIXTURE(TestSystemPacketBuffer, CheckHandleCloneData) // This is only testable on heap allocation configurations, where pbuf records the allocation size and we can manually // construct an oversize buffer. +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + constexpr uint32_t kOversizeDataSize = CHIP_CONFIG_MAX_LARGE_PAYLOAD_SIZE_BYTES + 99; +#else constexpr uint16_t kOversizeDataSize = PacketBuffer::kMaxSizeWithoutReserve + 99; +#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT PacketBuffer * p = reinterpret_cast(chip::Platform::MemoryAlloc(kStructureSize + kOversizeDataSize)); ASSERT_NE(p, nullptr); @@ -1698,15 +1710,20 @@ TEST_F_FROM_FIXTURE(TestSystemPacketBuffer, CheckHandleCloneData) PacketBufferHandle handle = PacketBufferHandle::Adopt(p); // Fill the buffer to maximum and verify that it can be cloned. +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + uint32_t maxSize = CHIP_CONFIG_MAX_LARGE_PAYLOAD_SIZE_BYTES; +#else + uint32_t maxSize = PacketBuffer::kMaxSizeWithoutReserve; +#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT - memset(handle->Start(), 1, PacketBuffer::kMaxSizeWithoutReserve); - handle->SetDataLength(PacketBuffer::kMaxSizeWithoutReserve); - EXPECT_EQ(handle->DataLength(), PacketBuffer::kMaxSizeWithoutReserve); + memset(handle->Start(), 1, maxSize); + handle->SetDataLength(maxSize); + EXPECT_EQ(handle->DataLength(), maxSize); PacketBufferHandle clone = handle.CloneData(); ASSERT_FALSE(clone.IsNull()); - EXPECT_EQ(clone->DataLength(), PacketBuffer::kMaxSizeWithoutReserve); - EXPECT_EQ(memcmp(handle->Start(), clone->Start(), PacketBuffer::kMaxSizeWithoutReserve), 0); + EXPECT_EQ(clone->DataLength(), maxSize); + EXPECT_EQ(memcmp(handle->Start(), clone->Start(), maxSize), 0); // Overfill the buffer and verify that it can not be cloned. memset(handle->Start(), 2, kOversizeDataSize); diff --git a/src/transport/raw/TCP.cpp b/src/transport/raw/TCP.cpp index e33590a63a6fdf..421a5a1808e99d 100644 --- a/src/transport/raw/TCP.cpp +++ b/src/transport/raw/TCP.cpp @@ -40,10 +40,10 @@ namespace { using namespace chip::Encoding; // Packets start with a 16-bit size -constexpr size_t kPacketSizeBytes = 2; +constexpr size_t kPacketSizeBytes = sizeof(uint32_t); // TODO: Actual limit may be lower (spec issue #2119) -constexpr uint16_t kMaxMessageSize = static_cast(System::PacketBuffer::kMaxSizeWithoutReserve - kPacketSizeBytes); +constexpr uint32_t kMaxTCPMessageSize = static_cast(CHIP_CONFIG_MAX_LARGE_PAYLOAD_SIZE_BYTES - kPacketSizeBytes); constexpr int kListenBacklogSize = 2; @@ -202,7 +202,7 @@ CHIP_ERROR TCPBase::SendMessage(const Transport::PeerAddress & address, System:: VerifyOrReturnError(address.GetTransportType() == Type::kTcp, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(mState == TCPState::kInitialized, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(kPacketSizeBytes + msgBuf->DataLength() <= std::numeric_limits::max(), + VerifyOrReturnError(kPacketSizeBytes + msgBuf->DataLength() <= std::numeric_limits::max(), CHIP_ERROR_INVALID_ARGUMENT); // The check above about kPacketSizeBytes + msgBuf->DataLength() means it definitely fits in uint16_t. @@ -211,7 +211,7 @@ CHIP_ERROR TCPBase::SendMessage(const Transport::PeerAddress & address, System:: msgBuf->SetStart(msgBuf->Start() - kPacketSizeBytes); uint8_t * output = msgBuf->Start(); - LittleEndian::Write16(output, static_cast(msgBuf->DataLength() - kPacketSizeBytes)); + LittleEndian::Write32(output, static_cast(msgBuf->DataLength() - kPacketSizeBytes)); // Reuse existing connection if one exists, otherwise a new one // will be established @@ -324,11 +324,11 @@ CHIP_ERROR TCPBase::ProcessReceivedBuffer(Inet::TCPEndPoint * endPoint, const Pe { return err; } - uint16_t messageSize = LittleEndian::Get16(messageSizeBuf); - if (messageSize >= kMaxMessageSize) + uint32_t messageSize = LittleEndian::Get32(messageSizeBuf); + if (messageSize >= kMaxTCPMessageSize) { - - // This message is too long for upper layers. + // Message is too big for node to process. Disconnect with peer. + CloseConnectionInternal(state, CHIP_ERROR_MESSAGE_TOO_LONG, SuppressCallback::No); return CHIP_ERROR_MESSAGE_TOO_LONG; } // The subtraction will not underflow because we successfully read kPacketSizeBytes. @@ -344,7 +344,7 @@ CHIP_ERROR TCPBase::ProcessReceivedBuffer(Inet::TCPEndPoint * endPoint, const Pe return CHIP_NO_ERROR; } -CHIP_ERROR TCPBase::ProcessSingleMessage(const PeerAddress & peerAddress, ActiveTCPConnectionState * state, uint16_t messageSize) +CHIP_ERROR TCPBase::ProcessSingleMessage(const PeerAddress & peerAddress, ActiveTCPConnectionState * state, size_t messageSize) { // We enter with `state->mReceived` containing at least one full message, perhaps in a chain. // `state->mReceived->Start()` currently points to the message data. diff --git a/src/transport/raw/TCP.h b/src/transport/raw/TCP.h index bb4671215b96c8..cfdf53a1d29dc0 100644 --- a/src/transport/raw/TCP.h +++ b/src/transport/raw/TCP.h @@ -252,7 +252,7 @@ class DLL_EXPORT TCPBase : public Base * is no other data). * @param[in] messageSize Size of the single message. */ - CHIP_ERROR ProcessSingleMessage(const PeerAddress & peerAddress, ActiveTCPConnectionState * state, uint16_t messageSize); + CHIP_ERROR ProcessSingleMessage(const PeerAddress & peerAddress, ActiveTCPConnectionState * state, size_t messageSize); /** * Initiate a connection to the given peer. On connection completion, diff --git a/src/transport/raw/TCPConfig.h b/src/transport/raw/TCPConfig.h index d54a9466b4d294..18ac7391070125 100644 --- a/src/transport/raw/TCPConfig.h +++ b/src/transport/raw/TCPConfig.h @@ -69,7 +69,7 @@ namespace chip { * @brief Maximum payload size of a message over a TCP connection */ #ifndef CHIP_CONFIG_MAX_TCP_PAYLOAD_SIZE_BYTES -#define CHIP_CONFIG_MAX_TCP_PAYLOAD_SIZE_BYTES 1000000 +#define CHIP_CONFIG_MAX_TCP_PAYLOAD_SIZE_BYTES (CHIP_CONFIG_MAX_LARGE_PAYLOAD_SIZE_BYTES) #endif /** diff --git a/src/transport/raw/tests/TestTCP.cpp b/src/transport/raw/tests/TestTCP.cpp index 6a60fb330c70f7..8431c4e20df3da 100644 --- a/src/transport/raw/tests/TestTCP.cpp +++ b/src/transport/raw/tests/TestTCP.cpp @@ -49,7 +49,7 @@ namespace { constexpr size_t kMaxTcpActiveConnectionCount = 4; constexpr size_t kMaxTcpPendingPackets = 4; -constexpr uint16_t kPacketSizeBytes = static_cast(sizeof(uint16_t)); +constexpr size_t kPacketSizeBytes = sizeof(uint32_t); uint16_t gChipTCPPort = static_cast(CHIP_PORT + chip::Crypto::GetRandU16() % 100); chip::Transport::AppTCPConnectionCallbackCtxt gAppTCPConnCbCtxt; chip::Transport::ActiveTCPConnectionState * gActiveTCPConnState = nullptr; @@ -444,7 +444,7 @@ struct TestData // the last buffer will be made larger. TestData() : mPayload(nullptr), mTotalLength(0), mMessageLength(0), mMessageOffset(0) {} ~TestData() { Free(); } - bool Init(const uint16_t sizes[]); + bool Init(const uint32_t sizes[]); void Free(); bool IsValid() { return !mHandle.IsNull() && (mPayload != nullptr); } @@ -455,7 +455,7 @@ struct TestData size_t mMessageOffset; }; -bool TestData::Init(const uint16_t sizes[]) +bool TestData::Init(const uint32_t sizes[]) { Free(); @@ -471,17 +471,17 @@ bool TestData::Init(const uint16_t sizes[]) mTotalLength += sizes[bufferCount]; } --bufferCount; - uint16_t additionalLength = 0; + uint32_t additionalLength = 0; if (headerLength + kPacketSizeBytes > mTotalLength) { - additionalLength = static_cast((headerLength + kPacketSizeBytes) - mTotalLength); + additionalLength = static_cast((headerLength + kPacketSizeBytes) - mTotalLength); mTotalLength += additionalLength; } - if (mTotalLength > UINT16_MAX) + if (mTotalLength > UINT32_MAX) { return false; } - uint16_t messageLength = static_cast(mTotalLength - kPacketSizeBytes); + uint32_t messageLength = static_cast(mTotalLength - kPacketSizeBytes); // Build the test payload. uint8_t * payload = static_cast(chip::Platform::MemoryCalloc(1, mTotalLength)); @@ -489,7 +489,7 @@ bool TestData::Init(const uint16_t sizes[]) { return false; } - chip::Encoding::LittleEndian::Put16(payload, messageLength); + chip::Encoding::LittleEndian::Put32(payload, messageLength); uint16_t headerSize; CHIP_ERROR err = header.Encode(payload + kPacketSizeBytes, messageLength, &headerSize); if (err != CHIP_NO_ERROR) @@ -509,10 +509,10 @@ bool TestData::Init(const uint16_t sizes[]) System::PacketBufferHandle head = chip::System::PacketBufferHandle::New(sizes[0], 0 /* reserve */); for (int i = 1; i <= bufferCount; ++i) { - uint16_t size = sizes[i]; + size_t size = sizes[i]; if (i == bufferCount) { - size = static_cast(size + additionalLength); + size = size + additionalLength; } chip::System::PacketBufferHandle buffer = chip::System::PacketBufferHandle::New(size, 0 /* reserve */); if (buffer.IsNull()) @@ -541,7 +541,7 @@ bool TestData::Init(const uint16_t sizes[]) if (lToWriteToCurrentBuf != 0) { memcpy(iterator->Start(), writePayload, lToWriteToCurrentBuf); - iterator->SetDataLength(static_cast(iterator->DataLength() + lToWriteToCurrentBuf), head); + iterator->SetDataLength(iterator->DataLength() + lToWriteToCurrentBuf, head); writePayload += lToWriteToCurrentBuf; writeLength -= lToWriteToCurrentBuf; } @@ -602,9 +602,9 @@ class TCPTest MockTransportMgrDelegate gMockTransportMgrDelegate(ctx); gMockTransportMgrDelegate.InitializeMessageTest(tcp, addr); - // Send a packet to get TCP going, so that we can find a TCPEndPoint to pass to ProcessReceivedBuffer. + // Connect over TCP, so that we can find a TCPEndPoint to pass to ProcessReceivedBuffer. // (The current TCPEndPoint implementation is not effectively mockable.) - gMockTransportMgrDelegate.SingleMessageTest(tcp, addr); + gMockTransportMgrDelegate.ConnectTest(tcp, addr); Transport::PeerAddress lPeerAddress = Transport::PeerAddress::TCP(addr, gChipTCPPort); chip::Transport::ActiveTCPConnectionState * state = tcp.FindActiveConnection(lPeerAddress); @@ -618,22 +618,22 @@ class TCPTest // Test a single packet buffer. gMockTransportMgrDelegate.mReceiveHandlerCallCount = 0; - EXPECT_TRUE(testData[0].Init((const uint16_t[]){ 111, 0 })); + EXPECT_TRUE(testData[0].Init((const uint32_t[]){ 111, 0 })); err = tcp.ProcessReceivedBuffer(lEndPoint, lPeerAddress, std::move(testData[0].mHandle)); EXPECT_EQ(err, CHIP_NO_ERROR); EXPECT_EQ(gMockTransportMgrDelegate.mReceiveHandlerCallCount, 1); // Test a message in a chain of three packet buffers. The message length is split across buffers. gMockTransportMgrDelegate.mReceiveHandlerCallCount = 0; - EXPECT_TRUE(testData[0].Init((const uint16_t[]){ 1, 122, 123, 0 })); + EXPECT_TRUE(testData[0].Init((const uint32_t[]){ 1, 122, 123, 0 })); err = tcp.ProcessReceivedBuffer(lEndPoint, lPeerAddress, std::move(testData[0].mHandle)); EXPECT_EQ(err, CHIP_NO_ERROR); EXPECT_EQ(gMockTransportMgrDelegate.mReceiveHandlerCallCount, 1); // Test two messages in a chain. gMockTransportMgrDelegate.mReceiveHandlerCallCount = 0; - EXPECT_TRUE(testData[0].Init((const uint16_t[]){ 131, 0 })); - EXPECT_TRUE(testData[1].Init((const uint16_t[]){ 132, 0 })); + EXPECT_TRUE(testData[0].Init((const uint32_t[]){ 131, 0 })); + EXPECT_TRUE(testData[1].Init((const uint32_t[]){ 132, 0 })); testData[0].mHandle->AddToEnd(std::move(testData[1].mHandle)); err = tcp.ProcessReceivedBuffer(lEndPoint, lPeerAddress, std::move(testData[0].mHandle)); EXPECT_EQ(err, CHIP_NO_ERROR); @@ -641,24 +641,32 @@ class TCPTest // Test a chain of two messages, each a chain. gMockTransportMgrDelegate.mReceiveHandlerCallCount = 0; - EXPECT_TRUE(testData[0].Init((const uint16_t[]){ 141, 142, 0 })); - EXPECT_TRUE(testData[1].Init((const uint16_t[]){ 143, 144, 0 })); + EXPECT_TRUE(testData[0].Init((const uint32_t[]){ 141, 142, 0 })); + EXPECT_TRUE(testData[1].Init((const uint32_t[]){ 143, 144, 0 })); testData[0].mHandle->AddToEnd(std::move(testData[1].mHandle)); err = tcp.ProcessReceivedBuffer(lEndPoint, lPeerAddress, std::move(testData[0].mHandle)); EXPECT_EQ(err, CHIP_NO_ERROR); EXPECT_EQ(gMockTransportMgrDelegate.mReceiveHandlerCallCount, 2); + // Test a single packet buffer that is larger than + // kMaxSizeWithoutReserve but less than CHIP_CONFIG_MAX_LARGE_PAYLOAD_SIZE_BYTES. + gMockTransportMgrDelegate.mReceiveHandlerCallCount = 0; + EXPECT_TRUE(testData[0].Init((const uint32_t[]){ System::PacketBuffer::kMaxSizeWithoutReserve + 1, 0 })); + err = tcp.ProcessReceivedBuffer(lEndPoint, lPeerAddress, std::move(testData[0].mHandle)); + EXPECT_EQ(err, CHIP_NO_ERROR); + EXPECT_EQ(gMockTransportMgrDelegate.mReceiveHandlerCallCount, 1); + // Test a message that is too large to coalesce into a single packet buffer. gMockTransportMgrDelegate.mReceiveHandlerCallCount = 0; gMockTransportMgrDelegate.SetCallback(TestDataCallbackCheck, &testData[1]); - EXPECT_TRUE(testData[0].Init((const uint16_t[]){ 51, System::PacketBuffer::kMaxSizeWithoutReserve, 0 })); + EXPECT_TRUE(testData[0].Init((const uint32_t[]){ 51, CHIP_CONFIG_MAX_LARGE_PAYLOAD_SIZE_BYTES, 0 })); // Sending only the first buffer of the long chain. This should be enough to trigger the error. System::PacketBufferHandle head = testData[0].mHandle.PopHead(); err = tcp.ProcessReceivedBuffer(lEndPoint, lPeerAddress, std::move(head)); EXPECT_EQ(err, CHIP_ERROR_MESSAGE_TOO_LONG); - EXPECT_EQ(gMockTransportMgrDelegate.mReceiveHandlerCallCount, 0); - - gMockTransportMgrDelegate.DisconnectTest(tcp, addr); + // The receipt of a message exceeding the allowed size should have + // closed the connection. + EXPECT_EQ(state->mEndPoint, nullptr); } }; } // namespace Transport