Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gcoap: multi-transport support #16688

Merged
merged 2 commits into from
Mar 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/gcoap/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ static const char *_link_params[] = {
static gcoap_listener_t _listener = {
&_resources[0],
ARRAY_SIZE(_resources),
GCOAP_SOCKET_TYPE_UNDEF,
_encode_link,
NULL,
NULL
Expand Down
143 changes: 112 additions & 31 deletions sys/include/net/gcoap.h
Original file line number Diff line number Diff line change
Expand Up @@ -704,13 +704,53 @@ typedef int (*gcoap_request_matcher_t)(gcoap_listener_t *listener,
const coap_resource_t **resource,
coap_pkt_t *pdu);

/**
* @brief CoAP socket types
*
* May be used as flags for @ref gcoap_listener_t, but must be used numerically
* with @ref gcoap_req_send_tl().
*/
typedef enum {
GCOAP_SOCKET_TYPE_UNDEF = 0x0, /**< undefined */
GCOAP_SOCKET_TYPE_UDP = 0x1, /**< Unencrypted UDP transport */
GCOAP_SOCKET_TYPE_DTLS = 0x2, /**< DTLS-over-UDP transport */
} gcoap_socket_type_t;

/**
* @brief CoAP socket to handle multiple transport types
*/
typedef struct {
gcoap_socket_type_t type; /**< Type of stored socket */
union {
sock_udp_t *udp;
#if IS_USED(MODULE_GCOAP_DTLS) || defined(DOXYGEN)
sock_dtls_t *dtls;
#endif
} socket; /**< Stored socket */
#if IS_USED(MODULE_GCOAP_DTLS) || defined(DOXYGEN)
sock_dtls_session_t ctx_dtls_session; /**< Session object for the stored socket.
Used for exchanging a session between
functions. */
#endif
} gcoap_socket_t;

/**
* @brief A modular collection of resources for a server
*/
struct gcoap_listener {
const coap_resource_t *resources; /**< First element in the array of
* resources; must order alphabetically */
size_t resources_len; /**< Length of array */
/**
* @brief Transport type for the listener
*
* Any transport supported by the implementation can be set as a flag.
* If @ref GCOAP_SOCKET_TYPE_UNDEF is set, the listener listens on all
* supported transports. If non of the transports beyond UDP are compiled in
* (i.e. no usage of modules `gcoap_dtls`, ...) this will be ignored and
* @ref GCOAP_SOCKET_TYPE_UDP assumed.
*/
gcoap_socket_type_t tl_type;
gcoap_link_encoder_t link_encoder; /**< Writes a link for a resource */
struct gcoap_listener *next; /**< Next listener in list */

Expand Down Expand Up @@ -768,6 +808,7 @@ struct gcoap_request_memo {
void *context; /**< ptr to user defined context data */
event_timeout_t resp_evt_tmout; /**< Limits wait for response */
event_callback_t resp_tmout_cb; /**< Callback for response timeout */
gcoap_socket_t socket; /**< Transport type to remote endpoint */
};

/**
Expand All @@ -778,35 +819,9 @@ typedef struct {
const coap_resource_t *resource; /**< Entity being observed */
uint8_t token[GCOAP_TOKENLEN_MAX]; /**< Client token for notifications */
unsigned token_len; /**< Actual length of token attribute */
gcoap_socket_t socket; /**< Transport type to observer */
} gcoap_observe_memo_t;

/**
* @brief Coap socket types
*/
typedef enum {
GCOAP_SOCKET_TYPE_UNDEF = 0,
GCOAP_SOCKET_TYPE_UDP,
GCOAP_SOCKET_TYPE_DTLS
} gcoap_socket_type_t;

/**
* @brief Coap socket to handle multiple transport types
*/
typedef struct {
gcoap_socket_type_t type; /**< Type of stored socket */
union {
sock_udp_t *udp;
#if IS_USED(MODULE_GCOAP_DTLS) || defined(DOXYGEN)
sock_dtls_t *dtls;
#endif
} socket; /**< Stored socket */
#if IS_USED(MODULE_GCOAP_DTLS) || defined(DOXYGEN)
sock_dtls_session_t ctx_dtls_session; /**< Session object for the stored socket.
Used for exchanging a session between
functions. */
#endif
} gcoap_socket_t;

/**
* @brief Initializes the gcoap thread and device
*
Expand Down Expand Up @@ -907,19 +922,53 @@ static inline ssize_t gcoap_request(coap_pkt_t *pdu, uint8_t *buf, size_t len,
/**
* @brief Sends a buffer containing a CoAP request to the provided endpoint
*
* @deprecated Will be an alias for @ref gcoap_req_send after the 2022.01
* release. Will be removed after the 2022.04 release.
*
* @param[in] buf Buffer containing the PDU
* @param[in] len Length of the buffer
* @param[in] remote Destination for the packet
* @param[in] resp_handler Callback when response received, may be NULL
* @param[in] context User defined context passed to the response handler
* @param[in] tl_type The transport type to use for send. When
* @ref GCOAP_SOCKET_TYPE_UNDEF is selected, the highest
* available (by value) will be selected. Only single
* types are allowed, not a combination of them.
*
* @return length of the packet
* @return -ENOTCONN, if DTLS was used and session establishment failed
* @return -EINVAL, if @p tl_type is is not supported
* @return 0 if cannot send
*/
ssize_t gcoap_req_send(const uint8_t *buf, size_t len,
const sock_udp_ep_t *remote,
gcoap_resp_handler_t resp_handler, void *context);
ssize_t gcoap_req_send_tl(const uint8_t *buf, size_t len,
const sock_udp_ep_t *remote,
gcoap_resp_handler_t resp_handler, void *context,
gcoap_socket_type_t tl_type);

/**
* @brief Sends a buffer containing a CoAP request to the provided endpoint
*
* @param[in] buf Buffer containing the PDU
* @param[in] len Length of the buffer
* @param[in] remote Destination for the packet
* @param[in] resp_handler Callback when response received, may be NULL
* @param[in] context User defined context passed to the response handler
*
* @note The highest supported (by value) gcoap_socket_type_t will be selected
* as transport type.
*
* @return length of the packet
* @return -ENOTCONN, if DTLS was used and session establishment failed
* @return 0 if cannot send
*/
static inline ssize_t gcoap_req_send(const uint8_t *buf, size_t len,
const sock_udp_ep_t *remote,
gcoap_resp_handler_t resp_handler,
void *context)
{
return gcoap_req_send_tl(buf, len, remote, resp_handler, context,
GCOAP_SOCKET_TYPE_UNDEF);
}

/**
* @brief Initializes a CoAP response packet on a buffer
Expand Down Expand Up @@ -1002,21 +1051,53 @@ uint8_t gcoap_op_state(void);
* @brief Get the resource list, currently only `CoRE Link Format`
* (COAP_FORMAT_LINK) supported
*
* @deprecated Will be an alias for @ref gcoap_get_resource_list after the
* 2022.01 release. Will be removed after the 2022.04 release.
*
* If @p buf := NULL, nothing will be written but the size of the resulting
* resource list is computed and returned.
*
* @param[out] buf output buffer to write resource list into, my be NULL
* @param[in] maxlen length of @p buf, ignored if @p buf is NULL
* @param[in] cf content format to use for the resource list, currently
* only COAP_FORMAT_LINK supported
* @param[in] tl_type Transport type to get the list for.
* @ref GCOAP_SOCKET_TYPE_UNDEF for all transport types.
* If non of the transports beyond UDP are compiled in
* (i.e. usage of modules no `gcoap_dtls`, ...) this will
* be ignored and @ref GCOAP_SOCKET_TYPE_UDP assumed.
*
* @todo add support for `JSON CoRE Link Format`
* @todo add support for 'CBOR CoRE Link Format`
*
* @return the number of bytes written to @p buf
* @return -1 on error
*/
int gcoap_get_resource_list(void *buf, size_t maxlen, uint8_t cf);
int gcoap_get_resource_list_tl(void *buf, size_t maxlen, uint8_t cf,
gcoap_socket_type_t tl_type);

/**
* @brief Get the resource list for all transports,
* currently only `CoRE Link Format` (COAP_FORMAT_LINK) supported
*
* If @p buf := NULL, nothing will be written but the size of the resulting
* resource list is computed and returned.
*
* @param[out] buf output buffer to write resource list into, my be NULL
* @param[in] maxlen length of @p buf, ignored if @p buf is NULL
* @param[in] cf content format to use for the resource list, currently
* only COAP_FORMAT_LINK supported
*
* @todo add support for `JSON CoRE Link Format`
* @todo add support for 'CBOR CoRE Link Format`
*
* @return the number of bytes written to @p buf
* @return -1 on error
*/
static inline int gcoap_get_resource_list(void *buf, size_t maxlen, uint8_t cf)
{
return gcoap_get_resource_list_tl(buf, maxlen, cf, GCOAP_SOCKET_TYPE_UNDEF);
}

/**
* @brief Writes a resource in CoRE Link Format to a provided buffer.
Expand Down
7 changes: 7 additions & 0 deletions sys/include/net/nanocoap.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,13 @@ typedef struct {
BITFIELD(opt_crit, CONFIG_NANOCOAP_NOPTS_MAX); /**< unhandled critical option */
#ifdef MODULE_GCOAP
uint32_t observe_value; /**< observe value */
/**
* @brief transport the packet was received over
* @see @ref gcoap_socket_type_t for values.
* @note @ref gcoap_socket_type_t can not be used, as this would
* cyclically include the @ref net_gcoap header.
*/
uint32_t tl_type;
#endif
} coap_pkt_t;

Expand Down
Loading