text:
/**
 * @file
 * @brief
 *  This file defines the top-level functions for the OpenThread CoAP implementation.
 */

#ifndef OPENTHREAD_COAP_H_
#define OPENTHREAD_COAP_H_

#ifdef OPENTHREAD_CONFIG_FILE
#include OPENTHREAD_CONFIG_FILE
#else
#include <openthread-config.h>
#endif

#include <stdint.h>

#include "openthread/types.h"
#include "openthread/message.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @addtogroup coap  CoAP
 *
 * @brief
 *   This module includes functions that control CoAP communication.
 *
 * @{
 *
 */

#define OT_DEFAULT_COAP_PORT  5683  ///< Default CoAP port, as specified in RFC 7252

/**
 * CoAP Type values.
 *
 */
typedef enum otCoapType
{
    kCoapTypeConfirmable    = 0x00,  ///< Confirmable
    kCoapTypeNonConfirmable = 0x10,  ///< Non-confirmable
    kCoapTypeAcknowledgment = 0x20,  ///< Acknowledgment
    kCoapTypeReset          = 0x30,  ///< Reset
} otCoapType;

/**
 * CoAP Code values.
 *
 */
typedef enum otCoapCode
{
    kCoapCodeEmpty       = 0x00,  ///< Empty message code
    kCoapRequestGet      = 0x01,  ///< Get
    kCoapRequestPost     = 0x02,  ///< Post
    kCoapRequestPut      = 0x03,  ///< Put
    kCoapRequestDelete   = 0x04,  ///< Delete
    kCoapResponseCodeMin = 0x40,  ///< 2.00
    kCoapResponseCreated = 0x41,  ///< Created
    kCoapResponseDeleted = 0x42,  ///< Deleted
    kCoapResponseValid   = 0x43,  ///< Valid
    kCoapResponseChanged = 0x44,  ///< Changed
    kCoapResponseContent = 0x45,  ///< Content
} otCoapCode;

/**
 * CoAP Option Numbers
 */
typedef enum otCoapOptionType
{
    kCoapOptionObserve       = 6,    ///< Observe
    kCoapOptionUriPath       = 11,   ///< Uri-Path
    kCoapOptionContentFormat = 12,   ///< Content-Format
    kCoapOptionMaxAge        = 14,   ///< Max-Age
    kCoapOptionUriQuery      = 15,   ///< Uri-Query
} otCoapOptionType;

/**
 * This structure represents a CoAP option.
 *
 */
typedef struct otCoapOption
{
    uint16_t       mNumber;  ///< Option Number
    uint16_t       mLength;  ///< Option Length
    const uint8_t *mValue;   ///< A pointer to the Option Value
} otCoapOption;

#define OT_COAP_HEADER_MAX_LENGTH       128  ///< 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
    uint8_t mHeaderLength;                          ///< The CoAP header length (bytes)
    uint16_t mOptionLast;                           ///< The last CoAP Option Number value
    uint16_t mFirstOptionOffset;                    ///< The byte offset for the first CoAP Option
    uint16_t mNextOptionOffset;                     ///< The byte offset for the next CoAP Option
    otCoapOption mOption;                           ///< A structure representing the current CoAP Option.
} otCoapHeader;

/**
 * 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.
 *
 * @retval  kThreadError_None             A response was received successfully.
 * @retval  kThreadError_Abort            A CoAP transaction was reseted by peer.
 * @retval  kThreadError_ResponseTimeout  No response or acknowledgment received during timeout period.
 *
 */
typedef void (*otCoapResponseHandler)(void *aContext, otCoapHeader *aHeader, otMessage *aMessage,
                                      const otMessageInfo *aMessageInfo, ThreadError aResult);

/**
 * 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);

/**
 * This structure represents a CoAP resource.
 *
 */
typedef struct otCoapResource
{
    const char *mUriPath;           ///< The URI Path string
    otCoapRequestHandler mHandler;  ///< The callback for handling a received request
    void *mContext;                 ///< Application-specific context
    struct otCoapResource *mNext;   ///< The next CoAP resource in the list
} otCoapResource;

#if OPENTHREAD_ENABLE_APPLICATION_COAP
/**
 * 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.
 *
 */
