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 <bzbarsky@apple.com>
* Update src/app/ReadHandler.cpp
Co-authored-by: Andrei Litvin <andy314@gmail.com>
---------
Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
Co-authored-by: Andrei Litvin <andy314@gmail.com>
diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp
index dd4c928..487acd2 100644
--- a/src/app/ReadHandler.cpp
+++ b/src/app/ReadHandler.cpp
@@ -919,5 +919,15 @@
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 a30f1f8..c973432 100644
--- a/src/app/ReadHandler.h
+++ b/src/app/ReadHandler.h
@@ -333,6 +333,15 @@
*/
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 93f2557..e823c33 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 39c582f..dfa64cf 100644
--- a/src/app/reporting/Engine.cpp
+++ b/src/app/reporting/Engine.cpp
@@ -492,10 +492,11 @@
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 @@
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<uint16_t>(bufHandle->AvailableDataLength() - kMaxSecureSduLengthBytes);
+ reservedSize = static_cast<uint16_t>(bufHandle->AvailableDataLength() - reportBufferMaxSize);
}
reportDataWriter.Init(std::move(bufHandle));
@@ -525,8 +530,8 @@
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<uint32_t>(reservedSize + chip::Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES));