Files
openthread/tests/unit/test_dnssd_discovery_proxy.cpp
T
Abtin Keshavarzian d163dee2af [dns-client] enhance logic for following up with IPv4 address query (#10781)
This commit updates the `ReplaceWithIp4Query()` method, which
determines whether an unsuccessful IPv6 address query should be
followed up with an IPv4 query.

The logic is changed as follows:

- If the response code to the IPv6 query indicates success but the
  answer section is empty (meaning the name exists but has no IPv6
  address), or the response code indicates an error other than
  `NameError`, the query is replaced with an IPv4 address resolution
  query for the same name.
- If the server responds with `NameError` (RCode=3), indicating that
  the name doesn't exist, an IPv4 query is not attempted.

This replaces the previous behavior where a follow-up query was
attempted for any error response code.
2024-10-11 10:32:53 -07:00

2893 lines
113 KiB
C++

/*
* Copyright (c) 2023, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <openthread/config.h>
#include "test_platform.h"
#include "test_util.hpp"
#include <openthread/dataset_ftd.h>
#include <openthread/dns_client.h>
#include <openthread/srp_client.h>
#include <openthread/srp_server.h>
#include <openthread/thread.h>
#include "common/arg_macros.hpp"
#include "common/array.hpp"
#include "common/clearable.hpp"
#include "common/string.hpp"
#include "common/time.hpp"
#include "instance/instance.hpp"
#if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE && OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE && \
OPENTHREAD_CONFIG_DNS_CLIENT_DEFAULT_SERVER_ADDRESS_AUTO_SET_ENABLE && OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE && \
OPENTHREAD_CONFIG_DNSSD_DISCOVERY_PROXY_ENABLE && OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && \
OPENTHREAD_CONFIG_PLATFORM_DNSSD_ALLOW_RUN_TIME_SELECTION && OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE && \
!OPENTHREAD_CONFIG_TIME_SYNC_ENABLE && !OPENTHREAD_PLATFORM_POSIX
#define ENABLE_DISCOVERY_PROXY_TEST 1
#else
#define ENABLE_DISCOVERY_PROXY_TEST 0
#endif
#if ENABLE_DISCOVERY_PROXY_TEST
using namespace ot;
// Logs a message and adds current time (sNow) as "<hours>:<min>:<secs>.<msec>"
#define Log(...) \
printf("%02u:%02u:%02u.%03u " OT_FIRST_ARG(__VA_ARGS__) "\n", (sNow / 36000000), (sNow / 60000) % 60, \
(sNow / 1000) % 60, sNow % 1000 OT_REST_ARGS(__VA_ARGS__))
static constexpr uint16_t kMaxRaSize = 800;
static ot::Instance *sInstance;
static uint32_t sNow = 0;
static uint32_t sAlarmTime;
static bool sAlarmOn = false;
static otRadioFrame sRadioTxFrame;
static uint8_t sRadioTxFramePsdu[OT_RADIO_FRAME_MAX_SIZE];
static bool sRadioTxOngoing = false;
//----------------------------------------------------------------------------------------------------------------------
// Function prototypes
void ProcessRadioTxAndTasklets(void);
void AdvanceTime(uint32_t aDuration);
//----------------------------------------------------------------------------------------------------------------------
// `otPlatRadio`
extern "C" {
otRadioCaps otPlatRadioGetCaps(otInstance *) { return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF; }
otError otPlatRadioTransmit(otInstance *, otRadioFrame *)
{
sRadioTxOngoing = true;
return OT_ERROR_NONE;
}
otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *) { return &sRadioTxFrame; }
//----------------------------------------------------------------------------------------------------------------------
// `otPlatAlaram`
void otPlatAlarmMilliStop(otInstance *) { sAlarmOn = false; }
void otPlatAlarmMilliStartAt(otInstance *, uint32_t aT0, uint32_t aDt)
{
sAlarmOn = true;
sAlarmTime = aT0 + aDt;
}
uint32_t otPlatAlarmMilliGetNow(void) { return sNow; }
//----------------------------------------------------------------------------------------------------------------------
Array<void *, 500> sHeapAllocatedPtrs;
#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
void *otPlatCAlloc(size_t aNum, size_t aSize)
{
void *ptr = calloc(aNum, aSize);
SuccessOrQuit(sHeapAllocatedPtrs.PushBack(ptr));
return ptr;
}
void otPlatFree(void *aPtr)
{
if (aPtr != nullptr)
{
void **entry = sHeapAllocatedPtrs.Find(aPtr);
VerifyOrQuit(entry != nullptr, "A heap allocated item is freed twice");
sHeapAllocatedPtrs.Remove(*entry);
}
free(aPtr);
}
#endif
#if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED
void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
{
OT_UNUSED_VARIABLE(aLogLevel);
OT_UNUSED_VARIABLE(aLogRegion);
va_list args;
printf(" ");
va_start(args, aFormat);
vprintf(aFormat, args);
va_end(args);
printf("\n");
}
#endif
} // extern "C"
//---------------------------------------------------------------------------------------------------------------------
void ProcessRadioTxAndTasklets(void)
{
do
{
if (sRadioTxOngoing)
{
sRadioTxOngoing = false;
otPlatRadioTxStarted(sInstance, &sRadioTxFrame);
otPlatRadioTxDone(sInstance, &sRadioTxFrame, nullptr, OT_ERROR_NONE);
}
otTaskletsProcess(sInstance);
} while (otTaskletsArePending(sInstance));
}
void AdvanceTime(uint32_t aDuration)
{
uint32_t time = sNow + aDuration;
Log("AdvanceTime for %u.%03u", aDuration / 1000, aDuration % 1000);
while (TimeMilli(sAlarmTime) <= TimeMilli(time))
{
ProcessRadioTxAndTasklets();
sNow = sAlarmTime;
otPlatAlarmMilliFired(sInstance);
}
ProcessRadioTxAndTasklets();
sNow = time;
}
void InitTest(void)
{
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Initialize OT instance.
sNow = 0;
sAlarmOn = false;
sInstance = static_cast<Instance *>(testInitInstance());
memset(&sRadioTxFrame, 0, sizeof(sRadioTxFrame));
sRadioTxFrame.mPsdu = sRadioTxFramePsdu;
sRadioTxOngoing = false;
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Initialize Border Router and start Thread operation.
otOperationalDataset dataset;
otOperationalDatasetTlvs datasetTlvs;
SuccessOrQuit(otDatasetCreateNewNetwork(sInstance, &dataset));
otDatasetConvertToTlvs(&dataset, &datasetTlvs);
SuccessOrQuit(otDatasetSetActiveTlvs(sInstance, &datasetTlvs));
SuccessOrQuit(otIp6SetEnabled(sInstance, true));
SuccessOrQuit(otThreadSetEnabled(sInstance, true));
// Configure the `Dnssd` module to use `otPlatDnssd` APIs.
sInstance->Get<Dnssd>().SetUseNativeMdns(false);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ensure device starts as leader.
AdvanceTime(10000);
VerifyOrQuit(otThreadGetDeviceRole(sInstance) == OT_DEVICE_ROLE_LEADER);
}
void FinalizeTest(void)
{
SuccessOrQuit(otIp6SetEnabled(sInstance, false));
SuccessOrQuit(otThreadSetEnabled(sInstance, false));
// Make sure there is no message/buffer leak
VerifyOrQuit(sInstance->Get<MessagePool>().GetFreeBufferCount() ==
sInstance->Get<MessagePool>().GetTotalBufferCount());
SuccessOrQuit(otInstanceErasePersistentInfo(sInstance));
testFreeInstance(sInstance);
}
//---------------------------------------------------------------------------------------------------------------------
// DNS Client callback
void LogServiceInfo(const Dns::Client::ServiceInfo &aInfo)
{
Log(" TTL: %u", aInfo.mTtl);
Log(" Port: %u", aInfo.mPort);
Log(" Weight: %u", aInfo.mWeight);
Log(" HostName: %s", aInfo.mHostNameBuffer);
Log(" HostAddr: %s", AsCoreType(&aInfo.mHostAddress).ToString().AsCString());
Log(" TxtDataLength: %u", aInfo.mTxtDataSize);
Log(" TxtDataTTL: %u", aInfo.mTxtDataTtl);
}
const char *ServiceModeToString(Dns::Client::QueryConfig::ServiceMode aMode)
{
static const char *const kServiceModeStrings[] = {
"unspec", // kServiceModeUnspecified (0)
"srv", // kServiceModeSrv (1)
"txt", // kServiceModeTxt (2)
"srv_txt", // kServiceModeSrvTxt (3)
"srv_txt_sep", // kServiceModeSrvTxtSeparate (4)
"srv_txt_opt", // kServiceModeSrvTxtOptimize (5)
};
static_assert(Dns::Client::QueryConfig::kServiceModeUnspecified == 0, "Unspecified value is incorrect");
static_assert(Dns::Client::QueryConfig::kServiceModeSrv == 1, "Srv value is incorrect");
static_assert(Dns::Client::QueryConfig::kServiceModeTxt == 2, "Txt value is incorrect");
static_assert(Dns::Client::QueryConfig::kServiceModeSrvTxt == 3, "SrvTxt value is incorrect");
static_assert(Dns::Client::QueryConfig::kServiceModeSrvTxtSeparate == 4, "SrvTxtSeparate value is incorrect");
static_assert(Dns::Client::QueryConfig::kServiceModeSrvTxtOptimize == 5, "SrvTxtOptimize value is incorrect");
return kServiceModeStrings[aMode];
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
struct BrowseInfo
{
void Reset(void) { mCallbackCount = 0; }
uint16_t mCallbackCount;
Error mError;
char mServiceName[Dns::Name::kMaxNameSize];
char mInstanceLabel[Dns::Name::kMaxLabelSize];
uint16_t mNumInstances;
Dns::Client::ServiceInfo mServiceInfo;
char mHostNameBuffer[Dns::Name::kMaxNameSize];
uint8_t mTxtBuffer[255];
};
static BrowseInfo sBrowseInfo;
void BrowseCallback(otError aError, const otDnsBrowseResponse *aResponse, void *aContext)
{
const Dns::Client::BrowseResponse &response = AsCoreType(aResponse);
Log("BrowseCallback");
Log(" Error: %s", ErrorToString(aError));
VerifyOrQuit(aContext == sInstance);
sBrowseInfo.mCallbackCount++;
sBrowseInfo.mError = aError;
SuccessOrExit(aError);
SuccessOrQuit(response.GetServiceName(sBrowseInfo.mServiceName, sizeof(sBrowseInfo.mServiceName)));
Log(" ServiceName: %s", sBrowseInfo.mServiceName);
for (uint16_t index = 0;; index++)
{
Error error;
error = response.GetServiceInstance(index, sBrowseInfo.mInstanceLabel, sizeof(sBrowseInfo.mInstanceLabel));
if (error == kErrorNotFound)
{
sBrowseInfo.mNumInstances = index;
break;
}
SuccessOrQuit(error);
Log(" %2u) %s", index + 1, sBrowseInfo.mInstanceLabel);
}
if (sBrowseInfo.mNumInstances == 1)
{
sBrowseInfo.mServiceInfo.mHostNameBuffer = sBrowseInfo.mHostNameBuffer;
sBrowseInfo.mServiceInfo.mHostNameBufferSize = sizeof(sBrowseInfo.mHostNameBuffer);
sBrowseInfo.mServiceInfo.mTxtData = sBrowseInfo.mTxtBuffer;
sBrowseInfo.mServiceInfo.mTxtDataSize = sizeof(sBrowseInfo.mTxtBuffer);
SuccessOrExit(response.GetServiceInfo(sBrowseInfo.mInstanceLabel, sBrowseInfo.mServiceInfo));
LogServiceInfo(sBrowseInfo.mServiceInfo);
}
exit:
return;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static constexpr uint8_t kMaxHostAddresses = 10;
static constexpr uint16_t kMaxTxtBuffer = 256;
struct ResolveServiceInfo
{
void Reset(void)
{
memset(this, 0, sizeof(*this));
mInfo.mHostNameBuffer = mNameBuffer;
mInfo.mHostNameBufferSize = sizeof(mNameBuffer);
mInfo.mTxtData = mTxtBuffer;
mInfo.mTxtDataSize = sizeof(mTxtBuffer);
};
uint16_t mCallbackCount;
Error mError;
Dns::Client::ServiceInfo mInfo;
char mNameBuffer[Dns::Name::kMaxNameSize];
uint8_t mTxtBuffer[kMaxTxtBuffer];
Ip6::Address mHostAddresses[kMaxHostAddresses];
uint8_t mNumHostAddresses;
};
static ResolveServiceInfo sResolveServiceInfo;
void ServiceCallback(otError aError, const otDnsServiceResponse *aResponse, void *aContext)
{
const Dns::Client::ServiceResponse &response = AsCoreType(aResponse);
char instLabel[Dns::Name::kMaxLabelSize];
char serviceName[Dns::Name::kMaxNameSize];
Log("ServiceCallback");
Log(" Error: %s", ErrorToString(aError));
VerifyOrQuit(aContext == sInstance);
SuccessOrQuit(response.GetServiceName(instLabel, sizeof(instLabel), serviceName, sizeof(serviceName)));
Log(" InstLabel: %s", instLabel);
Log(" ServiceName: %s", serviceName);
sResolveServiceInfo.mCallbackCount++;
sResolveServiceInfo.mError = aError;
SuccessOrExit(aError);
aError = response.GetServiceInfo(sResolveServiceInfo.mInfo);
if (aError == kErrorNotFound)
{
sResolveServiceInfo.mError = aError;
ExitNow();
}
SuccessOrQuit(aError);
for (uint8_t index = 0; index < kMaxHostAddresses; index++)
{
Error error;
uint32_t ttl;
error = response.GetHostAddress(sResolveServiceInfo.mInfo.mHostNameBuffer, index,
sResolveServiceInfo.mHostAddresses[index], ttl);
if (error == kErrorNotFound)
{
sResolveServiceInfo.mNumHostAddresses = index;
break;
}
SuccessOrQuit(error);
}
LogServiceInfo(sResolveServiceInfo.mInfo);
Log(" NumHostAddresses: %u", sResolveServiceInfo.mNumHostAddresses);
for (uint8_t index = 0; index < sResolveServiceInfo.mNumHostAddresses; index++)
{
Log(" %s", sResolveServiceInfo.mHostAddresses[index].ToString().AsCString());
}
exit:
return;
}
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
struct ResolveAddressInfo
{
void Reset(void) { memset(this, 0, sizeof(*this)); };
uint16_t mCallbackCount;
Error mError;
char mHostName[Dns::Name::kMaxNameSize];
Ip6::Address mHostAddresses[kMaxHostAddresses];
uint8_t mNumHostAddresses;
uint32_t mTtl;
};
static ResolveAddressInfo sResolveAddressInfo;
void AddressCallback(otError aError, const otDnsAddressResponse *aResponse, void *aContext)
{
const Dns::Client::AddressResponse &response = AsCoreType(aResponse);
Log("AddressCallback");
Log(" Error: %s", ErrorToString(aError));
VerifyOrQuit(aContext == sInstance);
sResolveAddressInfo.mCallbackCount++;
sResolveAddressInfo.mError = aError;
SuccessOrExit(aError);
SuccessOrQuit(response.GetHostName(sResolveAddressInfo.mHostName, sizeof(sResolveAddressInfo.mHostName)));
Log(" HostName: %s", sResolveAddressInfo.mHostName);
for (uint8_t index = 0; index < kMaxHostAddresses; index++)
{
Error error;
uint32_t ttl;
error = response.GetAddress(index, sResolveAddressInfo.mHostAddresses[index], sResolveAddressInfo.mTtl);
if (error == kErrorNotFound)
{
sResolveAddressInfo.mNumHostAddresses = index;
break;
}
SuccessOrQuit(error);
}
Log(" NumHostAddresses: %u", sResolveAddressInfo.mNumHostAddresses);
for (uint8_t index = 0; index < sResolveAddressInfo.mNumHostAddresses; index++)
{
Log(" %s", sResolveAddressInfo.mHostAddresses[index].ToString().AsCString());
}
exit:
return;
}
//----------------------------------------------------------------------------------------------------------------------
// otPlatDnssd APIs
constexpr uint32_t kInfraIfIndex = 1;
static otPlatDnssdState sDnssdState = OT_PLAT_DNSSD_READY;
template <uint16_t kSize> void CopyString(char (&aStringBuffer)[kSize], const char *aString)
{
if (aString == nullptr)
{
memset(aStringBuffer, 0, kSize);
}
else
{
uint16_t length = StringLength(aString, kSize);
VerifyOrQuit(length < kSize);
memcpy(aStringBuffer, aString, length + 1);
}
}
struct BrowserInfo : public Clearable<BrowserInfo>
{
bool ServiceTypeMatches(const char *aType) const { return !strcmp(mServiceType, aType); }
bool SubTypeMatches(const char *aSubType) const { return !strcmp(mSubTypeLabel, aSubType); }
void UpdateFrom(const otPlatDnssdBrowser *aBrowser)
{
mCallCount++;
CopyString(mServiceType, aBrowser->mServiceType);
CopyString(mSubTypeLabel, aBrowser->mSubTypeLabel);
mCallback = aBrowser->mCallback;
}
uint16_t mCallCount;
char mServiceType[Dns::Name::kMaxNameSize];
char mSubTypeLabel[Dns::Name::kMaxNameSize];
otPlatDnssdBrowseCallback mCallback;
};
struct SrvResolverInfo : public Clearable<SrvResolverInfo>
{
bool ServiceTypeMatches(const char *aType) const { return !strcmp(mServiceType, aType); }
bool ServiceInstanceMatches(const char *aInstance) const { return !strcmp(mServiceInstance, aInstance); }
void UpdateFrom(const otPlatDnssdSrvResolver *aResolver)
{
mCallCount++;
CopyString(mServiceInstance, aResolver->mServiceInstance);
CopyString(mServiceType, aResolver->mServiceType);
mCallback = aResolver->mCallback;
}
uint16_t mCallCount;
char mServiceInstance[Dns::Name::kMaxLabelSize];
char mServiceType[Dns::Name::kMaxNameSize];
otPlatDnssdSrvCallback mCallback;
};
struct TxtResolverInfo : public Clearable<TxtResolverInfo>
{
bool ServiceTypeMatches(const char *aType) const { return !strcmp(mServiceType, aType); }
bool ServiceInstanceMatches(const char *aInstance) const { return !strcmp(mServiceInstance, aInstance); }
void UpdateFrom(const otPlatDnssdTxtResolver *aResolver)
{
mCallCount++;
CopyString(mServiceInstance, aResolver->mServiceInstance);
CopyString(mServiceType, aResolver->mServiceType);
mCallback = aResolver->mCallback;
}
uint16_t mCallCount;
char mServiceInstance[Dns::Name::kMaxLabelSize];
char mServiceType[Dns::Name::kMaxNameSize];
otPlatDnssdTxtCallback mCallback;
};
struct IpAddrResolverInfo : public Clearable<IpAddrResolverInfo>
{
bool HostNameMatches(const char *aName) const { return !strcmp(mHostName, aName); }
void UpdateFrom(const otPlatDnssdAddressResolver *aResolver)
{
mCallCount++;
CopyString(mHostName, aResolver->mHostName);
mCallback = aResolver->mCallback;
}
uint16_t mCallCount;
char mHostName[Dns::Name::kMaxNameSize];
otPlatDnssdAddressCallback mCallback;
};
struct InvokeOnStart : public Clearable<InvokeOnStart>
{
// When not null, these entries are used to invoke callback
// directly from `otPlatDnssdStart{Browser/Resolver}()` APIs.
// This is used in `TestProxyInvokeCallbackFromStartApi()`.
const otPlatDnssdBrowseResult *mBrowseResult;
const otPlatDnssdSrvResult *mSrvResult;
const otPlatDnssdTxtResult *mTxtResult;
const otPlatDnssdAddressResult *mIp6AddrResult;
const otPlatDnssdAddressResult *mIp4AddrResult;
};
static BrowserInfo sStartBrowserInfo;
static BrowserInfo sStopBrowserInfo;
static SrvResolverInfo sStartSrvResolverInfo;
static SrvResolverInfo sStopSrvResolverInfo;
static TxtResolverInfo sStartTxtResolverInfo;
static TxtResolverInfo sStopTxtResolverInfo;
static IpAddrResolverInfo sStartIp6AddrResolverInfo;
static IpAddrResolverInfo sStopIp6AddrResolverInfo;
static IpAddrResolverInfo sStartIp4AddrResolverInfo;
static IpAddrResolverInfo sStopIp4AddrResolverInfo;
static InvokeOnStart sInvokeOnStart;
void ResetPlatDnssdApiInfo(void)
{
sStartBrowserInfo.Clear();
sStopBrowserInfo.Clear();
sStartSrvResolverInfo.Clear();
sStopSrvResolverInfo.Clear();
sStartTxtResolverInfo.Clear();
sStopTxtResolverInfo.Clear();
sStartIp6AddrResolverInfo.Clear();
sStopIp6AddrResolverInfo.Clear();
sStartIp4AddrResolverInfo.Clear();
sStopIp4AddrResolverInfo.Clear();
sInvokeOnStart.Clear();
}
const char *StringNullCheck(const char *aString) { return (aString != nullptr) ? aString : "(null)"; }
void InvokeBrowserCallback(otPlatDnssdBrowseCallback aCallback, const otPlatDnssdBrowseResult &aResult)
{
Log("Invoking browser callback");
Log(" serviceType : \"%s\"", StringNullCheck(aResult.mServiceType));
Log(" subType : \"%s\"", StringNullCheck(aResult.mSubTypeLabel));
Log(" serviceInstance: \"%s\"", StringNullCheck(aResult.mServiceInstance));
Log(" ttl : %u", aResult.mTtl);
Log(" if-index : %u", aResult.mInfraIfIndex);
aCallback(sInstance, &aResult);
}
void InvokeSrvResolverCallback(otPlatDnssdSrvCallback aCallback, const otPlatDnssdSrvResult &aResult)
{
Log("Invoking SRV resolver callback");
Log(" serviceInstance: %s", StringNullCheck(aResult.mServiceInstance));
Log(" serviceType : %s", StringNullCheck(aResult.mServiceType));
Log(" hostName : %s", StringNullCheck(aResult.mHostName));
Log(" port : %u", aResult.mPort);
Log(" priority : %u", aResult.mPriority);
Log(" weight : %u", aResult.mWeight);
Log(" ttl : %u", aResult.mTtl);
Log(" if-index : %u", aResult.mInfraIfIndex);
aCallback(sInstance, &aResult);
}
void InvokeTxtResolverCallback(otPlatDnssdTxtCallback aCallback, const otPlatDnssdTxtResult &aResult)
{
Log("Invoking TXT resolver callback");
Log(" serviceInstance: %s", StringNullCheck(aResult.mServiceInstance));
Log(" serviceType : %s", StringNullCheck(aResult.mServiceType));
Log(" txt-data-len : %u", aResult.mTxtDataLength);
Log(" ttl : %u", aResult.mTtl);
Log(" if-index : %u", aResult.mInfraIfIndex);
aCallback(sInstance, &aResult);
}
void InvokeIp6AddrResolverCallback(const otPlatDnssdAddressCallback aCallback, const otPlatDnssdAddressResult &aResult)
{
Log("Invoking Ip6 resolver callback");
Log(" hostName : %s", aResult.mHostName);
Log(" if-index : %u", aResult.mInfraIfIndex);
Log(" numAddresses : %u", aResult.mAddressesLength);
for (uint16_t index = 0; index < aResult.mAddressesLength; index++)
{
Log(" address[%u] : %s", index, AsCoreType(&aResult.mAddresses[index].mAddress).ToString().AsCString());
Log(" ttl[%u] : %u", index, aResult.mAddresses[index].mTtl);
}
aCallback(sInstance, &aResult);
}
void InvokeIp4AddrResolverCallback(const otPlatDnssdAddressCallback aCallback, const otPlatDnssdAddressResult &aResult)
{
Log("Invoking Ip4 resolver callback");
Log(" hostName : %s", aResult.mHostName);
Log(" if-index : %u", aResult.mInfraIfIndex);
Log(" numAddresses : %u", aResult.mAddressesLength);
for (uint16_t index = 0; index < aResult.mAddressesLength; index++)
{
Log(" address[%u] : %s", index, AsCoreType(&aResult.mAddresses[index].mAddress).ToString().AsCString());
Log(" ttl[%u] : %u", index, aResult.mAddresses[index].mTtl);
}
aCallback(sInstance, &aResult);
}
otPlatDnssdState otPlatDnssdGetState(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return sDnssdState;
}
void otPlatDnssdStartBrowser(otInstance *aInstance, const otPlatDnssdBrowser *aBrowser)
{
VerifyOrQuit(aBrowser != nullptr);
Log("otPlatDnssdStartBrowser(\"%s\", sub-type:\"%s\")", aBrowser->mServiceType, aBrowser->mSubTypeLabel);
VerifyOrQuit(aInstance == sInstance);
VerifyOrQuit(aBrowser->mInfraIfIndex == kInfraIfIndex);
sStartBrowserInfo.UpdateFrom(aBrowser);
if (sInvokeOnStart.mBrowseResult != nullptr)
{
InvokeBrowserCallback(aBrowser->mCallback, *sInvokeOnStart.mBrowseResult);
}
}
void otPlatDnssdStopBrowser(otInstance *aInstance, const otPlatDnssdBrowser *aBrowser)
{
VerifyOrQuit(aBrowser != nullptr);
Log("otPlatDnssdStopBrowser(\"%s\", sub-type:\"%s\")", aBrowser->mServiceType, aBrowser->mSubTypeLabel);
VerifyOrQuit(aInstance == sInstance);
VerifyOrQuit(aBrowser->mInfraIfIndex == kInfraIfIndex);
sStopBrowserInfo.UpdateFrom(aBrowser);
}
void otPlatDnssdStartSrvResolver(otInstance *aInstance, const otPlatDnssdSrvResolver *aResolver)
{
VerifyOrQuit(aResolver != nullptr);
Log("otPlatDnssdStartSrvResolver(\"%s\", \"%s\")", aResolver->mServiceInstance, aResolver->mServiceType);
VerifyOrQuit(aInstance == sInstance);
VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
sStartSrvResolverInfo.UpdateFrom(aResolver);
if (sInvokeOnStart.mSrvResult != nullptr)
{
InvokeSrvResolverCallback(aResolver->mCallback, *sInvokeOnStart.mSrvResult);
}
}
void otPlatDnssdStopSrvResolver(otInstance *aInstance, const otPlatDnssdSrvResolver *aResolver)
{
VerifyOrQuit(aResolver != nullptr);
Log("otPlatDnssdStopSrvResolver(\"%s\", \"%s\")", aResolver->mServiceInstance, aResolver->mServiceType);
VerifyOrQuit(aInstance == sInstance);
VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
sStopSrvResolverInfo.UpdateFrom(aResolver);
}
void otPlatDnssdStartTxtResolver(otInstance *aInstance, const otPlatDnssdTxtResolver *aResolver)
{
VerifyOrQuit(aResolver != nullptr);
Log("otPlatDnssdStartTxtResolver(\"%s\", \"%s\")", aResolver->mServiceInstance, aResolver->mServiceType);
VerifyOrQuit(aInstance == sInstance);
VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
sStartTxtResolverInfo.UpdateFrom(aResolver);
if (sInvokeOnStart.mTxtResult != nullptr)
{
InvokeTxtResolverCallback(aResolver->mCallback, *sInvokeOnStart.mTxtResult);
}
}
void otPlatDnssdStopTxtResolver(otInstance *aInstance, const otPlatDnssdTxtResolver *aResolver)
{
VerifyOrQuit(aResolver != nullptr);
Log("otPlatDnssdStopTxtResolver(\"%s\", \"%s\")", aResolver->mServiceInstance, aResolver->mServiceType);
VerifyOrQuit(aInstance == sInstance);
VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
sStopTxtResolverInfo.UpdateFrom(aResolver);
}
void otPlatDnssdStartIp6AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver)
{
VerifyOrQuit(aResolver != nullptr);
Log("otPlatDnssdStartIp6AddressResolver(\"%s\")", aResolver->mHostName);
VerifyOrQuit(aInstance == sInstance);
VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
sStartIp6AddrResolverInfo.UpdateFrom(aResolver);
if (sInvokeOnStart.mIp6AddrResult != nullptr)
{
InvokeIp6AddrResolverCallback(aResolver->mCallback, *sInvokeOnStart.mIp6AddrResult);
}
}
void otPlatDnssdStopIp6AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver)
{
VerifyOrQuit(aResolver != nullptr);
Log("otPlatDnssdStopIp6AddressResolver(\"%s\")", aResolver->mHostName);
VerifyOrQuit(aInstance == sInstance);
VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
sStopIp6AddrResolverInfo.UpdateFrom(aResolver);
if (sInvokeOnStart.mIp6AddrResult != nullptr)
{
InvokeIp6AddrResolverCallback(aResolver->mCallback, *sInvokeOnStart.mIp6AddrResult);
}
}
void otPlatDnssdStartIp4AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver)
{
VerifyOrQuit(aResolver != nullptr);
Log("otPlatDnssdStartIp4AddressResolver(\"%s\")", aResolver->mHostName);
VerifyOrQuit(aInstance == sInstance);
VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
sStartIp4AddrResolverInfo.UpdateFrom(aResolver);
if (sInvokeOnStart.mIp4AddrResult != nullptr)
{
InvokeIp6AddrResolverCallback(aResolver->mCallback, *sInvokeOnStart.mIp4AddrResult);
}
}
void otPlatDnssdStopIp4AddressResolver(otInstance *aInstance, const otPlatDnssdAddressResolver *aResolver)
{
VerifyOrQuit(aResolver != nullptr);
Log("otPlatDnssdStopIp4AddressResolver(\"%s\")", aResolver->mHostName);
VerifyOrQuit(aInstance == sInstance);
VerifyOrQuit(aResolver->mInfraIfIndex == kInfraIfIndex);
sStopIp4AddrResolverInfo.UpdateFrom(aResolver);
if (sInvokeOnStart.mIp6AddrResult != nullptr)
{
InvokeIp4AddrResolverCallback(aResolver->mCallback, *sInvokeOnStart.mIp4AddrResult);
}
}
//----------------------------------------------------------------------------------------------------------------------
void TestProxyBasic(void)
{
static constexpr uint32_t kTtl = 300;
const uint8_t kTxtData[] = {3, 'A', '=', '1', 0};
Srp::Server *srpServer;
Srp::Client *srpClient;
Dns::Client *dnsClient;
Dns::ServiceDiscovery::Server *dnsServer;
Dnssd::BrowseResult browseResult;
Dnssd::SrvResult srvResult;
Dnssd::TxtResult txtResult;
Dnssd::AddressResult ip6AddrrResult;
Dnssd::AddressResult ip4AddrrResult;
Dnssd::AddressAndTtl addressAndTtl;
NetworkData::ExternalRouteConfig routeConfig;
Ip6::Address address;
Log("--------------------------------------------------------------------------------------------");
Log("TestProxyBasic");
InitTest();
srpServer = &sInstance->Get<Srp::Server>();
srpClient = &sInstance->Get<Srp::Client>();
dnsClient = &sInstance->Get<Dns::Client>();
dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP server.
SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
srpServer->SetEnabled(true);
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
AdvanceTime(10000);
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP client.
srpClient->EnableAutoStartMode(nullptr, nullptr);
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
AdvanceTime(2000);
VerifyOrQuit(srpClient->IsRunning());
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Add a route prefix (with NAT64 flag) to network data");
routeConfig.Clear();
SuccessOrQuit(AsCoreType(&routeConfig.mPrefix.mPrefix).FromString("64:ff9b::"));
routeConfig.mPrefix.mLength = 96;
routeConfig.mPreference = NetworkData::kRoutePreferenceMedium;
routeConfig.mNat64 = true;
routeConfig.mStable = true;
SuccessOrQuit(otBorderRouterAddRoute(sInstance, &routeConfig));
SuccessOrQuit(otBorderRouterRegister(sInstance));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sBrowseInfo.Reset();
ResetPlatDnssdApiInfo();
Log("Browse()");
SuccessOrQuit(dnsClient->Browse("_avenger._udp.default.service.arpa.", BrowseCallback, sInstance));
AdvanceTime(10);
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_avenger._udp"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke Browser callback");
browseResult.mServiceType = "_avenger._udp";
browseResult.mSubTypeLabel = nullptr;
browseResult.mServiceInstance = "hulk";
browseResult.mTtl = kTtl;
browseResult.mInfraIfIndex = kInfraIfIndex;
InvokeBrowserCallback(sStartBrowserInfo.mCallback, browseResult);
AdvanceTime(10);
// Check that browser is stopped and a service resolver is started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStopBrowserInfo.mCallback == sStartBrowserInfo.mCallback);
VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("hulk"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke SRV resolver callback");
srvResult.mServiceInstance = "hulk";
srvResult.mServiceType = "_avenger._udp";
srvResult.mHostName = "compound";
srvResult.mPort = 7777;
srvResult.mTtl = kTtl;
srvResult.mInfraIfIndex = kInfraIfIndex;
InvokeSrvResolverCallback(sStartSrvResolverInfo.mCallback, srvResult);
AdvanceTime(10);
// Check that SRV resolver is stopped and a TXT resolver is started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStopSrvResolverInfo.ServiceInstanceMatches("hulk"));
VerifyOrQuit(sStopSrvResolverInfo.mCallback == sStartSrvResolverInfo.mCallback);
VerifyOrQuit(sStartTxtResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStartTxtResolverInfo.ServiceInstanceMatches("hulk"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke TXT resolver callback");
txtResult.mServiceInstance = "hulk";
txtResult.mServiceType = "_avenger._udp";
txtResult.mTxtData = kTxtData;
txtResult.mTxtDataLength = sizeof(kTxtData);
txtResult.mTtl = kTtl;
txtResult.mInfraIfIndex = kInfraIfIndex;
InvokeTxtResolverCallback(sStartTxtResolverInfo.mCallback, txtResult);
AdvanceTime(10);
// Check that TXT resolver is stopped and an address resolver is started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStopTxtResolverInfo.ServiceInstanceMatches("hulk"));
VerifyOrQuit(sStopTxtResolverInfo.mCallback == sStartTxtResolverInfo.mCallback);
VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("compound"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke Address Resolver callback");
SuccessOrQuit(AsCoreType(&addressAndTtl.mAddress).FromString("fd00::1234"));
addressAndTtl.mTtl = kTtl;
ip6AddrrResult.mHostName = "compound";
ip6AddrrResult.mInfraIfIndex = kInfraIfIndex;
ip6AddrrResult.mAddresses = &addressAndTtl;
ip6AddrrResult.mAddressesLength = 1;
InvokeIp6AddrResolverCallback(sStartIp6AddrResolverInfo.mCallback, ip6AddrrResult);
AdvanceTime(10);
// Check that address resolver is stopped
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("compound"));
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallback == sStartIp6AddrResolverInfo.mCallback);
// Check that response is sent to client and validate it
VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
SuccessOrQuit(sBrowseInfo.mError);
VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
VerifyOrQuit(!strcmp(sBrowseInfo.mServiceName, "_avenger._udp.default.service.arpa."));
VerifyOrQuit(!strcmp(sBrowseInfo.mInstanceLabel, "hulk"));
VerifyOrQuit(!strcmp(sBrowseInfo.mServiceInfo.mHostNameBuffer, "compound.default.service.arpa."));
VerifyOrQuit(sBrowseInfo.mServiceInfo.mPort == 7777);
VerifyOrQuit(sBrowseInfo.mServiceInfo.mTtl == kTtl);
VerifyOrQuit(AsCoreType(&sBrowseInfo.mServiceInfo.mHostAddress) == AsCoreType(&addressAndTtl.mAddress));
VerifyOrQuit(sBrowseInfo.mServiceInfo.mHostAddressTtl == kTtl);
VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataSize == sizeof(kTxtData));
VerifyOrQuit(!memcmp(sBrowseInfo.mServiceInfo.mTxtData, kTxtData, sizeof(kTxtData)));
VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataTtl == kTtl);
VerifyOrQuit(!sBrowseInfo.mServiceInfo.mTxtDataTruncated);
Log("--------------------------------------------------------------------------------------------");
ResetPlatDnssdApiInfo();
sResolveServiceInfo.Reset();
Log("ResolveService() with dot `.` character in service instance label");
SuccessOrQuit(
dnsClient->ResolveService("iron.man", "_avenger._udp.default.service.arpa.", ServiceCallback, sInstance));
AdvanceTime(10);
// Check that a service resolver is started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("iron.man"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke SRV Resolver callback for wrong name");
srvResult.mServiceInstance = "hulk";
srvResult.mServiceType = "_avenger._udp";
srvResult.mHostName = "compound";
srvResult.mPort = 7777;
srvResult.mTtl = kTtl;
srvResult.mInfraIfIndex = kInfraIfIndex;
InvokeSrvResolverCallback(sStartSrvResolverInfo.mCallback, srvResult);
AdvanceTime(10);
// Check that no changes to browsers/resolvers
VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 0);
Log("Invoke SRV Resolver callback for correct name");
srvResult.mServiceInstance = "iron.man";
srvResult.mServiceType = "_avenger._udp";
srvResult.mHostName = "starktower";
srvResult.mPort = 1024;
srvResult.mTtl = kTtl;
srvResult.mInfraIfIndex = kInfraIfIndex;
InvokeSrvResolverCallback(sStartSrvResolverInfo.mCallback, srvResult);
AdvanceTime(10);
// Check that SRV resolver is stopped and TXT resolver is started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStopSrvResolverInfo.ServiceInstanceMatches("iron.man"));
VerifyOrQuit(sStopSrvResolverInfo.mCallback == sStartSrvResolverInfo.mCallback);
VerifyOrQuit(sStartTxtResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStartTxtResolverInfo.ServiceInstanceMatches("iron.man"));
Log("Invoke TXT Resolver callback");
txtResult.mServiceInstance = "iron.man";
txtResult.mServiceType = "_avenger._udp";
txtResult.mTxtData = kTxtData;
txtResult.mTxtDataLength = sizeof(kTxtData);
txtResult.mTtl = kTtl;
txtResult.mInfraIfIndex = kInfraIfIndex;
InvokeTxtResolverCallback(sStartTxtResolverInfo.mCallback, txtResult);
AdvanceTime(10);
// Check that TXT resolver is stopped and addr resolver is started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStopTxtResolverInfo.ServiceInstanceMatches("iron.man"));
VerifyOrQuit(sStopTxtResolverInfo.mCallback == sStartTxtResolverInfo.mCallback);
VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("starktower"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke Address Resolver callback");
ip6AddrrResult.mHostName = "starktower";
InvokeIp6AddrResolverCallback(sStartIp6AddrResolverInfo.mCallback, ip6AddrrResult);
AdvanceTime(10);
// Check that address resolver is stopped
VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("starktower"));
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallback == sStartIp6AddrResolverInfo.mCallback);
// Check that response is sent to client and validate it
VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
VerifyOrQuit(sResolveServiceInfo.mError == kErrorNone);
VerifyOrQuit(!strcmp(sResolveServiceInfo.mInfo.mHostNameBuffer, "starktower.default.service.arpa."));
VerifyOrQuit(sResolveServiceInfo.mInfo.mPort == 1024);
VerifyOrQuit(sResolveServiceInfo.mInfo.mTtl == kTtl);
VerifyOrQuit(AsCoreType(&sResolveServiceInfo.mInfo.mHostAddress) == AsCoreType(&addressAndTtl.mAddress));
VerifyOrQuit(sResolveServiceInfo.mInfo.mHostAddressTtl == kTtl);
VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataSize == sizeof(kTxtData));
VerifyOrQuit(!memcmp(sResolveServiceInfo.mInfo.mTxtData, kTxtData, sizeof(kTxtData)));
VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataTtl == kTtl);
VerifyOrQuit(!sResolveServiceInfo.mInfo.mTxtDataTruncated);
Log("--------------------------------------------------------------------------------------------");
ResetPlatDnssdApiInfo();
sResolveAddressInfo.Reset();
Log("ResolveAddress()");
SuccessOrQuit(dnsClient->ResolveAddress("earth.default.service.arpa.", AddressCallback, sInstance));
AdvanceTime(10);
// Check that an address resolver is started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("earth"));
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke Address Resolver callback");
SuccessOrQuit(AsCoreType(&addressAndTtl.mAddress).FromString("fd00::7777"));
addressAndTtl.mTtl = kTtl;
ip6AddrrResult.mHostName = "earth";
ip6AddrrResult.mInfraIfIndex = kInfraIfIndex;
ip6AddrrResult.mAddresses = &addressAndTtl;
ip6AddrrResult.mAddressesLength = 1;
InvokeIp6AddrResolverCallback(sStartIp6AddrResolverInfo.mCallback, ip6AddrrResult);
AdvanceTime(10);
// Check that the address resolver is stopped
VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("earth"));
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallback == sStartIp6AddrResolverInfo.mCallback);
// Check that response is sent to client and validate it
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
SuccessOrQuit(sResolveAddressInfo.mError);
VerifyOrQuit(!strcmp(sResolveAddressInfo.mHostName, "earth.default.service.arpa."));
VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 1);
VerifyOrQuit(sResolveAddressInfo.mHostAddresses[0] == AsCoreType(&addressAndTtl.mAddress));
VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl);
Log("--------------------------------------------------------------------------------------------");
ResetPlatDnssdApiInfo();
sResolveAddressInfo.Reset();
Log("ResolveIp4Address()");
SuccessOrQuit(dnsClient->ResolveIp4Address("shield.default.service.arpa.", AddressCallback, sInstance));
AdvanceTime(10);
// Check that an IPv4 address resolver is started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp4AddrResolverInfo.HostNameMatches("shield"));
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke IPv4 Address Resolver callback");
SuccessOrQuit(AsCoreType(&addressAndTtl.mAddress).FromString("::ffff:1.2.3.4"));
addressAndTtl.mTtl = kTtl;
ip4AddrrResult.mHostName = "shield";
ip4AddrrResult.mInfraIfIndex = kInfraIfIndex;
ip4AddrrResult.mAddresses = &addressAndTtl;
ip4AddrrResult.mAddressesLength = 1;
InvokeIp4AddrResolverCallback(sStartIp4AddrResolverInfo.mCallback, ip4AddrrResult);
AdvanceTime(10);
// Check that the IPv4 address resolver is stopped
VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp4AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp4AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp4AddrResolverInfo.HostNameMatches("shield"));
VerifyOrQuit(sStopIp4AddrResolverInfo.mCallback == sStartIp4AddrResolverInfo.mCallback);
// Check that response is sent to client and validate it
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
SuccessOrQuit(sResolveAddressInfo.mError);
VerifyOrQuit(!strcmp(sResolveAddressInfo.mHostName, "shield.default.service.arpa."));
VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 1);
// The 1.2.3.4 address with the NAT64 prefix
SuccessOrQuit(address.FromString("64:ff9b:0:0:0:0:102:304"));
VerifyOrQuit(sResolveAddressInfo.mHostAddresses[0] == address);
VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl);
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
SuccessOrQuit(sResolveAddressInfo.mError);
VerifyOrQuit(!strcmp(sResolveAddressInfo.mHostName, "shield.default.service.arpa."));
VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 1);
VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl);
VerifyOrQuit(sResolveAddressInfo.mHostAddresses[0] == address);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Stop DNS-SD server");
dnsServer->Stop();
AdvanceTime(10);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Finalize OT instance and validate all heap allocations are freed.
Log("Finalizing OT instance");
FinalizeTest();
Log("End of TestProxyBasic");
}
//----------------------------------------------------------------------------------------------------------------------
void TestProxySubtypeBrowse(void)
{
static constexpr uint32_t kTtl = 300;
const uint8_t kTxtData[] = {3, 'G', '=', '0', 0};
Srp::Server *srpServer;
Srp::Client *srpClient;
Dns::Client *dnsClient;
Dns::ServiceDiscovery::Server *dnsServer;
Dnssd::BrowseResult browseResult;
Dnssd::SrvResult srvResult;
Dnssd::TxtResult txtResult;
Dnssd::AddressResult ip6AddrrResult;
Dnssd::AddressAndTtl addressAndTtl;
Log("--------------------------------------------------------------------------------------------");
Log("TestProxySubtypeBrowse");
InitTest();
srpServer = &sInstance->Get<Srp::Server>();
srpClient = &sInstance->Get<Srp::Client>();
dnsClient = &sInstance->Get<Dns::Client>();
dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP server.
SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
srpServer->SetEnabled(true);
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
AdvanceTime(10000);
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP client.
srpClient->EnableAutoStartMode(nullptr, nullptr);
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
AdvanceTime(2000);
VerifyOrQuit(srpClient->IsRunning());
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sBrowseInfo.Reset();
ResetPlatDnssdApiInfo();
Log("Browse() for sub-type service");
SuccessOrQuit(dnsClient->Browse("_god._sub._avenger._udp.default.service.arpa.", BrowseCallback, sInstance));
AdvanceTime(10);
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStartBrowserInfo.SubTypeMatches("_god"));
VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke Browser callback");
browseResult.mServiceType = "_avenger._udp";
browseResult.mSubTypeLabel = "_god";
browseResult.mServiceInstance = "thor";
browseResult.mTtl = kTtl;
browseResult.mInfraIfIndex = kInfraIfIndex;
InvokeBrowserCallback(sStartBrowserInfo.mCallback, browseResult);
AdvanceTime(10);
// Check that browser is stopped and a service resolver is started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStopBrowserInfo.SubTypeMatches("_god"));
VerifyOrQuit(sStopBrowserInfo.mCallback == sStartBrowserInfo.mCallback);
// Check that the SRV resolver is correctly using the base service type
// and not the sub-type name
VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("thor"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke Service Resolver callback");
srvResult.mServiceInstance = "thor";
srvResult.mServiceType = "_avenger._udp";
srvResult.mHostName = "asgard";
srvResult.mPort = 1234;
srvResult.mTtl = kTtl;
srvResult.mInfraIfIndex = kInfraIfIndex;
InvokeSrvResolverCallback(sStartSrvResolverInfo.mCallback, srvResult);
AdvanceTime(10);
// Check that SRV resolver is stopped and a TXT resolver is started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStopSrvResolverInfo.ServiceInstanceMatches("thor"));
VerifyOrQuit(sStopSrvResolverInfo.mCallback == sStartSrvResolverInfo.mCallback);
VerifyOrQuit(sStartTxtResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStartTxtResolverInfo.ServiceInstanceMatches("thor"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke Service Resolver callback");
txtResult.mServiceInstance = "thor";
txtResult.mServiceType = "_avenger._udp";
txtResult.mTxtData = kTxtData;
txtResult.mTxtDataLength = sizeof(kTxtData);
txtResult.mTtl = kTtl;
txtResult.mInfraIfIndex = kInfraIfIndex;
InvokeTxtResolverCallback(sStartTxtResolverInfo.mCallback, txtResult);
AdvanceTime(10);
// Check that TXT resolver is stopped and an address resolver is started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStopTxtResolverInfo.ServiceInstanceMatches("thor"));
VerifyOrQuit(sStopTxtResolverInfo.mCallback == sStartTxtResolverInfo.mCallback);
VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("asgard"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke Address Resolver callback");
SuccessOrQuit(AsCoreType(&addressAndTtl.mAddress).FromString("fd00::1234"));
addressAndTtl.mTtl = kTtl;
ip6AddrrResult.mHostName = "asgard";
ip6AddrrResult.mInfraIfIndex = kInfraIfIndex;
ip6AddrrResult.mAddresses = &addressAndTtl;
ip6AddrrResult.mAddressesLength = 1;
InvokeIp6AddrResolverCallback(sStartIp6AddrResolverInfo.mCallback, ip6AddrrResult);
AdvanceTime(10);
// Check that address resolver is stopped
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("asgard"));
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallback == sStartIp6AddrResolverInfo.mCallback);
// Check that response is sent to client and validate it
VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
SuccessOrQuit(sBrowseInfo.mError);
VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
VerifyOrQuit(!strcmp(sBrowseInfo.mServiceName, "_god._sub._avenger._udp.default.service.arpa."));
VerifyOrQuit(!strcmp(sBrowseInfo.mInstanceLabel, "thor"));
VerifyOrQuit(!strcmp(sBrowseInfo.mServiceInfo.mHostNameBuffer, "asgard.default.service.arpa."));
VerifyOrQuit(sBrowseInfo.mServiceInfo.mPort == 1234);
VerifyOrQuit(sBrowseInfo.mServiceInfo.mTtl == kTtl);
VerifyOrQuit(AsCoreType(&sBrowseInfo.mServiceInfo.mHostAddress) == AsCoreType(&addressAndTtl.mAddress));
VerifyOrQuit(sBrowseInfo.mServiceInfo.mHostAddressTtl == kTtl);
VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataSize == sizeof(kTxtData));
VerifyOrQuit(!memcmp(sBrowseInfo.mServiceInfo.mTxtData, kTxtData, sizeof(kTxtData)));
VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataTtl == kTtl);
VerifyOrQuit(!sBrowseInfo.mServiceInfo.mTxtDataTruncated);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Stop DNS-SD server");
dnsServer->Stop();
AdvanceTime(10);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Finalize OT instance and validate all heap allocations are freed.
Log("Finalizing OT instance");
FinalizeTest();
Log("End of TestProxySubtypeBrowse");
}
//----------------------------------------------------------------------------------------------------------------------
void TestProxyTimeout(void)
{
static constexpr uint32_t kTtl = 300;
Srp::Server *srpServer;
Srp::Client *srpClient;
Dns::Client *dnsClient;
Dns::ServiceDiscovery::Server *dnsServer;
Dns::Client::QueryConfig config;
Dnssd::BrowseResult browseResult;
Log("--------------------------------------------------------------------------------------------");
Log("TestProxyTimeout");
InitTest();
srpServer = &sInstance->Get<Srp::Server>();
srpClient = &sInstance->Get<Srp::Client>();
dnsClient = &sInstance->Get<Dns::Client>();
dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP server.
SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
srpServer->SetEnabled(true);
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
AdvanceTime(10000);
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP client.
srpClient->EnableAutoStartMode(nullptr, nullptr);
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
AdvanceTime(2000);
VerifyOrQuit(srpClient->IsRunning());
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Increase default response retry timeout on DNS client");
config.Clear();
config.mResponseTimeout = 120 * 1000; // 2 minutes (in msec)
config.mNat64Mode = OT_DNS_NAT64_DISALLOW;
dnsClient->SetDefaultConfig(config);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sBrowseInfo.Reset();
ResetPlatDnssdApiInfo();
Log("Browse()");
SuccessOrQuit(dnsClient->Browse("_game._ps5.default.service.arpa.", BrowseCallback, sInstance));
AdvanceTime(10);
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_game._ps5"));
VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Wait for timeout and check empty response on client");
AdvanceTime(10 * 1000);
VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
VerifyOrQuit(sBrowseInfo.mNumInstances == 0);
// Check that the browser is stopped
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_game._ps5"));
VerifyOrQuit(sStopBrowserInfo.mCallback == sStartBrowserInfo.mCallback);
Log("--------------------------------------------------------------------------------------------");
Log("Timeout during service resolution");
sBrowseInfo.Reset();
ResetPlatDnssdApiInfo();
SuccessOrQuit(dnsClient->Browse("_avenger._udp.default.service.arpa.", BrowseCallback, sInstance));
AdvanceTime(10);
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_avenger._udp"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke Browser callback");
browseResult.mServiceType = "_avenger._udp";
browseResult.mSubTypeLabel = nullptr;
browseResult.mServiceInstance = "spiderman";
browseResult.mTtl = kTtl;
browseResult.mInfraIfIndex = kInfraIfIndex;
InvokeBrowserCallback(sStartBrowserInfo.mCallback, browseResult);
AdvanceTime(10);
// Check that browser is stopped and a service resolver is started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("spiderman"));
VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Wait for timeout");
AdvanceTime(10 * 1000);
VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
// Check that the browser is stopped
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_avenger._udp"));
// Validate the response received by client
VerifyOrQuit(!strcmp(sBrowseInfo.mServiceName, "_avenger._udp.default.service.arpa."));
VerifyOrQuit(!strcmp(sBrowseInfo.mInstanceLabel, "spiderman"));
Log("--------------------------------------------------------------------------------------------");
Log("Timeout during multiple requests");
sBrowseInfo.Reset();
sResolveServiceInfo.Reset();
sResolveAddressInfo.Reset();
ResetPlatDnssdApiInfo();
Log("Browse()");
SuccessOrQuit(dnsClient->Browse("_avenger._udp.default.service.arpa.", BrowseCallback, sInstance));
AdvanceTime(10);
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_avenger._udp"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Another Browse()");
SuccessOrQuit(dnsClient->Browse("_game._udp.default.service.arpa.", BrowseCallback, sInstance));
AdvanceTime(10);
VerifyOrQuit(sStartBrowserInfo.mCallCount == 2);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_game._udp"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("ResolveService()");
SuccessOrQuit(
dnsClient->ResolveService("wanda", "_avenger._udp.default.service.arpa.", ServiceCallback, sInstance));
AdvanceTime(10);
VerifyOrQuit(sStartBrowserInfo.mCallCount == 2);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("wanda"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("ResolveAddress()");
SuccessOrQuit(dnsClient->ResolveAddress("earth.default.service.arpa.", AddressCallback, sInstance));
AdvanceTime(10);
VerifyOrQuit(sStartBrowserInfo.mCallCount == 2);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("earth"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Wait for timeout for all requests");
AdvanceTime(10 * 1000);
VerifyOrQuit(sBrowseInfo.mCallbackCount == 2);
VerifyOrQuit(sBrowseInfo.mNumInstances == 0);
VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
VerifyOrQuit(sResolveServiceInfo.mError == kErrorNotFound);
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 0);
// Check that all browsers/resolvers are stopped.
VerifyOrQuit(sStartBrowserInfo.mCallCount == 2);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 2);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStopSrvResolverInfo.ServiceInstanceMatches("wanda"));
VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("earth"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Stop DNS-SD server");
dnsServer->Stop();
AdvanceTime(10);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Finalize OT instance and validate all heap allocations are freed.
Log("Finalizing OT instance");
FinalizeTest();
Log("End of TestProxyTimeout");
}
void TestProxySharedResolver(void)
{
static constexpr uint32_t kTtl = 300;
const uint8_t kTxtData[] = {3, 'A', '=', '1', 0};
Srp::Server *srpServer;
Srp::Client *srpClient;
Dns::Client *dnsClient;
Dns::ServiceDiscovery::Server *dnsServer;
Dnssd::BrowseResult browseResult;
Dnssd::SrvResult srvResult;
Dnssd::TxtResult txtResult;
Dnssd::AddressResult ip6AddrrResult;
Dnssd::AddressAndTtl addressAndTtl[2];
Log("--------------------------------------------------------------------------------------------");
Log("TestProxySharedResolver");
InitTest();
srpServer = &sInstance->Get<Srp::Server>();
srpClient = &sInstance->Get<Srp::Client>();
dnsClient = &sInstance->Get<Dns::Client>();
dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP server.
SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
srpServer->SetEnabled(true);
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
AdvanceTime(10000);
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP client.
srpClient->EnableAutoStartMode(nullptr, nullptr);
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
AdvanceTime(2000);
VerifyOrQuit(srpClient->IsRunning());
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sBrowseInfo.Reset();
sResolveServiceInfo.Reset();
sResolveAddressInfo.Reset();
ResetPlatDnssdApiInfo();
Log("ResolveAddress()");
SuccessOrQuit(dnsClient->ResolveAddress("knowhere.default.service.arpa.", AddressCallback, sInstance));
AdvanceTime(10);
Log("ResolveService()");
SuccessOrQuit(
dnsClient->ResolveService("starlord", "_guardian._glaxy.default.service.arpa.", ServiceCallback, sInstance));
AdvanceTime(10);
Log("Browse()");
SuccessOrQuit(dnsClient->Browse("_guardian._glaxy.default.service.arpa.", BrowseCallback, sInstance));
AdvanceTime(10);
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("starlord"));
VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("knowhere"));
VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 0);
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke Browser callback");
browseResult.mServiceType = "_guardian._glaxy";
browseResult.mSubTypeLabel = nullptr;
browseResult.mServiceInstance = "starlord";
browseResult.mTtl = kTtl;
browseResult.mInfraIfIndex = kInfraIfIndex;
InvokeBrowserCallback(sStartBrowserInfo.mCallback, browseResult);
AdvanceTime(10);
// Check that browser is stopped and since the service instance
// name matches an existing resolver, we should not see any new
// resolver starting.
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 0);
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke Service Resolver callback");
srvResult.mServiceInstance = "starlord";
srvResult.mServiceType = "_guardian._glaxy";
srvResult.mHostName = "knowhere";
srvResult.mPort = 3333;
srvResult.mTtl = kTtl;
srvResult.mInfraIfIndex = kInfraIfIndex;
InvokeSrvResolverCallback(sStartSrvResolverInfo.mCallback, srvResult);
AdvanceTime(10);
// Check that SRV resolver is now stopped and a TXT resolver
// is started for same service.
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sStopSrvResolverInfo.ServiceInstanceMatches("starlord"));
txtResult.mServiceInstance = "starlord";
txtResult.mServiceType = "_guardian._glaxy";
txtResult.mTxtData = kTxtData;
txtResult.mTxtDataLength = sizeof(kTxtData);
txtResult.mTtl = kTtl;
txtResult.mInfraIfIndex = kInfraIfIndex;
InvokeTxtResolverCallback(sStartTxtResolverInfo.mCallback, txtResult);
AdvanceTime(10);
// Check that TXT resolver is now stopped but again since the
// host name matches an existing address resolver we should not
// see any new address resolver.
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sStopTxtResolverInfo.ServiceInstanceMatches("starlord"));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke Address Resolver callback");
SuccessOrQuit(AsCoreType(&addressAndTtl[0].mAddress).FromString("fd00::5555"));
SuccessOrQuit(AsCoreType(&addressAndTtl[1].mAddress).FromString("fd00::1234"));
addressAndTtl[0].mTtl = kTtl;
addressAndTtl[1].mTtl = kTtl;
ip6AddrrResult.mHostName = "knowhere";
ip6AddrrResult.mInfraIfIndex = kInfraIfIndex;
ip6AddrrResult.mAddresses = addressAndTtl;
ip6AddrrResult.mAddressesLength = 2;
InvokeIp6AddrResolverCallback(sStartIp6AddrResolverInfo.mCallback, ip6AddrrResult);
AdvanceTime(10);
// Check that the address resolver is now stopped.
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("knowhere"));
// Check the browse response received on client
VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
SuccessOrQuit(sBrowseInfo.mError);
VerifyOrQuit(sBrowseInfo.mNumInstances == 1);
VerifyOrQuit(!strcmp(sBrowseInfo.mServiceName, "_guardian._glaxy.default.service.arpa."));
VerifyOrQuit(!strcmp(sBrowseInfo.mInstanceLabel, "starlord"));
VerifyOrQuit(!strcmp(sBrowseInfo.mServiceInfo.mHostNameBuffer, "knowhere.default.service.arpa."));
VerifyOrQuit(sBrowseInfo.mServiceInfo.mPort == 3333);
VerifyOrQuit(sBrowseInfo.mServiceInfo.mTtl == kTtl);
VerifyOrQuit(sBrowseInfo.mServiceInfo.mHostAddressTtl == kTtl);
VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataSize == sizeof(kTxtData));
VerifyOrQuit(!memcmp(sBrowseInfo.mServiceInfo.mTxtData, kTxtData, sizeof(kTxtData)));
VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataTtl == kTtl);
VerifyOrQuit(!sBrowseInfo.mServiceInfo.mTxtDataTruncated);
// Check the service resolve response received on client
VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
SuccessOrQuit(sResolveServiceInfo.mError);
VerifyOrQuit(!strcmp(sResolveServiceInfo.mInfo.mHostNameBuffer, "knowhere.default.service.arpa."));
VerifyOrQuit(sResolveServiceInfo.mInfo.mPort == 3333);
VerifyOrQuit(sResolveServiceInfo.mInfo.mTtl == kTtl);
VerifyOrQuit(sResolveServiceInfo.mInfo.mHostAddressTtl == kTtl);
VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataSize == sizeof(kTxtData));
VerifyOrQuit(!memcmp(sResolveServiceInfo.mInfo.mTxtData, kTxtData, sizeof(kTxtData)));
VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataTtl == kTtl);
VerifyOrQuit(!sResolveServiceInfo.mInfo.mTxtDataTruncated);
VerifyOrQuit(sResolveServiceInfo.mNumHostAddresses == 2);
for (uint16_t index = 0; index < 2; index++)
{
VerifyOrQuit(sResolveServiceInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[0].mAddress) ||
sResolveServiceInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[1].mAddress));
}
// Check the address resolve response received on client
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
SuccessOrQuit(sResolveAddressInfo.mError);
VerifyOrQuit(!strcmp(sResolveAddressInfo.mHostName, "knowhere.default.service.arpa."));
VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl);
VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 2);
for (uint16_t index = 0; index < 2; index++)
{
VerifyOrQuit(sResolveAddressInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[0].mAddress) ||
sResolveAddressInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[1].mAddress));
}
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Stop DNS-SD server");
dnsServer->Stop();
AdvanceTime(10);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Finalize OT instance and validate all heap allocations are freed.
Log("Finalizing OT instance");
FinalizeTest();
Log("End of TestProxySharedResolver");
}
void TestProxyFilterInvalidAddresses(void)
{
static constexpr uint32_t kTtl = 300;
Srp::Server *srpServer;
Srp::Client *srpClient;
Dns::Client *dnsClient;
Dns::ServiceDiscovery::Server *dnsServer;
Dnssd::AddressResult ip6AddrrResult;
Dnssd::AddressAndTtl addressAndTtl[10];
Log("--------------------------------------------------------------------------------------------");
Log("TestProxyFilterInvalidAddresses");
InitTest();
srpServer = &sInstance->Get<Srp::Server>();
srpClient = &sInstance->Get<Srp::Client>();
dnsClient = &sInstance->Get<Dns::Client>();
dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP server.
SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
srpServer->SetEnabled(true);
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
AdvanceTime(10000);
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP client.
srpClient->EnableAutoStartMode(nullptr, nullptr);
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
AdvanceTime(2000);
VerifyOrQuit(srpClient->IsRunning());
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sResolveAddressInfo.Reset();
ResetPlatDnssdApiInfo();
Log("ResolveAddress()");
SuccessOrQuit(dnsClient->ResolveAddress("host.default.service.arpa.", AddressCallback, sInstance));
AdvanceTime(10);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("host"));
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke Address Resolver callback with invalid addresses");
SuccessOrQuit(AsCoreType(&addressAndTtl[0].mAddress).FromString("::")); // Unspecified
SuccessOrQuit(AsCoreType(&addressAndTtl[1].mAddress).FromString("fe80::1234")); // Link local
SuccessOrQuit(AsCoreType(&addressAndTtl[2].mAddress).FromString("ff00::1234")); // Multicast
SuccessOrQuit(AsCoreType(&addressAndTtl[3].mAddress).FromString("::1")); // Lookback
for (uint16_t index = 0; index < 5; index++)
{
addressAndTtl[index].mTtl = kTtl;
}
ip6AddrrResult.mHostName = "host";
ip6AddrrResult.mInfraIfIndex = kInfraIfIndex;
ip6AddrrResult.mAddresses = addressAndTtl;
ip6AddrrResult.mAddressesLength = 4;
InvokeIp6AddrResolverCallback(sStartIp6AddrResolverInfo.mCallback, ip6AddrrResult);
AdvanceTime(10);
// Check that the address resolver is not stopped, since all addresses where
// invalid address.
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Invoke Address Resolver callback with invalid addresses with one valid");
SuccessOrQuit(AsCoreType(&addressAndTtl[4].mAddress).FromString("f00::1234"));
ip6AddrrResult.mAddressesLength = 5;
InvokeIp6AddrResolverCallback(sStartIp6AddrResolverInfo.mCallback, ip6AddrrResult);
AdvanceTime(10);
// Check that address resolver is not stopped
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("host"));
// Check that response received on client is valid and only contains
// the valid two addresses and filters all others.
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
SuccessOrQuit(sResolveAddressInfo.mError);
VerifyOrQuit(!strcmp(sResolveAddressInfo.mHostName, "host.default.service.arpa."));
VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl);
VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 1);
VerifyOrQuit(sResolveAddressInfo.mHostAddresses[0] == AsCoreType(&addressAndTtl[4].mAddress));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Stop DNS-SD server");
dnsServer->Stop();
AdvanceTime(10);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Finalize OT instance and validate all heap allocations are freed.
Log("Finalizing OT instance");
FinalizeTest();
Log("End of TestProxyFilterInvalidAddresses");
}
void TestProxyStateChanges(void)
{
static constexpr uint32_t kTtl = 300;
Srp::Server *srpServer;
Srp::Client *srpClient;
Dns::Client *dnsClient;
Dns::ServiceDiscovery::Server *dnsServer;
Log("--------------------------------------------------------------------------------------------");
Log("TestProxyStateChanges");
InitTest();
srpServer = &sInstance->Get<Srp::Server>();
srpClient = &sInstance->Get<Srp::Client>();
dnsClient = &sInstance->Get<Dns::Client>();
dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP server.
SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
srpServer->SetEnabled(true);
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
AdvanceTime(10000);
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP client.
srpClient->EnableAutoStartMode(nullptr, nullptr);
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
AdvanceTime(2000);
VerifyOrQuit(srpClient->IsRunning());
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Signal DNS-SD platform state is stopped and not yet ready");
sDnssdState = OT_PLAT_DNSSD_STOPPED;
otPlatDnssdStateHandleStateChange(sInstance);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sResolveAddressInfo.Reset();
ResetPlatDnssdApiInfo();
Log("ResolveAddress()");
SuccessOrQuit(dnsClient->ResolveAddress("host.default.service.arpa.", AddressCallback, sInstance));
AdvanceTime(10);
// Check that none of the DNS-SD resolver/browser APIs are called
// since the platform is not yet ready
VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Signal DNS-SD platform state is now ready");
sDnssdState = OT_PLAT_DNSSD_READY;
otPlatDnssdStateHandleStateChange(sInstance);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sResolveAddressInfo.Reset();
ResetPlatDnssdApiInfo();
Log("ResolveAddress()");
SuccessOrQuit(dnsClient->ResolveAddress("host.default.service.arpa.", AddressCallback, sInstance));
AdvanceTime(10);
// Check that address resolver is started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("host"));
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sBrowseInfo.Reset();
Log("Browse()");
SuccessOrQuit(dnsClient->Browse("_magic._udp.default.service.arpa.", BrowseCallback, sInstance));
AdvanceTime(10);
// Check that browser is also started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 0);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_magic._udp"));
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 0);
VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Signal infra-if is not running");
SuccessOrQuit(otPlatInfraIfStateChanged(sInstance, kInfraIfIndex, /* aIsRunning */ false));
AdvanceTime(10);
// Check that both address resolver and browser are stopped
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("host"));
VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_magic._udp"));
// And response is sent to client
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sResolveAddressInfo.Reset();
Log("ResolveAddress()");
SuccessOrQuit(dnsClient->ResolveAddress("earth.default.service.arpa.", AddressCallback, sInstance));
AdvanceTime(10);
// Check that no resolver is started.
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Signal that infra-if is running again ");
SuccessOrQuit(otPlatInfraIfStateChanged(sInstance, kInfraIfIndex, /* aIsRunning */ true));
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sResolveServiceInfo.Reset();
Log("ResolveService()");
SuccessOrQuit(dnsClient->ResolveService("captain.america", "_avenger._udp.default.service.arpa.", ServiceCallback,
sInstance));
AdvanceTime(10);
// The proxy should be started again so check that a service resolver
// is started for new request
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_avenger._udp"));
VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("captain.america"));
VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Signal DNS-SD platform state is stopped");
sDnssdState = OT_PLAT_DNSSD_STOPPED;
otPlatDnssdStateHandleStateChange(sInstance);
AdvanceTime(10);
// This should stop proxy but since DNS-SD platform is stopped
// we assume all browsers/resolvers are also stopped, so there
// should be no explicit call to stop it.
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
// Check that response is sent to client
VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Signal DNS-SD platform state is ready again");
sDnssdState = OT_PLAT_DNSSD_READY;
otPlatDnssdStateHandleStateChange(sInstance);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sBrowseInfo.Reset();
Log("Browse()");
SuccessOrQuit(dnsClient->Browse("_magical._udp.default.service.arpa.", BrowseCallback, sInstance));
AdvanceTime(10);
// Proxy should be started again and we should see a new browser started
VerifyOrQuit(sStartBrowserInfo.mCallCount == 2);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_magical._udp"));
VerifyOrQuit(sBrowseInfo.mCallbackCount == 0);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Stop DNS-SD server");
dnsServer->Stop();
AdvanceTime(10);
// Check that the browser is stopped
VerifyOrQuit(sStartBrowserInfo.mCallCount == 2);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 2);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 0);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_magical._udp"));
// And response is sent to client
VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Finalize OT instance and validate all heap allocations are freed.
Log("Finalizing OT instance");
FinalizeTest();
Log("End of TestProxyStateChanges");
}
void TestProxyInvokeCallbackFromStartApi(void)
{
static constexpr uint32_t kTtl = 300;
const uint8_t kTxtData[] = {3, 'A', '=', '1', 0};
Srp::Server *srpServer;
Srp::Client *srpClient;
Dns::Client *dnsClient;
Dns::ServiceDiscovery::Server *dnsServer;
Dnssd::BrowseResult browseResult;
Dnssd::SrvResult srvResult;
Dnssd::TxtResult txtResult;
Dnssd::AddressResult ip6AddrrResult;
Dnssd::AddressAndTtl addressAndTtl[2];
Log("--------------------------------------------------------------------------------------------");
Log("TestProxyInvokeCallbackFromStartApi");
InitTest();
srpServer = &sInstance->Get<Srp::Server>();
srpClient = &sInstance->Get<Srp::Client>();
dnsClient = &sInstance->Get<Dns::Client>();
dnsServer = &sInstance->Get<Dns::ServiceDiscovery::Server>();
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP server.
SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
srpServer->SetEnabled(true);
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
AdvanceTime(10000);
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start SRP client.
srpClient->EnableAutoStartMode(nullptr, nullptr);
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
AdvanceTime(2000);
VerifyOrQuit(srpClient->IsRunning());
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Enable invoking of callback directly from otPlatDnssdStart{Browsers/Resolver} APIs");
ResetPlatDnssdApiInfo();
sInvokeOnStart.mBrowseResult = &browseResult;
sInvokeOnStart.mSrvResult = &srvResult;
sInvokeOnStart.mTxtResult = &txtResult;
sInvokeOnStart.mIp6AddrResult = &ip6AddrrResult;
browseResult.mServiceType = "_guardian._glaxy";
browseResult.mSubTypeLabel = nullptr;
browseResult.mServiceInstance = "mantis";
browseResult.mTtl = kTtl;
browseResult.mInfraIfIndex = kInfraIfIndex;
srvResult.mServiceInstance = "mantis";
srvResult.mServiceType = "_guardian._glaxy";
srvResult.mHostName = "nova";
srvResult.mPort = 3333;
srvResult.mTtl = kTtl;
srvResult.mInfraIfIndex = kInfraIfIndex;
txtResult.mServiceInstance = "mantis";
txtResult.mServiceType = "_guardian._glaxy";
txtResult.mTxtData = kTxtData;
txtResult.mTxtDataLength = sizeof(kTxtData);
txtResult.mTtl = kTtl;
txtResult.mInfraIfIndex = kInfraIfIndex;
SuccessOrQuit(AsCoreType(&addressAndTtl[0].mAddress).FromString("fd00::5555"));
SuccessOrQuit(AsCoreType(&addressAndTtl[1].mAddress).FromString("fd00::1234"));
addressAndTtl[0].mTtl = kTtl;
addressAndTtl[1].mTtl = kTtl;
ip6AddrrResult.mHostName = "nova";
ip6AddrrResult.mInfraIfIndex = kInfraIfIndex;
ip6AddrrResult.mAddresses = addressAndTtl;
ip6AddrrResult.mAddressesLength = 2;
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sBrowseInfo.Reset();
Log("Browse()");
SuccessOrQuit(dnsClient->Browse("_guardian._glaxy.default.service.arpa.", BrowseCallback, sInstance));
AdvanceTime(10);
// All browsers/resolvers should be started and stopped
// (since the callbacks are invoked directly from API)
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 1);
VerifyOrQuit(sStartBrowserInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sStopBrowserInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("mantis"));
VerifyOrQuit(sStopSrvResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sStopSrvResolverInfo.ServiceInstanceMatches("mantis"));
VerifyOrQuit(sStartTxtResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sStartTxtResolverInfo.ServiceInstanceMatches("mantis"));
VerifyOrQuit(sStopTxtResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sStopTxtResolverInfo.ServiceInstanceMatches("mantis"));
VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("nova"));
VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("nova"));
// Check that response is revived by client and validate it
VerifyOrQuit(sBrowseInfo.mCallbackCount == 1);
VerifyOrQuit(!strcmp(sBrowseInfo.mServiceName, "_guardian._glaxy.default.service.arpa."));
VerifyOrQuit(!strcmp(sBrowseInfo.mInstanceLabel, "mantis"));
VerifyOrQuit(!strcmp(sBrowseInfo.mServiceInfo.mHostNameBuffer, "nova.default.service.arpa."));
VerifyOrQuit(sBrowseInfo.mServiceInfo.mPort == 3333);
VerifyOrQuit(sBrowseInfo.mServiceInfo.mTtl == kTtl);
VerifyOrQuit(sBrowseInfo.mServiceInfo.mHostAddressTtl == kTtl);
VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataSize == sizeof(kTxtData));
VerifyOrQuit(!memcmp(sBrowseInfo.mServiceInfo.mTxtData, kTxtData, sizeof(kTxtData)));
VerifyOrQuit(sBrowseInfo.mServiceInfo.mTxtDataTtl == kTtl);
VerifyOrQuit(!sBrowseInfo.mServiceInfo.mTxtDataTruncated);
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sResolveServiceInfo.Reset();
Log("ResolveService()");
SuccessOrQuit(
dnsClient->ResolveService("mantis", "_guardian._glaxy.default.service.arpa.", ServiceCallback, sInstance));
AdvanceTime(10);
// Check that new SRV/TXT resolver and address resolvers are
// started and stopped.
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 2);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 2);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 2);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 2);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 2);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 2);
VerifyOrQuit(sStartSrvResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sStartSrvResolverInfo.ServiceInstanceMatches("mantis"));
VerifyOrQuit(sStopSrvResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sStopSrvResolverInfo.ServiceInstanceMatches("mantis"));
VerifyOrQuit(sStartTxtResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sStartTxtResolverInfo.ServiceInstanceMatches("mantis"));
VerifyOrQuit(sStopTxtResolverInfo.ServiceTypeMatches("_guardian._glaxy"));
VerifyOrQuit(sStopTxtResolverInfo.ServiceInstanceMatches("mantis"));
VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("nova"));
VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("nova"));
// Check the service resolve response received on client
VerifyOrQuit(sResolveServiceInfo.mCallbackCount == 1);
SuccessOrQuit(sResolveServiceInfo.mError);
VerifyOrQuit(!strcmp(sResolveServiceInfo.mInfo.mHostNameBuffer, "nova.default.service.arpa."));
VerifyOrQuit(sResolveServiceInfo.mInfo.mPort == 3333);
VerifyOrQuit(sResolveServiceInfo.mInfo.mTtl == kTtl);
VerifyOrQuit(sResolveServiceInfo.mInfo.mHostAddressTtl == kTtl);
VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataSize == sizeof(kTxtData));
VerifyOrQuit(!memcmp(sResolveServiceInfo.mInfo.mTxtData, kTxtData, sizeof(kTxtData)));
VerifyOrQuit(sResolveServiceInfo.mInfo.mTxtDataTtl == kTtl);
VerifyOrQuit(!sResolveServiceInfo.mInfo.mTxtDataTruncated);
VerifyOrQuit(sResolveServiceInfo.mNumHostAddresses == 2);
for (uint16_t index = 0; index < 2; index++)
{
VerifyOrQuit(sResolveServiceInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[0].mAddress) ||
sResolveServiceInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[1].mAddress));
}
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
sResolveAddressInfo.Reset();
Log("ResolveAddress()");
SuccessOrQuit(dnsClient->ResolveAddress("nova.default.service.arpa.", AddressCallback, sInstance));
AdvanceTime(10);
// Check that new address resolver is started and stopped.
VerifyOrQuit(sStartBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStopBrowserInfo.mCallCount == 1);
VerifyOrQuit(sStartSrvResolverInfo.mCallCount == 2);
VerifyOrQuit(sStopSrvResolverInfo.mCallCount == 2);
VerifyOrQuit(sStartTxtResolverInfo.mCallCount == 2);
VerifyOrQuit(sStopTxtResolverInfo.mCallCount == 2);
VerifyOrQuit(sStartIp6AddrResolverInfo.mCallCount == 3);
VerifyOrQuit(sStopIp6AddrResolverInfo.mCallCount == 3);
VerifyOrQuit(sStartIp6AddrResolverInfo.HostNameMatches("nova"));
VerifyOrQuit(sStopIp6AddrResolverInfo.HostNameMatches("nova"));
// Check the address resolve response received on client
VerifyOrQuit(sResolveAddressInfo.mCallbackCount == 1);
SuccessOrQuit(sResolveAddressInfo.mError);
VerifyOrQuit(!strcmp(sResolveAddressInfo.mHostName, "nova.default.service.arpa."));
VerifyOrQuit(sResolveAddressInfo.mTtl == kTtl);
VerifyOrQuit(sResolveAddressInfo.mNumHostAddresses == 2);
for (uint16_t index = 0; index < 2; index++)
{
VerifyOrQuit(sResolveAddressInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[0].mAddress) ||
sResolveAddressInfo.mHostAddresses[index] == AsCoreType(&addressAndTtl[1].mAddress));
}
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
Log("Stop DNS-SD server");
dnsServer->Stop();
AdvanceTime(10);
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Finalize OT instance and validate all heap allocations are freed.
Log("Finalizing OT instance");
FinalizeTest();
Log("End of TestProxyInvokeCallbackFromStartApi");
}
#endif // ENABLE_DISCOVERY_PROXY_TEST
int main(void)
{
#if ENABLE_DISCOVERY_PROXY_TEST
TestProxyBasic();
TestProxySubtypeBrowse();
TestProxyTimeout();
TestProxySharedResolver();
TestProxyFilterInvalidAddresses();
TestProxyStateChanges();
TestProxyInvokeCallbackFromStartApi();
printf("All tests passed\n");
#else
printf("DISCOVERY_PROXY feature or a related feature required by this unit test is not enabled\n");
#endif
return 0;
}