Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add _I subtype to operational discovery. #9754

Merged
merged 5 commits into from
Sep 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ using namespace ::chip;
CHIP_ERROR DiscoverCommissionablesCommand::Run()
{
mCommissioner = GetExecContext()->commissioner;
Mdns::DiscoveryFilter filter(Mdns::DiscoveryFilterType::kNone, (uint16_t) 0);
Mdns::DiscoveryFilter filter(Mdns::DiscoveryFilterType::kNone, (uint64_t) 0);
return mCommissioner->DiscoverCommissionableNodes(filter);
}

Expand Down
2 changes: 1 addition & 1 deletion examples/platform/linux/ControllerShellCommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ static CHIP_ERROR discover(bool printHeader)
streamer_printf(sout, "Discover: ");
}

Mdns::DiscoveryFilter filter(Mdns::DiscoveryFilterType::kNone, (uint16_t) 0);
Mdns::DiscoveryFilter filter(Mdns::DiscoveryFilterType::kNone, (uint64_t) 0);
gCommissioner->DiscoverCommissionableNodes(filter);

streamer_printf(sout, "done\r\n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ ChipError::StorageType pychip_DeviceController_CloseSession(chip::Controller::De

ChipError::StorageType pychip_DeviceController_DiscoverAllCommissionableNodes(chip::Controller::DeviceCommissioner * devCtrl)
{
Mdns::DiscoveryFilter filter(Mdns::DiscoveryFilterType::kNone, static_cast<uint16_t>(0));
Mdns::DiscoveryFilter filter(Mdns::DiscoveryFilterType::kNone, static_cast<uint64_t>(0));
return devCtrl->DiscoverCommissionableNodes(filter).AsInteger();
}

Expand Down
16 changes: 9 additions & 7 deletions src/lib/mdns/Advertiser.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,15 @@ static constexpr size_t kKeyPairingInstructionMaxLength = 128;
static constexpr size_t kKeyPairingHintMaxLength = 10;

// Commissionable/commissioner node subtypes
static constexpr size_t kSubTypeShortDiscriminatorMaxLength = 4; // _S<dd>
static constexpr size_t kSubTypeLongDiscriminatorMaxLength = 6; // _L<dddd>
static constexpr size_t kSubTypeVendorMaxLength = 7; // _V<ddddd>
static constexpr size_t kSubTypeDeviceTypeMaxLength = 5; // _T<ddd>
static constexpr size_t kSubTypeCommissioningModeMaxLength = 3; // _C<d>
static constexpr size_t kSubTypeAdditionalCommissioningMaxLength = 3; // _A<d>
static constexpr size_t kSubTypeMaxNumber = 6;
static constexpr size_t kSubTypeShortDiscriminatorMaxLength = 4; // _S<dd>
static constexpr size_t kSubTypeLongDiscriminatorMaxLength = 6; // _L<dddd>
static constexpr size_t kSubTypeVendorMaxLength = 7; // _V<ddddd>
static constexpr size_t kSubTypeDeviceTypeMaxLength = 5; // _T<ddd>
static constexpr size_t kSubTypeCommissioningModeMaxLength = 3; // _C<d>
static constexpr size_t kSubTypeAdditionalCommissioningMaxLength = 3; // _A<d>
static constexpr size_t kSubTypeCompressedFabricIdMaxLength = 18; //_I<16-hex-digits>
// These are the max vals for comissioning adverts
static constexpr size_t kSubTypeMaxNumber = 6;
static constexpr size_t kSubTypeTotalLength = kSubTypeShortDiscriminatorMaxLength + kSubTypeLongDiscriminatorMaxLength +
kSubTypeVendorMaxLength + kSubTypeDeviceTypeMaxLength + kSubTypeCommissioningModeMaxLength +
kSubTypeAdditionalCommissioningMaxLength;
Expand Down
44 changes: 28 additions & 16 deletions src/lib/mdns/Advertiser_ImplMinimalMdns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ class AdvertiserMinMdns : public ServiceAdvertiser,
return CHIP_NO_ERROR;
}

