diff --git a/src/core/api/commissioner_api.cpp b/src/core/api/commissioner_api.cpp index 9e9f38244..57aaa2f2b 100644 --- a/src/core/api/commissioner_api.cpp +++ b/src/core/api/commissioner_api.cpp @@ -64,7 +64,7 @@ otError otCommissionerStop(otInstance *aInstance) otError error; Instance &instance = *static_cast(aInstance); - SuccessOrExit(error = instance.Get().Stop()); + SuccessOrExit(error = instance.Get().Stop(/* aResign */ true)); #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE SuccessOrExit(error = instance.Get().Start()); #endif diff --git a/src/core/meshcop/commissioner.cpp b/src/core/meshcop/commissioner.cpp index 3066bdeba..97b89e7b8 100644 --- a/src/core/meshcop/commissioner.cpp +++ b/src/core/meshcop/commissioner.cpp @@ -164,27 +164,42 @@ otError Commissioner::Start(otCommissionerStateCallback aStateCallback, SetState(OT_COMMISSIONER_STATE_PETITION); exit: + if (error != OT_ERROR_NONE) + { + Get().Stop(); + } return error; } -otError Commissioner::Stop(void) +otError Commissioner::Stop(bool aResign) { - otError error = OT_ERROR_NONE; + otError error = OT_ERROR_NONE; + bool needResign = false; VerifyOrExit(mState != OT_COMMISSIONER_STATE_DISABLED, error = OT_ERROR_INVALID_STATE); Get().Stop(); - Get().RemoveUnicastAddress(mCommissionerAloc); - RemoveCoapResources(); - ClearJoiners(); - mTransmitAttempts = 0; + if (mState == OT_COMMISSIONER_STATE_ACTIVE) + { + Get().RemoveUnicastAddress(mCommissionerAloc); + RemoveCoapResources(); + ClearJoiners(); + needResign = true; + } + else if (mState == OT_COMMISSIONER_STATE_PETITION) + { + mTransmitAttempts = 0; + } mTimer.Stop(); SetState(OT_COMMISSIONER_STATE_DISABLED); - SendKeepAlive(); + if (needResign && aResign) + { + SendKeepAlive(); + } exit: return error; @@ -696,16 +711,25 @@ void Commissioner::HandleLeaderPetitionResponse(Coap::Message * aMessage uint8_t state; bool retransmit = false; - VerifyOrExit(mState == OT_COMMISSIONER_STATE_PETITION, SetState(OT_COMMISSIONER_STATE_DISABLED)); - VerifyOrExit(aResult == OT_ERROR_NONE && aMessage->GetCode() == OT_COAP_CODE_CHANGED, retransmit = true); + VerifyOrExit(mState != OT_COMMISSIONER_STATE_ACTIVE); + VerifyOrExit(aResult == OT_ERROR_NONE && aMessage->GetCode() == OT_COAP_CODE_CHANGED, + retransmit = (mState == OT_COMMISSIONER_STATE_PETITION)); otLogInfoMeshCoP("received Leader Petition response"); SuccessOrExit(Tlv::ReadUint8Tlv(*aMessage, Tlv::kState, state)); - VerifyOrExit(state == StateTlv::kAccept, SetState(OT_COMMISSIONER_STATE_DISABLED)); + VerifyOrExit(state == StateTlv::kAccept, Stop(/* aResign */ false)); SuccessOrExit(Tlv::ReadUint16Tlv(*aMessage, Tlv::kCommissionerSessionId, mSessionId)); + // reject this session by sending KeepAlive reject if commissioner is in disabled state + // this could happen if commissioner is stopped by API during petitioning + if (mState == OT_COMMISSIONER_STATE_DISABLED) + { + SendKeepAlive(mSessionId); + ExitNow(); + } + Get().GetCommissionerAloc(mCommissionerAloc.GetAddress(), mSessionId); Get().AddUnicastAddress(mCommissionerAloc); @@ -721,7 +745,7 @@ exit: { if (mTransmitAttempts >= kPetitionRetryCount) { - SetState(OT_COMMISSIONER_STATE_DISABLED); + Stop(/* aResign */ false); } else { @@ -731,6 +755,11 @@ exit: } otError Commissioner::SendKeepAlive(void) +{ + return SendKeepAlive(mSessionId); +} + +otError Commissioner::SendKeepAlive(uint16_t aSessionId) { otError error = OT_ERROR_NONE; Coap::Message * message = NULL; @@ -745,7 +774,7 @@ otError Commissioner::SendKeepAlive(void) error = Tlv::AppendUint8Tlv(*message, Tlv::kState, (mState == OT_COMMISSIONER_STATE_ACTIVE) ? StateTlv::kAccept : StateTlv::kReject)); - SuccessOrExit(error = Tlv::AppendUint16Tlv(*message, Tlv::kCommissionerSessionId, mSessionId)); + SuccessOrExit(error = Tlv::AppendUint16Tlv(*message, Tlv::kCommissionerSessionId, aSessionId)); messageInfo.SetSockAddr(Get().GetMeshLocal16()); SuccessOrExit(error = Get().GetLeaderAloc(messageInfo.GetPeerAddr())); @@ -782,24 +811,18 @@ void Commissioner::HandleLeaderKeepAliveResponse(Coap::Message * aMessag uint8_t state; - VerifyOrExit(mState == OT_COMMISSIONER_STATE_ACTIVE, SetState(OT_COMMISSIONER_STATE_DISABLED)); - VerifyOrExit(aResult == OT_ERROR_NONE && aMessage->GetCode() == OT_COAP_CODE_CHANGED, - SetState(OT_COMMISSIONER_STATE_DISABLED)); + VerifyOrExit(mState == OT_COMMISSIONER_STATE_ACTIVE); + VerifyOrExit(aResult == OT_ERROR_NONE && aMessage->GetCode() == OT_COAP_CODE_CHANGED, Stop(/* aResign */ false)); otLogInfoMeshCoP("received Leader keep-alive response"); SuccessOrExit(Tlv::ReadUint8Tlv(*aMessage, Tlv::kState, state)); - VerifyOrExit(state == StateTlv::kAccept, SetState(OT_COMMISSIONER_STATE_DISABLED)); + VerifyOrExit(state == StateTlv::kAccept, Stop(/* aResign */ false)); mTimer.Start(Time::SecToMsec(kKeepAliveTimeout) / 2); exit: - - if (mState != OT_COMMISSIONER_STATE_ACTIVE) - { - Get().RemoveUnicastAddress(mCommissionerAloc); - RemoveCoapResources(); - } + return; } void Commissioner::HandleRelayReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo) diff --git a/src/core/meshcop/commissioner.hpp b/src/core/meshcop/commissioner.hpp index a59dc6e29..de7026d8a 100644 --- a/src/core/meshcop/commissioner.hpp +++ b/src/core/meshcop/commissioner.hpp @@ -84,11 +84,13 @@ public: /** * This method stops the Commissioner service. * + * @param[in] aResign Whether send LEAD_KA.req to resign as Commissioner + * * @retval OT_ERROR_NONE Successfully stopped the Commissioner service. * @retval OT_ERROR_INVALID_STATE Commissioner is already stopped. * */ - otError Stop(void); + otError Stop(bool aResign); /** * This method clears all Joiner entries. @@ -320,6 +322,7 @@ private: otError SendCommissionerSet(void); otError SendPetition(void); otError SendKeepAlive(void); + otError SendKeepAlive(uint16_t aSessionId); void SetState(otCommissionerState aState); void SignalJoinerEvent(otCommissionerJoinerEvent aEvent, const Mac::ExtAddress &aJoinerId);