blob: 861be46ea30013ac45673787f5ad88d4165fc552 [file] [log] [blame]
Trevor Holbrook934f89c2020-11-18 15:34:14 -08001/*
2 *
Kevin Schoedel2d48e752021-02-08 09:29:17 -05003 * Copyright (c) 2020-2021 Project CHIP Authors
Trevor Holbrook934f89c2020-11-18 15:34:14 -08004 * All rights reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19/**
20 * @file
21 * Implements utility methods for working with some complex BDX messages.
22 */
23
24#include <protocols/bdx/BdxMessages.h>
25
Zang MingJie53dd5832021-09-03 03:05:16 +080026#include <lib/support/BufferReader.h>
27#include <lib/support/BufferWriter.h>
28#include <lib/support/CodeUtils.h>
Trevor Holbrook934f89c2020-11-18 15:34:14 -080029
30#include <limits>
Kevin Schoedelb5a5d892020-12-03 19:01:10 -050031#include <utility>
Trevor Holbrook934f89c2020-11-18 15:34:14 -080032
33namespace {
Carol Yang1fd382d2022-03-02 20:36:27 -080034constexpr uint8_t kVersionMask = 0x0F;
Trevor Holbrook934f89c2020-11-18 15:34:14 -080035} // namespace
36
37using namespace chip;
Trevor Holbrook775e37f2021-02-05 07:23:29 -080038using namespace chip::bdx;
Trevor Holbrook934f89c2020-11-18 15:34:14 -080039using namespace chip::Encoding::LittleEndian;
40
41// WARNING: this function should never return early, since MessageSize() relies on it to calculate
42// the size of the message (even if the message is incomplete or filled out incorrectly).
Kevin Schoedel2d48e752021-02-08 09:29:17 -050043BufferWriter & TransferInit::WriteToBuffer(BufferWriter & aBuffer) const
Trevor Holbrook934f89c2020-11-18 15:34:14 -080044{
Kevin Schoedel8ea423a2021-03-11 11:49:18 -050045 const BitFlags<TransferControlFlags> proposedTransferCtl(Version & kVersionMask, TransferCtlOptions);
46 const bool widerange =
47 (StartOffset > std::numeric_limits<uint32_t>::max()) || (MaxLength > std::numeric_limits<uint32_t>::max());
Trevor Holbrook934f89c2020-11-18 15:34:14 -080048
Kevin Schoedel8ea423a2021-03-11 11:49:18 -050049 BitFlags<RangeControlFlags> rangeCtlFlags;
50 rangeCtlFlags.Set(RangeControlFlags::kDefLen, MaxLength > 0);
51 rangeCtlFlags.Set(RangeControlFlags::kStartOffset, StartOffset > 0);
52 rangeCtlFlags.Set(RangeControlFlags::kWiderange, widerange);
Trevor Holbrook934f89c2020-11-18 15:34:14 -080053
Kevin Schoedel8ea423a2021-03-11 11:49:18 -050054 aBuffer.Put(proposedTransferCtl.Raw());
Trevor Holbrook934f89c2020-11-18 15:34:14 -080055 aBuffer.Put(rangeCtlFlags.Raw());
Rob Walkercc92b632020-11-21 13:21:56 -080056 aBuffer.Put16(MaxBlockSize);
Trevor Holbrook934f89c2020-11-18 15:34:14 -080057
58 if (StartOffset > 0)
59 {
60 if (widerange)
61 {
Rob Walkercc92b632020-11-21 13:21:56 -080062 aBuffer.Put64(StartOffset);
Trevor Holbrook934f89c2020-11-18 15:34:14 -080063 }
64 else
65 {
Rob Walkercc92b632020-11-21 13:21:56 -080066 aBuffer.Put32(static_cast<uint32_t>(StartOffset));
Trevor Holbrook934f89c2020-11-18 15:34:14 -080067 }
68 }
69
70 if (MaxLength > 0)
71 {
72 if (widerange)
73 {
Rob Walkercc92b632020-11-21 13:21:56 -080074 aBuffer.Put64(MaxLength);
Trevor Holbrook934f89c2020-11-18 15:34:14 -080075 }
76 else
77 {
Rob Walkercc92b632020-11-21 13:21:56 -080078 aBuffer.Put32(static_cast<uint32_t>(MaxLength));
Trevor Holbrook934f89c2020-11-18 15:34:14 -080079 }
80 }
81
Rob Walkercc92b632020-11-21 13:21:56 -080082 aBuffer.Put16(FileDesLength);
Trevor Holbrook934f89c2020-11-18 15:34:14 -080083 if (FileDesignator != nullptr)
84 {
85 aBuffer.Put(FileDesignator, static_cast<size_t>(FileDesLength));
86 }
87
88 if (Metadata != nullptr)
89 {
90 aBuffer.Put(Metadata, static_cast<size_t>(MetadataLength));
91 }
Rob Walkercc92b632020-11-21 13:21:56 -080092 return aBuffer;
Trevor Holbrook934f89c2020-11-18 15:34:14 -080093}
94
Trevor Holbrook4d875fb2021-02-05 11:57:48 -080095CHIP_ERROR TransferInit::Parse(System::PacketBufferHandle aBuffer)
Trevor Holbrook934f89c2020-11-18 15:34:14 -080096{
Trevor Holbrook934f89c2020-11-18 15:34:14 -080097 uint8_t proposedTransferCtl;
Trevor Holbrook934f89c2020-11-18 15:34:14 -080098 uint32_t tmpUint32Value = 0; // Used for reading non-wide length and offset fields
Kevin Schoedelb5a5d892020-12-03 19:01:10 -050099 uint8_t * bufStart = aBuffer->Start();
100 Reader bufReader(bufStart, aBuffer->DataLength());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800101
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400102 ReturnErrorOnFailure(
103 bufReader.Read8(&proposedTransferCtl).Read8(mRangeCtlFlags.RawStorage()).Read16(&MaxBlockSize).StatusCode());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800104
105 Version = proposedTransferCtl & kVersionMask;
106 TransferCtlOptions.SetRaw(static_cast<uint8_t>(proposedTransferCtl & ~kVersionMask));
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800107
108 StartOffset = 0;
Carol Yangfde6a172021-11-08 17:30:19 -0800109 if (mRangeCtlFlags.Has(RangeControlFlags::kStartOffset))
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800110 {
Carol Yangfde6a172021-11-08 17:30:19 -0800111 if (mRangeCtlFlags.Has(RangeControlFlags::kWiderange))
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800112 {
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400113 ReturnErrorOnFailure(bufReader.Read64(&StartOffset).StatusCode());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800114 }
115 else
116 {
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400117 ReturnErrorOnFailure(bufReader.Read32(&tmpUint32Value).StatusCode());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800118 StartOffset = tmpUint32Value;
119 }
120 }
121
122 MaxLength = 0;
Carol Yangfde6a172021-11-08 17:30:19 -0800123 if (mRangeCtlFlags.Has(RangeControlFlags::kDefLen))
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800124 {
Carol Yangfde6a172021-11-08 17:30:19 -0800125 if (mRangeCtlFlags.Has(RangeControlFlags::kWiderange))
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800126 {
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400127 ReturnErrorOnFailure(bufReader.Read64(&MaxLength).StatusCode());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800128 }
129 else
130 {
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400131 ReturnErrorOnFailure(bufReader.Read32(&tmpUint32Value).StatusCode());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800132 MaxLength = tmpUint32Value;
133 }
134 }
135
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400136 ReturnErrorOnFailure(bufReader.Read16(&FileDesLength).StatusCode());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800137
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400138 VerifyOrReturnError(bufReader.HasAtLeast(FileDesLength), CHIP_ERROR_MESSAGE_INCOMPLETE);
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800139 FileDesignator = &bufStart[bufReader.OctetsRead()];
140
141 // Rest of message is metadata (could be empty)
142 Metadata = nullptr;
143 MetadataLength = 0;
144 if (bufReader.Remaining() > FileDesLength)
145 {
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800146 uint16_t metadataStartIndex = static_cast<uint16_t>(bufReader.OctetsRead() + FileDesLength);
147 Metadata = &bufStart[metadataStartIndex];
Kevin Schoedelb5a5d892020-12-03 19:01:10 -0500148 MetadataLength = static_cast<uint16_t>(aBuffer->DataLength() - metadataStartIndex);
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800149 }
150
Kevin Schoedelbd11f982021-01-26 13:34:29 -0500151 // Retain ownership of the packet buffer so that the FileDesignator and Metadata pointers remain valid.
Kevin Schoedelb5a5d892020-12-03 19:01:10 -0500152 Buffer = std::move(aBuffer);
153
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400154 return CHIP_NO_ERROR;
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800155}
156
Trevor Holbrook4d875fb2021-02-05 11:57:48 -0800157size_t TransferInit::MessageSize() const
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800158{
Kevin Schoedel2d48e752021-02-08 09:29:17 -0500159 BufferWriter emptyBuf(nullptr, 0);
Rob Walkercc92b632020-11-21 13:21:56 -0800160 return WriteToBuffer(emptyBuf).Needed();
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800161}
162
Carol Yangfde6a172021-11-08 17:30:19 -0800163#if CHIP_AUTOMATION_LOGGING
164void TransferInit::LogMessage(bdx::MessageType messageType) const
165{
166 char fd[kMaxFileDesignatorLen];
Boris Zbarsky2b52b362021-11-17 16:59:07 -0500167 snprintf(fd, sizeof(fd), "%.*s", static_cast<int>(FileDesLength), FileDesignator);
Carol Yangfde6a172021-11-08 17:30:19 -0800168
169 switch (messageType)
170 {
171 case MessageType::SendInit:
172 ChipLogAutomation("SendInit");
173 break;
174 case MessageType::ReceiveInit:
175 ChipLogAutomation("ReceiveInit");
176 break;
177 default:
178 break;
179 }
180
181 ChipLogAutomation(" Proposed Transfer Control: 0x%X", static_cast<unsigned>(TransferCtlOptions.Raw() | Version));
182 ChipLogAutomation(" Range Control: 0x%X", static_cast<unsigned>(mRangeCtlFlags.Raw()));
andrei-menzopol57471cb2022-04-20 23:31:17 +0300183 ChipLogAutomation(" Proposed Max Block Size: %u", MaxBlockSize);
Carol Yangfde6a172021-11-08 17:30:19 -0800184 ChipLogAutomation(" Start Offset: 0x" ChipLogFormatX64, ChipLogValueX64(StartOffset));
185 ChipLogAutomation(" Proposed Max Length: 0x" ChipLogFormatX64, ChipLogValueX64(MaxLength));
andrei-menzopol57471cb2022-04-20 23:31:17 +0300186 ChipLogAutomation(" File Designator Length: %u", FileDesLength);
Carol Yangfde6a172021-11-08 17:30:19 -0800187 ChipLogAutomation(" File Designator: %s", fd);
188}
189#endif // CHIP_AUTOMATION_LOGGING
190
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800191bool TransferInit::operator==(const TransferInit & another) const
192{
193 if ((MetadataLength != another.MetadataLength) || (FileDesLength != another.FileDesLength))
194 {
195 return false;
196 }
197
198 bool fileDesMatches = true;
199 if (FileDesLength > 0)
200 {
201 fileDesMatches = (memcmp(FileDesignator, another.FileDesignator, FileDesLength) == 0);
202 }
203
204 bool metadataMatches = true;
205 if (MetadataLength > 0)
206 {
207 metadataMatches = (memcmp(Metadata, another.Metadata, MetadataLength) == 0);
208 }
209
Kevin Schoedel8ea423a2021-03-11 11:49:18 -0500210 return ((Version == another.Version) && (TransferCtlOptions == another.TransferCtlOptions) &&
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800211 (StartOffset == another.StartOffset) && (MaxLength == another.MaxLength) && (MaxBlockSize == another.MaxBlockSize) &&
212 fileDesMatches && metadataMatches);
213}
214
215// WARNING: this function should never return early, since MessageSize() relies on it to calculate
216// the size of the message (even if the message is incomplete or filled out incorrectly).
Kevin Schoedel2d48e752021-02-08 09:29:17 -0500217Encoding::LittleEndian::BufferWriter & SendAccept::WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800218{
Kevin Schoedel8ea423a2021-03-11 11:49:18 -0500219 const BitFlags<TransferControlFlags> transferCtl(Version & kVersionMask, TransferCtlFlags);
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800220
Kevin Schoedel8ea423a2021-03-11 11:49:18 -0500221 aBuffer.Put(transferCtl.Raw());
Rob Walkercc92b632020-11-21 13:21:56 -0800222 aBuffer.Put16(MaxBlockSize);
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800223
224 if (Metadata != nullptr)
225 {
226 aBuffer.Put(Metadata, static_cast<size_t>(MetadataLength));
227 }
Rob Walkercc92b632020-11-21 13:21:56 -0800228 return aBuffer;
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800229}
230
Trevor Holbrook4d875fb2021-02-05 11:57:48 -0800231CHIP_ERROR SendAccept::Parse(System::PacketBufferHandle aBuffer)
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800232{
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800233 uint8_t transferCtl = 0;
Kevin Schoedelb5a5d892020-12-03 19:01:10 -0500234 uint8_t * bufStart = aBuffer->Start();
235 Reader bufReader(bufStart, aBuffer->DataLength());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800236
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400237 ReturnErrorOnFailure(bufReader.Read8(&transferCtl).Read16(&MaxBlockSize).StatusCode());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800238
239 Version = transferCtl & kVersionMask;
240
241 // Only one of these values should be set. It is up to the caller to verify this.
242 TransferCtlFlags.SetRaw(static_cast<uint8_t>(transferCtl & ~kVersionMask));
243
244 // Rest of message is metadata (could be empty)
245 Metadata = nullptr;
246 MetadataLength = 0;
247 if (bufReader.Remaining() > 0)
248 {
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800249 Metadata = &bufStart[bufReader.OctetsRead()];
250 MetadataLength = bufReader.Remaining();
251 }
252
Kevin Schoedelbd11f982021-01-26 13:34:29 -0500253 // Retain ownership of the packet buffer so that the Metadata pointer remains valid.
Kevin Schoedelb5a5d892020-12-03 19:01:10 -0500254 Buffer = std::move(aBuffer);
255
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400256 return CHIP_NO_ERROR;
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800257}
258
Trevor Holbrook4d875fb2021-02-05 11:57:48 -0800259size_t SendAccept::MessageSize() const
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800260{
Kevin Schoedel2d48e752021-02-08 09:29:17 -0500261 BufferWriter emptyBuf(nullptr, 0);
Rob Walkercc92b632020-11-21 13:21:56 -0800262 return WriteToBuffer(emptyBuf).Needed();
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800263}
264
Carol Yangfde6a172021-11-08 17:30:19 -0800265#if CHIP_AUTOMATION_LOGGING
266void SendAccept::LogMessage(bdx::MessageType messageType) const
267{
268 (void) messageType;
269 ChipLogAutomation("SendAccept");
270 ChipLogAutomation(" Transfer Control: 0x%X", static_cast<unsigned>(TransferCtlFlags.Raw() | Version));
andrei-menzopol57471cb2022-04-20 23:31:17 +0300271 ChipLogAutomation(" Max Block Size: %u", MaxBlockSize);
Carol Yangfde6a172021-11-08 17:30:19 -0800272}
273#endif // CHIP_AUTOMATION_LOGGING
274
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800275bool SendAccept::operator==(const SendAccept & another) const
276{
277 if (MetadataLength != another.MetadataLength)
278 {
279 return false;
280 }
281
282 bool metadataMatches = true;
283 if (MetadataLength > 0)
284 {
285 metadataMatches = (memcmp(Metadata, another.Metadata, MetadataLength) == 0);
286 }
287
Kevin Schoedel8ea423a2021-03-11 11:49:18 -0500288 return ((Version == another.Version) && (TransferCtlFlags == another.TransferCtlFlags) &&
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800289 (MaxBlockSize == another.MaxBlockSize) && metadataMatches);
290}
291
292// WARNING: this function should never return early, since MessageSize() relies on it to calculate
293// the size of the message (even if the message is incomplete or filled out incorrectly).
Kevin Schoedel2d48e752021-02-08 09:29:17 -0500294Encoding::LittleEndian::BufferWriter & ReceiveAccept::WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800295{
Kevin Schoedel8ea423a2021-03-11 11:49:18 -0500296 const BitFlags<TransferControlFlags> transferCtlFlags(Version & kVersionMask, TransferCtlFlags);
297 const bool widerange = (StartOffset > std::numeric_limits<uint32_t>::max()) || (Length > std::numeric_limits<uint32_t>::max());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800298
Kevin Schoedel8ea423a2021-03-11 11:49:18 -0500299 BitFlags<RangeControlFlags> rangeCtlFlags;
300 rangeCtlFlags.Set(RangeControlFlags::kDefLen, Length > 0);
301 rangeCtlFlags.Set(RangeControlFlags::kStartOffset, StartOffset > 0);
302 rangeCtlFlags.Set(RangeControlFlags::kWiderange, widerange);
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800303
Kevin Schoedel8ea423a2021-03-11 11:49:18 -0500304 aBuffer.Put(transferCtlFlags.Raw());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800305 aBuffer.Put(rangeCtlFlags.Raw());
Rob Walkercc92b632020-11-21 13:21:56 -0800306 aBuffer.Put16(MaxBlockSize);
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800307
308 if (StartOffset > 0)
309 {
310 if (widerange)
311 {
Rob Walkercc92b632020-11-21 13:21:56 -0800312 aBuffer.Put64(StartOffset);
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800313 }
314 else
315 {
Rob Walkercc92b632020-11-21 13:21:56 -0800316 aBuffer.Put32(static_cast<uint32_t>(StartOffset));
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800317 }
318 }
319
320 if (Length > 0)
321 {
322 if (widerange)
323 {
Rob Walkercc92b632020-11-21 13:21:56 -0800324 aBuffer.Put64(Length);
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800325 }
326 else
327 {
Rob Walkercc92b632020-11-21 13:21:56 -0800328 aBuffer.Put32(static_cast<uint32_t>(Length));
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800329 }
330 }
331
332 if (Metadata != nullptr)
333 {
334 aBuffer.Put(Metadata, static_cast<size_t>(MetadataLength));
335 }
Rob Walkercc92b632020-11-21 13:21:56 -0800336 return aBuffer;
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800337}
338
Trevor Holbrook4d875fb2021-02-05 11:57:48 -0800339CHIP_ERROR ReceiveAccept::Parse(System::PacketBufferHandle aBuffer)
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800340{
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800341 uint8_t transferCtl = 0;
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800342 uint32_t tmpUint32Value = 0; // Used for reading non-wide length and offset fields
Kevin Schoedelb5a5d892020-12-03 19:01:10 -0500343 uint8_t * bufStart = aBuffer->Start();
344 Reader bufReader(bufStart, aBuffer->DataLength());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800345
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400346 ReturnErrorOnFailure(bufReader.Read8(&transferCtl).Read8(mRangeCtlFlags.RawStorage()).Read16(&MaxBlockSize).StatusCode());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800347
348 Version = transferCtl & kVersionMask;
349
350 // Only one of these values should be set. It is up to the caller to verify this.
351 TransferCtlFlags.SetRaw(static_cast<uint8_t>(transferCtl & ~kVersionMask));
352
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800353 StartOffset = 0;
Carol Yangfde6a172021-11-08 17:30:19 -0800354 if (mRangeCtlFlags.Has(RangeControlFlags::kStartOffset))
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800355 {
Carol Yangfde6a172021-11-08 17:30:19 -0800356 if (mRangeCtlFlags.Has(RangeControlFlags::kWiderange))
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800357 {
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400358 ReturnErrorOnFailure(bufReader.Read64(&StartOffset).StatusCode());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800359 }
360 else
361 {
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400362 ReturnErrorOnFailure(bufReader.Read32(&tmpUint32Value).StatusCode());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800363 StartOffset = tmpUint32Value;
364 }
365 }
366
367 Length = 0;
Carol Yangfde6a172021-11-08 17:30:19 -0800368 if (mRangeCtlFlags.Has(RangeControlFlags::kDefLen))
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800369 {
Carol Yangfde6a172021-11-08 17:30:19 -0800370 if (mRangeCtlFlags.Has(RangeControlFlags::kWiderange))
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800371 {
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400372 ReturnErrorOnFailure(bufReader.Read64(&Length).StatusCode());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800373 }
374 else
375 {
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400376 ReturnErrorOnFailure(bufReader.Read32(&tmpUint32Value).StatusCode());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800377 Length = tmpUint32Value;
378 }
379 }
380
381 // Rest of message is metadata (could be empty)
382 Metadata = nullptr;
383 MetadataLength = 0;
384 if (bufReader.Remaining() > 0)
385 {
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800386 Metadata = &bufStart[bufReader.OctetsRead()];
387 MetadataLength = bufReader.Remaining();
388 }
389
Kevin Schoedelbd11f982021-01-26 13:34:29 -0500390 // Retain ownership of the packet buffer so that the Metadata pointer remains valid.
Kevin Schoedelb5a5d892020-12-03 19:01:10 -0500391 Buffer = std::move(aBuffer);
392
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400393 return CHIP_NO_ERROR;
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800394}
395
Trevor Holbrook4d875fb2021-02-05 11:57:48 -0800396size_t ReceiveAccept::MessageSize() const
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800397{
Kevin Schoedel2d48e752021-02-08 09:29:17 -0500398 BufferWriter emptyBuf(nullptr, 0);
Rob Walkercc92b632020-11-21 13:21:56 -0800399 return WriteToBuffer(emptyBuf).Needed();
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800400}
401
Carol Yangfde6a172021-11-08 17:30:19 -0800402#if CHIP_AUTOMATION_LOGGING
403void ReceiveAccept::LogMessage(bdx::MessageType messageType) const
404{
405 (void) messageType;
406 ChipLogAutomation("ReceiveAccept");
407 ChipLogAutomation(" Transfer Control: 0x%X", TransferCtlFlags.Raw() | Version);
408 ChipLogAutomation(" Range Control: 0x%X", mRangeCtlFlags.Raw());
andrei-menzopol57471cb2022-04-20 23:31:17 +0300409 ChipLogAutomation(" Max Block Size: %u", MaxBlockSize);
Carol Yangfde6a172021-11-08 17:30:19 -0800410 ChipLogAutomation(" Length: 0x" ChipLogFormatX64, ChipLogValueX64(Length));
411}
412#endif // CHIP_AUTOMATION_LOGGING
413
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800414bool ReceiveAccept::operator==(const ReceiveAccept & another) const
415{
416 if (MetadataLength != another.MetadataLength)
417 {
418 return false;
419 }
420
421 bool metadataMatches = true;
422 if (MetadataLength > 0)
423 {
424 metadataMatches = (memcmp(Metadata, another.Metadata, MetadataLength) == 0);
425 }
426
Kevin Schoedel8ea423a2021-03-11 11:49:18 -0500427 return ((Version == another.Version) && (TransferCtlFlags == another.TransferCtlFlags) &&
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800428 (StartOffset == another.StartOffset) && (MaxBlockSize == another.MaxBlockSize) && (Length == another.Length) &&
429 metadataMatches);
430}
431
432// WARNING: this function should never return early, since MessageSize() relies on it to calculate
433// the size of the message (even if the message is incomplete or filled out incorrectly).
Kevin Schoedel2d48e752021-02-08 09:29:17 -0500434Encoding::LittleEndian::BufferWriter & CounterMessage::WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800435{
Rob Walkercc92b632020-11-21 13:21:56 -0800436 return aBuffer.Put32(BlockCounter);
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800437}
438
Trevor Holbrook4d875fb2021-02-05 11:57:48 -0800439CHIP_ERROR CounterMessage::Parse(System::PacketBufferHandle aBuffer)
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800440{
Kevin Schoedelb5a5d892020-12-03 19:01:10 -0500441 uint8_t * bufStart = aBuffer->Start();
442 Reader bufReader(bufStart, aBuffer->DataLength());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800443 return bufReader.Read32(&BlockCounter).StatusCode();
444}
445
Trevor Holbrook4d875fb2021-02-05 11:57:48 -0800446size_t CounterMessage::MessageSize() const
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800447{
Kevin Schoedel2d48e752021-02-08 09:29:17 -0500448 BufferWriter emptyBuf(nullptr, 0);
Rob Walkercc92b632020-11-21 13:21:56 -0800449 return WriteToBuffer(emptyBuf).Needed();
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800450}
451
452bool CounterMessage::operator==(const CounterMessage & another) const
453{
454 return (BlockCounter == another.BlockCounter);
455}
456
Carol Yangfde6a172021-11-08 17:30:19 -0800457#if CHIP_AUTOMATION_LOGGING
458void CounterMessage::LogMessage(bdx::MessageType messageType) const
459{
460 switch (messageType)
461 {
462 case MessageType::BlockQuery:
463 ChipLogAutomation("BlockQuery");
464 break;
465 case MessageType::BlockAck:
466 ChipLogAutomation("BlockAck");
467 break;
468 case MessageType::BlockAckEOF:
469 ChipLogAutomation("BlockAckEOF");
470 break;
471 default:
472 break;
473 }
474
475 ChipLogAutomation(" Block Counter: %" PRIu32, BlockCounter);
476}
477#endif // CHIP_AUTOMATION_LOGGING
478
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800479// WARNING: this function should never return early, since MessageSize() relies on it to calculate
480// the size of the message (even if the message is incomplete or filled out incorrectly).
Kevin Schoedel2d48e752021-02-08 09:29:17 -0500481Encoding::LittleEndian::BufferWriter & DataBlock::WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800482{
Rob Walkercc92b632020-11-21 13:21:56 -0800483 aBuffer.Put32(BlockCounter);
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800484 if (Data != nullptr)
485 {
486 aBuffer.Put(Data, DataLength);
487 }
Rob Walkercc92b632020-11-21 13:21:56 -0800488 return aBuffer;
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800489}
490
Trevor Holbrook4d875fb2021-02-05 11:57:48 -0800491CHIP_ERROR DataBlock::Parse(System::PacketBufferHandle aBuffer)
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800492{
Kevin Schoedelb5a5d892020-12-03 19:01:10 -0500493 uint8_t * bufStart = aBuffer->Start();
494 Reader bufReader(bufStart, aBuffer->DataLength());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800495
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400496 ReturnErrorOnFailure(bufReader.Read32(&BlockCounter).StatusCode());
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800497
498 // Rest of message is data
499 Data = nullptr;
500 DataLength = 0;
501 if (bufReader.Remaining() > 0)
502 {
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800503 Data = &bufStart[bufReader.OctetsRead()];
504 DataLength = bufReader.Remaining();
505 }
506
Kevin Schoedelbd11f982021-01-26 13:34:29 -0500507 // Retain ownership of the packet buffer so that the Data pointer remains valid.
Kevin Schoedelb5a5d892020-12-03 19:01:10 -0500508 Buffer = std::move(aBuffer);
509
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400510 return CHIP_NO_ERROR;
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800511}
512
Trevor Holbrook4d875fb2021-02-05 11:57:48 -0800513size_t DataBlock::MessageSize() const
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800514{
Kevin Schoedel2d48e752021-02-08 09:29:17 -0500515 BufferWriter emptyBuf(nullptr, 0);
Rob Walkercc92b632020-11-21 13:21:56 -0800516 return WriteToBuffer(emptyBuf).Needed();
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800517}
518
Carol Yangfde6a172021-11-08 17:30:19 -0800519#if CHIP_AUTOMATION_LOGGING
520void DataBlock::LogMessage(bdx::MessageType messageType) const
521{
522 switch (messageType)
523 {
524 case MessageType::Block:
525 ChipLogAutomation("Block");
526 break;
527 case MessageType::BlockEOF:
528 ChipLogAutomation("BlockEOF");
529 break;
530 default:
531 break;
532 }
533
534 ChipLogAutomation(" Block Counter: %" PRIu32, BlockCounter);
andrei-menzopol57471cb2022-04-20 23:31:17 +0300535 ChipLogAutomation(" Data Length: %u", static_cast<unsigned int>(DataLength));
Carol Yangfde6a172021-11-08 17:30:19 -0800536}
537#endif // CHIP_AUTOMATION_LOGGING
538
Trevor Holbrook934f89c2020-11-18 15:34:14 -0800539bool DataBlock::operator==(const DataBlock & another) const
540{
541 if (DataLength != another.DataLength)
542 {
543 return false;
544 }
545
546 bool dataMatches = true;
547 if (DataLength > 0)
548 {
549 dataMatches = memcmp(Data, another.Data, DataLength) == 0;
550 }
551
552 return ((BlockCounter == another.BlockCounter) && dataMatches);
553}
Shubham Patil6c928f42021-12-13 21:21:50 +0530554
555// WARNING: this function should never return early, since MessageSize() relies on it to calculate
556// the size of the message (even if the message is incomplete or filled out incorrectly).
557Encoding::LittleEndian::BufferWriter & BlockQueryWithSkip::WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const
558{
559 aBuffer.Put32(BlockCounter);
560 aBuffer.Put64(BytesToSkip);
561 return aBuffer;
562}
563
564CHIP_ERROR BlockQueryWithSkip::Parse(System::PacketBufferHandle aBuffer)
565{
Shubham Patil6c928f42021-12-13 21:21:50 +0530566 uint8_t * bufStart = aBuffer->Start();
567 Reader bufReader(bufStart, aBuffer->DataLength());
Shubham Patil6c928f42021-12-13 21:21:50 +0530568
Boris Zbarskyad5253a2023-05-26 02:22:37 -0400569 return bufReader.Read32(&BlockCounter).Read64(&BytesToSkip).StatusCode();
Shubham Patil6c928f42021-12-13 21:21:50 +0530570}
571
572size_t BlockQueryWithSkip::MessageSize() const
573{
574 BufferWriter emptyBuf(nullptr, 0);
575 return WriteToBuffer(emptyBuf).Needed();
576}
577
578bool BlockQueryWithSkip::operator==(const BlockQueryWithSkip & another) const
579{
580 return (BlockCounter == another.BlockCounter && BytesToSkip == another.BytesToSkip);
581}
582
583#if CHIP_AUTOMATION_LOGGING
584void BlockQueryWithSkip::LogMessage(bdx::MessageType messageType) const
585{
586 ChipLogAutomation("BlockQueryWithSkip");
587 ChipLogAutomation(" Block Counter: %" PRIu32, BlockCounter);
Boris Zbarsky75de58d2023-11-17 09:43:20 -0500588 ChipLogAutomation(" Bytes To Skip: 0x" ChipLogFormatX64, ChipLogValueX64(BytesToSkip));
Shubham Patil6c928f42021-12-13 21:21:50 +0530589}
590#endif // CHIP_AUTOMATION_LOGGING