Matter SDK Coverage Report
Current view: top level - lib/dnssd - ServiceNaming.cpp (source / functions) Coverage Total Hit
Test: SHA:e021a368d10ac6f3f201c101585146211fdcdaa2 Lines: 88.8 % 89 79
Test Date: 2026-02-13 08:13:38 Functions: 100.0 % 5 5

            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 "ServiceNaming.h"
      19              : 
      20              : #include <lib/core/CHIPEncoding.h>
      21              : #include <lib/support/BytesToHex.h>
      22              : #include <lib/support/CodeUtils.h>
      23              : #include <lib/support/StringBuilder.h>
      24              : 
      25              : #include <cstdio>
      26              : #include <inttypes.h>
      27              : #include <string.h>
      28              : 
      29              : namespace chip {
      30              : namespace Dnssd {
      31              : 
      32           45 : CHIP_ERROR MakeInstanceName(char * buffer, size_t bufferLen, const PeerId & peerId)
      33              : {
      34           45 :     VerifyOrReturnError(bufferLen > Operational::kInstanceNameMaxLength, CHIP_ERROR_BUFFER_TOO_SMALL);
      35              : 
      36           11 :     NodeId nodeId               = peerId.GetNodeId();
      37           11 :     CompressedFabricId fabricId = peerId.GetCompressedFabricId();
      38              : 
      39           11 :     uint32_t fabricIdHi = static_cast<uint32_t>(fabricId >> 32);
      40           11 :     uint32_t fabricIdLo = static_cast<uint32_t>(fabricId);
      41           11 :     uint32_t nodeIdHi   = static_cast<uint32_t>(nodeId >> 32);
      42           11 :     uint32_t nodeIdLo   = static_cast<uint32_t>(nodeId);
      43           11 :     StringBuilderBase builder(buffer, bufferLen);
      44           11 :     builder.AddFormat("%08" PRIX32 "%08" PRIX32 "-%08" PRIX32 "%08" PRIX32, fabricIdHi, fabricIdLo, nodeIdHi, nodeIdLo);
      45              : 
      46           11 :     VerifyOrReturnError(builder.Fit(), CHIP_ERROR_BUFFER_TOO_SMALL);
      47           11 :     return CHIP_NO_ERROR;
      48              : }
      49              : 
      50           19 : CHIP_ERROR ExtractIdFromInstanceName(const char * name, PeerId * peerId)
      51              : {
      52           19 :     VerifyOrReturnError(name != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
      53           17 :     VerifyOrReturnError(peerId != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
      54              : 
      55              :     // Make sure the string is long enough.
      56              :     static constexpr size_t fabricIdByteLength   = 8;
      57              :     static constexpr size_t fabricIdStringLength = fabricIdByteLength * 2;
      58              :     static constexpr size_t nodeIdByteLength     = 8;
      59              :     static constexpr size_t nodeIdStringLength   = nodeIdByteLength * 2;
      60              :     static constexpr size_t totalLength          = fabricIdStringLength + nodeIdStringLength + 1; // +1 for '-'
      61              : 
      62              :     // Ensure we have at least totalLength chars.
      63           16 :     size_t len = strnlen(name, totalLength);
      64           16 :     VerifyOrReturnError(len >= totalLength, CHIP_ERROR_INVALID_ARGUMENT);
      65              : 
      66              :     // Check that we have a proper terminator.
      67           12 :     VerifyOrReturnError(name[totalLength] == '\0' || name[totalLength] == '.', CHIP_ERROR_WRONG_NODE_ID);
      68              : 
      69              :     // Check what we have a separator where we expect.
      70           10 :     VerifyOrReturnError(name[fabricIdStringLength] == '-', CHIP_ERROR_WRONG_NODE_ID);
      71              : 
      72              :     static constexpr size_t bufferSize = std::max(fabricIdByteLength, nodeIdByteLength);
      73              :     uint8_t buf[bufferSize];
      74              : 
      75            5 :     VerifyOrReturnError(Encoding::HexToBytes(name, fabricIdStringLength, buf, bufferSize) != 0, CHIP_ERROR_WRONG_NODE_ID);
      76              :     // Buf now stores the fabric id, as big-endian bytes.
      77              :     static_assert(fabricIdByteLength == sizeof(uint64_t), "Wrong number of bytes");
      78            4 :     peerId->SetCompressedFabricId(Encoding::BigEndian::Get64(buf));
      79              : 
      80            4 :     VerifyOrReturnError(Encoding::HexToBytes(name + fabricIdStringLength + 1, nodeIdStringLength, buf, bufferSize) != 0,
      81              :                         CHIP_ERROR_WRONG_NODE_ID);
      82              :     // Buf now stores the node id id, as big-endian bytes.
      83              :     static_assert(nodeIdByteLength == sizeof(uint64_t), "Wrong number of bytes");
      84            4 :     peerId->SetNodeId(Encoding::BigEndian::Get64(buf));
      85              : 
      86            4 :     return CHIP_NO_ERROR;
      87              : }
      88              : 
      89           22 : CHIP_ERROR MakeHostName(char * buffer, size_t bufferLen, const chip::ByteSpan & macOrEui64)
      90              : {
      91           22 :     VerifyOrReturnError(bufferLen >= macOrEui64.size() * 2 + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
      92              : 
      93           22 :     int idx = 0;
      94          178 :     for (size_t i = 0; i < macOrEui64.size(); ++i)
      95              :     {
      96          156 :         idx += snprintf(buffer + idx, 3, "%02X", macOrEui64.data()[i]);
      97              :     }
      98           22 :     return CHIP_NO_ERROR;
      99              : }
     100              : 
     101           92 : CHIP_ERROR MakeServiceSubtype(char * buffer, size_t bufferLen, DiscoveryFilter subtype)
     102              : {
     103              :     int requiredSize;
     104           92 :     switch (subtype.type)
     105              :     {
     106           20 :     case DiscoveryFilterType::kShortDiscriminator:
     107              :         // 4-bit number
     108           20 :         if (subtype.code >= 1 << 4)
     109              :         {
     110            2 :             return CHIP_ERROR_INVALID_ARGUMENT;
     111              :         }
     112           18 :         requiredSize = snprintf(buffer, bufferLen, "_S%u", static_cast<uint16_t>(subtype.code));
     113           18 :         break;
     114           20 :     case DiscoveryFilterType::kLongDiscriminator:
     115              :         // 12-bit number
     116           20 :         if (subtype.code >= 1 << 12)
     117              :         {
     118            2 :             return CHIP_ERROR_INVALID_ARGUMENT;
     119              :         }
     120           18 :         requiredSize = snprintf(buffer, bufferLen, "_L%u", static_cast<uint16_t>(subtype.code));
     121           18 :         break;
     122           19 :     case DiscoveryFilterType::kVendorId:
     123           19 :         if (subtype.code >= 1 << 16)
     124              :         {
     125            2 :             return CHIP_ERROR_INVALID_ARGUMENT;
     126              :         }
     127           17 :         requiredSize = snprintf(buffer, bufferLen, "_V%u", static_cast<uint16_t>(subtype.code));
     128           17 :         break;
     129            5 :     case DiscoveryFilterType::kDeviceType:
     130            5 :         requiredSize = snprintf(buffer, bufferLen, "_T%" PRIu32, static_cast<uint32_t>(subtype.code));
     131            5 :         break;
     132           16 :     case DiscoveryFilterType::kCommissioningMode:
     133           16 :         requiredSize = snprintf(buffer, bufferLen, "_CM");
     134           16 :         break;
     135            0 :     case DiscoveryFilterType::kCommissioner:
     136            0 :         if (subtype.code > 1)
     137              :         {
     138            0 :             return CHIP_ERROR_INVALID_ARGUMENT;
     139              :         }
     140            0 :         requiredSize = snprintf(buffer, bufferLen, "_D%u", static_cast<uint16_t>(subtype.code));
     141            0 :         break;
     142           10 :     case DiscoveryFilterType::kCompressedFabricId:
     143           10 :         requiredSize = snprintf(buffer, bufferLen, "_I");
     144           20 :         return Encoding::Uint64ToHex(subtype.code, &buffer[requiredSize], bufferLen - static_cast<size_t>(requiredSize),
     145           10 :                                      Encoding::HexFlags::kUppercaseAndNullTerminate);
     146              :         break;
     147            1 :     case DiscoveryFilterType::kInstanceName:
     148            1 :         requiredSize = snprintf(buffer, bufferLen, "%s", subtype.instanceName);
     149            1 :         break;
     150            1 :     case DiscoveryFilterType::kNone:
     151            1 :         requiredSize = 0;
     152            1 :         buffer[0]    = '\0';
     153            1 :         break;
     154              :     }
     155           76 :     return (static_cast<size_t>(requiredSize) <= (bufferLen - 1)) ? CHIP_NO_ERROR : CHIP_ERROR_NO_MEMORY;
     156              : }
     157              : 
     158           17 : CHIP_ERROR MakeServiceTypeName(char * buffer, size_t bufferLen, DiscoveryFilter nameDesc, DiscoveryType type)
     159              : {
     160              :     int requiredSize;
     161           17 :     if (nameDesc.type == DiscoveryFilterType::kNone)
     162              :     {
     163            4 :         if (type == DiscoveryType::kCommissionableNode)
     164              :         {
     165            3 :             requiredSize = snprintf(buffer, bufferLen, kCommissionableServiceName);
     166              :         }
     167            1 :         else if (type == DiscoveryType::kCommissionerNode)
     168              :         {
     169            1 :             requiredSize = snprintf(buffer, bufferLen, kCommissionerServiceName);
     170              :         }
     171            0 :         else if (type == DiscoveryType::kOperational)
     172              :         {
     173            0 :             requiredSize = snprintf(buffer, bufferLen, kOperationalServiceName);
     174              :         }
     175              :         else
     176              :         {
     177            0 :             return CHIP_ERROR_NOT_IMPLEMENTED;
     178              :         }
     179              :     }
     180              :     else
     181              :     {
     182           13 :         ReturnErrorOnFailure(MakeServiceSubtype(buffer, bufferLen, nameDesc));
     183           10 :         size_t subtypeLen = strlen(buffer);
     184           10 :         if (type == DiscoveryType::kCommissionableNode)
     185              :         {
     186            9 :             requiredSize = snprintf(buffer + subtypeLen, bufferLen - subtypeLen, ".%s.%s", kSubtypeServiceNamePart,
     187              :                                     kCommissionableServiceName);
     188              :         }
     189            1 :         else if (type == DiscoveryType::kCommissionerNode)
     190              :         {
     191              :             requiredSize =
     192            0 :                 snprintf(buffer + subtypeLen, bufferLen - subtypeLen, ".%s.%s", kSubtypeServiceNamePart, kCommissionerServiceName);
     193              :         }
     194            1 :         else if (type == DiscoveryType::kOperational)
     195              :         {
     196              :             requiredSize =
     197            1 :                 snprintf(buffer + subtypeLen, bufferLen - subtypeLen, ".%s.%s", kSubtypeServiceNamePart, kOperationalServiceName);
     198              :         }
     199              :         else
     200              :         {
     201            0 :             return CHIP_ERROR_NOT_IMPLEMENTED;
     202              :         }
     203              :     }
     204              : 
     205           14 :     return (static_cast<size_t>(requiredSize) <= (bufferLen - 1)) ? CHIP_NO_ERROR : CHIP_ERROR_NO_MEMORY;
     206              : }
     207              : 
     208              : } // namespace Dnssd
     209              : } // namespace chip
        

Generated by: LCOV version 2.0-1