diff --git a/pkg/tinydtls/contrib/sock_dtls.c b/pkg/tinydtls/contrib/sock_dtls.c index 8aa00d3de1..912e7f0443 100644 --- a/pkg/tinydtls/contrib/sock_dtls.c +++ b/pkg/tinydtls/contrib/sock_dtls.c @@ -87,6 +87,8 @@ static int _read(struct dtls_context_t *ctx, session_t *session, uint8_t *buf, sock->buffer.session = session; #ifdef SOCK_HAS_ASYNC if (sock->async_cb != NULL) { + /* reset retrievable event session */ + memset(&sock->async_cb_session, 0, sizeof(sock->async_cb_session)); sock->async_cb(sock, SOCK_ASYNC_MSG_RECV, sock->async_cb_arg); } #endif @@ -138,6 +140,7 @@ static int _event(struct dtls_context_t *ctx, session_t *session, switch (code) { case DTLS_ALERT_CLOSE_NOTIFY: /* peer closed their session */ + memcpy(&sock->async_cb_session, session, sizeof(session_t)); sock->async_cb(sock, SOCK_ASYNC_CONN_FIN, sock->async_cb_arg); break; case DTLS_EVENT_CONNECTED: @@ -279,6 +282,7 @@ int sock_dtls_create(sock_dtls_t *sock, sock_udp_t *udp_sock, #ifdef SOCK_HAS_ASYNC sock->async_cb = NULL; sock->buf_ctx = NULL; + memset(&sock->async_cb_session, 0, sizeof(sock->async_cb_session)); #endif /* SOCK_HAS_ASYNC */ sock->role = role; sock->tag = tag; @@ -516,6 +520,7 @@ static ssize_t _complete_handshake(sock_dtls_t *sock, flags |= SOCK_ASYNC_CONN_RECV; } } + memcpy(&sock->async_cb_session, session, sizeof(session_t)); sock->async_cb(sock, flags, sock->async_cb_arg); } #else @@ -608,6 +613,19 @@ static inline uint32_t _update_timeout(uint32_t start, uint32_t timeout) } #ifdef SOCK_HAS_ASYNC +bool sock_dtls_get_event_session(sock_dtls_t *sock, + sock_dtls_session_t *session) +{ + assert(sock); + assert(session); + if (sock->async_cb_session.size > 0) { + memcpy(&session->dtls_session, &sock->async_cb_session, + sizeof(sock->async_cb_session)); + return true; + } + return false; +} + void _udp_cb(sock_udp_t *udp_sock, sock_async_flags_t flags, void *ctx) { sock_dtls_t *sock = ctx; diff --git a/pkg/tinydtls/include/sock_dtls_types.h b/pkg/tinydtls/include/sock_dtls_types.h index 12924a58a3..e472f59764 100644 --- a/pkg/tinydtls/include/sock_dtls_types.h +++ b/pkg/tinydtls/include/sock_dtls_types.h @@ -52,6 +52,7 @@ struct sock_dtls { */ sock_dtls_cb_t async_cb; void *async_cb_arg; /**< asynchronous callback arg */ + session_t async_cb_session; /**< asynchronous callback session */ #if defined(SOCK_HAS_ASYNC_CTX) || defined(DOXYGEN) /** * @brief Asynchronous event context diff --git a/sys/include/net/sock/async.h b/sys/include/net/sock/async.h index 123f9a4952..50cd513851 100644 --- a/sys/include/net/sock/async.h +++ b/sys/include/net/sock/async.h @@ -33,7 +33,25 @@ extern "C" { #if defined(MODULE_SOCK_DTLS) || defined(DOXYGEN) /** - * @brief Gets the asynchronous event context from sock object + * @brief Gets the asynchronous event session from sock object + * + * @pre `(sock != NULL) && (session != NULL)` + * + * @note Only available with @ref SOCK_HAS_ASYNC defined. + * Should only be called within a DTLS event and session is only available + * for the event types @ref SOCK_ASYNC_CONN_RDY and @ref SOCK_ASYNC_CONN_FIN. + * For other event types use @ref sock_dtls_recv() to get the session. + * + * @param[in] sock The DTLS sock object of the current event. + * @param[out] session Session object of the current event. + * + * @return true if the event session is available, false otherwise. + */ +bool sock_dtls_get_event_session(sock_dtls_t *sock, + sock_dtls_session_t *session); + +/** + * @brief Sets the asynchronous event context from sock object * * @pre `(sock != NULL)` * diff --git a/tests/pkg_tinydtls_sock_async/Makefile b/tests/pkg_tinydtls_sock_async/Makefile index a92e171268..0a8e161f68 100644 --- a/tests/pkg_tinydtls_sock_async/Makefile +++ b/tests/pkg_tinydtls_sock_async/Makefile @@ -12,6 +12,7 @@ USEMODULE += gnrc_ipv6_default USEMODULE += sock_async_event USEMODULE += sock_dtls USEMODULE += sock_udp +USEMODULE += sock_util USEMODULE += event_thread_medium USEMODULE += event_timeout diff --git a/tests/pkg_tinydtls_sock_async/dtls-client.c b/tests/pkg_tinydtls_sock_async/dtls-client.c index 2aefc75856..78d2fefa19 100644 --- a/tests/pkg_tinydtls_sock_async/dtls-client.c +++ b/tests/pkg_tinydtls_sock_async/dtls-client.c @@ -24,9 +24,11 @@ #include "net/sock/async/event.h" #include "net/sock/udp.h" #include "net/sock/dtls.h" +#include "net/sock/util.h" #include "net/ipv6/addr.h" #include "net/credman.h" #include "timex.h" +#include "test_utils/expect.h" #include "tinydtls_common.h" #include "tinydtls_keys.h" @@ -109,6 +111,8 @@ static void _dtls_handler(sock_dtls_t *sock, sock_async_flags_t type, void *arg) event_timeout_clear(&_timeouter); if (type & SOCK_ASYNC_CONN_RECV) { + expect(!sock_dtls_get_event_session(sock, &session)); + char *send_data = arg; puts("Session handshake received"); if (sock_dtls_recv(sock, &session, _recv_buf, sizeof(_recv_buf), @@ -134,9 +138,21 @@ static void _dtls_handler(sock_dtls_t *sock, sock_async_flags_t type, void *arg) _close_sock(sock); } if (type & SOCK_ASYNC_CONN_RDY) { - puts("Session became ready"); + if (sock_dtls_get_event_session(sock, &session)) { + sock_udp_ep_t ep; + char addrstr[IPV6_ADDR_MAX_STR_LEN]; + uint16_t port; + + sock_dtls_session_get_udp_ep(&session, &ep); + sock_udp_ep_fmt(&ep, addrstr, &port); + printf("Session became ready: [%s]:%u\n", addrstr, port); + } else { + puts("A session became ready, but the corresponding " \ + "session could not be retrieved from socket"); + } } if (type & SOCK_ASYNC_MSG_RECV) { + expect(!sock_dtls_get_event_session(sock, &session)); int res; if ((res = sock_dtls_recv(sock, &session, _recv_buf, sizeof(_recv_buf), diff --git a/tests/pkg_tinydtls_sock_async/dtls-server.c b/tests/pkg_tinydtls_sock_async/dtls-server.c index 476235706d..060a6f10b7 100644 --- a/tests/pkg_tinydtls_sock_async/dtls-server.c +++ b/tests/pkg_tinydtls_sock_async/dtls-server.c @@ -25,9 +25,11 @@ #include "net/sock/async/event.h" #include "net/sock/udp.h" #include "net/sock/dtls.h" +#include "net/sock/util.h" #include "net/credman.h" #include "msg.h" #include "thread.h" +#include "test_utils/expect.h" #include "tinydtls_common.h" #include "tinydtls_keys.h" @@ -105,8 +107,10 @@ static void _dtls_handler(sock_dtls_t *sock, sock_async_flags_t type, void *arg) return; } + sock_dtls_session_t session = { 0 }; + if (type & SOCK_ASYNC_CONN_RECV) { - sock_dtls_session_t session = { 0 }; + expect(!sock_dtls_get_event_session(sock, &session)); puts("Session handshake received"); if (sock_dtls_recv(sock, &session, _recv_buf, sizeof(_recv_buf), @@ -117,13 +121,35 @@ static void _dtls_handler(sock_dtls_t *sock, sock_async_flags_t type, void *arg) puts("New client connected"); } if (type & SOCK_ASYNC_CONN_FIN) { - puts("Session was destroyed by peer"); + if (sock_dtls_get_event_session(sock, &session)) { + sock_udp_ep_t ep; + char addrstr[IPV6_ADDR_MAX_STR_LEN]; + uint16_t port; + + sock_dtls_session_get_udp_ep(&session, &ep); + sock_udp_ep_fmt(&ep, addrstr, &port); + printf("Session was destroyed by peer: [%s]:%u\n", addrstr, port); + } else { + puts("A session was destroyed by peer, but the corresponding " \ + "session could not be retrieved from socket"); + } } if (type & SOCK_ASYNC_CONN_RDY) { - puts("Session became ready"); + if (sock_dtls_get_event_session(sock, &session)) { + sock_udp_ep_t ep; + char addrstr[IPV6_ADDR_MAX_STR_LEN]; + uint16_t port; + + sock_dtls_session_get_udp_ep(&session, &ep); + sock_udp_ep_fmt(&ep, addrstr, &port); + printf("Session became ready: [%s]:%u\n", addrstr, port); + } else { + puts("A session became ready, but the corresponding session " \ + "could not be retrieved from the socket"); + } } if (type & SOCK_ASYNC_MSG_RECV) { - sock_dtls_session_t session = { 0 }; + expect(!sock_dtls_get_event_session(sock, &session)); ssize_t res; res = sock_dtls_recv(sock, &session, _recv_buf, sizeof(_recv_buf), 0);