Skip to content

Commit

Permalink
Add support for accessory DNS browse and resolve on Thread devices. (#…
Browse files Browse the repository at this point in the history
…8132)

* Add support for accessory DNS browse and resolve on Thread devices.

Currently Thread platform doesn't provide mDNS browse and resolve
implementation. Moreover there is no way to trigger browse
or resolve queries on accessory devices to perform operational
discovery from accessory device perspective.

For all:
* Added set of dns shell commands allowing to invoke dns browse
and dns resolve commands.

For Thread:
* Implemented ChipMdnsBrowse and ChipMdnsResolve.
* Implemented ThreadStackMgr DnsResolve and DnsBrowse commands
using OpenThread API for performing DNS queries.
* Changed SRP service buffers sizes to allow handling Commissionable
Discovery records (currently it was assumed to support only
Operational Discovery and sizes are not big enough).
* Added configs allowing to decide whether Thread DNS client
and Thread Commissionable Discovery should be enabled
(to avoid potential memory consumption problems on different
platforms as Commissionable Discovery data are pretty heavy).

For nrfconnect:
* Enabled DNS client and commissionable discovery support
by default.
* Extended shell commands documentation about dns.

What this change doesn't introduce:
* Support for commissionable discovery on Thread devices,
it only allows for handling commissionable discovery records
responses when performing dns browse.
* DNS browsing/resolving support on platforms other than
nrfconnect, as it needs to be enabled individually by setting
CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT

* Addressed review comments
  • Loading branch information
kkasperczyk-no authored and pull[bot] committed Sep 21, 2021
1 parent dd2d83e commit 1296520
Show file tree
Hide file tree
Showing 14 changed files with 608 additions and 13 deletions.
1 change: 0 additions & 1 deletion config/nrfconnect/app/sample-defaults.conf
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ CONFIG_OPENTHREAD_FTD=n
CONFIG_OPENTHREAD_SLAAC=y
CONFIG_OPENTHREAD_DHCP6_CLIENT=y
CONFIG_OPENTHREAD_SNTP_CLIENT=y
CONFIG_OPENTHREAD_DNS_CLIENT=y
CONFIG_OPENTHREAD_MTD_NETDIAG=y
CONFIG_OPENTHREAD_ENABLE_SERVICE=y
CONFIG_OPENTHREAD_MANUAL_START=y
Expand Down
7 changes: 7 additions & 0 deletions config/zephyr/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ config CHIP_ENABLE_DNSSD_SRP
help
Enables DNS-SD SRP client support

config CHIP_ENABLE_DNS_CLIENT
bool "Enable support for DNS client"
default y
imply OPENTHREAD_DNS_CLIENT
help
Enables DNS client support used for resolving and browsing services.