// Max number of records for operational = PTR, SRV, TXT, A, AAAA, no subtypes.
static constexpr size_t kMaxOperationalRecords = 5;
// Max number of records for operational = PTR, SRV, TXT, A, AAAA, I subtype.
static constexpr size_t kMaxOperationalRecords = 6;
static constexpr size_t kMaxOperationalNetworks = 5;
QueryResponderAllocator<kMaxOperationalRecords> mQueryResponderAllocatorOperational[kMaxOperationalNetworks];
// Max number of records for commissionable = 7 x PTR (base + 6 sub types - _S, _L, _D, _T, _C, _A), SRV, TXT, A, AAAA
Expand Down Expand Up @@ -342,60 +342,72 @@ CHIP_ERROR AdvertiserMinMdns::Advertise(const OperationalAdvertisingParameters &
}
}

FullQName operationalServiceName =
operationalAllocator->AllocateQName(kOperationalServiceName, kOperationalProtocol, kLocalDomain);
FullQName operationalServerName =
FullQName serviceName = operationalAllocator->AllocateQName(kOperationalServiceName, kOperationalProtocol, kLocalDomain);
FullQName instanceName =
operationalAllocator->AllocateQName(nameBuffer, kOperationalServiceName, kOperationalProtocol, kLocalDomain);

ReturnErrorOnFailure(MakeHostName(nameBuffer, sizeof(nameBuffer), params.GetMac()));
FullQName serverName = operationalAllocator->AllocateQName(nameBuffer, kLocalDomain);
FullQName hostName = operationalAllocator->AllocateQName(nameBuffer, kLocalDomain);

if ((operationalServiceName.nameCount == 0) || (operationalServerName.nameCount == 0) || (serverName.nameCount == 0))
if ((serviceName.nameCount == 0) || (instanceName.nameCount == 0) || (hostName.nameCount == 0))
{
ChipLogError(Discovery, "Failed to allocate QNames.");
return CHIP_ERROR_NO_MEMORY;
}

