net: samples: Convert echo-client to use network app API
This commit will convert echo-client to use the net app API when creating the connection to peer. Most of the network setup code will be removed from echo-client by this commit. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
2e7c3519a4
commit
76e6e32cad
10 changed files with 948 additions and 862 deletions
|
@ -31,6 +31,9 @@ CONFIG_NET_MGMT_EVENT=y
|
|||
CONFIG_NET_SHELL=y
|
||||
CONFIG_NET_L2_BLUETOOTH_SHELL=y
|
||||
|
||||
CONFIG_NET_APP=y
|
||||
CONFIG_NET_APP_NEED_IPV6=y
|
||||
CONFIG_NET_APP_CLIENT=y
|
||||
CONFIG_NET_APP_SETTINGS=y
|
||||
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2"
|
||||
|
|
|
@ -49,6 +49,9 @@ CONFIG_IEEE802154_CC2520_SPI_DRV_NAME="SPI_0"
|
|||
CONFIG_IEEE802154_CC2520_SPI_FREQ=4000000
|
||||
CONFIG_IEEE802154_CC2520_SPI_SLAVE=0
|
||||
|
||||
CONFIG_NET_APP=y
|
||||
CONFIG_NET_APP_NEED_IPV6=y
|
||||
CONFIG_NET_APP_CLIENT=y
|
||||
CONFIG_NET_APP_SETTINGS=y
|
||||
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2"
|
||||
|
|
|
@ -13,17 +13,25 @@ CONFIG_SYS_LOG_SHOW_COLOR=y
|
|||
CONFIG_INIT_STACKS=y
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_NET_STATISTICS=y
|
||||
CONFIG_NET_PKT_RX_COUNT=10
|
||||
CONFIG_NET_PKT_TX_COUNT=10
|
||||
CONFIG_NET_BUF_RX_COUNT=20
|
||||
CONFIG_NET_BUF_TX_COUNT=20
|
||||
CONFIG_NET_PKT_RX_COUNT=50
|
||||
CONFIG_NET_PKT_TX_COUNT=50
|
||||
CONFIG_NET_BUF_RX_COUNT=50
|
||||
CONFIG_NET_BUF_TX_COUNT=50
|
||||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
|
||||
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2
|
||||
CONFIG_NET_MAX_CONTEXTS=10
|
||||
|
||||
CONFIG_NET_SHELL=y
|
||||
|
||||
CONFIG_NET_APP=y
|
||||
CONFIG_NET_APP_NEED_IPV6=y
|
||||
CONFIG_NET_APP_NEED_IPV4=y
|
||||
CONFIG_NET_APP_CLIENT=y
|
||||
CONFIG_NET_APP_SETTINGS=y
|
||||
|
||||
# The addresses are selected so that qemu<->qemu connectivity works ok.
|
||||
# For linux<->qemu connectivity, create a new conf file and swap the
|
||||
# addresses (so that peer address is ending to 2).
|
||||
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::2"
|
||||
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.2"
|
||||
|
|
48
samples/net/echo_client/prj_qemu_x86_tls.conf
Normal file
48
samples/net/echo_client/prj_qemu_x86_tls.conf
Normal file
|
@ -0,0 +1,48 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_UDP=n
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NET_BUF_LOG=y
|
||||
CONFIG_SYS_LOG_NET_BUF_LEVEL=2
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_SYS_LOG_NET_LEVEL=2
|
||||
CONFIG_NET_SLIP_TAP=y
|
||||
CONFIG_SYS_LOG_SHOW_COLOR=y
|
||||
CONFIG_INIT_STACKS=y
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_NET_STATISTICS=y
|
||||
CONFIG_NET_PKT_RX_COUNT=50
|
||||
CONFIG_NET_PKT_TX_COUNT=50
|
||||
CONFIG_NET_BUF_RX_COUNT=50
|
||||
CONFIG_NET_BUF_TX_COUNT=50
|
||||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=4
|
||||
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=4
|
||||
CONFIG_NET_MAX_CONTEXTS=10
|
||||
|
||||
CONFIG_NET_SHELL=y
|
||||
|
||||
CONFIG_NET_APP=y
|
||||
CONFIG_NET_APP_NEED_IPV6=y
|
||||
CONFIG_NET_APP_NEED_IPV4=y
|
||||
CONFIG_NET_APP_CLIENT=y
|
||||
CONFIG_NET_APP_SETTINGS=y
|
||||
|
||||
# The addresses are selected here so that qemu<->linux connectivity works ok.
|
||||
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2"
|
||||
CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1"
|
||||
CONFIG_NET_APP_PEER_IPV4_ADDR="192.0.2.2"
|
||||
|
||||
CONFIG_NET_APP_TLS=y
|
||||
|
||||
CONFIG_MBEDTLS=y
|
||||
CONFIG_MBEDTLS_BUILTIN=y
|
||||
CONFIG_MBEDTLS_ENABLE_HEAP=y
|
||||
CONFIG_MBEDTLS_HEAP_SIZE=30000
|
||||
CONFIG_MBEDTLS_CFG_FILE="config-mini-tls1_2.h"
|
||||
|
||||
CONFIG_RAM_SIZE=300
|
||||
|
||||
CONFIG_NET_DEBUG_NET_PKT=y
|
|
@ -1,33 +1,11 @@
|
|||
obj-y = echo-client.o
|
||||
#
|
||||
# Copyright (c) 2017 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
ifeq ($(CONFIG_IEEE802154_CC2520),y)
|
||||
include $(ZEPHYR_BASE)/samples/net/common/Makefile.common
|
||||
|
||||
ifeq ($(CONFIG_BOARD_ARDUINO_101),y)
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/include/drivers/
|
||||
obj-y += ../../common/cc2520_a101.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BOARD_FRDM_K64F),y)
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/drivers/
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/include/drivers/
|
||||
obj-y += ../../common/cc2520_frdm_k64f.o
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NET_TESTING), y)
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/samples/net/common/
|
||||
ccflags-y +=-DNET_TESTING_SERVER=0
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NET_L2_BLUETOOTH), y)
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/samples/bluetooth/
|
||||
obj-y += ../../../bluetooth/gatt/ipss.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NET_L2_IEEE802154), y)
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/samples/net/common/
|
||||
ifeq ($(CONFIG_NET_APP_SETTINGS), y)
|
||||
obj-y += ../../common/ieee802154_settings.o
|
||||
endif
|
||||
endif
|
||||
obj-y += echo-client.o
|
||||
obj-$(CONFIG_NET_UDP) += udp.o
|
||||
obj-$(CONFIG_NET_TCP) += tcp.o
|
||||
|
|
53
samples/net/echo_client/src/common.h
Normal file
53
samples/net/echo_client/src/common.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Value of 0 will cause the IP stack to select next free port */
|
||||
#define MY_PORT 0
|
||||
|
||||
#define PEER_PORT 4242
|
||||
|
||||
#define WAIT_TIME K_SECONDS(10)
|
||||
#define CONNECT_TIME K_SECONDS(10)
|
||||
|
||||
struct data {
|
||||
/* Work controlling udp data sending */
|
||||
struct k_delayed_work recv;
|
||||
struct net_app_ctx *udp;
|
||||
|
||||
const char *proto;
|
||||
u32_t expecting_udp;
|
||||
u32_t expecting_tcp;
|
||||
u32_t received_tcp;
|
||||
};
|
||||
|
||||
struct configs {
|
||||
struct data ipv4;
|
||||
struct data ipv6;
|
||||
};
|
||||
|
||||
#if !defined(CONFIG_NET_APP_PEER_IPV4_ADDR)
|
||||
#define CONFIG_NET_APP_PEER_IPV4_ADDR ""
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_NET_APP_PEER_IPV6_ADDR)
|
||||
#define CONFIG_NET_APP_PEER_IPV6_ADDR ""
|
||||
#endif
|
||||
|
||||
extern const char lorem_ipsum[];
|
||||
extern int ipsum_len;
|
||||
extern struct configs conf;
|
||||
extern struct k_sem tcp_ready;
|
||||
|
||||
void start_udp(void);
|
||||
void stop_udp(void);
|
||||
|
||||
int start_tcp(void);
|
||||
void stop_tcp(void);
|
||||
|
||||
struct net_pkt *prepare_send_pkt(struct net_app_ctx *ctx,
|
||||
const char *name,
|
||||
int expecting_len);
|
||||
void panic(const char *msg);
|
|
@ -1,7 +1,7 @@
|
|||
/* echo-client.c - Networking echo client */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
* Copyright (c) 2017 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -11,6 +11,9 @@
|
|||
* and echo-server is run in the host acting as a server. The client will send
|
||||
* either unicast or multicast packets to the server which will reply the packet
|
||||
* back to the originator.
|
||||
*
|
||||
* In this sample application we create four threads that start to send data.
|
||||
* This might not be what you want to do in your app so caveat emptor.
|
||||
*/
|
||||
|
||||
#if 1
|
||||
|
@ -20,15 +23,14 @@
|
|||
#endif
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <linker/sections.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <net/net_pkt.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_context.h>
|
||||
#include <net/net_mgmt.h>
|
||||
|
||||
#include <net/net_app.h>
|
||||
|
||||
#if defined(CONFIG_NET_L2_BLUETOOTH)
|
||||
#include <bluetooth/bluetooth.h>
|
||||
|
@ -39,10 +41,14 @@
|
|||
#include <ieee802154_settings.h>
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define APP_BANNER "Run echo client"
|
||||
|
||||
/* Generated by http://www.lipsum.com/
|
||||
* 3 paragraphs, 176 words, 1230 bytes of Lorem Ipsum
|
||||
*/
|
||||
static char *lorem_ipsum =
|
||||
const char lorem_ipsum[] =
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
|
||||
"Vestibulum id cursus felis, sit amet suscipit velit. Integer "
|
||||
"facilisis malesuada porta. Nunc at accumsan mauris. Etiam vehicula, "
|
||||
|
@ -68,871 +74,120 @@ static char *lorem_ipsum =
|
|||
"Phasellus efficitur imperdiet metus."
|
||||
"\n";
|
||||
|
||||
#define STACKSIZE 2048
|
||||
int ipsum_len = sizeof(lorem_ipsum) - 1;
|
||||
|
||||
static int ipsum_len;
|
||||
|
||||
/* Note that both tcp and udp can share the same pool but in this
|
||||
* example the UDP context and TCP context have separate pools.
|
||||
*/
|
||||
#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
NET_PKT_TX_SLAB_DEFINE(echo_tx_tcp, 15);
|
||||
NET_PKT_DATA_POOL_DEFINE(echo_data_tcp, 30);
|
||||
|
||||
static struct k_mem_slab *tx_tcp_slab(void)
|
||||
{
|
||||
return &echo_tx_tcp;
|
||||
}
|
||||
|
||||
static struct net_buf_pool *data_tcp_pool(void)
|
||||
{
|
||||
return &echo_data_tcp;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_UDP)
|
||||
NET_PKT_TX_SLAB_DEFINE(echo_tx_udp, 5);
|
||||
NET_PKT_DATA_POOL_DEFINE(echo_data_udp, 20);
|
||||
|
||||
static struct k_mem_slab *tx_udp_slab(void)
|
||||
{
|
||||
return &echo_tx_udp;
|
||||
}
|
||||
|
||||
static struct net_buf_pool *data_udp_pool(void)
|
||||
{
|
||||
return &echo_data_udp;
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
|
||||
|
||||
#define MY_PORT 8484
|
||||
#define PEER_PORT 4242
|
||||
|
||||
struct data {
|
||||
u32_t expecting_udp;
|
||||
u32_t expecting_tcp;
|
||||
u32_t received_tcp;
|
||||
struct configs conf = {
|
||||
.ipv4 = {
|
||||
.proto = "IPv4",
|
||||
},
|
||||
.ipv6 = {
|
||||
.proto = "IPv6",
|
||||
},
|
||||
};
|
||||
|
||||
static struct {
|
||||
#if defined(CONFIG_NET_UDP)
|
||||
/* semaphore for controlling udp data sending */
|
||||
struct k_sem recv_ipv6;
|
||||
struct k_sem recv_ipv4;
|
||||
#endif /* CONFIG_NET_UDP */
|
||||
static struct k_sem quit_lock;
|
||||
struct k_sem tcp_ready;
|
||||
|
||||
struct data ipv4;
|
||||
struct data ipv6;
|
||||
} conf;
|
||||
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
static bool send_tcp_data(struct net_context *ctx,
|
||||
char *proto,
|
||||
struct data *data);
|
||||
#endif /* CONFIG_NET_TCP */
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
/* Define the peer IP address where to send messages */
|
||||
#define PEER_IP6ADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x2 } } }
|
||||
|
||||
#define MY_IP6ADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } }
|
||||
|
||||
#define MY_PREFIX_LEN 64
|
||||
|
||||
#if defined(CONFIG_NET_APP_SETTINGS)
|
||||
static struct in6_addr in6addr_my = MY_IP6ADDR;
|
||||
static struct in6_addr in6addr_peer = PEER_IP6ADDR;
|
||||
#endif
|
||||
|
||||
static struct sockaddr_in6 my_addr6 = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_port = htons(MY_PORT),
|
||||
};
|
||||
|
||||
static struct sockaddr_in6 peer_addr6 = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_port = htons(PEER_PORT),
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_UDP)
|
||||
static K_THREAD_STACK_DEFINE(ipv6_udp_stack, STACKSIZE);
|
||||
static struct k_thread ipv6_udp_thread_data;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
static K_THREAD_STACK_DEFINE(ipv6_tcp_stack, STACKSIZE);
|
||||
static struct k_thread ipv6_tcp_thread_data;
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
#define MY_IP4ADDR { { { 192, 0, 2, 1 } } }
|
||||
#define PEER_IP4ADDR { { { 192, 0, 2, 2 } } }
|
||||
|
||||
#if defined(CONFIG_NET_APP_SETTINGS)
|
||||
static struct in_addr in4addr_my = MY_IP4ADDR;
|
||||
static struct in_addr in4addr_peer = PEER_IP4ADDR;
|
||||
#endif
|
||||
|
||||
static struct sockaddr_in my_addr4 = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(MY_PORT),
|
||||
};
|
||||
|
||||
static struct sockaddr_in peer_addr4 = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(PEER_PORT),
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_UDP)
|
||||
static K_THREAD_STACK_DEFINE(ipv4_udp_stack, STACKSIZE);
|
||||
static struct k_thread ipv4_udp_thread_data;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
static K_THREAD_STACK_DEFINE(ipv4_tcp_stack, STACKSIZE);
|
||||
static struct k_thread ipv4_tcp_thread_data;
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
|
||||
#define WAIT_TIME (2 * MSEC_PER_SEC)
|
||||
|
||||
#if defined(CONFIG_NET_MGMT_EVENT)
|
||||
static struct net_mgmt_event_callback cb;
|
||||
#endif
|
||||
|
||||
static inline void init_app(void)
|
||||
void panic(const char *msg)
|
||||
{
|
||||
NET_INFO("Run echo client");
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
#if defined(CONFIG_NET_APP_SETTINGS)
|
||||
if (net_addr_pton(AF_INET6,
|
||||
CONFIG_NET_APP_MY_IPV6_ADDR,
|
||||
&my_addr6.sin6_addr) < 0) {
|
||||
NET_ERR("Invalid IPv6 address %s",
|
||||
CONFIG_NET_APP_MY_IPV6_ADDR);
|
||||
|
||||
net_ipaddr_copy(&my_addr6.sin6_addr, &in6addr_my);
|
||||
if (msg) {
|
||||
NET_ERR("%s", msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_APP_SETTINGS)
|
||||
if (net_addr_pton(AF_INET6,
|
||||
CONFIG_NET_APP_PEER_IPV6_ADDR,
|
||||
&peer_addr6.sin6_addr) < 0) {
|
||||
NET_ERR("Invalid peer IPv6 address %s",
|
||||
CONFIG_NET_APP_PEER_IPV6_ADDR);
|
||||
k_sem_give(&quit_lock);
|
||||
|
||||
net_ipaddr_copy(&peer_addr6.sin6_addr, &in6addr_peer);
|
||||
for (;;) {
|
||||
k_sleep(K_FOREVER);
|
||||
}
|
||||
#endif
|
||||
|
||||
do {
|
||||
struct net_if_addr *ifaddr;
|
||||
|
||||
ifaddr = net_if_ipv6_addr_add(net_if_get_default(),
|
||||
&my_addr6.sin6_addr,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
} while (0);
|
||||
|
||||
#if defined(CONFIG_NET_UDP)
|
||||
k_sem_init(&conf.recv_ipv6, 0, UINT_MAX);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
#if defined(CONFIG_NET_DHCPV4)
|
||||
net_dhcpv4_start(net_if_get_default());
|
||||
#else
|
||||
#if defined(CONFIG_NET_APP_SETTINGS)
|
||||
if (net_addr_pton(AF_INET,
|
||||
CONFIG_NET_APP_MY_IPV4_ADDR,
|
||||
&my_addr4.sin_addr) < 0) {
|
||||
NET_ERR("Invalid IPv4 address %s",
|
||||
CONFIG_NET_APP_MY_IPV4_ADDR);
|
||||
|
||||
net_ipaddr_copy(&my_addr4.sin_addr, &in4addr_my);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_APP_SETTINGS)
|
||||
if (net_addr_pton(AF_INET,
|
||||
CONFIG_NET_APP_PEER_IPV4_ADDR,
|
||||
&peer_addr4.sin_addr) < 0) {
|
||||
NET_ERR("Invalid peer IPv4 address %s",
|
||||
CONFIG_NET_APP_PEER_IPV4_ADDR);
|
||||
|
||||
net_ipaddr_copy(&peer_addr4.sin_addr, &in4addr_peer);
|
||||
}
|
||||
#endif
|
||||
|
||||
net_if_ipv4_addr_add(net_if_get_default(), &my_addr4.sin_addr,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
#endif /* CONFIG_NET_DHCPV4 */
|
||||
|
||||
#if defined(CONFIG_NET_UDP)
|
||||
k_sem_init(&conf.recv_ipv4, 0, UINT_MAX);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool get_context(struct net_context **udp_recv4,
|
||||
struct net_context **udp_recv6,
|
||||
struct net_context **tcp_recv4,
|
||||
struct net_context **tcp_recv6)
|
||||
static inline int init_app(void)
|
||||
{
|
||||
int ret;
|
||||
NET_INFO(APP_BANNER);
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_UDP)
|
||||
ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, udp_recv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context for IPv6 UDP (%d)",
|
||||
ret);
|
||||
return false;
|
||||
k_sem_init(&quit_lock, 0, UINT_MAX);
|
||||
|
||||
#if defined(CONFIG_NET_L2_BLUETOOTH)
|
||||
if (bt_enable(NULL)) {
|
||||
NET_ERR("Bluetooth init failed");
|
||||
return -EFAULT;
|
||||
}
|
||||
ipss_init();
|
||||
ipss_advertise();
|
||||
#endif
|
||||
|
||||
net_context_setup_pools(*udp_recv6, tx_udp_slab, data_udp_pool);
|
||||
|
||||
ret = net_context_bind(*udp_recv6, (struct sockaddr *)&my_addr6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv6 UDP port %d (%d)",
|
||||
ntohs(my_addr6.sin6_port), ret);
|
||||
return false;
|
||||
#if defined(CONFIG_NET_L2_IEEE802154)
|
||||
if (ieee802154_sample_setup()) {
|
||||
NET_ERR("IEEE 802.15.4 setup failed");
|
||||
return -EFAULT;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_UDP)
|
||||
ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP, udp_recv4);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context for IPv4 UDP (%d)",
|
||||
ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
net_context_setup_pools(*udp_recv4, tx_udp_slab, data_udp_pool);
|
||||
|
||||
ret = net_context_bind(*udp_recv4, (struct sockaddr *)&my_addr4,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv4 UDP port %d (%d)",
|
||||
ntohs(my_addr4.sin_port), ret);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_TCP)
|
||||
if (tcp_recv6) {
|
||||
ret = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP,
|
||||
tcp_recv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context "
|
||||
"for IPv6 TCP (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
net_context_setup_pools(*tcp_recv6, tx_tcp_slab, data_tcp_pool);
|
||||
|
||||
ret = net_context_bind(*tcp_recv6,
|
||||
(struct sockaddr *)&my_addr6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv6 TCP port %d (%d)",
|
||||
ntohs(my_addr6.sin6_port), ret);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_TCP)
|
||||
if (tcp_recv4) {
|
||||
ret = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP,
|
||||
tcp_recv4);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context for IPv4 TCP");
|
||||
return false;
|
||||
}
|
||||
|
||||
net_context_setup_pools(*tcp_recv4, tx_tcp_slab, data_tcp_pool);
|
||||
|
||||
ret = net_context_bind(*tcp_recv4,
|
||||
(struct sockaddr *)&my_addr4,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv4 TCP port %d",
|
||||
ntohs(my_addr4.sin_port));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool wait_reply(const char *name,
|
||||
struct k_sem *sem)
|
||||
{
|
||||
int ret = k_sem_take(sem, WAIT_TIME);
|
||||
|
||||
ARG_UNUSED(name);
|
||||
|
||||
if (!ret) {
|
||||
return true;
|
||||
}
|
||||
|
||||
NET_ERR("wait_reply returned %s",
|
||||
ret == -EAGAIN ? "on time out" : "directly");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct net_pkt *prepare_send_pkt(const char *name,
|
||||
struct net_context *context,
|
||||
int expecting_len)
|
||||
struct net_pkt *prepare_send_pkt(struct net_app_ctx *ctx,
|
||||
const char *name,
|
||||
int expecting_len)
|
||||
{
|
||||
struct net_pkt *send_pkt;
|
||||
bool status;
|
||||
|
||||
send_pkt = net_pkt_get_tx(context, K_FOREVER);
|
||||
send_pkt = net_app_get_net_pkt(ctx, K_FOREVER);
|
||||
|
||||
NET_ASSERT(send_pkt);
|
||||
|
||||
status = net_pkt_append_all(send_pkt, expecting_len, lorem_ipsum,
|
||||
K_FOREVER);
|
||||
K_FOREVER);
|
||||
if (!status) {
|
||||
NET_ERR("%s: cannot create send pkt", name);
|
||||
net_pkt_unref(send_pkt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return send_pkt;
|
||||
}
|
||||
|
||||
static inline void udp_sent(struct net_context *context,
|
||||
int status,
|
||||
void *bytes_sent,
|
||||
void *user_data)
|
||||
{
|
||||
ARG_UNUSED(context);
|
||||
|
||||
if (!status) {
|
||||
NET_INFO("%s: sent %u bytes", (char *)user_data,
|
||||
POINTER_TO_UINT(bytes_sent));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void set_dst_addr(sa_family_t family,
|
||||
struct net_pkt *pkt,
|
||||
struct sockaddr *dst_addr)
|
||||
{
|
||||
ARG_UNUSED(pkt);
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (family == AF_INET6) {
|
||||
net_ipaddr_copy(&net_sin6(dst_addr)->sin6_addr,
|
||||
&peer_addr6.sin6_addr);
|
||||
net_sin6(dst_addr)->sin6_family = AF_INET6;
|
||||
net_sin6(dst_addr)->sin6_port = htons(PEER_PORT);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
if (family == AF_INET) {
|
||||
net_ipaddr_copy(&net_sin(dst_addr)->sin_addr,
|
||||
&peer_addr4.sin_addr);
|
||||
net_sin(dst_addr)->sin_family = AF_INET;
|
||||
net_sin(dst_addr)->sin_port = htons(PEER_PORT);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_UDP)
|
||||
static bool compare_udp_data(struct net_pkt *pkt, int expecting_len)
|
||||
{
|
||||
u8_t *ptr = net_pkt_appdata(pkt);
|
||||
struct net_buf *frag;
|
||||
int pos = 0;
|
||||
int len;
|
||||
|
||||
/* frag will now point to first fragment with IP header
|
||||
* in it.
|
||||
*/
|
||||
frag = pkt->frags;
|
||||
|
||||
/* Do not include the protocol headers in the first fragment.
|
||||
* The remaining fragments contain only data so the user data
|
||||
* length is directly the fragment len.
|
||||
*/
|
||||
len = frag->len - (ptr - frag->data);
|
||||
|
||||
while (frag) {
|
||||
if (memcmp(ptr, lorem_ipsum + pos, len)) {
|
||||
NET_DBG("Invalid data received");
|
||||
return false;
|
||||
} else {
|
||||
pos += len;
|
||||
|
||||
frag = frag->frags;
|
||||
if (!frag) {
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = frag->data;
|
||||
len = frag->len;
|
||||
}
|
||||
}
|
||||
|
||||
NET_DBG("Compared %d bytes, all ok", expecting_len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void setup_udp_recv(struct net_context *udp, void *user_data,
|
||||
net_context_recv_cb_t cb)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = net_context_recv(udp, cb, 0, user_data);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot receive UDP packets");
|
||||
}
|
||||
}
|
||||
|
||||
static bool send_udp_data(struct net_context *udp,
|
||||
sa_family_t family,
|
||||
char *proto,
|
||||
struct data *data)
|
||||
{
|
||||
bool status = false;
|
||||
struct net_pkt *send_pkt;
|
||||
struct sockaddr dst_addr;
|
||||
socklen_t addrlen;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
data->expecting_udp = sys_rand32_get() % ipsum_len;
|
||||
|
||||
send_pkt = prepare_send_pkt(proto, udp, data->expecting_udp);
|
||||
if (!send_pkt) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = net_pkt_get_len(send_pkt);
|
||||
|
||||
NET_ASSERT_INFO(data->expecting_udp == len,
|
||||
"Data to send %d bytes, real len %zu",
|
||||
data->expecting_udp, len);
|
||||
|
||||
set_dst_addr(family, send_pkt, &dst_addr);
|
||||
|
||||
if (family == AF_INET6) {
|
||||
addrlen = sizeof(struct sockaddr_in6);
|
||||
} else {
|
||||
addrlen = sizeof(struct sockaddr_in);
|
||||
}
|
||||
|
||||
ret = net_context_sendto(send_pkt, &dst_addr,
|
||||
addrlen, udp_sent, 0,
|
||||
UINT_TO_POINTER(len),
|
||||
proto);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot send %s data to peer (%d)", proto, ret);
|
||||
net_pkt_unref(send_pkt);
|
||||
} else {
|
||||
status = true;
|
||||
}
|
||||
out:
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void udp_received(struct net_context *context,
|
||||
struct net_pkt *pkt,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
sa_family_t family = net_pkt_family(pkt);
|
||||
struct data *data = user_data;
|
||||
struct k_sem *recv;
|
||||
|
||||
ARG_UNUSED(context);
|
||||
ARG_UNUSED(status);
|
||||
|
||||
if (family == AF_INET) {
|
||||
recv = &conf.recv_ipv4;
|
||||
} else {
|
||||
recv = &conf.recv_ipv6;
|
||||
}
|
||||
|
||||
if (data->expecting_udp != net_pkt_appdatalen(pkt)) {
|
||||
NET_ERR("Sent %d bytes, received %u bytes",
|
||||
data->expecting_udp, net_pkt_appdatalen(pkt));
|
||||
}
|
||||
|
||||
if (!compare_udp_data(pkt, data->expecting_udp)) {
|
||||
NET_DBG("Data mismatch");
|
||||
}
|
||||
|
||||
net_pkt_unref(pkt);
|
||||
|
||||
k_sem_give(recv);
|
||||
}
|
||||
|
||||
static void send_udp(struct net_context *udp,
|
||||
sa_family_t family,
|
||||
char *proto,
|
||||
struct k_sem *sem,
|
||||
struct data *data)
|
||||
{
|
||||
setup_udp_recv(udp, data, udp_received);
|
||||
|
||||
NET_INFO("Starting to send %s data", proto);
|
||||
|
||||
do {
|
||||
/* We first send a packet, then wait for a packet to arrive.
|
||||
* If the reply does not come in time, we send another packet.
|
||||
*/
|
||||
send_udp_data(udp, family, proto, data);
|
||||
|
||||
NET_DBG("Waiting %s packet", proto);
|
||||
|
||||
if (!wait_reply(proto, sem)) {
|
||||
NET_DBG("Waited %d bytes but did not receive them.",
|
||||
data->expecting_udp);
|
||||
}
|
||||
|
||||
k_yield();
|
||||
} while (1);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_UDP */
|
||||
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
static bool compare_tcp_data(struct net_pkt *pkt, int expecting_len,
|
||||
int received_len)
|
||||
{
|
||||
u8_t *ptr = net_pkt_appdata(pkt), *start;
|
||||
int pos = 0;
|
||||
struct net_buf *frag;
|
||||
int len;
|
||||
|
||||
/* frag will point to first fragment with IP header in it.
|
||||
*/
|
||||
frag = pkt->frags;
|
||||
|
||||
/* Do not include the protocol headers for the first fragment.
|
||||
* The remaining fragments contain only data so the user data
|
||||
* length is directly the fragment len.
|
||||
*/
|
||||
len = frag->len - (ptr - frag->data);
|
||||
|
||||
start = lorem_ipsum + received_len;
|
||||
|
||||
while (frag) {
|
||||
if (memcmp(ptr, start + pos, len)) {
|
||||
NET_DBG("Invalid data received");
|
||||
return false;
|
||||
}
|
||||
|
||||
pos += len;
|
||||
|
||||
frag = frag->frags;
|
||||
if (!frag) {
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = frag->data;
|
||||
len = frag->len;
|
||||
}
|
||||
|
||||
NET_DBG("Compared %d bytes, all ok", net_pkt_appdatalen(pkt));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void tcp_received(struct net_context *context,
|
||||
struct net_pkt *pkt,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
struct data *data = user_data;
|
||||
char *proto;
|
||||
|
||||
ARG_UNUSED(status);
|
||||
|
||||
if (!pkt || net_pkt_appdatalen(pkt) == 0) {
|
||||
if (pkt) {
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (net_pkt_family(pkt) == AF_INET6) {
|
||||
proto = "IPv6";
|
||||
} else {
|
||||
proto = "IPv4";
|
||||
}
|
||||
|
||||
NET_DBG("Sent %d bytes, received %u bytes",
|
||||
data->expecting_tcp, net_pkt_appdatalen(pkt));
|
||||
|
||||
if (!compare_tcp_data(pkt, data->expecting_tcp, data->received_tcp)) {
|
||||
NET_DBG("Data mismatch");
|
||||
} else {
|
||||
data->received_tcp += net_pkt_appdatalen(pkt);
|
||||
}
|
||||
|
||||
if (data->expecting_tcp <= data->received_tcp) {
|
||||
/* Send more data */
|
||||
send_tcp_data(context, proto, data);
|
||||
}
|
||||
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
|
||||
static void setup_tcp_recv(struct net_context *tcp,
|
||||
net_context_recv_cb_t cb,
|
||||
void *user_data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = net_context_recv(tcp, cb, 0, user_data);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot receive TCP packets (%d)", ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void tcp_sent(struct net_context *context,
|
||||
int status,
|
||||
void *token,
|
||||
void *user_data)
|
||||
{
|
||||
u32_t len = POINTER_TO_UINT(token);
|
||||
|
||||
if (len) {
|
||||
if (status) {
|
||||
NET_DBG("%s: len %u status %d", (char *)user_data,
|
||||
len, status);
|
||||
} else {
|
||||
NET_DBG("%s: len %u", (char *)user_data, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool send_tcp_data(struct net_context *ctx,
|
||||
char *proto,
|
||||
struct data *data)
|
||||
{
|
||||
struct net_pkt *send_pkt;
|
||||
bool status = false;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
data->expecting_tcp = sys_rand32_get() % ipsum_len;
|
||||
data->received_tcp = 0;
|
||||
|
||||
send_pkt = prepare_send_pkt(proto, ctx, data->expecting_tcp);
|
||||
if (!send_pkt) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = net_pkt_get_len(send_pkt);
|
||||
|
||||
NET_ASSERT_INFO(data->expecting_tcp == len,
|
||||
"%s data to send %d bytes, real len %zu",
|
||||
proto, data->expecting_tcp, len);
|
||||
|
||||
ret = net_context_send(send_pkt, tcp_sent, 0,
|
||||
UINT_TO_POINTER(len), proto);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot send %s data to peer (%d)", proto, ret);
|
||||
net_pkt_unref(send_pkt);
|
||||
} else {
|
||||
status = true;
|
||||
}
|
||||
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
static void tcp_connected(struct net_context *context,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
/* Start to send data */
|
||||
sa_family_t family = POINTER_TO_UINT(user_data);
|
||||
const char *str_family = (family == AF_INET) ? "IPv4" : "IPv6";
|
||||
|
||||
if (status < 0) {
|
||||
NET_ERR("Couldn't connect using %s: %d", str_family, status);
|
||||
return;
|
||||
}
|
||||
|
||||
NET_DBG("%s connected.", str_family);
|
||||
|
||||
if (family == AF_INET) {
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
setup_tcp_recv(context, tcp_received, &conf.ipv4);
|
||||
|
||||
send_tcp_data(context, "IPv4", &conf.ipv4);
|
||||
#else
|
||||
NET_DBG("IPv4 data skipped.");
|
||||
#endif
|
||||
} else if (family == AF_INET6) {
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
setup_tcp_recv(context, tcp_received, &conf.ipv6);
|
||||
|
||||
send_tcp_data(context, "IPv6", &conf.ipv6);
|
||||
#else
|
||||
NET_DBG("IPv6 data skipped.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
static void tcp_connect4(struct net_context *tcp_send)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = net_context_connect(tcp_send,
|
||||
(struct sockaddr *)&peer_addr4,
|
||||
sizeof(peer_addr4),
|
||||
tcp_connected,
|
||||
K_FOREVER,
|
||||
UINT_TO_POINTER(AF_INET));
|
||||
if (ret < 0) {
|
||||
NET_DBG("Cannot connect to IPv4 peer (%d)", ret);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static void tcp_connect6(struct net_context *tcp_send)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = net_context_connect(tcp_send,
|
||||
(struct sockaddr *)&peer_addr6,
|
||||
sizeof(peer_addr6),
|
||||
tcp_connected,
|
||||
K_FOREVER,
|
||||
UINT_TO_POINTER(AF_INET6));
|
||||
if (ret < 0) {
|
||||
NET_DBG("Cannot connect to IPv6 peer (%d)", ret);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
#endif /* CONFIG_NET_TCP */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_UDP)
|
||||
static void send_udp_ipv4(struct net_context *udp)
|
||||
{
|
||||
send_udp(udp, AF_INET, "IPv4", &conf.recv_ipv4, &conf.ipv4);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_TCP)
|
||||
static void send_tcp_ipv4(struct net_context *tcp)
|
||||
{
|
||||
tcp_connect4(tcp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_UDP)
|
||||
static void send_udp_ipv6(struct net_context *udp)
|
||||
{
|
||||
send_udp(udp, AF_INET6, "IPv6", &conf.recv_ipv6, &conf.ipv6);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_TCP)
|
||||
static void send_tcp_ipv6(struct net_context *tcp)
|
||||
{
|
||||
tcp_connect6(tcp);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void event_iface_up(struct net_mgmt_event_callback *cb,
|
||||
u32_t mgmt_event, struct net_if *iface)
|
||||
{
|
||||
struct net_context *udp_send4 = { 0 };
|
||||
struct net_context *udp_send6 = { 0 };
|
||||
struct net_context *tcp_send4 = { 0 };
|
||||
struct net_context *tcp_send6 = { 0 };
|
||||
|
||||
ipsum_len = strlen(lorem_ipsum);
|
||||
|
||||
if (!get_context(&udp_send4, &udp_send6,
|
||||
&tcp_send4, &tcp_send6)) {
|
||||
NET_ERR("Cannot get network contexts");
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_UDP)
|
||||
k_thread_create(&ipv4_udp_thread_data, ipv4_udp_stack, STACKSIZE,
|
||||
(k_thread_entry_t)send_udp_ipv4,
|
||||
udp_send4, NULL, NULL, K_PRIO_COOP(7), 0, 0);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_TCP)
|
||||
k_thread_create(&ipv4_tcp_thread_data, ipv4_tcp_stack, STACKSIZE,
|
||||
(k_thread_entry_t)send_tcp_ipv4,
|
||||
tcp_send4, NULL, NULL, K_PRIO_COOP(7), 0, 0);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_UDP)
|
||||
k_thread_create(&ipv6_udp_thread_data, ipv6_udp_stack, STACKSIZE,
|
||||
(k_thread_entry_t)send_udp_ipv6,
|
||||
udp_send6, NULL, NULL, K_PRIO_COOP(7), 0, 0);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_TCP)
|
||||
k_thread_create(&ipv6_tcp_thread_data, ipv6_tcp_stack, STACKSIZE,
|
||||
(k_thread_entry_t)send_tcp_ipv6,
|
||||
tcp_send6, NULL, NULL, K_PRIO_COOP(7), 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
struct net_if *iface = net_if_get_default();
|
||||
int ret;
|
||||
|
||||
init_app();
|
||||
|
||||
#if defined(CONFIG_NET_L2_BLUETOOTH)
|
||||
if (bt_enable(NULL)) {
|
||||
NET_ERR("Bluetooth init failed\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (IS_ENABLED(CONFIG_NET_TCP)) {
|
||||
if (IS_ENABLED(CONFIG_NET_UDP)) {
|
||||
k_sem_init(&tcp_ready, 0, 1);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_L2_IEEE802154)
|
||||
if (ieee802154_sample_setup()) {
|
||||
NET_ERR("IEEE 802.15.4 setup failed");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ret = start_tcp();
|
||||
if (ret < 0) {
|
||||
goto quit;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_MGMT_EVENT)
|
||||
/* Subscribe to NET_IF_UP if interface is not ready */
|
||||
if (!atomic_test_bit(iface->flags, NET_IF_UP)) {
|
||||
net_mgmt_init_event_callback(&cb, event_iface_up,
|
||||
NET_EVENT_IF_UP);
|
||||
net_mgmt_add_event_callback(&cb);
|
||||
return;
|
||||
/* We start the UDP after the TCP is connected properly.
|
||||
* This is done like this so that UDP does not use all the
|
||||
* buffers as it is basically flooding the link with UDP
|
||||
* data.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_NET_UDP)) {
|
||||
k_sem_take(&tcp_ready, K_FOREVER);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
event_iface_up(NULL, NET_EVENT_IF_UP, iface);
|
||||
if (IS_ENABLED(CONFIG_NET_UDP)) {
|
||||
start_udp();
|
||||
}
|
||||
|
||||
k_sem_take(&quit_lock, K_FOREVER);
|
||||
|
||||
quit:
|
||||
NET_INFO("Stopping...");
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_UDP)) {
|
||||
stop_udp();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_TCP)) {
|
||||
stop_tcp();
|
||||
}
|
||||
}
|
||||
|
|
369
samples/net/echo_client/src/tcp.c
Normal file
369
samples/net/echo_client/src/tcp.c
Normal file
|
@ -0,0 +1,369 @@
|
|||
/* tcp.c - TCP specific code for echo client */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#if 1
|
||||
#define SYS_LOG_DOMAIN "echo-client"
|
||||
#define NET_SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
|
||||
#define NET_LOG_ENABLED 1
|
||||
#endif
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <net/net_pkt.h>
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_context.h>
|
||||
|
||||
#include <net/net_app.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static struct net_app_ctx tcp6;
|
||||
static struct net_app_ctx tcp4;
|
||||
|
||||
static int connected_count;
|
||||
|
||||
/* Note that both tcp and udp can share the same pool but in this
|
||||
* example the UDP context and TCP context have separate pools.
|
||||
*/
|
||||
#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
|
||||
NET_PKT_TX_SLAB_DEFINE(echo_tx_tcp, 15);
|
||||
NET_PKT_DATA_POOL_DEFINE(echo_data_tcp, 30);
|
||||
|
||||
static struct k_mem_slab *tx_tcp_slab(void)
|
||||
{
|
||||
return &echo_tx_tcp;
|
||||
}
|
||||
|
||||
static struct net_buf_pool *data_tcp_pool(void)
|
||||
{
|
||||
return &echo_data_tcp;
|
||||
}
|
||||
#else
|
||||
#define tx_tcp_slab NULL
|
||||
#define data_tcp_pool NULL
|
||||
#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS)
|
||||
#define HOSTNAME "localhost" /* for cert verification if that is enabled */
|
||||
|
||||
/* The result buf size is set to large enough so that we can receive max size
|
||||
* buf back. Note that mbedtls needs also be configured to have equal size
|
||||
* value for its buffer size. See MBEDTLS_SSL_MAX_CONTENT_LEN option in TLS
|
||||
* config file.
|
||||
*/
|
||||
#define RESULT_BUF_SIZE 1500
|
||||
static u8_t tls_result_ipv6[RESULT_BUF_SIZE];
|
||||
static u8_t tls_result_ipv4[RESULT_BUF_SIZE];
|
||||
|
||||
#if !defined(CONFIG_NET_APP_TLS_STACK_SIZE)
|
||||
#define CONFIG_NET_APP_TLS_STACK_SIZE 6144
|
||||
#endif /* CONFIG_NET_APP_TLS_STACK_SIZE */
|
||||
|
||||
#define INSTANCE_INFO "Zephyr TLS echo-client #1"
|
||||
|
||||
/* Note that each net_app context needs its own stack as there will be
|
||||
* a separate thread needed.
|
||||
*/
|
||||
NET_STACK_DEFINE(NET_APP_TLS_IPv4, net_app_tls_stack_ipv4,
|
||||
CONFIG_NET_APP_TLS_STACK_SIZE, CONFIG_NET_APP_TLS_STACK_SIZE);
|
||||
|
||||
NET_STACK_DEFINE(NET_APP_TLS_IPv6, net_app_tls_stack_ipv6,
|
||||
CONFIG_NET_APP_TLS_STACK_SIZE, CONFIG_NET_APP_TLS_STACK_SIZE);
|
||||
|
||||
NET_APP_TLS_POOL_DEFINE(ssl_pool, 10);
|
||||
#else
|
||||
#define tls_result_ipv6 NULL
|
||||
#define tls_result_ipv4 NULL
|
||||
#define net_app_tls_stack_ipv4 NULL
|
||||
#define net_app_tls_stack_ipv6 NULL
|
||||
#endif /* CONFIG_NET_APP_TLS */
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS)
|
||||
/* Load the certificates and private RSA key. */
|
||||
|
||||
#include "test_certs.h"
|
||||
|
||||
static int setup_cert(struct net_app_ctx *ctx, void *cert)
|
||||
{
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
|
||||
mbedtls_ssl_conf_psk(&ctx->tls.mbedtls.conf,
|
||||
client_psk, sizeof(client_psk),
|
||||
(const unsigned char *)client_psk_id,
|
||||
sizeof(client_psk_id) - 1);
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
{
|
||||
mbedtls_x509_crt *ca_cert = cert;
|
||||
int ret;
|
||||
|
||||
ret = mbedtls_x509_crt_parse_der(ca_cert,
|
||||
ca_certificate,
|
||||
sizeof(ca_certificate));
|
||||
if (ret != 0) {
|
||||
NET_ERR("mbedtls_x509_crt_parse_der failed "
|
||||
"(-0x%x)", -ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_ca_chain(&ctx->tls.mbedtls.conf,
|
||||
ca_cert, NULL);
|
||||
|
||||
/* In this example, we skip the certificate checks. In real
|
||||
* life scenarios, one should always verify the certificates.
|
||||
*/
|
||||
mbedtls_ssl_conf_authmode(&ctx->tls.mbedtls.conf,
|
||||
MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
|
||||
mbedtls_ssl_conf_cert_profile(&ctx->tls.mbedtls.conf,
|
||||
&mbedtls_x509_crt_profile_default);
|
||||
#define VERIFY_CERTS 0
|
||||
#if VERIFY_CERTS
|
||||
mbedtls_ssl_conf_authmode(&ctx->tls.mbedtls.conf,
|
||||
MBEDTLS_SSL_VERIFY_OPTIONAL);
|
||||
#else
|
||||
;
|
||||
#endif /* VERIFY_CERTS */
|
||||
}
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_NET_APP_TLS */
|
||||
|
||||
static void send_tcp_data(struct net_app_ctx *ctx,
|
||||
struct data *data)
|
||||
{
|
||||
struct net_pkt *pkt;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
data->expecting_tcp = sys_rand32_get() % ipsum_len;
|
||||
} while (data->expecting_tcp == 0);
|
||||
|
||||
data->received_tcp = 0;
|
||||
|
||||
pkt = prepare_send_pkt(ctx, data->proto, data->expecting_tcp);
|
||||
if (!pkt) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = net_pkt_get_len(pkt);
|
||||
|
||||
NET_ASSERT_INFO(data->expecting_tcp == len,
|
||||
"%s data to send %d bytes, real len %zu",
|
||||
data->proto, data->expecting_tcp, len);
|
||||
|
||||
ret = net_app_send_pkt(ctx, pkt, NULL, 0, K_FOREVER,
|
||||
UINT_TO_POINTER(len));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot send %s data to peer (%d)", data->proto, ret);
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
static bool compare_tcp_data(struct net_pkt *pkt, int expecting_len,
|
||||
int received_len)
|
||||
{
|
||||
u8_t *ptr = net_pkt_appdata(pkt);
|
||||
const char *start;
|
||||
int pos = 0;
|
||||
struct net_buf *frag;
|
||||
int len;
|
||||
|
||||
/* frag will point to first fragment with IP header in it.
|
||||
*/
|
||||
frag = pkt->frags;
|
||||
|
||||
/* Do not include the protocol headers for the first fragment.
|
||||
* The remaining fragments contain only data so the user data
|
||||
* length is directly the fragment len.
|
||||
*/
|
||||
len = frag->len - (ptr - frag->data);
|
||||
|
||||
start = lorem_ipsum + received_len;
|
||||
|
||||
while (frag) {
|
||||
if (memcmp(ptr, start + pos, len)) {
|
||||
NET_DBG("Invalid data received");
|
||||
return false;
|
||||
}
|
||||
|
||||
pos += len;
|
||||
|
||||
frag = frag->frags;
|
||||
if (!frag) {
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = frag->data;
|
||||
len = frag->len;
|
||||
}
|
||||
|
||||
NET_DBG("Compared %d bytes, all ok", net_pkt_appdatalen(pkt));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void tcp_received(struct net_app_ctx *ctx,
|
||||
struct net_pkt *pkt,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
struct data *data = ctx->user_data;
|
||||
|
||||
ARG_UNUSED(user_data);
|
||||
ARG_UNUSED(status);
|
||||
|
||||
if (!pkt || net_pkt_appdatalen(pkt) == 0) {
|
||||
if (pkt) {
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
NET_DBG("Sent %d bytes, received %u bytes",
|
||||
data->expecting_tcp, net_pkt_appdatalen(pkt));
|
||||
|
||||
if (!compare_tcp_data(pkt, data->expecting_tcp, data->received_tcp)) {
|
||||
NET_DBG("Data mismatch");
|
||||
} else {
|
||||
data->received_tcp += net_pkt_appdatalen(pkt);
|
||||
}
|
||||
|
||||
if (data->expecting_tcp <= data->received_tcp) {
|
||||
/* Send more data */
|
||||
send_tcp_data(ctx, data);
|
||||
}
|
||||
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
|
||||
static void tcp_connected(struct net_app_ctx *ctx,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
if (status < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
connected_count++;
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_UDP)) {
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6) &&
|
||||
IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
if (connected_count > 1) {
|
||||
k_sem_give(&tcp_ready);
|
||||
}
|
||||
} else {
|
||||
k_sem_give(&tcp_ready);
|
||||
}
|
||||
}
|
||||
|
||||
send_tcp_data(ctx, user_data);
|
||||
}
|
||||
|
||||
static int connect_tcp(struct net_app_ctx *ctx, const char *peer,
|
||||
void *user_data, u8_t *result_buf,
|
||||
size_t result_buf_len, u8_t *stack, size_t stack_size)
|
||||
{
|
||||
struct data *data = user_data;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_tcp_client(ctx, NULL, NULL, peer, PEER_PORT,
|
||||
WAIT_TIME, user_data);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot init %s TCP client (%d)", data->proto, ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
|
||||
net_app_set_net_pkt_pool(ctx, tx_tcp_slab, data_tcp_pool);
|
||||
#endif
|
||||
|
||||
ret = net_app_set_cb(ctx, tcp_connected, tcp_received, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot set callbacks (%d)", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS)
|
||||
ret = net_app_client_tls(ctx,
|
||||
result_buf,
|
||||
result_buf_len,
|
||||
INSTANCE_INFO,
|
||||
strlen(INSTANCE_INFO),
|
||||
setup_cert,
|
||||
HOSTNAME,
|
||||
NULL,
|
||||
&ssl_pool,
|
||||
stack,
|
||||
stack_size);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot init TLS");
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = net_app_connect(ctx, CONNECT_TIME);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot connect TCP (%d)", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int start_tcp(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||
ret = connect_tcp(&tcp6, CONFIG_NET_APP_PEER_IPV6_ADDR,
|
||||
&conf.ipv6, tls_result_ipv6,
|
||||
sizeof(tls_result_ipv6),
|
||||
net_app_tls_stack_ipv6,
|
||||
K_THREAD_STACK_SIZEOF(
|
||||
net_app_tls_stack_ipv6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot init IPv6 TCP client (%d)", ret);
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
ret = connect_tcp(&tcp4, CONFIG_NET_APP_PEER_IPV4_ADDR,
|
||||
&conf.ipv4, tls_result_ipv4,
|
||||
sizeof(tls_result_ipv4),
|
||||
net_app_tls_stack_ipv4,
|
||||
K_THREAD_STACK_SIZEOF(
|
||||
net_app_tls_stack_ipv4));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot init IPv6 TCP client (%d)", ret);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void stop_tcp(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||
net_app_close(&tcp6);
|
||||
net_app_release(&tcp6);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
net_app_close(&tcp4);
|
||||
net_app_release(&tcp4);
|
||||
}
|
||||
}
|
122
samples/net/echo_client/src/test_certs.h
Normal file
122
samples/net/echo_client/src/test_certs.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __TEST_CERTS_H__
|
||||
#define __TEST_CERTS_H__
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
/* This is the same cert as what is found in net-tools/echo-apps-cert.pem file
|
||||
*/
|
||||
static const unsigned char ca_certificate[] = {
|
||||
0x30, 0x82, 0x02, 0xfb, 0x30, 0x82, 0x01, 0xe3,
|
||||
0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
|
||||
0xee, 0x10, 0x1f, 0xc1, 0xf2, 0x30, 0xe9, 0x11,
|
||||
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
|
||||
0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30,
|
||||
0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
|
||||
0x04, 0x03, 0x0c, 0x09, 0x6c, 0x6f, 0x63, 0x61,
|
||||
0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x1e, 0x17,
|
||||
0x0d, 0x31, 0x37, 0x30, 0x36, 0x32, 0x36, 0x31,
|
||||
0x30, 0x35, 0x36, 0x31, 0x30, 0x5a, 0x17, 0x0d,
|
||||
0x34, 0x34, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30,
|
||||
0x35, 0x36, 0x31, 0x30, 0x5a, 0x30, 0x14, 0x31,
|
||||
0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03,
|
||||
0x0c, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68,
|
||||
0x6f, 0x73, 0x74, 0x30, 0x82, 0x01, 0x22, 0x30,
|
||||
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82,
|
||||
0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02,
|
||||
0x82, 0x01, 0x01, 0x00, 0xc6, 0x00, 0x7b, 0x0d,
|
||||
0xd1, 0x17, 0x43, 0x6b, 0xa9, 0xa7, 0x79, 0x9c,
|
||||
0x0f, 0x8d, 0x77, 0x91, 0xd2, 0xf7, 0x47, 0x35,
|
||||
0xb3, 0x17, 0xe2, 0xdd, 0xed, 0x6d, 0x01, 0xf9,
|
||||
0xb1, 0x92, 0xc9, 0x48, 0x80, 0xe0, 0x1f, 0xcf,
|
||||
0xb7, 0xa4, 0x5f, 0xf0, 0x36, 0xea, 0xbf, 0xe1,
|
||||
0x33, 0xf8, 0xa9, 0xc5, 0xe6, 0xd4, 0x19, 0x8b,
|
||||
0x82, 0x25, 0xd9, 0x19, 0x74, 0x70, 0x79, 0xec,
|
||||
0xc6, 0x68, 0xc9, 0xef, 0xce, 0x1a, 0xa9, 0xf0,
|
||||
0xb7, 0x01, 0x35, 0x91, 0xff, 0xd3, 0x75, 0x6e,
|
||||
0x02, 0xba, 0x06, 0x9a, 0x2a, 0xac, 0xcf, 0x22,
|
||||
0xbf, 0x2b, 0x1f, 0xc1, 0x72, 0x38, 0x22, 0x35,
|
||||
0xea, 0xda, 0x6f, 0xdd, 0x67, 0xa2, 0x2b, 0x19,
|
||||
0x38, 0x19, 0x0e, 0x44, 0xd1, 0x71, 0x38, 0xb4,
|
||||
0x6d, 0x26, 0x85, 0xd6, 0xc6, 0xbe, 0xc1, 0x6f,
|
||||
0x3c, 0xee, 0xaf, 0x94, 0x3c, 0x05, 0x56, 0x4e,
|
||||
0xad, 0x53, 0x81, 0x8b, 0xd4, 0x23, 0x31, 0x69,
|
||||
0x72, 0x27, 0x93, 0xb4, 0x3a, 0xac, 0x23, 0xe8,
|
||||
0x10, 0xae, 0xf5, 0x9f, 0x0b, 0xa6, 0x6e, 0xd3,
|
||||
0x73, 0xca, 0x18, 0x11, 0xca, 0xbe, 0x71, 0x00,
|
||||
0x56, 0x29, 0x34, 0x54, 0xcc, 0xda, 0x29, 0x5b,
|
||||
0x26, 0x29, 0x99, 0x4d, 0x5f, 0xa1, 0xa6, 0xb9,
|
||||
0xcb, 0x2b, 0xb2, 0x0f, 0x10, 0x00, 0x04, 0xa9,
|
||||
0x11, 0x2c, 0x48, 0xb1, 0x99, 0xa5, 0xca, 0x7c,
|
||||
0x67, 0xa5, 0xbe, 0x14, 0x20, 0x12, 0xb7, 0x3b,
|
||||
0x7a, 0x4f, 0xdc, 0xc7, 0xd5, 0x2d, 0x04, 0x66,
|
||||
0xbb, 0xf5, 0x0c, 0xcd, 0xf1, 0x32, 0x39, 0xd7,
|
||||
0x51, 0x9b, 0xba, 0xdb, 0xf1, 0xa7, 0xfe, 0x2d,
|
||||
0x9a, 0xe6, 0x9c, 0x6b, 0x54, 0xda, 0xf1, 0xdd,
|
||||
0x48, 0xf9, 0xd7, 0xf0, 0x35, 0x7c, 0x8e, 0x24,
|
||||
0x7e, 0x44, 0x2f, 0xf3, 0xbf, 0x39, 0x0e, 0x96,
|
||||
0xab, 0xe1, 0x45, 0x03, 0x8b, 0x54, 0xdc, 0xe1,
|
||||
0xb6, 0x11, 0x81, 0x21, 0x02, 0x03, 0x01, 0x00,
|
||||
0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06,
|
||||
0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14,
|
||||
0xa4, 0xef, 0x6d, 0xdc, 0x9b, 0x23, 0xc5, 0x3a,
|
||||
0xdd, 0x34, 0xd9, 0x01, 0x1c, 0x68, 0x03, 0x53,
|
||||
0xae, 0x92, 0xc2, 0xc9, 0x30, 0x1f, 0x06, 0x03,
|
||||
0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
|
||||
0x14, 0xa4, 0xef, 0x6d, 0xdc, 0x9b, 0x23, 0xc5,
|
||||
0x3a, 0xdd, 0x34, 0xd9, 0x01, 0x1c, 0x68, 0x03,
|
||||
0x53, 0xae, 0x92, 0xc2, 0xc9, 0x30, 0x0c, 0x06,
|
||||
0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03,
|
||||
0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a,
|
||||
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
|
||||
0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x67,
|
||||
0x65, 0xbf, 0x93, 0x89, 0xde, 0x4f, 0x71, 0xff,
|
||||
0x1c, 0x93, 0x68, 0xa0, 0x64, 0x09, 0x5e, 0x95,
|
||||
0x94, 0xf5, 0xd5, 0xf4, 0x6b, 0x20, 0x32, 0xd8,
|
||||
0x04, 0x80, 0xac, 0xf8, 0x52, 0x36, 0x7a, 0x38,
|
||||
0x83, 0xae, 0xab, 0x29, 0x22, 0x42, 0x71, 0x7e,
|
||||
0xea, 0xe5, 0x4f, 0x71, 0xac, 0x44, 0x3f, 0x9e,
|
||||
0x5e, 0x49, 0x22, 0x05, 0xee, 0xa6, 0x7b, 0xab,
|
||||
0x56, 0x2e, 0xb3, 0x9a, 0x35, 0x1a, 0x88, 0xc3,
|
||||
0x54, 0x9b, 0xfd, 0xac, 0x65, 0x54, 0xaf, 0x21,
|
||||
0xa7, 0xe0, 0xdd, 0x62, 0x29, 0x8c, 0xae, 0x26,
|
||||
0x0b, 0x84, 0x1f, 0x69, 0x78, 0x84, 0xc6, 0x7e,
|
||||
0xcf, 0xc8, 0xf5, 0x92, 0x8c, 0x05, 0xa8, 0x13,
|
||||
0x38, 0xcd, 0x0b, 0x98, 0x53, 0xfb, 0xdd, 0x8d,
|
||||
0x51, 0x90, 0xa8, 0x51, 0xfa, 0x52, 0xbe, 0x28,
|
||||
0xd4, 0x71, 0x50, 0x73, 0x1f, 0xb0, 0xb6, 0x0e,
|
||||
0x45, 0xb1, 0x47, 0x41, 0x06, 0xd9, 0x1d, 0x7a,
|
||||
0x34, 0xe7, 0x80, 0x2e, 0x0c, 0x02, 0x50, 0x97,
|
||||
0xde, 0xa8, 0x7a, 0x84, 0x2c, 0x1d, 0xf4, 0x51,
|
||||
0x56, 0xa5, 0x52, 0xb5, 0x04, 0x2e, 0xcb, 0xdd,
|
||||
0x8b, 0x2e, 0x16, 0xc6, 0xde, 0xc8, 0xe9, 0x8d,
|
||||
0xee, 0x5e, 0xb6, 0xa0, 0xe0, 0x2b, 0x85, 0x2a,
|
||||
0x89, 0x7b, 0xba, 0x68, 0x80, 0x2b, 0xfb, 0x6e,
|
||||
0x2e, 0x80, 0xe7, 0x7a, 0x97, 0x09, 0xb5, 0x2f,
|
||||
0x20, 0x8e, 0xed, 0xbc, 0x98, 0x6f, 0x95, 0xd5,
|
||||
0x5b, 0x3d, 0x26, 0x19, 0x26, 0x14, 0x39, 0x82,
|
||||
0xa8, 0xa8, 0x42, 0x46, 0xab, 0x59, 0x93, 0x47,
|
||||
0x83, 0xf7, 0x79, 0xbf, 0x73, 0xb5, 0x5d, 0x5d,
|
||||
0x78, 0xfe, 0x62, 0xac, 0xed, 0xb7, 0x1e, 0x4a,
|
||||
0xad, 0xc3, 0x99, 0x39, 0x7d, 0x3e, 0x30, 0x21,
|
||||
0x26, 0x1d, 0x66, 0xdb, 0x0d, 0xf3, 0xba, 0x87,
|
||||
0x46, 0xf0, 0x04, 0xfc, 0xc3, 0xbe, 0x84, 0x85,
|
||||
0x3c, 0x01, 0xef, 0xe0, 0x68, 0x65, 0xee,
|
||||
};
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
|
||||
const unsigned char client_psk[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
|
||||
};
|
||||
|
||||
const char client_psk_id[] = "Client_identity";
|
||||
#endif
|
||||
|
||||
#endif
|
247
samples/net/echo_client/src/udp.c
Normal file
247
samples/net/echo_client/src/udp.c
Normal file
|
@ -0,0 +1,247 @@
|
|||
/* udp.c - UDP specific code for echo client */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#if 1
|
||||
#define SYS_LOG_DOMAIN "echo-client"
|
||||
#define NET_SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
|
||||
#define NET_LOG_ENABLED 1
|
||||
#endif
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <net/net_pkt.h>
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_context.h>
|
||||
|
||||
#include <net/net_app.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static struct net_app_ctx udp6;
|
||||
static struct net_app_ctx udp4;
|
||||
|
||||
#define UDP_SLEEP K_MSEC(150)
|
||||
|
||||
/* Note that both tcp and udp can share the same pool but in this
|
||||
* example the UDP context and TCP context have separate pools.
|
||||
*/
|
||||
#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
|
||||
NET_PKT_TX_SLAB_DEFINE(echo_tx_udp, 5);
|
||||
NET_PKT_DATA_POOL_DEFINE(echo_data_udp, 20);
|
||||
|
||||
static struct k_mem_slab *tx_udp_slab(void)
|
||||
{
|
||||
return &echo_tx_udp;
|
||||
}
|
||||
|
||||
static struct net_buf_pool *data_udp_pool(void)
|
||||
{
|
||||
return &echo_data_udp;
|
||||
}
|
||||
#else
|
||||
#define tx_udp_slab NULL
|
||||
#define data_udp_pool NULL
|
||||
#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
|
||||
|
||||
static void send_udp_data(struct net_app_ctx *ctx, struct data *data)
|
||||
{
|
||||
struct net_pkt *pkt;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
data->expecting_udp = sys_rand32_get() % ipsum_len;
|
||||
|
||||
pkt = prepare_send_pkt(ctx, data->proto, data->expecting_udp);
|
||||
if (!pkt) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = net_pkt_get_len(pkt);
|
||||
|
||||
NET_ASSERT_INFO(data->expecting_udp == len,
|
||||
"Data to send %d bytes, real len %zu",
|
||||
data->expecting_udp, len);
|
||||
|
||||
ret = net_app_send_pkt(ctx, pkt, NULL, 0, K_FOREVER,
|
||||
UINT_TO_POINTER(len));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot send %s data to peer (%d)", data->proto, ret);
|
||||
|
||||
net_pkt_unref(pkt);
|
||||
}
|
||||
|
||||
k_delayed_work_submit(&data->recv, WAIT_TIME);
|
||||
}
|
||||
|
||||
static bool compare_udp_data(struct net_pkt *pkt, int expecting_len)
|
||||
{
|
||||
u8_t *ptr = net_pkt_appdata(pkt);
|
||||
struct net_buf *frag;
|
||||
int pos = 0;
|
||||
int len;
|
||||
|
||||
/* frag will now point to first fragment with IP header
|
||||
* in it.
|
||||
*/
|
||||
frag = pkt->frags;
|
||||
|
||||
/* Do not include the protocol headers in the first fragment.
|
||||
* The remaining fragments contain only data so the user data
|
||||
* length is directly the fragment len.
|
||||
*/
|
||||
len = frag->len - (ptr - frag->data);
|
||||
|
||||
while (frag) {
|
||||
if (memcmp(ptr, lorem_ipsum + pos, len)) {
|
||||
NET_DBG("Invalid data received");
|
||||
return false;
|
||||
} else {
|
||||
pos += len;
|
||||
|
||||
frag = frag->frags;
|
||||
if (!frag) {
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = frag->data;
|
||||
len = frag->len;
|
||||
}
|
||||
}
|
||||
|
||||
NET_DBG("Compared %d bytes, all ok", expecting_len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void udp_received(struct net_app_ctx *ctx,
|
||||
struct net_pkt *pkt,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
struct data *data = ctx->user_data;
|
||||
|
||||
ARG_UNUSED(user_data);
|
||||
ARG_UNUSED(status);
|
||||
|
||||
if (data->expecting_udp != net_pkt_appdatalen(pkt)) {
|
||||
NET_ERR("Sent %d bytes, received %u bytes",
|
||||
data->expecting_udp, net_pkt_appdatalen(pkt));
|
||||
}
|
||||
|
||||
if (!compare_udp_data(pkt, data->expecting_udp)) {
|
||||
NET_DBG("Data mismatch");
|
||||
}
|
||||
|
||||
net_pkt_unref(pkt);
|
||||
|
||||
k_delayed_work_cancel(&data->recv);
|
||||
|
||||
/* Do not flood the link if we have also TCP configured */
|
||||
if (IS_ENABLED(CONFIG_NET_TCP)) {
|
||||
k_sleep(UDP_SLEEP);
|
||||
}
|
||||
|
||||
send_udp_data(ctx, data);
|
||||
}
|
||||
|
||||
/* We can start to send data when UDP is "connected" */
|
||||
static void udp_connected(struct net_app_ctx *ctx,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
struct data *data = user_data;
|
||||
|
||||
data->udp = ctx;
|
||||
|
||||
send_udp_data(ctx, data);
|
||||
}
|
||||
|
||||
static int connect_udp(struct net_app_ctx *ctx, const char *peer,
|
||||
void *user_data)
|
||||
{
|
||||
struct data *data = user_data;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_udp_client(ctx, NULL, NULL, peer, PEER_PORT,
|
||||
WAIT_TIME, user_data);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot init %s UDP client (%d)", data->proto, ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
|
||||
net_app_set_net_pkt_pool(ctx, tx_udp_slab, data_udp_pool);
|
||||
#endif
|
||||
|
||||
ret = net_app_set_cb(ctx, udp_connected, udp_received, NULL, NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot set callbacks (%d)", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = net_app_connect(ctx, CONNECT_TIME);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot connect UDP (%d)", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void wait_reply(struct k_work *work)
|
||||
{
|
||||
/* This means that we did not receive response in time. */
|
||||
struct data *data = CONTAINER_OF(work, struct data, recv);
|
||||
|
||||
NET_ERR("Data packet not received");
|
||||
|
||||
/* Send a new packet at this point */
|
||||
send_udp_data(data->udp, data);
|
||||
}
|
||||
|
||||
void start_udp(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||
k_delayed_work_init(&conf.ipv6.recv, wait_reply);
|
||||
|
||||
ret = connect_udp(&udp6, CONFIG_NET_APP_PEER_IPV6_ADDR,
|
||||
&conf.ipv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot init IPv6 UDP client (%d)", ret);
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
k_delayed_work_init(&conf.ipv4.recv, wait_reply);
|
||||
|
||||
ret = connect_udp(&udp4, CONFIG_NET_APP_PEER_IPV4_ADDR,
|
||||
&conf.ipv4);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot init IPv4 UDP client (%d)", ret);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void stop_udp(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||
net_app_close(&udp6);
|
||||
net_app_release(&udp6);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
net_app_close(&udp4);
|
||||
net_app_release(&udp4);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue