Matter SDK Coverage Report
Current view: top level - controller - ThreadMeshcopCommissionProxy.cpp (source / functions) Coverage Total Hit
Test: SHA:209dc18e4021e7d0dff8120ccc585909391dd862 Lines: 2.7 % 299 8
Test Date: 2026-06-16 07:34:53 Functions: 10.0 % 20 2

            Line data    Source code
       1              : /*
       2              :  *   Copyright (c) 2026 Project CHIP Authors
       3              :  *   All rights reserved.
       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              : 
      19              : #include "ThreadMeshcopCommissionProxy.h"
      20              : 
      21              : #include <lib/core/CHIPEncoding.h>
      22              : #include <lib/dnssd/TxtFields.h>
      23              : #include <lib/dnssd/minimal_mdns/core/QNameString.h> // nogncheck
      24              : #include <lib/support/BytesToHex.h>
      25              : #include <lib/support/CHIPMemString.h>
      26              : #include <lib/support/CodeUtils.h>
      27              : #include <lib/support/logging/CHIPLogging.h>
      28              : #include <transport/raw/MessageHeader.h>
      29              : 
      30              : #include <json/json.h>
      31              : 
      32              : #include <errno.h>
      33              : #include <inttypes.h>
      34              : #include <netinet/in.h>
      35              : #include <sys/socket.h>
      36              : #include <unistd.h>
      37              : 
      38              : #include <chrono>
      39              : #include <thread>
      40              : 
      41              : using namespace chip;
      42              : 
      43              : namespace {
      44              : /**
      45              :  * Internal OT Commissioner Logger implementation.
      46              :  */
      47              : class CommissionerLogger : public ot::commissioner::Logger
      48              : {
      49              : public:
      50            0 :     void Log(ot::commissioner::LogLevel level, const std::string & region, const std::string & message) override
      51              :     {
      52            0 :         ChipLogProgress(Controller, "[ot-commissioner][%u][%s] %s", static_cast<unsigned>(level), region.c_str(), message.c_str());
      53            0 :     }
      54              : };
      55              : 
      56              : constexpr char kMatterCServiceSuffix[] = "_matterc._udp.local";
      57              : 
      58            0 : uint64_t JoinerIdFromBytes(const std::vector<uint8_t> & bytes)
      59              : {
      60            0 :     const uint8_t * buffer = bytes.data();
      61            0 :     return Encoding::BigEndian::Read64(buffer);
      62              : }
      63              : 
      64            0 : std::vector<uint8_t> DiscoveryCodeToVector(Thread::DiscoveryCode code)
      65              : {
      66              :     uint8_t bytes[sizeof(uint64_t)];
      67            0 :     Encoding::BigEndian::Put64(bytes, code.AsUInt64());
      68            0 :     return std::vector<uint8_t>(bytes, bytes + sizeof(bytes));
      69              : }
      70              : 
      71              : } // namespace
      72              : 
      73              : namespace chip {
      74              : namespace Controller {
      75              : 
      76           13 : ThreadMeshcopCommissionProxy::ThreadMeshcopCommissionProxy() : mState(State::kConnecting), mPromiseFulfilled(false)
      77              : {
      78           13 :     mCommissioner = ot::commissioner::Commissioner::Create(*this);
      79           13 : }
      80              : 
      81           13 : ThreadMeshcopCommissionProxy::~ThreadMeshcopCommissionProxy()
      82              : {
      83           13 :     std::unique_lock<std::recursive_mutex> lock(mMutex);
      84           13 :     if (mProxyFd != -1)
      85              :     {
      86            0 :         if (shutdown(mProxyFd, SHUT_RDWR) == 0 || errno != EBADF)
      87              :         {
      88            0 :             close(mProxyFd);
      89              :         }
      90              : 
      91            0 :         mProxyFd = -1;
      92              :     }
      93              : 
      94           13 :     if (mProxyThread.joinable())
      95              :     {
      96            0 :         lock.unlock();
      97            0 :         mProxyThread.join();
      98              :     }
      99           13 : }
     100              : 
     101            0 : void ThreadMeshcopCommissionProxy::ResetCommissionerForDiscovery()
     102              : {
     103            0 :     std::unique_lock<std::recursive_mutex> lock(mMutex);
     104            0 :     if (mProxyFd != -1)
     105              :     {
     106            0 :         if (shutdown(mProxyFd, SHUT_RDWR) == 0 || errno != EBADF)
     107              :         {
     108            0 :             close(mProxyFd);
     109              :         }
     110            0 :         mProxyFd = -1;
     111              :     }
     112              : 
     113            0 :     if (mProxyThread.joinable())
     114              :     {
     115            0 :         lock.unlock();
     116            0 :         mProxyThread.join();
     117            0 :         lock.lock();
     118              :     }
     119              : 
     120            0 :     mServicePort  = 0;
     121            0 :     mCommissioner = ot::commissioner::Commissioner::Create(*this);
     122            0 : }
     123              : 
     124            0 : void ThreadMeshcopCommissionProxy::SetState(State state)
     125              : {
     126            0 :     mState = state;
     127            0 : }
     128              : 
     129            0 : void ThreadMeshcopCommissionProxy::OnHeader(mdns::Minimal::ConstHeaderRef & header)
     130              : {
     131            0 :     ChipLogDetail(Controller, "mDNS Response: ID=%u, Answers=%u, Additional=%u", header.GetMessageId(), header.GetAnswerCount(),
     132              :                   header.GetAdditionalCount());
     133            0 : }
     134              : 
     135            0 : void ThreadMeshcopCommissionProxy::OnQuery(const mdns::Minimal::QueryData & data)
     136              : {
     137            0 :     if (mState != State::kDiscovering)
     138              :     {
     139            0 :         ChipLogProgress(Controller, "Received mDNS query but proxy is not in discovery state");
     140              :     }
     141              : 
     142            0 :     ChipLogDetail(Controller, "mDNS query: %s", mdns::Minimal::QNameString(data.GetName()).c_str());
     143            0 :     mNodeData.Set<Dnssd::CommissionNodeData>();
     144            0 : }
     145              : 
     146            0 : void ThreadMeshcopCommissionProxy::OnResource(mdns::Minimal::ResourceType section, const mdns::Minimal::ResourceData & data)
     147              : {
     148            0 :     if (mState != State::kDiscovering)
     149              :     {
     150            0 :         return;
     151              :     }
     152              : 
     153            0 :     auto name             = mdns::Minimal::QNameString(data.GetName());
     154            0 :     auto & commissionData = mNodeData.Get<Dnssd::CommissionNodeData>();
     155              : 
     156            0 :     commissionData.threadMeshcop = true;
     157              : 
     158            0 :     switch (data.GetType())
     159              :     {
     160            0 :     case mdns::Minimal::QType::A:
     161              :     case mdns::Minimal::QType::AAAA:
     162            0 :         Platform::CopyString(commissionData.hostName, name.c_str());
     163            0 :         break;
     164              : 
     165            0 :     case mdns::Minimal::QType::SRV: {
     166            0 :         mdns::Minimal::SrvRecord srv;
     167            0 :         if (!srv.Parse(data.GetData(), mDnsPacket))
     168              :         {
     169            0 :             ChipLogError(Controller, "Failed to parse mDNS SRV record");
     170            0 :             return;
     171              :         }
     172              : 
     173            0 :         if (!name.EndsWith(kMatterCServiceSuffix))
     174              :         {
     175            0 :             ChipLogDetail(Controller, "Ignoring non-Matter service: %s", name.c_str());
     176            0 :             return;
     177              :         }
     178              : 
     179              :         // Extract the instance label (portion before "._matterc._udp.local") for CommissionNodeData::instanceName.
     180            0 :         std::string fullName(name.c_str());
     181            0 :         constexpr size_t kMatterCServiceSuffixLen = sizeof(kMatterCServiceSuffix) - 1; // exclude null terminator
     182            0 :         if (fullName.length() >= kMatterCServiceSuffixLen)
     183              :         {
     184            0 :             fullName.erase(fullName.length() - kMatterCServiceSuffixLen);
     185              :         }
     186            0 :         Platform::CopyString(commissionData.instanceName, fullName.c_str());
     187              : 
     188            0 :         mServicePort = srv.GetPort();
     189              : 
     190            0 :         if (mProxyFd == -1)
     191              :         {
     192            0 :             CHIP_ERROR err = CreateProxySocket(commissionData);
     193            0 :             if (err != CHIP_NO_ERROR)
     194              :             {
     195            0 :                 ChipLogError(Controller, "Failed to setup proxy socket: %" CHIP_ERROR_FORMAT, err.Format());
     196            0 :                 SetState(State::kAborted);
     197              :             }
     198              :         }
     199            0 :         break;
     200            0 :     }
     201              : 
     202            0 :     case mdns::Minimal::QType::TXT:
     203            0 :         mdns::Minimal::ParseTxtRecord(data.GetData(), this);
     204            0 :         break;
     205              : 
     206            0 :     default:
     207            0 :         break;
     208              :     }
     209              : }
     210              : 
     211            0 : CHIP_ERROR ThreadMeshcopCommissionProxy::CreateProxySocket(chip::Dnssd::CommissionNodeData & commissionData)
     212              : {
     213            0 :     mProxyFd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
     214            0 :     VerifyOrReturnError(mProxyFd >= 0, CHIP_ERROR_POSIX(errno));
     215              : 
     216            0 :     sockaddr_in6 addr = {};
     217            0 :     addr.sin6_family  = AF_INET6;
     218            0 :     addr.sin6_port    = 0;
     219            0 :     addr.sin6_addr    = in6addr_loopback;
     220              : 
     221            0 :     if (bind(mProxyFd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)) != 0)
     222              :     {
     223            0 :         close(mProxyFd);
     224            0 :         mProxyFd = -1;
     225            0 :         return CHIP_ERROR_POSIX(errno);
     226              :     }
     227              : 
     228            0 :     socklen_t addr_len = sizeof(addr);
     229            0 :     if (getsockname(mProxyFd, reinterpret_cast<struct sockaddr *>(&addr), &addr_len) == -1)
     230              :     {
     231            0 :         close(mProxyFd);
     232            0 :         mProxyFd = -1;
     233            0 :         return CHIP_ERROR_POSIX(errno);
     234              :     }
     235              : 
     236            0 :     commissionData.numIPs       = 1;
     237            0 :     commissionData.port         = ntohs(addr.sin6_port);
     238            0 :     commissionData.ipAddress[0] = Inet::IPAddress::FromSockAddr(addr);
     239            0 :     commissionData.interfaceId  = Inet::InterfaceId::FromIPAddress(commissionData.ipAddress[0]);
     240              : 
     241            0 :     ChipLogProgress(Controller, "Proxy socket created on port %u", commissionData.port);
     242            0 :     return CHIP_NO_ERROR;
     243              : }
     244              : 
     245            0 : std::string ThreadMeshcopCommissionProxy::GetLastDiscoveryDiagnosticJson()
     246              : {
     247            0 :     DiscoveryDiagnostic diagnostic;
     248              :     {
     249            0 :         std::lock_guard<std::recursive_mutex> lock(mMutex);
     250            0 :         diagnostic = mLastDiscoveryDiagnostic;
     251            0 :     }
     252              : 
     253            0 :     Json::Value root(Json::objectValue);
     254            0 :     Json::StreamWriterBuilder writerBuilder;
     255              : 
     256              :     char steeringDataHex[ot::commissioner::kMaxSteeringDataLength * 2 + 1];
     257              :     char rotatingIdHex[Dnssd::kMaxRotatingIdLen * 2 + 1];
     258            0 :     if (Encoding::BytesToUppercaseHexString(diagnostic.steeringData.data(), diagnostic.steeringData.size(), steeringDataHex,
     259            0 :                                             sizeof(steeringDataHex)) != CHIP_NO_ERROR)
     260              :     {
     261            0 :         diagnostic.valid = false;
     262              :     }
     263            0 :     if (Encoding::BytesToUppercaseHexString(diagnostic.commissionData.rotatingId, diagnostic.commissionData.rotatingIdLen,
     264            0 :                                             rotatingIdHex, sizeof(rotatingIdHex)) != CHIP_NO_ERROR)
     265              :     {
     266            0 :         diagnostic.valid = false;
     267              :     }
     268            0 :     root["valid"] = diagnostic.valid;
     269            0 :     if (!diagnostic.valid)
     270              :     {
     271            0 :         return Json::writeString(writerBuilder, root);
     272              :     }
     273              : 
     274            0 :     root["requested_discriminator_type"] = diagnostic.requestedShort ? "short" : "long";
     275            0 :     root["requested_discriminator"]      = static_cast<Json::Value::UInt>(diagnostic.requestedValue);
     276            0 :     root["expected_long_discriminator"]  = static_cast<Json::Value::UInt>(diagnostic.expectedLongValue);
     277            0 :     root["discovery_code"]               = static_cast<Json::Value::UInt64>(diagnostic.discoveryCode);
     278            0 :     root["steering_data_hex"]            = steeringDataHex;
     279            0 :     root["joiner_id"]                    = static_cast<Json::Value::UInt64>(diagnostic.joinerId);
     280            0 :     root["joiner_udp_port"]              = static_cast<Json::Value::UInt>(diagnostic.joinerUdpPort);
     281              : 
     282            0 :     Json::Value dnsAnnouncement(Json::objectValue);
     283            0 :     dnsAnnouncement["long_discriminator"] = static_cast<Json::Value::UInt>(diagnostic.commissionData.longDiscriminator);
     284            0 :     dnsAnnouncement["commissioning_mode"] = static_cast<Json::Value::UInt>(diagnostic.commissionData.commissioningMode);
     285            0 :     dnsAnnouncement["device_type"]        = static_cast<Json::Value::UInt>(diagnostic.commissionData.deviceType);
     286            0 :     dnsAnnouncement["vendor_id"]          = static_cast<Json::Value::UInt>(diagnostic.commissionData.vendorId);
     287            0 :     dnsAnnouncement["product_id"]         = static_cast<Json::Value::UInt>(diagnostic.commissionData.productId);
     288            0 :     dnsAnnouncement["pairing_hint"]       = static_cast<Json::Value::UInt>(diagnostic.commissionData.pairingHint);
     289            0 :     dnsAnnouncement["service_port"]       = static_cast<Json::Value::UInt>(diagnostic.matterUdpPort);
     290            0 :     dnsAnnouncement["thread_meshcop"]     = diagnostic.commissionData.threadMeshcop;
     291            0 :     dnsAnnouncement["supports_commissioner_generated_passcode"] = diagnostic.commissionData.supportsCommissionerGeneratedPasscode;
     292            0 :     dnsAnnouncement["instance_name"]                            = diagnostic.commissionData.instanceName;
     293            0 :     dnsAnnouncement["hostname"]                                 = diagnostic.commissionData.hostName;
     294            0 :     dnsAnnouncement["rotating_id_hex"]                          = rotatingIdHex;
     295            0 :     root["dns_announcement"]                                    = dnsAnnouncement;
     296              : 
     297            0 :     return Json::writeString(writerBuilder, root);
     298            0 : }
     299              : 
     300            0 : void ThreadMeshcopCommissionProxy::OnRecord(const mdns::Minimal::BytesRange & name, const mdns::Minimal::BytesRange & value)
     301              : {
     302            0 :     ByteSpan key(name.Start(), name.Size());
     303            0 :     ByteSpan val(value.Start(), value.Size());
     304              : 
     305            0 :     Dnssd::FillNodeDataFromTxt(key, val, mNodeData.Get<Dnssd::CommissionNodeData>());
     306            0 : }
     307              : 
     308            0 : void ThreadMeshcopCommissionProxy::ProcessAnnouncement(const std::vector<uint8_t> & joinerIdBytes, uint16_t joinerPort,
     309              :                                                        const std::vector<uint8_t> & payload)
     310              : {
     311            0 :     std::lock_guard<std::recursive_mutex> lock(mMutex);
     312              : 
     313            0 :     if (mPromiseFulfilled)
     314              :     {
     315            0 :         return;
     316              :     }
     317              : 
     318            0 :     mNodeData.Set<Dnssd::CommissionNodeData>();
     319            0 :     mDnsPacket = mdns::Minimal::BytesRange(payload.data(), payload.data() + payload.size());
     320              : 
     321            0 :     if (!mdns::Minimal::ParsePacket(mDnsPacket, this))
     322              :     {
     323            0 :         ChipLogError(Controller, "Failed to parse joiner mDNS announcement");
     324            0 :         return;
     325              :     }
     326              : 
     327            0 :     uint32_t discoveredDiscriminator = mNodeData.Get<Dnssd::CommissionNodeData>().longDiscriminator;
     328            0 :     ChipLogProgress(Controller, "Discovered joiner with discriminator: %u", discoveredDiscriminator);
     329              : 
     330            0 :     if (!mExpectedDiscriminator.MatchesLongDiscriminator(static_cast<uint16_t>(discoveredDiscriminator)))
     331              :     {
     332            0 :         ChipLogProgress(Controller, "Discriminator mismatch (Expected %u, Got %u). Ignoring announcement.",
     333              :                         mExpectedDiscriminator.GetLongValue(), discoveredDiscriminator);
     334            0 :         return;
     335              :     }
     336              : 
     337            0 :     mDiscoveredNodePromise.set_value(mNodeData);
     338            0 :     mPromiseFulfilled = true;
     339              : 
     340            0 :     mLastDiscoveryDiagnostic.valid          = true;
     341            0 :     mLastDiscoveryDiagnostic.joinerId       = JoinerIdFromBytes(joinerIdBytes);
     342            0 :     mLastDiscoveryDiagnostic.joinerUdpPort  = joinerPort;
     343            0 :     mLastDiscoveryDiagnostic.matterUdpPort  = mServicePort;
     344            0 :     mLastDiscoveryDiagnostic.commissionData = mNodeData.Get<Dnssd::CommissionNodeData>();
     345              : 
     346            0 :     SetState(State::kDiscovered);
     347              : 
     348            0 :     if (mProxyThread.joinable())
     349              :     {
     350            0 :         mProxyThread.join();
     351              :     }
     352              : 
     353            0 :     mProxyThread = std::thread([id = joinerIdBytes, this]() {
     354              :         struct sockaddr_storage addr;
     355            0 :         socklen_t len = sizeof(addr);
     356              :         uint8_t buf[chip::detail::kMaxIPPacketSizeBytes];
     357              :         ssize_t received;
     358              : 
     359            0 :         while ((received = recvfrom(mProxyFd, buf, sizeof(buf), 0, reinterpret_cast<struct sockaddr *>(&addr), &len)) > 0)
     360              :         {
     361            0 :             switch (mState)
     362              :             {
     363            0 :             case State::kDiscovered: {
     364            0 :                 int rval = connect(mProxyFd, reinterpret_cast<struct sockaddr *>(&addr), len);
     365            0 :                 if (rval < 0)
     366              :                 {
     367            0 :                     ChipLogError(Controller, "Failed to connect to Matter Commissioner: %s", strerror(errno));
     368            0 :                     continue;
     369              :                 }
     370            0 :                 SetState(State::kCommissioning);
     371              :                 FALLTHROUGH;
     372              :             }
     373              : 
     374            0 :             case State::kCommissioning: {
     375            0 :                 std::vector<uint8_t> pkt(buf, buf + received);
     376              : 
     377            0 :                 auto error = mCommissioner->SendToJoiner(id, mServicePort, pkt);
     378            0 :                 if (error != ot::commissioner::ErrorCode::kNone)
     379              :                 {
     380            0 :                     ChipLogError(Controller, "Failed to send packet to joiner: %s", error.GetMessage().c_str());
     381            0 :                     return;
     382              :                 }
     383            0 :                 break;
     384            0 :             }
     385            0 :             default:
     386            0 :                 ChipLogError(Controller, "Invalid CommissionProxy state: %d", static_cast<int>(mState.load()));
     387            0 :                 return;
     388              :             }
     389              :         }
     390            0 :     });
     391            0 : }
     392              : 
     393            0 : void ThreadMeshcopCommissionProxy::OnJoinerMessage(const std::vector<uint8_t> & joinerIdBytes, uint16_t joinerPort,
     394              :                                                    const std::vector<uint8_t> & payload)
     395              : {
     396            0 :     std::lock_guard<std::recursive_mutex> lock(mMutex);
     397              : 
     398            0 :     if (joinerIdBytes.size() != sizeof(uint64_t) || mState == State::kAborted)
     399              :     {
     400            0 :         return;
     401              :     }
     402              : 
     403            0 :     uint64_t joinerId = JoinerIdFromBytes(joinerIdBytes);
     404            0 :     ChipLogDetail(Controller, "Message from joiner 0x%" PRIx64 " on port %u", joinerId, joinerPort);
     405              : 
     406            0 :     if (mJoinerId == 0)
     407              :     {
     408            0 :         mJoinerId = joinerId;
     409              :     }
     410            0 :     else if (mJoinerId != joinerId)
     411              :     {
     412            0 :         ChipLogProgress(Controller, "Ignoring message from unexpected joiner 0x%" PRIx64, joinerId);
     413            0 :         return;
     414              :     }
     415              : 
     416            0 :     switch (mState)
     417              :     {
     418            0 :     case State::kCommissioning:
     419            0 :         if (mProxyFd != -1)
     420              :         {
     421            0 :             if (send(mProxyFd, payload.data(), payload.size(), 0) < 0)
     422              :             {
     423            0 :                 ChipLogError(Controller, "Failed to forward packet to local proxy: %s", strerror(errno));
     424            0 :                 SetState(State::kAborted);
     425              :             }
     426              :         }
     427            0 :         break;
     428            0 :     case State::kAborted:
     429            0 :         break;
     430            0 :     case State::kConnecting:
     431              :         // First message from joiner is usually the mDNS announcement
     432            0 :         SetState(State::kDiscovering);
     433              :         FALLTHROUGH;
     434            0 :     case State::kDiscovering:
     435            0 :         ProcessAnnouncement(joinerIdBytes, joinerPort, payload);
     436            0 :         break;
     437            0 :     case State::kDiscovered:
     438            0 :         ChipLogProgress(Controller, "WARNING ignore unsolicited messages after joiner is already discovered");
     439            0 :         break;
     440              :     }
     441            0 : }
     442              : 
     443            0 : ot::commissioner::CommissionerDataset ThreadMeshcopCommissionProxy::MakeCommissionerDataset(Thread::DiscoveryCode code)
     444              : {
     445            0 :     ot::commissioner::CommissionerDataset dataset;
     446              : 
     447            0 :     dataset.mJoinerUdpPort = ot::commissioner::kDefaultJoinerUdpPort;
     448            0 :     dataset.mPresentFlags |= ot::commissioner::CommissionerDataset::kJoinerUdpPortBit;
     449            0 :     dataset.mPresentFlags &=
     450              :         ~(ot::commissioner::CommissionerDataset::kSessionIdBit | ot::commissioner::CommissionerDataset::kBorderAgentLocatorBit);
     451              : 
     452            0 :     if (code.IsAny())
     453              :     {
     454            0 :         dataset.mSteeringData = std::vector<uint8_t>{ 0xff };
     455              :     }
     456              :     else
     457              :     {
     458            0 :         std::vector<uint8_t> steeringData(ot::commissioner::kMaxSteeringDataLength);
     459            0 :         ot::commissioner::Commissioner::AddJoiner(steeringData, DiscoveryCodeToVector(code));
     460            0 :         dataset.mSteeringData = steeringData;
     461            0 :     }
     462              : 
     463            0 :     dataset.mPresentFlags |= ot::commissioner::CommissionerDataset::kSteeringDataBit;
     464            0 :     return dataset;
     465              : }
     466            0 : CHIP_ERROR ThreadMeshcopCommissionProxy::InitializeCommissioner(ByteSpan & pskc)
     467              : {
     468            0 :     VerifyOrReturnError(pskc.size() == Thread::kSizePSKc, CHIP_ERROR_INVALID_ARGUMENT);
     469            0 :     ot::commissioner::Config config;
     470            0 :     config.mLogger    = std::make_shared<CommissionerLogger>();
     471            0 :     config.mEnableCcm = false;
     472            0 :     config.mProxyMode = true;
     473            0 :     config.mPSKc      = std::vector<uint8_t>(pskc.begin(), pskc.end());
     474              : 
     475            0 :     auto error = mCommissioner->Init(config);
     476            0 :     if (error != ot::commissioner::ErrorCode::kNone)
     477              :     {
     478            0 :         ChipLogError(Controller, "OT Commissioner Init failed: %s", error.GetMessage().c_str());
     479            0 :         return CHIP_ERROR_INTERNAL;
     480              :     }
     481            0 :     return CHIP_NO_ERROR;
     482            0 : }
     483              : 
     484            0 : CHIP_ERROR ThreadMeshcopCommissionProxy::Discover(ByteSpan & pskc, const Transport::PeerAddress & peerAddr,
     485              :                                                   const Thread::DiscoveryCode code, SetupDiscriminator expectedDiscriminator,
     486              :                                                   Dnssd::DiscoveredNodeData & nodeData, uint16_t timeout)
     487              : {
     488              :     using ot::commissioner::Error;
     489              : 
     490            0 :     Error error;
     491            0 :     ResetCommissionerForDiscovery();
     492              : 
     493              :     // Reset the promise and state for a new discovery session
     494            0 :     std::future<Dnssd::DiscoveredNodeData> future;
     495              :     {
     496            0 :         std::lock_guard<std::recursive_mutex> lock(mMutex);
     497            0 :         mExpectedDiscriminator = expectedDiscriminator;
     498            0 :         SetState(State::kConnecting);
     499            0 :         mDiscoveredNodePromise                  = std::promise<Dnssd::DiscoveredNodeData>();
     500            0 :         future                                  = mDiscoveredNodePromise.get_future();
     501            0 :         mPromiseFulfilled                       = false;
     502            0 :         mJoinerId                               = 0;
     503            0 :         mLastDiscoveryDiagnostic                = DiscoveryDiagnostic();
     504            0 :         mLastDiscoveryDiagnostic.requestedShort = expectedDiscriminator.IsShortDiscriminator();
     505            0 :         mLastDiscoveryDiagnostic.requestedValue =
     506            0 :             mLastDiscoveryDiagnostic.requestedShort ? expectedDiscriminator.GetShortValue() : expectedDiscriminator.GetLongValue();
     507            0 :         mLastDiscoveryDiagnostic.expectedLongValue =
     508            0 :             expectedDiscriminator.IsShortDiscriminator() ? 0 : expectedDiscriminator.GetLongValue();
     509            0 :         mLastDiscoveryDiagnostic.discoveryCode = code.AsUInt64();
     510            0 :     }
     511              : 
     512            0 :     ReturnErrorOnFailure(InitializeCommissioner(pskc));
     513              : 
     514              :     {
     515            0 :         std::string id;
     516              :         char host[Inet::IPAddress::kMaxStringLength];
     517            0 :         peerAddr.GetIPAddress().ToString(host);
     518              : 
     519            0 :         ChipLogProgress(Controller, "Petitioning Thread Border Agent at %s:%u", host, peerAddr.GetPort());
     520            0 :         error = mCommissioner->Petition(id, std::string(host), peerAddr.GetPort());
     521            0 :         if (error != ot::commissioner::ErrorCode::kNone)
     522              :         {
     523            0 :             ChipLogError(Controller, "Petition failed: %s", error.GetMessage().c_str());
     524            0 :             SetState(State::kAborted);
     525            0 :             return CHIP_ERROR_INTERNAL;
     526              :         }
     527              : 
     528            0 :         ChipLogProgress(Controller, "Thread Commissioner active with ID: %s", id.c_str());
     529            0 :     }
     530              : 
     531            0 :     auto commissionerDataset = MakeCommissionerDataset(code);
     532              :     {
     533            0 :         std::lock_guard<std::recursive_mutex> lock(mMutex);
     534            0 :         mLastDiscoveryDiagnostic.steeringData = commissionerDataset.mSteeringData;
     535            0 :     }
     536              : 
     537            0 :     error = mCommissioner->SetCommissionerDataset(commissionerDataset);
     538            0 :     if (error != ot::commissioner::ErrorCode::kNone)
     539              :     {
     540            0 :         ChipLogError(Controller, "Failed to set Steering Data: %s", error.GetMessage().c_str());
     541            0 :         SetState(State::kAborted);
     542            0 :         return CHIP_ERROR_INTERNAL;
     543              :     }
     544              : 
     545            0 :     ChipLogProgress(Controller, "Waiting for mDNS announcement from joiner...");
     546            0 :     auto waitDuration = std::chrono::seconds(timeout);
     547            0 :     if (future.wait_for(waitDuration) == std::future_status::timeout)
     548              :     {
     549            0 :         ChipLogError(Controller, "Timed out waiting for joiner mDNS announcement after %u seconds", timeout);
     550            0 :         SetState(State::kAborted);
     551            0 :         return CHIP_ERROR_TIMEOUT;
     552              :     }
     553            0 :     nodeData = future.get();
     554            0 :     return CHIP_NO_ERROR;
     555            0 : }
     556              : } // namespace Controller
     557              : } // namespace chip
        

Generated by: LCOV version 2.0-1