LCOV - code coverage report
Current view: top level - protocols/bdx - BdxMessages.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 251 275 91.3 %
Date: 2024-02-15 08:20:41 Functions: 29 30 96.7 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4             :  *    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             : 
      26             : #include <lib/support/BufferReader.h>
      27             : #include <lib/support/BufferWriter.h>
      28             : #include <lib/support/CodeUtils.h>
      29             : 
      30             : #include <limits>
      31             : #include <utility>
      32             : 
      33             : namespace {
      34             : constexpr uint8_t kVersionMask = 0x0F;
      35             : } // namespace
      36             : 
      37             : using namespace chip;
      38             : using namespace chip::bdx;
      39             : using 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).
      43          12 : BufferWriter & TransferInit::WriteToBuffer(BufferWriter & aBuffer) const
      44             : {
      45          12 :     const BitFlags<TransferControlFlags> proposedTransferCtl(Version & kVersionMask, TransferCtlOptions);
      46             :     const bool widerange =
      47          12 :         (StartOffset > std::numeric_limits<uint32_t>::max()) || (MaxLength > std::numeric_limits<uint32_t>::max());
      48             : 
      49          12 :     BitFlags<RangeControlFlags> rangeCtlFlags;
      50          12 :     rangeCtlFlags.Set(RangeControlFlags::kDefLen, MaxLength > 0);
      51          12 :     rangeCtlFlags.Set(RangeControlFlags::kStartOffset, StartOffset > 0);
      52          12 :     rangeCtlFlags.Set(RangeControlFlags::kWiderange, widerange);
      53             : 
      54          12 :     aBuffer.Put(proposedTransferCtl.Raw());
      55          12 :     aBuffer.Put(rangeCtlFlags.Raw());
      56          12 :     aBuffer.Put16(MaxBlockSize);
      57             : 
      58          12 :     if (StartOffset > 0)
      59             :     {
      60           2 :         if (widerange)
      61             :         {
      62           2 :             aBuffer.Put64(StartOffset);
      63             :         }
      64             :         else
      65             :         {
      66           0 :             aBuffer.Put32(static_cast<uint32_t>(StartOffset));
      67             :         }
      68             :     }
      69             : 
      70          12 :     if (MaxLength > 0)
      71             :     {
      72           2 :         if (widerange)
      73             :         {
      74           2 :             aBuffer.Put64(MaxLength);
      75             :         }
      76             :         else
      77             :         {
      78           0 :             aBuffer.Put32(static_cast<uint32_t>(MaxLength));
      79             :         }
      80             :     }
      81             : 
      82          12 :     aBuffer.Put16(FileDesLength);
      83          12 :     if (FileDesignator != nullptr)
      84             :     {
      85          12 :         aBuffer.Put(FileDesignator, static_cast<size_t>(FileDesLength));
      86             :     }
      87             : 
      88          12 :     if (Metadata != nullptr)
      89             :     {
      90           4 :         aBuffer.Put(Metadata, static_cast<size_t>(MetadataLength));
      91             :     }
      92          12 :     return aBuffer;
      93             : }
      94             : 
      95           5 : CHIP_ERROR TransferInit::Parse(System::PacketBufferHandle aBuffer)
      96             : {
      97             :     uint8_t proposedTransferCtl;
      98           5 :     uint32_t tmpUint32Value = 0; // Used for reading non-wide length and offset fields
      99           5 :     uint8_t * bufStart      = aBuffer->Start();
     100           5 :     Reader bufReader(bufStart, aBuffer->DataLength());
     101             : 
     102           5 :     ReturnErrorOnFailure(
     103             :         bufReader.Read8(&proposedTransferCtl).Read8(mRangeCtlFlags.RawStorage()).Read16(&MaxBlockSize).StatusCode());
     104             : 
     105           5 :     Version = proposedTransferCtl & kVersionMask;
     106           5 :     TransferCtlOptions.SetRaw(static_cast<uint8_t>(proposedTransferCtl & ~kVersionMask));
     107             : 
     108           5 :     StartOffset = 0;
     109           5 :     if (mRangeCtlFlags.Has(RangeControlFlags::kStartOffset))
     110             :     {
     111           1 :         if (mRangeCtlFlags.Has(RangeControlFlags::kWiderange))
     112             :         {
     113           1 :             ReturnErrorOnFailure(bufReader.Read64(&StartOffset).StatusCode());
     114             :         }
     115             :         else
     116             :         {
     117           0 :             ReturnErrorOnFailure(bufReader.Read32(&tmpUint32Value).StatusCode());
     118           0 :             StartOffset = tmpUint32Value;
     119             :         }
     120             :     }
     121             : 
     122           5 :     MaxLength = 0;
     123           5 :     if (mRangeCtlFlags.Has(RangeControlFlags::kDefLen))
     124             :     {
     125           1 :         if (mRangeCtlFlags.Has(RangeControlFlags::kWiderange))
     126             :         {
     127           1 :             ReturnErrorOnFailure(bufReader.Read64(&MaxLength).StatusCode());
     128             :         }
     129             :         else
     130             :         {
     131           0 :             ReturnErrorOnFailure(bufReader.Read32(&tmpUint32Value).StatusCode());
     132           0 :             MaxLength = tmpUint32Value;
     133             :         }
     134             :     }
     135             : 
     136           5 :     ReturnErrorOnFailure(bufReader.Read16(&FileDesLength).StatusCode());
     137             : 
     138           5 :     VerifyOrReturnError(bufReader.HasAtLeast(FileDesLength), CHIP_ERROR_MESSAGE_INCOMPLETE);
     139           5 :     FileDesignator = &bufStart[bufReader.OctetsRead()];
     140             : 
     141             :     // Rest of message is metadata (could be empty)
     142           5 :     Metadata       = nullptr;
     143           5 :     MetadataLength = 0;
     144           5 :     if (bufReader.Remaining() > FileDesLength)
     145             :     {
     146           2 :         uint16_t metadataStartIndex = static_cast<uint16_t>(bufReader.OctetsRead() + FileDesLength);
     147           2 :         Metadata                    = &bufStart[metadataStartIndex];
     148           2 :         MetadataLength              = static_cast<uint16_t>(aBuffer->DataLength() - metadataStartIndex);
     149             :     }
     150             : 
     151             :     // Retain ownership of the packet buffer so that the FileDesignator and Metadata pointers remain valid.
     152           5 :     Buffer = std::move(aBuffer);
     153             : 
     154           5 :     return CHIP_NO_ERROR;
     155             : }
     156             : 
     157           6 : size_t TransferInit::MessageSize() const
     158             : {
     159           6 :     BufferWriter emptyBuf(nullptr, 0);
     160           6 :     return WriteToBuffer(emptyBuf).Needed();
     161             : }
     162             : 
     163             : #if CHIP_AUTOMATION_LOGGING
     164           9 : void TransferInit::LogMessage(bdx::MessageType messageType) const
     165             : {
     166             :     char fd[kMaxFileDesignatorLen];
     167           9 :     snprintf(fd, sizeof(fd), "%.*s", static_cast<int>(FileDesLength), FileDesignator);
     168             : 
     169           9 :     switch (messageType)
     170             :     {
     171           2 :     case MessageType::SendInit:
     172           2 :         ChipLogAutomation("SendInit");
     173           2 :         break;
     174           7 :     case MessageType::ReceiveInit:
     175           7 :         ChipLogAutomation("ReceiveInit");
     176           7 :         break;
     177           0 :     default:
     178           0 :         break;
     179             :     }
     180             : 
     181           9 :     ChipLogAutomation("  Proposed Transfer Control: 0x%X", static_cast<unsigned>(TransferCtlOptions.Raw() | Version));
     182           9 :     ChipLogAutomation("  Range Control: 0x%X", static_cast<unsigned>(mRangeCtlFlags.Raw()));
     183           9 :     ChipLogAutomation("  Proposed Max Block Size: %u", MaxBlockSize);
     184           9 :     ChipLogAutomation("  Start Offset: 0x" ChipLogFormatX64, ChipLogValueX64(StartOffset));
     185           9 :     ChipLogAutomation("  Proposed Max Length: 0x" ChipLogFormatX64, ChipLogValueX64(MaxLength));
     186           9 :     ChipLogAutomation("  File Designator Length: %u", FileDesLength);
     187           9 :     ChipLogAutomation("  File Designator: %s", fd);
     188           9 : }
     189             : #endif // CHIP_AUTOMATION_LOGGING
     190             : 
     191           1 : bool TransferInit::operator==(const TransferInit & another) const
     192             : {
     193           1 :     if ((MetadataLength != another.MetadataLength) || (FileDesLength != another.FileDesLength))
     194             :     {
     195           0 :         return false;
     196             :     }
     197             : 
     198           1 :     bool fileDesMatches = true;
     199           1 :     if (FileDesLength > 0)
     200             :     {
     201           1 :         fileDesMatches = (memcmp(FileDesignator, another.FileDesignator, FileDesLength) == 0);
     202             :     }
     203             : 
     204           1 :     bool metadataMatches = true;
     205           1 :     if (MetadataLength > 0)
     206             :     {
     207           1 :         metadataMatches = (memcmp(Metadata, another.Metadata, MetadataLength) == 0);
     208             :     }
     209             : 
     210           1 :     return ((Version == another.Version) && (TransferCtlOptions == another.TransferCtlOptions) &&
     211           1 :             (StartOffset == another.StartOffset) && (MaxLength == another.MaxLength) && (MaxBlockSize == another.MaxBlockSize) &&
     212           2 :             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).
     217           4 : Encoding::LittleEndian::BufferWriter & SendAccept::WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const
     218             : {
     219           4 :     const BitFlags<TransferControlFlags> transferCtl(Version & kVersionMask, TransferCtlFlags);
     220             : 
     221           4 :     aBuffer.Put(transferCtl.Raw());
     222           4 :     aBuffer.Put16(MaxBlockSize);
     223             : 
     224           4 :     if (Metadata != nullptr)
     225             :     {
     226           2 :         aBuffer.Put(Metadata, static_cast<size_t>(MetadataLength));
     227             :     }
     228           4 :     return aBuffer;
     229             : }
     230             : 
     231           2 : CHIP_ERROR SendAccept::Parse(System::PacketBufferHandle aBuffer)
     232             : {
     233           2 :     uint8_t transferCtl = 0;
     234           2 :     uint8_t * bufStart  = aBuffer->Start();
     235           2 :     Reader bufReader(bufStart, aBuffer->DataLength());
     236             : 
     237           2 :     ReturnErrorOnFailure(bufReader.Read8(&transferCtl).Read16(&MaxBlockSize).StatusCode());
     238             : 
     239           2 :     Version = transferCtl & kVersionMask;
     240             : 
     241             :     // Only one of these values should be set. It is up to the caller to verify this.
     242           2 :     TransferCtlFlags.SetRaw(static_cast<uint8_t>(transferCtl & ~kVersionMask));
     243             : 
     244             :     // Rest of message is metadata (could be empty)
     245           2 :     Metadata       = nullptr;
     246           2 :     MetadataLength = 0;
     247           2 :     if (bufReader.Remaining() > 0)
     248             :     {
     249           1 :         Metadata       = &bufStart[bufReader.OctetsRead()];
     250           1 :         MetadataLength = bufReader.Remaining();
     251             :     }
     252             : 
     253             :     // Retain ownership of the packet buffer so that the Metadata pointer remains valid.
     254           2 :     Buffer = std::move(aBuffer);
     255             : 
     256           2 :     return CHIP_NO_ERROR;
     257             : }
     258             : 
     259           2 : size_t SendAccept::MessageSize() const
     260             : {
     261           2 :     BufferWriter emptyBuf(nullptr, 0);
     262           2 :     return WriteToBuffer(emptyBuf).Needed();
     263             : }
     264             : 
     265             : #if CHIP_AUTOMATION_LOGGING
     266           2 : void SendAccept::LogMessage(bdx::MessageType messageType) const
     267             : {
     268             :     (void) messageType;
     269           2 :     ChipLogAutomation("SendAccept");
     270           2 :     ChipLogAutomation("  Transfer Control: 0x%X", static_cast<unsigned>(TransferCtlFlags.Raw() | Version));
     271           2 :     ChipLogAutomation("  Max Block Size: %u", MaxBlockSize);
     272           2 : }
     273             : #endif // CHIP_AUTOMATION_LOGGING
     274             : 
     275           1 : bool SendAccept::operator==(const SendAccept & another) const
     276             : {
     277           1 :     if (MetadataLength != another.MetadataLength)
     278             :     {
     279           0 :         return false;
     280             :     }
     281             : 
     282           1 :     bool metadataMatches = true;
     283           1 :     if (MetadataLength > 0)
     284             :     {
     285           1 :         metadataMatches = (memcmp(Metadata, another.Metadata, MetadataLength) == 0);
     286             :     }
     287             : 
     288           1 :     return ((Version == another.Version) && (TransferCtlFlags == another.TransferCtlFlags) &&
     289           2 :             (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).
     294           6 : Encoding::LittleEndian::BufferWriter & ReceiveAccept::WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const
     295             : {
     296           6 :     const BitFlags<TransferControlFlags> transferCtlFlags(Version & kVersionMask, TransferCtlFlags);
     297           6 :     const bool widerange = (StartOffset > std::numeric_limits<uint32_t>::max()) || (Length > std::numeric_limits<uint32_t>::max());
     298             : 
     299           6 :     BitFlags<RangeControlFlags> rangeCtlFlags;
     300           6 :     rangeCtlFlags.Set(RangeControlFlags::kDefLen, Length > 0);
     301           6 :     rangeCtlFlags.Set(RangeControlFlags::kStartOffset, StartOffset > 0);
     302           6 :     rangeCtlFlags.Set(RangeControlFlags::kWiderange, widerange);
     303             : 
     304           6 :     aBuffer.Put(transferCtlFlags.Raw());
     305           6 :     aBuffer.Put(rangeCtlFlags.Raw());
     306           6 :     aBuffer.Put16(MaxBlockSize);
     307             : 
     308           6 :     if (StartOffset > 0)
     309             :     {
     310           6 :         if (widerange)
     311             :         {
     312           2 :             aBuffer.Put64(StartOffset);
     313             :         }
     314             :         else
     315             :         {
     316           4 :             aBuffer.Put32(static_cast<uint32_t>(StartOffset));
     317             :         }
     318             :     }
     319             : 
     320           6 :     if (Length > 0)
     321             :     {
     322           2 :         if (widerange)
     323             :         {
     324           2 :             aBuffer.Put64(Length);
     325             :         }
     326             :         else
     327             :         {
     328           0 :             aBuffer.Put32(static_cast<uint32_t>(Length));
     329             :         }
     330             :     }
     331             : 
     332           6 :     if (Metadata != nullptr)
     333             :     {
     334           4 :         aBuffer.Put(Metadata, static_cast<size_t>(MetadataLength));
     335             :     }
     336           6 :     return aBuffer;
     337             : }
     338             : 
     339           3 : CHIP_ERROR ReceiveAccept::Parse(System::PacketBufferHandle aBuffer)
     340             : {
     341           3 :     uint8_t transferCtl     = 0;
     342           3 :     uint32_t tmpUint32Value = 0; // Used for reading non-wide length and offset fields
     343           3 :     uint8_t * bufStart      = aBuffer->Start();
     344           3 :     Reader bufReader(bufStart, aBuffer->DataLength());
     345             : 
     346           3 :     ReturnErrorOnFailure(bufReader.Read8(&transferCtl).Read8(mRangeCtlFlags.RawStorage()).Read16(&MaxBlockSize).StatusCode());
     347             : 
     348           3 :     Version = transferCtl & kVersionMask;
     349             : 
     350             :     // Only one of these values should be set. It is up to the caller to verify this.
     351           3 :     TransferCtlFlags.SetRaw(static_cast<uint8_t>(transferCtl & ~kVersionMask));
     352             : 
     353           3 :     StartOffset = 0;
     354           3 :     if (mRangeCtlFlags.Has(RangeControlFlags::kStartOffset))
     355             :     {
     356           3 :         if (mRangeCtlFlags.Has(RangeControlFlags::kWiderange))
     357             :         {
     358           1 :             ReturnErrorOnFailure(bufReader.Read64(&StartOffset).StatusCode());
     359             :         }
     360             :         else
     361             :         {
     362           2 :             ReturnErrorOnFailure(bufReader.Read32(&tmpUint32Value).StatusCode());
     363           2 :             StartOffset = tmpUint32Value;
     364             :         }
     365             :     }
     366             : 
     367           3 :     Length = 0;
     368           3 :     if (mRangeCtlFlags.Has(RangeControlFlags::kDefLen))
     369             :     {
     370           1 :         if (mRangeCtlFlags.Has(RangeControlFlags::kWiderange))
     371             :         {
     372           1 :             ReturnErrorOnFailure(bufReader.Read64(&Length).StatusCode());
     373             :         }
     374             :         else
     375             :         {
     376           0 :             ReturnErrorOnFailure(bufReader.Read32(&tmpUint32Value).StatusCode());
     377           0 :             Length = tmpUint32Value;
     378             :         }
     379             :     }
     380             : 
     381             :     // Rest of message is metadata (could be empty)
     382           3 :     Metadata       = nullptr;
     383           3 :     MetadataLength = 0;
     384           3 :     if (bufReader.Remaining() > 0)
     385             :     {
     386           2 :         Metadata       = &bufStart[bufReader.OctetsRead()];
     387           2 :         MetadataLength = bufReader.Remaining();
     388             :     }
     389             : 
     390             :     // Retain ownership of the packet buffer so that the Metadata pointer remains valid.
     391           3 :     Buffer = std::move(aBuffer);
     392             : 
     393           3 :     return CHIP_NO_ERROR;
     394             : }
     395             : 
     396           3 : size_t ReceiveAccept::MessageSize() const
     397             : {
     398           3 :     BufferWriter emptyBuf(nullptr, 0);
     399           3 :     return WriteToBuffer(emptyBuf).Needed();
     400             : }
     401             : 
     402             : #if CHIP_AUTOMATION_LOGGING
     403           4 : void ReceiveAccept::LogMessage(bdx::MessageType messageType) const
     404             : {
     405             :     (void) messageType;
     406           4 :     ChipLogAutomation("ReceiveAccept");
     407           4 :     ChipLogAutomation("  Transfer Control: 0x%X", TransferCtlFlags.Raw() | Version);
     408           4 :     ChipLogAutomation("  Range Control: 0x%X", mRangeCtlFlags.Raw());
     409           4 :     ChipLogAutomation("  Max Block Size: %u", MaxBlockSize);
     410           4 :     ChipLogAutomation("  Length: 0x" ChipLogFormatX64, ChipLogValueX64(Length));
     411           4 : }
     412             : #endif // CHIP_AUTOMATION_LOGGING
     413             : 
     414           1 : bool ReceiveAccept::operator==(const ReceiveAccept & another) const
     415             : {
     416           1 :     if (MetadataLength != another.MetadataLength)
     417             :     {
     418           0 :         return false;
     419             :     }
     420             : 
     421           1 :     bool metadataMatches = true;
     422           1 :     if (MetadataLength > 0)
     423             :     {
     424           1 :         metadataMatches = (memcmp(Metadata, another.Metadata, MetadataLength) == 0);
     425             :     }
     426             : 
     427           1 :     return ((Version == another.Version) && (TransferCtlFlags == another.TransferCtlFlags) &&
     428           2 :             (StartOffset == another.StartOffset) && (MaxBlockSize == another.MaxBlockSize) && (Length == another.Length) &&
     429           1 :             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).
     434          38 : Encoding::LittleEndian::BufferWriter & CounterMessage::WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const
     435             : {
     436          38 :     return aBuffer.Put32(BlockCounter);
     437             : }
     438             : 
     439          19 : CHIP_ERROR CounterMessage::Parse(System::PacketBufferHandle aBuffer)
     440             : {
     441          19 :     uint8_t * bufStart = aBuffer->Start();
     442          19 :     Reader bufReader(bufStart, aBuffer->DataLength());
     443          19 :     return bufReader.Read32(&BlockCounter).StatusCode();
     444             : }
     445             : 
     446          19 : size_t CounterMessage::MessageSize() const
     447             : {
     448          19 :     BufferWriter emptyBuf(nullptr, 0);
     449          19 :     return WriteToBuffer(emptyBuf).Needed();
     450             : }
     451             : 
     452           1 : bool CounterMessage::operator==(const CounterMessage & another) const
     453             : {
     454           1 :     return (BlockCounter == another.BlockCounter);
     455             : }
     456             : 
     457             : #if CHIP_AUTOMATION_LOGGING
     458          36 : void CounterMessage::LogMessage(bdx::MessageType messageType) const
     459             : {
     460          36 :     switch (messageType)
     461             :     {
     462          24 :     case MessageType::BlockQuery:
     463          24 :         ChipLogAutomation("BlockQuery");
     464          24 :         break;
     465           8 :     case MessageType::BlockAck:
     466           8 :         ChipLogAutomation("BlockAck");
     467           8 :         break;
     468           4 :     case MessageType::BlockAckEOF:
     469           4 :         ChipLogAutomation("BlockAckEOF");
     470           4 :         break;
     471           0 :     default:
     472           0 :         break;
     473             :     }
     474             : 
     475          36 :     ChipLogAutomation("  Block Counter: %" PRIu32, BlockCounter);
     476          36 : }
     477             : #endif // CHIP_AUTOMATION_LOGGING
     478             : 
     479             : // 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).
     481          32 : Encoding::LittleEndian::BufferWriter & DataBlock::WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const
     482             : {
     483          32 :     aBuffer.Put32(BlockCounter);
     484          32 :     if (Data != nullptr)
     485             :     {
     486          32 :         aBuffer.Put(Data, DataLength);
     487             :     }
     488          32 :     return aBuffer;
     489             : }
     490             : 
     491          17 : CHIP_ERROR DataBlock::Parse(System::PacketBufferHandle aBuffer)
     492             : {
     493          17 :     uint8_t * bufStart = aBuffer->Start();
     494          17 :     Reader bufReader(bufStart, aBuffer->DataLength());
     495             : 
     496          17 :     ReturnErrorOnFailure(bufReader.Read32(&BlockCounter).StatusCode());
     497             : 
     498             :     // Rest of message is data
     499          17 :     Data       = nullptr;
     500          17 :     DataLength = 0;
     501          17 :     if (bufReader.Remaining() > 0)
     502             :     {
     503          17 :         Data       = &bufStart[bufReader.OctetsRead()];
     504          17 :         DataLength = bufReader.Remaining();
     505             :     }
     506             : 
     507             :     // Retain ownership of the packet buffer so that the Data pointer remains valid.
     508          17 :     Buffer = std::move(aBuffer);
     509             : 
     510          17 :     return CHIP_NO_ERROR;
     511             : }
     512             : 
     513          16 : size_t DataBlock::MessageSize() const
     514             : {
     515          16 :     BufferWriter emptyBuf(nullptr, 0);
     516          16 :     return WriteToBuffer(emptyBuf).Needed();
     517             : }
     518             : 
     519             : #if CHIP_AUTOMATION_LOGGING
     520          30 : void DataBlock::LogMessage(bdx::MessageType messageType) const
     521             : {
     522          30 :     switch (messageType)
     523             :     {
     524          26 :     case MessageType::Block:
     525          26 :         ChipLogAutomation("Block");
     526          26 :         break;
     527           4 :     case MessageType::BlockEOF:
     528           4 :         ChipLogAutomation("BlockEOF");
     529           4 :         break;
     530           0 :     default:
     531           0 :         break;
     532             :     }
     533             : 
     534          30 :     ChipLogAutomation("  Block Counter: %" PRIu32, BlockCounter);
     535          30 :     ChipLogAutomation("  Data Length: %u", static_cast<unsigned int>(DataLength));
     536          30 : }
     537             : #endif // CHIP_AUTOMATION_LOGGING
     538             : 
     539           1 : bool DataBlock::operator==(const DataBlock & another) const
     540             : {
     541           1 :     if (DataLength != another.DataLength)
     542             :     {
     543           0 :         return false;
     544             :     }
     545             : 
     546           1 :     bool dataMatches = true;
     547           1 :     if (DataLength > 0)
     548             :     {
     549           1 :         dataMatches = memcmp(Data, another.Data, DataLength) == 0;
     550             :     }
     551             : 
     552           1 :     return ((BlockCounter == another.BlockCounter) && dataMatches);
     553             : }
     554             : 
     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).
     557           2 : Encoding::LittleEndian::BufferWriter & BlockQueryWithSkip::WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const
     558             : {
     559           2 :     aBuffer.Put32(BlockCounter);
     560           2 :     aBuffer.Put64(BytesToSkip);
     561           2 :     return aBuffer;
     562             : }
     563             : 
     564           1 : CHIP_ERROR BlockQueryWithSkip::Parse(System::PacketBufferHandle aBuffer)
     565             : {
     566           1 :     uint8_t * bufStart = aBuffer->Start();
     567           1 :     Reader bufReader(bufStart, aBuffer->DataLength());
     568             : 
     569           1 :     return bufReader.Read32(&BlockCounter).Read64(&BytesToSkip).StatusCode();
     570             : }
     571             : 
     572           1 : size_t BlockQueryWithSkip::MessageSize() const
     573             : {
     574           1 :     BufferWriter emptyBuf(nullptr, 0);
     575           1 :     return WriteToBuffer(emptyBuf).Needed();
     576             : }
     577             : 
     578           1 : bool BlockQueryWithSkip::operator==(const BlockQueryWithSkip & another) const
     579             : {
     580           1 :     return (BlockCounter == another.BlockCounter && BytesToSkip == another.BytesToSkip);
     581             : }
     582             : 
     583             : #if CHIP_AUTOMATION_LOGGING
     584           0 : void BlockQueryWithSkip::LogMessage(bdx::MessageType messageType) const
     585             : {
     586           0 :     ChipLogAutomation("BlockQueryWithSkip");
     587           0 :     ChipLogAutomation("  Block Counter: %" PRIu32, BlockCounter);
     588           0 :     ChipLogAutomation("  Bytes To Skip: 0x" ChipLogFormatX64, ChipLogValueX64(BytesToSkip));
     589           0 : }
     590             : #endif // CHIP_AUTOMATION_LOGGING

Generated by: LCOV version 1.14