mirror of
https://github.com/espressif/openthread.git
synced 2026-08-04 09:57:47 +00:00
[srp-server] support address modes & sharing of socket with DNS-SD (#6826)
This commit updates `Srp::Server` to add support for selecting its address mode (unicast or anycast). The address mode specifies how the SRP server determines its address and port number and how this info is published in Thread Network Data. In anycast address mode, the SRP server will use port number 53 which is also used by DNS resolver/server. So if both `Srp::Server` and `Dns::ServiceDiscovery::Server` are enabled on a device, they both need to listen on the same port number and share the same UDP socket instance. This commit adds the mechanism in the code to realize this. The `Srp::Server` will monitor when/if DNS-SD is active and checks whether the port numbers match and if so it will close its own socket and re-use the one from DNS-SD. In this case, an incoming UDP message is first given to `Srp::Server` to process and if it fails to process it then the message is given to DNS-SD. This commit also adds CLI commands under `srp server` to get/set the address mode (and update the `README_SRP_SERVER.md` documentation). It also adds a new test `test_srp_server_anycast_mode` which covers the SRP server address mode and the newly added behaviors.
This commit is contained in:
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (160)
|
||||
#define OPENTHREAD_API_VERSION (161)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -142,6 +142,19 @@ typedef enum
|
||||
OT_SRP_SERVER_STATE_STOPPED = 2, ///< The SRP server is stopped.
|
||||
} otSrpServerState;
|
||||
|
||||
/**
|
||||
* This enumeration represents the address mode used by the SRP server.
|
||||
*
|
||||
* Address mode specifies how the address and port number are determined by the SRP server and how this info is
|
||||
* published in the Thread Network Data.
|
||||
*
|
||||
*/
|
||||
typedef enum otSrpServerAddressMode
|
||||
{
|
||||
OT_SRP_SREVER_ADDRESS_MODE_UNICAST = 0, ///< Unicast address mode.
|
||||
OT_SRP_SERVER_ADDRESS_MODE_ANYCAST = 1, ///< Anycast address mode.
|
||||
} otSrpServerAddressMode;
|
||||
|
||||
/**
|
||||
* This structure includes SRP server LEASE and KEY-LEASE configurations.
|
||||
*
|
||||
@@ -194,6 +207,52 @@ otError otSrpServerSetDomain(otInstance *aInstance, const char *aDomain);
|
||||
*/
|
||||
otSrpServerState otSrpServerGetState(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* This function returns the address mode being used by the SRP server.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @returns The SRP server's address mode.
|
||||
*
|
||||
*/
|
||||
otSrpServerAddressMode otSrpServerGetAddressMode(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* This function sets the address mode to be used by the SRP server.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aMode The address mode to use.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully set the address mode.
|
||||
* @retval OT_ERROR_INVALID_STATE The SRP server is enabled and the address mode cannot be changed.
|
||||
*
|
||||
*/
|
||||
otError otSrpServerSetAddressMode(otInstance *aInstance, otSrpServerAddressMode aMode);
|
||||
|
||||
/**
|
||||
* This function returns the sequence number used with anycast address mode.
|
||||
*
|
||||
* The sequence number is included in "DNS/SRP Service Anycast Address" entry published in the Network Data.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @returns The anycast sequence number.
|
||||
*
|
||||
*/
|
||||
uint8_t otSrpServerGetAnycastModeSequenceNumber(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* This function sets the sequence number used with anycast address mode.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aSequenceNumber The sequence number to use.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully set the address mode.
|
||||
* @retval OT_ERROR_INVALID_STATE The SRP server is enabled and the sequence number cannot be changed.
|
||||
*
|
||||
*/
|
||||
otError otSrpServerSetAnycastModeSequenceNumber(otInstance *aInstance, uint8_t aSequenceNumber);
|
||||
|
||||
/**
|
||||
* This function enables/disables the SRP server.
|
||||
*
|
||||
|
||||
@@ -7,11 +7,13 @@ See [README_SRP.md](README_SRP.md).
|
||||
## Command List
|
||||
|
||||
- [help](#help)
|
||||
- [addrmode](#addrmode)
|
||||
- [disable](#disable)
|
||||
- [domain](#domain)
|
||||
- [enable](#enable)
|
||||
- [host](#host)
|
||||
- [lease](#lease)
|
||||
- [seqnum](#seqnum)
|
||||
- [service](#service)
|
||||
- [state](#state)
|
||||
|
||||
@@ -25,17 +27,46 @@ Print SRP server help menu.
|
||||
|
||||
```bash
|
||||
> srp server help
|
||||
addrmode
|
||||
disable
|
||||
domain
|
||||
enable
|
||||
help
|
||||
host
|
||||
lease
|
||||
seqnum
|
||||
service
|
||||
state
|
||||
Done
|
||||
```
|
||||
|
||||
### addrmode
|
||||
|
||||
Usage: `srp server addrmode [unicast|anycast]`
|
||||
|
||||
Get or set the address mode used by the SRP server.
|
||||
|
||||
Address mode specifies how the address and port number are determined by the SRP server and this is published in the Thread Network Data.
|
||||
|
||||
Get the address mode.
|
||||
|
||||
```bash
|
||||
> srp server addrmode
|
||||
unicast
|
||||
Done
|
||||
```
|
||||
|
||||
Set the address mode.
|
||||
|
||||
```bash
|
||||
> srp server addrmode anycast
|
||||
Done
|
||||
|
||||
> srp server addrmode
|
||||
anycast
|
||||
Done
|
||||
```
|
||||
|
||||
### disable
|
||||
|
||||
Usage: `srp server disable`
|
||||
@@ -116,6 +147,23 @@ Set LEASE and KEY-LEASE values.
|
||||
Done
|
||||
```
|
||||
|
||||
### seqnum
|
||||
|
||||
Usage: `srp server seqnum [<seqnum>]`
|
||||
|
||||
Get or set the sequence number used with anycast address mode.
|
||||
|
||||
The sequence number is included in "DNS/SRP Service Anycast Address" entry published in the Network Data.
|
||||
|
||||
```bash
|
||||
> srp server seqnum 20
|
||||
Done
|
||||
|
||||
> srp server seqnum
|
||||
20
|
||||
Done
|
||||
```
|
||||
|
||||
### service
|
||||
|
||||
Usage: `srp server service`
|
||||
|
||||
@@ -65,6 +65,37 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SrpServer::ProcessAddrMode(Arg aArgs[])
|
||||
{
|
||||
otError error = OT_ERROR_INVALID_ARGS;
|
||||
|
||||
if (aArgs[0].IsEmpty())
|
||||
{
|
||||
switch (otSrpServerGetAddressMode(mInterpreter.mInstance))
|
||||
{
|
||||
case OT_SRP_SREVER_ADDRESS_MODE_UNICAST:
|
||||
mInterpreter.OutputLine("unicast");
|
||||
break;
|
||||
|
||||
case OT_SRP_SERVER_ADDRESS_MODE_ANYCAST:
|
||||
mInterpreter.OutputLine("anycast");
|
||||
break;
|
||||
}
|
||||
|
||||
error = OT_ERROR_NONE;
|
||||
}
|
||||
else if (aArgs[0] == "unicast")
|
||||
{
|
||||
error = otSrpServerSetAddressMode(mInterpreter.mInstance, OT_SRP_SREVER_ADDRESS_MODE_UNICAST);
|
||||
}
|
||||
else if (aArgs[0] == "anycast")
|
||||
{
|
||||
error = otSrpServerSetAddressMode(mInterpreter.mInstance, OT_SRP_SERVER_ADDRESS_MODE_ANYCAST);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SrpServer::ProcessDomain(Arg aArgs[])
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
@@ -280,6 +311,26 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SrpServer::ProcessSeqNum(Arg aArgs[])
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
if (aArgs[0].IsEmpty())
|
||||
{
|
||||
mInterpreter.OutputLine("%u", otSrpServerGetAnycastModeSequenceNumber(mInterpreter.mInstance));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t sequenceNumber;
|
||||
|
||||
SuccessOrExit(error = aArgs[0].ParseAsUint8(sequenceNumber));
|
||||
error = otSrpServerSetAnycastModeSequenceNumber(mInterpreter.mInstance, sequenceNumber);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError SrpServer::ProcessHelp(Arg aArgs[])
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aArgs);
|
||||
|
||||
@@ -86,6 +86,7 @@ private:
|
||||
otError (SrpServer::*mHandler)(Arg aArgs[]);
|
||||
};
|
||||
|
||||
otError ProcessAddrMode(Arg aArgs[]);
|
||||
otError ProcessDomain(Arg aArgs[]);
|
||||
otError ProcessState(Arg aArgs[]);
|
||||
otError ProcessEnable(Arg aArgs[]);
|
||||
@@ -93,15 +94,17 @@ private:
|
||||
otError ProcessLease(Arg aArgs[]);
|
||||
otError ProcessHost(Arg aArgs[]);
|
||||
otError ProcessService(Arg aArgs[]);
|
||||
otError ProcessSeqNum(Arg aArgs[]);
|
||||
otError ProcessHelp(Arg aArgs[]);
|
||||
|
||||
void OutputHostAddresses(const otSrpServerHost *aHost);
|
||||
|
||||
static constexpr Command sCommands[] = {
|
||||
{"disable", &SrpServer::ProcessDisable}, {"domain", &SrpServer::ProcessDomain},
|
||||
{"enable", &SrpServer::ProcessEnable}, {"help", &SrpServer::ProcessHelp},
|
||||
{"host", &SrpServer::ProcessHost}, {"lease", &SrpServer::ProcessLease},
|
||||
{"service", &SrpServer::ProcessService}, {"state", &SrpServer::ProcessState},
|
||||
{"addrmode", &SrpServer::ProcessAddrMode}, {"disable", &SrpServer::ProcessDisable},
|
||||
{"domain", &SrpServer::ProcessDomain}, {"enable", &SrpServer::ProcessEnable},
|
||||
{"help", &SrpServer::ProcessHelp}, {"host", &SrpServer::ProcessHost},
|
||||
{"lease", &SrpServer::ProcessLease}, {"seqnum", &SrpServer::ProcessSeqNum},
|
||||
{"service", &SrpServer::ProcessService}, {"state", &SrpServer::ProcessState},
|
||||
};
|
||||
|
||||
static_assert(Utils::LookupTable::IsSorted(sCommands), "Command Table is not sorted");
|
||||
|
||||
@@ -63,6 +63,34 @@ otSrpServerState otSrpServerGetState(otInstance *aInstance)
|
||||
return static_cast<otSrpServerState>(instance.Get<Srp::Server>().GetState());
|
||||
}
|
||||
|
||||
otSrpServerAddressMode otSrpServerGetAddressMode(otInstance *aInstance)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return static_cast<otSrpServerAddressMode>(instance.Get<Srp::Server>().GetAddressMode());
|
||||
}
|
||||
|
||||
otError otSrpServerSetAddressMode(otInstance *aInstance, otSrpServerAddressMode aMode)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<Srp::Server>().SetAddressMode(static_cast<Srp::Server::AddressMode>(aMode));
|
||||
}
|
||||
|
||||
uint8_t otSrpServerGetAnycastModeSequenceNumber(otInstance *aInstance)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<Srp::Server>().GetAnycastModeSequenceNumber();
|
||||
}
|
||||
|
||||
otError otSrpServerSetAnycastModeSequenceNumber(otInstance *aInstance, uint8_t aSequenceNumber)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<Srp::Server>().SetAnycastModeSequenceNumber(aSequenceNumber);
|
||||
}
|
||||
|
||||
void otSrpServerSetEnabled(otInstance *aInstance, bool aEnabled)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
@@ -45,6 +45,21 @@
|
||||
#define OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_SRP_SERVER_DEFAULT_ADDDRESS_MODE
|
||||
*
|
||||
* Specifies the default address mode used by the SRP server.
|
||||
*
|
||||
* The address mode specifies how address and port number are determined by the SRP server and how this info is
|
||||
* published in the Thread Network Data.
|
||||
*
|
||||
* The value of this configuration should be from `otSrpServerAddressMode` enumeration.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_SRP_SERVER_DEFAULT_ADDDRESS_MODE
|
||||
#define OPENTHREAD_CONFIG_SRP_SERVER_DEFAULT_ADDDRESS_MODE OT_SRP_SREVER_ADDRESS_MODE_UNICAST
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MIN
|
||||
*
|
||||
|
||||
@@ -71,6 +71,10 @@ Error Server::Start(void)
|
||||
SuccessOrExit(error = mSocket.Open(&Server::HandleUdpReceive, this));
|
||||
SuccessOrExit(error = mSocket.Bind(kPort, kBindUnspecifiedNetif ? OT_NETIF_UNSPECIFIED : OT_NETIF_THREAD));
|
||||
|
||||
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
|
||||
Get<Srp::Server>().HandleDnssdServerStateChange();
|
||||
#endif
|
||||
|
||||
exit:
|
||||
otLogInfoDns("[server] started: %s", ErrorToString(error));
|
||||
|
||||
@@ -97,6 +101,10 @@ void Server::Stop(void)
|
||||
|
||||
IgnoreError(mSocket.Close());
|
||||
otLogInfoDns("[server] stopped");
|
||||
|
||||
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
|
||||
Get<Srp::Server>().HandleDnssdServerStateChange();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Server::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
|
||||
@@ -107,13 +115,21 @@ void Server::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessa
|
||||
|
||||
void Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Header requestHeader;
|
||||
|
||||
SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), requestHeader));
|
||||
VerifyOrExit(requestHeader.GetType() == Header::kTypeQuery, error = kErrorDrop);
|
||||
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
|
||||
// We first let the `Srp::Server` process the received message.
|
||||
// It returns `kErrorNone` to indicate that it successfully
|
||||
// processed the message.
|
||||
|
||||
VerifyOrExit(Get<Srp::Server>().HandleDnssdServerUdpReceive(aMessage, aMessageInfo) != kErrorNone);
|
||||
#endif
|
||||
|
||||
SuccessOrExit(aMessage.Read(aMessage.GetOffset(), requestHeader));
|
||||
VerifyOrExit(requestHeader.GetType() == Header::kTypeQuery);
|
||||
|
||||
ProcessQuery(requestHeader, aMessage, aMessageInfo);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,11 @@
|
||||
*/
|
||||
|
||||
namespace ot {
|
||||
|
||||
namespace Srp {
|
||||
class Server;
|
||||
}
|
||||
|
||||
namespace Dns {
|
||||
namespace ServiceDiscovery {
|
||||
|
||||
@@ -58,6 +63,8 @@ namespace ServiceDiscovery {
|
||||
*/
|
||||
class Server : public InstanceLocator, private NonCopyable
|
||||
{
|
||||
friend class Srp::Server;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This enumeration specifies a DNS-SD query type.
|
||||
|
||||
+157
-30
@@ -89,6 +89,8 @@ Server::Server(Instance &aInstance)
|
||||
, mServiceUpdateId(Random::NonCrypto::GetUint32())
|
||||
, mPort(kUdpPortMin)
|
||||
, mState(kStateDisabled)
|
||||
, mAddressMode(kDefaultAddressMode)
|
||||
, mAnycastSequenceNumber(0)
|
||||
, mHasRegisteredAnyService(false)
|
||||
{
|
||||
IgnoreError(SetDomain(kDefaultDomain));
|
||||
@@ -100,6 +102,32 @@ void Server::SetServiceHandler(otSrpServerServiceUpdateHandler aServiceHandler,
|
||||
mServiceUpdateHandlerContext = aServiceHandlerContext;
|
||||
}
|
||||
|
||||
Error Server::SetAddressMode(AddressMode aMode)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(mState == kStateDisabled, error = kErrorInvalidState);
|
||||
VerifyOrExit(mAddressMode != aMode);
|
||||
otLogInfoSrp("[server] Address Mode: %s -> %s", AddressModeToString(mAddressMode), AddressModeToString(aMode));
|
||||
mAddressMode = aMode;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Server::SetAnycastModeSequenceNumber(uint8_t aSequenceNumber)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(mState == kStateDisabled, error = kErrorInvalidState);
|
||||
mAnycastSequenceNumber = aSequenceNumber;
|
||||
|
||||
otLogInfoSrp("[server] Set Anycast Address Mode Seq Number to %d", aSequenceNumber);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Server::SetEnabled(bool aEnabled)
|
||||
{
|
||||
if (aEnabled)
|
||||
@@ -107,15 +135,23 @@ void Server::SetEnabled(bool aEnabled)
|
||||
VerifyOrExit(mState == kStateDisabled);
|
||||
mState = kStateStopped;
|
||||
|
||||
// Select a port and then publish "DNS/SRP Unicast Address
|
||||
// Service" in Thread Network Data using the device's
|
||||
// mesh-local EID as the address. Then wait for callback
|
||||
// `HandleNetDataPublisherEntryChange()` from to `Publisher` to
|
||||
// start server operation when entry is published (i.e., added
|
||||
// to the Network Data).
|
||||
// Request publishing of "DNS/SRP Address Service" entry in the
|
||||
// Thread Network Data based of `mAddressMode`. Then wait for
|
||||
// callback `HandleNetDataPublisherEntryChange()` from the
|
||||
// `Publisher` to start the SRP server.
|
||||
|
||||
SelectPort();
|
||||
Get<NetworkData::Publisher>().PublishDnsSrpServiceUnicast(mPort);
|
||||
switch (mAddressMode)
|
||||
{
|
||||
case kAddressModeUnicast:
|
||||
SelectPort();
|
||||
Get<NetworkData::Publisher>().PublishDnsSrpServiceUnicast(mPort);
|
||||
break;
|
||||
|
||||
case kAddressModeAnycast:
|
||||
mPort = kAnycastAddressModePort;
|
||||
Get<NetworkData::Publisher>().PublishDnsSrpServiceAnycast(mAnycastSequenceNumber);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -388,12 +424,12 @@ void Server::CommitSrpUpdate(Error aError,
|
||||
shouldFreeHost = false;
|
||||
|
||||
#if OPENTHREAD_CONFIG_SRP_SERVER_PORT_SWITCH_ENABLE
|
||||
if (!mHasRegisteredAnyService)
|
||||
if (!mHasRegisteredAnyService && (mAddressMode == kAddressModeUnicast))
|
||||
{
|
||||
Settings::SrpServerInfo info;
|
||||
|
||||
mHasRegisteredAnyService = true;
|
||||
info.SetPort(mSocket.mSockName.mPort);
|
||||
info.SetPort(GetSocket().mSockName.mPort);
|
||||
IgnoreError(Get<Settings>().Save(info));
|
||||
}
|
||||
#endif
|
||||
@@ -442,25 +478,96 @@ void Server::SelectPort(void)
|
||||
|
||||
void Server::Start(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(mState == kStateStopped);
|
||||
|
||||
mState = kStateRunning;
|
||||
|
||||
SuccessOrExit(error = mSocket.Open(HandleUdpReceive, this));
|
||||
SuccessOrExit(error = mSocket.Bind(mPort, OT_NETIF_THREAD));
|
||||
|
||||
PrepareSocket();
|
||||
otLogInfoSrp("[server] start listening on port %u", mPort);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Server::PrepareSocket(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
|
||||
Ip6::Udp::Socket &dnsSocket = Get<Dns::ServiceDiscovery::Server>().mSocket;
|
||||
|
||||
if (dnsSocket.GetSockName().GetPort() == mPort)
|
||||
{
|
||||
// If the DNS-SD socket matches our port number, we use the
|
||||
// same socket so we close our own socket (in case it was
|
||||
// open). `GetSocket()` will now return the DNS-SD socket.
|
||||
|
||||
IgnoreError(mSocket.Close());
|
||||
ExitNow();
|
||||
}
|
||||
#endif
|
||||
|
||||
VerifyOrExit(!mSocket.IsOpen());
|
||||
SuccessOrExit(error = mSocket.Open(HandleUdpReceive, this));
|
||||
error = mSocket.Bind(mPort, OT_NETIF_THREAD);
|
||||
|
||||
exit:
|
||||
if (error != kErrorNone)
|
||||
{
|
||||
otLogCritSrp("[server] failed to start: %s", ErrorToString(error));
|
||||
otLogCritSrp("[server] failed to prepare socket: %s", ErrorToString(error));
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
Ip6::Udp::Socket &Server::GetSocket(void)
|
||||
{
|
||||
Ip6::Udp::Socket *socket = &mSocket;
|
||||
|
||||
#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
|
||||
Ip6::Udp::Socket &dnsSocket = Get<Dns::ServiceDiscovery::Server>().mSocket;
|
||||
|
||||
if (dnsSocket.GetSockName().GetPort() == mPort)
|
||||
{
|
||||
socket = &dnsSocket;
|
||||
}
|
||||
#endif
|
||||
|
||||
return *socket;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
|
||||
|
||||
void Server::HandleDnssdServerStateChange(void)
|
||||
{
|
||||
// This is called from` Dns::ServiceDiscovery::Server` to notify
|
||||
// that it has started or stopped. We check whether we need to
|
||||
// share the socket.
|
||||
|
||||
if (mState == kStateRunning)
|
||||
{
|
||||
PrepareSocket();
|
||||
}
|
||||
}
|
||||
|
||||
Error Server::HandleDnssdServerUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
// This is called from` Dns::ServiceDiscovery::Server` when a UDP
|
||||
// message is received on its socket. We check whether we are
|
||||
// sharing socket and if so we process the received message. We
|
||||
// return `kErrorNone` to indicate that message was successfully
|
||||
// processed by `Srp::Server`, otherwise `kErrorDrop` is returned.
|
||||
|
||||
Error error = kErrorDrop;
|
||||
|
||||
VerifyOrExit((mState == kStateRunning) && !mSocket.IsOpen());
|
||||
|
||||
error = ProcessMessage(aMessage, aMessageInfo);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
|
||||
|
||||
void Server::Stop(void)
|
||||
{
|
||||
VerifyOrExit(mState == kStateRunning);
|
||||
@@ -523,10 +630,10 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Server::HandleDnsUpdate(Message & aMessage,
|
||||
const Ip6::MessageInfo & aMessageInfo,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
uint16_t aOffset)
|
||||
void Server::ProcessDnsUpdate(Message & aMessage,
|
||||
const Ip6::MessageInfo & aMessageInfo,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
uint16_t aOffset)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Dns::Zone zone;
|
||||
@@ -1056,7 +1163,7 @@ void Server::SendResponse(const Dns::UpdateHeader & aHeader,
|
||||
Message * response = nullptr;
|
||||
Dns::UpdateHeader header;
|
||||
|
||||
response = mSocket.NewMessage(0);
|
||||
response = GetSocket().NewMessage(0);
|
||||
VerifyOrExit(response != nullptr, error = kErrorNoBufs);
|
||||
|
||||
header.SetMessageId(aHeader.GetMessageId());
|
||||
@@ -1065,7 +1172,7 @@ void Server::SendResponse(const Dns::UpdateHeader & aHeader,
|
||||
header.SetResponseCode(aResponseCode);
|
||||
SuccessOrExit(error = response->Append(header));
|
||||
|
||||
SuccessOrExit(error = mSocket.SendTo(*response, aMessageInfo));
|
||||
SuccessOrExit(error = GetSocket().SendTo(*response, aMessageInfo));
|
||||
|
||||
if (aResponseCode != Dns::UpdateHeader::kResponseSuccess)
|
||||
{
|
||||
@@ -1095,7 +1202,7 @@ void Server::SendResponse(const Dns::UpdateHeader &aHeader,
|
||||
Dns::OptRecord optRecord;
|
||||
Dns::LeaseOption leaseOption;
|
||||
|
||||
response = mSocket.NewMessage(0);
|
||||
response = GetSocket().NewMessage(0);
|
||||
VerifyOrExit(response != nullptr, error = kErrorNoBufs);
|
||||
|
||||
header.SetMessageId(aHeader.GetMessageId());
|
||||
@@ -1119,7 +1226,7 @@ void Server::SendResponse(const Dns::UpdateHeader &aHeader,
|
||||
leaseOption.SetKeyLeaseInterval(aKeyLease);
|
||||
SuccessOrExit(error = response->Append(leaseOption));
|
||||
|
||||
SuccessOrExit(error = mSocket.SendTo(*response, aMessageInfo));
|
||||
SuccessOrExit(error = GetSocket().SendTo(*response, aMessageInfo));
|
||||
|
||||
otLogInfoSrp("[server] send response with granted lease: %u and key lease: %u", aLease, aKeyLease);
|
||||
|
||||
@@ -1138,6 +1245,16 @@ void Server::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessa
|
||||
}
|
||||
|
||||
void Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
Error error = ProcessMessage(aMessage, aMessageInfo);
|
||||
|
||||
if (error != kErrorNone)
|
||||
{
|
||||
otLogInfoSrp("[server] failed to handle DNS message: %s", ErrorToString(error));
|
||||
}
|
||||
}
|
||||
|
||||
Error Server::ProcessMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
Error error;
|
||||
Dns::UpdateHeader dnsHeader;
|
||||
@@ -1152,7 +1269,7 @@ void Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessag
|
||||
switch (dnsHeader.GetQueryType())
|
||||
{
|
||||
case Dns::UpdateHeader::kQueryTypeUpdate:
|
||||
HandleDnsUpdate(aMessage, aMessageInfo, dnsHeader, offset);
|
||||
ProcessDnsUpdate(aMessage, aMessageInfo, dnsHeader, offset);
|
||||
break;
|
||||
default:
|
||||
error = kErrorDrop;
|
||||
@@ -1160,10 +1277,7 @@ void Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessag
|
||||
}
|
||||
|
||||
exit:
|
||||
if (error != kErrorNone)
|
||||
{
|
||||
otLogInfoSrp("[server] failed to handle DNS message: %s", ErrorToString(error));
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
void Server::HandleLeaseTimer(Timer &aTimer)
|
||||
@@ -1299,6 +1413,19 @@ void Server::HandleOutstandingUpdatesTimer(void)
|
||||
}
|
||||
}
|
||||
|
||||
const char *Server::AddressModeToString(AddressMode aMode)
|
||||
{
|
||||
static const char *const kAddressModeStrings[] = {
|
||||
"unicast", // (0) kAddressModeUnicast
|
||||
"anycast", // (1) kAddressModeAnycast
|
||||
};
|
||||
|
||||
static_assert(kAddressModeUnicast == 0, "kAddressModeUnicast value is incorrect");
|
||||
static_assert(kAddressModeAnycast == 1, "kAddressModeAnycast value is incorrect");
|
||||
|
||||
return kAddressModeStrings[aMode];
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Server::Service
|
||||
|
||||
|
||||
@@ -68,6 +68,13 @@
|
||||
#include "thread/network_data_publisher.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
namespace Dns {
|
||||
namespace ServiceDiscovery {
|
||||
class Server;
|
||||
}
|
||||
} // namespace Dns
|
||||
|
||||
namespace Srp {
|
||||
|
||||
/**
|
||||
@@ -80,6 +87,7 @@ class Server : public InstanceLocator, private NonCopyable
|
||||
friend class UpdateMetadata;
|
||||
friend class Service;
|
||||
friend class Host;
|
||||
friend class Dns::ServiceDiscovery::Server;
|
||||
|
||||
public:
|
||||
static constexpr uint16_t kUdpPortMin = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MIN; ///< The reserved min port.
|
||||
@@ -93,6 +101,19 @@ public:
|
||||
*/
|
||||
typedef otSrpServerServiceUpdateId ServiceUpdateId;
|
||||
|
||||
/**
|
||||
* This enumeration represents the address mode used by the SRP server.
|
||||
*
|
||||
* Address mode specifies how the address and port number are determined by the SRP server and how this info ins
|
||||
* published in the Thread Network Data.
|
||||
*
|
||||
*/
|
||||
enum AddressMode : uint8_t
|
||||
{
|
||||
kAddressModeUnicast = OT_SRP_SREVER_ADDRESS_MODE_UNICAST, ///< Unicast address mode.
|
||||
kAddressModeAnycast = OT_SRP_SERVER_ADDRESS_MODE_ANYCAST, ///< Anycast address mode.
|
||||
};
|
||||
|
||||
class Host;
|
||||
|
||||
enum State : uint8_t
|
||||
@@ -599,6 +620,46 @@ public:
|
||||
*/
|
||||
Error SetDomain(const char *aDomain);
|
||||
|
||||
/**
|
||||
* This method returns the address mode being used by the SRP server.
|
||||
*
|
||||
* @returns The SRP server's address mode.
|
||||
*
|
||||
*/
|
||||
AddressMode GetAddressMode(void) const { return mAddressMode; }
|
||||
|
||||
/**
|
||||
* This method sets the address mode to be used by the SRP server.
|
||||
*
|
||||
* @param[in] aMode The address mode to use.
|
||||
*
|
||||
* @retval kErrorNone Successfully set the address mode.
|
||||
* @retval kErrorInvalidState The SRP server is enabled and the address mode cannot be changed.
|
||||
*
|
||||
*/
|
||||
Error SetAddressMode(AddressMode aMode);
|
||||
|
||||
/**
|
||||
* This method gets the sequence number used with anycast address mode.
|
||||
*
|
||||
* The sequence number is included in "DNS/SRP Service Anycast Address" entry published in the Network Data.
|
||||
*
|
||||
* @returns The anycast sequence number.
|
||||
*
|
||||
*/
|
||||
uint8_t GetAnycastModeSequenceNumber(void) const { return mAnycastSequenceNumber; }
|
||||
|
||||
/**
|
||||
* This method sets the sequence number used with anycast address mode.
|
||||
*
|
||||
* @param[in] aSequenceNumber The sequence number to use.
|
||||
*
|
||||
* @retval kErrorNone Successfully set the address mode.
|
||||
* @retval kErrorInvalidState The SRP server is enabled and the sequence number cannot be changed.
|
||||
*
|
||||
*/
|
||||
Error SetAnycastModeSequenceNumber(uint8_t aSequenceNumber);
|
||||
|
||||
/**
|
||||
* This method tells whether the SRP server is currently running.
|
||||
*
|
||||
@@ -675,6 +736,11 @@ private:
|
||||
static constexpr uint32_t kDefaultMaxKeyLease = 3600u * 24 * 14; // 14 days (in seconds).
|
||||
static constexpr uint32_t kDefaultEventsHandlerTimeout = OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT;
|
||||
|
||||
static constexpr AddressMode kDefaultAddressMode =
|
||||
static_cast<AddressMode>(OPENTHREAD_CONFIG_SRP_SERVER_DEFAULT_ADDDRESS_MODE);
|
||||
|
||||
static constexpr uint16_t kAnycastAddressModePort = 53;
|
||||
|
||||
// This class includes metadata for processing a SRP update (register, deregister)
|
||||
// and sending DNS response to the client.
|
||||
class UpdateMetadata : public InstanceLocator, public LinkedListEntry<UpdateMetadata>
|
||||
@@ -708,9 +774,17 @@ private:
|
||||
UpdateMetadata * mNext;
|
||||
};
|
||||
|
||||
void Start(void);
|
||||
void Stop(void);
|
||||
void SelectPort(void);
|
||||
void Start(void);
|
||||
void Stop(void);
|
||||
void SelectPort(void);
|
||||
void PrepareSocket(void);
|
||||
Ip6::Udp::Socket &GetSocket(void);
|
||||
|
||||
#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
|
||||
void HandleDnssdServerStateChange(void);
|
||||
Error HandleDnssdServerUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
#endif
|
||||
|
||||
void HandleNetDataPublisherEvent(NetworkData::Publisher::Event aEvent);
|
||||
|
||||
ServiceUpdateId AllocateId(void) { return mServiceUpdateId++; }
|
||||
@@ -719,10 +793,11 @@ private:
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
Host & aHost,
|
||||
const Ip6::MessageInfo & aMessageInfo);
|
||||
void HandleDnsUpdate(Message & aMessage,
|
||||
const Ip6::MessageInfo & aMessageInfo,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
uint16_t aOffset);
|
||||
Error ProcessMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
void ProcessDnsUpdate(Message & aMessage,
|
||||
const Ip6::MessageInfo & aMessageInfo,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
uint16_t aOffset);
|
||||
Error ProcessUpdateSection(Host & aHost,
|
||||
const Message & aMessage,
|
||||
const Dns::UpdateHeader &aDnsHeader,
|
||||
@@ -781,6 +856,7 @@ private:
|
||||
|
||||
void HandleServiceUpdateResult(UpdateMetadata *aUpdate, Error aError);
|
||||
const UpdateMetadata *FindOutstandingUpdate(const Ip6::MessageInfo &aMessageInfo, uint16_t aDnsMessageId);
|
||||
static const char * AddressModeToString(AddressMode aMode);
|
||||
|
||||
Ip6::Udp::Socket mSocket;
|
||||
otSrpServerServiceUpdateHandler mServiceUpdateHandler;
|
||||
@@ -799,6 +875,8 @@ private:
|
||||
ServiceUpdateId mServiceUpdateId;
|
||||
uint16_t mPort;
|
||||
State mState;
|
||||
AddressMode mAddressMode;
|
||||
uint8_t mAnycastSequenceNumber;
|
||||
bool mHasRegisteredAnyService : 1;
|
||||
};
|
||||
|
||||
|
||||
@@ -187,6 +187,7 @@ EXTRA_DIST = \
|
||||
test_srp_lease.py \
|
||||
test_srp_name_conflicts.py \
|
||||
test_srp_register_single_service.py \
|
||||
test_srp_server_anycast_mode.py \
|
||||
test_srp_server_reboot_port.py \
|
||||
test_srp_sub_type.py \
|
||||
test_zero_len_external_route.py \
|
||||
@@ -254,6 +255,7 @@ check_SCRIPTS = \
|
||||
test_srp_lease.py \
|
||||
test_srp_name_conflicts.py \
|
||||
test_srp_register_single_service.py \
|
||||
test_srp_server_anycast_mode.py \
|
||||
test_srp_server_reboot_port.py \
|
||||
test_srp_sub_type.py \
|
||||
test_zero_len_external_route.py \
|
||||
|
||||
@@ -800,6 +800,23 @@ class NodeImpl:
|
||||
self.send_command('srp server state')
|
||||
return self._expect_result(states)
|
||||
|
||||
def srp_server_get_addr_mode(self):
|
||||
modes = [r'unicast', r'anycast']
|
||||
self.send_command(f'srp server addrmode')
|
||||
return self._expect_result(modes)
|
||||
|
||||
def srp_server_set_addr_mode(self, mode):
|
||||
self.send_command(f'srp server addrmode {mode}')
|
||||
self._expect_done()
|
||||
|
||||
def srp_server_get_anycast_seq_num(self):
|
||||
self.send_command(f'srp server seqnum')
|
||||
return int(self._expect_result(r'\d+'))
|
||||
|
||||
def srp_server_set_anycast_seq_num(self, seqnum):
|
||||
self.send_command(f'srp server seqnum {seqnum}')
|
||||
self._expect_done()
|
||||
|
||||
def srp_server_set_enabled(self, enable):
|
||||
cmd = f'srp server {"enable" if enable else "disable"}'
|
||||
self.send_command(cmd)
|
||||
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2021, 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.
|
||||
#
|
||||
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
|
||||
# Test description:
|
||||
#
|
||||
# This test covers the SRP server's behavior using different address
|
||||
# modes (unicast or anycast). The address mode indicates how the SRP
|
||||
# server determines its address and port and how this info is
|
||||
# published in the Thread Network Data. When using anycast address
|
||||
# mode, the SRP server and DNS server/resolver will both listen on port
|
||||
# 53 and they re-use the same socket. This test verifies the behavior of
|
||||
# both modules in such a situation.
|
||||
#
|
||||
#
|
||||
# Topology:
|
||||
#
|
||||
# One leader and two router nodes, all connected. The leader acts as SRP
|
||||
# server and DNS resolver. One router acts as SRP client, and the
|
||||
# other acts as DNS client browsing for registered service names.
|
||||
#
|
||||
|
||||
SERVER = 1
|
||||
CLIENT = 2
|
||||
BROWSER = 3
|
||||
|
||||
DOMAIN = 'default.service.arpa.'
|
||||
HOST = 'host'
|
||||
INSTANCE = 'ins1'
|
||||
SERVICE = '_srv._udp'
|
||||
SERVICE_PORT = 1313
|
||||
|
||||
SRP_SERVER_ANYCAST_PORT = 53
|
||||
SRP_SERVER_ANYCAST_SEQ_NUM = 17
|
||||
DNS_RESOLVER_PORT = 53
|
||||
|
||||
THREAD_ENTERPRISE_NUMBER = 44970
|
||||
ANYCAST_SERVICE_NUM = 0x5c
|
||||
UNICAST_SERVICE_NUM = 0x5d
|
||||
|
||||
|
||||
class TestSrpServerAnycastMode(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
SERVER: {
|
||||
'mode': 'rdn',
|
||||
},
|
||||
CLIENT: {
|
||||
'mode': 'rdn',
|
||||
},
|
||||
BROWSER: {
|
||||
'mode': 'rdn',
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
server = self.nodes[SERVER]
|
||||
client = self.nodes[CLIENT]
|
||||
browser = self.nodes[BROWSER]
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# Form the network.
|
||||
|
||||
server.start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(server.get_state(), 'leader')
|
||||
|
||||
client.start()
|
||||
browser.start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(client.get_state(), 'router')
|
||||
self.assertEqual(browser.get_state(), 'router')
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# Go through the entire test twice, first time using anycast address
|
||||
# mode and second time using unicast address mode.
|
||||
|
||||
for addr_mode in ['anycast', 'unicast']:
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Set the SRP server address mode and start the SRP server.
|
||||
|
||||
server.srp_server_set_addr_mode(addr_mode)
|
||||
|
||||
if addr_mode == 'anycast':
|
||||
server.srp_server_set_anycast_seq_num(SRP_SERVER_ANYCAST_SEQ_NUM)
|
||||
self.assertEqual(server.srp_server_get_anycast_seq_num(), SRP_SERVER_ANYCAST_SEQ_NUM)
|
||||
|
||||
self.assertEqual(server.srp_server_get_addr_mode(), addr_mode)
|
||||
server.srp_server_set_enabled(True)
|
||||
self.simulator.go(5)
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Verify the published SRP server info in the Network Data.
|
||||
|
||||
netdata_services = client.get_services()
|
||||
self.assertEqual(len(netdata_services), 1)
|
||||
netdata_service = netdata_services[0]
|
||||
|
||||
self.assertEqual(int(netdata_service[0]), THREAD_ENTERPRISE_NUMBER)
|
||||
data = bytes.fromhex(netdata_service[1])
|
||||
self.assertEqual(netdata_service[3], 's')
|
||||
|
||||
if addr_mode == 'anycast':
|
||||
self.assertTrue(len(data) >= 2)
|
||||
self.assertEqual(data[0], ANYCAST_SERVICE_NUM)
|
||||
self.assertEqual(data[1], SRP_SERVER_ANYCAST_SEQ_NUM)
|
||||
else:
|
||||
self.assertTrue(len(data) >= 1)
|
||||
self.assertEqual(data[0], UNICAST_SERVICE_NUM)
|
||||
self.assertEqual(netdata_service[3], 's')
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Enable auto-start on SRP client. Verify that it does find the
|
||||
# server and uses the proper address and port number.
|
||||
|
||||
client.srp_client_enable_auto_start_mode()
|
||||
self.simulator.go(5)
|
||||
|
||||
if addr_mode == 'anycast':
|
||||
server_alocs = server.get_ip6_address(config.ADDRESS_TYPE.ALOC)
|
||||
self.assertEqual(client.srp_client_get_state(), 'Enabled')
|
||||
self.assertIn(client.srp_client_get_server_address(), server_alocs)
|
||||
self.assertEqual(client.srp_client_get_server_port(), SRP_SERVER_ANYCAST_PORT)
|
||||
else:
|
||||
self.assertIn(client.srp_client_get_server_address(), server.get_mleid())
|
||||
self.assertEqual(client.srp_client_get_server_port(), server.get_srp_server_port())
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Add a service on the SRP client and verify its successful
|
||||
# registration with SRP server.
|
||||
|
||||
client.srp_client_set_host_name(HOST)
|
||||
client.srp_client_set_host_address(client.get_mleid())
|
||||
client.srp_client_add_service(INSTANCE, SERVICE, SERVICE_PORT)
|
||||
self.simulator.go(5)
|
||||
|
||||
client_services = client.srp_client_get_services()
|
||||
self.assertEqual(len(client_services), 1)
|
||||
client_service = client_services[0]
|
||||
self.assertEqual(client_service['instance'], INSTANCE)
|
||||
self.assertEqual(client_service['name'], SERVICE)
|
||||
self.assertEqual(int(client_service['port']), SERVICE_PORT)
|
||||
self.assertEqual(client_service['state'], 'Registered')
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Browse for a matching service name and verify that the registered
|
||||
# service is successfully found.
|
||||
|
||||
service_instances = browser.dns_browse(f'{SERVICE}.{DOMAIN}', server.get_mleid(), DNS_RESOLVER_PORT)
|
||||
self.assertEqual({INSTANCE}, set(service_instances.keys()))
|
||||
|
||||
service_instance = service_instances[INSTANCE]
|
||||
self.assertEqual(service_instance['host'], f'{HOST}.{DOMAIN}')
|
||||
self.assertEqual(int(service_instance['port']), SERVICE_PORT)
|
||||
self.assertEqual(service_instance['address'], client.get_mleid())
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Stop SRP client and server and clear host (and service) on the
|
||||
# client.
|
||||
|
||||
client.srp_client_clear_host()
|
||||
client.srp_client_stop()
|
||||
server.srp_server_set_enabled(False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -510,6 +510,14 @@
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE 1
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
|
||||
*
|
||||
* Define to 1 to enable DNS-SD Server support.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE 1
|
||||
|
||||
#if OPENTHREAD_RADIO
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MAC_SOFTWARE_ACK_TIMEOUT_ENABLE
|
||||
|
||||
Reference in New Issue
Block a user