[coap] reorder block-wise related methods for improved readability (#12228)

This commit reorders block-wise related methods in both header and
source files to group them within the same `#if` block. This is a
purely stylistic change to improve code organization and readability
and do not alter any functionality.
This commit is contained in:
Abtin Keshavarzian
2025-12-22 13:33:11 -08:00
committed by GitHub
parent 7d23c9009a
commit 1d25510d57
2 changed files with 435 additions and 441 deletions
+415 -412
View File
@@ -80,16 +80,6 @@ void CoapBase::ClearRequests(const Ip6::Address *aAddress)
}
}
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
void CoapBase::AddBlockWiseResource(ResourceBlockWise &aResource) { IgnoreError(mBlockWiseResources.Add(aResource)); }
void CoapBase::RemoveBlockWiseResource(ResourceBlockWise &aResource)
{
IgnoreError(mBlockWiseResources.Remove(aResource));
aResource.SetNext(nullptr);
}
#endif
void CoapBase::AddResource(Resource &aResource) { IgnoreError(mResources.Add(aResource)); }
void CoapBase::RemoveResource(Resource &aResource)
@@ -634,408 +624,6 @@ void CoapBase::DequeueMessage(Message &aMessage)
ScheduleRetransmissionTimer();
}
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
void CoapBase::FreeLastBlockResponse(void)
{
if (mLastResponse != nullptr)
{
mLastResponse->Free();
mLastResponse = nullptr;
}
}
Error CoapBase::CacheLastBlockResponse(Message *aResponse)
{
Error error = kErrorNone;
// Save last response for block-wise transfer
FreeLastBlockResponse();
if ((mLastResponse = aResponse->Clone()) == nullptr)
{
error = kErrorNoBufs;
}
return error;
}
Error CoapBase::PrepareNextBlockRequest(Message::BlockType aType,
bool aMoreBlocks,
Message &aRequestOld,
Message &aRequest,
Message &aMessage)
{
Error error = kErrorNone;
bool isOptionSet = false;
uint16_t blockOption = 0;
Option::Iterator iterator;
Metadata metadata;
blockOption = (aType == Message::kBlockType1) ? kOptionBlock1 : kOptionBlock2;
aRequest.Init(kTypeConfirmable, static_cast<ot::Coap::Code>(aRequestOld.GetCode()));
// Iterate after metadata copied and removed.
metadata.ReadFrom(aRequestOld);
metadata.RemoveFrom(aRequestOld);
// Per RFC 7959, all requests in a block-wise transfer MUST use the same token.
IgnoreError(aRequest.SetTokenFromMessage(aRequestOld));
SuccessOrExit(error = iterator.Init(aRequestOld));
// Copy options from last response to next message
for (; !iterator.IsDone() && iterator.GetOption()->GetLength() != 0; error = iterator.Advance())
{
uint16_t optionNumber = iterator.GetOption()->GetNumber();
SuccessOrExit(error);
// Check if option to copy next is higher than or equal to Block1 option
if (optionNumber >= blockOption && !isOptionSet)
{
// Write Block1 option to next message
SuccessOrExit(error = aRequest.AppendBlockOption(aType, aMessage.GetBlockWiseBlockNumber() + 1, aMoreBlocks,
aMessage.GetBlockWiseBlockSize()));
aRequest.SetBlockWiseBlockNumber(aMessage.GetBlockWiseBlockNumber() + 1);
aRequest.SetBlockWiseBlockSize(aMessage.GetBlockWiseBlockSize());
aRequest.SetMoreBlocksFlag(aMoreBlocks);
isOptionSet = true;
// If option to copy next is Block1 or Block2 option, option is not copied
if (optionNumber == kOptionBlock1 || optionNumber == kOptionBlock2)
{
continue;
}
}
// Copy option
SuccessOrExit(error = aRequest.AppendOptionFromMessage(optionNumber, iterator.GetOption()->GetLength(),
iterator.GetMessage(),
iterator.GetOptionValueMessageOffset()));
}
if (!isOptionSet)
{
// Write Block1 option to next message
SuccessOrExit(error = aRequest.AppendBlockOption(aType, aMessage.GetBlockWiseBlockNumber() + 1, aMoreBlocks,
aMessage.GetBlockWiseBlockSize()));
aRequest.SetBlockWiseBlockNumber(aMessage.GetBlockWiseBlockNumber() + 1);
aRequest.SetBlockWiseBlockSize(aMessage.GetBlockWiseBlockSize());
aRequest.SetMoreBlocksFlag(aMoreBlocks);
}
error = metadata.AppendTo(aRequestOld);
exit:
return error;
}
Error CoapBase::SendNextBlock1Request(Message &aRequest,
Message &aMessage,
const Ip6::MessageInfo &aMessageInfo,
const Metadata &aCoapMetadata)
{
Error error = kErrorNone;
Message *request = nullptr;
bool moreBlocks = false;
uint8_t buf[kMaxBlockLength] = {0};
uint16_t bufLen = kMaxBlockLength;
SuccessOrExit(error = aRequest.ReadBlockOptionValues(kOptionBlock1));
SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock1));
// Conclude block-wise transfer if last block has been received
if (!aRequest.IsMoreBlocksFlagSet())
{
FinalizeCoapTransaction(aRequest, aCoapMetadata, &aMessage, &aMessageInfo, kErrorNone);
ExitNow();
}
// Get next block
VerifyOrExit((bufLen = otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize())) <= kMaxBlockLength,
error = kErrorNoBufs);
SuccessOrExit(
error = aCoapMetadata.mBlockwiseTransmitHook(aCoapMetadata.mResponseContext, buf,
otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) *
(aMessage.GetBlockWiseBlockNumber() + 1),
&bufLen, &moreBlocks));
// Check if block length is valid
VerifyOrExit(bufLen <= otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()), error = kErrorInvalidArgs);
// Init request for next block
VerifyOrExit((request = NewMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = PrepareNextBlockRequest(Message::kBlockType1, moreBlocks, aRequest, *request, aMessage));
SuccessOrExit(error = request->SetPayloadMarker());
SuccessOrExit(error = request->AppendBytes(buf, bufLen));
DequeueMessage(aRequest);
LogInfo("Send Block1 Nr. %d, Size: %d bytes, More Blocks Flag: %d", request->GetBlockWiseBlockNumber(),
otCoapBlockSizeFromExponent(request->GetBlockWiseBlockSize()), request->IsMoreBlocksFlagSet());
SuccessOrExit(error = SendMessage(*request, aMessageInfo, TxParameters::GetDefault(),
aCoapMetadata.mResponseHandler, aCoapMetadata.mResponseContext,
aCoapMetadata.mBlockwiseTransmitHook, aCoapMetadata.mBlockwiseReceiveHook));
exit:
FreeMessageOnError(request, error);
return error;
}
Error CoapBase::SendNextBlock2Request(Message &aRequest,
Message &aMessage,
const Ip6::MessageInfo &aMessageInfo,
const Metadata &aCoapMetadata,
uint32_t aTotalLength,
bool aBeginBlock1Transfer)
{
Error error = kErrorNone;
Message *request = nullptr;
uint8_t buf[kMaxBlockLength] = {0};
uint16_t bufLen = kMaxBlockLength;
SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock2));
// Check payload and block length
VerifyOrExit((aMessage.GetLength() - aMessage.GetOffset()) <=
otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) &&
(aMessage.GetLength() - aMessage.GetOffset()) <= kMaxBlockLength,
error = kErrorNoBufs);
// Read and then forward payload to receive hook function
bufLen = aMessage.ReadBytes(aMessage.GetOffset(), buf, aMessage.GetLength() - aMessage.GetOffset());
SuccessOrExit(
error = aCoapMetadata.mBlockwiseReceiveHook(aCoapMetadata.mResponseContext, buf,
otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) *
aMessage.GetBlockWiseBlockNumber(),
bufLen, aMessage.IsMoreBlocksFlagSet(), aTotalLength));
// CoAP Block-Wise Transfer continues
LogInfo("Received Block2 Nr. %d , Size: %d bytes, More Blocks Flag: %d", aMessage.GetBlockWiseBlockNumber(),
otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()), aMessage.IsMoreBlocksFlagSet());
// Conclude block-wise transfer if last block has been received
if (!aMessage.IsMoreBlocksFlagSet())
{
FinalizeCoapTransaction(aRequest, aCoapMetadata, &aMessage, &aMessageInfo, kErrorNone);
ExitNow();
}
// Init request for next block
VerifyOrExit((request = NewMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = PrepareNextBlockRequest(Message::kBlockType2, aMessage.IsMoreBlocksFlagSet(), aRequest,
*request, aMessage));
if (!aBeginBlock1Transfer)
{
DequeueMessage(aRequest);
}
LogInfo("Request Block2 Nr. %d, Size: %d bytes", request->GetBlockWiseBlockNumber(),
otCoapBlockSizeFromExponent(request->GetBlockWiseBlockSize()));
SuccessOrExit(error =
SendMessage(*request, aMessageInfo, TxParameters::GetDefault(), aCoapMetadata.mResponseHandler,
aCoapMetadata.mResponseContext, nullptr, aCoapMetadata.mBlockwiseReceiveHook));
exit:
FreeMessageOnError(request, error);
return error;
}
Error CoapBase::ProcessBlock1Request(Message &aMessage,
const Ip6::MessageInfo &aMessageInfo,
const ResourceBlockWise &aResource,
uint32_t aTotalLength)
{
Error error = kErrorNone;
Message *response = nullptr;
uint8_t buf[kMaxBlockLength] = {0};
uint16_t bufLen = kMaxBlockLength;
SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock1));
// Read and then forward payload to receive hook function
VerifyOrExit((aMessage.GetLength() - aMessage.GetOffset()) <= kMaxBlockLength, error = kErrorNoBufs);
bufLen = aMessage.ReadBytes(aMessage.GetOffset(), buf, aMessage.GetLength() - aMessage.GetOffset());
SuccessOrExit(error = aResource.HandleBlockReceive(buf,
otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) *
aMessage.GetBlockWiseBlockNumber(),
bufLen, aMessage.IsMoreBlocksFlagSet(), aTotalLength));
if (aMessage.IsMoreBlocksFlagSet())
{
// Set up next response
VerifyOrExit((response = NewMessage()) != nullptr, error = kErrorFailed);
response->Init(kTypeAck, kCodeContinue);
response->SetMessageId(aMessage.GetMessageId());
IgnoreReturnValue(response->SetToken(AsConst(aMessage).GetToken(), aMessage.GetTokenLength()));
response->SetBlockWiseBlockNumber(aMessage.GetBlockWiseBlockNumber());
response->SetMoreBlocksFlag(aMessage.IsMoreBlocksFlagSet());
response->SetBlockWiseBlockSize(aMessage.GetBlockWiseBlockSize());
SuccessOrExit(error = response->AppendBlockOption(Message::kBlockType1, response->GetBlockWiseBlockNumber(),
response->IsMoreBlocksFlagSet(),
response->GetBlockWiseBlockSize()));
SuccessOrExit(error = CacheLastBlockResponse(response));
LogInfo("Acknowledge Block1 Nr. %d, Size: %d bytes", response->GetBlockWiseBlockNumber(),
otCoapBlockSizeFromExponent(response->GetBlockWiseBlockSize()));
SuccessOrExit(error = SendMessage(*response, aMessageInfo));
error = kErrorBusy;
}
else
{
// Conclude block-wise transfer if last block has been received
FreeLastBlockResponse();
error = kErrorNone;
}
exit:
if (error != kErrorNone && error != kErrorBusy && response != nullptr)
{
response->Free();
}
return error;
}
Error CoapBase::ProcessBlock2Request(Message &aMessage,
const Ip6::MessageInfo &aMessageInfo,
const ResourceBlockWise &aResource)
{
Error error = kErrorNone;
Message *response = nullptr;
uint8_t buf[kMaxBlockLength] = {0};
uint16_t bufLen = kMaxBlockLength;
bool moreBlocks = false;
uint64_t optionBuf = 0;
Option::Iterator iterator;
SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock2));
LogInfo("Request for Block2 Nr. %d, Size: %d bytes received", aMessage.GetBlockWiseBlockNumber(),
otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()));
if (aMessage.GetBlockWiseBlockNumber() == 0)
{
aResource.HandleRequest(aMessage, aMessageInfo);
ExitNow();
}
// Set up next response
VerifyOrExit((response = NewMessage()) != nullptr, error = kErrorNoBufs);
response->Init(kTypeAck, kCodeContent);
response->SetMessageId(aMessage.GetMessageId());
SuccessOrExit(error = response->SetTokenFromMessage(aMessage));
VerifyOrExit((bufLen = otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize())) <= kMaxBlockLength,
error = kErrorNoBufs);
SuccessOrExit(error = aResource.HandleBlockTransmit(buf,
otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) *
aMessage.GetBlockWiseBlockNumber(),
&bufLen, &moreBlocks));
response->SetMoreBlocksFlag(moreBlocks);
if (moreBlocks)
{
switch (bufLen)
{
case 1024:
response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_1024);
break;
case 512:
response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_512);
break;
case 256:
response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_256);
break;
case 128:
response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_128);
break;
case 64:
response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_64);
break;
case 32:
response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_32);
break;
case 16:
response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_16);
break;
default:
error = kErrorInvalidArgs;
ExitNow();
break;
}
}
else
{
// Verify that buffer length is not larger than requested block size
VerifyOrExit(bufLen <= otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()),
error = kErrorInvalidArgs);
response->SetBlockWiseBlockSize(aMessage.GetBlockWiseBlockSize());
}
response->SetBlockWiseBlockNumber(
(otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) * aMessage.GetBlockWiseBlockNumber()) /
(otCoapBlockSizeFromExponent(response->GetBlockWiseBlockSize())));
// Copy options from last response
SuccessOrExit(error = iterator.Init(*mLastResponse));
while (!iterator.IsDone())
{
uint16_t optionNumber = iterator.GetOption()->GetNumber();
if (optionNumber == kOptionBlock2)
{
SuccessOrExit(error = response->AppendBlockOption(Message::kBlockType2, response->GetBlockWiseBlockNumber(),
response->IsMoreBlocksFlagSet(),
response->GetBlockWiseBlockSize()));
}
else if (optionNumber == kOptionBlock1)
{
SuccessOrExit(error = iterator.ReadOptionValue(&optionBuf));
SuccessOrExit(error = response->AppendOption(optionNumber, iterator.GetOption()->GetLength(), &optionBuf));
}
SuccessOrExit(error = iterator.Advance());
}
SuccessOrExit(error = response->SetPayloadMarker());
SuccessOrExit(error = response->AppendBytes(buf, bufLen));
if (response->IsMoreBlocksFlagSet())
{
SuccessOrExit(error = CacheLastBlockResponse(response));
}
else
{
// Conclude block-wise transfer if last block has been received
FreeLastBlockResponse();
}
LogInfo("Send Block2 Nr. %d, Size: %d bytes, More Blocks Flag %d", response->GetBlockWiseBlockNumber(),
otCoapBlockSizeFromExponent(response->GetBlockWiseBlockSize()), response->IsMoreBlocksFlagSet());
SuccessOrExit(error = SendMessage(*response, aMessageInfo));
exit:
FreeMessageOnError(response, error);
return error;
}
#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
void CoapBase::SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
Error error;
@@ -1535,6 +1123,421 @@ exit:
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// `CoapBase` - BLockwise transfer methods
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
void CoapBase::AddBlockWiseResource(ResourceBlockWise &aResource) { IgnoreError(mBlockWiseResources.Add(aResource)); }
void CoapBase::RemoveBlockWiseResource(ResourceBlockWise &aResource)
{
IgnoreError(mBlockWiseResources.Remove(aResource));
aResource.SetNext(nullptr);
}
void CoapBase::FreeLastBlockResponse(void)
{
if (mLastResponse != nullptr)
{
mLastResponse->Free();
mLastResponse = nullptr;
}
}
Error CoapBase::CacheLastBlockResponse(Message *aResponse)
{
Error error = kErrorNone;
// Save last response for block-wise transfer
FreeLastBlockResponse();
if ((mLastResponse = aResponse->Clone()) == nullptr)
{
error = kErrorNoBufs;
}
return error;
}
Error CoapBase::PrepareNextBlockRequest(Message::BlockType aType,
bool aMoreBlocks,
Message &aRequestOld,
Message &aRequest,
Message &aMessage)
{
Error error = kErrorNone;
bool isOptionSet = false;
uint16_t blockOption = 0;
Option::Iterator iterator;
Metadata metadata;
blockOption = (aType == Message::kBlockType1) ? kOptionBlock1 : kOptionBlock2;
aRequest.Init(kTypeConfirmable, static_cast<ot::Coap::Code>(aRequestOld.GetCode()));
// Iterate after metadata copied and removed.
metadata.ReadFrom(aRequestOld);
metadata.RemoveFrom(aRequestOld);
// Per RFC 7959, all requests in a block-wise transfer MUST use the same token.
IgnoreError(aRequest.SetTokenFromMessage(aRequestOld));
SuccessOrExit(error = iterator.Init(aRequestOld));
// Copy options from last response to next message
for (; !iterator.IsDone() && iterator.GetOption()->GetLength() != 0; error = iterator.Advance())
{
uint16_t optionNumber = iterator.GetOption()->GetNumber();
SuccessOrExit(error);
// Check if option to copy next is higher than or equal to Block1 option
if (optionNumber >= blockOption && !isOptionSet)
{
// Write Block1 option to next message
SuccessOrExit(error = aRequest.AppendBlockOption(aType, aMessage.GetBlockWiseBlockNumber() + 1, aMoreBlocks,
aMessage.GetBlockWiseBlockSize()));
aRequest.SetBlockWiseBlockNumber(aMessage.GetBlockWiseBlockNumber() + 1);
aRequest.SetBlockWiseBlockSize(aMessage.GetBlockWiseBlockSize());
aRequest.SetMoreBlocksFlag(aMoreBlocks);
isOptionSet = true;
// If option to copy next is Block1 or Block2 option, option is not copied
if (optionNumber == kOptionBlock1 || optionNumber == kOptionBlock2)
{
continue;
}
}
// Copy option
SuccessOrExit(error = aRequest.AppendOptionFromMessage(optionNumber, iterator.GetOption()->GetLength(),
iterator.GetMessage(),
iterator.GetOptionValueMessageOffset()));
}
if (!isOptionSet)
{
// Write Block1 option to next message
SuccessOrExit(error = aRequest.AppendBlockOption(aType, aMessage.GetBlockWiseBlockNumber() + 1, aMoreBlocks,
aMessage.GetBlockWiseBlockSize()));
aRequest.SetBlockWiseBlockNumber(aMessage.GetBlockWiseBlockNumber() + 1);
aRequest.SetBlockWiseBlockSize(aMessage.GetBlockWiseBlockSize());
aRequest.SetMoreBlocksFlag(aMoreBlocks);
}
error = metadata.AppendTo(aRequestOld);
exit:
return error;
}
Error CoapBase::SendNextBlock1Request(Message &aRequest,
Message &aMessage,
const Ip6::MessageInfo &aMessageInfo,
const Metadata &aCoapMetadata)
{
Error error = kErrorNone;
Message *request = nullptr;
bool moreBlocks = false;
uint8_t buf[kMaxBlockLength] = {0};
uint16_t bufLen = kMaxBlockLength;
SuccessOrExit(error = aRequest.ReadBlockOptionValues(kOptionBlock1));
SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock1));
// Conclude block-wise transfer if last block has been received
if (!aRequest.IsMoreBlocksFlagSet())
{
FinalizeCoapTransaction(aRequest, aCoapMetadata, &aMessage, &aMessageInfo, kErrorNone);
ExitNow();
}
// Get next block
VerifyOrExit((bufLen = otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize())) <= kMaxBlockLength,
error = kErrorNoBufs);
SuccessOrExit(
error = aCoapMetadata.mBlockwiseTransmitHook(aCoapMetadata.mResponseContext, buf,
otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) *
(aMessage.GetBlockWiseBlockNumber() + 1),
&bufLen, &moreBlocks));
// Check if block length is valid
VerifyOrExit(bufLen <= otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()), error = kErrorInvalidArgs);
// Init request for next block
VerifyOrExit((request = NewMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = PrepareNextBlockRequest(Message::kBlockType1, moreBlocks, aRequest, *request, aMessage));
SuccessOrExit(error = request->SetPayloadMarker());
SuccessOrExit(error = request->AppendBytes(buf, bufLen));
DequeueMessage(aRequest);
LogInfo("Send Block1 Nr. %d, Size: %d bytes, More Blocks Flag: %d", request->GetBlockWiseBlockNumber(),
otCoapBlockSizeFromExponent(request->GetBlockWiseBlockSize()), request->IsMoreBlocksFlagSet());
SuccessOrExit(error = SendMessage(*request, aMessageInfo, TxParameters::GetDefault(),
aCoapMetadata.mResponseHandler, aCoapMetadata.mResponseContext,
aCoapMetadata.mBlockwiseTransmitHook, aCoapMetadata.mBlockwiseReceiveHook));
exit:
FreeMessageOnError(request, error);
return error;
}
Error CoapBase::SendNextBlock2Request(Message &aRequest,
Message &aMessage,
const Ip6::MessageInfo &aMessageInfo,
const Metadata &aCoapMetadata,
uint32_t aTotalLength,
bool aBeginBlock1Transfer)
{
Error error = kErrorNone;
Message *request = nullptr;
uint8_t buf[kMaxBlockLength] = {0};
uint16_t bufLen = kMaxBlockLength;
SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock2));
// Check payload and block length
VerifyOrExit((aMessage.GetLength() - aMessage.GetOffset()) <=
otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) &&
(aMessage.GetLength() - aMessage.GetOffset()) <= kMaxBlockLength,
error = kErrorNoBufs);
// Read and then forward payload to receive hook function
bufLen = aMessage.ReadBytes(aMessage.GetOffset(), buf, aMessage.GetLength() - aMessage.GetOffset());
SuccessOrExit(
error = aCoapMetadata.mBlockwiseReceiveHook(aCoapMetadata.mResponseContext, buf,
otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) *
aMessage.GetBlockWiseBlockNumber(),
bufLen, aMessage.IsMoreBlocksFlagSet(), aTotalLength));
// CoAP Block-Wise Transfer continues
LogInfo("Received Block2 Nr. %d , Size: %d bytes, More Blocks Flag: %d", aMessage.GetBlockWiseBlockNumber(),
otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()), aMessage.IsMoreBlocksFlagSet());
// Conclude block-wise transfer if last block has been received
if (!aMessage.IsMoreBlocksFlagSet())
{
FinalizeCoapTransaction(aRequest, aCoapMetadata, &aMessage, &aMessageInfo, kErrorNone);
ExitNow();
}
// Init request for next block
VerifyOrExit((request = NewMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = PrepareNextBlockRequest(Message::kBlockType2, aMessage.IsMoreBlocksFlagSet(), aRequest,
*request, aMessage));
if (!aBeginBlock1Transfer)
{
DequeueMessage(aRequest);
}
LogInfo("Request Block2 Nr. %d, Size: %d bytes", request->GetBlockWiseBlockNumber(),
otCoapBlockSizeFromExponent(request->GetBlockWiseBlockSize()));
SuccessOrExit(error =
SendMessage(*request, aMessageInfo, TxParameters::GetDefault(), aCoapMetadata.mResponseHandler,
aCoapMetadata.mResponseContext, nullptr, aCoapMetadata.mBlockwiseReceiveHook));
exit:
FreeMessageOnError(request, error);
return error;
}
Error CoapBase::ProcessBlock1Request(Message &aMessage,
const Ip6::MessageInfo &aMessageInfo,
const ResourceBlockWise &aResource,
uint32_t aTotalLength)
{
Error error = kErrorNone;
Message *response = nullptr;
uint8_t buf[kMaxBlockLength] = {0};
uint16_t bufLen = kMaxBlockLength;
SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock1));
// Read and then forward payload to receive hook function
VerifyOrExit((aMessage.GetLength() - aMessage.GetOffset()) <= kMaxBlockLength, error = kErrorNoBufs);
bufLen = aMessage.ReadBytes(aMessage.GetOffset(), buf, aMessage.GetLength() - aMessage.GetOffset());
SuccessOrExit(error = aResource.HandleBlockReceive(buf,
otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) *
aMessage.GetBlockWiseBlockNumber(),
bufLen, aMessage.IsMoreBlocksFlagSet(), aTotalLength));
if (aMessage.IsMoreBlocksFlagSet())
{
// Set up next response
VerifyOrExit((response = NewMessage()) != nullptr, error = kErrorFailed);
response->Init(kTypeAck, kCodeContinue);
response->SetMessageId(aMessage.GetMessageId());
IgnoreReturnValue(response->SetToken(AsConst(aMessage).GetToken(), aMessage.GetTokenLength()));
response->SetBlockWiseBlockNumber(aMessage.GetBlockWiseBlockNumber());
response->SetMoreBlocksFlag(aMessage.IsMoreBlocksFlagSet());
response->SetBlockWiseBlockSize(aMessage.GetBlockWiseBlockSize());
SuccessOrExit(error = response->AppendBlockOption(Message::kBlockType1, response->GetBlockWiseBlockNumber(),
response->IsMoreBlocksFlagSet(),
response->GetBlockWiseBlockSize()));
SuccessOrExit(error = CacheLastBlockResponse(response));
LogInfo("Acknowledge Block1 Nr. %d, Size: %d bytes", response->GetBlockWiseBlockNumber(),
otCoapBlockSizeFromExponent(response->GetBlockWiseBlockSize()));
SuccessOrExit(error = SendMessage(*response, aMessageInfo));
error = kErrorBusy;
}
else
{
// Conclude block-wise transfer if last block has been received
FreeLastBlockResponse();
error = kErrorNone;
}
exit:
if (error != kErrorNone && error != kErrorBusy && response != nullptr)
{
response->Free();
}
return error;
}
Error CoapBase::ProcessBlock2Request(Message &aMessage,
const Ip6::MessageInfo &aMessageInfo,
const ResourceBlockWise &aResource)
{
Error error = kErrorNone;
Message *response = nullptr;
uint8_t buf[kMaxBlockLength] = {0};
uint16_t bufLen = kMaxBlockLength;
bool moreBlocks = false;
uint64_t optionBuf = 0;
Option::Iterator iterator;
SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock2));
LogInfo("Request for Block2 Nr. %d, Size: %d bytes received", aMessage.GetBlockWiseBlockNumber(),
otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()));
if (aMessage.GetBlockWiseBlockNumber() == 0)
{
aResource.HandleRequest(aMessage, aMessageInfo);
ExitNow();
}
// Set up next response
VerifyOrExit((response = NewMessage()) != nullptr, error = kErrorNoBufs);
response->Init(kTypeAck, kCodeContent);
response->SetMessageId(aMessage.GetMessageId());
SuccessOrExit(error = response->SetTokenFromMessage(aMessage));
VerifyOrExit((bufLen = otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize())) <= kMaxBlockLength,
error = kErrorNoBufs);
SuccessOrExit(error = aResource.HandleBlockTransmit(buf,
otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) *
aMessage.GetBlockWiseBlockNumber(),
&bufLen, &moreBlocks));
response->SetMoreBlocksFlag(moreBlocks);
if (moreBlocks)
{
switch (bufLen)
{
case 1024:
response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_1024);
break;
case 512:
response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_512);
break;
case 256:
response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_256);
break;
case 128:
response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_128);
break;
case 64:
response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_64);
break;
case 32:
response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_32);
break;
case 16:
response->SetBlockWiseBlockSize(OT_COAP_OPTION_BLOCK_SZX_16);
break;
default:
error = kErrorInvalidArgs;
ExitNow();
break;
}
}
else
{
// Verify that buffer length is not larger than requested block size
VerifyOrExit(bufLen <= otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()),
error = kErrorInvalidArgs);
response->SetBlockWiseBlockSize(aMessage.GetBlockWiseBlockSize());
}
response->SetBlockWiseBlockNumber(
(otCoapBlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) * aMessage.GetBlockWiseBlockNumber()) /
(otCoapBlockSizeFromExponent(response->GetBlockWiseBlockSize())));
// Copy options from last response
SuccessOrExit(error = iterator.Init(*mLastResponse));
while (!iterator.IsDone())
{
uint16_t optionNumber = iterator.GetOption()->GetNumber();
if (optionNumber == kOptionBlock2)
{
SuccessOrExit(error = response->AppendBlockOption(Message::kBlockType2, response->GetBlockWiseBlockNumber(),
response->IsMoreBlocksFlagSet(),
response->GetBlockWiseBlockSize()));
}
else if (optionNumber == kOptionBlock1)
{
SuccessOrExit(error = iterator.ReadOptionValue(&optionBuf));
SuccessOrExit(error = response->AppendOption(optionNumber, iterator.GetOption()->GetLength(), &optionBuf));
}
SuccessOrExit(error = iterator.Advance());
}
SuccessOrExit(error = response->SetPayloadMarker());
SuccessOrExit(error = response->AppendBytes(buf, bufLen));
if (response->IsMoreBlocksFlagSet())
{
SuccessOrExit(error = CacheLastBlockResponse(response));
}
else
{
// Conclude block-wise transfer if last block has been received
FreeLastBlockResponse();
}
LogInfo("Send Block2 Nr. %d, Size: %d bytes, More Blocks Flag %d", response->GetBlockWiseBlockNumber(),
otCoapBlockSizeFromExponent(response->GetBlockWiseBlockSize()), response->IsMoreBlocksFlagSet());
SuccessOrExit(error = SendMessage(*response, aMessageInfo));
exit:
FreeMessageOnError(response, error);
return error;
}
#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
//---------------------------------------------------------------------------------------------------------------------
// CoapBase::ResponseCache
+20 -29
View File
@@ -268,7 +268,7 @@ protected:
mHandler(mContext, &aMessage, &aMessageInfo);
}
};
#endif
#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
/**
* Implements the CoAP client and server.
@@ -276,10 +276,6 @@ protected:
class CoapBase : public InstanceLocator, private NonCopyable
{
public:
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
static constexpr uint16_t kMaxBlockLength = OPENTHREAD_CONFIG_COAP_MAX_BLOCK_LENGTH;
#endif
/**
* Pointer is called before CoAP server processing a CoAP message.
*
@@ -770,6 +766,8 @@ protected:
void SetResourceHandler(ResourceHandler aHandler) { mResourceHandler = aHandler; }
private:
static constexpr uint16_t kMaxBlockLength = OPENTHREAD_CONFIG_COAP_MAX_BLOCK_LENGTH;
struct Metadata : public Message::FooterData<Metadata>
{
Ip6::Address mSourceAddress; // IPv6 address of the message source.
@@ -828,28 +826,30 @@ private:
TimerMilliContext mTimer;
};
Message *InitMessage(Message *aMessage, Type aType, Uri aUri);
Message *InitResponse(Message *aMessage, const Message &aRequest);
Message *InitMessage(Message *aMessage, Type aType, Uri aUri);
Message *InitResponse(Message *aMessage, const Message &aRequest);
void ScheduleRetransmissionTimer(void);
static void HandleRetransmissionTimer(Timer &aTimer);
void HandleRetransmissionTimer(void);
void ClearRequests(const Ip6::Address *aAddress);
Message *CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLength, const Metadata &aMetadata);
void DequeueMessage(Message &aMessage);
Message *FindRelatedRequest(const Message &aResponse, const Ip6::MessageInfo &aMessageInfo, Metadata &aMetadata);
void FinalizeCoapTransaction(Message &aRequest,
const Metadata &aMetadata,
Message *aResponse,
const Ip6::MessageInfo *aMessageInfo,
Error aResult);
bool InvokeResponseFallback(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const;
void ClearRequests(const Ip6::Address *aAddress);
Message *CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLength, const Metadata &aMetadata);
void DequeueMessage(Message &aMessage);
Message *FindRelatedRequest(const Message &aResponse, const Ip6::MessageInfo &aMessageInfo, Metadata &aMetadata);
void FinalizeCoapTransaction(Message &aRequest,
const Metadata &aMetadata,
Message *aResponse,
const Ip6::MessageInfo *aMessageInfo,
Error aResult);
bool InvokeResponseFallback(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const;
void ProcessReceivedRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void ProcessReceivedResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
Error SendEmptyMessage(Type aType, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
Error Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
void FreeLastBlockResponse(void);
Error CacheLastBlockResponse(Message *aResponse);
Error PrepareNextBlockRequest(Message::BlockType aType,
bool aMoreBlocks,
Message &aRequestOld,
@@ -862,11 +862,6 @@ private:
Error ProcessBlock2Request(Message &aMessage,
const Ip6::MessageInfo &aMessageInfo,
const ResourceBlockWise &aResource);
#endif
void ProcessReceivedRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void ProcessReceivedResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
Error SendNextBlock1Request(Message &aRequest,
Message &aMessage,
const Ip6::MessageInfo &aMessageInfo,
@@ -878,10 +873,6 @@ private:
uint32_t aTotalLength,
bool aBeginBlock1Transfer);
#endif
void SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
Error SendEmptyMessage(Type aType, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
Error Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
MessageQueue mPendingRequests;
uint16_t mMessageId;