From 20805548b39e627e58d15768cf1575a2896d4189 Mon Sep 17 00:00:00 2001 From: "Martine S. Lenders" Date: Thu, 20 Feb 2020 12:09:20 +0100 Subject: [PATCH 1/8] lwip: introduce sock base-type --- pkg/lwip/contrib/sock/ip/lwip_sock_ip.c | 16 +++--- pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c | 60 +++++++++++------------ pkg/lwip/contrib/sock/udp/lwip_sock_udp.c | 18 +++---- pkg/lwip/include/sock_types.h | 24 +++++++-- 4 files changed, 67 insertions(+), 51 deletions(-) diff --git a/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c b/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c index b61b685ae9..e417ba0dcf 100644 --- a/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c +++ b/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c @@ -42,7 +42,7 @@ int sock_ip_create(sock_ip_t *sock, const sock_ip_ep_t *local, if ((res = lwip_sock_create(&tmp, (struct _sock_tl_ep *)local, (struct _sock_tl_ep *)remote, proto, flags, NETCONN_RAW)) == 0) { - sock->conn = tmp; + sock->base.conn = tmp; } return res; } @@ -50,23 +50,23 @@ int sock_ip_create(sock_ip_t *sock, const sock_ip_ep_t *local, void sock_ip_close(sock_ip_t *sock) { assert(sock != NULL); - if (sock->conn != NULL) { - netconn_delete(sock->conn); - sock->conn = NULL; + if (sock->base.conn != NULL) { + netconn_delete(sock->base.conn); + sock->base.conn = NULL; } } int sock_ip_get_local(sock_ip_t *sock, sock_ip_ep_t *ep) { assert(sock != NULL); - return (lwip_sock_get_addr(sock->conn, (struct _sock_tl_ep *)ep, + return (lwip_sock_get_addr(sock->base.conn, (struct _sock_tl_ep *)ep, 1)) ? -EADDRNOTAVAIL : 0; } int sock_ip_get_remote(sock_ip_t *sock, sock_ip_ep_t *ep) { assert(sock != NULL); - return (lwip_sock_get_addr(sock->conn, (struct _sock_tl_ep *)ep, + return (lwip_sock_get_addr(sock->base.conn, (struct _sock_tl_ep *)ep, 0)) ? -ENOTCONN : 0; } @@ -161,7 +161,7 @@ ssize_t sock_ip_recv(sock_ip_t *sock, void *data, size_t max_len, int res; assert((sock != NULL) && (data != NULL) && (max_len > 0)); - if ((res = lwip_sock_recv(sock->conn, timeout, &buf)) < 0) { + if ((res = lwip_sock_recv(sock->base.conn, timeout, &buf)) < 0) { return res; } res = _parse_iphdr(buf, data, max_len, remote); @@ -174,7 +174,7 @@ ssize_t sock_ip_send(sock_ip_t *sock, const void *data, size_t len, { assert((sock != NULL) || (remote != NULL)); assert((len == 0) || (data != NULL)); /* (len != 0) => (data != NULL) */ - return lwip_sock_send(sock ? sock->conn : NULL, data, len, proto, + return lwip_sock_send(sock ? sock->base.conn : NULL, data, len, proto, (struct _sock_tl_ep *)remote, NETCONN_RAW); } diff --git a/pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c b/pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c index 32e362a0a5..61ccbf5556 100644 --- a/pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c +++ b/pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c @@ -27,7 +27,7 @@ static inline void _tcp_sock_init(sock_tcp_t *sock, struct netconn *conn, { mutex_init(&sock->mutex); mutex_lock(&sock->mutex); - sock->conn = conn; + sock->base.conn = conn; sock->queue = queue; sock->last_buf = NULL; sock->last_offset = 0; @@ -74,13 +74,13 @@ int sock_tcp_listen(sock_tcp_queue_t *queue, const sock_tcp_ep_t *local, assert(tmp != NULL); /* just in case lwIP is trolling */ mutex_init(&queue->mutex); mutex_lock(&queue->mutex); - queue->conn = tmp; + queue->base.conn = tmp; queue->array = queue_array; queue->len = queue_len; queue->used = 0; memset(queue->array, 0, sizeof(sock_tcp_t) * queue_len); mutex_unlock(&queue->mutex); - switch (netconn_listen_with_backlog(queue->conn, queue->len)) { + switch (netconn_listen_with_backlog(queue->base.conn, queue->len)) { case ERR_OK: break; case ERR_MEM: @@ -90,8 +90,8 @@ int sock_tcp_listen(sock_tcp_queue_t *queue, const sock_tcp_ep_t *local, case ERR_VAL: return -EINVAL; default: - assert(false); /* should not happen since queue->conn is not closed - * and we have a TCP conn */ + assert(false); /* should not happen since queue->base.conn is not + * closed and we have a TCP conn */ break; } return 0; @@ -101,10 +101,10 @@ void sock_tcp_disconnect(sock_tcp_t *sock) { assert(sock != NULL); mutex_lock(&sock->mutex); - if (sock->conn != NULL) { - netconn_close(sock->conn); - netconn_delete(sock->conn); - sock->conn = NULL; + if (sock->base.conn != NULL) { + netconn_close(sock->base.conn); + netconn_delete(sock->base.conn); + sock->base.conn = NULL; /* if sock came from a sock_tcp_queue_t: since sock is a pointer in it's * array it is also deleted from there, but we need to decrement the used * counter */ @@ -122,10 +122,10 @@ void sock_tcp_stop_listen(sock_tcp_queue_t *queue) { assert(queue != NULL); mutex_lock(&queue->mutex); - if (queue->conn != NULL) { - netconn_close(queue->conn); - netconn_delete(queue->conn); - queue->conn = NULL; + if (queue->base.conn != NULL) { + netconn_close(queue->base.conn); + netconn_delete(queue->base.conn); + queue->base.conn = NULL; /* sever connections established through this queue */ for (unsigned i = 0; i < queue->len; i++) { sock_tcp_disconnect(&queue->array[i]); @@ -143,7 +143,7 @@ int sock_tcp_get_local(sock_tcp_t *sock, sock_tcp_ep_t *ep) int res = 0; assert(sock != NULL); mutex_lock(&sock->mutex); - if ((sock->conn == NULL) || lwip_sock_get_addr(sock->conn, + if ((sock->base.conn == NULL) || lwip_sock_get_addr(sock->base.conn, (struct _sock_tl_ep *)ep, 1)) { res = -EADDRNOTAVAIL; @@ -157,7 +157,7 @@ int sock_tcp_get_remote(sock_tcp_t *sock, sock_tcp_ep_t *ep) int res = 0; assert(sock != NULL); mutex_lock(&sock->mutex); - if ((sock->conn == NULL) || lwip_sock_get_addr(sock->conn, + if ((sock->base.conn == NULL) || lwip_sock_get_addr(sock->base.conn, (struct _sock_tl_ep *)ep, 0)) { res = -ENOTCONN; @@ -172,7 +172,7 @@ int sock_tcp_queue_get_local(sock_tcp_queue_t *queue, sock_tcp_ep_t *ep) assert(queue != NULL); mutex_lock(&queue->mutex); - if ((queue->conn == NULL) || lwip_sock_get_addr(queue->conn, + if ((queue->base.conn == NULL) || lwip_sock_get_addr(queue->base.conn, (struct _sock_tl_ep *)ep, 1)) { res = -EADDRNOTAVAIL; @@ -188,7 +188,7 @@ int sock_tcp_accept(sock_tcp_queue_t *queue, sock_tcp_t **sock, int res = 0; assert((queue != NULL) && (sock != NULL)); - if (queue->conn == NULL) { + if (queue->base.conn == NULL) { return -EINVAL; } if (timeout == 0) { @@ -202,19 +202,19 @@ int sock_tcp_accept(sock_tcp_queue_t *queue, sock_tcp_t **sock, if (queue->used < queue->len) { #if LWIP_SO_RCVTIMEO if ((timeout != 0) && (timeout != SOCK_NO_TIMEOUT)) { - netconn_set_recvtimeout(queue->conn, timeout / US_PER_MS); + netconn_set_recvtimeout(queue->base.conn, timeout / US_PER_MS); } else #endif - if ((timeout == 0) && !cib_avail(&queue->conn->acceptmbox.mbox.cib)) { + if ((timeout == 0) && !cib_avail(&queue->base.conn->acceptmbox.mbox.cib)) { mutex_unlock(&queue->mutex); return -EAGAIN; } - switch (netconn_accept(queue->conn, &tmp)) { + switch (netconn_accept(queue->base.conn, &tmp)) { case ERR_OK: for (unsigned short i = 0; i < queue->len; i++) { sock_tcp_t *s = &queue->array[i]; - if (s->conn == NULL) { + if (s->base.conn == NULL) { _tcp_sock_init(s, tmp, queue); queue->used++; assert(queue->used > 0); @@ -244,7 +244,7 @@ int sock_tcp_accept(sock_tcp_queue_t *queue, sock_tcp_t **sock, res = -ENOMEM; } #if LWIP_SO_RCVTIMEO - netconn_set_recvtimeout(queue->conn, 0); + netconn_set_recvtimeout(queue->base.conn, 0); #endif mutex_unlock(&queue->mutex); return res; @@ -259,7 +259,7 @@ ssize_t sock_tcp_read(sock_tcp_t *sock, void *data, size_t max_len, bool done = false; assert((sock != NULL) && (data != NULL) && (max_len > 0)); - if (sock->conn == NULL) { + if (sock->base.conn == NULL) { return -ENOTCONN; } if (timeout == 0) { @@ -272,11 +272,11 @@ ssize_t sock_tcp_read(sock_tcp_t *sock, void *data, size_t max_len, } #if LWIP_SO_RCVTIMEO if ((timeout != 0) && (timeout != SOCK_NO_TIMEOUT)) { - netconn_set_recvtimeout(sock->conn, timeout / US_PER_MS); + netconn_set_recvtimeout(sock->base.conn, timeout / US_PER_MS); } else #endif - if ((timeout == 0) && !cib_avail(&sock->conn->recvmbox.mbox.cib)) { + if ((timeout == 0) && !cib_avail(&sock->base.conn->recvmbox.mbox.cib)) { mutex_unlock(&sock->mutex); return -EAGAIN; } @@ -287,7 +287,7 @@ ssize_t sock_tcp_read(sock_tcp_t *sock, void *data, size_t max_len, } else { err_t err; - if ((err = netconn_recv_tcp_pbuf(sock->conn, &buf)) < 0) { + if ((err = netconn_recv_tcp_pbuf(sock->base.conn, &buf)) < 0) { switch (err) { case ERR_ABRT: res = -ECONNABORTED; @@ -343,9 +343,9 @@ ssize_t sock_tcp_read(sock_tcp_t *sock, void *data, size_t max_len, } /* unset flags */ #if LWIP_SO_RCVTIMEO - netconn_set_recvtimeout(sock->conn, 0); + netconn_set_recvtimeout(sock->base.conn, 0); #endif - netconn_set_nonblocking(sock->conn, false); + netconn_set_nonblocking(sock->base.conn, false); mutex_unlock(&sock->mutex); return res; } @@ -358,11 +358,11 @@ ssize_t sock_tcp_write(sock_tcp_t *sock, const void *data, size_t len) assert(sock != NULL); assert((len == 0) || (data != NULL)); /* (len != 0) => (data != NULL) */ mutex_lock(&sock->mutex); - if (sock->conn == NULL) { + if (sock->base.conn == NULL) { mutex_unlock(&sock->mutex); return -ENOTCONN; } - conn = sock->conn; + conn = sock->base.conn; mutex_unlock(&sock->mutex); /* we won't change anything to sock here (lwip_sock_send neither, since it remote is NULL) so we can leave the mutex */ diff --git a/pkg/lwip/contrib/sock/udp/lwip_sock_udp.c b/pkg/lwip/contrib/sock/udp/lwip_sock_udp.c index aefde44690..597cfb5b07 100644 --- a/pkg/lwip/contrib/sock/udp/lwip_sock_udp.c +++ b/pkg/lwip/contrib/sock/udp/lwip_sock_udp.c @@ -37,7 +37,7 @@ int sock_udp_create(sock_udp_t *sock, const sock_udp_ep_t *local, if ((res = lwip_sock_create(&tmp, (struct _sock_tl_ep *)local, (struct _sock_tl_ep *)remote, 0, flags, NETCONN_UDP)) == 0) { - sock->conn = tmp; + sock->base.conn = tmp; } return res; } @@ -45,23 +45,23 @@ int sock_udp_create(sock_udp_t *sock, const sock_udp_ep_t *local, void sock_udp_close(sock_udp_t *sock) { assert(sock != NULL); - if (sock->conn != NULL) { - netconn_delete(sock->conn); - sock->conn = NULL; + if (sock->base.conn != NULL) { + netconn_delete(sock->base.conn); + sock->base.conn = NULL; } } int sock_udp_get_local(sock_udp_t *sock, sock_udp_ep_t *ep) { assert(sock != NULL); - return (lwip_sock_get_addr(sock->conn, (struct _sock_tl_ep *)ep, + return (lwip_sock_get_addr(sock->base.conn, (struct _sock_tl_ep *)ep, 1)) ? -EADDRNOTAVAIL : 0; } int sock_udp_get_remote(sock_udp_t *sock, sock_udp_ep_t *ep) { assert(sock != NULL); - return (lwip_sock_get_addr(sock->conn, (struct _sock_tl_ep *)ep, + return (lwip_sock_get_addr(sock->base.conn, (struct _sock_tl_ep *)ep, 0)) ? -ENOTCONN : 0; } @@ -73,7 +73,7 @@ ssize_t sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len, int res; assert((sock != NULL) && (data != NULL) && (max_len > 0)); - if ((res = lwip_sock_recv(sock->conn, timeout, &buf)) < 0) { + if ((res = lwip_sock_recv(sock->base.conn, timeout, &buf)) < 0) { return res; } res = buf->p->tot_len; @@ -85,7 +85,7 @@ ssize_t sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len, /* convert remote */ size_t addr_len; #if LWIP_IPV6 - if (sock->conn->type & NETCONN_TYPE_IPV6) { + if (sock->base.conn->type & NETCONN_TYPE_IPV6) { addr_len = sizeof(ipv6_addr_t); remote->family = AF_INET6; } @@ -128,7 +128,7 @@ ssize_t sock_udp_send(sock_udp_t *sock, const void *data, size_t len, if ((remote != NULL) && (remote->port == 0)) { return -EINVAL; } - return lwip_sock_send((sock) ? sock->conn : NULL, data, len, 0, + return lwip_sock_send((sock) ? sock->base.conn : NULL, data, len, 0, (struct _sock_tl_ep *)remote, NETCONN_UDP); } diff --git a/pkg/lwip/include/sock_types.h b/pkg/lwip/include/sock_types.h index ea0a033d27..15f3a2d0c2 100644 --- a/pkg/lwip/include/sock_types.h +++ b/pkg/lwip/include/sock_types.h @@ -25,6 +25,22 @@ extern "C" { #endif +/** + * @brief Forward declaration + * @internal + */ +typedef struct lwip_sock_base lwip_sock_base_t; + +/** + * @brief Sock base type + * @warning For network stack internal purposes only. Do not access members + * externally. + * @internal + */ +struct lwip_sock_base { + struct netconn *conn; /**< lwIP network connection object */ +}; + /** * @brief Raw IP sock type * @warning For network stack internal purposes only. Do not access members @@ -32,7 +48,7 @@ extern "C" { * @internal */ struct sock_ip { - struct netconn *conn; /**< lwIP network connection object */ + lwip_sock_base_t base; /**< parent class */ }; /** @@ -42,7 +58,7 @@ struct sock_ip { * @internal */ struct sock_tcp { - struct netconn *conn; /**< lwIP network connection object */ + lwip_sock_base_t base; /**< parent class */ struct sock_tcp_queue *queue; /**< Queue the sock might have been generated from */ mutex_t mutex; /**< Mutex to protect the sock */ struct pbuf *last_buf; /**< Last received data */ @@ -55,7 +71,7 @@ struct sock_tcp { * externally. */ struct sock_tcp_queue { - struct netconn *conn; /**< lwIP network connection object */ + lwip_sock_base_t base; /**< parent class */ struct sock_tcp *array; /**< Allocation array for sock objects to generate */ mutex_t mutex; /**< Mutex to protect the queue */ unsigned short len; /**< Length of the struct sock_tcp_queue::array */ @@ -69,7 +85,7 @@ struct sock_tcp_queue { * @internal */ struct sock_udp { - struct netconn *conn; /**< lwIP network connection object */ + lwip_sock_base_t base; /**< parent class */ }; #ifdef __cplusplus From 0f391a554e0b92b2f39281d88780e663162a64a4 Mon Sep 17 00:00:00 2001 From: "Martine S. Lenders" Date: Thu, 20 Feb 2020 12:25:31 +0100 Subject: [PATCH 2/8] sock_async_event: fix typo in tcp_queue function This was never checked at compile time before so a naming error sneaked in. --- sys/net/sock/async/event/sock_async_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/net/sock/async/event/sock_async_event.c b/sys/net/sock/async/event/sock_async_event.c index f2e7d6673d..d0954d2986 100644 --- a/sys/net/sock/async/event/sock_async_event.c +++ b/sys/net/sock/async/event/sock_async_event.c @@ -104,7 +104,7 @@ void sock_tcp_queue_event_init(sock_tcp_queue_t *queue, event_queue_t *ev_queue, sock_tcp_queue_cb_t handler) { - sock_async_ctx_t *ctx = sock_tcp_queue_get_async_ctx(sock); + sock_async_ctx_t *ctx = sock_tcp_queue_get_async_ctx(queue); _set_ctx(ctx, ev_queue); ctx->event.cb.tcp_queue = handler; From fc67e6143a9d43fc67ea30d1202ae594edf843fe Mon Sep 17 00:00:00 2001 From: "Martine S. Lenders" Date: Thu, 20 Feb 2020 12:51:19 +0100 Subject: [PATCH 3/8] lwip: provide sock_async support --- pkg/lwip/Makefile.dep | 4 + pkg/lwip/Makefile.include | 4 + pkg/lwip/contrib/sock/ip/lwip_sock_ip.c | 17 +++ pkg/lwip/contrib/sock/lwip_sock.c | 72 ++++++++++- pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c | 26 ++++ pkg/lwip/contrib/sock/udp/lwip_sock_udp.c | 17 +++ pkg/lwip/include/lwipopts.h | 2 +- pkg/lwip/include/sock_types.h | 39 ++++++ ...001-netconn-add-callback-arg-storage.patch | 120 ++++++++++++++++++ 9 files changed, 299 insertions(+), 2 deletions(-) create mode 100644 pkg/lwip/patches/0001-netconn-add-callback-arg-storage.patch diff --git a/pkg/lwip/Makefile.dep b/pkg/lwip/Makefile.dep index 2e00d37edf..0525342e32 100644 --- a/pkg/lwip/Makefile.dep +++ b/pkg/lwip/Makefile.dep @@ -3,3 +3,7 @@ FEATURES_REQUIRED += arch_32bit DEFAULT_MODULE += auto_init_lwip + +ifneq (,$(filter lwip_sock_async,$(USEMODULE))) + USEMODULE += sock_async +endif diff --git a/pkg/lwip/Makefile.include b/pkg/lwip/Makefile.include index 3cd5a28a02..bc6e3cea75 100644 --- a/pkg/lwip/Makefile.include +++ b/pkg/lwip/Makefile.include @@ -15,6 +15,7 @@ PSEUDOMODULES += lwip_stats PSEUDOMODULES += lwip_tcp PSEUDOMODULES += lwip_udp PSEUDOMODULES += lwip_udplite +PSEUDOMODULES += lwip_sock_async ifneq (,$(filter lwip_contrib,$(USEMODULE))) DIRS += $(RIOTBASE)/pkg/lwip/contrib @@ -28,6 +29,9 @@ ifneq (,$(filter lwip_sock,$(USEMODULE))) endif DIRS += $(RIOTBASE)/pkg/lwip/contrib/sock endif +ifneq (,$(filter lwip_sock_async,$(USEMODULE))) + CFLAGS += -DSOCK_HAS_ASYNC +endif ifneq (,$(filter lwip_sock_ip,$(USEMODULE))) DIRS += $(RIOTBASE)/pkg/lwip/contrib/sock/ip endif diff --git a/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c b/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c index e417ba0dcf..e70e3fd47d 100644 --- a/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c +++ b/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c @@ -43,6 +43,9 @@ int sock_ip_create(sock_ip_t *sock, const sock_ip_ep_t *local, (struct _sock_tl_ep *)remote, proto, flags, NETCONN_RAW)) == 0) { sock->base.conn = tmp; +#if IS_ACTIVE(SOCK_HAS_ASYNC) + netconn_set_callback_arg(sock->base.conn, &sock->base); +#endif } return res; } @@ -178,4 +181,18 @@ ssize_t sock_ip_send(sock_ip_t *sock, const void *data, size_t len, (struct _sock_tl_ep *)remote, NETCONN_RAW); } +#ifdef SOCK_HAS_ASYNC +void sock_ip_set_cb(sock_ip_t *sock, sock_ip_cb_t cb) +{ + sock->base.async_cb.ip = cb; +} + +#ifdef SOCK_HAS_ASYNC_CTX +sock_async_ctx_t *sock_ip_get_async_ctx(sock_ip_t *sock) +{ + return &sock->base.async_ctx; +} +#endif /* SOCK_HAS_ASYNC_CTX */ +#endif /* SOCK_HAS_ASYNC */ + /** @} */ diff --git a/pkg/lwip/contrib/sock/lwip_sock.c b/pkg/lwip/contrib/sock/lwip_sock.c index de38335a2a..9be9951c49 100644 --- a/pkg/lwip/contrib/sock/lwip_sock.c +++ b/pkg/lwip/contrib/sock/lwip_sock.c @@ -23,9 +23,12 @@ #include "lwip/err.h" #include "lwip/ip.h" +#include "lwip/tcp.h" #include "lwip/netif.h" #include "lwip/opt.h" +#include "sock_types.h" + #if !LWIP_IPV4 && !LWIP_IPV6 #error "lwip_sock needs IPv4 or IPv6 support" #endif @@ -255,11 +258,78 @@ static int _sock_ep_to_netconn_pars(const struct _sock_tl_ep *local, return res; } +static void _netconn_cb(struct netconn *conn, enum netconn_evt evt, + u16_t len) +{ +#if IS_ACTIVE(SOCK_HAS_ASYNC) + lwip_sock_base_t *sock = netconn_get_callback_arg(conn); + if (sock && conn->pcb.raw && + /* lwIP's TCP implementation initializes callback_arg.socket with -1 + * when not provided */ + (conn->callback_arg.socket != -1)) { + sock_async_flags_t flags = 0; + + (void)len; + switch (evt) { + case NETCONN_EVT_RCVPLUS: + if (LWIP_TCP && (conn->type & NETCONN_TCP)) { +#if LWIP_TCP /* additional guard needed due to dependent member access */ + switch (conn->pcb.tcp->state) { + case CLOSED: + case CLOSE_WAIT: + case CLOSING: + flags |= SOCK_ASYNC_CONN_FIN; + break; + default: + break; + } + if (cib_avail(&conn->acceptmbox.mbox.cib)) { + flags |= SOCK_ASYNC_CONN_RECV; + } + if (cib_avail(&conn->recvmbox.mbox.cib)) { + flags |= SOCK_ASYNC_MSG_RECV; + } +#endif + } + else { + flags |= SOCK_ASYNC_MSG_RECV; + } + break; + case NETCONN_EVT_SENDPLUS: + flags |= SOCK_ASYNC_MSG_SENT; + break; + case NETCONN_EVT_ERROR: + if (LWIP_TCP && (conn->type & NETCONN_TCP)) { + /* try to report this */ + flags |= SOCK_ASYNC_CONN_FIN; + } + break; + case NETCONN_EVT_RCVMINUS: + case NETCONN_EVT_SENDMINUS: + break; + default: + LWIP_ASSERT("unknown event", 0); + break; + } + if (flags && sock->async_cb.gen) { + sock->async_cb.gen(sock, flags); + } + } +#else + (void)conn; + (void)evt; + (void)len; +#endif +} + static int _create(int type, int proto, uint16_t flags, struct netconn **out) { - if ((*out = netconn_new_with_proto_and_callback(type, proto, NULL)) == NULL) { + if ((*out = netconn_new_with_proto_and_callback( + type, proto, + IS_ACTIVE(SOCK_HAS_ASYNC) ? _netconn_cb : NULL)) == NULL) { return -ENOMEM; } + netconn_set_callback_arg(*out, NULL); #if LWIP_IPV4 && LWIP_IPV6 if (type & NETCONN_TYPE_IPV6) { netconn_set_ipv6only(*out, 1); diff --git a/pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c b/pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c index 61ccbf5556..438d0b1fdd 100644 --- a/pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c +++ b/pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c @@ -28,6 +28,7 @@ static inline void _tcp_sock_init(sock_tcp_t *sock, struct netconn *conn, mutex_init(&sock->mutex); mutex_lock(&sock->mutex); sock->base.conn = conn; + netconn_set_callback_arg(sock->base.conn, &sock->base); sock->queue = queue; sock->last_buf = NULL; sock->last_offset = 0; @@ -75,6 +76,7 @@ int sock_tcp_listen(sock_tcp_queue_t *queue, const sock_tcp_ep_t *local, mutex_init(&queue->mutex); mutex_lock(&queue->mutex); queue->base.conn = tmp; + netconn_set_callback_arg(queue->base.conn, &queue->base); queue->array = queue_array; queue->len = queue_len; queue->used = 0; @@ -370,4 +372,28 @@ ssize_t sock_tcp_write(sock_tcp_t *sock, const void *data, size_t len) return res; } +#ifdef SOCK_HAS_ASYNC +void sock_tcp_set_cb(sock_tcp_t *sock, sock_tcp_cb_t cb) +{ + sock->base.async_cb.tcp = cb; +} + +void sock_tcp_queue_set_cb(sock_tcp_queue_t *queue, sock_tcp_queue_cb_t cb) +{ + queue->base.async_cb.tcp_queue = cb; +} + +#ifdef SOCK_HAS_ASYNC_CTX +sock_async_ctx_t *sock_tcp_get_async_ctx(sock_tcp_t *sock) +{ + return &sock->base.async_ctx; +} + +sock_async_ctx_t *sock_tcp_queue_get_async_ctx(sock_tcp_queue_t *queue) +{ + return &queue->base.async_ctx; +} +#endif /* SOCK_HAS_ASYNC_CTX */ +#endif /* SOCK_HAS_ASYNC */ + /** @} */ diff --git a/pkg/lwip/contrib/sock/udp/lwip_sock_udp.c b/pkg/lwip/contrib/sock/udp/lwip_sock_udp.c index 597cfb5b07..77e03d376b 100644 --- a/pkg/lwip/contrib/sock/udp/lwip_sock_udp.c +++ b/pkg/lwip/contrib/sock/udp/lwip_sock_udp.c @@ -38,6 +38,9 @@ int sock_udp_create(sock_udp_t *sock, const sock_udp_ep_t *local, (struct _sock_tl_ep *)remote, 0, flags, NETCONN_UDP)) == 0) { sock->base.conn = tmp; +#if IS_ACTIVE(SOCK_HAS_ASYNC) + netconn_set_callback_arg(sock->base.conn, &sock->base); +#endif } return res; } @@ -132,4 +135,18 @@ ssize_t sock_udp_send(sock_udp_t *sock, const void *data, size_t len, (struct _sock_tl_ep *)remote, NETCONN_UDP); } +#ifdef SOCK_HAS_ASYNC +void sock_udp_set_cb(sock_udp_t *sock, sock_udp_cb_t cb) +{ + sock->base.async_cb.udp = cb; +} + +#ifdef SOCK_HAS_ASYNC_CTX +sock_async_ctx_t *sock_udp_get_async_ctx(sock_udp_t *sock) +{ + return &sock->base.async_ctx; +} +#endif /* SOCK_HAS_ASYNC_CTX */ +#endif /* SOCK_HAS_ASYNC */ + /** @} */ diff --git a/pkg/lwip/include/lwipopts.h b/pkg/lwip/include/lwipopts.h index 7b42705f9d..3a497aeae3 100644 --- a/pkg/lwip/include/lwipopts.h +++ b/pkg/lwip/include/lwipopts.h @@ -129,7 +129,7 @@ extern "C" { #define LWIP_UDPLITE (0) #endif /* MODULE_LWIP_UDPLITE */ -#if defined(MODULE_LWIP_CONN) || defined(MODULE_LWIP_SOCK) +#if defined(MODULE_LWIP_SOCK) #define LWIP_NETCONN (1) #else #define LWIP_NETCONN (0) diff --git a/pkg/lwip/include/sock_types.h b/pkg/lwip/include/sock_types.h index 15f3a2d0c2..2f7126a04e 100644 --- a/pkg/lwip/include/sock_types.h +++ b/pkg/lwip/include/sock_types.h @@ -20,6 +20,9 @@ #include "net/af.h" #include "lwip/api.h" +#ifdef SOCK_HAS_ASYNC +#include "net/sock/async/types.h" +#endif #ifdef __cplusplus extern "C" { @@ -31,6 +34,15 @@ extern "C" { */ typedef struct lwip_sock_base lwip_sock_base_t; +#ifdef SOCK_HAS_ASYNC +/** + * @brief Event callback for @ref lwip_sock_base_t + * @internal + */ +typedef void (*lwip_sock_cb_t)(lwip_sock_base_t *sock, + sock_async_flags_t flags); +#endif /* SOCK_HAS_ASYNC */ + /** * @brief Sock base type * @warning For network stack internal purposes only. Do not access members @@ -39,6 +51,33 @@ typedef struct lwip_sock_base lwip_sock_base_t; */ struct lwip_sock_base { struct netconn *conn; /**< lwIP network connection object */ +#ifdef SOCK_HAS_ASYNC + /** + * @brief Asynchronous upper layer callback + * + * @note All have void return value and a (sock pointer, sock_async_flags_t) + * pair, so casting between these function pointers is okay. + */ + union { + lwip_sock_cb_t gen; /**< generic version */ +#ifdef MODULE_SOCK_IP + sock_ip_cb_t ip; /**< IP version */ +#endif +#ifdef MODULE_SOCK_TCP + sock_tcp_cb_t tcp; /**< TCP version */ + /** + * @brief TCP queue version + */ + sock_tcp_queue_cb_t tcp_queue; +#endif +#ifdef MODULE_SOCK_UDP + sock_udp_cb_t udp; /**< UDP version */ +#endif + } async_cb; +#ifdef SOCK_HAS_ASYNC_CTX + sock_async_ctx_t async_ctx; /**< asynchronous event context */ +#endif /* SOCK_HAS_ASYNC_CTX */ +#endif /* SOCK_HAS_ASYNC */ }; /** diff --git a/pkg/lwip/patches/0001-netconn-add-callback-arg-storage.patch b/pkg/lwip/patches/0001-netconn-add-callback-arg-storage.patch new file mode 100644 index 0000000000..d4a19d4f92 --- /dev/null +++ b/pkg/lwip/patches/0001-netconn-add-callback-arg-storage.patch @@ -0,0 +1,120 @@ +From 59d78b78b683c9212949d4950355ea5f424c1da9 Mon Sep 17 00:00:00 2001 +From: Simon Goldschmidt +Date: Sat, 13 Jul 2019 20:46:36 +0200 +Subject: [PATCH] netconn: add callback arg storage + +This reuses the member 'int socket' by making it a union containing +both int and void pointer. + +See bug #56593. + +Signed-off-by: Simon Goldschmidt +Suggested-by: Wilfred +(cherry picked from commit 5465fdfd6988354e77dc0e7a6117303d4c87cbd0) +--- + src/api/api_msg.c | 4 +--- + src/api/sockets.c | 14 +++++++------- + src/include/lwip/api.h | 11 +++++++---- + 3 files changed, 15 insertions(+), 14 deletions(-) + +diff --git a/src/api/api_msg.c b/src/api/api_msg.c +index 39531024..19218de3 100644 +--- a/src/api/api_msg.c ++++ b/src/api/api_msg.c +@@ -756,10 +756,8 @@ netconn_alloc(enum netconn_type t, netconn_callback callback) + sys_mbox_set_invalid(&conn->acceptmbox); + #endif + conn->state = NETCONN_NONE; +-#if LWIP_SOCKET + /* initialize socket to -1 since 0 is a valid socket */ +- conn->socket = -1; +-#endif /* LWIP_SOCKET */ ++ conn->callback_arg.socket = -1; + conn->callback = callback; + #if LWIP_TCP + conn->current_msg = NULL; +diff --git a/src/api/sockets.c b/src/api/sockets.c +index cb7df914..ce12af1e 100644 +--- a/src/api/sockets.c ++++ b/src/api/sockets.c +@@ -666,8 +666,8 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) + * so nsock->rcvevent is >= 1 here! + */ + SYS_ARCH_PROTECT(lev); +- recvevent = (s16_t)(-1 - newconn->socket); +- newconn->socket = newsock; ++ recvevent = (s16_t)(-1 - newconn->callback_arg.socket); ++ newconn->callback_arg.socket = newsock; + SYS_ARCH_UNPROTECT(lev); + + if (newconn->callback) { +@@ -1735,7 +1735,7 @@ lwip_socket(int domain, int type, int protocol) + set_errno(ENFILE); + return -1; + } +- conn->socket = i; ++ conn->callback_arg.socket = i; + done_socket(&sockets[i - LWIP_SOCKET_OFFSET]); + LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i)); + set_errno(0); +@@ -2484,7 +2484,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) + + /* Get socket */ + if (conn) { +- s = conn->socket; ++ s = conn->callback_arg.socket; + if (s < 0) { + /* Data comes in right away after an accept, even though + * the server task might not have created a new socket yet. +@@ -2492,16 +2492,16 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) + * will use the data later. Note that only receive events + * can happen before the new socket is set up. */ + SYS_ARCH_PROTECT(lev); +- if (conn->socket < 0) { ++ if (conn->callback_arg.socket < 0) { + if (evt == NETCONN_EVT_RCVPLUS) { + /* conn->socket is -1 on initialization + lwip_accept adjusts sock->recvevent if conn->socket < -1 */ +- conn->socket--; ++ conn->callback_arg.socket--; + } + SYS_ARCH_UNPROTECT(lev); + return; + } +- s = conn->socket; ++ s = conn->callback_arg.socket; + SYS_ARCH_UNPROTECT(lev); + } + +diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h +index c2afaf26..d6e8fa1f 100644 +--- a/src/include/lwip/api.h ++++ b/src/include/lwip/api.h +@@ -246,10 +246,10 @@ struct netconn { + all threads when closing while threads are waiting. */ + int mbox_threads_waiting; + #endif +- /** only used for socket layer */ +-#if LWIP_SOCKET +- int socket; +-#endif /* LWIP_SOCKET */ ++ union { ++ int socket; ++ void *ptr; ++ } callback_arg; + #if LWIP_SO_SNDTIMEO + /** timeout to wait for sending data (which means enqueueing data for sending + in internal buffers) in milliseconds */ +@@ -373,6 +373,9 @@ err_t netconn_err(struct netconn *conn); + #define netconn_clear_flags(conn, clr_flags) do { (conn)->flags = (u8_t)((conn)->flags & (u8_t)(~(clr_flags) & 0xff)); } while(0) + #define netconn_is_flag_set(conn, flag) (((conn)->flags & (flag)) != 0) + ++#define netconn_set_callback_arg(conn, arg) do { (conn)->callback_arg.ptr = (arg); } while(0) ++#define netconn_get_callback_arg(conn) ((conn)->callback_arg.ptr) ++ + /** Set the blocking status of netconn calls (@todo: write/send is missing) */ + #define netconn_set_nonblocking(conn, val) do { if(val) { \ + netconn_set_flags(conn, NETCONN_FLAG_NON_BLOCKING); \ +-- +2.25.1 + From ba2dd2cf44189e5d68b57e18c7a7411ca960ad74 Mon Sep 17 00:00:00 2001 From: "Martine S. Lenders" Date: Thu, 20 Feb 2020 18:24:01 +0100 Subject: [PATCH 4/8] tests/lwip: adapt test to use sock_async --- tests/lwip/Makefile | 2 + tests/lwip/ip.c | 41 +++++++++------- tests/lwip/tcp.c | 114 +++++++++++++++++++++++++++----------------- tests/lwip/udp.c | 45 ++++++++++------- 4 files changed, 125 insertions(+), 77 deletions(-) diff --git a/tests/lwip/Makefile b/tests/lwip/Makefile index d7fb08019b..4e229a031e 100644 --- a/tests/lwip/Makefile +++ b/tests/lwip/Makefile @@ -20,6 +20,8 @@ endif USEMODULE += lwip lwip_sock_ip lwip_netdev USEMODULE += lwip_udp lwip_sock_udp USEMODULE += lwip_tcp lwip_sock_tcp +USEMODULE += lwip_sock_async +USEMODULE += sock_async_event USEMODULE += shell USEMODULE += shell_commands USEMODULE += ps diff --git a/tests/lwip/ip.c b/tests/lwip/ip.c index 541c5cf96a..3292ac90d2 100644 --- a/tests/lwip/ip.c +++ b/tests/lwip/ip.c @@ -23,6 +23,7 @@ #include "common.h" #include "od.h" #include "net/af.h" +#include "net/sock/async/event.h" #include "net/sock/ip.h" #include "shell.h" #include "thread.h" @@ -43,25 +44,14 @@ static sock_ip_t server_sock; static char server_stack[THREAD_STACKSIZE_DEFAULT]; static msg_t server_msg_queue[SERVER_MSG_QUEUE_SIZE]; -static void *_server_thread(void *args) +static void _ip_recv(sock_ip_t *sock, sock_async_flags_t flags) { - sock_ip_ep_t server_addr = SOCK_IP_EP_ANY; - uint8_t protocol; - - msg_init_queue(server_msg_queue, SERVER_MSG_QUEUE_SIZE); - /* parse protocol */ - protocol = atoi(args); - if (sock_ip_create(&server_sock, &server_addr, NULL, protocol, 0) < 0) { - return NULL; - } - server_running = true; - printf("Success: started IP server on protocol %u\n", protocol); - while (1) { - int res; + if (flags & SOCK_ASYNC_MSG_RECV) { sock_ip_ep_t src; + int res; - if ((res = sock_ip_recv(&server_sock, sock_inbuf, sizeof(sock_inbuf), - SOCK_NO_TIMEOUT, &src)) < 0) { + if ((res = sock_ip_recv(sock, sock_inbuf, sizeof(sock_inbuf), + 0, &src)) < 0) { puts("Error on receive"); } else if (res == 0) { @@ -82,6 +72,25 @@ static void *_server_thread(void *args) od_hex_dump(sock_inbuf, res, 0); } } +} + +static void *_server_thread(void *args) +{ + event_queue_t queue; + sock_ip_ep_t server_addr = SOCK_IP_EP_ANY; + uint8_t protocol; + + msg_init_queue(server_msg_queue, SERVER_MSG_QUEUE_SIZE); + /* parse protocol */ + protocol = atoi(args); + if (sock_ip_create(&server_sock, &server_addr, NULL, protocol, 0) < 0) { + return NULL; + } + server_running = true; + printf("Success: started IP server on protocol %u\n", protocol); + event_queue_init(&queue); + sock_ip_event_init(&server_sock, &queue, _ip_recv); + event_loop(&queue); return NULL; } diff --git a/tests/lwip/tcp.c b/tests/lwip/tcp.c index 6a0e020f22..5bfdab0a46 100644 --- a/tests/lwip/tcp.c +++ b/tests/lwip/tcp.c @@ -23,6 +23,7 @@ #include "common.h" #include "od.h" #include "net/af.h" +#include "net/sock/async/event.h" #include "net/sock/tcp.h" #include "shell.h" #include "thread.h" @@ -43,6 +44,72 @@ static sock_tcp_t server_sock, client_sock; static sock_tcp_queue_t server_queue; static char server_stack[THREAD_STACKSIZE_DEFAULT]; static msg_t server_msg_queue[SERVER_MSG_QUEUE_SIZE]; +static char _addr_str[IPV6_ADDR_MAX_STR_LEN]; +static event_queue_t _ev_queue; + +static void _tcp_recv(sock_tcp_t *sock, sock_async_flags_t flags) +{ + sock_tcp_ep_t client; + + if (sock_tcp_get_remote(sock, &client) < 0) { + /* socket was disconnected between event firing and this handler */ + return; + } +#ifdef MODULE_LWIP_IPV6 + ipv6_addr_to_str(_addr_str, (ipv6_addr_t *)&client.addr.ipv6, + sizeof(_addr_str)); +#else + ipv4_addr_to_str(_addr_str, (ipv4_addr_t *)&client.addr.ipv4, + sizeof(_addr_str)); +#endif + if (flags & SOCK_ASYNC_MSG_RECV) { + int res; + + /* we don't use timeouts so all errors should be related to a lost + * connection */ + while ((res = sock_tcp_read(sock, sock_inbuf, sizeof(sock_inbuf), + 0)) >= 0) { + printf("Received TCP data from client [%s]:%u:\n", _addr_str, + client.port); + if (res > 0) { + od_hex_dump(sock_inbuf, res, 0); + } + else { + puts("(nul)"); + } + } + } + if (flags & SOCK_ASYNC_CONN_FIN) { + printf("TCP connection to [%s]:%u reset\n", _addr_str, client.port); + sock_tcp_disconnect(sock); + } +} + +static void _tcp_accept(sock_tcp_queue_t *queue, sock_async_flags_t flags) +{ + if (flags & SOCK_ASYNC_CONN_RECV) { + sock_tcp_t *sock = NULL; + int res; + + if ((res = sock_tcp_accept(queue, &sock, 0)) < 0) { + printf("Error on TCP accept [%d]\n", res); + } + else { + sock_tcp_ep_t client; + + sock_tcp_event_init(sock, &_ev_queue, _tcp_recv); + sock_tcp_get_remote(sock, &client); +#ifdef MODULE_LWIP_IPV6 + ipv6_addr_to_str(_addr_str, (ipv6_addr_t *)&client.addr.ipv6, + sizeof(_addr_str)); +#else + ipv4_addr_to_str(_addr_str, (ipv4_addr_t *)&client.addr.ipv4, + sizeof(_addr_str)); +#endif + printf("TCP client [%s]:%u connected\n", _addr_str, client.port); + } + } +} static void *_server_thread(void *args) { @@ -61,48 +128,9 @@ static void *_server_thread(void *args) server_running = true; printf("Success: started TCP server on port %" PRIu16 "\n", server_addr.port); - while (1) { - char client_addr[IPV6_ADDR_MAX_STR_LEN]; - sock_tcp_t *sock = NULL; - int res; - unsigned client_port; - - if ((res = sock_tcp_accept(&server_queue, &sock, SOCK_NO_TIMEOUT)) < 0) { - puts("Error on TCP accept"); - continue; - } - else { - sock_tcp_ep_t client; - - sock_tcp_get_remote(sock, &client); -#ifdef MODULE_LWIP_IPV6 - ipv6_addr_to_str(client_addr, (ipv6_addr_t *)&client.addr.ipv6, - sizeof(client_addr)); -#else - ipv4_addr_to_str(client_addr, (ipv4_addr_t *)&client.addr.ipv4, - sizeof(client_addr)); -#endif - client_port = client.port; - printf("TCP client [%s]:%u connected\n", - client_addr, client_port); - } - /* we don't use timeouts so all errors should be related to a lost - * connection */ - while ((res = sock_tcp_read(sock, sock_inbuf, sizeof(sock_inbuf), - SOCK_NO_TIMEOUT)) >= 0) { - printf("Received TCP data from client [%s]:%u:\n", - client_addr, client_port); - if (res > 0) { - od_hex_dump(sock_inbuf, res, 0); - } - else { - puts("(nul)"); - } - } - printf("TCP connection to [%s]:%u reset, starting to accept again\n", - client_addr, client_port); - sock_tcp_disconnect(sock); - } + event_queue_init(&_ev_queue); + sock_tcp_queue_event_init(&server_queue, &_ev_queue, _tcp_accept); + event_loop(&_ev_queue); return NULL; } @@ -112,7 +140,7 @@ static int tcp_connect(char *addr_str, char *port_str, char *local_port_str) uint16_t local_port = 0; if (client_running) { - puts("Cient already connected"); + puts("Client already connected"); } /* parse destination address */ diff --git a/tests/lwip/udp.c b/tests/lwip/udp.c index c9b17845a2..d0e15bcb6e 100644 --- a/tests/lwip/udp.c +++ b/tests/lwip/udp.c @@ -23,6 +23,7 @@ #include "common.h" #include "od.h" #include "net/af.h" +#include "net/sock/async/event.h" #include "net/sock/udp.h" #include "shell.h" #include "thread.h" @@ -43,28 +44,14 @@ static sock_udp_t server_sock; static char server_stack[THREAD_STACKSIZE_DEFAULT]; static msg_t server_msg_queue[SERVER_MSG_QUEUE_SIZE]; -static void *_server_thread(void *args) +static void _udp_recv(sock_udp_t *sock, sock_async_flags_t flags) { - sock_udp_ep_t server_addr = SOCK_IP_EP_ANY; - int res; - - msg_init_queue(server_msg_queue, SERVER_MSG_QUEUE_SIZE); - /* parse port */ - server_addr.port = atoi(args); - if ((res = sock_udp_create(&server_sock, &server_addr, NULL, 0)) < 0) { - printf("Unable to open UDP server on port %" PRIu16 " (error code %d)\n", - server_addr.port, -res); - return NULL; - } - server_running = true; - printf("Success: started UDP server on port %" PRIu16 "\n", - server_addr.port); - while (1) { + if (flags & SOCK_ASYNC_MSG_RECV) { sock_udp_ep_t src; int res; - if ((res = sock_udp_recv(&server_sock, sock_inbuf, sizeof(sock_inbuf), - SOCK_NO_TIMEOUT, &src)) < 0) { + if ((res = sock_udp_recv(sock, sock_inbuf, sizeof(sock_inbuf), + 0, &src)) < 0) { puts("Error on receive"); } else if (res == 0) { @@ -85,6 +72,28 @@ static void *_server_thread(void *args) od_hex_dump(sock_inbuf, res, 0); } } +} + +static void *_server_thread(void *args) +{ + event_queue_t queue; + sock_udp_ep_t server_addr = SOCK_IP_EP_ANY; + int res; + + msg_init_queue(server_msg_queue, SERVER_MSG_QUEUE_SIZE); + /* parse port */ + server_addr.port = atoi(args); + if ((res = sock_udp_create(&server_sock, &server_addr, NULL, 0)) < 0) { + printf("Unable to open UDP server on port %" PRIu16 " (error code %d)\n", + server_addr.port, -res); + return NULL; + } + server_running = true; + printf("Success: started UDP server on port %" PRIu16 "\n", + server_addr.port); + event_queue_init(&queue); + sock_udp_event_init(&server_sock, &queue, _udp_recv); + event_loop(&queue); return NULL; } From e98e2f614336478deba4ff44264ed38bc9020885 Mon Sep 17 00:00:00 2001 From: "Martine S. Lenders" Date: Thu, 20 Feb 2020 18:43:53 +0100 Subject: [PATCH 5/8] lwip: fix style errors found by Vera++ --- pkg/lwip/contrib/sock/ip/lwip_sock_ip.c | 1 - pkg/lwip/include/lwipopts.h | 1 - 2 files changed, 2 deletions(-) diff --git a/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c b/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c index e70e3fd47d..2e4248c5f3 100644 --- a/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c +++ b/pkg/lwip/contrib/sock/ip/lwip_sock_ip.c @@ -28,7 +28,6 @@ #include "lwip/sys.h" #include "lwip/sock_internal.h" - int sock_ip_create(sock_ip_t *sock, const sock_ip_ep_t *local, const sock_ip_ep_t *remote, uint8_t proto, uint16_t flags) { diff --git a/pkg/lwip/include/lwipopts.h b/pkg/lwip/include/lwipopts.h index 3a497aeae3..b6808383b9 100644 --- a/pkg/lwip/include/lwipopts.h +++ b/pkg/lwip/include/lwipopts.h @@ -86,7 +86,6 @@ extern "C" { #define LWIP_IPV6 (0) #endif /* MODULE_LWIP_IPV6 */ - #ifdef MODULE_LWIP_NETIF_PPP #define PPP_SUPPORT (1) #else /* MODULE_LWIP_NETIF_PPP */ From 1a4e6e9cdbc53b02d04add729466bca6cd006ccd Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Fri, 21 Feb 2020 20:06:26 +0100 Subject: [PATCH 6/8] lwip_sock_tcp: close accepted connection if queue is full --- pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c b/pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c index 438d0b1fdd..133c4e1bcc 100644 --- a/pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c +++ b/pkg/lwip/contrib/sock/tcp/lwip_sock_tcp.c @@ -243,6 +243,13 @@ int sock_tcp_accept(sock_tcp_queue_t *queue, sock_tcp_t **sock, } } else { + while (cib_avail(&queue->base.conn->acceptmbox.mbox.cib)) { + /* close connections potentially accepted by lwIP */ + if (netconn_accept(queue->base.conn, &tmp) == ERR_OK) { + netconn_close(tmp); + netconn_delete(tmp); + } + } res = -ENOMEM; } #if LWIP_SO_RCVTIMEO From a7ef50636ef1f59b5e65f1c769bd5d1208457b4c Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Fri, 21 Feb 2020 20:12:22 +0100 Subject: [PATCH 7/8] lwip: activate TCP_LISTEN_BACKLOG per default with `sock_tcp` Prevents unnecessary usage of resources, as the queue of `sock_tcp` is restricted. --- pkg/lwip/include/lwipopts.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/lwip/include/lwipopts.h b/pkg/lwip/include/lwipopts.h index b6808383b9..f8a8d1ef2d 100644 --- a/pkg/lwip/include/lwipopts.h +++ b/pkg/lwip/include/lwipopts.h @@ -134,6 +134,14 @@ extern "C" { #define LWIP_NETCONN (0) #endif +#ifndef TCP_LISTEN_BACKLOG +# if defined(MODULE_LWIP_SOCK_TCP) +# define TCP_LISTEN_BACKLOG (1) +# else +# define TCP_LISTEN_BACKLOG (0) +# endif +#endif /* TCP_LISTEN_BACKLOG */ + #define LWIP_SOCKET (0) #define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS From 37df4ea7e2fa711ca02d9f73160c396ce900ad07 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Fri, 21 Feb 2020 21:48:43 +0100 Subject: [PATCH 8/8] tests/lwip: add regression test for multiple simultaneous connect case --- tests/lwip/tests/01-run.py | 50 +++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/tests/lwip/tests/01-run.py b/tests/lwip/tests/01-run.py index fe9cc555ac..12a8bd3480 100755 --- a/tests/lwip/tests/01-run.py +++ b/tests/lwip/tests/01-run.py @@ -14,6 +14,7 @@ import subprocess import time import types import pexpect +import socket DEFAULT_TIMEOUT = 5 @@ -268,6 +269,53 @@ def test_tcpv6_send(board_group, application, env=None): client.expect_exact(u"could not send") +def test_tcpv6_multiconnect(board_group, application, env=None): + if any(b.name != "native" for b in board_group.boards): + # run test only with native + print("SKIP_TEST INFO found non-native board") + return + env_client = os.environ.copy() + if env is not None: + env_client.update(env) + env_client.update(board_group.boards[0].to_env()) + env_server = os.environ.copy() + if env is not None: + env_server.update(env) + env_server.update(board_group.boards[1].to_env()) + with pexpect.spawnu("make", ["-C", application, "term"], env=env_client, + timeout=DEFAULT_TIMEOUT) as client, \ + pexpect.spawnu("make", ["-C", application, "term"], env=env_server, + timeout=DEFAULT_TIMEOUT) as server: + port = random.randint(0x0000, 0xffff) + server_ip = get_ipv6_address(server) + client_ip = get_ipv6_address(client) + + try: + connect_addr = socket.getaddrinfo( + "%s%%tapbr0" % server_ip, port)[0][4] + except socket.gaierror as e: + print("SKIP_TEST INFO", e) + return + server.sendline(u"tcp server start %d" % port) + # wait for neighbor discovery to be done + time.sleep(5) + client.sendline(u"tcp connect %s %d" % (server_ip, port)) + server.expect(u"TCP client \\[%s\\]:[0-9]+ connected" % client_ip) + with socket.socket(socket.AF_INET6) as sock: + sock.connect(connect_addr) + server.expect(u"Error on TCP accept \\[-[0-9]+\\]") + client.sendline(u"tcp disconnect") + server.expect(u"TCP connection to \\[%s\\]:[0-9]+ reset" % client_ip) + client.sendline(u"tcp connect %s %d" % (server_ip, port)) + server.expect(u"TCP client \\[%s\\]:[0-9]+ connected" % client_ip) + client.sendline(u"tcp disconnect") + server.expect(u"TCP connection to \\[%s\\]:[0-9]+ reset" % client_ip) + with socket.socket(socket.AF_INET6) as sock: + sock.connect(connect_addr) + server.expect(u"TCP client \\[[0-9a-f:]+\\]:[0-9]+ connected") + server.expect(u"TCP connection to \\[[0-9a-f:]+\\]:[0-9]+ reset") + + def test_triple_send(board_group, application, env=None): env_sender = os.environ.copy() if env is not None: @@ -312,4 +360,4 @@ if __name__ == "__main__": TestStrategy().execute([BoardGroup((Board("native", "tap0"), Board("native", "tap1")))], [test_ipv6_send, test_udpv6_send, test_tcpv6_send, - test_triple_send]) + test_tcpv6_multiconnect, test_triple_send])