mirror of
https://github.com/espressif/openthread.git
synced 2026-07-29 23:27:46 +00:00
[dataset] add callback to receive MGMT_SET responses (#6887)
This commit is contained in:
@@ -290,6 +290,21 @@ typedef enum otMeshcopTlvType
|
||||
OT_MESHCOP_TLV_JOINERADVERTISEMENT = 241, ///< meshcop Joiner Advertisement TLV
|
||||
} otMeshcopTlvType;
|
||||
|
||||
/**
|
||||
* This function pointer is called when a response to a MGMT_SET request is received or times out.
|
||||
*
|
||||
* @param[in] aResult A result of the operation.
|
||||
* @param[in] aContext A pointer to application-specific context.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The request was accepted by the leader.
|
||||
* @retval OT_ERROR_REJECTED The request was rejected by the leader.
|
||||
* @retval OT_ERROR_PARSE An error occurred during parsing the response.
|
||||
* @retval OT_ERROR_ABORT The request was reset by peer.
|
||||
* @retval OT_ERROR_RESPONSE_TIMEOUT No response or acknowledgment received during timeout period.
|
||||
*
|
||||
*/
|
||||
typedef void (*otDatasetMgmtSetCallback)(otError aResult, void *aContext);
|
||||
|
||||
/**
|
||||
* This function indicates whether a valid network is present in the Active Operational Dataset or not.
|
||||
*
|
||||
@@ -452,15 +467,20 @@ otError otDatasetSendMgmtActiveGet(otInstance * aInstan
|
||||
* @param[in] aDataset A pointer to operational dataset.
|
||||
* @param[in] aTlvs A pointer to TLVs.
|
||||
* @param[in] aLength The length of TLVs.
|
||||
* @param[in] aCallback A pointer to a function that is called on response reception or timeout.
|
||||
* @param[in] aContext A pointer to application-specific context for @p aCallback.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully send the meshcop dataset command.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space to send.
|
||||
* @retval OT_ERROR_BUSY A previous request is ongoing.
|
||||
*
|
||||
*/
|
||||
otError otDatasetSendMgmtActiveSet(otInstance * aInstance,
|
||||
const otOperationalDataset *aDataset,
|
||||
const uint8_t * aTlvs,
|
||||
uint8_t aLength);
|
||||
uint8_t aLength,
|
||||
otDatasetMgmtSetCallback aCallback,
|
||||
void * aContext);
|
||||
|
||||
/**
|
||||
* This function sends MGMT_PENDING_GET.
|
||||
@@ -488,15 +508,20 @@ otError otDatasetSendMgmtPendingGet(otInstance * aInsta
|
||||
* @param[in] aDataset A pointer to operational dataset.
|
||||
* @param[in] aTlvs A pointer to TLVs.
|
||||
* @param[in] aLength The length of TLVs.
|
||||
* @param[in] aCallback A pointer to a function that is called on response reception or timeout.
|
||||
* @param[in] aContext A pointer to application-specific context for @p aCallback.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully send the meshcop dataset command.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient buffer space to send.
|
||||
* @retval OT_ERROR_BUSY A previous request is ongoing.
|
||||
*
|
||||
*/
|
||||
otError otDatasetSendMgmtPendingSet(otInstance * aInstance,
|
||||
const otOperationalDataset *aDataset,
|
||||
const uint8_t * aTlvs,
|
||||
uint8_t aLength);
|
||||
uint8_t aLength,
|
||||
otDatasetMgmtSetCallback aCallback,
|
||||
void * aContext);
|
||||
|
||||
/**
|
||||
* This function generates PSKc from a given pass-phrase, network name, and extended PAN ID.
|
||||
|
||||
@@ -234,6 +234,11 @@ typedef enum OT_MUST_USE_RESULT otError
|
||||
*/
|
||||
OT_ERROR_PENDING = 36,
|
||||
|
||||
/**
|
||||
* Request rejected.
|
||||
*/
|
||||
OT_ERROR_REJECTED = 37,
|
||||
|
||||
/**
|
||||
* The number of defined errors.
|
||||
*/
|
||||
|
||||
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (145)
|
||||
#define OPENTHREAD_API_VERSION (146)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -565,11 +565,13 @@ otError Dataset::ProcessMgmtSetCommand(Arg aArgs[])
|
||||
|
||||
if (aArgs[0] == "active")
|
||||
{
|
||||
error = otDatasetSendMgmtActiveSet(mInterpreter.mInstance, &dataset, tlvs, tlvsLength);
|
||||
error = otDatasetSendMgmtActiveSet(mInterpreter.mInstance, &dataset, tlvs, tlvsLength, /* aCallback */ nullptr,
|
||||
/* aContext */ nullptr);
|
||||
}
|
||||
else if (aArgs[0] == "pending")
|
||||
{
|
||||
error = otDatasetSendMgmtPendingSet(mInterpreter.mInstance, &dataset, tlvs, tlvsLength);
|
||||
error = otDatasetSendMgmtPendingSet(mInterpreter.mInstance, &dataset, tlvs, tlvsLength, /* aCallback */ nullptr,
|
||||
/* aContext */ nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -136,12 +136,14 @@ otError otDatasetSendMgmtActiveGet(otInstance * aInstan
|
||||
otError otDatasetSendMgmtActiveSet(otInstance * aInstance,
|
||||
const otOperationalDataset *aDataset,
|
||||
const uint8_t * aTlvs,
|
||||
uint8_t aLength)
|
||||
uint8_t aLength,
|
||||
otDatasetMgmtSetCallback aCallback,
|
||||
void * aContext)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<MeshCoP::ActiveDataset>().SendSetRequest(*static_cast<const MeshCoP::Dataset::Info *>(aDataset),
|
||||
aTlvs, aLength);
|
||||
aTlvs, aLength, aCallback, aContext);
|
||||
}
|
||||
|
||||
otError otDatasetSendMgmtPendingGet(otInstance * aInstance,
|
||||
@@ -159,12 +161,14 @@ otError otDatasetSendMgmtPendingGet(otInstance * aInsta
|
||||
otError otDatasetSendMgmtPendingSet(otInstance * aInstance,
|
||||
const otOperationalDataset *aDataset,
|
||||
const uint8_t * aTlvs,
|
||||
uint8_t aLength)
|
||||
uint8_t aLength,
|
||||
otDatasetMgmtSetCallback aCallback,
|
||||
void * aContext)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.Get<MeshCoP::PendingDataset>().SendSetRequest(
|
||||
*static_cast<const MeshCoP::Dataset::Info *>(aDataset), aTlvs, aLength);
|
||||
*static_cast<const MeshCoP::Dataset::Info *>(aDataset), aTlvs, aLength, aCallback, aContext);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
@@ -77,6 +77,7 @@ const char *ErrorToString(Error aError)
|
||||
"LinkMarginLow", // (34) kErrorLinkMarginLow
|
||||
"InvalidCommand", // (35) kErrorInvalidCommand
|
||||
"Pending", // (36) kErrorPending
|
||||
"Rejected", // (37) kErrorRejected
|
||||
};
|
||||
|
||||
return aError < OT_ARRAY_LENGTH(kErrorStrings) ? kErrorStrings[aError] : "UnknownErrorType";
|
||||
|
||||
@@ -88,6 +88,7 @@ constexpr Error kErrorNotLowpanDataFrame = OT_ERROR_NOT_LOWPAN_DATA_FRAM
|
||||
constexpr Error kErrorLinkMarginLow = OT_ERROR_LINK_MARGIN_LOW;
|
||||
constexpr Error kErrorInvalidCommand = OT_ERROR_INVALID_COMMAND;
|
||||
constexpr Error kErrorPending = OT_ERROR_PENDING;
|
||||
constexpr Error kErrorRejected = OT_ERROR_REJECTED;
|
||||
constexpr Error kErrorGeneric = OT_ERROR_GENERIC;
|
||||
|
||||
constexpr uint8_t kNumErrors = OT_NUM_ERRORS;
|
||||
|
||||
@@ -54,8 +54,10 @@ DatasetManager::DatasetManager(Instance &aInstance, Dataset::Type aType, Timer::
|
||||
: InstanceLocator(aInstance)
|
||||
, mLocal(aInstance, aType)
|
||||
, mTimestampValid(false)
|
||||
, mCoapPending(false)
|
||||
, mMgmtPending(false)
|
||||
, mTimer(aInstance, aTimerHandler)
|
||||
, mMgmtSetCallback(nullptr)
|
||||
, mMgmtSetCallbackContext(nullptr)
|
||||
{
|
||||
mTimestamp.Init();
|
||||
}
|
||||
@@ -277,7 +279,7 @@ void DatasetManager::SendSet(void)
|
||||
Ip6::MessageInfo messageInfo;
|
||||
Dataset dataset;
|
||||
|
||||
VerifyOrExit(!mCoapPending, error = kErrorBusy);
|
||||
VerifyOrExit(!mMgmtPending, error = kErrorBusy);
|
||||
VerifyOrExit(Get<Mle::MleRouter>().IsChild() || Get<Mle::MleRouter>().IsRouter(), error = kErrorInvalidState);
|
||||
VerifyOrExit(mLocal.Compare(GetTimestamp()) < 0, error = kErrorInvalidState);
|
||||
|
||||
@@ -308,8 +310,8 @@ void DatasetManager::SendSet(void)
|
||||
messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
|
||||
IgnoreError(Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
|
||||
messageInfo.SetPeerPort(Tmf::kUdpPort);
|
||||
SuccessOrExit(error =
|
||||
Get<Tmf::Agent>().SendMessage(*message, messageInfo, &DatasetManager::HandleCoapResponse, this));
|
||||
SuccessOrExit(
|
||||
error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, &DatasetManager::HandleMgmtSetResponse, this));
|
||||
|
||||
otLogInfoMeshCoP("Sent %s set to leader", Dataset::TypeToString(GetType()));
|
||||
|
||||
@@ -318,7 +320,7 @@ exit:
|
||||
switch (error)
|
||||
{
|
||||
case kErrorNone:
|
||||
mCoapPending = true;
|
||||
mMgmtPending = true;
|
||||
break;
|
||||
|
||||
case kErrorNoBufs:
|
||||
@@ -332,21 +334,54 @@ exit:
|
||||
}
|
||||
}
|
||||
|
||||
void DatasetManager::HandleCoapResponse(void * aContext,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo,
|
||||
Error aError)
|
||||
void DatasetManager::HandleMgmtSetResponse(void * aContext,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo,
|
||||
Error aError)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aMessage);
|
||||
OT_UNUSED_VARIABLE(aMessageInfo);
|
||||
OT_UNUSED_VARIABLE(aError);
|
||||
|
||||
static_cast<DatasetManager *>(aContext)->HandleCoapResponse();
|
||||
static_cast<DatasetManager *>(aContext)->HandleMgmtSetResponse(
|
||||
*static_cast<Coap::Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo), aError);
|
||||
}
|
||||
|
||||
void DatasetManager::HandleCoapResponse(void)
|
||||
void DatasetManager::HandleMgmtSetResponse(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Error aError)
|
||||
{
|
||||
mCoapPending = false;
|
||||
OT_UNUSED_VARIABLE(aMessageInfo);
|
||||
|
||||
Error error;
|
||||
StateTlv stateTlv;
|
||||
|
||||
SuccessOrExit(error = aError);
|
||||
VerifyOrExit(Tlv::FindTlv(aMessage, stateTlv) == kErrorNone, error = kErrorParse);
|
||||
|
||||
switch (stateTlv.GetState())
|
||||
{
|
||||
case StateTlv::kReject:
|
||||
error = kErrorRejected;
|
||||
break;
|
||||
case StateTlv::kAccept:
|
||||
error = kErrorNone;
|
||||
break;
|
||||
default:
|
||||
error = kErrorParse;
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
otLogInfoMeshCoP("MGMT_SET finished: %s", ErrorToString(error));
|
||||
|
||||
mMgmtPending = false;
|
||||
|
||||
if (mMgmtSetCallback != nullptr)
|
||||
{
|
||||
otDatasetMgmtSetCallback callback = mMgmtSetCallback;
|
||||
void * context = mMgmtSetCallbackContext;
|
||||
|
||||
mMgmtSetCallback = nullptr;
|
||||
mMgmtSetCallbackContext = nullptr;
|
||||
|
||||
callback(error, context);
|
||||
}
|
||||
|
||||
mTimer.Start(kSendSetDelay);
|
||||
}
|
||||
|
||||
@@ -460,12 +495,18 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error DatasetManager::SendSetRequest(const Dataset::Info &aDatasetInfo, const uint8_t *aTlvs, uint8_t aLength)
|
||||
Error DatasetManager::SendSetRequest(const Dataset::Info & aDatasetInfo,
|
||||
const uint8_t * aTlvs,
|
||||
uint8_t aLength,
|
||||
otDatasetMgmtSetCallback aCallback,
|
||||
void * aContext)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Coap::Message * message;
|
||||
Error error = kErrorNone;
|
||||
Coap::Message * message = nullptr;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
|
||||
VerifyOrExit(!mMgmtPending, error = kErrorBusy);
|
||||
|
||||
VerifyOrExit((message = NewMeshCoPMessage(Get<Tmf::Agent>())) != nullptr, error = kErrorNoBufs);
|
||||
|
||||
SuccessOrExit(error =
|
||||
@@ -508,7 +549,11 @@ Error DatasetManager::SendSetRequest(const Dataset::Info &aDatasetInfo, const ui
|
||||
messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
|
||||
IgnoreError(Get<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr()));
|
||||
messageInfo.SetPeerPort(Tmf::kUdpPort);
|
||||
SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
|
||||
|
||||
SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, HandleMgmtSetResponse, this));
|
||||
mMgmtSetCallback = aCallback;
|
||||
mMgmtSetCallbackContext = aContext;
|
||||
mMgmtPending = true;
|
||||
|
||||
otLogInfoMeshCoP("sent dataset set request to leader");
|
||||
|
||||
|
||||
@@ -149,12 +149,19 @@ public:
|
||||
* @param[in] aDatasetInfo The Operational Dataset.
|
||||
* @param[in] aTlvs Any additional raw TLVs to include.
|
||||
* @param[in] aLength Number of bytes in @p aTlvs.
|
||||
* @param[in] aCallback A pointer to a function that is called on response reception or timeout.
|
||||
* @param[in] aContext A pointer to application-specific context for @p aCallback.
|
||||
*
|
||||
* @retval kErrorNone Successfully send the meshcop dataset command.
|
||||
* @retval kErrorNoBufs Insufficient buffer space to send.
|
||||
* @retval kErrorBusy A previous request is ongoing.
|
||||
*
|
||||
*/
|
||||
Error SendSetRequest(const Dataset::Info &aDatasetInfo, const uint8_t *aTlvs, uint8_t aLength);
|
||||
Error SendSetRequest(const Dataset::Info & aDatasetInfo,
|
||||
const uint8_t * aTlvs,
|
||||
uint8_t aLength,
|
||||
otDatasetMgmtSetCallback aCallback,
|
||||
void * aContext);
|
||||
|
||||
/**
|
||||
* This method sends a MGMT_GET request.
|
||||
@@ -334,11 +341,11 @@ protected:
|
||||
bool mTimestampValid : 1;
|
||||
|
||||
private:
|
||||
static void HandleCoapResponse(void * aContext,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo,
|
||||
Error aError);
|
||||
void HandleCoapResponse(void);
|
||||
static void HandleMgmtSetResponse(void * aContext,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo,
|
||||
Error aError);
|
||||
void HandleMgmtSetResponse(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Error aError);
|
||||
|
||||
bool IsActiveDataset(void) const { return GetType() == Dataset::kActive; }
|
||||
bool IsPendingDataset(void) const { return GetType() == Dataset::kPending; }
|
||||
@@ -358,8 +365,11 @@ private:
|
||||
static constexpr uint8_t kMaxDatasetTlvs = 16; // Maximum number of TLVs in a Dataset.
|
||||
static constexpr uint32_t kSendSetDelay = 5000; // Milliseconds
|
||||
|
||||
bool mCoapPending : 1;
|
||||
bool mMgmtPending : 1;
|
||||
TimerMilli mTimer;
|
||||
|
||||
otDatasetMgmtSetCallback mMgmtSetCallback;
|
||||
void * mMgmtSetCallbackContext;
|
||||
};
|
||||
|
||||
class ActiveDataset : public DatasetManager, private NonCopyable
|
||||
|
||||
@@ -1672,7 +1672,8 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MGMT_SET_ACTIV
|
||||
uint8_t extraTlvsLength;
|
||||
|
||||
SuccessOrExit(error = DecodeOperationalDataset(dataset, &extraTlvs, &extraTlvsLength));
|
||||
error = otDatasetSendMgmtActiveSet(mInstance, &dataset, extraTlvs, extraTlvsLength);
|
||||
error = otDatasetSendMgmtActiveSet(mInstance, &dataset, extraTlvs, extraTlvsLength, /* aCallback */ nullptr,
|
||||
/* aContext */ nullptr);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -1686,7 +1687,8 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_MGMT_SET_PENDI
|
||||
uint8_t extraTlvsLength;
|
||||
|
||||
SuccessOrExit(error = DecodeOperationalDataset(dataset, &extraTlvs, &extraTlvsLength));
|
||||
error = otDatasetSendMgmtPendingSet(mInstance, &dataset, extraTlvs, extraTlvsLength);
|
||||
error = otDatasetSendMgmtPendingSet(mInstance, &dataset, extraTlvs, extraTlvsLength, /* aCallback */ nullptr,
|
||||
/* aContext */ nullptr);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
|
||||
Reference in New Issue
Block a user