net: app: Create support for network application API
The network application API is a higher level API for creating client and server type applications. Instead of applications dealing with low level details, the network application API provides services that most of the applications can use directly. This commit removes the internal net_sample_*() API and converts the existing users of it to use the new net_app API. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
c55870e885
commit
a1be6a8ba9
19 changed files with 3566 additions and 190 deletions
897
include/net/net_app.h
Normal file
897
include/net/net_app.h
Normal file
|
@ -0,0 +1,897 @@
|
||||||
|
/** @file
|
||||||
|
* @brief Common routines needed in various network applications.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __NET_APP_H
|
||||||
|
#define __NET_APP_H
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_APP_TLS)
|
||||||
|
#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 */
|
||||||
|
|
||||||
|
#include <net/net_ip.h>
|
||||||
|
#include <net/net_pkt.h>
|
||||||
|
#include <net/net_context.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Flags that tell what kind of functionality is needed by the application. */
|
||||||
|
#define NET_APP_NEED_ROUTER 0x00000001
|
||||||
|
#define NET_APP_NEED_IPV6 0x00000002
|
||||||
|
#define NET_APP_NEED_IPV4 0x00000004
|
||||||
|
|
||||||
|
enum net_app_type {
|
||||||
|
NET_APP_UNSPEC = 0,
|
||||||
|
NET_APP_SERVER,
|
||||||
|
NET_APP_CLIENT,
|
||||||
|
};
|
||||||
|
|
||||||
|
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)
|
||||||
|
/* Internal information for managing TLS data */
|
||||||
|
struct tls_context {
|
||||||
|
struct net_pkt *rx_pkt;
|
||||||
|
struct net_buf *frag;
|
||||||
|
struct k_sem tx_sem;
|
||||||
|
struct k_fifo tx_rx_fifo;
|
||||||
|
int remaining;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
|
||||||
|
/** Network application context. */
|
||||||
|
struct net_app_ctx {
|
||||||
|
#if defined(CONFIG_NET_IPV6)
|
||||||
|
/** Network IPv6 context. */
|
||||||
|
struct net_context *ipv6_ctx;
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_NET_IPV4)
|
||||||
|
/** Network IPv4 context. */
|
||||||
|
struct net_context *ipv4_ctx;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** 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;
|
||||||
|
|
||||||
|
/** Local address */
|
||||||
|
struct sockaddr local;
|
||||||
|
|
||||||
|
/** Remote address */
|
||||||
|
struct sockaddr remote;
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_APP_SERVER)
|
||||||
|
struct {
|
||||||
|
#if defined(CONFIG_NET_TCP)
|
||||||
|
/** Currently active network context. This will contain the
|
||||||
|
* new context that is created after connection is accepted
|
||||||
|
* when TCP is enabled.
|
||||||
|
*/
|
||||||
|
struct net_context *net_ctx;
|
||||||
|
#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)
|
||||||
|
struct {
|
||||||
|
/** TLS stack for mbedtls library. */
|
||||||
|
u8_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;
|
||||||
|
u8_t *personalization_data;
|
||||||
|
size_t personalization_data_len;
|
||||||
|
} mbedtls;
|
||||||
|
|
||||||
|
/** Have we called connect cb yet? */
|
||||||
|
bool connect_cb_called;
|
||||||
|
} tls;
|
||||||
|
#endif /* CONFIG_NET_APP_TLS */
|
||||||
|
|
||||||
|
#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;
|
||||||
|
|
||||||
|
/** 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 will need
|
||||||
|
* to be enabled manually.
|
||||||
|
*/
|
||||||
|
u8_t is_enabled : 1;
|
||||||
|
|
||||||
|
/** Unused bits */
|
||||||
|
u8_t _padding : 5;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize this network application.
|
||||||
|
*
|
||||||
|
* @param app_info String describing this application.
|
||||||
|
* @param flags Flags related to this application startup.
|
||||||
|
* @param timeout How long to wait the network setup before continuing
|
||||||
|
* the startup.
|
||||||
|
*
|
||||||
|
* @return 0 if ok, <0 if error.
|
||||||
|
*/
|
||||||
|
int net_app_init(const char *app_info, u32_t flags, s32_t timeout);
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
#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 syntex 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 syntex 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 syntex 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 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,
|
||||||
|
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 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)
|
||||||
|
#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 suppied 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 certifacates.
|
||||||
|
* @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,
|
||||||
|
u8_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 suppied 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 certifacates.
|
||||||
|
* @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,
|
||||||
|
u8_t *stack,
|
||||||
|
size_t stack_len);
|
||||||
|
|
||||||
|
bool net_app_server_tls_enable(struct net_app_ctx *ctx);
|
||||||
|
bool net_app_server_tls_disable(struct net_app_ctx *ctx);
|
||||||
|
#endif /* CONFIG_NET_APP_SERVER */
|
||||||
|
|
||||||
|
#endif /* CONFIG_NET_APP_SEC */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __NET_APP_H */
|
|
@ -13,9 +13,25 @@ endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_NET_L2_IEEE802154), y)
|
ifeq ($(CONFIG_NET_L2_IEEE802154), y)
|
||||||
ifeq ($(CONFIG_NET_APP_SETTINGS), y)
|
ifeq ($(CONFIG_NET_APP_SETTINGS), y)
|
||||||
|
ccflags-y += -I${ZEPHYR_BASE}/samples/net/common/
|
||||||
obj-y += ../../common/ieee802154_settings.o
|
obj-y += ../../common/ieee802154_settings.o
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_IEEE802154_CC2520),y)
|
||||||
|
ifeq ($(CONFIG_BOARD_ARDUINO_101),y)
|
||||||
|
ccflags-y +=-I${ZEPHYR_BASE}/include/drivers/
|
||||||
|
obj-y += ../../common/cc2520_a101.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_BOARD_FRDM_K64F),y)
|
||||||
|
ccflags-y +=-I${ZEPHYR_BASE}/drivers/
|
||||||
|
ccflags-y +=-I${ZEPHYR_BASE}/include/drivers/
|
||||||
|
obj-y += ../../common/cc2520_frdm_k64f.o
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_NET_TESTING), y)
|
||||||
ccflags-y +=-I${ZEPHYR_BASE}/samples/net/common/
|
ccflags-y +=-I${ZEPHYR_BASE}/samples/net/common/
|
||||||
obj-y += ../../common/sample_app_setup.o
|
ccflags-y +=-DNET_TESTING_SERVER=1
|
||||||
|
endif
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
/** @file
|
|
||||||
* @brief Common routines needed in various network sample applications.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2017 Intel Corporation
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __NET_SAMPLE_APP_H
|
|
||||||
#define __NET_SAMPLE_APP_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* What kind of functionality is needed by the application. */
|
|
||||||
#define NET_SAMPLE_NEED_ROUTER 0x00000001
|
|
||||||
#define NET_SAMPLE_NEED_IPV6 0x00000002
|
|
||||||
#define NET_SAMPLE_NEED_IPV4 0x00000004
|
|
||||||
|
|
||||||
int net_sample_app_init(const char *app_info, u32_t flags, s32_t timeout);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __NET_SAMPLE_APP_H */
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include <net/http.h>
|
#include <net/http.h>
|
||||||
|
|
||||||
#include <net_sample_app.h>
|
#include <net/net_app.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
@ -307,7 +307,7 @@ void main(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = net_sample_app_init("Run HTTP client", 0, APP_STARTUP_TIME);
|
ret = net_app_init("Run HTTP client", 0, APP_STARTUP_TIME);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
panic("Application init failed");
|
panic("Application init failed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include <net/net_context.h>
|
#include <net/net_context.h>
|
||||||
#include <net/http.h>
|
#include <net/http.h>
|
||||||
|
|
||||||
#include <net_sample_app.h>
|
#include <net/net_app.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
@ -279,13 +279,13 @@ void main(void)
|
||||||
* before continuing.
|
* before continuing.
|
||||||
*/
|
*/
|
||||||
#if defined(CONFIG_NET_IPV6)
|
#if defined(CONFIG_NET_IPV6)
|
||||||
flags |= NET_SAMPLE_NEED_IPV6;
|
flags |= NET_APP_NEED_IPV6;
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_NET_IPV4)
|
#if defined(CONFIG_NET_IPV4)
|
||||||
flags |= NET_SAMPLE_NEED_IPV4;
|
flags |= NET_APP_NEED_IPV4;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ret = net_sample_app_init(APP_BANNER, flags, APP_STARTUP_TIME);
|
ret = net_app_init(APP_BANNER, flags, APP_STARTUP_TIME);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
panic("Application init failed");
|
panic("Application init failed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,4 @@
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
include $(ZEPHYR_BASE)/samples/net/common/Makefile.common
|
|
||||||
|
|
||||||
obj-y += main.o
|
obj-y += main.o
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include <net/http.h>
|
#include <net/http.h>
|
||||||
|
|
||||||
#include <net_sample_app.h>
|
#include <net/net_app.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@ void main(void)
|
||||||
bool failure = false;
|
bool failure = false;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = net_sample_app_init("Run HTTPS client", 0, APP_STARTUP_TIME);
|
ret = net_app_init("Run HTTPS client", 0, APP_STARTUP_TIME);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
panic("Application init failed");
|
panic("Application init failed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -345,6 +345,4 @@ source "subsys/net/ip/Kconfig.rpl"
|
||||||
|
|
||||||
source "subsys/net/ip/Kconfig.stats"
|
source "subsys/net/ip/Kconfig.stats"
|
||||||
|
|
||||||
source "subsys/net/ip/Kconfig.app"
|
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -1,113 +0,0 @@
|
||||||
# Kconfig.app - Options for sample applications
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2016 Intel Corporation.
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
#
|
|
||||||
|
|
||||||
menuconfig NET_APP_SETTINGS
|
|
||||||
bool "Set network settings for sample applications"
|
|
||||||
default n
|
|
||||||
help
|
|
||||||
Allow IP addresses to be set in config file for
|
|
||||||
networking client/server sample applications, or
|
|
||||||
some link-layer dedicated settings like the channel.
|
|
||||||
Beware this is not meant to be used for proper
|
|
||||||
provisioning but quick sampling/testing.
|
|
||||||
|
|
||||||
if NET_APP_SETTINGS
|
|
||||||
|
|
||||||
if NET_IPV6
|
|
||||||
|
|
||||||
config NET_APP_MY_IPV6_ADDR
|
|
||||||
string "My IPv6 address"
|
|
||||||
help
|
|
||||||
Use 2001:db8::1 here if uncertain.
|
|
||||||
|
|
||||||
config NET_APP_PEER_IPV6_ADDR
|
|
||||||
string "Peer IPv6 address"
|
|
||||||
help
|
|
||||||
This is only applicable in client side applications that try
|
|
||||||
to establish a connection to peer host.
|
|
||||||
Use 2001:db8::2 here if uncertain.
|
|
||||||
|
|
||||||
endif # NET_IPV6
|
|
||||||
|
|
||||||
if NET_IPV4
|
|
||||||
|
|
||||||
config NET_APP_MY_IPV4_ADDR
|
|
||||||
string "My IPv4 address"
|
|
||||||
help
|
|
||||||
Use 192.0.2.1 here if uncertain.
|
|
||||||
|
|
||||||
config NET_APP_PEER_IPV4_ADDR
|
|
||||||
string "Peer IPv4 address"
|
|
||||||
help
|
|
||||||
This is only applicable in client side applications that try
|
|
||||||
to establish a connection to peer host.
|
|
||||||
Use 192.0.2.2 here if uncertain.
|
|
||||||
|
|
||||||
endif # NET_IPV4
|
|
||||||
|
|
||||||
if NET_L2_IEEE802154 || NET_L2_RAW_CHANNEL
|
|
||||||
|
|
||||||
config NET_APP_IEEE802154_DEV_NAME
|
|
||||||
string "IEEE 802.15.4 device name"
|
|
||||||
help
|
|
||||||
The device name to get bindings from in the sample application.
|
|
||||||
|
|
||||||
config NET_APP_IEEE802154_PAN_ID
|
|
||||||
hex "IEEE 802.15.4 PAN ID"
|
|
||||||
default 0xabcd
|
|
||||||
help
|
|
||||||
The PAN ID to use by default in the sample.
|
|
||||||
|
|
||||||
config NET_APP_IEEE802154_CHANNEL
|
|
||||||
int "IEEE 802.15.4 channel"
|
|
||||||
default 26
|
|
||||||
help
|
|
||||||
The channel to use by default in the sample application.
|
|
||||||
|
|
||||||
config NET_APP_IEEE802154_RADIO_TX_POWER
|
|
||||||
int "IEEE 802.15.4 TX power in dbm"
|
|
||||||
default 0
|
|
||||||
help
|
|
||||||
The TX power to use by default in the sample application.
|
|
||||||
See NET_L2_IEEE802154_RADIO_DFLT_TX_POWER for more info.
|
|
||||||
|
|
||||||
config NET_APP_IEEE802154_SECURITY_KEY
|
|
||||||
string "IEEE 802.15.4 security key"
|
|
||||||
default "moooh!"
|
|
||||||
depends on NET_L2_IEEE802154_SECURITY
|
|
||||||
help
|
|
||||||
The key string to use for the link-layer security part.
|
|
||||||
|
|
||||||
config NET_APP_IEEE802154_SECURITY_KEY_MODE
|
|
||||||
int "IEEE 802.15.4 security key mode"
|
|
||||||
default 0
|
|
||||||
range 0 0
|
|
||||||
depends on NET_L2_IEEE802154_SECURITY
|
|
||||||
help
|
|
||||||
The key mode to use for the link-layer security part.
|
|
||||||
Only implicit mode is supported, thus 0.
|
|
||||||
|
|
||||||
config NET_APP_IEEE802154_SECURITY_LEVEL
|
|
||||||
int "IEEE 802.15.4 security level (0-7)"
|
|
||||||
default 0
|
|
||||||
range 0 7
|
|
||||||
depends on NET_L2_IEEE802154_SECURITY
|
|
||||||
help
|
|
||||||
The security level to use for the link-layer security part.
|
|
||||||
0 means no security
|
|
||||||
1 authentication only with a 4 bytes length tag
|
|
||||||
2 authentication only with a 8 bytes length tag
|
|
||||||
3 authentication only with a 16 bytes length tag
|
|
||||||
4 encryption only
|
|
||||||
5 encryption/authentication with a 4 bytes length tag
|
|
||||||
6 encryption/authentication with a 8 bytes length tag
|
|
||||||
7 encryption/authentication with a 16 bytes length tag
|
|
||||||
|
|
||||||
endif # NET_L2_IEEE802154 || NET_L2_RAW_CHANNEL
|
|
||||||
|
|
||||||
endif # NET_APP_SETTINGS
|
|
|
@ -3,3 +3,4 @@ obj-$(CONFIG_ZOAP) += zoap/
|
||||||
obj-$(CONFIG_DNS_RESOLVER) += dns/
|
obj-$(CONFIG_DNS_RESOLVER) += dns/
|
||||||
obj-$(CONFIG_MQTT_LIB) += mqtt/
|
obj-$(CONFIG_MQTT_LIB) += mqtt/
|
||||||
obj-$(CONFIG_HTTP) += http/
|
obj-$(CONFIG_HTTP) += http/
|
||||||
|
obj-$(CONFIG_NET_APP_SETTINGS) += app/
|
||||||
|
|
|
@ -17,3 +17,9 @@ source "subsys/net/lib/mqtt/Kconfig"
|
||||||
source "subsys/net/lib/http/Kconfig"
|
source "subsys/net/lib/http/Kconfig"
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
menu "Network Applications"
|
||||||
|
|
||||||
|
source "subsys/net/lib/app/Kconfig"
|
||||||
|
|
||||||
|
endmenu
|
||||||
|
|
|
@ -17,3 +17,7 @@ endif
|
||||||
ifdef CONFIG_HTTP
|
ifdef CONFIG_HTTP
|
||||||
include $(srctree)/subsys/net/lib/http/Makefile
|
include $(srctree)/subsys/net/lib/http/Makefile
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_NET_APP_SETTINGS
|
||||||
|
include $(srctree)/subsys/net/lib/app/Makefile
|
||||||
|
endif
|
||||||
|
|
223
subsys/net/lib/app/Kconfig
Normal file
223
subsys/net/lib/app/Kconfig
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
# 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
|
||||||
|
|
||||||
|
config NET_APP_AUTO_INIT
|
||||||
|
bool "Init networking support automatically during device startup"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
If this option is set, then the net_app API is automatically
|
||||||
|
initialized when the device is started. If you do not wish to do
|
||||||
|
this, then disable this and call net_app_init() in your application.
|
||||||
|
|
||||||
|
config NET_APP_INIT_PRIO
|
||||||
|
int "Startup priority for the network application init"
|
||||||
|
default 95
|
||||||
|
depends on NET_APP_AUTO_INIT
|
||||||
|
|
||||||
|
config NET_APP_INIT_TIMEOUT
|
||||||
|
int "How long to wait for networking to be ready and available"
|
||||||
|
default 30
|
||||||
|
depends on NET_APP_AUTO_INIT
|
||||||
|
help
|
||||||
|
The value is in seconds. If for example IPv4 address from DHCPv4 is not
|
||||||
|
received within this limit, then the net_app_init() call will fail
|
||||||
|
during the device startup.
|
||||||
|
|
||||||
|
config NET_APP_NEED_IPV6
|
||||||
|
bool "This application wants IPv6 support"
|
||||||
|
depends on NET_APP_AUTO_INIT
|
||||||
|
select NET_IPV6
|
||||||
|
help
|
||||||
|
The network application needs IPv6 support to function properly.
|
||||||
|
This option makes sure the network application is initialized properly
|
||||||
|
in order to use IPv6.
|
||||||
|
|
||||||
|
config NET_APP_NEED_IPV6_ROUTER
|
||||||
|
bool "This application wants IPv6 router to exists"
|
||||||
|
depends on NET_APP_AUTO_INIT
|
||||||
|
depends on NET_IPV6
|
||||||
|
help
|
||||||
|
The network application needs IPv6 router to exists before continuing.
|
||||||
|
What this means that the application wants to wait until it receives
|
||||||
|
IPv6 router advertisement message before continuing.
|
||||||
|
|
||||||
|
config NET_APP_NEED_IPV4
|
||||||
|
bool "This application wants IPv4 support"
|
||||||
|
depends on NET_APP_AUTO_INIT
|
||||||
|
select NET_IPV4
|
||||||
|
help
|
||||||
|
The network application needs IPv4 support to function properly.
|
||||||
|
This option makes sure the network application is initialized properly
|
||||||
|
in order to use IPv4.
|
||||||
|
|
||||||
|
config NET_DEBUG_APP
|
||||||
|
bool "Debug net app library"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enables net app library to output debug messages
|
||||||
|
|
||||||
|
config NET_APP_SERVER
|
||||||
|
bool "Enable server support"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enables net app library server APIs.
|
||||||
|
|
||||||
|
config NET_APP_CLIENT
|
||||||
|
bool "Enable client support"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enables net app library client APIs.
|
||||||
|
|
||||||
|
config NET_APP_TLS
|
||||||
|
bool "Enable TLS support for TCP applications"
|
||||||
|
default n
|
||||||
|
select MBEDTLS
|
||||||
|
help
|
||||||
|
Enables net app library to use TLS for encrypted communication.
|
||||||
|
|
||||||
|
config NET_DEBUG_APP_TLS_LEVEL
|
||||||
|
int "Debug level for mbedtls in net app library"
|
||||||
|
depends on NET_APP_TLS && NET_DEBUG_APP
|
||||||
|
default 0
|
||||||
|
range 0 4
|
||||||
|
help
|
||||||
|
Sets log level for the mbedtls when debugging net_app library.
|
||||||
|
Levels are (from ext/lib/crypto/mbedtls/include/mbedtls/debug.h):
|
||||||
|
0 No debug
|
||||||
|
1 Error
|
||||||
|
2 State change
|
||||||
|
3 Information
|
||||||
|
4 Verbose
|
||||||
|
|
||||||
|
config NET_APP_TLS_STACK_SIZE
|
||||||
|
int "TLS handler thread stack size"
|
||||||
|
default 8192
|
||||||
|
depends on NET_APP_TLS
|
||||||
|
help
|
||||||
|
TLS handler thread stack size. The mbedtls routines will use this stack
|
||||||
|
thus it is by default very large.
|
||||||
|
|
||||||
|
endif # NET_APP
|
||||||
|
|
||||||
|
menuconfig NET_APP_SETTINGS
|
||||||
|
bool "Set network settings for applications"
|
||||||
|
default n
|
||||||
|
depends on NET_APP
|
||||||
|
help
|
||||||
|
Allow IP addresses to be set in config file for
|
||||||
|
networking client/server sample applications, or
|
||||||
|
some link-layer dedicated settings like the channel.
|
||||||
|
Beware this is not meant to be used for proper
|
||||||
|
provisioning but quick sampling/testing.
|
||||||
|
|
||||||
|
if NET_APP_SETTINGS
|
||||||
|
|
||||||
|
if NET_IPV6
|
||||||
|
|
||||||
|
config NET_APP_MY_IPV6_ADDR
|
||||||
|
string "My IPv6 address"
|
||||||
|
help
|
||||||
|
Use 2001:db8::1 here if uncertain.
|
||||||
|
|
||||||
|
config NET_APP_PEER_IPV6_ADDR
|
||||||
|
string "Peer IPv6 address"
|
||||||
|
help
|
||||||
|
This is only applicable in client side applications that try
|
||||||
|
to establish a connection to peer host.
|
||||||
|
Use 2001:db8::2 here if uncertain.
|
||||||
|
|
||||||
|
endif # NET_IPV6
|
||||||
|
|
||||||
|
if NET_IPV4
|
||||||
|
|
||||||
|
config NET_APP_MY_IPV4_ADDR
|
||||||
|
string "My IPv4 address"
|
||||||
|
help
|
||||||
|
Use 192.0.2.1 here if uncertain.
|
||||||
|
|
||||||
|
config NET_APP_PEER_IPV4_ADDR
|
||||||
|
string "Peer IPv4 address"
|
||||||
|
help
|
||||||
|
This is only applicable in client side applications that try
|
||||||
|
to establish a connection to peer host.
|
||||||
|
Use 192.0.2.2 here if uncertain.
|
||||||
|
|
||||||
|
endif # NET_IPV4
|
||||||
|
|
||||||
|
if NET_L2_IEEE802154 || NET_L2_RAW_CHANNEL
|
||||||
|
|
||||||
|
config NET_APP_IEEE802154_DEV_NAME
|
||||||
|
string "IEEE 802.15.4 device name"
|
||||||
|
help
|
||||||
|
The device name to get bindings from in the sample application.
|
||||||
|
|
||||||
|
config NET_APP_IEEE802154_PAN_ID
|
||||||
|
hex "IEEE 802.15.4 PAN ID"
|
||||||
|
default 0xabcd
|
||||||
|
help
|
||||||
|
The PAN ID to use by default in the sample.
|
||||||
|
|
||||||
|
config NET_APP_IEEE802154_CHANNEL
|
||||||
|
int "IEEE 802.15.4 channel"
|
||||||
|
default 26
|
||||||
|
help
|
||||||
|
The channel to use by default in the sample application.
|
||||||
|
|
||||||
|
config NET_APP_IEEE802154_RADIO_TX_POWER
|
||||||
|
int "IEEE 802.15.4 TX power in dbm"
|
||||||
|
default 0
|
||||||
|
help
|
||||||
|
The TX power to use by default in the sample application.
|
||||||
|
See NET_L2_IEEE802154_RADIO_DFLT_TX_POWER for more info.
|
||||||
|
|
||||||
|
config NET_APP_IEEE802154_SECURITY_KEY
|
||||||
|
string "IEEE 802.15.4 security key"
|
||||||
|
default "moooh!"
|
||||||
|
depends on NET_L2_IEEE802154_SECURITY
|
||||||
|
help
|
||||||
|
The key string to use for the link-layer security part.
|
||||||
|
|
||||||
|
config NET_APP_IEEE802154_SECURITY_KEY_MODE
|
||||||
|
int "IEEE 802.15.4 security key mode"
|
||||||
|
default 0
|
||||||
|
range 0 0
|
||||||
|
depends on NET_L2_IEEE802154_SECURITY
|
||||||
|
help
|
||||||
|
The key mode to use for the link-layer security part.
|
||||||
|
Only implicit mode is supported, thus 0.
|
||||||
|
|
||||||
|
config NET_APP_IEEE802154_SECURITY_LEVEL
|
||||||
|
int "IEEE 802.15.4 security level (0-7)"
|
||||||
|
default 0
|
||||||
|
range 0 7
|
||||||
|
depends on NET_L2_IEEE802154_SECURITY
|
||||||
|
help
|
||||||
|
The security level to use for the link-layer security part.
|
||||||
|
0 means no security
|
||||||
|
1 authentication only with a 4 bytes length tag
|
||||||
|
2 authentication only with a 8 bytes length tag
|
||||||
|
3 authentication only with a 16 bytes length tag
|
||||||
|
4 encryption only
|
||||||
|
5 encryption/authentication with a 4 bytes length tag
|
||||||
|
6 encryption/authentication with a 8 bytes length tag
|
||||||
|
7 encryption/authentication with a 16 bytes length tag
|
||||||
|
|
||||||
|
endif # NET_L2_IEEE802154 || NET_L2_RAW_CHANNEL
|
||||||
|
|
||||||
|
endif # NET_APP_SETTINGS
|
20
subsys/net/lib/app/Makefile
Normal file
20
subsys/net/lib/app/Makefile
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2017 Intel Corporation
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
ccflags-$(CONFIG_NET_L2_BLUETOOTH) += -I${ZEPHYR_BASE}/samples/bluetooth/
|
||||||
|
ccflags-$(CONFIG_NET_L2_IEEE802154) += -I${ZEPHYR_BASE}/samples/net/common/
|
||||||
|
|
||||||
|
obj-$(CONFIG_NET_APP) += init.o
|
||||||
|
obj-$(CONFIG_NET_APP_SERVER) += server.o
|
||||||
|
obj-$(CONFIG_NET_APP_CLIENT) += client.o
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_NET_APP_SERVER),y)
|
||||||
|
obj-y += net_app.o
|
||||||
|
else
|
||||||
|
ifeq ($(CONFIG_NET_APP_CLIENT),y)
|
||||||
|
obj-y += net_app.o
|
||||||
|
endif
|
||||||
|
endif
|
602
subsys/net/lib/app/client.c
Normal file
602
subsys/net/lib/app/client.c
Normal file
|
@ -0,0 +1,602 @@
|
||||||
|
/* client.c */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Intel Corporation.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_DEBUG_APP)
|
||||||
|
#define SYS_LOG_DOMAIN "net/app"
|
||||||
|
#define NET_SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
|
||||||
|
#define NET_LOG_ENABLED 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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 "net_app_private.h"
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_APP_TLS)
|
||||||
|
#define TLS_STARTUP_TIMEOUT K_SECONDS(5)
|
||||||
|
static int start_tls_client(struct net_app_ctx *ctx);
|
||||||
|
#endif /* CONFIG_NET_APP_TLS */
|
||||||
|
|
||||||
|
#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->remote)->sin_addr,
|
||||||
|
&net_sin(&info->ai_addr)->sin_addr);
|
||||||
|
#else
|
||||||
|
goto out;
|
||||||
|
#endif
|
||||||
|
} else if (info->ai_family == AF_INET6) {
|
||||||
|
#if defined(CONFIG_NET_IPV6)
|
||||||
|
net_ipaddr_copy(&net_sin6(&ctx->remote)->sin6_addr,
|
||||||
|
&net_sin6(&info->ai_addr)->sin6_addr);
|
||||||
|
#else
|
||||||
|
goto out;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->remote.family = info->ai_family;
|
||||||
|
|
||||||
|
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)", 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", peer_addr_str);
|
||||||
|
ctx->client.dns_id = 0;
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->client.dns_id = 0;
|
||||||
|
|
||||||
|
if (ctx->remote.family == AF_UNSPEC) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DNS_RESOLVER */
|
||||||
|
|
||||||
|
static int get_port_number(const char *peer_addr_str,
|
||||||
|
char *buf,
|
||||||
|
size_t buf_len)
|
||||||
|
{
|
||||||
|
u16_t port = 0;
|
||||||
|
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 int set_remote_addr(struct net_app_ctx *ctx,
|
||||||
|
const char *peer_addr_str,
|
||||||
|
u16_t peer_port,
|
||||||
|
s32_t timeout)
|
||||||
|
{
|
||||||
|
char addr_str[INET6_ADDRSTRLEN + 1];
|
||||||
|
char *addr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* If the peer string contains port number, use that and ignore
|
||||||
|
* the port number parameter.
|
||||||
|
*/
|
||||||
|
ret = get_port_number(peer_addr_str, addr_str, sizeof(addr_str));
|
||||||
|
if (ret > 0) {
|
||||||
|
addr = addr_str;
|
||||||
|
peer_port = ret;
|
||||||
|
} else {
|
||||||
|
addr = (char *)peer_addr_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
|
||||||
|
ret = net_addr_pton(AF_INET6, addr,
|
||||||
|
&net_sin6(&ctx->remote)->sin6_addr);
|
||||||
|
if (ret < 0) {
|
||||||
|
/* Could be hostname, try DNS if configured. */
|
||||||
|
#if !defined(CONFIG_DNS_RESOLVER)
|
||||||
|
NET_ERR("Invalid IPv6 address %s", addr);
|
||||||
|
return -EINVAL;
|
||||||
|
#else
|
||||||
|
ret = resolve_name(ctx, addr, DNS_QUERY_TYPE_AAAA, timeout);
|
||||||
|
if (ret < 0) {
|
||||||
|
NET_ERR("Cannot resolve %s (%d)", addr, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
net_sin6(&ctx->remote)->sin6_port = htons(peer_port);
|
||||||
|
net_sin6(&ctx->remote)->sin6_family = AF_INET6;
|
||||||
|
#endif /* IPV6 && !IPV4 */
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
|
||||||
|
ret = net_addr_pton(AF_INET, addr,
|
||||||
|
&net_sin(&ctx->remote)->sin_addr);
|
||||||
|
if (ret < 0) {
|
||||||
|
/* Could be hostname, try DNS if configured. */
|
||||||
|
#if !defined(CONFIG_DNS_RESOLVER)
|
||||||
|
NET_ERR("Invalid IPv4 address %s", addr);
|
||||||
|
return -EINVAL;
|
||||||
|
#else
|
||||||
|
ret = resolve_name(ctx, addr, DNS_QUERY_TYPE_A, timeout);
|
||||||
|
if (ret < 0) {
|
||||||
|
NET_ERR("Cannot resolve %s (%d)", addr, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
net_sin(&ctx->remote)->sin_port = htons(peer_port);
|
||||||
|
net_sin(&ctx->remote)->sin_family = AF_INET;
|
||||||
|
#endif /* IPV6 && !IPV4 */
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6)
|
||||||
|
ret = net_addr_pton(AF_INET, addr,
|
||||||
|
&net_sin(&ctx->remote)->sin_addr);
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = net_addr_pton(AF_INET6, addr,
|
||||||
|
&net_sin6(&ctx->remote)->sin6_addr);
|
||||||
|
if (ret < 0) {
|
||||||
|
/* Could be hostname, try DNS if configured. */
|
||||||
|
#if !defined(CONFIG_DNS_RESOLVER)
|
||||||
|
NET_ERR("Invalid IPv4 or IPv6 address %s", addr);
|
||||||
|
return -EINVAL;
|
||||||
|
#else
|
||||||
|
ret = resolve_name(ctx, addr,
|
||||||
|
DNS_QUERY_TYPE_A, timeout);
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = resolve_name(ctx, addr,
|
||||||
|
DNS_QUERY_TYPE_AAAA,
|
||||||
|
timeout);
|
||||||
|
if (ret < 0) {
|
||||||
|
NET_ERR("Cannot resolve %s (%d)",
|
||||||
|
addr, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto ipv6;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto ipv4;
|
||||||
|
#endif /* !CONFIG_DNS_RESOLVER */
|
||||||
|
} else {
|
||||||
|
#if defined(CONFIG_DNS_RESOLVER)
|
||||||
|
ipv6:
|
||||||
|
#endif
|
||||||
|
net_sin6(&ctx->remote)->sin6_port =
|
||||||
|
htons(peer_port);
|
||||||
|
net_sin6(&ctx->remote)->sin6_family = AF_INET6;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#if defined(CONFIG_DNS_RESOLVER)
|
||||||
|
ipv4:
|
||||||
|
#endif
|
||||||
|
net_sin(&ctx->remote)->sin_port = htons(peer_port);
|
||||||
|
net_sin(&ctx->remote)->sin_family = AF_INET;
|
||||||
|
}
|
||||||
|
#endif /* IPV4 && IPV6 */
|
||||||
|
|
||||||
|
/* If we have not yet figured out what is the protocol family,
|
||||||
|
* then we cannot continue.
|
||||||
|
*/
|
||||||
|
if (ctx->remote.family == AF_UNSPEC) {
|
||||||
|
NET_ERR("Unknown protocol family.");
|
||||||
|
return -EPFNOSUPPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
struct sockaddr addr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->is_init) {
|
||||||
|
return -EALREADY;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
|
||||||
|
if (client_addr) {
|
||||||
|
memcpy(&addr, client_addr, sizeof(addr));
|
||||||
|
} else {
|
||||||
|
addr.family = AF_UNSPEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
ret = _net_app_config_local_ctx(ctx, sock_type, proto, &addr);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peer_addr) {
|
||||||
|
memcpy(&ctx->remote, peer_addr,
|
||||||
|
sizeof(ctx->remote));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!peer_addr_str) {
|
||||||
|
NET_ERR("Cannot know where to connect.");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = set_remote_addr(ctx, peer_addr_str, peer_port, timeout);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_IPV4)
|
||||||
|
if (ctx->remote.family == AF_INET) {
|
||||||
|
ctx->local.family = AF_INET;
|
||||||
|
_net_app_set_local_addr(&ctx->local, NULL,
|
||||||
|
net_sin(&ctx->local)->sin_port);
|
||||||
|
|
||||||
|
ret = _net_app_set_net_ctx(ctx, ctx->ipv4_ctx, &ctx->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->remote.family == AF_INET6) {
|
||||||
|
ctx->local.family = AF_INET6;
|
||||||
|
_net_app_set_local_addr(&ctx->local, NULL,
|
||||||
|
net_sin6(&ctx->local)->sin6_port);
|
||||||
|
|
||||||
|
ret = _net_app_set_net_ctx(ctx, ctx->ipv6_ctx, &ctx->local,
|
||||||
|
sizeof(struct sockaddr_in6),
|
||||||
|
ctx->proto);
|
||||||
|
if (ret < 0) {
|
||||||
|
net_context_put(ctx->ipv6_ctx);
|
||||||
|
ctx->ipv6_ctx = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_net_app_print_info(ctx);
|
||||||
|
|
||||||
|
out:
|
||||||
|
ctx->is_init = true;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _app_connected(struct net_context *net_ctx,
|
||||||
|
int status,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct net_app_ctx *ctx = user_data;
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_APP_TLS)
|
||||||
|
if (ctx->is_tls && ctx->proto == IPPROTO_TCP) {
|
||||||
|
k_sem_give(&ctx->client.connect_wait);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
net_context_recv(net_ctx, ctx->recv_cb, K_NO_WAIT, ctx);
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_APP_TLS)
|
||||||
|
if (ctx->is_tls && ctx->proto == IPPROTO_TCP) {
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (!net_ctx) {
|
||||||
|
return -EAFNOSUPPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_APP_TLS)
|
||||||
|
if (ctx->is_tls && ctx->proto == IPPROTO_TCP && !ctx->tls.tid) {
|
||||||
|
/* 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 */
|
||||||
|
|
||||||
|
ret = net_context_connect(net_ctx,
|
||||||
|
&ctx->remote,
|
||||||
|
sizeof(ctx->remote),
|
||||||
|
_app_connected,
|
||||||
|
timeout,
|
||||||
|
ctx);
|
||||||
|
if (ret < 0) {
|
||||||
|
NET_DBG("Cannot connect to peer (%d)", ret);
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_APP_TLS)
|
||||||
|
if (started) {
|
||||||
|
_net_app_tls_handler_stop(ctx);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_APP_TLS)
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* We wait until TLS connection is established */
|
||||||
|
k_sem_take(&ctx->client.connect_wait, K_FOREVER);
|
||||||
|
|
||||||
|
_net_app_ssl_mainloop(ctx);
|
||||||
|
|
||||||
|
mbedtls_ssl_close_notify(&ctx->tls.mbedtls.ssl);
|
||||||
|
|
||||||
|
/* 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,
|
||||||
|
u8_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 */
|
|
@ -1,4 +1,4 @@
|
||||||
/* sample_app_setup.c */
|
/* init.c */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017 Intel Corporation.
|
* Copyright (c) 2017 Intel Corporation.
|
||||||
|
@ -6,30 +6,26 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if 1
|
#if defined(CONFIG_NET_DEBUG_APP)
|
||||||
#define SYS_LOG_DOMAIN "sample/net"
|
#define SYS_LOG_DOMAIN "net/app"
|
||||||
#define NET_SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
|
#define NET_SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
|
||||||
#define NET_LOG_ENABLED 1
|
#define NET_LOG_ENABLED 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <zephyr.h>
|
#include <zephyr.h>
|
||||||
|
#include <init.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <net/net_core.h>
|
#include <net/net_core.h>
|
||||||
#include <net/net_ip.h>
|
#include <net/net_ip.h>
|
||||||
#include <net/net_if.h>
|
#include <net/net_if.h>
|
||||||
#include <net/dhcpv4.h>
|
#include <net/dhcpv4.h>
|
||||||
#include <net/net_mgmt.h>
|
#include <net/net_mgmt.h>
|
||||||
|
#include <net/dns_resolve.h>
|
||||||
|
|
||||||
#include "net_sample_app.h"
|
#include <net/net_app.h>
|
||||||
|
|
||||||
#if defined(CONFIG_NET_L2_BLUETOOTH)
|
|
||||||
#include <bluetooth/bluetooth.h>
|
|
||||||
#include <gatt/ipss.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CONFIG_NET_L2_IEEE802154)
|
|
||||||
#include <ieee802154_settings.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct k_sem waiter = K_SEM_INITIALIZER(waiter, 0, 1);
|
static struct k_sem waiter = K_SEM_INITIALIZER(waiter, 0, 1);
|
||||||
static struct k_sem counter;
|
static struct k_sem counter;
|
||||||
|
@ -41,7 +37,9 @@ static void ipv4_addr_add_handler(struct net_mgmt_event_callback *cb,
|
||||||
u32_t mgmt_event,
|
u32_t mgmt_event,
|
||||||
struct net_if *iface)
|
struct net_if *iface)
|
||||||
{
|
{
|
||||||
|
#if defined(CONFIG_NET_DEBUG_APP) && CONFIG_SYS_LOG_NET_LEVEL > 1
|
||||||
char hr_addr[NET_IPV4_ADDR_LEN];
|
char hr_addr[NET_IPV4_ADDR_LEN];
|
||||||
|
#endif
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) {
|
if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) {
|
||||||
|
@ -95,7 +93,9 @@ static void setup_dhcpv4(struct net_if *iface)
|
||||||
|
|
||||||
static void setup_ipv4(struct net_if *iface)
|
static void setup_ipv4(struct net_if *iface)
|
||||||
{
|
{
|
||||||
|
#if defined(CONFIG_NET_DEBUG_APP) && CONFIG_SYS_LOG_NET_LEVEL > 1
|
||||||
char hr_addr[NET_IPV4_ADDR_LEN];
|
char hr_addr[NET_IPV4_ADDR_LEN];
|
||||||
|
#endif
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
|
|
||||||
if (net_addr_pton(AF_INET, CONFIG_NET_APP_MY_IPV4_ADDR, &addr)) {
|
if (net_addr_pton(AF_INET, CONFIG_NET_APP_MY_IPV4_ADDR, &addr)) {
|
||||||
|
@ -128,7 +128,9 @@ static void ipv6_event_handler(struct net_mgmt_event_callback *cb,
|
||||||
u32_t mgmt_event, struct net_if *iface)
|
u32_t mgmt_event, struct net_if *iface)
|
||||||
{
|
{
|
||||||
if (mgmt_event == NET_EVENT_IPV6_DAD_SUCCEED) {
|
if (mgmt_event == NET_EVENT_IPV6_DAD_SUCCEED) {
|
||||||
|
#if defined(CONFIG_NET_DEBUG_APP) && CONFIG_SYS_LOG_NET_LEVEL > 1
|
||||||
char hr_addr[NET_IPV6_ADDR_LEN];
|
char hr_addr[NET_IPV6_ADDR_LEN];
|
||||||
|
#endif
|
||||||
struct net_if_addr *ifaddr;
|
struct net_if_addr *ifaddr;
|
||||||
|
|
||||||
ifaddr = net_if_ipv6_addr_lookup(&laddr, &iface);
|
ifaddr = net_if_ipv6_addr_lookup(&laddr, &iface);
|
||||||
|
@ -163,7 +165,7 @@ static void setup_ipv6(struct net_if *iface, u32_t flags)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & NET_SAMPLE_NEED_ROUTER) {
|
if (flags & NET_APP_NEED_ROUTER) {
|
||||||
mask |= NET_EVENT_IPV6_ROUTER_ADD;
|
mask |= NET_EVENT_IPV6_ROUTER_ADD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +184,7 @@ static void setup_ipv6(struct net_if *iface, u32_t flags)
|
||||||
#define setup_ipv6(...)
|
#define setup_ipv6(...)
|
||||||
#endif /* CONFIG_NET_IPV6 */
|
#endif /* CONFIG_NET_IPV6 */
|
||||||
|
|
||||||
int net_sample_app_init(const char *app_info, u32_t flags, s32_t timeout)
|
int net_app_init(const char *app_info, u32_t flags, s32_t timeout)
|
||||||
{
|
{
|
||||||
#define LOOP_DEVIDER 10
|
#define LOOP_DEVIDER 10
|
||||||
struct net_if *iface = net_if_get_default();
|
struct net_if *iface = net_if_get_default();
|
||||||
|
@ -193,28 +195,11 @@ int net_sample_app_init(const char *app_info, u32_t flags, s32_t timeout)
|
||||||
NET_INFO("%s", app_info);
|
NET_INFO("%s", app_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_NET_L2_BLUETOOTH)
|
if (flags & NET_APP_NEED_IPV6) {
|
||||||
if (bt_enable(NULL)) {
|
|
||||||
NET_ERR("Bluetooth init failed");
|
|
||||||
return -EFAULT;
|
|
||||||
} else {
|
|
||||||
ipss_init();
|
|
||||||
ipss_advertise();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CONFIG_NET_L2_IEEE802154)
|
|
||||||
if (ieee802154_sample_setup()) {
|
|
||||||
NET_ERR("IEEE 802.15.4 setup failed");
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (flags & NET_SAMPLE_NEED_IPV6) {
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & NET_SAMPLE_NEED_IPV4) {
|
if (flags & NET_APP_NEED_IPV4) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,3 +237,36 @@ int net_sample_app_init(const char *app_info, u32_t flags, s32_t timeout)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_APP_AUTO_INIT)
|
||||||
|
static int init_net_app(struct device *device)
|
||||||
|
{
|
||||||
|
u32_t flags = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ARG_UNUSED(device);
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_NET_APP_NEED_IPV6)) {
|
||||||
|
flags |= NET_APP_NEED_IPV6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_NET_APP_NEED_IPV6_ROUTER)) {
|
||||||
|
flags |= NET_APP_NEED_ROUTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_NET_APP_NEED_IPV4)) {
|
||||||
|
flags |= NET_APP_NEED_IPV4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the application automatically if needed */
|
||||||
|
ret = net_app_init("Initializing network", flags,
|
||||||
|
K_SECONDS(CONFIG_NET_APP_INIT_TIMEOUT));
|
||||||
|
if (ret < 0) {
|
||||||
|
NET_ERR("Network initialization failed (%d)", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_INIT(init_net_app, APPLICATION, CONFIG_NET_APP_INIT_PRIO);
|
||||||
|
#endif /* CONFIG_NET_APP_AUTO_INIT */
|
1259
subsys/net/lib/app/net_app.c
Normal file
1259
subsys/net/lib/app/net_app.c
Normal file
File diff suppressed because it is too large
Load diff
113
subsys/net/lib/app/net_app_private.h
Normal file
113
subsys/net/lib/app/net_app_private.h
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
/** @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_DEBUG_C)
|
||||||
|
#include <mbedtls/debug.h>
|
||||||
|
/* - Debug levels (from ext/lib/crypto/mbedtls/include/mbedtls/debug.h)
|
||||||
|
* - 0 No debug
|
||||||
|
* - 1 Error
|
||||||
|
* - 2 State change
|
||||||
|
* - 3 Informational
|
||||||
|
* - 4 Verbose
|
||||||
|
*/
|
||||||
|
#if defined(CONFIG_NET_DEBUG_APP_TLS_LEVEL)
|
||||||
|
#define DEBUG_THRESHOLD CONFIG_NET_DEBUG_APP_TLS_LEVEL
|
||||||
|
#else
|
||||||
|
#define DEBUG_THRESHOLD 0
|
||||||
|
#endif /* CONFIG_NET_DEBUG_APP_TLS_LEVEL */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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, 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
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_DEBUG_APP)
|
||||||
|
void _net_app_print_info(struct net_app_ctx *ctx);
|
||||||
|
#else
|
||||||
|
#define _net_app_print_info(...)
|
||||||
|
#endif /* CONFIG_NET_DEBUG_APP */
|
||||||
|
|
||||||
|
#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 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);
|
||||||
|
struct net_context *_net_app_select_net_ctx(struct net_app_ctx *ctx);
|
||||||
|
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);
|
||||||
|
|
||||||
|
#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)
|
||||||
|
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 */
|
||||||
|
|
||||||
|
#endif /* CONFIG_NET_APP_SERVER || CONFIG_NET_APP_CLIENT */
|
363
subsys/net/lib/app/server.c
Normal file
363
subsys/net/lib/app/server.c
Normal file
|
@ -0,0 +1,363 @@
|
||||||
|
/* server.c */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Intel Corporation.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_DEBUG_APP)
|
||||||
|
#define SYS_LOG_DOMAIN "net/app"
|
||||||
|
#define NET_SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
|
||||||
|
#define NET_LOG_ENABLED 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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 defined(CONFIG_NET_DEBUG_APP) && (CONFIG_SYS_LOG_NET_LEVEL > 2)
|
||||||
|
#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)",
|
||||||
|
_net_app_sprint_ipaddr(buf, sizeof(buf), addr),
|
||||||
|
net_ctx);
|
||||||
|
#endif /* CONFIG_NET_DEBUG_APP */
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
ARG_UNUSED(addr);
|
||||||
|
ARG_UNUSED(addrlen);
|
||||||
|
|
||||||
|
if (status != 0 || ctx->server.net_ctx) {
|
||||||
|
/* We are already connected and support only one connection at
|
||||||
|
* a time 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 (ctx->server.net_ctx) {
|
||||||
|
NET_DBG("Already connected via context %p",
|
||||||
|
ctx->server.net_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->server.net_ctx = net_ctx;
|
||||||
|
|
||||||
|
new_client(net_ctx, addr);
|
||||||
|
|
||||||
|
net_context_recv(net_ctx, ctx->recv_cb, K_NO_WAIT, ctx);
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
bool dual = false;
|
||||||
|
|
||||||
|
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->local.family == AF_UNSPEC) {
|
||||||
|
ctx->local.family = AF_INET;
|
||||||
|
dual = true;
|
||||||
|
|
||||||
|
_net_app_set_local_addr(&ctx->local, NULL,
|
||||||
|
net_sin(&ctx->local)->sin_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = _net_app_set_net_ctx(ctx, ctx->ipv4_ctx, &ctx->local,
|
||||||
|
sizeof(struct sockaddr_in), ctx->proto);
|
||||||
|
if (ret < 0) {
|
||||||
|
net_context_put(ctx->ipv4_ctx);
|
||||||
|
ctx->ipv4_ctx = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* We ignore the IPv4 error if IPv6 is enabled */
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_IPV6)
|
||||||
|
if (ctx->local.family == AF_UNSPEC || dual) {
|
||||||
|
ctx->local.family = AF_INET6;
|
||||||
|
|
||||||
|
_net_app_set_local_addr(&ctx->local, NULL,
|
||||||
|
net_sin6(&ctx->local)->sin6_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = _net_app_set_net_ctx(ctx, ctx->ipv6_ctx, &ctx->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_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ctx->local, 0, sizeof(ctx->local));
|
||||||
|
|
||||||
|
if (server_addr) {
|
||||||
|
memcpy(&ctx->local, server_addr,
|
||||||
|
sizeof(ctx->local));
|
||||||
|
} else {
|
||||||
|
ctx->local.family = AF_UNSPEC;
|
||||||
|
|
||||||
|
if (port == 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
net_sin(&ctx->local)->sin_port = htons(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
&ctx->local);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->is_init = true;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_NET_APP_TLS)
|
||||||
|
static inline void new_server(struct net_app_ctx *ctx,
|
||||||
|
const char *server_banner,
|
||||||
|
const struct sockaddr *addr)
|
||||||
|
{
|
||||||
|
#if defined(CONFIG_NET_DEBUG_APP) && (CONFIG_SYS_LOG_NET_LEVEL > 2)
|
||||||
|
#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 (addr) {
|
||||||
|
NET_INFO("%s %s (%p)", server_banner,
|
||||||
|
_net_app_sprint_ipaddr(buf, sizeof(buf), addr), ctx);
|
||||||
|
} else {
|
||||||
|
NET_INFO("%s (%p)", server_banner, ctx);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_NET_DEBUG_APP */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tls_server_handler(struct net_app_ctx *ctx,
|
||||||
|
struct k_sem *startup_sync)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
_net_app_ssl_mainloop(ctx);
|
||||||
|
|
||||||
|
mbedtls_ssl_close_notify(&ctx->tls.mbedtls.ssl);
|
||||||
|
|
||||||
|
if (ctx->cb.close) {
|
||||||
|
ctx->cb.close(ctx, -ESHUTDOWN, ctx->user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->server.net_ctx) {
|
||||||
|
NET_DBG("Server context %p removed",
|
||||||
|
ctx->server.net_ctx);
|
||||||
|
net_context_put(ctx->server.net_ctx);
|
||||||
|
ctx->server.net_ctx = 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->is_enabled = true;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
ctx->is_enabled = false;
|
||||||
|
|
||||||
|
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,
|
||||||
|
u8_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->local);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 */
|
Loading…
Add table
Add a link
Reference in a new issue