1 /* udp.c - UDP specific code for echo client */
2
3 /*
4 * Copyright (c) 2017 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_DECLARE(net_echo_client_sample, LOG_LEVEL_DBG);
12
13 #include <zephyr/kernel.h>
14 #include <errno.h>
15 #include <stdio.h>
16
17 #include <zephyr/posix/sys/socket.h>
18 #include <zephyr/posix/arpa/inet.h>
19 #include <zephyr/posix/unistd.h>
20
21 #include <zephyr/net/socket.h>
22 #include <zephyr/net/tls_credentials.h>
23 #include <zephyr/random/random.h>
24
25 #include "common.h"
26 #include "ca_certificate.h"
27
28 #define RECV_BUF_SIZE 1280
29 #define UDP_SLEEP K_MSEC(150)
30 #define UDP_WAIT K_SECONDS(10)
31
32 static APP_BMEM char recv_buf[RECV_BUF_SIZE];
33
34 static K_THREAD_STACK_DEFINE(udp_tx_thread_stack, UDP_STACK_SIZE);
35 static struct k_thread udp_tx_thread;
36
37 /* Kernel objects should not be placed in a memory area accessible from user
38 * threads.
39 */
40 static struct udp_control udp4_ctrl, udp6_ctrl;
41 static struct k_poll_signal udp_kill;
42
43 static int send_udp_data(struct sample_data *data);
44 static void wait_reply(struct k_timer *timer);
45 static void wait_transmit(struct k_timer *timer);
46
process_udp_tx(void * p1,void * p2,void * p3)47 static void process_udp_tx(void *p1, void *p2, void *p3)
48 {
49 ARG_UNUSED(p1);
50 ARG_UNUSED(p2);
51 ARG_UNUSED(p3);
52
53 struct k_poll_event events[] = {
54 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
55 K_POLL_MODE_NOTIFY_ONLY,
56 &udp_kill),
57 #if defined(CONFIG_NET_IPV4)
58 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
59 K_POLL_MODE_NOTIFY_ONLY,
60 &udp4_ctrl.tx_signal),
61 #endif
62 #if defined(CONFIG_NET_IPV6)
63 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
64 K_POLL_MODE_NOTIFY_ONLY,
65 &udp6_ctrl.tx_signal),
66 #endif
67 };
68
69 while (true) {
70 k_poll(events, ARRAY_SIZE(events), K_FOREVER);
71
72 for (int i = 0; i < ARRAY_SIZE(events); i++) {
73 unsigned int signaled;
74 int result;
75
76 k_poll_signal_check(events[i].signal, &signaled, &result);
77 if (signaled == 0) {
78 continue;
79 }
80
81 k_poll_signal_reset(events[i].signal);
82 events[i].state = K_POLL_STATE_NOT_READY;
83
84 if (events[i].signal == &udp_kill) {
85 return;
86 } else if (events[i].signal == &udp4_ctrl.tx_signal) {
87 send_udp_data(&conf.ipv4);
88 } else if (events[i].signal == &udp6_ctrl.tx_signal) {
89 send_udp_data(&conf.ipv6);
90 }
91 }
92 }
93 }
94
udp_control_init(struct udp_control * ctrl)95 static void udp_control_init(struct udp_control *ctrl)
96 {
97 k_timer_init(&ctrl->rx_timer, wait_reply, NULL);
98 k_timer_init(&ctrl->tx_timer, wait_transmit, NULL);
99 k_poll_signal_init(&ctrl->tx_signal);
100 }
101
udp_control_access_grant(struct udp_control * ctrl)102 static void udp_control_access_grant(struct udp_control *ctrl)
103 {
104 k_thread_access_grant(k_current_get(),
105 &ctrl->rx_timer,
106 &ctrl->tx_timer,
107 &ctrl->tx_signal);
108 }
109
init_udp(void)110 void init_udp(void)
111 {
112 /* k_timer_init() is not a system call, therefore initialize kernel
113 * objects here.
114 */
115 if (IS_ENABLED(CONFIG_NET_IPV4)) {
116 udp_control_init(&udp4_ctrl);
117 conf.ipv4.udp.ctrl = &udp4_ctrl;
118 }
119
120 if (IS_ENABLED(CONFIG_NET_IPV6)) {
121 udp_control_init(&udp6_ctrl);
122 conf.ipv6.udp.ctrl = &udp6_ctrl;
123 }
124
125 k_poll_signal_init(&udp_kill);
126
127 if (IS_ENABLED(CONFIG_USERSPACE)) {
128 k_thread_access_grant(k_current_get(),
129 &udp_tx_thread,
130 &udp_tx_thread_stack,
131 &udp_kill);
132
133 if (IS_ENABLED(CONFIG_NET_IPV4)) {
134 udp_control_access_grant(&udp4_ctrl);
135 }
136
137 if (IS_ENABLED(CONFIG_NET_IPV6)) {
138 udp_control_access_grant(&udp6_ctrl);
139 }
140 }
141 }
142
send_udp_data(struct sample_data * data)143 static int send_udp_data(struct sample_data *data)
144 {
145 int ret;
146
147 do {
148 data->udp.expecting = sys_rand32_get() % ipsum_len;
149 } while (data->udp.expecting == 0U ||
150 data->udp.expecting > data->udp.mtu);
151
152 ret = send(data->udp.sock, lorem_ipsum, data->udp.expecting, 0);
153
154 if (PRINT_PROGRESS) {
155 LOG_DBG("%s UDP: Sent %d bytes", data->proto, data->udp.expecting);
156 }
157
158 k_timer_start(&data->udp.ctrl->rx_timer, UDP_WAIT, K_NO_WAIT);
159
160 return ret < 0 ? -EIO : 0;
161 }
162
compare_udp_data(struct sample_data * data,const char * buf,uint32_t received)163 static int compare_udp_data(struct sample_data *data, const char *buf, uint32_t received)
164 {
165 if (received != data->udp.expecting) {
166 LOG_ERR("Invalid amount of data received: UDP %s", data->proto);
167 return -EIO;
168 }
169
170 if (memcmp(buf, lorem_ipsum, received) != 0) {
171 LOG_ERR("Invalid data received: UDP %s", data->proto);
172 return -EIO;
173 }
174
175 return 0;
176 }
177
wait_reply(struct k_timer * timer)178 static void wait_reply(struct k_timer *timer)
179 {
180 /* This means that we did not receive response in time. */
181 struct udp_control *ctrl = CONTAINER_OF(timer, struct udp_control, rx_timer);
182 struct sample_data *data = (ctrl == conf.ipv4.udp.ctrl) ? &conf.ipv4 : &conf.ipv6;
183
184 LOG_ERR("UDP %s: Data packet not received", data->proto);
185
186 /* Send a new packet at this point */
187 k_poll_signal_raise(&ctrl->tx_signal, 0);
188 }
189
wait_transmit(struct k_timer * timer)190 static void wait_transmit(struct k_timer *timer)
191 {
192 struct udp_control *ctrl = CONTAINER_OF(timer, struct udp_control, tx_timer);
193
194 k_poll_signal_raise(&ctrl->tx_signal, 0);
195 }
196
start_udp_proto(struct sample_data * data,sa_family_t family,struct sockaddr * addr,socklen_t addrlen)197 static int start_udp_proto(struct sample_data *data, sa_family_t family,
198 struct sockaddr *addr, socklen_t addrlen)
199 {
200 int optval;
201 int ret;
202
203 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
204 data->udp.sock = socket(family, SOCK_DGRAM, IPPROTO_DTLS_1_2);
205 #else
206 data->udp.sock = socket(family, SOCK_DGRAM, IPPROTO_UDP);
207 #endif
208 if (data->udp.sock < 0) {
209 LOG_ERR("Failed to create UDP socket (%s): %d", data->proto,
210 errno);
211 return -errno;
212 }
213
214 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
215 sec_tag_t sec_tag_list[] = {
216 CA_CERTIFICATE_TAG,
217 #if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
218 PSK_TAG,
219 #endif
220 };
221
222 ret = setsockopt(data->udp.sock, SOL_TLS, TLS_SEC_TAG_LIST,
223 sec_tag_list, sizeof(sec_tag_list));
224 if (ret < 0) {
225 LOG_ERR("Failed to set TLS_SEC_TAG_LIST option (%s): %d",
226 data->proto, errno);
227 ret = -errno;
228 }
229
230 ret = setsockopt(data->udp.sock, SOL_TLS, TLS_HOSTNAME,
231 TLS_PEER_HOSTNAME, sizeof(TLS_PEER_HOSTNAME));
232 if (ret < 0) {
233 LOG_ERR("Failed to set TLS_HOSTNAME option (%s): %d",
234 data->proto, errno);
235 ret = -errno;
236 }
237 #endif
238
239 /* Prefer IPv6 temporary addresses */
240 if (family == AF_INET6) {
241 optval = IPV6_PREFER_SRC_TMP;
242 (void)setsockopt(data->udp.sock, IPPROTO_IPV6,
243 IPV6_ADDR_PREFERENCES,
244 &optval, sizeof(optval));
245 }
246
247 /* Call connect so we can use send and recv. */
248 ret = connect(data->udp.sock, addr, addrlen);
249 if (ret < 0) {
250 LOG_ERR("Cannot connect to UDP remote (%s): %d", data->proto,
251 errno);
252 ret = -errno;
253 }
254
255 return ret;
256 }
257
process_udp_proto(struct sample_data * data)258 static int process_udp_proto(struct sample_data *data)
259 {
260 int ret, received;
261
262 received = recv(data->udp.sock, recv_buf, sizeof(recv_buf),
263 MSG_DONTWAIT);
264
265 if (received == 0) {
266 return -EIO;
267 }
268 if (received < 0) {
269 if (errno == EAGAIN || errno == EWOULDBLOCK) {
270 ret = 0;
271 } else {
272 ret = -errno;
273 }
274 return ret;
275 }
276
277 ret = compare_udp_data(data, recv_buf, received);
278 if (ret != 0) {
279 LOG_WRN("%s UDP: Received and compared %d bytes, data "
280 "mismatch", data->proto, received);
281 return 0;
282 }
283
284 if (PRINT_PROGRESS) {
285 /* Correct response received */
286 LOG_DBG("%s UDP: Received and compared %d bytes, all ok",
287 data->proto, received);
288 }
289
290 if (++data->udp.counter % 1000 == 0U) {
291 LOG_INF("%s UDP: Exchanged %u packets", data->proto,
292 data->udp.counter);
293 }
294
295 k_timer_stop(&data->udp.ctrl->rx_timer);
296
297 /* Do not flood the link if we have also TCP configured */
298 if (IS_ENABLED(CONFIG_NET_TCP)) {
299 k_timer_start(&data->udp.ctrl->tx_timer, UDP_SLEEP, K_NO_WAIT);
300 } else {
301 k_poll_signal_raise(&data->udp.ctrl->tx_signal, 0);
302 }
303
304 return ret;
305 }
306
start_udp(void)307 int start_udp(void)
308 {
309 int ret = 0;
310 struct sockaddr_in addr4;
311 struct sockaddr_in6 addr6;
312
313 if (IS_ENABLED(CONFIG_NET_IPV6)) {
314 addr6.sin6_family = AF_INET6;
315 addr6.sin6_port = htons(PEER_PORT);
316 inet_pton(AF_INET6, CONFIG_NET_CONFIG_PEER_IPV6_ADDR,
317 &addr6.sin6_addr);
318
319 ret = start_udp_proto(&conf.ipv6, AF_INET6,
320 (struct sockaddr *)&addr6,
321 sizeof(addr6));
322 if (ret < 0) {
323 return ret;
324 }
325 }
326
327 if (IS_ENABLED(CONFIG_NET_IPV4)) {
328 addr4.sin_family = AF_INET;
329 addr4.sin_port = htons(PEER_PORT);
330 inet_pton(AF_INET, CONFIG_NET_CONFIG_PEER_IPV4_ADDR,
331 &addr4.sin_addr);
332
333 ret = start_udp_proto(&conf.ipv4, AF_INET,
334 (struct sockaddr *)&addr4,
335 sizeof(addr4));
336 if (ret < 0) {
337 return ret;
338 }
339 }
340
341 k_thread_create(&udp_tx_thread, udp_tx_thread_stack,
342 K_THREAD_STACK_SIZEOF(udp_tx_thread_stack),
343 process_udp_tx,
344 NULL, NULL, NULL, THREAD_PRIORITY,
345 IS_ENABLED(CONFIG_USERSPACE) ?
346 K_USER | K_INHERIT_PERMS : 0,
347 K_NO_WAIT);
348
349 k_thread_name_set(&udp_tx_thread, "udp_tx");
350
351 if (IS_ENABLED(CONFIG_NET_IPV6)) {
352 k_poll_signal_raise(&conf.ipv6.udp.ctrl->tx_signal, 0);
353 }
354
355 if (IS_ENABLED(CONFIG_NET_IPV4)) {
356 k_poll_signal_raise(&conf.ipv4.udp.ctrl->tx_signal, 0);
357 }
358
359 return ret;
360 }
361
process_udp(void)362 int process_udp(void)
363 {
364 int ret = 0;
365
366 if (IS_ENABLED(CONFIG_NET_IPV6)) {
367 ret = process_udp_proto(&conf.ipv6);
368 if (ret < 0) {
369 return ret;
370 }
371 }
372
373 if (IS_ENABLED(CONFIG_NET_IPV4)) {
374 ret = process_udp_proto(&conf.ipv4);
375 if (ret < 0) {
376 return ret;
377 }
378 }
379
380 return ret;
381 }
382
stop_udp(void)383 void stop_udp(void)
384 {
385 if (IS_ENABLED(CONFIG_NET_IPV6)) {
386 k_timer_stop(&udp6_ctrl.tx_timer);
387 k_timer_stop(&udp6_ctrl.rx_timer);
388
389 if (conf.ipv6.udp.sock >= 0) {
390 (void)close(conf.ipv6.udp.sock);
391 }
392 }
393
394 if (IS_ENABLED(CONFIG_NET_IPV4)) {
395 k_timer_stop(&udp4_ctrl.tx_timer);
396 k_timer_stop(&udp4_ctrl.rx_timer);
397
398 if (conf.ipv4.udp.sock >= 0) {
399 (void)close(conf.ipv4.udp.sock);
400 }
401 }
402
403 k_poll_signal_raise(&udp_kill, 0);
404 }
405