Skip to content

Commit

Permalink
Implement User Directed Commissioning - Phase 1 (#8034)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdecenzo authored Jul 1, 2021
1 parent 07894bd commit dac287b
Show file tree
Hide file tree
Showing 14 changed files with 172 additions and 55 deletions.
33 changes: 19 additions & 14 deletions examples/minimal-mdns/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,22 +188,27 @@ int main(int argc, char ** args)
mdns::Minimal::Server<10 /* endpoints */> mdnsServer;
mdns::Minimal::QueryResponder<16 /* maxRecords */> queryResponder;

mdns::Minimal::QNamePart tcpServiceName[] = { kOperationalServiceName, kOperationalProtocol, kLocalDomain };
mdns::Minimal::QNamePart tcpServerServiceName[] = { gOptions.instanceName, kOperationalServiceName, kOperationalProtocol,
kLocalDomain };
mdns::Minimal::QNamePart udpServiceName[] = { kCommissionableServiceName, kCommissionProtocol, kLocalDomain };
mdns::Minimal::QNamePart udpServerServiceName[] = { gOptions.instanceName, kCommissionableServiceName, kCommissionProtocol,
kLocalDomain };
mdns::Minimal::QNamePart tcpServiceName[] = { chip::Mdns::kOperationalServiceName, chip::Mdns::kOperationalProtocol,
chip::Mdns::kLocalDomain };
mdns::Minimal::QNamePart tcpServerServiceName[] = { gOptions.instanceName, chip::Mdns::kOperationalServiceName,
chip::Mdns::kOperationalProtocol, chip::Mdns::kLocalDomain };
mdns::Minimal::QNamePart udpServiceName[] = { chip::Mdns::kCommissionableServiceName, chip::Mdns::kCommissionProtocol,
chip::Mdns::kLocalDomain };
mdns::Minimal::QNamePart udpServerServiceName[] = { gOptions.instanceName, chip::Mdns::kCommissionableServiceName,
chip::Mdns::kCommissionProtocol, chip::Mdns::kLocalDomain };

// several UDP versions for discriminators
mdns::Minimal::QNamePart udpDiscriminator1[] = { "S52", kSubtypeServiceNamePart, kCommissionableServiceName,
kCommissionProtocol, kLocalDomain };
mdns::Minimal::QNamePart udpDiscriminator2[] = { "V123", kSubtypeServiceNamePart, kCommissionableServiceName,
kCommissionProtocol, kLocalDomain };
mdns::Minimal::QNamePart udpDiscriminator3[] = { "L840", kSubtypeServiceNamePart, kCommissionableServiceName,
kCommissionProtocol, kLocalDomain };

mdns::Minimal::QNamePart serverName[] = { gOptions.instanceName, kLocalDomain };
mdns::Minimal::QNamePart udpDiscriminator1[] = { "S52", chip::Mdns::kSubtypeServiceNamePart,
chip::Mdns::kCommissionableServiceName, chip::Mdns::kCommissionProtocol,
chip::Mdns::kLocalDomain };
mdns::Minimal::QNamePart udpDiscriminator2[] = { "V123", chip::Mdns::kSubtypeServiceNamePart,
chip::Mdns::kCommissionableServiceName, chip::Mdns::kCommissionProtocol,
chip::Mdns::kLocalDomain };
mdns::Minimal::QNamePart udpDiscriminator3[] = { "L840", chip::Mdns::kSubtypeServiceNamePart,
chip::Mdns::kCommissionableServiceName, chip::Mdns::kCommissionProtocol,
chip::Mdns::kLocalDomain };

mdns::Minimal::QNamePart serverName[] = { gOptions.instanceName, chip::Mdns::kLocalDomain };

mdns::Minimal::IPv4Responder ipv4Responder(serverName);
mdns::Minimal::IPv6Responder ipv6Responder(serverName);
Expand Down
7 changes: 7 additions & 0 deletions src/app/server/Mdns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <core/Optional.h>
#include <mdns/Advertiser.h>
#include <mdns/ServiceNaming.h>
#include <messaging/ReliableMessageProtocolConfig.h>
#if CONFIG_DEVICE_LAYER
#include <platform/CHIPDeviceLayer.h>
Expand Down Expand Up @@ -87,6 +88,12 @@ chip::ByteSpan FillMAC(uint8_t (&mac)[8])

} // namespace

