1 /* echo-server.c - Networking echo server */
2
3 /*
4 * Copyright (c) 2016 Intel Corporation.
5 * Copyright (c) 2018 Nordic Semiconductor ASA.
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(net_echo_server_sample, LOG_LEVEL_DBG);
12
13 #include <zephyr/kernel.h>
14 #include <zephyr/linker/sections.h>
15 #include <errno.h>
16 #include <zephyr/shell/shell.h>
17
18 #include <zephyr/net/net_core.h>
19 #include <zephyr/net/tls_credentials.h>
20
21 #include <zephyr/net/net_mgmt.h>
22 #include <zephyr/net/net_event.h>
23 #include <zephyr/net/conn_mgr_monitor.h>
24
25 #include "common.h"
26 #include "certificate.h"
27
28 #define APP_BANNER "Run echo server"
29
30 static struct k_sem quit_lock;
31 static struct net_mgmt_event_callback mgmt_cb;
32 static bool connected;
33 K_SEM_DEFINE(run_app, 0, 1);
34 static bool want_to_quit;
35
36 #if defined(CONFIG_USERSPACE)
37 K_APPMEM_PARTITION_DEFINE(app_partition);
38 struct k_mem_domain app_domain;
39 #endif
40
41 #define EVENT_MASK (NET_EVENT_L4_CONNECTED | \
42 NET_EVENT_L4_DISCONNECTED)
43
44 APP_DMEM struct configs conf = {
45 .ipv4 = {
46 .proto = "IPv4",
47 },
48 .ipv6 = {
49 .proto = "IPv6",
50 },
51 };
52
quit(void)53 void quit(void)
54 {
55 k_sem_give(&quit_lock);
56 }
57
start_udp_and_tcp(void)58 static void start_udp_and_tcp(void)
59 {
60 LOG_INF("Starting...");
61
62 if (IS_ENABLED(CONFIG_NET_TCP)) {
63 start_tcp();
64 }
65
66 if (IS_ENABLED(CONFIG_NET_UDP)) {
67 start_udp();
68 }
69 }
70
stop_udp_and_tcp(void)71 static void stop_udp_and_tcp(void)
72 {
73 LOG_INF("Stopping...");
74
75 if (IS_ENABLED(CONFIG_NET_UDP)) {
76 stop_udp();
77 }
78
79 if (IS_ENABLED(CONFIG_NET_TCP)) {
80 stop_tcp();
81 }
82 }
83
event_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)84 static void event_handler(struct net_mgmt_event_callback *cb,
85 uint32_t mgmt_event, struct net_if *iface)
86 {
87 ARG_UNUSED(iface);
88 ARG_UNUSED(cb);
89
90 if ((mgmt_event & EVENT_MASK) != mgmt_event) {
91 return;
92 }
93
94 if (want_to_quit) {
95 k_sem_give(&run_app);
96 want_to_quit = false;
97 }
98
99 if (mgmt_event == NET_EVENT_L4_CONNECTED) {
100 LOG_INF("Network connected");
101
102 connected = true;
103 k_sem_give(&run_app);
104
105 return;
106 }
107
108 if (mgmt_event == NET_EVENT_L4_DISCONNECTED) {
109 if (connected == false) {
110 LOG_INF("Waiting network to be connected");
111 } else {
112 LOG_INF("Network disconnected");
113 connected = false;
114 }
115
116 k_sem_reset(&run_app);
117
118 return;
119 }
120 }
121
init_app(void)122 static void init_app(void)
123 {
124 #if defined(CONFIG_USERSPACE)
125 struct k_mem_partition *parts[] = {
126 #if Z_LIBC_PARTITION_EXISTS
127 &z_libc_partition,
128 #endif
129 &app_partition
130 };
131
132 int ret = k_mem_domain_init(&app_domain, ARRAY_SIZE(parts), parts);
133
134 __ASSERT(ret == 0, "k_mem_domain_init() failed %d", ret);
135 ARG_UNUSED(ret);
136 #endif
137
138 k_sem_init(&quit_lock, 0, K_SEM_MAX_LIMIT);
139
140 LOG_INF(APP_BANNER);
141
142 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
143 int err;
144
145 #if defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC)
146 err = tls_credential_add(SERVER_CERTIFICATE_TAG,
147 TLS_CREDENTIAL_CA_CERTIFICATE,
148 ca_certificate,
149 sizeof(ca_certificate));
150 if (err < 0) {
151 LOG_ERR("Failed to register CA certificate: %d", err);
152 }
153 #endif /* defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC) */
154
155 err = tls_credential_add(SERVER_CERTIFICATE_TAG,
156 TLS_CREDENTIAL_SERVER_CERTIFICATE,
157 server_certificate,
158 sizeof(server_certificate));
159 if (err < 0) {
160 LOG_ERR("Failed to register public certificate: %d", err);
161 }
162
163
164 err = tls_credential_add(SERVER_CERTIFICATE_TAG,
165 TLS_CREDENTIAL_PRIVATE_KEY,
166 private_key, sizeof(private_key));
167 if (err < 0) {
168 LOG_ERR("Failed to register private key: %d", err);
169 }
170
171 #if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
172 err = tls_credential_add(PSK_TAG,
173 TLS_CREDENTIAL_PSK,
174 psk,
175 sizeof(psk));
176 if (err < 0) {
177 LOG_ERR("Failed to register PSK: %d", err);
178 }
179 err = tls_credential_add(PSK_TAG,
180 TLS_CREDENTIAL_PSK_ID,
181 psk_id,
182 sizeof(psk_id) - 1);
183 if (err < 0) {
184 LOG_ERR("Failed to register PSK ID: %d", err);
185 }
186 #endif /* defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) */
187 #endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */
188
189 if (IS_ENABLED(CONFIG_NET_CONNECTION_MANAGER)) {
190 net_mgmt_init_event_callback(&mgmt_cb,
191 event_handler, EVENT_MASK);
192 net_mgmt_add_event_callback(&mgmt_cb);
193
194 conn_mgr_mon_resend_status();
195 }
196
197 init_vlan();
198 init_tunnel();
199 init_ws();
200 init_usb();
201 }
202
cmd_sample_quit(const struct shell * sh,size_t argc,char * argv[])203 static int cmd_sample_quit(const struct shell *sh,
204 size_t argc, char *argv[])
205 {
206 want_to_quit = true;
207
208 conn_mgr_mon_resend_status();
209
210 quit();
211
212 return 0;
213 }
214
215 SHELL_STATIC_SUBCMD_SET_CREATE(sample_commands,
216 SHELL_CMD(quit, NULL,
217 "Quit the sample application\n",
218 cmd_sample_quit),
219 SHELL_SUBCMD_SET_END
220 );
221
222 SHELL_CMD_REGISTER(sample, &sample_commands,
223 "Sample application commands", NULL);
224
main(void)225 int main(void)
226 {
227 init_app();
228
229 if (!IS_ENABLED(CONFIG_NET_CONNECTION_MANAGER)) {
230 /* If the config library has not been configured to start the
231 * app only after we have a connection, then we can start
232 * it right away.
233 */
234 k_sem_give(&run_app);
235 }
236
237 /* Wait for the connection. */
238 k_sem_take(&run_app, K_FOREVER);
239
240 start_udp_and_tcp();
241
242 k_sem_take(&quit_lock, K_FOREVER);
243
244 if (connected) {
245 stop_udp_and_tcp();
246 }
247 return 0;
248 }
249