1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #16688 from miri64/gcoap/enh/multitransport

gcoap: multi-transport support
This commit is contained in:
benpicco 2022-03-03 12:15:48 +01:00 committed by GitHub
commit c411edef55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 245 additions and 105 deletions

View File

@ -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

View File

@ -704,6 +704,36 @@ 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
*/
@ -711,6 +741,16 @@ 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 */
@ -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 */
};
/**
@ -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
*
@ -904,6 +919,32 @@ static inline ssize_t gcoap_request(coap_pkt_t *pdu, uint8_t *buf, size_t len,
: -1;
}
/**
* @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_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
*
@ -913,13 +954,21 @@ static inline ssize_t gcoap_request(coap_pkt_t *pdu, uint8_t *buf, size_t len,
* @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
*/
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);
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
@ -1002,6 +1051,35 @@ 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_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.
*
@ -1016,7 +1094,10 @@ uint8_t gcoap_op_state(void);
* @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);
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.

View File

@ -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;

View File

@ -54,19 +54,20 @@ static void *_event_loop(void *arg);
static void _on_sock_udp_evt(sock_udp_t *sock, sock_async_flags_t type, void *arg);
static void _process_coap_pdu(gcoap_socket_t *sock, sock_udp_ep_t *remote,
uint8_t *buf, size_t len, bool truncated);
static void _tl_init_coap_socket(gcoap_socket_t *sock);
static int _tl_init_coap_socket(gcoap_socket_t *sock, gcoap_socket_type_t type);
static ssize_t _tl_send(gcoap_socket_t *sock, const void *data, size_t len,
const sock_udp_ep_t *remote);
static ssize_t _tl_authenticate(gcoap_socket_t *sock, const sock_udp_ep_t *remote,
uint32_t timeout);
static ssize_t _well_known_core_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, void *ctx);
static void _cease_retransmission(gcoap_request_memo_t *memo);
static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len,
sock_udp_ep_t *remote);
static size_t _handle_req(gcoap_socket_t *sock, coap_pkt_t *pdu, uint8_t *buf,
size_t len, sock_udp_ep_t *remote);
static void _expire_request(gcoap_request_memo_t *memo);
static void _find_req_memo(gcoap_request_memo_t **memo_ptr, coap_pkt_t *pdu,
const sock_udp_ep_t *remote, bool by_mid);
static int _find_resource(coap_pkt_t *pdu,
static int _find_resource(gcoap_socket_type_t tl_type,
coap_pkt_t *pdu,
const coap_resource_t **resource_ptr,
gcoap_listener_t **listener_ptr);
static int _find_observer(sock_udp_ep_t **observer, sock_udp_ep_t *remote);
@ -92,6 +93,7 @@ const coap_resource_t _default_resources[] = {
static gcoap_listener_t _default_listener = {
&_default_resources[0],
ARRAY_SIZE(_default_resources),
GCOAP_SOCKET_TYPE_UNDEF,
NULL,
NULL,
_request_matcher_default
@ -130,7 +132,7 @@ static sock_udp_t _sock_udp;
#if IS_USED(MODULE_GCOAP_DTLS)
/* DTLS variables and definitions */
#define SOCK_DTLS_CLIENT_TAG (2)
static sock_udp_t _sock_dtls_base;
static sock_dtls_t _sock_dtls;
static kernel_pid_t _auth_waiting_thread;
@ -147,11 +149,7 @@ static void *_event_loop(void *arg)
memset(&local, 0, sizeof(sock_udp_ep_t));
local.family = AF_INET6;
local.netif = SOCK_ADDR_ANY_NETIF;
if (IS_USED(MODULE_GCOAP_DTLS)) {
local.port = CONFIG_GCOAPS_PORT;
} else {
local.port = CONFIG_GCOAP_PORT;
}
local.port = CONFIG_GCOAP_PORT;
int res = sock_udp_create(&_sock_udp, &local, NULL, 0);
if (res < 0) {
DEBUG("gcoap: cannot create sock: %d\n", res);
@ -159,20 +157,25 @@ static void *_event_loop(void *arg)
}
event_queue_init(&_queue);
sock_udp_event_init(&_sock_udp, &_queue, _on_sock_udp_evt, NULL);
if (IS_USED(MODULE_GCOAP_DTLS)) {
#if IS_USED(MODULE_GCOAP_DTLS)
if (sock_dtls_create(&_sock_dtls, &_sock_udp,
local.port = CONFIG_GCOAPS_PORT;
if (sock_udp_create(&_sock_dtls_base, &local, NULL, 0)) {
DEBUG("gcoap: error creating DTLS transport sock\n");
return 0;
}
if (sock_dtls_create(&_sock_dtls, &_sock_dtls_base,
CREDMAN_TAG_EMPTY,
SOCK_DTLS_1_2, SOCK_DTLS_SERVER) < 0) {
DEBUG("gcoap: error creating DTLS sock");
sock_udp_close(&_sock_udp);
DEBUG("gcoap: error creating DTLS sock\n");
sock_udp_close(&_sock_dtls_base);
return 0;
}
sock_dtls_event_init(&_sock_dtls, &_queue, _on_sock_dtls_evt,
NULL);
#endif
} else {
sock_udp_event_init(&_sock_udp, &_queue, _on_sock_udp_evt, NULL);
}
event_loop(&_queue);
@ -383,7 +386,8 @@ static void _process_coap_pdu(gcoap_socket_t *sock, sock_udp_ep_t *remote,
pdu_len = gcoap_response(&pdu, _listen_buf, sizeof(_listen_buf),
COAP_CODE_REQUEST_ENTITY_TOO_LARGE);
} else {
pdu_len = _handle_req(&pdu, _listen_buf, sizeof(_listen_buf), remote);
pdu_len = _handle_req(sock, &pdu, _listen_buf,
sizeof(_listen_buf), remote);
}
if (pdu_len > 0) {
@ -485,9 +489,7 @@ static void _on_resp_timeout(void *arg) {
return;
}
gcoap_socket_t socket;
_tl_init_coap_socket(&socket);
ssize_t bytes = _tl_send(&socket, memo->msg.data.pdu_buf,
ssize_t bytes = _tl_send(&memo->socket, memo->msg.data.pdu_buf,
memo->msg.data.pdu_len, &memo->remote_ep);
if (bytes <= 0) {
DEBUG("gcoap: sock resend failed: %d\n", (int)bytes);
@ -529,8 +531,8 @@ static void _cease_retransmission(gcoap_request_memo_t *memo) {
*
* return length of response pdu, or < 0 if can't handle
*/
static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len,
sock_udp_ep_t *remote)
static size_t _handle_req(gcoap_socket_t *sock, coap_pkt_t *pdu, uint8_t *buf,
size_t len, sock_udp_ep_t *remote)
{
const coap_resource_t *resource = NULL;
gcoap_listener_t *listener = NULL;
@ -538,7 +540,7 @@ static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len,
gcoap_observe_memo_t *memo = NULL;
gcoap_observe_memo_t *resource_memo = NULL;
switch (_find_resource(pdu, &resource, &listener)) {
switch (_find_resource(sock->type, pdu, &resource, &listener)) {
case GCOAP_RESOURCE_WRONG_METHOD:
return gcoap_response(pdu, buf, len, COAP_CODE_METHOD_NOT_ALLOWED);
case GCOAP_RESOURCE_NO_PATH:
@ -567,7 +569,8 @@ static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len,
}
/* otherwise OK to re-register resource with the same token */
}
else if (sock_udp_ep_equal(remote, resource_memo->observer)) {
else if ((sock->type == resource_memo->socket.type) &&
sock_udp_ep_equal(remote, resource_memo->observer)) {
/* accept new token for resource */
memo = resource_memo;
}
@ -601,6 +604,7 @@ static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len,
/* resource may be assigned here if it is not already registered */
memo->resource = resource;
memo->token_len = coap_get_token_len(pdu);
memo->socket = *sock;
if (memo->token_len) {
memcpy(&memo->token[0], pdu->token, memo->token_len);
}
@ -630,6 +634,7 @@ static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len,
return -1;
}
pdu->tl_type = (uint32_t)sock->type;
ssize_t pdu_len = resource->handler(pdu, buf, len, resource->context);
if (pdu_len < 0) {
pdu_len = gcoap_response(pdu, buf, len,
@ -688,6 +693,7 @@ static int _request_matcher_default(gcoap_listener_t *listener,
/*
* Searches listener registrations for the resource matching the path in a PDU.
*
* param[in] tl_type -- transport the request for the resource came over.
* param[in] pdu -- the PDU to check the resource for
* param[out] resource_ptr -- found resource
* param[out] listener_ptr -- listener for found resource
@ -696,7 +702,8 @@ static int _request_matcher_default(gcoap_listener_t *listener,
* code didn't match and `GCOAP_RESOURCE_NO_PATH` if no matching
* resource was found.
*/
static int _find_resource(coap_pkt_t *pdu,
static int _find_resource(gcoap_socket_type_t tl_type,
coap_pkt_t *pdu,
const coap_resource_t **resource_ptr,
gcoap_listener_t **listener_ptr)
{
@ -707,8 +714,17 @@ static int _find_resource(coap_pkt_t *pdu,
while (listener) {
const coap_resource_t *resource;
int res = listener->request_matcher(listener, &resource, pdu);
int res;
/* only makes sense to check if non-UDP transports are supported,
* so check if module is used first. */
if (IS_USED(MODULE_GCOAP_DTLS) &&
(listener->tl_type != GCOAP_SOCKET_TYPE_UNDEF) &&
!(listener->tl_type & tl_type)) {
listener = listener->next;
continue;
}
res = listener->request_matcher(listener, &resource, pdu);
/* check next resource on mismatch */
if (res == GCOAP_RESOURCE_NO_PATH) {
listener = listener->next;
@ -825,8 +841,9 @@ static ssize_t _well_known_core_handler(coap_pkt_t* pdu, uint8_t *buf, size_t le
coap_opt_add_format(pdu, COAP_FORMAT_LINK);
ssize_t plen = coap_opt_finish(pdu, COAP_OPT_FINISH_PAYLOAD);
plen += gcoap_get_resource_list(pdu->payload, (size_t)pdu->payload_len,
COAP_FORMAT_LINK);
plen += gcoap_get_resource_list_tl(pdu->payload, (size_t)pdu->payload_len,
COAP_FORMAT_LINK,
(gcoap_socket_type_t)pdu->tl_type);
return plen;
}
@ -924,54 +941,72 @@ static void _find_obs_memo_resource(gcoap_observe_memo_t **memo,
* Transport layer functions
*/
static void _tl_init_coap_socket(gcoap_socket_t *sock)
static int _tl_init_coap_socket(gcoap_socket_t *sock, gcoap_socket_type_t type)
{
#if IS_USED(MODULE_GCOAP_DTLS)
sock->type = GCOAP_SOCKET_TYPE_DTLS;
sock->socket.dtls = &_sock_dtls;
#else
sock->type = GCOAP_SOCKET_TYPE_UDP;
sock->socket.udp = &_sock_udp;
switch (type) {
#if !IS_USED(MODULE_GCOAP_DTLS)
case GCOAP_SOCKET_TYPE_UNDEF:
#endif
case GCOAP_SOCKET_TYPE_UDP:
sock->type = GCOAP_SOCKET_TYPE_UDP;
sock->socket.udp = &_sock_udp;
break;
#if IS_USED(MODULE_GCOAP_DTLS)
case GCOAP_SOCKET_TYPE_UNDEF:
case GCOAP_SOCKET_TYPE_DTLS:
sock->type = GCOAP_SOCKET_TYPE_DTLS;
sock->socket.dtls = &_sock_dtls;
break;
#else
default:
return -1;
#endif
}
return 0;
}
static ssize_t _tl_send(gcoap_socket_t *sock, const void *data, size_t len,
const sock_udp_ep_t *remote)
const sock_udp_ep_t *remote)
{
ssize_t res = -1;
if (sock->type == GCOAP_SOCKET_TYPE_DTLS) {
switch (sock->type) {
case GCOAP_SOCKET_TYPE_UDP:
res = sock_udp_send(sock->socket.udp, data, len, remote);
break;
#if IS_USED(MODULE_GCOAP_DTLS)
/* prepare session */
sock_dtls_session_set_udp_ep(&sock->ctx_dtls_session, remote);
dsm_state_t session_state = dsm_store(sock->socket.dtls, &sock->ctx_dtls_session,
SESSION_STATE_HANDSHAKE, true);
if (session_state == NO_SPACE) {
return -1;
}
case GCOAP_SOCKET_TYPE_DTLS:
/* prepare session */
sock_dtls_session_set_udp_ep(&sock->ctx_dtls_session, remote);
dsm_state_t session_state = dsm_store(sock->socket.dtls,
&sock->ctx_dtls_session,
SESSION_STATE_HANDSHAKE,
true);
if (session_state == NO_SPACE) {
return -1;
}
/* send application data */
res = sock_dtls_send(sock->socket.dtls, &sock->ctx_dtls_session, data, len,
SOCK_NO_TIMEOUT);
switch (res) {
case -EHOSTUNREACH:
case -ENOTCONN:
case 0:
DEBUG("gcoap: DTLS sock not connected or remote unreachable. "
"Destroying session.\n");
dsm_remove(sock->socket.dtls, &sock->ctx_dtls_session);
sock_dtls_session_destroy(sock->socket.dtls, &sock->ctx_dtls_session);
/* send application data */
res = sock_dtls_send(sock->socket.dtls, &sock->ctx_dtls_session, data, len,
SOCK_NO_TIMEOUT);
switch (res) {
case -EHOSTUNREACH:
case -ENOTCONN:
case 0:
DEBUG("gcoap: DTLS sock not connected or remote unreachable. "
"Destroying session.\n");
dsm_remove(sock->socket.dtls, &sock->ctx_dtls_session);
sock_dtls_session_destroy(sock->socket.dtls, &sock->ctx_dtls_session);
break;
default:
/* Temporary error. Keeping the DTLS session */
break;
}
break;
default:
/* Temporary error. Keeping the DTLS session */
break;
}
#endif
} else if (sock->type == GCOAP_SOCKET_TYPE_UDP) {
res = sock_udp_send(sock->socket.udp, data, len, remote);
} else {
DEBUG("gcoap: undefined socket type\n");
default:
DEBUG("gcoap: undefined socket type\n");
break;
}
return res;
}
@ -986,6 +1021,9 @@ static ssize_t _tl_authenticate(gcoap_socket_t *sock, const sock_udp_ep_t *remot
#else
int res;
if (sock->type != GCOAP_SOCKET_TYPE_DTLS) {
return 0;
}
/* prepare session */
sock_dtls_session_set_udp_ep(&sock->ctx_dtls_session, remote);
dsm_state_t session_state = dsm_store(sock->socket.dtls, &sock->ctx_dtls_session,
@ -1111,16 +1149,23 @@ int gcoap_req_init_path_buffer(coap_pkt_t *pdu, uint8_t *buf, size_t len,
return (res > 0) ? 0 : res;
}
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)
{
gcoap_socket_t socket = { 0 };
gcoap_request_memo_t *memo = NULL;
unsigned msg_type = (*buf & 0x30) >> 4;
uint32_t timeout = 0;
ssize_t res = 0;
assert(remote != NULL);
res = _tl_init_coap_socket(&socket, tl_type);
if (res < 0) {
return -EINVAL;
}
/* Only allocate memory if necessary (i.e. if user is interested in the
* response or request is confirmable) */
if ((resp_handler != NULL) || (msg_type == COAP_TYPE_CON)) {
@ -1142,6 +1187,7 @@ ssize_t gcoap_req_send(const uint8_t *buf, size_t len,
memo->resp_handler = resp_handler;
memo->context = context;
memcpy(&memo->remote_ep, remote, sizeof(sock_udp_ep_t));
memo->socket = socket;
switch (msg_type) {
case COAP_TYPE_CON:
@ -1186,10 +1232,7 @@ ssize_t gcoap_req_send(const uint8_t *buf, size_t len,
}
}
ssize_t res = 0;
gcoap_socket_t socket = { 0 };
_tl_init_coap_socket(&socket);
_tl_init_coap_socket(&socket, tl_type);
if (IS_USED(MODULE_GCOAP_DTLS) && socket.type == GCOAP_SOCKET_TYPE_DTLS) {
res = _tl_authenticate(&socket, remote, CONFIG_GCOAP_DTLS_HANDSHAKE_TIMEOUT_MSEC);
}
@ -1283,12 +1326,10 @@ size_t gcoap_obs_send(const uint8_t *buf, size_t len,
const coap_resource_t *resource)
{
gcoap_observe_memo_t *memo = NULL;
gcoap_socket_t socket;
_tl_init_coap_socket(&socket);
_find_obs_memo_resource(&memo, resource);
if (memo) {
ssize_t bytes = _tl_send(&socket, buf, len, memo->observer);
ssize_t bytes = _tl_send(&memo->socket, buf, len, memo->observer);
return (size_t)((bytes > 0) ? bytes : 0);
}
else {
@ -1307,7 +1348,8 @@ uint8_t gcoap_op_state(void)
return count;
}
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)
{
assert(cf == COAP_FORMAT_LINK);
@ -1326,6 +1368,15 @@ int gcoap_get_resource_list(void *buf, size_t maxlen, uint8_t cf)
if (!listener->link_encoder) {
continue;
}
/* only makes sense to check if non-UDP transports are supported,
* so check if module is used first. */
if (IS_USED(MODULE_GCOAP_DTLS) &&
(tl_type != GCOAP_SOCKET_TYPE_UNDEF) &&
(listener->tl_type != GCOAP_SOCKET_TYPE_UNDEF) &&
((listener->tl_type & GCOAP_SOCKET_TYPE_UDP) != (tl_type & GCOAP_SOCKET_TYPE_UDP)) &&
((listener->tl_type & GCOAP_SOCKET_TYPE_DTLS) != (tl_type & GCOAP_SOCKET_TYPE_DTLS))) {
continue;
}
ctx.link_pos = 0;
for (; ctx.link_pos < listener->resources_len; ctx.link_pos++) {