CHIP_ERROR GetCommissionableInstanceName(char * buffer, size_t bufferLen)
{
auto & mdnsAdvertiser = chip::Mdns::ServiceAdvertiser::Instance();
return mdnsAdvertiser.GetCommissionableInstanceName(buffer, bufferLen);
}

/// Set MDNS operational advertisement
CHIP_ERROR AdvertiseOperational()
{
Expand Down
3 changes: 3 additions & 0 deletions src/app/server/Mdns.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ void StartServer();

CHIP_ERROR GenerateRotatingDeviceId(char rotatingDeviceIdHexBuffer[], size_t rotatingDeviceIdHexBufferSize);

/// Generates the (random) instance name that a CHIP device is to use for pre-commissioning DNS-SD
CHIP_ERROR GetCommissionableInstanceName(char * buffer, size_t bufferLen);

} // namespace Mdns
} // namespace app
} // namespace chip
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ CHIP_ERROR pychip_DeviceController_ConnectIP(chip::Controller::DeviceCommissione

CHIP_ERROR pychip_DeviceController_DiscoverAllCommissionableNodes(chip::Controller::DeviceCommissioner * devCtrl)
{
Mdns::DiscoveryFilter filter(Mdns::DiscoveryFilterType::kNone, 0);
Mdns::DiscoveryFilter filter(Mdns::DiscoveryFilterType::kNone, (uint16_t) 0);
return devCtrl->DiscoverCommissionableNodes(filter);
}

Expand Down
55 changes: 40 additions & 15 deletions src/lib/mdns/Advertiser.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <core/PeerId.h>
#include <inet/InetLayer.h>
#include <lib/support/Span.h>
#include <support/CHIPMemString.h>

namespace chip {
namespace Mdns {
Expand Down Expand Up @@ -179,34 +180,55 @@ class CommissionAdvertisingParameters : public BaseAdvertisingParams<CommissionA
{
if (deviceName.HasValue())
{
strncpy(sDeviceName, deviceName.Value(), min(strlen(deviceName.Value()) + 1, sizeof(sDeviceName)));
mDeviceName = Optional<const char *>::Value(static_cast<const char *>(sDeviceName));
chip::Platform::CopyString(mDeviceName, sizeof(mDeviceName), deviceName.Value());
mDeviceNameHasValue = true;
}
else
{
mDeviceNameHasValue = false;
}
return *this;
}
Optional<const char *> GetDeviceName() const { return mDeviceName; }
Optional<const char *> GetDeviceName() const
{
return mDeviceNameHasValue ? Optional<const char *>::Value(mDeviceName) : Optional<const char *>::Missing();
}

CommissionAdvertisingParameters & SetRotatingId(Optional<const char *> rotatingId)
{
if (rotatingId.HasValue())
{
strncpy(sRotatingId, rotatingId.Value(), min(strlen(rotatingId.Value()) + 1, sizeof(sRotatingId)));
mRotatingId = Optional<const char *>::Value(static_cast<const char *>(sRotatingId));
chip::Platform::CopyString(mRotatingId, sizeof(mRotatingId), rotatingId.Value());
mRotatingIdHasValue = true;
}
else
{
mRotatingIdHasValue = false;
}
return *this;
}
Optional<const char *> GetRotatingId() const { return mRotatingId; }
Optional<const char *> GetRotatingId() const
{
return mRotatingIdHasValue ? Optional<const char *>::Value(mRotatingId) : Optional<const char *>::Missing();
}

CommissionAdvertisingParameters & SetPairingInstr(Optional<const char *> pairingInstr)
{
if (pairingInstr.HasValue())
{
strncpy(sPairingInstr, pairingInstr.Value(), min(strlen(pairingInstr.Value()) + 1, sizeof(sPairingInstr)));
mPairingInstr = Optional<const char *>::Value(static_cast<const char *>(sPairingInstr));
chip::Platform::CopyString(mPairingInstr, sizeof(mPairingInstr), pairingInstr.Value());
mPairingInstrHasValue = true;
}
else
{
mPairingInstrHasValue = false;
}
return *this;
}
Optional<const char *> GetPairingInstr() const { return mPairingInstr; }
Optional<const char *> GetPairingInstr() const
{
return mPairingInstrHasValue ? Optional<const char *>::Value(mPairingInstr) : Optional<const char *>::Missing();
}

CommissionAdvertisingParameters & SetPairingHint(Optional<uint16_t> pairingHint)
{
Expand All @@ -233,14 +255,14 @@ class CommissionAdvertisingParameters : public BaseAdvertisingParams<CommissionA
chip::Optional<uint16_t> mDeviceType;
chip::Optional<uint16_t> mPairingHint;

char sDeviceName[kKeyDeviceNameMaxLength + 1];
chip::Optional<const char *> mDeviceName;
char mDeviceName[kKeyDeviceNameMaxLength + 1];
bool mDeviceNameHasValue = false;

char sRotatingId[kKeyRotatingIdMaxLength + 1];
chip::Optional<const char *> mRotatingId;
char mRotatingId[kKeyRotatingIdMaxLength + 1];
bool mRotatingIdHasValue = false;

char sPairingInstr[kKeyPairingInstructionMaxLength + 1];
chip::Optional<const char *> mPairingInstr;
char mPairingInstr[kKeyPairingInstructionMaxLength + 1];
bool mPairingInstrHasValue = false;
};

/// Handles advertising of CHIP nodes
Expand All @@ -264,6 +286,9 @@ class ServiceAdvertiser

/// Provides the system-wide implementation of the service advertiser
static ServiceAdvertiser & Instance();

/// Returns DNS-SD instance name formatted as hex string
virtual CHIP_ERROR GetCommissionableInstanceName(char * instanceName, size_t maxLength) = 0;
};

} // namespace Mdns
Expand Down
48 changes: 33 additions & 15 deletions src/lib/mdns/Advertiser_ImplMinimalMdns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class AdvertiserMinMdns : public ServiceAdvertiser,
CHIP_ERROR Advertise(const OperationalAdvertisingParameters & params) override;
CHIP_ERROR Advertise(const CommissionAdvertisingParameters & params) override;
CHIP_ERROR StopPublishDevice() override;
CHIP_ERROR GetCommissionableInstanceName(char * instanceName, size_t maxLength) override;

// MdnsPacketDelegate
void OnMdnsPacketData(const BytesRange & data, const chip::Inet::IPPacketInfo * info) override;
Expand Down Expand Up @@ -146,6 +147,8 @@ class AdvertiserMinMdns : public ServiceAdvertiser,
QueryResponderAllocator<kMaxCommissionRecords> mQueryResponderAllocatorCommissioner;

ResponseSender mResponseSender;
uint32_t mCommissionInstanceName1;
uint32_t mCommissionInstanceName2;

// current request handling
const chip::Inet::IPPacketInfo * mCurrentSource = nullptr;
Expand Down Expand Up @@ -191,6 +194,9 @@ CHIP_ERROR AdvertiserMinMdns::Start(chip::Inet::InetLayer * inetLayer, uint16_t
{
GlobalMinimalMdnsServer::Server().Shutdown();

mCommissionInstanceName1 = GetRandU32();
mCommissionInstanceName2 = GetRandU32();

ReturnErrorOnFailure(GlobalMinimalMdnsServer::Instance().StartServer(inetLayer, port));

ChipLogProgress(Discovery, "CHIP minimal mDNS started advertising.");
Expand Down Expand Up @@ -277,8 +283,23 @@ CHIP_ERROR AdvertiserMinMdns::Advertise(const OperationalAdvertisingParameters &
return CHIP_NO_ERROR;
}

CHIP_ERROR AdvertiserMinMdns::GetCommissionableInstanceName(char * instanceName, size_t maxLength)
{
if (maxLength < (kMaxInstanceNameSize + 1))
{
return CHIP_ERROR_NO_MEMORY;
}
size_t len = snprintf(instanceName, maxLength, ChipLogFormatX64, mCommissionInstanceName1, mCommissionInstanceName2);
if (len >= maxLength)
{
return CHIP_ERROR_NO_MEMORY;
}
return CHIP_NO_ERROR;
}

CHIP_ERROR AdvertiserMinMdns::Advertise(const CommissionAdvertisingParameters & params)
{

// TODO: When multi-admin is enabled, operational does not need to be cleared here.
if (params.GetCommissionAdvertiseMode() == CommssionAdvertiseMode::kCommissionableNode)
{
Expand All @@ -291,11 +312,8 @@ CHIP_ERROR AdvertiserMinMdns::Advertise(const CommissionAdvertisingParameters &

// TODO: need to detect colisions here
char nameBuffer[64] = "";
size_t len = snprintf(nameBuffer, sizeof(nameBuffer), ChipLogFormatX64, GetRandU32(), GetRandU32());
if (len >= sizeof(nameBuffer))
{
return CHIP_ERROR_NO_MEMORY;
}
ReturnErrorOnFailure(GetCommissionableInstanceName(nameBuffer, sizeof(nameBuffer)));

QueryResponderAllocator<kMaxCommissionRecords> * allocator =
params.GetCommissionAdvertiseMode() == CommssionAdvertiseMode::kCommissionableNode ? &mQueryResponderAllocatorCommissionable
: &mQueryResponderAllocatorCommissioner;
Expand Down Expand Up @@ -486,26 +504,26 @@ FullQName AdvertiserMinMdns::GetCommisioningTextEntries(const CommissionAdvertis
char txtVidPid[chip::Mdns::kKeyVendorProductMaxLength + 4];
if (params.GetProductId().HasValue() && params.GetVendorId().HasValue())
{
sprintf(txtVidPid, "VP=%d+%d", params.GetVendorId().Value(), params.GetProductId().Value());
snprintf(txtVidPid, sizeof(txtVidPid), "VP=%d+%d", params.GetVendorId().Value(), params.GetProductId().Value());
txtFields[numTxtFields++] = txtVidPid;
}
else if (params.GetVendorId().HasValue())
{
sprintf(txtVidPid, "VP=%d", params.GetVendorId().Value());
snprintf(txtVidPid, sizeof(txtVidPid), "VP=%d", params.GetVendorId().Value());
txtFields[numTxtFields++] = txtVidPid;
}

char txtDeviceType[chip::Mdns::kKeyDeviceTypeMaxLength + 4];
if (params.GetDeviceType().HasValue())
{
sprintf(txtDeviceType, "DT=%d", params.GetDeviceType().Value());
snprintf(txtDeviceType, sizeof(txtDeviceType), "DT=%d", params.GetDeviceType().Value());
txtFields[numTxtFields++] = txtDeviceType;
}

char txtDeviceName[chip::Mdns::kKeyDeviceNameMaxLength + 4];
if (params.GetDeviceName().HasValue())
{
sprintf(txtDeviceName, "DN=%s", params.GetDeviceName().Value());
snprintf(txtDeviceName, sizeof(txtDeviceName), "DN=%s", params.GetDeviceName().Value());
txtFields[numTxtFields++] = txtDeviceName;
}

Expand All @@ -514,7 +532,7 @@ FullQName AdvertiserMinMdns::GetCommisioningTextEntries(const CommissionAdvertis
{
// a discriminator always exists
char txtDiscriminator[chip::Mdns::kKeyDiscriminatorMaxLength + 3];
sprintf(txtDiscriminator, "D=%d", params.GetLongDiscriminator());
snprintf(txtDiscriminator, sizeof(txtDiscriminator), "D=%d", params.GetLongDiscriminator());
txtFields[numTxtFields++] = txtDiscriminator;

if (!params.GetVendorId().HasValue())
Expand All @@ -523,34 +541,34 @@ FullQName AdvertiserMinMdns::GetCommisioningTextEntries(const CommissionAdvertis
}

char txtCommissioningMode[chip::Mdns::kKeyCommissioningModeMaxLength + 4];
sprintf(txtCommissioningMode, "CM=%d", params.GetCommissioningMode() ? 1 : 0);
snprintf(txtCommissioningMode, sizeof(txtCommissioningMode), "CM=%d", params.GetCommissioningMode() ? 1 : 0);
txtFields[numTxtFields++] = txtCommissioningMode;

char txtOpenWindowCommissioningMode[chip::Mdns::kKeyAdditionalPairingMaxLength + 4];
if (params.GetCommissioningMode() && params.GetOpenWindowCommissioningMode())
{
sprintf(txtOpenWindowCommissioningMode, "AP=1");
snprintf(txtOpenWindowCommissioningMode, sizeof(txtOpenWindowCommissioningMode), "AP=1");
txtFields[numTxtFields++] = txtOpenWindowCommissioningMode;
}

char txtRotatingDeviceId[chip::Mdns::kKeyRotatingIdMaxLength + 4];
if (params.GetRotatingId().HasValue())
{
sprintf(txtRotatingDeviceId, "RI=%s", params.GetRotatingId().Value());
snprintf(txtRotatingDeviceId, sizeof(txtRotatingDeviceId), "RI=%s", params.GetRotatingId().Value());
txtFields[numTxtFields++] = txtRotatingDeviceId;
}

char txtPairingHint[chip::Mdns::kKeyPairingInstructionMaxLength + 4];
if (params.GetPairingHint().HasValue())
{
sprintf(txtPairingHint, "PH=%d", params.GetPairingHint().Value());
snprintf(txtPairingHint, sizeof(txtPairingHint), "PH=%d", params.GetPairingHint().Value());
txtFields[numTxtFields++] = txtPairingHint;
}

char txtPairingInstr[chip::Mdns::kKeyPairingInstructionMaxLength + 4];
if (params.GetPairingInstr().HasValue())
{
sprintf(txtPairingInstr, "PI=%s", params.GetPairingInstr().Value());
snprintf(txtPairingInstr, sizeof(txtPairingInstr), "PI=%s", params.GetPairingInstr().Value());
txtFields[numTxtFields++] = txtPairingInstr;
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/lib/mdns/Advertiser_ImplNone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ class NoneAdvertiser : public ServiceAdvertiser
ChipLogError(Discovery, "mDNS advertising not available. mDNS stop not available.");
return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR GetCommissionableInstanceName(char * instanceName, size_t maxLength) override
{
ChipLogError(Discovery, "mDNS advertising not available. mDNS GetCommissionableInstanceName not available.");
return CHIP_ERROR_NOT_IMPLEMENTED;
}
};

NoneAdvertiser gAdvertiser;
Expand Down
19 changes: 17 additions & 2 deletions src/lib/mdns/Discovery_ImplPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,21 @@ void DiscoveryImplPlatform::HandleMdnsError(void * context, CHIP_ERROR error)
}
}

CHIP_ERROR DiscoveryImplPlatform::GetCommissionableInstanceName(char * instanceName, size_t maxLength)
{
if (maxLength < (chip::Mdns::kMaxInstanceNameSize + 1))
{
return CHIP_ERROR_NO_MEMORY;
}
size_t len = snprintf(instanceName, maxLength, "%08" PRIX32 "%08" PRIX32, static_cast<uint32_t>(mCommissionInstanceName >> 32),
static_cast<uint32_t>(mCommissionInstanceName));
if (len >= maxLength)
{
return CHIP_ERROR_NO_MEMORY;
}
return CHIP_NO_ERROR;
}

CHIP_ERROR DiscoveryImplPlatform::Advertise(const CommissionAdvertisingParameters & params)
{
CHIP_ERROR error = CHIP_NO_ERROR;
Expand Down Expand Up @@ -143,8 +158,8 @@ CHIP_ERROR DiscoveryImplPlatform::Advertise(const CommissionAdvertisingParameter
return error;
}

snprintf(service.mName, sizeof(service.mName), "%08" PRIX32 "%08" PRIX32, static_cast<uint32_t>(mCommissionInstanceName >> 32),
static_cast<uint32_t>(mCommissionInstanceName));
ReturnErrorOnFailure(GetCommissionableInstanceName(service.mName, sizeof(service.mName)));

if (params.GetCommissionAdvertiseMode() == CommssionAdvertiseMode::kCommissionableNode)
{
strncpy(service.mType, kCommissionableServiceName, sizeof(service.mType));
Expand Down
3 changes: 3 additions & 0 deletions src/lib/mdns/Discovery_ImplPlatform.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ class DiscoveryImplPlatform : public ServiceAdvertiser, public Resolver
/// This function stops publishing the device on mDNS.
CHIP_ERROR StopPublishDevice() override;

/// Returns DNS-SD instance name formatted as hex string
CHIP_ERROR GetCommissionableInstanceName(char * instanceName, size_t maxLength) override;

/// Registers a resolver delegate if none has been registered before
CHIP_ERROR SetResolverDelegate(ResolverDelegate * delegate) override;

Expand Down
Loading

0 comments on commit dac287b

Please sign in to comment.