From 5eee323b8d6df0b4ecf535b021604efc1cfd723d Mon Sep 17 00:00:00 2001 From: Yakun Xu Date: Tue, 15 Jan 2019 21:00:21 +0800 Subject: [PATCH] [coap] process CoAP header in message (#3419) This commit refines Coap::Header into Coap::Message to avoid declaring the big Coap::Header in stack which was causing problems in low-memory systems such as CC2538. A UDP reserves 56 bytes by default, which will not be used before an outbound message goes down to transport layer and after an inbound message is delievered to CoAP agent. To get better performance, this commit utilizes these reserved bytes of cache basic header of CoAP message including CoAP version, code, message ID and token. These cached data are parsed when CoAP agent receives a CoAP message and are dumped into the correct place of a CoAP Message before sending by lower layer. To make sure there is enough reserved bytes for an inbound message, This commit removes headers in UDP layer before delivering a ot::Message to handlers. --- Android.mk | 2 +- etc/visual-studio/libopenthread.vcxproj | 4 +- .../libopenthread.vcxproj.filters | 4 +- etc/visual-studio/libopenthread_k.vcxproj | 4 +- .../libopenthread_k.vcxproj.filters | 4 +- include/openthread/coap.h | 157 +++-- src/cli/cli.hpp | 4 +- src/cli/cli_coap.cpp | 73 ++- src/cli/cli_coap.hpp | 15 +- src/cli/cli_coap_secure.cpp | 101 ++-- src/cli/cli_coap_secure.hpp | 24 +- src/core/Makefile.am | 4 +- src/core/api/coap_api.cpp | 231 ++++---- src/core/api/coap_secure_api.cpp | 6 +- src/core/coap/coap.cpp | 239 ++++---- src/core/coap/coap.hpp | 66 +-- src/core/coap/coap_header.cpp | 541 ------------------ src/core/coap/coap_message.cpp | 459 +++++++++++++++ .../{coap_header.hpp => coap_message.hpp} | 235 +++++--- src/core/coap/coap_secure.cpp | 18 +- src/core/coap/coap_secure.hpp | 4 +- src/core/common/code_utils.hpp | 11 + src/core/common/message.hpp | 1 + src/core/meshcop/announce_begin_client.cpp | 17 +- src/core/meshcop/border_agent.cpp | 281 ++++----- src/core/meshcop/border_agent.hpp | 31 +- src/core/meshcop/commissioner.cpp | 186 +++--- src/core/meshcop/commissioner.hpp | 43 +- src/core/meshcop/dataset_manager.cpp | 94 ++- src/core/meshcop/dataset_manager.hpp | 42 +- src/core/meshcop/dataset_manager_ftd.cpp | 49 +- src/core/meshcop/energy_scan_client.cpp | 30 +- src/core/meshcop/energy_scan_client.hpp | 7 +- src/core/meshcop/joiner.cpp | 64 +-- src/core/meshcop/joiner.hpp | 17 +- src/core/meshcop/joiner_router.cpp | 51 +- src/core/meshcop/joiner_router.hpp | 17 +- src/core/meshcop/leader.cpp | 65 +-- src/core/meshcop/leader.hpp | 18 +- src/core/meshcop/meshcop.hpp | 4 +- src/core/meshcop/panid_query_client.cpp | 30 +- src/core/meshcop/panid_query_client.hpp | 7 +- src/core/net/udp6.cpp | 2 + src/core/thread/address_resolver.cpp | 79 +-- src/core/thread/address_resolver.hpp | 21 +- src/core/thread/announce_begin_server.cpp | 18 +- src/core/thread/announce_begin_server.hpp | 7 +- src/core/thread/energy_scan_server.cpp | 32 +- src/core/thread/energy_scan_server.hpp | 7 +- src/core/thread/mle_router.cpp | 76 +-- src/core/thread/mle_router_ftd.hpp | 24 +- src/core/thread/network_data.cpp | 19 +- src/core/thread/network_data_leader.cpp | 2 +- src/core/thread/network_data_leader_ftd.cpp | 74 +-- src/core/thread/network_data_leader_ftd.hpp | 25 +- src/core/thread/network_diagnostic.cpp | 135 ++--- src/core/thread/network_diagnostic.hpp | 34 +- src/core/thread/panid_query_server.cpp | 31 +- src/core/thread/panid_query_server.hpp | 7 +- src/core/thread/thread_netif.cpp | 2 +- src/core/thread/thread_netif.hpp | 2 +- 61 files changed, 1725 insertions(+), 2132 deletions(-) delete mode 100644 src/core/coap/coap_header.cpp create mode 100644 src/core/coap/coap_message.cpp rename src/core/coap/{coap_header.hpp => coap_message.hpp} (64%) diff --git a/Android.mk b/Android.mk index 528a1d97d..48e708302 100644 --- a/Android.mk +++ b/Android.mk @@ -109,7 +109,7 @@ LOCAL_SRC_FILES := \ src/core/api/thread_ftd_api.cpp \ src/core/api/udp_api.cpp \ src/core/coap/coap.cpp \ - src/core/coap/coap_header.cpp \ + src/core/coap/coap_message.cpp \ src/core/coap/coap_secure.cpp \ src/core/common/crc16.cpp \ src/core/common/instance.cpp \ diff --git a/etc/visual-studio/libopenthread.vcxproj b/etc/visual-studio/libopenthread.vcxproj index b6723fa52..03c08a266 100644 --- a/etc/visual-studio/libopenthread.vcxproj +++ b/etc/visual-studio/libopenthread.vcxproj @@ -75,7 +75,7 @@ - + @@ -163,7 +163,7 @@ - + diff --git a/etc/visual-studio/libopenthread.vcxproj.filters b/etc/visual-studio/libopenthread.vcxproj.filters index 578559e0d..85352d9f6 100644 --- a/etc/visual-studio/libopenthread.vcxproj.filters +++ b/etc/visual-studio/libopenthread.vcxproj.filters @@ -126,7 +126,7 @@ Source Files\coap - + Source Files\coap @@ -380,7 +380,7 @@ Header Files\coap - + Header Files\coap diff --git a/etc/visual-studio/libopenthread_k.vcxproj b/etc/visual-studio/libopenthread_k.vcxproj index 18e7a31d8..3581df3a0 100644 --- a/etc/visual-studio/libopenthread_k.vcxproj +++ b/etc/visual-studio/libopenthread_k.vcxproj @@ -84,7 +84,7 @@ - + @@ -192,7 +192,7 @@ - + diff --git a/etc/visual-studio/libopenthread_k.vcxproj.filters b/etc/visual-studio/libopenthread_k.vcxproj.filters index 18de14e4f..442501cb6 100644 --- a/etc/visual-studio/libopenthread_k.vcxproj.filters +++ b/etc/visual-studio/libopenthread_k.vcxproj.filters @@ -123,7 +123,7 @@ Source Files\coap - + Source Files\coap @@ -374,7 +374,7 @@ Header Files\coap - + Header Files\coap diff --git a/include/openthread/coap.h b/include/openthread/coap.h index e9b2fa9ef..1ed780a02 100644 --- a/include/openthread/coap.h +++ b/include/openthread/coap.h @@ -146,9 +146,8 @@ typedef enum otCoapOptionType */ typedef struct otCoapOption { - uint16_t mNumber; ///< Option Number - uint16_t mLength; ///< Option Length - const uint8_t *mValue; ///< A pointer to the Option Value + uint16_t mNumber; ///< Option Number + uint16_t mLength; ///< Option Length } otCoapOption; /** @@ -294,36 +293,10 @@ typedef enum otCoapOptionContentFormat OT_COAP_OPTION_CONTENT_FORMAT_SENSML_XML = 311 } otCoapOptionContentFormat; -#define OT_COAP_HEADER_MAX_LENGTH 512 ///< Max CoAP header length (bytes) - -/** - * This structure represents a CoAP header. - * - */ -typedef struct otCoapHeader -{ - union - { - struct - { - uint8_t mVersionTypeToken; ///< The CoAP Version, Type, and Token Length - uint8_t mCode; ///< The CoAP Code - uint16_t mMessageId; ///< The CoAP Message ID - } mFields; ///< Structure representing a CoAP base header - uint8_t mBytes[OT_COAP_HEADER_MAX_LENGTH]; ///< The raw byte encoding for the CoAP header - } mHeader; ///< The CoAP header encoding - uint16_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; - /** * This function pointer is called when a CoAP response is received or on the request timeout. * * @param[in] aContext A pointer to application-specific context. - * @param[in] aHeader A pointer to the received CoAP header. NULL if no response was received. * @param[in] aMessage A pointer to the message buffer containing the response. NULL if no response was received. * @param[in] aMessageInfo A pointer to the message info for @p aMessage. NULL if no response was received. * @param[in] aResult A result of the CoAP transaction. @@ -334,7 +307,6 @@ typedef struct otCoapHeader * */ typedef void (*otCoapResponseHandler)(void * aContext, - otCoapHeader * aHeader, otMessage * aMessage, const otMessageInfo *aMessageInfo, otError aResult); @@ -343,15 +315,11 @@ typedef void (*otCoapResponseHandler)(void * aContext, * This function pointer is called when a CoAP request with a given Uri-Path is received. * * @param[in] aContext A pointer to arbitrary context information. - * @param[in] aHeader A pointer to the CoAP header. * @param[in] aMessage A pointer to the message. * @param[in] aMessageInfo A pointer to the message info for @p aMessage. * */ -typedef void (*otCoapRequestHandler)(void * aContext, - otCoapHeader * aHeader, - otMessage * aMessage, - const otMessageInfo *aMessageInfo); +typedef void (*otCoapRequestHandler)(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); /** * This structure represents a CoAP resource. @@ -368,43 +336,43 @@ typedef struct otCoapResource /** * This function initializes the CoAP header. * - * @param[inout] aHeader A pointer to the CoAP header to initialize. - * @param[in] aType CoAP message type. - * @param[in] aCode CoAP message code. + * @param[inout] aMessage A pointer to the CoAP message to initialize. + * @param[in] aType CoAP message type. + * @param[in] aCode CoAP message code. * */ -void otCoapHeaderInit(otCoapHeader *aHeader, otCoapType aType, otCoapCode aCode); +void otCoapMessageInit(otMessage *aMessage, otCoapType aType, otCoapCode aCode); /** * This function sets the Token value and length in a header. * - * @param[inout] aHeader A pointer to the CoAP header. - * @param[in] aToken A pointer to the Token value. - * @param[in] aTokenLength The Length of @p aToken. + * @param[inout] aMessage A pointer to the CoAP message. + * @param[in] aToken A pointer to the Token value. + * @param[in] aTokenLength The Length of @p aToken. * */ -void otCoapHeaderSetToken(otCoapHeader *aHeader, const uint8_t *aToken, uint8_t aTokenLength); +void otCoapMessageSetToken(otMessage *aMessage, const uint8_t *aToken, uint8_t aTokenLength); /** * This function sets the Token length and randomizes its value. * - * @param[inout] aHeader A pointer to the CoAP header. + * @param[inout] aMessage A pointer to the CoAP message. * @param[in] aTokenLength The Length of a Token to set. * */ -void otCoapHeaderGenerateToken(otCoapHeader *aHeader, uint8_t aTokenLength); +void otCoapMessageGenerateToken(otMessage *aMessage, uint8_t aTokenLength); /** * This function appends the Content Format CoAP option as specified in * https://tools.ietf.org/html/rfc7252#page-92. This *must* be called before - * setting otCoapHeaderSetPayloadMarker if a payload is to be included in the + * setting otCoapMessageSetPayloadMarker if a payload is to be included in the * message. * - * The function is a convenience wrapper around otCoapHeaderAppendUintOption, + * The function is a convenience wrapper around otCoapMessageAppendUintOption, * and if the desired format type code isn't listed in otCoapOptionContentFormat, * this base function should be used instead. * - * @param[inout] aHeader A pointer to the CoAP header. + * @param[inout] aMessage A pointer to the CoAP message. * @param[in] aContentFormat One of the content formats listed in * otCoapOptionContentFormat above. * @@ -413,26 +381,28 @@ void otCoapHeaderGenerateToken(otCoapHeader *aHeader, uint8_t aTokenLength); * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size. * */ -otError otCoapHeaderAppendContentFormatOption(otCoapHeader *aHeader, otCoapOptionContentFormat aContentFormat); +otError otCoapMessageAppendContentFormatOption(otMessage *aMessage, otCoapOptionContentFormat aContentFormat); /** * This function appends a CoAP option in a header. * - * @param[inout] aHeader A pointer to the CoAP header. - * @param[in] aOption A pointer to the CoAP option. + * @param[inout] aMessage A pointer to the CoAP message. + * @param[in] aNumber The CoAP Option number. + * @param[in] aLength The CoAP Option length. + * @param[in] aValue A pointer to the CoAP value. * * @retval OT_ERROR_NONE Successfully appended the option. * @retval OT_ERROR_INVALID_ARGS The option type is not equal or greater than the last option type. * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size. * */ -otError otCoapHeaderAppendOption(otCoapHeader *aHeader, const otCoapOption *aOption); +otError otCoapMessageAppendOption(otMessage *aMessage, uint16_t aNumber, uint16_t aLength, const void *aValue); /** * This function appends an unsigned integer CoAP option as specified in * https://tools.ietf.org/html/rfc7252#section-3.2 * - * @param[inout] aHeader A pointer to the CoAP header. + * @param[inout] aMessage A pointer to the CoAP message. * @param[in] aNumber The CoAP Option number. * @param[in] aValue The CoAP Option unsigned integer value. * @@ -441,12 +411,12 @@ otError otCoapHeaderAppendOption(otCoapHeader *aHeader, const otCoapOption *aOpt * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size. * */ -otError otCoapHeaderAppendUintOption(otCoapHeader *aHeader, uint16_t aNumber, uint32_t aValue); +otError otCoapMessageAppendUintOption(otMessage *aMessage, uint16_t aNumber, uint32_t aValue); /** * This function appends an Observe option. * - * @param[inout] aHeader A pointer to the CoAP header. + * @param[inout] aMessage A pointer to the CoAP message. * @param[in] aObserve Observe field value. * * @retval OT_ERROR_NONE Successfully appended the option. @@ -454,12 +424,12 @@ otError otCoapHeaderAppendUintOption(otCoapHeader *aHeader, uint16_t aNumber, ui * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size. * */ -otError otCoapHeaderAppendObserveOption(otCoapHeader *aHeader, uint32_t aObserve); +otError otCoapMessageAppendObserveOption(otMessage *aMessage, uint32_t aObserve); /** * This function appends a Uri-Path option. * - * @param[inout] aHeader A pointer to the CoAP header. + * @param[inout] aMessage A pointer to the CoAP message. * @param[in] aUriPath A pointer to a NULL-terminated string. * * @retval OT_ERROR_NONE Successfully appended the option. @@ -467,12 +437,12 @@ otError otCoapHeaderAppendObserveOption(otCoapHeader *aHeader, uint32_t aObserve * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size. * */ -otError otCoapHeaderAppendUriPathOptions(otCoapHeader *aHeader, const char *aUriPath); +otError otCoapMessageAppendUriPathOptions(otMessage *aMessage, const char *aUriPath); /** * This function appends a Proxy-Uri option. * - * @param[inout] aHeader A pointer to the CoAP header. + * @param[inout] aMessage A pointer to the CoAP message. * @param[in] aUriPath A pointer to a NULL-terminated string. * * @retval OT_ERROR_NONE Successfully appended the option. @@ -480,12 +450,12 @@ otError otCoapHeaderAppendUriPathOptions(otCoapHeader *aHeader, const char *aUri * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size. * */ -otError otCoapHeaderAppendProxyUriOption(otCoapHeader *aHeader, const char *aUriPath); +otError otCoapMessageAppendProxyUriOption(otMessage *aMessage, const char *aUriPath); /** * This function appends a Max-Age option. * - * @param[inout] aHeader A pointer to the CoAP header. + * @param[inout] aMessage A pointer to the CoAP message. * @param[in] aMaxAge The Max-Age value. * * @retval OT_ERROR_NONE Successfully appended the option. @@ -493,134 +463,145 @@ otError otCoapHeaderAppendProxyUriOption(otCoapHeader *aHeader, const char *aUri * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size. * */ -otError otCoapHeaderAppendMaxAgeOption(otCoapHeader *aHeader, uint32_t aMaxAge); +otError otCoapMessageAppendMaxAgeOption(otMessage *aMessage, uint32_t aMaxAge); /** * This function appends a single Uri-Query option. * - * @param[inout] aHeader A pointer to the CoAP header. + * @param[inout] aMessage A pointer to the CoAP message. * @param[in] aUriQuery A pointer to NULL-terminated string, which should contain a single key=value pair. * * @retval OT_ERROR_NONE Successfully appended the option. * @retval OT_ERROR_INVALID_ARGS The option type is not equal or greater than the last option type. * @retval OT_ERROR_NO_BUFS The option length exceeds the buffer size. */ -otError otCoapHeaderAppendUriQueryOption(otCoapHeader *aHeader, const char *aUriQuery); +otError otCoapMessageAppendUriQueryOption(otMessage *aMessage, const char *aUriQuery); /** * This function adds Payload Marker indicating beginning of the payload to the CoAP header. * - * @param[inout] aHeader A pointer to the CoAP header. + * @param[inout] aMessage A pointer to the CoAP message. * * @retval OT_ERROR_NONE Payload Marker successfully added. * @retval OT_ERROR_NO_BUFS Header Payload Marker exceeds the buffer size. * */ -otError otCoapHeaderSetPayloadMarker(otCoapHeader *aHeader); +otError otCoapMessageSetPayloadMarker(otMessage *aMessage); /** * This function sets the Message ID value. * - * @param[in] aHeader A pointer to the CoAP header. - * @param[in] aMessageId The Message ID value. + * @param[in] aMessage A pointer to the CoAP message. + * @param[in] aMessageId The Message ID value. * */ -void otCoapHeaderSetMessageId(otCoapHeader *aHeader, uint16_t aMessageId); +void otCoapMessageSetMessageId(otMessage *aMessage, uint16_t aMessageId); /** * This function returns the Type value. * - * @param[in] aHeader A pointer to the CoAP header. + * @param[in] aMessage A pointer to the CoAP message. * * @returns The Type value. * */ -otCoapType otCoapHeaderGetType(const otCoapHeader *aHeader); +otCoapType otCoapMessageGetType(const otMessage *aMessage); /** * This function returns the Code value. * - * @param[in] aHeader A pointer to the CoAP header. + * @param[in] aMessage A pointer to the CoAP message. * * @returns The Code value. * */ -otCoapCode otCoapHeaderGetCode(const otCoapHeader *aHeader); +otCoapCode otCoapMessageGetCode(const otMessage *aMessage); /** * This method returns the CoAP Code as human readable string. * - * @param[in] aHeader A pointer to the CoAP header. + * @param[in] aMessage A pointer to the CoAP message. * * @ returns The CoAP Code as string. * */ -const char *otCoapHeaderCodeToString(const otCoapHeader *aHeader); +const char *otCoapMessageCodeToString(const otMessage *aMessage); /** * This function returns the Message ID value. * - * @param[in] aHeader A pointer to the CoAP header. + * @param[in] aMessage A pointer to the CoAP message. * * @returns The Message ID value. * */ -uint16_t otCoapHeaderGetMessageId(const otCoapHeader *aHeader); +uint16_t otCoapMessageGetMessageId(const otMessage *aMessage); /** * This function returns the Token length. * - * @param[in] aHeader A pointer to the CoAP header. + * @param[in] aMessage A pointer to the CoAP message. * * @returns The Token length. * */ -uint8_t otCoapHeaderGetTokenLength(const otCoapHeader *aHeader); +uint8_t otCoapMessageGetTokenLength(const otMessage *aMessage); /** * This function returns a pointer to the Token value. * - * @param[in] aHeader A pointer to the CoAP header. + * @param[in] aMessage A pointer to the CoAP message. * * @returns A pointer to the Token value. * */ -const uint8_t *otCoapHeaderGetToken(const otCoapHeader *aHeader); +const uint8_t *otCoapMessageGetToken(const otMessage *aMessage); /** * This function returns a pointer to the first option. * - * @param[in] aHeader A pointer to the CoAP header. + * @param[in] aMessage A pointer to the CoAP message. * * @returns A pointer to the first option. If no option is present NULL pointer is returned. * */ -const otCoapOption *otCoapHeaderGetFirstOption(otCoapHeader *aHeader); +const otCoapOption *otCoapMessageGetFirstOption(otMessage *aMessage); /** * This function returns a pointer to the next option. * - * @param[in] aHeader A pointer to the CoAP header. + * @param[in] aMessage A pointer to the CoAP message. * * @returns A pointer to the next option. If no more options are present NULL pointer is returned. * */ -const otCoapOption *otCoapHeaderGetNextOption(otCoapHeader *aHeader); +const otCoapOption *otCoapMessageGetNextOption(otMessage *aMessage); /** - * This function creates a new message with a CoAP header. + * This function fills current option value into @p aValue. + * + * @param[in] aMessage A pointer to the CoAP message. + * @param[out] aValue A pointer to a buffer to receive the option value. + * + * @retval OT_ERROR_NONE Successfully filled value. + * @retval OT_ERROR_NOT_FOUND No current option. + * + */ +otError otCoapMessageGetOptionValue(otMessage *aMessage, void *aValue); + +/** + * This function creates a new CoAP message. * * @note If @p aSettings is 'NULL', the link layer security is enabled and the message priority is set to * OT_MESSAGE_PRIORITY_NORMAL by default. * * @param[in] aInstance A pointer to an OpenThread instance. - * @param[in] aHeader A pointer to a CoAP header that is used to create the message. * @param[in] aSettings A pointer to the message settings or NULL to set default settings. * * @returns A pointer to the message buffer or NULL if no message buffers are available or parameters are invalid. * */ -otMessage *otCoapNewMessage(otInstance *aInstance, const otCoapHeader *aHeader, const otMessageSettings *aSettings); +otMessage *otCoapNewMessage(otInstance *aInstance, const otMessageSettings *aSettings); /** * This function sends a CoAP request. diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 7122f9d52..efafa621d 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -46,12 +46,12 @@ #include "cli/cli_udp_example.hpp" #if OPENTHREAD_ENABLE_APPLICATION_COAP -#include +#include #include "cli/cli_coap.hpp" #endif #if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE -#include +#include #include "cli/cli_coap_secure.hpp" #endif diff --git a/src/cli/cli_coap.cpp b/src/cli/cli_coap.cpp index ba6398310..d992da8a8 100644 --- a/src/cli/cli_coap.cpp +++ b/src/cli/cli_coap.cpp @@ -38,7 +38,7 @@ #include #include "cli/cli.hpp" -#include "coap/coap_header.hpp" +#include "coap/coap_message.hpp" namespace ot { namespace Cli { @@ -115,21 +115,17 @@ exit: return error; } -void OTCALL Coap::HandleServerResponse(void * aContext, - otCoapHeader * aHeader, - otMessage * aMessage, - const otMessageInfo *aMessageInfo) +void OTCALL Coap::HandleServerResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo) { - static_cast(aContext)->HandleServerResponse(aHeader, aMessage, aMessageInfo); + static_cast(aContext)->HandleServerResponse(aMessage, aMessageInfo); } -void Coap::HandleServerResponse(otCoapHeader *aHeader, otMessage *aMessage, const otMessageInfo *aMessageInfo) +void Coap::HandleServerResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo) { - otError error = OT_ERROR_NONE; - otCoapHeader responseHeader; - otMessage * responseMessage = NULL; - otCoapCode responseCode = OT_COAP_CODE_EMPTY; - char responseContent = '0'; + otError error = OT_ERROR_NONE; + otMessage *responseMessage = NULL; + otCoapCode responseCode = OT_COAP_CODE_EMPTY; + char responseContent = '0'; mInterpreter.mServer->OutputFormat( "Received coap request from [%x:%x:%x:%x:%x:%x:%x:%x]: ", HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[0]), @@ -138,7 +134,7 @@ void Coap::HandleServerResponse(otCoapHeader *aHeader, otMessage *aMessage, cons HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[5]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[6]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[7])); - switch (otCoapHeaderGetCode(aHeader)) + switch (otCoapMessageGetCode(aMessage)) { case OT_COAP_CODE_GET: mInterpreter.mServer->OutputFormat("GET"); @@ -163,9 +159,10 @@ void Coap::HandleServerResponse(otCoapHeader *aHeader, otMessage *aMessage, cons PrintPayload(aMessage); - if ((otCoapHeaderGetType(aHeader) == OT_COAP_TYPE_CONFIRMABLE) || otCoapHeaderGetCode(aHeader) == OT_COAP_CODE_GET) + if (otCoapMessageGetType(aMessage) == OT_COAP_TYPE_CONFIRMABLE || + otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET) { - if (otCoapHeaderGetCode(aHeader) == OT_COAP_CODE_GET) + if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET) { responseCode = OT_COAP_CODE_CONTENT; } @@ -174,19 +171,19 @@ void Coap::HandleServerResponse(otCoapHeader *aHeader, otMessage *aMessage, cons responseCode = OT_COAP_CODE_VALID; } - otCoapHeaderInit(&responseHeader, OT_COAP_TYPE_ACKNOWLEDGMENT, responseCode); - otCoapHeaderSetMessageId(&responseHeader, otCoapHeaderGetMessageId(aHeader)); - otCoapHeaderSetToken(&responseHeader, otCoapHeaderGetToken(aHeader), otCoapHeaderGetTokenLength(aHeader)); - - if (otCoapHeaderGetCode(aHeader) == OT_COAP_CODE_GET) - { - otCoapHeaderSetPayloadMarker(&responseHeader); - } - - responseMessage = otCoapNewMessage(mInterpreter.mInstance, &responseHeader, NULL); + responseMessage = otCoapNewMessage(mInterpreter.mInstance, NULL); VerifyOrExit(responseMessage != NULL, error = OT_ERROR_NO_BUFS); - if (otCoapHeaderGetCode(aHeader) == OT_COAP_CODE_GET) + otCoapMessageInit(responseMessage, OT_COAP_TYPE_ACKNOWLEDGMENT, responseCode); + otCoapMessageSetMessageId(responseMessage, otCoapMessageGetMessageId(aMessage)); + otCoapMessageSetToken(responseMessage, otCoapMessageGetToken(aMessage), otCoapMessageGetTokenLength(aMessage)); + + if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET) + { + otCoapMessageSetPayloadMarker(responseMessage); + } + + if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET) { SuccessOrExit(error = otMessageAppend(responseMessage, &responseContent, sizeof(responseContent))); } @@ -216,7 +213,6 @@ otError Coap::ProcessRequest(int argc, char *argv[]) otError error = OT_ERROR_NONE; otMessage * message = NULL; otMessageInfo messageInfo; - otCoapHeader header; uint16_t payloadLength = 0; // Default parameters @@ -278,9 +274,12 @@ otError Coap::ProcessRequest(int argc, char *argv[]) } } - otCoapHeaderInit(&header, coapType, coapCode); - otCoapHeaderGenerateToken(&header, ot::Coap::Header::kDefaultTokenLength); - SuccessOrExit(error = otCoapHeaderAppendUriPathOptions(&header, coapUri)); + message = otCoapNewMessage(mInterpreter.mInstance, NULL); + VerifyOrExit(message != NULL, error = OT_ERROR_NO_BUFS); + + otCoapMessageInit(message, coapType, coapCode); + otCoapMessageGenerateToken(message, ot::Coap::Message::kDefaultTokenLength); + SuccessOrExit(error = otCoapMessageAppendUriPathOptions(message, coapUri)); if (argc > 4) { @@ -288,13 +287,10 @@ otError Coap::ProcessRequest(int argc, char *argv[]) if (payloadLength > 0) { - otCoapHeaderSetPayloadMarker(&header); + otCoapMessageSetPayloadMarker(message); } } - message = otCoapNewMessage(mInterpreter.mInstance, &header, NULL); - VerifyOrExit(message != NULL, error = OT_ERROR_NO_BUFS); - // Embed content into message if given if (payloadLength > 0) { @@ -328,20 +324,15 @@ exit: } void OTCALL Coap::HandleClientResponse(void * aContext, - otCoapHeader * aHeader, otMessage * aMessage, const otMessageInfo *aMessageInfo, otError aError) { - static_cast(aContext)->HandleClientResponse(aHeader, aMessage, aMessageInfo, aError); + static_cast(aContext)->HandleClientResponse(aMessage, aMessageInfo, aError); } -void Coap::HandleClientResponse(otCoapHeader * aHeader, - otMessage * aMessage, - const otMessageInfo *aMessageInfo, - otError aError) +void Coap::HandleClientResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError) { - OT_UNUSED_VARIABLE(aHeader); OT_UNUSED_VARIABLE(aMessageInfo); if (aError != OT_ERROR_NONE) diff --git a/src/cli/cli_coap.hpp b/src/cli/cli_coap.hpp index 5b1ea75fc..89e281c81 100644 --- a/src/cli/cli_coap.hpp +++ b/src/cli/cli_coap.hpp @@ -38,7 +38,7 @@ #if OPENTHREAD_ENABLE_APPLICATION_COAP -#include "coap/coap_header.hpp" +#include "coap/coap_message.hpp" namespace ot { namespace Cli { @@ -80,21 +80,14 @@ private: otError ProcessRequest(int argc, char *argv[]); - static void OTCALL HandleServerResponse(void * aContext, - otCoapHeader * aHeader, - otMessage * aMessage, - const otMessageInfo *aMessageInfo); - void HandleServerResponse(otCoapHeader *aHeader, otMessage *aMessage, const otMessageInfo *aMessageInfo); + static void OTCALL HandleServerResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); + void HandleServerResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo); static void OTCALL HandleClientResponse(void * aContext, - otCoapHeader * aHeader, - otMessage * aMessage, - const otMessageInfo *aMessageInfo, - otError aError); - void HandleClientResponse(otCoapHeader * aHeader, otMessage * aMessage, const otMessageInfo *aMessageInfo, otError aError); + void HandleClientResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError); otCoapResource mResource; char mUriPath[kMaxUriLength]; diff --git a/src/cli/cli_coap_secure.cpp b/src/cli/cli_coap_secure.cpp index d90462546..277b8ee76 100644 --- a/src/cli/cli_coap_secure.cpp +++ b/src/cli/cli_coap_secure.cpp @@ -57,13 +57,13 @@ CoapSecure::CoapSecure(Interpreter &aInterpreter) memset(&mPskId, 0, sizeof(mPskId)); } -void CoapSecure::PrintHeaderInfos(otCoapHeader *aHeader) const +void CoapSecure::PrintHeaderInfos(otMessage *aMessage) const { otCoapCode mCoapCode; otCoapType mCoapType; - mCoapCode = otCoapHeaderGetCode(aHeader); - mCoapType = otCoapHeaderGetType(aHeader); + mCoapCode = otCoapMessageGetCode(aMessage); + mCoapType = otCoapMessageGetType(aMessage); mInterpreter.mServer->OutputFormat("\r\n CoapSecure RX Header Information:" "\r\n Type %d => ", @@ -87,7 +87,7 @@ void CoapSecure::PrintHeaderInfos(otCoapHeader *aHeader) const break; } mInterpreter.mServer->OutputFormat("\r\n Code %d => %s\r\n", static_cast(mCoapCode), - static_cast(otCoapHeaderCodeToString(aHeader))); + static_cast(otCoapMessageCodeToString(aMessage))); } void CoapSecure::PrintPayload(otMessage *aMessage) const @@ -348,21 +348,17 @@ void CoapSecure::HandleClientConnect(bool aConnected) } } -void OTCALL CoapSecure::HandleServerResponse(void * aContext, - otCoapHeader * aHeader, - otMessage * aMessage, - const otMessageInfo *aMessageInfo) +void OTCALL CoapSecure::HandleServerResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo) { - static_cast(aContext)->HandleServerResponse(aHeader, aMessage, aMessageInfo); + static_cast(aContext)->HandleServerResponse(aMessage, aMessageInfo); } -void CoapSecure::HandleServerResponse(otCoapHeader *aHeader, otMessage *aMessage, const otMessageInfo *aMessageInfo) +void CoapSecure::HandleServerResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo) { - otError error = OT_ERROR_NONE; - otCoapHeader responseHeader; - otMessage * responseMessage = NULL; - otCoapCode responseCode = OT_COAP_CODE_EMPTY; - char responseContent[] = "helloWorld"; + otError error = OT_ERROR_NONE; + otMessage *responseMessage = NULL; + otCoapCode responseCode = OT_COAP_CODE_EMPTY; + char responseContent[] = "helloWorld"; mInterpreter.mServer->OutputFormat( "Received coap secure request from [%x:%x:%x:%x:%x:%x:%x:%x]: ", @@ -371,7 +367,7 @@ void CoapSecure::HandleServerResponse(otCoapHeader *aHeader, otMessage *aMessage HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[4]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[5]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[6]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[7])); - switch (otCoapHeaderGetCode(aHeader)) + switch (otCoapMessageGetCode(aMessage)) { case OT_COAP_CODE_GET: mInterpreter.mServer->OutputFormat("GET"); @@ -396,9 +392,10 @@ void CoapSecure::HandleServerResponse(otCoapHeader *aHeader, otMessage *aMessage PrintPayload(aMessage); - if ((otCoapHeaderGetType(aHeader) == OT_COAP_TYPE_CONFIRMABLE) || otCoapHeaderGetCode(aHeader) == OT_COAP_CODE_GET) + if ((otCoapMessageGetType(aMessage) == OT_COAP_TYPE_CONFIRMABLE) || + (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET)) { - if (otCoapHeaderGetCode(aHeader) == OT_COAP_CODE_GET) + if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET) { responseCode = OT_COAP_CODE_CONTENT; } @@ -407,19 +404,19 @@ void CoapSecure::HandleServerResponse(otCoapHeader *aHeader, otMessage *aMessage responseCode = OT_COAP_CODE_VALID; } - otCoapHeaderInit(&responseHeader, OT_COAP_TYPE_ACKNOWLEDGMENT, responseCode); - otCoapHeaderSetMessageId(&responseHeader, otCoapHeaderGetMessageId(aHeader)); - otCoapHeaderSetToken(&responseHeader, otCoapHeaderGetToken(aHeader), otCoapHeaderGetTokenLength(aHeader)); - - if (otCoapHeaderGetCode(aHeader) == OT_COAP_CODE_GET) - { - otCoapHeaderSetPayloadMarker(&responseHeader); - } - - responseMessage = otCoapNewMessage(mInterpreter.mInstance, &responseHeader, NULL); + responseMessage = otCoapNewMessage(mInterpreter.mInstance, NULL); VerifyOrExit(responseMessage != NULL, error = OT_ERROR_NO_BUFS); - if (otCoapHeaderGetCode(aHeader) == OT_COAP_CODE_GET) + otCoapMessageInit(responseMessage, OT_COAP_TYPE_ACKNOWLEDGMENT, responseCode); + otCoapMessageSetMessageId(responseMessage, otCoapMessageGetMessageId(aMessage)); + otCoapMessageSetToken(responseMessage, otCoapMessageGetToken(aMessage), otCoapMessageGetTokenLength(aMessage)); + + if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET) + { + otCoapMessageSetPayloadMarker(responseMessage); + } + + if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET) { SuccessOrExit(error = otMessageAppend(responseMessage, &responseContent, sizeof(responseContent))); } @@ -446,7 +443,6 @@ otError CoapSecure::ProcessRequest(int argc, char *argv[]) otError error = OT_ERROR_NONE; otMessage * message = NULL; otMessageInfo messageInfo; - otCoapHeader header; uint16_t payloadLength = 0; uint8_t indexShifter = 0; @@ -516,9 +512,12 @@ otError CoapSecure::ProcessRequest(int argc, char *argv[]) } } - otCoapHeaderInit(&header, coapType, coapCode); - otCoapHeaderGenerateToken(&header, ot::Coap::Header::kDefaultTokenLength); - SuccessOrExit(error = otCoapHeaderAppendUriPathOptions(&header, coapUri)); + message = otCoapNewMessage(mInterpreter.mInstance, NULL); + VerifyOrExit(message != NULL, error = OT_ERROR_NO_BUFS); + + otCoapMessageInit(message, coapType, coapCode); + otCoapMessageGenerateToken(message, ot::Coap::Message::kDefaultTokenLength); + SuccessOrExit(error = otCoapMessageAppendUriPathOptions(message, coapUri)); if (argc > (4 - indexShifter)) { @@ -526,13 +525,10 @@ otError CoapSecure::ProcessRequest(int argc, char *argv[]) if (payloadLength > 0) { - otCoapHeaderSetPayloadMarker(&header); + otCoapMessageSetPayloadMarker(message); } } - message = otCoapNewMessage(mInterpreter.mInstance, &header, NULL); - VerifyOrExit(message != NULL, error = OT_ERROR_NO_BUFS); - // add payload if (payloadLength > 0) { @@ -566,20 +562,15 @@ exit: } void OTCALL CoapSecure::HandleClientResponse(void * aContext, - otCoapHeader * aHeader, otMessage * aMessage, const otMessageInfo *aMessageInfo, otError aError) { - static_cast(aContext)->HandleClientResponse(aHeader, aMessage, aMessageInfo, aError); + static_cast(aContext)->HandleClientResponse(aMessage, aMessageInfo, aError); } -void CoapSecure::HandleClientResponse(otCoapHeader * aHeader, - otMessage * aMessage, - const otMessageInfo *aMessageInfo, - otError aError) +void CoapSecure::HandleClientResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError) { - OT_UNUSED_VARIABLE(aHeader); OT_UNUSED_VARIABLE(aMessageInfo); if (aError != OT_ERROR_NONE) @@ -590,35 +581,35 @@ void CoapSecure::HandleClientResponse(otCoapHeader * aHeader, else { mInterpreter.mServer->OutputFormat("Received coap secure response"); - PrintHeaderInfos(aHeader); + PrintHeaderInfos(aMessage); PrintPayload(aMessage); } } #if CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER void OTCALL CoapSecure::DefaultHandle(void * aContext, - otCoapHeader * aHeader, + otCoapMessage * aHeader, otMessage * aMessage, const otMessageInfo *aMessageInfo) { static_cast(aContext)->DefaultHandle(aHeader, aMessage, aMessageInfo); } -void CoapSecure::DefaultHandle(otCoapHeader *aHeader, otMessage *aMessage, const otMessageInfo *aMessageInfo) +void CoapSecure::DefaultHandle(otCoapMessage *aHeader, otMessage *aMessage, const otMessageInfo *aMessageInfo) { OT_UNUSED_VARIABLE(aMessage); - otError error = OT_ERROR_NONE; - otCoapHeader responseHeader; - otMessage * responseMessage; + otError error = OT_ERROR_NONE; + otCoapMessage responseHeader; + otMessage * responseMessage; - if (otCoapHeaderGetType(aHeader) == OT_COAP_TYPE_CONFIRMABLE || otCoapHeaderGetCode(aHeader) == OT_COAP_CODE_GET) + if (otCoapMessageGetType(aHeader) == OT_COAP_TYPE_CONFIRMABLE || otCoapMessageGetCode(aHeader) == OT_COAP_CODE_GET) { - otCoapHeaderInit(&responseHeader, OT_COAP_TYPE_NON_CONFIRMABLE, OT_COAP_CODE_NOT_FOUND); - otCoapHeaderSetMessageId(&responseHeader, otCoapHeaderGetMessageId(aHeader)); - otCoapHeaderSetToken(&responseHeader, otCoapHeaderGetToken(aHeader), otCoapHeaderGetTokenLength(aHeader)); + otCoapMessageInit(&responseHeader, OT_COAP_TYPE_NON_CONFIRMABLE, OT_COAP_CODE_NOT_FOUND); + otCoapMessageSetMessageId(&responseHeader, otCoapMessageGetMessageId(aHeader)); + otCoapMessageSetToken(&responseHeader, otCoapMessageGetToken(aHeader), otCoapMessageGetTokenLength(aHeader)); - responseMessage = otCoapNewMessage(mInterpreter.mInstance, &responseHeader, NULL); + responseMessage = otCoapNewMessage(mInterpreter.mInstance, NULL); VerifyOrExit(responseMessage != NULL, error = OT_ERROR_NO_BUFS); SuccessOrExit(error = otCoapSecureSendResponse(mInterpreter.mInstance, responseMessage, aMessageInfo)); } diff --git a/src/cli/cli_coap_secure.hpp b/src/cli/cli_coap_secure.hpp index da1f40354..083845d1e 100644 --- a/src/cli/cli_coap_secure.hpp +++ b/src/cli/cli_coap_secure.hpp @@ -38,7 +38,7 @@ #if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE -#include "coap/coap_header.hpp" +#include "coap/coap_message.hpp" #include "coap/coap_secure.hpp" /** @@ -84,7 +84,7 @@ private: kPskIdMaxLength = 32 }; - void PrintHeaderInfos(otCoapHeader *aHeader) const; + void PrintHeaderInfos(otMessage *aMessage) const; void PrintPayload(otMessage *aMessage) const; @@ -92,28 +92,18 @@ private: otError Stop(void); - static void OTCALL HandleServerResponse(void * aContext, - otCoapHeader * aHeader, - otMessage * aMessage, - const otMessageInfo *aMessageInfo); - void HandleServerResponse(otCoapHeader *aHeader, otMessage *aMessage, const otMessageInfo *aMessageInfo); + static void OTCALL HandleServerResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); + void HandleServerResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo); static void OTCALL HandleClientResponse(void * aContext, - otCoapHeader * aHeader, - otMessage * aMessage, - const otMessageInfo *aMessageInfo, - otError aError); - void HandleClientResponse(otCoapHeader * aHeader, otMessage * aMessage, const otMessageInfo *aMessageInfo, otError aError); + void HandleClientResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError); #if CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER - static void OTCALL DefaultHandle(void * aContext, - otCoapHeader * aHeader, - otMessage * aMessage, - const otMessageInfo *aMessageInfo); - void DefaultHandle(otCoapHeader *aHeader, otMessage *aMessage, const otMessageInfo *aMessageInfo); + static void OTCALL DefaultHandle(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); + void DefaultHandle(otMessage *aMessage, const otMessageInfo *aMessageInfo); #endif // CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER static void OTCALL HandleClientConnect(bool aConnected, void *aContext); diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 0f2ff4994..9115ec49e 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -132,7 +132,7 @@ SOURCES_COMMON = \ api/thread_ftd_api.cpp \ api/udp_api.cpp \ coap/coap.cpp \ - coap/coap_header.cpp \ + coap/coap_message.cpp \ coap/coap_secure.cpp \ common/crc16.cpp \ common/instance.cpp \ @@ -289,7 +289,7 @@ HEADERS_COMMON = \ openthread-core-config.h \ openthread-core-default-config.h \ coap/coap.hpp \ - coap/coap_header.hpp \ + coap/coap_message.hpp \ coap/coap_secure.hpp \ common/code_utils.hpp \ common/crc16.hpp \ diff --git a/src/core/api/coap_api.cpp b/src/core/api/coap_api.cpp index 28d97d350..46b5bcc27 100644 --- a/src/core/api/coap_api.cpp +++ b/src/core/api/coap_api.cpp @@ -35,137 +35,139 @@ #include -#include "coap/coap_header.hpp" +#include "coap/coap_message.hpp" #include "common/instance.hpp" #if OPENTHREAD_ENABLE_APPLICATION_COAP using namespace ot; -void otCoapHeaderInit(otCoapHeader *aHeader, otCoapType aType, otCoapCode aCode) -{ - Coap::Header *header = static_cast(aHeader); - header->Init(aType, aCode); -} - -void otCoapHeaderSetToken(otCoapHeader *aHeader, const uint8_t *aToken, uint8_t aTokenLength) -{ - static_cast(aHeader)->SetToken(aToken, aTokenLength); -} - -void otCoapHeaderGenerateToken(otCoapHeader *aHeader, uint8_t aTokenLength) -{ - static_cast(aHeader)->SetToken(aTokenLength); -} - -otError otCoapHeaderAppendContentFormatOption(otCoapHeader *aHeader, otCoapOptionContentFormat aContentFormat) -{ - return static_cast(aHeader)->AppendContentFormatOption(aContentFormat); -} - -otError otCoapHeaderAppendOption(otCoapHeader *aHeader, const otCoapOption *aOption) -{ - return static_cast(aHeader)->AppendOption(*static_cast(aOption)); -} - -otError otCoapHeaderAppendUintOption(otCoapHeader *aHeader, uint16_t aNumber, uint32_t aValue) -{ - return static_cast(aHeader)->AppendUintOption(aNumber, aValue); -} - -otError otCoapHeaderAppendObserveOption(otCoapHeader *aHeader, uint32_t aObserve) -{ - return static_cast(aHeader)->AppendObserveOption(aObserve); -} - -otError otCoapHeaderAppendUriPathOptions(otCoapHeader *aHeader, const char *aUriPath) -{ - return static_cast(aHeader)->AppendUriPathOptions(aUriPath); -} - -otError otCoapHeaderAppendProxyUriOption(otCoapHeader *aHeader, const char *aUriPath) -{ - return static_cast(aHeader)->AppendProxyUriOption(aUriPath); -} - -otError otCoapHeaderAppendMaxAgeOption(otCoapHeader *aHeader, uint32_t aMaxAge) -{ - return static_cast(aHeader)->AppendMaxAgeOption(aMaxAge); -} - -otError otCoapHeaderAppendUriQueryOption(otCoapHeader *aHeader, const char *aUriQuery) -{ - return static_cast(aHeader)->AppendUriQueryOption(aUriQuery); -} - -otError otCoapHeaderSetPayloadMarker(otCoapHeader *aHeader) -{ - return static_cast(aHeader)->SetPayloadMarker(); -} - -void otCoapHeaderSetMessageId(otCoapHeader *aHeader, uint16_t aMessageId) -{ - return static_cast(aHeader)->SetMessageId(aMessageId); -} - -otCoapType otCoapHeaderGetType(const otCoapHeader *aHeader) -{ - return static_cast(aHeader)->GetType(); -} - -otCoapCode otCoapHeaderGetCode(const otCoapHeader *aHeader) -{ - return static_cast(aHeader)->GetCode(); -} - -const char *otCoapHeaderCodeToString(const otCoapHeader *aHeader) -{ - return static_cast(aHeader)->CodeToString(); -} - -uint16_t otCoapHeaderGetMessageId(const otCoapHeader *aHeader) -{ - return static_cast(aHeader)->GetMessageId(); -} - -uint8_t otCoapHeaderGetTokenLength(const otCoapHeader *aHeader) -{ - return static_cast(aHeader)->GetTokenLength(); -} - -const uint8_t *otCoapHeaderGetToken(const otCoapHeader *aHeader) -{ - return static_cast(aHeader)->GetToken(); -} - -const otCoapOption *otCoapHeaderGetFirstOption(otCoapHeader *aHeader) -{ - return static_cast(static_cast(aHeader)->GetFirstOption()); -} - -const otCoapOption *otCoapHeaderGetNextOption(otCoapHeader *aHeader) -{ - return static_cast(static_cast(aHeader)->GetNextOption()); -} - -otMessage *otCoapNewMessage(otInstance *aInstance, const otCoapHeader *aHeader, const otMessageSettings *aSettings) +otMessage *otCoapNewMessage(otInstance *aInstance, const otMessageSettings *aSettings) { Message * message; Instance &instance = *static_cast(aInstance); - VerifyOrExit(aHeader != NULL, message = NULL); - if (aSettings != NULL) { VerifyOrExit(aSettings->mPriority <= OT_MESSAGE_PRIORITY_HIGH, message = NULL); } - message = instance.GetApplicationCoap().NewMessage(*(static_cast(aHeader)), aSettings); + message = instance.GetApplicationCoap().NewMessage(aSettings); exit: return message; } +void otCoapMessageInit(otMessage *aMessage, otCoapType aType, otCoapCode aCode) +{ + static_cast(aMessage)->Init(aType, aCode); +} + +void otCoapMessageSetToken(otMessage *aMessage, const uint8_t *aToken, uint8_t aTokenLength) +{ + static_cast(aMessage)->SetToken(aToken, aTokenLength); +} + +void otCoapMessageGenerateToken(otMessage *aMessage, uint8_t aTokenLength) +{ + static_cast(aMessage)->SetToken(aTokenLength); +} + +otError otCoapMessageAppendContentFormatOption(otMessage *aMessage, otCoapOptionContentFormat aContentFormat) +{ + return static_cast(aMessage)->AppendContentFormatOption(aContentFormat); +} + +otError otCoapMessageAppendOption(otMessage *aMessage, uint16_t aNumber, uint16_t aLength, const void *aValue) +{ + return static_cast(aMessage)->AppendOption(aNumber, aLength, aValue); +} + +otError otCoapMessageAppendUintOption(otMessage *aMessage, uint16_t aNumber, uint32_t aValue) +{ + return static_cast(aMessage)->AppendUintOption(aNumber, aValue); +} + +otError otCoapMessageAppendObserveOption(otMessage *aMessage, uint32_t aObserve) +{ + return static_cast(aMessage)->AppendObserveOption(aObserve); +} + +otError otCoapMessageAppendUriPathOptions(otMessage *aMessage, const char *aUriPath) +{ + return static_cast(aMessage)->AppendUriPathOptions(aUriPath); +} + +otError otCoapMessageAppendProxyUriOption(otMessage *aMessage, const char *aUriPath) +{ + return static_cast(aMessage)->AppendProxyUriOption(aUriPath); +} + +otError otCoapMessageAppendMaxAgeOption(otMessage *aMessage, uint32_t aMaxAge) +{ + return static_cast(aMessage)->AppendMaxAgeOption(aMaxAge); +} + +otError otCoapMessageAppendUriQueryOption(otMessage *aMessage, const char *aUriQuery) +{ + return static_cast(aMessage)->AppendUriQueryOption(aUriQuery); +} + +otError otCoapMessageSetPayloadMarker(otMessage *aMessage) +{ + return static_cast(aMessage)->SetPayloadMarker(); +} + +void otCoapMessageSetMessageId(otMessage *aMessage, uint16_t aMessageId) +{ + return static_cast(aMessage)->SetMessageId(aMessageId); +} + +otCoapType otCoapMessageGetType(const otMessage *aMessage) +{ + return static_cast(aMessage)->GetType(); +} + +otCoapCode otCoapMessageGetCode(const otMessage *aMessage) +{ + return static_cast(aMessage)->GetCode(); +} + +const char *otCoapMessageCodeToString(const otMessage *aMessage) +{ + return static_cast(aMessage)->CodeToString(); +} + +uint16_t otCoapMessageGetMessageId(const otMessage *aMessage) +{ + return static_cast(aMessage)->GetMessageId(); +} + +uint8_t otCoapMessageGetTokenLength(const otMessage *aMessage) +{ + return static_cast(aMessage)->GetTokenLength(); +} + +const uint8_t *otCoapMessageGetToken(const otMessage *aMessage) +{ + return static_cast(aMessage)->GetToken(); +} + +const otCoapOption *otCoapMessageGetFirstOption(otMessage *aMessage) +{ + return static_cast(aMessage)->GetFirstOption(); +} + +const otCoapOption *otCoapMessageGetNextOption(otMessage *aMessage) +{ + return static_cast(aMessage)->GetNextOption(); +} + +otError otCoapMessageGetOptionValue(otMessage *aMessage, void *aValue) +{ + return static_cast(aMessage)->GetOptionValue(aValue); +} + otError otCoapSendRequest(otInstance * aInstance, otMessage * aMessage, const otMessageInfo * aMessageInfo, @@ -174,8 +176,9 @@ otError otCoapSendRequest(otInstance * aInstance, { Instance &instance = *static_cast(aInstance); - return instance.GetApplicationCoap().SendMessage( - *static_cast(aMessage), *static_cast(aMessageInfo), aHandler, aContext); + return instance.GetApplicationCoap().SendMessage(*static_cast(aMessage), + *static_cast(aMessageInfo), aHandler, + aContext); } otError otCoapStart(otInstance *aInstance, uint16_t aPort) @@ -217,7 +220,7 @@ otError otCoapSendResponse(otInstance *aInstance, otMessage *aMessage, const otM { Instance &instance = *static_cast(aInstance); - return instance.GetApplicationCoap().SendMessage(*static_cast(aMessage), + return instance.GetApplicationCoap().SendMessage(*static_cast(aMessage), *static_cast(aMessageInfo)); } diff --git a/src/core/api/coap_secure_api.cpp b/src/core/api/coap_secure_api.cpp index 0200c76a8..092a18d0c 100644 --- a/src/core/api/coap_secure_api.cpp +++ b/src/core/api/coap_secure_api.cpp @@ -36,7 +36,7 @@ #include #include -#include "coap/coap_header.hpp" +#include "coap/coap_message.hpp" #include "coap/coap_secure.hpp" #include "common/instance.hpp" @@ -198,7 +198,7 @@ otError otCoapSecureSendRequest(otInstance * aInstance, { Instance &instance = *static_cast(aInstance); - return instance.GetApplicationCoapSecure().SendMessage(*static_cast(aMessage), aHandler, aContext); + return instance.GetApplicationCoapSecure().SendMessage(*static_cast(aMessage), aHandler, aContext); } otError otCoapSecureAddResource(otInstance *aInstance, otCoapResource *aResource) @@ -235,7 +235,7 @@ otError otCoapSecureSendResponse(otInstance *aInstance, otMessage *aMessage, con { Instance &instance = *static_cast(aInstance); - return instance.GetApplicationCoapSecure().SendMessage(*static_cast(aMessage), + return instance.GetApplicationCoapSecure().SendMessage(*static_cast(aMessage), *static_cast(aMessageInfo)); } diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp index aa1855584..57da1d45c 100644 --- a/src/core/coap/coap.cpp +++ b/src/core/coap/coap.cpp @@ -77,7 +77,7 @@ exit: otError Coap::Stop(void) { - Message * message = mPendingRequests.GetHead(); + Message * message = static_cast(mPendingRequests.GetHead()); Message * messageToRemove; CoapMetadata coapMetadata; @@ -85,10 +85,10 @@ otError Coap::Stop(void) while (message != NULL) { messageToRemove = message; - message = message->GetNext(); + message = static_cast(message->GetNext()); coapMetadata.ReadFrom(*messageToRemove); - FinalizeCoapTransaction(*messageToRemove, coapMetadata, NULL, NULL, NULL, OT_ERROR_ABORT); + FinalizeCoapTransaction(*messageToRemove, coapMetadata, NULL, NULL, OT_ERROR_ABORT); } mResponsesQueue.DequeueAllResponses(); @@ -140,15 +140,11 @@ void Coap::SetDefaultHandler(otCoapRequestHandler aHandler, void *aContext) mDefaultHandlerContext = aContext; } -Message *Coap::NewMessage(const Header &aHeader, const otMessageSettings *aSettings) +Message *Coap::NewMessage(const otMessageSettings *aSettings) { Message *message = NULL; - // Ensure that header has minimum required length. - VerifyOrExit(aHeader.GetLength() >= Header::kMinHeaderLength); - - VerifyOrExit((message = mSocket.NewMessage(aHeader.GetLength(), aSettings)) != NULL); - message->Prepend(aHeader.GetBytes(), aHeader.GetLength()); + VerifyOrExit((message = static_cast(mSocket.NewMessage(0, aSettings))) != NULL); message->SetOffset(0); exit: @@ -161,41 +157,39 @@ otError Coap::SendMessage(Message & aMessage, void * aContext) { otError error; - Header header; CoapMetadata coapMetadata; Message * storedCopy = NULL; uint16_t copyLength = 0; - SuccessOrExit(error = header.FromMessage(aMessage, 0)); - - if ((header.GetType() == OT_COAP_TYPE_ACKNOWLEDGMENT || header.GetType() == OT_COAP_TYPE_RESET) && - header.GetCode() != OT_COAP_CODE_EMPTY) + if ((aMessage.GetType() == OT_COAP_TYPE_ACKNOWLEDGMENT || aMessage.GetType() == OT_COAP_TYPE_RESET) && + aMessage.GetCode() != OT_COAP_CODE_EMPTY) { - mResponsesQueue.EnqueueResponse(header, aMessage, aMessageInfo); + mResponsesQueue.EnqueueResponse(aMessage, aMessageInfo); } // Set Message Id if it was not already set. - if (header.GetMessageId() == 0 && - (header.GetType() == OT_COAP_TYPE_CONFIRMABLE || header.GetType() == OT_COAP_TYPE_NON_CONFIRMABLE)) + if (aMessage.GetMessageId() == 0 && + (aMessage.GetType() == OT_COAP_TYPE_CONFIRMABLE || aMessage.GetType() == OT_COAP_TYPE_NON_CONFIRMABLE)) { - header.SetMessageId(mMessageId++); - aMessage.Write(0, Header::kMinHeaderLength, header.GetBytes()); + aMessage.SetMessageId(mMessageId++); } - if (header.IsConfirmable()) + aMessage.Finish(); + + if (aMessage.IsConfirmable()) { // Create a copy of entire message and enqueue it. copyLength = aMessage.GetLength(); } - else if (header.IsNonConfirmable() && (aHandler != NULL)) + else if (aMessage.IsNonConfirmable() && (aHandler != NULL)) { // As we do not retransmit non confirmable messages, create a copy of header only, for token information. - copyLength = header.GetLength(); + copyLength = aMessage.GetOptionStart(); } if (copyLength > 0) { - coapMetadata = CoapMetadata(header.IsConfirmable(), aMessageInfo, aHandler, aContext); + coapMetadata = CoapMetadata(aMessage.IsConfirmable(), aMessageInfo, aHandler, aContext); VerifyOrExit((storedCopy = CopyAndEnqueueMessage(aMessage, copyLength, coapMetadata)) != NULL, error = OT_ERROR_NO_BUFS); } @@ -214,21 +208,21 @@ exit: otError Coap::Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { + static_cast(aMessage).Finish(); return mSocket.SendTo(aMessage, aMessageInfo); } -otError Coap::SendEmptyMessage(Header::Type aType, const Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo) +otError Coap::SendEmptyMessage(Message::Type aType, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) { - otError error = OT_ERROR_NONE; - Header responseHeader; + otError error = OT_ERROR_NONE; Message *message = NULL; - VerifyOrExit(aRequestHeader.GetType() == OT_COAP_TYPE_CONFIRMABLE, error = OT_ERROR_INVALID_ARGS); + VerifyOrExit(aRequest.GetType() == OT_COAP_TYPE_CONFIRMABLE, error = OT_ERROR_INVALID_ARGS); - responseHeader.Init(aType, OT_COAP_CODE_EMPTY); - responseHeader.SetMessageId(aRequestHeader.GetMessageId()); + VerifyOrExit((message = NewMessage()) != NULL, error = OT_ERROR_NO_BUFS); - VerifyOrExit((message = NewMessage(responseHeader)) != NULL, error = OT_ERROR_NO_BUFS); + message->Init(aType, OT_COAP_CODE_EMPTY); + message->SetMessageId(aRequest.GetMessageId()); SuccessOrExit(error = Send(*message, aMessageInfo)); @@ -242,27 +236,24 @@ exit: return error; } -otError Coap::SendHeaderResponse(Header::Code aCode, const Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo) +otError Coap::SendHeaderResponse(Message::Code aCode, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) { - otError error = OT_ERROR_NONE; - Header responseHeader; - Header::Type requestType; - Message * message = NULL; + otError error = OT_ERROR_NONE; + Message *message = NULL; - VerifyOrExit(aRequestHeader.IsRequest(), error = OT_ERROR_INVALID_ARGS); + VerifyOrExit(aRequest.IsRequest(), error = OT_ERROR_INVALID_ARGS); + VerifyOrExit((message = NewMessage()) != NULL, error = OT_ERROR_NO_BUFS); - requestType = aRequestHeader.GetType(); - - switch (requestType) + switch (aRequest.GetType()) { case OT_COAP_TYPE_CONFIRMABLE: - responseHeader.Init(OT_COAP_TYPE_ACKNOWLEDGMENT, aCode); - responseHeader.SetMessageId(aRequestHeader.GetMessageId()); + message->Init(OT_COAP_TYPE_ACKNOWLEDGMENT, aCode); + message->SetMessageId(aRequest.GetMessageId()); break; case OT_COAP_TYPE_NON_CONFIRMABLE: - responseHeader.Init(OT_COAP_TYPE_NON_CONFIRMABLE, aCode); - responseHeader.SetMessageId(mMessageId++); + message->Init(OT_COAP_TYPE_NON_CONFIRMABLE, aCode); + message->SetMessageId(mMessageId++); break; default: @@ -270,9 +261,7 @@ otError Coap::SendHeaderResponse(Header::Code aCode, const Header &aRequestHeade break; } - responseHeader.SetToken(aRequestHeader.GetToken(), aRequestHeader.GetTokenLength()); - - VerifyOrExit((message = NewMessage(responseHeader)) != NULL, error = OT_ERROR_NO_BUFS); + message->SetToken(aRequest.GetToken(), aRequest.GetTokenLength()); SuccessOrExit(error = SendMessage(*message, aMessageInfo)); @@ -296,13 +285,13 @@ void Coap::HandleRetransmissionTimer(void) uint32_t now = TimerMilli::GetNow(); uint32_t nextDelta = 0xffffffff; CoapMetadata coapMetadata; - Message * message = mPendingRequests.GetHead(); + Message * message = static_cast(mPendingRequests.GetHead()); Message * nextMessage = NULL; Ip6::MessageInfo messageInfo; while (message != NULL) { - nextMessage = message->GetNext(); + nextMessage = static_cast(message->GetNext()); coapMetadata.ReadFrom(*message); if (coapMetadata.IsLater(now)) @@ -341,7 +330,7 @@ void Coap::HandleRetransmissionTimer(void) else { // No expected response or acknowledgment. - FinalizeCoapTransaction(*message, coapMetadata, NULL, NULL, NULL, OT_ERROR_RESPONSE_TIMEOUT); + FinalizeCoapTransaction(*message, coapMetadata, NULL, NULL, OT_ERROR_RESPONSE_TIMEOUT); } message = nextMessage; @@ -355,7 +344,6 @@ void Coap::HandleRetransmissionTimer(void) void Coap::FinalizeCoapTransaction(Message & aRequest, const CoapMetadata & aCoapMetadata, - Header * aResponseHeader, Message * aResponse, const Ip6::MessageInfo *aMessageInfo, otError aResult) @@ -364,8 +352,7 @@ void Coap::FinalizeCoapTransaction(Message & aRequest, if (aCoapMetadata.mResponseHandler != NULL) { - aCoapMetadata.mResponseHandler(aCoapMetadata.mResponseContext, aResponseHeader, aResponse, aMessageInfo, - aResult); + aCoapMetadata.mResponseHandler(aCoapMetadata.mResponseContext, aResponse, aMessageInfo, aResult); } } @@ -376,14 +363,14 @@ otError Coap::AbortTransaction(otCoapResponseHandler aHandler, void *aContext) Message * nextMessage; CoapMetadata coapMetadata; - for (message = mPendingRequests.GetHead(); message != NULL; message = nextMessage) + for (message = static_cast(mPendingRequests.GetHead()); message != NULL; message = nextMessage) { - nextMessage = message->GetNext(); + nextMessage = static_cast(message->GetNext()); coapMetadata.ReadFrom(*message); if (coapMetadata.mResponseHandler == aHandler && coapMetadata.mResponseContext == aContext) { - FinalizeCoapTransaction(*message, coapMetadata, NULL, NULL, NULL, OT_ERROR_ABORT); + FinalizeCoapTransaction(*message, coapMetadata, NULL, NULL, OT_ERROR_ABORT); error = OT_ERROR_NONE; } } @@ -472,12 +459,11 @@ exit: return error; } -Message *Coap::FindRelatedRequest(const Header & aResponseHeader, +Message *Coap::FindRelatedRequest(const Message & aResponse, const Ip6::MessageInfo &aMessageInfo, - Header & aRequestHeader, CoapMetadata & aCoapMetadata) { - Message *message = mPendingRequests.GetHead(); + Message *message = static_cast(mPendingRequests.GetHead()); while (message != NULL) { @@ -488,15 +474,11 @@ Message *Coap::FindRelatedRequest(const Header & aResponseHeader, aCoapMetadata.mDestinationAddress.IsAnycastRoutingLocator()) && (aCoapMetadata.mDestinationPort == aMessageInfo.GetPeerPort())) { - // FromMessage can return OT_ERROR_PARSE if only partial message was stored (header only), - // but payload marker is present. Assume, that stored messages are always valid. - aRequestHeader.FromMessage(*message, sizeof(CoapMetadata)); - - switch (aResponseHeader.GetType()) + switch (aResponse.GetType()) { case OT_COAP_TYPE_RESET: case OT_COAP_TYPE_ACKNOWLEDGMENT: - if (aResponseHeader.GetMessageId() == aRequestHeader.GetMessageId()) + if (aResponse.GetMessageId() == message->GetMessageId()) { ExitNow(); } @@ -505,7 +487,7 @@ Message *Coap::FindRelatedRequest(const Header & aResponseHeader, case OT_COAP_TYPE_CONFIRMABLE: case OT_COAP_TYPE_NON_CONFIRMABLE: - if (aResponseHeader.IsTokenEqual(aRequestHeader)) + if (aResponse.IsTokenEqual(*message)) { ExitNow(); } @@ -514,7 +496,7 @@ Message *Coap::FindRelatedRequest(const Header & aResponseHeader, } } - message = message->GetNext(); + message = static_cast(message->GetNext()); } exit: @@ -527,77 +509,68 @@ void Coap::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessage *static_cast(aMessageInfo)); } -void Coap::Receive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) +void Coap::Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { - otError error; - Header header; + Message &message = static_cast(aMessage); - SuccessOrExit(error = header.FromMessage(aMessage, 0)); - - if (header.IsRequest()) + if (message.ParseHeader() != OT_ERROR_NONE) { - ProcessReceivedRequest(header, aMessage, aMessageInfo); + otLogDebgCoap("Failed to parse CoAP header"); + } + else if (message.IsRequest()) + { + ProcessReceivedRequest(message, aMessageInfo); } else { - ProcessReceivedResponse(header, aMessage, aMessageInfo); - } - -exit: - - if (error) - { - otLogInfoCoapErr(error, "Receive failed"); + ProcessReceivedResponse(message, aMessageInfo); } } -void Coap::ProcessReceivedResponse(Header &aResponseHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) +void Coap::ProcessReceivedResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { - Header requestHeader; CoapMetadata coapMetadata; - Message * message = NULL; + Message * request = NULL; otError error = OT_ERROR_NONE; - aMessage.MoveOffset(aResponseHeader.GetLength()); + request = FindRelatedRequest(aMessage, aMessageInfo, coapMetadata); - message = FindRelatedRequest(aResponseHeader, aMessageInfo, requestHeader, coapMetadata); - - if (message == NULL) + if (request == NULL) { ExitNow(); } - switch (aResponseHeader.GetType()) + switch (aMessage.GetType()) { case OT_COAP_TYPE_RESET: - if (aResponseHeader.IsEmpty()) + if (aMessage.IsEmpty()) { - FinalizeCoapTransaction(*message, coapMetadata, NULL, NULL, NULL, OT_ERROR_ABORT); + FinalizeCoapTransaction(*request, coapMetadata, NULL, NULL, OT_ERROR_ABORT); } // Silently ignore non-empty reset messages (RFC 7252, p. 4.2). break; case OT_COAP_TYPE_ACKNOWLEDGMENT: - if (aResponseHeader.IsEmpty()) + if (aMessage.IsEmpty()) { // Empty acknowledgment. if (coapMetadata.mConfirmable) { coapMetadata.mAcknowledged = true; - coapMetadata.UpdateIn(*message); + coapMetadata.UpdateIn(*request); } // Remove the message if response is not expected, otherwise await response. if (coapMetadata.mResponseHandler == NULL) { - DequeueMessage(*message); + DequeueMessage(*request); } } - else if (aResponseHeader.IsResponse() && aResponseHeader.IsTokenEqual(requestHeader)) + else if (aMessage.IsResponse() && aMessage.IsTokenEqual(*request)) { // Piggybacked response. - FinalizeCoapTransaction(*message, coapMetadata, &aResponseHeader, &aMessage, &aMessageInfo, OT_ERROR_NONE); + FinalizeCoapTransaction(*request, coapMetadata, &aMessage, &aMessageInfo, OT_ERROR_NONE); } // Silently ignore acknowledgments carrying requests (RFC 7252, p. 4.2) @@ -606,45 +579,42 @@ void Coap::ProcessReceivedResponse(Header &aResponseHeader, Message &aMessage, c case OT_COAP_TYPE_CONFIRMABLE: // Send empty ACK if it is a CON message. - SendAck(aResponseHeader, aMessageInfo); + SendAck(aMessage, aMessageInfo); // fall through case OT_COAP_TYPE_NON_CONFIRMABLE: // Separate response. - FinalizeCoapTransaction(*message, coapMetadata, &aResponseHeader, &aMessage, &aMessageInfo, OT_ERROR_NONE); + FinalizeCoapTransaction(*request, coapMetadata, &aMessage, &aMessageInfo, OT_ERROR_NONE); break; } exit: - if (error == OT_ERROR_NONE && message == NULL) + if (error == OT_ERROR_NONE && request == NULL) { - if (aResponseHeader.IsConfirmable() || aResponseHeader.IsNonConfirmable()) + if (aMessage.IsConfirmable() || aMessage.IsNonConfirmable()) { // Successfully parsed a header but no matching request was found - reject the message by sending reset. - SendReset(aResponseHeader, aMessageInfo); + SendReset(aMessage, aMessageInfo); } } } -void Coap::ProcessReceivedRequest(Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) +void Coap::ProcessReceivedRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { - char uriPath[Resource::kMaxReceivedUriPath] = ""; - char * curUriPath = uriPath; - const Header::Option *coapOption; - Message * cachedResponse = NULL; - otError error = OT_ERROR_NOT_FOUND; + char uriPath[Resource::kMaxReceivedUriPath]; + char * curUriPath = uriPath; + Message *cachedResponse = NULL; + otError error = OT_ERROR_NOT_FOUND; if (mInterceptor != NULL) { SuccessOrExit(error = mInterceptor(aMessage, aMessageInfo, mContext)); } - aMessage.MoveOffset(aHeader.GetLength()); - - switch (mResponsesQueue.GetMatchedResponseCopy(aHeader, aMessageInfo, &cachedResponse)) + switch (mResponsesQueue.GetMatchedResponseCopy(aMessage, aMessageInfo, &cachedResponse)) { case OT_ERROR_NONE: error = Send(*cachedResponse, aMessageInfo); @@ -659,11 +629,9 @@ void Coap::ProcessReceivedRequest(Header &aHeader, Message &aMessage, const Ip6: break; } - coapOption = aHeader.GetFirstOption(); - - while (coapOption != NULL) + for (const otCoapOption *option = aMessage.GetFirstOption(); option != NULL; option = aMessage.GetNextOption()) { - switch (coapOption->mNumber) + switch (option->mNumber) { case OT_COAP_OPTION_URI_PATH: if (curUriPath != uriPath) @@ -671,17 +639,15 @@ void Coap::ProcessReceivedRequest(Header &aHeader, Message &aMessage, const Ip6: *curUriPath++ = '/'; } - VerifyOrExit(coapOption->mLength < sizeof(uriPath) - static_cast(curUriPath + 1 - uriPath)); + VerifyOrExit(option->mLength < sizeof(uriPath) - static_cast(curUriPath + 1 - uriPath)); - memcpy(curUriPath, coapOption->mValue, coapOption->mLength); - curUriPath += coapOption->mLength; + aMessage.GetOptionValue(curUriPath); + curUriPath += option->mLength; break; default: break; } - - coapOption = aHeader.GetNextOption(); } curUriPath[0] = '\0'; @@ -690,7 +656,7 @@ void Coap::ProcessReceivedRequest(Header &aHeader, Message &aMessage, const Ip6: { if (strcmp(resource->mUriPath, uriPath) == 0) { - resource->HandleRequest(aHeader, aMessage, aMessageInfo); + resource->HandleRequest(aMessage, aMessageInfo); error = OT_ERROR_NONE; ExitNow(); } @@ -698,7 +664,7 @@ void Coap::ProcessReceivedRequest(Header &aHeader, Message &aMessage, const Ip6: if (mDefaultHandler) { - mDefaultHandler(mDefaultHandlerContext, &aHeader, &aMessage, &aMessageInfo); + mDefaultHandler(mDefaultHandlerContext, &aMessage, &aMessageInfo); error = OT_ERROR_NONE; } @@ -710,7 +676,7 @@ exit: if (error == OT_ERROR_NOT_FOUND) { - SendNotFound(aHeader, aMessageInfo); + SendNotFound(aMessage, aMessageInfo); } if (cachedResponse != NULL) @@ -759,7 +725,7 @@ ResponsesQueue::ResponsesQueue(Instance &aInstance) { } -otError ResponsesQueue::GetMatchedResponseCopy(const Header & aHeader, +otError ResponsesQueue::GetMatchedResponseCopy(const Message & aRequest, const Ip6::MessageInfo &aMessageInfo, Message ** aResponse) { @@ -767,9 +733,9 @@ otError ResponsesQueue::GetMatchedResponseCopy(const Header & aHeader, Message * message; EnqueuedResponseHeader enqueuedResponseHeader; Ip6::MessageInfo messageInfo; - Header header; - for (message = mQueue.GetHead(); message != NULL; message = message->GetNext()) + for (message = static_cast(mQueue.GetHead()); message != NULL; + message = static_cast(message->GetNext())) { enqueuedResponseHeader.ReadFrom(*message); messageInfo = enqueuedResponseHeader.GetMessageInfo(); @@ -786,18 +752,12 @@ otError ResponsesQueue::GetMatchedResponseCopy(const Header & aHeader, } // Check Message Id - if (header.FromMessage(*message, sizeof(EnqueuedResponseHeader)) != OT_ERROR_NONE) + if (message->GetMessageId() != aRequest.GetMessageId()) { continue; } - if (header.GetMessageId() != aHeader.GetMessageId()) - { - continue; - } - - *aResponse = message->Clone(); - VerifyOrExit(*aResponse != NULL, error = OT_ERROR_NO_BUFS); + VerifyOrExit((*aResponse = message->Clone()) != NULL, error = OT_ERROR_NO_BUFS); EnqueuedResponseHeader::RemoveFrom(**aResponse); @@ -809,14 +769,14 @@ exit: return error; } -void ResponsesQueue::EnqueueResponse(const Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) +void ResponsesQueue::EnqueueResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { Message * copy; EnqueuedResponseHeader enqueuedResponseHeader(aMessageInfo); uint16_t messageCount; uint16_t bufferCount; - switch (GetMatchedResponseCopy(aHeader, aMessageInfo, ©)) + switch (GetMatchedResponseCopy(aMessage, aMessageInfo, ©)) { case OT_ERROR_NOT_FOUND: break; @@ -838,8 +798,7 @@ void ResponsesQueue::EnqueueResponse(const Header &aHeader, Message &aMessage, c DequeueOldestResponse(); } - copy = aMessage.Clone(); - VerifyOrExit(copy != NULL); + VerifyOrExit((copy = aMessage.Clone()) != NULL); enqueuedResponseHeader.AppendTo(*copy); mQueue.Enqueue(*copy); @@ -857,7 +816,7 @@ void ResponsesQueue::DequeueOldestResponse(void) { Message *message; - VerifyOrExit((message = mQueue.GetHead()) != NULL); + VerifyOrExit((message = static_cast(mQueue.GetHead())) != NULL); DequeueResponse(*message); exit: @@ -868,7 +827,7 @@ void ResponsesQueue::DequeueAllResponses(void) { Message *message; - while ((message = mQueue.GetHead()) != NULL) + while ((message = static_cast(mQueue.GetHead())) != NULL) { DequeueResponse(*message); } @@ -884,7 +843,7 @@ void ResponsesQueue::HandleTimer(void) Message * message; EnqueuedResponseHeader enqueuedResponseHeader; - while ((message = mQueue.GetHead()) != NULL) + while ((message = static_cast(mQueue.GetHead())) != NULL) { enqueuedResponseHeader.ReadFrom(*message); diff --git a/src/core/coap/coap.hpp b/src/core/coap/coap.hpp index a0b9a7f47..79b3073d4 100644 --- a/src/core/coap/coap.hpp +++ b/src/core/coap/coap.hpp @@ -33,7 +33,7 @@ #include -#include "coap/coap_header.hpp" +#include "coap/coap_message.hpp" #include "common/debug.hpp" #include "common/locator.hpp" #include "common/message.hpp" @@ -238,9 +238,9 @@ public: const char *GetUriPath(void) const { return mUriPath; }; private: - void HandleRequest(Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const + void HandleRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const { - mHandler(mContext, &aHeader, &aMessage, &aMessageInfo); + mHandler(mContext, &aMessage, &aMessageInfo); } }; @@ -363,12 +363,11 @@ public: * response is not added. * The CoAP response is copied before it is added to the cache. * - * @param[in] aHeader A reference to a CoAP header. * @param[in] aMessage The CoAP response to add to the cache. * @param[in] aMessageInfo The message info corresponding to @p aMessage. * */ - void EnqueueResponse(const Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + void EnqueueResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); /** * Remove the oldest response from the cache. @@ -385,7 +384,7 @@ public: /** * Get a copy of CoAP response from the cache that matches given Message ID and source endpoint. * - * @param[in] aHeader The CoAP message header containing Message ID. + * @param[in] aRequest The CoAP message containing Message ID. * @param[in] aMessageInfo The message info containing source endpoint address and port. * @param[out] aResponse A pointer to a copy of a cached CoAP response matching given arguments. * @@ -394,7 +393,7 @@ public: * @retval OT_ERROR_NOT_FOUND Matching response not found. * */ - otError GetMatchedResponseCopy(const Header &aHeader, const Ip6::MessageInfo &aMessageInfo, Message **aResponse); + otError GetMatchedResponseCopy(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo, Message **aResponse); /** * Get a reference to the cached CoAP responses queue. @@ -505,13 +504,12 @@ public: * @note If @p aSettings is 'NULL', the link layer security is enabled and the message priority is set to * OT_MESSAGE_PRIORITY_NORMAL by default. * - * @param[in] aHeader A reference to a CoAP header that is used to create the message. * @param[in] aSettings A pointer to the message settings or NULL to set default settings. * * @returns A pointer to the message or NULL if failed to allocate message. * */ - Message *NewMessage(const Header &aHeader, const otMessageSettings *aSettings = NULL); + Message *NewMessage(const otMessageSettings *aSettings = NULL); /** * This method sends a CoAP message. @@ -537,80 +535,80 @@ public: /** * This method sends a CoAP reset message. * - * @param[in] aRequestHeader A reference to the CoAP Header that was used in CoAP request. + * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. * @param[in] aMessageInfo The message info corresponding to the CoAP request. * * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message. * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response. - * @retval OT_ERROR_INVALID_ARGS The @p aRequestHeader header is not of confirmable type. + * @retval OT_ERROR_INVALID_ARGS The @p aRequest is not of confirmable type. * */ - otError SendReset(Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo) + otError SendReset(Message &aRequest, const Ip6::MessageInfo &aMessageInfo) { - return SendEmptyMessage(OT_COAP_TYPE_RESET, aRequestHeader, aMessageInfo); + return SendEmptyMessage(OT_COAP_TYPE_RESET, aRequest, aMessageInfo); }; /** * This method sends header-only CoAP response message. * * @param[in] aCode The CoAP code of this response. - * @param[in] aRequestHeader A reference to the CoAP Header that was used in CoAP request. + * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. * @param[in] aMessageInfo The message info corresponding to the CoAP request. * * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message. * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response. - * @retval OT_ERROR_INVALID_ARGS The @p aRequestHeader header is not of confirmable type. + * @retval OT_ERROR_INVALID_ARGS The @p aRequest header is not of confirmable type. * */ - otError SendHeaderResponse(Header::Code aCode, const Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo); + otError SendHeaderResponse(Message::Code aCode, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo); /** * This method sends a CoAP ACK empty message which is used in Separate Response for confirmable requests. * - * @param[in] aRequestHeader A reference to the CoAP Header that was used in CoAP request. + * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. * @param[in] aMessageInfo The message info corresponding to the CoAP request. * * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message. * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response. - * @retval OT_ERROR_INVALID_ARGS The @p aRequestHeader header is not of confirmable type. + * @retval OT_ERROR_INVALID_ARGS The @p aRequest header is not of confirmable type. * */ - otError SendAck(const Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo) + otError SendAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) { - return SendEmptyMessage(OT_COAP_TYPE_ACKNOWLEDGMENT, aRequestHeader, aMessageInfo); + return SendEmptyMessage(OT_COAP_TYPE_ACKNOWLEDGMENT, aRequest, aMessageInfo); }; /** * This method sends a CoAP ACK message on which a dummy CoAP response is piggybacked. * - * @param[in] aRequestHeader A reference to the CoAP Header that was used in CoAP request. + * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. * @param[in] aMessageInfo The message info corresponding to the CoAP request. * * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message. * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response. - * @retval OT_ERROR_INVALID_ARGS The @p aRequestHeader header is not of confirmable type. + * @retval OT_ERROR_INVALID_ARGS The @p aRequest header is not of confirmable type. * */ - otError SendEmptyAck(const Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo) + otError SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) { - return (aRequestHeader.GetType() == OT_COAP_TYPE_CONFIRMABLE - ? SendHeaderResponse(OT_COAP_CODE_CHANGED, aRequestHeader, aMessageInfo) + return (aRequest.GetType() == OT_COAP_TYPE_CONFIRMABLE + ? SendHeaderResponse(OT_COAP_CODE_CHANGED, aRequest, aMessageInfo) : OT_ERROR_INVALID_ARGS); } /** * This method sends a header-only CoAP message to indicate no resource matched for the request. * - * @param[in] aRequestHeader A reference to the CoAP Header that was used in CoAP request. + * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. * @param[in] aMessageInfo The message info corresponding to the CoAP request. * * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message. * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response. * */ - otError SendNotFound(const Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo) + otError SendNotFound(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) { - return SendHeaderResponse(OT_COAP_CODE_NOT_FOUND, aRequestHeader, aMessageInfo); + return SendHeaderResponse(OT_COAP_CODE_NOT_FOUND, aRequest, aMessageInfo); } /** @@ -673,7 +671,7 @@ protected: * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. * */ - virtual void Receive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + virtual void Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); Ip6::UdpSocket mSocket; @@ -685,22 +683,20 @@ private: Message *CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLength, const CoapMetadata &aCoapMetadata); void DequeueMessage(Message &aMessage); - Message *FindRelatedRequest(const Header & aResponseHeader, + Message *FindRelatedRequest(const Message & aResponse, const Ip6::MessageInfo &aMessageInfo, - Header & aRequestHeader, CoapMetadata & aCoapMetadata); void FinalizeCoapTransaction(Message & aRequest, const CoapMetadata & aCoapMetadata, - Header * aResponseHeader, Message * aResponse, const Ip6::MessageInfo *aMessageInfo, otError aResult); - void ProcessReceivedRequest(Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo); - void ProcessReceivedResponse(Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + void ProcessReceivedRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + void ProcessReceivedResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); otError SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo); - otError SendEmptyMessage(Header::Type aType, const Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo); + otError SendEmptyMessage(Message::Type aType, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo); MessageQueue mPendingRequests; uint16_t mMessageId; diff --git a/src/core/coap/coap_header.cpp b/src/core/coap/coap_header.cpp deleted file mode 100644 index 9ae90e6a9..000000000 --- a/src/core/coap/coap_header.cpp +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Copyright (c) 2016, The OpenThread Authors. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * This file implements the CoAP header generation and parsing. - */ - -#include "coap_header.hpp" - -#include "coap/coap.hpp" -#include "common/code_utils.hpp" -#include "common/debug.hpp" -#include "common/encoding.hpp" -#include "common/instance.hpp" -#include "common/random.hpp" - -namespace ot { -namespace Coap { - -void Header::Init(void) -{ - mHeaderLength = kMinHeaderLength; - mOptionLast = 0; - mFirstOptionOffset = 0; - mNextOptionOffset = 0; - memset(&mOption, 0, sizeof(mOption)); - memset(&mHeader, 0, sizeof(mHeader)); - SetVersion(kVersion1); -} - -void Header::Init(Type aType, Code aCode) -{ - Init(); - SetType(aType); - SetCode(aCode); -} - -otError Header::FromMessage(const Message &aMessage, uint16_t aMetadataSize) -{ - otError error = OT_ERROR_PARSE; - uint16_t offset = aMessage.GetOffset(); - uint16_t length = aMessage.GetLength() - aMessage.GetOffset(); - uint8_t tokenLength; - bool firstOption = true; - uint16_t optionDelta; - uint16_t optionLength; - - length -= aMetadataSize; - - Init(); - - VerifyOrExit(kTokenOffset <= length); - aMessage.Read(offset, kTokenOffset, mHeader.mBytes); - mHeaderLength = kTokenOffset; - offset += kTokenOffset; - - VerifyOrExit(GetVersion() == 1); - - tokenLength = GetTokenLength(); - VerifyOrExit(tokenLength <= OT_COAP_MAX_TOKEN_LENGTH && (mHeaderLength + tokenLength) <= length); - aMessage.Read(offset, tokenLength, mHeader.mBytes + mHeaderLength); - mHeaderLength += tokenLength; - offset += tokenLength; - - while (mHeaderLength < length) - { - VerifyOrExit(mHeaderLength + kMaxOptionHeaderSize <= kMaxHeaderLength); - - aMessage.Read(offset, kMaxOptionHeaderSize, mHeader.mBytes + mHeaderLength); - - if (mHeader.mBytes[mHeaderLength] == 0xff) - { - mHeaderLength += sizeof(uint8_t); - // RFC7252: The presence of a marker followed by a zero-length payload MUST be processed - // as a message format error. - VerifyOrExit(mHeaderLength < length); - ExitNow(error = OT_ERROR_NONE); - } - - if (firstOption) - { - mFirstOptionOffset = mHeaderLength; - } - - optionDelta = mHeader.mBytes[mHeaderLength] >> 4; - optionLength = mHeader.mBytes[mHeaderLength] & 0xf; - mHeaderLength += sizeof(uint8_t); - offset += sizeof(uint8_t); - - if (optionDelta < kOption1ByteExtension) - { - // do nothing - } - else if (optionDelta == kOption1ByteExtension) - { - optionDelta = kOption1ByteExtensionOffset + mHeader.mBytes[mHeaderLength]; - mHeaderLength += sizeof(uint8_t); - offset += sizeof(uint8_t); - } - else if (optionDelta == kOption2ByteExtension) - { - optionDelta = kOption2ByteExtensionOffset + static_cast((mHeader.mBytes[mHeaderLength] << 8) | - (mHeader.mBytes[mHeaderLength + 1])); - mHeaderLength += sizeof(uint16_t); - offset += sizeof(uint16_t); - } - else - { - ExitNow(error = OT_ERROR_PARSE); - } - - if (optionLength < kOption1ByteExtension) - { - // do nothing - } - else if (optionLength == kOption1ByteExtension) - { - optionLength = kOption1ByteExtensionOffset + mHeader.mBytes[mHeaderLength]; - mHeaderLength += sizeof(uint8_t); - offset += sizeof(uint8_t); - } - else if (optionLength == kOption2ByteExtension) - { - optionLength = kOption2ByteExtensionOffset + static_cast((mHeader.mBytes[mHeaderLength] << 8) | - (mHeader.mBytes[mHeaderLength + 1])); - mHeaderLength += sizeof(uint16_t); - offset += sizeof(uint16_t); - } - else - { - ExitNow(error = OT_ERROR_PARSE); - } - - if (firstOption) - { - mOption.mNumber = optionDelta; - mOption.mLength = optionLength; - mOption.mValue = mHeader.mBytes + mHeaderLength; - mNextOptionOffset = mHeaderLength + optionLength; - firstOption = false; - } - - VerifyOrExit(mHeaderLength + optionLength <= kMaxHeaderLength); - VerifyOrExit(mHeaderLength + optionLength <= length); - - aMessage.Read(offset, optionLength, mHeader.mBytes + mHeaderLength); - mHeaderLength += optionLength; - offset += optionLength; - } - - if (mHeaderLength == length) - { - // No payload present - return success. - error = OT_ERROR_NONE; - } - -exit: - - // In case any step failed, prevent access to corrupt Option - if (error != OT_ERROR_NONE) - { - mFirstOptionOffset = 0; - } - - return error; -} - -otError Header::AppendOption(const Option &aOption) -{ - otError error = OT_ERROR_NONE; - uint8_t *buf = mHeader.mBytes + mHeaderLength; - uint8_t *cur = buf + 1; - uint16_t optionDelta = aOption.mNumber - mOptionLast; - uint16_t optionLength; - - // Assure that no option is inserted out of order. - VerifyOrExit(aOption.mNumber >= mOptionLast, error = OT_ERROR_INVALID_ARGS); - - // Calculate the total option size and check the buffers. - optionLength = 1 + aOption.mLength; - optionLength += optionDelta < kOption1ByteExtensionOffset ? 0 : (optionDelta < kOption2ByteExtensionOffset ? 1 : 2); - optionLength += - aOption.mLength < kOption1ByteExtensionOffset ? 0 : (aOption.mLength < kOption2ByteExtensionOffset ? 1 : 2); - VerifyOrExit(mHeaderLength + optionLength < kMaxHeaderLength, error = OT_ERROR_NO_BUFS); - - // Insert option delta. - if (optionDelta < kOption1ByteExtensionOffset) - { - *buf = (optionDelta << Option::kOptionDeltaOffset) & Option::kOptionDeltaMask; - } - else if (optionDelta < kOption2ByteExtensionOffset) - { - *buf |= kOption1ByteExtension << Option::kOptionDeltaOffset; - *cur++ = (optionDelta - kOption1ByteExtensionOffset) & 0xff; - } - else - { - *buf |= kOption2ByteExtension << Option::kOptionDeltaOffset; - optionDelta -= kOption2ByteExtensionOffset; - *cur++ = optionDelta >> 8; - *cur++ = optionDelta & 0xff; - } - - // Insert option length. - if (aOption.mLength < kOption1ByteExtensionOffset) - { - *buf |= aOption.mLength; - } - else if (aOption.mLength < kOption2ByteExtensionOffset) - { - *buf |= kOption1ByteExtension; - *cur++ = (aOption.mLength - kOption1ByteExtensionOffset) & 0xff; - } - else - { - *buf |= kOption2ByteExtension; - optionLength = aOption.mLength - kOption2ByteExtensionOffset; - *cur++ = optionLength >> 8; - *cur++ = optionLength & 0xff; - } - - // Insert option value. - memcpy(cur, aOption.mValue, aOption.mLength); - cur += aOption.mLength; - - mHeaderLength += static_cast(cur - buf); - mOptionLast = aOption.mNumber; - -exit: - return error; -} - -otError Header::AppendUintOption(uint16_t aNumber, uint32_t aValue) -{ - Option coapOption; - - aValue = Encoding::BigEndian::HostSwap32(aValue); - coapOption.mNumber = aNumber; - coapOption.mLength = 4; - coapOption.mValue = reinterpret_cast(&aValue); - - // skip preceding zeros - while (coapOption.mValue[0] == 0 && coapOption.mLength > 0) - { - coapOption.mValue++; - coapOption.mLength--; - } - - return AppendOption(coapOption); -} - -otError Header::AppendStringOption(uint16_t aNumber, const char *aValue) -{ - Option coapOption; - - coapOption.mNumber = aNumber; - coapOption.mLength = static_cast(strlen(aValue)); - coapOption.mValue = reinterpret_cast(aValue); - - return AppendOption(coapOption); -} - -otError Header::AppendObserveOption(uint32_t aObserve) -{ - return AppendUintOption(OT_COAP_OPTION_OBSERVE, aObserve & 0xFFFFFF); -} - -otError Header::AppendUriPathOptions(const char *aUriPath) -{ - otError error = OT_ERROR_NONE; - const char *cur = aUriPath; - const char *end; - Option coapOption; - - coapOption.mNumber = OT_COAP_OPTION_URI_PATH; - - while ((end = strchr(cur, '/')) != NULL) - { - coapOption.mLength = static_cast(end - cur); - coapOption.mValue = reinterpret_cast(cur); - SuccessOrExit(error = AppendOption(coapOption)); - cur = end + 1; - } - - SuccessOrExit(error = AppendStringOption(OT_COAP_OPTION_URI_PATH, cur)); - -exit: - return error; -} - -otError Header::AppendProxyUriOption(const char *aProxyUri) -{ - return AppendStringOption(OT_COAP_OPTION_PROXY_URI, aProxyUri); -} - -otError Header::AppendContentFormatOption(otCoapOptionContentFormat aContentFormat) -{ - return AppendUintOption(OT_COAP_OPTION_CONTENT_FORMAT, static_cast(aContentFormat)); -} - -otError Header::AppendMaxAgeOption(uint32_t aMaxAge) -{ - return AppendUintOption(OT_COAP_OPTION_MAX_AGE, aMaxAge); -} - -otError Header::AppendUriQueryOption(const char *aUriQuery) -{ - return AppendStringOption(OT_COAP_OPTION_URI_QUERY, aUriQuery); -} - -const Header::Option *Header::GetFirstOption(void) -{ - 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) -{ - Option * rval = NULL; - uint16_t optionDelta; - uint16_t optionLength; - - VerifyOrExit(mNextOptionOffset < mHeaderLength); - - optionDelta = mHeader.mBytes[mNextOptionOffset] >> 4; - optionLength = mHeader.mBytes[mNextOptionOffset] & 0xf; - mNextOptionOffset += sizeof(uint8_t); - - if (optionDelta < kOption1ByteExtension) - { - // do nothing - } - else if (optionDelta == kOption1ByteExtension) - { - optionDelta = kOption1ByteExtensionOffset + mHeader.mBytes[mNextOptionOffset]; - mNextOptionOffset += sizeof(uint8_t); - } - else if (optionDelta == kOption2ByteExtension) - { - optionDelta = kOption2ByteExtensionOffset + static_cast((mHeader.mBytes[mNextOptionOffset] << 8) | - mHeader.mBytes[mNextOptionOffset + 1]); - mNextOptionOffset += sizeof(uint16_t); - } - else - { - ExitNow(); - } - - if (optionLength < kOption1ByteExtension) - { - // do nothing - } - else if (optionLength == kOption1ByteExtension) - { - optionLength = kOption1ByteExtensionOffset + mHeader.mBytes[mNextOptionOffset]; - mNextOptionOffset += sizeof(uint8_t); - } - else if (optionLength == kOption2ByteExtension) - { - optionLength = kOption2ByteExtensionOffset + static_cast((mHeader.mBytes[mNextOptionOffset] << 8) | - mHeader.mBytes[mNextOptionOffset + 1]); - mNextOptionOffset += sizeof(uint16_t); - } - else - { - ExitNow(); - } - - mOption.mNumber += optionDelta; - mOption.mLength = optionLength; - mOption.mValue = mHeader.mBytes + mNextOptionOffset; - mNextOptionOffset += optionLength; - rval = static_cast