emb6: provide sock_udp port
This commit is contained in:
parent
032c3b6883
commit
20f6ab6daf
|
@ -2,6 +2,11 @@ ifneq (,$(filter emb6_conn_udp,$(USEMODULE)))
|
|||
USEMODULE += emb6_sock
|
||||
endif
|
||||
|
||||
ifneq (,$(filter emb6_sock_%,$(USEMODULE)))
|
||||
USEMODULE += core_mbox
|
||||
USEMODULE += emb6_sock
|
||||
endif
|
||||
|
||||
ifneq (,$(filter emb6_%,$(USEMODULE)))
|
||||
USEMODULE += emb6
|
||||
endif
|
||||
|
@ -19,4 +24,5 @@ ifneq (,$(filter emb6,$(USEMODULE)))
|
|||
USEMODULE += emb6_rpl
|
||||
USEMODULE += emb6_sicslowpan
|
||||
USEMODULE += emb6_utils
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
|
|
@ -65,6 +65,11 @@ ifneq (,$(filter emb6_sock,$(USEMODULE)))
|
|||
INCLUDES += -I$(EMB6_DIR)/emb6/inc/tport
|
||||
endif
|
||||
|
||||
ifneq (,$(filter emb6_sock_udp,$(USEMODULE)))
|
||||
DIRS += $(EMB6_CONTRIB)/sock/udp
|
||||
CFLAGS += -DSOCK_HAS_IPV6
|
||||
endif
|
||||
|
||||
ifneq (,$(filter emb6_utils,$(USEMODULE)))
|
||||
DIRS += $(EMB6_DIR)/utils/src
|
||||
INCLUDES += -I$(EMB6_DIR)/utils/inc
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
MODULE := emb6_sock_udp
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
* 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 <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "evproc.h"
|
||||
#include "msg.h"
|
||||
#include "mutex.h"
|
||||
#include "net/af.h"
|
||||
#include "net/sock/udp.h"
|
||||
#include "net/ipv6/hdr.h"
|
||||
#include "sched.h"
|
||||
#include "uip.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
#define _MSG_TYPE_CLOSE (0x4123)
|
||||
#define _MSG_TYPE_TIMEOUT (0x4124)
|
||||
#define _MSG_TYPE_RCV (0x4125)
|
||||
|
||||
/* struct to describe a sendto command for emb6 thread */
|
||||
typedef struct {
|
||||
mutex_t block;
|
||||
struct udp_socket *sock;
|
||||
const sock_udp_ep_t *remote;
|
||||
int res;
|
||||
const void *data;
|
||||
size_t len;
|
||||
} _send_cmd_t;
|
||||
|
||||
extern uint16_t uip_slen;
|
||||
|
||||
static bool send_registered = false;
|
||||
|
||||
static void _timeout_callback(void *arg);
|
||||
static void _input_callback(struct udp_socket *c, void *ptr,
|
||||
const uip_ipaddr_t *src_addr, uint16_t src_port,
|
||||
const uip_ipaddr_t *dst_addr, uint16_t dst_port,
|
||||
const uint8_t *data, uint16_t datalen);
|
||||
static void _output_callback(c_event_t c_event, p_data_t p_data);
|
||||
|
||||
static int _reg(struct udp_socket *c, void *ptr, udp_socket_input_callback_t cb,
|
||||
const sock_udp_ep_t *local, const sock_udp_ep_t *remote)
|
||||
{
|
||||
if (((local != NULL) && (local->family != AF_INET6)) ||
|
||||
((remote != NULL) && (remote->family != AF_INET6))) {
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
if (udp_socket_register(c, ptr, cb) < 0) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (local != NULL) {
|
||||
if (udp_socket_bind(c, local->port) < 0) {
|
||||
udp_socket_close(c);
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
}
|
||||
if (remote != NULL) {
|
||||
/* check of return value not necessary, since neither c nor
|
||||
* c->udp_conn is NULL (only error case) at this point */
|
||||
udp_socket_connect(c, (uip_ipaddr_t *)&remote->addr, remote->port);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sock_udp_create(sock_udp_t *sock, const sock_udp_ep_t *local,
|
||||
const sock_udp_ep_t *remote, uint16_t flags)
|
||||
{
|
||||
int res;
|
||||
|
||||
(void)flags;
|
||||
assert((sock != NULL));
|
||||
assert((local == NULL) || (local->port != 0));
|
||||
assert((remote == NULL) || (remote->port != 0));
|
||||
if (sock->sock.input_callback != NULL) {
|
||||
sock_udp_close(sock);
|
||||
}
|
||||
mutex_init(&sock->mutex);
|
||||
mutex_lock(&sock->mutex);
|
||||
mbox_init(&sock->mbox, sock->mbox_queue, SOCK_MBOX_SIZE);
|
||||
atomic_flag_clear(&sock->receivers);
|
||||
if ((res = _reg(&sock->sock, sock, _input_callback, local, remote)) < 0) {
|
||||
sock->sock.input_callback = NULL;
|
||||
}
|
||||
mutex_unlock(&sock->mutex);
|
||||
return res;
|
||||
}
|
||||
|
||||
void sock_udp_close(sock_udp_t *sock)
|
||||
{
|
||||
assert(sock != NULL);
|
||||
if (sock->sock.input_callback != NULL) {
|
||||
while (atomic_fetch_sub(&sock->receivers, 1) > 0) {
|
||||
msg_t msg = { .type = _MSG_TYPE_CLOSE };
|
||||
mbox_put(&sock->mbox, &msg);
|
||||
}
|
||||
mutex_lock(&sock->mutex);
|
||||
udp_socket_close(&sock->sock);
|
||||
sock->sock.input_callback = NULL;
|
||||
mutex_unlock(&sock->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
int sock_udp_get_local(sock_udp_t *sock, sock_udp_ep_t *ep)
|
||||
{
|
||||
assert((sock != NULL) && (ep != NULL));
|
||||
if ((sock->sock.input_callback != NULL) &&
|
||||
(sock->sock.udp_conn->lport != 0)) {
|
||||
mutex_lock(&sock->mutex);
|
||||
/* local UDP endpoints do not have addresses in emb6 */
|
||||
memset(&ep->addr, 0, sizeof(ipv6_addr_t));
|
||||
ep->port = ntohs(sock->sock.udp_conn->lport);
|
||||
mutex_unlock(&sock->mutex);
|
||||
return sizeof(ipv6_addr_t);
|
||||
}
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
int sock_udp_get_remote(sock_udp_t *sock, sock_udp_ep_t *ep)
|
||||
{
|
||||
assert((sock != NULL) && (ep != NULL));
|
||||
if ((sock->sock.input_callback != NULL) &&
|
||||
(sock->sock.udp_conn->rport != 0)) {
|
||||
mutex_lock(&sock->mutex);
|
||||
memcpy(&ep->addr, &sock->sock.udp_conn->ripaddr, sizeof(ipv6_addr_t));
|
||||
ep->port = ntohs(sock->sock.udp_conn->rport);
|
||||
mutex_unlock(&sock->mutex);
|
||||
return sizeof(ipv6_addr_t);
|
||||
}
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
int sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len,
|
||||
uint32_t timeout, sock_udp_ep_t *remote)
|
||||
{
|
||||
xtimer_t timeout_timer;
|
||||
int blocking = BLOCKING;
|
||||
int res = -EIO;
|
||||
msg_t msg;
|
||||
|
||||
assert((sock != NULL) && (data != NULL) && (max_len > 0));
|
||||
if (sock->sock.input_callback == NULL) {
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
if (timeout == 0) {
|
||||
blocking = NON_BLOCKING;
|
||||
}
|
||||
else if (timeout != SOCK_NO_TIMEOUT) {
|
||||
timeout_timer.callback = _timeout_callback;
|
||||
timeout_timer.arg = &sock->mbox;
|
||||
xtimer_set(&timeout_timer, timeout);
|
||||
}
|
||||
atomic_fetch_add(&sock->receivers, 1);
|
||||
if (_mbox_get(&sock->mbox, &msg, blocking) == 0) {
|
||||
/* do not need to remove xtimer, since we only get here in non-blocking
|
||||
* mode (timeout > 0) */
|
||||
return -EAGAIN;
|
||||
}
|
||||
switch (msg.type) {
|
||||
case _MSG_TYPE_CLOSE:
|
||||
res = -EADDRNOTAVAIL;
|
||||
break;
|
||||
case _MSG_TYPE_TIMEOUT:
|
||||
res = -ETIMEDOUT;
|
||||
break;
|
||||
case _MSG_TYPE_RCV:
|
||||
mutex_lock(&sock->mutex);
|
||||
if (max_len < sock->recv_info.datalen) {
|
||||
res = -ENOBUFS;
|
||||
mutex_unlock(&sock->mutex);
|
||||
break;
|
||||
}
|
||||
memcpy(data, sock->recv_info.data, sock->recv_info.datalen);
|
||||
if (remote != NULL) {
|
||||
remote->family = AF_INET6;
|
||||
remote->netif = SOCK_ADDR_ANY_NETIF;
|
||||
memcpy(&remote->addr, &sock->recv_info.src, sizeof(ipv6_addr_t));
|
||||
remote->port = sock->recv_info.src_port;
|
||||
}
|
||||
res = (int)sock->recv_info.datalen;
|
||||
mutex_unlock(&sock->mutex);
|
||||
break;
|
||||
}
|
||||
atomic_fetch_sub(&sock->receivers, 1);
|
||||
return res;
|
||||
}
|
||||
|
||||
int sock_udp_send(sock_udp_t *sock, const void *data, size_t len,
|
||||
const sock_udp_ep_t *remote)
|
||||
{
|
||||
struct udp_socket tmp;
|
||||
_send_cmd_t send_cmd = { .block = MUTEX_INIT,
|
||||
.remote = remote,
|
||||
.data = data,
|
||||
.len = len };
|
||||
|
||||
assert((sock != NULL) || (remote != NULL));
|
||||
assert((len == 0) || (data != NULL)); /* (len != 0) => (data != NULL) */
|
||||
/* we want the send in the uip thread (which udp_socket_send does not offer)
|
||||
* so we need to do it manually */
|
||||
if (!send_registered) {
|
||||
if (evproc_regCallback(EVENT_TYPE_CONN_SEND, _output_callback) != E_SUCCESS) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
else {
|
||||
send_registered = true;
|
||||
}
|
||||
}
|
||||
if ((len > (UIP_BUFSIZE - (UIP_LLH_LEN + UIP_IPUDPH_LEN))) ||
|
||||
(len > UINT16_MAX)) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (remote != NULL) {
|
||||
if (remote->family != AF_INET6) {
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
if (remote->port == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
send_cmd.remote = remote;
|
||||
}
|
||||
else if (sock->sock.udp_conn->rport == 0) {
|
||||
return -ENOTCONN;
|
||||
}
|
||||
/* cppcheck-supress nullPointerRedundantCheck
|
||||
* remote == NULL implies that sock != NULL (see assert at start of
|
||||
* function) * that's why it is okay in the if-statement above to check
|
||||
* sock->... without checking (sock != NULL) first => this check afterwards
|
||||
* isn't redundant */
|
||||
if (sock == NULL) {
|
||||
int res;
|
||||
if ((res = _reg(&tmp, NULL, NULL, NULL, NULL)) < 0) {
|
||||
return res;
|
||||
}
|
||||
send_cmd.sock = &tmp;
|
||||
}
|
||||
else {
|
||||
send_cmd.sock = &sock->sock;
|
||||
}
|
||||
mutex_lock(&send_cmd.block);
|
||||
/* change to emb6 thread context */
|
||||
if (evproc_putEvent(E_EVPROC_TAIL, EVENT_TYPE_CONN_SEND, &send_cmd) == E_SUCCESS) {
|
||||
/* block thread until data was sent */
|
||||
mutex_lock(&send_cmd.block);
|
||||
}
|
||||
else {
|
||||
/* most likely error: event queue was full */
|
||||
send_cmd.res = -ENOMEM;
|
||||
}
|
||||
if (send_cmd.sock == &tmp) {
|
||||
udp_socket_close(&tmp);
|
||||
}
|
||||
mutex_unlock(&send_cmd.block);
|
||||
|
||||
return send_cmd.res;
|
||||
}
|
||||
|
||||
static void _timeout_callback(void *arg)
|
||||
{
|
||||
msg_t msg = { .type = _MSG_TYPE_TIMEOUT };
|
||||
mbox_t *mbox = arg;
|
||||
|
||||
/* should be safe, because otherwise if mbox were filled this callback is
|
||||
* senseless */
|
||||
mbox_try_put(mbox, &msg);
|
||||
}
|
||||
|
||||
static void _input_callback(struct udp_socket *c, void *ptr,
|
||||
const uip_ipaddr_t *src_addr, uint16_t src_port,
|
||||
const uip_ipaddr_t *dst_addr, uint16_t dst_port,
|
||||
const uint8_t *data, uint16_t datalen)
|
||||
{
|
||||
msg_t msg = { .type = _MSG_TYPE_RCV };
|
||||
sock_udp_t *sock = ptr;
|
||||
|
||||
(void)dst_addr;
|
||||
(void)dst_port;
|
||||
mutex_lock(&sock->mutex);
|
||||
sock->recv_info.src_port = src_port;
|
||||
sock->recv_info.src = (const ipv6_addr_t *)src_addr;
|
||||
sock->recv_info.data = data;
|
||||
sock->recv_info.datalen = datalen - sizeof(ipv6_hdr_t);
|
||||
mutex_unlock(&sock->mutex);
|
||||
mbox_put(&sock->mbox, &msg);
|
||||
}
|
||||
|
||||
static void _output_callback(c_event_t c_event, p_data_t p_data)
|
||||
{
|
||||
|
||||
if ((c_event != EVENT_TYPE_CONN_SEND) || (p_data == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_send_cmd_t *send_cmd = (_send_cmd_t *)p_data;
|
||||
|
||||
if (send_cmd->remote != NULL) {
|
||||
/* send_cmd->len was previously checked */
|
||||
send_cmd->res = udp_socket_sendto(send_cmd->sock, send_cmd->data,
|
||||
(uint16_t)send_cmd->len,
|
||||
(uip_ipaddr_t *)&send_cmd->remote->addr,
|
||||
send_cmd->remote->port);
|
||||
}
|
||||
else {
|
||||
/* send_cmd->len was previously checked */
|
||||
send_cmd->res = udp_socket_send(send_cmd->sock, send_cmd->data,
|
||||
(uint16_t)send_cmd->len);
|
||||
}
|
||||
send_cmd->res = (send_cmd->res < 0) ? -EHOSTUNREACH : send_cmd->res;
|
||||
/* notify notify waiting thread */
|
||||
mutex_unlock(&send_cmd->block);
|
||||
}
|
||||
/** @} */
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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 pkg_emb6_sock emb6-specific implementation of the sock API
|
||||
* @ingroup pkg_emb6
|
||||
* @brief
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief
|
||||
*
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*/
|
||||
#ifndef SOCK_TYPES_H_
|
||||
#define SOCK_TYPES_H_
|
||||
|
||||
#include <stdatomic.h>
|
||||
|
||||
#include "mbox.h"
|
||||
#include "mutex.h"
|
||||
#include "net/ipv6/addr.h"
|
||||
|
||||
#include "uip.h"
|
||||
#include "udp-socket.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef SOCK_MBOX_SIZE
|
||||
#define SOCK_MBOX_SIZE (2)
|
||||
#endif
|
||||
|
||||
#ifndef SOCK_HAS_IPV6
|
||||
#error "emb6 only runs with IPv6 support"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief @ref net_sock_udp definition for emb6
|
||||
*/
|
||||
struct sock_udp {
|
||||
struct udp_socket sock; /**< emb6 internal socket */
|
||||
mutex_t mutex; /**< mutex for the connection */
|
||||
mbox_t mbox; /**< mbox for receiving */
|
||||
msg_t mbox_queue[SOCK_MBOX_SIZE]; /**< queue for mbox */
|
||||
atomic_int receivers; /**< current number of recv calls */
|
||||
struct {
|
||||
const ipv6_addr_t *src; /**< source address */
|
||||
const void *data; /**< data of received packet */
|
||||
size_t datalen; /**< length of received packet data */
|
||||
uint16_t src_port; /**< source port */
|
||||
} recv_info; /**< info on received packet */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOCK_TYPES_H_ */
|
||||
/** @} */
|
|
@ -5,6 +5,9 @@ include ../Makefile.tests_common
|
|||
|
||||
FEATURES_REQUIRED = periph_gpio periph_spi # for at86rf231
|
||||
|
||||
# MSP-430 doesn't support C11's atomic functionality yet
|
||||
BOARD_BLACKLIST := msb-430 msb-430h telosb wsn430-v1_3b wsn430-v1_4 z1
|
||||
|
||||
BOARD_INSUFFICIENT_MEMORY := msb-430 msb-430h nucleo32-l031 nucleo32-f031 \
|
||||
nucleo32-f042 nucleo-l053 stm32f0discovery telosb \
|
||||
weio wsn430-v1_3b wsn430-v1_4 z1
|
||||
|
@ -12,7 +15,7 @@ BOARD_INSUFFICIENT_MEMORY := msb-430 msb-430h nucleo32-l031 nucleo32-f031 \
|
|||
USEPKG += emb6
|
||||
|
||||
USEMODULE += emb6_router
|
||||
USEMODULE += emb6_conn_udp
|
||||
USEMODULE += emb6_sock_udp
|
||||
USEMODULE += ipv6_addr
|
||||
USEMODULE += shell
|
||||
USEMODULE += shell_commands
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Definitions for tests/lwip/
|
||||
* @brief Definitions for tests/emb6/
|
||||
*
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
*/
|
||||
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
* @brief Application configuration
|
||||
* @{
|
||||
*/
|
||||
#define CONN_INBUF_SIZE (256)
|
||||
#define SOCK_INBUF_SIZE (256)
|
||||
#define SERVER_MSG_QUEUE_SIZE (8)
|
||||
#define SERVER_BUFFER_SIZE (64)
|
||||
/**
|
||||
|
@ -58,7 +58,7 @@ size_t hex2ints(uint8_t *out, const char *in);
|
|||
*/
|
||||
int ping_cmd(int argc, char **argv);
|
||||
|
||||
#ifdef MODULE_CONN_UDP
|
||||
#ifdef MODULE_EMB6_SOCK_UDP
|
||||
/**
|
||||
* @brief UDP IP shell command
|
||||
*
|
||||
|
|
|
@ -78,15 +78,14 @@ static void *_emb6_thread(void *args)
|
|||
|
||||
static const shell_command_t shell_commands[] = {
|
||||
{ "ping6", "Send pings and receive pongs", ping_cmd },
|
||||
#ifdef MODULE_CONN_UDP
|
||||
#ifdef MODULE_EMB6_SOCK_UDP
|
||||
{ "udp", "Send UDP messages and listen for messages on UDP port", udp_cmd },
|
||||
#endif
|
||||
{ "ifconfig", "Shows assigned IPv6 addresses", ifconfig },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
static char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
|
||||
char conn_inbuf[CONN_INBUF_SIZE];
|
||||
static char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
|
|
@ -25,29 +25,26 @@
|
|||
#include "common.h"
|
||||
#include "od.h"
|
||||
#include "net/af.h"
|
||||
#include "net/conn/udp.h"
|
||||
#include "net/sock/udp.h"
|
||||
#include "net/ipv6.h"
|
||||
#include "thread.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
#ifdef MODULE_CONN_UDP
|
||||
static char conn_inbuf[CONN_INBUF_SIZE];
|
||||
#ifdef MODULE_EMB6_SOCK_UDP
|
||||
static char sock_inbuf[SOCK_INBUF_SIZE];
|
||||
static bool server_running;
|
||||
static conn_udp_t server_conn;
|
||||
static sock_udp_t server_sock;
|
||||
static char server_stack[THREAD_STACKSIZE_DEFAULT];
|
||||
static msg_t server_msg_queue[SERVER_MSG_QUEUE_SIZE];
|
||||
|
||||
static void *_server_thread(void *args)
|
||||
{
|
||||
ipv6_addr_t server_addr = IPV6_ADDR_UNSPECIFIED;
|
||||
uint16_t port;
|
||||
int res;
|
||||
|
||||
msg_init_queue(server_msg_queue, SERVER_MSG_QUEUE_SIZE);
|
||||
/* parse port */
|
||||
port = (uint16_t)atoi((char *)args);
|
||||
if ((res = conn_udp_create(&server_conn, &server_addr,
|
||||
sizeof(server_addr), AF_INET6, port)) < 0) {
|
||||
uint16_t port = atoi(args);
|
||||
const sock_udp_ep_t server_addr = { .family = AF_INET6,
|
||||
.port = port };
|
||||
if ((res = sock_udp_create(&server_sock, &server_addr, NULL, 0)) < 0) {
|
||||
printf("Unable to open UDP server on port %" PRIu16 " (error code %d)\n",
|
||||
port, -res);
|
||||
return NULL;
|
||||
|
@ -55,12 +52,10 @@ static void *_server_thread(void *args)
|
|||
server_running = true;
|
||||
printf("Success: started UDP server on port %" PRIu16 "\n", port);
|
||||
while (1) {
|
||||
int res;
|
||||
ipv6_addr_t src;
|
||||
size_t src_len = sizeof(ipv6_addr_t);
|
||||
uint16_t sport;
|
||||
if ((res = conn_udp_recvfrom(&server_conn, conn_inbuf, sizeof(conn_inbuf), &src,
|
||||
&src_len, &sport)) < 0) {
|
||||
sock_udp_ep_t client_addr;
|
||||
|
||||
if ((res = sock_udp_recv(&server_sock, sock_inbuf, sizeof(sock_inbuf),
|
||||
SOCK_NO_TIMEOUT, &client_addr)) < 0) {
|
||||
puts("Error on receive");
|
||||
}
|
||||
else if (res == 0) {
|
||||
|
@ -68,9 +63,10 @@ static void *_server_thread(void *args)
|
|||
}
|
||||
else {
|
||||
char addrstr[IPV6_ADDR_MAX_STR_LEN];
|
||||
printf("Received from [%s]:%" PRIu16 ":\n", ipv6_addr_to_str(addrstr, &src,
|
||||
sizeof(addrstr)), sport);
|
||||
od_hex_dump(conn_inbuf, res, 0);
|
||||
printf("Received from [%s]:%" PRIu16 ":\n",
|
||||
ipv6_addr_to_str(addrstr, (ipv6_addr_t *)&client_addr.addr,
|
||||
sizeof(addrstr)), client_addr.port);
|
||||
od_hex_dump(sock_inbuf, res, 0);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
@ -79,27 +75,25 @@ static void *_server_thread(void *args)
|
|||
static int udp_send(char *addr_str, char *port_str, char *data, unsigned int num,
|
||||
unsigned int delay)
|
||||
{
|
||||
ipv6_addr_t src = IPV6_ADDR_UNSPECIFIED, dst;
|
||||
uint16_t port;
|
||||
uint8_t byte_data[strlen(data) / 2];
|
||||
sock_udp_ep_t dst = { .family = AF_INET6 };
|
||||
size_t data_len;
|
||||
|
||||
/* parse destination address */
|
||||
if (ipv6_addr_from_str(&dst, addr_str) == NULL) {
|
||||
if (ipv6_addr_from_str((ipv6_addr_t *)&dst.addr, addr_str) == NULL) {
|
||||
puts("Error: unable to parse destination address");
|
||||
return 1;
|
||||
}
|
||||
/* parse port */
|
||||
port = (uint16_t)atoi(port_str);
|
||||
dst.port = atoi(port_str);
|
||||
data_len = hex2ints(byte_data, data);
|
||||
for (unsigned int i = 0; i < num; i++) {
|
||||
if (conn_udp_sendto(byte_data, data_len, &src, sizeof(src), (struct sockaddr *)&dst,
|
||||
sizeof(dst), AF_INET6, port, port) < 0) {
|
||||
if (sock_udp_send(NULL, byte_data, data_len, &dst) < 0) {
|
||||
puts("could not send");
|
||||
}
|
||||
else {
|
||||
printf("Success: send %u byte to [%s]:%" PRIu16 ")\n",
|
||||
(unsigned)data_len, addr_str, port);
|
||||
(unsigned)data_len, addr_str, dst.port);
|
||||
}
|
||||
xtimer_usleep(delay);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue