26
26
#include < lib/support/logging/CHIPLogging.h>
27
27
#include < platform/CHIPDeviceLayer.h>
28
28
29
+ using namespace chip ;
29
30
using namespace chip ::Dnssd;
30
31
using namespace chip ::Dnssd::Internal;
31
32
32
33
namespace {
33
34
34
- constexpr char kLocalDot [] = " local." ;
35
+ // The extra time in milliseconds that we will wait for the resolution on the open thread domain to complete.
36
+ constexpr uint16_t kOpenThreadTimeoutInMsec = 250 ;
37
+
38
+ static bool hasOpenThreadTimerStarted = false ;
35
39
36
40
constexpr DNSServiceFlags kRegisterFlags = kDNSServiceFlagsNoAutoRename ;
37
- constexpr DNSServiceFlags kBrowseFlags = 0 ;
41
+ constexpr DNSServiceFlags kBrowseFlags = kDNSServiceFlagsShareConnection ;
38
42
constexpr DNSServiceFlags kGetAddrInfoFlags = kDNSServiceFlagsTimeout | kDNSServiceFlagsShareConnection ;
39
43
constexpr DNSServiceFlags kResolveFlags = kDNSServiceFlagsShareConnection ;
40
44
constexpr DNSServiceFlags kReconfirmRecordFlags = 0 ;
@@ -49,11 +53,27 @@ uint32_t GetInterfaceId(chip::Inet::InterfaceId interfaceId)
49
53
return interfaceId.IsPresent () ? interfaceId.GetPlatformInterface () : kDNSServiceInterfaceIndexAny ;
50
54
}
51
55
52
- std::string GetHostNameWithDomain (const char * hostname)
56
+ std::string GetHostNameWithLocalDomain (const char * hostname)
53
57
{
54
58
return std::string (hostname) + ' .' + kLocalDot ;
55
59
}
56
60
61
+ bool HostNameHasDomain (const char * hostname, const char * domain)
62
+ {
63
+ size_t domainLength = strlen (domain);
64
+ size_t hostnameLength = strlen (hostname);
65
+ if (domainLength > hostnameLength)
66
+ {
67
+ return false ;
68
+ }
69
+ const char * found = strstr (hostname, domain);
70
+ if (found == nullptr )
71
+ {
72
+ return false ;
73
+ }
74
+ return (strncmp (found, domain, domainLength) == 0 );
75
+ }
76
+
57
77
void LogOnFailure (const char * name, DNSServiceErrorType err)
58
78
{
59
79
if (kDNSServiceErr_NoError != err)
@@ -131,10 +151,54 @@ std::shared_ptr<uint32_t> GetCounterHolder(const char * name)
131
151
namespace chip {
132
152
namespace Dnssd {
133
153
154
+
155
+ std::string GetDomainNameFromHostName (const char * hostname)
156
+ {
157
+ if (HostNameHasDomain (hostname, kLocalDot ))
158
+ {
159
+ return std::string (kLocalDot );
160
+ }
161
+ else if (HostNameHasDomain (hostname, kOpenThreadDot ))
162
+ {
163
+ return std::string (kOpenThreadDot );
164
+ }
165
+ return std::string ();
166
+ }
167
+
134
168
Global<MdnsContexts> MdnsContexts::sInstance ;
135
169
136
170
namespace {
137
171
172
+ /* *
173
+ * @brief Callback that is called when the timeout for resolving on the kOpenThreadDot domain has expired.
174
+ *
175
+ * @param[in] systemLayer The system layer.
176
+ * @param[in] callbackContext The context passed to the timer callback.
177
+ */
178
+ void OpenThreadTimerExpiredCallback (System::Layer * systemLayer, void * callbackContext)
179
+ {
180
+ ChipLogProgress (Discovery, " Mdns: Resolve completed on the open thread domain." );
181
+ VerifyOrReturn (callbackContext != nullptr && systemLayer != nullptr , ChipLogError (Discovery, " Open thread timer callback context is null" ));
182
+
183
+ auto sdCtx = reinterpret_cast <ResolveContext *>(callbackContext);
184
+ VerifyOrReturn (sdCtx != nullptr , ChipLogError (Discovery, " Resolve Context is null" ));
185
+ sdCtx->Finalize ();
186
+ hasOpenThreadTimerStarted = false ;
187
+ }
188
+
189
+ /* *
190
+ * @brief Starts a timer to wait for the resolution on the kOpenThreadDot domain to happen.
191
+ *
192
+ * @param[in] timeoutSeconds The timeout in seconds.
193
+ * @param[in] ResolveContext The resolve context.
194
+ */
195
+ void StartOpenThreadTimer (uint16_t timeoutInMSecs, ResolveContext * ctx)
196
+ {
197
+ VerifyOrReturn (ctx != nullptr , ChipLogError (Discovery, " Can't schedule open thread timer since context is null" ));
198
+ DeviceLayer::SystemLayer ().StartTimer (System::Clock::Milliseconds16 (timeoutInMSecs),
199
+ OpenThreadTimerExpiredCallback, reinterpret_cast <void *>(ctx));
200
+ }
201
+
138
202
static void OnRegister (DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType err, const char * name, const char * type,
139
203
const char * domain, void * context)
140
204
{
@@ -183,14 +247,24 @@ static void OnBrowse(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interf
183
247
184
248
CHIP_ERROR Browse (BrowseHandler * sdCtx, uint32_t interfaceId, const char * type)
185
249
{
186
- ChipLogProgress (Discovery, " Browsing for: %s" , StringOrNullMarker (type));
187
- DNSServiceRef sdRef;
188
- auto err = DNSServiceBrowse (&sdRef, kBrowseFlags , interfaceId, type, kLocalDot , OnBrowse, sdCtx);
250
+ auto err = DNSServiceCreateConnection (&sdCtx->serviceRef );
189
251
VerifyOrReturnError (kDNSServiceErr_NoError == err, sdCtx->Finalize (err));
190
252
191
- return MdnsContexts::GetInstance ().Add (sdCtx, sdRef);
192
- }
253
+ // We will browse on both the local domain and the open thread domain.
254
+ ChipLogProgress (Discovery, " Browsing for: %s on domain %s" , StringOrNullMarker (type), kLocalDot );
255
+
256
+ auto sdRefLocal = sdCtx->serviceRef ; // Mandatory copy because of kDNSServiceFlagsShareConnection
257
+ err = DNSServiceBrowse (&sdRefLocal, kBrowseFlags , interfaceId, type, kLocalDot , OnBrowse, sdCtx);
258
+ VerifyOrReturnError (kDNSServiceErr_NoError == err, sdCtx->Finalize (err));
259
+
260
+ ChipLogProgress (Discovery, " Browsing for: %s on domain %s" , StringOrNullMarker (type), kOpenThreadDot );
261
+
262
+ DNSServiceRef sdRefOpenThread = sdCtx->serviceRef ; // Mandatory copy because of kDNSServiceFlagsShareConnection
263
+ err = DNSServiceBrowse (&sdRefOpenThread, kBrowseFlags , interfaceId, type, kOpenThreadDot , OnBrowse, sdCtx);
264
+ VerifyOrReturnError (kDNSServiceErr_NoError == err, sdCtx->Finalize (err));
193
265
266
+ return MdnsContexts::GetInstance ().Add (sdCtx, sdCtx->serviceRef );
267
+ }
194
268
CHIP_ERROR Browse (void * context, DnssdBrowseCallback callback, uint32_t interfaceId, const char * type,
195
269
DnssdServiceProtocol protocol, intptr_t * browseIdentifier)
196
270
{
@@ -219,25 +293,41 @@ static void OnGetAddrInfo(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t i
219
293
ReturnOnFailure (MdnsContexts::GetInstance ().Has (sdCtx));
220
294
LogOnFailure (__func__, err);
221
295
296
+ sdCtx->domainName = GetDomainNameFromHostName (hostname);
222
297
if (kDNSServiceErr_NoError == err)
223
298
{
224
- sdCtx->OnNewAddress (interfaceId, address);
299
+ std::pair<uint32_t , std::string> key = std::make_pair (interfaceId, sdCtx->domainName );
300
+ sdCtx->OnNewAddress (key, address);
225
301
}
226
302
227
303
if (!(flags & kDNSServiceFlagsMoreComing ))
228
304
{
229
305
VerifyOrReturn (sdCtx->HasAddress (), sdCtx->Finalize (kDNSServiceErr_BadState ));
230
- sdCtx->Finalize ();
306
+
307
+ if (sdCtx->domainName .compare (kOpenThreadDot ) == 0 )
308
+ {
309
+ ChipLogProgress (Discovery, " Mdns: Resolve completed on the open thread domain." );
310
+ sdCtx->Finalize ();
311
+ }
312
+ else if (sdCtx->domainName .compare (kLocalDot ) == 0 )
313
+ {
314
+ ChipLogProgress (Discovery, " Mdns: Resolve completed on the local domain. Starting a timer for the open thread resolve to come back" );
315
+ if (!hasOpenThreadTimerStarted)
316
+ {
317
+ // Schedule a timer to allow the resolve on OpenThread domain to complete.
318
+ StartOpenThreadTimer (kOpenThreadTimeoutInMsec , sdCtx);
319
+ hasOpenThreadTimerStarted = true ;
320
+ }
321
+ }
231
322
}
232
323
}
233
324
234
325
static void GetAddrInfo (ResolveContext * sdCtx)
235
326
{
236
327
auto protocol = sdCtx->protocol ;
237
-
238
328
for (auto & interface : sdCtx->interfaces )
239
329
{
240
- auto interfaceId = interface.first ;
330
+ auto interfaceId = interface.first . first ;
241
331
auto hostname = interface.second .fullyQualifiedDomainName .c_str ();
242
332
auto sdRefCopy = sdCtx->serviceRef ; // Mandatory copy because of kDNSServiceFlagsShareConnection
243
333
auto err = DNSServiceGetAddrInfo (&sdRefCopy, kGetAddrInfoFlags , interfaceId, protocol, hostname, OnGetAddrInfo, sdCtx);
@@ -263,7 +353,13 @@ static void OnResolve(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t inter
263
353
if (!(flags & kDNSServiceFlagsMoreComing ))
264
354
{
265
355
VerifyOrReturn (sdCtx->HasInterface (), sdCtx->Finalize (kDNSServiceErr_BadState ));
266
- GetAddrInfo (sdCtx);
356
+
357
+ // If a resolve was not requested on this context, call GetAddrInfo and set the isResolveRequested flag to true.
358
+ if (!sdCtx->isResolveRequested )
359
+ {
360
+ GetAddrInfo (sdCtx);
361
+ sdCtx->isResolveRequested = true ;
362
+ }
267
363
}
268
364
}
269
365
@@ -276,8 +372,13 @@ static CHIP_ERROR Resolve(ResolveContext * sdCtx, uint32_t interfaceId, chip::In
276
372
auto err = DNSServiceCreateConnection (&sdCtx->serviceRef );
277
373
VerifyOrReturnError (kDNSServiceErr_NoError == err, sdCtx->Finalize (err));
278
374
279
- auto sdRefCopy = sdCtx->serviceRef ; // Mandatory copy because of kDNSServiceFlagsShareConnection
280
- err = DNSServiceResolve (&sdRefCopy, kResolveFlags , interfaceId, name, type, kLocalDot , OnResolve, sdCtx);
375
+ // Similar to browse, will try to resolve using both the local domain and the open thread domain.
376
+ auto sdRefLocal = sdCtx->serviceRef ; // Mandatory copy because of kDNSServiceFlagsShareConnection
377
+ err = DNSServiceResolve (&sdRefLocal, kResolveFlags , interfaceId, name, type, kLocalDot , OnResolve, sdCtx);
378
+ VerifyOrReturnError (kDNSServiceErr_NoError == err, sdCtx->Finalize (err));
379
+
380
+ auto sdRefOpenThread = sdCtx->serviceRef ; // Mandatory copy because of kDNSServiceFlagsShareConnection
381
+ err = DNSServiceResolve (&sdRefOpenThread, kResolveFlags , interfaceId, name, type, kOpenThreadDot , OnResolve, sdCtx);
281
382
VerifyOrReturnError (kDNSServiceErr_NoError == err, sdCtx->Finalize (err));
282
383
283
384
auto retval = MdnsContexts::GetInstance ().Add (sdCtx, sdCtx->serviceRef );
@@ -339,7 +440,7 @@ CHIP_ERROR ChipDnssdPublishService(const DnssdService * service, DnssdPublishCal
339
440
340
441
auto regtype = GetFullTypeWithSubTypes (service);
341
442
auto interfaceId = GetInterfaceId (service->mInterface );
342
- auto hostname = GetHostNameWithDomain (service->mHostName );
443
+ auto hostname = GetHostNameWithLocalDomain (service->mHostName );
343
444
344
445
return Register (context, callback, interfaceId, regtype.c_str (), service->mName , service->mPort , record, service->mAddressType ,
345
446
hostname.c_str ());
@@ -485,7 +586,7 @@ CHIP_ERROR ChipDnssdReconfirmRecord(const char * hostname, chip::Inet::IPAddress
485
586
486
587
auto interfaceId = interface.GetPlatformInterface ();
487
588
auto rrclass = kDNSServiceClass_IN ;
488
- auto fullname = GetHostNameWithDomain (hostname);
589
+ auto fullname = GetHostNameWithLocalDomain (hostname);
489
590
490
591
uint16_t rrtype;
491
592
uint16_t rdlen;
0 commit comments