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_