[coap] simplify SendMessage() for block-wise transfers (#12239)

This commit simplifies the block-wise transfer implementation within
`CoapBase::SendMessage()`.

It extract the logic for handling the initial block of an outgoing
block-wise transfer from `CoapBase::SendMessage()` into a new private
method, `ProcessBlockwiseSend()`. This improves readability and
maintainability while removing code duplication when processing
block-wise sends for different message types.

It also cleans up `coap.hpp` by consolidating several declarations
related to block-wise transfers under a single
`OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE` block.
This commit is contained in:
Abtin Keshavarzian
2025-12-26 19:59:55 -08:00
committed by GitHub
parent c6b120e258
commit f69e6ba80a
2 changed files with 115 additions and 110 deletions
+57 -47
View File
@@ -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)
+58 -63
View File
@@ -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,