blob: ceaa4e2dea7466060745aef038c15cad23261155 [file] [log] [blame]
/*
* 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_