void otCoapHeaderInit(otCoapHeader *aHeader, 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.
 *
 */
void otCoapHeaderSetToken(otCoapHeader *aHeader, 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[in]     aTokenLength  The Length of a Token to set.
 *
 */
void otCoapHeaderGenerateToken(otCoapHeader *aHeader, uint8_t aTokenLength);

/**
 * 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.
 *
 * @retval kThreadError_None         Successfully appended the option.
 * @retval kThreadError_InvalidArgs  The option type is not equal or greater than the last option type.
 * @retval kThreadError_NoBufs       The option length exceeds the buffer size.
 *
 */
ThreadError otCoapHeaderAppendOption(otCoapHeader *aHeader, const otCoapOption *aOption);

/**
 * This function appends an Observe option.
 *
 * @param[inout]  aHeader   A pointer to the CoAP header.
 * @param[in]     aObserve  Observe field value.
 *
 * @retval kThreadError_None         Successfully appended the option.
 * @retval kThreadError_InvalidArgs  The option type is not equal or greater than the last option type.
 * @retval kThreadError_NoBufs       The option length exceeds the buffer size.
 */
ThreadError otCoapHeaderAppendObserveOption(otCoapHeader *aHeader, uint32_t aObserve);

/**
 * This function appends an Uri-Path option.
 *
 * @param[inout]  aHeader   A pointer to the CoAP header.
 * @param[in]     aUriPath  A pointer to a NULL-terminated string.
 *
 * @retval kThreadError_None         Successfully appended the option.
 * @retval kThreadError_InvalidArgs  The option type is not equal or greater than the last option type.
 * @retval kThreadError_NoBufs       The option length exceeds the buffer size.
 *
 */
ThreadError otCoapHeaderAppendUriPathOptions(otCoapHeader *aHeader, const char *aUriPath);

/**
 * This function appends a Max-Age option.
 *
 * @param[inout]  aHeader   A pointer to the CoAP header.
 * @param[in]     aMaxAge   The Max-Age value.
 *
 * @retval kThreadError_None         Successfully appended the option.
 * @retval kThreadError_InvalidArgs  The option type is not equal or greater than the last option type.
 * @retval kThreadError_NoBufs       The option length exceeds the buffer size.
 */
ThreadError otCoapHeaderAppendMaxAgeOption(otCoapHeader *aHeader, uint32_t aMaxAge);

/**
 * This function appends a single Uri-Query option.
 *
 * @param[inout]  aHeader   A pointer to the CoAP header.
 * @param[in]     aUriQuery A pointer to NULL-terminated string, which should contain a single key=value pair.
 *
 * @retval kThreadError_None         Successfully appended the option.
 * @retval kThreadError_InvalidArgs  The option type is not equal or greater than the last option type.
 * @retval kThreadError_NoBufs       The option length exceeds the buffer size.
 */
ThreadError otCoapHeaderAppendUriQueryOption(otCoapHeader *aHeader, const char *aUriQuery);

/**
 * This function adds Payload Marker indicating beginning of the payload to the CoAP header.
 *
 * @param[inout]  aHeader  A pointer to the CoAP header.
 *
 * @retval kThreadError_None    Payload Marker successfully added.
 * @retval kThreadError_NoBufs  Header Payload Marker exceeds the buffer size.
 *
 */
void otCoapHeaderSetPayloadMarker(otCoapHeader *aHeader);

/**
 * This function sets the Message ID value.
 *
 * @param[in]  aHeader     A pointer to the CoAP header.
 * @param[in]  aMessageId  The Message ID value.
 *
 */
void otCoapHeaderSetMessageId(otCoapHeader *aHeader, uint16_t aMessageId);

/**
 * This function returns the Type value.
 *
 * @param[in]  aHeader  A pointer to the CoAP header.
 *
 * @returns The Type value.
 *
 */
otCoapType otCoapHeaderGetType(const otCoapHeader *aHeader);

/**
 * This function returns the Code value.
 *
 * @param[in]  aHeader  A pointer to the CoAP header.
 *
 * @returns The Code value.
 *
 */
otCoapCode otCoapHeaderGetCode(const otCoapHeader *aHeader);

/**
* This function returns the Message ID value.
*
* @param[in]  aHeader  A pointer to the CoAP header.
*
* @returns The Message ID value.
*
*/
uint16_t otCoapHeaderGetMessageId(const otCoapHeader *aHeader);

/**
 * This function returns the Token length.
 *
 * @param[in]  aHeader  A pointer to the CoAP header.
 *
 * @returns The Token length.
 *
 */
uint8_t otCoapHeaderGetTokenLength(const otCoapHeader *aHeader);

/**
 * This function returns a pointer to the Token value.
 *
 * @param[in]  aHeader  A pointer to the CoAP header.
 *
 * @returns A pointer to the Token value.
 *
 */
const uint8_t *otCoapHeaderGetToken(const otCoapHeader *aHeader);

/**
 * This function returns a pointer to the first option.
 *
 * @param[in]  aHeader  A pointer to the CoAP header.
 *
 * @returns A pointer to the first option. If no option is present NULL pointer is returned.
 *
 */
const otCoapOption *otCoapHeaderGetFirstOption(otCoapHeader *aHeader);

/**
 * This function returns a pointer to the next option.
 *
 * @param[in]  aHeader  A pointer to the CoAP header.
 *
 * @returns A pointer to the next option. If no more options are present NULL pointer is returned.
 *
 */
const otCoapOption *otCoapHeaderGetNextOption(otCoapHeader *aHeader);

/**
 * This function creates a new message with a CoAP header.
 *
 * @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.
 *
 * @returns A pointer to the message or NULL if failed to allocate message.
 *
 */
otMessage *otCoapNewMessage(otInstance *aInstance, const otCoapHeader *aHeader);

/**
 * This function sends a CoAP request.
 *
 * If a response for a request is expected, respective function and context information should be provided.
 * If no response is expected, these arguments should be NULL pointers.
 *
 * @param[in]  aInstance     A pointer to an OpenThread instance.
 * @param[in]  aMessage      A pointer to the message to send.
 * @param[in]  aMessageInfo  A pointer to the message info associated with @p aMessage.
 * @param[in]  aHandler      A function pointer that shall be called on response reception or timeout.
 * @param[in]  aContext      A pointer to arbitrary context information. May be NULL if not used.
 *
 * @retval kThreadError_None   Successfully sent CoAP message.
 * @retval kThreadError_NoBufs Failed to allocate retransmission data.
 *
 */
ThreadError otCoapSendRequest(otInstance *aInstance, otMessage *aMessage, const otMessageInfo *aMessageInfo,
                              otCoapResponseHandler aHandler, void *aContext);

/**
 * This function starts the CoAP server.
 *
 * @param[in]  aInstance  A pointer to an OpenThread instance.
 *
 * @retval kThreadError_None  Successfully started the CoAP server.
 *
 */
ThreadError otCoapServerStart(otInstance *aInstance);

/**
 * This function stops the CoAP server.
 *
 * @param[in]  aInstance  A pointer to an OpenThread instance.
 *
 * @retval kThreadError_None  Successfully stopped the CoAP server.
 *
 */
ThreadError otCoapServerStop(otInstance *aInstance);

/**
 * This function sets CoAP server's port number.
 *
 * @param[in]  aInstance  A pointer to an OpenThread instance.
 * @param[in]  aPort  A port number to set.
 *
 * @retval kThreadError_None  Binding with a port succeeded.
 *
 */
ThreadError otCoapServerSetPort(otInstance *aInstance, uint16_t aPort);

/**
 * This function adds a resource to the CoAP server.
 *
 * @param[in]  aInstance  A pointer to an OpenThread instance.
 * @param[in]  aResource  A pointer to the resource.
 *
 * @retval kThreadError_None     Successfully added @p aResource.
 * @retval kThreadError_Already  The @p aResource was already added.
 *
 */
ThreadError otCoapServerAddResource(otInstance *aInstance, otCoapResource *aResource);

/**
 * This function removes a resource from the CoAP server.
 *
 * @param[in]  aInstance  A pointer to an OpenThread instance.
 * @param[in]  aResource  A pointer to the resource.
 *
 */
void otCoapServerRemoveResource(otInstance *aInstance, otCoapResource *aResource);

/**
 * This function sends a CoAP response from the server.
 *
 * @param[in]  aInstance     A pointer to an OpenThread instance.
 * @param[in]  aMessage      A pointer to the CoAP response to send.
 * @param[in]  aMessageInfo  A pointer to the message info associated with @p aMessage.
 *
 * @retval kThreadError_None    Successfully enqueued the CoAP response message.
 * @retval kThreadError_NoBufs  Insufficient buffers available to send the CoAP response.
 *
 */
ThreadError otCoapSendResponse(otInstance *aInstance, otMessage *aMessage, const otMessageInfo *aMessageInfo);
#endif // OPENTHREAD_ENABLE_APPLICATION_COAP

/**
 * @}
 *
 */

#ifdef __cplusplus
}  // extern "C"
#endif

#endif /* OPENTHREAD_COAP_H_ */