if (!operationalAllocator->AddResponder<PtrResponder>(operationalServiceName, operationalServerName)
.SetReportAdditional(operationalServerName)
if (!operationalAllocator->AddResponder<PtrResponder>(serviceName, instanceName)
.SetReportAdditional(instanceName)
.SetReportInServiceListing(true)
.IsValid())
{
ChipLogError(Discovery, "Failed to add service PTR record mDNS responder");
return CHIP_ERROR_NO_MEMORY;
}

if (!operationalAllocator->AddResponder<SrvResponder>(SrvResourceRecord(operationalServerName, serverName, params.GetPort()))
.SetReportAdditional(serverName)
if (!operationalAllocator->AddResponder<SrvResponder>(SrvResourceRecord(instanceName, hostName, params.GetPort()))
.SetReportAdditional(hostName)
.IsValid())
{
ChipLogError(Discovery, "Failed to add SRV record mDNS responder");
return CHIP_ERROR_NO_MEMORY;
}

if (!operationalAllocator
->AddResponder<TxtResponder>(TxtResourceRecord(operationalServerName, GetOperationalTxtEntries(params)))
.SetReportAdditional(serverName)
if (!operationalAllocator->AddResponder<TxtResponder>(TxtResourceRecord(instanceName, GetOperationalTxtEntries(params)))
.SetReportAdditional(hostName)
.IsValid())
{
ChipLogError(Discovery, "Failed to add TXT record mDNS responder");
return CHIP_ERROR_NO_MEMORY;
}

if (!operationalAllocator->AddResponder<IPv6Responder>(serverName).IsValid())
if (!operationalAllocator->AddResponder<IPv6Responder>(hostName).IsValid())
{
ChipLogError(Discovery, "Failed to add IPv6 mDNS responder");
return CHIP_ERROR_NO_MEMORY;
}

if (params.IsIPv4Enabled())
{
if (!operationalAllocator->AddResponder<IPv4Responder>(serverName).IsValid())
if (!operationalAllocator->AddResponder<IPv4Responder>(hostName).IsValid())
{
ChipLogError(Discovery, "Failed to add IPv4 mDNS responder");
return CHIP_ERROR_NO_MEMORY;
}
}
MakeServiceSubtype(nameBuffer, sizeof(nameBuffer),
DiscoveryFilter(DiscoveryFilterType::kCompressedFabricId, params.GetPeerId().GetCompressedFabricId()));
FullQName compressedFabricIdSubtype = operationalAllocator->AllocateQName(
nameBuffer, kSubtypeServiceNamePart, kOperationalServiceName, kOperationalProtocol, kLocalDomain);
ReturnErrorCodeIf(compressedFabricIdSubtype.nameCount == 0, CHIP_ERROR_NO_MEMORY);

if (!operationalAllocator->AddResponder<PtrResponder>(compressedFabricIdSubtype, instanceName)
.SetReportAdditional(instanceName)
.SetReportInServiceListing(true)
.IsValid())
{
ChipLogError(Discovery, "Failed to add device type PTR record mDNS responder");
return CHIP_ERROR_NO_MEMORY;
}

ChipLogProgress(Discovery, "CHIP minimal mDNS configured as 'Operational device'.");

Expand Down
13 changes: 12 additions & 1 deletion src/lib/mdns/Discovery_ImplPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,10 @@ CHIP_ERROR DiscoveryImplPlatform::Advertise(const OperationalAdvertisingParamete
MdnsService service;
CHIP_ERROR error = CHIP_NO_ERROR;

char compressedFabricIdSub[kSubTypeCompressedFabricIdMaxLength + 1];
const char * subTypes[1];
size_t subTypeSize = 0;

mOperationalAdvertisingParams = params;
// TODO: There may be multilple device/fabric ids after multi-admin.

Expand All @@ -393,6 +397,12 @@ CHIP_ERROR DiscoveryImplPlatform::Advertise(const OperationalAdvertisingParamete
ReturnLogErrorOnFailure(
AddCommonTxtElements(params, mrpRetryIntervalIdleBuf, mrpRetryIntervalActiveBuf, txtEntries, textEntrySize));

if (MakeServiceSubtype(compressedFabricIdSub, sizeof(compressedFabricIdSub),
DiscoveryFilter(DiscoveryFilterType::kCompressedFabricId, params.GetPeerId().GetCompressedFabricId())) ==
CHIP_NO_ERROR)
{
subTypes[subTypeSize++] = compressedFabricIdSub;
}
error = MakeHostName(service.mHostName, sizeof(service.mHostName), params.GetMac());
if (error != CHIP_NO_ERROR)
{
Expand All @@ -407,7 +417,8 @@ CHIP_ERROR DiscoveryImplPlatform::Advertise(const OperationalAdvertisingParamete
service.mTextEntrySize = textEntrySize;
service.mInterface = INET_NULL_INTERFACEID;
service.mAddressType = Inet::kIPAddressType_Any;
service.mSubTypeSize = 0;
service.mSubTypes = subTypes;
service.mSubTypeSize = subTypeSize;
error = ChipMdnsPublishService(&service);

if (error == CHIP_NO_ERROR)
Expand Down
7 changes: 4 additions & 3 deletions src/lib/mdns/Resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,16 +208,17 @@ enum class DiscoveryFilterType : uint8_t
kDeviceType,
kCommissioningMode,
kInstanceName,
kCommissioner
kCommissioner,
kCompressedFabricId,
};
struct DiscoveryFilter
{
DiscoveryFilterType type;
uint16_t code;
uint64_t code;
const char * instanceName;
DiscoveryFilter() : type(DiscoveryFilterType::kNone), code(0) {}
DiscoveryFilter(DiscoveryFilterType newType) : type(newType) {}
DiscoveryFilter(DiscoveryFilterType newType, uint16_t newCode) : type(newType), code(newCode) {}
DiscoveryFilter(DiscoveryFilterType newType, uint64_t newCode) : type(newType), code(newCode) {}
DiscoveryFilter(DiscoveryFilterType newType, const char * newInstanceName) : type(newType), instanceName(newInstanceName) {}
};
enum class DiscoveryType
Expand Down
26 changes: 19 additions & 7 deletions src/lib/mdns/ServiceNaming.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,24 +103,26 @@ CHIP_ERROR MakeServiceSubtype(char * buffer, size_t bufferLen, DiscoveryFilter s
{
return CHIP_ERROR_INVALID_ARGUMENT;
}
requiredSize = snprintf(buffer, bufferLen, "_S%u", subtype.code);
requiredSize = snprintf(buffer, bufferLen, "_S%" PRIu16, static_cast<uint16_t>(subtype.code));
break;
case DiscoveryFilterType::kLong:
// 12-bit number
if (subtype.code >= 1 << 12)
{
return CHIP_ERROR_INVALID_ARGUMENT;
}
requiredSize = snprintf(buffer, bufferLen, "_L%u", subtype.code);
requiredSize = snprintf(buffer, bufferLen, "_L%" PRIu16, static_cast<uint16_t>(subtype.code));
break;
case DiscoveryFilterType::kVendor:
// Vendor ID is 16-bit, so if it fits in the code, it's good.
// NOTE: size here is wrong, will be changed in upcming PR to remove leading zeros.
requiredSize = snprintf(buffer, bufferLen, "_V%u", subtype.code);
if (subtype.code >= 1 << 16)
{
return CHIP_ERROR_INVALID_ARGUMENT;
}
requiredSize = snprintf(buffer, bufferLen, "_V%" PRIu16, static_cast<uint16_t>(subtype.code));
break;
case DiscoveryFilterType::kDeviceType:
// TODO: Not totally clear the size required here: see spec issue #3226
requiredSize = snprintf(buffer, bufferLen, "_T%u", subtype.code);
requiredSize = snprintf(buffer, bufferLen, "_T%" PRIu16, static_cast<uint16_t>(subtype.code));
break;
case DiscoveryFilterType::kCommissioningMode:
requiredSize = snprintf(buffer, bufferLen, "_CM");
Expand All @@ -130,7 +132,12 @@ CHIP_ERROR MakeServiceSubtype(char * buffer, size_t bufferLen, DiscoveryFilter s
{
return CHIP_ERROR_INVALID_ARGUMENT;
}
requiredSize = snprintf(buffer, bufferLen, "_D%u", subtype.code);
requiredSize = snprintf(buffer, bufferLen, "_D%" PRIu16, static_cast<uint16_t>(subtype.code));
break;
case DiscoveryFilterType::kCompressedFabricId:
requiredSize = snprintf(buffer, bufferLen, "_I");
return Encoding::BytesToHex(subtype.code, &buffer[requiredSize], bufferLen - requiredSize,
Encoding::HexFlags::kUppercaseAndNullTerminate);
break;
case DiscoveryFilterType::kInstanceName:
requiredSize = snprintf(buffer, bufferLen, "%s", subtype.instanceName);
Expand Down Expand Up @@ -175,6 +182,11 @@ CHIP_ERROR MakeServiceTypeName(char * buffer, size_t bufferLen, DiscoveryFilter
requiredSize =
snprintf(buffer + subtypeLen, bufferLen - subtypeLen, ".%s.%s", kSubtypeServiceNamePart, kCommissionerServiceName);
}
else if (type == DiscoveryType::kOperational)
{
requiredSize =
snprintf(buffer + subtypeLen, bufferLen - subtypeLen, ".%s.%s", kSubtypeServiceNamePart, kOperationalServiceName);
}
else
{
return CHIP_ERROR_NOT_IMPLEMENTED;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/mdns/ServiceNaming.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

namespace chip {
namespace Mdns {
constexpr size_t kMaxSubtypeDescSize = 16; // max 16 char service name
constexpr size_t kMaxSubtypeDescSize = 19; // _I service subtype = 16 chars for 64-bit id, + 2 for "_I" + nullchar
constexpr char kSubtypeServiceNamePart[] = "_sub";
constexpr char kCommissionableServiceName[] = "_matterc";
constexpr char kOperationalServiceName[] = "_matter";
Expand Down
4 changes: 4 additions & 0 deletions src/lib/mdns/minimal/tests/CheckOnlyServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ class CheckOnlyServer : public ServerBase, public ParserDelegate, public TxtReco
if (!header.GetFlags().IsTruncated())
{
NL_TEST_ASSERT(mInSuite, mTotalRecords == GetNumExpectedRecords());
if (mTotalRecords != GetNumExpectedRecords())
{
ChipLogError(Discovery, "Received %d records, expected %d", mTotalRecords, GetNumExpectedRecords());
}
mHeaderFound = true;
}
}
Expand Down
13 changes: 13 additions & 0 deletions src/lib/mdns/minimal/tests/TestAdvertiser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ const QNamePart kInstanceNameParts2[] = { "5555666677778888-1212343456
const FullQName kInstanceName2 = FullQName(kInstanceNameParts2);
const QNamePart kTxtRecordEmptyParts[] = { "=" };
const FullQName kTxtRecordEmptyName = FullQName(kTxtRecordEmptyParts);
const QNamePart kCompressedIdSubParts1[] = { "_IBEEFBEEFF00DF00D", "_sub", "_matter", "_tcp", "local" };
FullQName kCompressedIdSubName1 = FullQName(kCompressedIdSubParts1);
const QNamePart kCompressedIdSubParts2[] = { "_I5555666677778888", "_sub", "_matter", "_tcp", "local" };
FullQName kCompressedIdSubName2 = FullQName(kCompressedIdSubParts2);
PtrResourceRecord ptrServiceSubCompressedId1 = PtrResourceRecord(kDnsSdQueryName, kCompressedIdSubName1);
PtrResourceRecord ptrServiceSubCompressedId2 = PtrResourceRecord(kDnsSdQueryName, kCompressedIdSubName2);

OperationalAdvertisingParameters operationalParams1 =
OperationalAdvertisingParameters()
.SetPeerId(kPeerId1)
Expand Down Expand Up @@ -215,6 +222,7 @@ void OperationalAdverts(nlTestSuite * inSuite, void * inContext)
// Test for PTR response to _services request.
ChipLogProgress(Discovery, "Checking response to _services._dns-sd._udp.local");
server.AddExpectedRecord(&ptrOperationalService);
server.AddExpectedRecord(&ptrServiceSubCompressedId1);
NL_TEST_ASSERT(inSuite, SendQuery(kDnsSdQueryName) == CHIP_NO_ERROR);

// These check that the requested records added are sent out correctly.
Expand Down Expand Up @@ -251,6 +259,7 @@ void OperationalAdverts(nlTestSuite * inSuite, void * inContext)
ChipLogProgress(Discovery, "Checking response to _services._dns-sd._udp.local");
server.Reset();
server.AddExpectedRecord(&ptrOperationalService);
server.AddExpectedRecord(&ptrServiceSubCompressedId1);
NL_TEST_ASSERT(inSuite, SendQuery(kDnsSdQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
Expand All @@ -275,6 +284,8 @@ void OperationalAdverts(nlTestSuite * inSuite, void * inContext)
ChipLogProgress(Discovery, "Checking response to _services._dns-sd._udp.local");
server.AddExpectedRecord(&ptrOperationalService);
server.AddExpectedRecord(&ptrOperationalService);
server.AddExpectedRecord(&ptrServiceSubCompressedId1);
server.AddExpectedRecord(&ptrServiceSubCompressedId2);
NL_TEST_ASSERT(inSuite, SendQuery(kDnsSdQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
Expand Down Expand Up @@ -456,6 +467,8 @@ void CommissionableAndOperationalAdverts(nlTestSuite * inSuite, void * inContext
server.AddExpectedRecord(&ptrServiceSubCM);
server.AddExpectedRecord(&ptrServiceSubVendor);
server.AddExpectedRecord(&ptrServiceSubDeviceType);
server.AddExpectedRecord(&ptrServiceSubCompressedId1);
server.AddExpectedRecord(&ptrServiceSubCompressedId2);
NL_TEST_ASSERT(inSuite, SendQuery(kDnsSdQueryName) == CHIP_NO_ERROR);
NL_TEST_ASSERT(inSuite, server.GetSendCalled());
NL_TEST_ASSERT(inSuite, server.GetHeaderFound());
Expand Down
4 changes: 3 additions & 1 deletion src/lib/mdns/platform/tests/TestPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ test::ExpectedCall operationalCall1 = test::ExpectedCall()
.SetProtocol(MdnsServiceProtocol::kMdnsProtocolTcp)
.SetServiceName("_matter")
.SetInstanceName("BEEFBEEFF00DF00D-1111222233334444")
.SetHostName(host);
.SetHostName(host)
.AddSubtype("_IBEEFBEEFF00DF00D");
OperationalAdvertisingParameters operationalParams2 = OperationalAdvertisingParameters()
.SetPeerId(kPeerId2)
.SetMac(ByteSpan(kMac))
Expand All @@ -55,6 +56,7 @@ test::ExpectedCall operationalCall2 = test::ExpectedCall()
.SetServiceName("_matter")
.SetInstanceName("5555666677778888-1212343456567878")
.SetHostName(host)
.AddSubtype("_I5555666677778888")
.AddTxt("CRI", "32")
.AddTxt("CRA", "33");

Expand Down
Loading