diff --git a/examples/chip-tool/BUILD.gn b/examples/chip-tool/BUILD.gn index 85f1c56e2d8266..f56b53a0dd824d 100644 --- a/examples/chip-tool/BUILD.gn +++ b/examples/chip-tool/BUILD.gn @@ -61,7 +61,6 @@ static_library("chip-tool-utils") { "commands/common/Commands.cpp", "commands/common/Commands.h", "commands/common/CredentialIssuerCommands.h", - "commands/common/DeviceScanner.cpp", "commands/common/HexConversion.h", "commands/common/RemoteDataModelLogger.cpp", "commands/common/RemoteDataModelLogger.h", @@ -97,6 +96,10 @@ static_library("chip-tool-utils") { sources += [ "commands/tests/TestCommand.cpp" ] } + if (chip_device_platform == "darwin") { + sources += [ "commands/common/DeviceScanner.cpp" ] + } + public_deps = [ "${chip_root}/src/app/server", "${chip_root}/src/app/tests/suites/commands/commissioner", diff --git a/examples/chip-tool/commands/common/DeviceScanner.cpp b/examples/chip-tool/commands/common/DeviceScanner.cpp index f5c1e39fda7d9d..c1ea12205d4f4d 100644 --- a/examples/chip-tool/commands/common/DeviceScanner.cpp +++ b/examples/chip-tool/commands/common/DeviceScanner.cpp @@ -19,34 +19,38 @@ #include "DeviceScanner.h" using namespace chip; -using namespace chip::Ble; using namespace chip::Dnssd; +#if CONFIG_NETWORK_LAYER_BLE +using namespace chip::Ble; +constexpr const char * kBleKey = "BLE"; +#endif // CONFIG_NETWORK_LAYER_BLE + CHIP_ERROR DeviceScanner::Start() { mDiscoveredResults.clear(); -#if CHIP_TOOL_DEVICE_SCANNER_USE_BLE +#if CONFIG_NETWORK_LAYER_BLE ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().StartBleScan(this)); -#endif // CHIP_TOOL_DEVICE_SCANNER_USE_BLE +#endif // CONFIG_NETWORK_LAYER_BLE - ReturnErrorOnFailure(mDNSResolver.Init(DeviceLayer::UDPEndPointManager())); - mDNSResolver.SetCommissioningDelegate(this); + ReturnErrorOnFailure(chip::Dnssd::Resolver::Instance().Init(DeviceLayer::UDPEndPointManager())); - DiscoveryFilter filter(DiscoveryFilterType::kNone, (uint64_t) 0); - return mDNSResolver.DiscoverCommissionableNodes(filter); + char serviceName[kMaxCommissionableServiceNameSize]; + auto filter = DiscoveryFilterType::kNone; + ReturnErrorOnFailure(MakeServiceTypeName(serviceName, sizeof(serviceName), filter, DiscoveryType::kCommissionableNode)); + + return ChipDnssdBrowse(serviceName, DnssdServiceProtocol::kDnssdProtocolUdp, Inet::IPAddressType::kAny, + Inet::InterfaceId::Null(), this); } CHIP_ERROR DeviceScanner::Stop() { -#if CHIP_TOOL_DEVICE_SCANNER_USE_BLE +#if CONFIG_NETWORK_LAYER_BLE ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().StopBleScan()); -#endif // CHIP_TOOL_DEVICE_SCANNER_USE_BLE +#endif // CONFIG_NETWORK_LAYER_BLE - mDNSResolver.SetCommissioningDelegate(nullptr); - ReturnErrorOnFailure(mDNSResolver.StopDiscovery()); - mDNSResolver.Shutdown(); - return CHIP_NO_ERROR; + return ChipDnssdStopBrowse(this); } void DeviceScanner::OnNodeDiscovered(const DiscoveredNodeData & nodeData) @@ -61,41 +65,149 @@ void DeviceScanner::OnNodeDiscovered(const DiscoveredNodeData & nodeData) productId); auto & resolutionData = nodeData.resolutionData; + + auto & instanceData = mDiscoveredResults[commissionData.instanceName]; + auto & interfaceData = instanceData[resolutionData.interfaceId.GetPlatformInterface()]; + for (size_t i = 0; i < resolutionData.numIPs; i++) { auto params = Controller::SetUpCodePairerParameters(resolutionData, i); - DeviceScannerResult result = { params, vendorId, productId, discriminator }; - mDiscoveredResults.push_back(result); + DeviceScannerResult result = { params, vendorId, productId, discriminator, chip::MakeOptional(resolutionData) }; + interfaceData.push_back(result); } nodeData.LogDetail(); } -#if CHIP_TOOL_DEVICE_SCANNER_USE_BLE +void DeviceScanner::OnBrowseAdd(chip::Dnssd::DnssdService service) +{ + ChipLogProgress(chipTool, "OnBrowseAdd: %s", service.mName); + LogErrorOnFailure(ChipDnssdResolve(&service, service.mInterface, this)); + + auto & instanceData = mDiscoveredResults[service.mName]; + auto & interfaceData = instanceData[service.mInterface.GetPlatformInterface()]; + (void) interfaceData; +} + +void DeviceScanner::OnBrowseRemove(chip::Dnssd::DnssdService service) +{ + ChipLogProgress(chipTool, "OnBrowseRemove: %s", service.mName); + auto & instanceData = mDiscoveredResults[service.mName]; + auto & interfaceData = instanceData[service.mInterface.GetPlatformInterface()]; + + // Check if the interface data has been resolved already, otherwise, just inform the + // back end that we may not need it anymore. + if (interfaceData.size() == 0) + { + ChipDnssdResolveNoLongerNeeded(service.mName); + } + + // Delete the interface placeholder. + instanceData.erase(service.mInterface.GetPlatformInterface()); + + // If there is nothing else to resolve for the given instance name, just removes it + // too. + if (instanceData.size() == 0) + { + mDiscoveredResults.erase(service.mName); + } +} + +void DeviceScanner::OnBrowseStop(CHIP_ERROR error) +{ + ChipLogProgress(chipTool, "OnBrowseStop: %" CHIP_ERROR_FORMAT, error.Format()); + + for (auto & instance : mDiscoveredResults) + { + for (auto & interface : instance.second) + { + if (interface.second.size() == 0) + { + ChipDnssdResolveNoLongerNeeded(instance.first.c_str()); + } + } + } +} + +#if CONFIG_NETWORK_LAYER_BLE void DeviceScanner::OnBleScanAdd(BLE_CONNECTION_OBJECT connObj, const ChipBLEDeviceIdentificationInfo & info) { auto discriminator = info.GetDeviceDiscriminator(); auto vendorId = static_cast(info.GetVendorId()); auto productId = info.GetProductId(); - ChipLogProgress(chipTool, "OnNodeDiscovered (BLE): discriminator: %u, vendorId: %u, productId: %u", discriminator, vendorId, - productId); + ChipLogProgress(chipTool, "OnBleScanAdd (BLE): %p, discriminator: %u, vendorId: %u, productId: %u", connObj, discriminator, + vendorId, productId); auto params = Controller::SetUpCodePairerParameters(connObj, false /* connected */); DeviceScannerResult result = { params, vendorId, productId, discriminator }; - mDiscoveredResults.push_back(result); + + auto & instanceData = mDiscoveredResults[kBleKey]; + auto & interfaceData = instanceData[chip::Inet::InterfaceId::Null().GetPlatformInterface()]; + interfaceData.push_back(result); } -void DeviceScanner::OnBleScanRemove(BLE_CONNECTION_OBJECT connObj) {} -#endif // CHIP_TOOL_DEVICE_SCANNER_USE_BLE +void DeviceScanner::OnBleScanRemove(BLE_CONNECTION_OBJECT connObj) +{ + ChipLogProgress(chipTool, "OnBleScanRemove: %p", connObj); + + auto & instanceData = mDiscoveredResults[kBleKey]; + auto & interfaceData = instanceData[chip::Inet::InterfaceId::Null().GetPlatformInterface()]; + + interfaceData.erase(std::remove_if(interfaceData.begin(), interfaceData.end(), [connObj](const DeviceScannerResult & result) { + return result.mParams.HasDiscoveredObject() && result.mParams.GetDiscoveredObject() == connObj; + })); + + if (interfaceData.size() == 0) + { + instanceData.clear(); + mDiscoveredResults.erase(kBleKey); + } +} +#endif // CONFIG_NETWORK_LAYER_BLE CHIP_ERROR DeviceScanner::Get(uint16_t index, RendezvousParameters & params) { - VerifyOrReturnError(index < mDiscoveredResults.size(), CHIP_ERROR_NOT_FOUND); + uint16_t currentIndex = 0; + for (auto & instance : mDiscoveredResults) + { + for (auto & interface : instance.second) + { + for (auto & result : interface.second) + { + if (currentIndex == index) + { + params = result.mParams; + return CHIP_NO_ERROR; + } + currentIndex++; + } + } + } - auto & result = mDiscoveredResults.at(index); - params = result.mParams; - return CHIP_NO_ERROR; + return CHIP_ERROR_NOT_FOUND; +} + +CHIP_ERROR DeviceScanner::Get(uint16_t index, Dnssd::CommonResolutionData & resolutionData) +{ + uint16_t currentIndex = 0; + for (auto & instance : mDiscoveredResults) + { + for (auto & interface : instance.second) + { + for (auto & result : interface.second) + { + if (currentIndex == index && result.mResolutionData.HasValue()) + { + resolutionData = result.mResolutionData.Value(); + return CHIP_NO_ERROR; + } + currentIndex++; + } + } + } + + return CHIP_ERROR_NOT_FOUND; } void DeviceScanner::Log() const @@ -104,14 +216,21 @@ void DeviceScanner::Log() const VerifyOrReturn(resultsCount > 0, ChipLogProgress(chipTool, "No device discovered.")); uint16_t index = 0; - for (auto & result : mDiscoveredResults) + for (auto & instance : mDiscoveredResults) { - char addr[Transport::PeerAddress::kMaxToStringSize]; - result.mParams.GetPeerAddress().ToString(addr); - - ChipLogProgress(chipTool, "\t %u - Discriminator: %u - Vendor: %u - Product: %u - %s", index, result.mDiscriminator, - result.mVendorId, result.mProductId, addr); - index++; + ChipLogProgress(chipTool, "Instance Name: %s ", instance.first.c_str()); + for (auto & interface : instance.second) + { + for (auto & result : interface.second) + { + char addr[Transport::PeerAddress::kMaxToStringSize]; + result.mParams.GetPeerAddress().ToString(addr); + + ChipLogProgress(chipTool, "\t %u - Discriminator: %u - Vendor: %u - Product: %u - %s", index, result.mDiscriminator, + result.mVendorId, result.mProductId, addr); + index++; + } + } } } diff --git a/examples/chip-tool/commands/common/DeviceScanner.h b/examples/chip-tool/commands/common/DeviceScanner.h index 57dd6affc8ef46..5ea7d036bb3d66 100644 --- a/examples/chip-tool/commands/common/DeviceScanner.h +++ b/examples/chip-tool/commands/common/DeviceScanner.h @@ -18,54 +18,62 @@ #pragma once +#include + +#if CHIP_DEVICE_LAYER_TARGET_DARWIN + #include -#include +#include +#include #include #if CONFIG_NETWORK_LAYER_BLE -#if CHIP_DEVICE_LAYER_TARGET_DARWIN #include -#define CHIP_TOOL_DEVICE_SCANNER_USE_BLE 1 -#endif // CHIP_DEVICE_LAYER_TARGET_DARWIN #endif // CONFIG_NETWORK_LAYER_BLE -#ifndef CHIP_TOOL_DEVICE_SCANNER_USE_BLE -#define CHIP_TOOL_DEVICE_SCANNER_USE_BLE 0 -#endif // CHIP_TOOL_DEVICE_SCANNER_USE_BLE - struct DeviceScannerResult { chip::Controller::SetUpCodePairerParameters mParams; chip::VendorId mVendorId; uint16_t mProductId; uint16_t mDiscriminator; + chip::Optional mResolutionData; }; -class DeviceScanner : public chip::Dnssd::CommissioningResolveDelegate -#if CHIP_TOOL_DEVICE_SCANNER_USE_BLE +class DeviceScanner : public chip::Dnssd::CommissioningResolveDelegate, + public chip::Dnssd::DnssdBrowseDelegate +#if CONFIG_NETWORK_LAYER_BLE , public chip::DeviceLayer::BleScannerDelegate -#endif // CHIP_TOOL_DEVICE_SCANNER_USE_BLE +#endif // CONFIG_NETWORK_LAYER_BLE { public: CHIP_ERROR Start(); CHIP_ERROR Stop(); CHIP_ERROR Get(uint16_t index, chip::RendezvousParameters & params); + CHIP_ERROR Get(uint16_t index, chip::Dnssd::CommonResolutionData & resolutionData); void Log() const; /////////// CommissioningResolveDelegate Interface ///////// void OnNodeDiscovered(const chip::Dnssd::DiscoveredNodeData & nodeData) override; -#if CHIP_TOOL_DEVICE_SCANNER_USE_BLE + /////////// DnssdBrowseDelegate Interface ///////// + void OnBrowseAdd(chip::Dnssd::DnssdService service) override; + void OnBrowseRemove(chip::Dnssd::DnssdService service) override; + void OnBrowseStop(CHIP_ERROR error) override; + +#if CONFIG_NETWORK_LAYER_BLE /////////// BleScannerDelegate Interface ///////// void OnBleScanAdd(BLE_CONNECTION_OBJECT connObj, const chip::Ble::ChipBLEDeviceIdentificationInfo & info) override; void OnBleScanRemove(BLE_CONNECTION_OBJECT connObj) override; -#endif // CHIP_TOOL_DEVICE_SCANNER_USE_BLE +#endif // CONFIG_NETWORK_LAYER_BLE private: - std::vector mDiscoveredResults; - chip::Dnssd::ResolverProxy mDNSResolver; + std::unordered_map>> + mDiscoveredResults; }; DeviceScanner & GetDeviceScanner(); + +#endif // CHIP_DEVICE_LAYER_TARGET_DARWIN diff --git a/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.cpp b/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.cpp index ed5d33aa0ed274..9e65a87b16bac7 100644 --- a/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.cpp +++ b/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.cpp @@ -38,29 +38,41 @@ void DiscoverCommissionablesCommandBase::OnDiscoveredDevice(const chip::Dnssd::D CHIP_ERROR DiscoverCommissionablesStartCommand::RunCommand() { +#if CHIP_DEVICE_LAYER_TARGET_DARWIN VerifyOrReturnError(IsInteractive(), CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure(GetDeviceScanner().Start()); SetCommandExitStatus(CHIP_NO_ERROR); return CHIP_NO_ERROR; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif // CHIP_DEVICE_LAYER_TARGET_DARWIN } CHIP_ERROR DiscoverCommissionablesStopCommand::RunCommand() { +#if CHIP_DEVICE_LAYER_TARGET_DARWIN VerifyOrReturnError(IsInteractive(), CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure(GetDeviceScanner().Stop()); SetCommandExitStatus(CHIP_NO_ERROR); return CHIP_NO_ERROR; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif // CHIP_DEVICE_LAYER_TARGET_DARWIN } CHIP_ERROR DiscoverCommissionablesListCommand::RunCommand() { +#if CHIP_DEVICE_LAYER_TARGET_DARWIN VerifyOrReturnError(IsInteractive(), CHIP_ERROR_INCORRECT_STATE); GetDeviceScanner().Log(); SetCommandExitStatus(CHIP_NO_ERROR); return CHIP_NO_ERROR; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif // CHIP_DEVICE_LAYER_TARGET_DARWIN } CHIP_ERROR DiscoverCommissionablesCommand::RunCommand() diff --git a/examples/chip-tool/commands/pairing/Commands.h b/examples/chip-tool/commands/pairing/Commands.h index 4f4f445d929a8c..8b3c7af7776cdd 100644 --- a/examples/chip-tool/commands/pairing/Commands.h +++ b/examples/chip-tool/commands/pairing/Commands.h @@ -200,6 +200,15 @@ class PairAlreadyDiscoveredByIndexWithWiFi : public PairingCommand {} }; +class PairAlreadyDiscoveredByIndexWithCode : public PairingCommand +{ +public: + PairAlreadyDiscoveredByIndexWithCode(CredentialIssuerCommands * credsIssuerConfig) : + PairingCommand("already-discovered-by-index-with-code", PairingMode::AlreadyDiscoveredByIndexWithCode, + PairingNetworkType::None, credsIssuerConfig) + {} +}; + class StartUdcServerCommand : public CHIPCommand { public: @@ -229,6 +238,7 @@ void registerCommandsPairing(Commands & commands, CredentialIssuerCommands * cre make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), + make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), make_unique(credsIssuerConfig), diff --git a/examples/chip-tool/commands/pairing/PairingCommand.cpp b/examples/chip-tool/commands/pairing/PairingCommand.cpp index ed48fd912f91a3..75f3cf029e32e2 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.cpp +++ b/examples/chip-tool/commands/pairing/PairingCommand.cpp @@ -82,6 +82,9 @@ CHIP_ERROR PairingCommand::RunInternal(NodeId remoteId) case PairingMode::AlreadyDiscoveredByIndex: err = PairWithMdnsOrBleByIndex(remoteId, mIndex); break; + case PairingMode::AlreadyDiscoveredByIndexWithCode: + err = PairWithMdnsOrBleByIndexWithCode(remoteId, mIndex); + break; } return err; @@ -173,6 +176,7 @@ CHIP_ERROR PairingCommand::Pair(NodeId remoteId, PeerAddress address) CHIP_ERROR PairingCommand::PairWithMdnsOrBleByIndex(NodeId remoteId, uint16_t index) { +#if CHIP_DEVICE_LAYER_TARGET_DARWIN VerifyOrReturnError(IsInteractive(), CHIP_ERROR_INCORRECT_STATE); RendezvousParameters params; @@ -190,6 +194,57 @@ CHIP_ERROR PairingCommand::PairWithMdnsOrBleByIndex(NodeId remoteId, uint16_t in err = CurrentCommissioner().PairDevice(remoteId, params, commissioningParams); } return err; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif // CHIP_DEVICE_LAYER_TARGET_DARWIN +} + +CHIP_ERROR PairingCommand::PairWithMdnsOrBleByIndexWithCode(NodeId remoteId, uint16_t index) +{ +#if CHIP_DEVICE_LAYER_TARGET_DARWIN + VerifyOrReturnError(IsInteractive(), CHIP_ERROR_INCORRECT_STATE); + + Dnssd::CommonResolutionData resolutionData; + auto err = GetDeviceScanner().Get(index, resolutionData); + if (CHIP_ERROR_NOT_FOUND == err) + { + // There are no device with such index that has some resolution data. This could simply + // be because the device is a ble device. In this case let's fallback onto looking for + // a device with such index and some RendezVousParameters. + chip::SetupPayload payload; + bool isQRCode = strncmp(mOnboardingPayload, kQRCodePrefix, strlen(kQRCodePrefix)) == 0; + if (isQRCode) + { + ReturnErrorOnFailure(QRCodeSetupPayloadParser(mOnboardingPayload).populatePayload(payload)); + VerifyOrReturnError(payload.isValidQRCodePayload(), CHIP_ERROR_INVALID_ARGUMENT); + } + else + { + ReturnErrorOnFailure(ManualSetupPayloadParser(mOnboardingPayload).populatePayload(payload)); + VerifyOrReturnError(payload.isValidManualCode(), CHIP_ERROR_INVALID_ARGUMENT); + } + + mSetupPINCode = payload.setUpPINCode; + return PairWithMdnsOrBleByIndex(remoteId, index); + } + + err = CHIP_NO_ERROR; + if (mPaseOnly.ValueOr(false)) + { + err = CurrentCommissioner().EstablishPASEConnection(remoteId, mOnboardingPayload, DiscoveryType::kDiscoveryNetworkOnly, + MakeOptional(resolutionData)); + } + else + { + auto commissioningParams = GetCommissioningParameters(); + err = CurrentCommissioner().PairDevice(remoteId, mOnboardingPayload, commissioningParams, + DiscoveryType::kDiscoveryNetworkOnly, + MakeOptional(resolutionData)); + } + return err; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif // CHIP_DEVICE_LAYER_TARGET_DARWIN } CHIP_ERROR PairingCommand::PairWithMdns(NodeId remoteId) diff --git a/examples/chip-tool/commands/pairing/PairingCommand.h b/examples/chip-tool/commands/pairing/PairingCommand.h index 5c2a356d6aec73..a92ec4d1c67172 100644 --- a/examples/chip-tool/commands/pairing/PairingCommand.h +++ b/examples/chip-tool/commands/pairing/PairingCommand.h @@ -36,6 +36,7 @@ enum class PairingMode SoftAP, AlreadyDiscovered, AlreadyDiscoveredByIndex, + AlreadyDiscoveredByIndexWithCode, OnNetwork, }; @@ -122,6 +123,12 @@ class PairingCommand : public CHIPCommand, AddArgument("index", 0, UINT16_MAX, &mIndex); AddArgument("pase-only", 0, 1, &mPaseOnly); break; + case PairingMode::AlreadyDiscoveredByIndexWithCode: + AddArgument("skip-commissioning-complete", 0, 1, &mSkipCommissioningComplete); + AddArgument("payload", &mOnboardingPayload); + AddArgument("index", 0, UINT16_MAX, &mIndex); + AddArgument("pase-only", 0, 1, &mPaseOnly); + break; } switch (filterType) @@ -180,6 +187,7 @@ class PairingCommand : public CHIPCommand, CHIP_ERROR PairWithCode(NodeId remoteId); CHIP_ERROR PaseWithCode(NodeId remoteId); CHIP_ERROR PairWithMdnsOrBleByIndex(NodeId remoteId, uint16_t index); + CHIP_ERROR PairWithMdnsOrBleByIndexWithCode(NodeId remoteId, uint16_t index); CHIP_ERROR Unpair(NodeId remoteId); chip::Controller::CommissioningParameters GetCommissioningParameters();