| /* |
| * 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 includes definitions for generating and processing CoAP headers. |
| */ |
| |
| #ifndef COAP_HEADER_HPP_ |
| #define COAP_HEADER_HPP_ |
| |
| #include "utils/wrap_string.h" |
| |
| #include <openthread/coap.h> |
| |
| #include "common/encoding.hpp" |
| #include "common/message.hpp" |
| |
| using ot::Encoding::BigEndian::HostSwap16; |
| |
| namespace ot { |
| |
| /** |
| * @namespace ot::Coap |
| * @brief |
| * This namespace includes definitions for CoAP. |
| * |
| */ |
| namespace Coap { |
| |
| /** |
| * @addtogroup core-coap |
| * |
| * @brief |
| * This module includes definitions for CoAP. |
| * |
| * @{ |
| * |
| */ |
| |
| /** |
| * This class implements CoAP header generation and parsing. |
| * |
| */ |
| class Header : public otCoapHeader |
| { |
| public: |
| enum |
| { |
| kVersion1 = 1, ///< Version 1 |
| kMinHeaderLength = 4, ///< Minimum header length |
| kMaxHeaderLength = OT_COAP_HEADER_MAX_LENGTH, ///< Maximum header length |
| kDefaultTokenLength = 2 ///< Default token length |
| }; |
| |
| /** |
| * CoAP Type values. |
| * |
| */ |
| typedef otCoapType Type; |
| |
| /** |
| * CoAP Code values. |
| * |
| */ |
| typedef otCoapCode Code; |
| |
| /** |
| * This method initializes the CoAP header. |
| * |
| */ |
| void Init(void); |
| |
| /** |
| * This method initializes the CoAP header with specific Type and Code. |
| * |
| * @param[in] aType The Type value. |
| * @param[in] aCode The Code value. |
| * |
| */ |
| void Init(Type aType, Code aCode); |
| |
| /** |
| * This method parses the CoAP header from a message. |
| * |
| * @param[in] aMessage A reference to the message. |
| * @param[in] aMetadataSize A size of metadata appended to the message. |
| * |
| * @retval OT_ERROR_NONE Successfully parsed the message. |
| * @retval OT_ERROR_PARSE Failed to parse the message. |
| * |
| */ |
| otError FromMessage(const Message &aMessage, uint16_t aMetadataSize); |
| |
| /** |
| * This method returns the Version value. |
| * |
| * @returns The Version value. |
| * |
| */ |
| uint8_t GetVersion(void) const { return (mHeader.mFields.mVersionTypeToken & kVersionMask) >> kVersionOffset; } |
| |
| /** |
| * This method sets the Version value. |
| * |
| * @param[in] aVersion The Version value. |
| * |
| */ |
| void SetVersion(uint8_t aVersion) { |
| mHeader.mFields.mVersionTypeToken &= ~kVersionMask; |
| mHeader.mFields.mVersionTypeToken |= aVersion << kVersionOffset; |
| } |
| |
| /** |
| * This method returns the Type value. |
| * |
| * @returns The Type value. |
| * |
| */ |
| Type GetType(void) const { return static_cast<Header::Type>(mHeader.mFields.mVersionTypeToken & kTypeMask); } |
| |
| /** |
| * This method sets the Type value. |
| * |
| * @param[in] aType The Type value. |
| * |
| */ |
| void SetType(Type aType) { |
| mHeader.mFields.mVersionTypeToken &= ~kTypeMask; |
| mHeader.mFields.mVersionTypeToken |= aType; |
| } |
| |
| /** |
| * This method returns the Code value. |
| * |
| * @returns The Code value. |
| * |
| */ |
| Code GetCode(void) const { return static_cast<Code>(mHeader.mFields.mCode); } |
| |
| /** |
| * This method sets the Code value. |
| * |
| * @param[in] aCode The Code value. |
| * |
| */ |
| void SetCode(Code aCode) { mHeader.mFields.mCode = static_cast<uint8_t>(aCode); } |
| |
| /** |
| * This method returns the Message ID value. |
| * |
| * @returns The Message ID value. |
| * |
| */ |
| uint16_t GetMessageId(void) const { return HostSwap16(mHeader.mFields.mMessageId); } |
| |
| /** |
| * This method sets the Message ID value. |
| * |
| * @param[in] aMessageId The Message ID value. |
| * |
| */ |
| void SetMessageId(uint16_t aMessageId) { mHeader.mFields.mMessageId = HostSwap16(aMessageId); } |
| |
| /** |
| * This method returns the Token length. |
| * |
| * @returns The Token length. |
| * |
| */ |
| uint8_t GetTokenLength(void) const { return (mHeader.mFields.mVersionTypeToken & kTokenLengthMask) >> kTokenLengthOffset; } |
| |
| /** |
| * This method returns a pointer to the Token value. |
| * |
| * @returns A pointer to the Token value. |
| * |
| */ |
| const uint8_t *GetToken(void) const { return mHeader.mBytes + kTokenOffset; } |
| |
| /** |
| * This method sets the Token value and length. |
| * |
| * @param[in] aToken A pointer to the Token value. |
| * @param[in] aTokenLength The Length of @p aToken. |
| * |
| */ |
| void SetToken(const uint8_t *aToken, uint8_t aTokenLength) { |
| mHeader.mFields.mVersionTypeToken = (mHeader.mFields.mVersionTypeToken & ~kTokenLengthMask) | |
| ((aTokenLength << kTokenLengthOffset) & kTokenLengthMask); |
| memcpy(mHeader.mBytes + kTokenOffset, aToken, aTokenLength); |
| mHeaderLength += aTokenLength; |
| } |
| |
| /** |
| * This method sets the Token length and randomizes its value. |
| * |
| * @param[in] aTokenLength The Length of a Token to set. |
| * |
| */ |
| void SetToken(uint8_t aTokenLength); |
| |
| /** |
| * This method checks if Tokens in two CoAP headers are equal. |
| * |
| * @param[in] aHeader A header to compare. |
| * |
| * @retval TRUE If two Tokens are equal. |
| * @retval FALSE If Tokens differ in length or value. |
| * |
| */ |
| bool IsTokenEqual(const Header &aHeader) const { |
| return ((this->GetTokenLength() == aHeader.GetTokenLength()) && |
| (memcmp(this->GetToken(), aHeader.GetToken(), this->GetTokenLength()) == 0)); |
| } |
| |
| /** |
| * This structure represents a CoAP option. |
| * |
| */ |
| struct Option : public otCoapOption |
| { |
| /** |
| * Protocol Constants |
| * |
| */ |
| enum |
| { |
| kOptionDeltaOffset = 4, ///< Delta Offset |
| kOptionDeltaMask = 0xf << kOptionDeltaOffset, ///< Delta Mask |
| }; |
| |
| /** |
| * Option Numbers |
| */ |
| typedef otCoapOptionType Type; |
| }; |
| |
| /** |
| * This method appends a CoAP option. |
| * |
| * @param[in] aOption The CoAP Option. |
| * |
| * @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 AppendOption(const Option &aOption); |
| |
| /** |
| * This method appends an unsigned integer CoAP option as specified in |
| * https://tools.ietf.org/html/rfc7252#section-3.2 |
| * |
| * @param[in] aNumber The CoAP Option number. |
| * @param[in] aValue The CoAP Option unsigned integer 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 AppendUintOption(uint16_t aNumber, uint32_t aValue); |
| |
| /** |
| * This method appends an Observe option. |
| * |
| * @param[in] aObserve Observe field 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 AppendObserveOption(uint32_t aObserve); |
| |
| /** |
| * This method appends a Uri-Path option. |
| * |
| * @param[in] aUriPath A pointer to a NULL-terminated string. |
| * |
| * @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 AppendUriPathOptions(const char *aUriPath); |
| |
| /** |
| * This method appends a Content-Format option. |
| * |
| * @param[in] aContentFormat The Content Format 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 AppendContentFormatOption(otCoapOptionContentFormat aContentFormat); |
| |
| /** |
| * This method appends a Max-Age option. |
| * |
| * @param[in] aMaxAge The Max-Age 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 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 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 AppendUriQueryOption(const char *aUriQuery); |
| |
| /** |
| * This method returns a pointer to the first option. |
| * |
| * @returns A pointer to the first option. |
| * |
| */ |
| const Option *GetFirstOption(void); |
| |
| /** |
| * This method returns a pointer to the next option. |
| * |
| * @returns A pointer to the next option. |
| * |
| */ |
| const Option *GetNextOption(void); |
| |
| /** |
| * This method adds Payload Marker indicating beginning of the payload to the CoAP header. |
| * |
| * @retval OT_ERROR_NONE Payload Marker successfully added. |
| * @retval OT_ERROR_NO_BUFS Header Payload Marker exceeds the buffer size. |
| * |
| */ |
| otError SetPayloadMarker(void); |
| |
| /** |
| * This method returns a pointer to the first byte of the header. |
| * |
| * @returns A pointer to the first byte of the header. |
| * |
| */ |
| const uint8_t *GetBytes(void) const { return mHeader.mBytes; } |
| |
| /** |
| * This method returns the header length in bytes. |
| * |
| * @returns The header length in bytes. |
| * |
| */ |
| uint8_t GetLength(void) const { return mHeaderLength; } |
| |
| /** |
| * This method sets a default response header based on request header. |
| * |
| * @param[in] aRequestHeader Request header to base on. |
| * |
| */ |
| void SetDefaultResponseHeader(const Header &aRequestHeader); |
| |
| /** |
| * This method checks if a header is an empty message header. |
| * |
| * @retval TRUE Header is an empty message header. |
| * @retval FALSE Header is not an empty message header. |
| * |
| */ |
| bool IsEmpty(void) const { return (GetCode() == 0); }; |
| |
| /** |
| * This method checks if a header is a request header. |
| * |
| * @retval TRUE Header is a request header. |
| * @retval FALSE Header is not a request header. |
| * |
| */ |
| bool IsRequest(void) const { return (GetCode() >= OT_COAP_CODE_GET && GetCode() <= OT_COAP_CODE_DELETE); }; |
| |
| /** |
| * This method checks if a header is a response header. |
| * |
| * @retval TRUE Header is a response header. |
| * @retval FALSE Header is not a response header. |
| * |
| */ |
| bool IsResponse(void) const { return (GetCode() >= OT_COAP_CODE_RESPONSE_MIN); }; |
| |
| /** |
| * This method checks if a header is a CON message header. |
| * |
| * @retval TRUE Header is a CON message header. |
| * @retval FALSE Header is not is a CON message header. |
| * |
| */ |
| bool IsConfirmable(void) const { return (GetType() == OT_COAP_TYPE_CONFIRMABLE); }; |
| |
| /** |
| * This method checks if a header is a NON message header. |
| * |
| * @retval TRUE Header is a NON message header. |
| * @retval FALSE Header is not is a NON message header. |
| * |
| */ |
| bool IsNonConfirmable(void) const { return (GetType() == OT_COAP_TYPE_NON_CONFIRMABLE); }; |
| |
| /** |
| * This method checks if a header is a ACK message header. |
| * |
| * @retval TRUE Header is a ACK message header. |
| * @retval FALSE Header is not is a ACK message header. |
| * |
| */ |
| bool IsAck(void) const { return (GetType() == OT_COAP_TYPE_ACKNOWLEDGMENT); }; |
| |
| /** |
| * This method checks if a header is a RST message header. |
| * |
| * @retval TRUE Header is a RST message header. |
| * @retval FALSE Header is not is a RST message header. |
| * |
| */ |
| bool IsReset(void) const { return (GetType() == OT_COAP_TYPE_RESET); }; |
| |
| private: |
| /** |
| * Protocol Constants (RFC 7252). |
| * |
| */ |
| enum |
| { |
| kVersionMask = 0xc0, ///< Version mask as specified (RFC 7252). |
| kVersionOffset = 6, ///< Version offset as specified (RFC 7252). |
| |
| kTypeMask = 0x30, ///< Type mask as specified (RFC 7252). |
| |
| kTokenLengthMask = 0x0f, ///< Token Length mask as specified (RFC 7252). |
| kTokenLengthOffset = 0, ///< Token Length offset as specified (RFC 7252). |
| kTokenOffset = 4, ///< Token offset as specified (RFC 7252). |
| kMaxTokenLength = 8, ///< Max token length as specified (RFC 7252). |
| |
| kMaxOptionHeaderSize = 5, ///< Maximum size of an Option header |
| |
| kOption1ByteExtension = 13, ///< Indicates a 1 byte extension (RFC 7252). |
| kOption2ByteExtension = 14, ///< Indicates a 1 byte extension (RFC 7252). |
| |
| kOption1ByteExtensionOffset = 13, ///< Delta/Length offset as specified (RFC 7252). |
| kOption2ByteExtensionOffset = 269, ///< Delta/Length offset as specified (RFC 7252). |
| }; |
| }; |
| |
| /** |
| * @} |
| * |
| */ |
| |
| } // namespace Coap |
| } // namespace ot |
| |
| #endif // COAP_HEADER_HPP_ |