mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 05:12:57 +01:00
pkg/openwsn: add openwsn_sock_udp module
Co-authored-by: Timothy Claeys <timothy.claeys@inria.fr>
This commit is contained in:
parent
9d46bc7d7f
commit
5c26f53828
@ -1,6 +1,6 @@
|
||||
PKG_NAME=openwsn
|
||||
PKG_URL=https://github.com/openwsn-berkeley/openwsn-fw.git
|
||||
PKG_VERSION=028db872c0c60f756e16880a0c86d6282e421c71
|
||||
PKG_VERSION=e2958a031ad50a6f3eeca3a98ad1ae85aa773a48
|
||||
PKG_LICENSE=BSD-3-Clause
|
||||
|
||||
include $(RIOTBASE)/pkg/pkg.mk
|
||||
@ -8,11 +8,14 @@ include $(RIOTBASE)/pkg/pkg.mk
|
||||
# openwsn_% RIOT Modules or PSEUDOMODULES that don't have custom rules
|
||||
IGNORE_MODULES := openwsn_leds \
|
||||
openwsn_debugpins \
|
||||
openwsn_6lo_frag \
|
||||
openwsn_6lo_fragmentation \
|
||||
openwsn_icmpv6_echo \
|
||||
openwsn_iee802154e_security \
|
||||
openwsn_radio \
|
||||
openwsn_riotos \
|
||||
openwsn_sock \
|
||||
openwsn_sock_async \
|
||||
openwsn_sock_udp \
|
||||
openwsn_serial \
|
||||
openwsn_sctimer \
|
||||
openwsn_sctimer_rtt \
|
||||
@ -42,14 +45,13 @@ OPENWSN_PATH_openapps = openapps
|
||||
OPENWSN_PATH_openweb = openweb
|
||||
OPENWSN_PATH_drivers = drivers/common
|
||||
OPENWSN_PATH_crypto = drivers/common/crypto
|
||||
OPENWSN_PATH_openos = kernel/openos
|
||||
OPENWSN_PATH_cjoin = openapps/cjoin
|
||||
OPENWSN_PATH_opencoap = openweb/opencoap
|
||||
OPENWSN_PATH_coap = openweb/opencoap
|
||||
OPENWSN_PATH_mac_low = openstack/02a-MAClow
|
||||
OPENWSN_PATH_mac_high = openstack/02b-MAChigh
|
||||
OPENWSN_PATH_iphc = openstack/03a-IPHC
|
||||
OPENWSN_PATH_ipv6 = openstack/03b-IPv6
|
||||
OPENWSN_PATH_transport = openstack/04-TRAN
|
||||
OPENWSN_PATH_udp = openstack/04-TRAN
|
||||
OPENWSN_PATH_crosslayers = openstack/cross-layers
|
||||
|
||||
all: $(OPENWSN_MODULES)
|
||||
|
@ -3,9 +3,7 @@ ifneq (,$(filter openwsn_openstack,$(USEMODULE)))
|
||||
USEMODULE += openwsn_ipv6
|
||||
USEMODULE += openwsn_mac_low
|
||||
USEMODULE += openwsn_mac_high
|
||||
USEMODULE += openwsn_transport
|
||||
USEMODULE += openwsn_crosslayers
|
||||
|
||||
USEMODULE += openwsn_drivers
|
||||
USEMODULE += openwsn_sctimer
|
||||
USEMODULE += openwsn_radio
|
||||
@ -19,13 +17,7 @@ ifneq (,$(filter openwsn_openstack,$(USEMODULE)))
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_scheduler,$(USEMODULE)))
|
||||
ifeq (,$(filter openwsn_openos,$(USEMODULE)))
|
||||
USEMODULE += openwsn_riotos
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_openos,$(USEMODULE)))
|
||||
USEMODULE += core_thread_flags
|
||||
USEMODULE += openwsn_riotos
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_riotos,$(USEMODULE)))
|
||||
@ -39,10 +31,15 @@ ifneq (,$(filter openwsn_ipv6,$(USEMODULE)))
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_cjoin,$(USEMODULE)))
|
||||
USEMODULE += openwsn_opencoap
|
||||
USEMODULE += openwsn_coap
|
||||
USEMODULE += openwsn_crypto
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_coap,$(USEMODULE)))
|
||||
# The implementation of sock_udp used by openwsn_coap is asynchronous
|
||||
USEMODULE += openwsn_sock_async
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_crypto,$(USEMODULE)))
|
||||
USEMODULE += crypto_3des
|
||||
USEMODULE += cipher_modes
|
||||
@ -99,9 +96,24 @@ ifneq (,$(filter openwsn_debugpins,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += periph_gpio_irq
|
||||
endif
|
||||
|
||||
ifneq (,$(filter sock_udp,$(USEMODULE)))
|
||||
USEMODULE += ipv6_addr
|
||||
USEMODULE += openwsn_udp
|
||||
USEMODULE += openwsn_sock_udp
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_sock%,$(USEMODULE)))
|
||||
USEMODULE += openwsn_sock
|
||||
USEMODULE += core_mbox
|
||||
USEMODULE += ztimer_usec
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_sock_async,$(USEMODULE)))
|
||||
USEMODULE += sock_async
|
||||
endif
|
||||
|
||||
ifneq (,$(filter shell_commands,$(USEMODULE)))
|
||||
USEMODULE += l2util
|
||||
endif
|
||||
|
||||
# This port currently requires setting ISR_STACKSIZE
|
||||
FEATURES_BLACKLIST += arch_esp32 arch_esp8266 arch_riscv arch_avr8
|
||||
|
@ -1,9 +1,11 @@
|
||||
PSEUDOMODULES += openwsn_serial \
|
||||
openwsn_debugpins \
|
||||
openwsn_6lo_frag \
|
||||
openwsn_6lo_fragmentation \
|
||||
openwsn_icmpv6_echo \
|
||||
openwsn_iee802154e_security \
|
||||
openwsn_leds \
|
||||
openwsn_sock \
|
||||
openwsn_sock_async \
|
||||
openwsn_scheduler \
|
||||
openwsn_sctimer \
|
||||
openwsn_sctimer_rtt \
|
||||
@ -32,44 +34,30 @@ INCLUDES += -I$(PKGDIRBASE)/openwsn \
|
||||
-I$(PKGDIRBASE)/openwsn/openweb/opencoap \
|
||||
-I$(RIOTBASE)/pkg/openwsn/include \
|
||||
|
||||
ifneq (,$(filter openwsn_openos,$(USEMODULE)))
|
||||
INCLUDES += -I$(PKGDIRBASE)/openwsn/kernel/openos
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_riotos,$(USEMODULE)))
|
||||
INCLUDES += -I$(RIOTBASE)/pkg/openwsn/scheduler
|
||||
DIRS += $(RIOTBASE)/pkg/openwsn/scheduler
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_sock_udp,$(USEMODULE)))
|
||||
INCLUDES += -I$(RIOTBASE)/pkg/openwsn/sock
|
||||
DIRS += $(RIOTBASE)/pkg/openwsn/sock
|
||||
endif
|
||||
|
||||
# Set OpenWSN configurations flags, see $(PKG_SOURCE_DIR)/openwsn-fw/inc/config.h
|
||||
|
||||
ifneq (,$(filter openwsn_cjoin,$(USEMODULE)))
|
||||
CFLAGS += -DOPENWSN_CJOIN_C
|
||||
CFLAGS += -DBOARD_CRYPTOENGINE_ENABLED
|
||||
CFLAGS += -DBOARD_CRYPTOENGINE_ENABLED=1
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_transport,$(USEMODULE)))
|
||||
CFLAGS += -DOPENWSN_UDP_C
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_opencoap,$(USEMODULE)))
|
||||
CFLAGS += -DOPENWSN_COAP_C
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_6lo_frag,$(USEMODULE)))
|
||||
CFLAGS += -DOPENWSN_6LO_FRAGMENTATION_C
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_icmpv6_echo,$(USEMODULE)))
|
||||
CFLAGS += -DOPENWSN_ICMPV6ECHO_C
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_iee802154e_security,$(USEMODULE)))
|
||||
CFLAGS += -DOPENWSN_IEEE802154E_SECURITY_C
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openwsn_adaptive_msf,$(USEMODULE)))
|
||||
CFLAGS += -DOPENWSN_ADAPTIVE_MSF
|
||||
ifneq (,$(filter openwsn_sock%,$(USEMODULE)))
|
||||
CFLAGS += -DSOCK_HAS_IPV6
|
||||
ifneq (,$(filter openwsn_sock_async,$(USEMODULE)))
|
||||
CFLAGS += -DSOCK_HAS_ASYNC
|
||||
endif
|
||||
ifneq (,$(filter sock_async_event,$(USEMODULE)))
|
||||
# Needed only if using event and not simple callbacks
|
||||
CFLAGS += -DSOCK_HAS_ASYNC_CTX
|
||||
endif
|
||||
endif
|
||||
|
||||
# In OpenWSN the ISR stack is shared with the network stack. OpenWSN stack is
|
||||
|
@ -43,7 +43,7 @@ void eui64_get(uint8_t *addressToWrite)
|
||||
_eui64_is_set = true;
|
||||
}
|
||||
memcpy(addressToWrite, _eui64.uint8, sizeof(_eui64.uint8));
|
||||
#else
|
||||
#elif MODULE_OPENWSN_RADIO_NETDEV
|
||||
eui64_t eui64;
|
||||
|
||||
if (openwsn_radio.dev->driver->get(openwsn_radio.dev, NETOPT_ADDRESS_LONG,
|
||||
@ -54,5 +54,7 @@ void eui64_get(uint8_t *addressToWrite)
|
||||
else {
|
||||
luid_get_eui64((eui64_t *) addressToWrite);
|
||||
}
|
||||
#else
|
||||
memset(addressToWrite, 0, sizeof(eui64_t));
|
||||
#endif
|
||||
}
|
||||
|
@ -288,7 +288,7 @@
|
||||
lower the stack footprint.
|
||||
|
||||
- `openwsn_cjoin`: this enabled the use of Constrained Join Protocol (CoJP)
|
||||
- `openwsn_6lo_frag`: this enable 6LoWPAN fragmentation
|
||||
- `openwsn_6lo_fragmentation`: this enable 6LoWPAN fragmentation
|
||||
- `openwsn_iee802154e_security`: enable link layer security
|
||||
- `openwsn_adaptive_msf`: allow the MSF algorithm to dynamically remove and
|
||||
allocate slots
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
pkg/openwsn/patches/0010-inc-config.h-use-kerneldefines.patch
Normal file
BIN
pkg/openwsn/patches/0010-inc-config.h-use-kerneldefines.patch
Normal file
Binary file not shown.
BIN
pkg/openwsn/patches/0011-treewide-changes-to-use-RIOT-sock.patch
Normal file
BIN
pkg/openwsn/patches/0011-treewide-changes-to-use-RIOT-sock.patch
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
3
pkg/openwsn/sock/Makefile
Normal file
3
pkg/openwsn/sock/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = openwsn_sock_udp
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
557
pkg/openwsn/sock/openwsn_sock_udp.c
Normal file
557
pkg/openwsn/sock/openwsn_sock_udp.c
Normal file
@ -0,0 +1,557 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Inria
|
||||
*
|
||||
* 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 Timothy Claeys <timothy.claeys@inria.fr>
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef SOCK_HAS_ASYNC
|
||||
#include "net/sock/async.h"
|
||||
#endif
|
||||
#include "net/ipv6/addr.h"
|
||||
#include "net/iana/portrange.h"
|
||||
#include "net/sock/udp.h"
|
||||
#ifdef MODULE_ZTIMER_USEC
|
||||
#include "ztimer.h"
|
||||
#endif
|
||||
#include "utlist.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "openwsn.h"
|
||||
#include "opendefs.h"
|
||||
#include "kernel/scheduler.h"
|
||||
#include "cross-layers/packetfunctions.h"
|
||||
#include "cross-layers/openqueue.h"
|
||||
#include "cross-layers/openrandom.h"
|
||||
#include "cross-layers/idmanager.h"
|
||||
#include "04-TRAN/udp.h"
|
||||
|
||||
#define _MSG_TYPE_RECV_PKT (0x1601)
|
||||
#ifdef MODULE_ZTIMER_USEC
|
||||
#define _TIMEOUT_MAGIC (0xF38A0B63U)
|
||||
#define _TIMEOUT_MSG_TYPE (0x8474)
|
||||
#endif /* MODULE_ZTIMER_USEC */
|
||||
|
||||
static sock_udp_t *_udp_socket_list;
|
||||
|
||||
#ifdef MODULE_ZTIMER_USEC
|
||||
static void _timeout_cb(void *arg)
|
||||
{
|
||||
msg_t timeout_msg = { .sender_pid = KERNEL_PID_UNDEF,
|
||||
.type = _TIMEOUT_MSG_TYPE,
|
||||
.content = { .value = _TIMEOUT_MAGIC } };
|
||||
mbox_t *mbox = arg;
|
||||
|
||||
/* should be safe, because otherwise if mbox were filled this callback is
|
||||
* senseless */
|
||||
mbox_try_put(mbox, &timeout_msg);
|
||||
}
|
||||
#endif /* MODULE_ZTIMER_USEC */
|
||||
|
||||
static void _sock_transmit_internal(void)
|
||||
{
|
||||
OpenQueueEntry_t *pkt;
|
||||
|
||||
pkt = openqueue_getPacketByComponent(COMPONENT_SOCK_TO_UDP);
|
||||
|
||||
if (pkt == NULL) {
|
||||
LOG_ERROR("%s: not pkt in queue\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
udp_transmit(pkt);
|
||||
}
|
||||
|
||||
static bool _sock_valid_af(uint8_t af)
|
||||
{
|
||||
/* only AF_INET6 is supported*/
|
||||
return (af == AF_INET6);
|
||||
}
|
||||
|
||||
static bool _sock_valid_addr(sock_udp_ep_t *ep)
|
||||
{
|
||||
assert(ep != NULL);
|
||||
const uint8_t *p = (uint8_t *)&ep->addr;
|
||||
for (uint8_t i = 0; i < sizeof(ep->addr); i++) {
|
||||
if (p[i] != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool _sock_port_in_use(uint16_t port)
|
||||
{
|
||||
for (sock_udp_t *ptr = _udp_socket_list; ptr != NULL;
|
||||
ptr = (sock_udp_t *)ptr->next) {
|
||||
if (ptr->gen_sock.local.port == port) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns a UDP port, and checks for reuse if required
|
||||
*
|
||||
* implements "Another Simple Port Randomization Algorithm" as specified in
|
||||
* RFC 6056, see https://tools.ietf.org/html/rfc6056#section-3.3.2
|
||||
*/
|
||||
static uint16_t _get_dyn_port(void)
|
||||
{
|
||||
unsigned num = (IANA_DYNAMIC_PORTRANGE_MAX - IANA_DYNAMIC_PORTRANGE_MIN);
|
||||
unsigned count = num;
|
||||
|
||||
do {
|
||||
uint16_t port = IANA_DYNAMIC_PORTRANGE_MIN +
|
||||
(openrandom_get16b() % num);
|
||||
if (!_sock_port_in_use(port)) {
|
||||
return port;
|
||||
}
|
||||
--count;
|
||||
} while (count > 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sock_udp_init(void)
|
||||
{
|
||||
_udp_socket_list = NULL;
|
||||
}
|
||||
|
||||
int sock_udp_create(sock_udp_t *sock, const sock_udp_ep_t *local,
|
||||
const sock_udp_ep_t *remote, uint16_t flags)
|
||||
{
|
||||
/* sanity checks */
|
||||
assert(sock);
|
||||
assert(remote == NULL || remote->port != 0);
|
||||
/* check that if set netifs match */
|
||||
if ((local != NULL) && (remote != NULL) &&
|
||||
(local->netif != SOCK_ADDR_ANY_NETIF) &&
|
||||
(remote->netif != SOCK_ADDR_ANY_NETIF) &&
|
||||
(local->netif != remote->netif)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
/* if set netifs should match the only one available in OpenWSN*/
|
||||
if ((local != NULL) &&
|
||||
(local->netif != SOCK_ADDR_ANY_NETIF) &&
|
||||
(local->netif != openwsn_get_netif())) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((remote != NULL) &&
|
||||
(remote->netif != SOCK_ADDR_ANY_NETIF) &&
|
||||
(remote->netif != openwsn_get_netif())) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check local */
|
||||
memset(&sock->gen_sock.local, 0, sizeof(sock_udp_ep_t));
|
||||
if (local != NULL) {
|
||||
uint16_t port = local->port;
|
||||
if (!_sock_valid_af(local->family)) {
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
if (port == 0U) {
|
||||
port = _get_dyn_port();
|
||||
if (port == 0U) {
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
}
|
||||
else if (!(flags & SOCK_FLAGS_REUSE_EP)) {
|
||||
/* a single IPV6 address is possible in OpenWSN, so only check
|
||||
if port is in use */
|
||||
if (_sock_port_in_use(port)) {
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
}
|
||||
memcpy(&sock->gen_sock.local, local, sizeof(sock_udp_ep_t));
|
||||
sock->gen_sock.local.port = port;
|
||||
}
|
||||
|
||||
/* check and set remote */
|
||||
memset(&sock->gen_sock.remote, 0, sizeof(sock_udp_ep_t));
|
||||
if (remote != NULL) {
|
||||
if (!_sock_valid_af(remote->family)) {
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
if (!_sock_valid_addr((sock_udp_ep_t *)remote)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(&sock->gen_sock.remote, remote, sizeof(sock_udp_ep_t));
|
||||
}
|
||||
|
||||
/* if all ok and local != NULL, listen */
|
||||
if (local != NULL) {
|
||||
/* start mailbox */
|
||||
mbox_init(&sock->mbox, sock->mbox_queue, OPENWSN_SOCK_MBOX_SIZE);
|
||||
#ifdef SOCK_HAS_ASYNC
|
||||
sock->async_cb = NULL;
|
||||
#endif
|
||||
/* update socket list */
|
||||
LL_PREPEND(_udp_socket_list, sock);
|
||||
}
|
||||
|
||||
/* set flags */
|
||||
sock->gen_sock.flags = flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t sock_udp_send_aux(sock_udp_t *sock, const void *data, size_t len,
|
||||
const sock_udp_ep_t *remote, sock_udp_aux_tx_t *aux)
|
||||
{
|
||||
(void)aux;
|
||||
OpenQueueEntry_t *pkt;
|
||||
open_addr_t dst_addr, src_addr;
|
||||
|
||||
memset(&dst_addr, 0, sizeof(open_addr_t));
|
||||
memset(&src_addr, 0, sizeof(open_addr_t));
|
||||
uint16_t src_port = 0, dst_port;
|
||||
|
||||
/* asserts for sock_udp_send "pre" */
|
||||
assert((sock != NULL) || (remote != NULL));
|
||||
assert((len == 0) || (data != NULL)); /* (len != 0) => (data != NULL) */
|
||||
|
||||
/* check remote */
|
||||
if (remote != NULL) {
|
||||
if (remote->port == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
else if (!_sock_valid_af(remote->family)) {
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
else if (!_sock_valid_addr((sock_udp_ep_t *)remote)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
else if ((sock != NULL) &&
|
||||
(sock->gen_sock.local.netif != SOCK_ADDR_ANY_NETIF) &&
|
||||
(remote->netif != SOCK_ADDR_ANY_NETIF) &&
|
||||
(sock->gen_sock.local.netif != remote->netif)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
/* if set netifs should match the only one available in OpenWSN*/
|
||||
if ((sock != NULL) &&
|
||||
(((sock->gen_sock.local.netif != SOCK_ADDR_ANY_NETIF) &&
|
||||
(sock->gen_sock.local.netif != openwsn_get_netif())) ||
|
||||
((remote->netif != SOCK_ADDR_ANY_NETIF) &&
|
||||
(remote->netif != openwsn_get_netif())))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
dst_addr.type = ADDR_128B;
|
||||
memcpy(&dst_addr.addr_128b, &remote->addr, LENGTH_ADDR128b);
|
||||
dst_port = remote->port;
|
||||
}
|
||||
/* if remote is null then check that sock has a remote */
|
||||
else if (sock->gen_sock.remote.family == AF_UNSPEC) {
|
||||
return -ENOTCONN;
|
||||
}
|
||||
/* set destination port and address based on sock remote */
|
||||
else {
|
||||
dst_port = sock->gen_sock.remote.port;
|
||||
dst_addr.type = ADDR_128B;
|
||||
memcpy(&dst_addr.addr_128b, &sock->gen_sock.remote.addr,
|
||||
LENGTH_ADDR128b);
|
||||
}
|
||||
|
||||
if ((sock == NULL) || (sock->gen_sock.local.family == AF_UNSPEC)) {
|
||||
/* if no sock or unbound get a random port */
|
||||
if ((src_port = _get_dyn_port()) == 0) {
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* set src port from sock */
|
||||
src_port = sock->gen_sock.local.port;
|
||||
/* set addr if sock is not null or bound */
|
||||
src_addr.type = ADDR_128B;
|
||||
memcpy(&src_addr.addr_128b, &sock->gen_sock.local.addr,
|
||||
LENGTH_ADDR128b);
|
||||
}
|
||||
|
||||
/* get pkt buffer and take owner ship */
|
||||
if ((pkt = openqueue_getFreePacketBuffer(COMPONENT_SOCK_TO_UDP)) == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
pkt->owner = COMPONENT_SOCK_TO_UDP;
|
||||
pkt->creator = COMPONENT_SOCK_TO_UDP;
|
||||
|
||||
/* set addresses and ports */
|
||||
pkt->l3_destinationAdd.type = ADDR_128B;
|
||||
pkt->l3_sourceAdd.type = ADDR_128B;
|
||||
memcpy(&pkt->l3_sourceAdd.addr_128b, &src_addr.addr_128b, LENGTH_ADDR128b);
|
||||
memcpy(&pkt->l3_destinationAdd.addr_128b, &dst_addr.addr_128b,
|
||||
LENGTH_ADDR128b);
|
||||
pkt->l4_destination_port = dst_port;
|
||||
pkt->l4_sourcePortORicmpv6Type = src_port;
|
||||
|
||||
/* set payload */
|
||||
if (packetfunctions_reserveHeader(&pkt, len)) {
|
||||
openqueue_freePacketBuffer(pkt);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy(pkt->payload, data, len);
|
||||
pkt->l4_payload = pkt->payload;
|
||||
pkt->l4_length = pkt->length;
|
||||
|
||||
/* push task to scheduler send */
|
||||
scheduler_push_task(_sock_transmit_internal, TASKPRIO_UDP);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void sock_udp_close(sock_udp_t *sock)
|
||||
{
|
||||
if (_udp_socket_list == NULL) {
|
||||
return;
|
||||
}
|
||||
if (sock) {
|
||||
LL_DELETE(_udp_socket_list, sock);
|
||||
sock->next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int sock_udp_get_local(sock_udp_t *sock, sock_udp_ep_t *ep)
|
||||
{
|
||||
if (sock->gen_sock.local.family == AF_UNSPEC) {
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
memcpy(ep, &sock->gen_sock.local, sizeof(sock_udp_ep_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sock_udp_get_remote(sock_udp_t *sock, sock_udp_ep_t *ep)
|
||||
{
|
||||
if (sock->gen_sock.remote.family == AF_UNSPEC) {
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
memcpy(ep, &sock->gen_sock.remote, sizeof(sock_udp_ep_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t sock_udp_recv_aux(sock_udp_t *sock, void *data, size_t max_len,
|
||||
uint32_t timeout, sock_udp_ep_t *remote,
|
||||
sock_udp_aux_rx_t *aux)
|
||||
{
|
||||
void *pkt = NULL, *ctx = NULL;
|
||||
ssize_t res;
|
||||
|
||||
assert((sock != NULL) && (data != NULL) && (max_len > 0));
|
||||
res = sock_udp_recv_buf_aux(sock, &pkt, &ctx, timeout, remote, aux);
|
||||
/* set data to copy, check if enough buffer space */
|
||||
if (res >= 0) {
|
||||
ssize_t tmp;
|
||||
if ((ssize_t)max_len >= res) {
|
||||
memset(data, 0, max_len);
|
||||
if (res > 0) {
|
||||
/* copy received data */
|
||||
memcpy(data, pkt, res);
|
||||
/* free packet */
|
||||
tmp = sock_udp_recv_buf_aux(sock, &pkt, &ctx, timeout, remote,
|
||||
aux);
|
||||
assert(tmp == 0);
|
||||
}
|
||||
(void) tmp;
|
||||
}
|
||||
else {
|
||||
res = -ENOBUFS;
|
||||
/* free packet */
|
||||
tmp = sock_udp_recv_buf_aux(sock, &pkt, &ctx, timeout, remote, aux);
|
||||
assert(tmp == 0);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx,
|
||||
uint32_t timeout, sock_udp_ep_t *remote,
|
||||
sock_udp_aux_rx_t *aux)
|
||||
{
|
||||
(void) aux;
|
||||
sock_udp_ep_t ep;
|
||||
OpenQueueEntry_t *pkt = NULL;
|
||||
msg_t msg;
|
||||
|
||||
assert((sock != NULL) && (data != NULL) && (buf_ctx != NULL));
|
||||
|
||||
if (*buf_ctx != NULL) {
|
||||
*data = NULL;
|
||||
openqueue_freePacketBuffer(*buf_ctx);
|
||||
*buf_ctx = NULL;
|
||||
return 0;
|
||||
}
|
||||
if (sock->gen_sock.local.family == AF_UNSPEC) {
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
#ifdef MODULE_ZTIMER_USEC
|
||||
ztimer_t timer;
|
||||
|
||||
if ((timeout != SOCK_NO_TIMEOUT) && (timeout != 0)) {
|
||||
timer.callback = _timeout_cb;
|
||||
timer.arg = &sock->mbox;
|
||||
ztimer_set(ZTIMER_USEC, &timer, timeout);
|
||||
}
|
||||
#endif /* MODULE_ZTIMER_USEC */
|
||||
if (timeout != 0) {
|
||||
mbox_get(&sock->mbox, &msg);
|
||||
}
|
||||
else {
|
||||
if (!mbox_try_get(&sock->mbox, &msg)) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
#ifdef MODULE_ZTIMER_USEC
|
||||
if ((timeout != SOCK_NO_TIMEOUT) && (timeout != 0)) {
|
||||
ztimer_remove(ZTIMER_USEC, &timer);
|
||||
}
|
||||
#endif /* MODULE_ZTIMER_USEC */
|
||||
switch (msg.type) {
|
||||
case _MSG_TYPE_RECV_PKT:
|
||||
pkt = msg.content.ptr;
|
||||
break;
|
||||
#ifdef MODULE_ZTIMER_USEC
|
||||
case _TIMEOUT_MSG_TYPE:
|
||||
if (msg.content.value == _TIMEOUT_MAGIC) {
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
#endif /* MODULE_ZTIMER_USEC */
|
||||
/* Falls Through. */
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pkt == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* copy source port and address to end point */
|
||||
ep.family = AF_INET6;
|
||||
ep.port = pkt->l4_sourcePortORicmpv6Type;
|
||||
ep.netif = openwsn_get_netif();
|
||||
memcpy(&ep.addr, pkt->l3_sourceAdd.addr_128b, LENGTH_ADDR128b);
|
||||
|
||||
if (remote != NULL) {
|
||||
/* return remote if requested */
|
||||
memcpy(remote, &ep, sizeof(sock_udp_ep_t));
|
||||
}
|
||||
|
||||
if ((sock->gen_sock.remote.family != AF_UNSPEC) &&
|
||||
/* check remote end-point if set */
|
||||
((sock->gen_sock.remote.port != pkt->l4_sourcePortORicmpv6Type) ||
|
||||
/* We only have IPv6 for now, so just comparing the whole end point
|
||||
* should suffice */
|
||||
((memcmp(&sock->gen_sock.remote.addr, &ipv6_addr_unspecified,
|
||||
sizeof(ipv6_addr_t)) != 0) &&
|
||||
(memcmp(&sock->gen_sock.remote.addr, &ep.addr,
|
||||
sizeof(ipv6_addr_t)) != 0)))) {
|
||||
openqueue_freePacketBuffer(pkt);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
*data = pkt->l4_payload;
|
||||
*buf_ctx = pkt;
|
||||
|
||||
return pkt->l4_length;
|
||||
}
|
||||
|
||||
#ifdef SOCK_HAS_ASYNC
|
||||
void sock_udp_set_cb(sock_udp_t *sock, sock_udp_cb_t cb, void *cb_arg)
|
||||
{
|
||||
sock->async_cb = cb;
|
||||
sock->async_cb_arg = cb_arg;
|
||||
}
|
||||
|
||||
#ifdef SOCK_HAS_ASYNC_CTX
|
||||
sock_async_ctx_t *sock_udp_get_async_ctx(sock_udp_t *sock)
|
||||
{
|
||||
return &sock->async_ctx;
|
||||
}
|
||||
#endif /* SOCK_HAS_ASYNC_CTX*/
|
||||
#endif /* SOCK_HAS_ASYNC */
|
||||
|
||||
void sock_receive_internal(void)
|
||||
{
|
||||
OpenQueueEntry_t *pkt;
|
||||
sock_udp_t *current;
|
||||
|
||||
pkt = openqueue_getPacketByComponent(COMPONENT_UDP_TO_SOCK);
|
||||
|
||||
if (pkt == NULL) {
|
||||
LOG_ERROR("%s: not pkt in queue\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
current = _udp_socket_list;
|
||||
while (current != NULL) {
|
||||
if (current->gen_sock.local.port == pkt->l4_destination_port &&
|
||||
idmanager_isMyAddress(&pkt->l3_destinationAdd)) {
|
||||
msg_t msg;
|
||||
msg.type = _MSG_TYPE_RECV_PKT;
|
||||
msg.content.ptr = pkt;
|
||||
int ret = mbox_try_put(¤t->mbox, &msg);
|
||||
if (ret < 1) {
|
||||
LOG_ERROR(
|
||||
"openwsn_sock: dropped message to %p (was full)\n",
|
||||
(void *)¤t->mbox);
|
||||
}
|
||||
#ifdef SOCK_HAS_ASYNC
|
||||
if (current->async_cb != NULL) {
|
||||
current->async_cb(current, SOCK_ASYNC_MSG_RECV, NULL);
|
||||
}
|
||||
#endif /* SOCK_HAS_ASYNC */
|
||||
break;
|
||||
}
|
||||
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
if (current == NULL) {
|
||||
openqueue_freePacketBuffer(pkt);
|
||||
LOG_ERROR("%s: no associated socket found\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
void sock_senddone_internal(OpenQueueEntry_t *msg, owerror_t error)
|
||||
{
|
||||
/* In RIOT we can't know what message was sent... */
|
||||
(void)msg;
|
||||
#ifdef SOCK_HAS_ASYNC
|
||||
OpenQueueEntry_t *pkt;
|
||||
sock_udp_t *current;
|
||||
|
||||
pkt = openqueue_getPacketByComponent(COMPONENT_UDP);
|
||||
|
||||
if (pkt == NULL) {
|
||||
LOG_ERROR("%s: not pkt in queue\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
current = _udp_socket_list;
|
||||
|
||||
while (current != NULL) {
|
||||
if (current->gen_sock.local.port == pkt->l4_sourcePortORicmpv6Type &&
|
||||
current->async_cb != NULL) {
|
||||
current->async_cb(current, SOCK_ASYNC_MSG_SENT, &error);
|
||||
break;
|
||||
}
|
||||
|
||||
current = current->next;
|
||||
}
|
||||
#else /* SOCK_HAS_ASYNC */
|
||||
(void)error;
|
||||
#endif /*SOCK_HAS_ASYNC */
|
||||
}
|
95
pkg/openwsn/sock/sock_types.h
Normal file
95
pkg/openwsn/sock/sock_types.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Inria
|
||||
*
|
||||
* 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 pkg_openwsn_sock
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief OpenWSN-specific types
|
||||
*
|
||||
* @author Timothy Claeys <timothy.claeys@inria.fr>
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*/
|
||||
|
||||
#ifndef SOCK_TYPES_H
|
||||
#define SOCK_TYPES_H
|
||||
|
||||
#include "mbox.h"
|
||||
#include "net/af.h"
|
||||
#ifdef SOCK_HAS_ASYNC
|
||||
#include "net/sock/async/types.h"
|
||||
#endif
|
||||
#include "net/sock/udp.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default size for OpenWSN sock_udp_t::mbox_queue (as exponent of 2^n).
|
||||
*
|
||||
* As the queue size ALWAYS needs to be power of two, this option
|
||||
* represents the exponent of 2^n, which will be used as the size of
|
||||
* the queue.
|
||||
*/
|
||||
#ifndef CONFIG_OPENWSN_SOCK_MBOX_SIZE_EXP
|
||||
#define CONFIG_OPENWSN_SOCK_MBOX_SIZE_EXP (3)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Size for OpenWSN sock_udp_t::mbox_queue
|
||||
*/
|
||||
#ifndef OPENWSN_SOCK_MBOX_SIZE
|
||||
#define OPENWSN_SOCK_MBOX_SIZE (1 << CONFIG_OPENWSN_SOCK_MBOX_SIZE_EXP)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Forward declaration
|
||||
* @internal
|
||||
*/
|
||||
typedef struct openwsn_gen_sock openwsn_gen_sock_t;
|
||||
|
||||
/**
|
||||
* @brief Generic openwsn sock type
|
||||
* @warning For network stack internal purposes only. Do not access members
|
||||
* externally.
|
||||
* @internal
|
||||
*/
|
||||
struct openwsn_gen_sock {
|
||||
sock_udp_ep_t local; /**< local end-point */
|
||||
sock_udp_ep_t remote; /**< remote end-point */
|
||||
uint16_t flags; /**< option flags */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief UDP sock type
|
||||
* @warning For network stack internal purposes only. Do not access members
|
||||
* externally.
|
||||
* @internal
|
||||
*/
|
||||
struct sock_udp {
|
||||
struct sock_udp *next; /**< sock liked list */
|
||||
openwsn_gen_sock_t gen_sock; /**< Generic socket */
|
||||
mbox_t mbox; /**< @ref core_mbox target for the sock */
|
||||
msg_t mbox_queue[OPENWSN_SOCK_MBOX_SIZE]; /**< queue for gnrc_sock_reg_t::mbox */
|
||||
#ifdef MODULE_SOCK_ASYNC_EVENT
|
||||
sock_async_ctx_t async_ctx; /**< asynchronous event context */
|
||||
#endif
|
||||
#ifdef SOCK_HAS_ASYNC
|
||||
sock_udp_cb_t async_cb; /**< asynchronous callback */
|
||||
void* async_cb_arg;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOCK_TYPES_H */
|
||||
/** @} */
|
@ -837,12 +837,17 @@ endif
|
||||
|
||||
ifneq (,$(filter gcoap,$(USEMODULE)))
|
||||
USEMODULE += nanocoap
|
||||
USEMODULE += sock_async
|
||||
USEMODULE += sock_async_event
|
||||
USEMODULE += sock_udp
|
||||
USEMODULE += sock_util
|
||||
USEMODULE += event_callback
|
||||
USEMODULE += event_timeout
|
||||
ifneq (,$(filter gnrc%,$(USEMODULE)))
|
||||
USEMODULE += gnrc_sock_async
|
||||
endif
|
||||
ifneq (,$(filter openwsn%,$(USEMODULE)))
|
||||
USEMODULE += openwsn_sock_udp
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter luid,$(USEMODULE)))
|
||||
|
Loading…
Reference in New Issue
Block a user