From f917a5320f5c0834e3dd967c532aed93a3693b60 Mon Sep 17 00:00:00 2001 From: eeumay <154113236+eeumay@users.noreply.github.com> Date: Sat, 23 Mar 2024 01:25:59 +0800 Subject: [PATCH] [coap] fix copying option (#9894) - remove typo that passed a uint64_t pointer to a function which need a sufficiently large buffer - fix bug that coap copying uri path option or any other long option failed --- src/core/coap/coap.cpp | 6 +++--- src/core/coap/coap_message.cpp | 31 +++++++++++++++++++++++++++++-- src/core/coap/coap_message.hpp | 29 +++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp index 696d0fc83..6afd693a7 100644 --- a/src/core/coap/coap.cpp +++ b/src/core/coap/coap.cpp @@ -619,7 +619,6 @@ Error CoapBase::PrepareNextBlockRequest(Message::BlockType aType, { Error error = kErrorNone; bool isOptionSet = false; - uint64_t optionBuf = 0; uint16_t blockOption = 0; Option::Iterator iterator; @@ -655,8 +654,9 @@ Error CoapBase::PrepareNextBlockRequest(Message::BlockType aType, } // Copy option - SuccessOrExit(error = iterator.ReadOptionValue(&optionBuf)); - SuccessOrExit(error = aRequest.AppendOption(optionNumber, iterator.GetOption()->GetLength(), &optionBuf)); + SuccessOrExit(error = aRequest.AppendOptionFromMessage(optionNumber, iterator.GetOption()->GetLength(), + iterator.GetMessage(), + iterator.GetOptionValueMessageOffset())); } if (!isOptionSet) diff --git a/src/core/coap/coap_message.cpp b/src/core/coap/coap_message.cpp index cbf544813..4998de7a6 100644 --- a/src/core/coap/coap_message.cpp +++ b/src/core/coap/coap_message.cpp @@ -146,8 +146,12 @@ uint8_t Message::WriteExtendedOptionField(uint16_t aValue, uint8_t *&aBuffer) return rval; } -Error Message::AppendOption(uint16_t aNumber, uint16_t aLength, const void *aValue) +Error Message::AppendOptionHeader(uint16_t aNumber, uint16_t aLength) { + /* + * Appends a CoAP Option header field (Option Delta/Length) per RFC 7252. + */ + Error error = kErrorNone; uint16_t delta; uint8_t header[kMaxOptionHeaderSize]; @@ -167,10 +171,33 @@ Error Message::AppendOption(uint16_t aNumber, uint16_t aLength, const void *aVal VerifyOrExit(static_cast(GetLength()) + headerLength + aLength < kMaxHeaderLength, error = kErrorNoBufs); SuccessOrExit(error = AppendBytes(header, headerLength)); - SuccessOrExit(error = AppendBytes(aValue, aLength)); GetHelpData().mOptionLast = aNumber; +exit: + return error; +} + +Error Message::AppendOption(uint16_t aNumber, uint16_t aLength, const void *aValue) +{ + Error error = kErrorNone; + + SuccessOrExit(error = AppendOptionHeader(aNumber, aLength)); + SuccessOrExit(error = AppendBytes(aValue, aLength)); + + GetHelpData().mHeaderLength = GetLength(); + +exit: + return error; +} + +Error Message::AppendOptionFromMessage(uint16_t aNumber, uint16_t aLength, const Message &aMessage, uint16_t aOffset) +{ + Error error = kErrorNone; + + SuccessOrExit(error = AppendOptionHeader(aNumber, aLength)); + SuccessOrExit(error = AppendBytesFromMessage(aMessage, aOffset, aLength)); + GetHelpData().mHeaderLength = GetLength(); exit: diff --git a/src/core/coap/coap_message.hpp b/src/core/coap/coap_message.hpp index 789c91939..62128b6a3 100644 --- a/src/core/coap/coap_message.hpp +++ b/src/core/coap/coap_message.hpp @@ -401,6 +401,23 @@ public: */ Error AppendOption(uint16_t aNumber, uint16_t aLength, const void *aValue); + /** + * Appends a CoAP option reading Option value from another or potentially the same message. + * + * @param[in] aNumber The CoAP Option number. + * @param[in] aLength The CoAP Option length. + * @param[in] aMessage The message to read the CoAP Option value from (it can be the same as the current message). + * @param[in] aOffset The offset in @p aMessage to start reading the CoAP Option value from (@p aLength bytes are + * used as Option value). + * + * @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. + * @retval kErrorParse Not enough bytes in @p aMessage to read @p aLength bytes from @p aOffset. + * + */ + Error AppendOptionFromMessage(uint16_t aNumber, uint16_t aLength, const Message &aMessage, uint16_t aOffset); + /** * Appends an unsigned integer CoAP option as specified in RFC-7252 section-3.2 * @@ -966,6 +983,8 @@ private: } uint8_t WriteExtendedOptionField(uint16_t aValue, uint8_t *&aBuffer); + + Error AppendOptionHeader(uint16_t aNumber, uint16_t aLength); }; /** @@ -1187,6 +1206,16 @@ public: */ uint16_t GetPayloadMessageOffset(void) const { return mNextOptionOffset; } + /** + * Gets the offset of beginning of the CoAP Option Value. + * + * MUST be used during the iterator is in progress. + * + * @returns The offset of beginning of the CoAP Option Value + * + */ + uint16_t GetOptionValueMessageOffset(void) const { return mNextOptionOffset - mOption.mLength; } + private: // `mOption.mLength` value to indicate iterator is done. static constexpr uint16_t kIteratorDoneLength = 0xffff;