Matter SDK Coverage Report
Current view: top level - lib/dnssd - ServiceNaming.cpp (source / functions) Coverage Total Hit
Test: SHA:6c8f029dd2432dc900f1c9245c324e69bd79e40a Lines: 88.8 % 89 79
Test Date: 2026-08-08 07:40:09 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           23 : CHIP_ERROR MakeHostName(char * buffer, size_t bufferLen, const chip::ByteSpan & macOrEui64)
      90              : {
      91           23 :     VerifyOrReturnError(bufferLen >= macOrEui64.size() * 2 + 1, CHIP_ERROR_BUFFER_TOO_SMALL);
      92              : 
      93           23 :     int idx = 0;
      94          185 :     for (size_t i = 0; i < macOrEui64.size(); ++i)
      95              :     {
      96          162 :         idx += snprintf(buffer + idx, 3, "%02X", macOrEui64.data()[i]);
      97              :     }
      98           23 :     return CHIP_NO_ERROR;
      99              : }
     100              : 
     101           97 : CHIP_ERROR MakeServiceSubtype(char * buffer, size_t bufferLen, DiscoveryFilter subtype)
     102              : {
     103              :     int requiredSize;
     104           97 :     switch (subtype.type)
     105              :     {
     106           21 :     case DiscoveryFilterType::kShortDiscriminator:
     107              :         // 4-bit number
     108           21 :         if (subtype.code >= 1 << 4)
     109              :         {
     110            2 :             return CHIP_ERROR_INVALID_ARGUMENT;
     111              :         }
     112           19 :         requiredSize = snprintf(buffer, bufferLen, "_S%u", static_cast<uint16_t>(subtype.code));
     113           19 :         break;
     114           21 :     case DiscoveryFilterType::kLongDiscriminator:
     115              :         // 12-bit number
     116           21 :         if (subtype.code >= 1 << 12)
     117              :         {
     118            2 :             return CHIP_ERROR_INVALID_ARGUMENT;
     119              :         }
     120           19 :         requiredSize = snprintf(buffer, bufferLen, "_L%u", static_cast<uint16_t>(subtype.code));
     121           19 :         break;
     122           20 :     case DiscoveryFilterType::kVendorId:
     123           20 :         if (subtype.code >= 1 << 16)
     124              :         {
     125            2 :             return CHIP_ERROR_INVALID_ARGUMENT;
     126              :         }
     127           18 :         requiredSize = snprintf(buffer, bufferLen, "_V%u", static_cast<uint16_t>(subtype.code));
     128           18 :         break;
     129            5 :     case DiscoveryFilterType::kDeviceType:
     130            5 :         requiredSize = snprintf(buffer, bufferLen, "_T%" PRIu32, static_cast<uint32_t>(subtype.code));
     131            5 :         break;
     132           17 :     case DiscoveryFilterType::kCommissioningMode:
     133           17 :         requiredSize = snprintf(buffer, bufferLen, "_CM");
     134           17 :         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           11 :     case DiscoveryFilterType::kCompressedFabricId:
     143              :         // Make sure the "_I" prefix (2 chars + null) fits before writing it and offsetting past it;
     144              :         // Uint64ToHex validates that the remaining space holds the hex-encoded fabric id.
     145           11 :         VerifyOrReturnError(bufferLen >= 3, CHIP_ERROR_BUFFER_TOO_SMALL);
     146           10 :         strcpy(buffer, "_I");
     147           10 :         return Encoding::Uint64ToHex(subtype.code, &buffer[2], bufferLen - 2, Encoding::HexFlags::kUppercaseAndNullTerminate);
     148            1 :     case DiscoveryFilterType::kInstanceName:
     149            1 :         requiredSize = snprintf(buffer, bufferLen, "%s", subtype.instanceName);
     150            1 :         break;
     151            1 :     case DiscoveryFilterType::kNone:
     152            1 :         requiredSize = 0;
     153            1 :         buffer[0]    = '\0';
     154            1 :         break;
     155              :     }
     156           80 :     return (static_cast<size_t>(requiredSize) <= (bufferLen - 1)) ? CHIP_NO_ERROR : CHIP_ERROR_NO_MEMORY;
     157              : }
     158              : 
     159           17 : CHIP_ERROR MakeServiceTypeName(char * buffer, size_t bufferLen, DiscoveryFilter nameDesc, DiscoveryType type)
     160              : {
     161              :     int requiredSize;
     162           17 :     if (nameDesc.type == DiscoveryFilterType::kNone)
     163              :     {
     164            4 :         if (type == DiscoveryType::kCommissionableNode)
     165              :         {
     166            3 :             requiredSize = snprintf(buffer, bufferLen, kCommissionableServiceName);
     167              :         }
     168            1 :         else if (type == DiscoveryType::kCommissionerNode)
     169              :         {
     170            1 :             requiredSize = snprintf(buffer, bufferLen, kCommissionerServiceName);
     171              :         }
     172            0 :         else if (type == DiscoveryType::kOperational)
     173              :         {
     174            0 :             requiredSize = snprintf(buffer, bufferLen, kOperationalServiceName);
     175              :         }
     176              :         else
     177              :         {
     178            0 :             return CHIP_ERROR_NOT_IMPLEMENTED;
     179              :         }
     180              :     }
     181              :     else
     182              :     {
     183           13 :         ReturnErrorOnFailure(MakeServiceSubtype(buffer, bufferLen, nameDesc));
     184           10 :         size_t subtypeLen = strlen(buffer);
     185           10 :         if (type == DiscoveryType::kCommissionableNode)
     186              :         {
     187            9 :             requiredSize = snprintf(buffer + subtypeLen, bufferLen - subtypeLen, ".%s.%s", kSubtypeServiceNamePart,
     188              :                                     kCommissionableServiceName);
     189              :         }
     190            1 :         else if (type == DiscoveryType::kCommissionerNode)
     191              :         {
     192              :             requiredSize =
     193            0 :                 snprintf(buffer + subtypeLen, bufferLen - subtypeLen, ".%s.%s", kSubtypeServiceNamePart, kCommissionerServiceName);
     194              :         }
     195            1 :         else if (type == DiscoveryType::kOperational)
     196              :         {
     197              :             requiredSize =
     198            1 :                 snprintf(buffer + subtypeLen, bufferLen - subtypeLen, ".%s.%s", kSubtypeServiceNamePart, kOperationalServiceName);
     199              :         }
     200              :         else
     201              :         {
     202            0 :             return CHIP_ERROR_NOT_IMPLEMENTED;
     203              :         }
     204              :     }
     205              : 
     206           14 :     return (static_cast<size_t>(requiredSize) <= (bufferLen - 1)) ? CHIP_NO_ERROR : CHIP_ERROR_NO_MEMORY;
     207              : }
     208              : 
     209              : } // namespace Dnssd
     210              : } // namespace chip
        

Generated by: LCOV version 2.0-1