Merge pull request #12602 from miri64/sock_async_event/feat/initial
sock_async: initial import of event-based implementation
This commit is contained in:
commit
43d2ca4771
@ -804,6 +804,11 @@ ifneq (,$(filter vfs,$(USEMODULE)))
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter sock_async_event,$(USEMODULE)))
|
||||||
|
USEMODULE += sock_async
|
||||||
|
USEMODULE += event
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter sock_dns,$(USEMODULE)))
|
ifneq (,$(filter sock_dns,$(USEMODULE)))
|
||||||
USEMODULE += sock_util
|
USEMODULE += sock_util
|
||||||
USEMODULE += posix_headers
|
USEMODULE += posix_headers
|
||||||
|
|||||||
@ -112,6 +112,9 @@ endif
|
|||||||
ifneq (,$(filter emcute,$(USEMODULE)))
|
ifneq (,$(filter emcute,$(USEMODULE)))
|
||||||
DIRS += net/application_layer/emcute
|
DIRS += net/application_layer/emcute
|
||||||
endif
|
endif
|
||||||
|
ifneq (,$(filter sock_async_event,$(USEMODULE)))
|
||||||
|
DIRS += net/sock/async/event
|
||||||
|
endif
|
||||||
ifneq (,$(filter sock_util,$(USEMODULE)))
|
ifneq (,$(filter sock_util,$(USEMODULE)))
|
||||||
DIRS += net/sock
|
DIRS += net/sock
|
||||||
endif
|
endif
|
||||||
|
|||||||
@ -96,6 +96,10 @@ ifneq (,$(filter riotboot,$(FEATURES_USED)))
|
|||||||
include $(RIOTBASE)/sys/riotboot/Makefile.include
|
include $(RIOTBASE)/sys/riotboot/Makefile.include
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter sock_async_event,$(USEMODULE)))
|
||||||
|
include $(RIOTBASE)/sys/net/sock/async/event/Makefile.include
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter ssp,$(USEMODULE)))
|
ifneq (,$(filter ssp,$(USEMODULE)))
|
||||||
include $(RIOTBASE)/sys/ssp/Makefile.include
|
include $(RIOTBASE)/sys/ssp/Makefile.include
|
||||||
endif
|
endif
|
||||||
|
|||||||
260
sys/include/net/sock/async/event.h
Normal file
260
sys/include/net/sock/async/event.h
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup net_sock_async_event Asynchronous sock with event API
|
||||||
|
* @ingroup net_sock
|
||||||
|
* @brief Provides an implementation of asynchronous sock for
|
||||||
|
* @ref sys_event
|
||||||
|
* @experimental This API is still under development and should not be used
|
||||||
|
* in production yet.
|
||||||
|
*
|
||||||
|
* How To Use
|
||||||
|
* ----------
|
||||||
|
*
|
||||||
|
* You need to [include](@ref including-modules) at least one module that
|
||||||
|
* implements a [`sock` API](@ref net_sock) (e.g. `gnrc_sock_udp` and
|
||||||
|
* `gnrc_sock_async` for the [GNRC](@ref net_gnrc) implementation using UDP) and
|
||||||
|
* the module `sock_async_event` in your application's Makefile.
|
||||||
|
*
|
||||||
|
* For the following example [`sock_udp`](@ref net_sock_udp) is used. It is
|
||||||
|
* however easily adaptable for other `sock` types:
|
||||||
|
*
|
||||||
|
* ### An asynchronous UDP Echo server using the event API
|
||||||
|
*
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
||||||
|
* #include <stdio.h>
|
||||||
|
*
|
||||||
|
* #include "net/sock/udp.h"
|
||||||
|
* #include "net/sock/async/event.h"
|
||||||
|
*
|
||||||
|
* event_queue_t queue;
|
||||||
|
* uint8_t buf[128];
|
||||||
|
*
|
||||||
|
* void handler(sock_udp_t *sock, sock_async_flags_t type)
|
||||||
|
* {
|
||||||
|
* if (type & SOCK_ASYNC_MSG_RECV) {
|
||||||
|
* sock_udp_ep_t remote;
|
||||||
|
* ssize_t res;
|
||||||
|
*
|
||||||
|
* if ((res = sock_udp_recv(sock, buf, sizeof(buf), 0,
|
||||||
|
* &remote)) >= 0) {
|
||||||
|
* puts("Received a message");
|
||||||
|
* if (sock_udp_send(sock, buf, res, &remote) < 0) {
|
||||||
|
* puts("Error sending reply");
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* int main(void)
|
||||||
|
* {
|
||||||
|
* sock_udp_ep_t local = SOCK_IPV6_EP_ANY;
|
||||||
|
* sock_udp_t sock;
|
||||||
|
*
|
||||||
|
* local.port = 12345;
|
||||||
|
*
|
||||||
|
* if (sock_udp_create(&sock, &local, NULL, 0) < 0) {
|
||||||
|
* puts("Error creating UDP sock");
|
||||||
|
* return 1;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* event_queue_init(&queue);
|
||||||
|
* sock_udp_event_init(&sock, &queue, handler);
|
||||||
|
* event_loop(&queue);
|
||||||
|
* return 0;
|
||||||
|
* }
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* Above you see a simple UDP echo server using @ref sys_event. Don't forget to
|
||||||
|
* also @ref including-modules "include" the IPv6 module of your networking
|
||||||
|
* implementation (e.g. `gnrc_ipv6_default` for @ref net_gnrc GNRC) and at least
|
||||||
|
* one network device.
|
||||||
|
*
|
||||||
|
* After including the header file for @ref net_sock_udp "UDP sock" and
|
||||||
|
* @ref net_sock_async_event "asynchronous handling", we create the event queue
|
||||||
|
* `queue` and allocate some buffer space `buf` to store the data received by
|
||||||
|
* the server:
|
||||||
|
*
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
||||||
|
* #include "net/sock/udp.h"
|
||||||
|
* #include "net/sock/async/event.h"
|
||||||
|
*
|
||||||
|
* event_queue_t queue;
|
||||||
|
* uint8_t buf[128];
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* We then define an event handler in form of a function. The event handler
|
||||||
|
* checks if the triggering event was a receive event by checking the flags
|
||||||
|
* provided with sock_event_t::type. If it is a receive event it copies the
|
||||||
|
* incoming message to `buf` and its sender into `remote` using @ref
|
||||||
|
* sock_udp_recv(). Note, that we use @ref sock_udp_recv() non-blocking by
|
||||||
|
* setting `timeout` to 0. If an error occurs on receive, we just ignore it and
|
||||||
|
* return from the event handler.
|
||||||
|
*
|
||||||
|
* If we receive a message we use its `remote` to reply. In case of an error on
|
||||||
|
* send, we print an according message:
|
||||||
|
*
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
||||||
|
* void handler(sock_udp_t *sock, sock_async_flags_t type)
|
||||||
|
* {
|
||||||
|
* if (type & SOCK_ASYNC_MSG_RECV) {
|
||||||
|
* sock_udp_ep_t remote;
|
||||||
|
* ssize_t res;
|
||||||
|
*
|
||||||
|
* if ((res = sock_udp_recv(sock, buf, sizeof(buf), 0,
|
||||||
|
* &remote)) >= 0) {
|
||||||
|
* puts("Received a message");
|
||||||
|
* if (sock_udp_send(sock, buf, res, &remote) < 0) {
|
||||||
|
* puts("Error sending reply");
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* To be able to listen for incoming packets we bind the `sock` by setting a
|
||||||
|
* local end point with a port (`12345` in this case).
|
||||||
|
*
|
||||||
|
* We then proceed to create the `sock`. It is bound to `local` and thus listens
|
||||||
|
* for UDP packets with @ref udp_hdr_t::dst_port "destination port" `12345`.
|
||||||
|
* Since we don't need any further configuration we set the flags to 0.
|
||||||
|
* In case of an error we stop the program:
|
||||||
|
*
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
||||||
|
* sock_udp_ep_t local = SOCK_IPV6_EP_ANY;
|
||||||
|
* sock_udp_t sock;
|
||||||
|
*
|
||||||
|
* local.port = 12345;
|
||||||
|
*
|
||||||
|
* if (sock_udp_create(&sock, &local, NULL, 0) < 0) {
|
||||||
|
* puts("Error creating UDP sock");
|
||||||
|
* return 1;
|
||||||
|
* }
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* Finally, we initialize the event queue `queue`, initialize asynchronous event
|
||||||
|
* handling for `sock` using it and the previously defined event handler, and go
|
||||||
|
* into an endless loop to handle all occurring events on `queue`:
|
||||||
|
*
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
||||||
|
* event_queue_init(&queue);
|
||||||
|
* sock_udp_event_init(&sock, &queue, handler);
|
||||||
|
* event_loop(&queue);
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Asynchronous sock using @ref sys_event definitions.
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||||
|
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||||
|
*/
|
||||||
|
#ifndef NET_SOCK_ASYNC_EVENT_H
|
||||||
|
#define NET_SOCK_ASYNC_EVENT_H
|
||||||
|
|
||||||
|
#include "event.h"
|
||||||
|
/* guard required since `sock_dtls_types.h` might not be provided */
|
||||||
|
#ifdef MODULE_SOCK_DTLS
|
||||||
|
#include "net/sock/dtls.h"
|
||||||
|
#endif /* MODULE_SOCK_DTLS */
|
||||||
|
#include "net/sock/ip.h"
|
||||||
|
#include "net/sock/tcp.h"
|
||||||
|
#include "net/sock/udp.h"
|
||||||
|
#include "net/sock/async.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* guard required since `sock_dtls_types.h` might not be provided */
|
||||||
|
#if defined(MODULE_SOCK_DTLS) || defined(DOXYGEN)
|
||||||
|
/**
|
||||||
|
* @brief Makes a DTLS sock able to handle asynchronous events using
|
||||||
|
* @ref sys_event.
|
||||||
|
*
|
||||||
|
* @param[in] sock A DTLS sock object.
|
||||||
|
* @param[in] ev_queue The queue the events on @p sock will be added to.
|
||||||
|
* @param[in] handler The event handler function to call on an event on
|
||||||
|
* @p sock.
|
||||||
|
*
|
||||||
|
* @note Only available with module `sock_dtls`.
|
||||||
|
*/
|
||||||
|
void sock_dtls_event_init(sock_dtls_t *sock, event_queue_t *ev_queue,
|
||||||
|
sock_dtls_cb_t handler);
|
||||||
|
#endif /* defined(MODULE_SOCK_DTLS) || defined(DOXYGEN) */
|
||||||
|
|
||||||
|
#if defined(MODULE_SOCK_IP) || defined(DOXYGEN)
|
||||||
|
/**
|
||||||
|
* @brief Makes a raw IPv4/IPv6 sock able to handle asynchronous events using
|
||||||
|
* @ref sys_event.
|
||||||
|
*
|
||||||
|
* @param[in] sock A raw IPv4/IPv6 sock object.
|
||||||
|
* @param[in] ev_queue The queue the events on @p sock will be added to.
|
||||||
|
* @param[in] handler The event handler function to call on an event on
|
||||||
|
* @p sock.
|
||||||
|
*
|
||||||
|
* @note Only available with module `sock_ip`.
|
||||||
|
*/
|
||||||
|
void sock_ip_event_init(sock_ip_t *sock, event_queue_t *ev_queue,
|
||||||
|
sock_ip_cb_t handler);
|
||||||
|
#endif /* defined(MODULE_SOCK_IP) || defined(DOXYGEN) */
|
||||||
|
|
||||||
|
#if defined(MODULE_SOCK_TCP) || defined(DOXYGEN)
|
||||||
|
/**
|
||||||
|
* @brief Makes a TCP sock able to handle asynchronous events using
|
||||||
|
* @ref sys_event.
|
||||||
|
*
|
||||||
|
* @param[in] sock A TCP sock object.
|
||||||
|
* @param[in] ev_queue The queue the events on @p sock will be added to.
|
||||||
|
* @param[in] handler The event handler function to call on an event on
|
||||||
|
* @p sock.
|
||||||
|
*
|
||||||
|
* @note Only available with module `sock_tcp`.
|
||||||
|
*/
|
||||||
|
void sock_tcp_event_init(sock_tcp_t *sock, event_queue_t *ev_queue,
|
||||||
|
sock_tcp_cb_t handler);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Makes a TCP listening queue able to handle asynchronous events using
|
||||||
|
* @ref sys_event.
|
||||||
|
*
|
||||||
|
* @param[in] queue A TCP listening queue.
|
||||||
|
* @param[in] ev_queue The queue the events on @p sock will be added to.
|
||||||
|
* @param[in] handler The event handler function to call on an event on
|
||||||
|
* @p sock.
|
||||||
|
*
|
||||||
|
* @note Only available with module `sock_tcp`.
|
||||||
|
*/
|
||||||
|
void sock_tcp_queue_event_init(sock_tcp_queue_t *queue, event_queue_t *ev_queue,
|
||||||
|
sock_tcp_queue_cb_t handler);
|
||||||
|
#endif /* defined(MODULE_SOCK_TCP) || defined(DOXYGEN) */
|
||||||
|
|
||||||
|
#if defined(MODULE_SOCK_UDP) || defined(DOXYGEN)
|
||||||
|
/**
|
||||||
|
* @brief Makes a UDP sock able to handle asynchronous events using
|
||||||
|
* @ref sys_event.
|
||||||
|
*
|
||||||
|
* @param[in] sock A UDP sock object.
|
||||||
|
* @param[in] ev_queue The queue the events on @p sock will be added to.
|
||||||
|
* @param[in] handler The event handler function to call on an event on
|
||||||
|
* @p sock.
|
||||||
|
*
|
||||||
|
* @note Only available with module `sock_udp`.
|
||||||
|
*/
|
||||||
|
void sock_udp_event_init(sock_udp_t *sock, event_queue_t *ev_queue,
|
||||||
|
sock_udp_cb_t handler);
|
||||||
|
#endif /* defined(MODULE_SOCK_UDP) || defined(DOXYGEN) */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* NET_SOCK_ASYNC_EVENT_H */
|
||||||
|
/** @} */
|
||||||
3
sys/net/sock/async/event/Makefile
Normal file
3
sys/net/sock/async/event/Makefile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
MODULE := sock_async_event
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
2
sys/net/sock/async/event/Makefile.include
Normal file
2
sys/net/sock/async/event/Makefile.include
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/sock/async/event
|
||||||
|
CFLAGS += -DSOCK_HAS_ASYNC -DSOCK_HAS_ASYNC_CTX
|
||||||
71
sys/net/sock/async/event/sock_async_ctx.h
Normal file
71
sys/net/sock/async/event/sock_async_ctx.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup net_sock_async_event
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Type definitions for asynchronous socks with @ref sys_event
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
#ifndef SOCK_ASYNC_CTX_H
|
||||||
|
#define SOCK_ASYNC_CTX_H
|
||||||
|
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generalized callback type
|
||||||
|
*/
|
||||||
|
typedef union {
|
||||||
|
void (*generic)(void *, sock_async_flags_t); /**< anything goes */
|
||||||
|
#ifdef MODULE_SOCK_DTLS
|
||||||
|
sock_dtls_cb_t dtls; /**< DTLS callback */
|
||||||
|
#endif
|
||||||
|
#ifdef MODULE_SOCK_IP
|
||||||
|
sock_ip_cb_t ip; /**< IP callback */
|
||||||
|
#endif
|
||||||
|
#ifdef MODULE_SOCK_TCP
|
||||||
|
sock_tcp_cb_t tcp; /**< TCP callback */
|
||||||
|
sock_tcp_queue_cb_t tcp_queue; /**< TCP queue callback */
|
||||||
|
#endif
|
||||||
|
#ifdef MODULE_SOCK_UDP
|
||||||
|
sock_udp_cb_t udp; /**< UDP callback */
|
||||||
|
#endif
|
||||||
|
} sock_event_cb_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Event definition for context scope
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
event_t super; /**< event structure that gets extended */
|
||||||
|
sock_event_cb_t cb; /**< callback */
|
||||||
|
void *sock; /**< generic pointer to a @ref net_sock object */
|
||||||
|
sock_async_flags_t type; /**< types of the event */
|
||||||
|
} sock_event_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Asynchronous context for @ref net_sock_async_event
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
sock_event_t event; /**< event storage */
|
||||||
|
event_queue_t *queue; /**< event queue to post socket events to */
|
||||||
|
} sock_async_ctx_t;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SOCK_ASYNC_CTX_H */
|
||||||
|
/** @} */
|
||||||
126
sys/net/sock/async/event/sock_async_event.c
Normal file
126
sys/net/sock/async/event/sock_async_event.c
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "net/sock/async/event.h"
|
||||||
|
|
||||||
|
static void _event_handler(event_t *ev)
|
||||||
|
{
|
||||||
|
sock_event_t *event = (sock_event_t *)ev;
|
||||||
|
|
||||||
|
event->cb.generic(event->sock, event->type);
|
||||||
|
event->type = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _cb(void *sock, sock_async_flags_t type,
|
||||||
|
sock_async_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
ctx->event.sock = sock;
|
||||||
|
ctx->event.type |= type;
|
||||||
|
event_post(ctx->queue, &ctx->event.super);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _set_ctx(sock_async_ctx_t *ctx, event_queue_t *ev_queue)
|
||||||
|
{
|
||||||
|
ctx->event.type = 0;
|
||||||
|
ctx->event.super.list_node.next = NULL;
|
||||||
|
ctx->event.super.handler = _event_handler;
|
||||||
|
ctx->queue = ev_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MODULE_SOCK_DTLS
|
||||||
|
static void _dtls_cb(sock_dtls_t *sock, sock_async_flags_t type)
|
||||||
|
{
|
||||||
|
_cb(sock, type, sock_dtls_get_async_ctx(sock));
|
||||||
|
}
|
||||||
|
|
||||||
|
void sock_dtls_event_init(sock_dtls_t *sock, event_queue_t *ev_queue,
|
||||||
|
sock_dtls_cb_t handler)
|
||||||
|
{
|
||||||
|
sock_async_ctx_t *ctx = sock_dtls_get_async_ctx(sock);
|
||||||
|
|
||||||
|
_set_ctx(ctx, ev_queue);
|
||||||
|
ctx->event.cb.dtls = handler;
|
||||||
|
sock_dtls_set_cb(sock, _dtls_cb);
|
||||||
|
}
|
||||||
|
#endif /* MODULE_SOCK_DTLS */
|
||||||
|
|
||||||
|
#ifdef MODULE_SOCK_IP
|
||||||
|
static void _ip_cb(sock_ip_t *sock, sock_async_flags_t type)
|
||||||
|
{
|
||||||
|
_cb(sock, type, sock_ip_get_async_ctx(sock));
|
||||||
|
}
|
||||||
|
|
||||||
|
void sock_ip_event_init(sock_ip_t *sock, event_queue_t *ev_queue,
|
||||||
|
sock_ip_cb_t handler)
|
||||||
|
{
|
||||||
|
sock_async_ctx_t *ctx = sock_ip_get_async_ctx(sock);
|
||||||
|
|
||||||
|
_set_ctx(ctx, ev_queue);
|
||||||
|
ctx->event.cb.ip = handler;
|
||||||
|
sock_ip_set_cb(sock, _ip_cb);
|
||||||
|
}
|
||||||
|
#endif /* MODULE_SOCK_IP */
|
||||||
|
|
||||||
|
#ifdef MODULE_SOCK_TCP
|
||||||
|
static void _tcp_cb(sock_tcp_t *sock, sock_async_flags_t type)
|
||||||
|
{
|
||||||
|
_cb(sock, type, sock_tcp_get_async_ctx(sock));
|
||||||
|
}
|
||||||
|
|
||||||
|
void sock_tcp_event_init(sock_tcp_t *sock, event_queue_t *ev_queue,
|
||||||
|
sock_tcp_cb_t handler)
|
||||||
|
{
|
||||||
|
sock_async_ctx_t *ctx = sock_tcp_get_async_ctx(sock);
|
||||||
|
|
||||||
|
_set_ctx(ctx, ev_queue);
|
||||||
|
ctx->event.cb.tcp = handler;
|
||||||
|
sock_tcp_set_cb(sock, _tcp_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _tcp_queue_cb(sock_tcp_queue_t *queue, sock_async_flags_t type)
|
||||||
|
{
|
||||||
|
_cb(queue, type, sock_tcp_queue_get_async_ctx(queue));
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
_set_ctx(ctx, ev_queue);
|
||||||
|
ctx->event.cb.tcp_queue = handler;
|
||||||
|
sock_tcp_queue_set_cb(queue, _tcp_queue_cb);
|
||||||
|
}
|
||||||
|
#endif /* MODULE_SOCK_TCP */
|
||||||
|
|
||||||
|
#ifdef MODULE_SOCK_UDP
|
||||||
|
static void _udp_cb(sock_udp_t *sock, sock_async_flags_t type)
|
||||||
|
{
|
||||||
|
_cb(sock, type, sock_udp_get_async_ctx(sock));
|
||||||
|
}
|
||||||
|
|
||||||
|
void sock_udp_event_init(sock_udp_t *sock, event_queue_t *ev_queue,
|
||||||
|
sock_udp_cb_t handler)
|
||||||
|
{
|
||||||
|
sock_async_ctx_t *ctx = sock_udp_get_async_ctx(sock);
|
||||||
|
|
||||||
|
_set_ctx(ctx, ev_queue);
|
||||||
|
ctx->event.cb.udp = handler;
|
||||||
|
sock_udp_set_cb(sock, _udp_cb);
|
||||||
|
}
|
||||||
|
#endif /* MODULE_SOCK_UDP */
|
||||||
|
|
||||||
|
/** @} */
|
||||||
@ -6,6 +6,7 @@ USEMODULE += gnrc_pktdump
|
|||||||
USEMODULE += gnrc_sock_async
|
USEMODULE += gnrc_sock_async
|
||||||
USEMODULE += gnrc_sock_ip
|
USEMODULE += gnrc_sock_ip
|
||||||
USEMODULE += gnrc_sock_udp
|
USEMODULE += gnrc_sock_udp
|
||||||
|
USEMODULE += sock_async_event
|
||||||
USEMODULE += od
|
USEMODULE += od
|
||||||
USEMODULE += xtimer
|
USEMODULE += xtimer
|
||||||
|
|
||||||
@ -18,9 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "event.h"
|
||||||
#include "net/ipv6/addr.h"
|
#include "net/ipv6/addr.h"
|
||||||
#include "net/ipv6/hdr.h"
|
#include "net/ipv6/hdr.h"
|
||||||
#include "net/sock/async.h"
|
|
||||||
#include "net/sock/ip.h"
|
#include "net/sock/ip.h"
|
||||||
#include "net/sock/udp.h"
|
#include "net/sock/udp.h"
|
||||||
#include "net/gnrc.h"
|
#include "net/gnrc.h"
|
||||||
@ -31,6 +31,8 @@
|
|||||||
#include "od.h"
|
#include "od.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
|
||||||
|
#include "net/sock/async/event.h"
|
||||||
|
|
||||||
#define RECV_BUFFER_SIZE (128)
|
#define RECV_BUFFER_SIZE (128)
|
||||||
|
|
||||||
#define TEST_PORT (38664U)
|
#define TEST_PORT (38664U)
|
||||||
@ -47,6 +49,7 @@ static const uint8_t _test_payload[] = TEST_PAYLOAD;
|
|||||||
static gnrc_netreg_entry_t _pktdump;
|
static gnrc_netreg_entry_t _pktdump;
|
||||||
|
|
||||||
static char _addr_str[IPV6_ADDR_MAX_STR_LEN];
|
static char _addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||||
|
static event_queue_t _ev_queue;
|
||||||
static uint8_t _buffer[128];
|
static uint8_t _buffer[128];
|
||||||
static sock_ip_t _ip_sock;
|
static sock_ip_t _ip_sock;
|
||||||
static sock_udp_t _udp_sock;
|
static sock_udp_t _udp_sock;
|
||||||
@ -113,6 +116,7 @@ int main(void)
|
|||||||
sock_udp_ep_t local = SOCK_IPV6_EP_ANY;
|
sock_udp_ep_t local = SOCK_IPV6_EP_ANY;
|
||||||
sock_udp_ep_t remote = SOCK_IPV6_EP_ANY;
|
sock_udp_ep_t remote = SOCK_IPV6_EP_ANY;
|
||||||
|
|
||||||
|
event_queue_init(&_ev_queue);
|
||||||
/* register for IPv6 to have a target */
|
/* register for IPv6 to have a target */
|
||||||
gnrc_netreg_entry_init_pid(&_pktdump, GNRC_NETREG_DEMUX_CTX_ALL,
|
gnrc_netreg_entry_init_pid(&_pktdump, GNRC_NETREG_DEMUX_CTX_ALL,
|
||||||
gnrc_pktdump_pid);
|
gnrc_pktdump_pid);
|
||||||
@ -122,11 +126,8 @@ int main(void)
|
|||||||
sock_udp_create(&_udp_sock, &local, NULL, 0);
|
sock_udp_create(&_udp_sock, &local, NULL, 0);
|
||||||
sock_ip_create(&_ip_sock, (sock_ip_ep_t *)&local, NULL, PROTNUM_UDP, 0);
|
sock_ip_create(&_ip_sock, (sock_ip_ep_t *)&local, NULL, PROTNUM_UDP, 0);
|
||||||
|
|
||||||
|
sock_udp_event_init(&_udp_sock, &_ev_queue, _recv_udp);
|
||||||
/* XXX don't do it like this in production and use a proper `sock_async`
|
sock_ip_event_init(&_ip_sock, &_ev_queue, _recv_ip);
|
||||||
* frontend! This is just for testing. */
|
|
||||||
sock_udp_set_cb(&_udp_sock, _recv_udp);
|
|
||||||
sock_ip_set_cb(&_ip_sock, _recv_ip);
|
|
||||||
memcpy(remote.addr.ipv6, _test_remote, sizeof(_test_remote));
|
memcpy(remote.addr.ipv6, _test_remote, sizeof(_test_remote));
|
||||||
remote.port = TEST_PORT - 1;
|
remote.port = TEST_PORT - 1;
|
||||||
|
|
||||||
@ -155,6 +156,7 @@ int main(void)
|
|||||||
gnrc_netapi_dispatch_receive(GNRC_NETTYPE_UDP, TEST_PORT, pkt);
|
gnrc_netapi_dispatch_receive(GNRC_NETTYPE_UDP, TEST_PORT, pkt);
|
||||||
/* trigger receive on IP sock */
|
/* trigger receive on IP sock */
|
||||||
gnrc_netapi_dispatch_receive(GNRC_NETTYPE_IPV6, PROTNUM_UDP, pkt);
|
gnrc_netapi_dispatch_receive(GNRC_NETTYPE_IPV6, PROTNUM_UDP, pkt);
|
||||||
|
event_loop(&_ev_queue);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11,16 +11,14 @@ from testrunner import run
|
|||||||
|
|
||||||
|
|
||||||
def testfunc(child):
|
def testfunc(child):
|
||||||
child.expect_exact("UDP event triggered: 0020")
|
child.expect_exact("UDP event triggered: 0030")
|
||||||
child.expect_exact("UDP message successfully sent")
|
|
||||||
child.expect_exact("IP event triggered: 0020")
|
|
||||||
child.expect_exact("IP message successfully sent")
|
|
||||||
child.expect_exact("UDP event triggered: 0010")
|
|
||||||
child.expect_exact("Received UDP packet from [fe80::2]:38663:")
|
child.expect_exact("Received UDP packet from [fe80::2]:38663:")
|
||||||
child.expect_exact("00000000 01 23 45 67 89 AB CD EF")
|
child.expect_exact("00000000 01 23 45 67 89 AB CD EF")
|
||||||
child.expect_exact("IP event triggered: 0010")
|
child.expect_exact("UDP message successfully sent")
|
||||||
|
child.expect_exact("IP event triggered: 0030")
|
||||||
child.expect_exact("Received IP packet from [fe80::2]:")
|
child.expect_exact("Received IP packet from [fe80::2]:")
|
||||||
child.expect_exact("00000000 01 23 45 67 89 AB CD EF")
|
child.expect_exact("00000000 01 23 45 67 89 AB CD EF")
|
||||||
|
child.expect_exact("IP message successfully sent")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
Loading…
x
Reference in New Issue
Block a user