diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp index 67720cb8f..3bfce6337 100644 --- a/src/core/coap/coap.cpp +++ b/src/core/coap/coap.cpp @@ -196,11 +196,7 @@ Error CoapBase::SendMessage(Message &aMessage, Error error; Message *storedCopy = nullptr; uint16_t copyLength = 0; -#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - uint8_t buf[kMaxBlockLength] = {0}; - uint16_t bufLen = kMaxBlockLength; - bool moreBlocks = false; -#endif + Metadata metadata; if (aTxParameters == nullptr) { @@ -211,51 +207,22 @@ Error CoapBase::SendMessage(Message &aMessage, SuccessOrExit(error = aTxParameters->ValidateFor(aMessage)); } +#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE + metadata.mBlockwiseReceiveHook = aReceiveHook; + metadata.mBlockwiseTransmitHook = aTransmitHook; + + SuccessOrExit(error = ProcessBlockwiseSend(aMessage, aTransmitHook, aContext)); +#endif + switch (aMessage.GetType()) { case kTypeAck: -#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - // Check for block-wise transfer - if ((aTransmitHook != nullptr) && (aMessage.ReadBlockOptionValues(kOptionBlock2) == kErrorNone) && - (aMessage.GetBlockWiseBlockNumber() == 0)) - { - // Set payload for first block of the transfer - VerifyOrExit((bufLen = BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize())) <= kMaxBlockLength, - error = kErrorNoBufs); - SuccessOrExit(error = aTransmitHook(aContext, buf, aMessage.GetBlockWiseBlockNumber() * bufLen, &bufLen, - &moreBlocks)); - SuccessOrExit(error = aMessage.AppendBytes(buf, bufLen)); - - SuccessOrExit(error = CacheLastBlockResponse(&aMessage)); - } -#endif - mResponseCache.Add(aMessage, aMessageInfo, aTxParameters->CalculateExchangeLifetime()); break; case kTypeReset: OT_ASSERT(aMessage.GetCode() == kCodeEmpty); break; default: -#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - // Check for block-wise transfer - if ((aTransmitHook != nullptr) && (aMessage.ReadBlockOptionValues(kOptionBlock1) == kErrorNone) && - (aMessage.GetBlockWiseBlockNumber() == 0)) - { - // Set payload for first block of the transfer - VerifyOrExit((bufLen = BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize())) <= kMaxBlockLength, - error = kErrorNoBufs); - SuccessOrExit(error = aTransmitHook(aContext, buf, aMessage.GetBlockWiseBlockNumber() * bufLen, &bufLen, - &moreBlocks)); - SuccessOrExit(error = aMessage.AppendBytes(buf, bufLen)); - - // Block-Wise messages always have to be confirmable - if (aMessage.IsNonConfirmable()) - { - aMessage.SetType(kTypeConfirmable); - } - } -#endif - aMessage.SetMessageId(mMessageId++); break; } @@ -275,8 +242,6 @@ Error CoapBase::SendMessage(Message &aMessage, if (copyLength > 0) { - Metadata metadata; - #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE // Whether or not to turn on special "Observe" handling. Option::Iterator iterator; @@ -324,10 +289,6 @@ Error CoapBase::SendMessage(Message &aMessage, metadata.mHopLimit = aMessageInfo.GetHopLimit(); metadata.mIsHostInterface = aMessageInfo.IsHostInterface(); #endif -#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - metadata.mBlockwiseReceiveHook = aReceiveHook; - metadata.mBlockwiseTransmitHook = aTransmitHook; -#endif #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE metadata.mObserve = observe; #endif @@ -1135,6 +1096,55 @@ void CoapBase::RemoveBlockWiseResource(ResourceBlockWise &aResource) aResource.SetNext(nullptr); } +Error CoapBase::SendMessage(Message &aMessage, + const Ip6::MessageInfo &aMessageInfo, + const TxParameters *aTxParameters, + ResponseHandler aHandler, + void *aContext) +{ + return SendMessage(aMessage, aMessageInfo, aTxParameters, aHandler, aContext, nullptr, nullptr); +} + +Error CoapBase::ProcessBlockwiseSend(Message &aMessage, BlockwiseTransmitHook aTransmitHook, void *aContext) +{ + Error error = kErrorNone; + uint8_t type = aMessage.GetType(); + bool moreBlocks = false; + uint16_t bufLen; + uint8_t buf[kMaxBlockLength]; + + VerifyOrExit(type != kTypeReset); + + VerifyOrExit(aTransmitHook != nullptr); + VerifyOrExit(aMessage.GetBlockWiseBlockNumber() == 0); + + SuccessOrExit(aMessage.ReadBlockOptionValues(type == kTypeAck ? kOptionBlock2 : kOptionBlock1)); + + bufLen = BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()); + VerifyOrExit(bufLen <= kMaxBlockLength, error = kErrorNoBufs); + + SuccessOrExit(error = aTransmitHook(aContext, buf, 0, &bufLen, &moreBlocks)); + SuccessOrExit(error = aMessage.AppendBytes(buf, bufLen)); + + switch (type) + { + case kTypeAck: + SuccessOrExit(error = CacheLastBlockResponse(&aMessage)); + break; + + case kTypeNonConfirmable: + // Block-Wise messages always have to be confirmable + aMessage.SetType(kTypeConfirmable); + break; + + default: + break; + } + +exit: + return error; +} + void CoapBase::FreeLastBlockResponse(void) { if (mLastResponse != nullptr) diff --git a/src/core/coap/coap.hpp b/src/core/coap/coap.hpp index 1b3fe475f..8297fc861 100644 --- a/src/core/coap/coap.hpp +++ b/src/core/coap/coap.hpp @@ -269,23 +269,6 @@ public: */ void ClearRequests(const Ip6::Address &aAddress); -#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - - /** - * Adds a block-wise resource to the CoAP server. - * - * @param[in] aResource A reference to the resource. - */ - void AddBlockWiseResource(ResourceBlockWise &aResource); - - /** - * Removes a block-wise resource from the CoAP server. - * - * @param[in] aResource A reference to the resource. - */ - void RemoveBlockWiseResource(ResourceBlockWise &aResource); -#endif - /** * Adds a resource to the CoAP server. * @@ -423,34 +406,6 @@ public: */ Message *NewResponseMessage(const Message &aRequest); -#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - /** - * Sends a CoAP message block-wise with custom transmission parameters. - * - * If a response for a request is expected, respective function and context information should be provided. - * If no response is expected, these arguments should be NULL pointers. - * If Message ID was not set in the header (equal to 0), this method will assign unique Message ID to the message. - * - * @param[in] aMessage A reference to the message to send. - * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. - * @param[in] aTxParameters A pointer to `TxParameters`. If `nullptr`, default `TxParameters` will be used. - * @param[in] aHandler A function pointer that shall be called on response reception or time-out. - * @param[in] aContext A pointer to arbitrary context information. - * @param[in] aTransmitHook A pointer to a hook function for outgoing block-wise transfer. - * @param[in] aReceiveHook A pointer to a hook function for incoming block-wise transfer. - * - * @retval kErrorNone Successfully sent CoAP message. - * @retval kErrorNoBufs Failed to allocate retransmission data. - */ - Error SendMessage(Message &aMessage, - const Ip6::MessageInfo &aMessageInfo, - const TxParameters *aTxParameters, - otCoapResponseHandler aHandler, - void *aContext, - otCoapBlockwiseTransmitHook aTransmitHook = nullptr, - otCoapBlockwiseReceiveHook aReceiveHook = nullptr); -#else // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - /** * Sends a CoAP message with custom transmission parameters. * @@ -472,7 +427,6 @@ public: const TxParameters *aTxParameters, ResponseHandler aHandler, void *aContext); -#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE /** * Sends a CoAP message with custom transmission parameters. @@ -629,23 +583,6 @@ public: */ Error SendNotFound(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo); -#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - /** - * Sends a header-only CoAP message to indicate not all blocks have been sent or - * were sent out of order. - * - * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. - * @param[in] aMessageInfo The message info corresponding to the CoAP request. - * - * @retval kErrorNone Successfully enqueued the CoAP response message. - * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response. - */ - Error SendRequestEntityIncomplete(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) - { - return SendHeaderResponse(kCodeRequestIncomplete, aRequest, aMessageInfo); - } -#endif - /** * Aborts CoAP transactions associated with given handler and context. * @@ -677,6 +614,63 @@ public: */ void GetRequestAndCachedResponsesQueueInfo(MessageQueue::Info &aQueueInfo) const; +#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE + /** + * Adds a block-wise resource to the CoAP server. + * + * @param[in] aResource A reference to the resource. + */ + void AddBlockWiseResource(ResourceBlockWise &aResource); + + /** + * Removes a block-wise resource from the CoAP server. + * + * @param[in] aResource A reference to the resource. + */ + void RemoveBlockWiseResource(ResourceBlockWise &aResource); + + /** + * Sends a CoAP message block-wise with custom transmission parameters. + * + * If a response for a request is expected, respective function and context information should be provided. + * If no response is expected, these arguments should be NULL pointers. + * If Message ID was not set in the header (equal to 0), this method will assign unique Message ID to the message. + * + * @param[in] aMessage A reference to the message to send. + * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. + * @param[in] aTxParameters A pointer to `TxParameters`. If `nullptr`, default `TxParameters will be used. + * @param[in] aHandler A function pointer that shall be called on response reception or time-out. + * @param[in] aContext A pointer to arbitrary context information. + * @param[in] aTransmitHook A pointer to a hook function for outgoing block-wise transfer. + * @param[in] aReceiveHook A pointer to a hook function for incoming block-wise transfer. + * + * @retval kErrorNone Successfully sent CoAP message. + * @retval kErrorNoBufs Failed to allocate retransmission data. + */ + Error SendMessage(Message &aMessage, + const Ip6::MessageInfo &aMessageInfo, + const TxParameters *aTxParameters, + otCoapResponseHandler aHandler, + void *aContext, + BlockwiseTransmitHook aTransmitHook, + BlockwiseReceiveHook aReceiveHook); + + /** + * Sends a header-only CoAP message to indicate not all blocks have been sent or + * were sent out of order. + * + * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. + * @param[in] aMessageInfo The message info corresponding to the CoAP request. + * + * @retval kErrorNone Successfully enqueued the CoAP response message. + * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response. + */ + Error SendRequestEntityIncomplete(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) + { + return SendHeaderResponse(kCodeRequestIncomplete, aRequest, aMessageInfo); + } +#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE + protected: /** * Defines function pointer to handle a CoAP resource. @@ -817,6 +811,7 @@ private: #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE + Error ProcessBlockwiseSend(Message &aMessage, BlockwiseTransmitHook aTransmitHook, void *aContext); void FreeLastBlockResponse(void); Error CacheLastBlockResponse(Message *aResponse); Error PrepareNextBlockRequest(Message::BlockType aType,