LCOV - code coverage report
Current view: top level - lib/core - TLVUpdater.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 112 112 100.0 %
Date: 2024-02-15 08:20:41 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4             :  *    Copyright (c) 2015-2017 Nest Labs, Inc.
       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             : #include <lib/core/TLVUpdater.h>
      19             : 
      20             : #include <stdint.h>
      21             : #include <string.h>
      22             : 
      23             : #include <lib/core/CHIPConfig.h>
      24             : #include <lib/core/CHIPError.h>
      25             : #include <lib/core/TLVCommon.h>
      26             : #include <lib/core/TLVReader.h>
      27             : #include <lib/core/TLVTags.h>
      28             : #include <lib/core/TLVTypes.h>
      29             : #include <lib/core/TLVWriter.h>
      30             : #include <lib/support/BufferWriter.h>
      31             : #include <lib/support/CodeUtils.h>
      32             : #include <lib/support/logging/Constants.h>
      33             : #include <lib/support/logging/TextOnlyLogging.h>
      34             : 
      35             : namespace chip {
      36             : namespace TLV {
      37             : 
      38             : using namespace chip::Encoding;
      39             : 
      40           4 : CHIP_ERROR TLVUpdater::Init(uint8_t * buf, uint32_t dataLen, uint32_t maxLen)
      41             : {
      42             :     uint32_t freeLen;
      43             : 
      44           4 :     VerifyOrReturnError(buf != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
      45             : 
      46           4 :     VerifyOrReturnError(maxLen >= dataLen, CHIP_ERROR_BUFFER_TOO_SMALL);
      47             : 
      48             :     // memmove the buffer data to end of the buffer
      49           4 :     freeLen = maxLen - dataLen;
      50           4 :     memmove(buf + freeLen, buf, dataLen);
      51             : 
      52             :     // Init reader
      53           4 :     mUpdaterReader.Init(buf + freeLen, dataLen);
      54             : 
      55             :     // Init writer
      56           4 :     mUpdaterWriter.Init(buf, freeLen);
      57           4 :     mUpdaterWriter.SetCloseContainerReserved(false);
      58           4 :     mElementStartAddr = buf + freeLen;
      59             : 
      60           4 :     return CHIP_NO_ERROR;
      61             : }
      62             : 
      63           2 : CHIP_ERROR TLVUpdater::Init(TLVReader & aReader, uint32_t freeLen)
      64             : {
      65           2 :     uint8_t * buf             = const_cast<uint8_t *>(aReader.GetReadPoint());
      66           2 :     uint32_t remainingDataLen = aReader.GetRemainingLength();
      67           2 :     uint32_t readDataLen      = aReader.GetLengthRead();
      68             : 
      69             :     // TLVUpdater does not support backing stores yet
      70           2 :     VerifyOrReturnError(aReader.mBackingStore == nullptr, CHIP_ERROR_NOT_IMPLEMENTED);
      71             : 
      72             :     // TLVReader should point to a non-NULL buffer
      73           2 :     VerifyOrReturnError(buf != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
      74             : 
      75             :     // If reader is already on an element, reset it to start of element
      76           2 :     if (aReader.ElementType() != TLVElementType::NotSpecified)
      77             :     {
      78             :         uint8_t elemHeadLen;
      79             : 
      80           2 :         ReturnErrorOnFailure(aReader.GetElementHeadLength(elemHeadLen));
      81             : 
      82           2 :         buf -= elemHeadLen;
      83           2 :         remainingDataLen += elemHeadLen;
      84           2 :         readDataLen -= elemHeadLen;
      85             :     }
      86             : 
      87             :     // memmove the buffer data to end of the buffer
      88           2 :     memmove(buf + freeLen, buf, remainingDataLen);
      89             : 
      90             :     // Initialize the internal reader object
      91           2 :     mUpdaterReader.mBackingStore  = nullptr;
      92           2 :     mUpdaterReader.mReadPoint     = buf + freeLen;
      93           2 :     mUpdaterReader.mBufEnd        = buf + freeLen + remainingDataLen;
      94           2 :     mUpdaterReader.mLenRead       = readDataLen;
      95           2 :     mUpdaterReader.mMaxLen        = aReader.mMaxLen;
      96           2 :     mUpdaterReader.mControlByte   = kTLVControlByte_NotSpecified;
      97           2 :     mUpdaterReader.mElemTag       = AnonymousTag();
      98           2 :     mUpdaterReader.mElemLenOrVal  = 0;
      99           2 :     mUpdaterReader.mContainerType = aReader.mContainerType;
     100           2 :     mUpdaterReader.SetContainerOpen(false);
     101             : 
     102           2 :     mUpdaterReader.ImplicitProfileId = aReader.ImplicitProfileId;
     103           2 :     mUpdaterReader.AppData           = aReader.AppData;
     104             : 
     105             :     // TODO(#30825): Need to ensure we use TLVWriter public API rather than touch the innards.
     106             : 
     107             :     // Initialize the internal writer object
     108           2 :     mUpdaterWriter.mBackingStore  = nullptr;
     109           2 :     mUpdaterWriter.mBufStart      = buf - readDataLen;
     110           2 :     mUpdaterWriter.mWritePoint    = buf;
     111           2 :     mUpdaterWriter.mRemainingLen  = freeLen;
     112           2 :     mUpdaterWriter.mLenWritten    = readDataLen;
     113           2 :     mUpdaterWriter.mMaxLen        = readDataLen + freeLen;
     114           2 :     mUpdaterWriter.mContainerType = aReader.mContainerType;
     115           2 :     mUpdaterWriter.SetContainerOpen(false);
     116           2 :     mUpdaterWriter.SetCloseContainerReserved(false);
     117             : 
     118           2 :     mUpdaterWriter.ImplicitProfileId     = aReader.ImplicitProfileId;
     119           2 :     mUpdaterWriter.mInitializationCookie = TLVWriter::kExpectedInitializationCookie;
     120             : 
     121             :     // Cache element start address for internal use
     122           2 :     mElementStartAddr = buf + freeLen;
     123             : 
     124             :     // Clear the input reader object before returning. The user can no longer
     125             :     // use the original TLVReader object anymore.
     126           2 :     aReader.Init(static_cast<const uint8_t *>(nullptr), 0);
     127             : 
     128           2 :     return CHIP_NO_ERROR;
     129             : }
     130             : 
     131           4 : void TLVUpdater::SetImplicitProfileId(uint32_t profileId)
     132             : {
     133           4 :     mUpdaterReader.ImplicitProfileId = profileId;
     134           4 :     mUpdaterWriter.ImplicitProfileId = profileId;
     135           4 : }
     136             : 
     137          23 : CHIP_ERROR TLVUpdater::Next()
     138             : {
     139             :     // Skip current element if the reader is already positioned on an element
     140          23 :     ReturnErrorOnFailure(mUpdaterReader.Skip());
     141             : 
     142          22 :     AdjustInternalWriterFreeSpace();
     143             : 
     144             :     // Move the reader to next element
     145          22 :     ReturnErrorOnFailure(mUpdaterReader.Next());
     146             : 
     147          14 :     return CHIP_NO_ERROR;
     148             : }
     149             : 
     150           6 : CHIP_ERROR TLVUpdater::Move()
     151             : {
     152           6 :     VerifyOrReturnError(mUpdaterWriter.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
     153             : 
     154             :     const uint8_t * elementEnd;
     155             :     uint32_t copyLen;
     156             : 
     157           6 :     VerifyOrReturnError(static_cast<TLVElementType>((mUpdaterReader.mControlByte & kTLVTypeMask)) != TLVElementType::EndOfContainer,
     158             :                         CHIP_END_OF_TLV);
     159             : 
     160           6 :     VerifyOrReturnError(mUpdaterReader.GetType() != kTLVType_NotSpecified, CHIP_ERROR_INVALID_TLV_ELEMENT);
     161             : 
     162             :     // Skip to the end of the element
     163           6 :     ReturnErrorOnFailure(mUpdaterReader.Skip());
     164             : 
     165           6 :     elementEnd = mUpdaterReader.mReadPoint;
     166             : 
     167           6 :     copyLen = static_cast<uint32_t>(elementEnd - mElementStartAddr);
     168             : 
     169             :     // Move the element to output TLV
     170           6 :     memmove(mUpdaterWriter.mWritePoint, mElementStartAddr, copyLen);
     171             : 
     172             :     // Adjust the updater state
     173           6 :     mElementStartAddr += copyLen;
     174           6 :     mUpdaterWriter.mWritePoint += copyLen;
     175           6 :     mUpdaterWriter.mLenWritten += copyLen;
     176           6 :     mUpdaterWriter.mMaxLen += copyLen;
     177             : 
     178           6 :     return CHIP_NO_ERROR;
     179             : }
     180             : 
     181           3 : void TLVUpdater::MoveUntilEnd()
     182             : {
     183           3 :     VerifyOrDie(mUpdaterWriter.IsInitialized());
     184             : 
     185           3 :     const uint8_t * buffEnd = mUpdaterReader.GetReadPoint() + mUpdaterReader.GetRemainingLength();
     186             : 
     187           3 :     uint32_t copyLen = static_cast<uint32_t>(buffEnd - mElementStartAddr);
     188             : 
     189             :     // Move all elements till end to output TLV
     190           3 :     memmove(mUpdaterWriter.mWritePoint, mElementStartAddr, copyLen);
     191             : 
     192             :     // TODO(#30825): Need to ensure public API is used rather than touching the innards.
     193             :     // Adjust the updater state
     194           3 :     mElementStartAddr += copyLen;
     195           3 :     mUpdaterWriter.mWritePoint += copyLen;
     196           3 :     mUpdaterWriter.mLenWritten += copyLen;
     197           3 :     mUpdaterWriter.mMaxLen += copyLen;
     198           3 :     mUpdaterWriter.mContainerType = kTLVType_NotSpecified;
     199           3 :     mUpdaterWriter.SetContainerOpen(false);
     200           3 :     mUpdaterWriter.SetCloseContainerReserved(false);
     201           3 :     mUpdaterReader.mReadPoint += copyLen;
     202           3 :     mUpdaterReader.mLenRead += copyLen;
     203           3 :     mUpdaterReader.mControlByte   = kTLVControlByte_NotSpecified;
     204           3 :     mUpdaterReader.mElemTag       = AnonymousTag();
     205           3 :     mUpdaterReader.mElemLenOrVal  = 0;
     206           3 :     mUpdaterReader.mContainerType = kTLVType_NotSpecified;
     207           3 :     mUpdaterReader.SetContainerOpen(false);
     208           3 : }
     209             : 
     210           3 : CHIP_ERROR TLVUpdater::EnterContainer(TLVType & outerContainerType)
     211             : {
     212           3 :     VerifyOrReturnError(mUpdaterWriter.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
     213             : 
     214             :     TLVType containerType;
     215             : 
     216           3 :     VerifyOrReturnError(TLVTypeIsContainer(static_cast<TLVType>(mUpdaterReader.mControlByte & kTLVTypeMask)),
     217             :                         CHIP_ERROR_INCORRECT_STATE);
     218             : 
     219             :     // Change the updater state
     220           3 :     AdjustInternalWriterFreeSpace();
     221             : 
     222           3 :     ReturnErrorOnFailure(mUpdaterWriter.StartContainer(mUpdaterReader.GetTag(), mUpdaterReader.GetType(), containerType));
     223             : 
     224           3 :     ReturnErrorOnFailure(mUpdaterReader.EnterContainer(containerType));
     225             : 
     226           3 :     outerContainerType = containerType;
     227             : 
     228           3 :     return CHIP_NO_ERROR;
     229             : }
     230             : 
     231           3 : CHIP_ERROR TLVUpdater::ExitContainer(TLVType outerContainerType)
     232             : {
     233           3 :     ReturnErrorOnFailure(mUpdaterReader.ExitContainer(outerContainerType));
     234             : 
     235             :     // Change the updater's state
     236           3 :     AdjustInternalWriterFreeSpace();
     237             : 
     238           3 :     ReturnErrorOnFailure(mUpdaterWriter.EndContainer(outerContainerType));
     239             : 
     240           3 :     return CHIP_NO_ERROR;
     241             : }
     242             : 
     243             : /**
     244             :  * This is a private method that adjusts the TLVUpdater's free space count by
     245             :  * accounting for the freespace from mElementStartAddr to current read point.
     246             :  */
     247          28 : void TLVUpdater::AdjustInternalWriterFreeSpace()
     248             : {
     249          28 :     VerifyOrDie(mUpdaterWriter.IsInitialized());
     250             : 
     251          28 :     const uint8_t * nextElementStart = mUpdaterReader.mReadPoint;
     252             : 
     253          28 :     if (nextElementStart != mElementStartAddr)
     254             :     {
     255             :         // Increase the internal writer's free space state variables
     256          11 :         uint32_t spaceIncrease = static_cast<uint32_t>(nextElementStart - mElementStartAddr);
     257          11 :         mUpdaterWriter.mRemainingLen += spaceIncrease;
     258          11 :         mUpdaterWriter.mMaxLen += spaceIncrease;
     259             : 
     260             :         // Cache the start address of the next element
     261          11 :         mElementStartAddr = nextElementStart;
     262             :     }
     263          28 : }
     264             : 
     265             : } // namespace TLV
     266             : } // namespace chip

Generated by: LCOV version 1.14