From b5b5994651d324fc283b43344c83691406798110 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Mon, 29 Mar 2021 21:30:36 -0700 Subject: [PATCH] [srp-client] adding buffer and service pool module (#6257) This commit adds a new module `Utils::SrpClientBuffers` which provides string/data buffers and a pool of service entries for use for SRP client. OpenThread SRP client implementation requires that the service, string/data buffers passed as parameters to its API to persist. This allows flexibility in how the SRP client can be used (users of API can decide on how to manage the memory). The new module provides an option to OT API user to use the buffer and service pool to allocate/free items (e.g., service entries). The new module is enabled by `OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE`. A set of new configs specifies the number of service entries in the pool, number of host address entries, and the size of different string buffers (e.g, size of service instance string, etc). This commit also updates CLI and NCP implementations to use the new common service pool for SRP client commands. --- Android.mk | 2 + include/Makefile.am | 1 + include/openthread/BUILD.gn | 1 + include/openthread/instance.h | 2 +- include/openthread/srp_client_buffers.h | 179 +++++++++++++++++ src/cli/cli_config.h | 24 --- src/cli/cli_srp_client.cpp | 212 ++++++++++---------- src/cli/cli_srp_client.hpp | 22 +-- src/core/BUILD.gn | 3 + src/core/CMakeLists.txt | 2 + src/core/Makefile.am | 3 + src/core/api/srp_client_buffers_api.cpp | 97 +++++++++ src/core/common/instance.hpp | 7 + src/core/common/pool.hpp | 14 ++ src/core/config/srp_client.h | 71 ++++++- src/core/thread/thread_netif.cpp | 3 + src/core/thread/thread_netif.hpp | 4 + src/core/utils/srp_client_buffers.cpp | 72 +++++++ src/core/utils/srp_client_buffers.hpp | 248 ++++++++++++++++++++++++ src/ncp/ncp_base.cpp | 1 - src/ncp/ncp_base.hpp | 20 +- src/ncp/ncp_base_mtd.cpp | 118 ++++++----- src/ncp/ncp_config.h | 24 --- 23 files changed, 882 insertions(+), 248 deletions(-) create mode 100644 include/openthread/srp_client_buffers.h create mode 100644 src/core/api/srp_client_buffers_api.cpp create mode 100644 src/core/utils/srp_client_buffers.cpp create mode 100644 src/core/utils/srp_client_buffers.hpp diff --git a/Android.mk b/Android.mk index 4ae6cd2c7..4d05813b3 100644 --- a/Android.mk +++ b/Android.mk @@ -194,6 +194,7 @@ LOCAL_SRC_FILES := \ src/core/api/server_api.cpp \ src/core/api/sntp_api.cpp \ src/core/api/srp_client_api.cpp \ + src/core/api/srp_client_buffers_api.cpp \ src/core/api/srp_server_api.cpp \ src/core/api/tasklet_api.cpp \ src/core/api/thread_api.cpp \ @@ -335,6 +336,7 @@ LOCAL_SRC_FILES := \ src/core/utils/parse_cmdline.cpp \ src/core/utils/ping_sender.cpp \ src/core/utils/slaac_address.cpp \ + src/core/utils/srp_client_buffers.cpp \ src/lib/hdlc/hdlc.cpp \ src/lib/platform/exit_code.c \ src/lib/spinel/spinel.c \ diff --git a/include/Makefile.am b/include/Makefile.am index 427133ee5..a590ce02a 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -78,6 +78,7 @@ openthread_headers = \ openthread/server.h \ openthread/sntp.h \ openthread/srp_client.h \ + openthread/srp_client_buffers.h \ openthread/srp_server.h \ openthread/tasklet.h \ openthread/thread.h \ diff --git a/include/openthread/BUILD.gn b/include/openthread/BUILD.gn index 767f670e8..954e6dfe4 100644 --- a/include/openthread/BUILD.gn +++ b/include/openthread/BUILD.gn @@ -118,6 +118,7 @@ source_set("openthread") { "server.h", "sntp.h", "srp_client.h", + "srp_client_buffers.h", "srp_server.h", "tasklet.h", "thread.h", diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 1b73e2949..c3e8abbb9 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (87) +#define OPENTHREAD_API_VERSION (88) /** * @addtogroup api-instance diff --git a/include/openthread/srp_client_buffers.h b/include/openthread/srp_client_buffers.h new file mode 100644 index 000000000..886eb60da --- /dev/null +++ b/include/openthread/srp_client_buffers.h @@ -0,0 +1,179 @@ +/* + * 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. + */ + +/** + * @file + * @brief + * This file defines the OpenThread SRP (Service Registration Protocol) client buffers and service pool. + */ + +#ifndef OPENTHREAD_SRP_CLIENT_BUFFERS_H_ +#define OPENTHREAD_SRP_CLIENT_BUFFERS_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup api-srp + * + * @brief + * This module includes functions for SRP client buffers and service pool. + * + * @{ + * + * Functions in this module are only available when feature OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE is enabled. + * + */ + +/** + * This struct represents a SRP client service pool entry. + * + */ +typedef struct otSrpClientBuffersServiceEntry +{ + otSrpClientService mService; ///< The SRP client service structure. + otDnsTxtEntry mTxtEntry; ///< The SRP client TXT entry. +} otSrpClientBuffersServiceEntry; + +/** + * This function gets the string buffer to use for SRP client host name. + * + * @param[in] aInstance A pointer to the OpenThread instance. + * @param[out] aSize Pointer to a variable to return the size (number of bytes) of the string buffer (MUST NOT be + * NULL). + * + * @returns A pointer to char buffer to use for SRP client host name. + * + */ +char *otSrpClientBuffersGetHostNameString(otInstance *aInstance, uint16_t *aSize); + +/** + * This function gets the array of IPv6 address entries to use as SRP client host address list. + * + * @param[in] aInstance A pointer to the OpenThread instance. + * @param[out] aArrayLength Pointer to a variable to return the array length i.e., number of IPv6 address entries in + * the array (MUST NOT be NULL). + * + * @returns A pointer to an array of `otIp6Address` entries (number of entries is returned in @p aArrayLength). + * + */ +otIp6Address *otSrpClientBuffersGetHostAddressesArray(otInstance *aInstance, uint8_t *aArrayLength); + +/** + * This function allocates a new service entry from the pool. + * + * The returned service entry instance will be initialized as follows: + * + * - `mService.mName` will point to an allocated string buffer which can be retrieved using the function + * `otSrpClientBuffersGetServiceEntryServiceNameString()`. + * - `mService.mInstanceName` will point to an allocated string buffer which can be retrieved using the function + * `otSrpClientBuffersGetServiceEntryInstanceNameString()`. + * - `mService.mTxtEntries` will point to `mTxtEntry`. + * - `mService.mNumTxtEntries` will be set to one. + * - Other `mService` fields (port, priority, weight) are set to zero. + * - `mTxtEntry.mKey` is set to NULL (value is treated as already encoded). + * - `mTxtEntry.mValue` will point to an allocated buffer which can be retrieved using the function + * `otSrpClientBuffersGetServiceEntryTxtBuffer()`. + * - `mTxtEntry.mValueLength` is set to zero. + * + * @param[in] aInstance A pointer to the OpenThread instance. + * + * @returns A pointer to the newly allocated service entry or NULL if not more entry available in the pool. + * + */ +otSrpClientBuffersServiceEntry *otSrpClientBuffersAllocateService(otInstance *aInstance); + +/** + * This function frees a previously allocated service entry. + * + * The @p aService MUST be previously allocated using `otSrpClientBuffersAllocateService()` and not yet freed. Otherwise + * the behavior of this function is undefined. + * + * @param[in] aInstance A pointer to the OpenThread instance. + * @param[in] aSevice A pointer to the service entry to free (MUST NOT be NULL). + * + */ +void otSrpClientBuffersFreeService(otInstance *aInstance, otSrpClientBuffersServiceEntry *aService); + +/** + * This function frees all previously allocated service entries. + * + * @param[in] aInstance A pointer to the OpenThread instance. + * + */ +void otSrpClientBuffersFreeAllServices(otInstance *aInstance); + +/** + * This function gets the string buffer for service name from a service entry. + * + * @param[in] aEntry A pointer to a previously allocated service entry (MUST NOT be NULL). + * @param[out] aSize A pointer to a variable to return the size (number of bytes) of the string buffer (MUST NOT be + * NULL). + * + * @returns A pointer to the string buffer. + * + */ +char *otSrpClientBuffersGetServiceEntryServiceNameString(otSrpClientBuffersServiceEntry *aEntry, uint16_t *aSize); + +/** + * This function gets the string buffer for service instance name from a service entry. + * + * @param[in] aEntry A pointer to a previously allocated service entry (MUST NOT be NULL). + * @param[out] aSize A pointer to a variable to return the size (number of bytes) of the string buffer (MUST NOT be + * NULL). + * + * @returns A pointer to the string buffer. + * + */ +char *otSrpClientBuffersGetServiceEntryInstanceNameString(otSrpClientBuffersServiceEntry *aEntry, uint16_t *aSize); + +/** + * This function gets the buffer for TXT record from a service entry. + * + * @param[in] aEntry A pointer to a previously allocated service entry (MUST NOT be NULL). + * @param[out] aSize A pointer to a variable to return the size (number of bytes) of the buffer (MUST NOT be NULL). + * + * @returns A pointer to the buffer. + * + */ +uint8_t *otSrpClientBuffersGetServiceEntryTxtBuffer(otSrpClientBuffersServiceEntry *aEntry, uint16_t *aSize); + +/** + * @} + * + */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // OPENTHREAD_SRP_CLIENT_BUFFERS_H_ diff --git a/src/cli/cli_config.h b/src/cli/cli_config.h index 7c8fda0df..439872574 100644 --- a/src/cli/cli_config.h +++ b/src/cli/cli_config.h @@ -56,28 +56,4 @@ #define OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH 384 #endif -/** - * @def OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_SERVICES - * - * The maximum number of service entries supported by SRP client. - * - * This is only applicable when SRP client is enabled, i.e. OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE is set. - * - */ -#ifndef OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_SERVICES -#define OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_SERVICES 2 -#endif - -/** - * @def OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_HOST_ADDRESSES - * - * The maximum number of host IPv6 address entries supported by SRP client. - * - * This is only applicable when SRP client is enabled, i.e. OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE is set. - * - */ -#ifndef OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_HOST_ADDRESSES -#define OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_HOST_ADDRESSES 2 -#endif - #endif // CONFIG_CLI_H_ diff --git a/src/cli/cli_srp_client.cpp b/src/cli/cli_srp_client.cpp index be3f40342..4b9114c67 100644 --- a/src/cli/cli_srp_client.cpp +++ b/src/cli/cli_srp_client.cpp @@ -51,7 +51,7 @@ namespace Cli { constexpr SrpClient::Command SrpClient::sCommands[]; -template static otError CopyString(char (&aDestination)[kDestSize], const char *aSource) +static otError CopyString(char *aDest, uint16_t aDestSize, const char *aSource) { // Copies a string from `aSource` to `aDestination` (char array), // verifying that the string fits in the destination array. @@ -59,8 +59,8 @@ template static otError CopyString(char (&aDestination)[kDe otError error = OT_ERROR_NONE; size_t len = strlen(aSource); - VerifyOrExit(len + 1 <= kDestSize, error = OT_ERROR_INVALID_ARGS); - memcpy(aDestination, aSource, len + 1); + VerifyOrExit(len + 1 <= aDestSize, error = OT_ERROR_INVALID_ARGS); + memcpy(aDest, aSource, len + 1); exit: return error; @@ -70,13 +70,6 @@ SrpClient::SrpClient(Interpreter &aInterpreter) : mInterpreter(aInterpreter) , mCallbackEnabled(false) { - for (Service &service : mServicePool) - { - service.MarkAsNotInUse(); - } - - memset(mHostAddresses, 0, sizeof(mHostAddresses)); - otSrpClientSetCallback(mInterpreter.mInstance, SrpClient::HandleCallback, this); } @@ -190,9 +183,26 @@ otError SrpClient::ProcessHost(uint8_t aArgsLength, char *aArgs[]) } else { + size_t len; + uint16_t size; + char * hostName; + VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = CopyString(mHostName, aArgs[1])); - error = otSrpClientSetHostName(mInterpreter.mInstance, mHostName); + hostName = otSrpClientBuffersGetHostNameString(mInterpreter.mInstance, &size); + + len = strlen(aArgs[1]); + VerifyOrExit(len + 1 <= size, error = OT_ERROR_INVALID_ARGS); + + // We first make sure we can set the name, and if so + // we copy it to the persisted string buffer and set + // the host name again now with the persisted buffer. + // This ensures that we do not overwrite a previous + // buffer with a host name that cannot be set. + + SuccessOrExit(error = otSrpClientSetHostName(mInterpreter.mInstance, aArgs[1])); + memcpy(hostName, aArgs[1], len + 1); + + IgnoreError(otSrpClientSetHostName(mInterpreter.mInstance, hostName)); } } else if (strcmp(aArgs[0], "state") == 0) @@ -215,24 +225,30 @@ otError SrpClient::ProcessHost(uint8_t aArgsLength, char *aArgs[]) } else { - uint8_t numAddresses; - otIp6Address addresses[kMaxHostAddresses]; + uint8_t numAddresses = aArgsLength - 1; + otIp6Address addresses[kMaxHostAddresses]; + uint8_t arrayLength; + otIp6Address *hostAddressArray; - numAddresses = 0; - memset(addresses, 0, sizeof(addresses)); + hostAddressArray = otSrpClientBuffersGetHostAddressesArray(mInterpreter.mInstance, &arrayLength); - while (aArgsLength > 1) + // We first make sure we can set the addresses, and if so + // we copy the address list into the persisted address array + // and set it again. This ensures that we do not overwrite + // a previous list before we know it is safe to set/change + // the address list. + + VerifyOrExit(numAddresses <= arrayLength, error = OT_ERROR_NO_BUFS); + + for (uint8_t index = 1; index < aArgsLength; index++) { - VerifyOrExit(numAddresses < kMaxHostAddresses, error = OT_ERROR_NO_BUFS); - aArgsLength--; - aArgs++; - SuccessOrExit(error = ParseAsIp6Address(aArgs[0], addresses[numAddresses++])); + SuccessOrExit(error = ParseAsIp6Address(aArgs[index], addresses[index - 1])); } - VerifyOrExit(numAddresses > 0, error = OT_ERROR_INVALID_ARGS); - memcpy(mHostAddresses, addresses, sizeof(addresses)); + SuccessOrExit(error = otSrpClientSetHostAddresses(mInterpreter.mInstance, addresses, numAddresses)); - error = otSrpClientSetHostAddresses(mInterpreter.mInstance, mHostAddresses, numAddresses); + memcpy(hostAddressArray, addresses, numAddresses * sizeof(hostAddressArray[0])); + IgnoreError(otSrpClientSetHostAddresses(mInterpreter.mInstance, hostAddressArray, numAddresses)); } } else if (strcmp(aArgs[0], "remove") == 0) @@ -251,11 +267,7 @@ otError SrpClient::ProcessHost(uint8_t aArgsLength, char *aArgs[]) { VerifyOrExit(aArgsLength == 1, error = OT_ERROR_INVALID_ARGS); otSrpClientClearHostAndServices(mInterpreter.mInstance); - - for (Service &poolEntry : mServicePool) - { - poolEntry.MarkAsNotInUse(); - } + otSrpClientBuffersFreeAllServices(mInterpreter.mInstance); } else { @@ -349,82 +361,27 @@ otError SrpClient::ProcessService(uint8_t aArgsLength, char *aArgs[]) if (strcmp(aArgs[0], "add") == 0) { - // `add` [priority] [weight] [txt] - - Service *entry = nullptr; - - VerifyOrExit(4 <= aArgsLength && aArgsLength <= 7, error = OT_ERROR_INVALID_ARGS); - - for (Service &poolEntry : mServicePool) - { - if (!poolEntry.IsInUse()) - { - entry = &poolEntry; - break; - } - } - - VerifyOrExit(entry != nullptr, error = OT_ERROR_NO_BUFS); - - memset(&entry->mService, 0, sizeof(entry->mService)); - - SuccessOrExit(error = CopyString(entry->mInstanceName, aArgs[1])); - entry->mService.mInstanceName = entry->mInstanceName; - - SuccessOrExit(error = CopyString(entry->mServiceName, aArgs[2])); - entry->mService.mName = entry->mServiceName; - - SuccessOrExit(error = ParseAsUint16(aArgs[3], entry->mService.mPort)); - - if (aArgsLength >= 5) - { - SuccessOrExit(error = ParseAsUint16(aArgs[4], entry->mService.mPriority)); - } - - if (aArgsLength >= 6) - { - SuccessOrExit(error = ParseAsUint16(aArgs[5], entry->mService.mWeight)); - } - - if (aArgsLength >= 7) - { - entry->mService.mNumTxtEntries = 1; - entry->mService.mTxtEntries = &entry->mTxtEntry; - entry->mTxtEntry.mKey = nullptr; // Treat `mValue` as an already encoded TXT-DATA - entry->mTxtEntry.mValue = entry->mTxtBuffer; - entry->mTxtEntry.mValueLength = sizeof(entry->mTxtBuffer); - - SuccessOrExit(error = ParseAsHexString(aArgs[6], entry->mTxtEntry.mValueLength, entry->mTxtBuffer)); - } - - error = otSrpClientAddService(mInterpreter.mInstance, &entry->mService); - - if (error != OT_ERROR_NONE) - { - entry->MarkAsNotInUse(); - } + error = ProcessServiceAdd(aArgsLength, aArgs); } else if (strcmp(aArgs[0], "remove") == 0) { // `remove` - Service *entry = nullptr; + const otSrpClientService *service; VerifyOrExit(aArgsLength == 3, error = OT_ERROR_INVALID_ARGS); - for (Service &poolEntry : mServicePool) + for (service = otSrpClientGetServices(mInterpreter.mInstance); service != nullptr; service = service->mNext) { - if (poolEntry.IsInUse() && (strcmp(aArgs[1], poolEntry.mInstanceName) == 0) && - (strcmp(aArgs[2], poolEntry.mServiceName) == 0)) + if ((strcmp(aArgs[1], service->mInstanceName) == 0) && (strcmp(aArgs[2], service->mName) == 0)) { - entry = &poolEntry; break; } } - VerifyOrExit(entry != nullptr, error = OT_ERROR_NOT_FOUND); + VerifyOrExit(service != nullptr, error = OT_ERROR_NOT_FOUND); - error = otSrpClientRemoveService(mInterpreter.mInstance, &entry->mService); + error = otSrpClientRemoveService(mInterpreter.mInstance, const_cast(service)); } else { @@ -435,6 +392,66 @@ exit: return error; } +otError SrpClient::ProcessServiceAdd(uint8_t aArgsLength, char *aArgs[]) +{ + // `add` [priority] [weight] [txt] + + otSrpClientBuffersServiceEntry *entry = nullptr; + uint16_t size; + char * string; + otError error; + + VerifyOrExit(4 <= aArgsLength && aArgsLength <= 7, error = OT_ERROR_INVALID_ARGS); + + entry = otSrpClientBuffersAllocateService(mInterpreter.mInstance); + + VerifyOrExit(entry != nullptr, error = OT_ERROR_NO_BUFS); + + string = otSrpClientBuffersGetServiceEntryInstanceNameString(entry, &size); + SuccessOrExit(error = CopyString(string, size, aArgs[1])); + + string = otSrpClientBuffersGetServiceEntryServiceNameString(entry, &size); + SuccessOrExit(error = CopyString(string, size, aArgs[2])); + + SuccessOrExit(error = ParseAsUint16(aArgs[3], entry->mService.mPort)); + + if (aArgsLength >= 5) + { + SuccessOrExit(error = ParseAsUint16(aArgs[4], entry->mService.mPriority)); + } + + if (aArgsLength >= 6) + { + SuccessOrExit(error = ParseAsUint16(aArgs[5], entry->mService.mWeight)); + } + + if (aArgsLength >= 7) + { + uint8_t *txtBuffer; + + txtBuffer = otSrpClientBuffersGetServiceEntryTxtBuffer(entry, &size); + entry->mTxtEntry.mValueLength = size; + + SuccessOrExit(error = ParseAsHexString(aArgs[6], entry->mTxtEntry.mValueLength, txtBuffer)); + } + else + { + entry->mService.mNumTxtEntries = 0; + } + + SuccessOrExit(error = otSrpClientAddService(mInterpreter.mInstance, &entry->mService)); + + entry = nullptr; + +exit: + if (entry != nullptr) + { + otSrpClientBuffersFreeService(mInterpreter.mInstance, entry); + } + + return error; +} + void SrpClient::OutputHostInfo(uint8_t aIndentSize, const otSrpClientHostInfo &aHostInfo) { mInterpreter.OutputFormat(aIndentSize, "name:"); @@ -554,21 +571,16 @@ void SrpClient::HandleCallback(otError aError, } } - // Go through removed services and mark the corresponding entry in - // `mServicePool` as "not in use". + // Go through removed services and free all removed services for (const otSrpClientService *service = aRemovedServices; service != nullptr; service = next) { next = service->mNext; + otSrpClientBuffersServiceEntry *entry; - for (Service &poolEntry : mServicePool) - { - if (service == &poolEntry.mService) - { - poolEntry.MarkAsNotInUse(); - break; - } - } + entry = reinterpret_cast(const_cast(service)); + + otSrpClientBuffersFreeService(mInterpreter.mInstance, entry); } } diff --git a/src/cli/cli_srp_client.hpp b/src/cli/cli_srp_client.hpp index ef541c10e..e62075867 100644 --- a/src/cli/cli_srp_client.hpp +++ b/src/cli/cli_srp_client.hpp @@ -37,6 +37,7 @@ #include "openthread-core-config.h" #include +#include #include "cli/cli_config.h" #include "utils/lookup_table.hpp" @@ -75,25 +76,10 @@ public: private: enum : uint8_t { - kMaxServices = OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_SERVICES, - kMaxHostAddresses = OPENTHREAD_CONFIG_CLI_SRP_CLIENT_MAX_HOST_ADDRESSES, - kNameSize = 64, - kTxtSize = 255, + kMaxHostAddresses = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_HOST_ADDRSSES, kIndentSize = 4, }; - struct Service - { - void MarkAsNotInUse(void) { mService.mNext = &mService; } - bool IsInUse(void) const { return (mService.mNext != &mService); } - - otSrpClientService mService; - otDnsTxtEntry mTxtEntry; - char mInstanceName[kNameSize]; - char mServiceName[kNameSize]; - uint8_t mTxtBuffer[kTxtSize]; - }; - struct Command { const char *mName; @@ -108,6 +94,7 @@ private: otError ProcessKeyLeaseInterval(uint8_t aArgsLength, char *aArgs[]); otError ProcessServer(uint8_t aArgsLength, char *aArgs[]); otError ProcessService(uint8_t aArgsLength, char *aArgs[]); + otError ProcessServiceAdd(uint8_t aArgsLength, char *aArgs[]); otError ProcessStart(uint8_t aArgsLength, char *aArgs[]); otError ProcessState(uint8_t aArgsLength, char *aArgs[]); otError ProcessStop(uint8_t aArgsLength, char *aArgs[]); @@ -144,9 +131,6 @@ private: Interpreter &mInterpreter; bool mCallbackEnabled; - char mHostName[kNameSize]; - otIp6Address mHostAddresses[kMaxHostAddresses]; - Service mServicePool[kMaxServices]; }; } // namespace Cli diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index 8e5ffb1b5..71561da5d 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -330,6 +330,7 @@ openthread_core_files = [ "api/server_api.cpp", "api/sntp_api.cpp", "api/srp_client_api.cpp", + "api/srp_client_buffers_api.cpp", "api/srp_server_api.cpp", "api/tasklet_api.cpp", "api/thread_api.cpp", @@ -630,6 +631,8 @@ openthread_core_files = [ "utils/ping_sender.hpp", "utils/slaac_address.cpp", "utils/slaac_address.hpp", + "utils/srp_client_buffers.cpp", + "utils/srp_client_buffers.hpp", ] openthread_radio_sources = [ diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 157814d96..2e9ef874e 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -70,6 +70,7 @@ set(COMMON_SOURCES api/server_api.cpp api/sntp_api.cpp api/srp_client_api.cpp + api/srp_client_buffers_api.cpp api/srp_server_api.cpp api/tasklet_api.cpp api/thread_api.cpp @@ -211,6 +212,7 @@ set(COMMON_SOURCES utils/parse_cmdline.cpp utils/ping_sender.cpp utils/slaac_address.cpp + utils/srp_client_buffers.cpp ) set(OT_VENDOR_EXTENSION "" CACHE STRING "specify a C++ source file built as part of OpenThread core library") diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 0d243b8aa..88ae2e395 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -147,6 +147,7 @@ SOURCES_COMMON = \ api/server_api.cpp \ api/sntp_api.cpp \ api/srp_client_api.cpp \ + api/srp_client_buffers_api.cpp \ api/srp_server_api.cpp \ api/tasklet_api.cpp \ api/thread_api.cpp \ @@ -288,6 +289,7 @@ SOURCES_COMMON = \ utils/parse_cmdline.cpp \ utils/ping_sender.cpp \ utils/slaac_address.cpp \ + utils/srp_client_buffers.cpp \ $(NULL) EXTRA_DIST = \ @@ -550,6 +552,7 @@ HEADERS_COMMON = \ utils/parse_cmdline.hpp \ utils/ping_sender.hpp \ utils/slaac_address.hpp \ + utils/srp_client_buffers.hpp \ $(NULL) noinst_HEADERS = \ diff --git a/src/core/api/srp_client_buffers_api.cpp b/src/core/api/srp_client_buffers_api.cpp new file mode 100644 index 000000000..f701d9299 --- /dev/null +++ b/src/core/api/srp_client_buffers_api.cpp @@ -0,0 +1,97 @@ +/* + * 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. + */ + +/** + * @file + * This file implements the OpenThread SRP client buffers and service pool APIs. + */ + +#include "openthread-core-config.h" + +#include + +#include "common/instance.hpp" +#include "common/locator-getters.hpp" +#include "utils/srp_client_buffers.hpp" + +using namespace ot; + +#if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE + +char *otSrpClientBuffersGetHostNameString(otInstance *aInstance, uint16_t *aSize) +{ + Instance &instance = *static_cast(aInstance); + + return instance.Get().GetHostNameString(*aSize); +} + +otIp6Address *otSrpClientBuffersGetHostAddressesArray(otInstance *aInstance, uint8_t *aArrayLength) +{ + Instance &instance = *static_cast(aInstance); + + return instance.Get().GetHostAddressesArray(*aArrayLength); +} + +otSrpClientBuffersServiceEntry *otSrpClientBuffersAllocateService(otInstance *aInstance) +{ + Instance &instance = *static_cast(aInstance); + + return instance.Get().AllocateService(); +} + +void otSrpClientBuffersFreeService(otInstance *aInstance, otSrpClientBuffersServiceEntry *aService) +{ + Instance &instance = *static_cast(aInstance); + + instance.Get().FreeService( + *static_cast(aService)); +} + +void otSrpClientBuffersFreeAllServices(otInstance *aInstance) +{ + Instance &instance = *static_cast(aInstance); + + instance.Get().FreeAllServices(); +} + +char *otSrpClientBuffersGetServiceEntryServiceNameString(otSrpClientBuffersServiceEntry *aEntry, uint16_t *aSize) +{ + return static_cast(aEntry)->GetServiceNameString(*aSize); +} + +char *otSrpClientBuffersGetServiceEntryInstanceNameString(otSrpClientBuffersServiceEntry *aEntry, uint16_t *aSize) +{ + return static_cast(aEntry)->GetInstanceNameString(*aSize); +} + +uint8_t *otSrpClientBuffersGetServiceEntryTxtBuffer(otSrpClientBuffersServiceEntry *aEntry, uint16_t *aSize) +{ + return static_cast(aEntry)->GetTxtBuffer(*aSize); +} + +#endif // OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp index d2997a59e..a4ad5be90 100644 --- a/src/core/common/instance.hpp +++ b/src/core/common/instance.hpp @@ -690,6 +690,13 @@ template <> inline Srp::Client &Instance::Get(void) } #endif +#if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE +template <> inline Utils::SrpClientBuffers &Instance::Get(void) +{ + return mThreadNetif.mSrpClientBuffers; +} +#endif + #if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE template <> inline Dns::ServiceDiscovery::Server &Instance::Get(void) { diff --git a/src/core/common/pool.hpp b/src/core/common/pool.hpp index 322df885c..66e8c7188 100644 --- a/src/core/common/pool.hpp +++ b/src/core/common/pool.hpp @@ -115,6 +115,20 @@ public: */ void Free(Type &aEntry) { mFreeList.Push(aEntry); } + /** + * This method frees all previously allocated objects. + * + */ + void FreeAll(void) + { + mFreeList.Clear(); + + for (Type &entry : mPool) + { + mFreeList.Push(entry); + } + } + /** * This method returns the pool size. * diff --git a/src/core/config/srp_client.h b/src/core/config/srp_client.h index e25115177..37818a8e0 100644 --- a/src/core/config/srp_client.h +++ b/src/core/config/srp_client.h @@ -63,7 +63,7 @@ * * Define the default mode (enabled or disabled) of auto-start mode. * - * This config is applicable/used only when `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE` is enabled. + * This config is applicable only when `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE` is enabled. * */ #ifndef OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE @@ -218,4 +218,73 @@ #define OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_INTERVAL_GROWTH_FACTOR_DENOMINATOR 10 #endif +/** + * @def OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE + * + * Define to 1 to enable SRP Client buffers and service pool feature. + * + */ +#define OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE + +/** + * @def OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_SERVICES + * + * Specifies number of service entries in the SRP client service pool. + * + * This config is applicable only when `OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE` is enabled. + * + */ +#define OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_SERVICES 2 + +/** + * @def OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_HOST_ADDRSSES + * + * Specifies number of host IPv6 address entries in the SRP client buffers and service pool. + * + * This config is applicable only when `OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE` is enabled. + * + */ +#define OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_HOST_ADDRSSES 2 + +/** + * @def OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_HOST_NAME_SIZE + * + * Specifies the size (number of chars) of host name string buffer in the SRP client buffers and service pool. + * + * This config is applicable only when `OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE` is enabled. + * + */ +#define OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_HOST_NAME_SIZE 64 + +/** + * @def OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_SERVICE_NAME_SIZE + * + * Specifies the size (number of chars) of service name string buffer in the SRP client buffers and service pool. + * + * This config is applicable only when `OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE` is enabled. + * + */ +#define OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_SERVICE_NAME_SIZE 64 + +/** + * @def OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_SERVICE_INSTANCE_NAME_SIZE + * + * Specifies the size (number of chars) of service instance name string buffer in the SRP client buffers and service + * pool. + * + * This config is applicable only when `OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE` is enabled. + * + */ +#define OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_SERVICE_INSTANCE_NAME_SIZE 64 + +/** + * @def OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_TXT_BUFFER_SIZE + * + * Specifies the size (number of bytes) of TXT record value buffer in the SRP client buffers and service pool. + * + * This config is applicable only when `OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE` is enabled. + * + */ +#define OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_TXT_BUFFER_SIZE 64 + #endif // CONFIG_SRP_CLIENT_H_ diff --git a/src/core/thread/thread_netif.cpp b/src/core/thread/thread_netif.cpp index 3824c1d70..6d27245ff 100644 --- a/src/core/thread/thread_netif.cpp +++ b/src/core/thread/thread_netif.cpp @@ -65,6 +65,9 @@ ThreadNetif::ThreadNetif(Instance &aInstance) #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE , mSrpClient(aInstance) #endif +#if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE + , mSrpClientBuffers(aInstance) +#endif #if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE , mDnssdServer(aInstance) #endif diff --git a/src/core/thread/thread_netif.hpp b/src/core/thread/thread_netif.hpp index 3fd86cf44..5d92c404b 100644 --- a/src/core/thread/thread_netif.hpp +++ b/src/core/thread/thread_netif.hpp @@ -102,6 +102,7 @@ #include "thread/radio_selector.hpp" #include "thread/time_sync_service.hpp" #include "utils/child_supervision.hpp" +#include "utils/srp_client_buffers.hpp" #if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE #include "utils/slaac_address.hpp" @@ -207,6 +208,9 @@ private: #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE Srp::Client mSrpClient; #endif +#if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE + Utils::SrpClientBuffers mSrpClientBuffers; +#endif #if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE Dns::ServiceDiscovery::Server mDnssdServer; #endif diff --git a/src/core/utils/srp_client_buffers.cpp b/src/core/utils/srp_client_buffers.cpp new file mode 100644 index 000000000..169015336 --- /dev/null +++ b/src/core/utils/srp_client_buffers.cpp @@ -0,0 +1,72 @@ +/* + * 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. + */ + +/** + * @file + * This file implements the SRP client buffers and service pool. + */ + +#include "srp_client_buffers.hpp" + +#if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE + +#include + +#include "common/code_utils.hpp" +#include "common/instance.hpp" +#include "common/locator-getters.hpp" + +namespace ot { +namespace Utils { + +SrpClientBuffers::SrpClientBuffers(Instance &aInstance) + : InstanceLocator(aInstance) +{ +} + +SrpClientBuffers::ServiceEntry *SrpClientBuffers::AllocateService(void) +{ + ServiceEntry *entry = mServicePool.Allocate(); + + VerifyOrExit(entry != nullptr); + + entry->Clear(); + entry->mService.mName = entry->mServiceName; + entry->mService.mInstanceName = entry->mInstanceName; + entry->mService.mTxtEntries = &entry->mTxtEntry; + entry->mService.mNumTxtEntries = 1; + entry->mTxtEntry.mValue = entry->mTxtBuffer; + +exit: + return entry; +} + +} // namespace Utils +} // namespace ot + +#endif // OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE diff --git a/src/core/utils/srp_client_buffers.hpp b/src/core/utils/srp_client_buffers.hpp new file mode 100644 index 000000000..7e12cba9f --- /dev/null +++ b/src/core/utils/srp_client_buffers.hpp @@ -0,0 +1,248 @@ +/* + * 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. + */ + +/** + * @file + * This file includes definitions for the SRP client buffers and service pool. + */ + +#ifndef SRP_CLIENT_BUFFERS_HPP_ +#define SRP_CLIENT_BUFFERS_HPP_ + +#include "openthread-core-config.h" + +#include + +#include "common/clearable.hpp" +#include "common/locator.hpp" +#include "common/non_copyable.hpp" +#include "common/pool.hpp" +#include "net/srp_client.hpp" + +namespace ot { +namespace Utils { + +#if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE + +#if !OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE +#error "OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE requires OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE feature." +#endif + +/** + * This class represents the SRP client buffers and service pool. + * + */ +class SrpClientBuffers : public InstanceLocator, private NonCopyable +{ +public: + enum : uint16_t + { + /** + * Maximum number of service entries in the pool. + * + */ + kMaxServices = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_SERVICES, + + /** + * Max number of host address entries. + * + */ + kMaxHostAddresses = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_HOST_ADDRSSES, + + /** + * Size (number of char) of host name string (includes null `\0` termination char). + * + */ + kHostNameSize = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_HOST_NAME_SIZE, + + /** + * Size (number of char) of service name string (includes null `\0` termination char). + * + */ + kServiceNameSize = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_SERVICE_NAME_SIZE, + + /** + * Size (number of char) of service instance name string (includes null `\0` termination char). + * + */ + kInstanceNameSize = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_SERVICE_INSTANCE_NAME_SIZE, + + /** + * Size (number of bytes) of TXT record buffer. + * + */ + kTxtBufferSize = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_TXT_BUFFER_SIZE, + }; + + /** + * This class represents a SRP client service entry from the pool. + * + */ + class ServiceEntry : public otSrpClientBuffersServiceEntry, public Clearable + { + friend class SrpClientBuffers; + friend class LinkedList; + + public: + /** + * This method gets the string buffer for the service name from the service entry. + * + * @param[out] aSize Reference to a variable to return the size (number of bytes) of the string buffer. + * + * @returns A pointer to the string buffer. + * + */ + char *GetServiceNameString(uint16_t &aSize) + { + aSize = sizeof(mServiceName); + return mServiceName; + } + + /** + * This method gets the string buffer for the instance name from the service entry. + * + * @param[out] aSize Reference to a variable to return the size (number of bytes) of the string buffer. + * + * @returns A pointer to the string buffer. + * + */ + char *GetInstanceNameString(uint16_t &aSize) + { + aSize = sizeof(mInstanceName); + return mInstanceName; + } + + /** + * This method gets the buffer for the TXT value from the service entry. + * + * @param[out] aSize Reference to a variable to return the size (number of bytes) of the buffer. + * + * @returns A pointer to the buffer. + * + */ + uint8_t *GetTxtBuffer(uint16_t &aSize) + { + aSize = sizeof(mTxtBuffer); + return mTxtBuffer; + } + + private: + ServiceEntry * GetNext(void) { return reinterpret_cast(mService.mNext); } + const ServiceEntry *GetNext(void) const { return reinterpret_cast(mService.mNext); } + void SetNext(ServiceEntry *aEntry) { mService.mNext = reinterpret_cast(aEntry); } + + char mServiceName[kServiceNameSize]; + char mInstanceName[kInstanceNameSize]; + uint8_t mTxtBuffer[kTxtBufferSize]; + }; + + /** + * This constructor initializes the `SrpClientBuffers` object. + * + * @param[in] aInstance A reference to the OpenThread instance. + * + */ + explicit SrpClientBuffers(Instance &aInstance); + + /** + * This method gets the string buffer to use for SRP client host name. + * + * @param[out] aSize Reference to a variable to return the size (number of bytes) of the string buffer. + * + * @returns A pointer to char buffer to use for SRP client host name. + * + */ + char *GetHostNameString(uint16_t &aSize) + { + aSize = sizeof(mHostName); + return mHostName; + } + + /** + * This method gets the array of IPv6 address entries to use as SRP client host address list. + * + * @param[out] aArrayLength Reference to a variable to return the array length (number of IPv6 address entries in + * * the array). + * + * @returns A pointer to an array of `Ip6::Address` entries (number of entries is returned in @p aArrayLength). + * + */ + Ip6::Address *GetHostAddressesArray(uint8_t &aArrayLength) + { + aArrayLength = OT_ARRAY_LENGTH(mHostAddresses); + return &mHostAddresses[0]; + } + + /** + * This method allocates a new service entry from the pool. + * + * The returned service entry instance will be initialized as follows: + * + * - `mService.mName` points to a string buffer which can be retrieved using `GetServiceNameString()`. + * - `mService.mInstanceName` points to a string buffer which can be retrieved `GetInstanceNameString()`. + * - `mService.mTxtEntries` points to `mTxtEntry`. + * - `mService.mNumTxtEntries` is set to one (one entry in the list). + * - Other `mService` fields (port, priority, weight) are set to zero. + * - `mTxtEntry.mKey` is set to `nullptr` (value is treated as already encoded data). + * - `mTxtEntry.mValue` points to a buffer which can be retrieved using `GetTxtBuffer()` + * - `mTxtEntry.mValueLength` is set to zero. + * + * @returns A pointer to the newly allocated service entry or `nullptr` if not more entry available in the pool. + * + */ + ServiceEntry *AllocateService(void); + + /** + * This method frees a previously allocated service entry. + * + * The @p aService MUST be previously allocated using `AllocateService()` and not yet freed. Otherwise the behavior + * of this method is undefined. + * + * @param[in] aServiceEntry A service entry to free. + * + */ + void FreeService(ServiceEntry &aServiceEntry) { mServicePool.Free(aServiceEntry); } + + /** + * This method frees all previously allocated service entries. + * + */ + void FreeAllServices(void) { mServicePool.FreeAll(); } + +private: + char mHostName[kHostNameSize]; + Ip6::Address mHostAddresses[kMaxHostAddresses]; + Pool mServicePool; +}; + +#endif // OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE + +} // namespace Utils +} // namespace ot + +#endif // SRP_CLIENT_BUFFERS_HPP_ diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 4fbb8f6a2..fd4a0d7e3 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -248,7 +248,6 @@ NcpBase::NcpBase(Instance *aInstance) , mDroppedOutboundIpFrameCounter(0) , mDroppedInboundIpFrameCounter(0) #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE - , mSrpClientNumHostAddresses(0) , mSrpClientCallbackEnabled(false) #endif #endif // OPENTHREAD_MTD || OPENTHREAD_FTD diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 990c514db..a9a227340 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -611,19 +611,7 @@ protected: #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE enum : uint8_t { - kSrpClientMaxServices = OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_SERVICES, - kSrpClientMaxHostAddresses = OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_HOST_ADDRESSES, - kSrpClientNameSize = 64, - }; - - struct SrpClientService - { - void MarkAsNotInUse(void) { mService.mNext = &mService; } - bool IsInUse(void) const { return (mService.mNext != &mService); } - - otSrpClientService mService; - char mInstanceName[kSrpClientNameSize]; - char mServiceName[kSrpClientNameSize]; + kSrpClientMaxHostAddresses = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_HOST_ADDRSSES, }; otError EncodeSrpClientHostInfo(const otSrpClientHostInfo &aHostInfo); @@ -639,11 +627,7 @@ protected: const otSrpClientService * aServices, const otSrpClientService * aRemovedServices); - char mSrpClientHostName[kSrpClientNameSize]; - SrpClientService mSrpClientServicePool[kSrpClientMaxServices]; - otIp6Address mSrpClientHostAddresses[kSrpClientMaxHostAddresses]; - uint8_t mSrpClientNumHostAddresses; - bool mSrpClientCallbackEnabled; + bool mSrpClientCallbackEnabled; #endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE #if OPENTHREAD_CONFIG_LEGACY_ENABLE diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp index 3c0faab0e..7f200e854 100644 --- a/src/ncp/ncp_base_mtd.cpp +++ b/src/ncp/ncp_base_mtd.cpp @@ -63,6 +63,9 @@ #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) #include "openthread/backbone_router.h" #endif +#if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE +#include +#endif #include "common/code_utils.hpp" #include "common/debug.hpp" @@ -3548,21 +3551,25 @@ template <> otError NcpBase::HandlePropertySet { otError error; const char *name; + uint16_t size; + char * hostNameBuffer; SuccessOrExit(error = mDecoder.ReadUtf8(name)); - VerifyOrExit(StringLength(name, kSrpClientNameSize) < kSrpClientNameSize, error = OT_ERROR_INVALID_ARGS); + hostNameBuffer = otSrpClientBuffersGetHostNameString(mInstance, &size); + + VerifyOrExit(StringLength(name, size) < size, error = OT_ERROR_INVALID_ARGS); // We first make sure we can set the name, and if so - // we copy it to the `mSrpClientHostName` buffer and set - // the host name again now with the persisted buffer + // we copy it to the persisted buffer and set + // the host name again now with the persisted buffer. // This ensures that we do not overwrite a previous - // `mSrpClientHostName` when host name cannot be set. + // buffer with a host name that cannot be set. SuccessOrExit(error = otSrpClientSetHostName(mInstance, name)); - strcpy(mSrpClientHostName, name); - error = otSrpClientSetHostName(mInstance, mSrpClientHostName); + strcpy(hostNameBuffer, name); + error = otSrpClientSetHostName(mInstance, hostNameBuffer); OT_ASSERT(error == OT_ERROR_NONE); exit: @@ -3585,9 +3592,14 @@ exit: template <> otError NcpBase::HandlePropertySet(void) { - otError error; - otIp6Address addresses[kSrpClientMaxHostAddresses]; - uint8_t numAddresses = 0; + otError error; + otIp6Address addresses[kSrpClientMaxHostAddresses]; + uint8_t numAddresses = 0; + otIp6Address *hostAddressArray; + uint8_t hostAddressArrayLength; + + hostAddressArray = otSrpClientBuffersGetHostAddressesArray(mInstance, &hostAddressArrayLength); + OT_ASSERT(hostAddressArrayLength <= kSrpClientMaxHostAddresses); while (!mDecoder.IsAllReadInStruct()) { @@ -3597,18 +3609,16 @@ template <> otError NcpBase::HandlePropertySet otError NcpBase::HandlePropertyGet( template <> otError NcpBase::HandlePropertyInsert(void) { - otError error = OT_ERROR_NONE; - SrpClientService *entry = nullptr; - const char * serviceName; - const char * instanceName; - - for (SrpClientService &poolEntry : mSrpClientServicePool) - { - if (!poolEntry.IsInUse()) - { - entry = &poolEntry; - break; - } - } + otError error = OT_ERROR_NONE; + otSrpClientBuffersServiceEntry *entry = nullptr; + const char * serviceName; + const char * instanceName; + char * stringBuffer; + uint16_t size; + entry = otSrpClientBuffersAllocateService(mInstance); VerifyOrExit(entry != nullptr, error = OT_ERROR_NO_BUFS); + stringBuffer = otSrpClientBuffersGetServiceEntryServiceNameString(entry, &size); SuccessOrExit(error = mDecoder.ReadUtf8(serviceName)); - VerifyOrExit(StringLength(serviceName, kSrpClientNameSize) < kSrpClientNameSize, error = OT_ERROR_INVALID_ARGS); - strcpy(entry->mServiceName, serviceName); - entry->mService.mName = entry->mServiceName; + VerifyOrExit(StringLength(serviceName, size) < size, error = OT_ERROR_INVALID_ARGS); + strcpy(stringBuffer, serviceName); + stringBuffer = otSrpClientBuffersGetServiceEntryInstanceNameString(entry, &size); SuccessOrExit(error = mDecoder.ReadUtf8(instanceName)); - VerifyOrExit(StringLength(instanceName, kSrpClientNameSize) < kSrpClientNameSize, error = OT_ERROR_INVALID_ARGS); - strcpy(entry->mInstanceName, instanceName); - entry->mService.mInstanceName = entry->mInstanceName; + VerifyOrExit(StringLength(instanceName, size) < size, error = OT_ERROR_INVALID_ARGS); + strcpy(stringBuffer, instanceName); SuccessOrExit(error = mDecoder.ReadUint16(entry->mService.mPort)); SuccessOrExit(error = mDecoder.ReadUint16(entry->mService.mPriority)); SuccessOrExit(error = mDecoder.ReadUint16(entry->mService.mWeight)); - error = otSrpClientAddService(mInstance, &entry->mService); - - if (error != OT_ERROR_NONE) - { - entry->MarkAsNotInUse(); - } + SuccessOrExit(error = otSrpClientAddService(mInstance, &entry->mService)); + entry = nullptr; exit: + if (entry != nullptr) + { + otSrpClientBuffersFreeService(mInstance, entry); + } + return error; } template <> otError NcpBase::HandlePropertyRemove(void) { - otError error = OT_ERROR_NONE; - const char *serviceName; - const char *instanceName; + otError error = OT_ERROR_NONE; + const char * serviceName; + const char * instanceName; + const otSrpClientService *service; SuccessOrExit(error = mDecoder.ReadUtf8(serviceName)); SuccessOrExit(error = mDecoder.ReadUtf8(instanceName)); - for (SrpClientService &poolEntry : mSrpClientServicePool) + for (service = otSrpClientGetServices(mInstance); service != nullptr; service = service->mNext) { - if (!poolEntry.IsInUse() || (strcmp(serviceName, poolEntry.mServiceName) != 0) || - (strcmp(instanceName, poolEntry.mInstanceName) != 0)) + if ((strcmp(serviceName, service->mName) == 0) || (strcmp(instanceName, service->mInstanceName) == 0)) { - continue; + break; } - - error = otSrpClientRemoveService(mInstance, &poolEntry.mService); - ExitNow(); } - error = OT_ERROR_NOT_FOUND; + VerifyOrExit(service != nullptr, error = OT_ERROR_NOT_FOUND); + error = otSrpClientRemoveService(mInstance, const_cast(service)); exit: return error; @@ -3825,13 +3828,8 @@ exit: { next = service->mNext; - for (SrpClientService &poolEntry : mSrpClientServicePool) - { - if (&poolEntry.mService == service) - { - poolEntry.MarkAsNotInUse(); - } - } + otSrpClientBuffersFreeService( + mInstance, reinterpret_cast(const_cast(service))); } } diff --git a/src/ncp/ncp_config.h b/src/ncp/ncp_config.h index 60ab9c64a..bc54fb52a 100644 --- a/src/ncp/ncp_config.h +++ b/src/ncp/ncp_config.h @@ -189,28 +189,4 @@ #define OPENTHREAD_ENABLE_NCP_VENDOR_HOOK 0 #endif -/** - * @def OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_SERVICES - * - * The maximum number of service entries supported by SRP client. - * - * This is only applicable when SRP client is enabled, i.e., OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE is set. - * - */ -#ifndef OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_SERVICES -#define OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_SERVICES 2 -#endif - -/** - * @def OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_HOST_ADDRESSES - * - * The maximum number of host IPv6 address entries supported by SRP client. - * - * This is only applicable when SRP client is enabled, i.e., OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE is set. - * - */ -#ifndef OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_HOST_ADDRESSES -#define OPENTHREAD_CONFIG_NCP_SRP_CLIENT_MAX_HOST_ADDRESSES 2 -#endif - #endif // CONFIG_NCP_H_