From cc32575367c7f7f75ae8ecfe0d6482c51fcc9ed4 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Wed, 26 Oct 2016 18:10:17 +0200 Subject: [PATCH] Utilize CoAP client in commissioning (#878) * Use Message::Clone method in CoAP Client * Use CoAP Client in commissioner * Use CoAP client for Joiner Entrust. --- src/core/coap/coap_client.cpp | 9 +- src/core/meshcop/commissioner.cpp | 289 +++++++++++++++-------------- src/core/meshcop/commissioner.hpp | 24 ++- src/core/meshcop/joiner.cpp | 36 +++- src/core/meshcop/joiner.hpp | 3 + src/core/meshcop/joiner_router.cpp | 11 +- src/core/meshcop/joiner_router.hpp | 2 + 7 files changed, 214 insertions(+), 160 deletions(-) diff --git a/src/core/coap/coap_client.cpp b/src/core/coap/coap_client.cpp index e52ae10f8..2403dc767 100644 --- a/src/core/coap/coap_client.cpp +++ b/src/core/coap/coap_client.cpp @@ -144,9 +144,7 @@ Message *Client::CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLe uint32_t alarmFireTime; // Create a message copy of requested size. - VerifyOrExit((messageCopy = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs); - SuccessOrExit(error = messageCopy->SetLength(aCopyLength)); - aMessage.CopyTo(0, 0, aCopyLength, *messageCopy); + VerifyOrExit((messageCopy = aMessage.Clone(aCopyLength)) != NULL, error = kThreadError_NoBufs); // Append the copy with retransmission data. SuccessOrExit(error = aRequestMetadata.AppendTo(*messageCopy)); @@ -204,9 +202,8 @@ ThreadError Client::SendCopy(const Message &aMessage, const Ip6::MessageInfo &aM Message *messageCopy = NULL; // Create a message copy for lower layers. - VerifyOrExit((messageCopy = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs); - SuccessOrExit(error = messageCopy->SetLength(aMessage.GetLength() - sizeof(RequestMetadata))); - aMessage.CopyTo(0, 0, aMessage.GetLength() - sizeof(RequestMetadata), *messageCopy); + VerifyOrExit((messageCopy = aMessage.Clone(aMessage.GetLength() - sizeof(RequestMetadata))) != NULL, + error = kThreadError_NoBufs); // Send the copy. SuccessOrExit(error = mSocket.SendTo(*messageCopy, aMessageInfo)); diff --git a/src/core/meshcop/commissioner.cpp b/src/core/meshcop/commissioner.cpp index ef0132f94..7de95d2be 100644 --- a/src/core/meshcop/commissioner.cpp +++ b/src/core/meshcop/commissioner.cpp @@ -66,12 +66,11 @@ Commissioner::Commissioner(ThreadNetif &aThreadNetif): mTimer(aThreadNetif.GetIp6().mTimerScheduler, HandleTimer, this), mTransmitTask(aThreadNetif.GetIp6().mTaskletScheduler, &Commissioner::HandleUdpTransmit, this), mSendKek(false), - mSocket(aThreadNetif.GetIp6().mUdp), mRelayReceive(OPENTHREAD_URI_RELAY_RX, &Commissioner::HandleRelayReceive, this), mDatasetChanged(OPENTHREAD_URI_DATASET_CHANGED, &Commissioner::HandleDatasetChanged, this), mCoapServer(aThreadNetif.GetCoapServer()), - mNetif(aThreadNetif), - mIsSendMgmtCommRequest(false) + mCoapClient(aThreadNetif.GetCoapClient()), + mNetif(aThreadNetif) { memset(mJoiners, 0, sizeof(mJoiners)); mCoapServer.AddResource(mRelayReceive); @@ -85,8 +84,6 @@ ThreadError Commissioner::Start(void) otLogFuncEntry(); VerifyOrExit(mState == kStateDisabled, error = kThreadError_InvalidState); - SuccessOrExit(error = mSocket.Open(HandleUdpReceive, this)); - mState = kStatePetition; mTransmitAttempts = 0; @@ -107,6 +104,8 @@ ThreadError Commissioner::Stop(void) mState = kStateDisabled; mTransmitAttempts = 0; + mTimer.Stop(); + SendKeepAlive(); exit: @@ -286,7 +285,6 @@ void Commissioner::HandleTimer(void) switch (mState) { case kStateDisabled: - mSocket.Close(); break; case kStatePetition: @@ -309,21 +307,17 @@ ThreadError Commissioner::SendMgmtCommissionerGetRequest(const uint8_t *aTlvs, MeshCoP::Tlv tlv; otLogFuncEntry(); - mIsSendMgmtCommRequest = true; - - for (size_t i = 0; i < sizeof(mCoapToken); i++) - { - mCoapToken[i] = static_cast(otPlatRandomGet()); - } header.Init(kCoapTypeConfirmable, kCoapRequestPost); - header.SetMessageId(++mCoapMessageId); - header.SetToken(mCoapToken, sizeof(mCoapToken)); + header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(OPENTHREAD_URI_COMMISSIONER_GET); - header.SetPayloadMarker(); - VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs); - SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength())); + if (aLength > 0) + { + header.SetPayloadMarker(); + } + + VerifyOrExit((message = mCoapClient.NewMessage(header)) != NULL, error = kThreadError_NoBufs); if (aLength > 0) { @@ -336,7 +330,8 @@ ThreadError Commissioner::SendMgmtCommissionerGetRequest(const uint8_t *aTlvs, memset(&messageInfo, 0, sizeof(messageInfo)); mNetif.GetMle().GetLeaderAloc(messageInfo.GetPeerAddr()); messageInfo.mPeerPort = kCoapUdpPort; - SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); + SuccessOrExit(error = mCoapClient.SendMessage(*message, messageInfo, + Commissioner::HandleMgmtCommissionerGetResponse, this)); otLogInfoMeshCoP("sent MGMT_COMMISSIONER_GET.req to leader"); @@ -344,7 +339,6 @@ exit: if (error != kThreadError_None && message != NULL) { - mIsSendMgmtCommRequest = false; message->Free(); } @@ -352,6 +346,26 @@ exit: return error; } +void Commissioner::HandleMgmtCommissionerGetResponse(void *aContext, otCoapHeader *aHeader, otMessage aMessage, + ThreadError aResult) +{ + static_cast(aContext)->HandleMgmtCommissisonerGetResponse( + static_cast(aHeader), static_cast(aMessage), aResult); +} + +void Commissioner::HandleMgmtCommissisonerGetResponse(Coap::Header *aHeader, Message *aMessage, ThreadError aResult) +{ + (void) aMessage; + + otLogFuncEntry(); + + VerifyOrExit(aResult == kThreadError_None && aHeader->GetCode() == kCoapResponseChanged, ;); + otLogInfoMeshCoP("received MGMT_COMMISSIONER_GET response"); + +exit: + otLogFuncExit(); +} + ThreadError Commissioner::SendMgmtCommissionerSetRequest(const otCommissioningDataset &aDataset, const uint8_t *aTlvs, uint8_t aLength) { @@ -361,21 +375,13 @@ ThreadError Commissioner::SendMgmtCommissionerSetRequest(const otCommissioningDa Ip6::MessageInfo messageInfo; otLogFuncEntry(); - mIsSendMgmtCommRequest = true; - - for (size_t i = 0; i < sizeof(mCoapToken); i++) - { - mCoapToken[i] = static_cast(otPlatRandomGet()); - } header.Init(kCoapTypeConfirmable, kCoapRequestPost); - header.SetMessageId(++mCoapMessageId); - header.SetToken(mCoapToken, sizeof(mCoapToken)); + header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(OPENTHREAD_URI_COMMISSIONER_SET); header.SetPayloadMarker(); - VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs); - SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength())); + VerifyOrExit((message = mCoapClient.NewMessage(header)) != NULL, error = kThreadError_NoBufs); if (aDataset.mIsLocatorSet) { @@ -418,7 +424,8 @@ ThreadError Commissioner::SendMgmtCommissionerSetRequest(const otCommissioningDa memset(&messageInfo, 0, sizeof(messageInfo)); mNetif.GetMle().GetLeaderAloc(messageInfo.GetPeerAddr()); messageInfo.mPeerPort = kCoapUdpPort; - SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); + SuccessOrExit(error = mCoapClient.SendMessage(*message, messageInfo, + Commissioner::HandleMgmtCommissionerSetResponse, this)); otLogInfoMeshCoP("sent MGMT_COMMISSIONER_SET.req to leader"); @@ -426,7 +433,6 @@ exit: if (error != kThreadError_None && message != NULL) { - mIsSendMgmtCommRequest = false; message->Free(); } @@ -434,6 +440,26 @@ exit: return error; } +void Commissioner::HandleMgmtCommissionerSetResponse(void *aContext, otCoapHeader *aHeader, otMessage aMessage, + ThreadError aResult) +{ + static_cast(aContext)->HandleMgmtCommissisonerSetResponse( + static_cast(aHeader), static_cast(aMessage), aResult); +} + +void Commissioner::HandleMgmtCommissisonerSetResponse(Coap::Header *aHeader, Message *aMessage, ThreadError aResult) +{ + (void) aMessage; + + otLogFuncEntry(); + + VerifyOrExit(aResult == kThreadError_None && aHeader->GetCode() == kCoapResponseChanged, ;); + otLogInfoMeshCoP("received MGMT_COMMISSIONER_SET response"); + +exit: + otLogFuncExit(); +} + ThreadError Commissioner::SendPetition(void) { ThreadError error = kThreadError_None; @@ -444,29 +470,14 @@ ThreadError Commissioner::SendPetition(void) otLogFuncEntry(); - if (mTransmitAttempts >= kPetitionRetryCount) - { - mState = kStateDisabled; - ExitNow(); - } - - mTimer.Start(Timer::SecToMsec(kPetitionRetryDelay)); mTransmitAttempts++; - for (size_t i = 0; i < sizeof(mCoapToken); i++) - { - mCoapToken[i] = otPlatRandomGet() & 0xff; - } - header.Init(kCoapTypeConfirmable, kCoapRequestPost); - header.SetMessageId(++mCoapMessageId); - header.SetToken(mCoapToken, sizeof(mCoapToken)); + header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(OPENTHREAD_URI_LEADER_PETITION); header.SetPayloadMarker(); - VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs); - SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength())); - + VerifyOrExit((message = mCoapClient.NewMessage(header)) != NULL, error = kThreadError_NoBufs); commissionerId.Init(); commissionerId.SetCommissionerId("OpenThread Commissioner"); @@ -475,7 +486,8 @@ ThreadError Commissioner::SendPetition(void) memset(&messageInfo, 0, sizeof(messageInfo)); mNetif.GetMle().GetLeaderAloc(*static_cast(&messageInfo.mPeerAddr)); messageInfo.mPeerPort = kCoapUdpPort; - SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); + SuccessOrExit(error = mCoapClient.SendMessage(*message, messageInfo, + Commissioner::HandleLeaderPetitionResponse, this)); otLogInfoMeshCoP("sent petition"); @@ -490,6 +502,58 @@ exit: return error; } +void Commissioner::HandleLeaderPetitionResponse(void *aContext, otCoapHeader *aHeader, otMessage aMessage, + ThreadError aResult) +{ + static_cast(aContext)->HandleLeaderPetitionResponse( + static_cast(aHeader), static_cast(aMessage), aResult); + +} + +void Commissioner::HandleLeaderPetitionResponse(Coap::Header *aHeader, Message *aMessage, ThreadError aResult) +{ + StateTlv state; + CommissionerSessionIdTlv sessionId; + bool retransmit = false; + + otLogFuncEntry(); + + VerifyOrExit(mState == kStatePetition, mState = kStateDisabled); + VerifyOrExit(aResult == kThreadError_None && + aHeader->GetCode() == kCoapResponseChanged, retransmit = true); + + otLogInfoMeshCoP("received Leader Petition response"); + + SuccessOrExit(Tlv::GetTlv(*aMessage, Tlv::kState, sizeof(state), state)); + VerifyOrExit(state.IsValid(), ;); + + VerifyOrExit(state.GetState() == StateTlv::kAccept, mState = kStateDisabled); + + SuccessOrExit(Tlv::GetTlv(*aMessage, Tlv::kCommissionerSessionId, sizeof(sessionId), sessionId)); + VerifyOrExit(sessionId.IsValid(), ;); + mSessionId = sessionId.GetCommissionerSessionId(); + + mState = kStateActive; + mTransmitAttempts = 0; + mTimer.Start(Timer::SecToMsec(kKeepAliveTimeout) / 2); + +exit: + + if (retransmit) + { + if (mTransmitAttempts >= kPetitionRetryCount) + { + mState = kStateDisabled; + } + else + { + mTimer.Start(Timer::SecToMsec(kPetitionRetryDelay)); + } + } + + otLogFuncExit(); +} + ThreadError Commissioner::SendKeepAlive(void) { ThreadError error = kThreadError_None; @@ -501,28 +565,12 @@ ThreadError Commissioner::SendKeepAlive(void) otLogFuncEntry(); - if (mTransmitAttempts >= kPetitionRetryCount) - { - mState = kStateDisabled; - ExitNow(); - } - - mTimer.Start(Timer::SecToMsec(kPetitionRetryDelay)); - mTransmitAttempts++; - - for (size_t i = 0; i < sizeof(mCoapToken); i++) - { - mCoapToken[i] = otPlatRandomGet() & 0xff; - } - header.Init(kCoapTypeConfirmable, kCoapRequestPost); - header.SetMessageId(++mCoapMessageId); - header.SetToken(mCoapToken, sizeof(mCoapToken)); + header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(OPENTHREAD_URI_LEADER_KEEP_ALIVE); header.SetPayloadMarker(); - VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs); - SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength())); + VerifyOrExit((message = mCoapClient.NewMessage(header)) != NULL, error = kThreadError_NoBufs); state.Init(); state.SetState(mState == kStateActive ? StateTlv::kAccept : StateTlv::kReject); @@ -535,7 +583,8 @@ ThreadError Commissioner::SendKeepAlive(void) memset(&messageInfo, 0, sizeof(messageInfo)); mNetif.GetMle().GetLeaderAloc(*static_cast(&messageInfo.mPeerAddr)); messageInfo.mPeerPort = kCoapUdpPort; - SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); + SuccessOrExit(error = mCoapClient.SendMessage(*message, messageInfo, + Commissioner::HandleLeaderKeepAliveResponse, this)); otLogInfoMeshCoP("sent keep alive"); @@ -550,6 +599,36 @@ exit: return error; } +void Commissioner::HandleLeaderKeepAliveResponse(void *aContext, otCoapHeader *aHeader, otMessage aMessage, + ThreadError aResult) +{ + static_cast(aContext)->HandleLeaderKeepAliveResponse( + static_cast(aHeader), static_cast(aMessage), aResult); +} + +void Commissioner::HandleLeaderKeepAliveResponse(Coap::Header *aHeader, Message *aMessage, ThreadError aResult) +{ + StateTlv state; + + otLogFuncEntry(); + + VerifyOrExit(mState == kStateActive, mState = kStateDisabled); + VerifyOrExit(aResult == kThreadError_None && + aHeader->GetCode() == kCoapResponseChanged, mState = kStateDisabled); + + otLogInfoMeshCoP("received Leader Petition response"); + + SuccessOrExit(Tlv::GetTlv(*aMessage, Tlv::kState, sizeof(state), state)); + VerifyOrExit(state.IsValid(), ;); + + VerifyOrExit(state.GetState() == StateTlv::kAccept, mState = kStateDisabled); + + mTimer.Start(Timer::SecToMsec(kKeepAliveTimeout) / 2); + +exit: + otLogFuncExit(); +} + void Commissioner::HandleRelayReceive(void *aContext, Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { @@ -669,70 +748,6 @@ exit: otLogFuncExit(); } -void Commissioner::HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo) -{ - static_cast(aContext)->HandleUdpReceive(*static_cast(aMessage), - *static_cast(aMessageInfo)); -} - -void Commissioner::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) -{ - Coap::Header header; - StateTlv state; - CommissionerSessionIdTlv sessionId; - - otLogFuncEntry(); - SuccessOrExit(header.FromMessage(aMessage)); - VerifyOrExit(header.GetType() == kCoapTypeAcknowledgment && - header.GetCode() == kCoapResponseChanged && - header.GetMessageId() == mCoapMessageId && - header.GetTokenLength() == sizeof(mCoapToken) && - memcmp(mCoapToken, header.GetToken(), sizeof(mCoapToken)) == 0, ;); - aMessage.MoveOffset(header.GetLength()); - - if (mIsSendMgmtCommRequest) - { - mIsSendMgmtCommRequest = false; - - otLogInfoMeshCoP("received MGMT_COMMISSIONER_SET and MGMT_COMMISSIONER_GET response"); - - ExitNow(); - } - - SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kState, sizeof(state), state)); - VerifyOrExit(state.IsValid(), ;); - - VerifyOrExit(state.GetState() == StateTlv::kAccept, mState = kStateDisabled); - - switch (mState) - { - case kStateDisabled: - break; - - case kStatePetition: - SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kCommissionerSessionId, sizeof(sessionId), sessionId)); - VerifyOrExit(sessionId.IsValid(), ;); - mSessionId = sessionId.GetCommissionerSessionId(); - - otLogInfoMeshCoP("received petition response"); - - mState = kStateActive; - mTransmitAttempts = 0; - mTimer.Start(Timer::SecToMsec(kKeepAliveTimeout) / 2); - break; - - case kStateActive: - otLogInfoMeshCoP("received keep alive response"); - mTransmitAttempts = 0; - mTimer.Start(Timer::SecToMsec(kKeepAliveTimeout) / 2); - break; - } - -exit: - (void)aMessageInfo; - otLogFuncExit(); -} - ThreadError Commissioner::HandleDtlsSend(void *aContext, const uint8_t *aBuf, uint16_t aLength) { otLogInfoMeshCoP("Commissioner::HandleDtlsTransmit"); @@ -753,14 +768,11 @@ ThreadError Commissioner::HandleDtlsSend(const unsigned char *aBuf, uint16_t aLe JoinerRouterLocatorTlv rloc; ExtendedTlv tlv; - VerifyOrExit((mTransmitMessage = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs); - header.Init(kCoapTypeNonConfirmable, kCoapRequestPost); - header.SetMessageId(0); - header.SetToken(NULL, 0); header.AppendUriPathOptions(OPENTHREAD_URI_RELAY_TX); header.SetPayloadMarker(); - SuccessOrExit(error = mTransmitMessage->Append(header.GetBytes(), header.GetLength())); + + VerifyOrExit((mTransmitMessage = mCoapClient.NewMessage(header)) != NULL, error = kThreadError_NoBufs); udpPort.Init(); udpPort.SetUdpPort(mJoinerPort); @@ -835,6 +847,7 @@ void Commissioner::HandleUdpTransmit(void) tlv.SetType(Tlv::kJoinerDtlsEncapsulation); tlv.SetLength(mTransmitMessage->GetLength() - mTransmitMessage->GetOffset() - sizeof(tlv)); mTransmitMessage->Write(mTransmitMessage->GetOffset(), sizeof(tlv), &tlv); + mTransmitMessage->SetOffset(0); memset(&messageInfo, 0, sizeof(messageInfo)); messageInfo.GetPeerAddr() = *mNetif.GetMle().GetMeshLocal16(); @@ -842,7 +855,7 @@ void Commissioner::HandleUdpTransmit(void) messageInfo.mPeerPort = kCoapUdpPort; messageInfo.mInterfaceId = mNetif.GetInterfaceId(); - SuccessOrExit(error = mSocket.SendTo(*mTransmitMessage, messageInfo)); + SuccessOrExit(error = mCoapClient.SendMessage(*mTransmitMessage, messageInfo)); exit: diff --git a/src/core/meshcop/commissioner.hpp b/src/core/meshcop/commissioner.hpp index 17ba6bcf7..41c65d89f 100644 --- a/src/core/meshcop/commissioner.hpp +++ b/src/core/meshcop/commissioner.hpp @@ -36,6 +36,7 @@ #include +#include #include #include #include @@ -188,6 +189,19 @@ private: static void HandleTimer(void *aContext); void HandleTimer(void); + static void HandleMgmtCommissionerSetResponse(void *aContext, otCoapHeader *aHeader, + otMessage aMessage, ThreadError aResult); + void HandleMgmtCommissisonerSetResponse(Coap::Header *aHeader, Message *aMessage, ThreadError aResult); + static void HandleMgmtCommissionerGetResponse(void *aContext, otCoapHeader *aHeader, + otMessage aMessage, ThreadError aResult); + void HandleMgmtCommissisonerGetResponse(Coap::Header *aHeader, Message *aMessage, ThreadError aResult); + static void HandleLeaderPetitionResponse(void *aContext, otCoapHeader *aHeader, + otMessage aMessage, ThreadError aResult); + void HandleLeaderPetitionResponse(Coap::Header *aHeader, Message *aMessage, ThreadError aResult); + static void HandleLeaderKeepAliveResponse(void *aContext, otCoapHeader *aHeader, + otMessage aMessage, ThreadError aResult); + void HandleLeaderKeepAliveResponse(Coap::Header *aHeader, Message *aMessage, ThreadError aResult); + static void HandleRelayReceive(void *aContext, Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo); void HandleRelayReceive(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo); @@ -196,9 +210,6 @@ private: Message &aMessage, const Ip6::MessageInfo &aMessageInfo); void HandleDatasetChanged(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo); - static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo); - void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); - static void HandleDtlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength); void HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength); @@ -242,15 +253,12 @@ private: uint8_t mTransmitAttempts; bool mSendKek; - Ip6::UdpSocket mSocket; - uint8_t mCoapToken[2]; - uint16_t mCoapMessageId; - Coap::Resource mRelayReceive; Coap::Resource mDatasetChanged; Coap::Server &mCoapServer; + Coap::Client &mCoapClient; + ThreadNetif &mNetif; - bool mIsSendMgmtCommRequest; }; } // namespace MeshCoP diff --git a/src/core/meshcop/joiner.cpp b/src/core/meshcop/joiner.cpp index 1bd7d93b6..45b5e9f63 100644 --- a/src/core/meshcop/joiner.cpp +++ b/src/core/meshcop/joiner.cpp @@ -64,9 +64,10 @@ Joiner::Joiner(ThreadNetif &aNetif): mTransmitTask(aNetif.GetIp6().mTaskletScheduler, &Joiner::HandleUdpTransmit, this), mTimer(aNetif.GetIp6().mTimerScheduler, &Joiner::HandleTimer, this), mJoinerEntrust(OPENTHREAD_URI_JOINER_ENTRUST, &Joiner::HandleJoinerEntrust, this), + mCoapServer(aNetif.GetCoapServer()), mNetif(aNetif) { - mNetif.GetCoapServer().AddResource(mJoinerEntrust); + mCoapServer.AddResource(mJoinerEntrust); } ThreadError Joiner::Start(const char *aPSKd, const char *aProvisioningUrl) @@ -387,14 +388,45 @@ void Joiner::HandleJoinerEntrust(Coap::Header &aHeader, Message &aMessage, const otLogInfoMeshCoP("join success!"); + // Send dummy response. + SendJoinerEntrustResponse(aHeader, aMessageInfo); + // Delay extended address configuration to allow DTLS wrap up. mTimer.Start(kConfigExtAddressDelay); exit: - (void)aMessageInfo; otLogFuncExit(); } +void Joiner::SendJoinerEntrustResponse(const Coap::Header &aRequestHeader, + const Ip6::MessageInfo &aRequestInfo) +{ + + ThreadError error = kThreadError_None; + Message *message; + Coap::Header responseHeader; + Ip6::MessageInfo responseInfo; + + VerifyOrExit((message = mCoapServer.NewMessage(0)) != NULL, error = kThreadError_NoBufs); + + responseHeader.SetDefaultResponseHeader(aRequestHeader); + + SuccessOrExit(error = message->Append(responseHeader.GetBytes(), responseHeader.GetLength())); + + memcpy(&responseInfo, &aRequestInfo, sizeof(responseInfo)); + memset(&responseInfo.mSockAddr, 0, sizeof(responseInfo.mSockAddr)); + SuccessOrExit(error = mCoapServer.SendMessage(*message, responseInfo)); + + otLogInfoArp("Sent address notification acknowledgment"); + +exit: + + if (error != kThreadError_None && message != NULL) + { + message->Free(); + } +} + void Joiner::HandleTimer(void *aContext) { static_cast(aContext)->HandleTimer(); diff --git a/src/core/meshcop/joiner.hpp b/src/core/meshcop/joiner.hpp index 8012c7118..87f18834b 100644 --- a/src/core/meshcop/joiner.hpp +++ b/src/core/meshcop/joiner.hpp @@ -104,6 +104,8 @@ private: Message &aMessage, const Ip6::MessageInfo &aMessageInfo); void HandleJoinerEntrust(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + void SendJoinerEntrustResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aRequestInfo); + static void HandleTimer(void *aContext); void HandleTimer(void); @@ -121,6 +123,7 @@ private: Tasklet mTransmitTask; Timer mTimer; Coap::Resource mJoinerEntrust; + Coap::Server &mCoapServer; ThreadNetif &mNetif; }; diff --git a/src/core/meshcop/joiner_router.cpp b/src/core/meshcop/joiner_router.cpp index 378173734..74c3c6819 100644 --- a/src/core/meshcop/joiner_router.cpp +++ b/src/core/meshcop/joiner_router.cpp @@ -59,6 +59,7 @@ namespace MeshCoP { JoinerRouter::JoinerRouter(ThreadNetif &aNetif): mSocket(aNetif.GetIp6().mUdp), mRelayTransmit(OPENTHREAD_URI_RELAY_TX, &JoinerRouter::HandleRelayTransmit, this), + mCoapClient(aNetif.GetCoapClient()), mNetif(aNetif), mIsJoinerPortConfigured(false) { @@ -347,15 +348,13 @@ ThreadError JoinerRouter::SendJoinerEntrust(const Ip6::MessageInfo &aMessageInfo Tlv *tlv; otLogFuncEntry(); - VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs); - message->SetSubType(Message::kSubTypeJoinerEntrust); header.Init(kCoapTypeConfirmable, kCoapRequestPost); - header.SetMessageId(0); - header.SetToken(NULL, 0); header.AppendUriPathOptions(OPENTHREAD_URI_JOINER_ENTRUST); header.SetPayloadMarker(); - SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength())); + + VerifyOrExit((message = mCoapClient.NewMessage(header)) != NULL, error = kThreadError_NoBufs); + message->SetSubType(Message::kSubTypeJoinerEntrust); masterKey.Init(); masterKey.SetNetworkMasterKey(mNetif.GetKeyManager().GetMasterKey(NULL)); @@ -419,7 +418,7 @@ ThreadError JoinerRouter::SendJoinerEntrust(const Ip6::MessageInfo &aMessageInfo messageInfo = aMessageInfo; messageInfo.mPeerPort = kCoapUdpPort; - SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); + SuccessOrExit(error = mCoapClient.SendMessage(*message, messageInfo)); otLogInfoMeshCoP("Sent joiner entrust length = %d", message->GetLength()); otLogCertMeshCoP("[THCI] direction=send | msg_type=JOIN_ENT.ntf"); diff --git a/src/core/meshcop/joiner_router.hpp b/src/core/meshcop/joiner_router.hpp index b852ac1f0..1af638f82 100644 --- a/src/core/meshcop/joiner_router.hpp +++ b/src/core/meshcop/joiner_router.hpp @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -96,6 +97,7 @@ private: Ip6::UdpSocket mSocket; Coap::Resource mRelayTransmit; + Coap::Client &mCoapClient; ThreadNetif &mNetif; uint16_t mJoinerUdpPort;