[srp] implement AdvertisingProxy and define Dnssd platform APIs (#9268)

This commit adds a generic SRP Advertising Proxy implementation to
OpenThread core, which uses a set of newly defined `otPlatDnssd`
platform APIs for DNS-SD (mDNS) support on infrastructure network on
a Border Router.

`Srp::Server` provides `ServiceUpdateHandler` callback mechanism that
allows platforms to implement their own advertising proxy function.
While this is still supported, the new generic advertising proxy
implementation makes it easier to port and support the proxy function
on new platforms. The platform needs to provide the DNS-SD platform
APIs, which are designed to be simple and easy to implement.

The `AdvertisingProxy` directly interacts with `Srp::Server` and its
registered `Host` and `Service` entries, tracking whether an entry
has been successfully advertised, is currently being advertised, or
has been replaced by a new registration.

The `AdvertisingProxy` ensures that consecutive SRP updates for the
same host or service are committed on the server in the order they
are received, even if their advertisements are finished in a
different order. This is important for SRP Replication support, as
the server may receive a large number of SRP updates back-to-back for
the same host.

The `AdvertisingProxy` will also register key records for SRP host and
service instance names. This will keep the claim on the name of a
removed entry while its key lease is not expired. It is also used
when an SRP host registration has no off-mesh routable address.

This commit adds a detailed unit test `test_srp_adv_proxy` that
validates the `AdvertisingProxy` under many scenarios. The test
covers a range of cases, including delayed registration callbacks and
timeouts, new registrations replacing outstanding advertisements,
platform DNS-SD state changes and failures, host address changes
adding/removing OMR addresses.
This commit is contained in:
Abtin Keshavarzian
2024-02-09 10:43:47 -08:00
committed by GitHub
parent 905a22e0c7
commit b212a0a748
30 changed files with 5788 additions and 16 deletions
+2 -1
View File
@@ -172,8 +172,10 @@
* @defgroup plat-ble BLE
* @defgroup plat-crypto Crypto - Platform
* @defgroup plat-dns DNS - Platform
* @defgroup plat-dns-sd DNS-SD (mDNS)
* @defgroup plat-entropy Entropy
* @defgroup plat-factory-diagnostics Factory Diagnostics - Platform
* @defgroup plat-infra-if Infrastructure Interface
* @defgroup plat-logging Logging - Platform
* @defgroup plat-memory Memory
* @defgroup plat-messagepool Message Pool
@@ -186,7 +188,6 @@
* @defgroup plat-time Time Service
* @defgroup plat-toolchain Toolchain
* @defgroup plat-trel TREL - Platform
* @defgroup plat-infra-if Infrastructure Interface
*
* @}
*
+1
View File
@@ -238,6 +238,7 @@ ot_option(OT_SERVICE OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE "Network Data
ot_option(OT_SETTINGS_RAM OPENTHREAD_SETTINGS_RAM "volatile-only storage of settings")
ot_option(OT_SLAAC OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE "SLAAC address")
ot_option(OT_SNTP_CLIENT OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE "SNTP client")
ot_option(OT_SRP_ADV_PROXY OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE "SRP advertising proxy")
ot_option(OT_SRP_CLIENT OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE "SRP client")
ot_option(OT_SRP_SERVER OPENTHREAD_CONFIG_SRP_SERVER_ENABLE "SRP server")
ot_option(OT_TCP OPENTHREAD_CONFIG_TCP_ENABLE "TCP")
@@ -63,6 +63,7 @@ add_library(openthread-simulation
crypto.c
diag.c
dns.c
dnssd.c
dso_transport.c
entropy.c
flash.c
+107
View File
@@ -0,0 +1,107 @@
/*
* 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 "platform-simulation.h"
#include <openthread/platform/dnssd.h>
#if OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
otPlatDnssdState otPlatDnssdGetState(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return OT_PLAT_DNSSD_STOPPED;
}
void otPlatDnssdRegisterService(otInstance *aInstance,
const otPlatDnssdService *aService,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aService);
OT_UNUSED_VARIABLE(aRequestId);
OT_UNUSED_VARIABLE(aCallback);
}
void otPlatDnssdUnregisterService(otInstance *aInstance,
const otPlatDnssdService *aService,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aService);
OT_UNUSED_VARIABLE(aRequestId);
OT_UNUSED_VARIABLE(aCallback);
}
void otPlatDnssdRegisterHost(otInstance *aInstance,
const otPlatDnssdHost *aHost,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aHost);
OT_UNUSED_VARIABLE(aRequestId);
OT_UNUSED_VARIABLE(aCallback);
}
void otPlatDnssdUnregisterHost(otInstance *aInstance,
const otPlatDnssdHost *aHost,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aHost);
OT_UNUSED_VARIABLE(aRequestId);
OT_UNUSED_VARIABLE(aCallback);
}
void otPlatDnssdRegisterKey(otInstance *aInstance,
const otPlatDnssdKey *aKey,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aKey);
OT_UNUSED_VARIABLE(aRequestId);
OT_UNUSED_VARIABLE(aCallback);
}
void otPlatDnssdUnregisterKey(otInstance *aInstance,
const otPlatDnssdKey *aKey,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aKey);
OT_UNUSED_VARIABLE(aRequestId);
OT_UNUSED_VARIABLE(aCallback);
}
#endif // OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
+1
View File
@@ -91,6 +91,7 @@ source_set("openthread") {
"platform/debug_uart.h",
"platform/diag.h",
"platform/dns.h",
"platform/dnssd.h",
"platform/dso_transport.h",
"platform/entropy.h",
"platform/flash.h",
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (394)
#define OPENTHREAD_API_VERSION (395)
/**
* @addtogroup api-instance
+427
View File
@@ -0,0 +1,427 @@
/*
* 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.
*/
/**
* @file
* @brief
* This file includes the platform abstraction for DNS-SD (e.g., mDNS) on the infrastructure network.
*
*/
#ifndef OPENTHREAD_PLATFORM_DNSSD_H_
#define OPENTHREAD_PLATFORM_DNSSD_H_
#include <stdint.h>
#include <openthread/dns.h>
#include <openthread/error.h>
#include <openthread/instance.h>
#include <openthread/ip6.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup plat-dns-sd
*
* @brief
* This module includes the platform abstraction for DNS-SD (e.g., mDNS) on the infrastructure network.
*
* @{
*
* The DNS-SD platform APIs are used only when `OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE` is enabled.
*
*/
/**
* Represents the state of the DNS-SD platform.
*
*/
typedef enum otPlatDnssdState
{
OT_PLAT_DNSSD_STOPPED, ///< Stopped and unable to register any service or host.
OT_PLAT_DNSSD_READY, ///< Running and ready to register service or host.
} otPlatDnssdState;
/**
* Represents a request ID for registering/unregistering a service or host.
*
*/
typedef uint32_t otPlatDnssdRequestId;
/**
* Represents the callback function used when registering/unregistering a host or service.
*
* See `otPlatDnssdRegisterService()`, `otPlatDnssdUnregisterService()`, `otPlatDnssdRegisterHost()`, and
* `otPlatDnssdUnregisterHost()` for more details about when to invoke the callback and the `aError` values that can
* be returned in each case.
*
* @param[in] aInstance The OpenThread instance.
* @param[in] aRequestId The request ID.
* @param[in] aError Error indicating the outcome of request.
*
*/
typedef void (*otPlatDnssdRegisterCallback)(otInstance *aInstance, otPlatDnssdRequestId aRequestId, otError aError);
/**
* Represents a DNS-SD service.
*
* See `otPlatDnssdRegisterService()`, `otPlatDnssdUnregisterService()` for more details about fields in each case.
*
*/
typedef struct otPlatDnssdService
{
const char *mHostName; ///< The host name (does not include domain name).
const char *mServiceInstance; ///< The service instance name label (not the full name).
const char *mServiceType; ///< The service type (e.g., "_mt._udp", does not include domain name).
const char *const *mSubTypeLabels; ///< Array of sub-type labels (can be NULL if no label).
uint16_t mSubTypeLabelsLength; ///< Length of array of sub-type labels.
const uint8_t *mTxtData; ///< Encoded TXT data bytes.
uint16_t mTxtDataLength; ///< Length of TXT data.
uint16_t mPort; ///< The service port number.
uint16_t mPriority; ///< The service priority.
uint16_t mWeight; ///< The service weight.
uint32_t mTtl; ///< The service TTL in seconds.
uint32_t mInfraIfIndex; ///< The infrastructure network interface index.
} otPlatDnssdService;
/**
* Represents a DNS-SD host.
*
* See `otPlatDnssdRegisterHost()`, `otPlatDnssdUnregisterHost()` for more details about fields in each case.
*
*/
typedef struct otPlatDnssdHost
{
const char *mHostName; ///< The host name (does not include domain name).
const otIp6Address *mAddresses; ///< Array of IPv6 host addresses.
uint16_t mAddressesLength; ///< Number of entries in @p mAddresses array.
uint32_t mTtl; ///< The host TTL in seconds.
uint32_t mInfraIfIndex; ///< The infrastructure network interface index.
} otPlatDnssdHost;
/**
* Represents a DNS-SD key record.
*
* See `otPlatDnssdRegisterKey()`, `otPlatDnssdUnregisterKey()` for more details about fields in each case.
*
*/
typedef struct otPlatDnssdKey
{
const char *mName; ///< A host or a service instance name (does not include domain name).
const char *mServiceType; ///< The service type if key is for a service (does not include domain name).
const uint8_t *mKeyData; ///< Byte array containing the key record data.
uint16_t mKeyDataLength; ///< Length of @p mKeyData in bytes.
uint16_t mClass; ///< The resource record class.
uint32_t mTtl; ///< The TTL in seconds.
uint32_t mInfraIfIndex; ///< The infrastructure network interface index.
} otPlatDnssdKey;
/**
* Callback to notify state changes of the DNS-SD platform.
*
* The OpenThread stack will call `otPlatDnssdGetState()` (from this callback or later) to get the new state. The
* platform MUST therefore ensure that the returned state from `otPlatDnssdGetState()` is updated before calling this.
*
* @param[in] aInstance The OpenThread instance structure.
*
*/
extern void otPlatDnssdStateHandleStateChange(otInstance *aInstance);
/**
* Gets the current state of the DNS-SD module.
*
* The platform MUST notify the OpenThread stack whenever its state gets changed by invoking
* `otPlatDnssdStateHandleStateChange()`.
*
* @param[in] aInstance The OpenThread instance.
*
* @returns The current state of the DNS-SD module.
*
*/
otPlatDnssdState otPlatDnssdGetState(otInstance *aInstance);
/**
* Registers or updates a service on the infrastructure network's DNS-SD module.
*
* The @p aService and all its contained information (strings and buffers) are only valid during this call. The
* platform MUST save a copy of the information if it wants to retain the information after returning from this
* function.
*
* The fields in @p aService follow these rules:
*
* - The `mServiceInstance` and `mServiceType` fields specify the service instance label and service type name,
* respectively. They are never NULL.
* - The `mHostName` field specifies the host name of the service if it is not NULL. Otherwise, if it is NULL, it
* indicates that this service is for the device itself and leaves the host name selection to DNS-SD platform.
* - The `mSubTypeLabels` is an array of strings representing sub-types associated with the service. It can be NULL
* if there are no sub-types. Otherwise, the array length is specified by `mSubTypeLabelsLength`.
* - The `mTxtData` and `mTxtDataLength` fields specify the encoded TXT data.
* - The `mPort`, `mWeight`, and `mPriority` fields specify the service's parameters (as specified in DNS SRV record).
* - The `mTtl` field specifies the TTL if non-zero. If zero, the platform can choose the TTL to use.
* - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this
* request. If zero, the platform implementation can decided the interface.
*
* When the `mHostName` field in @p aService is not NULL (indicating that this registration is on behalf of another
* host), the OpenThread stack will ensure that `otPlatDnssdRegisterHost()` is also called for the same host before any
* service registration requests for the same host.
*
* Once the registration request is finished, either successfully or failed, the platform reports the outcome by
* invoking the @p aCallback and passing the same @p aRequestId in the callback. The @p aCallback function pointer can
* be NULL, which indicates that the OpenThread stack does not need to be notified of the outcome of the request.
* If the outcome is determined, the platform implementation may invoke the @p aCallback before returning from this
* function. The OpenThread stack will ensure to handle such a situation.
*
* On success, the @p aCallback MUST be called (if non-NULL) with `OT_ERROR_NONE` as the `aError` input parameter. If
* the registration causes a name conflict on DNS-SD domain (the service instance name is already claimed by another
* host), the `OT_ERROR_DUPLICATED` error MUST be used. The platform implementation can use other `OT_ERROR` types for
* other types of errors.
*
* The platform implementation MUST not assume that the @p aRequestId used in subsequent requests will be different.
* OpenThread may reuse the same request ID again for a different request.
*
* The OpenThread stack will not register the same service (with no changes) that was registered successfully earlier.
* Therefore, the platform implementation does not need to check for duplicate/same service and can assume that calls
* to this function are either registering a new entry or changing some parameter in a previously registered item. As
* a result, these changes always need to be synced on the infrastructure DNS-SD module.
*
* The OpenThread stack does not require the platform implementation to always invoke the @p aCallback function.
* The OpenThread stack has its own mechanism to time out an aged request with no response. This relaxes the
* requirement for platform implementations.
*
* @param[in] aInstance The OpenThread instance.
* @param[in] aService Information about the service to register.
* @param[in] aRequestId The ID associated with this request.
* @param[in] aCallback The callback function pointer to report the outcome (may be NULL if no callback needed).
*
*/
void otPlatDnssdRegisterService(otInstance *aInstance,
const otPlatDnssdService *aService,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback);
/**
* Unregisters a service on the infrastructure network's DNS-SD module.
*
* The @p aService and all its contained information (strings and buffers) are only valid during this call. The
* platform MUST save a copy of the information if it wants to retain the information after returning from this
* function.
*
* The fields in @p aService follow these rules:
*
* - The `mServiceInstance` and `mServiceType` fields specify the service instance label and service type name,
* respectively. They are never NULL.
* - The `mHostName` field specifies the host name of the service if it is not NULL. Otherwise, if it is NULL, it
* indicates that this service is for the device itself and leaves the host name selection to DNS-SD platform.
* - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this
* request. If zero, the platform implementation can decided the interface.
* - The rest of the fields in @p aService structure MUST be ignored in `otPlatDnssdUnregisterService()` call and may
* be set to zero by the OpenThread stack.
*
* Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same
* rules as described in `otPlatDnssdRegisterService()`.
*
* The OpenThread stack may request the unregistration of a service that was not previously registered, and the
* platform implementation MUST handle this case. In such a case, the platform can use either `OT_ERROR_NOT_FOUND` to
* indicate that there was no such registration, or `OT_ERROR_NONE` when invoking the @p aCallback function. The
* OpenThread stack will handle either case correctly.
*
* @param[in] aInstance The OpenThread instance.
* @param[in] aService Information about the service to unregister.
* @param[in] aRequestId The ID associated with this request.
* @param[in] aCallback The callback function pointer to report the outcome (may be NULL if no callback needed).
*
*/
void otPlatDnssdUnregisterService(otInstance *aInstance,
const otPlatDnssdService *aService,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback);
/**
* Registers or updates a host on the infrastructure network's DNS-SD module.
*
* The @p aHost and all its contained information (strings and arrays) are only valid during this call. The
* platform MUST save a copy of the information if it wants to retain the information after returning from this
* function.
*
* The fields in @p aHost follow these rules:
*
* - The `mHostName` field specifies the host name to register. It is never NULL.
* - The `mAddresses` field is an array of IPv6 addresses to register with the host. `mAddressesLength` field provides
* the number of entries in `mAddresses` array. The platform implementation MUST not filter or remove any of
* addresses in the list.
* The OpenThread stack will already ensure that the given addresses are externally reachable. For example, when
* registering host from an SRP registration, link-local or mesh-local addresses associated with the host which are
* intended for use within Thread mesh are not included in `mAddresses` array passed to this API. The `mAddresses`
* array can be empty with zero `mAddressesLength`. In such a case, the platform MUST stop advertising any addresses
* for this host name on the infrastructure DNS-SD.
* - The `mTtl` field specifies the TTL if non-zero. If zero, the platform can choose the TTL to use.
* - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this
* request. If zero, the platform implementation can decided the interface.
*
* Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same
* rules as described in `otPlatDnssdRegisterService()`.
*
* The OpenThread stack will not register the same host (with no changes) that was registered successfully earlier.
* Therefore, the platform implementation does not need to check for duplicate/same host and can assume that calls
* to this function are either registering a new entry or changing some parameter in a previously registered item. As
* a result, these changes always need to be synced on the infrastructure DNS-SD module.
*
* @param[in] aInstance The OpenThread instance.
* @param[in] aHost Information about the host to register.
* @param[in] aRequestId The ID associated with this request.
* @param[in] aCallback The callback function pointer to report the outcome (may be NULL if no callback needed).
*
*/
void otPlatDnssdRegisterHost(otInstance *aInstance,
const otPlatDnssdHost *aHost,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback);
/**
* Unregisters a host on the infrastructure network's DNS-SD module.
*
* The @p aHost and all its contained information (strings and arrays) are only valid during this call. The
* platform MUST save a copy of the information if it wants to retain the information after returning from this
* function.
*
* The fields in @p aHost follow these rules:
*
* - The `mHostName` field specifies the host name to unregister. It is never NULL.
* - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this
* request. If zero, the platform implementation can decided the interface.
* - The rest of the fields in @p aHost structure MUST be ignored in `otPlatDnssdUnregisterHost()` call and may
* be set to zero by the OpenThread stack.
*
* Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same
* rules as described in `otPlatDnssdRegisterService()`.
*
* The OpenThread stack may request the unregistration of a host that was not previously registered, and the platform
* implementation MUST handle this case. In such a case, the platform can use either `OT_ERROR_NOT_FOUND` to indicate
* that there was no such registration, or `OT_ERROR_NONE` when invoking the @p aCallback function. OpenThread stack
* will handle either case correctly.
*
* When unregistering a host, the OpenThread stack will also unregister any previously registered services
* associated with the same host (by calling `otPlatDnssdUnregisterService()`). However, the platform implementation
* MAY assume that unregistering a host also unregisters all its associated services.
*
* @param[in] aInstance The OpenThread instance.
* @param[in] aHost Information about the host to unregister.
* @param[in] aRequestId The ID associated with this request.
* @param[in] aCallback The callback function pointer to report the outcome (may be NULL if no callback needed).
*
*/
void otPlatDnssdUnregisterHost(otInstance *aInstance,
const otPlatDnssdHost *aHost,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback);
/**
* Registers or updates a key record on the infrastructure network's DNS-SD module.
*
* The @p aKey and all its contained information (strings and arrays) are only valid during this call. The
* platform MUST save a copy of the information if it wants to retain the information after returning from this
* function.
*
* The fields in @p aKey follow these rules:
*
* - If the key is associated with a host, `mName` field specifies the host name and `mServiceType` will be NULL.
* - If the key is associated with a service, `mName` field specifies the service instance label and `mServiceType`
* field specifies the service type. In this case the DNS name for key record is `{mName}.{mServiceTye}`.
* - The `mKeyData` field contains the key record's data with `mKeyDataLength` as its length in byes. It is never NULL.
* - The `mClass` fields specifies the resource record class to use when registering key record.
* - The `mTtl` field specifies the TTL if non-zero. If zero, the platform can choose the TTL to use.
* - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this
* request. If zero, the platform implementation can decided the interface.
*
* Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same
* rules as described in `otPlatDnssdRegisterService()`.
*
* The OpenThread stack will not register the same key (with no changes) that was registered successfully earlier.
* Therefore, the platform implementation does not need to check for duplicate/same name and can assume that calls
* to this function are either registering a new key or changing the key data in a previously registered one. As
* a result, these changes always need to be synced on the infrastructure DNS-SD module.
*
* @param[in] aInstance The OpenThread instance.
* @param[in] aHost Information about the key record to register.
* @param[in] aRequestId The ID associated with this request.
* @param[in] aCallback The callback function pointer to report the outcome (may be NULL if no callback needed).
*
*/
void otPlatDnssdRegisterKey(otInstance *aInstance,
const otPlatDnssdKey *aKey,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback);
/**
* Unregisters a key record on the infrastructure network's DNS-SD module.
*
* The @p aKey and all its contained information (strings and arrays) are only valid during this call. The
* platform MUST save a copy of the information if it wants to retain the information after returning from this
* function.
*
* The fields in @p aKey follow these rules:
*
* - If the key is associated with a host, `mName` field specifies the host name and `mServiceType` will be NULL.
* - If the key is associated with a service, `mName` field specifies the service instance label and `mServiceType`
* field specifies the service type. In this case the DNS name for key record is `{mName}.{mServiceTye}`.
* - The `mInfraIfIndex` field, if non-zero, specifies the infrastructure network interface index to use for this
* request. If zero, the platform implementation can decided the interface.
* - The rest of the fields in @p aKey structure MUST be ignored in `otPlatDnssdUnregisterKey()` call and may
* be set to zero by the OpenThread stack.
*
* Regarding the invocation of the @p aCallback and the reuse of the @p aRequestId, this function follows the same
* rules as described in `otPlatDnssdRegisterService()`.
*
* The OpenThread stack may request the unregistration of a key that was not previously registered, and the platform
* implementation MUST handle this case. In such a case, the platform can use either `OT_ERROR_NOT_FOUND` to indicate
* that there was no such registration, or `OT_ERROR_NONE` when invoking the @p aCallback function. the OpenThread
* stack will handle either case correctly.
*
* @param[in] aInstance The OpenThread instance.
* @param[in] aKey Information about the key to unregister.
* @param[in] aRequestId The ID associated with this request.
* @param[in] aCallback The callback function pointer to report the outcome (may be NULL if no callback needed).
*
*/
void otPlatDnssdUnregisterKey(otInstance *aInstance,
const otPlatDnssdKey *aKey,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback);
/**
* @}
*
*/
#ifdef __cplusplus
} // extern "C"
#endif
#endif // OPENTHREAD_PLATFORM_DNSSD_H_
+1
View File
@@ -74,6 +74,7 @@ OT_BUILD_OPTIONS=(
"-DOT_SERVICE=ON"
"-DOT_SLAAC=ON"
"-DOT_SNTP_CLIENT=ON"
"-DOT_SRP_ADV_PROXY=ON"
"-DOT_SRP_CLIENT=ON"
"-DOT_SRP_SERVER=ON"
"-DOT_VENDOR_NAME=OpenThread"
+1
View File
@@ -131,6 +131,7 @@ OT_CLANG_TIDY_BUILD_OPTS=(
'-DOT_SERVICE=ON'
'-DOT_SLAAC=ON'
'-DOT_SNTP_CLIENT=ON'
'-DOT_SRP_ADV_PROXY=ON'
'-DOT_SRP_CLIENT=ON'
'-DOT_SRP_SERVER=ON'
'-DOT_THREAD_VERSION=1.3'
+4
View File
@@ -553,6 +553,8 @@ openthread_core_files = [
"net/dns_platform.cpp",
"net/dns_types.cpp",
"net/dns_types.hpp",
"net/dnssd.cpp",
"net/dnssd.hpp",
"net/dnssd_server.cpp",
"net/dnssd_server.hpp",
"net/icmp6.cpp",
@@ -582,6 +584,8 @@ openthread_core_files = [
"net/sntp_client.hpp",
"net/socket.cpp",
"net/socket.hpp",
"net/srp_advertising_proxy.cpp",
"net/srp_advertising_proxy.hpp",
"net/srp_client.cpp",
"net/srp_client.hpp",
"net/srp_server.cpp",
+2
View File
@@ -168,6 +168,7 @@ set(COMMON_SOURCES
net/dns_dso.cpp
net/dns_platform.cpp
net/dns_types.cpp
net/dnssd.cpp
net/dnssd_server.cpp
net/icmp6.cpp
net/ip4_types.cpp
@@ -182,6 +183,7 @@ set(COMMON_SOURCES
net/netif.cpp
net/sntp_client.cpp
net/socket.cpp
net/srp_advertising_proxy.cpp
net/srp_client.cpp
net/srp_server.cpp
net/tcp6.cpp
+4
View File
@@ -152,6 +152,10 @@ Error InfraIf::HandleStateChanged(uint32_t aIfIndex, bool aIsRunning)
Get<RoutingManager>().HandleInfraIfStateChanged();
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
Get<Srp::AdvertisingProxy>().HandleInfraIfStateChanged();
#endif
exit:
return error;
}
+11
View File
@@ -181,6 +181,17 @@ public:
*/
bool Matches(const uint8_t *aBuffer, uint16_t aLength) const;
/**
* Overloads operator `==` to compare the `Data` content with the content from another one.
*
* @param[in] aOtherData The other `Data` to compare with.
*
* @retval TRUE The two `Data` instances have matching content (same length and same bytes).
* @retval FALSE The two `Data` instances do not have matching content.
*
*/
bool operator==(const Data &aOtherData) const { return mData == aOtherData.mData; }
/**
* Frees any buffer allocated by the `Heap::Data`.
*
+12
View File
@@ -35,6 +35,8 @@
#ifndef CONFIG_PLATFORM_H_
#define CONFIG_PLATFORM_H_
#include "config/srp_server.h"
/**
* @addtogroup config-platform
*
@@ -107,6 +109,16 @@
#define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 0
#endif
/**
* @def OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
*
* Define as 1 to enable DNSSD (mDNS) platform module.
*
*/
#ifndef OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
#define OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
#endif
/**
* @def OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
*
+10
View File
@@ -119,6 +119,16 @@
#define OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT ((4 * 250u) + 250u)
#endif
/**
* @def OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
*
* Define to 1 to enable Advertising Proxy for SRP Sever.
*
*/
#ifndef OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
#define OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE 0
#endif
/**
* @}
*
+8
View File
@@ -87,6 +87,11 @@ Instance::Instance(void)
, mSettings(*this)
, mSettingsDriver(*this)
, mMessagePool(*this)
#if OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
// DNS-SD (mDNS) platform is initialized early to
// allow other modules to use it.
, mDnssd(*this)
#endif
, mIp6(*this)
, mThreadNetif(*this)
, mTmfAgent(*this)
@@ -185,6 +190,9 @@ Instance::Instance(void)
#endif
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
, mSrpServer(*this)
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
, mSrpAdvertisingProxy(*this)
#endif
#endif
#if OPENTHREAD_FTD
, mChildSupervisor(*this)
+19 -1
View File
@@ -88,6 +88,7 @@
#include "net/dhcp6_server.hpp"
#include "net/dns_client.hpp"
#include "net/dns_dso.hpp"
#include "net/dnssd.hpp"
#include "net/dnssd_server.hpp"
#include "net/ip6.hpp"
#include "net/ip6_filter.hpp"
@@ -95,6 +96,7 @@
#include "net/nd_agent.hpp"
#include "net/netif.hpp"
#include "net/sntp_client.hpp"
#include "net/srp_advertising_proxy.hpp"
#include "net/srp_client.hpp"
#include "net/srp_server.hpp"
#include "radio/ble_secure.hpp"
@@ -458,6 +460,12 @@ private:
SettingsDriver mSettingsDriver;
MessagePool mMessagePool;
#if OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
// DNS-SD (mDNS) platform is initialized early to
// allow other modules to use it.
Dnssd mDnssd;
#endif
Ip6::Ip6 mIp6;
ThreadNetif mThreadNetif;
Tmf::Agent mTmfAgent;
@@ -584,6 +592,9 @@ private:
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
Srp::Server mSrpServer;
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
Srp::AdvertisingProxy mSrpAdvertisingProxy;
#endif
#endif
#if OPENTHREAD_FTD
@@ -861,6 +872,10 @@ template <> inline EnergyScanClient &Instance::Get(void) { return mCommissioner.
template <> inline PanIdQueryClient &Instance::Get(void) { return mCommissioner.GetPanIdQueryClient(); }
#endif
#if OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
template <> inline Dnssd &Instance::Get(void) { return mDnssd; }
#endif
#if OPENTHREAD_CONFIG_JOINER_ENABLE
template <> inline MeshCoP::Joiner &Instance::Get(void) { return mJoiner; }
#endif
@@ -1012,7 +1027,7 @@ template <> inline Utils::Otns &Instance::Get(void) { return mOtns; }
template <> inline BorderRouter::RoutingManager &Instance::Get(void) { return mRoutingManager; }
template <> inline BorderRouter::InfraIf &Instance::Get(void) { return mRoutingManager.mInfraIf; }
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#endif
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
template <> inline Nat64::Translator &Instance::Get(void) { return mNat64Translator; }
@@ -1020,7 +1035,10 @@ template <> inline Nat64::Translator &Instance::Get(void) { return mNat64Transla
#if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
template <> inline Srp::Server &Instance::Get(void) { return mSrpServer; }
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
template <> inline Srp::AdvertisingProxy &Instance::Get(void) { return mSrpAdvertisingProxy; }
#endif
#endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
template <> inline Ble::BleSecure &Instance::Get(void) { return mApplicationBleSecure; }
+9 -1
View File
@@ -2254,13 +2254,21 @@ public:
bool IsValid(void) const;
/**
* Returns the ECDSA P-256 public kek.
* Returns the ECDSA P-256 public key.
*
* @returns A reference to the public key.
*
*/
const Crypto::Ecdsa::P256::PublicKey &GetKey(void) const { return mKey; }
/**
* Sets the ECDSA P-256 public key.
*
* @param[in] aKey The public key.
*
*/
void SetKey(const Crypto::Ecdsa::P256::PublicKey &aKey) { mKey = aKey; }
private:
Crypto::Ecdsa::P256::PublicKey mKey;
} OT_TOOL_PACKED_END;
+158
View File
@@ -0,0 +1,158 @@
/*
* 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.
*/
/**
* @file
* This file implements infrastructure DNS-SD (mDNS) platform APIs.
*/
#include "dnssd.hpp"
#if OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
#include "common/code_utils.hpp"
#include "common/locator_getters.hpp"
#include "instance/instance.hpp"
namespace ot {
//---------------------------------------------------------------------------------------------------------------------
// Dnssd::RequestIdRange
void Dnssd::RequestIdRange::Add(RequestId aId)
{
if (IsEmpty())
{
mStart = aId;
mEnd = aId + 1;
}
else if (SerialNumber::IsLess(aId, mStart)) // Equivalent to (aId < mStart)
{
mStart = aId;
}
else if (!SerialNumber::IsLess(aId, mEnd)) // Equivalent to !(aId < mEd) -> (aId >= mEnd)
{
mEnd = aId + 1;
}
}
void Dnssd::RequestIdRange::Remove(RequestId aId)
{
if (!IsEmpty())
{
if (aId == mStart)
{
mStart++;
}
else if (aId + 1 == mEnd)
{
mEnd--;
}
}
}
bool Dnssd::RequestIdRange::Contains(RequestId aId) const
{
// Equivalent to `(aId >= mStart) && (aId < mEnd)`
return (!SerialNumber::IsLess(aId, mStart) && SerialNumber::IsLess(aId, mEnd));
}
//---------------------------------------------------------------------------------------------------------------------
// Dnssd
Dnssd::Dnssd(Instance &aInstance)
: InstanceLocator(aInstance)
{
}
Dnssd::State Dnssd::GetState(void) const { return MapEnum(otPlatDnssdGetState(&GetInstance())); }
void Dnssd::RegisterService(const Service &aService, RequestId aRequestId, RegisterCallback aCallback)
{
if (IsReady())
{
otPlatDnssdRegisterService(&GetInstance(), &aService, aRequestId, aCallback);
}
}
void Dnssd::UnregisterService(const Service &aService, RequestId aRequestId, RegisterCallback aCallback)
{
if (IsReady())
{
otPlatDnssdUnregisterService(&GetInstance(), &aService, aRequestId, aCallback);
}
}
void Dnssd::RegisterHost(const Host &aHost, RequestId aRequestId, RegisterCallback aCallback)
{
if (IsReady())
{
otPlatDnssdRegisterHost(&GetInstance(), &aHost, aRequestId, aCallback);
}
}
void Dnssd::UnregisterHost(const Host &aHost, RequestId aRequestId, RegisterCallback aCallback)
{
if (IsReady())
{
otPlatDnssdUnregisterHost(&GetInstance(), &aHost, aRequestId, aCallback);
}
}
void Dnssd::RegisterKey(const Key &aKey, RequestId aRequestId, RegisterCallback aCallback)
{
if (IsReady())
{
otPlatDnssdRegisterKey(&GetInstance(), &aKey, aRequestId, aCallback);
}
}
void Dnssd::UnregisterKey(const Key &aKey, RequestId aRequestId, RegisterCallback aCallback)
{
if (IsReady())
{
otPlatDnssdUnregisterKey(&GetInstance(), &aKey, aRequestId, aCallback);
}
}
void Dnssd::HandleStateChange(void)
{
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
Get<Srp::AdvertisingProxy>().HandleDnssdPlatformStateChange();
#endif
}
extern "C" void otPlatDnssdStateHandleStateChange(otInstance *aInstance)
{
AsCoreType(aInstance).Get<Dnssd>().HandleStateChange();
}
} // namespace ot
#endif // OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
+282
View File
@@ -0,0 +1,282 @@
/*
* 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.
*/
/**
* @file
* This file includes definitions for infrastructure DNS-SD (mDNS) platform.
*/
#ifndef DNSSD_HPP_
#define DNSSD_HPP_
#include "openthread-core-config.h"
#if OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
#include <openthread/platform/dnssd.h>
#include "common/clearable.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "net/ip6_address.hpp"
namespace ot {
/**
* @addtogroup core-dns
*
* @brief
* This module includes definitions for DNS-SD (mDNS) platform.
*
* @{
*
*/
extern "C" void otPlatDnssdStateHandleStateChange(otInstance *aInstance);
/**
* Represents DNS-SD (mDNS) platform.
*
*/
class Dnssd : public InstanceLocator, private NonCopyable
{
friend void otPlatDnssdStateHandleStateChange(otInstance *aInstance);
public:
/**
* Represents state of DNS-SD platform.
*
*/
enum State : uint8_t
{
kStopped = OT_PLAT_DNSSD_STOPPED, ///< Stopped and unable to register any service or host.
kReady = OT_PLAT_DNSSD_READY ///< Running and ready to register service or host.
};
typedef otPlatDnssdRequestId RequestId; ///< A request ID.
typedef otPlatDnssdRegisterCallback RegisterCallback; ///< The registration request callback
class Host : public otPlatDnssdHost, public Clearable<Host> ///< Host information.
{
};
class Service : public otPlatDnssdService, public Clearable<Service> ///< Service information.
{
};
class Key : public otPlatDnssdKey, public Clearable<Key> ///< Key information
{
};
/**
* Represents a range of `RequestId` values.
*
* The range is stored using start and end ID values. The implementation handles the case when ID values roll over.
*
*/
struct RequestIdRange : public Clearable<RequestIdRange>
{
/**
* Initializes a range as empty.
*
*/
RequestIdRange(void)
: mStart(0)
, mEnd(0)
{
}
/**
* Adds a request ID to the range.
*
* @param[in] aId The ID to add to the range.
*
*/
void Add(RequestId aId);
/**
* Removes a request ID from the range.
*
* @param[in] aId The ID to remove from the range.
*
*/
void Remove(RequestId aId);
/**
* Indicates whether or not a given ID is contained within the range.
*
* @param[in] aId The ID to check.
*
* @retval TRUE The @p aID is contained within the range.
* @retval FALSE The @p aId is not contained within the range.
*
*/
bool Contains(RequestId aId) const;
/**
* Indicates whether or not the range is empty.
*
* @retval TRUE The range is empty.
* @retval FALSE The range is not empty.
*
*/
bool IsEmpty(void) const { return (mStart == mEnd); }
private:
// The range is represented as all `RequestId` values from
// `mStart` up to, but not including, `mEnd`. It uses serial
// number arithmetic logic when comparing `RequestId` values,
// so `Contains()` and other methods work correctly even when
// the ID value rolls over.
RequestId mStart;
RequestId mEnd;
};
/**
* Initializes `Dnssd` object.
*
* @param[in] aInstance The OpenThread instance.
*
*/
explicit Dnssd(Instance &aInstance);
/**
* Gets the current state of DNS-SD platform module.
*
* @returns The current state of DNS-SD platform.
*
*/
State GetState(void) const;
/**
* Indicates whether or not DNS-SD platform is ready (in `kReady` state).
*
* @retval TRUE The DNS-SD platform is ready.
* @retval FALSE The DNS-SD platform is not ready.
*
*/
bool IsReady(void) const { return GetState() == kReady; }
/**
* Registers or updates a service on the infrastructure network's DNS-SD module.
*
* Refer to the documentation for `otPlatDnssdRegisterService()`, for a more detailed description of the behavior
* of this method.
*
* @param[in] aService Information about service to unregister.
* @param[in] aRequestId The ID associated with this request.
* @param[in] aCallback The callback function pointer to report the outcome (may be `nullptr`).
*
*/
void RegisterService(const Service &aService, RequestId aRequestId, RegisterCallback aCallback);
/**
* Unregisters a service on the infrastructure network's DNS-SD module.
*
* Refer to the documentation for `otPlatDnssdUnregisterService()`, for a more detailed description of the behavior
* of this method.
*
* @param[in] aService Information about service to unregister.
* @param[in] aRequestId The ID associated with this request.
* @param[in] aCallback The callback function pointer to report the outcome (may be `nullptr`).
*
*/
void UnregisterService(const Service &aService, RequestId aRequestId, RegisterCallback aCallback);
/**
* Registers or updates a host on the infrastructure network's DNS-SD module.
*
* Refer to the documentation for `otPlatDnssdRegisterHost()`, for a more detailed description of the behavior
* of this method.
*
* @param[in] aHost Information about host to register.
* @param[in] aRequestId The ID associated with this request.
* @param[in] aCallback The callback function pointer to report the outcome (may be `nullptr`).
*
*/
void RegisterHost(const Host &aHost, RequestId aRequestId, RegisterCallback aCallback);
/**
* Unregisters a host on the infrastructure network's DNS-SD module.
*
* Refer to the documentation for `otPlatDnssdUnregisterHost()`, for a more detailed description of the behavior
* of this method.
*
* @param[in] aHost Information about the host to unregister.
* @param[in] aRequestId The ID associated with this request.
* @param[in] aCallback The callback function pointer to report the outcome (may be NULL if no callback needed).
*
*/
void UnregisterHost(const Host &aHost, RequestId aRequestId, RegisterCallback aCallback);
/**
* Registers or updates a key record on the infrastructure network's DNS-SD module.
*
* Refer to the documentation for `otPlatDnssdRegisterKey()`, for a more detailed description of the behavior
* of this method.
*
* @param[in] aKey Information about the key to register.
* @param[in] aRequestId The ID associated with this request.
* @param[in] aCallback The callback function pointer to report the outcome (may be `nullptr`).
*
*/
void RegisterKey(const Key &aKey, RequestId aRequestId, RegisterCallback aCallback);
/**
* Unregisters a key record on the infrastructure network's DNS-SD module.
*
* Refer to the documentation for `otPlatDnssdUnregisterKey()`, for a more detailed description of the behavior
* of this method.
*
* @param[in] aKey Information about the key to unregister.
* @param[in] aRequestId The ID associated with this request.
* @param[in] aCallback The callback function pointer to report the outcome (may be NULL if no callback needed).
*
*/
void UnregisterKey(const Key &aKey, RequestId aRequestId, RegisterCallback aCallback);
private:
void HandleStateChange(void);
};
/**
* @}
*
*/
DefineMapEnum(otPlatDnssdState, Dnssd::State);
DefineCoreType(otPlatDnssdService, Dnssd::Service);
DefineCoreType(otPlatDnssdHost, Dnssd::Host);
DefineCoreType(otPlatDnssdKey, Dnssd::Key);
} // namespace ot
#endif // OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
#endif // DNSSD_HPP_
File diff suppressed because it is too large Load Diff
+322
View File
@@ -0,0 +1,322 @@
/*
* 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.
*/
/**
* @file
* This file includes definitions for Advertising Proxy.
*/
#ifndef SRP_ADVERTISING_PROXY_HPP_
#define SRP_ADVERTISING_PROXY_HPP_
#include "openthread-core-config.h"
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
#if !OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
#error "OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE requires OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE"
#endif
#if !OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
#error "OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE requires OPENTHREAD_CONFIG_SRP_SERVER_ENABLE"
#endif
#if !OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
#error "OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE requires OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE"
#endif
#include "common/clearable.hpp"
#include "common/heap_allocatable.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "common/owning_list.hpp"
#include "common/tasklet.hpp"
#include "common/timer.hpp"
#include "net/dnssd.hpp"
#include "net/srp_server.hpp"
namespace ot {
namespace Srp {
/**
* Implements SRP Advertising Proxy.
*
*/
class AdvertisingProxy : public InstanceLocator, private NonCopyable
{
public:
typedef Server::Host Host; ///< An SRP server host registration.
typedef Server::Service Service; ///< An SRP server service registration.
/**
* Represents counters for Advertising Proxy.
*
*/
struct Counters : public Clearable<Counters>
{
uint32_t mAdvTotal; ///< Total number of advertisement requests, i.e., calls to `Advertise()`.
uint32_t mAdvReplaced; ///< Number of advertisements that were replaced by a newer one.
uint32_t mAdvSkipped; ///< Number of advertisement that were skipped (DNS-SD platform not yet ready).
uint32_t mAdvSuccessful; ///< Number of successful adv (all requests registered successfully).
uint32_t mAdvRejected; ///< Number of rejected adv (at least one request was rejected by DNS-SD plat).
uint32_t mAdvTimeout; ///< Number of advertisements that timed out (no response from DNS-SD platform).
uint32_t mAdvHostRemovals; ///< Number of host removal adv, i.e., calls to `AdvertiseRemovalOf(Host &)`
uint32_t mAdvServiceRemovals; ///< Number of service removal adv, i.e., calls to `AdvertiseRemovalOf(Service &)`
uint32_t mStateChanges; ///< Number of state changes of Advertising Proxy.
};
/**
* Initializes the `AdvertisingProxy` object.
*
* @param[in] aInstance The OpenThread instance
*
*/
explicit AdvertisingProxy(Instance &aInstance);
/**
* Indicates whether or not the Advertising Proxy is running.
*
* @retval TRUE The Advertising Proxy is running.
* @retval FALSE The Advertising Proxy is not running (it is stopped).
*
*/
bool IsRunning(void) const { return mState == kStateRunning; }
/**
* Requests advertisement of a newly received SRP Update message.
*
* Once advertisement is completed, `AdvertisingProxy` notifies server by invoking `Server::CommitSrpUpdate()`
* using the same `aHost` and `aMetadata` as input parameters along with an `Error` indicating the outcome of the
* advertisement.
*
* The `aHost` instance ownership is passed to `AdvertisingProxy` until it is passed back to the `Server` in the
* `CommitSrpUpdate()` call. The call to `CommitSrpUpdate()` may happen before this method returns, for example,
* if the proxy is not running and therefore the advertisement is skipped.
*
* @param[in] aHost The `aHost` instance constructed from processing a newly received SRP Update message.
* @param[in] aMetadata The `MessageMetadata` associated with the received SRP Update message by server.
*
*/
void Advertise(Host &aHost, const Server::MessageMetadata &aMetadata);
/**
* Requests advertisement of removal of an already committed host and all its services, for example, due to its
* lease expiration.
*
* The removal does not use any callback to notify the SRP server since the server always immediately commits the
* removed entries.
*
* If there is an outstanding advertisement request (an earlier call to `Advertise()` that has not yet completed)
* that is registering the same host name as @p aHost that is being removed, the outstanding advertisement is
* rejected using the `kErrorAbort` error. This situation can happen if the client tries to refresh or update its
* registration close to its lease expiration time. By rejecting any outstanding advertisements, we ensure that an
* expired host is not re-added by mistake due to a delay in registration by the DNS-SD platform. The error is
* passed back to the client, triggering it to retry its registration.
*
* @param[in] aHost The host which is being removed.
*
*/
void AdvertiseRemovalOf(Host &aHost);
/**
* Requests advertisement of removal of an already committed service, for example, due to its lease expiration.
*
* The removal does not use any callback to notify the SRP server since the server always immediately commits the
* removed services.
*
* If there is an outstanding advertisement request (an earlier call to `Advertise()` that has not yet completed)
* that is registering the same service as @p aService that is being removed, we skip the advertisement of service
* removal (do not unregister the service on infrastructure DNS-SD). This ensures that when the outstanding
* advertisement is completed, the service is re-added successfully (and it is still being advertised by proxy).
* This behavior is different from `AdvertiseRemovalOf(Host &)`, where the outstanding advertisement is rejected
* because service removals are individual, compared to when removing a host where the host and all its associated
* services are removed.
*
* @param[in] aHost The host which is being removed.
*
*/
void AdvertiseRemovalOf(Service &aService);
/**
* Gets the set of counters.
*
* @returns The `AdvertisingProxy` counter.
*
*/
const Counters &GetCounters(void) const { return mCounters; }
/**
* Resets the counters
*
*/
void ResetCounters(void) { mCounters.Clear(); }
/**
* Gets the advertisement timeout (in msec).
*
* The default value of `OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT` is used when not explicitly set.
*
* @returns The advertisement timeout (in msec).
*
*/
uint32_t GetAdvTimeout(void) const { return mAdvTimeout; }
/**
* Sets the advertisement timeout.
*
* Changing the timeout is intended for testing purposes only. This allows tests to use a long timeout to validate
* the behavior of `AdvertisingProxy` when new `Advertise()` requests replace entries in earlier requests.
*
* @param[in] aTimeout The advertisement timeout (in msec).
*
*/
void SetAdvTimeout(uint32_t aTimeout) { mAdvTimeout = Max(aTimeout, kAdvTimeout); }
/**
* Notifies `AdvertisingProxy` that SRP sever state changed.
*
*/
void HandleServerStateChange(void) { UpdateState(); }
/**
* Notifies `AdvertisingProxy` that DND-SD platform state changed.
*
*/
void HandleDnssdPlatformStateChange(void) { UpdateState(); }
/**
* Notifies `AdvertisingProxy` that `InfraIf` state changed.
*
*/
void HandleInfraIfStateChanged(void) { UpdateState(); }
private:
typedef Dnssd::RequestId RequestId;
typedef char DnsName[Dns::Name::kMaxNameSize];
static constexpr RequestId kInvalidRequestId = Server::kInvalidRequestId;
static constexpr uint32_t kAdvTimeout = OPENTHREAD_CONFIG_SRP_SERVER_SERVICE_UPDATE_TIMEOUT; // in msec
enum State : uint8_t
{
kStateStopped,
kStateRunning,
};
struct AdvInfo : public Heap::Allocatable<AdvInfo>, public LinkedListEntry<AdvInfo>, public GetProvider<AdvInfo>
{
struct CompletionChecker
{
// Used in `Matches()` to check if advertisement is
// completed (successfully or failed).
};
struct ExpirationChecker
{
explicit ExpirationChecker(TimeMilli aNow)
: mNow(aNow)
{
}
TimeMilli mNow;
};
AdvInfo(Host &aHost, const Server::MessageMetadata &aMetadata, uint32_t aTimeout);
void SignalServerToCommit(void);
bool IsCompleted(void) const;
bool Matches(const CompletionChecker &) const { return IsCompleted(); }
bool Matches(const ExpirationChecker &aChecker) const { return (mExpireTime <= aChecker.mNow); }
Instance &GetInstance(void) const { return mHost.GetInstance(); }
AdvInfo *mNext;
AdvInfo *mBlockingAdv;
Host &mHost;
TimeMilli mExpireTime;
Server::MessageMetadata mMessageMetadata;
Ip6::MessageInfo mMessageInfo;
Error mError;
};
template <typename Entry> void UpdateAdvIdRangeOn(Entry &aEntry);
template <typename Entry> bool IsRegisteredOrRegistering(const Entry &aEntry) const;
template <typename Entry> bool IsKeyRegisteredOrRegistering(const Entry &aEntry) const;
template <typename Entry> void DecideToAdvertise(Entry &aEntry, bool aUnregisterEntry, bool aUnregisterKey);
template <typename Entry> void UpdateKeyRegistrationStatus(Entry &aEntry, const Entry &aExistingEntry);
template <typename Entry> bool CompareAndUpdate(Entry &aEntry, Entry &aExistingEntry);
template <typename Entry> bool EntriesMatch(const Entry &aFirstEntry, const Entry &aSecondEntry);
void Start(void);
void Stop(void);
void UpdateState(void);
RequestId AllocateNextRequestId(void);
void Advertise(Host &aHost);
void UnregisterHostAndItsServicesAndKeys(Host &aHost);
bool CompareAndUpdateHostAndServices(Host &aHost, Host &aExistingHost);
bool CompareAndUpdateHost(Host &aHost, Host &aExistingHost);
bool CompareAndUpdateService(Service &aService, Service &aExistingService);
void RegisterHost(Host &aHost);
void UnregisterHost(Host &aHost);
void RegisterService(Service &aService);
void UnregisterService(Service &aService);
void RegisterKey(Host &aHost);
void RegisterKey(Service &aService);
void RegisterKey(const char *aName,
const char *aServiceType,
const Host::Key &aKey,
RequestId aRequestId,
uint32_t aTtl);
void UnregisterKey(Service &aService);
void UnregisterKey(Host &aHost);
void UnregisterKey(const char *aName, const char *aServiceType);
void CopyNameAndRemoveDomain(DnsName &aName, const char *aFullName);
static void HandleRegistered(otInstance *aInstance, otPlatDnssdRequestId aRequestId, otError aError);
void HandleRegistered(RequestId aRequestId, Error aError);
bool HandleRegisteredRequestIdOn(Host &aHost, RequestId aRequestId, Error aError);
void HandleTimer(void);
void HandleTasklet(void);
void SignalAdvCompleted(AdvInfo &aAdvInfo);
using AdvTimer = TimerMilliIn<AdvertisingProxy, &AdvertisingProxy::HandleTimer>;
using AdvTasklet = TaskletIn<AdvertisingProxy, &AdvertisingProxy::HandleTasklet>;
State mState;
RequestId mCurrentRequestId;
uint32_t mAdvTimeout;
OwningList<AdvInfo> mAdvInfoList;
AdvTimer mTimer;
AdvTasklet mTasklet;
Counters mCounters;
};
} // namespace Srp
} // namespace ot
#endif // OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
#endif // SRP_ADVERTISING_PROXY_HPP_
+96 -11
View File
@@ -329,7 +329,7 @@ void Server::RemoveHost(Host *aHost, RetainName aRetainName)
if (mServiceUpdateHandler.IsSet())
{
uint32_t updateId = AllocateId();
uint32_t updateId = AllocateServiceUpdateId();
LogInfo("SRP update handler is notified (updatedId = %lu)", ToUlong(updateId));
mServiceUpdateHandler.Invoke(updateId, aHost, static_cast<uint32_t>(kDefaultEventsHandlerTimeout));
@@ -339,6 +339,12 @@ void Server::RemoveHost(Host *aHost, RetainName aRetainName)
// only when there is system failure of the platform mDNS implementation
// and in which case the host is not expected to be still registered.
}
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
else
{
Get<AdvertisingProxy>().AdvertiseRemovalOf(*aHost);
}
#endif
if (!aRetainName)
{
@@ -456,7 +462,7 @@ void Server::CommitSrpUpdate(Error aError,
uint32_t grantedKeyLease = 0;
bool useShortLease = aHost.ShouldUseShortLeaseOption();
if (aError != kErrorNone)
if (aError != kErrorNone || (mState != kStateRunning))
{
aHost.Free();
ExitNow();
@@ -525,7 +531,27 @@ void Server::CommitSrpUpdate(Error aError,
if (!aHost.HasService(existingService->GetInstanceName()))
{
aHost.AddService(*existingService);
existingService->Log(Service::kKeepUnchanged);
// If host is deleted we make sure to add any existing
// service that is not already included as deleted.
// When processing an SRP update message that removes
// a host, we construct `aHost` and add any existing
// services that we have for the same host name as
// deleted. However, due to asynchronous nature
// of "update handler" (advertising proxy), by the
// time we get the callback to commit `aHost`, there
// may be new services added that were not included
// when constructing `aHost`.
if (aHost.IsDeleted() && !existingService->IsDeleted())
{
existingService->mIsDeleted = true;
existingService->Log(Service::kRemoveButRetainName);
}
else
{
existingService->Log(Service::kKeepUnchanged);
}
}
else
{
@@ -599,6 +625,10 @@ void Server::Start(void)
PrepareSocket();
LogInfo("Start listening on port %u", mPort);
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
Get<AdvertisingProxy>().HandleServerStateChange();
#endif
exit:
return;
}
@@ -708,6 +738,10 @@ void Server::Stop(void)
IgnoreError(mSocket.Close());
mHasRegisteredAnyService = false;
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
Get<AdvertisingProxy>().HandleServerStateChange();
#endif
exit:
return;
}
@@ -1202,18 +1236,25 @@ Error Server::ProcessAdditionalSection(Host *aHost, const Message &aMessage, Mes
aHost->SetLease(leaseOption.GetLeaseInterval());
aHost->SetKeyLease(leaseOption.GetKeyLeaseInterval());
for (Service &service : aHost->mServices)
{
if (aHost->GetLease() == 0)
{
service.mIsDeleted = true;
}
service.mLease = service.mIsDeleted ? 0 : leaseOption.GetLeaseInterval();
service.mKeyLease = leaseOption.GetKeyLeaseInterval();
}
// If the client included the short variant of Lease Option,
// server must also use the short variant in its response.
aHost->SetUseShortLeaseOption(leaseOption.IsShortVariant());
if (aHost->GetLease() > 0)
{
uint8_t hostAddressesNum;
aHost->GetAddresses(hostAddressesNum);
// There MUST be at least one valid address if we have nonzero lease.
VerifyOrExit(hostAddressesNum > 0, error = kErrorFailed);
VerifyOrExit(aHost->mAddresses.GetLength() > 0, error = kErrorFailed);
}
// SIG(0).
@@ -1340,6 +1381,7 @@ void Server::HandleUpdate(Host &aHost, const MessageMetadata &aMetadata)
SuccessOrExit(error = service->mServiceName.Set(existingService.GetServiceName()));
service->mIsDeleted = true;
service->mKeyLease = existingService.mKeyLease;
}
exit:
@@ -1410,6 +1452,17 @@ void Server::InformUpdateHandlerOrCommit(Error aError, Host &aHost, const Messag
aError = kErrorNoBufs;
}
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
else if (aError == kErrorNone)
{
// Ask `AdvertisingProxy` to advertise the new update.
// Proxy will report the outcome by calling
// `Server::CommitSrpUpdate()` directly.
Get<AdvertisingProxy>().Advertise(aHost, aMetadata);
ExitNow();
}
#endif
CommitSrpUpdate(aError, aHost, aMetadata);
@@ -1421,10 +1474,12 @@ void Server::SendResponse(const Dns::UpdateHeader &aHeader,
Dns::UpdateHeader::Response aResponseCode,
const Ip6::MessageInfo &aMessageInfo)
{
Error error;
Error error = kErrorNone;
Message *response = nullptr;
Dns::UpdateHeader header;
VerifyOrExit(mState == kStateRunning, error = kErrorInvalidState);
response = GetSocket().NewMessage();
VerifyOrExit(response != nullptr, error = kErrorNoBufs);
@@ -1752,6 +1807,15 @@ Error Server::Service::Init(const char *aInstanceName, const char *aInstanceLabe
mUpdateTime = aUpdateTime;
mIsDeleted = false;
mIsCommitted = false;
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
mIsRegistered = false;
mIsKeyRegistered = false;
mIsReplaced = false;
mShouldAdvertise = false;
mShouldRegisterKey = false;
mAdvId = kInvalidRequestId;
mKeyAdvId = kInvalidRequestId;
#endif
mParsedDeleteAllRrset = false;
mParsedSrv = false;
@@ -1930,6 +1994,15 @@ Server::Host::Host(Instance &aInstance, TimeMilli aUpdateTime)
, mUpdateTime(aUpdateTime)
, mParsedKey(false)
, mUseShortLeaseOption(false)
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
, mIsRegistered(false)
, mIsKeyRegistered(false)
, mIsReplaced(false)
, mShouldAdvertise(false)
, mShouldRegisterKey(false)
, mAdvId(kInvalidRequestId)
, mKeyAdvId(kInvalidRequestId)
#endif
{
}
@@ -2041,12 +2114,18 @@ void Server::Host::RemoveService(Service *aService, RetainName aRetainName, Noti
VerifyOrExit(aService != nullptr);
aService->mIsDeleted = true;
aService->mLease = 0;
if (!aRetainName)
{
aService->mKeyLease = 0;
}
aService->Log(aRetainName ? Service::kRemoveButRetainName : Service::kFullyRemove);
if (aNotifyServiceHandler && server.mServiceUpdateHandler.IsSet())
{
uint32_t updateId = server.AllocateId();
uint32_t updateId = server.AllocateServiceUpdateId();
LogInfo("SRP update handler is notified (updatedId = %lu)", ToUlong(updateId));
server.mServiceUpdateHandler.Invoke(updateId, this, static_cast<uint32_t>(kDefaultEventsHandlerTimeout));
@@ -2056,6 +2135,12 @@ void Server::Host::RemoveService(Service *aService, RetainName aRetainName, Noti
// failure of the platform mDNS implementation and in which case the
// service is not expected to be still registered.
}
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
else if (aNotifyServiceHandler)
{
Get<AdvertisingProxy>().AdvertiseRemovalOf(*aService);
}
#endif
if (!aRetainName)
{
@@ -2119,7 +2204,7 @@ Server::UpdateMetadata::UpdateMetadata(Instance &aInstance, Host &aHost, const M
, mNext(nullptr)
, mExpireTime(TimerMilli::GetNow() + kDefaultEventsHandlerTimeout)
, mDnsHeader(aMessageMetadata.mDnsHeader)
, mId(Get<Server>().AllocateId())
, mId(Get<Server>().AllocateServiceUpdateId())
, mTtlConfig(aMessageMetadata.mTtlConfig)
, mLeaseConfig(aMessageMetadata.mLeaseConfig)
, mHost(aHost)
+31 -1
View File
@@ -72,6 +72,7 @@
#include "common/timer.hpp"
#include "crypto/ecdsa.hpp"
#include "net/dns_types.hpp"
#include "net/dnssd.hpp"
#include "net/ip6.hpp"
#include "net/ip6_address.hpp"
#include "net/udp6.hpp"
@@ -101,6 +102,8 @@ class RoutingManager;
namespace Srp {
class AdvertisingProxy;
/**
* Implements the SRP server.
*
@@ -112,6 +115,7 @@ class Server : public InstanceLocator, private NonCopyable
friend class Service;
friend class Host;
friend class Dns::ServiceDiscovery::Server;
friend class AdvertisingProxy;
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
friend class BorderRouter::RoutingManager;
#endif
@@ -128,6 +132,10 @@ class Server : public InstanceLocator, private NonCopyable
kNotifyServiceHandler = true,
};
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
static constexpr Dnssd::RequestId kInvalidRequestId = 0;
#endif
public:
static constexpr uint16_t kUdpPortMin = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MIN; ///< The reserved min port.
static constexpr uint16_t kUdpPortMax = OPENTHREAD_CONFIG_SRP_SERVER_UDP_PORT_MAX; ///< The reserved max port.
@@ -185,6 +193,7 @@ public:
friend class LinkedList<Service>;
friend class LinkedListEntry<Service>;
friend class Heap::Allocatable<Service>;
friend class AdvertisingProxy;
public:
/**
@@ -432,6 +441,15 @@ public:
bool mParsedDeleteAllRrset : 1;
bool mParsedSrv : 1;
bool mParsedTxt : 1;
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
bool mIsRegistered : 1;
bool mIsKeyRegistered : 1;
bool mIsReplaced : 1;
bool mShouldAdvertise : 1;
bool mShouldRegisterKey : 1;
Dnssd::RequestId mAdvId;
Dnssd::RequestId mKeyAdvId;
#endif
};
/**
@@ -447,6 +465,7 @@ public:
friend class Server;
friend class LinkedListEntry<Host>;
friend class Heap::Allocatable<Host>;
friend class AdvertisingProxy;
public:
typedef Crypto::Ecdsa::P256::PublicKey Key; ///< Host key (public ECDSA P256 key).
@@ -603,6 +622,16 @@ public:
LinkedList<Service> mServices;
bool mParsedKey : 1;
bool mUseShortLeaseOption : 1; // Use short lease option (lease only 4 bytes).
#if OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE
bool mIsRegistered : 1;
bool mIsKeyRegistered : 1;
bool mIsReplaced : 1;
bool mShouldAdvertise : 1;
bool mShouldRegisterKey : 1;
Dnssd::RequestId mAdvId;
Dnssd::RequestId mKeyAdvId;
Dnssd::RequestIdRange mAdvIdRange;
#endif
};
/**
@@ -945,6 +974,7 @@ private:
void SelectPort(void);
void PrepareSocket(void);
Ip6::Udp::Socket &GetSocket(void);
LinkedList<Host> &GetHosts(void) { return mHosts; }
#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
void HandleDnssdServerStateChange(void);
@@ -953,7 +983,7 @@ private:
void HandleNetDataPublisherEvent(NetworkData::Publisher::Event aEvent);
ServiceUpdateId AllocateId(void) { return mServiceUpdateId++; }
ServiceUpdateId AllocateServiceUpdateId(void) { return mServiceUpdateId++; }
void InformUpdateHandlerOrCommit(Error aError, Host &aHost, const MessageMetadata &aMetadata);
void CommitSrpUpdate(Error aError, Host &aHost, const MessageMetadata &aMessageMetadata);
+1
View File
@@ -68,6 +68,7 @@ set -euxo pipefail
-DOT_SERVICE=ON \
-DOT_SLAAC=ON \
-DOT_SNTP_CLIENT=ON \
-DOT_SRN_ADV_PROXY=ON \
-DOT_SRP_CLIENT=ON \
-DOT_SRP_SERVER=ON \
-DOT_THREAD_VERSION=1.3 \
@@ -61,6 +61,10 @@
#define OPENTHREAD_CONFIG_DNS_DSO_ENABLE 1
#define OPENTHREAD_CONFIG_SRP_SERVER_ADVERTISING_PROXY_ENABLE 1
#define OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE 1
#define OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE 1
#define OPENTHREAD_CONFIG_BORDER_ROUTING_USE_HEAP_ENABLE 1
+21
View File
@@ -1116,6 +1116,27 @@ target_link_libraries(ot-test-serial-number
add_test(NAME ot-test-serial-number COMMAND ot-test-serial-number)
add_executable(ot-test-srp-adv-proxy
test_srp_adv_proxy.cpp
)
target_include_directories(ot-test-srp-adv-proxy
PRIVATE
${COMMON_INCLUDES}
)
target_compile_options(ot-test-srp-adv-proxy
PRIVATE
${COMMON_COMPILE_OPTIONS}
)
target_link_libraries(ot-test-srp-adv-proxy
PRIVATE
${COMMON_LIBS}
)
add_test(NAME ot-test-srp-adv-proxy COMMAND ot-test-srp-adv-proxy)
add_executable(ot-test-srp-server
test_srp_server.cpp
)
+77
View File
@@ -738,4 +738,81 @@ otError otPlatBleGattServerIndicate(otInstance *aInstance, uint16_t aHandle, con
}
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
#if OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
OT_TOOL_WEAK otPlatDnssdState otPlatDnssdGetState(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return OT_PLAT_DNSSD_STOPPED;
}
OT_TOOL_WEAK void otPlatDnssdRegisterService(otInstance *aInstance,
const otPlatDnssdService *aService,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aService);
OT_UNUSED_VARIABLE(aRequestId);
OT_UNUSED_VARIABLE(aCallback);
}
OT_TOOL_WEAK void otPlatDnssdUnregisterService(otInstance *aInstance,
const otPlatDnssdService *aService,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aService);
OT_UNUSED_VARIABLE(aRequestId);
OT_UNUSED_VARIABLE(aCallback);
}
OT_TOOL_WEAK void otPlatDnssdRegisterHost(otInstance *aInstance,
const otPlatDnssdHost *aHost,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aHost);
OT_UNUSED_VARIABLE(aRequestId);
OT_UNUSED_VARIABLE(aCallback);
}
OT_TOOL_WEAK void otPlatDnssdUnregisterHost(otInstance *aInstance,
const otPlatDnssdHost *aHost,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aHost);
OT_UNUSED_VARIABLE(aRequestId);
OT_UNUSED_VARIABLE(aCallback);
}
OT_TOOL_WEAK void otPlatDnssdRegisterKey(otInstance *aInstance,
const otPlatDnssdKey *aKey,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aKey);
OT_UNUSED_VARIABLE(aRequestId);
OT_UNUSED_VARIABLE(aCallback);
}
OT_TOOL_WEAK void otPlatDnssdUnregisterKey(otInstance *aInstance,
const otPlatDnssdKey *aKey,
otPlatDnssdRequestId aRequestId,
otPlatDnssdRegisterCallback aCallback)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aKey);
OT_UNUSED_VARIABLE(aRequestId);
OT_UNUSED_VARIABLE(aCallback);
}
#endif // OPENTHREAD_CONFIG_PLATFORM_DNSSD_ENABLE
} // extern "C"
+1
View File
@@ -34,6 +34,7 @@
#include <openthread/config.h>
#include <openthread/platform/alarm-milli.h>
#include <openthread/platform/dns.h>
#include <openthread/platform/dnssd.h>
#include <openthread/platform/dso_transport.h>
#include <openthread/platform/entropy.h>
#include <openthread/platform/logging.h>
File diff suppressed because it is too large Load Diff