Merge pull request #13495 from pokgak/pr/sock_dtls/fix_timeout_when_waiting

examples/dtls-sock: fix timeout msg stays in mbox
This commit is contained in:
MichelRottleuthner 2020-03-09 16:33:05 +01:00 committed by GitHub
commit 26f3caf9d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 53 deletions

View File

@ -118,13 +118,13 @@ static int client_send(char *addr_str, char *data, size_t datalen)
res = credman_add(&credential); res = credman_add(&credential);
if (res < 0 && res != CREDMAN_EXIST) { if (res < 0 && res != CREDMAN_EXIST) {
/* ignore duplicate credentials */ /* ignore duplicate credentials */
printf("Error cannot add credential to system: %zd\n", res); printf("Error cannot add credential to system: %d\n", (int)res);
return -1; return -1;
} }
res = sock_dtls_session_create(&dtls_sock, &remote, &session); res = sock_dtls_session_create(&dtls_sock, &remote, &session);
if (res < 0) { if (res < 0) {
printf("Error creating session: %zd\n", res); printf("Error creating session: %d\n", (int)res);
sock_dtls_close(&dtls_sock); sock_dtls_close(&dtls_sock);
sock_udp_close(&udp_sock); sock_udp_close(&udp_sock);
return -1; return -1;

View File

@ -103,7 +103,7 @@ void *dtls_server_wrapper(void *arg)
res = credman_add(&credential); res = credman_add(&credential);
if (res < 0 && res != CREDMAN_EXIST) { if (res < 0 && res != CREDMAN_EXIST) {
/* ignore duplicate credentials */ /* ignore duplicate credentials */
printf("Error cannot add credential to system: %zd\n", res); printf("Error cannot add credential to system: %d\n", (int)res);
return NULL; return NULL;
} }
@ -116,14 +116,14 @@ void *dtls_server_wrapper(void *arg)
10 * US_PER_SEC); 10 * US_PER_SEC);
if (res < 0) { if (res < 0) {
if (res != -ETIMEDOUT) { if (res != -ETIMEDOUT) {
printf("Error receiving UDP over DTLS %zd", res); printf("Error receiving UDP over DTLS %d", (int)res);
} }
continue; continue;
} }
printf("Received %zd bytes -- (echo!)\n", res); printf("Received %d bytes -- (echo!)\n", (int)res);
res = sock_dtls_send(&sock, &session, rcv, (size_t)res); res = sock_dtls_send(&sock, &session, rcv, (size_t)res);
if (res < 0) { if (res < 0) {
printf("Error resending DTLS message: %zd", res); printf("Error resending DTLS message: %d", (int)res);
} }
} }
} }

View File

