From 1a8c6d2a6cf1c246b1593c6be35c0495d09fae38 Mon Sep 17 00:00:00 2001 From: Pradip De Date: Wed, 12 Jun 2024 13:40:50 -0700 Subject: [PATCH] Enable ReadHandler to support large payloads (#33814) * ReadHandler changes for large payloads When sending reports, if the session established with the peer supports large payloads, the ReadHandler will allocate a large buffer to, potentially, fit more attribute and event data. * Address comments and apply suggestions from code review Co-authored-by: Boris Zbarsky * Update src/app/ReadHandler.cpp Co-authored-by: Andrei Litvin --------- Co-authored-by: Boris Zbarsky Co-authored-by: Andrei Litvin --- src/app/ReadHandler.cpp | 10 ++++++++++ src/app/ReadHandler.h | 9 +++++++++ src/app/StatusResponse.h | 3 ++- src/app/reporting/Engine.cpp | 15 ++++++++++----- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index dd4c928a1bafa1..487acd27ed883e 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -919,5 +919,15 @@ void ReadHandler::ClearStateFlag(ReadHandlerFlags aFlag) SetStateFlag(aFlag, false); } +size_t ReadHandler::GetReportBufferMaxSize() +{ + Transport::SecureSession * session = GetSession(); + if (session && session->AllowsLargePayload()) + { + return kMaxLargeSecureSduLengthBytes; + } + return kMaxSecureSduLengthBytes; +} + } // namespace app } // namespace chip diff --git a/src/app/ReadHandler.h b/src/app/ReadHandler.h index a30f1f8974ad25..c973432953275b 100644 --- a/src/app/ReadHandler.h +++ b/src/app/ReadHandler.h @@ -333,6 +333,15 @@ class ReadHandler : public Messaging::ExchangeDelegate */ CHIP_ERROR SendReportData(System::PacketBufferHandle && aPayload, bool aMoreChunks); + /* + * Get the appropriate size of a packet buffer to allocate for encoding a Report message. + * This size might depend on the underlying session used by the ReadHandler. + * + * The size returned here is the size not including the various prepended headers + * (what System::PacketBuffer calls the "available size"). + */ + size_t GetReportBufferMaxSize(); + /** * Returns whether this ReadHandler represents a subscription that was created by the other side of the provided exchange. */ diff --git a/src/app/StatusResponse.h b/src/app/StatusResponse.h index 93f2557b679854..e823c33d84f22b 100644 --- a/src/app/StatusResponse.h +++ b/src/app/StatusResponse.h @@ -26,7 +26,8 @@ namespace chip { namespace app { -static constexpr size_t kMaxSecureSduLengthBytes = kMaxAppMessageLen + kMaxTagLen; +static constexpr size_t kMaxSecureSduLengthBytes = kMaxAppMessageLen + kMaxTagLen; +static constexpr size_t kMaxLargeSecureSduLengthBytes = kMaxLargeAppMessageLen + kMaxTagLen; class StatusResponse { diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index 39c582f3e45f0b..dfa64cf3b8f9de 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -492,10 +492,11 @@ CHIP_ERROR Engine::BuildAndSendSingleReportData(ReadHandler * apReadHandler) CHIP_ERROR err = CHIP_NO_ERROR; chip::System::PacketBufferTLVWriter reportDataWriter; ReportDataMessage::Builder reportDataBuilder; - chip::System::PacketBufferHandle bufHandle = System::PacketBufferHandle::New(chip::app::kMaxSecureSduLengthBytes); + chip::System::PacketBufferHandle bufHandle = nullptr; uint16_t reservedSize = 0; bool hasMoreChunks = false; bool needCloseReadHandler = false; + size_t reportBufferMaxSize = 0; // Reserved size for the MoreChunks boolean flag, which takes up 1 byte for the control tag and 1 byte for the context tag. const uint32_t kReservedSizeForMoreChunksFlag = 1 + 1; @@ -512,11 +513,15 @@ CHIP_ERROR Engine::BuildAndSendSingleReportData(ReadHandler * apReadHandler) VerifyOrExit(apReadHandler != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(apReadHandler->GetSession() != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + reportBufferMaxSize = apReadHandler->GetReportBufferMaxSize(); + + bufHandle = System::PacketBufferHandle::New(reportBufferMaxSize); VerifyOrExit(!bufHandle.IsNull(), err = CHIP_ERROR_NO_MEMORY); - if (bufHandle->AvailableDataLength() > kMaxSecureSduLengthBytes) + if (bufHandle->AvailableDataLength() > reportBufferMaxSize) { - reservedSize = static_cast(bufHandle->AvailableDataLength() - kMaxSecureSduLengthBytes); + reservedSize = static_cast(bufHandle->AvailableDataLength() - reportBufferMaxSize); } reportDataWriter.Init(std::move(bufHandle)); @@ -525,8 +530,8 @@ CHIP_ERROR Engine::BuildAndSendSingleReportData(ReadHandler * apReadHandler) reportDataWriter.ReserveBuffer(mReservedSize); #endif - // Always limit the size of the generated packet to fit within kMaxSecureSduLengthBytes regardless of the available buffer - // capacity. + // Always limit the size of the generated packet to fit within the max size returned by the ReadHandler regardless + // of the available buffer capacity. // Also, we need to reserve some extra space for the MIC field. reportDataWriter.ReserveBuffer(static_cast(reservedSize + chip::Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES));