Merge pull request #13427 from miri64/lwip/enh/sock_async
lwip: provide sock_async support
This commit is contained in:
commit
fc37d7bf81
@ -3,3 +3,7 @@
|
||||
FEATURES_REQUIRED += arch_32bit
|
||||
|
||||
DEFAULT_MODULE += auto_init_lwip
|
||||
|
||||
ifneq (,$(filter lwip_sock_async,$(USEMODULE)))
|
||||
USEMODULE += sock_async
|
||||
endif
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
{
|
||||
@ -42,7 +41,10 @@ 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;
|
||||
#if IS_ACTIVE(SOCK_HAS_ASYNC)
|
||||
netconn_set_callback_arg(sock->base.conn, &sock->base);
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -50,23 +52,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 +163,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,8 +176,22 @@ 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);
|
||||
}
|
||||
|
||||
#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 */
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -27,7 +27,8 @@ 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;
|
||||
netconn_set_callback_arg(sock->base.conn, &sock->base);
|
||||
sock->queue = queue;
|
||||
sock->last_buf = NULL;
|
||||
sock->last_offset = 0;
|
||||
@ -74,13 +75,14 @@ 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;
|
||||
netconn_set_callback_arg(queue->base.conn, &queue->base);
|
||||
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 +92,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 +103,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 +124,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 +145,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 +159,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 +174,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 +190,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 +204,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);
|
||||
@ -241,10 +243,17 @@ 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
|
||||
netconn_set_recvtimeout(queue->conn, 0);
|
||||
netconn_set_recvtimeout(queue->base.conn, 0);
|
||||
#endif
|
||||
mutex_unlock(&queue->mutex);
|
||||
return res;
|
||||
@ -259,7 +268,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 +281,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 +296,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 +352,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 +367,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 */
|
||||
@ -370,4 +379,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 */
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -37,7 +37,10 @@ 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;
|
||||
#if IS_ACTIVE(SOCK_HAS_ASYNC)
|
||||
netconn_set_callback_arg(sock->base.conn, &sock->base);
|
||||
#endif
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -45,23 +48,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 +76,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 +88,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,8 +131,22 @@ 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);
|
||||
}
|
||||
|
||||
#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 */
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -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 */
|
||||
@ -129,12 +128,20 @@ 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)
|
||||
#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
|
||||
|
||||
@ -20,11 +20,66 @@
|
||||
|
||||
#include "net/af.h"
|
||||
#include "lwip/api.h"
|
||||
#ifdef SOCK_HAS_ASYNC
|
||||
#include "net/sock/async/types.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Forward declaration
|
||||
* @internal
|
||||
*/
|
||||
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
|
||||
* externally.
|
||||
* @internal
|
||||
*/
|
||||
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 */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Raw IP sock type
|
||||
* @warning For network stack internal purposes only. Do not access members
|
||||
@ -32,7 +87,7 @@ extern "C" {
|
||||
* @internal
|
||||
*/
|
||||
struct sock_ip {
|
||||
struct netconn *conn; /**< lwIP network connection object */
|
||||
lwip_sock_base_t base; /**< parent class */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -42,7 +97,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 +110,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 +124,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
|
||||
|
||||
120
pkg/lwip/patches/0001-netconn-add-callback-arg-storage.patch
Normal file
120
pkg/lwip/patches/0001-netconn-add-callback-arg-storage.patch
Normal file
@ -0,0 +1,120 @@
|
||||
From 59d78b78b683c9212949d4950355ea5f424c1da9 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Goldschmidt <goldsimon@gmx.de>
|
||||
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 <goldsimon@gmx.de>
|
||||
Suggested-by: Wilfred <wilfrednilsen@hotmail.com>
|
||||
(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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
114
tests/lwip/tcp.c
114
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 */
|
||||
|
||||
@ -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])
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user