No use starting the application if the network interface is down. So start to listen connection management events and start the TCP and UDP handlers only after network is up and ready. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
225 lines
4.2 KiB
C
225 lines
4.2 KiB
C
/* echo-server.c - Networking echo server */
|
|
|
|
/*
|
|
* Copyright (c) 2016 Intel Corporation.
|
|
* Copyright (c) 2018 Nordic Semiconductor ASA.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <logging/log.h>
|
|
LOG_MODULE_REGISTER(net_echo_server_sample, LOG_LEVEL_DBG);
|
|
|
|
#include <zephyr.h>
|
|
#include <linker/sections.h>
|
|
#include <errno.h>
|
|
#include <shell/shell.h>
|
|
|
|
#include <net/net_core.h>
|
|
#include <net/tls_credentials.h>
|
|
|
|
#include <net/net_mgmt.h>
|
|
#include <net/net_event.h>
|
|
#include <net/net_conn_mgr.h>
|
|
|
|
#include "common.h"
|
|
#include "certificate.h"
|
|
|
|
#define APP_BANNER "Run echo server"
|
|
|
|
static struct k_sem quit_lock;
|
|
static struct net_mgmt_event_callback mgmt_cb;
|
|
static bool connected;
|
|
K_SEM_DEFINE(run_app, 0, 1);
|
|
static bool want_to_quit;
|
|
|
|
#define EVENT_MASK (NET_EVENT_L4_CONNECTED | \
|
|
NET_EVENT_L4_DISCONNECTED)
|
|
|
|
struct configs conf = {
|
|
.ipv4 = {
|
|
.proto = "IPv4",
|
|
},
|
|
.ipv6 = {
|
|
.proto = "IPv6",
|
|
},
|
|
};
|
|
|
|
void quit(void)
|
|
{
|
|
k_sem_give(&quit_lock);
|
|
}
|
|
|
|
static void start_udp_and_tcp(void)
|
|
{
|
|
LOG_INF("Starting...");
|
|
|
|
if (IS_ENABLED(CONFIG_NET_TCP)) {
|
|
start_tcp();
|
|
}
|
|
|
|
if (IS_ENABLED(CONFIG_NET_UDP)) {
|
|
start_udp();
|
|
}
|
|
}
|
|
|
|
static void stop_udp_and_tcp(void)
|
|
{
|
|
LOG_INF("Stopping...");
|
|
|
|
if (IS_ENABLED(CONFIG_NET_UDP)) {
|
|
stop_udp();
|
|
}
|
|
|
|
if (IS_ENABLED(CONFIG_NET_TCP)) {
|
|
stop_tcp();
|
|
}
|
|
}
|
|
|
|
static void event_handler(struct net_mgmt_event_callback *cb,
|
|
u32_t mgmt_event, struct net_if *iface)
|
|
{
|
|
if ((mgmt_event & EVENT_MASK) != mgmt_event) {
|
|
return;
|
|
}
|
|
|
|
if (want_to_quit) {
|
|
k_sem_give(&run_app);
|
|
want_to_quit = false;
|
|
}
|
|
|
|
if (mgmt_event == NET_EVENT_L4_CONNECTED) {
|
|
LOG_INF("Network connected");
|
|
|
|
connected = true;
|
|
k_sem_give(&run_app);
|
|
|
|
return;
|
|
}
|
|
|
|
if (mgmt_event == NET_EVENT_L4_DISCONNECTED) {
|
|
if (connected == false) {
|
|
LOG_INF("Waiting network to be connected");
|
|
} else {
|
|
LOG_INF("Network disconnected");
|
|
connected = false;
|
|
}
|
|
|
|
k_sem_reset(&run_app);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void init_app(void)
|
|
{
|
|
#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) || \
|
|
defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
|
|
int err;
|
|
#endif
|
|
k_sem_init(&quit_lock, 0, UINT_MAX);
|
|
|
|
LOG_INF(APP_BANNER);
|
|
|
|
#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
|
|
#if defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC)
|
|
err = tls_credential_add(SERVER_CERTIFICATE_TAG,
|
|
TLS_CREDENTIAL_CA_CERTIFICATE,
|
|
ca_certificate,
|
|
sizeof(ca_certificate));
|
|
if (err < 0) {
|
|
LOG_ERR("Failed to register CA certificate: %d", err);
|
|
}
|
|
#endif
|
|
|
|
err = tls_credential_add(SERVER_CERTIFICATE_TAG,
|
|
TLS_CREDENTIAL_SERVER_CERTIFICATE,
|
|
server_certificate,
|
|
sizeof(server_certificate));
|
|
if (err < 0) {
|
|
LOG_ERR("Failed to register public certificate: %d", err);
|
|
}
|
|
|
|
|
|
err = tls_credential_add(SERVER_CERTIFICATE_TAG,
|
|
TLS_CREDENTIAL_PRIVATE_KEY,
|
|
private_key, sizeof(private_key));
|
|
if (err < 0) {
|
|
LOG_ERR("Failed to register private key: %d", err);
|
|
}
|
|
#endif
|
|
|
|
#if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
|
|
err = tls_credential_add(PSK_TAG,
|
|
TLS_CREDENTIAL_PSK,
|
|
psk,
|
|
sizeof(psk));
|
|
if (err < 0) {
|
|
LOG_ERR("Failed to register PSK: %d", err);
|
|
}
|
|
err = tls_credential_add(PSK_TAG,
|
|
TLS_CREDENTIAL_PSK_ID,
|
|
psk_id,
|
|
sizeof(psk_id) - 1);
|
|
if (err < 0) {
|
|
LOG_ERR("Failed to register PSK ID: %d", err);
|
|
}
|
|
#endif
|
|
|
|
if (IS_ENABLED(CONFIG_NET_CONNECTION_MANAGER)) {
|
|
net_mgmt_init_event_callback(&mgmt_cb,
|
|
event_handler, EVENT_MASK);
|
|
net_mgmt_add_event_callback(&mgmt_cb);
|
|
|
|
net_conn_mgr_resend_status();
|
|
}
|
|
|
|
init_vlan();
|
|
}
|
|
|
|
static int cmd_sample_quit(const struct shell *shell,
|
|
size_t argc, char *argv[])
|
|
{
|
|
want_to_quit = true;
|
|
|
|
net_conn_mgr_resend_status();
|
|
|
|
quit();
|
|
|
|
return 0;
|
|
}
|
|
|
|
SHELL_STATIC_SUBCMD_SET_CREATE(sample_commands,
|
|
SHELL_CMD(quit, NULL,
|
|
"Quit the sample application\n",
|
|
cmd_sample_quit),
|
|
SHELL_SUBCMD_SET_END
|
|
);
|
|
|
|
SHELL_CMD_REGISTER(sample, &sample_commands,
|
|
"Sample application commands", NULL);
|
|
|
|
void main(void)
|
|
{
|
|
init_app();
|
|
|
|
if (!IS_ENABLED(CONFIG_NET_CONNECTION_MANAGER)) {
|
|
/* If the config library has not been configured to start the
|
|
* app only after we have a connection, then we can start
|
|
* it right away.
|
|
*/
|
|
k_sem_give(&run_app);
|
|
}
|
|
|
|
/* Wait for the connection. */
|
|
k_sem_take(&run_app, K_FOREVER);
|
|
|
|
start_udp_and_tcp();
|
|
|
|
k_sem_take(&quit_lock, K_FOREVER);
|
|
|
|
if (connected) {
|
|
stop_udp_and_tcp();
|
|
}
|
|
}
|