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