net: app: Remove net-app API files
The net-app API is removed. Users should use the BSD socket API for application development. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
05f411523d
commit
d1162600e9
|
@ -1,220 +0,0 @@
|
|||
.. _net_app_api:
|
||||
|
||||
Network Application API
|
||||
#######################
|
||||
|
||||
The Network Application (net-app) API allows applications to:
|
||||
|
||||
**Initialize**
|
||||
The application for networking use. This means, for example,
|
||||
that if the application needs to have an IPv4 address, and if DHCPv4 is
|
||||
enabled, then the net-app API will make sure that the device will get an
|
||||
IPv4 address before the application is started.
|
||||
|
||||
**Set**
|
||||
Various options for the networking subsystem. This means that if the
|
||||
user has set options like IP addresses, IEEE 802.15.4 channel etc. in the
|
||||
project configuration file, then those settings are applied to the system
|
||||
before the application starts.
|
||||
|
||||
**Create**
|
||||
A simple TCP/UDP server or client application. The net-app API
|
||||
has functions that make it easy to create a simple TCP or UDP based network
|
||||
application. The net-app API also provides transparent TLS and DTLS support
|
||||
for the application.
|
||||
|
||||
The net-app API functionality is enabled by :option:`CONFIG_NET_APP` option.
|
||||
The current net-app API implementation is still experimental and may change and
|
||||
improve in future releases.
|
||||
|
||||
Initialization
|
||||
**************
|
||||
|
||||
The net-app API provides a :cpp:func:`net_app_init()` function that can
|
||||
configure the networking subsystem for the application. The following
|
||||
configuration options control this configuration:
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_AUTO_INIT`
|
||||
automatically configures the system according to other configuration options.
|
||||
The user does not need to call :cpp:func:`net_app_init()` in this case as that
|
||||
function will be automatically called when the system boots. This option is
|
||||
enabled by default.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_INIT_TIMEOUT`
|
||||
specifies how long to wait for the network configuration during the system
|
||||
boot. For example, if DHCPv4 is enabled, and if the IPv4 address discovery
|
||||
takes too long or the DHCPv4 server is not found, the system will resume
|
||||
booting after this number of seconds.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_NEED_IPV6`
|
||||
specifies that the application needs IPv6 connectivity. The
|
||||
:cpp:func:`net_app_init()` function will wait until it is able to setup an
|
||||
IPv6 address for the system before continuing. This means that the IPv6
|
||||
duplicate address detection (DAD) has finished and the system has properly
|
||||
setup the IPv6 address.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_NEED_IPV6_ROUTER`
|
||||
specifies that the application needs IPv6 router connectivity; i.e., it needs
|
||||
access to external networks (such as the Internet). The
|
||||
:cpp:func:`net_app_init()` function will wait until it receives a router
|
||||
advertisement (RA) message from the IPv6 router before continuing.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_NEED_IPV4`
|
||||
specifies that the application needs IPv4 connectivity. The
|
||||
:cpp:func:`net_app_init()` function will wait, unless a static IP address is
|
||||
configured, until it is able to setup an IPv4 address for the network
|
||||
subsystem.
|
||||
|
||||
Setup
|
||||
*****
|
||||
|
||||
Various system level network configuration options can be added to the project
|
||||
configuration file. These settings are enabled by the
|
||||
:option:`CONFIG_NET_CONFIG_SETTINGS` configuration option. This option is disabled
|
||||
by default, and other net-app options may also be disabled by default if
|
||||
generic support for the networking feature is disabled. For example, the IPv6
|
||||
net-app options are only available if generic IPv6 support is enabled.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_MY_IPV6_ADDR`
|
||||
This option sets a static IPv6 address for the system. This is typically only
|
||||
useful in device testing as normally the system should use SLAAC (IPv6
|
||||
Stateless Address Auto Configuration), which is enabled by default in the
|
||||
system. The system can be configured to use multiple IPv6 addresses; this is
|
||||
controlled by the :option:`CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT`
|
||||
configuration option.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_PEER_IPV6_ADDR`
|
||||
This option specifies what is the peer device IPv6 address. This is only
|
||||
useful when testing client/server type applications. This peer address is
|
||||
typically used as a parameter when calling :cpp:func:`net_app_connect()`.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_MY_IPV4_ADDR`
|
||||
This option sets a static IPv4 address for the system. This is typically
|
||||
useful only in device testing as normally the system should use DHCPv4 to
|
||||
discover the IPv4 address.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_PEER_IPV4_ADDR`
|
||||
This option specifies what is the peer device IPv4 address. This is only
|
||||
useful when testing client/server type applications. This peer address is
|
||||
typically used as a parameter when connecting to other device.
|
||||
|
||||
The following options are only available if IEEE 802.15.4 wireless network
|
||||
technology support is enabled.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_IEEE802154_DEV_NAME`
|
||||
This option specifies the name of the IEEE 802.15.4 device.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_IEEE802154_PAN_ID`
|
||||
This option specifies the used PAN identifier.
|
||||
Note that the PAN id can be changed at runtime if needed.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_IEEE802154_CHANNEL`
|
||||
This option specifies the used radio channel.
|
||||
Note that the used channel can be changed at runtime if needed.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_IEEE802154_RADIO_TX_POWER`
|
||||
This option specifies the initial radio TX power level. The TX power level can
|
||||
be changed at runtime if needed.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_IEEE802154_SECURITY_KEY`
|
||||
This option specifies the initially used security key. The security key can be
|
||||
changed at runtime if needed.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_IEEE802154_SECURITY_KEY_MODE`
|
||||
This option specifies the initially used security key mode. The security key
|
||||
mode can be changed at runtime if needed.
|
||||
|
||||
:option:`CONFIG_NET_CONFIG_IEEE802154_SECURITY_LEVEL`
|
||||
This option specifies the initially used security level. The used security
|
||||
level can be changed at runtime if needed.
|
||||
|
||||
Client / Server Applications
|
||||
****************************
|
||||
|
||||
The net-app API provides functions that enable the application to create
|
||||
client / server applications easily. If needed, the applications can
|
||||
have the communication secured by TLS (for TCP connections) or DTLS (for
|
||||
UDP connections) automatically.
|
||||
|
||||
A simple **TCP server** application would make the following net-app API
|
||||
function calls:
|
||||
|
||||
* :cpp:func:`net_app_init_tcp_server()` to configure a local address and TCP
|
||||
port.
|
||||
|
||||
* :cpp:func:`net_app_set_cb()` to configure callback functions to invoke in
|
||||
response to events, such as data reception.
|
||||
|
||||
* :cpp:func:`net_app_server_tls()` will optionally setup the system for secured
|
||||
connections. To enable the TLS server, also call the
|
||||
:cpp:func:`net_app_server_tls_enable()` function.
|
||||
|
||||
* :cpp:func:`net_app_listen()` will start listening for new client connections.
|
||||
|
||||
Creating a **UDP server** is also very easy:
|
||||
|
||||
* :cpp:func:`net_app_init_udp_server()` to configure a local address and UDP
|
||||
port.
|
||||
|
||||
* :cpp:func:`net_app_set_cb()` to configure callback functions to invoke in
|
||||
response to events, such as data reception.
|
||||
|
||||
* :cpp:func:`net_app_server_tls()` will optionally setup the system for secured
|
||||
connections. To enable the DTLS server, also call the
|
||||
:cpp:func:`net_app_server_tls_enable()` function.
|
||||
|
||||
* :cpp:func:`net_app_listen()` will start listening for new client connections.
|
||||
|
||||
If the server wants to stop listening for connections, it can call
|
||||
:cpp:func:`net_app_release()`. After this, if the application wants to start
|
||||
listening for incoming connections again, it must call the server
|
||||
initialization functions.
|
||||
|
||||
For TLS/DTLS connections, the server can be disabled by a call to
|
||||
:cpp:func:`net_app_server_tls_disable()`. There are separate enable/disable
|
||||
functions for TLS support because we need a separate crypto thread for calling
|
||||
mbedtls crypto API functions. The enable/disable TLS functions will
|
||||
either create the TLS thread or kill it.
|
||||
|
||||
A simple **TCP client** application would make the following net-app API
|
||||
function calls:
|
||||
|
||||
* :cpp:func:`net_app_init_tcp_client()` to configure a local address, peer
|
||||
address and TCP port. If the DNS resolver support is enabled in the
|
||||
project configuration file, then the peer address can be given as a hostname,
|
||||
and the API tries to resolve it to IP address before connecting.
|
||||
|
||||
* :cpp:func:`net_app_set_cb()` to configure callback functions to invoke in
|
||||
response to events, such as data reception.
|
||||
|
||||
* :cpp:func:`net_app_client_tls()` will optionally setup the system for secured
|
||||
connections. The TLS crypto thread will be automatically created when the
|
||||
application calls :cpp:func:`net_app_connect()` function.
|
||||
|
||||
* :cpp:func:`net_app_connect()` will initiate a new connection to the peer host.
|
||||
|
||||
Creating a **UDP client** is also very easy:
|
||||
|
||||
* :cpp:func:`net_app_init_udp_client()` to configure a local address, peer
|
||||
address and UDP port. If peer name is a hostname, then it will be
|
||||
automatically resolved to IP address if DNS resolver is enabled.
|
||||
|
||||
* :cpp:func:`net_app_set_cb()` to configure callback functions to invoke in
|
||||
response to events, such as data reception.
|
||||
|
||||
* :cpp:func:`net_app_client_tls()` will optionally setup the system for secured
|
||||
connections. The DTLS crypto thread will be automatically created when the
|
||||
application calls :cpp:func:`net_app_connect()` function.
|
||||
|
||||
* :cpp:func:`net_app_connect()` will initiate a new connection to the peer host.
|
||||
As the UDP is connectionless protocol, this function is very simple and it
|
||||
will just call the connected callback if that is defined.
|
||||
|
||||
As both the ``echo_server`` and ``echo_client`` applications use net-app API
|
||||
functions, please see those applications for more detailed usage examples.
|
||||
|
||||
The `net-tools`_ project has information how to test the system if TLS and
|
||||
DTLS support is enabled. See the **README** file in that project for more
|
||||
information.
|
||||
|
||||
.. _`net-tools`: https://github.com/zephyrproject-rtos/net-tools
|
|
@ -1,994 +0,0 @@
|
|||
/** @file
|
||||
* @brief Common routines needed in various network applications.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_NET_NET_APP_H_
|
||||
#define ZEPHYR_INCLUDE_NET_NET_APP_H_
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
|
||||
#if defined(CONFIG_MBEDTLS)
|
||||
#if !defined(CONFIG_MBEDTLS_CFG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include CONFIG_MBEDTLS_CFG_FILE
|
||||
#endif /* CONFIG_MBEDTLS_CFG_FILE */
|
||||
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#define mbedtls_time_t time_t
|
||||
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
|
||||
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
|
||||
#endif /* MBEDTLS_PLATFORM_C */
|
||||
|
||||
#include <mbedtls/ssl_cookie.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/net_sockets.h>
|
||||
#include <mbedtls/x509.h>
|
||||
#include <mbedtls/x509_crt.h>
|
||||
#include <mbedtls/ssl.h>
|
||||
#include <mbedtls/error.h>
|
||||
#include <mbedtls/debug.h>
|
||||
#endif /* CONFIG_MBEDTLS */
|
||||
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
|
||||
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_pkt.h>
|
||||
#include <net/net_context.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Network application library
|
||||
* @defgroup net_app Network Application Library
|
||||
* @ingroup networking
|
||||
* @{
|
||||
*/
|
||||
|
||||
enum net_app_type {
|
||||
NET_APP_UNSPEC = 0,
|
||||
NET_APP_SERVER,
|
||||
NET_APP_CLIENT,
|
||||
} __packed;
|
||||
|
||||
struct net_app_ctx;
|
||||
|
||||
/**
|
||||
* @typedef net_app_recv_cb_t
|
||||
* @brief Network data receive callback.
|
||||
*
|
||||
* @details The recv callback is called after a network data is
|
||||
* received.
|
||||
*
|
||||
* @param ctx The context to use.
|
||||
* @param pkt Network buffer that is received. If the pkt is not NULL,
|
||||
* then the callback will own the buffer and it needs to to unref the pkt
|
||||
* as soon as it has finished working with it. On EOF, pkt will be NULL.
|
||||
* @param status Value is set to 0 if some data or the connection is
|
||||
* at EOF, <0 if there was an error receiving data, in this case the
|
||||
* pkt parameter is set to NULL.
|
||||
* @param user_data The user data given in init call.
|
||||
*/
|
||||
typedef void (*net_app_recv_cb_t)(struct net_app_ctx *ctx,
|
||||
struct net_pkt *pkt,
|
||||
int status,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @typedef net_app_connect_cb_t
|
||||
* @brief Connection callback.
|
||||
*
|
||||
* @details The connect callback is called after a connection is being
|
||||
* established.
|
||||
*
|
||||
* @param ctx The context to use.
|
||||
* @param status Status of the connection establishment. This is 0
|
||||
* if the connection was established successfully, <0 if there was an
|
||||
* error.
|
||||
* @param user_data The user data given in init call.
|
||||
*/
|
||||
typedef void (*net_app_connect_cb_t)(struct net_app_ctx *ctx,
|
||||
int status,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @typedef net_app_send_cb_t
|
||||
* @brief Network data send callback.
|
||||
*
|
||||
* @details The send callback is called after a network data is
|
||||
* sent.
|
||||
*
|
||||
* @param ctx The context to use.
|
||||
* @param status Value is set to 0 if all data was sent ok, <0 if
|
||||
* there was an error sending data. >0 amount of data that was
|
||||
* sent when not all data was sent ok.
|
||||
* @param user_data_send The user data given in net_app_send() call.
|
||||
* @param user_data The user data given in init call.
|
||||
*/
|
||||
typedef void (*net_app_send_cb_t)(struct net_app_ctx *ctx,
|
||||
int status,
|
||||
void *user_data_send,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @typedef net_app_close_cb_t
|
||||
* @brief Close callback.
|
||||
*
|
||||
* @details The close callback is called after a connection is being
|
||||
* shutdown.
|
||||
*
|
||||
* @param ctx The context to use.
|
||||
* @param status Error code for the closing.
|
||||
* @param user_data The user data given in init call.
|
||||
*/
|
||||
typedef void (*net_app_close_cb_t)(struct net_app_ctx *ctx,
|
||||
int status,
|
||||
void *user_data);
|
||||
|
||||
/** Network application callbacks */
|
||||
struct net_app_cb {
|
||||
/** Function that is called when a connection is established.
|
||||
*/
|
||||
net_app_connect_cb_t connect;
|
||||
|
||||
/** Function that is called when data is received from network.
|
||||
*/
|
||||
net_app_recv_cb_t recv;
|
||||
|
||||
/** Function that is called when net_pkt is sent.
|
||||
*/
|
||||
net_app_send_cb_t send;
|
||||
|
||||
/** Function that is called when connection is shutdown.
|
||||
*/
|
||||
net_app_close_cb_t close;
|
||||
};
|
||||
|
||||
/* This is the same prototype as what net_context_sendto() has
|
||||
* so that we can override the sending of the data for TLS traffic.
|
||||
*/
|
||||
typedef int (*net_app_send_data_t)(struct net_pkt *pkt,
|
||||
const struct sockaddr *dst_addr,
|
||||
socklen_t addrlen,
|
||||
net_context_send_cb_t cb,
|
||||
s32_t timeout,
|
||||
void *token,
|
||||
void *user_data);
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
|
||||
/* Internal information for managing TLS data */
|
||||
struct tls_context {
|
||||
struct net_pkt *rx_pkt;
|
||||
struct net_buf *hdr; /* IP + UDP/TCP header */
|
||||
struct net_buf *frag;
|
||||
struct k_sem tx_sem;
|
||||
struct k_fifo tx_rx_fifo;
|
||||
int remaining;
|
||||
#if defined(CONFIG_NET_APP_DTLS) && defined(CONFIG_NET_APP_SERVER)
|
||||
char client_id;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* This struct is used to pass data to TLS thread when reading or sending
|
||||
* data.
|
||||
*/
|
||||
struct net_app_fifo_block {
|
||||
struct k_mem_block block;
|
||||
struct net_pkt *pkt;
|
||||
void *token; /* Used when sending data */
|
||||
net_context_send_cb_t cb;
|
||||
u8_t dir;
|
||||
};
|
||||
|
||||
#define NET_APP_TLS_POOL_DEFINE(name, count) \
|
||||
K_MEM_POOL_DEFINE(name, sizeof(struct net_app_fifo_block), \
|
||||
sizeof(struct net_app_fifo_block), count, sizeof(int))
|
||||
|
||||
#if defined(CONFIG_NET_APP_SERVER)
|
||||
/**
|
||||
* @typedef net_app_cert_cb_t
|
||||
* @brief Callback used when the API user needs to setup the certs.
|
||||
*
|
||||
* @param ctx Net app context.
|
||||
* @param cert MBEDTLS certificate
|
||||
* @param pkey MBEDTLS private key
|
||||
*
|
||||
* @return 0 if ok, <0 if there is an error
|
||||
*/
|
||||
typedef int (*net_app_cert_cb_t)(struct net_app_ctx *ctx,
|
||||
mbedtls_x509_crt *cert,
|
||||
mbedtls_pk_context *pkey);
|
||||
#endif /* CONFIG_NET_APP_SERVER */
|
||||
|
||||
#if defined(CONFIG_NET_APP_CLIENT)
|
||||
/**
|
||||
* @typedef net_app_ca_cert_cb_t
|
||||
* @brief Callback used when the API user needs to setup certs.
|
||||
*
|
||||
* @param ctx Net app client context.
|
||||
* @param ca_cert MBEDTLS certificate. This is of type mbedtls_x509_crt
|
||||
* if MBEDTLS_X509_CRT_PARSE_C is defined.
|
||||
*
|
||||
* @return 0 if ok, <0 if there is an error
|
||||
*/
|
||||
typedef int (*net_app_ca_cert_cb_t)(struct net_app_ctx *ctx,
|
||||
void *ca_cert);
|
||||
#endif /* CONFIG_NET_APP_CLIENT */
|
||||
|
||||
/**
|
||||
* @typedef net_app_entropy_src_cb_t
|
||||
* @brief Callback used when the API user needs to setup the entropy source.
|
||||
* @details This is the same as mbedtls_entropy_f_source_ptr callback.
|
||||
*
|
||||
* @param data Callback-specific data pointer
|
||||
* @param output Data to fill
|
||||
* @param len Maximum size to provide
|
||||
* @param olen The actual amount of bytes put into the buffer (Can be 0)
|
||||
*/
|
||||
typedef int (*net_app_entropy_src_cb_t)(void *data, unsigned char *output,
|
||||
size_t len, size_t *olen);
|
||||
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
|
||||
|
||||
#if defined(CONFIG_NET_APP_DTLS)
|
||||
struct dtls_timing_context {
|
||||
u32_t snapshot;
|
||||
u32_t int_ms;
|
||||
u32_t fin_ms;
|
||||
};
|
||||
#endif /* CONFIG_NET_APP_DTLS */
|
||||
|
||||
/* Information for the context and local/remote addresses used. */
|
||||
struct net_app_endpoint {
|
||||
/** Network context. */
|
||||
struct net_context *ctx;
|
||||
|
||||
/** Local address */
|
||||
struct sockaddr local;
|
||||
|
||||
/** Remote address */
|
||||
struct sockaddr remote;
|
||||
};
|
||||
|
||||
/** Network application context. */
|
||||
struct net_app_ctx {
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
struct net_app_endpoint ipv6;
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
struct net_app_endpoint ipv4;
|
||||
#endif
|
||||
|
||||
/** What is the default endpoint for this context. */
|
||||
struct net_app_endpoint *default_ctx;
|
||||
|
||||
/** Internal function that is called when user data is sent to
|
||||
* network. By default this is set to net_context_sendto() but
|
||||
* is overridden for TLS as it requires special handling.
|
||||
*/
|
||||
net_app_send_data_t send_data;
|
||||
|
||||
/** Connection callbacks */
|
||||
struct net_app_cb cb;
|
||||
|
||||
/** Internal function that is called when data is received from
|
||||
* network. This will do what ever needed and then pass data to
|
||||
* application.
|
||||
*/
|
||||
net_context_recv_cb_t recv_cb;
|
||||
|
||||
#if defined(CONFIG_NET_APP_DTLS)
|
||||
struct {
|
||||
/** Currently active network context. This will contain the
|
||||
* new context that is created after connection is established
|
||||
* when UDP and DTLS is used.
|
||||
*/
|
||||
struct net_context *ctx;
|
||||
|
||||
/** DTLS final timer. Connection is terminated if this expires.
|
||||
*/
|
||||
struct k_delayed_work fin_timer;
|
||||
} dtls;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_APP_SERVER)
|
||||
struct {
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
/** Currently active network contexts. This will contain the
|
||||
* new contexts that are created after connection is accepted
|
||||
* when TCP is enabled.
|
||||
*/
|
||||
struct net_context *net_ctxs[CONFIG_NET_APP_SERVER_NUM_CONN];
|
||||
#endif
|
||||
} server;
|
||||
#endif /* CONFIG_NET_APP_SERVER */
|
||||
|
||||
#if defined(CONFIG_NET_APP_CLIENT)
|
||||
struct {
|
||||
/** Connect waiter */
|
||||
struct k_sem connect_wait;
|
||||
|
||||
#if defined(CONFIG_DNS_RESOLVER)
|
||||
/** DNS resolver waiter */
|
||||
struct k_sem dns_wait;
|
||||
|
||||
/** DNS query id. This is needed if the query needs to be
|
||||
* cancelled.
|
||||
*/
|
||||
u16_t dns_id;
|
||||
#endif
|
||||
} client;
|
||||
#endif /* CONFIG_NET_APP_CLIENT */
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
|
||||
struct {
|
||||
/** TLS stack for mbedtls library. */
|
||||
k_thread_stack_t *stack;
|
||||
|
||||
/** TLS stack size. */
|
||||
int stack_size;
|
||||
|
||||
/** TLS thread id */
|
||||
k_tid_t tid;
|
||||
|
||||
/** TLS thread */
|
||||
struct k_thread thread;
|
||||
|
||||
/** Memory pool for RX data */
|
||||
struct k_mem_pool *pool;
|
||||
|
||||
/** Where the encrypted request is stored, this is to be
|
||||
* provided by the user.
|
||||
*/
|
||||
u8_t *request_buf;
|
||||
|
||||
/** Hostname to be used in the certificate verification */
|
||||
const char *cert_host;
|
||||
|
||||
/** Request buffer maximum length */
|
||||
size_t request_buf_len;
|
||||
|
||||
/** mbedtls related configuration. */
|
||||
struct {
|
||||
#if defined(CONFIG_NET_APP_SERVER)
|
||||
net_app_cert_cb_t cert_cb;
|
||||
mbedtls_x509_crt srvcert;
|
||||
mbedtls_pk_context pkey;
|
||||
#endif
|
||||
#if defined(CONFIG_NET_APP_CLIENT)
|
||||
net_app_ca_cert_cb_t ca_cert_cb;
|
||||
mbedtls_x509_crt ca_cert;
|
||||
#endif
|
||||
struct tls_context ssl_ctx;
|
||||
net_app_entropy_src_cb_t entropy_src_cb;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_ssl_config conf;
|
||||
#if defined(CONFIG_NET_APP_DTLS)
|
||||
mbedtls_ssl_cookie_ctx cookie_ctx;
|
||||
struct dtls_timing_context timing_ctx;
|
||||
#endif
|
||||
u8_t *personalization_data;
|
||||
size_t personalization_data_len;
|
||||
} mbedtls;
|
||||
|
||||
/** Have we called connect cb yet? */
|
||||
u8_t connect_cb_called : 1;
|
||||
|
||||
/** User wants to close the connection */
|
||||
u8_t close_requested : 1;
|
||||
|
||||
/** Is there TX pending? If there is then the close operation
|
||||
* will be postponed after we have sent the data.
|
||||
*/
|
||||
u8_t tx_pending : 1;
|
||||
|
||||
/** Is the TLS/DTLS handshake fully done */
|
||||
u8_t handshake_done : 1;
|
||||
|
||||
/** Is the connection closing */
|
||||
u8_t connection_closing : 1;
|
||||
} tls;
|
||||
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
|
||||
/** Network packet (net_pkt) memory pool for network contexts attached
|
||||
* to this network app context.
|
||||
*/
|
||||
net_pkt_get_slab_func_t tx_slab;
|
||||
|
||||
/** Network data net_buf pool for network contexts attached to this
|
||||
* network app context.
|
||||
*/
|
||||
net_pkt_get_pool_func_t data_pool;
|
||||
#endif
|
||||
|
||||
/** User data pointer */
|
||||
void *user_data;
|
||||
|
||||
#if CONFIG_NET_APP_LOG_LEVEL >= LOG_LEVEL_DBG
|
||||
/** Used when debugging with net-shell */
|
||||
sys_snode_t node;
|
||||
#endif
|
||||
|
||||
/** Type of the connection (stream or datagram) */
|
||||
enum net_sock_type sock_type;
|
||||
|
||||
/** IP protocol type (UDP or TCP) */
|
||||
enum net_ip_protocol proto;
|
||||
|
||||
/** Application type (client or server) of this instance */
|
||||
enum net_app_type app_type;
|
||||
|
||||
/** Is this context setup or not */
|
||||
u8_t is_init : 1;
|
||||
|
||||
/** Is this instance supporting TLS or not.
|
||||
*/
|
||||
u8_t is_tls : 1;
|
||||
|
||||
/** Running status of the server. If true, then the server is enabled.
|
||||
* If false then it is disabled and will not serve clients.
|
||||
* The server is disabled by default after initialization and needs to
|
||||
* be manually enabled in order to serve any requests.
|
||||
*/
|
||||
u8_t is_enabled : 1;
|
||||
|
||||
/** Unused bits */
|
||||
u8_t _padding : 5;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
|
||||
/**
|
||||
* @brief Configure the net_pkt pool for this context.
|
||||
*
|
||||
* @details Use of this function is optional and if the pools are not set,
|
||||
* then the default TX and DATA pools are used.
|
||||
*
|
||||
* @param tx_slab Function which is used when allocating TX network packet.
|
||||
* This can be NULL in which case default TX memory pool is used.
|
||||
* @param data_pool Function which is used when allocating data network buffer.
|
||||
* This can be NULL in which case default DATA net_buf pool is used.
|
||||
*/
|
||||
int net_app_set_net_pkt_pool(struct net_app_ctx *ctx,
|
||||
net_pkt_get_slab_func_t tx_slab,
|
||||
net_pkt_get_pool_func_t data_pool);
|
||||
#else
|
||||
#define net_app_set_net_pkt_pool(...)
|
||||
#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
|
||||
|
||||
#if defined(CONFIG_NET_APP_SERVER)
|
||||
/**
|
||||
* @brief Create a network server application.
|
||||
*
|
||||
* @details Note that caller must create the context and initialize it to 0
|
||||
* before calling this function. The context must be valid for the whole
|
||||
* duration of the application life cycle. This usually means that it
|
||||
* cannot be allocated from stack.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
* @param sock_type Connection type (stream or datagram).
|
||||
* @param proto IP protocol (UDP or TCP)
|
||||
* @param server_addr Local address of the server. If set to NULL, then the
|
||||
* API will figure out a proper address where to bind the context.
|
||||
* @param port UDP or TCP port number where the service is located. This is
|
||||
* only used if server_addr parameter is NULL.
|
||||
* @param timeout Timeout for this function call. This timeout tells how
|
||||
* long to wait while accepting the data from network.
|
||||
* @param user_data User specific data.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
int net_app_init_server(struct net_app_ctx *ctx,
|
||||
enum net_sock_type sock_type,
|
||||
enum net_ip_protocol proto,
|
||||
struct sockaddr *server_addr,
|
||||
u16_t port,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Create a TCP server application.
|
||||
*
|
||||
* @details Note that caller must create the context and initialize it to 0
|
||||
* before calling this function. The context must be valid for the whole
|
||||
* duration of the application life cycle. This usually means that it
|
||||
* cannot be allocated from stack.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
* @param server_addr Local address of the server. If set to NULL, then the
|
||||
* API will figure out a proper address where to bind the context.
|
||||
* @param port UDP or TCP port number where the service is located. This is
|
||||
* only used if server_addr parameter is NULL.
|
||||
* @param timeout Timeout for this function call. This timeout tells how
|
||||
* long to wait while accepting the data from network.
|
||||
* @param user_data User specific data.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
static inline int net_app_init_tcp_server(struct net_app_ctx *ctx,
|
||||
struct sockaddr *server_addr,
|
||||
u16_t port,
|
||||
void *user_data)
|
||||
{
|
||||
return net_app_init_server(ctx,
|
||||
SOCK_STREAM,
|
||||
IPPROTO_TCP,
|
||||
server_addr,
|
||||
port,
|
||||
user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a UDP server application.
|
||||
*
|
||||
* @details Note that caller must create the context and initialize it to 0
|
||||
* before calling this function. The context must be valid for the whole
|
||||
* duration of the application life cycle. This usually means that it
|
||||
* cannot be allocated from stack.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
* @param server_addr Local address of the server. If set to NULL, then the
|
||||
* API will figure out a proper address where to bind the context.
|
||||
* @param port UDP or TCP port number where the service is located. This is
|
||||
* only used if server_addr parameter is NULL.
|
||||
* @param timeout Timeout for this function call. This timeout tells how
|
||||
* long to wait while accepting the data from network.
|
||||
* @param user_data User specific data.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
static inline int net_app_init_udp_server(struct net_app_ctx *ctx,
|
||||
struct sockaddr *server_addr,
|
||||
u16_t port,
|
||||
void *user_data)
|
||||
{
|
||||
return net_app_init_server(ctx,
|
||||
SOCK_DGRAM,
|
||||
IPPROTO_UDP,
|
||||
server_addr,
|
||||
port,
|
||||
user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait for an incoming connection.
|
||||
*
|
||||
* @details Note that caller must have called net_app_init_server() before
|
||||
* calling this function. This functionality is separated from init function
|
||||
* so that user can setup the callbacks after calling init. Only after calling
|
||||
* this function the server starts to listen connection attempts. This function
|
||||
* will not block but will initialize the local end point address so that
|
||||
* receive callback will be called for incoming connection.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
int net_app_listen(struct net_app_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @brief Enable server to serve connections.
|
||||
*
|
||||
* @details By default the server status is disabled.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
bool net_app_server_enable(struct net_app_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @brief Disable server so that it will not serve any clients.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
bool net_app_server_disable(struct net_app_ctx *ctx);
|
||||
|
||||
#endif /* CONFIG_NET_APP_SERVER */
|
||||
|
||||
#if defined(CONFIG_NET_APP_CLIENT)
|
||||
/**
|
||||
* @brief Create a network client application.
|
||||
*
|
||||
* @details Note that caller must create the context and initialize it to 0
|
||||
* before calling this function. The context must be valid for the whole
|
||||
* duration of the application life cycle. This usually means that it
|
||||
* cannot be allocated from stack.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
* @param sock_type Connection type (stream or datagram).
|
||||
* @param proto IP protocol (UDP or TCP)
|
||||
* @param client_addr Local address of the client. If set to NULL, then the
|
||||
* API will figure out a proper address where to bind the context.
|
||||
* @param peer_addr Peer (target) address. If this is NULL, then the
|
||||
* peer_add_str string and peer_port are used when connecting to peer.
|
||||
* @param peer_addr_str Peer (target) address as a string. If this is NULL,
|
||||
* then the peer_addr sockaddr is used to set the peer address. If DNS is
|
||||
* configured in the system, then the hostname is automatically resolved if
|
||||
* given here. Note that the port number is optional in the string. If the
|
||||
* port number is not given in the string, then peer_port variable is used
|
||||
* instead.
|
||||
* Following syntax is supported for the address:
|
||||
* 192.0.2.1
|
||||
* 192.0.2.1:5353
|
||||
* 2001:db8::1
|
||||
* [2001:db8::1]:5353
|
||||
* peer.example.com
|
||||
* peer.example.com:1234
|
||||
* @param peer_port Port number where to connect to. Ignored if port number is
|
||||
* found in the peer_addr_str.
|
||||
* @param timeout Timeout for this function call. This is used if the API
|
||||
* needs to do some time consuming operation, like resolving DNS address.
|
||||
* @param user_data User specific data.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
int net_app_init_client(struct net_app_ctx *ctx,
|
||||
enum net_sock_type sock_type,
|
||||
enum net_ip_protocol proto,
|
||||
struct sockaddr *client_addr,
|
||||
struct sockaddr *peer_addr,
|
||||
const char *peer_addr_str,
|
||||
u16_t peer_port,
|
||||
s32_t timeout,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Create a TCP client application.
|
||||
*
|
||||
* @details Note that caller must create the context and initialize it to 0
|
||||
* before calling this function. The context must be valid for the whole
|
||||
* duration of the application life cycle. This usually means that it
|
||||
* cannot be allocated from stack.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
* @param client_addr Local address of the client. If set to NULL, then the
|
||||
* API will figure out a proper address where to bind the context.
|
||||
* @param peer_addr Peer (target) address. If this is NULL, then the
|
||||
* peer_add_str string and peer_port are used when connecting to peer.
|
||||
* @param peer_addr_str Peer (target) address as a string. If this is NULL,
|
||||
* then the peer_addr sockaddr is used to set the peer address. If DNS is
|
||||
* configured in the system, then the hostname is automatically resolved if
|
||||
* given here. Note that the port number is optional in the string. If the
|
||||
* port number is not given in the string, then peer_port variable is used
|
||||
* instead.
|
||||
* Following syntax is supported for the address:
|
||||
* 192.0.2.1
|
||||
* 192.0.2.1:5353
|
||||
* 2001:db8::1
|
||||
* [2001:db8::1]:5353
|
||||
* peer.example.com
|
||||
* peer.example.com:1234
|
||||
* @param peer_port Port number where to connect to. Ignored if port number is
|
||||
* found in the peer_addr_str.
|
||||
* @param timeout Timeout for this function call. This is used if the API
|
||||
* needs to do some time consuming operation, like resolving DNS address.
|
||||
* @param user_data User specific data.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
static inline int net_app_init_tcp_client(struct net_app_ctx *ctx,
|
||||
struct sockaddr *client_addr,
|
||||
struct sockaddr *peer_addr,
|
||||
const char *peer_addr_str,
|
||||
u16_t peer_port,
|
||||
s32_t timeout,
|
||||
void *user_data)
|
||||
{
|
||||
return net_app_init_client(ctx,
|
||||
SOCK_STREAM,
|
||||
IPPROTO_TCP,
|
||||
client_addr,
|
||||
peer_addr,
|
||||
peer_addr_str,
|
||||
peer_port,
|
||||
timeout,
|
||||
user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a UDP client application.
|
||||
*
|
||||
* @details Note that caller must create the context and initialize it to 0
|
||||
* before calling this function. The context must be valid for the whole
|
||||
* duration of the application life cycle. This usually means that it
|
||||
* cannot be allocated from stack.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
* @param client_addr Local address of the client. If set to NULL, then the
|
||||
* API will figure out a proper address where to bind the context.
|
||||
* @param peer_addr Peer (target) address. If this is NULL, then the
|
||||
* peer_add_str string and peer_port are used when connecting to peer.
|
||||
* @param peer_addr_str Peer (target) address as a string. If this is NULL,
|
||||
* then the peer_addr sockaddr is used to set the peer address. If DNS is
|
||||
* configured in the system, then the hostname is automatically resolved if
|
||||
* given here. Note that the port number is optional in the string. If the
|
||||
* port number is not given in the string, then peer_port variable is used
|
||||
* instead.
|
||||
* Following syntax is supported for the address:
|
||||
* 192.0.2.1
|
||||
* 192.0.2.1:5353
|
||||
* 2001:db8::1
|
||||
* [2001:db8::1]:5353
|
||||
* peer.example.com
|
||||
* peer.example.com:1234
|
||||
* @param peer_port Port number where to connect to. Ignored if port number is
|
||||
* found in the peer_addr_str.
|
||||
* @param timeout Timeout for this function call. This is used if the API
|
||||
* needs to do some time consuming operation, like resolving DNS address.
|
||||
* @param user_data User specific data.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
static inline int net_app_init_udp_client(struct net_app_ctx *ctx,
|
||||
struct sockaddr *client_addr,
|
||||
struct sockaddr *peer_addr,
|
||||
const char *peer_addr_str,
|
||||
u16_t peer_port,
|
||||
s32_t timeout,
|
||||
void *user_data)
|
||||
{
|
||||
return net_app_init_client(ctx,
|
||||
SOCK_DGRAM,
|
||||
IPPROTO_UDP,
|
||||
client_addr,
|
||||
peer_addr,
|
||||
peer_addr_str,
|
||||
peer_port,
|
||||
timeout,
|
||||
user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Establish a network connection to peer.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
* @param timeout How long to wait the network connection before giving up.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
int net_app_connect(struct net_app_ctx *ctx, s32_t timeout);
|
||||
#endif /* CONFIG_NET_APP_CLIENT */
|
||||
|
||||
/**
|
||||
* @brief Set various network application callbacks.
|
||||
*
|
||||
* @param ctx Network app context.
|
||||
* @param connect_cb Connect callback.
|
||||
* @param recv_cb Data receive callback.
|
||||
* @param send_cb Data sent callback.
|
||||
* @param close_cb Close callback.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
int net_app_set_cb(struct net_app_ctx *ctx,
|
||||
net_app_connect_cb_t connect_cb,
|
||||
net_app_recv_cb_t recv_cb,
|
||||
net_app_send_cb_t send_cb,
|
||||
net_app_close_cb_t close_cb);
|
||||
|
||||
/**
|
||||
* @brief Send data that is found in net_pkt to peer.
|
||||
*
|
||||
* @details If the function return < 0, then it is caller responsibility
|
||||
* to unref the pkt. If the packet was sent successfully, then the lower
|
||||
* IP stack will release the network pkt.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
* @param pkt Network packet to send.
|
||||
* @param dst Destination address where to send packet. This is
|
||||
* ignored for TCP data.
|
||||
* @param dst_len Destination address structure size
|
||||
* @param timeout How long to wait the send before giving up.
|
||||
* @param user_data_send User data specific to this send call.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
int net_app_send_pkt(struct net_app_ctx *ctx,
|
||||
struct net_pkt *pkt,
|
||||
const struct sockaddr *dst,
|
||||
socklen_t dst_len,
|
||||
s32_t timeout,
|
||||
void *user_data_send);
|
||||
|
||||
/**
|
||||
* @brief Send data that is found in user specified buffer to peer.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
* @param buf Buffer to send.
|
||||
* @param buf_len Amount of data to send.
|
||||
* @param dst Destination address where to send packet. This is
|
||||
* ignored for TCP data.
|
||||
* @param dst_len Destination address structure size
|
||||
* @param timeout How long to wait the send before giving up.
|
||||
* @param user_data_send User data specific to this send call.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
int net_app_send_buf(struct net_app_ctx *ctx,
|
||||
u8_t *buf,
|
||||
size_t buf_len,
|
||||
const struct sockaddr *dst,
|
||||
socklen_t dst_len,
|
||||
s32_t timeout,
|
||||
void *user_data_send);
|
||||
|
||||
/**
|
||||
* @brief Create network packet.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
* @param family What kind of network packet to get (AF_INET or AF_INET6)
|
||||
* @param timeout How long to wait the send before giving up.
|
||||
*
|
||||
* @return valid net_pkt if ok, NULL if error.
|
||||
*/
|
||||
struct net_pkt *net_app_get_net_pkt(struct net_app_ctx *ctx,
|
||||
sa_family_t family,
|
||||
s32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Create network packet based on dst address.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
* @param dst Destination address to select net_context
|
||||
* @param timeout How long to wait the send before giving up.
|
||||
*
|
||||
* @return valid net_pkt if ok, NULL if error.
|
||||
*/
|
||||
struct net_pkt *net_app_get_net_pkt_with_dst(struct net_app_ctx *ctx,
|
||||
const struct sockaddr *dst,
|
||||
s32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Create network buffer that will hold network data.
|
||||
*
|
||||
* @details The returned net_buf is automatically appended to the
|
||||
* end of network packet fragment chain.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
* @param pkt Network packet to where the data buf is appended.
|
||||
* @param timeout How long to wait the send before giving up.
|
||||
*
|
||||
* @return valid net_pkt if ok, NULL if error.
|
||||
*/
|
||||
struct net_buf *net_app_get_net_buf(struct net_app_ctx *ctx,
|
||||
struct net_pkt *pkt,
|
||||
s32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Close a network connection to peer.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
int net_app_close(struct net_app_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @brief Close a specific network connection.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
* @param net_ctx Network context.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
int net_app_close2(struct net_app_ctx *ctx,
|
||||
struct net_context *net_ctx);
|
||||
|
||||
/**
|
||||
* @brief Release this network application context.
|
||||
*
|
||||
* @details No network data will be received via this context after this
|
||||
* call.
|
||||
*
|
||||
* @param ctx Network application context.
|
||||
*
|
||||
* @return 0 if ok, <0 if error.
|
||||
*/
|
||||
int net_app_release(struct net_app_ctx *ctx);
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
|
||||
#if defined(CONFIG_NET_APP_CLIENT)
|
||||
/**
|
||||
* @brief Initialize TLS support for this net_app client context.
|
||||
*
|
||||
* @param ctx net_app context.
|
||||
* @param request_buf Caller-supplied buffer where the TLS request will be
|
||||
* stored
|
||||
* @param request_buf_len Length of the caller-supplied buffer.
|
||||
* @param personalization_data Personalization data (Device specific
|
||||
* identifiers) for random number generator. (Can be NULL).
|
||||
* @param personalization_data_len Length of the personalization data.
|
||||
* @param cert_cb User-supplied callback that setups the certificates.
|
||||
* @param cert_host Hostname that is used to verify the server certificate.
|
||||
* This value is used when net_api API calls mbedtls_ssl_set_hostname()
|
||||
* which sets the hostname to check against the received server certificate.
|
||||
* See https://tls.mbed.org/kb/how-to/use-sni for more details.
|
||||
* This can be left NULL in which case mbedtls will silently skip certificate
|
||||
* verification entirely. This option is only used if MBEDTLS_X509_CRT_PARSE_C
|
||||
* is enabled in mbedtls config file.
|
||||
* @param entropy_src_cb User-supplied callback that setup the entropy. This
|
||||
* can be set to NULL, in which case default entropy source is used.
|
||||
* @param pool Memory pool for RX data reads.
|
||||
* @param stack TLS thread stack.
|
||||
* @param stack_len TLS thread stack size.
|
||||
*
|
||||
* @return Return 0 if ok, <0 if error.
|
||||
*/
|
||||
int net_app_client_tls(struct net_app_ctx *ctx,
|
||||
u8_t *request_buf,
|
||||
size_t request_buf_len,
|
||||
u8_t *personalization_data,
|
||||
size_t personalization_data_len,
|
||||
net_app_ca_cert_cb_t cert_cb,
|
||||
const char *cert_host,
|
||||
net_app_entropy_src_cb_t entropy_src_cb,
|
||||
struct k_mem_pool *pool,
|
||||
k_thread_stack_t *stack,
|
||||
size_t stack_size);
|
||||
#endif /* CONFIG_NET_APP_CLIENT */
|
||||
|
||||
#if defined(CONFIG_NET_APP_SERVER)
|
||||
/**
|
||||
* @brief Initialize TLS support for this net_app server context.
|
||||
*
|
||||
* @param ctx net_app context.
|
||||
* @param request_buf Caller-supplied buffer where the TLS request will be
|
||||
* stored
|
||||
* @param request_buf_len Length of the caller-supplied buffer.
|
||||
* @param server_banner Print information about started service. This is only
|
||||
* printed if net_app debugging is activated. The parameter can be set to NULL
|
||||
* if no extra prints are needed.
|
||||
* @param personalization_data Personalization data (Device specific
|
||||
* identifiers) for random number generator. (Can be NULL).
|
||||
* @param personalization_data_len Length of the personalization data.
|
||||
* @param cert_cb User-supplied callback that setups the certificates.
|
||||
* @param entropy_src_cb User-supplied callback that setup the entropy. This
|
||||
* can be set to NULL, in which case default entropy source is used.
|
||||
* @param pool Memory pool for RX data reads.
|
||||
* @param stack TLS thread stack.
|
||||
* @param stack_len TLS thread stack size.
|
||||
*
|
||||
* @return Return 0 if ok, <0 if error.
|
||||
*/
|
||||
int net_app_server_tls(struct net_app_ctx *ctx,
|
||||
u8_t *request_buf,
|
||||
size_t request_buf_len,
|
||||
const char *server_banner,
|
||||
u8_t *personalization_data,
|
||||
size_t personalization_data_len,
|
||||
net_app_cert_cb_t cert_cb,
|
||||
net_app_entropy_src_cb_t entropy_src_cb,
|
||||
struct k_mem_pool *pool,
|
||||
k_thread_stack_t *stack,
|
||||
size_t stack_len);
|
||||
|
||||
#endif /* CONFIG_NET_APP_SERVER */
|
||||
|
||||
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
typedef void (*net_app_ctx_cb_t)(struct net_app_ctx *ctx, void *user_data);
|
||||
void net_app_server_foreach(net_app_ctx_cb_t cb, void *user_data);
|
||||
void net_app_client_foreach(net_app_ctx_cb_t cb, void *user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_NET_NET_APP_H_ */
|
|
@ -21,7 +21,8 @@ source "subsys/net/Kconfig.template.log_config.net"
|
|||
|
||||
config NET_L2_ETHERNET_MGMT
|
||||
bool "Enable Ethernet network management interface"
|
||||
depends on NET_MGMT && NET_MGMT_EVENT
|
||||
select NET_MGMT
|
||||
select NET_MGMT_EVENT
|
||||
help
|
||||
Enable support net_mgmt Ethernet interface which can be used to
|
||||
configure at run-time Ethernet drivers and L2 settings.
|
||||
|
|
|
@ -3,7 +3,6 @@ add_subdirectory_if_kconfig(lwm2m)
|
|||
add_subdirectory_if_kconfig(sntp)
|
||||
add_subdirectory_ifdef(CONFIG_DNS_RESOLVER dns)
|
||||
add_subdirectory_ifdef(CONFIG_MQTT_LIB mqtt_sock)
|
||||
add_subdirectory_ifdef(CONFIG_NET_APP app)
|
||||
add_subdirectory_ifdef(CONFIG_NET_CONFIG_SETTINGS config)
|
||||
add_subdirectory_ifdef(CONFIG_NET_SOCKETS sockets)
|
||||
add_subdirectory_ifdef(CONFIG_TLS_CREDENTIALS tls_credentials)
|
||||
|
|
|
@ -24,8 +24,6 @@ menu "Network Libraries"
|
|||
|
||||
source "subsys/net/lib/config/Kconfig"
|
||||
|
||||
source "subsys/net/lib/app/Kconfig"
|
||||
|
||||
source "subsys/net/lib/sockets/Kconfig"
|
||||
|
||||
source "subsys/net/lib/tls_credentials/Kconfig"
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
zephyr_sources_ifdef(CONFIG_NET_APP_SERVER net_app.c server.c)
|
||||
zephyr_sources_ifdef(CONFIG_NET_APP_CLIENT net_app.c client.c)
|
||||
|
||||
zephyr_link_interface_ifdef(CONFIG_MBEDTLS mbedTLS)
|
||||
zephyr_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)
|
|
@ -1,75 +0,0 @@
|
|||
# Kconfig.app - Options for networking applications
|
||||
|
||||
#
|
||||
# Copyright (c) 2017 Intel Corporation.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
menuconfig NET_APP
|
||||
bool "Network application API support [EXPERIMENTAL]"
|
||||
default y
|
||||
select NET_MGMT
|
||||
select NET_MGMT_EVENT
|
||||
help
|
||||
Enable API that helps to create client/server network applications.
|
||||
This API is experimental and subject to change.
|
||||
|
||||
if NET_APP
|
||||
|
||||
module = NET_APP
|
||||
module-dep = NET_LOG
|
||||
module-str = Log level for net_app library
|
||||
module-help = Enables net app library to output debug messages.
|
||||
source "subsys/net/Kconfig.template.log_config.net"
|
||||
|
||||
config NET_APP_SERVER
|
||||
bool "Enable server support"
|
||||
help
|
||||
Enables net app library server APIs.
|
||||
|
||||
config NET_APP_SERVER_NUM_CONN
|
||||
int "Number of simultaneous incoming connections"
|
||||
default 1
|
||||
depends on NET_APP_SERVER
|
||||
help
|
||||
Tells how many simultaneous incoming connections the server instance can
|
||||
support. The value of CONFIG_NET_TCP_BACKLOG_SIZE must be greater than
|
||||
or equal to CONFIG_NET_APP_SERVER_NUM_CONN.
|
||||
|
||||
config NET_APP_CLIENT
|
||||
bool "Enable client support"
|
||||
help
|
||||
Enables net app library client APIs.
|
||||
|
||||
config NET_APP_TLS
|
||||
bool "Enable TLS support for TCP applications"
|
||||
depends on NET_TCP
|
||||
select MBEDTLS
|
||||
help
|
||||
Enables net app library to use TLS for encrypted communication.
|
||||
|
||||
config NET_APP_DTLS
|
||||
bool "Enable DTLS support for UDP applications"
|
||||
depends on NET_UDP
|
||||
select MBEDTLS
|
||||
help
|
||||
Enables net app library to use DTLS for encrypted UDP communication.
|
||||
|
||||
config NET_APP_DTLS_TIMEOUT
|
||||
int "DTLS session timeout"
|
||||
depends on NET_APP_DTLS
|
||||
default 15
|
||||
help
|
||||
If a DTLS session does not have any activity, then disconnect
|
||||
the session. The value is in seconds.
|
||||
|
||||
config NET_APP_TLS_STACK_SIZE
|
||||
int "TLS handler thread stack size"
|
||||
default 8192
|
||||
depends on NET_APP_TLS || NET_APP_DTLS
|
||||
help
|
||||
TLS handler thread stack size. The mbedtls routines will use this stack
|
||||
thus it is by default very large.
|
||||
|
||||
endif # NET_APP
|
|
@ -1,942 +0,0 @@
|
|||
/* client.c */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(net_app, CONFIG_NET_APP_LOG_LEVEL);
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/dns_resolve.h>
|
||||
|
||||
#include <net/net_app.h>
|
||||
|
||||
#include "../../ip/udp_internal.h"
|
||||
|
||||
#include "net_app_private.h"
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
|
||||
#define TLS_STARTUP_TIMEOUT K_SECONDS(5)
|
||||
static int start_tls_client(struct net_app_ctx *ctx);
|
||||
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
|
||||
|
||||
#if defined(CONFIG_DNS_RESOLVER)
|
||||
static void dns_cb(enum dns_resolve_status status,
|
||||
struct dns_addrinfo *info,
|
||||
void *user_data)
|
||||
{
|
||||
struct net_app_ctx *ctx = user_data;
|
||||
|
||||
if (!(status == DNS_EAI_INPROGRESS && info)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->ai_family == AF_INET) {
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
net_ipaddr_copy(&net_sin(&ctx->ipv4.remote)->sin_addr,
|
||||
&net_sin(&info->ai_addr)->sin_addr);
|
||||
ctx->ipv4.remote.sa_family = info->ai_family;
|
||||
#else
|
||||
goto out;
|
||||
#endif
|
||||
} else if (info->ai_family == AF_INET6) {
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
net_ipaddr_copy(&net_sin6(&ctx->ipv6.remote)->sin6_addr,
|
||||
&net_sin6(&info->ai_addr)->sin6_addr);
|
||||
ctx->ipv6.remote.sa_family = info->ai_family;
|
||||
#else
|
||||
goto out;
|
||||
#endif
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
k_sem_give(&ctx->client.dns_wait);
|
||||
}
|
||||
|
||||
static int resolve_name(struct net_app_ctx *ctx,
|
||||
const char *peer_addr_str,
|
||||
enum dns_query_type type,
|
||||
s32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
|
||||
k_sem_init(&ctx->client.dns_wait, 0, 1);
|
||||
|
||||
ret = dns_get_addr_info(peer_addr_str, type, &ctx->client.dns_id,
|
||||
dns_cb, ctx, timeout);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot resolve %s (%d)", log_strdup(peer_addr_str),
|
||||
ret);
|
||||
ctx->client.dns_id = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Wait a little longer for the DNS to finish so that
|
||||
* the DNS will timeout before the semaphore.
|
||||
*/
|
||||
if (k_sem_take(&ctx->client.dns_wait, timeout + K_SECONDS(1))) {
|
||||
NET_ERR("Timeout while resolving %s",
|
||||
log_strdup(peer_addr_str));
|
||||
ctx->client.dns_id = 0;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
ctx->client.dns_id = 0;
|
||||
|
||||
if (ctx->default_ctx->remote.sa_family == AF_UNSPEC) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DNS_RESOLVER */
|
||||
|
||||
static int try_resolve(struct net_app_ctx *ctx,
|
||||
const char *peer_addr_str,
|
||||
enum dns_query_type type,
|
||||
s32_t timeout)
|
||||
{
|
||||
#if !defined(CONFIG_DNS_RESOLVER)
|
||||
return -EINVAL;
|
||||
#else
|
||||
int ret;
|
||||
|
||||
ret = resolve_name(ctx, peer_addr_str, type, timeout);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot resolve %s (%d)",
|
||||
log_strdup(peer_addr_str), ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int set_remote_addr(struct net_app_ctx *ctx,
|
||||
struct sockaddr *remote_addr,
|
||||
const char *peer_addr_str,
|
||||
bool peer_addr_ok,
|
||||
s32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (peer_addr_ok && remote_addr->sa_family == AF_INET6) {
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
memcpy(&ctx->ipv6.remote, remote_addr,
|
||||
sizeof(struct sockaddr));
|
||||
ctx->default_ctx = &ctx->ipv6;
|
||||
return 0;
|
||||
#else
|
||||
return -EAFNOSUPPORT;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (peer_addr_ok && remote_addr->sa_family == AF_INET) {
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
memcpy(&ctx->ipv4.remote, remote_addr,
|
||||
sizeof(struct sockaddr));
|
||||
ctx->default_ctx = &ctx->ipv4;
|
||||
return 0;
|
||||
#else
|
||||
return -EAFNOSUPPORT;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
|
||||
/* Could be hostname, try DNS if configured. */
|
||||
ret = try_resolve(ctx, peer_addr_str, DNS_QUERY_TYPE_AAAA, timeout);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->default_ctx = &ctx->ipv6;
|
||||
return 0;
|
||||
#endif /* IPV6 && !IPV4 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
|
||||
ret = try_resolve(ctx, peer_addr_str, DNS_QUERY_TYPE_A, timeout);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->default_ctx = &ctx->ipv4;
|
||||
return 0;
|
||||
#endif /* IPV6 && !IPV4 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6)
|
||||
ret = try_resolve(ctx, peer_addr_str, DNS_QUERY_TYPE_A, timeout);
|
||||
if (ret < 0) {
|
||||
ret = try_resolve(ctx, peer_addr_str, DNS_QUERY_TYPE_AAAA,
|
||||
timeout);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->default_ctx = &ctx->ipv6;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx->default_ctx = &ctx->ipv4;
|
||||
return 0;
|
||||
#endif /* IPV4 && IPV6 */
|
||||
}
|
||||
|
||||
static int get_port_number(const char *peer_addr_str,
|
||||
char *buf,
|
||||
size_t buf_len)
|
||||
{
|
||||
u16_t port = 0U;
|
||||
char *ptr;
|
||||
int count, i;
|
||||
|
||||
if (peer_addr_str[0] == '[') {
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
/* IPv6 address with port number */
|
||||
int end;
|
||||
|
||||
ptr = strstr(peer_addr_str, "]:");
|
||||
if (!ptr) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
end = min(INET6_ADDRSTRLEN, ptr - (peer_addr_str + 1));
|
||||
memcpy(buf, peer_addr_str + 1, end);
|
||||
buf[end] = '\0';
|
||||
|
||||
port = strtol(ptr + 2, NULL, 10);
|
||||
|
||||
return port;
|
||||
#else
|
||||
return -EAFNOSUPPORT;
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
}
|
||||
|
||||
count = i = 0;
|
||||
while (peer_addr_str[i]) {
|
||||
if (peer_addr_str[i] == ':') {
|
||||
count++;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
/* IPv4 address with port number */
|
||||
int end;
|
||||
|
||||
ptr = strstr(peer_addr_str, ":");
|
||||
if (!ptr) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
end = min(NET_IPV4_ADDR_LEN, ptr - peer_addr_str);
|
||||
memcpy(buf, peer_addr_str, end);
|
||||
buf[end] = '\0';
|
||||
|
||||
port = strtol(ptr + 1, NULL, 10);
|
||||
|
||||
return port;
|
||||
#else
|
||||
return -EAFNOSUPPORT;
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void close_net_ctx(struct net_app_ctx *ctx)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (ctx->ipv6.ctx) {
|
||||
net_context_put(ctx->ipv6.ctx);
|
||||
ctx->ipv6.ctx = NULL;
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
if (ctx->ipv4.ctx) {
|
||||
net_context_put(ctx->ipv4.ctx);
|
||||
ctx->ipv4.ctx = NULL;
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_NET_APP_SERVER) && defined(CONFIG_NET_TCP)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_NET_APP_SERVER_NUM_CONN; i++) {
|
||||
if (ctx->server.net_ctxs[i]) {
|
||||
net_context_put(ctx->server.net_ctxs[i]);
|
||||
ctx->server.net_ctxs[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int bind_local(struct net_app_ctx *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
if (ctx->ipv4.remote.sa_family == AF_INET && ctx->ipv4.ctx) {
|
||||
ctx->ipv4.local.sa_family = AF_INET;
|
||||
_net_app_set_local_addr(ctx, &ctx->ipv4.local, NULL,
|
||||
ntohs(net_sin(&ctx->ipv4.local)->sin_port));
|
||||
|
||||
ret = _net_app_set_net_ctx(ctx, ctx->ipv4.ctx,
|
||||
&ctx->ipv4.local,
|
||||
sizeof(struct sockaddr_in),
|
||||
ctx->proto);
|
||||
if (ret < 0) {
|
||||
net_context_put(ctx->ipv4.ctx);
|
||||
ctx->ipv4.ctx = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (ctx->ipv6.remote.sa_family == AF_INET6 && ctx->ipv6.ctx) {
|
||||
ctx->ipv6.local.sa_family = AF_INET6;
|
||||
_net_app_set_local_addr(ctx, &ctx->ipv6.local, NULL,
|
||||
ntohs(net_sin6(&ctx->ipv6.local)->sin6_port));
|
||||
|
||||
ret = _net_app_set_net_ctx(ctx, ctx->ipv6.ctx,
|
||||
&ctx->ipv6.local,
|
||||
sizeof(struct sockaddr_in6),
|
||||
ctx->proto);
|
||||
if (ret < 0) {
|
||||
net_context_put(ctx->ipv6.ctx);
|
||||
ctx->ipv6.ctx = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int net_app_init_client(struct net_app_ctx *ctx,
|
||||
enum net_sock_type sock_type,
|
||||
enum net_ip_protocol proto,
|
||||
struct sockaddr *client_addr,
|
||||
struct sockaddr *peer_addr,
|
||||
const char *peer_addr_str,
|
||||
u16_t peer_port,
|
||||
s32_t timeout,
|
||||
void *user_data)
|
||||
{
|
||||
const char *base_peer_addr = peer_addr_str;
|
||||
char base_addr_str[INET6_ADDRSTRLEN + 1];
|
||||
struct sockaddr remote_addr;
|
||||
struct sockaddr addr;
|
||||
int ret, addr_ok = false;
|
||||
|
||||
if (!ctx) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ctx->is_init) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
(void)memset(&addr, 0, sizeof(addr));
|
||||
(void)memset(&remote_addr, 0, sizeof(remote_addr));
|
||||
|
||||
if (peer_addr) {
|
||||
memcpy(&remote_addr, peer_addr, sizeof(remote_addr));
|
||||
} else if (peer_addr_str) {
|
||||
/* If the peer string contains port number, use that and
|
||||
* ignore the port number parameter.
|
||||
*/
|
||||
ret = get_port_number(peer_addr_str, base_addr_str,
|
||||
sizeof(base_addr_str));
|
||||
if (ret > 0) {
|
||||
base_peer_addr = base_addr_str;
|
||||
peer_port = ret;
|
||||
} else {
|
||||
strncpy(base_addr_str, peer_addr_str,
|
||||
sizeof(base_addr_str) - 1);
|
||||
}
|
||||
|
||||
addr_ok = net_ipaddr_parse(base_peer_addr,
|
||||
strlen(base_peer_addr),
|
||||
&remote_addr);
|
||||
|
||||
/* The remote_addr will be used by set_remote_addr() to
|
||||
* set the actual peer address.
|
||||
*/
|
||||
}
|
||||
|
||||
if (client_addr) {
|
||||
u16_t local_port = 0U;
|
||||
bool empty_addr = false;
|
||||
|
||||
addr.sa_family = remote_addr.sa_family;
|
||||
|
||||
/* local_port is used if the IP address isn't specified */
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
if (client_addr->sa_family == AF_INET) {
|
||||
empty_addr = net_ipv4_is_addr_unspecified(
|
||||
&net_sin(client_addr)->sin_addr);
|
||||
local_port = net_sin(client_addr)->sin_port;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (client_addr->sa_family == AF_INET6) {
|
||||
empty_addr = net_ipv6_is_addr_unspecified(
|
||||
&net_sin6(client_addr)->sin6_addr);
|
||||
local_port = net_sin6(client_addr)->sin6_port;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (empty_addr) {
|
||||
if (remote_addr.sa_family == AF_INET6) {
|
||||
net_sin6(&addr)->sin6_port = local_port;
|
||||
} else {
|
||||
net_sin(&addr)->sin_port = local_port;
|
||||
}
|
||||
} else {
|
||||
memcpy(&addr, client_addr, sizeof(addr));
|
||||
|
||||
if (addr.sa_family != remote_addr.sa_family) {
|
||||
NET_DBG("Address family mismatch %d vs %d",
|
||||
addr.sa_family, remote_addr.sa_family);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addr.sa_family = remote_addr.sa_family;
|
||||
}
|
||||
|
||||
ctx->app_type = NET_APP_CLIENT;
|
||||
ctx->user_data = user_data;
|
||||
ctx->send_data = net_context_sendto;
|
||||
ctx->recv_cb = _net_app_received;
|
||||
ctx->proto = proto;
|
||||
ctx->sock_type = sock_type;
|
||||
ctx->is_enabled = true;
|
||||
|
||||
ret = _net_app_config_local_ctx(ctx, sock_type, proto, &addr);
|
||||
if (ret < 0) {
|
||||
close_net_ctx(ctx);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (peer_addr) {
|
||||
if (peer_addr->sa_family == AF_INET) {
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
memcpy(&ctx->ipv4.remote, peer_addr,
|
||||
sizeof(ctx->ipv4.remote));
|
||||
ctx->default_ctx = &ctx->ipv4;
|
||||
#else
|
||||
return -EPROTONOSUPPORT;
|
||||
#endif
|
||||
} else if (peer_addr->sa_family == AF_INET6) {
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
memcpy(&ctx->ipv6.remote, peer_addr,
|
||||
sizeof(ctx->ipv6.remote));
|
||||
ctx->default_ctx = &ctx->ipv6;
|
||||
#else
|
||||
return -EPROTONOSUPPORT;
|
||||
#endif
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!peer_addr_str) {
|
||||
NET_ERR("Cannot know where to connect.");
|
||||
ret = -EINVAL;
|
||||
close_net_ctx(ctx);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = set_remote_addr(ctx, &remote_addr, base_addr_str,
|
||||
addr_ok, timeout);
|
||||
if (ret < 0) {
|
||||
close_net_ctx(ctx);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* If we have not yet figured out what is the protocol family,
|
||||
* then we cannot continue.
|
||||
*/
|
||||
if (!ctx->default_ctx ||
|
||||
ctx->default_ctx->remote.sa_family == AF_UNSPEC) {
|
||||
NET_ERR("Unknown protocol family.");
|
||||
return -EPFNOSUPPORT;
|
||||
}
|
||||
|
||||
/* Set the port now that we know the sa_family */
|
||||
if (!peer_addr) {
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (ctx->default_ctx->remote.sa_family == AF_INET6) {
|
||||
net_sin6(&ctx->default_ctx->remote)->sin6_port =
|
||||
htons(peer_port);
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
if (ctx->default_ctx->remote.sa_family == AF_INET) {
|
||||
net_sin(&ctx->default_ctx->remote)->sin_port =
|
||||
htons(peer_port);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ret = bind_local(ctx);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
_net_app_print_info(ctx);
|
||||
|
||||
out:
|
||||
ctx->is_init = true;
|
||||
|
||||
_net_app_register(ctx);
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static void _app_connected(struct net_context *net_ctx,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
struct net_app_ctx *ctx = user_data;
|
||||
int ret;
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
|
||||
if (ctx->is_tls) {
|
||||
k_sem_give(&ctx->client.connect_wait);
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = net_context_recv(net_ctx, ctx->recv_cb, K_NO_WAIT, ctx);
|
||||
if (ret < 0) {
|
||||
NET_DBG("Cannot set recv_cb (%d)", ret);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
|
||||
if (ctx->is_tls) {
|
||||
/* If we have TLS connection, the connect cb is called
|
||||
* after TLS handshakes are done.
|
||||
*/
|
||||
NET_DBG("Postponing TLS connection cb for ctx %p", ctx);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (ctx->cb.connect) {
|
||||
ctx->cb.connect(ctx, status, ctx->user_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_APP_DTLS)
|
||||
static int connect_dtls(struct net_app_ctx *ctx, struct net_context *orig,
|
||||
struct sockaddr *remote)
|
||||
{
|
||||
struct net_context *dtls_context;
|
||||
struct sockaddr local_addr;
|
||||
int ret;
|
||||
|
||||
/* We create a new context that starts to send data and get replies
|
||||
* directly into correct callback.
|
||||
*/
|
||||
ret = net_context_get(net_context_get_family(orig), SOCK_DGRAM,
|
||||
IPPROTO_UDP, &dtls_context);
|
||||
if (ret < 0) {
|
||||
NET_DBG("Cannot get connect context");
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(&dtls_context->remote, remote, sizeof(dtls_context->remote));
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (net_context_get_family(orig) == AF_INET6) {
|
||||
struct sockaddr_in6 *local_addr6 = net_sin6(&local_addr);
|
||||
|
||||
net_sin6(&dtls_context->remote)->sin6_family = AF_INET6;
|
||||
|
||||
local_addr6->sin6_family = AF_INET6;
|
||||
local_addr6->sin6_port = net_sin6_ptr(&orig->local)->sin6_port;
|
||||
net_ipaddr_copy(&local_addr6->sin6_addr,
|
||||
net_sin6_ptr(&orig->local)->sin6_addr);
|
||||
} else
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
if (net_context_get_family(orig) == AF_INET) {
|
||||
struct sockaddr_in *local_addr4 = net_sin(&local_addr);
|
||||
|
||||
net_sin(&dtls_context->remote)->sin_family = AF_INET;
|
||||
|
||||
local_addr4->sin_family = AF_INET;
|
||||
local_addr4->sin_port = net_sin_ptr(&orig->local)->sin_port;
|
||||
net_ipaddr_copy(&local_addr4->sin_addr,
|
||||
net_sin_ptr(&orig->local)->sin_addr);
|
||||
} else
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
{
|
||||
NET_ASSERT_INFO(false, "Invalid protocol family %d",
|
||||
net_context_get_family(orig));
|
||||
goto ctx_drop;
|
||||
}
|
||||
|
||||
ret = net_context_bind(dtls_context, &local_addr, sizeof(local_addr));
|
||||
if (ret < 0) {
|
||||
NET_DBG("Cannot bind connect DTLS context");
|
||||
goto ctx_drop;
|
||||
}
|
||||
|
||||
dtls_context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
|
||||
|
||||
ret = net_udp_register(&dtls_context->remote,
|
||||
&local_addr,
|
||||
ntohs(net_sin(&dtls_context->remote)->sin_port),
|
||||
ntohs(net_sin(&local_addr)->sin_port),
|
||||
_net_app_dtls_established,
|
||||
ctx,
|
||||
&dtls_context->conn_handler);
|
||||
if (ret < 0) {
|
||||
NET_DBG("Cannot register connect DTLS handler (%d)", ret);
|
||||
goto ctx_drop;
|
||||
}
|
||||
|
||||
NET_DBG("New DTLS connection context %p created", dtls_context);
|
||||
|
||||
ctx->dtls.ctx = dtls_context;
|
||||
|
||||
return 0;
|
||||
|
||||
ctx_drop:
|
||||
net_context_unref(dtls_context);
|
||||
|
||||
out:
|
||||
return -ECONNABORTED;
|
||||
}
|
||||
#endif /* CONFIG_NET_APP_DTLS */
|
||||
|
||||
static void check_local_address(struct net_app_ctx *ctx,
|
||||
struct net_context *net_ctx)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (net_context_get_family(net_ctx) == AF_INET6) {
|
||||
const struct in6_addr *laddr;
|
||||
struct in6_addr *raddr;
|
||||
|
||||
laddr = &net_sin6(&ctx->ipv6.local)->sin6_addr;
|
||||
if (!net_ipv6_is_addr_unspecified(laddr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
raddr = &net_sin6(&ctx->ipv6.remote)->sin6_addr;
|
||||
|
||||
laddr = net_if_ipv6_select_src_addr(NULL, raddr);
|
||||
if (laddr && laddr != net_ipv6_unspecified_address()) {
|
||||
net_ipaddr_copy(&net_sin6(&ctx->ipv6.local)->sin6_addr,
|
||||
laddr);
|
||||
} else {
|
||||
NET_WARN("Source address is unspecified!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
if (net_context_get_family(net_ctx) == AF_INET) {
|
||||
struct in_addr *laddr;
|
||||
struct net_if *iface;
|
||||
|
||||
laddr = &net_sin(&ctx->ipv4.local)->sin_addr;
|
||||
if (!net_ipv4_is_addr_unspecified(laddr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Just take the first IPv4 address of an interface */
|
||||
iface = net_context_get_iface(net_ctx);
|
||||
if (iface) {
|
||||
laddr =
|
||||
&iface->config.ip.ipv4->unicast[0].address.in_addr;
|
||||
net_ipaddr_copy(&net_sin(&ctx->ipv4.local)->sin_addr,
|
||||
laddr);
|
||||
} else {
|
||||
NET_WARN("Source address is unspecified!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int net_app_connect(struct net_app_ctx *ctx, s32_t timeout)
|
||||
{
|
||||
struct net_context *net_ctx;
|
||||
bool started = false;
|
||||
int ret;
|
||||
|
||||
if (!ctx) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!ctx->is_init) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (ctx->app_type != NET_APP_CLIENT) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
net_ctx = _net_app_select_net_ctx(ctx, NULL);
|
||||
if (!net_ctx && ctx->is_enabled) {
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
if (!ctx->is_enabled) {
|
||||
ret = _net_app_config_local_ctx(ctx, ctx->sock_type,
|
||||
ctx->proto, NULL);
|
||||
if (ret < 0) {
|
||||
NET_DBG("Cannot get local endpoint (%d)", ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
net_ctx = _net_app_select_net_ctx(ctx, NULL);
|
||||
|
||||
NET_DBG("Re-conncting to net_ctx %p", net_ctx);
|
||||
|
||||
ret = bind_local(ctx);
|
||||
if (ret < 0) {
|
||||
NET_DBG("Cannot bind local endpoint (%d)", ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctx->is_enabled = true;
|
||||
|
||||
_net_app_print_info(ctx);
|
||||
} else {
|
||||
/* We cannot bind to local unspecified address when sending.
|
||||
* Select proper address depending on remote one in this case.
|
||||
*/
|
||||
check_local_address(ctx, net_ctx);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
|
||||
if (ctx->is_tls && !ctx->tls.tid &&
|
||||
(ctx->proto == IPPROTO_TCP ||
|
||||
(IS_ENABLED(CONFIG_NET_APP_DTLS) && ctx->proto == IPPROTO_UDP))) {
|
||||
/* TLS thread is not yet running, start it now */
|
||||
ret = start_tls_client(ctx);
|
||||
if (ret < 0) {
|
||||
NET_DBG("TLS thread cannot be started (%d)", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
started = true;
|
||||
|
||||
/* Let the TLS thread run first */
|
||||
k_yield();
|
||||
}
|
||||
#else
|
||||
ARG_UNUSED(started);
|
||||
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
|
||||
|
||||
#if defined(CONFIG_NET_APP_DTLS)
|
||||
if (ctx->proto == IPPROTO_UDP) {
|
||||
if (!ctx->dtls.ctx) {
|
||||
ret = connect_dtls(ctx, net_ctx,
|
||||
&ctx->default_ctx->remote);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = net_context_connect(ctx->dtls.ctx,
|
||||
&ctx->dtls.ctx->remote,
|
||||
sizeof(ctx->dtls.ctx->remote),
|
||||
_app_connected,
|
||||
timeout,
|
||||
ctx);
|
||||
} else {
|
||||
/* If we have already a connection, then we cannot
|
||||
* really continue.
|
||||
*/
|
||||
ret = -EAGAIN;
|
||||
}
|
||||
} else
|
||||
#endif /* CONFIG_NET_APP_DTLS */
|
||||
{
|
||||
ret = net_context_connect(net_ctx,
|
||||
&ctx->default_ctx->remote,
|
||||
sizeof(ctx->default_ctx->remote),
|
||||
_app_connected,
|
||||
timeout,
|
||||
ctx);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
NET_DBG("Cannot connect to peer (%d)", ret);
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
|
||||
if (started) {
|
||||
_net_app_tls_handler_stop(ctx);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
|
||||
static void tls_client_handler(struct net_app_ctx *ctx,
|
||||
struct k_sem *startup_sync)
|
||||
{
|
||||
int ret;
|
||||
|
||||
NET_DBG("Starting TLS client thread for %p", ctx);
|
||||
|
||||
ret = _net_app_tls_init(ctx, MBEDTLS_SSL_IS_CLIENT);
|
||||
if (ret < 0) {
|
||||
NET_DBG("TLS client init failed");
|
||||
return;
|
||||
}
|
||||
|
||||
k_sem_give(startup_sync);
|
||||
|
||||
while (1) {
|
||||
/* We wait until TLS connection is established */
|
||||
k_sem_take(&ctx->client.connect_wait, K_FOREVER);
|
||||
|
||||
ret = _net_app_ssl_mainloop(ctx);
|
||||
if (ctx->tls.connection_closing) {
|
||||
mbedtls_ssl_close_notify(&ctx->tls.mbedtls.ssl);
|
||||
|
||||
if (ctx->cb.close) {
|
||||
ctx->cb.close(ctx, -ESHUTDOWN, ctx->user_data);
|
||||
}
|
||||
|
||||
ctx->tls.connection_closing = false;
|
||||
ctx->is_enabled = false;
|
||||
|
||||
/* Wait more connection requests from user */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
NET_ERR("TLS mainloop startup failed (%d)", ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NET_DBG("Shutting down TLS handler");
|
||||
|
||||
/* If there is any pending data that have not been processed
|
||||
* yet, we need to free it here.
|
||||
*/
|
||||
if (ctx->tls.mbedtls.ssl_ctx.rx_pkt) {
|
||||
net_pkt_unref(ctx->tls.mbedtls.ssl_ctx.rx_pkt);
|
||||
ctx->tls.mbedtls.ssl_ctx.rx_pkt = NULL;
|
||||
ctx->tls.mbedtls.ssl_ctx.frag = NULL;
|
||||
}
|
||||
|
||||
if (ctx->cb.close) {
|
||||
ctx->cb.close(ctx, -ESHUTDOWN, ctx->user_data);
|
||||
}
|
||||
|
||||
_net_app_tls_handler_stop(ctx);
|
||||
}
|
||||
|
||||
static int start_tls_client(struct net_app_ctx *ctx)
|
||||
{
|
||||
struct k_sem startup_sync;
|
||||
|
||||
/* Start the thread that handles TLS traffic. */
|
||||
if (ctx->tls.tid) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
k_sem_init(&startup_sync, 0, 1);
|
||||
|
||||
ctx->tls.tid = k_thread_create(&ctx->tls.thread,
|
||||
ctx->tls.stack,
|
||||
ctx->tls.stack_size,
|
||||
(k_thread_entry_t)tls_client_handler,
|
||||
ctx, &startup_sync, 0,
|
||||
K_PRIO_COOP(7), 0, 0);
|
||||
|
||||
/* Wait until we know that the TLS thread startup was ok */
|
||||
if (k_sem_take(&startup_sync, TLS_STARTUP_TIMEOUT) < 0) {
|
||||
_net_app_tls_handler_stop(ctx);
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int net_app_client_tls(struct net_app_ctx *ctx,
|
||||
u8_t *request_buf,
|
||||
size_t request_buf_len,
|
||||
u8_t *personalization_data,
|
||||
size_t personalization_data_len,
|
||||
net_app_ca_cert_cb_t cert_cb,
|
||||
const char *cert_host,
|
||||
net_app_entropy_src_cb_t entropy_src_cb,
|
||||
struct k_mem_pool *pool,
|
||||
k_thread_stack_t *stack,
|
||||
size_t stack_size)
|
||||
{
|
||||
if (!request_buf || request_buf_len == 0) {
|
||||
NET_ERR("Request buf must be set");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* mbedtls cannot receive or send larger buffer as what is defined
|
||||
* in a file pointed by CONFIG_MBEDTLS_CFG_FILE.
|
||||
*/
|
||||
if (request_buf_len > MBEDTLS_SSL_MAX_CONTENT_LEN) {
|
||||
NET_ERR("Request buf too large, max len is %d",
|
||||
MBEDTLS_SSL_MAX_CONTENT_LEN);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!cert_cb) {
|
||||
NET_ERR("Cert callback must be set");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctx->is_tls = true;
|
||||
ctx->send_data = _net_app_tls_sendto;
|
||||
ctx->recv_cb = _net_app_tls_received;
|
||||
ctx->tls.request_buf = request_buf;
|
||||
ctx->tls.request_buf_len = request_buf_len;
|
||||
ctx->tls.cert_host = cert_host;
|
||||
ctx->tls.stack = stack;
|
||||
ctx->tls.stack_size = stack_size;
|
||||
ctx->tls.mbedtls.ca_cert_cb = cert_cb;
|
||||
ctx->tls.pool = pool;
|
||||
ctx->tls.mbedtls.personalization_data = personalization_data;
|
||||
ctx->tls.mbedtls.personalization_data_len = personalization_data_len;
|
||||
|
||||
if (entropy_src_cb) {
|
||||
ctx->tls.mbedtls.entropy_src_cb = entropy_src_cb;
|
||||
} else {
|
||||
ctx->tls.mbedtls.entropy_src_cb = _net_app_entropy_source;
|
||||
}
|
||||
|
||||
/* The semaphore is released when the client calls net_app_connect() */
|
||||
k_sem_init(&ctx->client.connect_wait, 0, 1);
|
||||
|
||||
/* The mbedtls is initialized in TLS thread because of mbedtls stack
|
||||
* requirements. TLS thread is started when we get the first client
|
||||
* request to send data.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
|
File diff suppressed because it is too large
Load diff
|
@ -1,118 +0,0 @@
|
|||
/** @file
|
||||
* @brief Private net_api API routines
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Print extra info about received TLS data */
|
||||
#define RX_EXTRA_DEBUG 0
|
||||
|
||||
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
|
||||
#include <mbedtls/memory_buffer_alloc.h>
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_ERROR_C)
|
||||
#define _net_app_print_error(fmt, ret) \
|
||||
do { \
|
||||
char error[80]; \
|
||||
\
|
||||
mbedtls_strerror(ret, error, sizeof(error)); \
|
||||
\
|
||||
NET_ERR(fmt " (%s)", -ret, log_strdup(error)); \
|
||||
} while (0)
|
||||
#else
|
||||
#define _net_app_print_error(fmt, ret) NET_ERR(fmt, -ret)
|
||||
#endif
|
||||
|
||||
/* Direction of the packet (sending / receiving) */
|
||||
enum _net_app_dir {
|
||||
NET_APP_PKT_UNKNOWN = 0,
|
||||
NET_APP_PKT_TX = 1,
|
||||
NET_APP_PKT_RX = 2,
|
||||
};
|
||||
|
||||
#define BUF_ALLOC_TIMEOUT 100
|
||||
|
||||
void _net_app_print_info(struct net_app_ctx *ctx);
|
||||
|
||||
#if defined(CONFIG_NET_APP_SERVER) || defined(CONFIG_NET_APP_CLIENT)
|
||||
char *_net_app_sprint_ipaddr(char *buf, int buflen,
|
||||
const struct sockaddr *addr);
|
||||
void _net_app_received(struct net_context *net_ctx,
|
||||
struct net_pkt *pkt,
|
||||
int status,
|
||||
void *user_data);
|
||||
int _net_app_set_local_addr(struct net_app_ctx *ctx, struct sockaddr *addr,
|
||||
const char *myaddr, u16_t port);
|
||||
int _net_app_set_net_ctx(struct net_app_ctx *ctx,
|
||||
struct net_context *net_ctx,
|
||||
struct sockaddr *addr,
|
||||
socklen_t socklen,
|
||||
enum net_ip_protocol proto);
|
||||
int _net_app_config_local_ctx(struct net_app_ctx *ctx,
|
||||
enum net_sock_type sock_type,
|
||||
enum net_ip_protocol proto,
|
||||
struct sockaddr *addr);
|
||||
|
||||
#if CONFIG_NET_APP_LOG_LEVEL >= LOG_LEVEL_ERR
|
||||
struct net_context *_net_app_select_net_ctx_debug(struct net_app_ctx *ctx,
|
||||
const struct sockaddr *dst,
|
||||
const char *caller,
|
||||
int line);
|
||||
#define _net_app_select_net_ctx(ctx, dst) \
|
||||
_net_app_select_net_ctx_debug(ctx, dst, __func__, __LINE__)
|
||||
#else
|
||||
struct net_context *_net_app_select_net_ctx(struct net_app_ctx *ctx,
|
||||
const struct sockaddr *dst);
|
||||
#endif
|
||||
|
||||
int _net_app_ssl_mux(void *context, unsigned char *buf, size_t size);
|
||||
int _net_app_tls_sendto(struct net_pkt *pkt,
|
||||
const struct sockaddr *dst_addr,
|
||||
socklen_t addrlen,
|
||||
net_context_send_cb_t cb,
|
||||
s32_t timeout,
|
||||
void *token,
|
||||
void *user_data);
|
||||
void _net_app_tls_received(struct net_context *context,
|
||||
struct net_pkt *pkt,
|
||||
int status,
|
||||
void *user_data);
|
||||
int _net_app_ssl_mainloop(struct net_app_ctx *ctx);
|
||||
int _net_app_tls_trigger_close(struct net_app_ctx *ctx);
|
||||
|
||||
#if defined(CONFIG_NET_APP_SERVER)
|
||||
void _net_app_accept_cb(struct net_context *net_ctx,
|
||||
struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
int status, void *data);
|
||||
#endif /* CONFIG_NET_APP_SERVER */
|
||||
|
||||
#if defined(CONFIG_NET_APP_CLIENT)
|
||||
#endif /* CONFIG_NET_APP_CLIENT */
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
|
||||
bool _net_app_server_tls_enable(struct net_app_ctx *ctx);
|
||||
bool _net_app_server_tls_disable(struct net_app_ctx *ctx);
|
||||
void _net_app_tls_handler_stop(struct net_app_ctx *ctx);
|
||||
int _net_app_tls_init(struct net_app_ctx *ctx, int client_or_server);
|
||||
int _net_app_entropy_source(void *data, unsigned char *output, size_t len,
|
||||
size_t *olen);
|
||||
int _net_app_ssl_tx(void *context, const unsigned char *buf, size_t size);
|
||||
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
|
||||
|
||||
#if defined(CONFIG_NET_APP_DTLS)
|
||||
#include "../../ip/connection.h"
|
||||
enum net_verdict _net_app_dtls_established(struct net_conn *conn,
|
||||
struct net_pkt *pkt,
|
||||
void *user_data);
|
||||
#endif /* CONFIG_NET_APP_DTLS */
|
||||
|
||||
void _net_app_register(struct net_app_ctx *ctx);
|
||||
void _net_app_unregister(struct net_app_ctx *ctx);
|
||||
|
||||
#endif /* CONFIG_NET_APP_SERVER || CONFIG_NET_APP_CLIENT */
|
|
@ -1,516 +0,0 @@
|
|||
/* server.c */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(net_app, CONFIG_NET_APP_LOG_LEVEL);
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_if.h>
|
||||
|
||||
#include <net/net_app.h>
|
||||
|
||||
#include "net_app_private.h"
|
||||
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
static void new_client(struct net_context *net_ctx,
|
||||
const struct sockaddr *addr)
|
||||
{
|
||||
#if CONFIG_NET_APP_LOG_LEVEL >= LOG_LEVEL_WRN
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
#define PORT_STR sizeof("[]:xxxxx")
|
||||
char buf[NET_IPV6_ADDR_LEN + PORT_STR];
|
||||
#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
|
||||
#define PORT_STR sizeof(":xxxxx")
|
||||
char buf[NET_IPV4_ADDR_LEN + PORT_STR];
|
||||
#endif
|
||||
|
||||
NET_INFO("Connection from %s (%p)",
|
||||
log_strdup(_net_app_sprint_ipaddr(buf, sizeof(buf), addr)),
|
||||
net_ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int get_avail_net_ctx(struct net_app_ctx *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_NET_APP_SERVER_NUM_CONN; i++) {
|
||||
if (!ctx->server.net_ctxs[i] ||
|
||||
!net_context_is_used(ctx->server.net_ctxs[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void _net_app_accept_cb(struct net_context *net_ctx,
|
||||
struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
int status, void *data)
|
||||
{
|
||||
struct net_app_ctx *ctx = data;
|
||||
int i, ret;
|
||||
|
||||
ARG_UNUSED(addr);
|
||||
ARG_UNUSED(addrlen);
|
||||
|
||||
i = get_avail_net_ctx(ctx);
|
||||
|
||||
if (i < 0 || status != 0 || !ctx->is_enabled) {
|
||||
/* We are already connected and there are no free context slots
|
||||
* available so this new connection must be closed.
|
||||
*/
|
||||
net_context_put(net_ctx);
|
||||
|
||||
if (ctx->cb.connect) {
|
||||
if (!status) {
|
||||
status = -ECONNREFUSED;
|
||||
}
|
||||
|
||||
ctx->cb.connect(ctx, status, ctx->user_data);
|
||||
}
|
||||
|
||||
if (i < 0) {
|
||||
NET_DBG("All connection slots occupied, new "
|
||||
"connection dropped");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
NET_DBG("[%d] Accepted net_ctx %p", i, net_ctx);
|
||||
|
||||
ret = net_context_recv(net_ctx, ctx->recv_cb, K_NO_WAIT, ctx);
|
||||
if (ret < 0) {
|
||||
NET_DBG("Cannot set recv_cb (%d)", ret);
|
||||
}
|
||||
|
||||
ctx->server.net_ctxs[i] = net_ctx;
|
||||
|
||||
/* We need to set the backpointer here, as otherwise it is impossible
|
||||
* to find the correct net_ctx from a list of net_ctxs.
|
||||
*/
|
||||
net_ctx->net_app = ctx;
|
||||
|
||||
new_client(net_ctx, addr);
|
||||
|
||||
if (ctx->cb.connect) {
|
||||
ctx->cb.connect(ctx, 0, ctx->user_data);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_NET_TCP */
|
||||
|
||||
int net_app_listen(struct net_app_ctx *ctx)
|
||||
{
|
||||
bool dual = false, v4_failed = false;
|
||||
int ret;
|
||||
|
||||
if (!ctx) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!ctx->is_init) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (ctx->app_type != NET_APP_SERVER) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
if (ctx->ipv4.local.sa_family == AF_UNSPEC) {
|
||||
ctx->ipv4.local.sa_family = AF_INET;
|
||||
dual = true;
|
||||
|
||||
_net_app_set_local_addr(ctx, &ctx->ipv4.local, NULL,
|
||||
net_sin(&ctx->ipv4.local)->sin_port);
|
||||
}
|
||||
|
||||
ret = _net_app_set_net_ctx(ctx, ctx->ipv4.ctx, &ctx->ipv4.local,
|
||||
sizeof(struct sockaddr_in), ctx->proto);
|
||||
if (ret < 0) {
|
||||
if (ctx->ipv4.ctx) {
|
||||
net_context_put(ctx->ipv4.ctx);
|
||||
ctx->ipv4.ctx = NULL;
|
||||
}
|
||||
|
||||
v4_failed = true;
|
||||
}
|
||||
#if defined(CONFIG_NET_APP_DTLS)
|
||||
else {
|
||||
if (ctx->is_tls && ctx->proto == IPPROTO_UDP) {
|
||||
net_context_recv(ctx->ipv4.ctx, ctx->recv_cb,
|
||||
K_NO_WAIT, ctx);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
|
||||
/* We ignore the IPv4 error if IPv6 is enabled */
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (ctx->ipv6.local.sa_family == AF_UNSPEC || dual) {
|
||||
ctx->ipv6.local.sa_family = AF_INET6;
|
||||
|
||||
_net_app_set_local_addr(ctx, &ctx->ipv6.local, NULL,
|
||||
net_sin6(&ctx->ipv6.local)->sin6_port);
|
||||
}
|
||||
|
||||
ret = _net_app_set_net_ctx(ctx, ctx->ipv6.ctx, &ctx->ipv6.local,
|
||||
sizeof(struct sockaddr_in6), ctx->proto);
|
||||
if (ret < 0) {
|
||||
if (ctx->ipv6.ctx) {
|
||||
net_context_put(ctx->ipv6.ctx);
|
||||
ctx->ipv6.ctx = NULL;
|
||||
}
|
||||
|
||||
if (!v4_failed) {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
#if defined(CONFIG_NET_APP_DTLS)
|
||||
else {
|
||||
if (ctx->is_tls && ctx->proto == IPPROTO_UDP) {
|
||||
net_context_recv(ctx->ipv6.ctx, ctx->recv_cb,
|
||||
K_NO_WAIT, ctx);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int net_app_init_server(struct net_app_ctx *ctx,
|
||||
enum net_sock_type sock_type,
|
||||
enum net_ip_protocol proto,
|
||||
struct sockaddr *server_addr,
|
||||
u16_t port,
|
||||
void *user_data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!ctx) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ctx->is_init) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
(void)memset(&ctx->ipv4.local, 0, sizeof(ctx->ipv4.local));
|
||||
ctx->ipv4.local.sa_family = AF_INET;
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
(void)memset(&ctx->ipv6.local, 0, sizeof(ctx->ipv6.local));
|
||||
ctx->ipv6.local.sa_family = AF_INET6;
|
||||
#endif
|
||||
|
||||
if (server_addr) {
|
||||
if (server_addr->sa_family == AF_INET) {
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
memcpy(&ctx->ipv4.local, server_addr,
|
||||
sizeof(ctx->ipv4.local));
|
||||
#else
|
||||
return -EPROTONOSUPPORT;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (server_addr->sa_family == AF_INET6) {
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
memcpy(&ctx->ipv6.local, server_addr,
|
||||
sizeof(ctx->ipv6.local));
|
||||
#else
|
||||
return -EPROTONOSUPPORT;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (server_addr->sa_family == AF_UNSPEC) {
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
net_sin(&ctx->ipv4.local)->sin_port =
|
||||
net_sin(server_addr)->sin_port;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
net_sin6(&ctx->ipv6.local)->sin6_port =
|
||||
net_sin6(server_addr)->sin6_port;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
if (port == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
net_sin(&ctx->ipv4.local)->sin_port = htons(port);
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
net_sin6(&ctx->ipv6.local)->sin6_port = htons(port);
|
||||
#endif
|
||||
}
|
||||
|
||||
ctx->app_type = NET_APP_SERVER;
|
||||
ctx->user_data = user_data;
|
||||
ctx->send_data = net_context_sendto;
|
||||
ctx->recv_cb = _net_app_received;
|
||||
ctx->proto = proto;
|
||||
ctx->sock_type = sock_type;
|
||||
|
||||
ret = _net_app_config_local_ctx(ctx, sock_type, proto, server_addr);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
NET_ASSERT_INFO(ctx->default_ctx, "Default ctx not selected");
|
||||
|
||||
ctx->is_init = true;
|
||||
|
||||
_net_app_register(ctx);
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
|
||||
static inline void new_server(struct net_app_ctx *ctx,
|
||||
const char *server_banner)
|
||||
{
|
||||
#if CONFIG_NET_APP_LOG_LEVEL >= LOG_LEVEL_WRN
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
#define PORT_STR sizeof("[]:xxxxx")
|
||||
char buf[NET_IPV6_ADDR_LEN + PORT_STR];
|
||||
#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
|
||||
#define PORT_STR sizeof(":xxxxx")
|
||||
char buf[NET_IPV4_ADDR_LEN + PORT_STR];
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
NET_INFO("%s %s (%p)", log_strdup(server_banner),
|
||||
log_strdup(_net_app_sprint_ipaddr(buf, sizeof(buf),
|
||||
&ctx->ipv6.local)),
|
||||
ctx);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
NET_INFO("%s %s (%p)", log_strdup(server_banner),
|
||||
log_strdup(_net_app_sprint_ipaddr(buf, sizeof(buf),
|
||||
&ctx->ipv4.local)),
|
||||
ctx);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct net_context *find_net_ctx(struct net_app_ctx *ctx,
|
||||
int *idx)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONFIG_NET_APP_SERVER_NUM_CONN; i++) {
|
||||
if (ctx->server.net_ctxs[i] &&
|
||||
ctx->server.net_ctxs[i]->net_app == ctx &&
|
||||
net_context_is_used(ctx->server.net_ctxs[i])) {
|
||||
*idx = i;
|
||||
return ctx->server.net_ctxs[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void tls_server_handler(struct net_app_ctx *ctx,
|
||||
struct k_sem *startup_sync)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
NET_DBG("Starting TLS server thread for %p", ctx);
|
||||
|
||||
ret = _net_app_tls_init(ctx, MBEDTLS_SSL_IS_SERVER);
|
||||
if (ret < 0) {
|
||||
NET_DBG("TLS server init failed");
|
||||
return;
|
||||
}
|
||||
|
||||
k_sem_give(startup_sync);
|
||||
|
||||
while (1) {
|
||||
struct net_context *net_ctx;
|
||||
|
||||
_net_app_ssl_mainloop(ctx);
|
||||
|
||||
NET_DBG("Closing %p connection", ctx);
|
||||
|
||||
ctx->tls.close_requested = false;
|
||||
|
||||
mbedtls_ssl_close_notify(&ctx->tls.mbedtls.ssl);
|
||||
|
||||
ctx->tls.tx_pending = false;
|
||||
|
||||
if (ctx->cb.close) {
|
||||
ctx->cb.close(ctx, -ESHUTDOWN, ctx->user_data);
|
||||
}
|
||||
|
||||
net_ctx = find_net_ctx(ctx, &i);
|
||||
if (net_ctx) {
|
||||
NET_DBG("Server context %p removed", net_ctx);
|
||||
net_context_put(net_ctx);
|
||||
ctx->server.net_ctxs[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define TLS_STARTUP_TIMEOUT K_SECONDS(5)
|
||||
|
||||
bool _net_app_server_tls_enable(struct net_app_ctx *ctx)
|
||||
{
|
||||
struct k_sem startup_sync;
|
||||
|
||||
NET_ASSERT(ctx);
|
||||
|
||||
if (!(ctx->tls.stack && ctx->tls.stack_size > 0)) {
|
||||
/* No stack or stack size is 0, we cannot enable */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Start the thread that handles TLS traffic. */
|
||||
if (!ctx->tls.tid) {
|
||||
k_sem_init(&startup_sync, 0, 1);
|
||||
|
||||
ctx->tls.tid = k_thread_create(&ctx->tls.thread,
|
||||
ctx->tls.stack,
|
||||
ctx->tls.stack_size,
|
||||
(k_thread_entry_t)
|
||||
tls_server_handler,
|
||||
ctx, &startup_sync, 0,
|
||||
K_PRIO_COOP(7), 0, 0);
|
||||
|
||||
/* Wait until we know that the TLS thread startup was ok */
|
||||
if (k_sem_take(&startup_sync, TLS_STARTUP_TIMEOUT) < 0) {
|
||||
NET_ERR("TLS server handler start failed");
|
||||
_net_app_tls_handler_stop(ctx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _net_app_server_tls_disable(struct net_app_ctx *ctx)
|
||||
{
|
||||
NET_ASSERT(ctx);
|
||||
|
||||
if (!ctx->tls.tid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_net_app_tls_handler_stop(ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int net_app_server_tls(struct net_app_ctx *ctx,
|
||||
u8_t *request_buf,
|
||||
size_t request_buf_len,
|
||||
const char *server_banner,
|
||||
u8_t *personalization_data,
|
||||
size_t personalization_data_len,
|
||||
net_app_cert_cb_t cert_cb,
|
||||
net_app_entropy_src_cb_t entropy_src_cb,
|
||||
struct k_mem_pool *pool,
|
||||
k_thread_stack_t *stack,
|
||||
size_t stack_size)
|
||||
{
|
||||
if (!request_buf || request_buf_len == 0) {
|
||||
NET_ERR("Request buf must be set");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* mbedtls cannot receive or send larger buffer as what is defined
|
||||
* in a file pointed by CONFIG_MBEDTLS_CFG_FILE.
|
||||
*/
|
||||
if (request_buf_len > MBEDTLS_SSL_MAX_CONTENT_LEN) {
|
||||
NET_ERR("Request buf too large, max len is %d",
|
||||
MBEDTLS_SSL_MAX_CONTENT_LEN);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!cert_cb) {
|
||||
NET_ERR("Cert callback must be set");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (server_banner) {
|
||||
new_server(ctx, server_banner);
|
||||
}
|
||||
|
||||
ctx->tls.request_buf = request_buf;
|
||||
ctx->tls.request_buf_len = request_buf_len;
|
||||
ctx->is_tls = true;
|
||||
ctx->tls.stack = stack;
|
||||
ctx->tls.stack_size = stack_size;
|
||||
ctx->tls.mbedtls.cert_cb = cert_cb;
|
||||
ctx->tls.pool = pool;
|
||||
|
||||
if (entropy_src_cb) {
|
||||
ctx->tls.mbedtls.entropy_src_cb = entropy_src_cb;
|
||||
} else {
|
||||
ctx->tls.mbedtls.entropy_src_cb = _net_app_entropy_source;
|
||||
}
|
||||
|
||||
ctx->tls.mbedtls.personalization_data = personalization_data;
|
||||
ctx->tls.mbedtls.personalization_data_len = personalization_data_len;
|
||||
ctx->send_data = _net_app_tls_sendto;
|
||||
ctx->recv_cb = _net_app_tls_received;
|
||||
|
||||
/* Then mbedtls specific initialization */
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
|
||||
|
||||
bool net_app_server_enable(struct net_app_ctx *ctx)
|
||||
{
|
||||
bool old;
|
||||
|
||||
NET_ASSERT(ctx);
|
||||
|
||||
old = ctx->is_enabled;
|
||||
|
||||
ctx->is_enabled = true;
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
|
||||
if (ctx->is_tls) {
|
||||
_net_app_server_tls_enable(ctx);
|
||||
}
|
||||
#endif
|
||||
return old;
|
||||
}
|
||||
|
||||
bool net_app_server_disable(struct net_app_ctx *ctx)
|
||||
{
|
||||
bool old;
|
||||
|
||||
NET_ASSERT(ctx);
|
||||
|
||||
old = ctx->is_enabled;
|
||||
|
||||
ctx->is_enabled = false;
|
||||
|
||||
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
|
||||
if (ctx->is_tls) {
|
||||
_net_app_server_tls_disable(ctx);
|
||||
}
|
||||
#endif
|
||||
return old;
|
||||
}
|
|
@ -9,3 +9,6 @@ zephyr_sources(
|
|||
zephyr_sources_ifdef(CONFIG_NET_SOCKETS_SOCKOPT_TLS sockets_tls.c)
|
||||
endif()
|
||||
zephyr_sources_ifdef(CONFIG_NET_SOCKETS_OFFLOAD socket_offload.c)
|
||||
|
||||
zephyr_link_interface_ifdef(CONFIG_MBEDTLS mbedTLS)
|
||||
zephyr_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.13.1)
|
||||
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||
project(net_app)
|
||||
|
||||
FILE(GLOB app_sources src/*.c)
|
||||
target_sources(app PRIVATE ${app_sources})
|
||||
|
||||
target_include_directories(app PRIVATE $ENV{ZEPHYR_BASE}/subsys/net/ip)
|
|
@ -1,29 +0,0 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_TEST=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=n
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_NET_DHCPV4=n
|
||||
CONFIG_NET_MAX_CONTEXTS=10
|
||||
CONFIG_NET_L2_DUMMY=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_ENTROPY_GENERATOR=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NET_IPV6_DAD=n
|
||||
CONFIG_NET_IPV6_MLD=n
|
||||
CONFIG_NET_IPV6_ND=n
|
||||
CONFIG_NET_PKT_TX_COUNT=10
|
||||
CONFIG_NET_PKT_RX_COUNT=10
|
||||
CONFIG_NET_BUF_RX_COUNT=10
|
||||
CONFIG_NET_BUF_TX_COUNT=10
|
||||
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=6
|
||||
CONFIG_NET_IPV6_MAX_NEIGHBORS=8
|
||||
CONFIG_NET_APP=y
|
||||
CONFIG_NET_APP_SERVER=y
|
||||
CONFIG_NET_APP_CLIENT=y
|
||||
CONFIG_NET_CONFIG_AUTO_INIT=n
|
||||
CONFIG_NET_CONFIG_SETTINGS=y
|
||||
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_ZTEST=y
|
||||
#CONFIG_NET_SHELL=y
|
|
@ -1,25 +0,0 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_TEST=y
|
||||
CONFIG_NET_IPV6=n
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_NET_DHCPV4=n
|
||||
CONFIG_NET_MAX_CONTEXTS=10
|
||||
CONFIG_NET_L2_DUMMY=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_ENTROPY_GENERATOR=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NET_PKT_TX_COUNT=10
|
||||
CONFIG_NET_PKT_RX_COUNT=10
|
||||
CONFIG_NET_BUF_RX_COUNT=10
|
||||
CONFIG_NET_BUF_TX_COUNT=10
|
||||
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3
|
||||
CONFIG_NET_APP=y
|
||||
CONFIG_NET_APP_SERVER=y
|
||||
CONFIG_NET_APP_CLIENT=y
|
||||
CONFIG_NET_CONFIG_AUTO_INIT=n
|
||||
CONFIG_NET_CONFIG_SETTINGS=y
|
||||
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
|
||||
CONFIG_ZTEST=y
|
||||
#CONFIG_NET_SHELL=y
|
|
@ -1,43 +0,0 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_TEST=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_NET_DHCPV4=n
|
||||
CONFIG_NET_MAX_CONTEXTS=10
|
||||
CONFIG_NET_L2_DUMMY=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_ENTROPY_GENERATOR=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NET_IPV6_DAD=n
|
||||
CONFIG_NET_IPV6_MLD=n
|
||||
CONFIG_NET_IPV6_ND=n
|
||||
CONFIG_NET_PKT_TX_COUNT=10
|
||||
CONFIG_NET_PKT_RX_COUNT=10
|
||||
CONFIG_NET_BUF_RX_COUNT=10
|
||||
CONFIG_NET_BUF_TX_COUNT=10
|
||||
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3
|
||||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6
|
||||
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=6
|
||||
CONFIG_NET_IPV6_MAX_NEIGHBORS=8
|
||||
CONFIG_NET_APP=y
|
||||
CONFIG_NET_APP_SERVER=y
|
||||
CONFIG_NET_APP_CLIENT=y
|
||||
CONFIG_NET_CONFIG_AUTO_INIT=n
|
||||
CONFIG_NET_CONFIG_SETTINGS=y
|
||||
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
|
||||
CONFIG_ZTEST=y
|
||||
|
||||
CONFIG_DNS_RESOLVER=y
|
||||
CONFIG_DNS_RESOLVER_MAX_SERVERS=4
|
||||
CONFIG_DNS_NUM_CONCUR_QUERIES=1
|
||||
CONFIG_DNS_SERVER_IP_ADDRESSES=y
|
||||
CONFIG_DNS_SERVER1="192.0.2.2"
|
||||
CONFIG_DNS_SERVER2="2001:db8::2"
|
||||
CONFIG_DNS_SERVER3="192.0.2.2:5353"
|
||||
CONFIG_DNS_SERVER4="[2001:db8::2]:5353"
|
||||
|
||||
#CONFIG_NET_SHELL=y
|
||||
CONFIG_COVERAGE=n
|
|
@ -1,31 +0,0 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_TEST=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=y
|
||||
CONFIG_NET_DHCPV4=n
|
||||
CONFIG_NET_MAX_CONTEXTS=10
|
||||
CONFIG_NET_L2_DUMMY=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_ENTROPY_GENERATOR=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NET_IPV6_DAD=n
|
||||
CONFIG_NET_IPV6_MLD=n
|
||||
CONFIG_NET_IPV6_ND=n
|
||||
CONFIG_NET_PKT_TX_COUNT=10
|
||||
CONFIG_NET_PKT_RX_COUNT=10
|
||||
CONFIG_NET_BUF_RX_COUNT=10
|
||||
CONFIG_NET_BUF_TX_COUNT=10
|
||||
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3
|
||||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6
|
||||
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=6
|
||||
CONFIG_NET_IPV6_MAX_NEIGHBORS=8
|
||||
CONFIG_NET_APP=y
|
||||
CONFIG_NET_APP_SERVER=y
|
||||
CONFIG_NET_APP_CLIENT=y
|
||||
CONFIG_NET_CONFIG_AUTO_INIT=n
|
||||
CONFIG_NET_CONFIG_SETTINGS=y
|
||||
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
|
||||
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
|
||||
CONFIG_ZTEST=y
|
|
@ -1,812 +0,0 @@
|
|||
/* main.c - Application main entry point */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(net_test, CONFIG_NET_APP_LOG_LEVEL);
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
#include <ztest.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/dummy.h>
|
||||
#include <net/buf.h>
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_if.h>
|
||||
|
||||
#include <net/net_config.h>
|
||||
#include <net/net_app.h>
|
||||
|
||||
#define NET_LOG_ENABLED 1
|
||||
#include "net_private.h"
|
||||
|
||||
#if defined(CONFIG_NET_APP_LOG_LEVEL_DBG)
|
||||
#define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DBG(fmt, ...)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
/* Interface 1 addresses */
|
||||
static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
|
||||
|
||||
/* Interface 2 addresses */
|
||||
static struct in6_addr my_addr2 = { { { 0x20, 0x01, 0x0d, 0xb8, 2, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
|
||||
|
||||
/* Extra address is assigned to ll_addr */
|
||||
static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0,
|
||||
0, 0, 0, 0xf2, 0xaa, 0x29, 0x02,
|
||||
0x04 } } };
|
||||
|
||||
static struct in6_addr in6addr_mcast = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
/* Interface 1 addresses IPv4 */
|
||||
static struct in_addr my_addr4 = { { { 192, 0, 1, 1 } } };
|
||||
#endif
|
||||
|
||||
static struct net_if *iface1;
|
||||
|
||||
static bool test_failed;
|
||||
static bool test_started;
|
||||
static struct k_sem wait_data;
|
||||
|
||||
#define WAIT_TIME 250
|
||||
|
||||
struct net_if_test {
|
||||
u8_t idx;
|
||||
u8_t mac_addr[sizeof(struct net_eth_addr)];
|
||||
struct net_linkaddr ll_addr;
|
||||
};
|
||||
|
||||
static int net_iface_dev_init(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8_t *net_iface_get_mac(struct device *dev)
|
||||
{
|
||||
struct net_if_test *data = dev->driver_data;
|
||||
|
||||
if (data->mac_addr[2] == 0x00) {
|
||||
/* 00-00-5E-00-53-xx Documentation RFC 7042 */
|
||||
data->mac_addr[0] = 0x00;
|
||||
data->mac_addr[1] = 0x00;
|
||||
data->mac_addr[2] = 0x5E;
|
||||
data->mac_addr[3] = 0x00;
|
||||
data->mac_addr[4] = 0x53;
|
||||
data->mac_addr[5] = sys_rand32_get();
|
||||
}
|
||||
|
||||
data->ll_addr.addr = data->mac_addr;
|
||||
data->ll_addr.len = 6;
|
||||
|
||||
return data->mac_addr;
|
||||
}
|
||||
|
||||
static void net_iface_init(struct net_if *iface)
|
||||
{
|
||||
u8_t *mac = net_iface_get_mac(net_if_get_device(iface));
|
||||
|
||||
net_if_set_link_addr(iface, mac, sizeof(struct net_eth_addr),
|
||||
NET_LINK_ETHERNET);
|
||||
}
|
||||
|
||||
static int sender_iface(struct device *dev, struct net_pkt *pkt)
|
||||
{
|
||||
if (!pkt->frags) {
|
||||
DBG("No data to send!\n");
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
if (test_started) {
|
||||
struct net_if_test *data = dev->driver_data;
|
||||
|
||||
if (net_if_get_by_iface(net_pkt_iface(pkt)) != data->idx) {
|
||||
DBG("Invalid interface %d index, expecting %d\n",
|
||||
data->idx, net_if_get_by_iface(net_pkt_iface(pkt)));
|
||||
test_failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
k_sem_give(&wait_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct net_if_test net_iface1_data;
|
||||
|
||||
static struct dummy_api net_iface_api = {
|
||||
.iface_api.init = net_iface_init,
|
||||
.send = sender_iface,
|
||||
};
|
||||
|
||||
#define _ETH_L2_LAYER DUMMY_L2
|
||||
#define _ETH_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2)
|
||||
|
||||
NET_DEVICE_INIT_INSTANCE(net_iface1_test,
|
||||
"iface1",
|
||||
iface1,
|
||||
net_iface_dev_init,
|
||||
&net_iface1_data,
|
||||
NULL,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&net_iface_api,
|
||||
_ETH_L2_LAYER,
|
||||
_ETH_L2_CTX_TYPE,
|
||||
127);
|
||||
|
||||
static void iface_setup(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
struct net_if_mcast_addr *maddr;
|
||||
#endif
|
||||
struct net_if_addr *ifaddr;
|
||||
int idx;
|
||||
|
||||
/* The semaphore is there to wait the data to be received. */
|
||||
k_sem_init(&wait_data, 0, UINT_MAX);
|
||||
|
||||
iface1 = net_if_get_by_index(0);
|
||||
|
||||
((struct net_if_test *)net_if_get_device(iface1)->driver_data)->idx = 0U;
|
||||
|
||||
idx = net_if_get_by_iface(iface1);
|
||||
zassert_equal(idx, 0, "Invalid index iface1");
|
||||
|
||||
DBG("Interfaces: [%d] iface1 %p\n",
|
||||
net_if_get_by_iface(iface1), iface1);
|
||||
|
||||
zassert_not_null(iface1, "Interface 1");
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
ifaddr = net_if_ipv6_addr_add(iface1, &my_addr1,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
if (!ifaddr) {
|
||||
DBG("Cannot add IPv6 address %s\n",
|
||||
net_sprint_ipv6_addr(&my_addr1));
|
||||
zassert_not_null(ifaddr, "addr1");
|
||||
}
|
||||
|
||||
/* For testing purposes we need to set the adddresses preferred */
|
||||
ifaddr->addr_state = NET_ADDR_PREFERRED;
|
||||
|
||||
ifaddr = net_if_ipv6_addr_add(iface1, &ll_addr,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
if (!ifaddr) {
|
||||
DBG("Cannot add IPv6 address %s\n",
|
||||
net_sprint_ipv6_addr(&ll_addr));
|
||||
zassert_not_null(ifaddr, "ll_addr");
|
||||
}
|
||||
|
||||
ifaddr->addr_state = NET_ADDR_PREFERRED;
|
||||
|
||||
net_ipv6_addr_create(&in6addr_mcast, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001);
|
||||
|
||||
maddr = net_if_ipv6_maddr_add(iface1, &in6addr_mcast);
|
||||
if (!maddr) {
|
||||
DBG("Cannot add multicast IPv6 address %s\n",
|
||||
net_sprint_ipv6_addr(&in6addr_mcast));
|
||||
zassert_not_null(maddr, "mcast");
|
||||
}
|
||||
#endif /* IPv6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
ifaddr = net_if_ipv4_addr_add(iface1, &my_addr4,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
if (!ifaddr) {
|
||||
DBG("Cannot add IPv4 address %s\n",
|
||||
net_sprint_ipv4_addr(&my_addr4));
|
||||
zassert_not_null(ifaddr, "addr4");
|
||||
}
|
||||
#endif
|
||||
|
||||
net_if_up(iface1);
|
||||
|
||||
/* The interface might receive data which might fail the checks
|
||||
* in the iface sending function, so we need to reset the failure
|
||||
* flag.
|
||||
*/
|
||||
test_failed = false;
|
||||
|
||||
test_started = true;
|
||||
}
|
||||
|
||||
static void app_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = net_config_init("Test app", 0, 1);
|
||||
zassert_equal(ret, 0, "app init");
|
||||
}
|
||||
|
||||
static struct net_app_ctx udp_server_ctx;
|
||||
static struct net_app_ctx tcp_server_ctx;
|
||||
|
||||
static void app_udp_server_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_udp_server(&udp_server_ctx, NULL, 42421, NULL);
|
||||
zassert_equal(ret, 0, "UDP server init");
|
||||
}
|
||||
|
||||
static void app_tcp_server_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_tcp_server(&tcp_server_ctx, NULL, 42422, NULL);
|
||||
zassert_equal(ret, 0, "TCP server init");
|
||||
}
|
||||
|
||||
static void app_udp_server_listen(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
net_app_server_enable(&udp_server_ctx);
|
||||
|
||||
ret = net_app_listen(&udp_server_ctx);
|
||||
zassert_equal(ret, 0, "UDP listen failed");
|
||||
}
|
||||
|
||||
static void app_tcp_server_listen(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
net_app_server_enable(&tcp_server_ctx);
|
||||
|
||||
ret = net_app_listen(&tcp_server_ctx);
|
||||
zassert_equal(ret, 0, "TCP listen failed");
|
||||
}
|
||||
|
||||
static void app_tcp6_client_peer(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static struct net_app_ctx ctx;
|
||||
int port;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_tcp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"2001:db8:200::1",
|
||||
42422,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, 0, "TCP IPv6 client init");
|
||||
|
||||
port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port);
|
||||
zassert_equal(port, 42422, "TCP port invalid");
|
||||
|
||||
ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr,
|
||||
&my_addr2);
|
||||
zassert_equal(ret, true, "IPv6 address mismatch");
|
||||
|
||||
ret = net_app_close(&ctx);
|
||||
zassert_equal(ret, 0, "TCP IPv6 client close");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_tcp4_client_peer(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
static struct net_app_ctx ctx;
|
||||
int port;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_tcp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"192.0.1.1",
|
||||
42422,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, 0, "TCP IPv4 client init");
|
||||
|
||||
port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port);
|
||||
zassert_equal(port, 42422, "TCP port invalid");
|
||||
|
||||
ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr,
|
||||
&my_addr4);
|
||||
zassert_equal(ret, true, "IPv4 address mismatch");
|
||||
|
||||
ret = net_app_close(&ctx);
|
||||
zassert_equal(ret, 0, "TCP IPv4 client close");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_udp6_client_peer(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static struct net_app_ctx ctx;
|
||||
int port;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_udp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"2001:db8:200::1",
|
||||
42421,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, 0, "UDP IPv6 client init");
|
||||
|
||||
port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port);
|
||||
zassert_equal(port, 42421, "UDP port invalid");
|
||||
|
||||
ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr,
|
||||
&my_addr2);
|
||||
zassert_equal(ret, true, "IPv6 address mismatch");
|
||||
|
||||
ret = net_app_close(&ctx);
|
||||
zassert_equal(ret, 0, "UDP IPv6 client close");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_udp4_client_peer(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
static struct net_app_ctx ctx;
|
||||
int port;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_udp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"192.0.1.1",
|
||||
42421,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, 0, "TCP IPv4 client init");
|
||||
|
||||
port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port);
|
||||
zassert_equal(port, 42421, "UDP port invalid");
|
||||
|
||||
ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr,
|
||||
&my_addr4);
|
||||
zassert_equal(ret, true, "IPv4 address mismatch");
|
||||
|
||||
ret = net_app_close(&ctx);
|
||||
zassert_equal(ret, 0, "UDP IPv4 client close");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_tcp6_client_peer_with_port(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static struct net_app_ctx ctx;
|
||||
int port;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_tcp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"[2001:db8:200::1]:1234",
|
||||
42422,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, 0, "TCP IPv6 client init");
|
||||
|
||||
port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port);
|
||||
zassert_equal(port, 1234, "TCP port invalid");
|
||||
|
||||
ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr,
|
||||
&my_addr2);
|
||||
zassert_equal(ret, true, "IPv6 address mismatch");
|
||||
|
||||
ret = net_app_close(&ctx);
|
||||
zassert_equal(ret, 0, "TCP IPv6 client close");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_tcp4_client_peer_with_port(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
static struct net_app_ctx ctx;
|
||||
int port;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_tcp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"192.0.1.1:1234",
|
||||
42422,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, 0, "TCP IPv4 client init");
|
||||
|
||||
port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port);
|
||||
zassert_equal(port, 1234, "TCP port invalid");
|
||||
|
||||
ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr,
|
||||
&my_addr4);
|
||||
zassert_equal(ret, true, "IPv4 address mismatch");
|
||||
|
||||
ret = net_app_close(&ctx);
|
||||
zassert_equal(ret, 0, "TCP IPv4 client close");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_udp6_client_peer_with_port(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static struct net_app_ctx ctx;
|
||||
int port;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_udp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"[2001:db8:200::1]:9999",
|
||||
42421,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, 0, "UDP IPv6 client init");
|
||||
|
||||
port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port);
|
||||
zassert_equal(port, 9999, "UDP port invalid");
|
||||
|
||||
ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr,
|
||||
&my_addr2);
|
||||
zassert_equal(ret, true, "IPv6 address mismatch");
|
||||
|
||||
ret = net_app_close(&ctx);
|
||||
zassert_equal(ret, 0, "UDP IPv6 client close");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_udp4_client_peer_with_port(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
static struct net_app_ctx ctx;
|
||||
int port;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_udp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"192.0.1.1:9999",
|
||||
42421,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, 0, "TCP IPv4 client init");
|
||||
|
||||
port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port);
|
||||
zassert_equal(port, 9999, "UDP port invalid");
|
||||
|
||||
ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr,
|
||||
&my_addr4);
|
||||
zassert_equal(ret, true, "IPv4 address mismatch");
|
||||
|
||||
ret = net_app_close(&ctx);
|
||||
zassert_equal(ret, 0, "UDP IPv4 client close");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_tcp6_client_peer_addr(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static struct net_app_ctx ctx;
|
||||
struct sockaddr_in6 peer;
|
||||
int port;
|
||||
int ret;
|
||||
|
||||
net_ipaddr_copy(&peer.sin6_addr, &my_addr2);
|
||||
peer.sin6_port = htons(8765);
|
||||
peer.sin6_family = AF_INET6;
|
||||
|
||||
ret = net_app_init_tcp_client(&ctx,
|
||||
NULL,
|
||||
(struct sockaddr *)&peer,
|
||||
"foobar",
|
||||
42422,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, 0, "TCP IPv6 client init");
|
||||
|
||||
port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port);
|
||||
zassert_equal(port, 8765, "TCP port invalid");
|
||||
|
||||
ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr,
|
||||
&my_addr2);
|
||||
zassert_equal(ret, true, "IPv6 address mismatch");
|
||||
|
||||
ret = net_app_close(&ctx);
|
||||
zassert_equal(ret, 0, "TCP IPv6 client close");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_tcp4_client_peer_addr(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
static struct net_app_ctx ctx;
|
||||
struct sockaddr_in peer;
|
||||
int port;
|
||||
int ret;
|
||||
|
||||
net_ipaddr_copy(&peer.sin_addr, &my_addr4);
|
||||
peer.sin_port = htons(8765);
|
||||
peer.sin_family = AF_INET;
|
||||
|
||||
ret = net_app_init_tcp_client(&ctx,
|
||||
NULL,
|
||||
(struct sockaddr *)&peer,
|
||||
"foobar",
|
||||
42422,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, 0, "TCP IPv4 client init");
|
||||
|
||||
port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port);
|
||||
zassert_equal(port, 8765, "TCP port invalid");
|
||||
|
||||
ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr,
|
||||
&my_addr4);
|
||||
zassert_equal(ret, true, "IPv4 address mismatch");
|
||||
|
||||
ret = net_app_close(&ctx);
|
||||
zassert_equal(ret, 0, "TCP IPv4 client close");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_udp6_client_peer_addr(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static struct net_app_ctx ctx;
|
||||
struct sockaddr_in6 peer;
|
||||
int port;
|
||||
int ret;
|
||||
|
||||
net_ipaddr_copy(&peer.sin6_addr, &my_addr2);
|
||||
peer.sin6_port = htons(8765);
|
||||
peer.sin6_family = AF_INET6;
|
||||
|
||||
ret = net_app_init_udp_client(&ctx,
|
||||
NULL,
|
||||
(struct sockaddr *)&peer,
|
||||
"foobar",
|
||||
42422,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, 0, "UDP IPv6 client init");
|
||||
|
||||
port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port);
|
||||
zassert_equal(port, 8765, "UDP port invalid");
|
||||
|
||||
ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr,
|
||||
&my_addr2);
|
||||
zassert_equal(ret, true, "IPv6 address mismatch");
|
||||
|
||||
ret = net_app_close(&ctx);
|
||||
zassert_equal(ret, 0, "UDP IPv6 client close");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_udp4_client_peer_addr(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
static struct net_app_ctx ctx;
|
||||
struct sockaddr_in peer;
|
||||
int port;
|
||||
int ret;
|
||||
|
||||
net_ipaddr_copy(&peer.sin_addr, &my_addr4);
|
||||
peer.sin_port = htons(8765);
|
||||
peer.sin_family = AF_INET;
|
||||
|
||||
ret = net_app_init_udp_client(&ctx,
|
||||
NULL,
|
||||
(struct sockaddr *)&peer,
|
||||
"foobar",
|
||||
42422,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, 0, "UDP IPv4 client init");
|
||||
|
||||
port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port);
|
||||
zassert_equal(port, 8765, "UDP port invalid");
|
||||
|
||||
ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr,
|
||||
&my_addr4);
|
||||
zassert_equal(ret, true, "IPv4 address mismatch");
|
||||
|
||||
ret = net_app_close(&ctx);
|
||||
zassert_equal(ret, 0, "UDP IPv4 client close");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_tcp6_client_hostname_fail(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static struct net_app_ctx ctx;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_tcp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"foobar",
|
||||
42422,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, -EINVAL, "TCP IPv6 client init");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_tcp4_client_hostname_fail(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
static struct net_app_ctx ctx;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_tcp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"foobar",
|
||||
42422,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, -EINVAL, "TCP IPv4 client init");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_udp6_client_hostname_fail(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static struct net_app_ctx ctx;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_udp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"foobar",
|
||||
42422,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, -EINVAL, "UDP IPv6 client init");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_udp4_client_hostname_fail(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
static struct net_app_ctx ctx;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_udp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"foobar",
|
||||
42422,
|
||||
0,
|
||||
NULL);
|
||||
zassert_equal(ret, -EINVAL, "UDP IPv4 client init");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_tcp6_client_hostname(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_DNS_RESOLVER)
|
||||
static struct net_app_ctx ctx;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_tcp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"foobar",
|
||||
42422,
|
||||
MSEC(100),
|
||||
NULL);
|
||||
zassert_equal(ret, -ETIMEDOUT, "TCP IPv6 client init");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_tcp4_client_hostname(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_DNS_RESOLVER)
|
||||
static struct net_app_ctx ctx;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_tcp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"foobar",
|
||||
42422,
|
||||
MSEC(100),
|
||||
NULL);
|
||||
zassert_equal(ret, -ETIMEDOUT, "TCP IPv4 client init");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_udp6_client_hostname(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_DNS_RESOLVER)
|
||||
static struct net_app_ctx ctx;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_udp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"foobar",
|
||||
42422,
|
||||
MSEC(100),
|
||||
NULL);
|
||||
zassert_equal(ret, -ETIMEDOUT, "UDP IPv6 client init");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_udp4_client_hostname(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_DNS_RESOLVER)
|
||||
static struct net_app_ctx ctx;
|
||||
int ret;
|
||||
|
||||
ret = net_app_init_udp_client(&ctx,
|
||||
NULL,
|
||||
NULL,
|
||||
"foobar",
|
||||
42422,
|
||||
MSEC(100),
|
||||
NULL);
|
||||
zassert_equal(ret, -ETIMEDOUT, "UDP IPv4 client init");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_close_server(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = net_app_close(&udp_server_ctx);
|
||||
zassert_equal(ret, 0, "UDP server close");
|
||||
|
||||
ret = net_app_close(&tcp_server_ctx);
|
||||
zassert_equal(ret, 0, "TCP server close");
|
||||
}
|
||||
|
||||
void test_main(void)
|
||||
{
|
||||
ztest_test_suite(net_app_test,
|
||||
ztest_unit_test(iface_setup),
|
||||
ztest_unit_test(app_init),
|
||||
ztest_unit_test(app_udp_server_init),
|
||||
ztest_unit_test(app_tcp_server_init),
|
||||
ztest_unit_test(app_udp_server_listen),
|
||||
ztest_unit_test(app_tcp_server_listen),
|
||||
ztest_unit_test(app_tcp6_client_peer),
|
||||
ztest_unit_test(app_udp6_client_peer),
|
||||
ztest_unit_test(app_tcp4_client_peer),
|
||||
ztest_unit_test(app_udp4_client_peer),
|
||||
ztest_unit_test(app_tcp6_client_peer_with_port),
|
||||
ztest_unit_test(app_tcp4_client_peer_with_port),
|
||||
ztest_unit_test(app_udp6_client_peer_with_port),
|
||||
ztest_unit_test(app_udp4_client_peer_with_port),
|
||||
ztest_unit_test(app_tcp6_client_peer_addr),
|
||||
ztest_unit_test(app_tcp4_client_peer_addr),
|
||||
ztest_unit_test(app_udp6_client_peer_addr),
|
||||
ztest_unit_test(app_udp4_client_peer_addr),
|
||||
ztest_unit_test(app_tcp6_client_hostname_fail),
|
||||
ztest_unit_test(app_tcp4_client_hostname_fail),
|
||||
ztest_unit_test(app_udp6_client_hostname_fail),
|
||||
ztest_unit_test(app_udp4_client_hostname_fail),
|
||||
ztest_unit_test(app_tcp6_client_hostname),
|
||||
ztest_unit_test(app_tcp4_client_hostname),
|
||||
ztest_unit_test(app_udp6_client_hostname),
|
||||
ztest_unit_test(app_udp4_client_hostname),
|
||||
ztest_unit_test(app_close_server)
|
||||
);
|
||||
|
||||
ztest_run_test_suite(net_app_test);
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
common:
|
||||
depends_on: netif
|
||||
platform_whitelist: native_posix qemu_x86 qemu_cortex_m3
|
||||
tests:
|
||||
net.app:
|
||||
min_ram: 32
|
||||
tags: net
|
||||
net.app.no-ipv4:
|
||||
extra_args: CONF_FILE=prj-no-ipv4.conf
|
||||
min_ram: 32
|
||||
tags: net
|
||||
net.app.no-ipv6:
|
||||
extra_args: CONF_FILE=prj-no-ipv6.conf
|
||||
min_ram: 32
|
||||
tags: net
|
||||
net.app.with-dns:
|
||||
extra_args: CONF_FILE=prj-with-dns.conf
|
||||
min_ram: 32
|
||||
tags: net dns
|
|
@ -21,7 +21,6 @@ CONFIG_NET_IF_MAX_IPV4_COUNT=2
|
|||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6
|
||||
CONFIG_NET_IPV6_ND=n
|
||||
CONFIG_ZTEST=y
|
||||
CONFIG_NET_APP=n
|
||||
CONFIG_NET_CONFIG_SETTINGS=n
|
||||
CONFIG_NET_SHELL=n
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ CONFIG_NET_IF_MAX_IPV6_COUNT=6
|
|||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6
|
||||
CONFIG_NET_IPV6_ND=n
|
||||
CONFIG_ZTEST=y
|
||||
CONFIG_NET_APP=n
|
||||
CONFIG_NET_CONFIG_SETTINGS=n
|
||||
CONFIG_NET_SHELL=n
|
||||
CONFIG_PTP_CLOCK=y
|
||||
|
|
|
@ -28,7 +28,6 @@ CONFIG_NET_CONTEXT_PRIORITY=y
|
|||
CONFIG_NET_TC_TX_COUNT=8
|
||||
CONFIG_NET_TC_RX_COUNT=8
|
||||
CONFIG_ZTEST=y
|
||||
CONFIG_NET_APP=n
|
||||
CONFIG_NET_CONFIG_SETTINGS=n
|
||||
CONFIG_NET_SHELL=n
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ CONFIG_NET_IF_MAX_IPV6_COUNT=6
|
|||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6
|
||||
CONFIG_NET_IPV6_ND=n
|
||||
CONFIG_ZTEST=y
|
||||
CONFIG_NET_APP=n
|
||||
CONFIG_NET_CONFIG_SETTINGS=n
|
||||
CONFIG_NET_SHELL=n
|
||||
CONFIG_NET_PKT_TIMESTAMP=y
|
||||
|
|
|
@ -23,7 +23,6 @@ CONFIG_NET_VLAN=y
|
|||
CONFIG_NET_VLAN_COUNT=4
|
||||
CONFIG_NET_CONTEXT_PRIORITY=y
|
||||
CONFIG_ZTEST=y
|
||||
CONFIG_NET_APP=n
|
||||
CONFIG_NET_CONFIG_SETTINGS=n
|
||||
CONFIG_NET_SHELL=n
|
||||
|
||||
|
|
Loading…
Reference in a new issue