633 lines
19 KiB
C++
633 lines
19 KiB
C++
/*
|
|
* Copyright (c) 2020, 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 a simple CLI for the SRP Client.
|
|
*/
|
|
|
|
#include "cli_srp_client.hpp"
|
|
|
|
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
|
|
|
|
#include <string.h>
|
|
|
|
#include "cli/cli.hpp"
|
|
|
|
namespace ot {
|
|
namespace Cli {
|
|
|
|
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.
|
|
|
|
otError error = OT_ERROR_NONE;
|
|
size_t len = strlen(aSource);
|
|
|
|
VerifyOrExit(len + 1 <= aDestSize, error = OT_ERROR_INVALID_ARGS);
|
|
memcpy(aDest, aSource, len + 1);
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
SrpClient::SrpClient(Output &aOutput)
|
|
: OutputWrapper(aOutput)
|
|
, mCallbackEnabled(false)
|
|
{
|
|
otSrpClientSetCallback(GetInstancePtr(), SrpClient::HandleCallback, this);
|
|
}
|
|
|
|
#if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
|
|
|
|
template <> otError SrpClient::Process<Cmd("autostart")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
bool enable;
|
|
|
|
if (aArgs[0].IsEmpty())
|
|
{
|
|
OutputEnabledDisabledStatus(otSrpClientIsAutoStartModeEnabled(GetInstancePtr()));
|
|
ExitNow();
|
|
}
|
|
|
|
SuccessOrExit(error = Interpreter::ParseEnableOrDisable(aArgs[0], enable));
|
|
|
|
if (enable)
|
|
{
|
|
otSrpClientEnableAutoStartMode(GetInstancePtr(), /* aCallback */ nullptr, /* aContext */ nullptr);
|
|
}
|
|
else
|
|
{
|
|
otSrpClientDisableAutoStartMode(GetInstancePtr());
|
|
}
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
#endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
|
|
|
|
template <> otError SrpClient::Process<Cmd("callback")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
|
|
if (aArgs[0].IsEmpty())
|
|
{
|
|
OutputEnabledDisabledStatus(mCallbackEnabled);
|
|
ExitNow();
|
|
}
|
|
|
|
error = Interpreter::ParseEnableOrDisable(aArgs[0], mCallbackEnabled);
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
template <> otError SrpClient::Process<Cmd("host")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
|
|
if (aArgs[0].IsEmpty())
|
|
{
|
|
OutputHostInfo(0, *otSrpClientGetHostInfo(GetInstancePtr()));
|
|
}
|
|
else if (aArgs[0] == "name")
|
|
{
|
|
if (aArgs[1].IsEmpty())
|
|
{
|
|
const char *name = otSrpClientGetHostInfo(GetInstancePtr())->mName;
|
|
OutputLine("%s", (name != nullptr) ? name : "(null)");
|
|
}
|
|
else
|
|
{
|
|
uint16_t len;
|
|
uint16_t size;
|
|
char * hostName;
|
|
|
|
VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
hostName = otSrpClientBuffersGetHostNameString(GetInstancePtr(), &size);
|
|
|
|
len = aArgs[1].GetLength();
|
|
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(GetInstancePtr(), aArgs[1].GetCString()));
|
|
memcpy(hostName, aArgs[1].GetCString(), len + 1);
|
|
|
|
IgnoreError(otSrpClientSetHostName(GetInstancePtr(), hostName));
|
|
}
|
|
}
|
|
else if (aArgs[0] == "state")
|
|
{
|
|
VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
OutputLine("%s", otSrpClientItemStateToString(otSrpClientGetHostInfo(GetInstancePtr())->mState));
|
|
}
|
|
else if (aArgs[0] == "address")
|
|
{
|
|
if (aArgs[1].IsEmpty())
|
|
{
|
|
const otSrpClientHostInfo *hostInfo = otSrpClientGetHostInfo(GetInstancePtr());
|
|
|
|
if (hostInfo->mAutoAddress)
|
|
{
|
|
OutputLine("auto");
|
|
}
|
|
else
|
|
{
|
|
for (uint8_t index = 0; index < hostInfo->mNumAddresses; index++)
|
|
{
|
|
OutputIp6AddressLine(hostInfo->mAddresses[index]);
|
|
}
|
|
}
|
|
}
|
|
else if (aArgs[1] == "auto")
|
|
{
|
|
error = otSrpClientEnableAutoHostAddress(GetInstancePtr());
|
|
}
|
|
else
|
|
{
|
|
uint8_t numAddresses = 0;
|
|
otIp6Address addresses[kMaxHostAddresses];
|
|
uint8_t arrayLength;
|
|
otIp6Address *hostAddressArray;
|
|
|
|
hostAddressArray = otSrpClientBuffersGetHostAddressesArray(GetInstancePtr(), &arrayLength);
|
|
|
|
// 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.
|
|
|
|
if (arrayLength > kMaxHostAddresses)
|
|
{
|
|
arrayLength = kMaxHostAddresses;
|
|
}
|
|
|
|
for (Arg *arg = &aArgs[1]; !arg->IsEmpty(); arg++)
|
|
{
|
|
VerifyOrExit(numAddresses < arrayLength, error = OT_ERROR_NO_BUFS);
|
|
SuccessOrExit(error = arg->ParseAsIp6Address(addresses[numAddresses]));
|
|
numAddresses++;
|
|
}
|
|
|
|
SuccessOrExit(error = otSrpClientSetHostAddresses(GetInstancePtr(), addresses, numAddresses));
|
|
|
|
memcpy(hostAddressArray, addresses, numAddresses * sizeof(hostAddressArray[0]));
|
|
IgnoreError(otSrpClientSetHostAddresses(GetInstancePtr(), hostAddressArray, numAddresses));
|
|
}
|
|
}
|
|
else if (aArgs[0] == "remove")
|
|
{
|
|
bool removeKeyLease = false;
|
|
bool sendUnregToServer = false;
|
|
|
|
if (!aArgs[1].IsEmpty())
|
|
{
|
|
SuccessOrExit(error = aArgs[1].ParseAsBool(removeKeyLease));
|
|
|
|
if (!aArgs[2].IsEmpty())
|
|
{
|
|
SuccessOrExit(error = aArgs[2].ParseAsBool(sendUnregToServer));
|
|
VerifyOrExit(aArgs[3].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
}
|
|
}
|
|
|
|
error = otSrpClientRemoveHostAndServices(GetInstancePtr(), removeKeyLease, sendUnregToServer);
|
|
}
|
|
else if (aArgs[0] == "clear")
|
|
{
|
|
VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
otSrpClientClearHostAndServices(GetInstancePtr());
|
|
otSrpClientBuffersFreeAllServices(GetInstancePtr());
|
|
}
|
|
else
|
|
{
|
|
error = OT_ERROR_INVALID_COMMAND;
|
|
}
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
template <> otError SrpClient::Process<Cmd("leaseinterval")>(Arg aArgs[])
|
|
{
|
|
return Interpreter::GetInterpreter().ProcessGetSet(aArgs, otSrpClientGetLeaseInterval, otSrpClientSetLeaseInterval);
|
|
}
|
|
|
|
template <> otError SrpClient::Process<Cmd("keyleaseinterval")>(Arg aArgs[])
|
|
{
|
|
return Interpreter::GetInterpreter().ProcessGetSet(aArgs, otSrpClientGetKeyLeaseInterval,
|
|
otSrpClientSetKeyLeaseInterval);
|
|
}
|
|
|
|
template <> otError SrpClient::Process<Cmd("server")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
const otSockAddr *serverSockAddr = otSrpClientGetServerAddress(GetInstancePtr());
|
|
|
|
if (aArgs[0].IsEmpty())
|
|
{
|
|
OutputSockAddrLine(*serverSockAddr);
|
|
ExitNow();
|
|
}
|
|
|
|
VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
|
|
if (aArgs[0] == "address")
|
|
{
|
|
OutputIp6AddressLine(serverSockAddr->mAddress);
|
|
}
|
|
else if (aArgs[0] == "port")
|
|
{
|
|
OutputLine("%u", serverSockAddr->mPort);
|
|
}
|
|
else
|
|
{
|
|
error = OT_ERROR_INVALID_COMMAND;
|
|
}
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
template <> otError SrpClient::Process<Cmd("service")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
bool isRemove;
|
|
|
|
if (aArgs[0].IsEmpty())
|
|
{
|
|
OutputServiceList(0, otSrpClientGetServices(GetInstancePtr()));
|
|
}
|
|
else if (aArgs[0] == "add")
|
|
{
|
|
error = ProcessServiceAdd(aArgs);
|
|
}
|
|
else if ((isRemove = (aArgs[0] == "remove")) || (aArgs[0] == "clear"))
|
|
{
|
|
// `remove`|`clear` <instance-name> <service-name>
|
|
|
|
const otSrpClientService *service;
|
|
|
|
VerifyOrExit(!aArgs[2].IsEmpty() && aArgs[3].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
|
|
for (service = otSrpClientGetServices(GetInstancePtr()); service != nullptr; service = service->mNext)
|
|
{
|
|
if ((aArgs[1] == service->mInstanceName) && (aArgs[2] == service->mName))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
VerifyOrExit(service != nullptr, error = OT_ERROR_NOT_FOUND);
|
|
|
|
if (isRemove)
|
|
{
|
|
error = otSrpClientRemoveService(GetInstancePtr(), const_cast<otSrpClientService *>(service));
|
|
}
|
|
else
|
|
{
|
|
SuccessOrExit(error = otSrpClientClearService(GetInstancePtr(), const_cast<otSrpClientService *>(service)));
|
|
|
|
otSrpClientBuffersFreeService(GetInstancePtr(), reinterpret_cast<otSrpClientBuffersServiceEntry *>(
|
|
const_cast<otSrpClientService *>(service)));
|
|
}
|
|
}
|
|
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
|
|
else if (aArgs[0] == "key")
|
|
{
|
|
// `key [enable/disable]`
|
|
|
|
bool enable;
|
|
|
|
if (aArgs[1].IsEmpty())
|
|
{
|
|
OutputEnabledDisabledStatus(otSrpClientIsServiceKeyRecordEnabled(GetInstancePtr()));
|
|
ExitNow();
|
|
}
|
|
|
|
SuccessOrExit(error = Interpreter::ParseEnableOrDisable(aArgs[1], enable));
|
|
VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
otSrpClientSetServiceKeyRecordEnabled(GetInstancePtr(), enable);
|
|
}
|
|
#endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
|
|
else
|
|
{
|
|
error = OT_ERROR_INVALID_COMMAND;
|
|
}
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
otError SrpClient::ProcessServiceAdd(Arg aArgs[])
|
|
{
|
|
// `add` <instance-name> <service-name> <port> [priority] [weight] [txt]
|
|
|
|
otSrpClientBuffersServiceEntry *entry = nullptr;
|
|
uint16_t size;
|
|
char * string;
|
|
otError error;
|
|
char * label;
|
|
|
|
entry = otSrpClientBuffersAllocateService(GetInstancePtr());
|
|
|
|
VerifyOrExit(entry != nullptr, error = OT_ERROR_NO_BUFS);
|
|
|
|
SuccessOrExit(error = aArgs[3].ParseAsUint16(entry->mService.mPort));
|
|
|
|
// Successfully parsing aArgs[3] indicates that aArgs[1] and
|
|
// aArgs[2] are also non-empty.
|
|
|
|
string = otSrpClientBuffersGetServiceEntryInstanceNameString(entry, &size);
|
|
SuccessOrExit(error = CopyString(string, size, aArgs[1].GetCString()));
|
|
|
|
string = otSrpClientBuffersGetServiceEntryServiceNameString(entry, &size);
|
|
SuccessOrExit(error = CopyString(string, size, aArgs[2].GetCString()));
|
|
|
|
// Service subtypes are added as part of service name as a comma separated list
|
|
// e.g., "_service._udp,_sub1,_sub2"
|
|
|
|
label = strchr(string, ',');
|
|
|
|
if (label != nullptr)
|
|
{
|
|
uint16_t arrayLength;
|
|
const char **subTypeLabels = otSrpClientBuffersGetSubTypeLabelsArray(entry, &arrayLength);
|
|
|
|
// Leave the last array element as `nullptr` to indicate end of array.
|
|
for (uint16_t index = 0; index + 1 < arrayLength; index++)
|
|
{
|
|
*label++ = '\0';
|
|
subTypeLabels[index] = label;
|
|
|
|
label = strchr(label, ',');
|
|
|
|
if (label == nullptr)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
VerifyOrExit(label == nullptr, error = OT_ERROR_NO_BUFS);
|
|
}
|
|
|
|
SuccessOrExit(error = aArgs[3].ParseAsUint16(entry->mService.mPort));
|
|
|
|
if (!aArgs[4].IsEmpty())
|
|
{
|
|
SuccessOrExit(error = aArgs[4].ParseAsUint16(entry->mService.mPriority));
|
|
}
|
|
|
|
if (!aArgs[5].IsEmpty())
|
|
{
|
|
SuccessOrExit(error = aArgs[5].ParseAsUint16(entry->mService.mWeight));
|
|
}
|
|
|
|
if (!aArgs[6].IsEmpty())
|
|
{
|
|
uint8_t *txtBuffer;
|
|
|
|
txtBuffer = otSrpClientBuffersGetServiceEntryTxtBuffer(entry, &size);
|
|
entry->mTxtEntry.mValueLength = size;
|
|
|
|
SuccessOrExit(error = aArgs[6].ParseAsHexString(entry->mTxtEntry.mValueLength, txtBuffer));
|
|
VerifyOrExit(aArgs[7].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
}
|
|
else
|
|
{
|
|
entry->mService.mNumTxtEntries = 0;
|
|
}
|
|
|
|
SuccessOrExit(error = otSrpClientAddService(GetInstancePtr(), &entry->mService));
|
|
|
|
entry = nullptr;
|
|
|
|
exit:
|
|
if (entry != nullptr)
|
|
{
|
|
otSrpClientBuffersFreeService(GetInstancePtr(), entry);
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
void SrpClient::OutputHostInfo(uint8_t aIndentSize, const otSrpClientHostInfo &aHostInfo)
|
|
{
|
|
OutputFormat(aIndentSize, "name:");
|
|
|
|
if (aHostInfo.mName != nullptr)
|
|
{
|
|
OutputFormat("\"%s\"", aHostInfo.mName);
|
|
}
|
|
else
|
|
{
|
|
OutputFormat("(null)");
|
|
}
|
|
|
|
OutputFormat(", state:%s, addrs:", otSrpClientItemStateToString(aHostInfo.mState));
|
|
|
|
if (aHostInfo.mAutoAddress)
|
|
{
|
|
OutputLine("auto");
|
|
}
|
|
else
|
|
{
|
|
OutputFormat("[");
|
|
|
|
for (uint8_t index = 0; index < aHostInfo.mNumAddresses; index++)
|
|
{
|
|
if (index > 0)
|
|
{
|
|
OutputFormat(", ");
|
|
}
|
|
|
|
OutputIp6Address(aHostInfo.mAddresses[index]);
|
|
}
|
|
|
|
OutputLine("]");
|
|
}
|
|
}
|
|
|
|
void SrpClient::OutputServiceList(uint8_t aIndentSize, const otSrpClientService *aServices)
|
|
{
|
|
while (aServices != nullptr)
|
|
{
|
|
OutputService(aIndentSize, *aServices);
|
|
aServices = aServices->mNext;
|
|
}
|
|
}
|
|
|
|
void SrpClient::OutputService(uint8_t aIndentSize, const otSrpClientService &aService)
|
|
{
|
|
OutputFormat(aIndentSize, "instance:\"%s\", name:\"%s", aService.mInstanceName, aService.mName);
|
|
|
|
if (aService.mSubTypeLabels != nullptr)
|
|
{
|
|
for (uint16_t index = 0; aService.mSubTypeLabels[index] != nullptr; index++)
|
|
{
|
|
OutputFormat(",%s", aService.mSubTypeLabels[index]);
|
|
}
|
|
}
|
|
|
|
OutputLine("\", state:%s, port:%d, priority:%d, weight:%d", otSrpClientItemStateToString(aService.mState),
|
|
aService.mPort, aService.mPriority, aService.mWeight);
|
|
}
|
|
|
|
template <> otError SrpClient::Process<Cmd("start")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
otSockAddr serverSockAddr;
|
|
|
|
SuccessOrExit(error = aArgs[0].ParseAsIp6Address(serverSockAddr.mAddress));
|
|
SuccessOrExit(error = aArgs[1].ParseAsUint16(serverSockAddr.mPort));
|
|
VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
|
|
error = otSrpClientStart(GetInstancePtr(), &serverSockAddr);
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
template <> otError SrpClient::Process<Cmd("state")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
|
|
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
|
|
OutputEnabledDisabledStatus(otSrpClientIsRunning(GetInstancePtr()));
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
template <> otError SrpClient::Process<Cmd("stop")>(Arg aArgs[])
|
|
{
|
|
otError error = OT_ERROR_NONE;
|
|
|
|
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
|
otSrpClientStop(GetInstancePtr());
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
template <> otError SrpClient::Process<Cmd("ttl")>(Arg aArgs[])
|
|
{
|
|
return Interpreter::GetInterpreter().ProcessGetSet(aArgs, otSrpClientGetTtl, otSrpClientSetTtl);
|
|
}
|
|
|
|
void SrpClient::HandleCallback(otError aError,
|
|
const otSrpClientHostInfo *aHostInfo,
|
|
const otSrpClientService * aServices,
|
|
const otSrpClientService * aRemovedServices,
|
|
void * aContext)
|
|
{
|
|
static_cast<SrpClient *>(aContext)->HandleCallback(aError, aHostInfo, aServices, aRemovedServices);
|
|
}
|
|
|
|
void SrpClient::HandleCallback(otError aError,
|
|
const otSrpClientHostInfo *aHostInfo,
|
|
const otSrpClientService * aServices,
|
|
const otSrpClientService * aRemovedServices)
|
|
{
|
|
otSrpClientService *next;
|
|
|
|
if (mCallbackEnabled)
|
|
{
|
|
OutputLine("SRP client callback - error:%s", otThreadErrorToString(aError));
|
|
OutputLine("Host info:");
|
|
OutputHostInfo(kIndentSize, *aHostInfo);
|
|
|
|
OutputLine("Service list:");
|
|
OutputServiceList(kIndentSize, aServices);
|
|
|
|
if (aRemovedServices != nullptr)
|
|
{
|
|
OutputLine("Removed service list:");
|
|
OutputServiceList(kIndentSize, aRemovedServices);
|
|
}
|
|
}
|
|
|
|
// Go through removed services and free all removed services
|
|
|
|
for (const otSrpClientService *service = aRemovedServices; service != nullptr; service = next)
|
|
{
|
|
next = service->mNext;
|
|
|
|
otSrpClientBuffersFreeService(GetInstancePtr(), reinterpret_cast<otSrpClientBuffersServiceEntry *>(
|
|
const_cast<otSrpClientService *>(service)));
|
|
}
|
|
}
|
|
|
|
otError SrpClient::Process(Arg aArgs[])
|
|
{
|
|
#define CmdEntry(aCommandString) \
|
|
{ \
|
|
aCommandString, &SrpClient::Process<Cmd(aCommandString)> \
|
|
}
|
|
|
|
static constexpr Command kCommands[] = {
|
|
CmdEntry("autostart"), CmdEntry("callback"), CmdEntry("host"), CmdEntry("keyleaseinterval"),
|
|
CmdEntry("leaseinterval"), CmdEntry("server"), CmdEntry("service"), CmdEntry("start"),
|
|
CmdEntry("state"), CmdEntry("stop"), CmdEntry("ttl"),
|
|
};
|
|
|
|
static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
|
|
|
|
otError error = OT_ERROR_INVALID_COMMAND;
|
|
const Command *command;
|
|
|
|
if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
|
|
{
|
|
OutputCommandTable(kCommands);
|
|
ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE);
|
|
}
|
|
|
|
command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
|
|
VerifyOrExit(command != nullptr);
|
|
|
|
error = (this->*command->mHandler)(aArgs + 1);
|
|
|
|
exit:
|
|
return error;
|
|
}
|
|
|
|
} // namespace Cli
|
|
} // namespace ot
|
|
|
|
#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
|