@ -24,8 +24,6 @@
#include "debug.h" #include "debug.h"
#include "dtls_debug.h" #include "dtls_debug.h"
#define DTLS_EVENT_TIMEOUT (0x01E1)
#define DTLS_HANDSHAKE_BUFSIZE (256) /**< Size buffer used in handshake #define DTLS_HANDSHAKE_BUFSIZE (256) /**< Size buffer used in handshake
to hold credentials */ to hold credentials */
/* ECC handshake takes more time */ /* ECC handshake takes more time */
@ -35,8 +33,6 @@
#define DTLS_HANDSHAKE_TIMEOUT (1 * US_PER_SEC) #define DTLS_HANDSHAKE_TIMEOUT (1 * US_PER_SEC)
#endif /* CONFIG_DTLS_ECC */ #endif /* CONFIG_DTLS_ECC */
static void _timeout_callback(void *arg);
#ifdef CONFIG_DTLS_PSK #ifdef CONFIG_DTLS_PSK
static int _get_psk_info(struct dtls_context_t *ctx, const session_t *session, static int _get_psk_info(struct dtls_context_t *ctx, const session_t *session,
dtls_credentials_type_t type, dtls_credentials_type_t type,
@ -102,7 +98,7 @@ static int _write(struct dtls_context_t *ctx, session_t *session, uint8_t *buf,
ssize_t res = sock_udp_send(sock->udp_sock, buf, len, &remote); ssize_t res = sock_udp_send(sock->udp_sock, buf, len, &remote);
if (res < 0) { if (res < 0) {
DEBUG("sock_dtls: failed to send DTLS record: %zd\n", res); DEBUG("sock_dtls: failed to send DTLS record: %d\n", (int)res);
} }
return res; return res;
} }
@ -291,7 +287,7 @@ int sock_dtls_session_create(sock_dtls_t *sock, const sock_udp_ep_t *ep,
DEBUG("sock_dtls: starting handshake\n"); DEBUG("sock_dtls: starting handshake\n");
res = dtls_connect(sock->dtls_ctx, &remote->dtls_session); res = dtls_connect(sock->dtls_ctx, &remote->dtls_session);
if (res < 0) { if (res < 0) {
DEBUG("sock_dtls: error establishing a session: %zd\n", res); DEBUG("sock_dtls: error establishing a session: %d\n", (int)res);
return -ENOMEM; return -ENOMEM;
} }
else if (res == 0) { else if (res == 0) {
@ -305,7 +301,7 @@ int sock_dtls_session_create(sock_dtls_t *sock, const sock_udp_ep_t *ep,
res = sock_udp_recv(sock->udp_sock, rcv_buffer, sizeof(rcv_buffer), res = sock_udp_recv(sock->udp_sock, rcv_buffer, sizeof(rcv_buffer),
DTLS_HANDSHAKE_TIMEOUT, &remote->ep); DTLS_HANDSHAKE_TIMEOUT, &remote->ep);
if (res <= 0) { if (res <= 0) {
DEBUG("sock_dtls: error receiving handshake messages: %zd\n", res); DEBUG("sock_dtls: error receiving handshake messages: %d\n", (int)res);
/* deletes peer created in dtls_connect() */ /* deletes peer created in dtls_connect() */
dtls_peer_t *peer = dtls_get_peer(sock->dtls_ctx, dtls_peer_t *peer = dtls_get_peer(sock->dtls_ctx,
&remote->dtls_session); &remote->dtls_session);
@ -348,18 +344,13 @@ ssize_t sock_dtls_send(sock_dtls_t *sock, sock_dtls_session_t *remote,
} }
else if (res > 0) { else if (res > 0) {
/* handshake initiated, wait until connected or timed out */ /* handshake initiated, wait until connected or timed out */
xtimer_t timeout_timer;
timeout_timer.callback = _timeout_callback;
timeout_timer.arg = sock;
xtimer_set(&timeout_timer, DTLS_HANDSHAKE_TIMEOUT);
msg_t msg; msg_t msg;
do { do {
mbox_get(&sock->mbox, &msg); res = xtimer_msg_receive_timeout(&msg, 3 * DTLS_HANDSHAKE_TIMEOUT);
} while ((msg.type != DTLS_EVENT_CONNECTED) && }
(msg.type != DTLS_EVENT_TIMEOUT)); while ((res != -1) && (msg.type != DTLS_EVENT_CONNECTED));
if (res == -1) {
if (msg.type == DTLS_EVENT_TIMEOUT) {
DEBUG("sock_dtls: handshake process timed out\n"); DEBUG("sock_dtls: handshake process timed out\n");
/* deletes peer created in dtls_connect() before */ /* deletes peer created in dtls_connect() before */
@ -367,12 +358,10 @@ ssize_t sock_dtls_send(sock_dtls_t *sock, sock_dtls_session_t *remote,
dtls_reset_peer(sock->dtls_ctx, peer); dtls_reset_peer(sock->dtls_ctx, peer);
return -EHOSTUNREACH; return -EHOSTUNREACH;
} }
xtimer_remove(&timeout_timer);
} }
} }
return dtls_write(sock->dtls_ctx, &remote->dtls_session, (uint8_t *)data, return dtls_write(sock->dtls_ctx, &remote->dtls_session, (uint8_t *)data, len);
len);
} }
static ssize_t _copy_buffer(sock_dtls_t *sock, void *data, size_t max_len) static ssize_t _copy_buffer(sock_dtls_t *sock, void *data, size_t max_len)
@ -393,8 +382,6 @@ static ssize_t _copy_buffer(sock_dtls_t *sock, void *data, size_t max_len)
ssize_t sock_dtls_recv(sock_dtls_t *sock, sock_dtls_session_t *remote, ssize_t sock_dtls_recv(sock_dtls_t *sock, sock_dtls_session_t *remote,
void *data, size_t max_len, uint32_t timeout) void *data, size_t max_len, uint32_t timeout)
{ {
xtimer_t timeout_timer;
assert(sock); assert(sock);
assert(data); assert(data);
assert(remote); assert(remote);
@ -403,11 +390,6 @@ ssize_t sock_dtls_recv(sock_dtls_t *sock, sock_dtls_session_t *remote,
/* there is already decrypted data available */ /* there is already decrypted data available */
return _copy_buffer(sock, data, max_len); return _copy_buffer(sock, data, max_len);
} }
if ((timeout != SOCK_NO_TIMEOUT) && (timeout != 0)) {
timeout_timer.callback = _timeout_callback;
timeout_timer.arg = sock;
xtimer_set(&timeout_timer, timeout);
}
/* loop breaks when timeout or application data read */ /* loop breaks when timeout or application data read */
while(1) { while(1) {
@ -415,11 +397,14 @@ ssize_t sock_dtls_recv(sock_dtls_t *sock, sock_dtls_session_t *remote,
ssize_t res = sock_udp_recv(sock->udp_sock, data, max_len, timeout, ssize_t res = sock_udp_recv(sock->udp_sock, data, max_len, timeout,
&remote->ep); &remote->ep);
if (res <= 0) { if (res <= 0) {
DEBUG("sock_dtls: error receiving UDP packet: %zd\n", res); DEBUG("sock_dtls: error receiving UDP packet: %d\n", (int)res);
xtimer_remove(&timeout_timer);
return res; return res;
} }
_ep_to_session(&remote->ep, &remote->dtls_session);
res = dtls_handle_message(sock->dtls_ctx, &remote->dtls_session,
(uint8_t *)data, res);
if ((timeout != SOCK_NO_TIMEOUT) && (timeout != 0)) { if ((timeout != SOCK_NO_TIMEOUT) && (timeout != 0)) {
uint32_t time_passed = (xtimer_now_usec() - start_recv); uint32_t time_passed = (xtimer_now_usec() - start_recv);
timeout = (time_passed > timeout) ? 0: timeout - time_passed; timeout = (time_passed > timeout) ? 0: timeout - time_passed;
@ -430,21 +415,10 @@ ssize_t sock_dtls_recv(sock_dtls_t *sock, sock_dtls_session_t *remote,
(uint8_t *)data, res); (uint8_t *)data, res);
if (sock->buf != NULL) { if (sock->buf != NULL) {
xtimer_remove(&timeout_timer);
return _copy_buffer(sock, data, max_len); return _copy_buffer(sock, data, max_len);
} }
/* reset msg type */
msg_t msg;
if (mbox_try_get(&sock->mbox, &msg)) {
switch(msg.type) {
case DTLS_EVENT_TIMEOUT:
DEBUG("sock_dtls: timed out while decrypting message\n");
return -ETIMEDOUT;
default:
break;
}
}
else if (timeout == 0) { else if (timeout == 0) {
DEBUG("sock_dtls: timed out while decrypting message\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
} }
@ -478,11 +452,4 @@ static void _session_to_ep(const session_t *session, sock_udp_ep_t *ep)
memcpy(&ep->addr.ipv6, &session->addr, sizeof(ipv6_addr_t)); memcpy(&ep->addr.ipv6, &session->addr, sizeof(ipv6_addr_t));
} }
static void _timeout_callback(void *arg)
{
msg_t timeout_msg = { .type = DTLS_EVENT_TIMEOUT };
sock_dtls_t *sock = arg;
mbox_try_put(&sock->mbox, &timeout_msg);
}
/** @} */ /** @} */

View File

@ -618,6 +618,10 @@ ssize_t sock_dtls_recv(sock_dtls_t *sock, sock_dtls_session_t *remote,
* @note Function may block until a session is created if there is no * @note Function may block until a session is created if there is no
* existing session with @p remote. * existing session with @p remote.
* *
* @note Initiating a session through this function will require
* @ref sock_dtls_recv() called from another thread to receive the handshake
* messages.
*
* @return The number of bytes sent on success * @return The number of bytes sent on success
* @return -EADDRINUSE, if sock_dtls_t::udp_sock has no local end-point. * @return -EADDRINUSE, if sock_dtls_t::udp_sock has no local end-point.
* @return -EAFNOSUPPORT, if `remote->ep != NULL` and * @return -EAFNOSUPPORT, if `remote->ep != NULL` and