[ncp] add support for SRP client in NCP and spinel (#6062)

This commit adds new spinel definitions for SRP client support
(mirroring the public OT APIs of SRP client) and implements get, set,
add, and remove handlers in `Ncp` for the new spinel properties.
This commit is contained in:
Abtin Keshavarzian
2021-01-28 08:29:12 -08:00
committed by GitHub
parent 8bbbe194f1
commit 563e2a0801
7 changed files with 738 additions and 0 deletions
+44
View File
@@ -2003,6 +2003,46 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
ret = "NEIGHBOR_TABLE_MULTI_RADIO_INFO";
break;
case SPINEL_PROP_SRP_CLIENT_START:
ret = "SRP_CLIENT_START";
break;
case SPINEL_PROP_SRP_CLIENT_LEASE_INTERVAL:
ret = "SRP_CLIENT_LEASE_INTERVAL";
break;
case SPINEL_PROP_SRP_CLIENT_KEY_LEASE_INTERVAL:
ret = "SRP_CLIENT_KEY_LEASE_INTERVAL";
break;
case SPINEL_PROP_SRP_CLIENT_HOST_INFO:
ret = "SRP_CLIENT_HOST_INFO";
break;
case SPINEL_PROP_SRP_CLIENT_HOST_NAME:
ret = "SRP_CLIENT_HOST_NAME";
break;
case SPINEL_PROP_SRP_CLIENT_HOST_ADDRESSES:
ret = "SRP_CLIENT_HOST_ADDRESSES";
break;
case SPINEL_PROP_SRP_CLIENT_SERVICES:
ret = "SRP_CLIENT_SERVICES";
break;
case SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_REMOVE:
ret = "SRP_CLIENT_HOST_SERVICES_REMOVE";
break;
case SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_CLEAR:
ret = "SRP_CLIENT_HOST_SERVICES_CLEAR";
break;
case SPINEL_PROP_SRP_CLIENT_EVENT:
ret = "SRP_CLIENT_EVENT";
break;
case SPINEL_PROP_SERVER_ALLOW_LOCAL_DATA_CHANGE:
ret = "SERVER_ALLOW_LOCAL_DATA_CHANGE";
break;
@@ -2695,6 +2735,10 @@ const char *spinel_capability_to_cstr(spinel_capability_t capability)
ret = "MULTI_RADIO";
break;
case SPINEL_CAP_SRP_CLIENT:
ret = "SRP_CLIENT";
break;
case SPINEL_CAP_ERROR_RATE_TRACKING:
ret = "ERROR_RATE_TRACKING";
break;
+164
View File
@@ -718,6 +718,32 @@ enum
SPINEL_RADIO_LINK_TREL_UDP6 = 1,
};
typedef enum
{
SPINEL_SRP_CLIENT_ITEM_STATE_TO_ADD = 0, // Item to be added/registered.
SPINEL_SRP_CLIENT_ITEM_STATE_ADDING = 1, // Item is being added/registered.
SPINEL_SRP_CLIENT_ITEM_STATE_TO_REFRESH = 2, // Item to be refreshed (re-register to renew lease).
SPINEL_SRP_CLIENT_ITEM_STATE_REFRESHING = 3, // Item is being refreshed.
SPINEL_SRP_CLIENT_ITEM_STATE_TO_REMOVE = 4, // Item to be removed.
SPINEL_SRP_CLIENT_ITEM_STATE_REMOVING = 5, // Item is being removed.
SPINEL_SRP_CLIENT_ITEM_STATE_REGISTERED = 6, // Item is registered with server.
SPINEL_SRP_CLIENT_ITEM_STATE_REMOVED = 7, // Item is removed.
} spinel_srp_client_item_state_t;
typedef enum
{
SPINEL_SRP_CLIENT_ERROR_NONE = 0, // No error.
SPINEL_SRP_CLIENT_ERROR_PARSE = 1, // Server unable to interpret due to format error.
SPINEL_SRP_CLIENT_ERROR_FAILED = 2, // Server encountered an internal failure.
SPINEL_SRP_CLIENT_ERROR_NOT_FOUND = 3, // Name that ought to exist, does not exists.
SPINEL_SRP_CLIENT_ERROR_NOT_IMPLEMENTED = 4, // Server does not support the query type.
SPINEL_SRP_CLIENT_ERROR_SECURITY = 5, // Service is not authoritative for zone.
SPINEL_SRP_CLIENT_ERROR_DUPLICATED = 6, // Some name that ought not to exist, does exist.
SPINEL_SRP_CLIENT_ERROR_RESPONSE_TIMEOUT = 7, // Timed out waiting for response from server (client would retry).
SPINEL_SRP_CLIENT_ERROR_INVALID_ARGS = 8, // Invalid args (e.g., bad service name or TXT-DATA).
SPINEL_SRP_CLIENT_ERROR_NO_BUFS = 9, // No buffer to send the SRP update message.
} spinel_srp_client_error_t;
typedef struct
{
uint8_t bytes[8];
@@ -1153,6 +1179,7 @@ enum
SPINEL_CAP_RADIO_COEX = (SPINEL_CAP_OPENTHREAD__BEGIN + 11),
SPINEL_CAP_MAC_RETRY_HISTOGRAM = (SPINEL_CAP_OPENTHREAD__BEGIN + 12),
SPINEL_CAP_MULTI_RADIO = (SPINEL_CAP_OPENTHREAD__BEGIN + 13),
SPINEL_CAP_SRP_CLIENT = (SPINEL_CAP_OPENTHREAD__BEGIN + 14),
SPINEL_CAP_OPENTHREAD__END = 640,
SPINEL_CAP_THREAD__BEGIN = 1024,
@@ -3637,6 +3664,143 @@ enum
*/
SPINEL_PROP_NEIGHBOR_TABLE_MULTI_RADIO_INFO = SPINEL_PROP_OPENTHREAD__BEGIN + 16,
/// SRP Client Start
/** Format: `b(6Sb)` - Write only
* Required capability: `SPINEL_CAP_SRP_CLIENT`.
*
* Writing to this property allows user to start or stop the SRP client operation with a given SRP server.
*
* Written value format is:
*
* `b` : TRUE to start the client, FALSE to stop the client.
*
* When used to start the SRP client, the following fields should also be included:
*
* `6` : SRP server IPv6 address.
* `U` : SRP server port number.
* `b` : Boolean to indicate whether or not to emit SRP client events (using `SPINEL_PROP_SRP_CLIENT_EVENT`).
*
*/
SPINEL_PROP_SRP_CLIENT_START = SPINEL_PROP_OPENTHREAD__BEGIN + 17,
/// SRP Client Lease Interval
/** Format: `L` - Read/Write
* Required capability: `SPINEL_CAP_SRP_CLIENT`.
*
* The lease interval used in SRP update requests (in seconds).
*
*/
SPINEL_PROP_SRP_CLIENT_LEASE_INTERVAL = SPINEL_PROP_OPENTHREAD__BEGIN + 18,
/// SRP Client Key Lease Interval
/** Format: `L` - Read/Write
* Required capability: `SPINEL_CAP_SRP_CLIENT`.
*
* The key lease interval used in SRP update requests (in seconds).
*
*/
SPINEL_PROP_SRP_CLIENT_KEY_LEASE_INTERVAL = SPINEL_PROP_OPENTHREAD__BEGIN + 19,
/// SRP Client Host Info
/** Format: `UCt(A(6))` - Read only
* Required capability: `SPINEL_CAP_SRP_CLIENT`.
*
* Format is:
*
* `U` : The host name.
* `C` : The host state (values from `spinel_srp_client_item_state_t`).
* `t(A(6))` : Structure containing array of host IPv6 addresses.
*
*/
SPINEL_PROP_SRP_CLIENT_HOST_INFO = SPINEL_PROP_OPENTHREAD__BEGIN + 20,
/// SRP Client Host Name (label).
/** Format: `U` - Read/Write
* Required capability: `SPINEL_CAP_SRP_CLIENT`.
*
*/
SPINEL_PROP_SRP_CLIENT_HOST_NAME = SPINEL_PROP_OPENTHREAD__BEGIN + 21,
/// SRP Client Host Addresses
/** Format: `A(6)` - Read/Write
* Required capability: `SPINEL_CAP_SRP_CLIENT`.
*
*/
SPINEL_PROP_SRP_CLIENT_HOST_ADDRESSES = SPINEL_PROP_OPENTHREAD__BEGIN + 22,
/// SRP Client Services
/** Format: `A(t(UUSSSd))` - Read/Insert/Remove
* Required capability: `SPINEL_CAP_SRP_CLIENT`.
*
* This property provide a list/array of services. Data per item is
*
* `U` : The service name labels (e.g., "_chip._udp", not the full domain name.
* `U` : The service instance name label (not the full name).
* `S` : The service port number.
* `S` : The service priority.
* `S` : The service weight.
*
* During remove operation, only service name and service instance name would be used.
*
*/
SPINEL_PROP_SRP_CLIENT_SERVICES = SPINEL_PROP_OPENTHREAD__BEGIN + 23,
/// SRP Client Host And Services Remove
/** Format: `b` : Write only
* Required capability: `SPINEL_CAP_SRP_CLIENT`.
*
* Writing to this property starts the remove process of the host info and all services.
* Please see `otSrpClientRemoveHostAndServices()` for more details.
*
* Format is:
*
* `b` : A boolean indicating whether or not the host key lease should also be removed.
*
*/
SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_REMOVE = SPINEL_PROP_OPENTHREAD__BEGIN + 24,
/// SRP Client Host And Services Clear
/** Format: Empty : Write only
* Required capability: `SPINEL_CAP_SRP_CLIENT`.
*
* Writing to this property clears all host info and all the services.
* Please see `otSrpClientClearHostAndServices()` for more details.
*
*/
SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_CLEAR = SPINEL_PROP_OPENTHREAD__BEGIN + 25,
/// SRP Client Event
/** Format: t() : Asynchronous event only
* Required capability: `SPINEL_CAP_SRP_CLIENT`.
*
* This property is asynchronously emitted when there is an event from SRP client notifying some state changes or
* errors.
*
* The general format of this property is as follows:
*
* `S` : Error code (see `spinel_srp_client_error_t` enumeration).
* `d` : Host info data.
* `d` : Active services.
* `d` : Removed services.
*
* The host info data contains:
*
* `U` : The host name.
* `C` : The host state (values from `spinel_srp_client_item_state_t`).
* `t(A(6))` : Structure containing array of host IPv6 addresses.
*
* The active or removed services data is an array of services `A(t(UUSSSd))` with each service format:
*
* `U` : The service name labels (e.g., "_chip._udp", not the full domain name.
* `U` : The service instance name label (not the full name).
* `S` : The service port number.
* `S` : The service priority.
* `S` : The service weight.
* `d` : The encoded TXT-DATA.
*
*/
SPINEL_PROP_SRP_CLIENT_EVENT = SPINEL_PROP_OPENTHREAD__BEGIN + 26,
SPINEL_PROP_OPENTHREAD__END = 0x2000,
SPINEL_PROP_SERVER__BEGIN = 0xA0,
+9
View File
@@ -243,6 +243,10 @@ NcpBase::NcpBase(Instance *aInstance)
, mOutboundInsecureIpFrameCounter(0)
, mDroppedOutboundIpFrameCounter(0)
, mDroppedInboundIpFrameCounter(0)
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
, mSrpClientNumHostAddresses(0)
, mSrpClientCallbackEnabled(false)
#endif
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
, mFramingErrorCounter(0)
, mRxSpinelFrameCounter(0)
@@ -281,6 +285,7 @@ NcpBase::NcpBase(Instance *aInstance)
#endif
otThreadRegisterParentResponseCallback(mInstance, &NcpBase::HandleParentResponseInfo, static_cast<void *>(this));
#endif // OPENTHREAD_FTD
#if OPENTHREAD_CONFIG_LEGACY_ENABLE
mLegacyNodeDidJoin = false;
mLegacyHandlers = nullptr;
@@ -1911,6 +1916,10 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CAPS>(void)
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_MULTI_RADIO));
#endif
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_SRP_CLIENT));
#endif
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
exit:
+42
View File
@@ -50,6 +50,9 @@
#if OPENTHREAD_CONFIG_MULTI_RADIO
#include <openthread/multi_radio.h>
#endif
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
#include <openthread/srp_client.h>
#endif
#include "changed_props_set.hpp"
#include "common/instance.hpp"
@@ -594,6 +597,45 @@ protected:
uint32_t mOutboundInsecureIpFrameCounter; // Number of insecure outbound data/IP frames.
uint32_t mDroppedOutboundIpFrameCounter; // Number of dropped outbound data/IP frames.
uint32_t mDroppedInboundIpFrameCounter; // Number of dropped inbound data/IP frames.
#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];
};
otError EncodeSrpClientHostInfo(const otSrpClientHostInfo &aHostInfo);
otError EncodeSrpClientServices(const otSrpClientService *aServices);
static void HandleSrpClientCallback(otError aError,
const otSrpClientHostInfo *aHostInfo,
const otSrpClientService * aServices,
const otSrpClientService * aRemovedServices,
void * aContext);
void HandleSrpClientCallback(otError aError,
const otSrpClientHostInfo *aHostInfo,
const otSrpClientService * aServices,
const otSrpClientService * aRemovedServices);
char mSrpClientHostName[kSrpClientNameSize];
SrpClientService mSrpClientServicePool[kSrpClientMaxServices];
otIp6Address mSrpClientHostAddresses[kSrpClientMaxHostAddresses];
uint8_t mSrpClientNumHostAddresses;
bool mSrpClientCallbackEnabled;
#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
#if OPENTHREAD_CONFIG_LEGACY_ENABLE
const otNcpLegacyHandlers *mLegacyHandlers;
uint8_t mLegacyUlaPrefix[OT_NCP_LEGACY_ULA_PREFIX_LENGTH];
+28
View File
@@ -329,6 +329,15 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey)
#if OPENTHREAD_CONFIG_MULTI_RADIO
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_NEIGHBOR_TABLE_MULTI_RADIO_INFO),
#endif
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_LEASE_INTERVAL),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_KEY_LEASE_INTERVAL),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_HOST_INFO),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_HOST_NAME),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_HOST_ADDRESSES),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_SERVICES),
#endif
#if OPENTHREAD_CONFIG_LEGACY_ENABLE
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_NEST_LEGACY_ULA_PREFIX),
OT_NCP_GET_HANDLER_ENTRY(SPINEL_PROP_NEST_LEGACY_LAST_NODE_JOINED),
@@ -544,6 +553,15 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey)
#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SLAAC_ENABLED),
#endif
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_START),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_LEASE_INTERVAL),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_KEY_LEASE_INTERVAL),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_HOST_NAME),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_HOST_ADDRESSES),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_REMOVE),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_CLEAR),
#endif
#if OPENTHREAD_CONFIG_LEGACY_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_NEST_LEGACY_ULA_PREFIX),
#endif
@@ -602,6 +620,11 @@ NcpBase::PropertyHandler NcpBase::FindInsertPropertyHandler(spinel_prop_key_t aK
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
OT_NCP_INSERT_HANDLER_ENTRY(SPINEL_PROP_THREAD_JOINERS),
#endif
#if OPENTHREAD_FTD || OPENTHREAD_MTD
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
OT_NCP_INSERT_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_SERVICES),
#endif
#endif
};
@@ -650,6 +673,11 @@ NcpBase::PropertyHandler NcpBase::FindRemovePropertyHandler(spinel_prop_key_t aK
#endif
#if OPENTHREAD_FTD
OT_NCP_REMOVE_HANDLER_ENTRY(SPINEL_PROP_THREAD_ACTIVE_ROUTER_IDS),
#endif
#if OPENTHREAD_FTD || OPENTHREAD_MTD
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
OT_NCP_REMOVE_HANDLER_ENTRY(SPINEL_PROP_SRP_CLIENT_SERVICES),
#endif
#endif
};
+427
View File
@@ -64,6 +64,7 @@
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/instance.hpp"
#include "common/string.hpp"
#include "net/ip6.hpp"
#if OPENTHREAD_MTD || OPENTHREAD_FTD
@@ -3213,6 +3214,432 @@ exit:
}
#endif // OPENTHREAD_CONFIG_MULTI_RADIO
// ----------------------------------------------------------------------------
// SRP Client
// ----------------------------------------------------------------------------
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_CLIENT_START>(void)
{
otError error = OT_ERROR_NONE;
bool start;
bool callbackEnabled;
otSockAddr serverAddr;
SuccessOrExit(error = mDecoder.ReadBool(start));
if (!start)
{
otSrpClientStop(mInstance);
ExitNow();
}
SuccessOrExit(error = mDecoder.ReadIp6Address(serverAddr.mAddress));
SuccessOrExit(error = mDecoder.ReadUint16(serverAddr.mPort));
SuccessOrExit(error = mDecoder.ReadBool(callbackEnabled));
SuccessOrExit(error = otSrpClientStart(mInstance, &serverAddr, HandleSrpClientCallback, this));
mSrpClientCallbackEnabled = callbackEnabled;
exit:
return error;
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SRP_CLIENT_LEASE_INTERVAL>(void)
{
return mEncoder.WriteUint32(otSrpClientGetLeaseInterval(mInstance));
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_CLIENT_LEASE_INTERVAL>(void)
{
otError error;
uint32_t interval;
SuccessOrExit(error = mDecoder.ReadUint32(interval));
otSrpClientSetLeaseInterval(mInstance, interval);
exit:
return error;
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SRP_CLIENT_KEY_LEASE_INTERVAL>(void)
{
return mEncoder.WriteUint32(otSrpClientGetKeyLeaseInterval(mInstance));
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_CLIENT_KEY_LEASE_INTERVAL>(void)
{
otError error;
uint32_t interval;
SuccessOrExit(error = mDecoder.ReadUint32(interval));
otSrpClientSetKeyLeaseInterval(mInstance, interval);
exit:
return error;
}
static spinel_srp_client_item_state_t SrpClientItemStatetoSpinel(otSrpClientItemState aItemState)
{
spinel_srp_client_item_state_t state = SPINEL_SRP_CLIENT_ITEM_STATE_REMOVED;
switch (aItemState)
{
case OT_SRP_CLIENT_ITEM_STATE_TO_ADD:
state = SPINEL_SRP_CLIENT_ITEM_STATE_TO_ADD;
break;
case OT_SRP_CLIENT_ITEM_STATE_ADDING:
state = SPINEL_SRP_CLIENT_ITEM_STATE_ADDING;
break;
case OT_SRP_CLIENT_ITEM_STATE_TO_REFRESH:
state = SPINEL_SRP_CLIENT_ITEM_STATE_TO_REFRESH;
break;
case OT_SRP_CLIENT_ITEM_STATE_REFRESHING:
state = SPINEL_SRP_CLIENT_ITEM_STATE_REFRESHING;
break;
case OT_SRP_CLIENT_ITEM_STATE_TO_REMOVE:
state = SPINEL_SRP_CLIENT_ITEM_STATE_TO_REMOVE;
break;
case OT_SRP_CLIENT_ITEM_STATE_REMOVING:
state = SPINEL_SRP_CLIENT_ITEM_STATE_REMOVING;
break;
case OT_SRP_CLIENT_ITEM_STATE_REGISTERED:
state = SPINEL_SRP_CLIENT_ITEM_STATE_REGISTERED;
break;
case OT_SRP_CLIENT_ITEM_STATE_REMOVED:
state = SPINEL_SRP_CLIENT_ITEM_STATE_REMOVED;
break;
}
return state;
}
otError NcpBase::EncodeSrpClientHostInfo(const otSrpClientHostInfo &aHostInfo)
{
otError error;
SuccessOrExit(error = mEncoder.WriteUtf8(aHostInfo.mName != nullptr ? aHostInfo.mName : ""));
SuccessOrExit(error = mEncoder.WriteUint8(SrpClientItemStatetoSpinel(aHostInfo.mState)));
SuccessOrExit(error = mEncoder.OpenStruct());
for (uint8_t index = 0; index < aHostInfo.mNumAddresses; index++)
{
SuccessOrExit(error = mEncoder.WriteIp6Address(aHostInfo.mAddresses[index]));
}
SuccessOrExit(error = mEncoder.CloseStruct());
exit:
return error;
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SRP_CLIENT_HOST_INFO>(void)
{
return EncodeSrpClientHostInfo(*otSrpClientGetHostInfo(mInstance));
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SRP_CLIENT_HOST_NAME>(void)
{
const char *name = otSrpClientGetHostInfo(mInstance)->mName;
return mEncoder.WriteUtf8(name != nullptr ? name : "");
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_CLIENT_HOST_NAME>(void)
{
otError error;
const char *name;
SuccessOrExit(error = mDecoder.ReadUtf8(name));
VerifyOrExit(StringLength(name, kSrpClientNameSize) < kSrpClientNameSize, 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
// This ensures that we do not overwrite a previous
// `mSrpClientHostName` when host name cannot be set.
SuccessOrExit(error = otSrpClientSetHostName(mInstance, name));
strcpy(mSrpClientHostName, name);
error = otSrpClientSetHostName(mInstance, mSrpClientHostName);
OT_ASSERT(error == OT_ERROR_NONE);
exit:
return error;
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SRP_CLIENT_HOST_ADDRESSES>(void)
{
otError error = OT_ERROR_NONE;
const otSrpClientHostInfo *hostInfo = otSrpClientGetHostInfo(mInstance);
for (uint8_t index = 0; index < hostInfo->mNumAddresses; index++)
{
SuccessOrExit(error = mEncoder.WriteIp6Address(hostInfo->mAddresses[index]));
}
exit:
return error;
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_CLIENT_HOST_ADDRESSES>(void)
{
otError error;
otIp6Address addresses[kSrpClientMaxHostAddresses];
uint8_t numAddresses = 0;
while (!mDecoder.IsAllReadInStruct())
{
VerifyOrExit(numAddresses < kSrpClientMaxHostAddresses, error = OT_ERROR_NO_BUFS);
SuccessOrExit(error = mDecoder.ReadIp6Address(addresses[numAddresses]));
numAddresses++;
}
// We first make sure we can set the addresses, and if so
// we copy the address list into `mSrpClientHostAddresses`
// 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.
SuccessOrExit(error = otSrpClientSetHostAddresses(mInstance, addresses, numAddresses));
memcpy(mSrpClientHostAddresses, addresses, sizeof(addresses));
mSrpClientNumHostAddresses = numAddresses;
error = otSrpClientSetHostAddresses(mInstance, mSrpClientHostAddresses, numAddresses);
OT_ASSERT(error == OT_ERROR_NONE);
exit:
return error;
}
otError NcpBase::EncodeSrpClientServices(const otSrpClientService *aServices)
{
otError error = OT_ERROR_NONE;
for (; aServices != nullptr; aServices = aServices->mNext)
{
SuccessOrExit(error = mEncoder.OpenStruct());
SuccessOrExit(error = mEncoder.WriteUtf8(aServices->mName));
SuccessOrExit(error = mEncoder.WriteUtf8(aServices->mInstanceName));
SuccessOrExit(error = mEncoder.WriteUint16(aServices->mPort));
SuccessOrExit(error = mEncoder.WriteUint16(aServices->mPriority));
SuccessOrExit(error = mEncoder.WriteUint16(aServices->mWeight));
SuccessOrExit(error = mEncoder.CloseStruct());
}
exit:
return error;
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_SRP_CLIENT_SERVICES>(void)
{
return EncodeSrpClientServices(otSrpClientGetServices(mInstance));
}
template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_SRP_CLIENT_SERVICES>(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;
}
}
VerifyOrExit(entry != nullptr, error = OT_ERROR_NO_BUFS);
SuccessOrExit(error = mDecoder.ReadUtf8(serviceName));
VerifyOrExit(StringLength(serviceName, kSrpClientNameSize) < kSrpClientNameSize, error = OT_ERROR_INVALID_ARGS);
strcpy(entry->mServiceName, serviceName);
entry->mService.mName = entry->mServiceName;
SuccessOrExit(error = mDecoder.ReadUtf8(instanceName));
VerifyOrExit(StringLength(instanceName, kSrpClientNameSize) < kSrpClientNameSize, error = OT_ERROR_INVALID_ARGS);
strcpy(entry->mInstanceName, instanceName);
entry->mService.mInstanceName = entry->mInstanceName;
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();
}
exit:
return error;
}
template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_SRP_CLIENT_SERVICES>(void)
{
otError error = OT_ERROR_NONE;
const char *serviceName;
const char *instanceName;
SuccessOrExit(error = mDecoder.ReadUtf8(serviceName));
SuccessOrExit(error = mDecoder.ReadUtf8(instanceName));
for (SrpClientService &poolEntry : mSrpClientServicePool)
{
if (!poolEntry.IsInUse() || (strcmp(serviceName, poolEntry.mServiceName) != 0) ||
(strcmp(instanceName, poolEntry.mInstanceName) != 0))
{
continue;
}
error = otSrpClientRemoveService(mInstance, &poolEntry.mService);
ExitNow();
}
error = OT_ERROR_NOT_FOUND;
exit:
return error;
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_REMOVE>(void)
{
otError error = OT_ERROR_NONE;
bool removeKeyLease;
SuccessOrExit(error = mDecoder.ReadBool(removeKeyLease));
error = otSrpClientRemoveHostAndServices(mInstance, removeKeyLease);
exit:
return error;
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_SRP_CLIENT_HOST_SERVICES_CLEAR>(void)
{
otSrpClientClearHostAndServices(mInstance);
return OT_ERROR_NONE;
}
static spinel_srp_client_error_t SrpClientErrorToSpinelError(otError aError)
{
spinel_srp_client_error_t error = SPINEL_SRP_CLIENT_ERROR_FAILED;
switch (aError)
{
case OT_ERROR_NONE:
error = SPINEL_SRP_CLIENT_ERROR_NONE;
break;
case OT_ERROR_PARSE:
error = SPINEL_SRP_CLIENT_ERROR_PARSE;
break;
case OT_ERROR_NOT_FOUND:
error = SPINEL_SRP_CLIENT_ERROR_NOT_FOUND;
break;
case OT_ERROR_NOT_IMPLEMENTED:
error = SPINEL_SRP_CLIENT_ERROR_NOT_IMPLEMENTED;
break;
case OT_ERROR_SECURITY:
error = SPINEL_SRP_CLIENT_ERROR_SECURITY;
break;
case OT_ERROR_DUPLICATED:
error = SPINEL_SRP_CLIENT_ERROR_DUPLICATED;
break;
case OT_ERROR_RESPONSE_TIMEOUT:
error = SPINEL_SRP_CLIENT_ERROR_RESPONSE_TIMEOUT;
break;
case OT_ERROR_INVALID_ARGS:
error = SPINEL_SRP_CLIENT_ERROR_INVALID_ARGS;
break;
case OT_ERROR_NO_BUFS:
error = SPINEL_SRP_CLIENT_ERROR_NO_BUFS;
break;
case OT_ERROR_FAILED:
default:
error = SPINEL_SRP_CLIENT_ERROR_FAILED;
break;
}
return error;
}
void NcpBase::HandleSrpClientCallback(otError aError,
const otSrpClientHostInfo *aHostInfo,
const otSrpClientService * aServices,
const otSrpClientService * aRemovedServices,
void * aContext)
{
static_cast<NcpBase *>(aContext)->HandleSrpClientCallback(aError, aHostInfo, aServices, aRemovedServices);
}
void NcpBase::HandleSrpClientCallback(otError aError,
const otSrpClientHostInfo *aHostInfo,
const otSrpClientService * aServices,
const otSrpClientService * aRemovedServices)
{
otError error = OT_ERROR_NONE;
const otSrpClientService *service;
const otSrpClientService *next;
VerifyOrExit(mSrpClientCallbackEnabled);
SuccessOrExit(error = mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_PROP_VALUE_IS,
SPINEL_PROP_SRP_CLIENT_EVENT));
SuccessOrExit(error = mEncoder.WriteUint16(SrpClientErrorToSpinelError(aError)));
SuccessOrExit(error = mEncoder.OpenStruct());
SuccessOrExit(error = EncodeSrpClientHostInfo(*aHostInfo));
SuccessOrExit(error = mEncoder.CloseStruct());
SuccessOrExit(error = mEncoder.OpenStruct());
SuccessOrExit(error = EncodeSrpClientServices(aServices));
SuccessOrExit(error = mEncoder.CloseStruct());
SuccessOrExit(error = mEncoder.OpenStruct());
SuccessOrExit(error = EncodeSrpClientServices(aRemovedServices));
SuccessOrExit(error = mEncoder.CloseStruct());
SuccessOrExit(error = mEncoder.EndFrame());
exit:
if (error != OT_ERROR_NONE)
{
// Emit a NONMEM status if we fail to send the event.
mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
mUpdateChangedPropsTask.Post();
}
for (service = aRemovedServices; service != nullptr; service = next)
{
next = service->mNext;
for (SrpClientService &poolEntry : mSrpClientServicePool)
{
if (&poolEntry.mService == service)
{
poolEntry.MarkAsNotInUse();
}
}
}
}
#endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
#if OPENTHREAD_CONFIG_LEGACY_ENABLE
void NcpBase::RegisterLegacyHandlers(const otNcpLegacyHandlers *aHandlers)
+24
View File
@@ -189,4 +189,28 @@
#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_