Merge pull request #5772 from miri64/gnrc/feat/sock
gnrc_sock: provide port for sock_ip and sock_udp
This commit is contained in:
commit
f6413ee5f5
13
Makefile.dep
13
Makefile.dep
@ -58,6 +58,19 @@ ifneq (,$(filter gnrc_conn_udp,$(USEMODULE)))
|
|||||||
USEMODULE += gnrc_udp
|
USEMODULE += gnrc_udp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter gnrc_sock_%,$(USEMODULE)))
|
||||||
|
USEMODULE += gnrc_sock
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter gnrc_sock_udp,$(USEMODULE)))
|
||||||
|
USEMODULE += gnrc_udp
|
||||||
|
USEMODULE += random # to generate random ports
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter gnrc_sock,$(USEMODULE)))
|
||||||
|
USEMODULE += gnrc_netapi_mbox
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter gnrc_netapi_mbox,$(USEMODULE)))
|
ifneq (,$(filter gnrc_netapi_mbox,$(USEMODULE)))
|
||||||
USEMODULE += core_mbox
|
USEMODULE += core_mbox
|
||||||
endif
|
endif
|
||||||
|
|||||||
@ -21,6 +21,7 @@ PSEUDOMODULES += gnrc_sixlowpan_iphc_nhc
|
|||||||
PSEUDOMODULES += gnrc_sixlowpan_nd_border_router
|
PSEUDOMODULES += gnrc_sixlowpan_nd_border_router
|
||||||
PSEUDOMODULES += gnrc_sixlowpan_router
|
PSEUDOMODULES += gnrc_sixlowpan_router
|
||||||
PSEUDOMODULES += gnrc_sixlowpan_router_default
|
PSEUDOMODULES += gnrc_sixlowpan_router_default
|
||||||
|
PSEUDOMODULES += gnrc_sock_check_reuse
|
||||||
PSEUDOMODULES += log
|
PSEUDOMODULES += log
|
||||||
PSEUDOMODULES += log_printfnoformat
|
PSEUDOMODULES += log_printfnoformat
|
||||||
PSEUDOMODULES += lwip_arp
|
PSEUDOMODULES += lwip_arp
|
||||||
@ -51,6 +52,10 @@ PSEUDOMODULES += saul_adc
|
|||||||
PSEUDOMODULES += saul_default
|
PSEUDOMODULES += saul_default
|
||||||
PSEUDOMODULES += saul_gpio
|
PSEUDOMODULES += saul_gpio
|
||||||
PSEUDOMODULES += schedstatistics
|
PSEUDOMODULES += schedstatistics
|
||||||
|
PSEUDOMODULES += sock
|
||||||
|
PSEUDOMODULES += sock_ip
|
||||||
|
PSEUDOMODULES += sock_tcp
|
||||||
|
PSEUDOMODULES += sock_udp
|
||||||
|
|
||||||
# include variants of the AT86RF2xx drivers as pseudo modules
|
# include variants of the AT86RF2xx drivers as pseudo modules
|
||||||
PSEUDOMODULES += at86rf23%
|
PSEUDOMODULES += at86rf23%
|
||||||
|
|||||||
@ -9,6 +9,12 @@ endif
|
|||||||
ifneq (,$(filter fib,$(USEMODULE)))
|
ifneq (,$(filter fib,$(USEMODULE)))
|
||||||
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
|
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
|
||||||
endif
|
endif
|
||||||
|
ifneq (,$(filter gnrc_sock,$(USEMODULE)))
|
||||||
|
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/gnrc/sock/include
|
||||||
|
ifneq (,$(filter gnrc_ipv6,$(USEMODULE)))
|
||||||
|
CFLAGS += -DSOCK_HAS_IPV6
|
||||||
|
endif
|
||||||
|
endif
|
||||||
ifneq (,$(filter posix,$(USEMODULE)))
|
ifneq (,$(filter posix,$(USEMODULE)))
|
||||||
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
|
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
|
||||||
endif
|
endif
|
||||||
|
|||||||
@ -112,6 +112,15 @@ endif
|
|||||||
ifneq (,$(filter gnrc_slip,$(USEMODULE)))
|
ifneq (,$(filter gnrc_slip,$(USEMODULE)))
|
||||||
DIRS += link_layer/slip
|
DIRS += link_layer/slip
|
||||||
endif
|
endif
|
||||||
|
ifneq (,$(filter gnrc_sock,$(USEMODULE)))
|
||||||
|
DIRS += sock
|
||||||
|
endif
|
||||||
|
ifneq (,$(filter gnrc_sock_ip,$(USEMODULE)))
|
||||||
|
DIRS += sock/ip
|
||||||
|
endif
|
||||||
|
ifneq (,$(filter gnrc_sock_udp,$(USEMODULE)))
|
||||||
|
DIRS += sock/udp
|
||||||
|
endif
|
||||||
ifneq (,$(filter gnrc_udp,$(USEMODULE)))
|
ifneq (,$(filter gnrc_udp,$(USEMODULE)))
|
||||||
DIRS += transport_layer/udp
|
DIRS += transport_layer/udp
|
||||||
endif
|
endif
|
||||||
|
|||||||
3
sys/net/gnrc/sock/Makefile
Normal file
3
sys/net/gnrc/sock/Makefile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
MODULE = gnrc_sock
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
197
sys/net/gnrc/sock/gnrc_sock.c
Normal file
197
sys/net/gnrc/sock/gnrc_sock.c
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||||
|
*
|
||||||
|
* 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 <mlenders@inf.fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "net/af.h"
|
||||||
|
#include "net/ipv6/hdr.h"
|
||||||
|
#include "net/gnrc/ipv6/hdr.h"
|
||||||
|
#include "net/gnrc/ipv6/netif.h"
|
||||||
|
#include "net/gnrc/netreg.h"
|
||||||
|
#include "net/udp.h"
|
||||||
|
#include "utlist.h"
|
||||||
|
#include "xtimer.h"
|
||||||
|
|
||||||
|
#include "sock_types.h"
|
||||||
|
#include "gnrc_sock_internal.h"
|
||||||
|
|
||||||
|
#ifdef MODULE_XTIMER
|
||||||
|
#define _TIMEOUT_MAGIC (0xF38A0B63U)
|
||||||
|
#define _TIMEOUT_MSG_TYPE (0x8474)
|
||||||
|
|
||||||
|
static void _callback_put(void *arg)
|
||||||
|
{
|
||||||
|
msg_t timeout_msg = { .sender_pid = KERNEL_PID_UNDEF,
|
||||||
|
.type = _TIMEOUT_MSG_TYPE,
|
||||||
|
.content = { .value = _TIMEOUT_MAGIC } };
|
||||||
|
gnrc_sock_reg_t *reg = arg;
|
||||||
|
|
||||||
|
/* should be safe, because otherwise if mbox were filled this callback is
|
||||||
|
* senseless */
|
||||||
|
mbox_try_put(®->mbox, &timeout_msg);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void gnrc_sock_create(gnrc_sock_reg_t *reg, gnrc_nettype_t type, uint32_t demux_ctx)
|
||||||
|
{
|
||||||
|
mbox_init(®->mbox, reg->mbox_queue, SOCK_MBOX_SIZE);
|
||||||
|
gnrc_netreg_entry_init_mbox(®->entry, demux_ctx, ®->mbox);
|
||||||
|
gnrc_netreg_register(type, ®->entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt_out,
|
||||||
|
uint32_t timeout, sock_ip_ep_t *remote)
|
||||||
|
{
|
||||||
|
gnrc_pktsnip_t *pkt, *ip, *netif;
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
#ifdef MODULE_XTIMER
|
||||||
|
xtimer_t timeout_timer;
|
||||||
|
|
||||||
|
if ((timeout != SOCK_NO_TIMEOUT) && (timeout != 0)) {
|
||||||
|
timeout_timer.callback = _callback_put;
|
||||||
|
timeout_timer.arg = reg;
|
||||||
|
xtimer_set(&timeout_timer, timeout);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (timeout != 0) {
|
||||||
|
mbox_get(®->mbox, &msg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!mbox_try_get(®->mbox, &msg)) {
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef MODULE_XTIMER
|
||||||
|
xtimer_remove(&timeout_timer);
|
||||||
|
#endif
|
||||||
|
switch (msg.type) {
|
||||||
|
case GNRC_NETAPI_MSG_TYPE_RCV:
|
||||||
|
pkt = msg.content.ptr;
|
||||||
|
break;
|
||||||
|
#ifdef MODULE_XTIMER
|
||||||
|
case _TIMEOUT_MSG_TYPE:
|
||||||
|
if (msg.content.value == _TIMEOUT_MAGIC) {
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return -EINTR;
|
||||||
|
}
|
||||||
|
/* TODO: discern NETTYPE from remote->family (set in caller), when IPv4
|
||||||
|
* was implemented */
|
||||||
|
ipv6_hdr_t *ipv6_hdr;
|
||||||
|
ip = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_IPV6);
|
||||||
|
assert((ip != NULL) && (ip->size >= 40));
|
||||||
|
ipv6_hdr = ip->data;
|
||||||
|
memcpy(&remote->addr, &ipv6_hdr->src, sizeof(ipv6_addr_t));
|
||||||
|
remote->family = AF_INET6;
|
||||||
|
netif = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF);
|
||||||
|
if (netif == NULL) {
|
||||||
|
remote->netif = SOCK_ADDR_ANY_NETIF;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gnrc_netif_hdr_t *netif_hdr = netif->data;
|
||||||
|
/* TODO: use API in #5511 */
|
||||||
|
remote->netif = (uint16_t)netif_hdr->if_pid;
|
||||||
|
}
|
||||||
|
*pkt_out = pkt; /* set out parameter */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t gnrc_sock_send(gnrc_pktsnip_t *payload, sock_ip_ep_t *local,
|
||||||
|
const sock_ip_ep_t *remote, uint8_t nh)
|
||||||
|
{
|
||||||
|
gnrc_pktsnip_t *pkt;
|
||||||
|
kernel_pid_t iface = KERNEL_PID_UNDEF;
|
||||||
|
gnrc_nettype_t type;
|
||||||
|
size_t payload_len = gnrc_pkt_len(payload);
|
||||||
|
|
||||||
|
if (local->family != remote->family) {
|
||||||
|
gnrc_pktbuf_release(payload);
|
||||||
|
return -EAFNOSUPPORT;
|
||||||
|
}
|
||||||
|
switch (local->family) {
|
||||||
|
#ifdef SOCK_HAS_IPV6
|
||||||
|
case AF_INET6: {
|
||||||
|
ipv6_hdr_t *hdr;
|
||||||
|
pkt = gnrc_ipv6_hdr_build(payload, (ipv6_addr_t *)&local->addr.ipv6,
|
||||||
|
(ipv6_addr_t *)&remote->addr.ipv6);
|
||||||
|
if (pkt == NULL) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
if (payload->type == GNRC_NETTYPE_UNDEF) {
|
||||||
|
payload->type = GNRC_NETTYPE_IPV6;
|
||||||
|
type = GNRC_NETTYPE_IPV6;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
type = payload->type;
|
||||||
|
}
|
||||||
|
hdr = pkt->data;
|
||||||
|
hdr->nh = nh;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
(void)nh;
|
||||||
|
gnrc_pktbuf_release(payload);
|
||||||
|
return -EAFNOSUPPORT;
|
||||||
|
}
|
||||||
|
if (local->netif != SOCK_ADDR_ANY_NETIF) {
|
||||||
|
/* TODO: use API in #5511 */
|
||||||
|
iface = (kernel_pid_t)local->netif;
|
||||||
|
}
|
||||||
|
else if (remote->netif != SOCK_ADDR_ANY_NETIF) {
|
||||||
|
/* TODO: use API in #5511 */
|
||||||
|
iface = (kernel_pid_t)remote->netif;
|
||||||
|
}
|
||||||
|
if (iface != KERNEL_PID_UNDEF) {
|
||||||
|
gnrc_pktsnip_t *netif = gnrc_netif_hdr_build(NULL, 0, NULL, 0);
|
||||||
|
gnrc_netif_hdr_t *netif_hdr;
|
||||||
|
|
||||||
|
if (netif == NULL) {
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
netif_hdr = netif->data;
|
||||||
|
netif_hdr->if_pid = iface;
|
||||||
|
LL_PREPEND(pkt, netif);
|
||||||
|
}
|
||||||
|
#ifdef MODULE_GNRC_NETERR
|
||||||
|
gnrc_neterr_reg(pkt); /* no error should occur since pkt was created here */
|
||||||
|
#endif
|
||||||
|
if (!gnrc_netapi_dispatch_send(type, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) {
|
||||||
|
/* this should not happen, but just in case */
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
return -EBADMSG;
|
||||||
|
}
|
||||||
|
#ifdef MODULE_GNRC_NETERR
|
||||||
|
msg_t err_report;
|
||||||
|
err_report.type = 0;
|
||||||
|
|
||||||
|
while (err_report.type != GNRC_NETERR_MSG_TYPE) {
|
||||||
|
msg_try_receive(err_report);
|
||||||
|
if (err_report.type != GNRC_NETERR_MSG_TYPE) {
|
||||||
|
msg_try_send(err_report, sched_active_pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (err_report.content.value != GNRC_NETERR_SUCCESS) {
|
||||||
|
return (int)(-err_report.content.value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return payload_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
99
sys/net/gnrc/sock/include/gnrc_sock_internal.h
Normal file
99
sys/net/gnrc/sock/include/gnrc_sock_internal.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||||
|
*
|
||||||
|
* 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_gnrc_sock GNRC-specific implementation of the sock API
|
||||||
|
* @ingroup net_gnrc
|
||||||
|
* @brief Provides an implementation of the @ref net_sock by the
|
||||||
|
* @ref net_gnrc
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief GNRC-specific types and function definitions
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||||
|
*/
|
||||||
|
#ifndef GNRC_SOCK_INTERNAL_H_
|
||||||
|
#define GNRC_SOCK_INTERNAL_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "mbox.h"
|
||||||
|
#include "net/af.h"
|
||||||
|
#include "net/gnrc.h"
|
||||||
|
#include "net/gnrc/netreg.h"
|
||||||
|
#include "net/sock/ip.h"
|
||||||
|
|
||||||
|
#include "sock_types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Internal helper functions for GNRC
|
||||||
|
* @internal
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @brief Checks if address family is not supported
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
static inline bool gnrc_af_not_supported(int af)
|
||||||
|
{
|
||||||
|
/* TODO: add AF_INET support */
|
||||||
|
return (af != AF_INET6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if end point points to any address
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
static inline bool gnrc_ep_addr_any(const sock_ip_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 false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a sock internally
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
void gnrc_sock_create(gnrc_sock_reg_t *reg, gnrc_nettype_t type, uint32_t demux_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Receive a packet internally
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt, uint32_t timeout,
|
||||||
|
sock_ip_ep_t *remote);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send a packet internally
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
ssize_t gnrc_sock_send(gnrc_pktsnip_t *payload, sock_ip_ep_t *local,
|
||||||
|
const sock_ip_ep_t *remote, uint8_t nh);
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* GNRC_SOCK_INTERNAL_H_ */
|
||||||
|
/** @} */
|
||||||
81
sys/net/gnrc/sock/include/sock_types.h
Normal file
81
sys/net/gnrc/sock/include/sock_types.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||||
|
*
|
||||||
|
* 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_gnrc_sock GNRC-specific implementation of the sock API
|
||||||
|
* @ingroup net_gnrc
|
||||||
|
* @brief Provides an implementation of the @ref net_sock by the
|
||||||
|
* @ref net_gnrc
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief GNRC-specific types and function definitions
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||||
|
*/
|
||||||
|
#ifndef SOCK_TYPES_H_
|
||||||
|
#define SOCK_TYPES_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "mbox.h"
|
||||||
|
#include "net/gnrc.h"
|
||||||
|
#include "net/gnrc/netreg.h"
|
||||||
|
#include "net/sock/ip.h"
|
||||||
|
#include "net/sock/udp.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SOCK_MBOX_SIZE
|
||||||
|
#define SOCK_MBOX_SIZE (8) /**< Size for gnrc_sock_reg_t::mbox_queue */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief sock @ref net_gnrc_netreg info
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
typedef struct gnrc_sock_reg {
|
||||||
|
#ifdef MODULE_GNRC_SOCK_CHECK_REUSE
|
||||||
|
struct gnrc_sock_reg *next; /**< list-like for internal storage */
|
||||||
|
#endif
|
||||||
|
gnrc_netreg_entry_t entry; /**< @ref net_gnrc_netreg entry for mbox */
|
||||||
|
mbox_t mbox; /**< @ref core_mbox target for the sock */
|
||||||
|
msg_t mbox_queue[SOCK_MBOX_SIZE]; /**< queue for gnrc_sock_reg_t::mbox */
|
||||||
|
} gnrc_sock_reg_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Raw IP sock type
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
struct sock_ip {
|
||||||
|
gnrc_sock_reg_t reg; /**< netreg info */
|
||||||
|
sock_ip_ep_t local; /**< local end-point */
|
||||||
|
sock_ip_ep_t remote; /**< remote end-point */
|
||||||
|
uint16_t flags; /**< option flags */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief UDP sock type
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
struct sock_udp {
|
||||||
|
gnrc_sock_reg_t reg; /**< netreg info */
|
||||||
|
sock_udp_ep_t local; /**< local end-point */
|
||||||
|
sock_udp_ep_t remote; /**< remote end-point */
|
||||||
|
uint16_t flags; /**< option flags */
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SOCK_TYPES_H_ */
|
||||||
|
/** @} */
|
||||||
3
sys/net/gnrc/sock/ip/Makefile
Normal file
3
sys/net/gnrc/sock/ip/Makefile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
MODULE = gnrc_sock_ip
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
199
sys/net/gnrc/sock/ip/gnrc_sock_ip.c
Normal file
199
sys/net/gnrc/sock/ip/gnrc_sock_ip.c
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* @brief GNRC implementation of @ref net_sock_ip
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "byteorder.h"
|
||||||
|
#include "net/af.h"
|
||||||
|
#include "net/protnum.h"
|
||||||
|
#include "net/gnrc/ipv6.h"
|
||||||
|
#include "net/sock/ip.h"
|
||||||
|
#include "random.h"
|
||||||
|
|
||||||
|
#include "gnrc_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)
|
||||||
|
{
|
||||||
|
assert(sock);
|
||||||
|
if ((local != NULL) && (remote != NULL) &&
|
||||||
|
(local->netif != SOCK_ADDR_ANY_NETIF) &&
|
||||||
|
(remote->netif != SOCK_ADDR_ANY_NETIF) &&
|
||||||
|
(local->netif != remote->netif)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
memset(&sock->local, 0, sizeof(sock_ip_t));
|
||||||
|
if (local != NULL) {
|
||||||
|
if (gnrc_af_not_supported(local->family)) {
|
||||||
|
return -EAFNOSUPPORT;
|
||||||
|
}
|
||||||
|
memcpy(&sock->local, local, sizeof(sock_ip_t));
|
||||||
|
}
|
||||||
|
memset(&sock->remote, 0, sizeof(sock_ip_t));
|
||||||
|
if (remote != NULL) {
|
||||||
|
if (gnrc_af_not_supported(remote->family)) {
|
||||||
|
return -EAFNOSUPPORT;
|
||||||
|
}
|
||||||
|
if (gnrc_ep_addr_any(remote)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
memcpy(&sock->remote, remote, sizeof(sock_ip_t));
|
||||||
|
}
|
||||||
|
gnrc_sock_create(&sock->reg, GNRC_NETTYPE_IPV6,
|
||||||
|
proto);
|
||||||
|
sock->flags = flags;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sock_ip_close(sock_ip_t *sock)
|
||||||
|
{
|
||||||
|
assert(sock != NULL);
|
||||||
|
gnrc_netreg_unregister(GNRC_NETTYPE_IPV6, &sock->reg.entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sock_ip_get_local(sock_ip_t *sock, sock_ip_ep_t *local)
|
||||||
|
{
|
||||||
|
assert(sock && local);
|
||||||
|
if (sock->local.family == AF_UNSPEC) {
|
||||||
|
return -EADDRNOTAVAIL;
|
||||||
|
}
|
||||||
|
memcpy(local, &sock->local, sizeof(sock_ip_ep_t));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sock_ip_get_remote(sock_ip_t *sock, sock_ip_ep_t *remote)
|
||||||
|
{
|
||||||
|
assert(sock && remote);
|
||||||
|
if (sock->remote.family == AF_UNSPEC) {
|
||||||
|
return -ENOTCONN;
|
||||||
|
}
|
||||||
|
memcpy(remote, &sock->remote, sizeof(sock_ip_ep_t));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t sock_ip_recv(sock_ip_t *sock, void *data, size_t max_len,
|
||||||
|
uint32_t timeout, sock_ip_ep_t *remote)
|
||||||
|
{
|
||||||
|
gnrc_pktsnip_t *pkt;
|
||||||
|
sock_ip_ep_t tmp;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
assert((sock != NULL) && (data != NULL) && (max_len > 0));
|
||||||
|
if (sock->local.family == 0) {
|
||||||
|
return -EADDRNOTAVAIL;
|
||||||
|
}
|
||||||
|
tmp.family = sock->local.family;
|
||||||
|
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp);
|
||||||
|
if (res < 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (pkt->size > max_len) {
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
return -ENOBUFS;
|
||||||
|
}
|
||||||
|
if (remote != NULL) {
|
||||||
|
/* return remote to possibly block if wrong remote */
|
||||||
|
memcpy(remote, &tmp, sizeof(tmp));
|
||||||
|
}
|
||||||
|
if ((sock->remote.family != AF_UNSPEC) && /* check remote end-point if set */
|
||||||
|
/* We only have IPv6 for now, so just comparing the whole end point
|
||||||
|
* should suffice */
|
||||||
|
((memcmp(&sock->remote.addr, &ipv6_addr_unspecified,
|
||||||
|
sizeof(ipv6_addr_t)) != 0) &&
|
||||||
|
(memcmp(&sock->remote.addr, &tmp.addr, sizeof(ipv6_addr_t)) != 0))) {
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
return -EPROTO;
|
||||||
|
}
|
||||||
|
memcpy(data, pkt->data, pkt->size);
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
return (int)pkt->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t sock_ip_send(sock_ip_t *sock, const void *data, size_t len,
|
||||||
|
uint8_t proto, const sock_ip_ep_t *remote)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
gnrc_pktsnip_t *pkt;
|
||||||
|
sock_ip_ep_t local;
|
||||||
|
sock_ip_ep_t rem;
|
||||||
|
|
||||||
|
assert((sock != NULL) || (remote != NULL));
|
||||||
|
assert((len == 0) || (data != NULL)); /* (len != 0) => (data != NULL) */
|
||||||
|
if ((remote != NULL) && (sock != NULL) &&
|
||||||
|
(sock->local.netif != SOCK_ADDR_ANY_NETIF) &&
|
||||||
|
(remote->netif != SOCK_ADDR_ANY_NETIF) &&
|
||||||
|
(sock->local.netif != remote->netif)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if ((remote == NULL) &&
|
||||||
|
/* sock can't be NULL as per assertion above */
|
||||||
|
(sock->remote.family == AF_UNSPEC)) {
|
||||||
|
return -ENOTCONN;
|
||||||
|
}
|
||||||
|
else if ((remote != NULL) && (gnrc_ep_addr_any(remote))) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
/* compiler evaluates lazily so this isn't a redundundant check and cppcheck
|
||||||
|
* is being weird here anyways */
|
||||||
|
/* cppcheck-suppress nullPointerRedundantCheck */
|
||||||
|
/* cppcheck-suppress nullPointer */
|
||||||
|
if ((sock == NULL) || (sock->local.family == AF_UNSPEC)) {
|
||||||
|
/* no sock or sock currently unbound */
|
||||||
|
memset(&local, 0, sizeof(local));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (sock != NULL) {
|
||||||
|
proto = (uint8_t)sock->reg.entry.demux_ctx;
|
||||||
|
}
|
||||||
|
memcpy(&local, &sock->local, sizeof(local));
|
||||||
|
}
|
||||||
|
if (remote == NULL) {
|
||||||
|
/* sock can't be NULL at this point */
|
||||||
|
memcpy(&rem, &sock->remote, sizeof(rem));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memcpy(&rem, remote, sizeof(rem));
|
||||||
|
}
|
||||||
|
if ((remote != NULL) && (remote->family == AF_UNSPEC) &&
|
||||||
|
(sock->remote.family != AF_UNSPEC)) {
|
||||||
|
/* remote was set on create so take its family */
|
||||||
|
rem.family = sock->remote.family;
|
||||||
|
}
|
||||||
|
else if ((remote != NULL) && gnrc_af_not_supported(remote->family)) {
|
||||||
|
return -EAFNOSUPPORT;
|
||||||
|
}
|
||||||
|
else if ((local.family == AF_UNSPEC) && (rem.family != AF_UNSPEC)) {
|
||||||
|
/* local was set to 0 above */
|
||||||
|
local.family = rem.family;
|
||||||
|
}
|
||||||
|
else if ((local.family != AF_UNSPEC) && (rem.family == AF_UNSPEC)) {
|
||||||
|
/* local was given on create, but remote family wasn't given by user and
|
||||||
|
* there was no remote given on create, take from local */
|
||||||
|
rem.family = local.family;
|
||||||
|
}
|
||||||
|
pkt = gnrc_pktbuf_add(NULL, (void *)data, len, GNRC_NETTYPE_UNDEF);
|
||||||
|
if (pkt == NULL) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
res = gnrc_sock_send(pkt, &local, &rem, proto);
|
||||||
|
if (res <= 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
3
sys/net/gnrc/sock/udp/Makefile
Normal file
3
sys/net/gnrc/sock/udp/Makefile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
MODULE = gnrc_sock_udp
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
277
sys/net/gnrc/sock/udp/gnrc_sock_udp.c
Normal file
277
sys/net/gnrc/sock/udp/gnrc_sock_udp.c
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* @brief GNRC implementation of @ref net_sock_udp
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "byteorder.h"
|
||||||
|
#include "net/af.h"
|
||||||
|
#include "net/protnum.h"
|
||||||
|
#include "net/gnrc/ipv6.h"
|
||||||
|
#include "net/gnrc/udp.h"
|
||||||
|
#include "net/sock/udp.h"
|
||||||
|
#include "net/udp.h"
|
||||||
|
#include "random.h"
|
||||||
|
|
||||||
|
#include "gnrc_sock_internal.h"
|
||||||
|
|
||||||
|
#ifdef MODULE_GNRC_SOCK_CHECK_REUSE
|
||||||
|
static sock_udp_t *_udp_socks = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int sock_udp_create(sock_udp_t *sock, const sock_udp_ep_t *local,
|
||||||
|
const sock_udp_ep_t *remote, uint16_t flags)
|
||||||
|
{
|
||||||
|
assert(sock);
|
||||||
|
assert(local == NULL || local->port != 0);
|
||||||
|
assert(remote == NULL || remote->port != 0);
|
||||||
|
if ((local != NULL) && (remote != NULL) &&
|
||||||
|
(local->netif != SOCK_ADDR_ANY_NETIF) &&
|
||||||
|
(remote->netif != SOCK_ADDR_ANY_NETIF) &&
|
||||||
|
(local->netif != remote->netif)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
memset(&sock->local, 0, sizeof(sock_udp_ep_t));
|
||||||
|
if (local != NULL) {
|
||||||
|
#ifdef MODULE_GNRC_SOCK_CHECK_REUSE
|
||||||
|
if (!(flags & SOCK_FLAGS_REUSE_EP)) {
|
||||||
|
for (sock_udp_t *ptr = _udp_socks; ptr != NULL;
|
||||||
|
ptr = (sock_udp_t *)ptr->reg.next) {
|
||||||
|
if (memcmp(&ptr->local, local, sizeof(sock_udp_ep_t)) == 0) {
|
||||||
|
return -EADDRINUSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* prepend to current socks */
|
||||||
|
sock->reg.next = (gnrc_sock_reg_t *)_udp_socks;
|
||||||
|
_udp_socks = sock;
|
||||||
|
#endif
|
||||||
|
if (gnrc_af_not_supported(local->family)) {
|
||||||
|
return -EAFNOSUPPORT;
|
||||||
|
}
|
||||||
|
memcpy(&sock->local, local, sizeof(sock_udp_ep_t));
|
||||||
|
}
|
||||||
|
memset(&sock->remote, 0, sizeof(sock_udp_ep_t));
|
||||||
|
if (remote != NULL) {
|
||||||
|
if (gnrc_af_not_supported(remote->family)) {
|
||||||
|
return -EAFNOSUPPORT;
|
||||||
|
}
|
||||||
|
if (gnrc_ep_addr_any((const sock_ip_ep_t *)remote)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
memcpy(&sock->remote, remote, sizeof(sock_udp_ep_t));
|
||||||
|
}
|
||||||
|
if (local != NULL) {
|
||||||
|
/* listen only with local given */
|
||||||
|
gnrc_sock_create(&sock->reg, GNRC_NETTYPE_UDP,
|
||||||
|
local->port);
|
||||||
|
}
|
||||||
|
sock->flags = flags;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sock_udp_close(sock_udp_t *sock)
|
||||||
|
{
|
||||||
|
assert(sock != NULL);
|
||||||
|
gnrc_netreg_unregister(GNRC_NETTYPE_UDP, &sock->reg.entry);
|
||||||
|
#ifdef MODULE_GNRC_SOCK_CHECK_REUSE
|
||||||
|
if (_udp_socks != NULL) {
|
||||||
|
gnrc_sock_reg_t *head = (gnrc_sock_reg_t *)_udp_socks;
|
||||||
|
LL_DELETE(head, (gnrc_sock_reg_t *)sock);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int sock_udp_get_local(sock_udp_t *sock, sock_udp_ep_t *local)
|
||||||
|
{
|
||||||
|
assert(sock && local);
|
||||||
|
if (sock->local.family == AF_UNSPEC) {
|
||||||
|
return -EADDRNOTAVAIL;
|
||||||
|
}
|
||||||
|
memcpy(local, &sock->local, sizeof(sock_udp_ep_t));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sock_udp_get_remote(sock_udp_t *sock, sock_udp_ep_t *remote)
|
||||||
|
{
|
||||||
|
assert(sock && remote);
|
||||||
|
if (sock->remote.family == AF_UNSPEC) {
|
||||||
|
return -ENOTCONN;
|
||||||
|
}
|
||||||
|
memcpy(remote, &sock->remote, sizeof(sock_udp_ep_t));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len,
|
||||||
|
uint32_t timeout, sock_udp_ep_t *remote)
|
||||||
|
{
|
||||||
|
gnrc_pktsnip_t *pkt, *udp;
|
||||||
|
udp_hdr_t *hdr;
|
||||||
|
sock_ip_ep_t tmp;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
assert((sock != NULL) && (data != NULL) && (max_len > 0));
|
||||||
|
if (sock->local.family == AF_UNSPEC) {
|
||||||
|
return -EADDRNOTAVAIL;
|
||||||
|
}
|
||||||
|
tmp.family = sock->local.family;
|
||||||
|
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp);
|
||||||
|
if (res < 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (pkt->size > max_len) {
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
return -ENOBUFS;
|
||||||
|
}
|
||||||
|
udp = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_UDP);
|
||||||
|
assert(udp);
|
||||||
|
hdr = udp->data;
|
||||||
|
if (remote != NULL) {
|
||||||
|
/* return remote to possibly block if wrong remote */
|
||||||
|
memcpy(remote, &tmp, sizeof(tmp));
|
||||||
|
remote->port = byteorder_ntohs(hdr->src_port);
|
||||||
|
}
|
||||||
|
if ((sock->remote.family != AF_UNSPEC) && /* check remote end-point if set */
|
||||||
|
((sock->remote.port != byteorder_ntohs(hdr->src_port)) ||
|
||||||
|
/* We only have IPv6 for now, so just comparing the whole end point
|
||||||
|
* should suffice */
|
||||||
|
((memcmp(&sock->remote.addr, &ipv6_addr_unspecified,
|
||||||
|
sizeof(ipv6_addr_t)) != 0) &&
|
||||||
|
(memcmp(&sock->remote.addr, &tmp.addr, sizeof(ipv6_addr_t)) != 0)))) {
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
return -EPROTO;
|
||||||
|
}
|
||||||
|
memcpy(data, pkt->data, pkt->size);
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
return (int)pkt->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t sock_udp_send(sock_udp_t *sock, const void *data, size_t len,
|
||||||
|
const sock_udp_ep_t *remote)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
gnrc_pktsnip_t *payload, *pkt;
|
||||||
|
uint16_t src_port = 0, dst_port;
|
||||||
|
sock_ip_ep_t local;
|
||||||
|
sock_ip_ep_t rem;
|
||||||
|
|
||||||
|
assert((sock != NULL) || (remote != NULL));
|
||||||
|
assert((len == 0) || (data != NULL)); /* (len != 0) => (data != NULL) */
|
||||||
|
if ((remote != NULL) && (sock != NULL) &&
|
||||||
|
(sock->local.netif != SOCK_ADDR_ANY_NETIF) &&
|
||||||
|
(remote->netif != SOCK_ADDR_ANY_NETIF) &&
|
||||||
|
(sock->local.netif != remote->netif)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if ((remote != NULL) && ((remote->port == 0) ||
|
||||||
|
gnrc_ep_addr_any((const sock_ip_ep_t *)remote))) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if ((remote == NULL) &&
|
||||||
|
/* sock can't be NULL as per assertion above */
|
||||||
|
(sock->remote.port == AF_UNSPEC)) {
|
||||||
|
return -ENOTCONN;
|
||||||
|
}
|
||||||
|
/* compiler evaluates lazily so this isn't a redundundant check and cppcheck
|
||||||
|
* is being weird here anyways */
|
||||||
|
/* cppcheck-suppress nullPointerRedundantCheck */
|
||||||
|
/* cppcheck-suppress nullPointer */
|
||||||
|
if ((sock == NULL) || (sock->local.family == AF_UNSPEC)) {
|
||||||
|
/* no sock or sock currently unbound */
|
||||||
|
while (src_port == 0) {
|
||||||
|
src_port = (uint16_t)(random_uint32() & UINT16_MAX);
|
||||||
|
#ifdef MODULE_GNRC_SOCK_CHECK_REUSE
|
||||||
|
if ((sock == NULL) || !(sock->flags & SOCK_FLAGS_REUSE_EP)) {
|
||||||
|
/* check if port already registered somewhere */
|
||||||
|
for (sock_udp_t *ptr = _udp_socks; ptr != NULL;
|
||||||
|
ptr = (sock_udp_t *)ptr->reg.next) {
|
||||||
|
bool spec_addr = false;
|
||||||
|
for (unsigned i = 0; i < sizeof(ptr->local.addr); i++) {
|
||||||
|
const uint8_t *const p = (uint8_t *)&ptr->local.addr;
|
||||||
|
if (p[i] != 0) {
|
||||||
|
spec_addr = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (spec_addr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ptr->local.port == src_port) {
|
||||||
|
/* we already have one of this port registered
|
||||||
|
* => generate a new one */
|
||||||
|
src_port = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
memset(&local, 0, sizeof(local));
|
||||||
|
if (sock != NULL) {
|
||||||
|
/* bind sock object implicitly */
|
||||||
|
sock->local.port = src_port;
|
||||||
|
#ifdef MODULE_GNRC_SOCK_CHECK_REUSE
|
||||||
|
/* prepend to current socks */
|
||||||
|
sock->reg.next = (gnrc_sock_reg_t *)_udp_socks;
|
||||||
|
_udp_socks = sock;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
src_port = sock->local.port;
|
||||||
|
memcpy(&local, &sock->local, sizeof(local));
|
||||||
|
}
|
||||||
|
if (remote == NULL) {
|
||||||
|
/* sock can't be NULL at this point */
|
||||||
|
memcpy(&rem, &sock->remote, sizeof(rem));
|
||||||
|
dst_port = sock->remote.port;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memcpy(&rem, remote, sizeof(rem));
|
||||||
|
dst_port = remote->port;
|
||||||
|
}
|
||||||
|
if ((remote != NULL) && (remote->family == AF_UNSPEC) &&
|
||||||
|
(sock->remote.family != AF_UNSPEC)) {
|
||||||
|
/* remote was set on create so take its family */
|
||||||
|
rem.family = sock->remote.family;
|
||||||
|
}
|
||||||
|
else if ((remote != NULL) && gnrc_af_not_supported(remote->family)) {
|
||||||
|
return -EAFNOSUPPORT;
|
||||||
|
}
|
||||||
|
else if ((local.family == AF_UNSPEC) && (rem.family != AF_UNSPEC)) {
|
||||||
|
/* local was set to 0 above */
|
||||||
|
local.family = rem.family;
|
||||||
|
}
|
||||||
|
else if ((local.family != AF_UNSPEC) && (rem.family == AF_UNSPEC)) {
|
||||||
|
/* local was given on create, but remote family wasn't given by user and
|
||||||
|
* there was no remote given on create, take from local */
|
||||||
|
rem.family = local.family;
|
||||||
|
}
|
||||||
|
payload = gnrc_pktbuf_add(NULL, (void *)data, len, GNRC_NETTYPE_UNDEF);
|
||||||
|
if (payload == NULL) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
pkt = gnrc_udp_hdr_build(payload, src_port, dst_port);
|
||||||
|
if (pkt == NULL) {
|
||||||
|
gnrc_pktbuf_release(payload);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
res = gnrc_sock_send(pkt, &local, &rem, PROTNUM_UDP);
|
||||||
|
if (res <= 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return res - sizeof(udp_hdr_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
20
tests/gnrc_sock_ip/Makefile
Normal file
20
tests/gnrc_sock_ip/Makefile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
APPLICATION = gnrc_sock_ip
|
||||||
|
|
||||||
|
BOARD ?= native
|
||||||
|
|
||||||
|
RIOTBASE ?= $(CURDIR)/../..
|
||||||
|
|
||||||
|
USEMODULE += gnrc_sock_ip
|
||||||
|
USEMODULE += gnrc_ipv6
|
||||||
|
USEMODULE += ps
|
||||||
|
|
||||||
|
CFLAGS += -DDEVELHELP
|
||||||
|
CFLAGS += -DGNRC_PKTBUF_SIZE=200
|
||||||
|
CFLAGS += -DTEST_SUITES
|
||||||
|
|
||||||
|
QUIET ?= 1
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.include
|
||||||
|
|
||||||
|
test:
|
||||||
|
./tests/01-run.py
|
||||||
43
tests/gnrc_sock_ip/constants.h
Normal file
43
tests/gnrc_sock_ip/constants.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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
|
||||||
|
* @ingroup
|
||||||
|
* @brief
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
#ifndef CONSTANTS_H_
|
||||||
|
#define CONSTANTS_H_
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _TEST_PROTO (254) /* https://tools.ietf.org/html/rfc3692#section-2.1 */
|
||||||
|
#define _TEST_NETIF (31)
|
||||||
|
#define _TEST_TIMEOUT (1000000U)
|
||||||
|
#define _TEST_ADDR_LOCAL { 0x7f, 0xc4, 0x11, 0x5a, 0xe6, 0x91, 0x8d, 0x5d, \
|
||||||
|
0x8c, 0xd1, 0x47, 0x07, 0xb7, 0x6f, 0x9b, 0x48 }
|
||||||
|
#define _TEST_ADDR_REMOTE { 0xe8, 0xb3, 0xb2, 0xe6, 0x70, 0xd4, 0x55, 0xba, \
|
||||||
|
0x93, 0xcf, 0x11, 0xe1, 0x72, 0x44, 0xc5, 0x9d }
|
||||||
|
#define _TEST_ADDR_WRONG { 0x2a, 0xce, 0x5d, 0x4e, 0xc8, 0xbf, 0x86, 0xf7, \
|
||||||
|
0x85, 0x49, 0xb4, 0x19, 0xf2, 0x28, 0xde, 0x9b }
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONSTANTS_H_ */
|
||||||
|
/** @} */
|
||||||
640
tests/gnrc_sock_ip/main.c
Normal file
640
tests/gnrc_sock_ip/main.c
Normal file
@ -0,0 +1,640 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup examples
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Test for raw IP socks
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "net/af.h"
|
||||||
|
#include "net/sock/ip.h"
|
||||||
|
#include "xtimer.h"
|
||||||
|
|
||||||
|
#include "constants.h"
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
|
#define _TEST_BUFFER_SIZE (128)
|
||||||
|
|
||||||
|
#define CALL(fn) puts("Calling " # fn); fn; tear_down()
|
||||||
|
|
||||||
|
static sock_ip_t _sock, _sock2;
|
||||||
|
static uint8_t _test_buffer[_TEST_BUFFER_SIZE];
|
||||||
|
|
||||||
|
static void tear_down(void)
|
||||||
|
{
|
||||||
|
sock_ip_close(&_sock);
|
||||||
|
memset(&_sock, 0, sizeof(_sock));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_create__EAFNOSUPPORT(void)
|
||||||
|
{
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_UNSPEC };
|
||||||
|
static const sock_ip_ep_t remote = { .family = AF_UNSPEC };
|
||||||
|
|
||||||
|
assert(-EAFNOSUPPORT == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(-EAFNOSUPPORT == sock_ip_create(&_sock, NULL, &remote, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_create__EINVAL_addr(void)
|
||||||
|
{
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF };
|
||||||
|
static const sock_ip_ep_t remote = { .family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF };
|
||||||
|
|
||||||
|
assert(-EINVAL == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_create__EINVAL_netif(void)
|
||||||
|
{
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF };
|
||||||
|
static const sock_ip_ep_t remote = { .family = AF_INET6,
|
||||||
|
.netif = (_TEST_NETIF + 1),
|
||||||
|
.addr = { .ipv6 = _TEST_ADDR_REMOTE } };
|
||||||
|
|
||||||
|
assert(-EINVAL == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_create__no_endpoints(void)
|
||||||
|
{
|
||||||
|
sock_ip_ep_t ep;
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, NULL, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(-EADDRNOTAVAIL == sock_ip_get_local(&_sock, &ep));
|
||||||
|
assert(-ENOTCONN == sock_ip_get_remote(&_sock, &ep));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_create__only_local(void)
|
||||||
|
{
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_INET6 };
|
||||||
|
sock_ip_ep_t ep;
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(0 == sock_ip_get_local(&_sock, &ep));
|
||||||
|
assert(AF_INET6 == ep.family);
|
||||||
|
assert(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6,
|
||||||
|
sizeof(ipv6_addr_t)) == 0);
|
||||||
|
assert(SOCK_ADDR_ANY_NETIF == ep.netif);
|
||||||
|
assert(-ENOTCONN == sock_ip_get_remote(&_sock, &ep));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_create__only_local_reuse_ep(void)
|
||||||
|
{
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_INET6 };
|
||||||
|
sock_ip_ep_t ep, ep2;
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(0 == sock_ip_create(&_sock2, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(0 == sock_ip_get_local(&_sock, &ep));
|
||||||
|
assert(0 == sock_ip_get_local(&_sock2, &ep2));
|
||||||
|
assert(AF_INET6 == ep.family);
|
||||||
|
assert(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6,
|
||||||
|
sizeof(ipv6_addr_t)) == 0);
|
||||||
|
assert(SOCK_ADDR_ANY_NETIF == ep.netif);
|
||||||
|
assert(-ENOTCONN == sock_ip_get_remote(&_sock, &ep));
|
||||||
|
assert(AF_INET6 == ep2.family);
|
||||||
|
assert(memcmp(&ipv6_addr_unspecified, &ep2.addr.ipv6,
|
||||||
|
sizeof(ipv6_addr_t)) == 0);
|
||||||
|
assert(SOCK_ADDR_ANY_NETIF == ep2.netif);
|
||||||
|
assert(-ENOTCONN == sock_ip_get_remote(&_sock, &ep2));
|
||||||
|
sock_ip_close(&_sock2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_create__only_remote(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t remote_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_ip_ep_t remote = { .family = AF_INET6,
|
||||||
|
.addr = { .ipv6 = _TEST_ADDR_REMOTE } };
|
||||||
|
sock_ip_ep_t ep;
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, NULL, &remote, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(-EADDRNOTAVAIL == sock_ip_get_local(&_sock, &ep));
|
||||||
|
assert(0 == sock_ip_get_remote(&_sock, &ep));
|
||||||
|
assert(AF_INET6 == ep.family);
|
||||||
|
assert(memcmp(&remote_addr, &ep.addr.ipv6, sizeof(ipv6_addr_t)) == 0);
|
||||||
|
assert(SOCK_ADDR_ANY_NETIF == ep.netif);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_create__full(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t remote_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF };
|
||||||
|
static const sock_ip_ep_t remote = { .family = AF_INET6,
|
||||||
|
.addr = { .ipv6 = _TEST_ADDR_REMOTE } };
|
||||||
|
sock_ip_ep_t ep;
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(0 == sock_ip_get_local(&_sock, &ep));
|
||||||
|
assert(AF_INET6 == ep.family);
|
||||||
|
assert(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6,
|
||||||
|
sizeof(ipv6_addr_t)) == 0);
|
||||||
|
assert(_TEST_NETIF == ep.netif);
|
||||||
|
assert(0 == sock_ip_get_remote(&_sock, &ep));
|
||||||
|
assert(AF_INET6 == ep.family);
|
||||||
|
assert(memcmp(&remote_addr, &ep.addr.ipv6, sizeof(ipv6_addr_t)) == 0);
|
||||||
|
assert(SOCK_ADDR_ANY_NETIF == ep.netif);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_recv__EADDRNOTAVAIL(void)
|
||||||
|
{
|
||||||
|
assert(0 == sock_ip_create(&_sock, NULL, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
|
||||||
|
assert(-EADDRNOTAVAIL == sock_ip_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer), SOCK_NO_TIMEOUT,
|
||||||
|
NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_recv__EAGAIN(void)
|
||||||
|
{
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
|
||||||
|
assert(-EAGAIN == sock_ip_recv(&_sock, _test_buffer, sizeof(_test_buffer),
|
||||||
|
0, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_recv__ENOBUFS(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_INET6 };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
assert(-ENOBUFS == sock_ip_recv(&_sock, _test_buffer, 2, SOCK_NO_TIMEOUT,
|
||||||
|
NULL));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_recv__EPROTO(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_WRONG };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_INET6 };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
assert(-EPROTO == sock_ip_recv(&_sock, _test_buffer, sizeof(_test_buffer),
|
||||||
|
SOCK_NO_TIMEOUT, NULL));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_recv__ETIMEDOUT(void)
|
||||||
|
{
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
|
||||||
|
puts(" * Calling sock_ip_recv()");
|
||||||
|
assert(-ETIMEDOUT == sock_ip_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer), _TEST_TIMEOUT,
|
||||||
|
NULL));
|
||||||
|
printf(" * (timed out with timeout %lu)\n", (long unsigned)_TEST_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_recv__socketed(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_INET6 };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer), SOCK_NO_TIMEOUT,
|
||||||
|
NULL));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_recv__socketed_with_remote(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_INET6 };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
sock_ip_ep_t result;
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer), SOCK_NO_TIMEOUT,
|
||||||
|
&result));
|
||||||
|
assert(AF_INET6 == result.family);
|
||||||
|
assert(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
|
||||||
|
assert(_TEST_NETIF == result.netif);
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_recv__unsocketed(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer), SOCK_NO_TIMEOUT,
|
||||||
|
NULL));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_recv__unsocketed_with_remote(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_INET6 };
|
||||||
|
sock_ip_ep_t result;
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer), SOCK_NO_TIMEOUT,
|
||||||
|
&result));
|
||||||
|
assert(AF_INET6 == result.family);
|
||||||
|
assert(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
|
||||||
|
assert(_TEST_NETIF == result.netif);
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_recv__with_timeout(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_INET6 };
|
||||||
|
sock_ip_ep_t result;
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer), _TEST_TIMEOUT,
|
||||||
|
&result));
|
||||||
|
assert(AF_INET6 == result.family);
|
||||||
|
assert(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
|
||||||
|
assert(_TEST_NETIF == result.netif);
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_recv__non_blocking(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_ip_ep_t local = { .family = AF_INET6 };
|
||||||
|
sock_ip_ep_t result;
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer), 0, &result));
|
||||||
|
assert(AF_INET6 == result.family);
|
||||||
|
assert(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
|
||||||
|
assert(_TEST_NETIF == result.netif);
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__EAFNOSUPPORT(void)
|
||||||
|
{
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET };
|
||||||
|
|
||||||
|
assert(-EAFNOSUPPORT == sock_ip_send(NULL, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_PROTO, &remote));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__EINVAL_addr(void)
|
||||||
|
{
|
||||||
|
static const sock_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF };
|
||||||
|
static const sock_ip_ep_t remote = { .family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(-EINVAL == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"), _TEST_PROTO,
|
||||||
|
&remote));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__EINVAL_netif(void)
|
||||||
|
{
|
||||||
|
static const sock_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF + 1 };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(-EINVAL == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"), _TEST_PROTO,
|
||||||
|
&remote));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__ENOTCONN(void)
|
||||||
|
{
|
||||||
|
assert(0 == sock_ip_create(&_sock, NULL, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(-ENOTCONN == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_PROTO, NULL));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__socketed_no_local_no_netif(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, NULL, &remote, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_PROTO, NULL));
|
||||||
|
assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), SOCK_ADDR_ANY_NETIF));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__socketed_no_netif(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_PROTO, NULL));
|
||||||
|
assert(_check_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), SOCK_ADDR_ANY_NETIF));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__socketed_no_local(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, NULL, &remote, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_PROTO, NULL));
|
||||||
|
assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__socketed(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, &remote, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_PROTO, NULL));
|
||||||
|
assert(_check_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__socketed_other_remote(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF };
|
||||||
|
static const sock_ip_ep_t sock_remote = { .addr = { .ipv6 = _TEST_ADDR_WRONG },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, &sock_remote, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_PROTO, &remote));
|
||||||
|
assert(_check_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__unsocketed_no_local_no_netif(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, NULL, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_PROTO, &remote));
|
||||||
|
assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), SOCK_ADDR_ANY_NETIF));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__unsocketed_no_netif(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_PROTO, &remote));
|
||||||
|
assert(_check_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), SOCK_ADDR_ANY_NETIF));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__unsocketed_no_local(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, NULL, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_PROTO, &remote));
|
||||||
|
assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__unsocketed(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_ip_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
|
||||||
|
assert(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO,
|
||||||
|
SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_ip_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_PROTO, &remote));
|
||||||
|
assert(_check_packet(&src_addr, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__no_sock_no_netif(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
|
||||||
|
assert(sizeof("ABCD") == sock_ip_send(NULL, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_PROTO, &remote));
|
||||||
|
assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), SOCK_ADDR_ANY_NETIF));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_ip_send__no_sock(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_ip_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF };
|
||||||
|
|
||||||
|
assert(sizeof("ABCD") == sock_ip_send(NULL, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_PROTO, &remote));
|
||||||
|
assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, _TEST_PROTO, "ABCD",
|
||||||
|
sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
_net_init();
|
||||||
|
tear_down();
|
||||||
|
/* EADDRINUSE does not apply for GNRC */
|
||||||
|
CALL(test_sock_ip_create__EAFNOSUPPORT());
|
||||||
|
CALL(test_sock_ip_create__EINVAL_addr());
|
||||||
|
CALL(test_sock_ip_create__EINVAL_netif());
|
||||||
|
/* EPROTONOSUPPORT does not apply for gnrc_ipv6 */
|
||||||
|
CALL(test_sock_ip_create__no_endpoints());
|
||||||
|
CALL(test_sock_ip_create__only_local());
|
||||||
|
CALL(test_sock_ip_create__only_local_reuse_ep());
|
||||||
|
CALL(test_sock_ip_create__only_remote());
|
||||||
|
CALL(test_sock_ip_create__full());
|
||||||
|
/* sock_ip_close() is tested in tear_down() */
|
||||||
|
/* sock_ip_get_local() is tested in sock_ip_create() tests */
|
||||||
|
/* sock_ip_get_remote() is tested in sock_ip_create() tests */
|
||||||
|
CALL(test_sock_ip_recv__EADDRNOTAVAIL());
|
||||||
|
CALL(test_sock_ip_recv__EAGAIN());
|
||||||
|
CALL(test_sock_ip_recv__ENOBUFS());
|
||||||
|
CALL(test_sock_ip_recv__EPROTO());
|
||||||
|
CALL(test_sock_ip_recv__ETIMEDOUT());
|
||||||
|
CALL(test_sock_ip_recv__socketed());
|
||||||
|
CALL(test_sock_ip_recv__socketed_with_remote());
|
||||||
|
CALL(test_sock_ip_recv__unsocketed());
|
||||||
|
CALL(test_sock_ip_recv__unsocketed_with_remote());
|
||||||
|
CALL(test_sock_ip_recv__with_timeout());
|
||||||
|
CALL(test_sock_ip_recv__non_blocking());
|
||||||
|
_prepare_send_checks();
|
||||||
|
CALL(test_sock_ip_send__EAFNOSUPPORT());
|
||||||
|
CALL(test_sock_ip_send__EINVAL_addr());
|
||||||
|
CALL(test_sock_ip_send__EINVAL_netif());
|
||||||
|
CALL(test_sock_ip_send__ENOTCONN());
|
||||||
|
/* EPROTOTYPE does not apply for gnrc_ipv6 */
|
||||||
|
CALL(test_sock_ip_send__socketed_no_local_no_netif());
|
||||||
|
CALL(test_sock_ip_send__socketed_no_netif());
|
||||||
|
CALL(test_sock_ip_send__socketed_no_local());
|
||||||
|
CALL(test_sock_ip_send__socketed());
|
||||||
|
CALL(test_sock_ip_send__socketed_other_remote());
|
||||||
|
CALL(test_sock_ip_send__unsocketed_no_local_no_netif());
|
||||||
|
CALL(test_sock_ip_send__unsocketed_no_netif());
|
||||||
|
CALL(test_sock_ip_send__unsocketed_no_local());
|
||||||
|
CALL(test_sock_ip_send__unsocketed());
|
||||||
|
CALL(test_sock_ip_send__no_sock_no_netif());
|
||||||
|
CALL(test_sock_ip_send__no_sock());
|
||||||
|
|
||||||
|
puts("ALL TESTS SUCCESSFUL");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
142
tests/gnrc_sock_ip/stack.c
Normal file
142
tests/gnrc_sock_ip/stack.c
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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 "stack.h"
|
||||||
|
|
||||||
|
#include "net/gnrc/ipv6.h"
|
||||||
|
#include "net/gnrc/netif/hdr.h"
|
||||||
|
#include "net/gnrc/netreg.h"
|
||||||
|
#include "net/sock.h"
|
||||||
|
#include "sched.h"
|
||||||
|
|
||||||
|
#define _MSG_QUEUE_SIZE (4)
|
||||||
|
|
||||||
|
static msg_t _msg_queue[_MSG_QUEUE_SIZE];
|
||||||
|
static gnrc_netreg_entry_t _ip_handler;
|
||||||
|
|
||||||
|
void _net_init(void)
|
||||||
|
{
|
||||||
|
msg_init_queue(_msg_queue, _MSG_QUEUE_SIZE);
|
||||||
|
gnrc_netreg_entry_init_pid(&_ip_handler, GNRC_NETREG_DEMUX_CTX_ALL,
|
||||||
|
sched_active_pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _prepare_send_checks(void)
|
||||||
|
{
|
||||||
|
gnrc_netreg_register(GNRC_NETTYPE_IPV6, &_ip_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gnrc_pktsnip_t *_build_ipv6_packet(const ipv6_addr_t *src,
|
||||||
|
const ipv6_addr_t *dst, uint8_t nh,
|
||||||
|
void *data, size_t data_len,
|
||||||
|
uint16_t netif)
|
||||||
|
{
|
||||||
|
gnrc_pktsnip_t *netif_hdr, *ipv6, *payload;
|
||||||
|
ipv6_hdr_t *ipv6_hdr;
|
||||||
|
|
||||||
|
if ((netif > INT16_MAX) || (data_len > UINT16_MAX)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload = gnrc_pktbuf_add(NULL, data, data_len, GNRC_NETTYPE_UNDEF);
|
||||||
|
if (payload == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ipv6 = gnrc_ipv6_hdr_build(NULL, src, dst);
|
||||||
|
if (ipv6 == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ipv6_hdr = ipv6->data;
|
||||||
|
ipv6_hdr->len = byteorder_htons((uint16_t)payload->size);
|
||||||
|
ipv6_hdr->nh = nh;
|
||||||
|
ipv6_hdr->hl = 64;
|
||||||
|
LL_APPEND(payload, ipv6);
|
||||||
|
netif_hdr = gnrc_netif_hdr_build(NULL, 0, NULL, 0);
|
||||||
|
if (netif_hdr == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
((gnrc_netif_hdr_t *)netif_hdr->data)->if_pid = (kernel_pid_t)netif;
|
||||||
|
LL_APPEND(payload, netif_hdr);
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool _inject_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||||
|
uint8_t proto, void *data, size_t data_len,
|
||||||
|
uint16_t netif)
|
||||||
|
{
|
||||||
|
gnrc_pktsnip_t *pkt = _build_ipv6_packet(src, dst, proto, data, data_len,
|
||||||
|
netif);
|
||||||
|
|
||||||
|
if (pkt == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* put directly in mbox, dispatching to IPv6 would result in the packet
|
||||||
|
* being dropped, since dst is not on any interface */
|
||||||
|
return (gnrc_netapi_dispatch_receive(GNRC_NETTYPE_IPV6, proto, pkt) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _check_net(void)
|
||||||
|
{
|
||||||
|
return (gnrc_pktbuf_is_sane() && gnrc_pktbuf_is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool _res(gnrc_pktsnip_t *pkt, bool res)
|
||||||
|
{
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _check_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||||
|
uint8_t proto, void *data, size_t data_len,
|
||||||
|
uint16_t netif)
|
||||||
|
{
|
||||||
|
gnrc_pktsnip_t *pkt, *ipv6;
|
||||||
|
ipv6_hdr_t *ipv6_hdr;
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
msg_receive(&msg);
|
||||||
|
if (msg.type != GNRC_NETAPI_MSG_TYPE_SND) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pkt = msg.content.ptr;
|
||||||
|
if (netif != SOCK_ADDR_ANY_NETIF) {
|
||||||
|
gnrc_netif_hdr_t *netif_hdr;
|
||||||
|
|
||||||
|
if (pkt->type != GNRC_NETTYPE_NETIF) {
|
||||||
|
return _res(pkt, false);
|
||||||
|
}
|
||||||
|
netif_hdr = pkt->data;
|
||||||
|
if (netif_hdr->if_pid != netif) {
|
||||||
|
return _res(pkt, false);
|
||||||
|
}
|
||||||
|
ipv6 = pkt->next;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ipv6 = pkt;
|
||||||
|
}
|
||||||
|
if (ipv6->type != GNRC_NETTYPE_IPV6) {
|
||||||
|
return _res(pkt, false);
|
||||||
|
}
|
||||||
|
ipv6_hdr = ipv6->data;
|
||||||
|
return _res(pkt, (memcmp(src, &ipv6_hdr->src, sizeof(ipv6_addr_t)) == 0) &&
|
||||||
|
(memcmp(dst, &ipv6_hdr->dst, sizeof(ipv6_addr_t)) == 0) &&
|
||||||
|
(ipv6_hdr->nh == proto) &&
|
||||||
|
(ipv6->next != NULL) &&
|
||||||
|
(data_len == ipv6->next->size) &&
|
||||||
|
(memcmp(data, ipv6->next->data, data_len) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
90
tests/gnrc_sock_ip/stack.h
Normal file
90
tests/gnrc_sock_ip/stack.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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
|
||||||
|
* @ingroup
|
||||||
|
* @brief
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||||
|
*/
|
||||||
|
#ifndef STACK_H_
|
||||||
|
#define STACK_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "net/ipv6/addr.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes networking for tests
|
||||||
|
*/
|
||||||
|
void _net_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Does what ever preparations are needed to check the packets sent
|
||||||
|
*/
|
||||||
|
void _prepare_send_checks(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Injects a received IPv6 packet into the stack
|
||||||
|
*
|
||||||
|
* @param[in] src The source address of the IPv6 packet
|
||||||
|
* @param[in] dst The destination address of the IPv6 packet
|
||||||
|
* @param[in] proto The next header field of the IPv6 packet
|
||||||
|
* @param[in] data The payload of the IPv6 packet
|
||||||
|
* @param[in] data_len The payload length of the IPv6 packet
|
||||||
|
* @param[in] netif The interface the packet came over
|
||||||
|
*
|
||||||
|
* @return true, if packet was successfully injected
|
||||||
|
* @return false, if an error occured during injection
|
||||||
|
*/
|
||||||
|
bool _inject_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||||
|
uint8_t proto, void *data, size_t data_len,
|
||||||
|
uint16_t netif);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks networking state (e.g. packet buffer state)
|
||||||
|
*
|
||||||
|
* @return true, if networking component is still in valid state
|
||||||
|
* @return false, if networking component is in an invalid state
|
||||||
|
*/
|
||||||
|
bool _check_net(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if a IPv6 packet was sent by the networking component
|
||||||
|
*
|
||||||
|
* @param[in] src Expected source address of the IPv6 packet
|
||||||
|
* @param[in] dst Expected destination address of the IPv6 packet
|
||||||
|
* @param[in] proto Expected next header field of the IPv6 packet
|
||||||
|
* @param[in] data Expected payload of the IPv6 packet
|
||||||
|
* @param[in] data_len Expected payload length of the IPv6 packet
|
||||||
|
* @param[in] netif Expected interface the packet is supposed to
|
||||||
|
* be send over
|
||||||
|
*
|
||||||
|
* @return true, if all parameters match as expected
|
||||||
|
* @return false, if not.
|
||||||
|
*/
|
||||||
|
bool _check_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||||
|
uint8_t proto, void *data, size_t data_len, uint16_t netif);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* STACK_H_ */
|
||||||
|
/** @} */
|
||||||
70
tests/gnrc_sock_ip/tests/01-run.py
Executable file
70
tests/gnrc_sock_ip/tests/01-run.py
Executable file
@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de>
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
sys.path.append(os.path.join(os.environ['RIOTBASE'], 'dist/tools/testrunner'))
|
||||||
|
import testrunner
|
||||||
|
|
||||||
|
class InvalidTimeout(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def testfunc(child):
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_create__EAFNOSUPPORT()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_create__EINVAL_addr()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_create__EINVAL_netif()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_create__no_endpoints()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_create__only_local()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_create__only_local_reuse_ep()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_create__only_remote()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_create__full()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_recv__EADDRNOTAVAIL()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_recv__ENOBUFS()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_recv__EPROTO()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_recv__ETIMEDOUT()")
|
||||||
|
child.match # get to ensure program reached that point
|
||||||
|
start = datetime.now()
|
||||||
|
child.expect_exact(u" * Calling sock_ip_recv()")
|
||||||
|
child.expect(u" \\* \\(timed out with timeout (\\d+)\\)")
|
||||||
|
exp_diff = int(child.match.group(1))
|
||||||
|
stop = datetime.now()
|
||||||
|
diff = (stop - start)
|
||||||
|
diff = (diff.seconds * 1000000) + diff.microseconds
|
||||||
|
# fail within 5% of expected
|
||||||
|
if diff > (exp_diff + (exp_diff * 0.05)) or \
|
||||||
|
diff < (exp_diff - (exp_diff * 0.05)):
|
||||||
|
raise InvalidTimeout("Invalid timeout %d (expected %d)" % (diff, exp_diff));
|
||||||
|
else:
|
||||||
|
print("Timed out correctly: %d (expected %d)" % (diff, exp_diff))
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_recv__socketed()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_recv__socketed_with_remote()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_recv__unsocketed()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_recv__unsocketed_with_remote()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_recv__with_timeout()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__EAFNOSUPPORT()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__EINVAL_addr()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__EINVAL_netif()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__ENOTCONN()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__socketed_no_local_no_netif()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__socketed_no_netif()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__socketed_no_local()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__socketed()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__socketed_other_remote()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__unsocketed_no_local_no_netif()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__unsocketed_no_netif()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__unsocketed_no_local()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__unsocketed()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__no_sock_no_netif()")
|
||||||
|
child.expect_exact(u"Calling test_sock_ip_send__no_sock()")
|
||||||
|
child.expect_exact(u"ALL TESTS SUCCESSFUL")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(testrunner.run(testfunc))
|
||||||
21
tests/gnrc_sock_udp/Makefile
Normal file
21
tests/gnrc_sock_udp/Makefile
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
APPLICATION = gnrc_sock_udp
|
||||||
|
|
||||||
|
BOARD ?= native
|
||||||
|
|
||||||
|
RIOTBASE ?= $(CURDIR)/../..
|
||||||
|
|
||||||
|
USEMODULE += gnrc_sock_check_reuse
|
||||||
|
USEMODULE += gnrc_sock_udp
|
||||||
|
USEMODULE += gnrc_ipv6
|
||||||
|
USEMODULE += ps
|
||||||
|
|
||||||
|
CFLAGS += -DDEVELHELP
|
||||||
|
CFLAGS += -DGNRC_PKTBUF_SIZE=200
|
||||||
|
CFLAGS += -DTEST_SUITES
|
||||||
|
|
||||||
|
QUIET ?= 1
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.include
|
||||||
|
|
||||||
|
test:
|
||||||
|
./tests/01-run.py
|
||||||
44
tests/gnrc_sock_udp/constants.h
Normal file
44
tests/gnrc_sock_udp/constants.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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
|
||||||
|
* @ingroup
|
||||||
|
* @brief
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
#ifndef CONSTANTS_H_
|
||||||
|
#define CONSTANTS_H_
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _TEST_PORT_LOCAL (0x2c94)
|
||||||
|
#define _TEST_PORT_REMOTE (0xa615)
|
||||||
|
#define _TEST_NETIF (31)
|
||||||
|
#define _TEST_TIMEOUT (1000000U)
|
||||||
|
#define _TEST_ADDR_LOCAL { 0x7f, 0xc4, 0x11, 0x5a, 0xe6, 0x91, 0x8d, 0x5d, \
|
||||||
|
0x8c, 0xd1, 0x47, 0x07, 0xb7, 0x6f, 0x9b, 0x48 }
|
||||||
|
#define _TEST_ADDR_REMOTE { 0xe8, 0xb3, 0xb2, 0xe6, 0x70, 0xd4, 0x55, 0xba, \
|
||||||
|
0x93, 0xcf, 0x11, 0xe1, 0x72, 0x44, 0xc5, 0x9d }
|
||||||
|
#define _TEST_ADDR_WRONG { 0x2a, 0xce, 0x5d, 0x4e, 0xc8, 0xbf, 0x86, 0xf7, \
|
||||||
|
0x85, 0x49, 0xb4, 0x19, 0xf2, 0x28, 0xde, 0x9b }
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CONSTANTS_H_ */
|
||||||
|
/** @} */
|
||||||
705
tests/gnrc_sock_udp/main.c
Normal file
705
tests/gnrc_sock_udp/main.c
Normal file
@ -0,0 +1,705 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup tests
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Test for UDP socks
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "net/af.h"
|
||||||
|
#include "net/sock/udp.h"
|
||||||
|
#include "xtimer.h"
|
||||||
|
|
||||||
|
#include "constants.h"
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
|
#define _TEST_BUFFER_SIZE (128)
|
||||||
|
|
||||||
|
static uint8_t _test_buffer[_TEST_BUFFER_SIZE];
|
||||||
|
static sock_udp_t _sock, _sock2;
|
||||||
|
|
||||||
|
#define CALL(fn) puts("Calling " # fn); fn; tear_down()
|
||||||
|
|
||||||
|
static void tear_down(void)
|
||||||
|
{
|
||||||
|
sock_udp_close(&_sock);
|
||||||
|
memset(&_sock, 0, sizeof(_sock));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MODULE_GNRC_SOCK_CHECK_REUSE
|
||||||
|
static void test_sock_udp_create__EADDRINUSE(void)
|
||||||
|
{
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, NULL, 0));
|
||||||
|
assert(-EADDRINUSE == sock_udp_create(&_sock2, &local, NULL, 0));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void test_sock_udp_create__EAFNOSUPPORT(void)
|
||||||
|
{
|
||||||
|
/* port may not be NULL according to doc */
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_UNSPEC,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
/* port may not be NULL according to doc */
|
||||||
|
static const sock_udp_ep_t remote = { .family = AF_UNSPEC,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(-EAFNOSUPPORT == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(-EAFNOSUPPORT == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_create__EINVAL_addr(void)
|
||||||
|
{
|
||||||
|
/* port may not be NULL according to doc */
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
/* port may not be NULL according to doc */
|
||||||
|
static const sock_udp_ep_t remote = { .family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(-EINVAL == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_create__EINVAL_netif(void)
|
||||||
|
{
|
||||||
|
/* port may not be NULL according to doc */
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
/* port may not be NULL according to doc */
|
||||||
|
static const sock_udp_ep_t remote = { .family = AF_INET6,
|
||||||
|
.netif = (_TEST_NETIF + 1),
|
||||||
|
.port = _TEST_PORT_REMOTE,
|
||||||
|
.addr = { .ipv6 = _TEST_ADDR_REMOTE } };
|
||||||
|
|
||||||
|
assert(-EINVAL == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_create__no_endpoints(void)
|
||||||
|
{
|
||||||
|
sock_udp_ep_t ep;
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(-EADDRNOTAVAIL == sock_udp_get_local(&_sock, &ep));
|
||||||
|
assert(-ENOTCONN == sock_udp_get_remote(&_sock, &ep));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_create__only_local(void)
|
||||||
|
{
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
sock_udp_ep_t ep;
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(0 == sock_udp_get_local(&_sock, &ep));
|
||||||
|
assert(AF_INET6 == ep.family);
|
||||||
|
assert(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6,
|
||||||
|
sizeof(ipv6_addr_t)) == 0);
|
||||||
|
assert(SOCK_ADDR_ANY_NETIF == ep.netif);
|
||||||
|
assert(_TEST_PORT_LOCAL == ep.port);
|
||||||
|
assert(-ENOTCONN == sock_udp_get_remote(&_sock, &ep));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_create__only_local_reuse_ep(void)
|
||||||
|
{
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
sock_udp_ep_t ep, ep2;
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(0 == sock_udp_create(&_sock2, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(0 == sock_udp_get_local(&_sock, &ep));
|
||||||
|
assert(0 == sock_udp_get_local(&_sock2, &ep2));
|
||||||
|
assert(AF_INET6 == ep.family);
|
||||||
|
assert(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6,
|
||||||
|
sizeof(ipv6_addr_t)) == 0);
|
||||||
|
assert(SOCK_ADDR_ANY_NETIF == ep.netif);
|
||||||
|
assert(_TEST_PORT_LOCAL == ep.port);
|
||||||
|
assert(-ENOTCONN == sock_udp_get_remote(&_sock, &ep));
|
||||||
|
assert(AF_INET6 == ep2.family);
|
||||||
|
assert(memcmp(&ipv6_addr_unspecified, &ep2.addr.ipv6,
|
||||||
|
sizeof(ipv6_addr_t)) == 0);
|
||||||
|
assert(SOCK_ADDR_ANY_NETIF == ep2.netif);
|
||||||
|
assert(_TEST_PORT_LOCAL == ep2.port);
|
||||||
|
assert(-ENOTCONN == sock_udp_get_remote(&_sock, &ep2));
|
||||||
|
sock_udp_close(&_sock2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_create__only_remote(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t remote_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_udp_ep_t remote = { .family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE,
|
||||||
|
.addr = { .ipv6 = _TEST_ADDR_REMOTE } };
|
||||||
|
sock_udp_ep_t ep;
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(-EADDRNOTAVAIL == sock_udp_get_local(&_sock, &ep));
|
||||||
|
assert(0 == sock_udp_get_remote(&_sock, &ep));
|
||||||
|
assert(AF_INET6 == ep.family);
|
||||||
|
assert(memcmp(&remote_addr, &ep.addr.ipv6, sizeof(ipv6_addr_t)) == 0);
|
||||||
|
assert(SOCK_ADDR_ANY_NETIF == ep.netif);
|
||||||
|
assert(_TEST_PORT_REMOTE == ep.port);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_create__full(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t remote_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
static const sock_udp_ep_t remote = { .family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE,
|
||||||
|
.addr = { .ipv6 = _TEST_ADDR_REMOTE } };
|
||||||
|
sock_udp_ep_t ep;
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(0 == sock_udp_get_local(&_sock, &ep));
|
||||||
|
assert(AF_INET6 == ep.family);
|
||||||
|
assert(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6,
|
||||||
|
sizeof(ipv6_addr_t)) == 0);
|
||||||
|
assert(_TEST_NETIF == ep.netif);
|
||||||
|
assert(_TEST_PORT_LOCAL == ep.port);
|
||||||
|
assert(0 == sock_udp_get_remote(&_sock, &ep));
|
||||||
|
assert(AF_INET6 == ep.family);
|
||||||
|
assert(memcmp(&remote_addr, &ep.addr.ipv6, sizeof(ipv6_addr_t)) == 0);
|
||||||
|
assert(SOCK_ADDR_ANY_NETIF == ep.netif);
|
||||||
|
assert(_TEST_PORT_REMOTE == ep.port);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_recv__EADDRNOTAVAIL(void)
|
||||||
|
{
|
||||||
|
assert(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
|
||||||
|
assert(-EADDRNOTAVAIL == sock_udp_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer),
|
||||||
|
SOCK_NO_TIMEOUT, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_recv__EAGAIN(void)
|
||||||
|
{
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
|
||||||
|
assert(-EAGAIN == sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer),
|
||||||
|
0, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_recv__ENOBUFS(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
|
||||||
|
_TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"), _TEST_NETIF));
|
||||||
|
assert(-ENOBUFS == sock_udp_recv(&_sock, _test_buffer, 2, SOCK_NO_TIMEOUT,
|
||||||
|
NULL));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_recv__EPROTO(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_WRONG };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
|
||||||
|
_TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_NETIF));
|
||||||
|
assert(-EPROTO == sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer),
|
||||||
|
SOCK_NO_TIMEOUT, NULL));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_recv__ETIMEDOUT(void)
|
||||||
|
{
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
|
||||||
|
puts(" * Calling sock_udp_recv()");
|
||||||
|
assert(-ETIMEDOUT == sock_udp_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer), _TEST_TIMEOUT,
|
||||||
|
NULL));
|
||||||
|
printf(" * (timed out with timeout %lu)\n", (long unsigned)_TEST_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_recv__socketed(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
|
||||||
|
_TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_NETIF));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer),
|
||||||
|
SOCK_NO_TIMEOUT, NULL));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_recv__socketed_with_remote(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
sock_udp_ep_t result;
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
|
||||||
|
_TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_NETIF));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer),
|
||||||
|
SOCK_NO_TIMEOUT, &result));
|
||||||
|
assert(AF_INET6 == result.family);
|
||||||
|
assert(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
|
||||||
|
assert(_TEST_PORT_REMOTE == result.port);
|
||||||
|
assert(_TEST_NETIF == result.netif);
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_recv__unsocketed(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
|
||||||
|
_TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_NETIF));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer),
|
||||||
|
SOCK_NO_TIMEOUT, NULL));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_recv__unsocketed_with_remote(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
sock_udp_ep_t result;
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
|
||||||
|
_TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_NETIF));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer),
|
||||||
|
SOCK_NO_TIMEOUT, &result));
|
||||||
|
assert(AF_INET6 == result.family);
|
||||||
|
assert(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
|
||||||
|
assert(_TEST_PORT_REMOTE == result.port);
|
||||||
|
assert(_TEST_NETIF == result.netif);
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_recv__with_timeout(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
sock_udp_ep_t result;
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
|
||||||
|
_TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_NETIF));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer), _TEST_TIMEOUT,
|
||||||
|
&result));
|
||||||
|
assert(AF_INET6 == result.family);
|
||||||
|
assert(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
|
||||||
|
assert(_TEST_PORT_REMOTE == result.port);
|
||||||
|
assert(_TEST_NETIF == result.netif);
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_recv__non_blocking(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const sock_udp_ep_t local = { .family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
sock_udp_ep_t result;
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
|
||||||
|
_TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_NETIF));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_recv(&_sock, _test_buffer,
|
||||||
|
sizeof(_test_buffer), 0, &result));
|
||||||
|
assert(AF_INET6 == result.family);
|
||||||
|
assert(memcmp(&result.addr, &src_addr, sizeof(result.addr)) == 0);
|
||||||
|
assert(_TEST_PORT_REMOTE == result.port);
|
||||||
|
assert(_TEST_NETIF == result.netif);
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__EAFNOSUPPORT(void)
|
||||||
|
{
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(-EAFNOSUPPORT == sock_udp_send(NULL, "ABCD", sizeof("ABCD"),
|
||||||
|
&remote));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__EINVAL_addr(void)
|
||||||
|
{
|
||||||
|
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE,
|
||||||
|
.netif = _TEST_NETIF };
|
||||||
|
static const sock_udp_ep_t remote = { .family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE,
|
||||||
|
.netif = _TEST_NETIF };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(-EINVAL == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), &remote));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__EINVAL_netif(void)
|
||||||
|
{
|
||||||
|
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE,
|
||||||
|
.netif = _TEST_NETIF };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE,
|
||||||
|
.netif = _TEST_NETIF + 1 };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(-EINVAL == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), &remote));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__EINVAL_port(void)
|
||||||
|
{
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6 };
|
||||||
|
|
||||||
|
assert(-EINVAL == sock_udp_send(NULL, "ABCD", sizeof("ABCD"), &remote));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__ENOTCONN(void)
|
||||||
|
{
|
||||||
|
assert(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(-ENOTCONN == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"), NULL));
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__socketed_no_local_no_netif(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
NULL));
|
||||||
|
assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0,
|
||||||
|
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
|
||||||
|
SOCK_ADDR_ANY_NETIF, true));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__socketed_no_netif(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
NULL));
|
||||||
|
assert(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL,
|
||||||
|
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
|
||||||
|
SOCK_ADDR_ANY_NETIF, false));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__socketed_no_local(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
NULL));
|
||||||
|
assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0,
|
||||||
|
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), _TEST_NETIF,
|
||||||
|
true));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__socketed(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
NULL));
|
||||||
|
assert(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL,
|
||||||
|
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_NETIF, false));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__socketed_other_remote(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
static const sock_udp_ep_t sock_remote = { .addr = { .ipv6 = _TEST_ADDR_WRONG },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE + _TEST_PORT_LOCAL };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, &sock_remote, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
&remote));
|
||||||
|
assert(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL,
|
||||||
|
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_NETIF, false));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__unsocketed_no_local_no_netif(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
&remote));
|
||||||
|
assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0,
|
||||||
|
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
|
||||||
|
SOCK_ADDR_ANY_NETIF, true));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__unsocketed_no_netif(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
&remote));
|
||||||
|
assert(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL,
|
||||||
|
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
|
||||||
|
SOCK_ADDR_ANY_NETIF, false));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__unsocketed_no_local(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
&remote));
|
||||||
|
assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0,
|
||||||
|
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"), _TEST_NETIF,
|
||||||
|
true));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__unsocketed(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_LOCAL };
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_udp_ep_t local = { .addr = { .ipv6 = _TEST_ADDR_LOCAL },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF,
|
||||||
|
.port = _TEST_PORT_LOCAL };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
|
||||||
|
assert(sizeof("ABCD") == sock_udp_send(&_sock, "ABCD", sizeof("ABCD"),
|
||||||
|
&remote));
|
||||||
|
assert(_check_packet(&src_addr, &dst_addr, _TEST_PORT_LOCAL,
|
||||||
|
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_NETIF, false));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__no_sock_no_netif(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(sizeof("ABCD") == sock_udp_send(NULL, "ABCD", sizeof("ABCD"),
|
||||||
|
&remote));
|
||||||
|
assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0,
|
||||||
|
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
|
||||||
|
SOCK_ADDR_ANY_NETIF, true));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_sock_udp_send__no_sock(void)
|
||||||
|
{
|
||||||
|
static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_REMOTE };
|
||||||
|
static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
|
||||||
|
.family = AF_INET6,
|
||||||
|
.netif = _TEST_NETIF,
|
||||||
|
.port = _TEST_PORT_REMOTE };
|
||||||
|
|
||||||
|
assert(sizeof("ABCD") == sock_udp_send(NULL, "ABCD", sizeof("ABCD"),
|
||||||
|
&remote));
|
||||||
|
assert(_check_packet(&ipv6_addr_unspecified, &dst_addr, 0,
|
||||||
|
_TEST_PORT_REMOTE, "ABCD", sizeof("ABCD"),
|
||||||
|
_TEST_NETIF, true));
|
||||||
|
xtimer_usleep(1000); /* let GNRC stack finish */
|
||||||
|
assert(_check_net());
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
_net_init();
|
||||||
|
tear_down();
|
||||||
|
#ifdef MODULE_GNRC_SOCK_CHECK_REUSE
|
||||||
|
CALL(test_sock_udp_create__EADDRINUSE());
|
||||||
|
#endif
|
||||||
|
CALL(test_sock_udp_create__EAFNOSUPPORT());
|
||||||
|
CALL(test_sock_udp_create__EINVAL_addr());
|
||||||
|
CALL(test_sock_udp_create__EINVAL_netif());
|
||||||
|
CALL(test_sock_udp_create__no_endpoints());
|
||||||
|
CALL(test_sock_udp_create__only_local());
|
||||||
|
CALL(test_sock_udp_create__only_local_reuse_ep());
|
||||||
|
CALL(test_sock_udp_create__only_remote());
|
||||||
|
CALL(test_sock_udp_create__full());
|
||||||
|
/* sock_udp_close() is tested in tear_down() */
|
||||||
|
/* sock_udp_get_local() is tested in sock_udp_create() tests */
|
||||||
|
/* sock_udp_get_remote() is tested in sock_udp_create() tests */
|
||||||
|
CALL(test_sock_udp_recv__EADDRNOTAVAIL());
|
||||||
|
CALL(test_sock_udp_recv__EAGAIN());
|
||||||
|
CALL(test_sock_udp_recv__ENOBUFS());
|
||||||
|
CALL(test_sock_udp_recv__EPROTO());
|
||||||
|
CALL(test_sock_udp_recv__ETIMEDOUT());
|
||||||
|
CALL(test_sock_udp_recv__socketed());
|
||||||
|
CALL(test_sock_udp_recv__socketed_with_remote());
|
||||||
|
CALL(test_sock_udp_recv__unsocketed());
|
||||||
|
CALL(test_sock_udp_recv__unsocketed_with_remote());
|
||||||
|
CALL(test_sock_udp_recv__with_timeout());
|
||||||
|
CALL(test_sock_udp_recv__non_blocking());
|
||||||
|
_prepare_send_checks();
|
||||||
|
CALL(test_sock_udp_send__EAFNOSUPPORT());
|
||||||
|
CALL(test_sock_udp_send__EINVAL_addr());
|
||||||
|
CALL(test_sock_udp_send__EINVAL_netif());
|
||||||
|
CALL(test_sock_udp_send__EINVAL_port());
|
||||||
|
CALL(test_sock_udp_send__ENOTCONN());
|
||||||
|
CALL(test_sock_udp_send__socketed_no_local_no_netif());
|
||||||
|
CALL(test_sock_udp_send__socketed_no_netif());
|
||||||
|
CALL(test_sock_udp_send__socketed_no_local());
|
||||||
|
CALL(test_sock_udp_send__socketed());
|
||||||
|
CALL(test_sock_udp_send__socketed_other_remote());
|
||||||
|
CALL(test_sock_udp_send__unsocketed_no_local_no_netif());
|
||||||
|
CALL(test_sock_udp_send__unsocketed_no_netif());
|
||||||
|
CALL(test_sock_udp_send__unsocketed_no_local());
|
||||||
|
CALL(test_sock_udp_send__unsocketed());
|
||||||
|
CALL(test_sock_udp_send__no_sock_no_netif());
|
||||||
|
CALL(test_sock_udp_send__no_sock());
|
||||||
|
|
||||||
|
puts("ALL TESTS SUCCESSFUL");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
172
tests/gnrc_sock_udp/stack.c
Normal file
172
tests/gnrc_sock_udp/stack.c
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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 <mlenders@inf.fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "msg.h"
|
||||||
|
#include "net/gnrc/ipv6.h"
|
||||||
|
#include "net/gnrc/netif/hdr.h"
|
||||||
|
#include "net/gnrc/netreg.h"
|
||||||
|
#include "net/gnrc/udp.h"
|
||||||
|
#include "net/sock.h"
|
||||||
|
#include "sched.h"
|
||||||
|
|
||||||
|
#include "stack.h"
|
||||||
|
|
||||||
|
#define _MSG_QUEUE_SIZE (4)
|
||||||
|
|
||||||
|
static msg_t _msg_queue[_MSG_QUEUE_SIZE];
|
||||||
|
static gnrc_netreg_entry_t _udp_handler;
|
||||||
|
|
||||||
|
void _net_init(void)
|
||||||
|
{
|
||||||
|
msg_init_queue(_msg_queue, _MSG_QUEUE_SIZE);
|
||||||
|
gnrc_netreg_entry_init_pid(&_udp_handler, GNRC_NETREG_DEMUX_CTX_ALL,
|
||||||
|
sched_active_pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _prepare_send_checks(void)
|
||||||
|
{
|
||||||
|
gnrc_netreg_register(GNRC_NETTYPE_UDP, &_udp_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gnrc_pktsnip_t *_build_udp_packet(const ipv6_addr_t *src,
|
||||||
|
const ipv6_addr_t *dst,
|
||||||
|
uint16_t src_port, uint16_t dst_port,
|
||||||
|
void *data, size_t data_len,
|
||||||
|
uint16_t netif)
|
||||||
|
{
|
||||||
|
gnrc_pktsnip_t *netif_hdr, *ipv6, *udp;
|
||||||
|
udp_hdr_t *udp_hdr;
|
||||||
|
ipv6_hdr_t *ipv6_hdr;
|
||||||
|
uint16_t csum = 0;
|
||||||
|
|
||||||
|
if ((netif > INT16_MAX) || ((sizeof(udp_hdr_t) + data_len) > UINT16_MAX)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
udp = gnrc_pktbuf_add(NULL, NULL, sizeof(udp_hdr_t) + data_len,
|
||||||
|
GNRC_NETTYPE_UNDEF);
|
||||||
|
if (udp == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
udp_hdr = udp->data;
|
||||||
|
udp_hdr->src_port = byteorder_htons(src_port);
|
||||||
|
udp_hdr->dst_port = byteorder_htons(dst_port);
|
||||||
|
udp_hdr->length = byteorder_htons((uint16_t)udp->size);
|
||||||
|
udp_hdr->checksum.u16 = 0;
|
||||||
|
memcpy(udp_hdr + 1, data, data_len);
|
||||||
|
csum = inet_csum(csum, (uint8_t *)udp->data, udp->size);
|
||||||
|
ipv6 = gnrc_ipv6_hdr_build(NULL, src, dst);
|
||||||
|
if (ipv6 == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ipv6_hdr = ipv6->data;
|
||||||
|
ipv6_hdr->len = byteorder_htons((uint16_t)udp->size);
|
||||||
|
ipv6_hdr->nh = PROTNUM_UDP;
|
||||||
|
ipv6_hdr->hl = 64;
|
||||||
|
csum = ipv6_hdr_inet_csum(csum, ipv6_hdr, PROTNUM_UDP, (uint16_t)udp->size);
|
||||||
|
if (csum == 0xffff) {
|
||||||
|
udp_hdr->checksum = byteorder_htons(csum);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
udp_hdr->checksum = byteorder_htons(~csum);
|
||||||
|
}
|
||||||
|
LL_APPEND(udp, ipv6);
|
||||||
|
netif_hdr = gnrc_netif_hdr_build(NULL, 0, NULL, 0);
|
||||||
|
if (netif_hdr == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
((gnrc_netif_hdr_t *)netif_hdr->data)->if_pid = (kernel_pid_t)netif;
|
||||||
|
LL_APPEND(udp, netif_hdr);
|
||||||
|
return udp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool _inject_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||||
|
uint16_t src_port, uint16_t dst_port,
|
||||||
|
void *data, size_t data_len, uint16_t netif)
|
||||||
|
{
|
||||||
|
gnrc_pktsnip_t *pkt = _build_udp_packet(src, dst, src_port, dst_port,
|
||||||
|
data, data_len, netif);
|
||||||
|
|
||||||
|
if (pkt == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (gnrc_netapi_dispatch_receive(GNRC_NETTYPE_UDP,
|
||||||
|
GNRC_NETREG_DEMUX_CTX_ALL, pkt) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _check_net(void)
|
||||||
|
{
|
||||||
|
return (gnrc_pktbuf_is_sane() && gnrc_pktbuf_is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool _res(gnrc_pktsnip_t *pkt, bool res)
|
||||||
|
{
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _check_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||||
|
uint16_t src_port, uint16_t dst_port,
|
||||||
|
void *data, size_t data_len, uint16_t iface,
|
||||||
|
bool random_src_port)
|
||||||
|
{
|
||||||
|
gnrc_pktsnip_t *pkt, *ipv6, *udp;
|
||||||
|
ipv6_hdr_t *ipv6_hdr;
|
||||||
|
udp_hdr_t *udp_hdr;
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
msg_receive(&msg);
|
||||||
|
if (msg.type != GNRC_NETAPI_MSG_TYPE_SND) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pkt = msg.content.ptr;
|
||||||
|
if (iface != SOCK_ADDR_ANY_NETIF) {
|
||||||
|
gnrc_netif_hdr_t *netif_hdr;
|
||||||
|
|
||||||
|
if (pkt->type != GNRC_NETTYPE_NETIF) {
|
||||||
|
return _res(pkt, false);
|
||||||
|
}
|
||||||
|
netif_hdr = pkt->data;
|
||||||
|
if (netif_hdr->if_pid != iface) {
|
||||||
|
return _res(pkt, false);
|
||||||
|
}
|
||||||
|
ipv6 = pkt->next;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ipv6 = pkt;
|
||||||
|
}
|
||||||
|
if (ipv6->type != GNRC_NETTYPE_IPV6) {
|
||||||
|
return _res(pkt, false);
|
||||||
|
}
|
||||||
|
ipv6_hdr = ipv6->data;
|
||||||
|
udp = gnrc_pktsnip_search_type(ipv6, GNRC_NETTYPE_UDP);
|
||||||
|
if (udp == NULL) {
|
||||||
|
return _res(pkt, false);
|
||||||
|
}
|
||||||
|
udp_hdr = udp->data;
|
||||||
|
return _res(pkt, (memcmp(src, &ipv6_hdr->src, sizeof(ipv6_addr_t)) == 0) &&
|
||||||
|
(memcmp(dst, &ipv6_hdr->dst, sizeof(ipv6_addr_t)) == 0) &&
|
||||||
|
(ipv6_hdr->nh == PROTNUM_UDP) &&
|
||||||
|
(random_src_port || (src_port == byteorder_ntohs(udp_hdr->src_port))) &&
|
||||||
|
(dst_port == byteorder_ntohs(udp_hdr->dst_port)) &&
|
||||||
|
(udp->next != NULL) &&
|
||||||
|
(data_len == udp->next->size) &&
|
||||||
|
(memcmp(data, udp->next->data, data_len) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @} */
|
||||||
95
tests/gnrc_sock_udp/stack.h
Normal file
95
tests/gnrc_sock_udp/stack.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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
|
||||||
|
* @ingroup
|
||||||
|
* @brief
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||||
|
*/
|
||||||
|
#ifndef STACK_H_
|
||||||
|
#define STACK_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "net/ipv6/addr.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes networking for tests
|
||||||
|
*/
|
||||||
|
void _net_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Does what ever preparations are needed to check the packets sent
|
||||||
|
*/
|
||||||
|
void _prepare_send_checks(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Injects a received UDP packet into the stack
|
||||||
|
*
|
||||||
|
* @param[in] src The source address of the UDP packet
|
||||||
|
* @param[in] dst The destination address of the UDP packet
|
||||||
|
* @param[in] src_port The source port of the UDP packet
|
||||||
|
* @param[in] dst_port The destination port of the UDP packet
|
||||||
|
* @param[in] data The payload of the UDP packet
|
||||||
|
* @param[in] data_len The payload length of the UDP packet
|
||||||
|
* @param[in] netif The interface the packet came over
|
||||||
|
*
|
||||||
|
* @return true, if packet was successfully injected
|
||||||
|
* @return false, if an error occured during injection
|
||||||
|
*/
|
||||||
|
bool _inject_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||||
|
uint16_t src_port, uint16_t dst_port,
|
||||||
|
void *data, size_t data_len, uint16_t netif);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks networking state (e.g. packet buffer state)
|
||||||
|
*
|
||||||
|
* @return true, if networking component is still in valid state
|
||||||
|
* @return false, if networking component is in an invalid state
|
||||||
|
*/
|
||||||
|
bool _check_net(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if a UDP packet was sent by the networking component
|
||||||
|
*
|
||||||
|
* @param[in] src Expected source address of the UDP packet
|
||||||
|
* @param[in] dst Expected destination address of the UDP packet
|
||||||
|
* @param[in] src_port Expected source port of the UDP packet
|
||||||
|
* @param[in] dst_port Expected destination port of the UDP packet
|
||||||
|
* @param[in] data Expected payload of the UDP packet
|
||||||
|
* @param[in] data_len Expected payload length of the UDP packet
|
||||||
|
* @param[in] netif Expected interface the packet is supposed to
|
||||||
|
* be send over
|
||||||
|
* @param[in] random_src_port Do not check source port, it might be random
|
||||||
|
*
|
||||||
|
* @return true, if all parameters match as expected
|
||||||
|
* @return false, if not.
|
||||||
|
*/
|
||||||
|
bool _check_packet(const ipv6_addr_t *src, const ipv6_addr_t *dst,
|
||||||
|
uint16_t src_port, uint16_t dst_port,
|
||||||
|
void *data, size_t data_len, uint16_t netif,
|
||||||
|
bool random_src_port);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* STACK_H_ */
|
||||||
|
/** @} */
|
||||||
74
tests/gnrc_sock_udp/tests/01-run.py
Executable file
74
tests/gnrc_sock_udp/tests/01-run.py
Executable file
@ -0,0 +1,74 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de>
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
sys.path.append(os.path.join(os.environ['RIOTBASE'], 'dist/tools/testrunner'))
|
||||||
|
import testrunner
|
||||||
|
|
||||||
|
class InvalidTimeout(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def testfunc(child):
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_create__EADDRINUSE()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_create__EAFNOSUPPORT()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_create__EINVAL_addr()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_create__EINVAL_netif()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_create__no_endpoints()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_create__only_local()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_create__only_local_reuse_ep()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_create__only_remote()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_create__full()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_recv__EADDRNOTAVAIL()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_recv__EAGAIN()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_recv__ENOBUFS()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_recv__EPROTO()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_recv__ETIMEDOUT()")
|
||||||
|
child.match # get to ensure program reached that point
|
||||||
|
start = datetime.now()
|
||||||
|
child.expect_exact(u" * Calling sock_udp_recv()")
|
||||||
|
child.expect(u" \\* \\(timed out with timeout (\\d+)\\)")
|
||||||
|
exp_diff = int(child.match.group(1))
|
||||||
|
stop = datetime.now()
|
||||||
|
diff = (stop - start)
|
||||||
|
diff = (diff.seconds * 1000000) + diff.microseconds
|
||||||
|
# fail within 5% of expected
|
||||||
|
if diff > (exp_diff + (exp_diff * 0.05)) or \
|
||||||
|
diff < (exp_diff - (exp_diff * 0.05)):
|
||||||
|
raise InvalidTimeout("Invalid timeout %d (expected %d)" % (diff, exp_diff));
|
||||||
|
else:
|
||||||
|
print("Timed out correctly: %d (expected %d)" % (diff, exp_diff))
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_recv__socketed()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_recv__socketed_with_remote()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_recv__unsocketed()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_recv__unsocketed_with_remote()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_recv__with_timeout()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_recv__non_blocking()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__EAFNOSUPPORT()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__EINVAL_addr()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__EINVAL_netif()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__EINVAL_port()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__ENOTCONN()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__socketed_no_local_no_netif()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__socketed_no_netif()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__socketed_no_local()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__socketed()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__socketed_other_remote()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__unsocketed_no_local_no_netif()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__unsocketed_no_netif()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__unsocketed_no_local()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__unsocketed()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__no_sock_no_netif()")
|
||||||
|
child.expect_exact(u"Calling test_sock_udp_send__no_sock()")
|
||||||
|
child.expect_exact(u"ALL TESTS SUCCESSFUL")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(testrunner.run(testfunc))
|
||||||
Loading…
x
Reference in New Issue
Block a user