mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
gcoap: Move from gnrc directory up to net directory
This commit is contained in:
parent
aab48458da
commit
fa815993ae
@ -96,10 +96,6 @@ ifneq (,$(filter gnrc_zep,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gcoap,$(USEMODULE)))
|
||||
USEMODULE += gnrc_udp
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_tftp,$(USEMODULE)))
|
||||
USEMODULE += gnrc_udp
|
||||
USEMODULE += xtimer
|
||||
|
@ -99,6 +99,9 @@ endif
|
||||
ifneq (,$(filter sema,$(USEMODULE)))
|
||||
DIRS += sema
|
||||
endif
|
||||
ifneq (,$(filter gcoap,$(USEMODULE)))
|
||||
DIRS += net/application_layer/coap
|
||||
endif
|
||||
|
||||
DIRS += $(dir $(wildcard $(addsuffix /Makefile, ${USEMODULE})))
|
||||
|
||||
|
388
sys/include/net/gcoap.h
Normal file
388
sys/include/net/gcoap.h
Normal file
@ -0,0 +1,388 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2016 Ken Bannister. All rights reserved.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup net_gcoap CoAP
|
||||
* @ingroup net
|
||||
* @brief sock-based implementation of CoAP protocol, RFC 7252
|
||||
*
|
||||
* ## Architecture ##
|
||||
* Requests and responses are exchanged via an asynchronous RIOT message
|
||||
* processing thread. Depends on nanocoap for base level structs and
|
||||
* functionality.
|
||||
*
|
||||
* Uses a single UDP port for communication to support RFC 6282 compression.
|
||||
*
|
||||
* ## Server Operation ##
|
||||
*
|
||||
* gcoap listens for requests on GCOAP_PORT, 5683 by default. You can redefine
|
||||
* this by uncommenting the appropriate lines in gcoap's make file.
|
||||
*
|
||||
* gcoap allows an application to specify a collection of request resource paths
|
||||
* it wants to be notified about. Create an array of resources, coap_resource_t
|
||||
* structs. Use gcoap_register_listener() at application startup to pass in
|
||||
* these resources, wrapped in a gcoap_listener_t.
|
||||
*
|
||||
* gcoap itself defines a resource for `/.well-known/core` discovery, which
|
||||
* lists all of the registered paths.
|
||||
*
|
||||
* ### Creating a response ###
|
||||
*
|
||||
* An application resource includes a callback function, a coap_handler_t. After
|
||||
* reading the request, the callback must use one or two functions provided by
|
||||
* gcoap to format the response, as described below. The callback *must* read
|
||||
* the request thoroughly before calling the functions, because the response
|
||||
* buffer likely reuses the request buffer. See `examples/gcoap/gcoap_cli.c`
|
||||
* for a simple example of a callback.
|
||||
*
|
||||
* Here is the expected sequence for a callback function:
|
||||
*
|
||||
* Read request completely and parse request payload, if any. Use the
|
||||
* coap_pkt_t _payload_ and _payload_len_ attributes.
|
||||
*
|
||||
* If there is a payload, follow the three steps below.
|
||||
*
|
||||
* -# Call gcoap_resp_init() to initialize the response.
|
||||
* -# Write the request payload, starting at the updated _payload_ pointer
|
||||
* in the coap_pkt_t. If some error occurs, return a negative errno
|
||||
* code from the handler, and gcoap will send a server error (5.00).
|
||||
* -# Call gcoap_finish() to complete the PDU after writing the payload,
|
||||
* and return the result. gcoap will send the message.
|
||||
*
|
||||
* If no payload, call only gcoap_response() to write the full response.
|
||||
* Alternatively, you still can use gcoap_resp_init() and gcoap_finish(), as
|
||||
* described above. In fact, the gcoap_response() function is inline, and uses
|
||||
* those two functions.
|
||||
*
|
||||
* ## Client Operation ##
|
||||
*
|
||||
* gcoap uses RIOT's asynchronous messaging facility to send and receive
|
||||
* messages. So, client operation includes two phases: creating and sending a
|
||||
* request, and handling the response aynchronously in a client supplied
|
||||
* callback. See `examples/gcoap/gcoap_cli.c` for a simple example of sending
|
||||
* a request and reading the response.
|
||||
*
|
||||
* ### Creating a request ###
|
||||
*
|
||||
* Here is the expected sequence for preparing and sending a request:
|
||||
*
|
||||
* Allocate a buffer and a coap_pkt_t for the request.
|
||||
*
|
||||
* If there is a payload, follow the three steps below.
|
||||
*
|
||||
* -# Call gcoap_req_init() to initialize the request.
|
||||
* -# Write the request payload, starting at the updated _payload_ pointer
|
||||
* in the coap_pkt_t.
|
||||
* -# Call gcoap_finish(), which updates the packet for the payload.
|
||||
*
|
||||
* If no payload, call only gcoap_request() to write the full request.
|
||||
* Alternatively, you still can use gcoap_req_init() and gcoap_finish(),
|
||||
* as described above. The gcoap_request() function is inline, and uses those
|
||||
* two functions.
|
||||
*
|
||||
* Finally, call gcoap_req_send() with the destination host and port, as well
|
||||
* as a callback function for the host's response.
|
||||
*
|
||||
* ### Handling the response ###
|
||||
*
|
||||
* When gcoap receives the response to a request, it executes the callback from
|
||||
* the request. gcoap also executes the callback when a response is not
|
||||
* received within GCOAP_RESPONSE_TIMEOUT.
|
||||
*
|
||||
* Here is the expected sequence for handling a response in the callback.
|
||||
*
|
||||
* -# Test for a server response or timeout in the _req_state_ callback
|
||||
* parameter. See the GCOAP_MEMO... constants.
|
||||
* -# Test the response with coap_get_code_class() and coap_get_code_detail().
|
||||
* -# Test the response payload with the coap_pkt_t _payload_len_ and
|
||||
* _content_type_ attributes.
|
||||
* -# Read the payload, if any.
|
||||
*
|
||||
* ## Implementation Notes ##
|
||||
*
|
||||
* ### Building a packet ###
|
||||
*
|
||||
* The sequence and functions described above to build a request or response
|
||||
* is designed to provide a relatively simple API for the user.
|
||||
*
|
||||
* The structure of a CoAP PDU requires that options are placed between the
|
||||
* header and the payload. So, gcoap provides space in the buffer for them in
|
||||
* the request/response ...init() function, and then writes them during
|
||||
* gcoap_finish(). We trade some inefficiency/work in the buffer for
|
||||
* simplicity for the user.
|
||||
*
|
||||
* ### Waiting for a response ###
|
||||
*
|
||||
* We take advantage of RIOT's GNRC stack by using an xtimer to wait for a
|
||||
* response, so the gcoap thread does not block while waiting. The user is
|
||||
* notified via the same callback whether the message is received or the wait
|
||||
* times out. We track the response with an entry in the
|
||||
* `_coap_state.open_reqs` array.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief gcoap definition
|
||||
*
|
||||
* @author Ken Bannister <kb2ma@runbox.com>
|
||||
*/
|
||||
|
||||
#ifndef GCOAP_H
|
||||
#define GCOAP_H
|
||||
|
||||
#include "net/gnrc.h"
|
||||
#include "net/gnrc/ipv6.h"
|
||||
#include "net/gnrc/udp.h"
|
||||
#include "nanocoap.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Size for module message queue */
|
||||
#define GCOAP_MSG_QUEUE_SIZE (4)
|
||||
|
||||
/** @brief Server port; use RFC 7252 default if not defined */
|
||||
#ifndef GCOAP_PORT
|
||||
#define GCOAP_PORT (5683)
|
||||
#endif
|
||||
|
||||
/** @brief Size of the buffer used to build a CoAP request or response. */
|
||||
#define GCOAP_PDU_BUF_SIZE (128)
|
||||
|
||||
/**
|
||||
* @brief Size of the buffer used to write options, other than Uri-Path, in a
|
||||
* request.
|
||||
*
|
||||
* Accommodates Content-Format.
|
||||
*/
|
||||
#define GCOAP_REQ_OPTIONS_BUF (8)
|
||||
|
||||
/**
|
||||
* @brief Size of the buffer used to write options in a response.
|
||||
*
|
||||
* Accommodates Content-Format.
|
||||
*/
|
||||
#define GCOAP_RESP_OPTIONS_BUF (8)
|
||||
|
||||
/** @brief Maximum number of requests awaiting a response */
|
||||
#define GCOAP_REQ_WAITING_MAX (2)
|
||||
|
||||
/** @brief Maximum length in bytes for a token */
|
||||
#define GCOAP_TOKENLEN_MAX (8)
|
||||
|
||||
/** @brief Maximum length in bytes for a header, including the token */
|
||||
#define GCOAP_HEADER_MAXLEN (sizeof(coap_hdr_t) + GCOAP_TOKENLEN_MAX)
|
||||
|
||||
/** @brief Length in bytes for a token; use 2 if not defined */
|
||||
#ifndef GCOAP_TOKENLEN
|
||||
#define GCOAP_TOKENLEN (2)
|
||||
#endif
|
||||
|
||||
/** @brief Marks the boundary between header and payload */
|
||||
#define GCOAP_PAYLOAD_MARKER (0xFF)
|
||||
|
||||
/**
|
||||
* @name States for the memo used to track waiting for a response
|
||||
* @{
|
||||
*/
|
||||
#define GCOAP_MEMO_UNUSED (0) /**< This memo is unused */
|
||||
#define GCOAP_MEMO_WAIT (1) /**< Request sent; awaiting response */
|
||||
#define GCOAP_MEMO_RESP (2) /**< Got response */
|
||||
#define GCOAP_MEMO_TIMEOUT (3) /**< Timeout waiting for response */
|
||||
#define GCOAP_MEMO_ERR (4) /**< Error processing response packet */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Default time to wait for a non-confirmable response, in usec
|
||||
*
|
||||
* Set to 0 to disable timeout.
|
||||
*/
|
||||
#define GCOAP_NON_TIMEOUT (5000000U)
|
||||
|
||||
/** @brief Identifies a gcoap-specific timeout IPC message */
|
||||
#define GCOAP_NETAPI_MSG_TYPE_TIMEOUT (0x1501)
|
||||
|
||||
/**
|
||||
* @brief A modular collection of resources for a server
|
||||
*/
|
||||
typedef struct gcoap_listener {
|
||||
coap_resource_t *resources; /**< First element in the array of resources;
|
||||
must order alphabetically */
|
||||
size_t resources_len; /**< Length of array */
|
||||
struct gcoap_listener *next; /**< Next listener in list */
|
||||
} gcoap_listener_t;
|
||||
|
||||
/**
|
||||
* @brief Handler function for a server response, including the state for the
|
||||
* originating request.
|
||||
*
|
||||
* If request timed out, the packet header is for the request.
|
||||
*/
|
||||
typedef void (*gcoap_resp_handler_t)(unsigned req_state, coap_pkt_t* pdu);
|
||||
|
||||
/**
|
||||
* @brief Memo to handle a response for a request
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned state; /**< State of this memo, a GCOAP_MEMO... */
|
||||
uint8_t hdr_buf[GCOAP_HEADER_MAXLEN];
|
||||
/**< Stores a copy of the request header */
|
||||
gcoap_resp_handler_t resp_handler; /**< Callback for the response */
|
||||
xtimer_t response_timer; /**< Limits wait for response */
|
||||
msg_t timeout_msg; /**< For response timer */
|
||||
} gcoap_request_memo_t;
|
||||
|
||||
/**
|
||||
* @brief Container for the state of gcoap itself
|
||||
*/
|
||||
typedef struct {
|
||||
gnrc_netreg_entry_t netreg_port; /**< Registration for IP port */
|
||||
gcoap_listener_t *listeners; /**< List of registered listeners */
|
||||
gcoap_request_memo_t open_reqs[GCOAP_REQ_WAITING_MAX];
|
||||
/**< Storage for open requests; if first
|
||||
byte of an entry is zero, the entry
|
||||
is available */
|
||||
uint16_t last_message_id; /**< Last message ID used */
|
||||
} gcoap_state_t;
|
||||
|
||||
/**
|
||||
* @brief Initializes the gcoap thread and device.
|
||||
*
|
||||
* Must call once before first use.
|
||||
*
|
||||
* @return PID of the gcoap thread on success.
|
||||
* @return -EEXIST, if thread already has been created.
|
||||
* @return -EINVAL, if the IP port already is in use.
|
||||
*/
|
||||
kernel_pid_t gcoap_init(void);
|
||||
|
||||
/**
|
||||
* @brief Starts listening for resource paths.
|
||||
*
|
||||
* @param listener Listener containing the resources.
|
||||
*/
|
||||
void gcoap_register_listener(gcoap_listener_t *listener);
|
||||
|
||||
/**
|
||||
* @brief Initializes a CoAP request PDU on a buffer.
|
||||
*
|
||||
* @param[in] pdu Request metadata
|
||||
* @param[in] buf Buffer containing the PDU
|
||||
* @param[in] len Length of the buffer
|
||||
* @param[in] code Request code
|
||||
* @param[in] path Resource path
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return < 0 on error
|
||||
*/
|
||||
int gcoap_req_init(coap_pkt_t *pdu, uint8_t *buf, size_t len, unsigned code,
|
||||
char *path);
|
||||
|
||||
/**
|
||||
* @brief Finishes formatting a CoAP PDU after the payload has been written.
|
||||
*
|
||||
* Assumes the PDU has been initialized with gcoap_req_init() or
|
||||
* gcoap_resp_init().
|
||||
*
|
||||
* @param[in] pdu Request metadata
|
||||
* @param[in] payload_len Length of the payload, or 0 if none
|
||||
* @param[in] format Format code for the payload; use COAP_FORMAT_NONE if not
|
||||
* specified
|
||||
*
|
||||
* @return size of the PDU
|
||||
* @return < 0 on error
|
||||
*/
|
||||
ssize_t gcoap_finish(coap_pkt_t *pdu, size_t payload_len, unsigned format);
|
||||
|
||||
/**
|
||||
* @brief Writes a complete CoAP request PDU when there is not a payload.
|
||||
*
|
||||
* @param[in] pdu Request metadata
|
||||
* @param[in] buf Buffer containing the PDU
|
||||
* @param[in] len Length of the buffer
|
||||
* @param[in] code Request code
|
||||
* @param[in] path Resource path
|
||||
*
|
||||
* @return size of the PDU within the buffer
|
||||
* @return < 0 on error
|
||||
*/
|
||||
static inline ssize_t gcoap_request(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
||||
unsigned code,
|
||||
char *path)
|
||||
{
|
||||
return (gcoap_req_init(pdu, buf, len, code, path) == 0)
|
||||
? gcoap_finish(pdu, 0, COAP_FORMAT_NONE)
|
||||
: -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a buffer containing a CoAP request to the provided host/port.
|
||||
*
|
||||
* @param[in] buf Buffer containing the PDU
|
||||
* @param[in] len Length of the buffer
|
||||
* @param[in] addr Destination for the packet
|
||||
* @param[in] port Port at the destination
|
||||
* @param[in] resp_handler Callback when response received
|
||||
*
|
||||
* @return length of the packet
|
||||
* @return 0 if cannot send
|
||||
*/
|
||||
size_t gcoap_req_send(uint8_t *buf, size_t len, ipv6_addr_t *addr, uint16_t port,
|
||||
gcoap_resp_handler_t resp_handler);
|
||||
|
||||
/**
|
||||
* @brief Initializes a CoAP response packet on a buffer.
|
||||
*
|
||||
* Initializes payload location within the buffer based on packet setup.
|
||||
*
|
||||
* @param[in] pdu Response metadata
|
||||
* @param[in] buf Buffer containing the PDU
|
||||
* @param[in] len Length of the buffer
|
||||
* @param[in] code Response code
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return < 0 on error
|
||||
*/
|
||||
int gcoap_resp_init(coap_pkt_t *pdu, uint8_t *buf, size_t len, unsigned code);
|
||||
|
||||
/**
|
||||
* @brief Writes a complete CoAP response PDU when there is no payload.
|
||||
*
|
||||
* @param[in] pdu Response metadata
|
||||
* @param[in] buf Buffer containing the PDU
|
||||
* @param[in] len Length of the buffer
|
||||
* @param[in] code Response code
|
||||
*
|
||||
* @return size of the PDU within the buffer
|
||||
* @return < 0 on error
|
||||
*/
|
||||
static inline ssize_t gcoap_response(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
||||
unsigned code)
|
||||
{
|
||||
return (gcoap_resp_init(pdu, buf, len, code) == 0)
|
||||
? gcoap_finish(pdu, 0, COAP_FORMAT_NONE)
|
||||
: -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provides important operational statistics.
|
||||
*
|
||||
* Useful for monitoring.
|
||||
*
|
||||
* @param[out] open_reqs Count of unanswered requests
|
||||
*/
|
||||
void gcoap_op_state(uint8_t *open_reqs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GCOAP_H */
|
||||
/** @} */
|
@ -7,382 +7,17 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup net_gnrc_coap CoAP
|
||||
* @ingroup net_gnrc
|
||||
* @brief GNRC implementation of CoAP protocol, RFC 7252
|
||||
*
|
||||
* ## Architecture ##
|
||||
* Requests and responses are exchanged via an asynchronous RIOT message
|
||||
* processing thread. Depends on nanocoap for base level structs and
|
||||
* functionality.
|
||||
*
|
||||
* Uses a single UDP port for communication to support RFC 6282 compression.
|
||||
*
|
||||
* ## Server Operation ##
|
||||
*
|
||||
* gcoap listens for requests on GCOAP_PORT, 5683 by default. You can redefine
|
||||
* this by uncommenting the appropriate lines in gcoap's make file.
|
||||
*
|
||||
* gcoap allows an application to specify a collection of request resource paths
|
||||
* it wants to be notified about. Create an array of resources, coap_resource_t
|
||||
* structs. Use gcoap_register_listener() at application startup to pass in
|
||||
* these resources, wrapped in a gcoap_listener_t.
|
||||
*
|
||||
* gcoap itself defines a resource for `/.well-known/core` discovery, which
|
||||
* lists all of the registered paths.
|
||||
*
|
||||
* ### Creating a response ###
|
||||
*
|
||||
* An application resource includes a callback function, a coap_handler_t. After
|
||||
* reading the request, the callback must use one or two functions provided by
|
||||
* gcoap to format the response, as described below. The callback *must* read
|
||||
* the request thoroughly before calling the functions, because the response
|
||||
* buffer likely reuses the request buffer. See `examples/gcoap/gcoap_cli.c`
|
||||
* for a simple example of a callback.
|
||||
*
|
||||
* Here is the expected sequence for a callback function:
|
||||
*
|
||||
* Read request completely and parse request payload, if any. Use the
|
||||
* coap_pkt_t _payload_ and _payload_len_ attributes.
|
||||
*
|
||||
* If there is a payload, follow the three steps below.
|
||||
*
|
||||
* -# Call gcoap_resp_init() to initialize the response.
|
||||
* -# Write the request payload, starting at the updated _payload_ pointer
|
||||
* in the coap_pkt_t. If some error occurs, return a negative errno
|
||||
* code from the handler, and gcoap will send a server error (5.00).
|
||||
* -# Call gcoap_finish() to complete the PDU after writing the payload,
|
||||
* and return the result. gcoap will send the message.
|
||||
*
|
||||
* If no payload, call only gcoap_response() to write the full response.
|
||||
* Alternatively, you still can use gcoap_resp_init() and gcoap_finish(), as
|
||||
* described above. In fact, the gcoap_response() function is inline, and uses
|
||||
* those two functions.
|
||||
*
|
||||
* ## Client Operation ##
|
||||
*
|
||||
* gcoap uses RIOT's asynchronous messaging facility to send and receive
|
||||
* messages. So, client operation includes two phases: creating and sending a
|
||||
* request, and handling the response aynchronously in a client supplied
|
||||
* callback. See `examples/gcoap/gcoap_cli.c` for a simple example of sending
|
||||
* a request and reading the response.
|
||||
*
|
||||
* ### Creating a request ###
|
||||
*
|
||||
* Here is the expected sequence for preparing and sending a request:
|
||||
*
|
||||
* Allocate a buffer and a coap_pkt_t for the request.
|
||||
*
|
||||
* If there is a payload, follow the three steps below.
|
||||
*
|
||||
* -# Call gcoap_req_init() to initialize the request.
|
||||
* -# Write the request payload, starting at the updated _payload_ pointer
|
||||
* in the coap_pkt_t.
|
||||
* -# Call gcoap_finish(), which updates the packet for the payload.
|
||||
*
|
||||
* If no payload, call only gcoap_request() to write the full request.
|
||||
* Alternatively, you still can use gcoap_req_init() and gcoap_finish(),
|
||||
* as described above. The gcoap_request() function is inline, and uses those
|
||||
* two functions.
|
||||
*
|
||||
* Finally, call gcoap_req_send() with the destination host and port, as well
|
||||
* as a callback function for the host's response.
|
||||
*
|
||||
* ### Handling the response ###
|
||||
*
|
||||
* When gcoap receives the response to a request, it executes the callback from
|
||||
* the request. gcoap also executes the callback when a response is not
|
||||
* received within GCOAP_RESPONSE_TIMEOUT.
|
||||
*
|
||||
* Here is the expected sequence for handling a response in the callback.
|
||||
*
|
||||
* -# Test for a server response or timeout in the _req_state_ callback
|
||||
* parameter. See the GCOAP_MEMO... constants.
|
||||
* -# Test the response with coap_get_code_class() and coap_get_code_detail().
|
||||
* -# Test the response payload with the coap_pkt_t _payload_len_ and
|
||||
* _content_type_ attributes.
|
||||
* -# Read the payload, if any.
|
||||
*
|
||||
* ## Implementation Notes ##
|
||||
*
|
||||
* ### Building a packet ###
|
||||
*
|
||||
* The sequence and functions described above to build a request or response
|
||||
* is designed to provide a relatively simple API for the user.
|
||||
*
|
||||
* The structure of a CoAP PDU requires that options are placed between the
|
||||
* header and the payload. So, gcoap provides space in the buffer for them in
|
||||
* the request/response ...init() function, and then writes them during
|
||||
* gcoap_finish(). We trade some inefficiency/work in the buffer for
|
||||
* simplicity for the user.
|
||||
*
|
||||
* ### Waiting for a response ###
|
||||
*
|
||||
* We take advantage of RIOT's GNRC stack by using an xtimer to wait for a
|
||||
* response, so the gcoap thread does not block while waiting. The user is
|
||||
* notified via the same callback whether the message is received or the wait
|
||||
* times out. We track the response with an entry in the
|
||||
* `_coap_state.open_reqs` array.
|
||||
* @ingroup net_gcoap
|
||||
* @brief Adapter for migration of GNRC-based gcoap to sock-based gcoap
|
||||
* @deprecated Use net/gcoap.h instead.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief gcoap definition
|
||||
*
|
||||
* @author Ken Bannister <kb2ma@runbox.com>
|
||||
*/
|
||||
|
||||
#ifndef GCOAP_H
|
||||
#define GCOAP_H
|
||||
#include "net/gcoap.h"
|
||||
|
||||
#include "net/gnrc.h"
|
||||
#include "net/gnrc/ipv6.h"
|
||||
#include "net/gnrc/udp.h"
|
||||
#include "nanocoap.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Size for module message queue */
|
||||
#define GCOAP_MSG_QUEUE_SIZE (4)
|
||||
|
||||
/** @brief Server port; use RFC 7252 default if not defined */
|
||||
#ifndef GCOAP_PORT
|
||||
#define GCOAP_PORT (5683)
|
||||
#endif
|
||||
|
||||
/** @brief Size of the buffer used to build a CoAP request or response. */
|
||||
#define GCOAP_PDU_BUF_SIZE (128)
|
||||
|
||||
/**
|
||||
* @brief Size of the buffer used to write options, other than Uri-Path, in a
|
||||
* request.
|
||||
*
|
||||
* Accommodates Content-Format.
|
||||
*/
|
||||
#define GCOAP_REQ_OPTIONS_BUF (8)
|
||||
|
||||
/**
|
||||
* @brief Size of the buffer used to write options in a response.
|
||||
*
|
||||
* Accommodates Content-Format.
|
||||
*/
|
||||
#define GCOAP_RESP_OPTIONS_BUF (8)
|
||||
|
||||
/** @brief Maximum number of requests awaiting a response */
|
||||
#define GCOAP_REQ_WAITING_MAX (2)
|
||||
|
||||
/** @brief Maximum length in bytes for a token */
|
||||
#define GCOAP_TOKENLEN_MAX (8)
|
||||
|
||||
/** @brief Maximum length in bytes for a header, including the token */
|
||||
#define GCOAP_HEADER_MAXLEN (sizeof(coap_hdr_t) + GCOAP_TOKENLEN_MAX)
|
||||
|
||||
/** @brief Length in bytes for a token; use 2 if not defined */
|
||||
#ifndef GCOAP_TOKENLEN
|
||||
#define GCOAP_TOKENLEN (2)
|
||||
#endif
|
||||
|
||||
/** @brief Marks the boundary between header and payload */
|
||||
#define GCOAP_PAYLOAD_MARKER (0xFF)
|
||||
|
||||
/**
|
||||
* @name States for the memo used to track waiting for a response
|
||||
* @{
|
||||
*/
|
||||
#define GCOAP_MEMO_UNUSED (0) /**< This memo is unused */
|
||||
#define GCOAP_MEMO_WAIT (1) /**< Request sent; awaiting response */
|
||||
#define GCOAP_MEMO_RESP (2) /**< Got response */
|
||||
#define GCOAP_MEMO_TIMEOUT (3) /**< Timeout waiting for response */
|
||||
#define GCOAP_MEMO_ERR (4) /**< Error processing response packet */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Default time to wait for a non-confirmable response, in usec
|
||||
*
|
||||
* Set to 0 to disable timeout.
|
||||
*/
|
||||
#define GCOAP_NON_TIMEOUT (5000000U)
|
||||
|
||||
/** @brief Identifies a gcoap-specific timeout IPC message */
|
||||
#define GCOAP_NETAPI_MSG_TYPE_TIMEOUT (0x1501)
|
||||
|
||||
/**
|
||||
* @brief A modular collection of resources for a server
|
||||
*/
|
||||
typedef struct gcoap_listener {
|
||||
coap_resource_t *resources; /**< First element in the array of resources;
|
||||
must order alphabetically */
|
||||
size_t resources_len; /**< Length of array */
|
||||
struct gcoap_listener *next; /**< Next listener in list */
|
||||
} gcoap_listener_t;
|
||||
|
||||
/**
|
||||
* @brief Handler function for a server response, including the state for the
|
||||
* originating request.
|
||||
*
|
||||
* If request timed out, the packet header is for the request.
|
||||
*/
|
||||
typedef void (*gcoap_resp_handler_t)(unsigned req_state, coap_pkt_t* pdu);
|
||||
|
||||
/**
|
||||
* @brief Memo to handle a response for a request
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned state; /**< State of this memo, a GCOAP_MEMO... */
|
||||
uint8_t hdr_buf[GCOAP_HEADER_MAXLEN];
|
||||
/**< Stores a copy of the request header */
|
||||
gcoap_resp_handler_t resp_handler; /**< Callback for the response */
|
||||
xtimer_t response_timer; /**< Limits wait for response */
|
||||
msg_t timeout_msg; /**< For response timer */
|
||||
} gcoap_request_memo_t;
|
||||
|
||||
/**
|
||||
* @brief Container for the state of gcoap itself
|
||||
*/
|
||||
typedef struct {
|
||||
gnrc_netreg_entry_t netreg_port; /**< Registration for IP port */
|
||||
gcoap_listener_t *listeners; /**< List of registered listeners */
|
||||
gcoap_request_memo_t open_reqs[GCOAP_REQ_WAITING_MAX];
|
||||
/**< Storage for open requests; if first
|
||||
byte of an entry is zero, the entry
|
||||
is available */
|
||||
uint16_t last_message_id; /**< Last message ID used */
|
||||
} gcoap_state_t;
|
||||
|
||||
/**
|
||||
* @brief Initializes the gcoap thread and device.
|
||||
*
|
||||
* Must call once before first use.
|
||||
*
|
||||
* @return PID of the gcoap thread on success.
|
||||
* @return -EEXIST, if thread already has been created.
|
||||
* @return -EINVAL, if the IP port already is in use.
|
||||
*/
|
||||
kernel_pid_t gcoap_init(void);
|
||||
|
||||
/**
|
||||
* @brief Starts listening for resource paths.
|
||||
*
|
||||
* @param listener Listener containing the resources.
|
||||
*/
|
||||
void gcoap_register_listener(gcoap_listener_t *listener);
|
||||
|
||||
/**
|
||||
* @brief Initializes a CoAP request PDU on a buffer.
|
||||
*
|
||||
* @param[in] pdu Request metadata
|
||||
* @param[in] buf Buffer containing the PDU
|
||||
* @param[in] len Length of the buffer
|
||||
* @param[in] code Request code
|
||||
* @param[in] path Resource path
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return < 0 on error
|
||||
*/
|
||||
int gcoap_req_init(coap_pkt_t *pdu, uint8_t *buf, size_t len, unsigned code,
|
||||
char *path);
|
||||
|
||||
/**
|
||||
* @brief Finishes formatting a CoAP PDU after the payload has been written.
|
||||
*
|
||||
* Assumes the PDU has been initialized with gcoap_req_init() or
|
||||
* gcoap_resp_init().
|
||||
*
|
||||
* @param[in] pdu Request metadata
|
||||
* @param[in] payload_len Length of the payload, or 0 if none
|
||||
* @param[in] format Format code for the payload; use COAP_FORMAT_NONE if not
|
||||
* specified
|
||||
*
|
||||
* @return size of the PDU
|
||||
* @return < 0 on error
|
||||
*/
|
||||
ssize_t gcoap_finish(coap_pkt_t *pdu, size_t payload_len, unsigned format);
|
||||
|
||||
/**
|
||||
* @brief Writes a complete CoAP request PDU when there is not a payload.
|
||||
*
|
||||
* @param[in] pdu Request metadata
|
||||
* @param[in] buf Buffer containing the PDU
|
||||
* @param[in] len Length of the buffer
|
||||
* @param[in] code Request code
|
||||
* @param[in] path Resource path
|
||||
*
|
||||
* @return size of the PDU within the buffer
|
||||
* @return < 0 on error
|
||||
*/
|
||||
static inline ssize_t gcoap_request(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
||||
unsigned code,
|
||||
char *path)
|
||||
{
|
||||
return (gcoap_req_init(pdu, buf, len, code, path) == 0)
|
||||
? gcoap_finish(pdu, 0, COAP_FORMAT_NONE)
|
||||
: -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a buffer containing a CoAP request to the provided host/port.
|
||||
*
|
||||
* @param[in] buf Buffer containing the PDU
|
||||
* @param[in] len Length of the buffer
|
||||
* @param[in] addr Destination for the packet
|
||||
* @param[in] port Port at the destination
|
||||
* @param[in] resp_handler Callback when response received
|
||||
*
|
||||
* @return length of the packet
|
||||
* @return 0 if cannot send
|
||||
*/
|
||||
size_t gcoap_req_send(uint8_t *buf, size_t len, ipv6_addr_t *addr, uint16_t port,
|
||||
gcoap_resp_handler_t resp_handler);
|
||||
|
||||
/**
|
||||
* @brief Initializes a CoAP response packet on a buffer.
|
||||
*
|
||||
* Initializes payload location within the buffer based on packet setup.
|
||||
*
|
||||
* @param[in] pdu Response metadata
|
||||
* @param[in] buf Buffer containing the PDU
|
||||
* @param[in] len Length of the buffer
|
||||
* @param[in] code Response code
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return < 0 on error
|
||||
*/
|
||||
int gcoap_resp_init(coap_pkt_t *pdu, uint8_t *buf, size_t len, unsigned code);
|
||||
|
||||
/**
|
||||
* @brief Writes a complete CoAP response PDU when there is no payload.
|
||||
*
|
||||
* @param[in] pdu Response metadata
|
||||
* @param[in] buf Buffer containing the PDU
|
||||
* @param[in] len Length of the buffer
|
||||
* @param[in] code Response code
|
||||
*
|
||||
* @return size of the PDU within the buffer
|
||||
* @return < 0 on error
|
||||
*/
|
||||
static inline ssize_t gcoap_response(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
||||
unsigned code)
|
||||
{
|
||||
return (gcoap_resp_init(pdu, buf, len, code) == 0)
|
||||
? gcoap_finish(pdu, 0, COAP_FORMAT_NONE)
|
||||
: -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provides important operational statistics.
|
||||
*
|
||||
* Useful for monitoring.
|
||||
*
|
||||
* @param[out] open_reqs Count of unanswered requests
|
||||
*/
|
||||
void gcoap_op_state(uint8_t *open_reqs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GCOAP_H */
|
||||
/** @} */
|
||||
|
@ -136,8 +136,5 @@ endif
|
||||
ifneq (,$(filter gnrc_tftp,$(USEMODULE)))
|
||||
DIRS += application_layer/tftp
|
||||
endif
|
||||
ifneq (,$(filter gcoap,$(USEMODULE)))
|
||||
DIRS += application_layer/coap
|
||||
endif
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
|
Loading…
Reference in New Issue
Block a user