Matter SDK Coverage Report
Current view: top level - lib/support - ThreadOperationalDataset.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 83.3 % 258 215
Test Date: 2025-01-17 19:00:11 Functions: 82.7 % 52 43

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2021 Project CHIP Authors
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : 
      18              : #include <lib/support/ThreadOperationalDataset.h>
      19              : 
      20              : #include <lib/core/CHIPEncoding.h>
      21              : 
      22              : #include <cassert>
      23              : #include <cstring>
      24              : 
      25              : namespace chip {
      26              : namespace Thread {
      27              : 
      28              : /**
      29              :  * Thread Operational Dataset TLV is defined in Thread Specification as the following format:
      30              :  *
      31              :  * +---------+---------+-------------------------+
      32              :  * | uint8_t | uint8_t | network byte order data |
      33              :  * | 1 byte  | 1 byte  | n byte (0 <= n < 255)   |
      34              :  * +---------+---------+-------------------------+
      35              :  * |  Type   | Length  | Value                   |
      36              :  * +---------+---------+-------------------------+
      37              :  *
      38              :  */
      39              : class ThreadTLV final
      40              : {
      41              :     static constexpr uint8_t kLengthEscape = 0xff; ///< This length value indicates the actual length is of two-bytes length, which
      42              :                                                    ///< is not allowed in Thread Operational Dataset TLVs.
      43              : 
      44              : public:
      45              :     static constexpr uint8_t kMaxLength = kLengthEscape - 1;
      46              : 
      47              :     enum : uint8_t
      48              :     {
      49              :         kChannel         = 0,
      50              :         kPanId           = 1,
      51              :         kExtendedPanId   = 2,
      52              :         kNetworkName     = 3,
      53              :         kPSKc            = 4,
      54              :         kMasterKey       = 5,
      55              :         kMeshLocalPrefix = 7,
      56              :         kSecurityPolicy  = 12,
      57              :         kActiveTimestamp = 14,
      58              :         kDelayTimer      = 52,
      59              :         kChannelMask     = 53,
      60              :     };
      61              : 
      62           31 :     uint8_t GetSize() const { return static_cast<uint8_t>(sizeof(*this) + GetLength()); }
      63              : 
      64          150 :     uint8_t GetType() const { return mType; }
      65              : 
      66           19 :     void SetType(uint8_t aType) { mType = aType; }
      67              : 
      68          236 :     uint8_t GetLength() const
      69              :     {
      70          236 :         assert(mLength != kLengthEscape);
      71          236 :         return mLength;
      72              :     }
      73              : 
      74           19 :     void SetLength(uint8_t aLength)
      75              :     {
      76           19 :         assert(mLength != kLengthEscape);
      77           19 :         mLength = aLength;
      78           19 :     }
      79              : 
      80          180 :     const uint8_t * GetValue() const
      81              :     {
      82          180 :         assert(mLength != kLengthEscape);
      83              : 
      84              :         static_assert(sizeof(*this) == sizeof(ThreadTLV::mType) + sizeof(ThreadTLV::mLength), "Wrong size for ThreadTLV header");
      85              : 
      86          180 :         return reinterpret_cast<const uint8_t *>(this) + sizeof(*this);
      87              :     }
      88              : 
      89           22 :     uint8_t * GetValue() { return const_cast<uint8_t *>(const_cast<const ThreadTLV *>(this)->GetValue()); }
      90              : 
      91            4 :     ByteSpan GetValueAsSpan() const { return ByteSpan(static_cast<const uint8_t *>(GetValue()), GetLength()); }
      92              : 
      93            2 :     void Get64(uint64_t & aValue) const
      94              :     {
      95            2 :         assert(GetLength() >= sizeof(aValue));
      96            2 :         aValue = Encoding::BigEndian::Get64(GetValue());
      97            2 :     }
      98              : 
      99            1 :     void Get32(uint32_t & aValue) const
     100              :     {
     101            1 :         assert(GetLength() >= sizeof(aValue));
     102            1 :         aValue = Encoding::BigEndian::Get32(GetValue());
     103            1 :     }
     104              : 
     105            2 :     void Get16(uint16_t & aValue) const
     106              :     {
     107            2 :         assert(GetLength() >= sizeof(aValue));
     108            2 :         aValue = Encoding::BigEndian::Get16(GetValue());
     109            2 :     }
     110              : 
     111            2 :     void Set64(uint64_t aValue)
     112              :     {
     113            2 :         SetLength(sizeof(aValue));
     114            2 :         Encoding::BigEndian::Put64(GetValue(), aValue);
     115            2 :     }
     116              : 
     117            0 :     void Set32(uint32_t aValue)
     118              :     {
     119            0 :         SetLength(sizeof(aValue));
     120            0 :         Encoding::BigEndian::Put32(GetValue(), aValue);
     121            0 :     }
     122              : 
     123            2 :     void Set16(uint16_t aValue)
     124              :     {
     125            2 :         SetLength(sizeof(aValue));
     126            2 :         Encoding::BigEndian::Put16(GetValue(), aValue);
     127            2 :     }
     128              : 
     129           15 :     void SetValue(const void * aValue, uint8_t aLength)
     130              :     {
     131           15 :         SetLength(aLength);
     132           15 :         memcpy(GetValue(), aValue, aLength);
     133           15 :     }
     134              : 
     135            0 :     void SetValue(const ByteSpan & aValue) { SetValue(aValue.data(), static_cast<uint8_t>(aValue.size())); }
     136              : 
     137          139 :     const ThreadTLV * GetNext() const
     138              :     {
     139              :         static_assert(alignof(ThreadTLV) == 1, "Wrong alignment for ThreadTLV header");
     140          139 :         return reinterpret_cast<const ThreadTLV *>(static_cast<const uint8_t *>(GetValue()) + GetLength());
     141              :     }
     142              : 
     143            3 :     ThreadTLV * GetNext() { return reinterpret_cast<ThreadTLV *>(static_cast<uint8_t *>(GetValue()) + GetLength()); }
     144              : 
     145            4 :     static bool IsValid(ByteSpan aData)
     146              :     {
     147            4 :         const uint8_t * const end = aData.data() + aData.size();
     148            4 :         const uint8_t * curr      = aData.data();
     149              : 
     150           25 :         while (curr + sizeof(ThreadTLV) < end)
     151              :         {
     152           21 :             const ThreadTLV * tlv = reinterpret_cast<const ThreadTLV *>(curr);
     153              : 
     154           21 :             if (tlv->GetLength() == kLengthEscape)
     155              :             {
     156            0 :                 break;
     157              :             }
     158              : 
     159           21 :             curr = reinterpret_cast<const uint8_t *>(tlv->GetNext());
     160              :         }
     161              : 
     162            4 :         return curr == end;
     163              :     }
     164              : 
     165              : private:
     166              :     uint8_t mType;
     167              :     uint8_t mLength;
     168              : };
     169              : 
     170            0 : bool OperationalDataset::IsValid(ByteSpan aData)
     171              : {
     172            0 :     return ThreadTLV::IsValid(aData);
     173              : }
     174              : 
     175            6 : CHIP_ERROR OperationalDataset::Init(ByteSpan aData)
     176              : {
     177            6 :     if (aData.size() > sizeof(mData))
     178              :     {
     179            1 :         return CHIP_ERROR_INVALID_ARGUMENT;
     180              :     }
     181              : 
     182            5 :     if (aData.size() > 0)
     183              :     {
     184            4 :         if (!ThreadTLV::IsValid(aData))
     185              :         {
     186            2 :             return CHIP_ERROR_INVALID_ARGUMENT;
     187              :         }
     188              : 
     189            2 :         memcpy(mData, aData.data(), aData.size());
     190              :     }
     191              : 
     192            3 :     mLength = static_cast<uint8_t>(aData.size());
     193            3 :     return CHIP_NO_ERROR;
     194              : }
     195              : 
     196            4 : CHIP_ERROR OperationalDataset::GetActiveTimestamp(uint64_t & aActiveTimestamp) const
     197              : {
     198            4 :     const ThreadTLV * tlv = Locate(ThreadTLV::kActiveTimestamp);
     199            4 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
     200            3 :     VerifyOrReturnError(tlv->GetLength() == sizeof(aActiveTimestamp), CHIP_ERROR_INVALID_TLV_ELEMENT);
     201            2 :     tlv->Get64(aActiveTimestamp);
     202            2 :     return CHIP_NO_ERROR;
     203              : }
     204              : 
     205            2 : CHIP_ERROR OperationalDataset::SetActiveTimestamp(uint64_t aActiveTimestamp)
     206              : {
     207            2 :     ThreadTLV * tlv = MakeRoom(ThreadTLV::kActiveTimestamp, sizeof(*tlv) + sizeof(aActiveTimestamp));
     208            2 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
     209              : 
     210            2 :     tlv->Set64(aActiveTimestamp);
     211              : 
     212            2 :     mLength = static_cast<uint8_t>(mLength + tlv->GetSize());
     213              : 
     214            2 :     return CHIP_NO_ERROR;
     215              : }
     216              : 
     217            4 : CHIP_ERROR OperationalDataset::GetChannel(uint16_t & aChannel) const
     218              : {
     219            4 :     const ThreadTLV * tlv = Locate(ThreadTLV::kChannel);
     220            4 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
     221            3 :     VerifyOrReturnError(tlv->GetLength() == 3, CHIP_ERROR_INVALID_TLV_ELEMENT);
     222              :     // Note: The channel page (byte 0) is not returned
     223            2 :     const uint8_t * value = tlv->GetValue();
     224            2 :     aChannel              = static_cast<uint16_t>((value[1] << 8) | value[2]);
     225            2 :     return CHIP_NO_ERROR;
     226              : }
     227              : 
     228            2 : CHIP_ERROR OperationalDataset::SetChannel(uint16_t aChannel)
     229              : {
     230            2 :     uint8_t value[] = { 0, static_cast<uint8_t>(aChannel >> 8), static_cast<uint8_t>(aChannel & 0xff) };
     231            2 :     ThreadTLV * tlv = MakeRoom(ThreadTLV::kChannel, sizeof(*tlv) + sizeof(value));
     232            2 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
     233              : 
     234            2 :     tlv->SetValue(value, sizeof(value));
     235              : 
     236            2 :     mLength = static_cast<uint8_t>(mLength + tlv->GetSize());
     237              : 
     238            2 :     return CHIP_NO_ERROR;
     239              : }
     240              : 
     241            3 : CHIP_ERROR OperationalDataset::GetExtendedPanId(uint8_t (&aExtendedPanId)[kSizeExtendedPanId]) const
     242              : {
     243            3 :     ByteSpan extPanIdSpan;
     244            3 :     ReturnErrorOnFailure(GetExtendedPanIdAsByteSpan(extPanIdSpan));
     245            2 :     memcpy(aExtendedPanId, extPanIdSpan.data(), extPanIdSpan.size());
     246            2 :     return CHIP_NO_ERROR;
     247              : }
     248              : 
     249            0 : CHIP_ERROR OperationalDataset::GetExtendedPanId(uint64_t & extendedPanId) const
     250              : {
     251            0 :     ByteSpan extPanIdSpan;
     252            0 :     ReturnErrorOnFailure(GetExtendedPanIdAsByteSpan(extPanIdSpan));
     253            0 :     VerifyOrDie(extPanIdSpan.size() == sizeof(extendedPanId));
     254            0 :     extendedPanId = Encoding::BigEndian::Get64(extPanIdSpan.data());
     255            0 :     return CHIP_NO_ERROR;
     256              : }
     257              : 
     258            5 : CHIP_ERROR OperationalDataset::GetExtendedPanIdAsByteSpan(ByteSpan & span) const
     259              : {
     260            5 :     const ThreadTLV * tlv = Locate(ThreadTLV::kExtendedPanId);
     261            5 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
     262            4 :     VerifyOrReturnError(tlv->GetLength() == kSizeExtendedPanId, CHIP_ERROR_INVALID_TLV_ELEMENT);
     263            3 :     span = tlv->GetValueAsSpan();
     264            3 :     return CHIP_NO_ERROR;
     265              : }
     266              : 
     267            2 : CHIP_ERROR OperationalDataset::SetExtendedPanId(const uint8_t (&aExtendedPanId)[kSizeExtendedPanId])
     268              : {
     269            2 :     ThreadTLV * tlv = MakeRoom(ThreadTLV::kExtendedPanId, sizeof(*tlv) + sizeof(aExtendedPanId));
     270            2 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
     271              : 
     272            2 :     tlv->SetValue(aExtendedPanId, sizeof(aExtendedPanId));
     273              : 
     274            2 :     assert(mLength + tlv->GetSize() <= sizeof(mData));
     275              : 
     276            2 :     mLength = static_cast<uint8_t>(mLength + tlv->GetSize());
     277              : 
     278            2 :     return CHIP_NO_ERROR;
     279              : }
     280              : 
     281            5 : CHIP_ERROR OperationalDataset::GetMasterKey(uint8_t (&aMasterKey)[kSizeMasterKey]) const
     282              : {
     283            5 :     const ThreadTLV * tlv = Locate(ThreadTLV::kMasterKey);
     284            5 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
     285            3 :     VerifyOrReturnError(tlv->GetLength() == sizeof(aMasterKey), CHIP_ERROR_INVALID_TLV_ELEMENT);
     286            2 :     memcpy(aMasterKey, tlv->GetValue(), sizeof(aMasterKey));
     287            2 :     return CHIP_NO_ERROR;
     288              : }
     289              : 
     290            3 : CHIP_ERROR OperationalDataset::SetMasterKey(const uint8_t (&aMasterKey)[kSizeMasterKey])
     291              : {
     292            3 :     ThreadTLV * tlv = MakeRoom(ThreadTLV::kMasterKey, sizeof(*tlv) + sizeof(aMasterKey));
     293            3 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
     294              : 
     295            3 :     tlv->SetValue(aMasterKey, sizeof(aMasterKey));
     296              : 
     297            3 :     assert(mLength + tlv->GetSize() <= sizeof(mData));
     298              : 
     299            3 :     mLength = static_cast<uint8_t>(mLength + tlv->GetSize());
     300              : 
     301            3 :     return CHIP_NO_ERROR;
     302              : }
     303              : 
     304            4 : CHIP_ERROR OperationalDataset::GetMeshLocalPrefix(uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix]) const
     305              : {
     306            4 :     const ThreadTLV * tlv = Locate(ThreadTLV::kMeshLocalPrefix);
     307            4 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
     308            3 :     VerifyOrReturnError(tlv->GetLength() == sizeof(aMeshLocalPrefix), CHIP_ERROR_INVALID_TLV_ELEMENT);
     309            2 :     memcpy(aMeshLocalPrefix, tlv->GetValue(), sizeof(aMeshLocalPrefix));
     310            2 :     return CHIP_NO_ERROR;
     311              : }
     312              : 
     313            2 : CHIP_ERROR OperationalDataset::SetMeshLocalPrefix(const uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix])
     314              : {
     315            2 :     ThreadTLV * tlv = MakeRoom(ThreadTLV::kMeshLocalPrefix, sizeof(*tlv) + sizeof(aMeshLocalPrefix));
     316            2 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
     317              : 
     318            2 :     tlv->SetValue(aMeshLocalPrefix, sizeof(aMeshLocalPrefix));
     319              : 
     320            2 :     mLength = static_cast<uint8_t>(mLength + tlv->GetSize());
     321              : 
     322            2 :     return CHIP_NO_ERROR;
     323              : }
     324              : 
     325            4 : CHIP_ERROR OperationalDataset::GetNetworkName(char (&aNetworkName)[kSizeNetworkName + 1]) const
     326              : {
     327            4 :     const ThreadTLV * tlv = Locate(ThreadTLV::kNetworkName);
     328            4 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
     329            3 :     VerifyOrReturnError(tlv->GetLength() <= kSizeNetworkName, CHIP_ERROR_INVALID_TLV_ELEMENT);
     330            2 :     memcpy(aNetworkName, tlv->GetValue(), tlv->GetLength());
     331            2 :     aNetworkName[tlv->GetLength()] = '\0';
     332            2 :     return CHIP_NO_ERROR;
     333              : }
     334              : 
     335            6 : CHIP_ERROR OperationalDataset::SetNetworkName(const char * aNetworkName)
     336              : {
     337            6 :     VerifyOrReturnError(aNetworkName != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     338            5 :     size_t len = strlen(aNetworkName);
     339            5 :     VerifyOrReturnError(0 < len && len <= kSizeNetworkName, CHIP_ERROR_INVALID_STRING_LENGTH);
     340              : 
     341            3 :     ThreadTLV * tlv = MakeRoom(ThreadTLV::kNetworkName, sizeof(*tlv) + len);
     342            3 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
     343              : 
     344            3 :     tlv->SetValue(aNetworkName, static_cast<uint8_t>(len));
     345              : 
     346            3 :     mLength = static_cast<uint8_t>(mLength + tlv->GetSize());
     347              : 
     348            3 :     return CHIP_NO_ERROR;
     349              : }
     350              : 
     351            4 : CHIP_ERROR OperationalDataset::GetPanId(uint16_t & aPanId) const
     352              : {
     353            4 :     const ThreadTLV * tlv = Locate(ThreadTLV::kPanId);
     354            4 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
     355            3 :     VerifyOrReturnError(tlv->GetLength() == sizeof(aPanId), CHIP_ERROR_INVALID_TLV_ELEMENT);
     356            2 :     tlv->Get16(aPanId);
     357            2 :     return CHIP_NO_ERROR;
     358              : }
     359              : 
     360            2 : CHIP_ERROR OperationalDataset::SetPanId(uint16_t aPanId)
     361              : {
     362            2 :     ThreadTLV * tlv = MakeRoom(ThreadTLV::kPanId, sizeof(*tlv) + sizeof(aPanId));
     363            2 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
     364              : 
     365            2 :     tlv->Set16(aPanId);
     366              : 
     367            2 :     mLength = static_cast<uint8_t>(mLength + tlv->GetSize());
     368              : 
     369            2 :     return CHIP_NO_ERROR;
     370              : }
     371              : 
     372            5 : CHIP_ERROR OperationalDataset::GetPSKc(uint8_t (&aPSKc)[kSizePSKc]) const
     373              : {
     374            5 :     const ThreadTLV * tlv = Locate(ThreadTLV::kPSKc);
     375            5 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
     376            3 :     VerifyOrReturnError(tlv->GetLength() == sizeof(aPSKc), CHIP_ERROR_INVALID_TLV_ELEMENT);
     377            2 :     memcpy(aPSKc, tlv->GetValue(), sizeof(aPSKc));
     378            2 :     return CHIP_NO_ERROR;
     379              : }
     380              : 
     381            3 : CHIP_ERROR OperationalDataset::SetPSKc(const uint8_t (&aPSKc)[kSizePSKc])
     382              : {
     383            3 :     ThreadTLV * tlv = MakeRoom(ThreadTLV::kPSKc, sizeof(*tlv) + sizeof(aPSKc));
     384            3 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
     385              : 
     386            3 :     tlv->SetValue(aPSKc, sizeof(aPSKc));
     387              : 
     388            3 :     mLength = static_cast<uint8_t>(mLength + tlv->GetSize());
     389              : 
     390            3 :     return CHIP_NO_ERROR;
     391              : }
     392              : 
     393            2 : CHIP_ERROR OperationalDataset::GetChannelMask(ByteSpan & aChannelMask) const
     394              : {
     395            2 :     const ThreadTLV * tlv = Locate(ThreadTLV::kChannelMask);
     396            2 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
     397            2 :     VerifyOrReturnError(tlv->GetLength() > 0, CHIP_ERROR_INVALID_TLV_ELEMENT);
     398            1 :     aChannelMask = tlv->GetValueAsSpan();
     399            1 :     return CHIP_NO_ERROR;
     400              : }
     401              : 
     402            0 : CHIP_ERROR OperationalDataset::SetChannelMask(ByteSpan aChannelMask)
     403              : {
     404            0 :     VerifyOrReturnError(0 < aChannelMask.size() && aChannelMask.size() < ThreadTLV::kMaxLength, CHIP_ERROR_INVALID_ARGUMENT);
     405            0 :     ThreadTLV * tlv = MakeRoom(ThreadTLV::kChannelMask, sizeof(*tlv) + aChannelMask.size());
     406            0 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
     407            0 :     tlv->SetValue(aChannelMask);
     408            0 :     mLength = static_cast<uint8_t>(mLength + tlv->GetSize());
     409            0 :     return CHIP_NO_ERROR;
     410              : }
     411              : 
     412            2 : CHIP_ERROR OperationalDataset::GetSecurityPolicy(uint32_t & aSecurityPolicy) const
     413              : {
     414            2 :     const ThreadTLV * tlv = Locate(ThreadTLV::kSecurityPolicy);
     415            2 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
     416            2 :     VerifyOrReturnError(tlv->GetLength() == sizeof(aSecurityPolicy), CHIP_ERROR_INVALID_TLV_ELEMENT);
     417            1 :     tlv->Get32(aSecurityPolicy);
     418            1 :     return CHIP_NO_ERROR;
     419              : }
     420              : 
     421            0 : CHIP_ERROR OperationalDataset::SetSecurityPolicy(uint32_t aSecurityPolicy)
     422              : {
     423            0 :     ThreadTLV * tlv = MakeRoom(ThreadTLV::kSecurityPolicy, sizeof(*tlv) + sizeof(aSecurityPolicy));
     424            0 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
     425            0 :     tlv->Set32(aSecurityPolicy);
     426            0 :     mLength = static_cast<uint8_t>(mLength + tlv->GetSize());
     427            0 :     return CHIP_NO_ERROR;
     428              : }
     429              : 
     430            0 : CHIP_ERROR OperationalDataset::GetDelayTimer(uint32_t & aDelayMillis) const
     431              : {
     432            0 :     const ThreadTLV * tlv = Locate(ThreadTLV::kDelayTimer);
     433            0 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
     434            0 :     VerifyOrReturnError(tlv->GetLength() == sizeof(aDelayMillis), CHIP_ERROR_INVALID_TLV_ELEMENT);
     435            0 :     tlv->Get32(aDelayMillis);
     436            0 :     return CHIP_NO_ERROR;
     437              : }
     438              : 
     439            0 : CHIP_ERROR OperationalDataset::SetDelayTimer(uint32_t aDelayMillis)
     440              : {
     441            0 :     ThreadTLV * tlv = MakeRoom(ThreadTLV::kDelayTimer, sizeof(*tlv) + sizeof(aDelayMillis));
     442            0 :     VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
     443            0 :     tlv->Set32(aDelayMillis);
     444            0 :     mLength = static_cast<uint8_t>(mLength + tlv->GetSize());
     445            0 :     return CHIP_NO_ERROR;
     446              : }
     447              : 
     448            1 : void OperationalDataset::UnsetMasterKey()
     449              : {
     450            1 :     Remove(ThreadTLV::kMasterKey);
     451            1 : }
     452              : 
     453            1 : void OperationalDataset::UnsetPSKc()
     454              : {
     455            1 :     Remove(ThreadTLV::kPSKc);
     456            1 : }
     457              : 
     458            0 : bool OperationalDataset::IsCommissioned() const
     459              : {
     460            0 :     return Has(ThreadTLV::kPanId) && Has(ThreadTLV::kMasterKey) && Has(ThreadTLV::kExtendedPanId) && Has(ThreadTLV::kChannel);
     461              : }
     462              : 
     463           60 : const ThreadTLV * OperationalDataset::Locate(uint8_t aType) const
     464              : {
     465           60 :     const ThreadTLV * tlv = &Begin();
     466           60 :     const ThreadTLV * end = &End();
     467              : 
     468          178 :     while (tlv < end)
     469              :     {
     470          150 :         if (tlv->GetType() == aType)
     471           32 :             break;
     472          118 :         tlv = tlv->GetNext();
     473              :     }
     474              : 
     475           60 :     assert(tlv < reinterpret_cast<const ThreadTLV *>(&mData[sizeof(mData)]));
     476              : 
     477           60 :     return tlv != end ? tlv : nullptr;
     478              : }
     479              : 
     480            3 : void OperationalDataset::Remove(ThreadTLV & aThreadTLV)
     481              : {
     482            3 :     uint8_t offset = static_cast<uint8_t>(reinterpret_cast<uint8_t *>(&aThreadTLV) - mData);
     483              : 
     484            3 :     if (offset < mLength && mLength >= (offset + aThreadTLV.GetSize()))
     485              :     {
     486            3 :         mLength = static_cast<uint8_t>(mLength - aThreadTLV.GetSize());
     487            3 :         memmove(&aThreadTLV, aThreadTLV.GetNext(), mLength - offset);
     488              :     }
     489            3 : }
     490              : 
     491            2 : void OperationalDataset::Remove(uint8_t aType)
     492              : {
     493            2 :     ThreadTLV * tlv = Locate(aType);
     494              : 
     495            2 :     if (tlv != nullptr)
     496              :     {
     497            2 :         Remove(*tlv);
     498              :     }
     499            2 : }
     500              : 
     501           19 : ThreadTLV * OperationalDataset::MakeRoom(uint8_t aType, size_t aSize)
     502              : {
     503           19 :     ThreadTLV * tlv = Locate(aType);
     504              : 
     505           19 :     size_t freeSpace = sizeof(mData) - mLength;
     506              : 
     507           19 :     if (tlv != nullptr)
     508              :     {
     509            1 :         if (freeSpace + tlv->GetSize() < aSize)
     510              :         {
     511            0 :             return nullptr;
     512              :         }
     513              : 
     514            1 :         Remove(*tlv);
     515              :     }
     516           18 :     else if (freeSpace < aSize)
     517              :     {
     518            0 :         return nullptr;
     519              :     }
     520              : 
     521           19 :     End().SetType(aType);
     522              : 
     523           19 :     return &End();
     524              : }
     525              : 
     526              : } // namespace Thread
     527              : } // namespace chip
        

Generated by: LCOV version 2.0-1