1 /*
2 * Copyright (c) 2023, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <openthread/config.h>
30
31 #include "test_platform.h"
32 #include "test_util.hpp"
33
34 #include <openthread/dataset_ftd.h>
35 #include <openthread/dns_client.h>
36 #include <openthread/srp_client.h>
37 #include <openthread/srp_server.h>
38 #include <openthread/thread.h>
39
40 #include "common/arg_macros.hpp"
41 #include "common/array.hpp"
42 #include "common/string.hpp"
43 #include "common/time.hpp"
44 #include "instance/instance.hpp"
45
46 #if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE && OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE && \
47 OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE && OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE && \
48 OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE && \
49 !OPENTHREAD_CONFIG_TIME_SYNC_ENABLE && !OPENTHREAD_PLATFORM_POSIX
50 #define ENABLE_DNS_TEST 1
51 #else
52 #define ENABLE_DNS_TEST 0
53 #endif
54
55 #if ENABLE_DNS_TEST
56
57 using namespace ot;
58
59 // Logs a message and adds current time (sNow) as "<hours>:<min>:<secs>.<msec>"
60 #define Log(...) \
61 printf("%02u:%02u:%02u.%03u " OT_FIRST_ARG(__VA_ARGS__) "\n", (sNow / 36000000), (sNow / 60000) % 60, \
62 (sNow / 1000) % 60, sNow % 1000 OT_REST_ARGS(__VA_ARGS__))
63
64 static constexpr uint16_t kMaxRaSize = 800;
65
66 static ot::Instance *sInstance;
67
68 static uint32_t sNow = 0;
69 static uint32_t sAlarmTime;
70 static bool sAlarmOn = false;
71
72 static otRadioFrame sRadioTxFrame;
73 static uint8_t sRadioTxFramePsdu[OT_RADIO_FRAME_MAX_SIZE];
74 static bool sRadioTxOngoing = false;
75
76 //----------------------------------------------------------------------------------------------------------------------
77 // Function prototypes
78
79 void ProcessRadioTxAndTasklets(void);
80 void AdvanceTime(uint32_t aDuration);
81
82 //----------------------------------------------------------------------------------------------------------------------
83 // `otPlatRadio`
84
85 extern "C" {
86
otPlatRadioGetCaps(otInstance *)87 otRadioCaps otPlatRadioGetCaps(otInstance *) { return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF; }
88
otPlatRadioTransmit(otInstance *,otRadioFrame *)89 otError otPlatRadioTransmit(otInstance *, otRadioFrame *)
90 {
91 sRadioTxOngoing = true;
92
93 return OT_ERROR_NONE;
94 }
95
otPlatRadioGetTransmitBuffer(otInstance *)96 otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *) { return &sRadioTxFrame; }
97
98 //----------------------------------------------------------------------------------------------------------------------
99 // `otPlatAlaram`
100
otPlatAlarmMilliStop(otInstance *)101 void otPlatAlarmMilliStop(otInstance *) { sAlarmOn = false; }
102
otPlatAlarmMilliStartAt(otInstance *,uint32_t aT0,uint32_t aDt)103 void otPlatAlarmMilliStartAt(otInstance *, uint32_t aT0, uint32_t aDt)
104 {
105 sAlarmOn = true;
106 sAlarmTime = aT0 + aDt;
107 }
108
otPlatAlarmMilliGetNow(void)109 uint32_t otPlatAlarmMilliGetNow(void) { return sNow; }
110
111 //----------------------------------------------------------------------------------------------------------------------
112
113 Array<void *, 500> sHeapAllocatedPtrs;
114
115 #if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
otPlatCAlloc(size_t aNum,size_t aSize)116 void *otPlatCAlloc(size_t aNum, size_t aSize)
117 {
118 void *ptr = calloc(aNum, aSize);
119
120 SuccessOrQuit(sHeapAllocatedPtrs.PushBack(ptr));
121
122 return ptr;
123 }
124
otPlatFree(void * aPtr)125 void otPlatFree(void *aPtr)
126 {
127 if (aPtr != nullptr)
128 {
129 void **entry = sHeapAllocatedPtrs.Find(aPtr);
130
131 VerifyOrQuit(entry != nullptr, "A heap allocated item is freed twice");
132 sHeapAllocatedPtrs.Remove(*entry);
133 }
134
135 free(aPtr);
136 }
137 #endif
138
139 #if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED
otPlatLog(otLogLevel aLogLevel,otLogRegion aLogRegion,const char * aFormat,...)140 void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
141 {
142 OT_UNUSED_VARIABLE(aLogLevel);
143 OT_UNUSED_VARIABLE(aLogRegion);
144
145 va_list args;
146
147 printf(" ");
148 va_start(args, aFormat);
149 vprintf(aFormat, args);
150 va_end(args);
151 printf("\n");
152 }
153 #endif
154
155 } // extern "C"
156
157 //---------------------------------------------------------------------------------------------------------------------
158
ProcessRadioTxAndTasklets(void)159 void ProcessRadioTxAndTasklets(void)
160 {
161 do
162 {
163 if (sRadioTxOngoing)
164 {
165 sRadioTxOngoing = false;
166 otPlatRadioTxStarted(sInstance, &sRadioTxFrame);
167 otPlatRadioTxDone(sInstance, &sRadioTxFrame, nullptr, OT_ERROR_NONE);
168 }
169
170 otTaskletsProcess(sInstance);
171 } while (otTaskletsArePending(sInstance));
172 }
173
AdvanceTime(uint32_t aDuration)174 void AdvanceTime(uint32_t aDuration)
175 {
176 uint32_t time = sNow + aDuration;
177
178 Log("AdvanceTime for %u.%03u", aDuration / 1000, aDuration % 1000);
179
180 while (TimeMilli(sAlarmTime) <= TimeMilli(time))
181 {
182 ProcessRadioTxAndTasklets();
183 sNow = sAlarmTime;
184 otPlatAlarmMilliFired(sInstance);
185 }
186
187 ProcessRadioTxAndTasklets();
188 sNow = time;
189 }
190
InitTest(void)191 void InitTest(void)
192 {
193 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
194 // Initialize OT instance.
195
196 sNow = 0;
197 sAlarmOn = false;
198 sInstance = static_cast<Instance *>(testInitInstance());
199
200 memset(&sRadioTxFrame, 0, sizeof(sRadioTxFrame));
201 sRadioTxFrame.mPsdu = sRadioTxFramePsdu;
202 sRadioTxOngoing = false;
203
204 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
205 // Initialize Border Router and start Thread operation.
206
207 otOperationalDataset dataset;
208 otOperationalDatasetTlvs datasetTlvs;
209
210 SuccessOrQuit(otDatasetCreateNewNetwork(sInstance, &dataset));
211 SuccessOrQuit(otDatasetConvertToTlvs(&dataset, &datasetTlvs));
212 SuccessOrQuit(otDatasetSetActiveTlvs(sInstance, &datasetTlvs));
213
214 SuccessOrQuit(otIp6SetEnabled(sInstance, true));
215 SuccessOrQuit(otThreadSetEnabled(sInstance, true));
216
217 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
218 // Ensure device starts as leader.
219
220 AdvanceTime(10000);
221
222 VerifyOrQuit(otThreadGetDeviceRole(sInstance) == OT_DEVICE_ROLE_LEADER);
223 }
224
FinalizeTest(void)225 void FinalizeTest(void)
226 {
227 SuccessOrQuit(otIp6SetEnabled(sInstance, false));
228 SuccessOrQuit(otThreadSetEnabled(sInstance, false));
229 // Make sure there is no message/buffer leak
230 VerifyOrQuit(sInstance->Get<MessagePool>().GetFreeBufferCount() ==
231 sInstance->Get<MessagePool>().GetTotalBufferCount());
232 SuccessOrQuit(otInstanceErasePersistentInfo(sInstance));
233 testFreeInstance(sInstance);
234 }
235
236 //---------------------------------------------------------------------------------------------------------------------
237
238 static const char kHostName[] = "elden";
239 static const char kHostFullName[] = "elden.default.service.arpa.";
240
241 static const char kService1Name[] = "_srv._udp";
242 static const char kService1FullName[] = "_srv._udp.default.service.arpa.";
243 static const char kInstance1Label[] = "srv-instance";
244 static const char kInstance1FullName[] = "srv-instance._srv._udp.default.service.arpa.";
245
246 static const char kService2Name[] = "_game._udp";
247 static const char kService2FullName[] = "_game._udp.default.service.arpa.";
248 static const char kService2SubTypeFullName[] = "_best._sub._game._udp.default.service.arpa.";
249 static const char kInstance2Label[] = "last-ninja";
250 static const char kInstance2FullName[] = "last-ninja._game._udp.default.service.arpa.";
251
PrepareService1(Srp::Client::Service & aService)252 void PrepareService1(Srp::Client::Service &aService)
253 {
254 static const char kSub1[] = "_sub1";
255 static const char kSub2[] = "_V1234567";
256 static const char kSub3[] = "_XYZWS";
257 static const char *kSubLabels[] = {kSub1, kSub2, kSub3, nullptr};
258 static const char kTxtKey1[] = "ABCD";
259 static const uint8_t kTxtValue1[] = {'a', '0'};
260 static const char kTxtKey2[] = "Z0";
261 static const uint8_t kTxtValue2[] = {'1', '2', '3'};
262 static const char kTxtKey3[] = "D";
263 static const uint8_t kTxtValue3[] = {0};
264 static const otDnsTxtEntry kTxtEntries[] = {
265 {kTxtKey1, kTxtValue1, sizeof(kTxtValue1)},
266 {kTxtKey2, kTxtValue2, sizeof(kTxtValue2)},
267 {kTxtKey3, kTxtValue3, sizeof(kTxtValue3)},
268 };
269
270 memset(&aService, 0, sizeof(aService));
271 aService.mName = kService1Name;
272 aService.mInstanceName = kInstance1Label;
273 aService.mSubTypeLabels = kSubLabels;
274 aService.mTxtEntries = kTxtEntries;
275 aService.mNumTxtEntries = 3;
276 aService.mPort = 777;
277 aService.mWeight = 1;
278 aService.mPriority = 2;
279 }
280
PrepareService2(Srp::Client::Service & aService)281 void PrepareService2(Srp::Client::Service &aService)
282 {
283 static const char kSub4[] = "_best";
284 static const char *kSubLabels2[] = {kSub4, nullptr};
285
286 memset(&aService, 0, sizeof(aService));
287 aService.mName = kService2Name;
288 aService.mInstanceName = kInstance2Label;
289 aService.mSubTypeLabels = kSubLabels2;
290 aService.mTxtEntries = nullptr;
291 aService.mNumTxtEntries = 0;
292 aService.mPort = 555;
293 aService.mWeight = 0;
294 aService.mPriority = 3;
295 }
296
ValidateHost(Srp::Server & aServer,const char * aHostName)297 void ValidateHost(Srp::Server &aServer, const char *aHostName)
298 {
299 // Validate that only a host with `aHostName` is
300 // registered on SRP server.
301
302 const Srp::Server::Host *host;
303 const char *name;
304
305 Log("ValidateHost()");
306
307 host = aServer.GetNextHost(nullptr);
308 VerifyOrQuit(host != nullptr);
309
310 name = host->GetFullName();
311 Log("Hostname: %s", name);
312
313 VerifyOrQuit(StringStartsWith(name, aHostName, kStringCaseInsensitiveMatch));
314 VerifyOrQuit(name[strlen(aHostName)] == '.');
315
316 // Only one host on server
317 VerifyOrQuit(aServer.GetNextHost(host) == nullptr);
318 }
319
320 //---------------------------------------------------------------------------------------------------------------------
321
LogServiceInfo(const Dns::Client::ServiceInfo & aInfo)322 void LogServiceInfo(const Dns::Client::ServiceInfo &aInfo)
323 {
324 Log(" TTL: %u", aInfo.mTtl);
325 Log(" Port: %u", aInfo.mPort);
326 Log(" Weight: %u", aInfo.mWeight);
327 Log(" HostName: %s", aInfo.mHostNameBuffer);
328 Log(" HostAddr: %s", AsCoreType(&aInfo.mHostAddress).ToString().AsCString());
329 Log(" TxtDataLength: %u", aInfo.mTxtDataSize);
330 Log(" TxtDataTTL: %u", aInfo.mTxtDataTtl);
331 }
332
ServiceModeToString(Dns::Client::QueryConfig::ServiceMode aMode)333 const char *ServiceModeToString(Dns::Client::QueryConfig::ServiceMode aMode)
334 {
335 static const char *const kServiceModeStrings[] = {
336 "unspec", // kServiceModeUnspecified (0)
337 "srv", // kServiceModeSrv (1)
338 "txt", // kServiceModeTxt (2)
339 "srv_txt", // kServiceModeSrvTxt (3)
340 "srv_txt_sep", // kServiceModeSrvTxtSeparate (4)
341 "srv_txt_opt", // kServiceModeSrvTxtOptimize (5)
342 };
343
344 static_assert(Dns::Client::QueryConfig::kServiceModeUnspecified == 0, "Unspecified value is incorrect");
345 static_assert(Dns::Client::QueryConfig::kServiceModeSrv == 1, "Srv value is incorrect");
346 static_assert(Dns::Client::QueryConfig::kServiceModeTxt == 2, "Txt value is incorrect");
347 static_assert(Dns::Client::QueryConfig::kServiceModeSrvTxt == 3, "SrvTxt value is incorrect");
348 static_assert(Dns::Client::QueryConfig::kServiceModeSrvTxtSeparate == 4, "SrvTxtSeparate value is incorrect");
349 static_assert(Dns::Client::QueryConfig::kServiceModeSrvTxtOptimize == 5, "SrvTxtOptimize value is incorrect");
350
351 return kServiceModeStrings[aMode];
352 }
353
354 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
355
356 struct BrowseInfo
357 {
ResetBrowseInfo358 void Reset(void) { mCallbackCount = 0; }
359
360 uint16_t mCallbackCount;
361 Error mError;
362 Dns::Name::Buffer mServiceName;
363 uint16_t mNumInstances;
364 };
365
366 static BrowseInfo sBrowseInfo;
367
BrowseCallback(otError aError,const otDnsBrowseResponse * aResponse,void * aContext)368 void BrowseCallback(otError aError, const otDnsBrowseResponse *aResponse, void *aContext)
369 {
370 const Dns::Client::BrowseResponse &response = AsCoreType(aResponse);
371
372 Log("BrowseCallback");
373 Log(" Error: %s", ErrorToString(aError));
374
375 VerifyOrQuit(aContext == sInstance);
376
377 sBrowseInfo.mCallbackCount++;
378 sBrowseInfo.mError = aError;
379
380 SuccessOrExit(aError);
381
382 SuccessOrQuit(response.GetServiceName(sBrowseInfo.mServiceName, sizeof(sBrowseInfo.mServiceName)));
383 Log(" ServiceName: %s", sBrowseInfo.mServiceName);
384
385 for (uint16_t index = 0;; index++)
386 {
387 Dns::Name::LabelBuffer instLabel;
388 Error error;
389
390 error = response.GetServiceInstance(index, instLabel, sizeof(instLabel));
391
392 if (error == kErrorNotFound)
393 {
394 sBrowseInfo.mNumInstances = index;
395 break;
396 }
397
398 SuccessOrQuit(error);
399
400 Log(" %2u) %s", index + 1, instLabel);
401 }
402
403 exit:
404 return;
405 }
406
407 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
408
409 static constexpr uint8_t kMaxHostAddresses = 10;
410 static constexpr uint16_t kMaxTxtBuffer = 256;
411
412 struct ResolveServiceInfo
413 {
ResetResolveServiceInfo414 void Reset(void)
415 {
416 memset(this, 0, sizeof(*this));
417 mInfo.mHostNameBuffer = mNameBuffer;
418 mInfo.mHostNameBufferSize = sizeof(mNameBuffer);
419 mInfo.mTxtData = mTxtBuffer;
420 mInfo.mTxtDataSize = sizeof(mTxtBuffer);
421 };
422
423 uint16_t mCallbackCount;
424 Error mError;
425 Dns::Client::ServiceInfo mInfo;
426 Dns::Name::Buffer mNameBuffer;
427 uint8_t mTxtBuffer[kMaxTxtBuffer];
428 Ip6::Address mHostAddresses[kMaxHostAddresses];
429 uint8_t mNumHostAddresses;
430 };
431
432 static ResolveServiceInfo sResolveServiceInfo;
433
ServiceCallback(otError aError,const otDnsServiceResponse * aResponse,void * aContext)434 void ServiceCallback(otError aError, const otDnsServiceResponse *aResponse, void *aContext)
435 {
436 const Dns::Client::ServiceResponse &response = AsCoreType(aResponse);
437 Dns::Name::LabelBuffer instLabel;
438 Dns::Name::Buffer serviceName;
439
440 Log("ServiceCallback");
441 Log(" Error: %s", ErrorToString(aError));
442
443 VerifyOrQuit(aContext == sInstance);
444
445 SuccessOrQuit(response.GetServiceName(instLabel, sizeof(instLabel), serviceName, sizeof(serviceName)));
446 Log(" InstLabel: %s", instLabel);
447 Log(" ServiceName: %s", serviceName);
448
449 sResolveServiceInfo.mCallbackCount++;
450 sResolveServiceInfo.mError = aError;
451
452 SuccessOrExit(aError);
453 SuccessOrQuit(response.GetServiceInfo(sResolveServiceInfo.mInfo));
454
455 for (uint8_t index = 0; index < kMaxHostAddresses; index++)
456 {
457 Error error;
458 uint32_t ttl;
459
460 error = response.GetHostAddress(sResolveServiceInfo.mInfo.mHostNameBuffer, index,
461 sResolveServiceInfo.mHostAddresses[index], ttl);
462
463 if (error == kErrorNotFound)
464 {
465 sResolveServiceInfo.mNumHostAddresses = index;
466 break;
467 }
468
469 SuccessOrQuit(error);
470 }
471
472 LogServiceInfo(sResolveServiceInfo.mInfo);
473 Log(" NumHostAddresses: %u", sResolveServiceInfo.mNumHostAddresses);
474
475 for (uint8_t index = 0; index < sResolveServiceInfo.mNumHostAddresses; index++)
476 {
477 Log(" %s", sResolveServiceInfo.mHostAddresses[index].ToString().AsCString());
478 }
479
480 exit:
481 return;
482 }
483
484 //----------------------------------------------------------------------------------------------------------------------
485
TestDnsClient(void)486 void TestDnsClient(void)
487 {
488 static constexpr uint8_t kNumAddresses = 2;
489
490 static const char *const kAddresses[kNumAddresses] = {"2001::beef:cafe", "fd00:1234:5678:9abc::1"};
491
492 const Dns::Client::QueryConfig::ServiceMode kServiceModes[] = {
493 Dns::Client::QueryConfig::kServiceModeSrv,
494 Dns::Client::QueryConfig::kServiceModeTxt,
495 Dns::Client::QueryConfig::kServiceModeSrvTxt,
496 Dns::Client::QueryConfig::kServiceModeSrvTxtSeparate,
497 Dns::Client::QueryConfig::kServiceModeSrvTxtOptimize,
498 };
499
500 Array<Ip6::Address, kNumAddresses> addresses;
501 Srp::Server *srpServer;
502 Srp::Client *srpClient;
503 Srp::Client::Service service1;
504 Srp::Client::Service service2;
505 Dns::Client *dnsClient;
506 Dns::Client::QueryConfig queryConfig;
507 Dns::ServiceDiscovery::Server *dnsServer;
508 uint16_t heapAllocations;
509
510 Log("--------------------------------------------------------------------------------------------");
511 Log("TestDnsClient");
512
513 InitTest();
514
515 for (const char *addrString : kAddresses)
516 {
517 otNetifAddress netifAddr;
518
519 memset(&netifAddr, 0, sizeof(netifAddr));
520 SuccessOrQuit(AsCoreType(&netifAddr.mAddress).FromString(addrString));
521 netifAddr.mPrefixLength = 64;
522 netifAddr.mAddressOrigin = OT_ADDRESS_ORIGIN_MANUAL;
523 netifAddr.mPreferred = true;
524 netifAddr.mValid = true;
525 SuccessOrQuit(otIp6AddUnicastAddress(sInstance, &netifAddr));
526
527 SuccessOrQuit(addresses.PushBack(AsCoreType(&netifAddr.mAddress)));
528 }
529
530 srpServer = &sInstance->Get<Srp::Server>();
531 srpClient = &sInstance->Get<Srp::Client>();
532 dnsClient = &sInstance->Get<Dns::Client>();
533 dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
534
535 heapAllocations = sHeapAllocatedPtrs.GetLength();
536
537 PrepareService1(service1);
538 PrepareService2(service2);
539
540 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
541 // Start SRP server.
542
543 SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
544 VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
545
546 srpServer->SetEnabled(true);
547 VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
548
549 AdvanceTime(10000);
550 VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
551
552 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
553 // Start SRP client.
554
555 srpClient->EnableAutoStartMode(nullptr, nullptr);
556 VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
557
558 AdvanceTime(2000);
559 VerifyOrQuit(srpClient->IsRunning());
560
561 SuccessOrQuit(srpClient->SetHostName(kHostName));
562 SuccessOrQuit(srpClient->EnableAutoHostAddress());
563
564 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
565 // Register two services on SRP.
566
567 SuccessOrQuit(srpClient->AddService(service1));
568 SuccessOrQuit(srpClient->AddService(service2));
569
570 AdvanceTime(2 * 1000);
571
572 VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
573 VerifyOrQuit(service2.GetState() == Srp::Client::kRegistered);
574 ValidateHost(*srpServer, kHostName);
575
576 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
577
578 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
579 // Check DNS Client's default config
580
581 VerifyOrQuit(dnsClient->GetDefaultConfig().GetServiceMode() ==
582 Dns::Client::QueryConfig::kServiceModeSrvTxtOptimize);
583
584 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
585 // Validate DNS Client `Browse()`
586
587 sBrowseInfo.Reset();
588 Log("Browse(%s)", kService1FullName);
589 SuccessOrQuit(dnsClient->Browse(kService1FullName, BrowseCallback, sInstance));
590 AdvanceTime(100);
591 VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
592 SuccessOrQuit(sBrowseInfo.mError);
593 VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
594
595 sBrowseInfo.Reset();
596
597 Log("Browse(%s)", kService2FullName);
598 SuccessOrQuit(dnsClient->Browse(kService2FullName, BrowseCallback, sInstance));
599 AdvanceTime(100);
600 VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
601 SuccessOrQuit(sBrowseInfo.mError);
602 VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
603
604 sBrowseInfo.Reset();
605
606 Log("Browse(%s)", kService2SubTypeFullName);
607 SuccessOrQuit(dnsClient->Browse(kService2SubTypeFullName, BrowseCallback, sInstance));
608 AdvanceTime(100);
609 VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
610 SuccessOrQuit(sBrowseInfo.mError);
611 VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
612
613 sBrowseInfo.Reset();
614 Log("Browse() for unknown service");
615 SuccessOrQuit(dnsClient->Browse("_unknown._udp.default.service.arpa.", BrowseCallback, sInstance));
616 AdvanceTime(100);
617 VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
618 VerifyOrQuit(sBrowseInfo.mError == kErrorNotFound);
619
620 Log("Issue four parallel `Browse()` at the same time");
621 sBrowseInfo.Reset();
622 SuccessOrQuit(dnsClient->Browse(kService1FullName, BrowseCallback, sInstance));
623 SuccessOrQuit(dnsClient->Browse(kService2FullName, BrowseCallback, sInstance));
624 SuccessOrQuit(dnsClient->Browse("_unknown._udp.default.service.arpa.", BrowseCallback, sInstance));
625 SuccessOrQuit(dnsClient->Browse("_unknown2._udp.default.service.arpa.", BrowseCallback, sInstance));
626 AdvanceTime(100);
627 VerifyOrQuit(sBrowseInfo.mCallbackCount == 4);
628
629 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
630 // Validate DNS Client `ResolveService()` using all service modes
631
632 for (Dns::Client::QueryConfig::ServiceMode mode : kServiceModes)
633 {
634 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
635 Log("ResolveService(%s,%s) with ServiceMode: %s", kInstance1Label, kService1FullName,
636 ServiceModeToString(mode));
637
638 queryConfig.Clear();
639 queryConfig.mServiceMode = static_cast<otDnsServiceMode>(mode);
640
641 sResolveServiceInfo.Reset();
642 SuccessOrQuit(
643 dnsClient->ResolveService(kInstance1Label, kService1FullName, ServiceCallback, sInstance, &queryConfig));
644 AdvanceTime(100);
645
646 VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
647 SuccessOrQuit(sResolveServiceInfo.mError);
648
649 if (mode != Dns::Client::QueryConfig::kServiceModeTxt)
650 {
651 VerifyOrQuit(sResolveServiceInfo.mInfo.mTtl != 0);
652 VerifyOrQuit(sResolveServiceInfo.mInfo.mPort == service1.mPort);
653 VerifyOrQuit(sResolveServiceInfo.mInfo.mWeight == service1.mWeight);
654 VerifyOrQuit(strcmp(sResolveServiceInfo.mInfo.mHostNameBuffer, kHostFullName) == 0);
655
656 VerifyOrQuit(sResolveServiceInfo.mNumHostAddresses == kNumAddresses);
657 VerifyOrQuit(AsCoreType(&sResolveServiceInfo.mInfo.mHostAddress) == sResolveServiceInfo.mHostAddresses[0]);
658
659 for (uint8_t index = 0; index < kNumAddresses; index++)
660 {
661 VerifyOrQuit(addresses.Contains(sResolveServiceInfo.mHostAddresses[index]));
662 }
663 }
664
665 if (mode != Dns::Client::QueryConfig::kServiceModeSrv)
666 {
667 VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataTtl != 0);
668 VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataSize != 0);
669 }
670 }
671
672 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
673
674 Log("Set TestMode on server to only accept single question");
675 dnsServer->SetTestMode(Dns::ServiceDiscovery::Server::kTestModeSingleQuestionOnly);
676
677 Log("ResolveService(%s,%s) with ServiceMode %s", kInstance1Label, kService1FullName,
678 ServiceModeToString(Dns::Client::QueryConfig::kServiceModeSrvTxtOptimize));
679
680 queryConfig.Clear();
681 queryConfig.mServiceMode = static_cast<otDnsServiceMode>(Dns::Client::QueryConfig::kServiceModeSrvTxtOptimize);
682
683 sResolveServiceInfo.Reset();
684 SuccessOrQuit(
685 dnsClient->ResolveService(kInstance1Label, kService1FullName, ServiceCallback, sInstance, &queryConfig));
686 AdvanceTime(200);
687
688 VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
689 SuccessOrQuit(sResolveServiceInfo.mError);
690
691 // Use `kServiceModeSrvTxt` and check that server does reject two questions.
692
693 Log("ResolveService(%s,%s) with ServiceMode %s", kInstance1Label, kService1FullName,
694 ServiceModeToString(Dns::Client::QueryConfig::kServiceModeSrvTxt));
695
696 queryConfig.Clear();
697 queryConfig.mServiceMode = static_cast<otDnsServiceMode>(Dns::Client::QueryConfig::kServiceModeSrvTxt);
698
699 sResolveServiceInfo.Reset();
700 SuccessOrQuit(
701 dnsClient->ResolveService(kInstance1Label, kService1FullName, ServiceCallback, sInstance, &queryConfig));
702 AdvanceTime(200);
703
704 VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
705 VerifyOrQuit(sResolveServiceInfo.mError != kErrorNone);
706
707 dnsServer->SetTestMode(Dns::ServiceDiscovery::Server::kTestModeDisabled);
708
709 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
710 // Validate DNS Client `ResolveService()` using all service modes
711 // when sever does not provide any RR in the addition data section.
712
713 for (Dns::Client::QueryConfig::ServiceMode mode : kServiceModes)
714 {
715 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
716 Log("Set TestMode on server to not include any RR in additional section");
717 dnsServer->SetTestMode(Dns::ServiceDiscovery::Server::kTestModeEmptyAdditionalSection);
718 Log("ResolveService(%s,%s) with ServiceMode: %s", kInstance1Label, kService1FullName,
719 ServiceModeToString(mode));
720
721 queryConfig.Clear();
722 queryConfig.mServiceMode = static_cast<otDnsServiceMode>(mode);
723
724 sResolveServiceInfo.Reset();
725 SuccessOrQuit(
726 dnsClient->ResolveService(kInstance1Label, kService1FullName, ServiceCallback, sInstance, &queryConfig));
727 AdvanceTime(100);
728
729 VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
730 SuccessOrQuit(sResolveServiceInfo.mError);
731
732 if (mode != Dns::Client::QueryConfig::kServiceModeTxt)
733 {
734 VerifyOrQuit(sResolveServiceInfo.mInfo.mTtl != 0);
735 VerifyOrQuit(sResolveServiceInfo.mInfo.mPort == service1.mPort);
736 VerifyOrQuit(sResolveServiceInfo.mInfo.mWeight == service1.mWeight);
737 VerifyOrQuit(strcmp(sResolveServiceInfo.mInfo.mHostNameBuffer, kHostFullName) == 0);
738 }
739
740 if (mode != Dns::Client::QueryConfig::kServiceModeSrv)
741 {
742 VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataTtl != 0);
743 VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataSize != 0);
744 }
745
746 // Since server is using `kTestModeEmptyAdditionalSection`, there
747 // should be no AAAA records for host address.
748
749 VerifyOrQuit(AsCoreType(&sResolveServiceInfo.mInfo.mHostAddress).IsUnspecified());
750 VerifyOrQuit(sResolveServiceInfo.mNumHostAddresses == 0);
751 }
752
753 dnsServer->SetTestMode(Dns::ServiceDiscovery::Server::kTestModeDisabled);
754
755 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
756 // Validate DNS Client `ResolveServiceAndHostAddress()` using all service modes
757 // with different TestMode configs on server:
758 // - Normal behavior when server provides AAAA records for host in
759 // additional section.
760 // - Server provides no records in additional section. We validate that
761 // client will send separate query to resolve host address.
762
763 for (Dns::Client::QueryConfig::ServiceMode mode : kServiceModes)
764 {
765 for (uint8_t testIter = 0; testIter <= 1; testIter++)
766 {
767 Error error;
768
769 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
770
771 if (testIter == 1)
772 {
773 Log("Set TestMode on server to not include any RR in additional section");
774 dnsServer->SetTestMode(Dns::ServiceDiscovery::Server::kTestModeEmptyAdditionalSection);
775 }
776 else
777 {
778 dnsServer->SetTestMode(Dns::ServiceDiscovery::Server::kTestModeDisabled);
779 }
780
781 Log("ResolveServiceAndHostAddress(%s,%s) with ServiceMode: %s", kInstance1Label, kService1FullName,
782 ServiceModeToString(mode));
783
784 queryConfig.Clear();
785 queryConfig.mServiceMode = static_cast<otDnsServiceMode>(mode);
786
787 sResolveServiceInfo.Reset();
788 error = dnsClient->ResolveServiceAndHostAddress(kInstance1Label, kService1FullName, ServiceCallback,
789 sInstance, &queryConfig);
790
791 if (mode == Dns::Client::QueryConfig::kServiceModeTxt)
792 {
793 Log("ResolveServiceAndHostAddress() with ServiceMode: %s failed correctly", ServiceModeToString(mode));
794 VerifyOrQuit(error == kErrorInvalidArgs);
795 continue;
796 }
797
798 SuccessOrQuit(error);
799
800 AdvanceTime(100);
801
802 VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
803 SuccessOrQuit(sResolveServiceInfo.mError);
804
805 if (mode != Dns::Client::QueryConfig::kServiceModeTxt)
806 {
807 VerifyOrQuit(sResolveServiceInfo.mInfo.mTtl != 0);
808 VerifyOrQuit(sResolveServiceInfo.mInfo.mPort == service1.mPort);
809 VerifyOrQuit(sResolveServiceInfo.mInfo.mWeight == service1.mWeight);
810 VerifyOrQuit(strcmp(sResolveServiceInfo.mInfo.mHostNameBuffer, kHostFullName) == 0);
811
812 VerifyOrQuit(sResolveServiceInfo.mNumHostAddresses == kNumAddresses);
813 VerifyOrQuit(AsCoreType(&sResolveServiceInfo.mInfo.mHostAddress) ==
814 sResolveServiceInfo.mHostAddresses[0]);
815
816 for (uint8_t index = 0; index < kNumAddresses; index++)
817 {
818 VerifyOrQuit(addresses.Contains(sResolveServiceInfo.mHostAddresses[index]));
819 }
820 }
821
822 if (mode != Dns::Client::QueryConfig::kServiceModeSrv)
823 {
824 VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataTtl != 0);
825 VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataSize != 0);
826 }
827 }
828 }
829
830 dnsServer->SetTestMode(Dns::ServiceDiscovery::Server::kTestModeDisabled);
831
832 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
833 Log("Set TestMode on server to not include any RR in additional section AND to only accept single question");
834 dnsServer->SetTestMode(Dns::ServiceDiscovery::Server::kTestModeEmptyAdditionalSection +
835 Dns::ServiceDiscovery::Server::kTestModeSingleQuestionOnly);
836
837 Log("ResolveServiceAndHostAddress(%s,%s) with ServiceMode: %s", kInstance1Label, kService1FullName,
838 ServiceModeToString(Dns::Client::QueryConfig::kServiceModeSrvTxtOptimize));
839
840 queryConfig.Clear();
841 queryConfig.mServiceMode = static_cast<otDnsServiceMode>(Dns::Client::QueryConfig::kServiceModeSrvTxtOptimize);
842
843 sResolveServiceInfo.Reset();
844 SuccessOrQuit(dnsClient->ResolveServiceAndHostAddress(kInstance1Label, kService1FullName, ServiceCallback,
845 sInstance, &queryConfig));
846
847 AdvanceTime(100);
848
849 VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
850 SuccessOrQuit(sResolveServiceInfo.mError);
851
852 VerifyOrQuit(sResolveServiceInfo.mInfo.mTtl != 0);
853 VerifyOrQuit(sResolveServiceInfo.mInfo.mPort == service1.mPort);
854 VerifyOrQuit(sResolveServiceInfo.mInfo.mWeight == service1.mWeight);
855 VerifyOrQuit(strcmp(sResolveServiceInfo.mInfo.mHostNameBuffer, kHostFullName) == 0);
856
857 VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataTtl != 0);
858 VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataSize != 0);
859
860 VerifyOrQuit(sResolveServiceInfo.mNumHostAddresses == kNumAddresses);
861 VerifyOrQuit(AsCoreType(&sResolveServiceInfo.mInfo.mHostAddress) == sResolveServiceInfo.mHostAddresses[0]);
862
863 for (uint8_t index = 0; index < kNumAddresses; index++)
864 {
865 VerifyOrQuit(addresses.Contains(sResolveServiceInfo.mHostAddresses[index]));
866 }
867
868 dnsServer->SetTestMode(Dns::ServiceDiscovery::Server::kTestModeDisabled);
869
870 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
871
872 Log("Stop DNS-SD server");
873 dnsServer->Stop();
874
875 Log("ResolveService(%s,%s) with ServiceMode %s", kInstance1Label, kService1FullName,
876 ServiceModeToString(Dns::Client::QueryConfig::kServiceModeSrvTxtSeparate));
877
878 queryConfig.Clear();
879 queryConfig.mServiceMode = static_cast<otDnsServiceMode>(Dns::Client::QueryConfig::kServiceModeSrvTxtSeparate);
880
881 sResolveServiceInfo.Reset();
882 SuccessOrQuit(
883 dnsClient->ResolveService(kInstance1Label, kService1FullName, ServiceCallback, sInstance, &queryConfig));
884 AdvanceTime(25 * 1000);
885
886 VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
887 VerifyOrQuit(sResolveServiceInfo.mError == kErrorResponseTimeout);
888
889 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
890
891 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
892 // Disable SRP server, verify that all heap allocations by SRP server
893 // and/or by DNS Client are freed.
894
895 Log("Disabling SRP server");
896
897 srpServer->SetEnabled(false);
898 AdvanceTime(100);
899
900 VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
901
902 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
903 // Finalize OT instance and validate all heap allocations are freed.
904
905 Log("Finalizing OT instance");
906 FinalizeTest();
907
908 VerifyOrQuit(sHeapAllocatedPtrs.IsEmpty());
909
910 Log("End of TestDnsClient");
911 }
912
913 //----------------------------------------------------------------------------------------------------------------------
914
915 Dns::Name::Buffer sLastSubscribeName;
916 Dns::Name::Buffer sLastUnsubscribeName;
917
QuerySubscribe(void * aContext,const char * aFullName)918 void QuerySubscribe(void *aContext, const char *aFullName)
919 {
920 uint16_t length = StringLength(aFullName, Dns::Name::kMaxNameSize);
921
922 Log("QuerySubscribe(%s)", aFullName);
923
924 VerifyOrQuit(aContext == sInstance);
925 VerifyOrQuit(length < Dns::Name::kMaxNameSize);
926 strcpy(sLastSubscribeName, aFullName);
927 }
928
QueryUnsubscribe(void * aContext,const char * aFullName)929 void QueryUnsubscribe(void *aContext, const char *aFullName)
930 {
931 uint16_t length = StringLength(aFullName, Dns::Name::kMaxNameSize);
932
933 Log("QueryUnsubscribe(%s)", aFullName);
934
935 VerifyOrQuit(aContext == sInstance);
936 VerifyOrQuit(length < Dns::Name::kMaxNameSize);
937 strcpy(sLastUnsubscribeName, aFullName);
938 }
939
TestDnssdServerProxyCallback(void)940 void TestDnssdServerProxyCallback(void)
941 {
942 Srp::Server *srpServer;
943 Srp::Client *srpClient;
944 Dns::Client *dnsClient;
945 Dns::ServiceDiscovery::Server *dnsServer;
946 otDnssdServiceInstanceInfo instanceInfo;
947
948 Log("--------------------------------------------------------------------------------------------");
949 Log("TestDnssdServerProxyCallback");
950
951 InitTest();
952
953 srpServer = &sInstance->Get<Srp::Server>();
954 srpClient = &sInstance->Get<Srp::Client>();
955 dnsClient = &sInstance->Get<Dns::Client>();
956 dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
957
958 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
959 // Start SRP server.
960
961 SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
962 VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
963
964 srpServer->SetEnabled(true);
965 VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
966
967 AdvanceTime(10000);
968 VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
969
970 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
971 // Start SRP client.
972
973 srpClient->EnableAutoStartMode(nullptr, nullptr);
974 VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
975
976 AdvanceTime(2000);
977 VerifyOrQuit(srpClient->IsRunning());
978
979 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
980 // Set the query subscribe/unsubscribe callbacks on server
981
982 dnsServer->SetQueryCallbacks(QuerySubscribe, QueryUnsubscribe, sInstance);
983
984 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
985
986 sLastSubscribeName[0] = '\0';
987 sLastUnsubscribeName[0] = '\0';
988
989 sBrowseInfo.Reset();
990 Log("Browse(%s)", kService1FullName);
991 SuccessOrQuit(dnsClient->Browse(kService1FullName, BrowseCallback, sInstance));
992 AdvanceTime(10);
993
994 VerifyOrQuit(strcmp(sLastSubscribeName, kService1FullName) == 0);
995 VerifyOrQuit(strcmp(sLastUnsubscribeName, "") == 0);
996
997 VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
998
999 Log("Invoke subscribe callback");
1000
1001 memset(&instanceInfo, 0, sizeof(instanceInfo));
1002 instanceInfo.mFullName = kInstance1FullName;
1003 instanceInfo.mHostName = kHostFullName;
1004 instanceInfo.mPort = 200;
1005
1006 dnsServer->HandleDiscoveredServiceInstance(kService1FullName, instanceInfo);
1007
1008 AdvanceTime(10);
1009
1010 VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
1011 SuccessOrQuit(sBrowseInfo.mError);
1012 VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
1013
1014 VerifyOrQuit(strcmp(sLastUnsubscribeName, kService1FullName) == 0);
1015
1016 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1017
1018 sLastSubscribeName[0] = '\0';
1019 sLastUnsubscribeName[0] = '\0';
1020
1021 sBrowseInfo.Reset();
1022 Log("Browse(%s)", kService2FullName);
1023 SuccessOrQuit(dnsClient->Browse(kService2FullName, BrowseCallback, sInstance));
1024 AdvanceTime(10);
1025
1026 VerifyOrQuit(strcmp(sLastSubscribeName, kService2FullName) == 0);
1027 VerifyOrQuit(strcmp(sLastUnsubscribeName, "") == 0);
1028
1029 Log("Invoke subscribe callback for wrong name");
1030
1031 memset(&instanceInfo, 0, sizeof(instanceInfo));
1032 instanceInfo.mFullName = kInstance1FullName;
1033 instanceInfo.mHostName = kHostFullName;
1034 instanceInfo.mPort = 200;
1035
1036 dnsServer->HandleDiscoveredServiceInstance(kService1FullName, instanceInfo);
1037
1038 AdvanceTime(10);
1039
1040 VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
1041
1042 Log("Invoke subscribe callback for correct name");
1043
1044 memset(&instanceInfo, 0, sizeof(instanceInfo));
1045 instanceInfo.mFullName = kInstance2FullName;
1046 instanceInfo.mHostName = kHostFullName;
1047 instanceInfo.mPort = 200;
1048
1049 dnsServer->HandleDiscoveredServiceInstance(kService2FullName, instanceInfo);
1050
1051 AdvanceTime(10);
1052
1053 VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
1054 SuccessOrQuit(sBrowseInfo.mError);
1055 VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
1056
1057 VerifyOrQuit(strcmp(sLastUnsubscribeName, kService2FullName) == 0);
1058
1059 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1060
1061 sLastSubscribeName[0] = '\0';
1062 sLastUnsubscribeName[0] = '\0';
1063
1064 sBrowseInfo.Reset();
1065 Log("Browse(%s)", kService2FullName);
1066 SuccessOrQuit(dnsClient->Browse(kService2FullName, BrowseCallback, sInstance));
1067 AdvanceTime(10);
1068
1069 VerifyOrQuit(strcmp(sLastSubscribeName, kService2FullName) == 0);
1070 VerifyOrQuit(strcmp(sLastUnsubscribeName, "") == 0);
1071
1072 Log("Do not invoke subscribe callback and let query to timeout");
1073
1074 // Query timeout is set to 6 seconds
1075
1076 AdvanceTime(5000);
1077
1078 VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
1079
1080 AdvanceTime(2000);
1081
1082 VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
1083 SuccessOrQuit(sBrowseInfo.mError);
1084 VerifyOrQuit(sBrowseInfo.mNumInstances == 0);
1085
1086 VerifyOrQuit(strcmp(sLastUnsubscribeName, kService2FullName) == 0);
1087
1088 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1089
1090 sLastSubscribeName[0] = '\0';
1091 sLastUnsubscribeName[0] = '\0';
1092
1093 sBrowseInfo.Reset();
1094 Log("Browse(%s)", kService2FullName);
1095 SuccessOrQuit(dnsClient->Browse(kService2FullName, BrowseCallback, sInstance));
1096 AdvanceTime(10);
1097
1098 VerifyOrQuit(strcmp(sLastSubscribeName, kService2FullName) == 0);
1099 VerifyOrQuit(strcmp(sLastUnsubscribeName, "") == 0);
1100
1101 VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
1102
1103 Log("Do not invoke subscribe callback and stop server");
1104
1105 dnsServer->Stop();
1106
1107 AdvanceTime(10);
1108
1109 VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
1110 VerifyOrQuit(sBrowseInfo.mError != kErrorNone);
1111
1112 VerifyOrQuit(strcmp(sLastUnsubscribeName, kService2FullName) == 0);
1113
1114 Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1115
1116 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1117 // Finalize OT instance and validate all heap allocations are freed.
1118
1119 Log("Finalizing OT instance");
1120 FinalizeTest();
1121
1122 Log("End of TestDnssdServerProxyCallback");
1123 }
1124
1125 #endif // ENABLE_DNS_TEST
1126
main(void)1127 int main(void)
1128 {
1129 #if ENABLE_DNS_TEST
1130 TestDnsClient();
1131 TestDnssdServerProxyCallback();
1132 printf("All tests passed\n");
1133 #else
1134 printf("DNS_CLIENT or DSNSSD_SERVER feature is not enabled\n");
1135 #endif
1136
1137 return 0;
1138 }
1139