mirror of
https://github.com/espressif/openthread.git
synced 2026-06-06 05:24:51 +00:00
c923900de0
This commit provides the platform-level implementation for the instance-aware logging API `otPlatLogOutput()`. This API is used when `OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE` is enabled, allowing the platform to receive the `otInstance` pointer with each log line. The new API is implemented across: - The simulation platform logging. - The POSIX platform using `syslog()`. - The NCP base to route logs to the NCP host. - The CLI logging module. - Unit tests and mock platforms. The `OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE` configuration is also enabled for Toranj simulations to support multi-instance log testing.
2794 lines
96 KiB
C++
2794 lines
96 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/srp_client.h>
|
|
#include <openthread/srp_server.h>
|
|
#include <openthread/thread.h>
|
|
|
|
#include "common/arg_macros.hpp"
|
|
#include "common/array.hpp"
|
|
#include "common/string.hpp"
|
|
#include "common/time.hpp"
|
|
#include "instance/instance.hpp"
|
|
|
|
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE && \
|
|
OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE && !OPENTHREAD_CONFIG_TIME_SYNC_ENABLE && \
|
|
!OPENTHREAD_PLATFORM_POSIX && OPENTHREAD_CONFIG_PLATFORM_DNSSD_ALLOW_RUN_TIME_SELECTION
|
|
#define ENABLE_ADV_PROXY_TEST 1
|
|
#else
|
|
#define ENABLE_ADV_PROXY_TEST 0
|
|
#endif
|
|
|
|
#if ENABLE_ADV_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; }
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// `otPlatAlarm`
|
|
|
|
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; }
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// `otPlatDnssd`
|
|
|
|
static constexpr uint16_t kDnssdArraySize = 128;
|
|
|
|
struct DnssdRequest
|
|
{
|
|
DnssdRequest(void) = default;
|
|
|
|
DnssdRequest(otPlatDnssdRequestId aId, otPlatDnssdRegisterCallback aCallback)
|
|
: mId(aId)
|
|
, mCallback(aCallback)
|
|
{
|
|
}
|
|
|
|
otPlatDnssdRequestId mId;
|
|
otPlatDnssdRegisterCallback mCallback;
|
|
};
|
|
|
|
static Array<DnssdRequest, kDnssdArraySize> sDnssdRegHostRequests;
|
|
static Array<DnssdRequest, kDnssdArraySize> sDnssdUnregHostRequests;
|
|
static Array<DnssdRequest, kDnssdArraySize> sDnssdRegServiceRequests;
|
|
static Array<DnssdRequest, kDnssdArraySize> sDnssdUnregServiceRequests;
|
|
static Array<DnssdRequest, kDnssdArraySize> sDnssdRegKeyRequests;
|
|
static Array<DnssdRequest, kDnssdArraySize> sDnssdUnregKeyRequests;
|
|
|
|
static bool sDnssdShouldCheckWithClient = true;
|
|
static Error sDnssdCallbackError = kErrorPending;
|
|
static otPlatDnssdState sDnssdState = OT_PLAT_DNSSD_READY;
|
|
static uint16_t sDnssdNumHostAddresses = 0;
|
|
|
|
constexpr uint32_t kInfraIfIndex = 1;
|
|
|
|
otPlatDnssdState otPlatDnssdGetState(otInstance *aInstance)
|
|
{
|
|
OT_UNUSED_VARIABLE(aInstance);
|
|
|
|
return sDnssdState;
|
|
}
|
|
|
|
void otPlatDnssdRegisterService(otInstance *aInstance,
|
|
const otPlatDnssdService *aService,
|
|
otPlatDnssdRequestId aRequestId,
|
|
otPlatDnssdRegisterCallback aCallback)
|
|
{
|
|
Log("otPlatDnssdRegisterService(aRequestId: %lu)", ToUlong(aRequestId));
|
|
Log(" hostName : %s", aService->mHostName);
|
|
Log(" serviceInstance: %s", aService->mServiceInstance);
|
|
Log(" serviceType : %s", aService->mServiceType);
|
|
Log(" num sub-types : %u", aService->mSubTypeLabelsLength);
|
|
|
|
for (uint16_t index = 0; index < aService->mSubTypeLabelsLength; index++)
|
|
{
|
|
Log(" sub-type %-4u : %s", index, aService->mSubTypeLabels[index]);
|
|
}
|
|
|
|
Log(" TXT data len : %u", aService->mTxtDataLength);
|
|
Log(" port : %u", aService->mPort);
|
|
Log(" priority : %u", aService->mPriority);
|
|
Log(" weight : %u", aService->mWeight);
|
|
Log(" TTL : %u", aService->mTtl);
|
|
Log(" Infra-if index : %u", aService->mInfraIfIndex);
|
|
|
|
VerifyOrQuit(aInstance == sInstance);
|
|
VerifyOrQuit(aService->mInfraIfIndex == kInfraIfIndex);
|
|
|
|
if (sDnssdShouldCheckWithClient)
|
|
{
|
|
Srp::Client &srpClient = AsCoreType(aInstance).Get<Srp::Client>();
|
|
bool didFind = false;
|
|
|
|
VerifyOrQuit(StringMatch(srpClient.GetHostInfo().GetName(), aService->mHostName));
|
|
|
|
didFind = false;
|
|
|
|
for (const Srp::Client::Service &service : srpClient.GetServices())
|
|
{
|
|
if (StringMatch(service.GetInstanceName(), aService->mServiceInstance))
|
|
{
|
|
didFind = true;
|
|
VerifyOrQuit(StringMatch(service.GetName(), aService->mServiceType));
|
|
VerifyOrQuit(service.GetPort() == aService->mPort);
|
|
VerifyOrQuit(service.GetWeight() == aService->mWeight);
|
|
VerifyOrQuit(service.GetPriority() == aService->mPriority);
|
|
VerifyOrQuit(service.HasSubType() == (aService->mSubTypeLabelsLength != 0));
|
|
}
|
|
}
|
|
|
|
VerifyOrQuit(didFind);
|
|
}
|
|
|
|
SuccessOrQuit(sDnssdRegServiceRequests.PushBack(DnssdRequest(aRequestId, aCallback)));
|
|
|
|
if ((sDnssdCallbackError != kErrorPending) && (aCallback != nullptr))
|
|
{
|
|
aCallback(aInstance, aRequestId, sDnssdCallbackError);
|
|
}
|
|
}
|
|
|
|
void otPlatDnssdUnregisterService(otInstance *aInstance,
|
|
const otPlatDnssdService *aService,
|
|
otPlatDnssdRequestId aRequestId,
|
|
otPlatDnssdRegisterCallback aCallback)
|
|
{
|
|
Log("otPlatDnssdUnregisterService(aRequestId: %lu)", ToUlong(aRequestId));
|
|
Log(" hostName : %s", aService->mHostName);
|
|
Log(" serviceInstance: %s", aService->mServiceInstance);
|
|
Log(" serviceName : %s", aService->mServiceType);
|
|
Log(" Infra-if index : %u", aService->mInfraIfIndex);
|
|
|
|
VerifyOrQuit(aInstance == sInstance);
|
|
VerifyOrQuit(aService->mInfraIfIndex == kInfraIfIndex);
|
|
|
|
if (sDnssdShouldCheckWithClient)
|
|
{
|
|
// Validate the received service info matches one of the services
|
|
// on SRP client.
|
|
|
|
Srp::Client &srpClient = AsCoreType(aInstance).Get<Srp::Client>();
|
|
bool didFind = false;
|
|
|
|
VerifyOrQuit(StringMatch(srpClient.GetHostInfo().GetName(), aService->mHostName));
|
|
|
|
for (const Srp::Client::Service &service : srpClient.GetServices())
|
|
{
|
|
if (StringMatch(service.GetInstanceName(), aService->mServiceInstance))
|
|
{
|
|
didFind = true;
|
|
VerifyOrQuit(StringMatch(service.GetName(), aService->mServiceType));
|
|
}
|
|
}
|
|
|
|
VerifyOrQuit(didFind);
|
|
}
|
|
|
|
SuccessOrQuit(sDnssdUnregServiceRequests.PushBack(DnssdRequest(aRequestId, aCallback)));
|
|
|
|
if ((sDnssdCallbackError != kErrorPending) && (aCallback != nullptr))
|
|
{
|
|
aCallback(aInstance, aRequestId, sDnssdCallbackError);
|
|
}
|
|
}
|
|
|
|
void otPlatDnssdRegisterHost(otInstance *aInstance,
|
|
const otPlatDnssdHost *aHost,
|
|
otPlatDnssdRequestId aRequestId,
|
|
otPlatDnssdRegisterCallback aCallback)
|
|
{
|
|
Log("otPlatDnssdRegisterHost(aRequestId: %lu)", ToUlong(aRequestId));
|
|
Log(" hostName : %s", aHost->mHostName);
|
|
Log(" numAddresses : %u", aHost->mAddressesLength);
|
|
|
|
for (uint16_t index = 0; index < aHost->mAddressesLength; index++)
|
|
{
|
|
Log(" Address %-4u : %s", index, AsCoreType(&aHost->mAddresses[index]).ToString().AsCString());
|
|
}
|
|
|
|
Log(" TTL : %u", aHost->mTtl);
|
|
Log(" Infra-if index : %u", aHost->mInfraIfIndex);
|
|
|
|
VerifyOrQuit(aInstance == sInstance);
|
|
VerifyOrQuit(aHost->mInfraIfIndex == kInfraIfIndex);
|
|
|
|
sDnssdNumHostAddresses = aHost->mAddressesLength;
|
|
|
|
if (sDnssdShouldCheckWithClient)
|
|
{
|
|
VerifyOrQuit(StringMatch(AsCoreType(aInstance).Get<Srp::Client>().GetHostInfo().GetName(), aHost->mHostName));
|
|
}
|
|
|
|
SuccessOrQuit(sDnssdRegHostRequests.PushBack(DnssdRequest(aRequestId, aCallback)));
|
|
|
|
if ((sDnssdCallbackError != kErrorPending) && (aCallback != nullptr))
|
|
{
|
|
aCallback(aInstance, aRequestId, sDnssdCallbackError);
|
|
}
|
|
}
|
|
|
|
void otPlatDnssdUnregisterHost(otInstance *aInstance,
|
|
const otPlatDnssdHost *aHost,
|
|
otPlatDnssdRequestId aRequestId,
|
|
otPlatDnssdRegisterCallback aCallback)
|
|
{
|
|
Log("otPlatDnssdUnregisterHost(aRequestId: %lu)", ToUlong(aRequestId));
|
|
Log(" hostName : %s", aHost->mHostName);
|
|
Log(" Infra-if index : %u", aHost->mInfraIfIndex);
|
|
|
|
VerifyOrQuit(sInstance == aInstance);
|
|
VerifyOrQuit(aHost->mInfraIfIndex == kInfraIfIndex);
|
|
|
|
if (sDnssdShouldCheckWithClient)
|
|
{
|
|
VerifyOrQuit(StringMatch(AsCoreType(aInstance).Get<Srp::Client>().GetHostInfo().GetName(), aHost->mHostName));
|
|
}
|
|
|
|
SuccessOrQuit(sDnssdUnregHostRequests.PushBack(DnssdRequest(aRequestId, aCallback)));
|
|
|
|
if ((sDnssdCallbackError != kErrorPending) && (aCallback != nullptr))
|
|
{
|
|
aCallback(aInstance, aRequestId, sDnssdCallbackError);
|
|
}
|
|
}
|
|
|
|
void otPlatDnssdRegisterKey(otInstance *aInstance,
|
|
const otPlatDnssdKey *aKey,
|
|
otPlatDnssdRequestId aRequestId,
|
|
otPlatDnssdRegisterCallback aCallback)
|
|
{
|
|
Log("otPlatDnssdRegisterKey(aRequestId: %lu)", ToUlong(aRequestId));
|
|
Log(" name : %s", aKey->mName);
|
|
Log(" serviceType : %s", aKey->mServiceType == nullptr ? "(null)" : aKey->mServiceType);
|
|
Log(" key data-len : %u", aKey->mKeyDataLength);
|
|
Log(" TTL : %u", aKey->mTtl);
|
|
|
|
VerifyOrQuit(aInstance == sInstance);
|
|
VerifyOrQuit(aKey->mInfraIfIndex == kInfraIfIndex);
|
|
|
|
if (sDnssdShouldCheckWithClient)
|
|
{
|
|
if (aKey->mServiceType == nullptr)
|
|
{
|
|
VerifyOrQuit(StringMatch(AsCoreType(aInstance).Get<Srp::Client>().GetHostInfo().GetName(), aKey->mName));
|
|
}
|
|
else
|
|
{
|
|
bool didFind = false;
|
|
|
|
for (const Srp::Client::Service &service : AsCoreType(aInstance).Get<Srp::Client>().GetServices())
|
|
{
|
|
if (StringMatch(service.GetInstanceName(), aKey->mName))
|
|
{
|
|
didFind = true;
|
|
VerifyOrQuit(StringMatch(service.GetName(), aKey->mServiceType));
|
|
}
|
|
}
|
|
|
|
VerifyOrQuit(didFind);
|
|
}
|
|
}
|
|
|
|
SuccessOrQuit(sDnssdRegKeyRequests.PushBack(DnssdRequest(aRequestId, aCallback)));
|
|
|
|
if ((sDnssdCallbackError != kErrorPending) && (aCallback != nullptr))
|
|
{
|
|
aCallback(aInstance, aRequestId, sDnssdCallbackError);
|
|
}
|
|
}
|
|
|
|
void otPlatDnssdUnregisterKey(otInstance *aInstance,
|
|
const otPlatDnssdKey *aKey,
|
|
otPlatDnssdRequestId aRequestId,
|
|
otPlatDnssdRegisterCallback aCallback)
|
|
{
|
|
Log("otPlatDnssdUnregisterKey(aRequestId: %lu)", ToUlong(aRequestId));
|
|
Log(" name : %s", aKey->mName);
|
|
|
|
VerifyOrQuit(aInstance == sInstance);
|
|
VerifyOrQuit(aKey->mInfraIfIndex == kInfraIfIndex);
|
|
|
|
if (sDnssdShouldCheckWithClient)
|
|
{
|
|
if (aKey->mServiceType == nullptr)
|
|
{
|
|
VerifyOrQuit(StringMatch(AsCoreType(aInstance).Get<Srp::Client>().GetHostInfo().GetName(), aKey->mName));
|
|
}
|
|
else
|
|
{
|
|
bool didFind = false;
|
|
|
|
for (const Srp::Client::Service &service : AsCoreType(aInstance).Get<Srp::Client>().GetServices())
|
|
{
|
|
if (StringMatch(service.GetInstanceName(), aKey->mName))
|
|
{
|
|
didFind = true;
|
|
VerifyOrQuit(StringMatch(service.GetName(), aKey->mServiceType));
|
|
}
|
|
}
|
|
|
|
VerifyOrQuit(didFind);
|
|
}
|
|
}
|
|
|
|
SuccessOrQuit(sDnssdUnregKeyRequests.PushBack(DnssdRequest(aRequestId, aCallback)));
|
|
|
|
if ((sDnssdCallbackError != kErrorPending) && (aCallback != nullptr))
|
|
{
|
|
aCallback(aInstance, aRequestId, sDnssdCallbackError);
|
|
}
|
|
}
|
|
|
|
// Number of times we expect each `otPlatDnssd` request to be called
|
|
struct DnssdRequestCounts : public Clearable<DnssdRequestCounts>
|
|
{
|
|
DnssdRequestCounts(void) { Clear(); }
|
|
|
|
uint16_t mKeyReg;
|
|
uint16_t mHostReg;
|
|
uint16_t mServiceReg;
|
|
uint16_t mKeyUnreg;
|
|
uint16_t mHostUnreg;
|
|
uint16_t mServiceUnreg;
|
|
};
|
|
|
|
void VerifyDnnsdRequests(const DnssdRequestCounts &aRequestCounts, bool aAllowMoreUnregs = false)
|
|
{
|
|
VerifyOrQuit(sDnssdRegKeyRequests.GetLength() == aRequestCounts.mKeyReg);
|
|
VerifyOrQuit(sDnssdRegHostRequests.GetLength() == aRequestCounts.mHostReg);
|
|
VerifyOrQuit(sDnssdRegServiceRequests.GetLength() == aRequestCounts.mServiceReg);
|
|
|
|
if (aAllowMoreUnregs)
|
|
{
|
|
VerifyOrQuit(sDnssdUnregKeyRequests.GetLength() >= aRequestCounts.mKeyUnreg);
|
|
VerifyOrQuit(sDnssdUnregHostRequests.GetLength() >= aRequestCounts.mHostUnreg);
|
|
VerifyOrQuit(sDnssdUnregServiceRequests.GetLength() >= aRequestCounts.mServiceUnreg);
|
|
}
|
|
else
|
|
{
|
|
VerifyOrQuit(sDnssdUnregKeyRequests.GetLength() == aRequestCounts.mKeyUnreg);
|
|
VerifyOrQuit(sDnssdUnregHostRequests.GetLength() == aRequestCounts.mHostUnreg);
|
|
VerifyOrQuit(sDnssdUnregServiceRequests.GetLength() == aRequestCounts.mServiceUnreg);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
|
|
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
|
|
#if OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE
|
|
void otPlatLogOutput(otInstance *, otLogLevel, const char *aLogLine) { printf(" %s\n", aLogLine); }
|
|
#else
|
|
void otPlatLog(otLogLevel, otLogRegion, const char *aFormat, ...)
|
|
{
|
|
va_list args;
|
|
|
|
printf(" ");
|
|
va_start(args, aFormat);
|
|
vprintf(aFormat, args);
|
|
va_end(args);
|
|
printf("\n");
|
|
}
|
|
#endif
|
|
#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;
|
|
|
|
sDnssdShouldCheckWithClient = true;
|
|
sDnssdState = OT_PLAT_DNSSD_READY;
|
|
sDnssdCallbackError = kErrorPending;
|
|
sDnssdRegHostRequests.Clear();
|
|
sDnssdUnregHostRequests.Clear();
|
|
sDnssdRegServiceRequests.Clear();
|
|
sDnssdUnregServiceRequests.Clear();
|
|
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// 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));
|
|
|
|
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
|
|
// Disable the Border Agent to prevent its attempt to
|
|
// register the `_meshcop._udp` service from
|
|
// interfering with this test.
|
|
sInstance->Get<MeshCoP::BorderAgent::Manager>().SetEnabled(false);
|
|
#endif
|
|
|
|
// 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));
|
|
SuccessOrQuit(otInstanceErasePersistentInfo(sInstance));
|
|
testFreeInstance(sInstance);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------------------------------------
|
|
// SRP Client callback
|
|
|
|
static bool sProcessedClientCallback = false;
|
|
static Error sLastClientCallbackError = kErrorNone;
|
|
|
|
void HandleSrpClientCallback(otError aError,
|
|
const otSrpClientHostInfo *aHostInfo,
|
|
const otSrpClientService *aServices,
|
|
const otSrpClientService *aRemovedServices,
|
|
void *aContext)
|
|
{
|
|
Log("HandleSrpClientCallback() called with error %s", ErrorToString(aError));
|
|
|
|
VerifyOrQuit(aContext == sInstance);
|
|
|
|
sProcessedClientCallback = true;
|
|
sLastClientCallbackError = aError;
|
|
|
|
OT_UNUSED_VARIABLE(aHostInfo);
|
|
OT_UNUSED_VARIABLE(aServices);
|
|
OT_UNUSED_VARIABLE(aRemovedServices);
|
|
}
|
|
|
|
static const char kHostName[] = "awesomehost";
|
|
|
|
void PrepareService1(Srp::Client::Service &aService)
|
|
{
|
|
static const char kServiceName[] = "_srv1._udp";
|
|
static const char kInstanceLabel[] = "service1";
|
|
static const char kSub1[] = "_sub1";
|
|
static const char kSub2[] = "_sub2";
|
|
static const char kSub3[] = "_sub3";
|
|
static const char *kSubLabels[] = {kSub1, kSub2, kSub3, nullptr};
|
|
static const char kTxtKey1[] = "ABCD";
|
|
static const uint8_t kTxtValue1[] = {'a', '0'};
|
|
static const char kTxtKey2[] = "Z0";
|
|
static const uint8_t kTxtValue2[] = {'1', '2', '3'};
|
|
static const char kTxtKey3[] = "D";
|
|
static const uint8_t kTxtValue3[] = {0};
|
|
static const otDnsTxtEntry kTxtEntries[] = {
|
|
{kTxtKey1, kTxtValue1, sizeof(kTxtValue1)},
|
|
{kTxtKey2, kTxtValue2, sizeof(kTxtValue2)},
|
|
{kTxtKey3, kTxtValue3, sizeof(kTxtValue3)},
|
|
};
|
|
|
|
memset(&aService, 0, sizeof(aService));
|
|
aService.mName = kServiceName;
|
|
aService.mInstanceName = kInstanceLabel;
|
|
aService.mSubTypeLabels = kSubLabels;
|
|
aService.mTxtEntries = kTxtEntries;
|
|
aService.mNumTxtEntries = 3;
|
|
aService.mPort = 777;
|
|
aService.mWeight = 1;
|
|
aService.mPriority = 2;
|
|
}
|
|
|
|
void PrepareService2(Srp::Client::Service &aService)
|
|
{
|
|
static const char kService2Name[] = "_matter._udp";
|
|
static const char kInstance2Label[] = "service2";
|
|
static const char kSub4[] = "_44444444";
|
|
static const char *kSubLabels2[] = {kSub4, nullptr};
|
|
|
|
memset(&aService, 0, sizeof(aService));
|
|
aService.mName = kService2Name;
|
|
aService.mInstanceName = kInstance2Label;
|
|
aService.mSubTypeLabels = kSubLabels2;
|
|
aService.mTxtEntries = nullptr;
|
|
aService.mNumTxtEntries = 0;
|
|
aService.mPort = 555;
|
|
aService.mWeight = 0;
|
|
aService.mPriority = 3;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
|
|
typedef Dnssd::RequestId RequestId;
|
|
typedef Dnssd::RequestIdRange RequestIdRange;
|
|
|
|
void ValidateRequestIdRange(const RequestIdRange &aIdRange, RequestId aStart, RequestId aEnd)
|
|
{
|
|
RequestId maxId = NumericLimits<RequestId>::kMax;
|
|
bool shouldContain = false;
|
|
|
|
VerifyOrQuit(!aIdRange.IsEmpty());
|
|
|
|
for (RequestId id = aStart - 5; id != aEnd + 6; id++)
|
|
{
|
|
// `idRange` should contain IDs within range `[aStart, aEnd]`
|
|
|
|
if (id == aStart)
|
|
{
|
|
shouldContain = true;
|
|
}
|
|
|
|
if (id == aEnd + 1)
|
|
{
|
|
shouldContain = false;
|
|
}
|
|
|
|
VerifyOrQuit(aIdRange.Contains(id) == shouldContain);
|
|
}
|
|
|
|
// Test values that half the range apart
|
|
|
|
for (RequestId id = aStart + maxId / 2 - 10; id != aEnd + maxId / 2 + 10; id++)
|
|
{
|
|
VerifyOrQuit(!aIdRange.Contains(id));
|
|
}
|
|
}
|
|
|
|
void TestDnssdRequestIdRange(void)
|
|
{
|
|
RequestId maxId = NumericLimits<RequestId>::kMax;
|
|
RequestIdRange idRange;
|
|
|
|
Log("--------------------------------------------------------------------------------------------");
|
|
Log("TestDnssdRequestIdRange");
|
|
|
|
VerifyOrQuit(idRange.IsEmpty());
|
|
|
|
idRange.Add(5);
|
|
ValidateRequestIdRange(idRange, 5, 5);
|
|
|
|
idRange.Remove(4);
|
|
ValidateRequestIdRange(idRange, 5, 5);
|
|
|
|
idRange.Remove(6);
|
|
ValidateRequestIdRange(idRange, 5, 5);
|
|
|
|
idRange.Remove(5);
|
|
VerifyOrQuit(idRange.IsEmpty());
|
|
VerifyOrQuit(!idRange.Contains(5));
|
|
|
|
// Adding and removing multiple IDs
|
|
|
|
idRange.Add(10);
|
|
idRange.Add(15);
|
|
ValidateRequestIdRange(idRange, 10, 15);
|
|
|
|
idRange.Add(12);
|
|
ValidateRequestIdRange(idRange, 10, 15);
|
|
idRange.Add(15);
|
|
ValidateRequestIdRange(idRange, 10, 15);
|
|
idRange.Add(10);
|
|
ValidateRequestIdRange(idRange, 10, 15);
|
|
|
|
idRange.Add(9);
|
|
ValidateRequestIdRange(idRange, 9, 15);
|
|
idRange.Add(16);
|
|
ValidateRequestIdRange(idRange, 9, 16);
|
|
|
|
idRange.Remove(10);
|
|
ValidateRequestIdRange(idRange, 9, 16);
|
|
idRange.Remove(15);
|
|
ValidateRequestIdRange(idRange, 9, 16);
|
|
|
|
idRange.Remove(8);
|
|
ValidateRequestIdRange(idRange, 9, 16);
|
|
idRange.Remove(17);
|
|
ValidateRequestIdRange(idRange, 9, 16);
|
|
|
|
idRange.Remove(9);
|
|
ValidateRequestIdRange(idRange, 10, 16);
|
|
idRange.Remove(16);
|
|
ValidateRequestIdRange(idRange, 10, 15);
|
|
|
|
idRange.Clear();
|
|
VerifyOrQuit(idRange.IsEmpty());
|
|
VerifyOrQuit(!idRange.Contains(10));
|
|
|
|
// Ranges close to roll-over max value
|
|
|
|
idRange.Add(maxId);
|
|
ValidateRequestIdRange(idRange, maxId, maxId);
|
|
|
|
idRange.Remove(0);
|
|
ValidateRequestIdRange(idRange, maxId, maxId);
|
|
idRange.Remove(maxId - 1);
|
|
ValidateRequestIdRange(idRange, maxId, maxId);
|
|
|
|
idRange.Add(0);
|
|
ValidateRequestIdRange(idRange, maxId, 0);
|
|
|
|
idRange.Add(maxId - 2);
|
|
ValidateRequestIdRange(idRange, maxId - 2, 0);
|
|
|
|
idRange.Add(3);
|
|
ValidateRequestIdRange(idRange, maxId - 2, 3);
|
|
idRange.Add(3);
|
|
ValidateRequestIdRange(idRange, maxId - 2, 3);
|
|
|
|
idRange.Remove(4);
|
|
ValidateRequestIdRange(idRange, maxId - 2, 3);
|
|
idRange.Remove(maxId - 3);
|
|
ValidateRequestIdRange(idRange, maxId - 2, 3);
|
|
|
|
idRange.Remove(3);
|
|
ValidateRequestIdRange(idRange, maxId - 2, 2);
|
|
|
|
idRange.Remove(maxId - 2);
|
|
ValidateRequestIdRange(idRange, maxId - 1, 2);
|
|
|
|
Log("End of TestDnssdRequestIdRange");
|
|
}
|
|
|
|
void TestSrpAdvProxy(void)
|
|
{
|
|
NetworkData::OnMeshPrefixConfig prefixConfig;
|
|
Srp::Server *srpServer;
|
|
Srp::Client *srpClient;
|
|
Srp::AdvertisingProxy *advProxy;
|
|
Srp::Client::Service service1;
|
|
Srp::Client::Service service2;
|
|
DnssdRequestCounts dnssdCounts;
|
|
uint16_t heapAllocations;
|
|
|
|
Log("--------------------------------------------------------------------------------------------");
|
|
Log("TestSrpAdvProxy");
|
|
|
|
InitTest();
|
|
|
|
srpServer = &sInstance->Get<Srp::Server>();
|
|
srpClient = &sInstance->Get<Srp::Client>();
|
|
advProxy = &sInstance->Get<Srp::AdvertisingProxy>();
|
|
|
|
heapAllocations = sHeapAllocatedPtrs.GetLength();
|
|
|
|
PrepareService1(service1);
|
|
PrepareService2(service2);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Add an on-mesh prefix (with SLAAC) to network data");
|
|
|
|
prefixConfig.Clear();
|
|
SuccessOrQuit(AsCoreType(&prefixConfig.mPrefix.mPrefix).FromString("fd00:cafe:beef::"));
|
|
prefixConfig.mPrefix.mLength = 64;
|
|
prefixConfig.mStable = true;
|
|
prefixConfig.mSlaac = true;
|
|
prefixConfig.mPreferred = true;
|
|
prefixConfig.mOnMesh = true;
|
|
prefixConfig.mDefaultRoute = false;
|
|
prefixConfig.mPreference = NetworkData::kRoutePreferenceMedium;
|
|
|
|
SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
|
|
SuccessOrQuit(otBorderRouterRegister(sInstance));
|
|
|
|
// Configure Dnssd platform API behavior
|
|
|
|
sDnssdRegHostRequests.Clear();
|
|
sDnssdRegServiceRequests.Clear();
|
|
sDnssdUnregHostRequests.Clear();
|
|
sDnssdUnregServiceRequests.Clear();
|
|
sDnssdRegKeyRequests.Clear();
|
|
sDnssdUnregKeyRequests.Clear();
|
|
|
|
sDnssdState = OT_PLAT_DNSSD_READY;
|
|
sDnssdShouldCheckWithClient = true;
|
|
sDnssdCallbackError = kErrorNone; // Invoke callback directly from dnssd APIs
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Start SRP server");
|
|
|
|
SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
|
|
|
|
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
|
|
VerifyOrQuit(srpServer->GetAddressMode() == Srp::Server::kAddressModeUnicast);
|
|
|
|
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
|
|
|
|
srpServer->SetServiceHandler(nullptr, sInstance);
|
|
|
|
srpServer->SetEnabled(true);
|
|
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
|
|
|
|
AdvanceTime(10000);
|
|
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
|
|
VerifyOrQuit(advProxy->IsRunning());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Start SRP client");
|
|
|
|
srpClient->SetCallback(HandleSrpClientCallback, sInstance);
|
|
srpClient->SetLeaseInterval(180);
|
|
|
|
srpClient->EnableAutoStartMode(nullptr, nullptr);
|
|
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
|
|
|
|
AdvanceTime(2000);
|
|
VerifyOrQuit(srpClient->IsRunning());
|
|
|
|
SuccessOrQuit(srpClient->SetHostName(kHostName));
|
|
SuccessOrQuit(srpClient->EnableAutoHostAddress());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Register a service");
|
|
|
|
SuccessOrQuit(srpClient->AddService(service1));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(2 * 1000);
|
|
|
|
dnssdCounts.mKeyReg += 2;
|
|
dnssdCounts.mHostReg++;
|
|
dnssdCounts.mServiceReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 1);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 1);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Register a second service");
|
|
|
|
SuccessOrQuit(srpClient->AddService(service2));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(2 * 1000);
|
|
|
|
// This time we should only see the new service and its key being
|
|
// registered as the host is same as before and already registered
|
|
|
|
dnssdCounts.mKeyReg++;
|
|
dnssdCounts.mServiceReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
VerifyOrQuit(service2.GetState() == Srp::Client::kRegistered);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 2);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 2);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Wait for longer than lease interval for client to refresh");
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(181 * 1000);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
|
|
// Validate that adv-proxy does not update any of registration on
|
|
// DNS-SD platform since there is no change.
|
|
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal >= 3);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == advProxy->GetCounters().mAdvTotal);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Add a new on-mesh prefix so to get a new host address");
|
|
|
|
prefixConfig.Clear();
|
|
SuccessOrQuit(AsCoreType(&prefixConfig.mPrefix.mPrefix).FromString("fd00:abba::"));
|
|
prefixConfig.mPrefix.mLength = 64;
|
|
prefixConfig.mStable = true;
|
|
prefixConfig.mSlaac = true;
|
|
prefixConfig.mPreferred = true;
|
|
prefixConfig.mOnMesh = true;
|
|
prefixConfig.mDefaultRoute = false;
|
|
prefixConfig.mPreference = NetworkData::kRoutePreferenceMedium;
|
|
|
|
SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
|
|
SuccessOrQuit(otBorderRouterRegister(sInstance));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(15 * 1000);
|
|
|
|
// This time we should only see new host registration
|
|
// since that's the only thing that changes
|
|
|
|
dnssdCounts.mHostReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
VerifyOrQuit(service2.GetState() == Srp::Client::kRegistered);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Remove the first service on client");
|
|
|
|
SuccessOrQuit(srpClient->RemoveService(service1));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(2 * 1000);
|
|
|
|
// We should see the service being unregistered
|
|
// by advertising proxy on DNS-SD platform but its key
|
|
// remains registered.
|
|
|
|
dnssdCounts.mServiceUnreg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRemoved);
|
|
VerifyOrQuit(service2.GetState() == Srp::Client::kRegistered);
|
|
|
|
// Wait for more than lease interval again and make sure
|
|
// there is no change in DNS-SD platform API calls.
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(181 * 1000);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRemoved);
|
|
VerifyOrQuit(service2.GetState() == Srp::Client::kRegistered);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Change service 2 on client, remove its sub-type");
|
|
|
|
SuccessOrQuit(srpClient->ClearService(service2));
|
|
PrepareService2(service2);
|
|
service2.mSubTypeLabels = nullptr;
|
|
|
|
SuccessOrQuit(srpClient->AddService(service2));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(2 * 1000);
|
|
|
|
// Since the service is now changed, advertising proxy
|
|
// should update it (re-register it) on DNS-SD APIs.
|
|
|
|
dnssdCounts.mServiceReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRemoved);
|
|
VerifyOrQuit(service2.GetState() == Srp::Client::kRegistered);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Remove the host on client");
|
|
|
|
SuccessOrQuit(srpClient->RemoveHostAndServices(/* aShouldRemoveKeyLease */ false));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(2 * 1000);
|
|
|
|
// We should see the host and service being unregistered
|
|
// on DNS-SD APIs but keys remain unchanged.
|
|
|
|
dnssdCounts.mHostUnreg++;
|
|
dnssdCounts.mServiceUnreg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRemoved);
|
|
VerifyOrQuit(service2.GetState() == Srp::Client::kRemoved);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Remove the host on client again and force an update to be sent to server");
|
|
|
|
SuccessOrQuit(srpClient->SetHostName(kHostName));
|
|
SuccessOrQuit(srpClient->RemoveHostAndServices(/* aShouldRemoveKeyLease */ false, /* aSendUnregToServer */ true));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(2 * 1000);
|
|
|
|
// We should see no changes (no calls) to DNS-SD APIs.
|
|
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Re-add service 1 on client and register with server");
|
|
|
|
SuccessOrQuit(srpClient->SetHostName(kHostName));
|
|
SuccessOrQuit(srpClient->EnableAutoHostAddress());
|
|
PrepareService1(service1);
|
|
SuccessOrQuit(srpClient->AddService(service1));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(2 * 1000);
|
|
|
|
// We should see one host register and one service register
|
|
// on DNS-SD APIs. Keys are already registered.
|
|
|
|
dnssdCounts.mHostReg++;
|
|
dnssdCounts.mServiceReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
|
|
// Wait for more than lease interval again and make sure
|
|
// there is no change in DNS-SD platform API calls.
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(181 * 1000);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Disable SRP client and wait for lease time to expire");
|
|
|
|
srpClient->ClearHostAndServices(); // does not signal removal to server
|
|
|
|
// Since we clear everything on SRP client, we disable
|
|
// matching the services with client from `otPlatDnssd`
|
|
// APIs.
|
|
sDnssdShouldCheckWithClient = false;
|
|
|
|
AdvanceTime(181 * 1000);
|
|
|
|
// Make sure host and service are unregistered.
|
|
|
|
dnssdCounts.mHostUnreg++;
|
|
dnssdCounts.mServiceUnreg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Disable SRP server");
|
|
|
|
// Verify that all heap allocations by SRP server
|
|
// and Advertising Proxy are freed.
|
|
|
|
srpServer->SetEnabled(false);
|
|
AdvanceTime(100);
|
|
VerifyOrQuit(!advProxy->IsRunning());
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == advProxy->GetCounters().mAdvTotal);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTimeout == 0);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvRejected == 0);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSkipped == 0);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 0);
|
|
|
|
dnssdCounts.mKeyUnreg += 3;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Finalize OT instance and validate all heap allocations are freed");
|
|
|
|
FinalizeTest();
|
|
|
|
VerifyOrQuit(sHeapAllocatedPtrs.IsEmpty());
|
|
|
|
Log("End of TestSrpAdvProxy");
|
|
}
|
|
|
|
void TestSrpAdvProxyDnssdStateChange(void)
|
|
{
|
|
NetworkData::OnMeshPrefixConfig prefixConfig;
|
|
Srp::Server *srpServer;
|
|
Srp::Client *srpClient;
|
|
Srp::AdvertisingProxy *advProxy;
|
|
Srp::Client::Service service1;
|
|
Srp::Client::Service service2;
|
|
DnssdRequestCounts dnssdCounts;
|
|
uint16_t heapAllocations;
|
|
|
|
Log("--------------------------------------------------------------------------------------------");
|
|
Log("TestSrpAdvProxyDnssdStateChange");
|
|
|
|
InitTest();
|
|
|
|
srpServer = &sInstance->Get<Srp::Server>();
|
|
srpClient = &sInstance->Get<Srp::Client>();
|
|
advProxy = &sInstance->Get<Srp::AdvertisingProxy>();
|
|
|
|
heapAllocations = sHeapAllocatedPtrs.GetLength();
|
|
|
|
PrepareService1(service1);
|
|
PrepareService2(service2);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Add an on-mesh prefix (with SLAAC) to network data");
|
|
|
|
prefixConfig.Clear();
|
|
SuccessOrQuit(AsCoreType(&prefixConfig.mPrefix.mPrefix).FromString("fd00:cafe:beef::"));
|
|
prefixConfig.mPrefix.mLength = 64;
|
|
prefixConfig.mStable = true;
|
|
prefixConfig.mSlaac = true;
|
|
prefixConfig.mPreferred = true;
|
|
prefixConfig.mOnMesh = true;
|
|
prefixConfig.mDefaultRoute = false;
|
|
prefixConfig.mPreference = NetworkData::kRoutePreferenceMedium;
|
|
|
|
SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
|
|
SuccessOrQuit(otBorderRouterRegister(sInstance));
|
|
|
|
// Configure Dnssd platform API behavior
|
|
|
|
sDnssdRegHostRequests.Clear();
|
|
sDnssdRegServiceRequests.Clear();
|
|
sDnssdUnregHostRequests.Clear();
|
|
sDnssdUnregServiceRequests.Clear();
|
|
sDnssdRegKeyRequests.Clear();
|
|
sDnssdUnregKeyRequests.Clear();
|
|
|
|
sDnssdState = OT_PLAT_DNSSD_STOPPED;
|
|
sDnssdShouldCheckWithClient = true;
|
|
sDnssdCallbackError = kErrorNone; // Invoke callback directly
|
|
|
|
VerifyOrQuit(!advProxy->IsRunning());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Start SRP server");
|
|
|
|
SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
|
|
|
|
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
|
|
VerifyOrQuit(srpServer->GetAddressMode() == Srp::Server::kAddressModeUnicast);
|
|
|
|
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
|
|
|
|
srpServer->SetServiceHandler(nullptr, sInstance);
|
|
|
|
srpServer->SetEnabled(true);
|
|
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
|
|
|
|
AdvanceTime(10000);
|
|
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
|
|
VerifyOrQuit(!advProxy->IsRunning());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Start SRP client");
|
|
|
|
srpClient->SetCallback(HandleSrpClientCallback, sInstance);
|
|
srpClient->SetLeaseInterval(180);
|
|
|
|
srpClient->EnableAutoStartMode(nullptr, nullptr);
|
|
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
|
|
|
|
AdvanceTime(2000);
|
|
VerifyOrQuit(srpClient->IsRunning());
|
|
|
|
SuccessOrQuit(srpClient->SetHostName(kHostName));
|
|
SuccessOrQuit(srpClient->EnableAutoHostAddress());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Register a services");
|
|
|
|
SuccessOrQuit(srpClient->AddService(service1));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(2 * 1000);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Register a second service");
|
|
|
|
SuccessOrQuit(srpClient->AddService(service2));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(2 * 1000);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
VerifyOrQuit(service2.GetState() == Srp::Client::kRegistered);
|
|
|
|
// None of the DNS-SD APIs should be called since its state
|
|
// `OT_PLAT_DNSSD_STOPPED` (`dnssdCounts` is all zeros).
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Update DNS-SD state and signal that state is changed");
|
|
|
|
sDnssdState = OT_PLAT_DNSSD_READY;
|
|
otPlatDnssdStateHandleStateChange(sInstance);
|
|
|
|
AdvanceTime(5);
|
|
|
|
VerifyOrQuit(advProxy->IsRunning());
|
|
VerifyOrQuit(advProxy->GetCounters().mStateChanges == 1);
|
|
|
|
// Now the host and two services should be registered on
|
|
// DNS-SD platform
|
|
|
|
dnssdCounts.mHostReg++;
|
|
dnssdCounts.mServiceReg += 2;
|
|
dnssdCounts.mKeyReg += 3;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
VerifyOrQuit(service2.GetState() == Srp::Client::kRegistered);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Wait for longer than lease interval for client to refresh");
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(181 * 1000);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
|
|
// Validate that adv-proxy does not update any of registration on
|
|
// DNS-SD platform since there is no change.
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Update DNS-SD state to `STOPPED` and signal its change");
|
|
|
|
sDnssdState = OT_PLAT_DNSSD_STOPPED;
|
|
otPlatDnssdStateHandleStateChange(sInstance);
|
|
|
|
AdvanceTime(5);
|
|
|
|
VerifyOrQuit(!advProxy->IsRunning());
|
|
VerifyOrQuit(advProxy->GetCounters().mStateChanges == 2);
|
|
|
|
// Since DNS-SD platform signal that it is stopped,
|
|
// there should be no calls to any of APIs.
|
|
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Wait for longer than lease interval for client to refresh");
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(181 * 1000);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
VerifyOrQuit(service2.GetState() == Srp::Client::kRegistered);
|
|
|
|
// The DNS-SD API counters should remain unchanged
|
|
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Update DNS-SD state to `READY` and signal its change");
|
|
|
|
sDnssdState = OT_PLAT_DNSSD_READY;
|
|
otPlatDnssdStateHandleStateChange(sInstance);
|
|
|
|
AdvanceTime(5);
|
|
|
|
VerifyOrQuit(advProxy->IsRunning());
|
|
VerifyOrQuit(advProxy->GetCounters().mStateChanges == 3);
|
|
|
|
// Check that the host and two services are again registered
|
|
// on DNS-SD platform by advertising proxy.
|
|
|
|
dnssdCounts.mHostReg++;
|
|
dnssdCounts.mServiceReg += 2;
|
|
dnssdCounts.mKeyReg += 3;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Update DNS-SD state to `STOPPED` and signal its change");
|
|
|
|
sDnssdState = OT_PLAT_DNSSD_STOPPED;
|
|
otPlatDnssdStateHandleStateChange(sInstance);
|
|
|
|
AdvanceTime(5);
|
|
|
|
VerifyOrQuit(!advProxy->IsRunning());
|
|
VerifyOrQuit(advProxy->GetCounters().mStateChanges == 4);
|
|
|
|
// Since DNS-SD platform signal that it is stopped,
|
|
// there should be no calls to any of APIs.
|
|
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Remove the first service on client");
|
|
|
|
SuccessOrQuit(srpClient->RemoveService(service1));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(2 * 1000);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRemoved);
|
|
VerifyOrQuit(service2.GetState() == Srp::Client::kRegistered);
|
|
|
|
// No changes to DNS-SD API counters (since it is stopped)
|
|
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Update DNS-SD state to `READY` and signal its change #2");
|
|
|
|
// Since the already removed `service1` is no longer available
|
|
// on SRP client, we disable checking the services with client
|
|
// from `otPlatDnssd` APIs.
|
|
sDnssdShouldCheckWithClient = false;
|
|
|
|
sDnssdState = OT_PLAT_DNSSD_READY;
|
|
otPlatDnssdStateHandleStateChange(sInstance);
|
|
|
|
AdvanceTime(5);
|
|
|
|
VerifyOrQuit(advProxy->IsRunning());
|
|
VerifyOrQuit(advProxy->GetCounters().mStateChanges == 5);
|
|
|
|
// We should see the host and `service2` registered again.
|
|
// And all 3 keys (even for removed `service1`) to be
|
|
// registered.
|
|
|
|
dnssdCounts.mHostReg++;
|
|
dnssdCounts.mServiceReg++;
|
|
dnssdCounts.mKeyReg += 3;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Disable SRP server");
|
|
|
|
// Verify that all heap allocations by SRP server
|
|
// and Advertising Proxy are freed.
|
|
|
|
srpServer->SetEnabled(false);
|
|
AdvanceTime(100);
|
|
|
|
VerifyOrQuit(!advProxy->IsRunning());
|
|
VerifyOrQuit(advProxy->GetCounters().mStateChanges == 6);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSkipped > 0);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal ==
|
|
(advProxy->GetCounters().mAdvSuccessful + advProxy->GetCounters().mAdvSkipped));
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTimeout == 0);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvRejected == 0);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 0);
|
|
|
|
dnssdCounts.mHostUnreg++;
|
|
dnssdCounts.mServiceUnreg++;
|
|
dnssdCounts.mKeyUnreg += 3;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Finalize OT instance and validate all heap allocations are freed");
|
|
|
|
FinalizeTest();
|
|
|
|
VerifyOrQuit(sHeapAllocatedPtrs.IsEmpty());
|
|
|
|
Log("End of TestSrpAdvProxyDnssdStateChange");
|
|
}
|
|
|
|
void TestSrpAdvProxyDelayedCallback(void)
|
|
{
|
|
NetworkData::OnMeshPrefixConfig prefixConfig;
|
|
Srp::Server *srpServer;
|
|
Srp::Client *srpClient;
|
|
Srp::AdvertisingProxy *advProxy;
|
|
Srp::Client::Service service1;
|
|
Srp::Client::Service service2;
|
|
DnssdRequestCounts dnssdCounts;
|
|
uint16_t heapAllocations;
|
|
const DnssdRequest *request;
|
|
|
|
Log("--------------------------------------------------------------------------------------------");
|
|
Log("TestSrpAdvProxyDelayedCallback");
|
|
|
|
InitTest();
|
|
|
|
srpServer = &sInstance->Get<Srp::Server>();
|
|
srpClient = &sInstance->Get<Srp::Client>();
|
|
advProxy = &sInstance->Get<Srp::AdvertisingProxy>();
|
|
|
|
heapAllocations = sHeapAllocatedPtrs.GetLength();
|
|
|
|
PrepareService1(service1);
|
|
PrepareService2(service2);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Add an on-mesh prefix (with SLAAC) to network data");
|
|
|
|
prefixConfig.Clear();
|
|
SuccessOrQuit(AsCoreType(&prefixConfig.mPrefix.mPrefix).FromString("fd00:cafe:beef::"));
|
|
prefixConfig.mPrefix.mLength = 64;
|
|
prefixConfig.mStable = true;
|
|
prefixConfig.mSlaac = true;
|
|
prefixConfig.mPreferred = true;
|
|
prefixConfig.mOnMesh = true;
|
|
prefixConfig.mDefaultRoute = false;
|
|
prefixConfig.mPreference = NetworkData::kRoutePreferenceMedium;
|
|
|
|
SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
|
|
SuccessOrQuit(otBorderRouterRegister(sInstance));
|
|
|
|
// Configure Dnssd platform API behavior
|
|
|
|
sDnssdRegHostRequests.Clear();
|
|
sDnssdRegServiceRequests.Clear();
|
|
sDnssdUnregHostRequests.Clear();
|
|
sDnssdUnregServiceRequests.Clear();
|
|
sDnssdRegKeyRequests.Clear();
|
|
sDnssdUnregKeyRequests.Clear();
|
|
|
|
sDnssdState = OT_PLAT_DNSSD_READY;
|
|
sDnssdShouldCheckWithClient = true;
|
|
sDnssdCallbackError = kErrorPending; // Do not call the callbacks directly
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Start SRP server");
|
|
|
|
SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
|
|
|
|
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
|
|
VerifyOrQuit(srpServer->GetAddressMode() == Srp::Server::kAddressModeUnicast);
|
|
|
|
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
|
|
|
|
srpServer->SetServiceHandler(nullptr, sInstance);
|
|
|
|
srpServer->SetEnabled(true);
|
|
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
|
|
|
|
AdvanceTime(10000);
|
|
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
|
|
VerifyOrQuit(advProxy->IsRunning());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Start SRP client");
|
|
|
|
srpClient->SetCallback(HandleSrpClientCallback, sInstance);
|
|
srpClient->SetLeaseInterval(180);
|
|
|
|
srpClient->EnableAutoStartMode(nullptr, nullptr);
|
|
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
|
|
|
|
AdvanceTime(2000);
|
|
VerifyOrQuit(srpClient->IsRunning());
|
|
|
|
SuccessOrQuit(srpClient->SetHostName(kHostName));
|
|
SuccessOrQuit(srpClient->EnableAutoHostAddress());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Register a service, invoke the registration callback after some delay");
|
|
|
|
SuccessOrQuit(srpClient->AddService(service1));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(1000);
|
|
|
|
dnssdCounts.mHostReg++;
|
|
dnssdCounts.mServiceReg++;
|
|
dnssdCounts.mKeyReg += 2;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 1);
|
|
|
|
VerifyOrQuit(!sProcessedClientCallback);
|
|
VerifyOrQuit(srpServer->GetNextHost(nullptr) == nullptr);
|
|
|
|
// Invoke the service and key callbacks first
|
|
request = &sDnssdRegServiceRequests[0];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
request = &sDnssdRegKeyRequests[0];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
request = &sDnssdRegKeyRequests[1];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
AdvanceTime(10);
|
|
VerifyOrQuit(!sProcessedClientCallback);
|
|
VerifyOrQuit(srpServer->GetNextHost(nullptr) == nullptr);
|
|
|
|
// Invoke the host registration callback next
|
|
request = &sDnssdRegHostRequests[0];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
AdvanceTime(10);
|
|
VerifyOrQuit(srpServer->GetNextHost(nullptr) != nullptr);
|
|
|
|
AdvanceTime(100);
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 1);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 1);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Register a second service, invoke registration callback with `kErrorDuplicated`");
|
|
|
|
SuccessOrQuit(srpClient->AddService(service2));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(1000);
|
|
|
|
VerifyOrQuit(!sProcessedClientCallback);
|
|
|
|
dnssdCounts.mServiceReg++;
|
|
dnssdCounts.mKeyReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 2);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 1);
|
|
|
|
// Invoke the service callback with kErrorDuplicated
|
|
|
|
request = &sDnssdRegServiceRequests[1];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorDuplicated);
|
|
|
|
AdvanceTime(100);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorDuplicated);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 2);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 1);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvRejected == 1);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Try registering service again from client, invoke callback with success");
|
|
|
|
SuccessOrQuit(srpClient->ClearService(service2));
|
|
PrepareService2(service2);
|
|
SuccessOrQuit(srpClient->AddService(service2));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(1000);
|
|
|
|
VerifyOrQuit(!sProcessedClientCallback);
|
|
|
|
// We should see a new service registration request.
|
|
|
|
dnssdCounts.mServiceReg++;
|
|
dnssdCounts.mKeyReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 3);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 1);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvRejected == 1);
|
|
|
|
// Invoked the service and key callback with success.
|
|
|
|
request = &sDnssdRegKeyRequests[sDnssdRegKeyRequests.GetLength() - 1];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
request = &sDnssdRegServiceRequests[sDnssdRegServiceRequests.GetLength() - 1];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
AdvanceTime(100);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
VerifyOrQuit(service2.GetState() == Srp::Client::kRegistered);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 3);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 2);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvRejected == 1);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Change the service and register again, but ignore the registration callback");
|
|
|
|
SuccessOrQuit(srpClient->ClearService(service2));
|
|
PrepareService2(service2);
|
|
service2.mSubTypeLabels = nullptr;
|
|
SuccessOrQuit(srpClient->AddService(service2));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(1000);
|
|
|
|
VerifyOrQuit(!sProcessedClientCallback);
|
|
|
|
// We should see a new service registration request.
|
|
|
|
dnssdCounts.mServiceReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
// Wait for advertising proxy timeout (there will be no callback from
|
|
// platform) so validate that registration failure is reported to
|
|
// the SRP client.
|
|
|
|
AdvanceTime(2 * 1000);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError != kErrorNone);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTimeout == 1);
|
|
|
|
// Wait for longer than client retry time.
|
|
|
|
AdvanceTime(3 * 1000);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Disable SRP server");
|
|
|
|
// Verify that all heap allocations by SRP server
|
|
// and Advertising Proxy are freed.
|
|
|
|
srpServer->SetEnabled(false);
|
|
AdvanceTime(100);
|
|
|
|
// Make sure the host and two services are unregistered
|
|
// (even though the second service was not successfully
|
|
// registered yet).
|
|
|
|
VerifyOrQuit(sDnssdRegHostRequests.GetLength() == 1);
|
|
VerifyOrQuit(sDnssdRegServiceRequests.GetLength() >= 4);
|
|
VerifyOrQuit(sDnssdRegKeyRequests.GetLength() >= 3);
|
|
VerifyOrQuit(sDnssdUnregHostRequests.GetLength() == 1);
|
|
VerifyOrQuit(sDnssdUnregServiceRequests.GetLength() == 2);
|
|
VerifyOrQuit(sDnssdUnregKeyRequests.GetLength() == 3);
|
|
|
|
VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Finalize OT instance and validate all heap allocations are freed");
|
|
|
|
FinalizeTest();
|
|
|
|
VerifyOrQuit(sHeapAllocatedPtrs.IsEmpty());
|
|
|
|
Log("End of TestSrpAdvProxyDelayedCallback");
|
|
}
|
|
|
|
void TestSrpAdvProxyReplacedEntries(void)
|
|
{
|
|
NetworkData::OnMeshPrefixConfig prefixConfig;
|
|
Srp::Server *srpServer;
|
|
Srp::Client *srpClient;
|
|
Srp::AdvertisingProxy *advProxy;
|
|
Srp::Client::Service service1;
|
|
Srp::Client::Service service2;
|
|
DnssdRequestCounts dnssdCounts;
|
|
uint16_t heapAllocations;
|
|
const DnssdRequest *request;
|
|
uint16_t numServices;
|
|
|
|
Log("--------------------------------------------------------------------------------------------");
|
|
Log("TestSrpAdvProxyReplacedEntries");
|
|
|
|
InitTest();
|
|
|
|
srpServer = &sInstance->Get<Srp::Server>();
|
|
srpClient = &sInstance->Get<Srp::Client>();
|
|
advProxy = &sInstance->Get<Srp::AdvertisingProxy>();
|
|
|
|
heapAllocations = sHeapAllocatedPtrs.GetLength();
|
|
|
|
PrepareService1(service1);
|
|
PrepareService2(service2);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Add an on-mesh prefix (with SLAAC) to network data");
|
|
|
|
prefixConfig.Clear();
|
|
SuccessOrQuit(AsCoreType(&prefixConfig.mPrefix.mPrefix).FromString("fd00:cafe:beef::"));
|
|
prefixConfig.mPrefix.mLength = 64;
|
|
prefixConfig.mStable = true;
|
|
prefixConfig.mSlaac = true;
|
|
prefixConfig.mPreferred = true;
|
|
prefixConfig.mOnMesh = true;
|
|
prefixConfig.mDefaultRoute = false;
|
|
prefixConfig.mPreference = NetworkData::kRoutePreferenceMedium;
|
|
|
|
SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
|
|
SuccessOrQuit(otBorderRouterRegister(sInstance));
|
|
|
|
// Configure Dnssd platform API behavior
|
|
|
|
sDnssdRegHostRequests.Clear();
|
|
sDnssdRegServiceRequests.Clear();
|
|
sDnssdUnregHostRequests.Clear();
|
|
sDnssdUnregServiceRequests.Clear();
|
|
sDnssdRegKeyRequests.Clear();
|
|
sDnssdUnregKeyRequests.Clear();
|
|
|
|
sDnssdState = OT_PLAT_DNSSD_READY;
|
|
sDnssdShouldCheckWithClient = true;
|
|
sDnssdCallbackError = kErrorPending; // Do not call the callbacks directly
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Start SRP server");
|
|
|
|
SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
|
|
|
|
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
|
|
VerifyOrQuit(srpServer->GetAddressMode() == Srp::Server::kAddressModeUnicast);
|
|
|
|
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
|
|
|
|
srpServer->SetServiceHandler(nullptr, sInstance);
|
|
|
|
srpServer->SetEnabled(true);
|
|
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
|
|
|
|
AdvanceTime(10000);
|
|
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
|
|
VerifyOrQuit(advProxy->IsRunning());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Set AdvTimeout to 5 minutes on AdvProxy");
|
|
|
|
// Change the timeout on AvdertisingProxy to 5 minutes
|
|
// so that we can send multiple SRP updates and create
|
|
// situations where previous advertisement are replaced.
|
|
|
|
advProxy->SetAdvTimeout(5 * 60 * 1000);
|
|
VerifyOrQuit(advProxy->GetAdvTimeout() == 5 * 60 * 1000);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Start SRP client");
|
|
|
|
srpClient->SetCallback(HandleSrpClientCallback, sInstance);
|
|
|
|
srpClient->EnableAutoStartMode(nullptr, nullptr);
|
|
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
|
|
|
|
AdvanceTime(2000);
|
|
VerifyOrQuit(srpClient->IsRunning());
|
|
|
|
SuccessOrQuit(srpClient->SetHostName(kHostName));
|
|
SuccessOrQuit(srpClient->EnableAutoHostAddress());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Register a service and do not invoke the registration request callbacks");
|
|
|
|
SuccessOrQuit(srpClient->AddService(service1));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(1200);
|
|
|
|
dnssdCounts.mHostReg++;
|
|
dnssdCounts.mServiceReg++;
|
|
dnssdCounts.mKeyReg += 2;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 1);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 0);
|
|
|
|
VerifyOrQuit(!sProcessedClientCallback);
|
|
VerifyOrQuit(srpServer->GetNextHost(nullptr) == nullptr);
|
|
|
|
// SRP client min retry is 1800 msec, we wait for longer
|
|
// to make sure client retries.
|
|
|
|
AdvanceTime(2000);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 2);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 0);
|
|
|
|
// We should see no new service or host registrations on
|
|
// DNS-SD platform APIs as the requests should be same
|
|
// and fully matching the outstanding ones.
|
|
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Invoke the DNS-SD API callbacks");
|
|
|
|
request = &sDnssdRegServiceRequests[0];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
request = &sDnssdRegHostRequests[0];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
for (uint16_t index = 0; index < 2; index++)
|
|
{
|
|
request = &sDnssdRegKeyRequests[index];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
}
|
|
|
|
AdvanceTime(100);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
VerifyOrQuit(srpServer->GetNextHost(nullptr) != nullptr);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 2);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 2);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 0);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Check outstanding Adv being replaced");
|
|
|
|
// Change service 1
|
|
SuccessOrQuit(srpClient->ClearService(service1));
|
|
PrepareService1(service1);
|
|
service1.mSubTypeLabels = nullptr; // No sub-types
|
|
SuccessOrQuit(srpClient->AddService(service1));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(1200);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 3);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 2);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 0);
|
|
|
|
// We should see the changed service registered on DNS-SD
|
|
// platform APIs.
|
|
|
|
dnssdCounts.mServiceReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
// Change service 1 again (add sub-types back).
|
|
SuccessOrQuit(srpClient->ClearService(service1));
|
|
PrepareService1(service1);
|
|
SuccessOrQuit(srpClient->AddService(service1));
|
|
|
|
AdvanceTime(1200);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 4);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 2);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 1);
|
|
|
|
// We should see the changed service registered on DNS-SD
|
|
// platform APIs again.
|
|
|
|
dnssdCounts.mServiceReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Invoke the replaced entry DNS-SD API callback");
|
|
|
|
request = &sDnssdRegServiceRequests[1];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
AdvanceTime(100);
|
|
|
|
// Since adv is replaced invoking the old registration callback
|
|
// should not complete it.
|
|
|
|
VerifyOrQuit(!sProcessedClientCallback);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 4);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 2);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 1);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Invoke the new entry DNS-SD API callback");
|
|
|
|
request = &sDnssdRegServiceRequests[2];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
AdvanceTime(100);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 4);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 4);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 1);
|
|
|
|
// Make sure the service entry on the SRP server is the
|
|
// last (most recent) request with three sub-types
|
|
|
|
VerifyOrQuit(srpServer->GetNextHost(nullptr)->GetServices().GetHead() != nullptr);
|
|
VerifyOrQuit(srpServer->GetNextHost(nullptr)->GetServices().GetHead()->GetNumberOfSubTypes() == 3);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Check replacing Adv being blocked till old Adv is completed");
|
|
|
|
// Change service 1 and add service 2
|
|
SuccessOrQuit(srpClient->ClearService(service1));
|
|
PrepareService1(service1);
|
|
service1.mSubTypeLabels = nullptr; // No sub-types
|
|
SuccessOrQuit(srpClient->AddService(service1));
|
|
SuccessOrQuit(srpClient->AddService(service2));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(1200);
|
|
|
|
// We should see a new Adv with two new service registrations
|
|
// on DNS-SD APIs.
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 5);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 4);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 1);
|
|
|
|
dnssdCounts.mServiceReg += 2;
|
|
dnssdCounts.mKeyReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
// Invoke the key registration callback
|
|
|
|
request = &sDnssdRegKeyRequests[sDnssdRegKeyRequests.GetLength() - 1];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
// Now have SRP client send a new SRP update message
|
|
// just changing `service2`. We clear `servcie1` on client
|
|
// so it is not included in new SRP update message.
|
|
|
|
SuccessOrQuit(srpClient->ClearService(service1));
|
|
SuccessOrQuit(srpClient->ClearService(service2));
|
|
PrepareService2(service2);
|
|
service2.mPort = 2222; // Use a different port number
|
|
SuccessOrQuit(srpClient->AddService(service2));
|
|
|
|
AdvanceTime(1200);
|
|
|
|
// We should see the new Adv (total increasing) and
|
|
// also replacing the outstanding one
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 6);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 4);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 2);
|
|
|
|
// We should see new registration for the changed `service2`
|
|
|
|
dnssdCounts.mServiceReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Invoke the callback for new registration replacing old one first");
|
|
|
|
request = &sDnssdRegServiceRequests[5];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
AdvanceTime(100);
|
|
|
|
// This should not change anything, since the new Avd should
|
|
// be still blocked by the earlier Adv that it replaced.
|
|
|
|
VerifyOrQuit(!sProcessedClientCallback);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 6);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 4);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 2);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Invoke the callback for replaced Adv services");
|
|
|
|
request = &sDnssdRegServiceRequests[4];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
request = &sDnssdRegServiceRequests[3];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
AdvanceTime(100);
|
|
|
|
// This should trigger both Adv to complete.
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 6);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 6);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 2);
|
|
|
|
VerifyOrQuit(service2.GetState() == Srp::Client::kRegistered);
|
|
|
|
// Make sure the `service2` entry on the SRP server is the
|
|
// last (most recent) request with new port number.
|
|
|
|
VerifyOrQuit(srpServer->GetNextHost(nullptr)->GetServices().GetHead() != nullptr);
|
|
|
|
numServices = 0;
|
|
|
|
for (const Srp::Server::Service &service : srpServer->GetNextHost(nullptr)->GetServices())
|
|
{
|
|
numServices++;
|
|
|
|
if (StringMatch(service.GetInstanceLabel(), service2.GetInstanceName(), kStringCaseInsensitiveMatch))
|
|
{
|
|
VerifyOrQuit(service.GetPort() == service2.GetPort());
|
|
}
|
|
else if (StringMatch(service.GetInstanceLabel(), service1.GetInstanceName(), kStringCaseInsensitiveMatch))
|
|
{
|
|
// Service 1 was changed to have no sub-types
|
|
VerifyOrQuit(service.GetPort() == service1.GetPort());
|
|
VerifyOrQuit(service.GetNumberOfSubTypes() == 0);
|
|
}
|
|
else
|
|
{
|
|
VerifyOrQuit(false); // Unexpected extra service on SRP server.
|
|
}
|
|
}
|
|
|
|
VerifyOrQuit(numServices == 2);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Check replacing Adv being blocked till old Adv is completed when removing services");
|
|
|
|
// Change and re-add both services so they are both
|
|
// included in a new SRP update message from client.
|
|
|
|
SuccessOrQuit(srpClient->ClearService(service2));
|
|
PrepareService1(service1);
|
|
PrepareService2(service2);
|
|
SuccessOrQuit(srpClient->AddService(service1));
|
|
SuccessOrQuit(srpClient->AddService(service2));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(1200);
|
|
|
|
// We should see a new Adv with two new service registrations
|
|
// on DNS-SD APIs.
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 7);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 6);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 2);
|
|
|
|
dnssdCounts.mServiceReg += 2;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
// Now have SRP client send a new SRP update message
|
|
// just removing `service1`. We clear `servcie2` on client
|
|
// so it is not included in new SRP update message.
|
|
|
|
SuccessOrQuit(srpClient->RemoveService(service1));
|
|
SuccessOrQuit(srpClient->ClearService(service2));
|
|
|
|
AdvanceTime(1200);
|
|
|
|
// We should see a new Adv added replacing the outstanding
|
|
// one.
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 8);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 6);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 3);
|
|
|
|
dnssdCounts.mServiceUnreg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
// Even though the new SRP update which removed `servcie2`
|
|
// is already unregistered, it should be blocked by the
|
|
// earlier Adv.
|
|
|
|
VerifyOrQuit(!sProcessedClientCallback);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Invoke the callback for replaced Adv services");
|
|
|
|
request = &sDnssdRegServiceRequests[6];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
request = &sDnssdRegServiceRequests[7];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
AdvanceTime(100);
|
|
|
|
// This should trigger both Adv to complete, and first one
|
|
// should be committed before the second one removing the
|
|
// `service2`.
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 8);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 8);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 3);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRemoved);
|
|
|
|
// Check services on server and make sure `service2`
|
|
// is marked as deleted.
|
|
|
|
VerifyOrQuit(srpServer->GetNextHost(nullptr)->GetServices().GetHead() != nullptr);
|
|
|
|
numServices = 0;
|
|
|
|
for (const Srp::Server::Service &service : srpServer->GetNextHost(nullptr)->GetServices())
|
|
{
|
|
numServices++;
|
|
|
|
if (StringMatch(service.GetInstanceLabel(), service1.GetInstanceName(), kStringCaseInsensitiveMatch))
|
|
{
|
|
VerifyOrQuit(service.IsDeleted());
|
|
}
|
|
else if (StringMatch(service.GetInstanceLabel(), service2.GetInstanceName(), kStringCaseInsensitiveMatch))
|
|
{
|
|
VerifyOrQuit(!service.IsDeleted());
|
|
}
|
|
else
|
|
{
|
|
VerifyOrQuit(false); // Unexpected extra service on SRP server.
|
|
}
|
|
}
|
|
|
|
VerifyOrQuit(numServices == 2);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Disable SRP server");
|
|
|
|
sDnssdShouldCheckWithClient = false;
|
|
|
|
// Verify that all heap allocations by SRP server
|
|
// and Advertising Proxy are freed.
|
|
|
|
srpServer->SetEnabled(false);
|
|
AdvanceTime(100);
|
|
|
|
VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Finalize OT instance and validate all heap allocations are freed");
|
|
|
|
FinalizeTest();
|
|
|
|
VerifyOrQuit(sHeapAllocatedPtrs.IsEmpty());
|
|
|
|
Log("End of TestSrpAdvProxyReplacedEntries");
|
|
}
|
|
|
|
void TestSrpAdvProxyHostWithOffMeshRoutableAddress(void)
|
|
{
|
|
NetworkData::OnMeshPrefixConfig prefixConfig;
|
|
Srp::Server *srpServer;
|
|
Srp::Client *srpClient;
|
|
Srp::AdvertisingProxy *advProxy;
|
|
Srp::Client::Service service1;
|
|
Srp::Client::Service service2;
|
|
DnssdRequestCounts dnssdCounts;
|
|
uint16_t heapAllocations;
|
|
const DnssdRequest *request;
|
|
|
|
Log("--------------------------------------------------------------------------------------------");
|
|
Log("TestSrpAdvProxyHostWithOffMeshRoutableAddress");
|
|
|
|
InitTest();
|
|
|
|
srpServer = &sInstance->Get<Srp::Server>();
|
|
srpClient = &sInstance->Get<Srp::Client>();
|
|
advProxy = &sInstance->Get<Srp::AdvertisingProxy>();
|
|
|
|
heapAllocations = sHeapAllocatedPtrs.GetLength();
|
|
|
|
PrepareService1(service1);
|
|
PrepareService2(service2);
|
|
|
|
// Configure Dnssd platform API behavior
|
|
|
|
sDnssdRegHostRequests.Clear();
|
|
sDnssdRegServiceRequests.Clear();
|
|
sDnssdUnregHostRequests.Clear();
|
|
sDnssdUnregServiceRequests.Clear();
|
|
sDnssdRegKeyRequests.Clear();
|
|
sDnssdUnregKeyRequests.Clear();
|
|
|
|
sDnssdState = OT_PLAT_DNSSD_READY;
|
|
sDnssdShouldCheckWithClient = true;
|
|
sDnssdCallbackError = kErrorNone; // Invoke callback directly from dnssd APIs
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Start SRP server");
|
|
|
|
SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
|
|
|
|
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
|
|
VerifyOrQuit(srpServer->GetAddressMode() == Srp::Server::kAddressModeUnicast);
|
|
|
|
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
|
|
|
|
srpServer->SetServiceHandler(nullptr, sInstance);
|
|
|
|
srpServer->SetEnabled(true);
|
|
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
|
|
|
|
AdvanceTime(10000);
|
|
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
|
|
VerifyOrQuit(advProxy->IsRunning());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Start SRP client");
|
|
|
|
srpClient->SetCallback(HandleSrpClientCallback, sInstance);
|
|
srpClient->SetLeaseInterval(400);
|
|
|
|
srpClient->EnableAutoStartMode(nullptr, nullptr);
|
|
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
|
|
|
|
AdvanceTime(2000);
|
|
VerifyOrQuit(srpClient->IsRunning());
|
|
|
|
SuccessOrQuit(srpClient->SetHostName(kHostName));
|
|
SuccessOrQuit(srpClient->EnableAutoHostAddress());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Register a service");
|
|
|
|
SuccessOrQuit(srpClient->AddService(service1));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(2 * 1000);
|
|
|
|
dnssdCounts.mHostReg++;
|
|
dnssdCounts.mServiceReg++;
|
|
dnssdCounts.mKeyReg += 2;
|
|
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
VerifyOrQuit(sDnssdNumHostAddresses == 0);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 1);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 1);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Register a second service");
|
|
|
|
SuccessOrQuit(srpClient->AddService(service2));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(2 * 1000);
|
|
|
|
dnssdCounts.mServiceReg++;
|
|
dnssdCounts.mKeyReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
VerifyOrQuit(service2.GetState() == Srp::Client::kRegistered);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 2);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 2);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Disable SRP server");
|
|
|
|
// Verify that all heap allocations by SRP server
|
|
// and Advertising Proxy are freed.
|
|
|
|
srpServer->SetEnabled(false);
|
|
AdvanceTime(100);
|
|
VerifyOrQuit(!advProxy->IsRunning());
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == advProxy->GetCounters().mAdvTotal);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTimeout == 0);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvRejected == 0);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSkipped == 0);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 0);
|
|
|
|
VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Finalize OT instance and validate all heap allocations are freed");
|
|
|
|
FinalizeTest();
|
|
|
|
VerifyOrQuit(sHeapAllocatedPtrs.IsEmpty());
|
|
|
|
Log("End of TestSrpAdvProxyHostWithOffMeshRoutableAddress");
|
|
}
|
|
|
|
void TestSrpAdvProxyRemoveBeforeCommitted(void)
|
|
{
|
|
NetworkData::OnMeshPrefixConfig prefixConfig;
|
|
Srp::Server *srpServer;
|
|
Srp::Client *srpClient;
|
|
Srp::AdvertisingProxy *advProxy;
|
|
Srp::Client::Service service1;
|
|
Srp::Client::Service service2;
|
|
DnssdRequestCounts dnssdCounts;
|
|
uint16_t heapAllocations;
|
|
const DnssdRequest *request;
|
|
|
|
Log("--------------------------------------------------------------------------------------------");
|
|
Log("TestSrpAdvProxyRemoveBeforeCommitted");
|
|
|
|
InitTest();
|
|
|
|
srpServer = &sInstance->Get<Srp::Server>();
|
|
srpClient = &sInstance->Get<Srp::Client>();
|
|
advProxy = &sInstance->Get<Srp::AdvertisingProxy>();
|
|
|
|
heapAllocations = sHeapAllocatedPtrs.GetLength();
|
|
|
|
PrepareService1(service1);
|
|
PrepareService2(service2);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Add an on-mesh prefix (with SLAAC) to network data");
|
|
|
|
prefixConfig.Clear();
|
|
SuccessOrQuit(AsCoreType(&prefixConfig.mPrefix.mPrefix).FromString("fd00:cafe:beef::"));
|
|
prefixConfig.mPrefix.mLength = 64;
|
|
prefixConfig.mStable = true;
|
|
prefixConfig.mSlaac = true;
|
|
prefixConfig.mPreferred = true;
|
|
prefixConfig.mOnMesh = true;
|
|
prefixConfig.mDefaultRoute = false;
|
|
prefixConfig.mPreference = NetworkData::kRoutePreferenceMedium;
|
|
|
|
SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
|
|
SuccessOrQuit(otBorderRouterRegister(sInstance));
|
|
|
|
// Configure Dnssd platform API behavior
|
|
|
|
sDnssdRegHostRequests.Clear();
|
|
sDnssdRegServiceRequests.Clear();
|
|
sDnssdUnregHostRequests.Clear();
|
|
sDnssdUnregServiceRequests.Clear();
|
|
sDnssdRegKeyRequests.Clear();
|
|
sDnssdUnregKeyRequests.Clear();
|
|
|
|
sDnssdState = OT_PLAT_DNSSD_READY;
|
|
sDnssdShouldCheckWithClient = true;
|
|
sDnssdCallbackError = kErrorNone; // Do not call the callbacks directly
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Start SRP server");
|
|
|
|
SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
|
|
|
|
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
|
|
VerifyOrQuit(srpServer->GetAddressMode() == Srp::Server::kAddressModeUnicast);
|
|
|
|
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
|
|
|
|
srpServer->SetServiceHandler(nullptr, sInstance);
|
|
|
|
srpServer->SetEnabled(true);
|
|
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
|
|
|
|
AdvanceTime(10000);
|
|
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
|
|
VerifyOrQuit(advProxy->IsRunning());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Start SRP client");
|
|
|
|
srpClient->SetCallback(HandleSrpClientCallback, sInstance);
|
|
|
|
srpClient->EnableAutoStartMode(nullptr, nullptr);
|
|
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
|
|
|
|
AdvanceTime(2000);
|
|
VerifyOrQuit(srpClient->IsRunning());
|
|
|
|
SuccessOrQuit(srpClient->SetHostName(kHostName));
|
|
SuccessOrQuit(srpClient->EnableAutoHostAddress());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Register host and one service");
|
|
|
|
SuccessOrQuit(srpClient->AddService(service1));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(2000);
|
|
|
|
dnssdCounts.mHostReg++;
|
|
dnssdCounts.mServiceReg++;
|
|
dnssdCounts.mKeyReg += 2;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 1);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 1);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 0);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Set AdvTimeout to 5 minutes on AdvProxy");
|
|
|
|
// Change the timeout on AvdertisingProxy to 5 minutes
|
|
// so that we can send multiple SRP updates and create
|
|
// situations where previous advertisement are replaced.
|
|
|
|
advProxy->SetAdvTimeout(5 * 60 * 1000);
|
|
VerifyOrQuit(advProxy->GetAdvTimeout() == 5 * 60 * 1000);
|
|
|
|
sDnssdCallbackError = kErrorPending; // Do not invoke callback
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Remove service1 while adding a new service2 and do not invoke callback from DNSSD plat");
|
|
|
|
SuccessOrQuit(srpClient->RemoveService(service1));
|
|
SuccessOrQuit(srpClient->AddService(service2));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(1000);
|
|
|
|
dnssdCounts.mServiceReg++;
|
|
dnssdCounts.mServiceUnreg++;
|
|
dnssdCounts.mKeyReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 2);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 1);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 0);
|
|
|
|
VerifyOrQuit(!sProcessedClientCallback);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Remove host and its services without removing key-lease");
|
|
|
|
SuccessOrQuit(srpClient->RemoveHostAndServices(/* aShouldRemoveKeyLease */ false));
|
|
|
|
AdvanceTime(1000);
|
|
|
|
// Proxy will unregister both services again
|
|
// (to be safe).
|
|
|
|
dnssdCounts.mHostUnreg++;
|
|
dnssdCounts.mServiceUnreg++;
|
|
VerifyDnnsdRequests(dnssdCounts, /* aAllowMoreUnregs */ true);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 3);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 1);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 1);
|
|
|
|
VerifyOrQuit(!sProcessedClientCallback);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Invoke callback for last key registration");
|
|
|
|
// This should be enough for all `AdvInfo` entries to be finished.
|
|
|
|
request = &sDnssdRegKeyRequests[sDnssdRegKeyRequests.GetLength() - 1];
|
|
VerifyOrQuit(request->mCallback != nullptr);
|
|
request->mCallback(sInstance, request->mId, kErrorNone);
|
|
|
|
AdvanceTime(50);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 3);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 3);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 1);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Disable SRP server");
|
|
|
|
sDnssdShouldCheckWithClient = false;
|
|
|
|
// Verify that all heap allocations by SRP server
|
|
// and Advertising Proxy are freed.
|
|
|
|
srpServer->SetEnabled(false);
|
|
AdvanceTime(100);
|
|
|
|
VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Finalize OT instance and validate all heap allocations are freed");
|
|
|
|
FinalizeTest();
|
|
|
|
VerifyOrQuit(sHeapAllocatedPtrs.IsEmpty());
|
|
|
|
Log("End of TestSrpAdvProxyRemoveBeforeCommitted");
|
|
}
|
|
|
|
void TestSrpAdvProxyFullyRemoveBeforeCommitted(void)
|
|
{
|
|
NetworkData::OnMeshPrefixConfig prefixConfig;
|
|
Srp::Server *srpServer;
|
|
Srp::Client *srpClient;
|
|
Srp::AdvertisingProxy *advProxy;
|
|
Srp::Client::Service service1;
|
|
Srp::Client::Service service2;
|
|
DnssdRequestCounts dnssdCounts;
|
|
uint16_t heapAllocations;
|
|
const DnssdRequest *request;
|
|
|
|
Log("--------------------------------------------------------------------------------------------");
|
|
Log("TestSrpAdvProxyFullyRemoveBeforeCommitted");
|
|
|
|
InitTest();
|
|
|
|
srpServer = &sInstance->Get<Srp::Server>();
|
|
srpClient = &sInstance->Get<Srp::Client>();
|
|
advProxy = &sInstance->Get<Srp::AdvertisingProxy>();
|
|
|
|
heapAllocations = sHeapAllocatedPtrs.GetLength();
|
|
|
|
PrepareService1(service1);
|
|
PrepareService2(service2);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Add an on-mesh prefix (with SLAAC) to network data");
|
|
|
|
prefixConfig.Clear();
|
|
SuccessOrQuit(AsCoreType(&prefixConfig.mPrefix.mPrefix).FromString("fd00:cafe:beef::"));
|
|
prefixConfig.mPrefix.mLength = 64;
|
|
prefixConfig.mStable = true;
|
|
prefixConfig.mSlaac = true;
|
|
prefixConfig.mPreferred = true;
|
|
prefixConfig.mOnMesh = true;
|
|
prefixConfig.mDefaultRoute = false;
|
|
prefixConfig.mPreference = NetworkData::kRoutePreferenceMedium;
|
|
|
|
SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
|
|
SuccessOrQuit(otBorderRouterRegister(sInstance));
|
|
|
|
// Configure Dnssd platform API behavior
|
|
|
|
sDnssdRegHostRequests.Clear();
|
|
sDnssdRegServiceRequests.Clear();
|
|
sDnssdUnregHostRequests.Clear();
|
|
sDnssdUnregServiceRequests.Clear();
|
|
sDnssdRegKeyRequests.Clear();
|
|
sDnssdUnregKeyRequests.Clear();
|
|
|
|
sDnssdState = OT_PLAT_DNSSD_READY;
|
|
sDnssdShouldCheckWithClient = true;
|
|
sDnssdCallbackError = kErrorNone; // Do not call the callbacks directly
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Start SRP server");
|
|
|
|
SuccessOrQuit(otBorderRoutingInit(sInstance, /* aInfraIfIndex */ kInfraIfIndex, /* aInfraIfIsRunning */ true));
|
|
|
|
SuccessOrQuit(srpServer->SetAddressMode(Srp::Server::kAddressModeUnicast));
|
|
VerifyOrQuit(srpServer->GetAddressMode() == Srp::Server::kAddressModeUnicast);
|
|
|
|
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateDisabled);
|
|
|
|
srpServer->SetServiceHandler(nullptr, sInstance);
|
|
|
|
srpServer->SetEnabled(true);
|
|
VerifyOrQuit(srpServer->GetState() != Srp::Server::kStateDisabled);
|
|
|
|
AdvanceTime(10000);
|
|
VerifyOrQuit(srpServer->GetState() == Srp::Server::kStateRunning);
|
|
VerifyOrQuit(advProxy->IsRunning());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Start SRP client");
|
|
|
|
srpClient->SetCallback(HandleSrpClientCallback, sInstance);
|
|
|
|
srpClient->EnableAutoStartMode(nullptr, nullptr);
|
|
VerifyOrQuit(srpClient->IsAutoStartModeEnabled());
|
|
|
|
AdvanceTime(2000);
|
|
VerifyOrQuit(srpClient->IsRunning());
|
|
|
|
SuccessOrQuit(srpClient->SetHostName(kHostName));
|
|
SuccessOrQuit(srpClient->EnableAutoHostAddress());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Register host and one service");
|
|
|
|
SuccessOrQuit(srpClient->AddService(service1));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(2000);
|
|
|
|
dnssdCounts.mHostReg++;
|
|
dnssdCounts.mServiceReg++;
|
|
dnssdCounts.mKeyReg += 2;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 1);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 1);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 0);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
VerifyOrQuit(sLastClientCallbackError == kErrorNone);
|
|
|
|
VerifyOrQuit(service1.GetState() == Srp::Client::kRegistered);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Set AdvTimeout to 5 minutes on AdvProxy");
|
|
|
|
// Change the timeout on AvdertisingProxy to 5 minutes
|
|
// so that we can send multiple SRP updates and create
|
|
// situations where previous advertisement are replaced.
|
|
|
|
advProxy->SetAdvTimeout(5 * 60 * 1000);
|
|
VerifyOrQuit(advProxy->GetAdvTimeout() == 5 * 60 * 1000);
|
|
|
|
sDnssdCallbackError = kErrorPending; // Do not invoke callback
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Remove service1 while adding a new service2 and do not invoke callback from DNSSD plat");
|
|
|
|
SuccessOrQuit(srpClient->RemoveService(service1));
|
|
SuccessOrQuit(srpClient->AddService(service2));
|
|
|
|
sProcessedClientCallback = false;
|
|
|
|
AdvanceTime(1000);
|
|
|
|
dnssdCounts.mServiceReg++;
|
|
dnssdCounts.mServiceUnreg++;
|
|
dnssdCounts.mKeyReg++;
|
|
VerifyDnnsdRequests(dnssdCounts);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 2);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 1);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 0);
|
|
|
|
VerifyOrQuit(!sProcessedClientCallback);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Remove host and its services and remove key-lease");
|
|
|
|
SuccessOrQuit(srpClient->RemoveHostAndServices(/* aShouldRemoveKeyLease */ true));
|
|
|
|
AdvanceTime(1000);
|
|
|
|
// Proxy should unregister everything.
|
|
// Keys may be unregistered multiple times.
|
|
|
|
dnssdCounts.mHostUnreg++;
|
|
dnssdCounts.mServiceUnreg++;
|
|
dnssdCounts.mKeyUnreg += 3;
|
|
VerifyDnnsdRequests(dnssdCounts, /* aAllowMoreUnregs */ true);
|
|
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvTotal == 3);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvSuccessful == 3);
|
|
VerifyOrQuit(advProxy->GetCounters().mAdvReplaced == 1);
|
|
|
|
VerifyOrQuit(sProcessedClientCallback);
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Disable SRP server");
|
|
|
|
sDnssdShouldCheckWithClient = false;
|
|
|
|
// Verify that all heap allocations by SRP server
|
|
// and Advertising Proxy are freed.
|
|
|
|
srpServer->SetEnabled(false);
|
|
AdvanceTime(100);
|
|
|
|
VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
|
|
|
|
Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
|
|
Log("Finalize OT instance and validate all heap allocations are freed");
|
|
|
|
FinalizeTest();
|
|
|
|
VerifyOrQuit(sHeapAllocatedPtrs.IsEmpty());
|
|
|
|
Log("End of TestSrpAdvProxyFullyRemoveBeforeCommitted");
|
|
}
|
|
|
|
#endif // ENABLE_ADV_PROXY_TEST
|
|
|
|
int main(void)
|
|
{
|
|
#if ENABLE_ADV_PROXY_TEST
|
|
TestDnssdRequestIdRange();
|
|
TestSrpAdvProxy();
|
|
TestSrpAdvProxyDnssdStateChange();
|
|
TestSrpAdvProxyDelayedCallback();
|
|
TestSrpAdvProxyReplacedEntries();
|
|
TestSrpAdvProxyHostWithOffMeshRoutableAddress();
|
|
TestSrpAdvProxyRemoveBeforeCommitted();
|
|
TestSrpAdvProxyFullyRemoveBeforeCommitted();
|
|
|
|
printf("All tests passed\n");
|
|
#else
|
|
printf("SRP_ADV_PROXY feature is not enabled\n");
|
|
#endif
|
|
|
|
return 0;
|
|
}
|