1 /*
2  * Copyright (c) 2023 Nordic Semiconductor
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL);
9 
10 #include <stdio.h>
11 #include <zephyr/ztest_assert.h>
12 
13 #include <zephyr/net/socket_service.h>
14 
15 #include "../../socket_helpers.h"
16 
17 #define BUF_AND_SIZE(buf) buf, sizeof(buf) - 1
18 #define STRLEN(buf) (sizeof(buf) - 1)
19 
20 #define TEST_STR_SMALL "test"
21 
22 #define MY_IPV6_ADDR "::1"
23 
24 #define ANY_PORT 0
25 #define SERVER_PORT 4242
26 #define CLIENT_PORT 9898
27 
28 #define TCP_TEARDOWN_TIMEOUT K_SECONDS(3)
29 
30 K_SEM_DEFINE(wait_data, 0, UINT_MAX);
31 K_SEM_DEFINE(wait_data_tcp, 0, UINT_MAX);
32 #define WAIT_TIME 500
33 
server_handler(struct net_socket_service_event * pev)34 static void server_handler(struct net_socket_service_event *pev)
35 {
36 	ARG_UNUSED(pev);
37 
38 	k_sem_give(&wait_data);
39 }
40 
tcp_server_handler(struct net_socket_service_event * pev)41 static void tcp_server_handler(struct net_socket_service_event *pev)
42 {
43 	ARG_UNUSED(pev);
44 
45 	k_sem_give(&wait_data_tcp);
46 
47 	k_yield();
48 
49 	Z_SPIN_DELAY(100);
50 }
51 
52 NET_SOCKET_SERVICE_SYNC_DEFINE(udp_service_sync, server_handler, 2);
53 NET_SOCKET_SERVICE_SYNC_DEFINE(tcp_service_small_sync, tcp_server_handler, 1);
54 NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(tcp_service_sync, tcp_server_handler, 2);
55 
56 
run_test_service(const struct net_socket_service_desc * udp_service,const struct net_socket_service_desc * tcp_service_small,const struct net_socket_service_desc * tcp_service)57 void run_test_service(const struct net_socket_service_desc *udp_service,
58 		      const struct net_socket_service_desc *tcp_service_small,
59 		      const struct net_socket_service_desc *tcp_service)
60 {
61 	int ret;
62 	int c_sock_udp;
63 	int s_sock_udp;
64 	int c_sock_tcp;
65 	int s_sock_tcp;
66 	int new_sock;
67 	struct sockaddr_in6 c_addr;
68 	struct sockaddr_in6 s_addr;
69 	ssize_t len;
70 	char buf[10];
71 	struct zsock_pollfd sock[2] = {
72 		[0] = { .fd = -1 },
73 		[1] = { .fd = -1 },
74 	};
75 
76 	prepare_sock_udp_v6(MY_IPV6_ADDR, CLIENT_PORT, &c_sock_udp, &c_addr);
77 	prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &s_sock_udp, &s_addr);
78 	prepare_sock_tcp_v6(MY_IPV6_ADDR, CLIENT_PORT, &c_sock_tcp, &c_addr);
79 	prepare_sock_tcp_v6(MY_IPV6_ADDR, SERVER_PORT, &s_sock_tcp, &s_addr);
80 
81 	sock[0].fd = s_sock_udp;
82 	sock[0].events = ZSOCK_POLLIN;
83 
84 	ret = net_socket_service_register(udp_service, sock, ARRAY_SIZE(sock), NULL);
85 	zassert_equal(ret, 0, "Cannot register udp service (%d)", ret);
86 
87 	sock[0].fd = s_sock_tcp;
88 	sock[0].events = ZSOCK_POLLIN;
89 
90 	ret = net_socket_service_register(tcp_service_small, sock, ARRAY_SIZE(sock) + 1, NULL);
91 	zassert_equal(ret, -ENOMEM, "Could register tcp service (%d)", ret);
92 
93 	ret = net_socket_service_register(tcp_service, sock, ARRAY_SIZE(sock), NULL);
94 	zassert_equal(ret, 0, "Cannot register tcp service (%d)", ret);
95 
96 	ret = bind(s_sock_udp, (struct sockaddr *)&s_addr, sizeof(s_addr));
97 	zassert_equal(ret, 0, "bind failed");
98 
99 	ret = connect(c_sock_udp, (struct sockaddr *)&s_addr, sizeof(s_addr));
100 	zassert_equal(ret, 0, "connect failed");
101 
102 	/* Send pkt for s_sock_udp and poll with timeout of 10 */
103 	len = send(c_sock_udp, BUF_AND_SIZE(TEST_STR_SMALL), 0);
104 	zassert_equal(len, STRLEN(TEST_STR_SMALL), "invalid send len");
105 
106 	if (k_sem_take(&wait_data, K_MSEC(WAIT_TIME))) {
107 		zassert_true(0, "Timeout while waiting callback");
108 	}
109 
110 	/* Recv pkt from s_sock_udp and ensure no poll events happen */
111 	len = recv(s_sock_udp, BUF_AND_SIZE(buf), 0);
112 	zassert_equal(len, STRLEN(TEST_STR_SMALL), "invalid recv len");
113 
114 	ret = bind(s_sock_tcp, (struct sockaddr *)&s_addr, sizeof(s_addr));
115 	zassert_equal(ret, 0, "bind failed (%d)", -errno);
116 	ret = listen(s_sock_tcp, 0);
117 	zassert_equal(ret, 0, "");
118 
119 	ret = connect(c_sock_tcp, (const struct sockaddr *)&s_addr,
120 		      sizeof(s_addr));
121 	zassert_equal(ret, 0, "");
122 
123 	/* Let the network stack run */
124 	k_msleep(10);
125 
126 	len = send(c_sock_tcp, BUF_AND_SIZE(TEST_STR_SMALL), 0);
127 	zassert_equal(len, STRLEN(TEST_STR_SMALL), "invalid send len");
128 
129 	if (k_sem_take(&wait_data_tcp, K_MSEC(WAIT_TIME))) {
130 		zassert_true(0, "Timeout while waiting callback");
131 	}
132 
133 	new_sock = accept(s_sock_tcp, NULL, NULL);
134 	zassert_true(new_sock >= 0, "");
135 
136 	sock[1].fd = new_sock;
137 	sock[1].events = ZSOCK_POLLIN;
138 
139 	ret = net_socket_service_register(tcp_service, sock, ARRAY_SIZE(sock), NULL);
140 	zassert_equal(ret, 0, "Cannot register tcp service (%d)", ret);
141 
142 	if (k_sem_take(&wait_data_tcp, K_MSEC(WAIT_TIME))) {
143 		zassert_true(0, "Timeout while waiting callback");
144 	}
145 
146 	len = recv(new_sock, BUF_AND_SIZE(buf), 0);
147 	zassert_equal(len, STRLEN(TEST_STR_SMALL), "invalid recv len");
148 
149 	ret = net_socket_service_unregister(tcp_service);
150 	zassert_equal(ret, 0, "Cannot unregister tcp service (%d)", ret);
151 
152 	ret = net_socket_service_unregister(udp_service);
153 	zassert_equal(ret, 0, "Cannot unregister tcp service (%d)", ret);
154 
155 	ret = net_socket_service_unregister(tcp_service_small);
156 	zassert_equal(ret, 0, "Cannot unregister tcp service (%d)", ret);
157 
158 	ret = close(new_sock);
159 	zassert_equal(ret, 0, "close failed");
160 
161 	ret = close(c_sock_tcp);
162 	zassert_equal(ret, 0, "close failed");
163 
164 	ret = close(s_sock_tcp);
165 	zassert_equal(ret, 0, "close failed");
166 
167 	ret = close(c_sock_udp);
168 	zassert_equal(ret, 0, "close failed");
169 
170 	ret = close(s_sock_udp);
171 	zassert_equal(ret, 0, "close failed");
172 
173 	/* Let the stack close the TCP sockets properly */
174 	k_msleep(100);
175 }
176 
ZTEST(net_socket_service,test_service_sync)177 ZTEST(net_socket_service, test_service_sync)
178 {
179 	run_test_service(&udp_service_sync, &tcp_service_small_sync,
180 			 &tcp_service_sync);
181 }
182 
183 ZTEST_SUITE(net_socket_service, NULL, NULL, NULL, NULL, NULL);
184