diff --git a/include/openthread/coap.h b/include/openthread/coap.h index 8afb34de7..0d341d62e 100644 --- a/include/openthread/coap.h +++ b/include/openthread/coap.h @@ -136,6 +136,7 @@ typedef struct otCoapHeader } mHeader; ///< The CoAP header encoding uint8_t mHeaderLength; ///< The CoAP header length (bytes) uint16_t mOptionLast; ///< The last CoAP Option Number value + uint16_t mFirstOptionOffset; ///< The byte offset for the first CoAP Option uint16_t mNextOptionOffset; ///< The byte offset for the next CoAP Option otCoapOption mOption; ///< A structure representing the current CoAP Option. } otCoapHeader; @@ -344,14 +345,14 @@ uint8_t otCoapHeaderGetTokenLength(const otCoapHeader *aHeader); const uint8_t *otCoapHeaderGetToken(const otCoapHeader *aHeader); /** - * This function returns a pointer to the current option. + * This function returns a pointer to the first option. * * @param[in] aHeader A pointer to the CoAP header. * - * @returns A pointer to the current option. If no option is present NULL pointer is returned. + * @returns A pointer to the first option. If no option is present NULL pointer is returned. * */ -const otCoapOption *otCoapHeaderGetCurrentOption(const otCoapHeader *aHeader); +const otCoapOption *otCoapHeaderGetFirstOption(otCoapHeader *aHeader); /** * This function returns a pointer to the next option. diff --git a/src/core/api/coap_api.cpp b/src/core/api/coap_api.cpp index c459208ef..beacdd5d9 100644 --- a/src/core/api/coap_api.cpp +++ b/src/core/api/coap_api.cpp @@ -116,9 +116,9 @@ const uint8_t *otCoapHeaderGetToken(const otCoapHeader *aHeader) return static_cast(aHeader)->GetToken(); } -const otCoapOption *otCoapHeaderGetCurrentOption(const otCoapHeader *aHeader) +const otCoapOption *otCoapHeaderGetFirstOption(otCoapHeader *aHeader) { - return static_cast(static_cast(aHeader)->GetCurrentOption()); + return static_cast(static_cast(aHeader)->GetFirstOption()); } const otCoapOption *otCoapHeaderGetNextOption(otCoapHeader *aHeader) diff --git a/src/core/coap/coap_header.cpp b/src/core/coap/coap_header.cpp index 1267bbce7..1d9269dbf 100644 --- a/src/core/coap/coap_header.cpp +++ b/src/core/coap/coap_header.cpp @@ -46,6 +46,7 @@ void Header::Init(void) { mHeaderLength = kMinHeaderLength; mOptionLast = 0; + mFirstOptionOffset = 0; mNextOptionOffset = 0; memset(&mOption, 0, sizeof(mOption)); memset(&mHeader, 0, sizeof(mHeader)); @@ -71,6 +72,8 @@ ThreadError Header::FromMessage(const Message &aMessage, uint16_t aMetadataSize) length -= aMetadataSize; + Init(); + VerifyOrExit(length >= kTokenOffset, error = kThreadError_Parse); aMessage.Read(offset, kTokenOffset, mHeader.mBytes); mHeaderLength = kTokenOffset; @@ -96,6 +99,11 @@ ThreadError Header::FromMessage(const Message &aMessage, uint16_t aMetadataSize) ExitNow(error = kThreadError_None); } + if (firstOption) + { + mFirstOptionOffset = mHeaderLength; + } + optionDelta = mHeader.mBytes[mHeaderLength] >> 4; optionLength = mHeader.mBytes[mHeaderLength] & 0xf; mHeaderLength += sizeof(uint8_t); @@ -173,6 +181,13 @@ ThreadError Header::FromMessage(const Message &aMessage, uint16_t aMetadataSize) } exit: + + // In case any step failed, prevent access to corrupt Option + if (error != kThreadError_None) + { + mFirstOptionOffset = 0; + } + return error; } @@ -328,9 +343,19 @@ ThreadError Header::AppendUriQueryOption(const char *aUriQuery) return AppendOption(coapOption); } -const Header::Option *Header::GetCurrentOption(void) const +const Header::Option *Header::GetFirstOption(void) { - return static_cast(&mOption); + const Option *rval = NULL; + + VerifyOrExit(mFirstOptionOffset > 0,); + + memset(&mOption, 0, sizeof(mOption)); + mNextOptionOffset = mFirstOptionOffset; + + rval = GetNextOption(); + +exit: + return rval; } const Header::Option *Header::GetNextOption(void) diff --git a/src/core/coap/coap_header.hpp b/src/core/coap/coap_header.hpp index 8af76aab5..35245eea2 100644 --- a/src/core/coap/coap_header.hpp +++ b/src/core/coap/coap_header.hpp @@ -340,12 +340,12 @@ public: ThreadError AppendUriQueryOption(const char *aUriQuery); /** - * This method returns a pointer to the current option. + * This method returns a pointer to the first option. * - * @returns A pointer to the current option. + * @returns A pointer to the first option. * */ - const Option *GetCurrentOption(void) const; + const Option *GetFirstOption(void); /** * This method returns a pointer to the next option. diff --git a/src/core/coap/coap_server.cpp b/src/core/coap/coap_server.cpp index 0736a9ae3..571fa935a 100644 --- a/src/core/coap/coap_server.cpp +++ b/src/core/coap/coap_server.cpp @@ -173,7 +173,7 @@ void Server::ProcessReceivedMessage(Message &aMessage, const Ip6::MessageInfo &a break; } - coapOption = header.GetCurrentOption(); + coapOption = header.GetFirstOption(); while (coapOption != NULL) { @@ -191,11 +191,8 @@ void Server::ProcessReceivedMessage(Message &aMessage, const Ip6::MessageInfo &a curUriPath += coapOption->mLength; break; - case kCoapOptionContentFormat: - break; - default: - ExitNow(); + break; } coapOption = header.GetNextOption();