diff --git a/src/core/api/coap_api.cpp b/src/core/api/coap_api.cpp index 56fd2d7b2..2b76c9edc 100644 --- a/src/core/api/coap_api.cpp +++ b/src/core/api/coap_api.cpp @@ -104,12 +104,24 @@ uint16_t otCoapBlockSizeFromExponent(otCoapBlockSzx aSize) { return Coap::BlockS otError otCoapMessageAppendBlock2Option(otMessage *aMessage, uint32_t aNum, bool aMore, otCoapBlockSzx aSize) { - return AsCoapMessage(aMessage).AppendBlockOption(Coap::Message::kBlockType2, aNum, aMore, MapEnum(aSize)); + Coap::BlockInfo blockInfo; + + blockInfo.mBlockNumber = aNum; + blockInfo.mBlockSzx = MapEnum(aSize); + blockInfo.mMoreBlocks = aMore; + + return AsCoapMessage(aMessage).AppendBlockOption(Coap::kOptionBlock2, blockInfo); } otError otCoapMessageAppendBlock1Option(otMessage *aMessage, uint32_t aNum, bool aMore, otCoapBlockSzx aSize) { - return AsCoapMessage(aMessage).AppendBlockOption(Coap::Message::kBlockType1, aNum, aMore, MapEnum(aSize)); + Coap::BlockInfo blockInfo; + + blockInfo.mBlockNumber = aNum; + blockInfo.mBlockSzx = MapEnum(aSize); + blockInfo.mMoreBlocks = aMore; + + return AsCoapMessage(aMessage).AppendBlockOption(Coap::kOptionBlock1, blockInfo); } otError otCoapMessageAppendProxyUriOption(otMessage *aMessage, const char *aUriPath) diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp index c56af6e3e..c9a69352d 100644 --- a/src/core/coap/coap.cpp +++ b/src/core/coap/coap.cpp @@ -915,24 +915,26 @@ Error CoapBase::SendMessage(Message &aMessage, 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]; + Error error = kErrorNone; + uint8_t type = aMessage.GetType(); + bool moreBlocks = false; + uint16_t blockSize; + uint8_t buf[kMaxBlockSize]; + BlockInfo blockInfo; VerifyOrExit(type != kTypeReset); VerifyOrExit(aTransmitHook != nullptr); - VerifyOrExit(aMessage.GetBlockWiseBlockNumber() == 0); - SuccessOrExit(aMessage.ReadBlockOptionValues(type == kTypeAck ? kOptionBlock2 : kOptionBlock1)); + SuccessOrExit(aMessage.ReadBlockOptionValues(type == kTypeAck ? kOptionBlock2 : kOptionBlock1, blockInfo)); - bufLen = BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()); - VerifyOrExit(bufLen <= kMaxBlockLength, error = kErrorNoBufs); + VerifyOrExit(blockInfo.mBlockNumber == 0); - SuccessOrExit(error = aTransmitHook(aContext, buf, 0, &bufLen, &moreBlocks)); - SuccessOrExit(error = aMessage.AppendBytes(buf, bufLen)); + blockSize = blockInfo.GetBlockSize(); + VerifyOrExit(blockSize <= kMaxBlockSize, error = kErrorNoBufs); + + SuccessOrExit(error = aTransmitHook(aContext, buf, 0, &blockSize, &moreBlocks)); + SuccessOrExit(error = aMessage.AppendBytes(buf, blockSize)); switch (type) { @@ -1168,7 +1170,7 @@ void CoapBase::FreeLastBlockResponse(void) Error CoapBase::CacheLastBlockResponse(Message *aResponse) { Error error = kErrorNone; - // Save last response for block-wise transfer + FreeLastBlockResponse(); if ((mLastResponse = aResponse->Clone()) == nullptr) @@ -1179,29 +1181,29 @@ Error CoapBase::CacheLastBlockResponse(Message *aResponse) return error; } -Error CoapBase::PrepareNextBlockRequest(Message::BlockType aType, - bool aMoreBlocks, - Message &aRequestOld, - Message &aRequest, - Message &aMessage) +Error CoapBase::PrepareNextBlockRequest(uint16_t aBlockOptionNumber, + Message &aRequestOld, + Message &aRequest, + const BlockInfo &aBlockInfo) { 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(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. + + // 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 + + SuccessOrExit(error = iterator.Init(aRequestOld)); + for (; !iterator.IsDone() && iterator.GetOption()->GetLength() != 0; error = iterator.Advance()) { uint16_t optionNumber = iterator.GetOption()->GetNumber(); @@ -1209,14 +1211,9 @@ Error CoapBase::PrepareNextBlockRequest(Message::BlockType aType, SuccessOrExit(error); // Check if option to copy next is higher than or equal to Block1 option - if (optionNumber >= blockOption && !isOptionSet) + if (optionNumber >= aBlockOptionNumber && !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); + SuccessOrExit(error = aRequest.AppendBlockOption(aBlockOptionNumber, aBlockInfo)); isOptionSet = true; @@ -1235,12 +1232,7 @@ Error CoapBase::PrepareNextBlockRequest(Message::BlockType aType, 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); + SuccessOrExit(error = aRequest.AppendBlockOption(aBlockOptionNumber, aBlockInfo)); } error = metadata.AppendTo(aRequestOld); @@ -1252,52 +1244,54 @@ exit: Error CoapBase::SendNextBlock1Request(Message &aRequest, Message &aMessage, const Ip6::MessageInfo &aMessageInfo, - const Metadata &aCoapMetadata) + const Metadata &aMetadata) { - Error error = kErrorNone; - Message *request = nullptr; - bool moreBlocks = false; - uint8_t buf[kMaxBlockLength] = {0}; - uint16_t bufLen = kMaxBlockLength; + Error error = kErrorNone; + Message *request = nullptr; + uint8_t buf[kMaxBlockSize] = {0}; + uint16_t blockSize; + BlockInfo msgBlockInfo; + BlockInfo requestBlockInfo; - SuccessOrExit(error = aRequest.ReadBlockOptionValues(kOptionBlock1)); - SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock1)); + SuccessOrExit(error = aRequest.ReadBlockOptionValues(kOptionBlock1, requestBlockInfo)); + SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock1, msgBlockInfo)); // Conclude block-wise transfer if last block has been received - if (!aRequest.IsMoreBlocksFlagSet()) + if (!requestBlockInfo.mMoreBlocks) { - FinalizeCoapTransaction(aRequest, aCoapMetadata, &aMessage, &aMessageInfo, kErrorNone); + FinalizeCoapTransaction(aRequest, aMetadata, &aMessage, &aMessageInfo, kErrorNone); ExitNow(); } - // Get next block - VerifyOrExit((bufLen = BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize())) <= kMaxBlockLength, - error = kErrorNoBufs); + blockSize = msgBlockInfo.GetBlockSize(); + VerifyOrExit(blockSize <= kMaxBlockSize, error = kErrorNoBufs); - SuccessOrExit(error = aCoapMetadata.mBlockwiseTransmitHook(aCoapMetadata.mResponseContext, buf, - BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) * - (aMessage.GetBlockWiseBlockNumber() + 1), - &bufLen, &moreBlocks)); + requestBlockInfo.mBlockNumber = msgBlockInfo.mBlockNumber + 1; + requestBlockInfo.mBlockSzx = msgBlockInfo.mBlockSzx; + requestBlockInfo.mMoreBlocks = false; - // Check if block length is valid - VerifyOrExit(bufLen <= BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()), error = kErrorInvalidArgs); + SuccessOrExit(error = aMetadata.mBlockwiseTransmitHook(aMetadata.mResponseContext, buf, + requestBlockInfo.GetBlockOffsetPosition(), &blockSize, + &requestBlockInfo.mMoreBlocks)); + + VerifyOrExit(blockSize <= msgBlockInfo.GetBlockSize(), error = kErrorInvalidArgs); - // Init request for next block VerifyOrExit((request = NewMessage()) != nullptr, error = kErrorNoBufs); - SuccessOrExit(error = PrepareNextBlockRequest(Message::kBlockType1, moreBlocks, aRequest, *request, aMessage)); + + SuccessOrExit(error = PrepareNextBlockRequest(kOptionBlock1, aRequest, *request, requestBlockInfo)); SuccessOrExit(error = request->SetPayloadMarker()); - SuccessOrExit(error = request->AppendBytes(buf, bufLen)); + SuccessOrExit(error = request->AppendBytes(buf, blockSize)); DequeueMessage(aRequest); - LogInfo("Send Block1 Nr. %d, Size: %d bytes, More Blocks Flag: %d", request->GetBlockWiseBlockNumber(), - BlockSizeFromExponent(request->GetBlockWiseBlockSize()), request->IsMoreBlocksFlagSet()); + LogInfo("Send Block1 Nr. %d, Size: %d bytes, More Blocks Flag: %d", requestBlockInfo.mBlockNumber, + requestBlockInfo.GetBlockSize(), requestBlockInfo.mMoreBlocks); - SuccessOrExit(error = SendMessage(*request, aMessageInfo, /* aTxParamters */ nullptr, - aCoapMetadata.mResponseHandler, aCoapMetadata.mResponseContext, - aCoapMetadata.mBlockwiseTransmitHook, aCoapMetadata.mBlockwiseReceiveHook)); + SuccessOrExit(error = SendMessage(*request, aMessageInfo, /* aTxParamters */ nullptr, aMetadata.mResponseHandler, + aMetadata.mResponseContext, aMetadata.mBlockwiseTransmitHook, + aMetadata.mBlockwiseReceiveHook)); exit: FreeMessageOnError(request, error); @@ -1308,57 +1302,54 @@ exit: Error CoapBase::SendNextBlock2Request(Message &aRequest, Message &aMessage, const Ip6::MessageInfo &aMessageInfo, - const Metadata &aCoapMetadata, + const Metadata &aMetadata, uint32_t aTotalLength, bool aBeginBlock1Transfer) { - Error error = kErrorNone; - Message *request = nullptr; - uint8_t buf[kMaxBlockLength] = {0}; - uint16_t bufLen = kMaxBlockLength; + Error error = kErrorNone; + Message *request = nullptr; + uint8_t buf[kMaxBlockSize]; + OffsetRange offsetRange; + BlockInfo msgBlockInfo; + BlockInfo requestBlockInfo; - SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock2)); + SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock2, msgBlockInfo)); - // Check payload and block length - VerifyOrExit((aMessage.GetLength() - aMessage.GetOffset()) <= - BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) && - (aMessage.GetLength() - aMessage.GetOffset()) <= kMaxBlockLength, - error = kErrorNoBufs); + VerifyOrExit(msgBlockInfo.GetBlockSize() <= kMaxBlockSize, 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, - BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) * - aMessage.GetBlockWiseBlockNumber(), - bufLen, aMessage.IsMoreBlocksFlagSet(), aTotalLength)); + offsetRange.InitFromMessageOffsetToEnd(aMessage); + VerifyOrExit(offsetRange.GetLength() <= msgBlockInfo.GetBlockSize(), error = kErrorNoBufs); - // CoAP Block-Wise Transfer continues - LogInfo("Received Block2 Nr. %d , Size: %d bytes, More Blocks Flag: %d", aMessage.GetBlockWiseBlockNumber(), - BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()), aMessage.IsMoreBlocksFlagSet()); + aMessage.ReadBytes(offsetRange, buf); + SuccessOrExit( + error = aMetadata.mBlockwiseReceiveHook(aMetadata.mResponseContext, buf, msgBlockInfo.GetBlockOffsetPosition(), + offsetRange.GetLength(), msgBlockInfo.mMoreBlocks, aTotalLength)); - // Conclude block-wise transfer if last block has been received - if (!aMessage.IsMoreBlocksFlagSet()) + LogInfo("Received Block2 Nr. %d , Size: %d bytes, More Blocks Flag: %d", msgBlockInfo.mBlockNumber, + msgBlockInfo.GetBlockSize(), msgBlockInfo.mMoreBlocks); + + if (!msgBlockInfo.mMoreBlocks) { - FinalizeCoapTransaction(aRequest, aCoapMetadata, &aMessage, &aMessageInfo, kErrorNone); + FinalizeCoapTransaction(aRequest, aMetadata, &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)); + + requestBlockInfo = msgBlockInfo; + requestBlockInfo.mBlockNumber++; + + SuccessOrExit(error = PrepareNextBlockRequest(kOptionBlock2, aRequest, *request, requestBlockInfo)); if (!aBeginBlock1Transfer) { DequeueMessage(aRequest); } - LogInfo("Request Block2 Nr. %d, Size: %d bytes", request->GetBlockWiseBlockNumber(), - BlockSizeFromExponent(request->GetBlockWiseBlockSize())); + LogInfo("Request Block2 Nr. %d, Size: %d bytes", requestBlockInfo.mBlockNumber, requestBlockInfo.GetBlockSize()); - SuccessOrExit(error = - SendMessage(*request, aMessageInfo, /* aTxParameters */ nullptr, aCoapMetadata.mResponseHandler, - aCoapMetadata.mResponseContext, nullptr, aCoapMetadata.mBlockwiseReceiveHook)); + SuccessOrExit(error = SendMessage(*request, aMessageInfo, /* aTxParameters */ nullptr, aMetadata.mResponseHandler, + aMetadata.mResponseContext, nullptr, aMetadata.mBlockwiseReceiveHook)); exit: FreeMessageOnError(request, error); @@ -1371,40 +1362,35 @@ Error CoapBase::ProcessBlock1Request(Message &aMessage, const ResourceBlockWise &aResource, uint32_t aTotalLength) { - Error error = kErrorNone; - Message *response = nullptr; - uint8_t buf[kMaxBlockLength] = {0}; - uint16_t bufLen = kMaxBlockLength; + Error error = kErrorNone; + Message *response = nullptr; + uint8_t buf[kMaxBlockSize]; + OffsetRange offsetRange; + BlockInfo msgBlockInfo; - SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock1)); + SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock1, msgBlockInfo)); - // 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, BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) * aMessage.GetBlockWiseBlockNumber(), - bufLen, aMessage.IsMoreBlocksFlagSet(), aTotalLength)); + offsetRange.InitFromMessageOffsetToEnd(aMessage); + VerifyOrExit(offsetRange.GetLength() <= kMaxBlockSize, error = kErrorNoBufs); - if (aMessage.IsMoreBlocksFlagSet()) + aMessage.ReadBytes(offsetRange, buf); + SuccessOrExit(error = + aResource.HandleBlockReceive(buf, msgBlockInfo.GetBlockOffsetPosition(), offsetRange.GetLength(), + msgBlockInfo.mMoreBlocks, aTotalLength)); + + if (msgBlockInfo.mMoreBlocks) { // 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())); + IgnoreError(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 = response->AppendBlockOption(kOptionBlock1, msgBlockInfo)); SuccessOrExit(error = CacheLastBlockResponse(response)); - LogInfo("Acknowledge Block1 Nr. %d, Size: %d bytes", response->GetBlockWiseBlockNumber(), - BlockSizeFromExponent(response->GetBlockWiseBlockSize())); + LogInfo("Acknowledge Block1 Nr. %d, Size: %d bytes", msgBlockInfo.mBlockNumber, msgBlockInfo.GetBlockSize()); SuccessOrExit(error = SendMessage(*response, aMessageInfo)); @@ -1430,57 +1416,49 @@ 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; + Error error = kErrorNone; + Message *response = nullptr; + uint64_t optionBuf = 0; + uint8_t buf[kMaxBlockSize] = {0}; + uint16_t blockSize; Option::Iterator iterator; + BlockInfo msgBlockInfo; + BlockInfo responseBlockInfo; - SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock2)); + SuccessOrExit(error = aMessage.ReadBlockOptionValues(kOptionBlock2, msgBlockInfo)); - LogInfo("Request for Block2 Nr. %d, Size: %d bytes received", aMessage.GetBlockWiseBlockNumber(), - BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize())); + LogInfo("Request for Block2 Nr. %d, Size: %d bytes received", msgBlockInfo.mBlockNumber, + msgBlockInfo.GetBlockSize()); - if (aMessage.GetBlockWiseBlockNumber() == 0) + if (msgBlockInfo.mBlockNumber == 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 = BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize())) <= kMaxBlockLength, - error = kErrorNoBufs); - SuccessOrExit(error = aResource.HandleBlockTransmit( - buf, BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) * aMessage.GetBlockWiseBlockNumber(), - &bufLen, &moreBlocks)); + responseBlockInfo.mMoreBlocks = false; - response->SetMoreBlocksFlag(moreBlocks); + VerifyOrExit((blockSize = msgBlockInfo.GetBlockSize()) <= kMaxBlockSize, error = kErrorNoBufs); + SuccessOrExit(error = aResource.HandleBlockTransmit(buf, msgBlockInfo.GetBlockOffsetPosition(), &blockSize, + &responseBlockInfo.mMoreBlocks)); - if (moreBlocks) + if (responseBlockInfo.mMoreBlocks) { - BlockSzx blockSzx; - - SuccessOrExit(error = DetermineBlockSzxFromSize(bufLen, blockSzx)); - response->SetBlockWiseBlockSize(blockSzx); + SuccessOrExit(error = DetermineBlockSzxFromSize(blockSize, responseBlockInfo.mBlockSzx)); } else { - // Verify that buffer length is not larger than requested block size - VerifyOrExit(bufLen <= BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()), error = kErrorInvalidArgs); - response->SetBlockWiseBlockSize(aMessage.GetBlockWiseBlockSize()); + VerifyOrExit(blockSize <= msgBlockInfo.GetBlockSize(), error = kErrorInvalidArgs); + responseBlockInfo.mBlockSzx = msgBlockInfo.mBlockSzx; } - response->SetBlockWiseBlockNumber( - (BlockSizeFromExponent(aMessage.GetBlockWiseBlockSize()) * aMessage.GetBlockWiseBlockNumber()) / - (BlockSizeFromExponent(response->GetBlockWiseBlockSize()))); + responseBlockInfo.mBlockNumber = msgBlockInfo.GetBlockOffsetPosition() / responseBlockInfo.GetBlockSize(); // Copy options from last response SuccessOrExit(error = iterator.Init(*mLastResponse)); @@ -1491,9 +1469,7 @@ Error CoapBase::ProcessBlock2Request(Message &aMessage, if (optionNumber == kOptionBlock2) { - SuccessOrExit(error = response->AppendBlockOption(Message::kBlockType2, response->GetBlockWiseBlockNumber(), - response->IsMoreBlocksFlagSet(), - response->GetBlockWiseBlockSize())); + SuccessOrExit(error = response->AppendBlockOption(kOptionBlock2, responseBlockInfo)); } else if (optionNumber == kOptionBlock1) { @@ -1505,9 +1481,9 @@ Error CoapBase::ProcessBlock2Request(Message &aMessage, } SuccessOrExit(error = response->SetPayloadMarker()); - SuccessOrExit(error = response->AppendBytes(buf, bufLen)); + SuccessOrExit(error = response->AppendBytes(buf, blockSize)); - if (response->IsMoreBlocksFlagSet()) + if (responseBlockInfo.mMoreBlocks) { SuccessOrExit(error = CacheLastBlockResponse(response)); } @@ -1517,8 +1493,8 @@ Error CoapBase::ProcessBlock2Request(Message &aMessage, FreeLastBlockResponse(); } - LogInfo("Send Block2 Nr. %d, Size: %d bytes, More Blocks Flag %d", response->GetBlockWiseBlockNumber(), - BlockSizeFromExponent(response->GetBlockWiseBlockSize()), response->IsMoreBlocksFlagSet()); + LogInfo("Send Block2 Nr. %d, Size: %d bytes, More Blocks Flag %d", responseBlockInfo.mBlockNumber, + responseBlockInfo.GetBlockSize(), responseBlockInfo.mMoreBlocks); SuccessOrExit(error = SendMessage(*response, aMessageInfo)); diff --git a/src/core/coap/coap.hpp b/src/core/coap/coap.hpp index 956b520d9..7ab85fc4d 100644 --- a/src/core/coap/coap.hpp +++ b/src/core/coap/coap.hpp @@ -728,7 +728,7 @@ protected: void SetResourceHandler(ResourceHandler aHandler) { mResourceHandler = aHandler; } private: - static constexpr uint16_t kMaxBlockLength = OPENTHREAD_CONFIG_COAP_MAX_BLOCK_LENGTH; + static constexpr uint16_t kMaxBlockSize = OPENTHREAD_CONFIG_COAP_MAX_BLOCK_LENGTH; struct Metadata : public Message::FooterData { @@ -822,11 +822,10 @@ private: bool &aDidHandle); void FreeLastBlockResponse(void); Error CacheLastBlockResponse(Message *aResponse); - Error PrepareNextBlockRequest(Message::BlockType aType, - bool aMoreBlocks, - Message &aRequestOld, - Message &aRequest, - Message &aMessage); + Error PrepareNextBlockRequest(uint16_t aBlockOptionNumber, + Message &aRequestOld, + Message &aRequest, + const BlockInfo &aBlockInfo); Error ProcessBlock1Request(Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const ResourceBlockWise &aResource, @@ -837,11 +836,11 @@ private: Error SendNextBlock1Request(Message &aRequest, Message &aMessage, const Ip6::MessageInfo &aMessageInfo, - const Metadata &aCoapMetadata); + const Metadata &aMetadata); Error SendNextBlock2Request(Message &aRequest, Message &aMessage, const Ip6::MessageInfo &aMessageInfo, - const Metadata &aCoapMetadata, + const Metadata &aMetadata, uint32_t aTotalLength, bool aBeginBlock1Transfer); diff --git a/src/core/coap/coap_message.cpp b/src/core/coap/coap_message.cpp index 0cca3a543..0440017fe 100644 --- a/src/core/coap/coap_message.cpp +++ b/src/core/coap/coap_message.cpp @@ -56,11 +56,6 @@ void Message::Init(void) GetHelpData().mHeaderLength = kMinHeaderLength; IgnoreError(SetLength(GetHelpData().mHeaderLength)); -#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - SetBlockWiseBlockNumber(0); - SetMoreBlocksFlag(false); - SetBlockWiseBlockSize(kBlockSzx16); -#endif } void Message::Init(Type aType, Code aCode) @@ -295,56 +290,70 @@ exit: return error; } -Error Message::AppendBlockOption(Message::BlockType aType, uint32_t aNum, bool aMore, BlockSzx aSize) +Error Message::AppendBlockOption(uint16_t aBlockOptionNumber, const BlockInfo &aInfo) { - Error error = kErrorNone; - uint32_t encoded = aSize; + Error error; + uint32_t encoded; - VerifyOrExit(aType == kBlockType1 || aType == kBlockType2, error = kErrorInvalidArgs); - VerifyOrExit(aSize <= kBlockSzx1024, error = kErrorInvalidArgs); - VerifyOrExit(aNum < kBlockNumMax, error = kErrorInvalidArgs); + switch (aBlockOptionNumber) + { + case kOptionBlock1: + case kOptionBlock2: + break; + default: + ExitNow(error = kErrorInvalidArgs); + } - encoded |= static_cast(aMore << kBlockMOffset); - encoded |= aNum << kBlockNumOffset; + VerifyOrExit(aInfo.mBlockSzx <= kBlockSzx1024, error = kErrorInvalidArgs); + VerifyOrExit(aInfo.mBlockNumber < kBlockNumMax, error = kErrorInvalidArgs); - error = AppendUintOption((aType == kBlockType1) ? kOptionBlock1 : kOptionBlock2, encoded); + encoded = aInfo.mBlockSzx; + encoded |= static_cast(aInfo.mMoreBlocks << kBlockMOffset); + encoded |= aInfo.mBlockNumber << kBlockNumOffset; + + error = AppendUintOption(aBlockOptionNumber, encoded); exit: return error; } #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE -Error Message::ReadBlockOptionValues(uint16_t aBlockType) + +Error Message::ReadBlockOptionValues(uint16_t aBlockOptionNumber, BlockInfo &aInfo) const { - Error error = kErrorNone; + Error error; uint8_t buf[kMaxOptionHeaderSize] = {0}; Option::Iterator iterator; - VerifyOrExit((aBlockType == kOptionBlock1) || (aBlockType == kOptionBlock2), error = kErrorInvalidArgs); + switch (aBlockOptionNumber) + { + case kOptionBlock1: + case kOptionBlock2: + break; + default: + ExitNow(error = kErrorInvalidArgs); + } - SuccessOrExit(error = iterator.Init(*this, aBlockType)); + SuccessOrExit(error = iterator.Init(*this, aBlockOptionNumber)); SuccessOrExit(error = iterator.ReadOptionValue(buf)); - SetBlockWiseBlockNumber(0); - SetMoreBlocksFlag(false); - switch (iterator.GetOption()->GetLength()) { case 0: case 1: - SetBlockWiseBlockNumber(static_cast((buf[0] & 0xf0) >> 4)); - SetMoreBlocksFlag(static_cast((buf[0] & 0x08) >> 3 == 1)); - SetBlockWiseBlockSize(static_cast(buf[0] & 0x07)); + aInfo.mBlockNumber = static_cast((buf[0] & 0xf0) >> 4); + aInfo.mMoreBlocks = (((buf[0] & 0x08) >> 3) == 1); + aInfo.mBlockSzx = (static_cast(buf[0] & 0x07)); break; case 2: - SetBlockWiseBlockNumber(static_cast((buf[0] << 4) + ((buf[1] & 0xf0) >> 4))); - SetMoreBlocksFlag(static_cast((buf[1] & 0x08) >> 3 == 1)); - SetBlockWiseBlockSize(static_cast(buf[1] & 0x07)); + aInfo.mBlockNumber = static_cast((buf[0] << 4) + ((buf[1] & 0xf0) >> 4)); + aInfo.mMoreBlocks = ((buf[1] & 0x08) >> 3 == 1); + aInfo.mBlockSzx = (static_cast(buf[1] & 0x07)); break; case 3: - SetBlockWiseBlockNumber(static_cast((buf[0] << 12) + (buf[1] << 4) + ((buf[2] & 0xf0) >> 4))); - SetMoreBlocksFlag(static_cast((buf[2] & 0x08) >> 3 == 1)); - SetBlockWiseBlockSize(static_cast(buf[2] & 0x07)); + aInfo.mBlockNumber = static_cast((buf[0] << 12) + (buf[1] << 4) + ((buf[2] & 0xf0) >> 4)); + aInfo.mMoreBlocks = ((buf[2] & 0x08) >> 3 == 1); + aInfo.mBlockSzx = (static_cast(buf[2] & 0x07)); break; default: error = kErrorInvalidArgs; @@ -354,6 +363,7 @@ Error Message::ReadBlockOptionValues(uint16_t aBlockType) exit: return error; } + #endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE Error Message::SetPayloadMarker(void) diff --git a/src/core/coap/coap_message.hpp b/src/core/coap/coap_message.hpp index 090ceb832..72cd711fe 100644 --- a/src/core/coap/coap_message.hpp +++ b/src/core/coap/coap_message.hpp @@ -176,6 +176,30 @@ enum BlockSzx : uint8_t */ uint16_t BlockSizeFromExponent(BlockSzx aBlockSzx); +/** + * Represents information in a Block1 or Block2 Option (for block-wise transfer). + */ +struct BlockInfo +{ + /** + * Returns the block size in bytes. + * + * @returns The block size in bytes derived from block size exponent (`mBlockSzx`). + */ + uint16_t GetBlockSize(void) const { return BlockSizeFromExponent(mBlockSzx); } + + /** + * Returns the current block offset position. + * + * @returns The block offset position, i.e. the current block number multiplied by the block size. + */ + uint32_t GetBlockOffsetPosition(void) const { return mBlockNumber * GetBlockSize(); } + + uint32_t mBlockNumber; ///< The block number. + BlockSzx mBlockSzx; ///< The block size exponent. + bool mMoreBlocks; ///< Whether more blocks are following (`M` flag). +}; + /** * Implements CoAP message generation and parsing. */ @@ -194,15 +218,6 @@ public: typedef char UriPathStringBuffer[kMaxReceivedUriPath + 1]; ///< Buffer to store a received URI Path string. - /** - * CoAP Block1/Block2 Types - */ - enum BlockType : uint8_t - { - kBlockType1 = 1, - kBlockType2 = 2, - }; - /** * Initializes the CoAP header. */ @@ -480,18 +495,30 @@ public: Error AppendUriQueryOptions(const char *aUriQuery); /** - * Appends a Block option - * - * @param[in] aType Type of block option, 1 or 2. - * @param[in] aNum Current block number. - * @param[in] aMore Boolean to indicate more blocks are to be sent. - * @param[in] aSize Maximum block size. + * Appends a Block1 or Block2 option. * + * @param[in] aBlockOptionNumber Block1 or Block2 option number. + * @param[out] aInfo A `BlockInfo` specifying block number, size, and more blocks flags. + * @retval kErrorNone Successfully appended the option. * @retval kErrorInvalidArgs The option type is not equal or greater than the last option type. * @retval kErrorNoBufs The option length exceeds the buffer size. */ - Error AppendBlockOption(BlockType aType, uint32_t aNum, bool aMore, BlockSzx aSize); + Error AppendBlockOption(uint16_t aBlockOptionNumber, const BlockInfo &aInfo); + +#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE + /** + * Reads the information contained in a Block1 or Block2 option from the CoAP message. + * + * @param[in] aBlockOptionNumber Block1 or Block2 option number. + * @param[out] aInfo A reference to `BlockInfo` to return the read Option + * + * @retval kErrorNone The option was read successfully. @p aInfo is updated. + * @retval kErrorNotFound The option has not been found. + * @retval kErrorInvalidArgs The option is invalid. + */ + Error ReadBlockOptionValues(uint16_t aBlockOptionNumber, BlockInfo &aInfo) const; +#endif /** * Appends a Proxy-Uri option. @@ -540,49 +567,6 @@ public: */ Error AppendUriQueryOption(const char *aUriQuery) { return AppendStringOption(kOptionUriQuery, aUriQuery); } -#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - /** - * Reads the information contained in a Block1 or Block2 option and set it in - * the HelpData of the message. - * - * @param[in] aBlockType Block1 or Block2 option value. - * - * @retval kErrorNone The option has been found and is valid. - * @retval kErrorNotFound The option has not been found. - * @retval kErrorInvalidArgs The option is invalid. - */ - Error ReadBlockOptionValues(uint16_t aBlockType); - - /** - * Returns the current header length of a message. - * - * @returns The length of the message header. - */ - uint16_t GetHeaderLength(void) const { return GetHelpData().mHeaderLength; } - - /** - * Returns the block number of a CoAP block-wise transfer message. - * - * @returns The block number. - */ - uint32_t GetBlockWiseBlockNumber(void) const { return GetHelpData().mBlockWiseData.mBlockNumber; } - - /** - * Checks if the More Blocks flag is set. - * - * @retval TRUE More Blocks flag is set. - * @retval FALSE More Blocks flag is not set. - */ - bool IsMoreBlocksFlagSet(void) const { return GetHelpData().mBlockWiseData.mMoreBlocks; } - - /** - * Returns the block size of a CoAP block-wise transfer message. - * - * @returns The block size. - */ - BlockSzx GetBlockWiseBlockSize(void) const { return GetHelpData().mBlockWiseData.mBlockSize; } -#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - /** * Reads and reassembles the URI path string and fills it into @p aUriPath. * @@ -626,30 +610,6 @@ public: */ Error SetDefaultResponseHeader(const Message &aRequest); -#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - - /** - * Sets the block number value in the message HelpData. - * - * @param[in] aBlockNumber Block number value to set. - */ - void SetBlockWiseBlockNumber(uint32_t aBlockNumber) { GetHelpData().mBlockWiseData.mBlockNumber = aBlockNumber; } - - /** - * Sets the More Blocks flag in the message HelpData. - * - * @param[in] aMoreBlocks TRUE or FALSE. - */ - void SetMoreBlocksFlag(bool aMoreBlocks) { GetHelpData().mBlockWiseData.mMoreBlocks = aMoreBlocks; } - - /** - * Sets the block size value in the message HelpData. - * - * @param[in] aBlockSize Block size value to set. - */ - void SetBlockWiseBlockSize(BlockSzx aBlockSize) { GetHelpData().mBlockWiseData.mBlockSize = aBlockSize; } -#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - /** * Checks if a header is an empty message header. * @@ -878,15 +838,6 @@ private: static constexpr uint32_t kObserveMask = 0xffffff; static constexpr uint32_t kBlockNumMax = 0xffff; -#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - struct BlockWiseData - { - uint32_t mBlockNumber; - bool mMoreBlocks; - BlockSzx mBlockSize; - }; -#endif - /** * Represents a CoAP header excluding CoAP options. */ @@ -909,9 +860,6 @@ private: uint16_t mHeaderOffset; ///< The byte offset for the CoAP Header uint16_t mHeaderLength; bool mPayloadMarkerSet; -#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE - BlockWiseData mBlockWiseData; -#endif }; class ConstIterator : public ot::Message::ConstIterator