From b8ae6722519257e43d7fc12aa2873a177ed74dff Mon Sep 17 00:00:00 2001 From: Giedrius Date: Mon, 27 Feb 2017 19:08:50 +0200 Subject: [PATCH] Implement more CoAP Options (#1362) * Implement more CoAP Options * Observe * Max-Age * Uri-Query --- include/openthread-coap.h | 39 ++++++++++++++++++++++++++++ src/core/coap/coap_header.cpp | 49 +++++++++++++++++++++++++++++++++++ src/core/coap/coap_header.hpp | 33 +++++++++++++++++++++++ src/core/openthread.cpp | 15 +++++++++++ 4 files changed, 136 insertions(+) diff --git a/include/openthread-coap.h b/include/openthread-coap.h index 785e18536..c8d7ca9ad 100644 --- a/include/openthread-coap.h +++ b/include/openthread-coap.h @@ -91,8 +91,11 @@ typedef enum otCoapCode */ typedef enum otCoapOptionType { + kCoapOptionObserve = 6, ///< Observe kCoapOptionUriPath = 11, ///< Uri-Path kCoapOptionContentFormat = 12, ///< Content-Format + kCoapOptionMaxAge = 14, ///< Max-Age + kCoapOptionUriQuery = 15, ///< Uri-Query } otCoapOptionType; /** @@ -214,6 +217,18 @@ void otCoapHeaderGenerateToken(otCoapHeader *aHeader, uint8_t aTokenLength); */ ThreadError otCoapHeaderAppendOption(otCoapHeader *aHeader, const otCoapOption *aOption); +/** + * This function appends an Observe option. + * + * @param[inout] aHeader A pointer to the CoAP header. + * @param[in] aObserve Observe field value. + * + * @retval kThreadError_None Successfully appended the option. + * @retval kThreadError_InvalidArgs The option type is not equal or greater than the last option type. + * @retval kThreadError_NoBufs The option length exceeds the buffer size. + */ +ThreadError otCoapHeaderAppendObserveOption(otCoapHeader *aHeader, uint32_t aObserve); + /** * This function appends an Uri-Path option. * @@ -227,6 +242,30 @@ ThreadError otCoapHeaderAppendOption(otCoapHeader *aHeader, const otCoapOption * */ ThreadError otCoapHeaderAppendUriPathOptions(otCoapHeader *aHeader, const char *aUriPath); +/** + * This function appends a Max-Age option. + * + * @param[inout] aHeader A pointer to the CoAP header. + * @param[in] aMaxAge The Max-Age value. + * + * @retval kThreadError_None Successfully appended the option. + * @retval kThreadError_InvalidArgs The option type is not equal or greater than the last option type. + * @retval kThreadError_NoBufs The option length exceeds the buffer size. + */ +ThreadError otCoapHeaderAppendMaxAgeOption(otCoapHeader *aHeader, uint32_t aMaxAge); + +/** + * This function appends a single Uri-Query option. + * + * @param[inout] aHeader A pointer to the CoAP header. + * @param[in] aUriQuery A pointer to NULL-terminated string, which should contain a single key=value pair. + * + * @retval kThreadError_None Successfully appended the option. + * @retval kThreadError_InvalidArgs The option type is not equal or greater than the last option type. + * @retval kThreadError_NoBufs The option length exceeds the buffer size. + */ +ThreadError otCoapHeaderAppendUriQueryOption(otCoapHeader *aHeader, const char *aUriQuery); + /** * This function adds Payload Marker indicating beginning of the payload to the CoAP header. * diff --git a/src/core/coap/coap_header.cpp b/src/core/coap/coap_header.cpp index d8dc48953..d483e4539 100644 --- a/src/core/coap/coap_header.cpp +++ b/src/core/coap/coap_header.cpp @@ -244,6 +244,25 @@ exit: return error; } +ThreadError Header::AppendObserveOption(uint32_t aObserve) +{ + Option coapOption; + + aObserve = Encoding::BigEndian::HostSwap32(aObserve & 0xFFFFFF); + coapOption.mNumber = kCoapOptionObserve; + coapOption.mLength = 4; + coapOption.mValue = reinterpret_cast(&aObserve); + + // skip preceding zeros, but make sure mLength is at least 1 + while (coapOption.mValue[0] == 0 && coapOption.mLength > 1) + { + coapOption.mValue++; + coapOption.mLength--; + } + + return AppendOption(coapOption); +} + ThreadError Header::AppendUriPathOptions(const char *aUriPath) { ThreadError error = kThreadError_None; @@ -281,6 +300,36 @@ ThreadError Header::AppendContentFormatOption(MediaType aType) return AppendOption(coapOption); } +ThreadError Header::AppendMaxAgeOption(uint32_t aMaxAge) +{ + Option coapOption; + + aMaxAge = Encoding::BigEndian::HostSwap32(aMaxAge); + coapOption.mNumber = kCoapOptionMaxAge; + coapOption.mLength = 4; + coapOption.mValue = reinterpret_cast(&aMaxAge); + + // skip preceding zeros, but make sure mLength is at least 1 + while (coapOption.mValue[0] == 0 && coapOption.mLength > 1) + { + coapOption.mValue++; + coapOption.mLength--; + } + + return AppendOption(coapOption); +} + +ThreadError Header::AppendUriQueryOption(const char *aUriQuery) +{ + Option coapOption; + + coapOption.mNumber = kCoapOptionUriQuery; + coapOption.mLength = static_cast(strlen(aUriQuery)); + coapOption.mValue = reinterpret_cast(aUriQuery); + + return AppendOption(coapOption); +} + const Header::Option *Header::GetCurrentOption(void) const { return static_cast(&mOption); diff --git a/src/core/coap/coap_header.hpp b/src/core/coap/coap_header.hpp index bcfcc7bef..756cf1b0d 100644 --- a/src/core/coap/coap_header.hpp +++ b/src/core/coap/coap_header.hpp @@ -273,6 +273,17 @@ public: */ ThreadError AppendOption(const Option &aOption); + /** + * This method appends an Observe option. + * + * @param[in] aObserve Observe field value. + * + * @retval kThreadError_None Successfully appended the option. + * @retval kThreadError_InvalidArgs The option type is not equal or greater than the last option type. + * @retval kThreadError_NoBufs The option length exceeds the buffer size. + */ + ThreadError AppendObserveOption(uint32_t aObserve); + /** * This method appends a Uri-Path option. * @@ -306,6 +317,28 @@ public: */ ThreadError AppendContentFormatOption(MediaType aType); + /** + * This method appends a Max-Age option. + * + * @param[in] aMaxAge The Max-Age value. + * + * @retval kThreadError_None Successfully appended the option. + * @retval kThreadError_InvalidArgs The option type is not equal or greater than the last option type. + * @retval kThreadError_NoBufs The option length exceeds the buffer size. + */ + ThreadError AppendMaxAgeOption(uint32_t aMaxAge); + + /** + * This method appends a single Uri-Query option. + * + * @param[in] aUriQuery A pointer to NULL-terminated string, which should contain a single key=value pair. + * + * @retval kThreadError_None Successfully appended the option. + * @retval kThreadError_InvalidArgs The option type is not equal or greater than the last option type. + * @retval kThreadError_NoBufs The option length exceeds the buffer size. + */ + ThreadError AppendUriQueryOption(const char *aUriQuery); + /** * This method returns a pointer to the current option. * diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp index a22b1555f..0f3ef89fa 100644 --- a/src/core/openthread.cpp +++ b/src/core/openthread.cpp @@ -1987,11 +1987,26 @@ ThreadError otCoapHeaderAppendOption(otCoapHeader *aHeader, const otCoapOption * return static_cast(aHeader)->AppendOption(*static_cast(aOption)); } +ThreadError otCoapHeaderAppendObserveOption(otCoapHeader *aHeader, uint32_t aObserve) +{ + return static_cast(aHeader)->AppendObserveOption(aObserve); +} + ThreadError otCoapHeaderAppendUriPathOptions(otCoapHeader *aHeader, const char *aUriPath) { return static_cast(aHeader)->AppendUriPathOptions(aUriPath); } +ThreadError otCoapHeaderAppendMaxAgeOption(otCoapHeader *aHeader, uint32_t aMaxAge) +{ + return static_cast(aHeader)->AppendMaxAgeOption(aMaxAge); +} + +ThreadError otCoapHeaderAppendUriQueryOption(otCoapHeader *aHeader, const char *aUriQuery) +{ + return static_cast(aHeader)->AppendUriQueryOption(aUriQuery); +} + void otCoapHeaderSetPayloadMarker(otCoapHeader *aHeader) { static_cast(aHeader)->SetPayloadMarker();