mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #14043 from pokgak/pr/sock_dtls/send_api_change
sock_dtls: add timeout to sock_dtls_send and add sock_dtls_session_init
This commit is contained in:
commit
e011e3ed38
@ -74,10 +74,11 @@ static int client_send(char *addr_str, char *data, size_t datalen)
|
|||||||
sock_udp_t udp_sock;
|
sock_udp_t udp_sock;
|
||||||
sock_dtls_t dtls_sock;
|
sock_dtls_t dtls_sock;
|
||||||
sock_dtls_session_t session;
|
sock_dtls_session_t session;
|
||||||
sock_udp_ep_t remote;
|
sock_udp_ep_t remote = SOCK_IPV6_EP_ANY;
|
||||||
sock_udp_ep_t local = SOCK_IPV6_EP_ANY;
|
sock_udp_ep_t local = SOCK_IPV6_EP_ANY;
|
||||||
local.port = 12345;
|
local.port = 12345;
|
||||||
remote.port = DTLS_DEFAULT_PORT;
|
remote.port = DTLS_DEFAULT_PORT;
|
||||||
|
uint8_t buf[DTLS_HANDSHAKE_BUFSIZE];
|
||||||
|
|
||||||
/* get interface */
|
/* get interface */
|
||||||
char* iface = ipv6_addr_split_iface(addr_str);
|
char* iface = ipv6_addr_split_iface(addr_str);
|
||||||
@ -122,26 +123,32 @@ static int client_send(char *addr_str, char *data, size_t datalen)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = sock_dtls_session_create(&dtls_sock, &remote, &session);
|
res = sock_dtls_session_init(&dtls_sock, &remote, &session);
|
||||||
if (res < 0) {
|
if (res <= 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = sock_dtls_recv(&dtls_sock, &session, buf, sizeof(buf),
|
||||||
|
SOCK_NO_TIMEOUT);
|
||||||
|
if (res != -SOCK_DTLS_HANDSHAKE) {
|
||||||
printf("Error creating session: %d\n", (int)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;
|
||||||
}
|
}
|
||||||
|
printf("Connection to server successful\n");
|
||||||
|
|
||||||
if (sock_dtls_send(&dtls_sock, &session, data, datalen) < 0) {
|
if (sock_dtls_send(&dtls_sock, &session, data, datalen, 0) < 0) {
|
||||||
puts("Error sending data");
|
puts("Error sending data");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("Sent DTLS message\n");
|
printf("Sent DTLS message\n");
|
||||||
|
|
||||||
uint8_t rcv[512];
|
uint8_t rcv[512];
|
||||||
if (sock_dtls_recv(&dtls_sock, &session, rcv, sizeof(rcv), SOCK_NO_TIMEOUT) < 0) {
|
if ((res = sock_dtls_recv(&dtls_sock, &session, rcv, sizeof(rcv),
|
||||||
printf("Error receiving DTLS message\n");
|
SOCK_NO_TIMEOUT)) >= 0) {
|
||||||
}
|
printf("Received %d bytes: \"%.*s\"\n", (int)res, (int)res,
|
||||||
else {
|
(char *)rcv);
|
||||||
printf("Received DTLS message\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,22 +108,22 @@ void *dtls_server_wrapper(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (active) {
|
while (active) {
|
||||||
if ((msg_try_receive(&msg) == 1) && (msg.type == DTLS_STOP_SERVER_MSG)) {
|
if ((msg_try_receive(&msg) == 1) &&
|
||||||
|
(msg.type == DTLS_STOP_SERVER_MSG)){
|
||||||
active = false;
|
active = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res = sock_dtls_recv(&sock, &session, rcv, sizeof(rcv),
|
res = sock_dtls_recv(&sock, &session, rcv, sizeof(rcv),
|
||||||
10 * US_PER_SEC);
|
10 * US_PER_SEC);
|
||||||
if (res < 0) {
|
if (res >= 0) {
|
||||||
if (res != -ETIMEDOUT) {
|
printf("Received %d bytes -- (echo)\n", (int)res);
|
||||||
printf("Error receiving UDP over DTLS %d", (int)res);
|
res = sock_dtls_send(&sock, &session, rcv, (size_t)res, 0);
|
||||||
|
if (res < 0) {
|
||||||
|
printf("Error resending DTLS message: %d", (int)res);
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
printf("Received %d bytes -- (echo!)\n", (int)res);
|
else if (res == -SOCK_DTLS_HANDSHAKE) {
|
||||||
res = sock_dtls_send(&sock, &session, rcv, (size_t)res);
|
printf("New client connected\n");
|
||||||
if (res < 0) {
|
|
||||||
printf("Error resending DTLS message: %d", (int)res);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,15 +24,6 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "dtls_debug.h"
|
#include "dtls_debug.h"
|
||||||
|
|
||||||
#define DTLS_HANDSHAKE_BUFSIZE (256) /**< Size buffer used in handshake
|
|
||||||
to hold credentials */
|
|
||||||
/* ECC handshake takes more time */
|
|
||||||
#ifdef CONFIG_DTLS_ECC
|
|
||||||
#define DTLS_HANDSHAKE_TIMEOUT (30 * US_PER_SEC)
|
|
||||||
#else
|
|
||||||
#define DTLS_HANDSHAKE_TIMEOUT (1 * US_PER_SEC)
|
|
||||||
#endif /* CONFIG_DTLS_ECC */
|
|
||||||
|
|
||||||
#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,
|
||||||
@ -61,6 +52,7 @@ static int _event(struct dtls_context_t *ctx, session_t *session,
|
|||||||
|
|
||||||
static void _session_to_ep(const session_t *session, sock_udp_ep_t *ep);
|
static void _session_to_ep(const session_t *session, sock_udp_ep_t *ep);
|
||||||
static void _ep_to_session(const sock_udp_ep_t *ep, session_t *session);
|
static void _ep_to_session(const sock_udp_ep_t *ep, session_t *session);
|
||||||
|
static uint32_t _update_timeout(uint32_t start, uint32_t timeout);
|
||||||
|
|
||||||
static dtls_handler_t _dtls_handler = {
|
static dtls_handler_t _dtls_handler = {
|
||||||
.event = _event,
|
.event = _event,
|
||||||
@ -112,7 +104,7 @@ static int _event(struct dtls_context_t *ctx, session_t *session,
|
|||||||
sock_dtls_t *sock = dtls_get_app_data(ctx);
|
sock_dtls_t *sock = dtls_get_app_data(ctx);
|
||||||
msg_t msg = { .type = code };
|
msg_t msg = { .type = code };
|
||||||
#ifdef ENABLE_DEBUG
|
#ifdef ENABLE_DEBUG
|
||||||
switch(code) {
|
switch (code) {
|
||||||
case DTLS_EVENT_CONNECT:
|
case DTLS_EVENT_CONNECT:
|
||||||
DEBUG("sock_dtls: event connect\n");
|
DEBUG("sock_dtls: event connect\n");
|
||||||
break;
|
break;
|
||||||
@ -155,7 +147,7 @@ static int _get_psk_info(struct dtls_context_t *ctx, const session_t *session,
|
|||||||
|
|
||||||
const void *c = NULL;
|
const void *c = NULL;
|
||||||
size_t c_len = 0;
|
size_t c_len = 0;
|
||||||
switch(type) {
|
switch (type) {
|
||||||
case DTLS_PSK_HINT:
|
case DTLS_PSK_HINT:
|
||||||
DEBUG("sock_dtls: psk hint request\n");
|
DEBUG("sock_dtls: psk hint request\n");
|
||||||
/* Ignored. See https://tools.ietf.org/html/rfc4279#section-5.2 */
|
/* Ignored. See https://tools.ietf.org/html/rfc4279#section-5.2 */
|
||||||
@ -267,27 +259,39 @@ int sock_dtls_create(sock_dtls_t *sock, sock_udp_t *udp_sock,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sock_dtls_session_create(sock_dtls_t *sock, const sock_udp_ep_t *ep,
|
int sock_dtls_session_init(sock_dtls_t *sock, const sock_udp_ep_t *ep,
|
||||||
sock_dtls_session_t *remote)
|
sock_dtls_session_t *remote)
|
||||||
{
|
{
|
||||||
uint8_t rcv_buffer[DTLS_HANDSHAKE_BUFSIZE];
|
|
||||||
msg_t msg;
|
|
||||||
ssize_t res;
|
|
||||||
|
|
||||||
assert(sock);
|
assert(sock);
|
||||||
assert(ep);
|
assert(ep);
|
||||||
assert(remote);
|
assert(remote);
|
||||||
|
|
||||||
|
sock_udp_ep_t local;
|
||||||
|
if (!sock->udp_sock || (sock_udp_get_local(sock->udp_sock, &local) < 0)) {
|
||||||
|
return -EADDRNOTAVAIL;
|
||||||
|
}
|
||||||
|
if (ep->port == 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
switch (ep->family) {
|
||||||
|
case AF_INET:
|
||||||
|
#if IS_ACTIVE(SOCK_HAS_IPV6)
|
||||||
|
case AF_INET6:
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/* prepare a the remote party to connect to */
|
/* prepare a the remote party to connect to */
|
||||||
memcpy(&remote->ep, ep, sizeof(sock_udp_ep_t));
|
memcpy(&remote->ep, ep, sizeof(sock_udp_ep_t));
|
||||||
memcpy(&remote->dtls_session.addr, &ep->addr.ipv6, sizeof(ipv6_addr_t));
|
memcpy(&remote->dtls_session.addr, &ep->addr.ipv6, sizeof(ipv6_addr_t));
|
||||||
_ep_to_session(ep, &remote->dtls_session);
|
_ep_to_session(ep, &remote->dtls_session);
|
||||||
|
|
||||||
/* start a handshake */
|
/* start the handshake */
|
||||||
DEBUG("sock_dtls: starting handshake\n");
|
int 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: %d\n", (int)res);
|
DEBUG("sock_dtls: error establishing a session: %d\n", res);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
else if (res == 0) {
|
else if (res == 0) {
|
||||||
@ -295,28 +299,8 @@ int sock_dtls_session_create(sock_dtls_t *sock, const sock_udp_ep_t *ep,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* receive all handshake messages or timeout if timer expires */
|
/* New handshake initiated */
|
||||||
while (!mbox_try_get(&sock->mbox, &msg) ||
|
return 1;
|
||||||
msg.type != DTLS_EVENT_CONNECTED) {
|
|
||||||
res = sock_udp_recv(sock->udp_sock, rcv_buffer, sizeof(rcv_buffer),
|
|
||||||
DTLS_HANDSHAKE_TIMEOUT, &remote->ep);
|
|
||||||
if (res <= 0) {
|
|
||||||
DEBUG("sock_dtls: error receiving handshake messages: %d\n", (int)res);
|
|
||||||
/* deletes peer created in dtls_connect() */
|
|
||||||
dtls_peer_t *peer = dtls_get_peer(sock->dtls_ctx,
|
|
||||||
&remote->dtls_session);
|
|
||||||
dtls_reset_peer(sock->dtls_ctx, peer);
|
|
||||||
return -ETIMEDOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = dtls_handle_message(sock->dtls_ctx, &remote->dtls_session,
|
|
||||||
rcv_buffer, res);
|
|
||||||
/* stop handshake if received fatal level alert */
|
|
||||||
if (res == -1) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sock_dtls_session_destroy(sock_dtls_t *sock, sock_dtls_session_t *remote)
|
void sock_dtls_session_destroy(sock_dtls_t *sock, sock_dtls_session_t *remote)
|
||||||
@ -325,7 +309,7 @@ void sock_dtls_session_destroy(sock_dtls_t *sock, sock_dtls_session_t *remote)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssize_t sock_dtls_send(sock_dtls_t *sock, sock_dtls_session_t *remote,
|
ssize_t sock_dtls_send(sock_dtls_t *sock, sock_dtls_session_t *remote,
|
||||||
const void *data, size_t len)
|
const void *data, size_t len, uint32_t timeout)
|
||||||
{
|
{
|
||||||
assert(sock);
|
assert(sock);
|
||||||
assert(remote);
|
assert(remote);
|
||||||
@ -335,6 +319,10 @@ ssize_t sock_dtls_send(sock_dtls_t *sock, sock_dtls_session_t *remote,
|
|||||||
if (!dtls_get_peer(sock->dtls_ctx, &remote->dtls_session)) {
|
if (!dtls_get_peer(sock->dtls_ctx, &remote->dtls_session)) {
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
if (timeout == 0) {
|
||||||
|
return -ENOTCONN;
|
||||||
|
}
|
||||||
|
|
||||||
/* no session with remote, creating new session.
|
/* no session with remote, creating new session.
|
||||||
* This will also create new peer for this session */
|
* This will also create new peer for this session */
|
||||||
res = dtls_connect(sock->dtls_ctx, &remote->dtls_session);
|
res = dtls_connect(sock->dtls_ctx, &remote->dtls_session);
|
||||||
@ -346,22 +334,31 @@ ssize_t sock_dtls_send(sock_dtls_t *sock, sock_dtls_session_t *remote,
|
|||||||
/* handshake initiated, wait until connected or timed out */
|
/* handshake initiated, wait until connected or timed out */
|
||||||
|
|
||||||
msg_t msg;
|
msg_t msg;
|
||||||
|
bool is_timed_out = false;
|
||||||
do {
|
do {
|
||||||
res = xtimer_msg_receive_timeout(&msg, 3 * DTLS_HANDSHAKE_TIMEOUT);
|
uint32_t start = xtimer_now_usec();
|
||||||
|
res = xtimer_msg_receive_timeout(&msg, timeout);
|
||||||
|
|
||||||
|
if (timeout != SOCK_NO_TIMEOUT) {
|
||||||
|
timeout = _update_timeout(start, timeout);
|
||||||
|
is_timed_out = (res < 0) || (timeout == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while ((res != -1) && (msg.type != DTLS_EVENT_CONNECTED));
|
while (!is_timed_out && (msg.type != DTLS_EVENT_CONNECTED));
|
||||||
if (res == -1) {
|
if (is_timed_out && (msg.type != DTLS_EVENT_CONNECTED)) {
|
||||||
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 */
|
||||||
dtls_peer_t *peer = dtls_get_peer(sock->dtls_ctx, &remote->dtls_session);
|
dtls_peer_t *peer = dtls_get_peer(sock->dtls_ctx,
|
||||||
|
&remote->dtls_session);
|
||||||
dtls_reset_peer(sock->dtls_ctx, peer);
|
dtls_reset_peer(sock->dtls_ctx, peer);
|
||||||
return -EHOSTUNREACH;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dtls_write(sock->dtls_ctx, &remote->dtls_session, (uint8_t *)data, len);
|
return dtls_write(sock->dtls_ctx, &remote->dtls_session,
|
||||||
|
(uint8_t *)data, 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)
|
||||||
@ -392,7 +389,7 @@ ssize_t sock_dtls_recv(sock_dtls_t *sock, sock_dtls_session_t *remote,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* loop breaks when timeout or application data read */
|
/* loop breaks when timeout or application data read */
|
||||||
while(1) {
|
while (1) {
|
||||||
uint32_t start_recv = xtimer_now_usec();
|
uint32_t start_recv = xtimer_now_usec();
|
||||||
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);
|
||||||
@ -406,13 +403,17 @@ ssize_t sock_dtls_recv(sock_dtls_t *sock, sock_dtls_session_t *remote,
|
|||||||
(uint8_t *)data, res);
|
(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);
|
timeout = _update_timeout(start_recv, timeout);
|
||||||
timeout = (time_passed > timeout) ? 0: timeout - time_passed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msg_t msg;
|
||||||
if (sock->buf != NULL) {
|
if (sock->buf != NULL) {
|
||||||
return _copy_buffer(sock, data, max_len);
|
return _copy_buffer(sock, data, max_len);
|
||||||
}
|
}
|
||||||
|
else if (mbox_try_get(&sock->mbox, &msg) &&
|
||||||
|
msg.type == DTLS_EVENT_CONNECTED) {
|
||||||
|
return -SOCK_DTLS_HANDSHAKE;
|
||||||
|
}
|
||||||
else if (timeout == 0) {
|
else if (timeout == 0) {
|
||||||
DEBUG("sock_dtls: timed out while decrypting message\n");
|
DEBUG("sock_dtls: timed out while decrypting message\n");
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
@ -448,4 +449,10 @@ 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 inline uint32_t _update_timeout(uint32_t start, uint32_t timeout)
|
||||||
|
{
|
||||||
|
uint32_t diff = (xtimer_now_usec() - start);
|
||||||
|
return (diff > timeout) ? 0: timeout - diff;
|
||||||
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
@ -29,12 +29,15 @@
|
|||||||
* 2. Add the credential using @ref credman_add()
|
* 2. Add the credential using @ref credman_add()
|
||||||
* - Server operation
|
* - Server operation
|
||||||
* 1. Create UDP sock @ref sock_udp_create()
|
* 1. Create UDP sock @ref sock_udp_create()
|
||||||
* 2. Create DTLS sock @ref sock_dtls_create() using role @ref SOCK_DTLS_SERVER
|
* 2. Create DTLS sock @ref sock_dtls_create() using role
|
||||||
|
* @ref SOCK_DTLS_SERVER
|
||||||
* 3. Start listening with @ref sock_dtls_recv()
|
* 3. Start listening with @ref sock_dtls_recv()
|
||||||
* - Client operation
|
* - Client operation
|
||||||
* 1. Create UDP sock @ref sock_udp_create()
|
* 1. Create UDP sock @ref sock_udp_create()
|
||||||
* 2. Create DTLS sock @ref sock_dtls_create() using role @ref SOCK_DTLS_CLIENT
|
* 2. Create DTLS sock @ref sock_dtls_create() using role
|
||||||
* 3. Create session to server @ref sock_dtls_session_create()
|
* @ref SOCK_DTLS_CLIENT
|
||||||
|
* 3. Start handshake session to server @ref sock_dtls_session_init()
|
||||||
|
* 4. Handle incoming handshake packets with @ref sock_dtls_recv()
|
||||||
* 4. Send packet to server @ref sock_dtls_send()
|
* 4. Send packet to server @ref sock_dtls_send()
|
||||||
*
|
*
|
||||||
* ## Makefile Includes
|
* ## Makefile Includes
|
||||||
@ -109,7 +112,7 @@
|
|||||||
* .y = server_ecdsa_pub_key_y,
|
* .y = server_ecdsa_pub_key_y,
|
||||||
* },
|
* },
|
||||||
* .client_keys = other_pubkeys,
|
* .client_keys = other_pubkeys,
|
||||||
* .client_keys_size = sizeof(other_pubkeys) / sizeof(other_pubkeys[0]),
|
* .client_keys_size = ARRAY_SIZE(other_pubkeys),
|
||||||
* },
|
* },
|
||||||
* },
|
* },
|
||||||
* };
|
* };
|
||||||
@ -298,7 +301,7 @@
|
|||||||
* #define SOCK_DTLS_CLIENT_TAG (20)
|
* #define SOCK_DTLS_CLIENT_TAG (20)
|
||||||
*
|
*
|
||||||
* #ifndef SERVER_ADDR
|
* #ifndef SERVER_ADDR
|
||||||
* #define SERVER_ADDR "fe80::aa:bb:cc:dd" // replace this with the server address
|
* #define SERVER_ADDR "fe80::aa:bb:cc:dd" // replace with the server address
|
||||||
* #endif
|
* #endif
|
||||||
*
|
*
|
||||||
* int main(void)
|
* int main(void)
|
||||||
@ -312,7 +315,7 @@
|
|||||||
* sock_udp_ep_t local = SOCK_IPV6_EP_ANY;
|
* sock_udp_ep_t local = SOCK_IPV6_EP_ANY;
|
||||||
* local.port = 12345;
|
* local.port = 12345;
|
||||||
*
|
*
|
||||||
* sock_udp_ep_t remote;
|
* sock_udp_ep_t remote = SOCK_IPV6_EP_ANY;
|
||||||
* remote.port = DTLS_DEFAULT_PORT;
|
* remote.port = DTLS_DEFAULT_PORT;
|
||||||
* remote.netif = gnrc_netif_iter(NULL)->pid; // only if gnrc_netif_highlander() returns true
|
* remote.netif = gnrc_netif_iter(NULL)->pid; // only if gnrc_netif_highlander() returns true
|
||||||
*
|
*
|
||||||
@ -337,7 +340,8 @@
|
|||||||
* return -1;
|
* return -1;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* if (sock_dtls_session_create(&dtls_sock, &remote, &session) < 0) {
|
* if (sock_dtls_session_create(&dtls_sock, &remote, &session,
|
||||||
|
* SOCK_NO_TIMEOUT) < 0) {
|
||||||
* puts("Error creating session");
|
* puts("Error creating session");
|
||||||
* sock_dtls_close(&dtls_sock);
|
* sock_dtls_close(&dtls_sock);
|
||||||
* sock_udp_close(&udp_sock);
|
* sock_udp_close(&udp_sock);
|
||||||
@ -345,10 +349,11 @@
|
|||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* const char data[] = "HELLO";
|
* const char data[] = "HELLO";
|
||||||
* int res = sock_dtls_send(&dtls_sock, &session, data, sizeof(data));
|
* int res = sock_dtls_send(&dtls_sock, &session, data, sizeof(data), 0);
|
||||||
* if (res >= 0) {
|
* if (res >= 0) {
|
||||||
* printf("Sent %d bytes\n", res);
|
* printf("Sent %d bytes\n", res);
|
||||||
* res = sock_dtls_recv(&dtls_sock, &session, rcv, sizeof(rcv), SOCK_NO_TIMEOUT);
|
* res = sock_dtls_recv(&dtls_sock, &session, rcv, sizeof(rcv),
|
||||||
|
* SOCK_NO_TIMEOUT);
|
||||||
* if (res > 0) {
|
* if (res > 0) {
|
||||||
* printf("Received %d bytes\n", res);
|
* printf("Received %d bytes\n", res);
|
||||||
* }
|
* }
|
||||||
@ -378,7 +383,7 @@
|
|||||||
* listening port, which is DTLS_DEFAULT_PORT (20220).
|
* listening port, which is DTLS_DEFAULT_PORT (20220).
|
||||||
*
|
*
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
||||||
* sock_udp_ep_t remote;
|
* sock_udp_ep_t remote = SOCK_IPV6_EP_ANY;
|
||||||
* remote.port = DTLS_DEFAULT_PORT;
|
* remote.port = DTLS_DEFAULT_PORT;
|
||||||
* remote.netif = gnrc_netif_iter(NULL)->pid; // only if gnrc_netif_highlander() returns true
|
* remote.netif = gnrc_netif_iter(NULL)->pid; // only if gnrc_netif_highlander() returns true
|
||||||
*
|
*
|
||||||
@ -390,10 +395,18 @@
|
|||||||
*
|
*
|
||||||
* After the UDP sock is created, we can proceed with creating the DTLS sock.
|
* After the UDP sock is created, we can proceed with creating the DTLS sock.
|
||||||
* Before sending the packet, we must first create a session with the remote
|
* Before sending the packet, we must first create a session with the remote
|
||||||
* endpoint using @ref sock_dtls_session_create(). If the handshake is
|
* endpoint using @ref sock_dtls_session_create(). We can set the timeout to `0`
|
||||||
* successful and the session is created, we send packets to it using
|
* if we want the function returns immediately after starting the handshake.
|
||||||
* @ref sock_dtls_send(). If the packet is successfully sent, we listen for
|
* In that case, we will need to call @ref sock_dtls_recv() to receive and
|
||||||
* the response with @ref sock_dtls_recv().
|
* process all the handshake packets. If the handshake is successful and the
|
||||||
|
* session is created, we send packets to it using @ref sock_dtls_send().
|
||||||
|
* As we already know the session exists, we can set the timeout to `0` and
|
||||||
|
* listen to the reply with @ref sock_dtls_recv().
|
||||||
|
*
|
||||||
|
* Alternatively, set the timeout to of @ref sock_dtls_send() to the duration we
|
||||||
|
* want to wait for the handshake process. We can also set the timeout to
|
||||||
|
* @ref SOCK_NO_TIMEOUT to block indefinitely until handshake is complete.
|
||||||
|
* After handshake completes, the packet will be sent.
|
||||||
*
|
*
|
||||||
* @ref sock_dtls_create() and @ref sock_dtls_close() only manages the DTLS
|
* @ref sock_dtls_create() and @ref sock_dtls_close() only manages the DTLS
|
||||||
* layer. That means we still have to clean up the created UDP sock from before
|
* layer. That means we still have to clean up the created UDP sock from before
|
||||||
@ -415,7 +428,8 @@
|
|||||||
* return -1;
|
* return -1;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* if (sock_dtls_session_create(&dtls_sock, &remote, &session) < 0) {
|
* if (sock_dtls_session_create(&dtls_sock, &remote, &session,
|
||||||
|
* SOCK_NO_TIMEOUT) < 0) {
|
||||||
* puts("Error creating session");
|
* puts("Error creating session");
|
||||||
* sock_dtls_close(&dtls_sock);
|
* sock_dtls_close(&dtls_sock);
|
||||||
* sock_udp_close(&udp_sock);
|
* sock_udp_close(&udp_sock);
|
||||||
@ -423,10 +437,11 @@
|
|||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* const char data[] = "HELLO";
|
* const char data[] = "HELLO";
|
||||||
* int res = sock_dtls_send(&dtls_sock, &session, data, sizeof(data));
|
* int res = sock_dtls_send(&dtls_sock, &session, data, sizeof(data), 0);
|
||||||
* if (res >= 0) {
|
* if (res >= 0) {
|
||||||
* printf("Sent %d bytes: %*.s\n", res, res, data);
|
* printf("Sent %d bytes: %*.s\n", res, res, data);
|
||||||
* res = sock_dtls_recv(&dtls_sock, &session, rcv, sizeof(rcv), SOCK_NO_TIMEOUT);
|
* res = sock_dtls_recv(&dtls_sock, &session, rcv, sizeof(rcv),
|
||||||
|
* SOCK_NO_TIMEOUT);
|
||||||
* if (res > 0) {
|
* if (res > 0) {
|
||||||
* printf("Received %d bytes: %*.s\n", res, res, rcv);
|
* printf("Received %d bytes: %*.s\n", res, res, rcv);
|
||||||
* }
|
* }
|
||||||
@ -476,6 +491,14 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef DTLS_HANDSHAKE_BUFSIZE
|
||||||
|
#define DTLS_HANDSHAKE_BUFSIZE (256) /**< Size buffer used in handshake to
|
||||||
|
hold credentials */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SOCK_DTLS_HANDSHAKE (EXDEV) /**< Return value for a successful
|
||||||
|
handshake */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief DTLS version number
|
* @brief DTLS version number
|
||||||
* @anchor sock_dtls_prot_version
|
* @anchor sock_dtls_prot_version
|
||||||
@ -547,25 +570,24 @@ int sock_dtls_create(sock_dtls_t *sock, sock_udp_t *udp_sock,
|
|||||||
credman_tag_t tag, unsigned version, unsigned role);
|
credman_tag_t tag, unsigned version, unsigned role);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new DTLS session
|
* @brief Initialize session handshake.
|
||||||
*
|
*
|
||||||
* Initializes handshake process with a DTLS server at @p ep.
|
* Sends a ClientHello message to initialize the handshake. Call
|
||||||
|
* @ref sock_dtls_recv() to finish the handshake.
|
||||||
*
|
*
|
||||||
* @param[in] sock DLTS sock to use
|
* @param[in] sock DTLS sock to use
|
||||||
* @param[in] ep Remote endpoint of the session
|
* @param[in] ep Remote endpoint to start a handshake with
|
||||||
* @param[out] remote The created session, cannot be NULL
|
* @param[out] remote Resulting session
|
||||||
*
|
*
|
||||||
* @return 0 on success
|
* @return 1, if new handshake is started
|
||||||
* @return -EAGAIN, if DTLS_HANDSHAKE_TIMEOUT is `0` and no data is available.
|
* @return 0, if there is an existing session
|
||||||
* @return -EADDRNOTAVAIL, if the local endpoint of @p sock is not set.
|
* @return -ENOMEM, not enough memory to allocate for new peer
|
||||||
* @return -EINVAL, if @p remote is invalid or @p sock is not properly
|
* @return -EADDRNOTAVAIL, if the local endpoint of @p sock is not set.
|
||||||
* initialized (or closed while sock_udp_recv() blocks).
|
* @return -EINVAL, if @p remote is invalid or @p sock is not properly
|
||||||
* @return -ENOBUFS, if buffer space is not large enough to store received
|
* initialized (or closed while sock_udp_recv() blocks).
|
||||||
* credentials.
|
|
||||||
* @return -ETIMEDOUT, if timed out when trying to create session.
|
|
||||||
*/
|
*/
|
||||||
int sock_dtls_session_create(sock_dtls_t *sock, const sock_udp_ep_t *ep,
|
int sock_dtls_session_init(sock_dtls_t *sock, const sock_udp_ep_t *ep,
|
||||||
sock_dtls_session_t *remote);
|
sock_dtls_session_t *remote);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destroys an existing DTLS session
|
* @brief Destroys an existing DTLS session
|
||||||
@ -578,7 +600,7 @@ int sock_dtls_session_create(sock_dtls_t *sock, const sock_udp_ep_t *ep,
|
|||||||
void sock_dtls_session_destroy(sock_dtls_t *sock, sock_dtls_session_t *remote);
|
void sock_dtls_session_destroy(sock_dtls_t *sock, sock_dtls_session_t *remote);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Decrypts and reads a message from a remote peer.
|
* @brief Receive handshake messages and application data from remote peer.
|
||||||
*
|
*
|
||||||
* @param[in] sock DTLS sock to use.
|
* @param[in] sock DTLS sock to use.
|
||||||
* @param[out] remote Remote DTLS session of the received data.
|
* @param[out] remote Remote DTLS session of the received data.
|
||||||
@ -593,7 +615,8 @@ void sock_dtls_session_destroy(sock_dtls_t *sock, sock_dtls_session_t *remote);
|
|||||||
*
|
*
|
||||||
* @note Function may block if data is not available and @p timeout != 0
|
* @note Function may block if data is not available and @p timeout != 0
|
||||||
*
|
*
|
||||||
* @return The number of bytes received on success
|
* @return The number of bytes received on success
|
||||||
|
* @return -SOCK_DTLS_HANDSHAKE when new handshake is completed
|
||||||
* @return -EADDRNOTAVAIL, if the local endpoint of @p sock is not set.
|
* @return -EADDRNOTAVAIL, if the local endpoint of @p sock is not set.
|
||||||
* @return -EAGAIN, if @p timeout is `0` and no data is available.
|
* @return -EAGAIN, if @p timeout is `0` and no data is available.
|
||||||
* @return -EINVAL, if @p remote is invalid or @p sock is not properly
|
* @return -EINVAL, if @p remote is invalid or @p sock is not properly
|
||||||
@ -657,28 +680,32 @@ ssize_t sock_dtls_recv_buf(sock_dtls_t *sock, sock_dtls_session_t *remote,
|
|||||||
* if no session exist between client and server.
|
* if no session exist between client and server.
|
||||||
* @param[in] data Pointer where the data to be send are stored
|
* @param[in] data Pointer where the data to be send are stored
|
||||||
* @param[in] len Length of @p data to be send
|
* @param[in] len Length of @p data to be send
|
||||||
|
* @param[in] timeout Handshake timeout in microseconds.
|
||||||
|
* If `timeout > 0`, will start a new handshake if no
|
||||||
|
* session exists yet. The function will block until
|
||||||
|
* handshake completed or timed out.
|
||||||
|
* May be SOCK_NO_TIMEOUT to block indefinitely until
|
||||||
|
* handshake complete.
|
||||||
*
|
*
|
||||||
* @note Function may block until a session is created if there is no
|
* @note When blocking, we will need an extra thread to call
|
||||||
* existing session with @p remote.
|
* @ref sock_dtls_recv() function to handle the incoming handshake
|
||||||
*
|
* messages.
|
||||||
* @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 -ENOTCONN, if `timeout == 0` and no existing session exists with
|
||||||
|
* @p remote
|
||||||
* @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
|
||||||
* sock_dtls_session_t::ep::family of @p remote is != AF_UNSPEC and
|
* sock_dtls_session_t::ep::family of @p remote is != AF_UNSPEC and
|
||||||
* not supported.
|
* not supported.
|
||||||
* @return -EHOSTUNREACH, if sock_dtls_session_t::ep of @p remote is not
|
|
||||||
* reachable.
|
|
||||||
* @return -EINVAL, if sock_udp_ep_t::addr of @p remote->ep is an
|
* @return -EINVAL, if sock_udp_ep_t::addr of @p remote->ep is an
|
||||||
* invalid address.
|
* invalid address.
|
||||||
* @return -EINVAL, if sock_udp_ep_t::port of @p remote->ep is 0.
|
* @return -EINVAL, if sock_udp_ep_t::port of @p remote->ep is 0.
|
||||||
* @return -ENOMEM, if no memory was available to send @p data.
|
* @return -ENOMEM, if no memory was available to send @p data.
|
||||||
|
* @return -ETIMEDOUT, `0 < timeout < SOCK_NO_TIMEOUT` and timed out.
|
||||||
*/
|
*/
|
||||||
ssize_t sock_dtls_send(sock_dtls_t *sock, sock_dtls_session_t *remote,
|
ssize_t sock_dtls_send(sock_dtls_t *sock, sock_dtls_session_t *remote,
|
||||||
const void *data, size_t len);
|
const void *data, size_t len, uint32_t timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Closes a DTLS sock
|
* @brief Closes a DTLS sock
|
||||||
@ -694,6 +721,49 @@ ssize_t sock_dtls_send(sock_dtls_t *sock, sock_dtls_session_t *remote,
|
|||||||
*/
|
*/
|
||||||
void sock_dtls_close(sock_dtls_t *sock);
|
void sock_dtls_close(sock_dtls_t *sock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a new DTLS session
|
||||||
|
*
|
||||||
|
* Initiates a handshake with a DTLS server at @p ep and wait until it
|
||||||
|
* completes or timed out.
|
||||||
|
*
|
||||||
|
* @deprecated Will not be available after the 2020.10 release.
|
||||||
|
* Please use @ref sock_dtls_session_init() and
|
||||||
|
* @ref sock_dtls_recv() instead.
|
||||||
|
*
|
||||||
|
* @param[in] sock DLTS sock to use
|
||||||
|
* @param[in] ep Remote endpoint of the session
|
||||||
|
* @param[out] remote The created session, cannot be NULL
|
||||||
|
* @param[in] timeout Timeout to wait for handshake to finish.
|
||||||
|
* Returns immediately if 0.
|
||||||
|
* May be SOCK_NO_TIMEOUT to wait indefinitely until
|
||||||
|
* handshake complete.
|
||||||
|
*
|
||||||
|
* @return 0 on success
|
||||||
|
* @return -ENOMEM, if no memory to allocate for new peer
|
||||||
|
* @return -EADDRNOTAVAIL, if the local endpoint of @p sock is not set.
|
||||||
|
* @return -EINVAL, if @p remote is invalid or @p sock is not properly
|
||||||
|
* initialized (or closed while sock_udp_recv() blocks).
|
||||||
|
*/
|
||||||
|
static inline int sock_dtls_session_create(sock_dtls_t *sock,
|
||||||
|
const sock_udp_ep_t *ep,
|
||||||
|
sock_dtls_session_t *remote,
|
||||||
|
unsigned timeout)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
uint8_t buf[DTLS_HANDSHAKE_BUFSIZE];
|
||||||
|
|
||||||
|
assert(sock);
|
||||||
|
assert(remote);
|
||||||
|
|
||||||
|
res = sock_dtls_session_init(sock, ep, remote);
|
||||||
|
if (res <= 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock_dtls_recv(sock, remote, buf, sizeof(buf), timeout);
|
||||||
|
}
|
||||||
|
|
||||||
#include "sock_dtls_types.h"
|
#include "sock_dtls_types.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
Loading…
Reference in New Issue
Block a user