config APP_LINK_WITH_CHIP
bool "Link 'app' with Connected Home over IP"
default y
Expand Down
39 changes: 39 additions & 0 deletions docs/guides/nrfconnect_examples_cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,3 +307,42 @@ Prints the information about the NFC tag emulation status.
uart:~$ matter nfc state
NFC tag emulation is disabled
```

### dns

Handles a group of commands that are used to trigger performing DNS queries. You
must use this command together with one of the additional subcommands listed
below.

#### browse

Browses for DNS services of `_matterc_udp` type and prints the received
response. Takes no argument.

```shell
uart:~$ matter dns browse
Browsing ...
DNS browse succeeded:
Hostname: 0E824F0CA6DE309C
Vendor ID: 9050
Product ID: 20043
Long discriminator: 3840
Device type: 0
Device name:
Commissioning mode: 0
IP addresses:
fd08:b65e:db8e:f9c7:2cc2:2043:1366:3b31
```

#### resolve

Resolves the specified Matter node service given by the <fabric-id> and
<node-id>.

```shell
uart:~$ matter dns resolve <fabric-id> <node-id>
Resolving ...
DNS resolve for 000000014A77CBB3-0000000000BC5C01 succeeded:
IP address: fd08:b65e:db8e:f9c7:8052:1a8e:4dd4:e1f3
Port: 11097
```
18 changes: 18 additions & 0 deletions src/include/platform/CHIPDeviceConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,24 @@
#define CHIP_DEVICE_CONFIG_THREAD_SRP_MAX_SERVICES 3
#endif

/**
* CHIP_DEVICE_CONFIG_ENABLE_THREAD_COMMISSIONABLE_DISCOVERY
*
* Enable support to Commissionable Discovery for Thread devices.
*/
#ifndef CHIP_DEVICE_CONFIG_ENABLE_THREAD_COMMISSIONABLE_DISCOVERY
#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_COMMISSIONABLE_DISCOVERY 0
#endif

/**
* CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT
*
* Enable support to DNS client usage for resolving and browsing services in CHIP.
*/
#ifndef CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT
#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT 0
#endif

// -------------------- Thread Configuration --------------------

/**
Expand Down
33 changes: 30 additions & 3 deletions src/include/platform/ThreadStackManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ namespace chip {

namespace Mdns {
struct TextEntry;
}
struct MdnsService;
} // namespace Mdns

namespace DeviceLayer {

Expand All @@ -56,6 +57,12 @@ template <class>
class GenericThreadStackManagerImpl_FreeRTOS;
} // namespace Internal

#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT
// Declaration of callback types corresponding to MdnsResolveCallback and MdnsBrowseCallback to avoid circular including.
using DnsResolveCallback = void (*)(void * context, chip::Mdns::MdnsService * result, CHIP_ERROR error);
using DnsBrowseCallback = void (*)(void * context, chip::Mdns::MdnsService * services, size_t servicesSize, CHIP_ERROR error);
#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT

/**
* Provides features for initializing and interacting with the Thread stack on
* a chip-enabled device.
Expand Down Expand Up @@ -86,11 +93,17 @@ class ThreadStackManager
CHIP_ERROR SetThreadEnabled(bool val);

#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT
CHIP_ERROR AddSrpService(const char * aInstanceName, const char * aName, uint16_t aPort, chip::Mdns::TextEntry * aTxtEntries,
size_t aTxtEntiresSize, uint32_t aLeaseInterval, uint32_t aKeyLeaseInterval);
CHIP_ERROR
AddSrpService(const char * aInstanceName, const char * aName, uint16_t aPort, chip::Mdns::TextEntry * aTxtEntries,
size_t aTxtEntiresSize, uint32_t aLeaseInterval, uint32_t aKeyLeaseInterval);
CHIP_ERROR RemoveSrpService(const char * aInstanceName, const char * aName);
CHIP_ERROR RemoveAllSrpServices();
CHIP_ERROR SetupSrpHost(const char * aHostName);

#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT
CHIP_ERROR DnsBrowse(const char * aServiceName, DnsBrowseCallback aCallback, void * aContext);
CHIP_ERROR DnsResolve(const char * aServiceName, const char * aInstanceName, DnsResolveCallback aCallback, void * aContext);
#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT
#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT

private:
Expand Down Expand Up @@ -249,6 +262,20 @@ inline CHIP_ERROR ThreadStackManager::SetupSrpHost(const char * aHostName)
{
return static_cast<ImplClass *>(this)->_SetupSrpHost(aHostName);
}

#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT
inline CHIP_ERROR ThreadStackManager::DnsBrowse(const char * aServiceName, DnsBrowseCallback aCallback, void * aContext)
{
return static_cast<ImplClass *>(this)->_DnsBrowse(aServiceName, aCallback, aContext);
}

inline CHIP_ERROR ThreadStackManager::DnsResolve(const char * aServiceName, const char * aInstanceName,
DnsResolveCallback aCallback, void * aContext)
{
return static_cast<ImplClass *>(this)->_DnsResolve(aServiceName, aInstanceName, aCallback, aContext);
}

#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT
#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT

inline bool ThreadStackManager::IsThreadProvisioned()
Expand Down
10 changes: 9 additions & 1 deletion src/lib/mdns/Discovery_ImplPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,15 @@ void DiscoveryImplPlatform::HandleNodeBrowse(void * context, MdnsService * servi
{
for (size_t i = 0; i < servicesSize; ++i)
{
ChipMdnsResolve(&services[i], INET_NULL_INTERFACEID, HandleNodeResolve, context);
// For some platforms browsed services are already resolved, so verify if resolve is really needed or call resolve callback
if (!services[i].mAddress.HasValue())
{
ChipMdnsResolve(&services[i], services[i].mInterface, HandleNodeResolve, context);
}
else
{
HandleNodeResolve(context, &services[i], error);
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/lib/shell/Commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,11 @@ void RegisterWiFiCommands();
*/
void RegisterNFCCommands();

/**
* This function registers the DNS client commands.
*
*/
void RegisterDnsCommands();

} // namespace Shell
} // namespace chip
3 changes: 3 additions & 0 deletions src/lib/shell/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ void Engine::RegisterDefaultCommands()
#if CHIP_DEVICE_CONFIG_ENABLE_NFC
RegisterNFCCommands();
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_MDNS
RegisterDnsCommands();
#endif
}

} // namespace Shell
Expand Down
4 changes: 4 additions & 0 deletions src/lib/shell/commands/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ source_set("commands") {
sources += [ "NFC.cpp" ]
}

if (chip_mdns != "none" && chip_device_platform != "none") {
sources += [ "Dns.cpp" ]
}

public_deps = [ "${chip_root}/src/lib/shell:shell_core" ]

if (chip_device_platform != "none") {
Expand Down
141 changes: 141 additions & 0 deletions src/lib/shell/commands/Dns.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
*
* Copyright (c) 2021 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <core/CHIPCore.h>
#include <core/PeerId.h>
#include <inet/IPAddress.h>
#include <lib/mdns/Advertiser.h>
#include <lib/mdns/Resolver.h>
#include <lib/mdns/platform/Mdns.h>
#include <lib/shell/Commands.h>
#include <lib/shell/Engine.h>
#include <lib/shell/commands/Help.h>
#include <platform/CHIPDeviceLayer.h>
#include <support/CHIPArgParser.hpp>
#include <support/CodeUtils.h>

namespace chip {
namespace Shell {

static chip::Shell::Engine sShellDnsSubcommands;
static bool isResolverStarted;

class DnsShellResolverDelegate : public chip::Mdns::ResolverDelegate
{
public:
void OnNodeIdResolved(const chip::Mdns::ResolvedNodeData & nodeData) override
{
streamer_printf(streamer_get(), "DNS resolve for " ChipLogFormatX64 "-" ChipLogFormatX64 " succeeded:\n",
ChipLogValueX64(nodeData.mPeerId.GetFabricId()), ChipLogValueX64(nodeData.mPeerId.GetNodeId()));
streamer_printf(streamer_get(), " IP address: %s\n", nodeData.mAddress.ToString(ipAddressBuf));
streamer_printf(streamer_get(), " Port: %d\n", nodeData.mPort);
}

void OnNodeIdResolutionFailed(const PeerId & peerId, CHIP_ERROR error) override {}

void OnNodeDiscoveryComplete(const chip::Mdns::DiscoveredNodeData & nodeData) override
{
if (!nodeData.IsValid())
{
streamer_printf(streamer_get(), "DNS browse failed - not found valid services \n");
return;
}
streamer_printf(streamer_get(), "DNS browse succeeded: \n");
streamer_printf(streamer_get(), " Hostname: %s\n", nodeData.hostName);
streamer_printf(streamer_get(), " Vendor ID: %d\n", nodeData.vendorId);
streamer_printf(streamer_get(), " Product ID: %d\n", nodeData.productId);
streamer_printf(streamer_get(), " Long discriminator: %d\n", nodeData.longDiscriminator);
streamer_printf(streamer_get(), " Device type: %d\n", nodeData.deviceType);
streamer_printf(streamer_get(), " Device name: %s\n", nodeData.deviceName);
streamer_printf(streamer_get(), " Commissioning mode: %d\n", nodeData.commissioningMode);
streamer_printf(streamer_get(), " IP addresses:\n");
for (uint8_t i = 0; i < nodeData.kMaxIPAddresses; i++)
{
if (nodeData.ipAddress[i] != chip::Inet::IPAddress::Any)
streamer_printf(streamer_get(), " %s\n", nodeData.ipAddress[i].ToString(ipAddressBuf));
}
}

private:
char ipAddressBuf[chip::Inet::kMaxIPAddressStringLength];
};

static DnsShellResolverDelegate sDnsShellResolverDelegate;

CHIP_ERROR DnsHelpHandler(int argc, char ** argv)
{
sShellDnsSubcommands.ForEachCommand(PrintCommandHelp, nullptr);
return CHIP_NO_ERROR;
}

static CHIP_ERROR ResolveHandler(int argc, char ** argv)
{
streamer_printf(streamer_get(), "Resolving ...\r\n");

VerifyOrReturnError(argc == 2, CHIP_ERROR_INVALID_ARGUMENT);

PeerId peerId;
peerId.SetFabricId(strtoull(argv[0], NULL, 10));
peerId.SetNodeId(strtoull(argv[1], NULL, 10));

return chip::Mdns::Resolver::Instance().ResolveNodeId(peerId, Inet::kIPAddressType_Any);
}

static CHIP_ERROR BrowseHandler(int argc, char ** argv)
{
streamer_printf(streamer_get(), "Browsing ...\r\n");

return chip::Mdns::Resolver::Instance().FindCommissionableNodes();
}

static CHIP_ERROR DnsHandler(int argc, char ** argv)
{
if (!isResolverStarted)
{
chip::Mdns::Resolver::Instance().StartResolver(&chip::DeviceLayer::InetLayer, chip::Mdns::kMdnsPort);
chip::Mdns::Resolver::Instance().SetResolverDelegate(&sDnsShellResolverDelegate);

isResolverStarted = true;
}

if (argc == 0)
{
DnsHelpHandler(argc, argv);
return CHIP_NO_ERROR;
}
return sShellDnsSubcommands.ExecCommand(argc, argv);
}

void RegisterDnsCommands()
{
static const shell_command_t sDnsSubCommands[] = {
{ &ResolveHandler, "resolve",
"Resolve the DNS service. Usage: dns resolve <fabric-id> <node-id> (e.g. dns resolve 5544332211 1)" },
{ &BrowseHandler, "browse", "Browse the services published by mdns. Usage: dns browse" },
};

static const shell_command_t sDnsCommand = { &DnsHandler, "dns", "Dns client commands" };

// Register `dns` subcommands with the local shell dispatcher.
sShellDnsSubcommands.RegisterCommands(sDnsSubCommands, ArraySize(sDnsSubCommands));

// Register the root `dns` command with the top-level shell.
Engine::Root().RegisterCommands(&sDnsCommand, 1);
}

} // namespace Shell
} // namespace chip
Loading

0 comments on commit 1296520

Please sign in to comment.