diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp index f25cf8a30..adedfbbd0 100644 --- a/src/core/coap/coap.cpp +++ b/src/core/coap/coap.cpp @@ -261,7 +261,6 @@ Error CoapBase::SendMessage(Message &aMessage, Message *storedCopy = nullptr; uint16_t copyLength = 0; Msg txMsg(aMessage, aMessageInfo); - Metadata metadata; SuccessOrExit(error = txMsg.ParseHeaderAndOptions(Msg::kRemovePayloadMarkerIfNoPayload)); @@ -304,33 +303,14 @@ Error CoapBase::SendMessage(Message &aMessage, if (copyLength > 0) { + Metadata metadata; + + metadata.Init(txMsg, *aTxParameters, aCallbacks); + #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE - { - bool shouldObserve = false; - - SuccessOrExit(error = ProcessObserveSend(txMsg, shouldObserve)); - metadata.mObserve = shouldObserve; - metadata.mIsRequest = txMsg.IsRequest(); - } + SuccessOrExit(error = ProcessObserveSend(txMsg, metadata)); #endif - metadata.mSourceAddress = txMsg.mMessageInfo.GetSockAddr(); - metadata.mDestinationPort = txMsg.mMessageInfo.GetPeerPort(); - metadata.mDestinationAddress = txMsg.mMessageInfo.GetPeerAddr(); - metadata.mMulticastLoop = txMsg.mMessageInfo.GetMulticastLoop(); - metadata.mCallbacks = aCallbacks; - metadata.mRetransmissionsRemaining = aTxParameters->mMaxRetransmit; - metadata.mRetransmissionTimeout = aTxParameters->CalculateInitialRetransmissionTimeout(); - metadata.mAcknowledged = false; - metadata.mConfirmable = txMsg.IsConfirmable(); -#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE - metadata.mHopLimit = txMsg.mMessageInfo.GetHopLimit(); - metadata.mIsHostInterface = txMsg.mMessageInfo.IsHostInterface(); -#endif - metadata.mNextTimerShot = - TimerMilli::GetNow() + - (metadata.mConfirmable ? metadata.mRetransmissionTimeout : aTxParameters->CalculateMaxTransmitWait()); - storedCopy = CopyAndEnqueueMessage(txMsg.mMessage, copyLength, metadata); VerifyOrExit(storedCopy != nullptr, error = kErrorNoBufs); } @@ -513,7 +493,7 @@ void CoapBase::ScheduleRetransmissionTimer(void) metadata.ReadFrom(message); #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE - if (IsObserveSubscription(metadata)) + if (metadata.IsObserveSubscription()) { // This is an RFC7641 subscription which is already acknowledged. // We do not time it out, so skip it when determining the next @@ -522,7 +502,7 @@ void CoapBase::ScheduleRetransmissionTimer(void) } #endif - nextTime.UpdateIfEarlier(metadata.mNextTimerShot); + nextTime.UpdateIfEarlier(metadata.mTimerFireTime); } mRetransmissionTimer.FireAt(nextTime); @@ -543,40 +523,27 @@ void CoapBase::HandleRetransmissionTimer(void) { metadata.ReadFrom(message); - if (now >= metadata.mNextTimerShot) + if (now >= metadata.mTimerFireTime) { #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE - if (IsObserveSubscription(metadata)) + if (metadata.IsObserveSubscription()) { continue; } #endif - if (!metadata.mConfirmable || (metadata.mRetransmissionsRemaining == 0)) + if (!metadata.ShouldRetransmit()) { - // No expected response or acknowledgment. FinalizeCoapTransaction(message, metadata, nullptr, kErrorResponseTimeout); continue; } - // Increment retransmission counter and timer. - metadata.mRetransmissionsRemaining--; - metadata.mRetransmissionTimeout *= 2; - metadata.mNextTimerShot = now + metadata.mRetransmissionTimeout; + metadata.UpdateRetxCounterAndTimeout(now); metadata.UpdateIn(message); - // Retransmit if (!metadata.mAcknowledged) { - messageInfo.SetPeerAddr(metadata.mDestinationAddress); - messageInfo.SetPeerPort(metadata.mDestinationPort); - messageInfo.SetSockAddr(metadata.mSourceAddress); -#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE - messageInfo.SetHopLimit(metadata.mHopLimit); - messageInfo.SetIsHostInterface(metadata.mIsHostInterface); -#endif - messageInfo.SetMulticastLoop(metadata.mMulticastLoop); - + metadata.CopyInfoTo(messageInfo); SendCopy(message, messageInfo); } } @@ -671,9 +638,8 @@ Message *CoapBase::FindRelatedRequest(const Msg &aMsg, Metadata &aMetadata) { aMetadata.ReadFrom(message); - if (((aMetadata.mDestinationAddress == aMsg.mMessageInfo.GetPeerAddr() && - aMetadata.mDestinationPort == aMsg.mMessageInfo.GetPeerPort()) || - aMetadata.mDestinationAddress.IsMulticast() || aMetadata.mDestinationAddress.GetIid().IsAnycastLocator())) + if (aMetadata.HasSamePeerAddrAndPort(aMsg.mMessageInfo) || aMetadata.mDestinationAddress.IsMulticast() || + aMetadata.mDestinationAddress.GetIid().IsAnycastLocator()) { switch (aMsg.GetType()) { @@ -1595,20 +1561,21 @@ exit: #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE -Error CoapBase::ProcessObserveSend(Msg &aTxMsg, bool &aShouldObserve) +Error CoapBase::ProcessObserveSend(Msg &aTxMsg, Metadata &aMetadata) { Error error; Option::Iterator iterator; - aShouldObserve = false; + aMetadata.mObserve = false; + aMetadata.mIsRequest = aTxMsg.IsRequest(); SuccessOrExit(error = iterator.Init(aTxMsg.mMessage, kOptionObserve)); - aShouldObserve = !iterator.IsDone(); + aMetadata.mObserve = !iterator.IsDone(); // Special case, if we're sending a GET with Observe=1, that is a // cancellation. - if (aShouldObserve && aTxMsg.IsGetRequest()) + if (aMetadata.mObserve && aTxMsg.IsGetRequest()) { uint64_t value = 0; @@ -1617,17 +1584,17 @@ Error CoapBase::ProcessObserveSend(Msg &aTxMsg, bool &aShouldObserve) if (value == 1) { Message *request; - Metadata metadata; + Metadata reqMetadata; - aShouldObserve = false; + aMetadata.mObserve = false; // If we can find the previous matching request, cancel that too. - request = FindRelatedRequest(aTxMsg, metadata); + request = FindRelatedRequest(aTxMsg, reqMetadata); if (request != nullptr) { - FinalizeCoapTransaction(*request, metadata, nullptr, kErrorNone); + FinalizeCoapTransaction(*request, reqMetadata, nullptr, kErrorNone); } } } @@ -1636,14 +1603,6 @@ exit: return error; } -bool CoapBase::IsObserveSubscription(const Metadata &aMetadata) -{ - // Indicate whether the message is an RFC7641 subscription which - // is already acknowledged. - - return aMetadata.mIsRequest && aMetadata.mObserve && aMetadata.mAcknowledged; -} - #endif // OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE //--------------------------------------------------------------------------------------------------------------------- @@ -1691,6 +1650,65 @@ void CoapBase::SendCallbacks::InvokeResponseHandler(Msg *aMsg, Error aResult) co } } +//--------------------------------------------------------------------------------------------------------------------- +// CoapBase::Metadata + +void CoapBase::Metadata::Init(const Msg &aTxMsg, const TxParameters &aTxParams, const SendCallbacks &aCallbacks) +{ + mSourceAddress = aTxMsg.mMessageInfo.GetSockAddr(); + mDestinationPort = aTxMsg.mMessageInfo.GetPeerPort(); + mDestinationAddress = aTxMsg.mMessageInfo.GetPeerAddr(); + mMulticastLoop = aTxMsg.mMessageInfo.GetMulticastLoop(); + mCallbacks = aCallbacks; + mRetxRemaining = aTxParams.mMaxRetransmit; + mRetxTimeout = aTxParams.CalculateInitialRetransmissionTimeout(); + mAcknowledged = false; + mConfirmable = aTxMsg.IsConfirmable(); +#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + mHopLimit = aTxMsg.mMessageInfo.GetHopLimit(); + mIsHostInterface = aTxMsg.mMessageInfo.IsHostInterface(); +#endif + + mTimerFireTime = TimerMilli::GetNow() + (mConfirmable ? mRetxTimeout : aTxParams.CalculateMaxTransmitWait()); +} + +bool CoapBase::Metadata::HasSamePeerAddrAndPort(const Ip6::MessageInfo &aMessageInfo) const +{ + return (mDestinationPort == aMessageInfo.GetPeerPort()) && (mDestinationAddress == aMessageInfo.GetPeerAddr()); +} + +bool CoapBase::Metadata::ShouldRetransmit(void) const { return mConfirmable && (mRetxRemaining > 0); } + +void CoapBase::Metadata::UpdateRetxCounterAndTimeout(TimeMilli aNow) +{ + mRetxRemaining--; + mRetxTimeout *= 2; + + mTimerFireTime = aNow + mRetxTimeout; +} + +void CoapBase::Metadata::CopyInfoTo(Ip6::MessageInfo &aMessageInfo) const +{ + aMessageInfo.SetPeerAddr(mDestinationAddress); + aMessageInfo.SetPeerPort(mDestinationPort); + aMessageInfo.SetSockAddr(mSourceAddress); + aMessageInfo.SetMulticastLoop(mMulticastLoop); +#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + aMessageInfo.SetHopLimit(mHopLimit); + aMessageInfo.SetIsHostInterface(mIsHostInterface); +#endif +} + +#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE +bool CoapBase::Metadata::IsObserveSubscription(void) const +{ + // Indicate whether the message is an RFC7641 subscription which + // is already acknowledged. + + return mIsRequest && mObserve && mAcknowledged; +} +#endif + //--------------------------------------------------------------------------------------------------------------------- // CoapBase::ResponseCache diff --git a/src/core/coap/coap.hpp b/src/core/coap/coap.hpp index ac76fa1a6..de3f72ece 100644 --- a/src/core/coap/coap.hpp +++ b/src/core/coap/coap.hpp @@ -784,24 +784,33 @@ private: struct Metadata : public Message::FooterData { - Ip6::Address mSourceAddress; // IPv6 address of the message source. - Ip6::Address mDestinationAddress; // IPv6 address of the message destination. - uint16_t mDestinationPort; // UDP port of the message destination. - SendCallbacks mCallbacks; // All callbacks, response handler and clockwise rx/tx hooks. - TimeMilli mNextTimerShot; // Time when the timer should shoot for this message. - uint32_t mRetransmissionTimeout; // Delay that is applied to next retransmission. - uint8_t mRetransmissionsRemaining; // Number of retransmissions remaining. -#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE - uint8_t mHopLimit; // The hop limit. + void Init(const Msg &aTxMsg, const TxParameters &aTxParams, const SendCallbacks &aCallbacks); + bool HasSamePeerAddrAndPort(const Ip6::MessageInfo &aMessageInfo) const; + bool ShouldRetransmit(void) const; + void UpdateRetxCounterAndTimeout(TimeMilli aNow); + void CopyInfoTo(Ip6::MessageInfo &aMessageInfo) const; +#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE + bool IsObserveSubscription(void) const; #endif - bool mAcknowledged : 1; // Information that request was acknowledged. - bool mConfirmable : 1; // Information that message is confirmable. - bool mMulticastLoop : 1; // Information that multicast loop is enabled. + + Ip6::Address mSourceAddress; + Ip6::Address mDestinationAddress; + uint16_t mDestinationPort; + SendCallbacks mCallbacks; + TimeMilli mTimerFireTime; + uint32_t mRetxTimeout; + uint8_t mRetxRemaining; #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE - bool mIsHostInterface : 1; // TRUE if packets sent/received via host interface, FALSE otherwise. + uint8_t mHopLimit; +#endif + bool mAcknowledged : 1; + bool mConfirmable : 1; + bool mMulticastLoop : 1; +#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE + bool mIsHostInterface : 1; #endif #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE - bool mObserve : 1; // Information that this request involves Observations. + bool mObserve : 1; bool mIsRequest : 1; #endif }; @@ -882,9 +891,7 @@ private: #endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE - Error ProcessObserveSend(Msg &aTxMsg, bool &aShouldObserve); - - static bool IsObserveSubscription(const Metadata &aMetadata); + Error ProcessObserveSend(Msg &aTxMsg, Metadata &aMetadata); #endif MessageQueue mPendingRequests;