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/clearable.hpp"
43 #include "common/string.hpp"
44 #include "common/time.hpp"
45 #include "instance/instance.hpp"
46 
47 #if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE && OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE &&                 \
48     OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE && OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE && \
49     OPENTHREAD_CONFIG_DNSSD_DISCOVERY_PROXY_ENABLE && OPENTHREAD_CONFIG_SRP_SERVER_ENABLE &&                        \
50     OPENTHREAD_CONFIG_PLATFORM_DNSSD_ALLOW_RUN_TIME_SELECTION && OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE &&             \
51     !OPENTHREAD_CONFIG_TIME_SYNC_ENABLE && !OPENTHREAD_PLATFORM_POSIX
52 #define ENABLE_DISCOVERY_PROXY_TEST 1
53 #else
54 #define ENABLE_DISCOVERY_PROXY_TEST 0
55 #endif
56 
57 #if ENABLE_DISCOVERY_PROXY_TEST
58 
59 using namespace ot;
60 
61 // Logs a message and adds current time (sNow) as "<hours>:<min>:<secs>.<msec>"
62 #define Log(...)                                                                                          \
63     printf("%02u:%02u:%02u.%03u " OT_FIRST_ARG(__VA_ARGS__) "\n", (sNow / 36000000), (sNow / 60000) % 60, \
64            (sNow / 1000) % 60, sNow % 1000 OT_REST_ARGS(__VA_ARGS__))
65 
66 static constexpr uint16_t kMaxRaSize = 800;
67 
68 static ot::Instance *sInstance;
69 
70 static uint32_t sNow = 0;
71 static uint32_t sAlarmTime;
72 static bool     sAlarmOn = false;
73 
74 static otRadioFrame sRadioTxFrame;
75 static uint8_t      sRadioTxFramePsdu[OT_RADIO_FRAME_MAX_SIZE];
76 static bool         sRadioTxOngoing = false;
77 
78 //----------------------------------------------------------------------------------------------------------------------
79 // Function prototypes
80 
81 void ProcessRadioTxAndTasklets(void);
82 void AdvanceTime(uint32_t aDuration);
83 
84 //----------------------------------------------------------------------------------------------------------------------
85 // `otPlatRadio`
86 
87 extern "C" {
88 
otPlatRadioGetCaps(otInstance *)89 otRadioCaps otPlatRadioGetCaps(otInstance *) { return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF; }
90 
otPlatRadioTransmit(otInstance *,otRadioFrame *)91 otError otPlatRadioTransmit(otInstance *, otRadioFrame *)
92 {
93     sRadioTxOngoing = true;
94 
95     return OT_ERROR_NONE;
96 }
97 
otPlatRadioGetTransmitBuffer(otInstance *)98 otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *) { return &sRadioTxFrame; }
99 
100 //----------------------------------------------------------------------------------------------------------------------
101 // `otPlatAlaram`
102 
otPlatAlarmMilliStop(otInstance *)103 void otPlatAlarmMilliStop(otInstance *) { sAlarmOn = false; }
104 
otPlatAlarmMilliStartAt(otInstance *,uint32_t aT0,uint32_t aDt)105 void otPlatAlarmMilliStartAt(otInstance *, uint32_t aT0, uint32_t aDt)
106 {
107     sAlarmOn   = true;
108     sAlarmTime = aT0 + aDt;
109 }
110 
otPlatAlarmMilliGetNow(void)111 uint32_t otPlatAlarmMilliGetNow(void) { return sNow; }
112 
113 //----------------------------------------------------------------------------------------------------------------------
114 
115 Array<void *, 500> sHeapAllocatedPtrs;
116 
117 #if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
otPlatCAlloc(size_t aNum,size_t aSize)118 void *otPlatCAlloc(size_t aNum, size_t aSize)
119 {
120     void *ptr = calloc(aNum, aSize);
121 
122     SuccessOrQuit(sHeapAllocatedPtrs.PushBack(ptr));
123 
124     return ptr;
125 }
126 
otPlatFree(void * aPtr)127 void otPlatFree(void *aPtr)
128 {
129     if (aPtr != nullptr)
130     {
131         void **entry = sHeapAllocatedPtrs.Find(aPtr);
132 
133         VerifyOrQuit(entry != nullptr, "A heap allocated item is freed twice");
134         sHeapAllocatedPtrs.Remove(*entry);
135     }
136 
137     free(aPtr);
138 }
139 #endif
140 
141 #if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED
otPlatLog(otLogLevel aLogLevel,otLogRegion aLogRegion,const char * aFormat,...)142 void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
143 {
144     OT_UNUSED_VARIABLE(aLogLevel);
145     OT_UNUSED_VARIABLE(aLogRegion);
146 
147     va_list args;
148 
149     printf("   ");
150     va_start(args, aFormat);
151     vprintf(aFormat, args);
152     va_end(args);
153     printf("\n");
154 }
155 #endif
156 
157 } // extern "C"
158 
159 //---------------------------------------------------------------------------------------------------------------------
160 
ProcessRadioTxAndTasklets(void)161 void ProcessRadioTxAndTasklets(void)
162 {
163     do
164     {
165         if (sRadioTxOngoing)
166         {
167             sRadioTxOngoing = false;
168             otPlatRadioTxStarted(sInstance, &sRadioTxFrame);
169             otPlatRadioTxDone(sInstance, &sRadioTxFrame, nullptr, OT_ERROR_NONE);
170         }
171 
172         otTaskletsProcess(sInstance);
173     } while (otTaskletsArePending(sInstance));
174 }
175 
AdvanceTime(uint32_t aDuration)176 void AdvanceTime(uint32_t aDuration)
177 {
178     uint32_t time = sNow + aDuration;
179 
180     Log("AdvanceTime for %u.%03u", aDuration / 1000, aDuration % 1000);
181 
182     while (TimeMilli(sAlarmTime) <= TimeMilli(time))
183     {
184         ProcessRadioTxAndTasklets();
185         sNow = sAlarmTime;
186         otPlatAlarmMilliFired(sInstance);
187     }
188 
189     ProcessRadioTxAndTasklets();
190     sNow = time;
191 }
192 
InitTest(void)193 void InitTest(void)
194 {
195     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
196     // Initialize OT instance.
197 
198     sNow      = 0;
199     sAlarmOn  = false;
200     sInstance = static_cast<Instance *>(testInitInstance());
201 
202     memset(&sRadioTxFrame, 0, sizeof(sRadioTxFrame));
203     sRadioTxFrame.mPsdu = sRadioTxFramePsdu;
204     sRadioTxOngoing     = false;
205 
206     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
207     // Initialize Border Router and start Thread operation.
208 
209     otOperationalDataset     dataset;
210     otOperationalDatasetTlvs datasetTlvs;
211 
212     SuccessOrQuit(otDatasetCreateNewNetwork(sInstance, &dataset));
213     otDatasetConvertToTlvs(&dataset, &datasetTlvs);
214     SuccessOrQuit(otDatasetSetActiveTlvs(sInstance, &datasetTlvs));
215 
216     SuccessOrQuit(otIp6SetEnabled(sInstance, true));
217     SuccessOrQuit(otThreadSetEnabled(sInstance, true));
218 
219     // Configure the `Dnssd` module to use `otPlatDnssd` APIs.
220 
221     sInstance->Get<Dnssd>().SetUseNativeMdns(false);
222 
223     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
224     // Ensure device starts as leader.
225 
226     AdvanceTime(10000);
227 
228     VerifyOrQuit(otThreadGetDeviceRole(sInstance) == OT_DEVICE_ROLE_LEADER);
229 }
230 
FinalizeTest(void)231 void FinalizeTest(void)
232 {
233     SuccessOrQuit(otIp6SetEnabled(sInstance, false));
234     SuccessOrQuit(otThreadSetEnabled(sInstance, false));
235     // Make sure there is no message/buffer leak
236     VerifyOrQuit(sInstance->Get<MessagePool>().GetFreeBufferCount() ==
237                  sInstance->Get<MessagePool>().GetTotalBufferCount());
238     SuccessOrQuit(otInstanceErasePersistentInfo(sInstance));
239     testFreeInstance(sInstance);
240 }
241 
242 //---------------------------------------------------------------------------------------------------------------------
243 // DNS Client callback
244 
LogServiceInfo(const Dns::Client::ServiceInfo & aInfo)245 void LogServiceInfo(const Dns::Client::ServiceInfo &aInfo)
246 {
247     Log("   TTL: %u", aInfo.mTtl);
248     Log("   Port: %u", aInfo.mPort);
249     Log("   Weight: %u", aInfo.mWeight);
250     Log("   HostName: %s", aInfo.mHostNameBuffer);
251     Log("   HostAddr: %s", AsCoreType(&aInfo.mHostAddress).ToString().AsCString());
252     Log("   TxtDataLength: %u", aInfo.mTxtDataSize);
253     Log("   TxtDataTTL: %u", aInfo.mTxtDataTtl);
254 }
255 
ServiceModeToString(Dns::Client::QueryConfig::ServiceMode aMode)256 const char *ServiceModeToString(Dns::Client::QueryConfig::ServiceMode aMode)
257 {
258     static const char *const kServiceModeStrings[] = {
259         "unspec",      // kServiceModeUnspecified     (0)
260         "srv",         // kServiceModeSrv             (1)
261         "txt",         // kServiceModeTxt             (2)
262         "srv_txt",     // kServiceModeSrvTxt          (3)
263         "srv_txt_sep", // kServiceModeSrvTxtSeparate  (4)
264         "srv_txt_opt", // kServiceModeSrvTxtOptimize  (5)
265     };
266 
267     static_assert(Dns::Client::QueryConfig::kServiceModeUnspecified == 0, "Unspecified value is incorrect");
268     static_assert(Dns::Client::QueryConfig::kServiceModeSrv == 1, "Srv value is incorrect");
269     static_assert(Dns::Client::QueryConfig::kServiceModeTxt == 2, "Txt value is incorrect");
270     static_assert(Dns::Client::QueryConfig::kServiceModeSrvTxt == 3, "SrvTxt value is incorrect");
271     static_assert(Dns::Client::QueryConfig::kServiceModeSrvTxtSeparate == 4, "SrvTxtSeparate value is incorrect");
272     static_assert(Dns::Client::QueryConfig::kServiceModeSrvTxtOptimize == 5, "SrvTxtOptimize value is incorrect");
273 
274     return kServiceModeStrings[aMode];
275 }
276 
277 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
278 
279 struct BrowseInfo
280 {
ResetBrowseInfo281     void Reset(void) { mCallbackCount = 0; }
282 
283     uint16_t                 mCallbackCount;
284     Error                    mError;
285     char                     mServiceName[Dns::Name::kMaxNameSize];
286     char                     mInstanceLabel[Dns::Name::kMaxLabelSize];
287     uint16_t                 mNumInstances;
288     Dns::Client::ServiceInfo mServiceInfo;
289     char                     mHostNameBuffer[Dns::Name::kMaxNameSize];
290     uint8_t                  mTxtBuffer[255];
291 };
292 
293 static BrowseInfo sBrowseInfo;
294 
BrowseCallback(otError aError,const otDnsBrowseResponse * aResponse,void * aContext)295 void BrowseCallback(otError aError, const otDnsBrowseResponse *aResponse, void *aContext)
296 {
297     const Dns::Client::BrowseResponse &response = AsCoreType(aResponse);
298 
299     Log("BrowseCallback");
300     Log("   Error: %s", ErrorToString(aError));
301 
302     VerifyOrQuit(aContext == sInstance);
303 
304     sBrowseInfo.mCallbackCount++;
305     sBrowseInfo.mError = aError;
306 
307     SuccessOrExit(aError);
308 
309     SuccessOrQuit(response.GetServiceName(sBrowseInfo.mServiceName, sizeof(sBrowseInfo.mServiceName)));
310     Log("   ServiceName: %s", sBrowseInfo.mServiceName);
311 
312     for (uint16_t index = 0;; index++)
313     {
314         Error error;
315 
316         error = response.GetServiceInstance(index, sBrowseInfo.mInstanceLabel, sizeof(sBrowseInfo.mInstanceLabel));
317 
318         if (error == kErrorNotFound)
319         {
320             sBrowseInfo.mNumInstances = index;
321             break;
322         }
323 
324         SuccessOrQuit(error);
325 
326         Log("  %2u) %s", index + 1, sBrowseInfo.mInstanceLabel);
327     }
328 
329     if (sBrowseInfo.mNumInstances == 1)
330     {
331         sBrowseInfo.mServiceInfo.mHostNameBuffer     = sBrowseInfo.mHostNameBuffer;
332         sBrowseInfo.mServiceInfo.mHostNameBufferSize = sizeof(sBrowseInfo.mHostNameBuffer);
333         sBrowseInfo.mServiceInfo.mTxtData            = sBrowseInfo.mTxtBuffer;
334         sBrowseInfo.mServiceInfo.mTxtDataSize        = sizeof(sBrowseInfo.mTxtBuffer);
335 
336         SuccessOrExit(response.GetServiceInfo(sBrowseInfo.mInstanceLabel, sBrowseInfo.mServiceInfo));
337         LogServiceInfo(sBrowseInfo.mServiceInfo);
338     }
339 
340 exit:
341     return;
342 }
343 
344 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
345 
346 static constexpr uint8_t  kMaxHostAddresses = 10;
347 static constexpr uint16_t kMaxTxtBuffer     = 256;
348 
349 struct ResolveServiceInfo
350 {
ResetResolveServiceInfo351     void Reset(void)
352     {
353         memset(this, 0, sizeof(*this));
354         mInfo.mHostNameBuffer     = mNameBuffer;
355         mInfo.mHostNameBufferSize = sizeof(mNameBuffer);
356         mInfo.mTxtData            = mTxtBuffer;
357         mInfo.mTxtDataSize        = sizeof(mTxtBuffer);
358     };
359 
360     uint16_t                 mCallbackCount;
361     Error                    mError;
362     Dns::Client::ServiceInfo mInfo;
363     char                     mNameBuffer[Dns::Name::kMaxNameSize];
364     uint8_t                  mTxtBuffer[kMaxTxtBuffer];
365     Ip6::Address             mHostAddresses[kMaxHostAddresses];
366     uint8_t                  mNumHostAddresses;
367 };
368 
369 static ResolveServiceInfo sResolveServiceInfo;
370 
ServiceCallback(otError aError,const otDnsServiceResponse * aResponse,void * aContext)371 void ServiceCallback(otError aError, const otDnsServiceResponse *aResponse, void *aContext)
372 {
373     const Dns::Client::ServiceResponse &response = AsCoreType(aResponse);
374     char                                instLabel[Dns::Name::kMaxLabelSize];
375     char                                serviceName[Dns::Name::kMaxNameSize];
376 
377     Log("ServiceCallback");
378     Log("   Error: %s", ErrorToString(aError));
379 
380     VerifyOrQuit(aContext == sInstance);
381 
382     SuccessOrQuit(response.GetServiceName(instLabel, sizeof(instLabel), serviceName, sizeof(serviceName)));
383     Log("   InstLabel: %s", instLabel);
384     Log("   ServiceName: %s", serviceName);
385 
386     sResolveServiceInfo.mCallbackCount++;
387     sResolveServiceInfo.mError = aError;
388 
389     SuccessOrExit(aError);
390 
391     aError = response.GetServiceInfo(sResolveServiceInfo.mInfo);
392 
393     if (aError == kErrorNotFound)
394     {
395         sResolveServiceInfo.mError = aError;
396         ExitNow();
397     }
398 
399     SuccessOrQuit(aError);
400 
401     for (uint8_t index = 0; index < kMaxHostAddresses; index++)
402     {
403         Error    error;
404         uint32_t ttl;
405 
406         error = response.GetHostAddress(sResolveServiceInfo.mInfo.mHostNameBuffer, index,
407                                         sResolveServiceInfo.mHostAddresses[index], ttl);
408 
409         if (error == kErrorNotFound)
410         {
411             sResolveServiceInfo.mNumHostAddresses = index;
412             break;
413         }
414 
415         SuccessOrQuit(error);
416     }
417 
418     LogServiceInfo(sResolveServiceInfo.mInfo);
419     Log("   NumHostAddresses: %u", sResolveServiceInfo.mNumHostAddresses);
420 
421     for (uint8_t index = 0; index < sResolveServiceInfo.mNumHostAddresses; index++)
422     {
423         Log("      %s", sResolveServiceInfo.mHostAddresses[index].ToString().AsCString());
424     }
425 
426 exit:
427     return;
428 }
429 
430 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
431 
432 struct ResolveAddressInfo
433 {
ResetResolveAddressInfo434     void Reset(void) { memset(this, 0, sizeof(*this)); };
435 
436     uint16_t     mCallbackCount;
437     Error        mError;
438     char         mHostName[Dns::Name::kMaxNameSize];
439     Ip6::Address mHostAddresses[kMaxHostAddresses];
440     uint8_t      mNumHostAddresses;
441     uint32_t     mTtl;
442 };
443 
444 static ResolveAddressInfo sResolveAddressInfo;
445 
AddressCallback(otError aError,const otDnsAddressResponse * aResponse,void * aContext)446 void AddressCallback(otError aError, const otDnsAddressResponse *aResponse, void *aContext)
447 {
448     const Dns::Client::AddressResponse &response = AsCoreType(aResponse);
449 
450     Log("AddressCallback");
451     Log("   Error: %s", ErrorToString(aError));
452 
453     VerifyOrQuit(aContext == sInstance);
454 
455     sResolveAddressInfo.mCallbackCount++;
456     sResolveAddressInfo.mError = aError;
457 
458     SuccessOrExit(aError);
459 
460     SuccessOrQuit(response.GetHostName(sResolveAddressInfo.mHostName, sizeof(sResolveAddressInfo.mHostName)));
461     Log("   HostName: %s", sResolveAddressInfo.mHostName);
462 
463     for (uint8_t index = 0; index < kMaxHostAddresses; index++)
464     {
465         Error    error;
466         uint32_t ttl;
467 
468         error = response.GetAddress(index, sResolveAddressInfo.mHostAddresses[index], sResolveAddressInfo.mTtl);
469 
470         if (error == kErrorNotFound)
471         {
472             sResolveAddressInfo.mNumHostAddresses = index;
473             break;
474         }
475 
476         SuccessOrQuit(error);
477     }
478 
479     Log("   NumHostAddresses: %u", sResolveAddressInfo.mNumHostAddresses);
480 
481     for (uint8_t index = 0; index < sResolveAddressInfo.mNumHostAddresses; index++)
482     {
483         Log("      %s", sResolveAddressInfo.mHostAddresses[index].ToString().AsCString());
484     }
485 
486 exit:
487     return;
488 }
489 
490 //----------------------------------------------------------------------------------------------------------------------
491 // otPlatDnssd APIs
492 
493 constexpr uint32_t kInfraIfIndex = 1;
494 
495 static otPlatDnssdState sDnssdState = OT_PLAT_DNSSD_READY;
496 
CopyString(char (& aStringBuffer)[kSize],const char * aString)497 template <uint16_t kSize> void CopyString(char (&aStringBuffer)[kSize], const char *aString)
498 {
499     if (aString == nullptr)
500     {
501         memset(aStringBuffer, 0, kSize);
502     }
503     else
504     {
505         uint16_t length = StringLength(aString, kSize);
506 
507         VerifyOrQuit(length < kSize);
508         memcpy(aStringBuffer, aString, length + 1);
509     }
510 }
511 
512 struct BrowserInfo : public Clearable<BrowserInfo>
513 {
ServiceTypeMatchesBrowserInfo514     bool ServiceTypeMatches(const char *aType) const { return !strcmp(mServiceType, aType); }
SubTypeMatchesBrowserInfo515     bool SubTypeMatches(const char *aSubType) const { return !strcmp(mSubTypeLabel, aSubType); }
516 
UpdateFromBrowserInfo517     void UpdateFrom(const otPlatDnssdBrowser *aBrowser)
518     {
519         mCallCount++;
520         CopyString(mServiceType, aBrowser->mServiceType);
521         CopyString(mSubTypeLabel, aBrowser->mSubTypeLabel);
522         mCallback = aBrowser->mCallback;
523     }
524 
525     uint16_t                  mCallCount;
526     char                      mServiceType[Dns::Name::kMaxNameSize];
527     char                      mSubTypeLabel[Dns::Name::kMaxNameSize];
528     otPlatDnssdBrowseCallback mCallback;
529 };
530 
531 struct SrvResolverInfo : public Clearable<SrvResolverInfo>
532 {
ServiceTypeMatchesSrvResolverInfo533     bool ServiceTypeMatches(const char *aType) const { return !strcmp(mServiceType, aType); }
ServiceInstanceMatchesSrvResolverInfo534     bool ServiceInstanceMatches(const char *aInstance) const { return !strcmp(mServiceInstance, aInstance); }
535 
UpdateFromSrvResolverInfo536     void UpdateFrom(const otPlatDnssdSrvResolver *aResolver)
537     {
538         mCallCount++;
539         CopyString(mServiceInstance, aResolver->mServiceInstance);
540         CopyString(mServiceType, aResolver->mServiceType);
541         mCallback = aResolver->mCallback;
542     }
543 
544     uint16_t               mCallCount;
545     char                   mServiceInstance[Dns::Name::kMaxLabelSize];
546     char                   mServiceType[Dns::Name::kMaxNameSize];
547     otPlatDnssdSrvCallback mCallback;
548 };
549 
550 struct TxtResolverInfo : public Clearable<TxtResolverInfo>
551 {
ServiceTypeMatchesTxtResolverInfo552     bool ServiceTypeMatches(const char *aType) const { return !strcmp(mServiceType, aType); }
ServiceInstanceMatchesTxtResolverInfo553     bool ServiceInstanceMatches(const char *aInstance) const { return !strcmp(mServiceInstance, aInstance); }
554 
UpdateFromTxtResolverInfo555     void UpdateFrom(const otPlatDnssdTxtResolver *aResolver)
556     {
557         mCallCount++;
558         CopyString(mServiceInstance, aResolver->mServiceInstance);
559         CopyString(mServiceType, aResolver->mServiceType);
560         mCallback = aResolver->mCallback;
561     }
562 
563     uint16_t               mCallCount;
564     char                   mServiceInstance[Dns::Name::kMaxLabelSize];
565     char                   mServiceType[Dns::Name::kMaxNameSize];
566     otPlatDnssdTxtCallback mCallback;
567 };
568 
569 struct IpAddrResolverInfo : public Clearable<IpAddrResolverInfo>
570 {
HostNameMatchesIpAddrResolverInfo571     bool HostNameMatches(const char *aName) const { return !strcmp(mHostName, aName); }
572 
UpdateFromIpAddrResolverInfo573     void UpdateFrom(const otPlatDnssdAddressResolver *aResolver)
574     {
575         mCallCount++;
576         CopyString(mHostName, aResolver->mHostName);
577         mCallback = aResolver->mCallback;
578     }
579 
580     uint16_t                   mCallCount;
581     char                       mHostName[Dns::Name::kMaxNameSize];
582     otPlatDnssdAddressCallback mCallback;
583 };
584 
585 struct InvokeOnStart : public Clearable<InvokeOnStart>
586 {
587     // When not null, these entries are used to invoke callback
588     // directly from `otPlatDnssdStart{Browser/Resolver}()` APIs.
589     // This is used in `TestProxyInvokeCallbackFromStartApi()`.
590 
591     const otPlatDnssdBrowseResult  *mBrowseResult;
592     const otPlatDnssdSrvResult     *mSrvResult;
593     const otPlatDnssdTxtResult     *mTxtResult;
594     const otPlatDnssdAddressResult *mIp6AddrResult;
595     const otPlatDnssdAddressResult *mIp4AddrResult;
596 };
597 
598 static BrowserInfo        sStartBrowserInfo;
599 static BrowserInfo        sStopBrowserInfo;
600 static SrvResolverInfo    sStartSrvResolverInfo;
601 static SrvResolverInfo    sStopSrvResolverInfo;
602 static TxtResolverInfo    sStartTxtResolverInfo;
603 static TxtResolverInfo    sStopTxtResolverInfo;
604 static IpAddrResolverInfo sStartIp6AddrResolverInfo;
605 static IpAddrResolverInfo sStopIp6AddrResolverInfo;
606 static IpAddrResolverInfo sStartIp4AddrResolverInfo;
607 static IpAddrResolverInfo sStopIp4AddrResolverInfo;
608 
609 static InvokeOnStart sInvokeOnStart;
610 
ResetPlatDnssdApiInfo(void)611 void ResetPlatDnssdApiInfo(void)
612 {
613     sStartBrowserInfo.Clear();
614     sStopBrowserInfo.Clear();
615     sStartSrvResolverInfo.Clear();
616     sStopSrvResolverInfo.Clear();
617     sStartTxtResolverInfo.Clear();
618     sStopTxtResolverInfo.Clear();
619     sStartIp6AddrResolverInfo.Clear();
620     sStopIp6AddrResolverInfo.Clear();
621     sStartIp4AddrResolverInfo.Clear();
622     sStopIp4AddrResolverInfo.Clear();
623     sInvokeOnStart.Clear();
624 }
625 
StringNullCheck(const char * aString)626 const char *StringNullCheck(const char *aString) { return (aString != nullptr) ? aString : "(null)"; }
627 
InvokeBrowserCallback(otPlatDnssdBrowseCallback aCallback,const otPlatDnssdBrowseResult & aResult)628 void InvokeBrowserCallback(otPlatDnssdBrowseCallback aCallback, const otPlatDnssdBrowseResult &aResult)
629 {
630     Log("Invoking browser callback");
631     Log("    serviceType    : \"%s\"", StringNullCheck(aResult.mServiceType));
632     Log("    subType        : \"%s\"", StringNullCheck(aResult.mSubTypeLabel));
633     Log("    serviceInstance: \"%s\"", StringNullCheck(aResult.mServiceInstance));
634     Log("    ttl            : %u", aResult.mTtl);
635     Log("    if-index       : %u", aResult.mInfraIfIndex);
636 
637     aCallback(sInstance, &aResult);
638 }
639 
InvokeSrvResolverCallback(otPlatDnssdSrvCallback aCallback,const otPlatDnssdSrvResult & aResult)640 void InvokeSrvResolverCallback(otPlatDnssdSrvCallback aCallback, const otPlatDnssdSrvResult &aResult)
641 {
642     Log("Invoking SRV resolver callback");
643     Log("    serviceInstance: %s", StringNullCheck(aResult.mServiceInstance));
644     Log("    serviceType    : %s", StringNullCheck(aResult.mServiceType));
645     Log("    hostName       : %s", StringNullCheck(aResult.mHostName));
646     Log("    port           : %u", aResult.mPort);
647     Log("    priority       : %u", aResult.mPriority);
648     Log("    weight         : %u", aResult.mWeight);
649     Log("    ttl            : %u", aResult.mTtl);
650     Log("    if-index       : %u", aResult.mInfraIfIndex);
651 
652     aCallback(sInstance, &aResult);
653 }
654 
InvokeTxtResolverCallback(otPlatDnssdTxtCallback aCallback,const otPlatDnssdTxtResult & aResult)655 void InvokeTxtResolverCallback(otPlatDnssdTxtCallback aCallback, const otPlatDnssdTxtResult &aResult)
656 {
657     Log("Invoking TXT resolver callback");
658     Log("    serviceInstance: %s", StringNullCheck(aResult.mServiceInstance));
659     Log("    serviceType    : %s", StringNullCheck(aResult.mServiceType));
660     Log("    txt-data-len   : %u", aResult.mTxtDataLength);
661     Log("    ttl            : %u", aResult.mTtl);
662     Log("    if-index       : %u", aResult.mInfraIfIndex);
663 
664     aCallback(sInstance, &aResult);
665 }
666 
InvokeIp6AddrResolverCallback(const otPlatDnssdAddressCallback aCallback,const otPlatDnssdAddressResult & aResult)667 void InvokeIp6AddrResolverCallback(const otPlatDnssdAddressCallback aCallback, const otPlatDnssdAddressResult &aResult)
668 {
669     Log("Invoking Ip6 resolver callback");
670     Log("    hostName       : %s", aResult.mHostName);
671     Log("    if-index       : %u", aResult.mInfraIfIndex);
672     Log("    numAddresses   : %u", aResult.mAddressesLength);
673     for (uint16_t index = 0; index < aResult.mAddressesLength; index++)
674     {
675         Log("    address[%u]     : %s", index, AsCoreType(&aResult.mAddresses[index].mAddress).ToString().AsCString());
676         Log("    ttl[%u]         : %u", index, aResult.mAddresses[index].mTtl);
677     }
678 
679     aCallback(sInstance, &aResult);
680 }
681 
InvokeIp4AddrResolverCallback(const otPlatDnssdAddressCallback aCallback,const otPlatDnssdAddressResult & aResult)682 void InvokeIp4AddrResolverCallback(const otPlatDnssdAddressCallback aCallback, const otPlatDnssdAddressResult &aResult)
683 {
684     Log("Invoking Ip4 resolver callback");
685     Log("    hostName       : %s", aResult.mHostName);
686     Log("    if-index       : %u", aResult.mInfraIfIndex);
687     Log("    numAddresses   : %u", aResult.mAddressesLength);
688     for (uint16_t index = 0; index < aResult.mAddressesLength; index++)
689     {
690         Log("    address[%u]     : %s", index, AsCoreType(&aResult.mAddresses[index].mAddress).ToString().AsCString());
691         Log("    ttl[%u]         : %u", index, aResult.mAddresses[index].mTtl);
692     }
693 
694     aCallback(sInstance, &aResult);
695 }
696 
otPlatDnssdGetState(otInstance * aInstance)697 otPlatDnssdState otPlatDnssdGetState(otInstance *aInstance)
698 {
699     OT_UNUSED_VARIABLE(aInstance);
700 
701     return sDnssdState;
702 }
703 
otPlatDnssdStartBrowser(otInstance * aInstance,const otPlatDnssdBrowser * aBrowser)704 void otPlatDnssdStartBrowser(otInstance *aInstance, const otPlatDnssdBrowser *aBrowser)
705 {
706     VerifyOrQuit(aBrowser != nullptr);
707 
708     Log("otPlatDnssdStartBrowser(\"%s\", sub-type:\"%s\")", aBrowser->mServiceType, aBrowser->mSubTypeLabel);
709 
710     VerifyOrQuit(aInstance == sInstance);
711     VerifyOrQuit(aBrowser->mInfraIfIndex == kInfraIfIndex);
712 
713     sStartBrowserInfo.UpdateFrom(aBrowser);
714 
715     if (sInvokeOnStart.mBrowseResult != nullptr)
716     {
717         InvokeBrowserCallback(aBrowser->mCallback, *sInvokeOnStart.mBrowseResult);
718     }
719 }
720 
otPlatDnssdStopBrowser(otInstance * aInstance,const otPlatDnssdBrowser * aBrowser)721 void otPlatDnssdStopBrowser(otInstance *aInstance, const otPlatDnssdBrowser *aBrowser)
722 {
723     VerifyOrQuit(aBrowser != nullptr);
724 
725     Log("otPlatDnssdStopBrowser(\"%s\", sub-type:\"%s\")", aBrowser->mServiceType, aBrowser->mSubTypeLabel);
726 
727     VerifyOrQuit(aInstance == sInstance);
728     VerifyOrQuit(aBrowser->mInfraIfIndex == kInfraIfIndex);
729 
730     sStopBrowserInfo.UpdateFrom(aBrowser);
731 }
732 
otPlatDnssdStartSrvResolver(otInstance * aInstance,const otPlatDnssdSrvResolver * aResolver)733 void otPlatDnssdStartSrvResolver(otInstance *aInstance, const otPlatDnssdSrvResolver *aResolver)
734 {
735     VerifyOrQuit(aResolver != nullptr);
736 
737     Log("otPlatDnssdStartSrvResolver(\"%s\", \"%s\")", aResolver->mServiceInstance, aResolver->mServiceType);
738 
739     VerifyOrQuit(aInstance == sInstance);
740     VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
741 
742     sStartSrvResolverInfo.UpdateFrom(aResolver);
743 
744     if (sInvokeOnStart.mSrvResult != nullptr)
745     {
746         InvokeSrvResolverCallback(aResolver->mCallback, *sInvokeOnStart.mSrvResult);
747     }
748 }
749 
otPlatDnssdStopSrvResolver(otInstance * aInstance,const otPlatDnssdSrvResolver * aResolver)750 void otPlatDnssdStopSrvResolver(otInstance *aInstance, const otPlatDnssdSrvResolver *aResolver)
751 {
752     VerifyOrQuit(aResolver != nullptr);
753 
754     Log("otPlatDnssdStopSrvResolver(\"%s\", \"%s\")", aResolver->mServiceInstance, aResolver->mServiceType);
755 
756     VerifyOrQuit(aInstance == sInstance);
757     VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
758 
759     sStopSrvResolverInfo.UpdateFrom(aResolver);
760 }
761 
otPlatDnssdStartTxtResolver(otInstance * aInstance,const otPlatDnssdTxtResolver * aResolver)762 void otPlatDnssdStartTxtResolver(otInstance *aInstance, const otPlatDnssdTxtResolver *aResolver)
763 {
764     VerifyOrQuit(aResolver != nullptr);
765 
766     Log("otPlatDnssdStartTxtResolver(\"%s\", \"%s\")", aResolver->mServiceInstance, aResolver->mServiceType);
767 
768     VerifyOrQuit(aInstance == sInstance);
769     VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
770 
771     sStartTxtResolverInfo.UpdateFrom(aResolver);
772 
773     if (sInvokeOnStart.mTxtResult != nullptr)
774     {
775         InvokeTxtResolverCallback(aResolver->mCallback, *sInvokeOnStart.mTxtResult);
776     }
777 }
778 
otPlatDnssdStopTxtResolver(otInstance * aInstance,const otPlatDnssdTxtResolver * aResolver)779 void otPlatDnssdStopTxtResolver(otInstance *aInstance, const otPlatDnssdTxtResolver *aResolver)
780 {
781     VerifyOrQuit(aResolver != nullptr);
782 
783     Log("otPlatDnssdStopTxtResolver(\"%s\", \"%s\")", aResolver->mServiceInstance, aResolver->mServiceType);
784 
785     VerifyOrQuit(aInstance == sInstance);
786     VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
787 
788     sStopTxtResolverInfo.UpdateFrom(aResolver);
789 }
790 
otPlatDnssdStartIp6AddressResolver(otInstance * aInstance,const otPlatDnssdAddressResolver * aResolver)791 void otPlatDnssdStartIp6AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver)
792 {
793     VerifyOrQuit(aResolver != nullptr);
794 
795     Log("otPlatDnssdStartIp6AddressResolver(\"%s\")", aResolver->mHostName);
796 
797     VerifyOrQuit(aInstance == sInstance);
798     VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
799 
800     sStartIp6AddrResolverInfo.UpdateFrom(aResolver);
801 
802     if (sInvokeOnStart.mIp6AddrResult != nullptr)
803     {
804         InvokeIp6AddrResolverCallback(aResolver->mCallback, *sInvokeOnStart.mIp6AddrResult);
805     }
806 }
807 
otPlatDnssdStopIp6AddressResolver(otInstance * aInstance,const otPlatDnssdAddressResolver * aResolver)808 void otPlatDnssdStopIp6AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver)
809 {
810     VerifyOrQuit(aResolver != nullptr);
811 
812     Log("otPlatDnssdStopIp6AddressResolver(\"%s\")", aResolver->mHostName);
813 
814     VerifyOrQuit(aInstance == sInstance);
815     VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
816 
817     sStopIp6AddrResolverInfo.UpdateFrom(aResolver);
818 
819     if (sInvokeOnStart.mIp6AddrResult != nullptr)
820     {
821         InvokeIp6AddrResolverCallback(aResolver->mCallback, *sInvokeOnStart.mIp6AddrResult);
822     }
823 }
824 
otPlatDnssdStartIp4AddressResolver(otInstance * aInstance,const otPlatDnssdAddressResolver * aResolver)825 void otPlatDnssdStartIp4AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver)
826 {
827     VerifyOrQuit(aResolver != nullptr);
828 
829     Log("otPlatDnssdStartIp4AddressResolver(\"%s\")", aResolver->mHostName);
830 
831     VerifyOrQuit(aInstance == sInstance);
832     VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
833 
834     sStartIp4AddrResolverInfo.UpdateFrom(aResolver);
835 
836     if (sInvokeOnStart.mIp4AddrResult != nullptr)
837     {
838         InvokeIp6AddrResolverCallback(aResolver->mCallback, *sInvokeOnStart.mIp4AddrResult);
839     }
840 }
841 
otPlatDnssdStopIp4AddressResolver(otInstance * aInstance,const otPlatDnssdAddressResolver * aResolver)842 void otPlatDnssdStopIp4AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver)
843 {
844     VerifyOrQuit(aResolver != nullptr);
845 
846     Log("otPlatDnssdStopIp4AddressResolver(\"%s\")", aResolver->mHostName);
847 
848     VerifyOrQuit(aInstance == sInstance);
849     VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
850 
851     sStopIp4AddrResolverInfo.UpdateFrom(aResolver);
852 
853     if (sInvokeOnStart.mIp6AddrResult != nullptr)
854     {
855         InvokeIp4AddrResolverCallback(aResolver->mCallback, *sInvokeOnStart.mIp4AddrResult);
856     }
857 }
858 
859 //----------------------------------------------------------------------------------------------------------------------
860 
TestProxyBasic(void)861 void TestProxyBasic(void)
862 {
863     static constexpr uint32_t kTtl = 300;
864 
865     const uint8_t kTxtData[] = {3, 'A', '=', '1', 0};
866 
867     Srp::Server                     *srpServer;
868     Srp::Client                     *srpClient;
869     Dns::Client                     *dnsClient;
870     Dns::ServiceDiscovery::Server   *dnsServer;
871     Dnssd::BrowseResult              browseResult;
872     Dnssd::SrvResult                 srvResult;
873     Dnssd::TxtResult                 txtResult;
874     Dnssd::AddressResult             ip6AddrrResult;
875     Dnssd::AddressResult             ip4AddrrResult;
876     Dnssd::AddressAndTtl             addressAndTtl;
877     NetworkData::ExternalRouteConfig routeConfig;
878     Ip6::Address                     address;
879 
880     Log("--------------------------------------------------------------------------------------------");
881     Log("TestProxyBasic");
882 
883     InitTest();
884 
885     srpServer = &sInstance->Get<Srp::Server>();
886     srpClient = &sInstance->Get<Srp::Client>();
887     dnsClient = &sInstance->Get<Dns::Client>();
888     dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
889 
890     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
891     // Start SRP server.
892 
893     SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
894 
895     SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
896     VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
897 
898     srpServer->SetEnabled(true);
899     VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
900 
901     AdvanceTime(10000);
902     VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
903 
904     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
905     // Start SRP client.
906 
907     srpClient->EnableAutoStartMode(nullptr, nullptr);
908     VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
909 
910     AdvanceTime(2000);
911     VerifyOrQuit(srpClient->IsRunning());
912 
913     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
914     Log("Add a route prefix (with NAT64 flag) to network data");
915 
916     routeConfig.Clear();
917     SuccessOrQuit(AsCoreType(&routeConfig.mPrefix.mPrefix).FromString("64:ff9b::"));
918     routeConfig.mPrefix.mLength = 96;
919     routeConfig.mPreference     = NetworkData::kRoutePreferenceMedium;
920     routeConfig.mNat64          = true;
921     routeConfig.mStable         = true;
922 
923     SuccessOrQuit(otBorderRouterAddRoute(sInstance, &routeConfig));
924     SuccessOrQuit(otBorderRouterRegister(sInstance));
925 
926     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
927 
928     sBrowseInfo.Reset();
929     ResetPlatDnssdApiInfo();
930 
931     Log("Browse()");
932     SuccessOrQuit(dnsClient->Browse("_avenger._udp.default.service.arpa.", BrowseCallback, sInstance));
933     AdvanceTime(10);
934 
935     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
936     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
937     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
938     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
939     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
940     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
941     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
942     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
943     VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
944     VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
945 
946     VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_avenger._udp"));
947 
948     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
949     Log("Invoke Browser callback");
950 
951     browseResult.mServiceType     = "_avenger._udp";
952     browseResult.mSubTypeLabel    = nullptr;
953     browseResult.mServiceInstance = "hulk";
954     browseResult.mTtl             = kTtl;
955     browseResult.mInfraIfIndex    = kInfraIfIndex;
956 
957     InvokeBrowserCallback(sStartBrowserInfo.mCallback, browseResult);
958 
959     AdvanceTime(10);
960 
961     // Check that browser is stopped and a service resolver is started
962 
963     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
964     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
965     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
966     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
967     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
968     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
969     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
970     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
971     VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
972     VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
973 
974     VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_avenger._udp"));
975     VerifyOrQuit(sStopBrowserInfo.mCallback == sStartBrowserInfo.mCallback);
976 
977     VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
978     VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("hulk"));
979 
980     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
981     Log("Invoke SRV resolver callback");
982 
983     srvResult.mServiceInstance = "hulk";
984     srvResult.mServiceType     = "_avenger._udp";
985     srvResult.mHostName        = "compound";
986     srvResult.mPort            = 7777;
987     srvResult.mTtl             = kTtl;
988     srvResult.mInfraIfIndex    = kInfraIfIndex;
989 
990     InvokeSrvResolverCallback(sStartSrvResolverInfo.mCallback, srvResult);
991 
992     AdvanceTime(10);
993 
994     // Check that SRV resolver is stopped and a TXT resolver is started
995 
996     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
997     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
998     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
999     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
1000     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
1001     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1002     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1003     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1004 
1005     VerifyOrQuit(sStopSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
1006     VerifyOrQuit(sStopSrvResolverInfo.ServiceInstanceMatches("hulk"));
1007     VerifyOrQuit(sStopSrvResolverInfo.mCallback == sStartSrvResolverInfo.mCallback);
1008 
1009     VerifyOrQuit(sStartTxtResolverInfo.ServiceTypeMatches("_avenger._udp"));
1010     VerifyOrQuit(sStartTxtResolverInfo.ServiceInstanceMatches("hulk"));
1011 
1012     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1013     Log("Invoke TXT resolver callback");
1014 
1015     txtResult.mServiceInstance = "hulk";
1016     txtResult.mServiceType     = "_avenger._udp";
1017     txtResult.mTxtData         = kTxtData;
1018     txtResult.mTxtDataLength   = sizeof(kTxtData);
1019     txtResult.mTtl             = kTtl;
1020     txtResult.mInfraIfIndex    = kInfraIfIndex;
1021 
1022     InvokeTxtResolverCallback(sStartTxtResolverInfo.mCallback, txtResult);
1023 
1024     AdvanceTime(10);
1025 
1026     // Check that TXT resolver is stopped and an address resolver is started
1027 
1028     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
1029     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
1030     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1031     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
1032     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
1033     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
1034     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
1035     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1036     VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
1037     VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
1038 
1039     VerifyOrQuit(sStopTxtResolverInfo.ServiceTypeMatches("_avenger._udp"));
1040     VerifyOrQuit(sStopTxtResolverInfo.ServiceInstanceMatches("hulk"));
1041     VerifyOrQuit(sStopTxtResolverInfo.mCallback == sStartTxtResolverInfo.mCallback);
1042 
1043     VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("compound"));
1044 
1045     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1046     Log("Invoke Address Resolver callback");
1047 
1048     SuccessOrQuit(AsCoreType(&addressAndTtl.mAddress).FromString("fd00::1234"));
1049     addressAndTtl.mTtl = kTtl;
1050 
1051     ip6AddrrResult.mHostName        = "compound";
1052     ip6AddrrResult.mInfraIfIndex    = kInfraIfIndex;
1053     ip6AddrrResult.mAddresses       = &addressAndTtl;
1054     ip6AddrrResult.mAddressesLength = 1;
1055 
1056     InvokeIp6AddrResolverCallback(sStartIp6AddrResolverInfo.mCallback, ip6AddrrResult);
1057 
1058     AdvanceTime(10);
1059 
1060     // Check that address resolver is stopped
1061 
1062     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
1063     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
1064     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1065     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
1066     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
1067     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
1068     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
1069     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
1070     VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
1071     VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
1072 
1073     VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("compound"));
1074     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallback == sStartIp6AddrResolverInfo.mCallback);
1075 
1076     // Check that response is sent to client and validate it
1077 
1078     VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
1079     SuccessOrQuit(sBrowseInfo.mError);
1080     VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
1081 
1082     VerifyOrQuit(!strcmp(sBrowseInfo.mServiceName, "_avenger._udp.default.service.arpa."));
1083     VerifyOrQuit(!strcmp(sBrowseInfo.mInstanceLabel, "hulk"));
1084     VerifyOrQuit(!strcmp(sBrowseInfo.mServiceInfo.mHostNameBuffer, "compound.default.service.arpa."));
1085     VerifyOrQuit(sBrowseInfo.mServiceInfo.mPort == 7777);
1086     VerifyOrQuit(sBrowseInfo.mServiceInfo.mTtl == kTtl);
1087     VerifyOrQuit(AsCoreType(&sBrowseInfo.mServiceInfo.mHostAddress) == AsCoreType(&addressAndTtl.mAddress));
1088     VerifyOrQuit(sBrowseInfo.mServiceInfo.mHostAddressTtl == kTtl);
1089     VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataSize == sizeof(kTxtData));
1090     VerifyOrQuit(!memcmp(sBrowseInfo.mServiceInfo.mTxtData, kTxtData, sizeof(kTxtData)));
1091     VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataTtl == kTtl);
1092     VerifyOrQuit(!sBrowseInfo.mServiceInfo.mTxtDataTruncated);
1093 
1094     Log("--------------------------------------------------------------------------------------------");
1095 
1096     ResetPlatDnssdApiInfo();
1097     sResolveServiceInfo.Reset();
1098 
1099     Log("ResolveService() with dot `.` character in service instance label");
1100     SuccessOrQuit(
1101         dnsClient->ResolveService("iron.man", "_avenger._udp.default.service.arpa.", ServiceCallback, sInstance));
1102 
1103     AdvanceTime(10);
1104 
1105     // Check that a service resolver is started
1106 
1107     VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
1108     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1109     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1110     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1111     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1112     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1113     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1114     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1115     VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
1116     VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
1117 
1118     VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
1119     VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("iron.man"));
1120 
1121     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1122     Log("Invoke SRV Resolver callback for wrong name");
1123 
1124     srvResult.mServiceInstance = "hulk";
1125     srvResult.mServiceType     = "_avenger._udp";
1126     srvResult.mHostName        = "compound";
1127     srvResult.mPort            = 7777;
1128     srvResult.mTtl             = kTtl;
1129     srvResult.mInfraIfIndex    = kInfraIfIndex;
1130 
1131     InvokeSrvResolverCallback(sStartSrvResolverInfo.mCallback, srvResult);
1132 
1133     AdvanceTime(10);
1134 
1135     // Check that no changes to browsers/resolvers
1136 
1137     VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
1138     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1139     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1140     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1141     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1142     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1143     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1144     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1145     VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
1146     VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
1147 
1148     VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 0);
1149 
1150     Log("Invoke SRV Resolver callback for correct name");
1151 
1152     srvResult.mServiceInstance = "iron.man";
1153     srvResult.mServiceType     = "_avenger._udp";
1154     srvResult.mHostName        = "starktower";
1155     srvResult.mPort            = 1024;
1156     srvResult.mTtl             = kTtl;
1157     srvResult.mInfraIfIndex    = kInfraIfIndex;
1158 
1159     InvokeSrvResolverCallback(sStartSrvResolverInfo.mCallback, srvResult);
1160 
1161     AdvanceTime(10);
1162 
1163     // Check that SRV resolver is stopped and TXT resolver is started
1164 
1165     VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
1166     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1167     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1168     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
1169     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
1170     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1171     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1172     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1173 
1174     VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 0);
1175 
1176     VerifyOrQuit(sStopSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
1177     VerifyOrQuit(sStopSrvResolverInfo.ServiceInstanceMatches("iron.man"));
1178     VerifyOrQuit(sStopSrvResolverInfo.mCallback == sStartSrvResolverInfo.mCallback);
1179 
1180     VerifyOrQuit(sStartTxtResolverInfo.ServiceTypeMatches("_avenger._udp"));
1181     VerifyOrQuit(sStartTxtResolverInfo.ServiceInstanceMatches("iron.man"));
1182 
1183     Log("Invoke TXT Resolver callback");
1184 
1185     txtResult.mServiceInstance = "iron.man";
1186     txtResult.mServiceType     = "_avenger._udp";
1187     txtResult.mTxtData         = kTxtData;
1188     txtResult.mTxtDataLength   = sizeof(kTxtData);
1189     txtResult.mTtl             = kTtl;
1190     txtResult.mInfraIfIndex    = kInfraIfIndex;
1191 
1192     InvokeTxtResolverCallback(sStartTxtResolverInfo.mCallback, txtResult);
1193     AdvanceTime(10);
1194 
1195     // Check that TXT resolver is stopped and addr resolver is started
1196 
1197     VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
1198     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1199     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1200     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
1201     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
1202     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
1203     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
1204     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1205     VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
1206     VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
1207 
1208     VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 0);
1209 
1210     VerifyOrQuit(sStopTxtResolverInfo.ServiceTypeMatches("_avenger._udp"));
1211     VerifyOrQuit(sStopTxtResolverInfo.ServiceInstanceMatches("iron.man"));
1212     VerifyOrQuit(sStopTxtResolverInfo.mCallback == sStartTxtResolverInfo.mCallback);
1213 
1214     VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("starktower"));
1215 
1216     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1217     Log("Invoke Address Resolver callback");
1218 
1219     ip6AddrrResult.mHostName = "starktower";
1220 
1221     InvokeIp6AddrResolverCallback(sStartIp6AddrResolverInfo.mCallback, ip6AddrrResult);
1222     AdvanceTime(10);
1223 
1224     // Check that address resolver is stopped
1225 
1226     VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
1227     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1228     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1229     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
1230     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
1231     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
1232     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
1233     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
1234     VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
1235     VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
1236 
1237     VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("starktower"));
1238     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallback == sStartIp6AddrResolverInfo.mCallback);
1239 
1240     // Check that response is sent to client and validate it
1241 
1242     VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
1243     VerifyOrQuit(sResolveServiceInfo.mError == kErrorNone);
1244 
1245     VerifyOrQuit(!strcmp(sResolveServiceInfo.mInfo.mHostNameBuffer, "starktower.default.service.arpa."));
1246     VerifyOrQuit(sResolveServiceInfo.mInfo.mPort == 1024);
1247     VerifyOrQuit(sResolveServiceInfo.mInfo.mTtl == kTtl);
1248     VerifyOrQuit(AsCoreType(&sResolveServiceInfo.mInfo.mHostAddress) == AsCoreType(&addressAndTtl.mAddress));
1249     VerifyOrQuit(sResolveServiceInfo.mInfo.mHostAddressTtl == kTtl);
1250     VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataSize == sizeof(kTxtData));
1251     VerifyOrQuit(!memcmp(sResolveServiceInfo.mInfo.mTxtData, kTxtData, sizeof(kTxtData)));
1252     VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataTtl == kTtl);
1253     VerifyOrQuit(!sResolveServiceInfo.mInfo.mTxtDataTruncated);
1254 
1255     Log("--------------------------------------------------------------------------------------------");
1256 
1257     ResetPlatDnssdApiInfo();
1258     sResolveAddressInfo.Reset();
1259 
1260     Log("ResolveAddress()");
1261     SuccessOrQuit(dnsClient->ResolveAddress("earth.default.service.arpa.", AddressCallback, sInstance));
1262     AdvanceTime(10);
1263 
1264     // Check that an address resolver is started
1265 
1266     VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
1267     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1268     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
1269     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1270     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1271     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1272     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
1273     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1274     VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
1275     VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
1276 
1277     VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("earth"));
1278 
1279     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
1280 
1281     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1282     Log("Invoke Address Resolver callback");
1283 
1284     SuccessOrQuit(AsCoreType(&addressAndTtl.mAddress).FromString("fd00::7777"));
1285     addressAndTtl.mTtl              = kTtl;
1286     ip6AddrrResult.mHostName        = "earth";
1287     ip6AddrrResult.mInfraIfIndex    = kInfraIfIndex;
1288     ip6AddrrResult.mAddresses       = &addressAndTtl;
1289     ip6AddrrResult.mAddressesLength = 1;
1290 
1291     InvokeIp6AddrResolverCallback(sStartIp6AddrResolverInfo.mCallback, ip6AddrrResult);
1292 
1293     AdvanceTime(10);
1294 
1295     // Check that the address resolver is stopped
1296 
1297     VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
1298     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1299     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
1300     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1301     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1302     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1303     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
1304     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
1305     VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
1306     VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
1307 
1308     VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("earth"));
1309     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallback == sStartIp6AddrResolverInfo.mCallback);
1310 
1311     // Check that response is sent to client and validate it
1312 
1313     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
1314     SuccessOrQuit(sResolveAddressInfo.mError);
1315 
1316     VerifyOrQuit(!strcmp(sResolveAddressInfo.mHostName, "earth.default.service.arpa."));
1317     VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 1);
1318     VerifyOrQuit(sResolveAddressInfo.mHostAddresses[0] == AsCoreType(&addressAndTtl.mAddress));
1319     VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl);
1320 
1321     Log("--------------------------------------------------------------------------------------------");
1322 
1323     ResetPlatDnssdApiInfo();
1324     sResolveAddressInfo.Reset();
1325 
1326     Log("ResolveIp4Address()");
1327     SuccessOrQuit(dnsClient->ResolveIp4Address("shield.default.service.arpa.", AddressCallback, sInstance));
1328     AdvanceTime(10);
1329 
1330     // Check that an IPv4 address resolver is started
1331 
1332     VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
1333     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1334     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
1335     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1336     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1337     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1338     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1339     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1340     VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 1);
1341     VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
1342 
1343     VerifyOrQuit(sStartIp4AddrResolverInfo.HostNameMatches("shield"));
1344 
1345     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
1346 
1347     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1348     Log("Invoke IPv4 Address Resolver callback");
1349 
1350     SuccessOrQuit(AsCoreType(&addressAndTtl.mAddress).FromString("::ffff:1.2.3.4"));
1351     addressAndTtl.mTtl              = kTtl;
1352     ip4AddrrResult.mHostName        = "shield";
1353     ip4AddrrResult.mInfraIfIndex    = kInfraIfIndex;
1354     ip4AddrrResult.mAddresses       = &addressAndTtl;
1355     ip4AddrrResult.mAddressesLength = 1;
1356 
1357     InvokeIp4AddrResolverCallback(sStartIp4AddrResolverInfo.mCallback, ip4AddrrResult);
1358 
1359     AdvanceTime(10);
1360 
1361     // Check that the IPv4 address resolver is stopped
1362 
1363     VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
1364     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1365     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
1366     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1367     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1368     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1369     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1370     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1371     VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 1);
1372     VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 1);
1373 
1374     VerifyOrQuit(sStopIp4AddrResolverInfo.HostNameMatches("shield"));
1375     VerifyOrQuit(sStopIp4AddrResolverInfo.mCallback == sStartIp4AddrResolverInfo.mCallback);
1376 
1377     // Check that response is sent to client and validate it
1378 
1379     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
1380     SuccessOrQuit(sResolveAddressInfo.mError);
1381 
1382     VerifyOrQuit(!strcmp(sResolveAddressInfo.mHostName, "shield.default.service.arpa."));
1383     VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 1);
1384 
1385     // The 1.2.3.4 address with the NAT64 prefix
1386     SuccessOrQuit(address.FromString("64:ff9b:0:0:0:0:102:304"));
1387     VerifyOrQuit(sResolveAddressInfo.mHostAddresses[0] == address);
1388     VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl);
1389 
1390     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
1391     SuccessOrQuit(sResolveAddressInfo.mError);
1392 
1393     VerifyOrQuit(!strcmp(sResolveAddressInfo.mHostName, "shield.default.service.arpa."));
1394     VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 1);
1395     VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl);
1396 
1397     VerifyOrQuit(sResolveAddressInfo.mHostAddresses[0] == address);
1398 
1399     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1400     Log("Stop DNS-SD server");
1401 
1402     dnsServer->Stop();
1403 
1404     AdvanceTime(10);
1405 
1406     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1407     // Finalize OT instance and validate all heap allocations are freed.
1408 
1409     Log("Finalizing OT instance");
1410     FinalizeTest();
1411 
1412     Log("End of TestProxyBasic");
1413 }
1414 
1415 //----------------------------------------------------------------------------------------------------------------------
1416 
TestProxySubtypeBrowse(void)1417 void TestProxySubtypeBrowse(void)
1418 {
1419     static constexpr uint32_t kTtl = 300;
1420 
1421     const uint8_t kTxtData[] = {3, 'G', '=', '0', 0};
1422 
1423     Srp::Server                   *srpServer;
1424     Srp::Client                   *srpClient;
1425     Dns::Client                   *dnsClient;
1426     Dns::ServiceDiscovery::Server *dnsServer;
1427     Dnssd::BrowseResult            browseResult;
1428     Dnssd::SrvResult               srvResult;
1429     Dnssd::TxtResult               txtResult;
1430     Dnssd::AddressResult           ip6AddrrResult;
1431     Dnssd::AddressAndTtl           addressAndTtl;
1432 
1433     Log("--------------------------------------------------------------------------------------------");
1434     Log("TestProxySubtypeBrowse");
1435 
1436     InitTest();
1437 
1438     srpServer = &sInstance->Get<Srp::Server>();
1439     srpClient = &sInstance->Get<Srp::Client>();
1440     dnsClient = &sInstance->Get<Dns::Client>();
1441     dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
1442 
1443     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1444     // Start SRP server.
1445 
1446     SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
1447 
1448     SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
1449     VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
1450 
1451     srpServer->SetEnabled(true);
1452     VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
1453 
1454     AdvanceTime(10000);
1455     VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
1456 
1457     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1458     // Start SRP client.
1459 
1460     srpClient->EnableAutoStartMode(nullptr, nullptr);
1461     VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
1462 
1463     AdvanceTime(2000);
1464     VerifyOrQuit(srpClient->IsRunning());
1465 
1466     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1467 
1468     sBrowseInfo.Reset();
1469     ResetPlatDnssdApiInfo();
1470 
1471     Log("Browse() for sub-type service");
1472     SuccessOrQuit(dnsClient->Browse("_god._sub._avenger._udp.default.service.arpa.", BrowseCallback, sInstance));
1473     AdvanceTime(10);
1474 
1475     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
1476     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1477     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
1478     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1479     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1480     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1481     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1482     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1483 
1484     VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_avenger._udp"));
1485     VerifyOrQuit(sStartBrowserInfo.SubTypeMatches("_god"));
1486 
1487     VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
1488 
1489     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1490     Log("Invoke Browser callback");
1491 
1492     browseResult.mServiceType     = "_avenger._udp";
1493     browseResult.mSubTypeLabel    = "_god";
1494     browseResult.mServiceInstance = "thor";
1495     browseResult.mTtl             = kTtl;
1496     browseResult.mInfraIfIndex    = kInfraIfIndex;
1497 
1498     InvokeBrowserCallback(sStartBrowserInfo.mCallback, browseResult);
1499 
1500     AdvanceTime(10);
1501 
1502     // Check that browser is stopped and a service resolver is started
1503 
1504     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
1505     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
1506     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1507     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1508     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1509     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1510     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1511     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1512 
1513     VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_avenger._udp"));
1514     VerifyOrQuit(sStopBrowserInfo.SubTypeMatches("_god"));
1515     VerifyOrQuit(sStopBrowserInfo.mCallback == sStartBrowserInfo.mCallback);
1516 
1517     // Check that the SRV resolver is correctly using the base service type
1518     // and not the sub-type name
1519 
1520     VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
1521     VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("thor"));
1522 
1523     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1524     Log("Invoke Service Resolver callback");
1525 
1526     srvResult.mServiceInstance = "thor";
1527     srvResult.mServiceType     = "_avenger._udp";
1528     srvResult.mHostName        = "asgard";
1529     srvResult.mPort            = 1234;
1530     srvResult.mTtl             = kTtl;
1531     srvResult.mInfraIfIndex    = kInfraIfIndex;
1532 
1533     InvokeSrvResolverCallback(sStartSrvResolverInfo.mCallback, srvResult);
1534 
1535     AdvanceTime(10);
1536 
1537     // Check that SRV resolver is stopped and a TXT resolver is started
1538 
1539     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
1540     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
1541     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1542     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
1543     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
1544     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1545     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1546     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1547 
1548     VerifyOrQuit(sStopSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
1549     VerifyOrQuit(sStopSrvResolverInfo.ServiceInstanceMatches("thor"));
1550     VerifyOrQuit(sStopSrvResolverInfo.mCallback == sStartSrvResolverInfo.mCallback);
1551 
1552     VerifyOrQuit(sStartTxtResolverInfo.ServiceTypeMatches("_avenger._udp"));
1553     VerifyOrQuit(sStartTxtResolverInfo.ServiceInstanceMatches("thor"));
1554 
1555     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1556     Log("Invoke Service Resolver callback");
1557 
1558     txtResult.mServiceInstance = "thor";
1559     txtResult.mServiceType     = "_avenger._udp";
1560     txtResult.mTxtData         = kTxtData;
1561     txtResult.mTxtDataLength   = sizeof(kTxtData);
1562     txtResult.mTtl             = kTtl;
1563     txtResult.mInfraIfIndex    = kInfraIfIndex;
1564 
1565     InvokeTxtResolverCallback(sStartTxtResolverInfo.mCallback, txtResult);
1566     AdvanceTime(10);
1567 
1568     // Check that TXT resolver is stopped and an address resolver is started
1569 
1570     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
1571     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
1572     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1573     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
1574     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
1575     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
1576     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
1577     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1578 
1579     VerifyOrQuit(sStopTxtResolverInfo.ServiceTypeMatches("_avenger._udp"));
1580     VerifyOrQuit(sStopTxtResolverInfo.ServiceInstanceMatches("thor"));
1581     VerifyOrQuit(sStopTxtResolverInfo.mCallback == sStartTxtResolverInfo.mCallback);
1582 
1583     VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("asgard"));
1584 
1585     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1586     Log("Invoke Address Resolver callback");
1587 
1588     SuccessOrQuit(AsCoreType(&addressAndTtl.mAddress).FromString("fd00::1234"));
1589     addressAndTtl.mTtl = kTtl;
1590 
1591     ip6AddrrResult.mHostName        = "asgard";
1592     ip6AddrrResult.mInfraIfIndex    = kInfraIfIndex;
1593     ip6AddrrResult.mAddresses       = &addressAndTtl;
1594     ip6AddrrResult.mAddressesLength = 1;
1595 
1596     InvokeIp6AddrResolverCallback(sStartIp6AddrResolverInfo.mCallback, ip6AddrrResult);
1597 
1598     AdvanceTime(10);
1599 
1600     // Check that address resolver is stopped
1601 
1602     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
1603     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
1604     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1605     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
1606     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
1607     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
1608     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
1609     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
1610 
1611     VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("asgard"));
1612     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallback == sStartIp6AddrResolverInfo.mCallback);
1613 
1614     // Check that response is sent to client and validate it
1615 
1616     VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
1617     SuccessOrQuit(sBrowseInfo.mError);
1618     VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
1619 
1620     VerifyOrQuit(!strcmp(sBrowseInfo.mServiceName, "_god._sub._avenger._udp.default.service.arpa."));
1621     VerifyOrQuit(!strcmp(sBrowseInfo.mInstanceLabel, "thor"));
1622     VerifyOrQuit(!strcmp(sBrowseInfo.mServiceInfo.mHostNameBuffer, "asgard.default.service.arpa."));
1623     VerifyOrQuit(sBrowseInfo.mServiceInfo.mPort == 1234);
1624     VerifyOrQuit(sBrowseInfo.mServiceInfo.mTtl == kTtl);
1625     VerifyOrQuit(AsCoreType(&sBrowseInfo.mServiceInfo.mHostAddress) == AsCoreType(&addressAndTtl.mAddress));
1626     VerifyOrQuit(sBrowseInfo.mServiceInfo.mHostAddressTtl == kTtl);
1627     VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataSize == sizeof(kTxtData));
1628     VerifyOrQuit(!memcmp(sBrowseInfo.mServiceInfo.mTxtData, kTxtData, sizeof(kTxtData)));
1629     VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataTtl == kTtl);
1630     VerifyOrQuit(!sBrowseInfo.mServiceInfo.mTxtDataTruncated);
1631 
1632     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1633     Log("Stop DNS-SD server");
1634 
1635     dnsServer->Stop();
1636 
1637     AdvanceTime(10);
1638 
1639     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1640     // Finalize OT instance and validate all heap allocations are freed.
1641 
1642     Log("Finalizing OT instance");
1643     FinalizeTest();
1644 
1645     Log("End of TestProxySubtypeBrowse");
1646 }
1647 
1648 //----------------------------------------------------------------------------------------------------------------------
1649 
TestProxyTimeout(void)1650 void TestProxyTimeout(void)
1651 {
1652     static constexpr uint32_t kTtl = 300;
1653 
1654     Srp::Server                   *srpServer;
1655     Srp::Client                   *srpClient;
1656     Dns::Client                   *dnsClient;
1657     Dns::ServiceDiscovery::Server *dnsServer;
1658     Dns::Client::QueryConfig       config;
1659     Dnssd::BrowseResult            browseResult;
1660 
1661     Log("--------------------------------------------------------------------------------------------");
1662     Log("TestProxyTimeout");
1663 
1664     InitTest();
1665 
1666     srpServer = &sInstance->Get<Srp::Server>();
1667     srpClient = &sInstance->Get<Srp::Client>();
1668     dnsClient = &sInstance->Get<Dns::Client>();
1669     dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
1670 
1671     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672     // Start SRP server.
1673 
1674     SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
1675 
1676     SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
1677     VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
1678 
1679     srpServer->SetEnabled(true);
1680     VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
1681 
1682     AdvanceTime(10000);
1683     VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
1684 
1685     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1686     // Start SRP client.
1687 
1688     srpClient->EnableAutoStartMode(nullptr, nullptr);
1689     VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
1690 
1691     AdvanceTime(2000);
1692     VerifyOrQuit(srpClient->IsRunning());
1693 
1694     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1695     Log("Increase default response retry timeout on DNS client");
1696 
1697     config.Clear();
1698     config.mResponseTimeout = 120 * 1000; // 2 minutes (in msec)
1699     dnsClient->SetDefaultConfig(config);
1700 
1701     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1702 
1703     sBrowseInfo.Reset();
1704     ResetPlatDnssdApiInfo();
1705 
1706     Log("Browse()");
1707     SuccessOrQuit(dnsClient->Browse("_game._ps5.default.service.arpa.", BrowseCallback, sInstance));
1708     AdvanceTime(10);
1709 
1710     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
1711     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1712     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
1713     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1714     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1715     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1716     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1717     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1718 
1719     VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_game._ps5"));
1720 
1721     VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
1722 
1723     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1724     Log("Wait for timeout and check empty response on client");
1725 
1726     AdvanceTime(10 * 1000);
1727 
1728     VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
1729     VerifyOrQuit(sBrowseInfo.mNumInstances == 0);
1730 
1731     // Check that the browser is stopped
1732 
1733     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
1734     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
1735 
1736     VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_game._ps5"));
1737     VerifyOrQuit(sStopBrowserInfo.mCallback == sStartBrowserInfo.mCallback);
1738 
1739     Log("--------------------------------------------------------------------------------------------");
1740     Log("Timeout during service resolution");
1741 
1742     sBrowseInfo.Reset();
1743     ResetPlatDnssdApiInfo();
1744 
1745     SuccessOrQuit(dnsClient->Browse("_avenger._udp.default.service.arpa.", BrowseCallback, sInstance));
1746     AdvanceTime(10);
1747 
1748     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
1749     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1750     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
1751     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1752     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1753     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1754     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1755     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1756 
1757     VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_avenger._udp"));
1758 
1759     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1760     Log("Invoke Browser callback");
1761 
1762     browseResult.mServiceType     = "_avenger._udp";
1763     browseResult.mSubTypeLabel    = nullptr;
1764     browseResult.mServiceInstance = "spiderman";
1765     browseResult.mTtl             = kTtl;
1766     browseResult.mInfraIfIndex    = kInfraIfIndex;
1767 
1768     InvokeBrowserCallback(sStartBrowserInfo.mCallback, browseResult);
1769 
1770     AdvanceTime(10);
1771 
1772     // Check that browser is stopped and a service resolver is started
1773 
1774     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
1775     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
1776     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1777     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1778     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1779     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1780     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1781     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1782 
1783     VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_avenger._udp"));
1784 
1785     VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
1786     VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("spiderman"));
1787 
1788     VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
1789 
1790     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1791     Log("Wait for timeout");
1792 
1793     AdvanceTime(10 * 1000);
1794 
1795     VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
1796     VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
1797 
1798     // Check that the browser is stopped
1799 
1800     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
1801     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
1802     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1803     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
1804     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1805     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1806     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1807     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1808 
1809     VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_avenger._udp"));
1810 
1811     // Validate the response received by client
1812 
1813     VerifyOrQuit(!strcmp(sBrowseInfo.mServiceName, "_avenger._udp.default.service.arpa."));
1814     VerifyOrQuit(!strcmp(sBrowseInfo.mInstanceLabel, "spiderman"));
1815 
1816     Log("--------------------------------------------------------------------------------------------");
1817     Log("Timeout during multiple requests");
1818 
1819     sBrowseInfo.Reset();
1820     sResolveServiceInfo.Reset();
1821     sResolveAddressInfo.Reset();
1822     ResetPlatDnssdApiInfo();
1823 
1824     Log("Browse()");
1825     SuccessOrQuit(dnsClient->Browse("_avenger._udp.default.service.arpa.", BrowseCallback, sInstance));
1826     AdvanceTime(10);
1827 
1828     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
1829     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1830     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
1831     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1832     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1833     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1834     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1835     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1836 
1837     VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_avenger._udp"));
1838 
1839     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1840     Log("Another Browse()");
1841     SuccessOrQuit(dnsClient->Browse("_game._udp.default.service.arpa.", BrowseCallback, sInstance));
1842     AdvanceTime(10);
1843 
1844     VerifyOrQuit(sStartBrowserInfo.mCallCount == 2);
1845     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1846     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
1847     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1848     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1849     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1850     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1851     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1852 
1853     VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_game._udp"));
1854 
1855     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1856     Log("ResolveService()");
1857     SuccessOrQuit(
1858         dnsClient->ResolveService("wanda", "_avenger._udp.default.service.arpa.", ServiceCallback, sInstance));
1859     AdvanceTime(10);
1860 
1861     VerifyOrQuit(sStartBrowserInfo.mCallCount == 2);
1862     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1863     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1864     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1865     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1866     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1867     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
1868     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1869 
1870     VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
1871     VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("wanda"));
1872 
1873     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1874     Log("ResolveAddress()");
1875     SuccessOrQuit(dnsClient->ResolveAddress("earth.default.service.arpa.", AddressCallback, sInstance));
1876     AdvanceTime(10);
1877 
1878     VerifyOrQuit(sStartBrowserInfo.mCallCount == 2);
1879     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
1880     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1881     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
1882     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1883     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1884     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
1885     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
1886 
1887     VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("earth"));
1888 
1889     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1890     Log("Wait for timeout for all requests");
1891 
1892     AdvanceTime(10 * 1000);
1893 
1894     VerifyOrQuit(sBrowseInfo.mCallbackCount == 2);
1895     VerifyOrQuit(sBrowseInfo.mNumInstances == 0);
1896 
1897     VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
1898     VerifyOrQuit(sResolveServiceInfo.mError == kErrorNotFound);
1899 
1900     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
1901     VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 0);
1902 
1903     // Check that all browsers/resolvers are stopped.
1904 
1905     VerifyOrQuit(sStartBrowserInfo.mCallCount == 2);
1906     VerifyOrQuit(sStopBrowserInfo.mCallCount == 2);
1907     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
1908     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
1909     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
1910     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
1911     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
1912     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
1913 
1914     VerifyOrQuit(sStopSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
1915     VerifyOrQuit(sStopSrvResolverInfo.ServiceInstanceMatches("wanda"));
1916     VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("earth"));
1917 
1918     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1919     Log("Stop DNS-SD server");
1920 
1921     dnsServer->Stop();
1922 
1923     AdvanceTime(10);
1924 
1925     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1926     // Finalize OT instance and validate all heap allocations are freed.
1927 
1928     Log("Finalizing OT instance");
1929     FinalizeTest();
1930 
1931     Log("End of TestProxyTimeout");
1932 }
1933 
TestProxySharedResolver(void)1934 void TestProxySharedResolver(void)
1935 {
1936     static constexpr uint32_t kTtl = 300;
1937 
1938     const uint8_t kTxtData[] = {3, 'A', '=', '1', 0};
1939 
1940     Srp::Server                   *srpServer;
1941     Srp::Client                   *srpClient;
1942     Dns::Client                   *dnsClient;
1943     Dns::ServiceDiscovery::Server *dnsServer;
1944     Dnssd::BrowseResult            browseResult;
1945     Dnssd::SrvResult               srvResult;
1946     Dnssd::TxtResult               txtResult;
1947     Dnssd::AddressResult           ip6AddrrResult;
1948     Dnssd::AddressAndTtl           addressAndTtl[2];
1949 
1950     Log("--------------------------------------------------------------------------------------------");
1951     Log("TestProxySharedResolver");
1952 
1953     InitTest();
1954 
1955     srpServer = &sInstance->Get<Srp::Server>();
1956     srpClient = &sInstance->Get<Srp::Client>();
1957     dnsClient = &sInstance->Get<Dns::Client>();
1958     dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
1959 
1960     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1961     // Start SRP server.
1962 
1963     SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
1964 
1965     SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
1966     VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
1967 
1968     srpServer->SetEnabled(true);
1969     VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
1970 
1971     AdvanceTime(10000);
1972     VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
1973 
1974     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1975     // Start SRP client.
1976 
1977     srpClient->EnableAutoStartMode(nullptr, nullptr);
1978     VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
1979 
1980     AdvanceTime(2000);
1981     VerifyOrQuit(srpClient->IsRunning());
1982 
1983     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
1984 
1985     sBrowseInfo.Reset();
1986     sResolveServiceInfo.Reset();
1987     sResolveAddressInfo.Reset();
1988     ResetPlatDnssdApiInfo();
1989 
1990     Log("ResolveAddress()");
1991     SuccessOrQuit(dnsClient->ResolveAddress("knowhere.default.service.arpa.", AddressCallback, sInstance));
1992     AdvanceTime(10);
1993 
1994     Log("ResolveService()");
1995     SuccessOrQuit(
1996         dnsClient->ResolveService("starlord", "_guardian._glaxy.default.service.arpa.", ServiceCallback, sInstance));
1997     AdvanceTime(10);
1998 
1999     Log("Browse()");
2000     SuccessOrQuit(dnsClient->Browse("_guardian._glaxy.default.service.arpa.", BrowseCallback, sInstance));
2001     AdvanceTime(10);
2002 
2003     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
2004     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
2005     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
2006     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
2007     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
2008     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
2009     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2010     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
2011 
2012     VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_guardian._glaxy"));
2013 
2014     VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
2015     VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("starlord"));
2016 
2017     VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("knowhere"));
2018 
2019     VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
2020     VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 0);
2021     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
2022 
2023     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2024     Log("Invoke Browser callback");
2025 
2026     browseResult.mServiceType     = "_guardian._glaxy";
2027     browseResult.mSubTypeLabel    = nullptr;
2028     browseResult.mServiceInstance = "starlord";
2029     browseResult.mTtl             = kTtl;
2030     browseResult.mInfraIfIndex    = kInfraIfIndex;
2031 
2032     InvokeBrowserCallback(sStartBrowserInfo.mCallback, browseResult);
2033 
2034     AdvanceTime(10);
2035 
2036     // Check that browser is stopped and since the service instance
2037     // name matches an existing resolver, we should not see any new
2038     // resolver starting.
2039 
2040     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
2041     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
2042     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
2043     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
2044     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
2045     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
2046     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2047     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
2048 
2049     VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_guardian._glaxy"));
2050 
2051     VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
2052     VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 0);
2053     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
2054 
2055     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2056     Log("Invoke Service Resolver callback");
2057 
2058     srvResult.mServiceInstance = "starlord";
2059     srvResult.mServiceType     = "_guardian._glaxy";
2060     srvResult.mHostName        = "knowhere";
2061     srvResult.mPort            = 3333;
2062     srvResult.mTtl             = kTtl;
2063     srvResult.mInfraIfIndex    = kInfraIfIndex;
2064 
2065     InvokeSrvResolverCallback(sStartSrvResolverInfo.mCallback, srvResult);
2066 
2067     AdvanceTime(10);
2068 
2069     // Check that SRV resolver is now stopped and a TXT resolver
2070     // is started for same service.
2071 
2072     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
2073     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
2074     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
2075     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
2076     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
2077     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
2078     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2079     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
2080 
2081     VerifyOrQuit(sStopSrvResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
2082     VerifyOrQuit(sStopSrvResolverInfo.ServiceInstanceMatches("starlord"));
2083 
2084     txtResult.mServiceInstance = "starlord";
2085     txtResult.mServiceType     = "_guardian._glaxy";
2086     txtResult.mTxtData         = kTxtData;
2087     txtResult.mTxtDataLength   = sizeof(kTxtData);
2088     txtResult.mTtl             = kTtl;
2089     txtResult.mInfraIfIndex    = kInfraIfIndex;
2090 
2091     InvokeTxtResolverCallback(sStartTxtResolverInfo.mCallback, txtResult);
2092 
2093     AdvanceTime(10);
2094 
2095     // Check that TXT resolver is now stopped but again since the
2096     // host name matches an existing address resolver we should not
2097     // see any new address resolver.
2098 
2099     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
2100     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
2101     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
2102     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
2103     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
2104     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
2105     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2106     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
2107 
2108     VerifyOrQuit(sStopTxtResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
2109     VerifyOrQuit(sStopTxtResolverInfo.ServiceInstanceMatches("starlord"));
2110 
2111     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2112     Log("Invoke Address Resolver callback");
2113 
2114     SuccessOrQuit(AsCoreType(&addressAndTtl[0].mAddress).FromString("fd00::5555"));
2115     SuccessOrQuit(AsCoreType(&addressAndTtl[1].mAddress).FromString("fd00::1234"));
2116     addressAndTtl[0].mTtl = kTtl;
2117     addressAndTtl[1].mTtl = kTtl;
2118 
2119     ip6AddrrResult.mHostName        = "knowhere";
2120     ip6AddrrResult.mInfraIfIndex    = kInfraIfIndex;
2121     ip6AddrrResult.mAddresses       = addressAndTtl;
2122     ip6AddrrResult.mAddressesLength = 2;
2123 
2124     InvokeIp6AddrResolverCallback(sStartIp6AddrResolverInfo.mCallback, ip6AddrrResult);
2125 
2126     AdvanceTime(10);
2127 
2128     // Check that the address resolver is now stopped.
2129 
2130     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
2131     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
2132     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
2133     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
2134     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
2135     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
2136     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2137     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
2138 
2139     VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("knowhere"));
2140 
2141     // Check the browse response received on client
2142 
2143     VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
2144     SuccessOrQuit(sBrowseInfo.mError);
2145     VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
2146 
2147     VerifyOrQuit(!strcmp(sBrowseInfo.mServiceName, "_guardian._glaxy.default.service.arpa."));
2148     VerifyOrQuit(!strcmp(sBrowseInfo.mInstanceLabel, "starlord"));
2149     VerifyOrQuit(!strcmp(sBrowseInfo.mServiceInfo.mHostNameBuffer, "knowhere.default.service.arpa."));
2150     VerifyOrQuit(sBrowseInfo.mServiceInfo.mPort == 3333);
2151     VerifyOrQuit(sBrowseInfo.mServiceInfo.mTtl == kTtl);
2152     VerifyOrQuit(sBrowseInfo.mServiceInfo.mHostAddressTtl == kTtl);
2153     VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataSize == sizeof(kTxtData));
2154     VerifyOrQuit(!memcmp(sBrowseInfo.mServiceInfo.mTxtData, kTxtData, sizeof(kTxtData)));
2155     VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataTtl == kTtl);
2156     VerifyOrQuit(!sBrowseInfo.mServiceInfo.mTxtDataTruncated);
2157 
2158     // Check the service resolve response received on client
2159 
2160     VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
2161     SuccessOrQuit(sResolveServiceInfo.mError);
2162 
2163     VerifyOrQuit(!strcmp(sResolveServiceInfo.mInfo.mHostNameBuffer, "knowhere.default.service.arpa."));
2164     VerifyOrQuit(sResolveServiceInfo.mInfo.mPort == 3333);
2165     VerifyOrQuit(sResolveServiceInfo.mInfo.mTtl == kTtl);
2166     VerifyOrQuit(sResolveServiceInfo.mInfo.mHostAddressTtl == kTtl);
2167     VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataSize == sizeof(kTxtData));
2168     VerifyOrQuit(!memcmp(sResolveServiceInfo.mInfo.mTxtData, kTxtData, sizeof(kTxtData)));
2169     VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataTtl == kTtl);
2170     VerifyOrQuit(!sResolveServiceInfo.mInfo.mTxtDataTruncated);
2171     VerifyOrQuit(sResolveServiceInfo.mNumHostAddresses == 2);
2172     for (uint16_t index = 0; index < 2; index++)
2173     {
2174         VerifyOrQuit(sResolveServiceInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[0].mAddress) ||
2175                      sResolveServiceInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[1].mAddress));
2176     }
2177 
2178     // Check the address resolve response received on client
2179 
2180     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
2181     SuccessOrQuit(sResolveAddressInfo.mError);
2182 
2183     VerifyOrQuit(!strcmp(sResolveAddressInfo.mHostName, "knowhere.default.service.arpa."));
2184     VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl);
2185     VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 2);
2186     for (uint16_t index = 0; index < 2; index++)
2187     {
2188         VerifyOrQuit(sResolveAddressInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[0].mAddress) ||
2189                      sResolveAddressInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[1].mAddress));
2190     }
2191 
2192     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2193     Log("Stop DNS-SD server");
2194 
2195     dnsServer->Stop();
2196 
2197     AdvanceTime(10);
2198 
2199     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2200     // Finalize OT instance and validate all heap allocations are freed.
2201 
2202     Log("Finalizing OT instance");
2203     FinalizeTest();
2204 
2205     Log("End of TestProxySharedResolver");
2206 }
2207 
TestProxyFilterInvalidAddresses(void)2208 void TestProxyFilterInvalidAddresses(void)
2209 {
2210     static constexpr uint32_t kTtl = 300;
2211 
2212     Srp::Server                   *srpServer;
2213     Srp::Client                   *srpClient;
2214     Dns::Client                   *dnsClient;
2215     Dns::ServiceDiscovery::Server *dnsServer;
2216     Dnssd::AddressResult           ip6AddrrResult;
2217     Dnssd::AddressAndTtl           addressAndTtl[10];
2218 
2219     Log("--------------------------------------------------------------------------------------------");
2220     Log("TestProxyFilterInvalidAddresses");
2221 
2222     InitTest();
2223 
2224     srpServer = &sInstance->Get<Srp::Server>();
2225     srpClient = &sInstance->Get<Srp::Client>();
2226     dnsClient = &sInstance->Get<Dns::Client>();
2227     dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
2228 
2229     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2230     // Start SRP server.
2231 
2232     SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
2233 
2234     SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
2235     VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
2236 
2237     srpServer->SetEnabled(true);
2238     VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
2239 
2240     AdvanceTime(10000);
2241     VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
2242 
2243     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2244     // Start SRP client.
2245 
2246     srpClient->EnableAutoStartMode(nullptr, nullptr);
2247     VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
2248 
2249     AdvanceTime(2000);
2250     VerifyOrQuit(srpClient->IsRunning());
2251 
2252     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2253 
2254     sResolveAddressInfo.Reset();
2255     ResetPlatDnssdApiInfo();
2256 
2257     Log("ResolveAddress()");
2258     SuccessOrQuit(dnsClient->ResolveAddress("host.default.service.arpa.", AddressCallback, sInstance));
2259     AdvanceTime(10);
2260 
2261     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2262     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
2263 
2264     VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("host"));
2265 
2266     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
2267 
2268     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2269     Log("Invoke Address Resolver callback with invalid addresses");
2270 
2271     SuccessOrQuit(AsCoreType(&addressAndTtl[0].mAddress).FromString("::"));         // Unspecified
2272     SuccessOrQuit(AsCoreType(&addressAndTtl[1].mAddress).FromString("fe80::1234")); // Link local
2273     SuccessOrQuit(AsCoreType(&addressAndTtl[2].mAddress).FromString("ff00::1234")); // Multicast
2274     SuccessOrQuit(AsCoreType(&addressAndTtl[3].mAddress).FromString("::1"));        // Lookback
2275 
2276     for (uint16_t index = 0; index < 5; index++)
2277     {
2278         addressAndTtl[index].mTtl = kTtl;
2279     }
2280 
2281     ip6AddrrResult.mHostName        = "host";
2282     ip6AddrrResult.mInfraIfIndex    = kInfraIfIndex;
2283     ip6AddrrResult.mAddresses       = addressAndTtl;
2284     ip6AddrrResult.mAddressesLength = 4;
2285 
2286     InvokeIp6AddrResolverCallback(sStartIp6AddrResolverInfo.mCallback, ip6AddrrResult);
2287 
2288     AdvanceTime(10);
2289 
2290     // Check that the address resolver is not stopped, since all addresses where
2291     // invalid address.
2292 
2293     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2294     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
2295 
2296     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
2297 
2298     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2299     Log("Invoke Address Resolver callback with invalid addresses with one valid");
2300 
2301     SuccessOrQuit(AsCoreType(&addressAndTtl[4].mAddress).FromString("f00::1234"));
2302 
2303     ip6AddrrResult.mAddressesLength = 5;
2304 
2305     InvokeIp6AddrResolverCallback(sStartIp6AddrResolverInfo.mCallback, ip6AddrrResult);
2306 
2307     AdvanceTime(10);
2308 
2309     // Check that address resolver is not stopped
2310 
2311     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2312     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
2313 
2314     VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("host"));
2315 
2316     // Check that response received on client is valid and only contains
2317     // the valid two addresses and filters all others.
2318 
2319     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
2320     SuccessOrQuit(sResolveAddressInfo.mError);
2321 
2322     VerifyOrQuit(!strcmp(sResolveAddressInfo.mHostName, "host.default.service.arpa."));
2323     VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl);
2324     VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 1);
2325     VerifyOrQuit(sResolveAddressInfo.mHostAddresses[0] == AsCoreType(&addressAndTtl[4].mAddress));
2326 
2327     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2328     Log("Stop DNS-SD server");
2329 
2330     dnsServer->Stop();
2331 
2332     AdvanceTime(10);
2333 
2334     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2335     // Finalize OT instance and validate all heap allocations are freed.
2336 
2337     Log("Finalizing OT instance");
2338     FinalizeTest();
2339 
2340     Log("End of TestProxyFilterInvalidAddresses");
2341 }
2342 
TestProxyStateChanges(void)2343 void TestProxyStateChanges(void)
2344 {
2345     static constexpr uint32_t kTtl = 300;
2346 
2347     Srp::Server                   *srpServer;
2348     Srp::Client                   *srpClient;
2349     Dns::Client                   *dnsClient;
2350     Dns::ServiceDiscovery::Server *dnsServer;
2351 
2352     Log("--------------------------------------------------------------------------------------------");
2353     Log("TestProxyStateChanges");
2354 
2355     InitTest();
2356 
2357     srpServer = &sInstance->Get<Srp::Server>();
2358     srpClient = &sInstance->Get<Srp::Client>();
2359     dnsClient = &sInstance->Get<Dns::Client>();
2360     dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
2361 
2362     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2363     // Start SRP server.
2364 
2365     SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
2366 
2367     SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
2368     VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
2369 
2370     srpServer->SetEnabled(true);
2371     VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
2372 
2373     AdvanceTime(10000);
2374     VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
2375 
2376     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2377     // Start SRP client.
2378 
2379     srpClient->EnableAutoStartMode(nullptr, nullptr);
2380     VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
2381 
2382     AdvanceTime(2000);
2383     VerifyOrQuit(srpClient->IsRunning());
2384 
2385     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2386     Log("Signal DNS-SD platform state is stopped and not yet ready");
2387 
2388     sDnssdState = OT_PLAT_DNSSD_STOPPED;
2389     otPlatDnssdStateHandleStateChange(sInstance);
2390 
2391     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2392 
2393     sResolveAddressInfo.Reset();
2394     ResetPlatDnssdApiInfo();
2395 
2396     Log("ResolveAddress()");
2397     SuccessOrQuit(dnsClient->ResolveAddress("host.default.service.arpa.", AddressCallback, sInstance));
2398     AdvanceTime(10);
2399 
2400     // Check that none of the DNS-SD resolver/browser APIs are called
2401     // since the platform is not yet ready
2402 
2403     VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
2404     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
2405     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
2406     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
2407     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
2408     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
2409     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
2410     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
2411 
2412     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
2413 
2414     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2415     Log("Signal DNS-SD platform state is now ready");
2416 
2417     sDnssdState = OT_PLAT_DNSSD_READY;
2418     otPlatDnssdStateHandleStateChange(sInstance);
2419 
2420     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2421 
2422     sResolveAddressInfo.Reset();
2423     ResetPlatDnssdApiInfo();
2424 
2425     Log("ResolveAddress()");
2426     SuccessOrQuit(dnsClient->ResolveAddress("host.default.service.arpa.", AddressCallback, sInstance));
2427     AdvanceTime(10);
2428 
2429     // Check that address resolver is started
2430 
2431     VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
2432     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
2433     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
2434     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
2435     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
2436     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
2437     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2438     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
2439 
2440     VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("host"));
2441 
2442     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
2443 
2444     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2445 
2446     sBrowseInfo.Reset();
2447 
2448     Log("Browse()");
2449     SuccessOrQuit(dnsClient->Browse("_magic._udp.default.service.arpa.", BrowseCallback, sInstance));
2450     AdvanceTime(10);
2451 
2452     // Check that browser is also started
2453 
2454     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
2455     VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
2456     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
2457     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
2458     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
2459     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
2460     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2461     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
2462 
2463     VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_magic._udp"));
2464 
2465     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
2466     VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
2467 
2468     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2469     Log("Signal infra-if is not running");
2470 
2471     SuccessOrQuit(otPlatInfraIfStateChanged(sInstance, kInfraIfIndex, /* aIsRunning */ false));
2472 
2473     AdvanceTime(10);
2474 
2475     // Check that both address resolver and browser are stopped
2476 
2477     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
2478     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
2479     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
2480     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
2481     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
2482     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
2483     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2484     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
2485 
2486     VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("host"));
2487     VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_magic._udp"));
2488 
2489     // And response is sent to client
2490 
2491     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
2492     VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
2493 
2494     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2495 
2496     sResolveAddressInfo.Reset();
2497 
2498     Log("ResolveAddress()");
2499     SuccessOrQuit(dnsClient->ResolveAddress("earth.default.service.arpa.", AddressCallback, sInstance));
2500     AdvanceTime(10);
2501 
2502     // Check that no resolver is started.
2503 
2504     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
2505     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
2506     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
2507     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
2508     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
2509     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
2510     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2511     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
2512 
2513     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
2514 
2515     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2516     Log("Signal that infra-if is running again ");
2517 
2518     SuccessOrQuit(otPlatInfraIfStateChanged(sInstance, kInfraIfIndex, /* aIsRunning */ true));
2519 
2520     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2521     sResolveServiceInfo.Reset();
2522     Log("ResolveService()");
2523     SuccessOrQuit(dnsClient->ResolveService("captain.america", "_avenger._udp.default.service.arpa.", ServiceCallback,
2524                                             sInstance));
2525     AdvanceTime(10);
2526 
2527     // The proxy should be started again so check that a service resolver
2528     // is started for new request
2529 
2530     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
2531     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
2532     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
2533     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
2534     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
2535     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
2536     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2537     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
2538 
2539     VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
2540     VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("captain.america"));
2541 
2542     VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 0);
2543 
2544     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2545     Log("Signal DNS-SD platform state is stopped");
2546 
2547     sDnssdState = OT_PLAT_DNSSD_STOPPED;
2548     otPlatDnssdStateHandleStateChange(sInstance);
2549 
2550     AdvanceTime(10);
2551 
2552     // This should stop proxy but since DNS-SD platform is stopped
2553     // we assume all browsers/resolvers are also stopped, so there
2554     // should be no explicit call to stop it.
2555 
2556     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
2557     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
2558     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
2559     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
2560     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
2561     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
2562     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2563     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
2564 
2565     // Check that response is sent to client
2566 
2567     VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
2568 
2569     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2570     Log("Signal DNS-SD platform state is ready again");
2571 
2572     sDnssdState = OT_PLAT_DNSSD_READY;
2573     otPlatDnssdStateHandleStateChange(sInstance);
2574 
2575     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2576 
2577     sBrowseInfo.Reset();
2578 
2579     Log("Browse()");
2580     SuccessOrQuit(dnsClient->Browse("_magical._udp.default.service.arpa.", BrowseCallback, sInstance));
2581     AdvanceTime(10);
2582 
2583     // Proxy should be started again and we should see a new browser started
2584 
2585     VerifyOrQuit(sStartBrowserInfo.mCallCount == 2);
2586     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
2587     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
2588     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
2589     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
2590     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
2591     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2592     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
2593 
2594     VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_magical._udp"));
2595 
2596     VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
2597 
2598     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2599     Log("Stop DNS-SD server");
2600 
2601     dnsServer->Stop();
2602 
2603     AdvanceTime(10);
2604 
2605     // Check that the browser is stopped
2606 
2607     VerifyOrQuit(sStartBrowserInfo.mCallCount == 2);
2608     VerifyOrQuit(sStopBrowserInfo.mCallCount == 2);
2609     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
2610     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
2611     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
2612     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
2613     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2614     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
2615 
2616     VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_magical._udp"));
2617 
2618     // And response is sent to client
2619 
2620     VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
2621 
2622     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2623     // Finalize OT instance and validate all heap allocations are freed.
2624 
2625     Log("Finalizing OT instance");
2626     FinalizeTest();
2627 
2628     Log("End of TestProxyStateChanges");
2629 }
2630 
TestProxyInvokeCallbackFromStartApi(void)2631 void TestProxyInvokeCallbackFromStartApi(void)
2632 {
2633     static constexpr uint32_t kTtl = 300;
2634 
2635     const uint8_t kTxtData[] = {3, 'A', '=', '1', 0};
2636 
2637     Srp::Server                   *srpServer;
2638     Srp::Client                   *srpClient;
2639     Dns::Client                   *dnsClient;
2640     Dns::ServiceDiscovery::Server *dnsServer;
2641     Dnssd::BrowseResult            browseResult;
2642     Dnssd::SrvResult               srvResult;
2643     Dnssd::TxtResult               txtResult;
2644     Dnssd::AddressResult           ip6AddrrResult;
2645     Dnssd::AddressAndTtl           addressAndTtl[2];
2646 
2647     Log("--------------------------------------------------------------------------------------------");
2648     Log("TestProxyInvokeCallbackFromStartApi");
2649 
2650     InitTest();
2651 
2652     srpServer = &sInstance->Get<Srp::Server>();
2653     srpClient = &sInstance->Get<Srp::Client>();
2654     dnsClient = &sInstance->Get<Dns::Client>();
2655     dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
2656 
2657     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2658     // Start SRP server.
2659 
2660     SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
2661 
2662     SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
2663     VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
2664 
2665     srpServer->SetEnabled(true);
2666     VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
2667 
2668     AdvanceTime(10000);
2669     VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
2670 
2671     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2672     // Start SRP client.
2673 
2674     srpClient->EnableAutoStartMode(nullptr, nullptr);
2675     VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
2676 
2677     AdvanceTime(2000);
2678     VerifyOrQuit(srpClient->IsRunning());
2679 
2680     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2681     Log("Enable invoking of callback directly from otPlatDnssdStart{Browsers/Resolver} APIs");
2682 
2683     ResetPlatDnssdApiInfo();
2684 
2685     sInvokeOnStart.mBrowseResult  = &browseResult;
2686     sInvokeOnStart.mSrvResult     = &srvResult;
2687     sInvokeOnStart.mTxtResult     = &txtResult;
2688     sInvokeOnStart.mIp6AddrResult = &ip6AddrrResult;
2689 
2690     browseResult.mServiceType     = "_guardian._glaxy";
2691     browseResult.mSubTypeLabel    = nullptr;
2692     browseResult.mServiceInstance = "mantis";
2693     browseResult.mTtl             = kTtl;
2694     browseResult.mInfraIfIndex    = kInfraIfIndex;
2695 
2696     srvResult.mServiceInstance = "mantis";
2697     srvResult.mServiceType     = "_guardian._glaxy";
2698     srvResult.mHostName        = "nova";
2699     srvResult.mPort            = 3333;
2700     srvResult.mTtl             = kTtl;
2701     srvResult.mInfraIfIndex    = kInfraIfIndex;
2702 
2703     txtResult.mServiceInstance = "mantis";
2704     txtResult.mServiceType     = "_guardian._glaxy";
2705     txtResult.mTxtData         = kTxtData;
2706     txtResult.mTxtDataLength   = sizeof(kTxtData);
2707     txtResult.mTtl             = kTtl;
2708     txtResult.mInfraIfIndex    = kInfraIfIndex;
2709 
2710     SuccessOrQuit(AsCoreType(&addressAndTtl[0].mAddress).FromString("fd00::5555"));
2711     SuccessOrQuit(AsCoreType(&addressAndTtl[1].mAddress).FromString("fd00::1234"));
2712     addressAndTtl[0].mTtl = kTtl;
2713     addressAndTtl[1].mTtl = kTtl;
2714 
2715     ip6AddrrResult.mHostName        = "nova";
2716     ip6AddrrResult.mInfraIfIndex    = kInfraIfIndex;
2717     ip6AddrrResult.mAddresses       = addressAndTtl;
2718     ip6AddrrResult.mAddressesLength = 2;
2719 
2720     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2721     sBrowseInfo.Reset();
2722 
2723     Log("Browse()");
2724     SuccessOrQuit(dnsClient->Browse("_guardian._glaxy.default.service.arpa.", BrowseCallback, sInstance));
2725     AdvanceTime(10);
2726 
2727     // All browsers/resolvers should be started and stopped
2728     // (since the callbacks are invoked directly from API)
2729 
2730     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
2731     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
2732     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
2733     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
2734     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
2735     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
2736     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
2737     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
2738 
2739     VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_guardian._glaxy"));
2740     VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_guardian._glaxy"));
2741 
2742     VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
2743     VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("mantis"));
2744     VerifyOrQuit(sStopSrvResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
2745     VerifyOrQuit(sStopSrvResolverInfo.ServiceInstanceMatches("mantis"));
2746 
2747     VerifyOrQuit(sStartTxtResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
2748     VerifyOrQuit(sStartTxtResolverInfo.ServiceInstanceMatches("mantis"));
2749     VerifyOrQuit(sStopTxtResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
2750     VerifyOrQuit(sStopTxtResolverInfo.ServiceInstanceMatches("mantis"));
2751 
2752     VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("nova"));
2753     VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("nova"));
2754 
2755     // Check that response is revived by client and validate it
2756 
2757     VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
2758 
2759     VerifyOrQuit(!strcmp(sBrowseInfo.mServiceName, "_guardian._glaxy.default.service.arpa."));
2760     VerifyOrQuit(!strcmp(sBrowseInfo.mInstanceLabel, "mantis"));
2761     VerifyOrQuit(!strcmp(sBrowseInfo.mServiceInfo.mHostNameBuffer, "nova.default.service.arpa."));
2762     VerifyOrQuit(sBrowseInfo.mServiceInfo.mPort == 3333);
2763     VerifyOrQuit(sBrowseInfo.mServiceInfo.mTtl == kTtl);
2764     VerifyOrQuit(sBrowseInfo.mServiceInfo.mHostAddressTtl == kTtl);
2765     VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataSize == sizeof(kTxtData));
2766     VerifyOrQuit(!memcmp(sBrowseInfo.mServiceInfo.mTxtData, kTxtData, sizeof(kTxtData)));
2767     VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataTtl == kTtl);
2768     VerifyOrQuit(!sBrowseInfo.mServiceInfo.mTxtDataTruncated);
2769 
2770     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2771     sResolveServiceInfo.Reset();
2772     Log("ResolveService()");
2773     SuccessOrQuit(
2774         dnsClient->ResolveService("mantis", "_guardian._glaxy.default.service.arpa.", ServiceCallback, sInstance));
2775     AdvanceTime(10);
2776 
2777     // Check that new SRV/TXT resolver and address resolvers are
2778     // started and stopped.
2779 
2780     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
2781     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
2782     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 2);
2783     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 2);
2784     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 2);
2785     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 2);
2786     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 2);
2787     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 2);
2788 
2789     VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
2790     VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("mantis"));
2791     VerifyOrQuit(sStopSrvResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
2792     VerifyOrQuit(sStopSrvResolverInfo.ServiceInstanceMatches("mantis"));
2793 
2794     VerifyOrQuit(sStartTxtResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
2795     VerifyOrQuit(sStartTxtResolverInfo.ServiceInstanceMatches("mantis"));
2796     VerifyOrQuit(sStopTxtResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
2797     VerifyOrQuit(sStopTxtResolverInfo.ServiceInstanceMatches("mantis"));
2798 
2799     VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("nova"));
2800     VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("nova"));
2801 
2802     // Check the service resolve response received on client
2803 
2804     VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
2805     SuccessOrQuit(sResolveServiceInfo.mError);
2806 
2807     VerifyOrQuit(!strcmp(sResolveServiceInfo.mInfo.mHostNameBuffer, "nova.default.service.arpa."));
2808     VerifyOrQuit(sResolveServiceInfo.mInfo.mPort == 3333);
2809     VerifyOrQuit(sResolveServiceInfo.mInfo.mTtl == kTtl);
2810     VerifyOrQuit(sResolveServiceInfo.mInfo.mHostAddressTtl == kTtl);
2811     VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataSize == sizeof(kTxtData));
2812     VerifyOrQuit(!memcmp(sResolveServiceInfo.mInfo.mTxtData, kTxtData, sizeof(kTxtData)));
2813     VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataTtl == kTtl);
2814     VerifyOrQuit(!sResolveServiceInfo.mInfo.mTxtDataTruncated);
2815     VerifyOrQuit(sResolveServiceInfo.mNumHostAddresses == 2);
2816     for (uint16_t index = 0; index < 2; index++)
2817     {
2818         VerifyOrQuit(sResolveServiceInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[0].mAddress) ||
2819                      sResolveServiceInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[1].mAddress));
2820     }
2821 
2822     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2823     sResolveAddressInfo.Reset();
2824     Log("ResolveAddress()");
2825     SuccessOrQuit(dnsClient->ResolveAddress("nova.default.service.arpa.", AddressCallback, sInstance));
2826     AdvanceTime(10);
2827 
2828     // Check that new address resolver is started and stopped.
2829 
2830     VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
2831     VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
2832     VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 2);
2833     VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 2);
2834     VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 2);
2835     VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 2);
2836     VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 3);
2837     VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 3);
2838 
2839     VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("nova"));
2840     VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("nova"));
2841 
2842     // Check the address resolve response received on client
2843 
2844     VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
2845     SuccessOrQuit(sResolveAddressInfo.mError);
2846 
2847     VerifyOrQuit(!strcmp(sResolveAddressInfo.mHostName, "nova.default.service.arpa."));
2848     VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl);
2849     VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 2);
2850     for (uint16_t index = 0; index < 2; index++)
2851     {
2852         VerifyOrQuit(sResolveAddressInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[0].mAddress) ||
2853                      sResolveAddressInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[1].mAddress));
2854     }
2855 
2856     Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
2857     Log("Stop DNS-SD server");
2858 
2859     dnsServer->Stop();
2860 
2861     AdvanceTime(10);
2862 
2863     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2864     // Finalize OT instance and validate all heap allocations are freed.
2865 
2866     Log("Finalizing OT instance");
2867     FinalizeTest();
2868 
2869     Log("End of TestProxyInvokeCallbackFromStartApi");
2870 }
2871 
2872 #endif // ENABLE_DISCOVERY_PROXY_TEST
2873 
main(void)2874 int main(void)
2875 {
2876 #if ENABLE_DISCOVERY_PROXY_TEST
2877     TestProxyBasic();
2878     TestProxySubtypeBrowse();
2879     TestProxyTimeout();
2880     TestProxySharedResolver();
2881     TestProxyFilterInvalidAddresses();
2882     TestProxyStateChanges();
2883     TestProxyInvokeCallbackFromStartApi();
2884 
2885     printf("All tests passed\n");
2886 #else
2887     printf("DISCOVERY_PROXY feature or a related feature required by this unit test is not enabled\n");
2888 #endif
2889 
2890     return 0;
2891 }
2892