/work/auto_tests/TCP_test.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include <errno.h> |
2 | | #include <stdlib.h> |
3 | | #include <string.h> |
4 | | |
5 | | #include "../testing/misc_tools.h" |
6 | | #include "../toxcore/TCP_client.h" |
7 | | #include "../toxcore/TCP_common.h" |
8 | | #include "../toxcore/TCP_server.h" |
9 | | #include "../toxcore/crypto_core.h" |
10 | | #include "../toxcore/mono_time.h" |
11 | | #include "../toxcore/net_profile.h" |
12 | | #include "../toxcore/network.h" |
13 | | #include "../toxcore/os_memory.h" |
14 | | #include "../toxcore/os_random.h" |
15 | | #include "auto_test_support.h" |
16 | | |
17 | 21 | #define NUM_PORTS 3 |
18 | | |
19 | | #ifndef USE_IPV6 |
20 | | #define USE_IPV6 1 |
21 | | #endif |
22 | | |
23 | | #if !USE_IPV6 |
24 | 6 | #define net_family_ipv6 net_family_ipv4 |
25 | | #endif |
26 | | |
27 | | static IP get_loopback(void) |
28 | 136 | { |
29 | 136 | IP ip; |
30 | | #if USE_IPV6 |
31 | | ip.family = net_family_ipv6(); |
32 | | ip.ip.v6 = get_ip6_loopback(); |
33 | | #else |
34 | 136 | ip.family = net_family_ipv4(); |
35 | 136 | ip.ip.v4 = get_ip4_loopback(); |
36 | 136 | #endif |
37 | 136 | return ip; |
38 | 136 | } |
39 | | |
40 | | static void do_tcp_server_delay(TCP_Server *tcp_s, Mono_Time *mono_time, int delay) |
41 | 29 | { |
42 | 29 | c_sleep(delay); |
43 | 29 | mono_time_update(mono_time); |
44 | 29 | do_tcp_server(tcp_s, mono_time); |
45 | 29 | c_sleep(delay); |
46 | 29 | } |
47 | | static uint16_t ports[NUM_PORTS] = {13215, 33445, 25643}; |
48 | | |
49 | | static void test_basic(void) |
50 | 1 | { |
51 | 1 | const Random *rng = os_random(); |
52 | 1 | ck_assert(rng != nullptr); |
53 | 1 | const Network *ns = os_network(); |
54 | 1 | ck_assert(ns != nullptr); |
55 | 1 | const Memory *mem = os_memory(); |
56 | 1 | ck_assert(mem != nullptr); |
57 | | |
58 | 1 | Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); |
59 | 1 | Logger *logger = logger_new(mem); |
60 | 1 | logger_callback_log(logger, print_debug_logger, nullptr, nullptr); |
61 | | |
62 | | // Attempt to create a new TCP_Server instance. |
63 | 1 | uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; |
64 | 1 | uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; |
65 | 1 | crypto_new_keypair(rng, self_public_key, self_secret_key); |
66 | 1 | TCP_Server *tcp_s = new_tcp_server(logger, mem, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr); |
67 | 1 | ck_assert_msg(tcp_s != nullptr, "Failed to create a TCP relay server."); |
68 | 1 | ck_assert_msg(tcp_server_listen_count(tcp_s) == NUM_PORTS, |
69 | 1 | "Failed to bind a TCP relay server to all %d attempted ports.", NUM_PORTS); |
70 | | |
71 | 1 | Socket sock = {0}; |
72 | 1 | IP_Port localhost; |
73 | 1 | localhost.ip = get_loopback(); |
74 | 1 | localhost.port = 0; |
75 | | |
76 | | // Check all opened ports for connectivity. |
77 | 4 | for (uint8_t i = 0; i < NUM_PORTS; i++) { |
78 | 3 | sock = net_socket(ns, net_family_ipv6(), TOX_SOCK_STREAM, TOX_PROTO_TCP); |
79 | 3 | localhost.port = net_htons(ports[i]); |
80 | 3 | Net_Err_Connect err; |
81 | 3 | bool ret = net_connect(ns, mem, logger, sock, &localhost, &err); |
82 | 3 | ck_assert_msg(ret, "Failed to connect to created TCP relay server on port %d (%d, %s).", ports[i], errno, net_err_connect_to_string(err)); |
83 | | |
84 | | // Leave open one connection for the next test. |
85 | 3 | if (i + 1 < NUM_PORTS) { |
86 | 2 | kill_sock(ns, sock); |
87 | 2 | } |
88 | 3 | } |
89 | | |
90 | | // Key creation. |
91 | 1 | uint8_t f_public_key[CRYPTO_PUBLIC_KEY_SIZE]; |
92 | 1 | uint8_t f_secret_key[CRYPTO_SECRET_KEY_SIZE]; |
93 | 1 | uint8_t f_nonce[CRYPTO_NONCE_SIZE]; |
94 | 1 | crypto_new_keypair(rng, f_public_key, f_secret_key); |
95 | 1 | random_nonce(rng, f_nonce); |
96 | | |
97 | | // Generation of the initial handshake. |
98 | 1 | uint8_t t_secret_key[CRYPTO_SECRET_KEY_SIZE]; |
99 | 1 | uint8_t *handshake_plain = (uint8_t *)malloc(TCP_HANDSHAKE_PLAIN_SIZE); |
100 | 1 | ck_assert(handshake_plain != nullptr); |
101 | 1 | crypto_new_keypair(rng, handshake_plain, t_secret_key); |
102 | 1 | memcpy(handshake_plain + CRYPTO_PUBLIC_KEY_SIZE, f_nonce, CRYPTO_NONCE_SIZE); |
103 | 1 | uint8_t *handshake = (uint8_t *)malloc(TCP_CLIENT_HANDSHAKE_SIZE); |
104 | 1 | ck_assert(handshake != nullptr); |
105 | 1 | memcpy(handshake, f_public_key, CRYPTO_PUBLIC_KEY_SIZE); |
106 | 1 | random_nonce(rng, handshake + CRYPTO_PUBLIC_KEY_SIZE); |
107 | | |
108 | | // Encrypting handshake |
109 | 1 | int ret = encrypt_data(mem, self_public_key, f_secret_key, handshake + CRYPTO_PUBLIC_KEY_SIZE, handshake_plain, |
110 | 1 | TCP_HANDSHAKE_PLAIN_SIZE, handshake + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); |
111 | 1 | ck_assert_msg(ret == TCP_CLIENT_HANDSHAKE_SIZE - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE), |
112 | 1 | "encrypt_data() call failed."); |
113 | | |
114 | 1 | free(handshake_plain); |
115 | | |
116 | | // Sending the handshake |
117 | 1 | ck_assert_msg(net_send(ns, logger, sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1, |
118 | 1 | &localhost, nullptr) == TCP_CLIENT_HANDSHAKE_SIZE - 1, |
119 | 1 | "An attempt to send the initial handshake minus last byte failed."); |
120 | | |
121 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
122 | | |
123 | 1 | ck_assert_msg(net_send(ns, logger, sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1, &localhost, nullptr) == 1, |
124 | 1 | "The attempt to send the last byte of handshake failed."); |
125 | | |
126 | 1 | free(handshake); |
127 | | |
128 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
129 | | |
130 | | // Receiving server response and decrypting it |
131 | 1 | uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; |
132 | 1 | uint8_t response_plain[TCP_HANDSHAKE_PLAIN_SIZE]; |
133 | 1 | ck_assert_msg(net_recv(ns, logger, sock, response, TCP_SERVER_HANDSHAKE_SIZE, &localhost) == TCP_SERVER_HANDSHAKE_SIZE, |
134 | 1 | "Could/did not receive a server response to the initial handshake."); |
135 | 1 | ret = decrypt_data(mem, self_public_key, f_secret_key, response, response + CRYPTO_NONCE_SIZE, |
136 | 1 | TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, response_plain); |
137 | 1 | ck_assert_msg(ret == TCP_HANDSHAKE_PLAIN_SIZE, "Failed to decrypt handshake response."); |
138 | 1 | uint8_t f_nonce_r[CRYPTO_NONCE_SIZE]; |
139 | 1 | uint8_t f_shared_key[CRYPTO_SHARED_KEY_SIZE]; |
140 | 1 | encrypt_precompute(response_plain, t_secret_key, f_shared_key); |
141 | 1 | memcpy(f_nonce_r, response_plain + CRYPTO_SHARED_KEY_SIZE, CRYPTO_NONCE_SIZE); |
142 | | |
143 | | // Building a request |
144 | 1 | uint8_t r_req_p[1 + CRYPTO_PUBLIC_KEY_SIZE]; |
145 | 1 | r_req_p[0] = TCP_PACKET_ROUTING_REQUEST; |
146 | 1 | memcpy(r_req_p + 1, f_public_key, CRYPTO_PUBLIC_KEY_SIZE); |
147 | 1 | uint8_t r_req[2 + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE]; |
148 | 1 | uint16_t size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE; |
149 | 1 | size = net_htons(size); |
150 | 1 | encrypt_data_symmetric(mem, f_shared_key, f_nonce, r_req_p, 1 + CRYPTO_PUBLIC_KEY_SIZE, r_req + 2); |
151 | 1 | increment_nonce(f_nonce); |
152 | 1 | memcpy(r_req, &size, 2); |
153 | | |
154 | | // Sending the request at random intervals in random pieces. |
155 | 20 | for (uint32_t i = 0; i < sizeof(r_req);) { |
156 | 19 | uint8_t msg_length = rand() % 5 + 1; // msg_length = 1 to 5 |
157 | | |
158 | 19 | if (i + msg_length >= sizeof(r_req)) { |
159 | 1 | msg_length = sizeof(r_req) - i; |
160 | 1 | } |
161 | | |
162 | 19 | ck_assert_msg(net_send(ns, logger, sock, r_req + i, msg_length, &localhost, nullptr) == msg_length, |
163 | 19 | "Failed to send request after completing the handshake."); |
164 | 19 | i += msg_length; |
165 | | |
166 | 19 | c_sleep(50); |
167 | 19 | mono_time_update(mono_time); |
168 | 19 | do_tcp_server(tcp_s, mono_time); |
169 | 19 | } |
170 | | |
171 | | // Receiving the second response and verifying its validity |
172 | 1 | const size_t max_packet_size = 4096; |
173 | 1 | uint8_t *packet_resp = (uint8_t *)malloc(max_packet_size); |
174 | 1 | ck_assert(packet_resp != nullptr); |
175 | 1 | int recv_data_len = net_recv(ns, logger, sock, packet_resp, 2 + 2 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE, &localhost); |
176 | 1 | ck_assert_msg(recv_data_len == 2 + 2 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE, |
177 | 1 | "Failed to receive server response to request. %d", recv_data_len); |
178 | 1 | memcpy(&size, packet_resp, 2); |
179 | 1 | ck_assert_msg(net_ntohs(size) == 2 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE, |
180 | 1 | "Wrong packet size for request response."); |
181 | | |
182 | 1 | uint8_t *packet_resp_plain = (uint8_t *)malloc(max_packet_size); |
183 | 1 | ck_assert(packet_resp_plain != nullptr); |
184 | 1 | ret = decrypt_data_symmetric(mem, f_shared_key, f_nonce_r, packet_resp + 2, recv_data_len - 2, packet_resp_plain); |
185 | 1 | ck_assert_msg(ret != -1, "Failed to decrypt the TCP server's response."); |
186 | 1 | increment_nonce(f_nonce_r); |
187 | | |
188 | 1 | ck_assert_msg(packet_resp_plain[0] == TCP_PACKET_ROUTING_RESPONSE, "Server sent the wrong packet id: %u", |
189 | 1 | packet_resp_plain[0]); |
190 | 1 | ck_assert_msg(packet_resp_plain[1] == 0, "Server did not refuse the connection."); |
191 | 1 | ck_assert_msg(pk_equal(packet_resp_plain + 2, f_public_key), "Server sent the wrong public key."); |
192 | | |
193 | 1 | free(packet_resp_plain); |
194 | 1 | free(packet_resp); |
195 | | |
196 | | // Closing connections. |
197 | 1 | kill_sock(ns, sock); |
198 | 1 | kill_tcp_server(tcp_s); |
199 | | |
200 | 1 | logger_kill(logger); |
201 | 1 | mono_time_free(mem, mono_time); |
202 | 1 | } |
203 | | |
204 | | struct sec_TCP_con { |
205 | | Socket sock; |
206 | | const Network *ns; |
207 | | const Memory *mem; |
208 | | uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; |
209 | | uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; |
210 | | uint8_t sent_nonce[CRYPTO_NONCE_SIZE]; |
211 | | uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; |
212 | | }; |
213 | | |
214 | | static struct sec_TCP_con *new_tcp_con(const Logger *logger, const Memory *mem, const Random *rng, const Network *ns, TCP_Server *tcp_s, Mono_Time *mono_time) |
215 | 3 | { |
216 | 3 | struct sec_TCP_con *sec_c = (struct sec_TCP_con *)malloc(sizeof(struct sec_TCP_con)); |
217 | 3 | ck_assert(sec_c != nullptr); |
218 | 3 | sec_c->ns = ns; |
219 | 3 | sec_c->mem = mem; |
220 | 3 | Socket sock = net_socket(ns, net_family_ipv6(), TOX_SOCK_STREAM, TOX_PROTO_TCP); |
221 | | |
222 | 3 | IP_Port localhost; |
223 | 3 | localhost.ip = get_loopback(); |
224 | 3 | localhost.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); |
225 | | |
226 | 3 | Net_Err_Connect err; |
227 | 3 | bool ok = net_connect(ns, mem, logger, sock, &localhost, &err); |
228 | 3 | ck_assert_msg(ok, "Failed to connect to the test TCP relay server: %s.", net_err_connect_to_string(err)); |
229 | | |
230 | 3 | uint8_t f_secret_key[CRYPTO_SECRET_KEY_SIZE]; |
231 | 3 | crypto_new_keypair(rng, sec_c->public_key, f_secret_key); |
232 | 3 | random_nonce(rng, sec_c->sent_nonce); |
233 | | |
234 | 3 | uint8_t t_secret_key[CRYPTO_SECRET_KEY_SIZE]; |
235 | 3 | uint8_t handshake_plain[TCP_HANDSHAKE_PLAIN_SIZE]; |
236 | 3 | crypto_new_keypair(rng, handshake_plain, t_secret_key); |
237 | 3 | memcpy(handshake_plain + CRYPTO_PUBLIC_KEY_SIZE, sec_c->sent_nonce, CRYPTO_NONCE_SIZE); |
238 | 3 | uint8_t handshake[TCP_CLIENT_HANDSHAKE_SIZE]; |
239 | 3 | memcpy(handshake, sec_c->public_key, CRYPTO_PUBLIC_KEY_SIZE); |
240 | 3 | random_nonce(rng, handshake + CRYPTO_PUBLIC_KEY_SIZE); |
241 | | |
242 | 3 | int ret = encrypt_data(mem, tcp_server_public_key(tcp_s), f_secret_key, handshake + CRYPTO_PUBLIC_KEY_SIZE, handshake_plain, |
243 | 3 | TCP_HANDSHAKE_PLAIN_SIZE, handshake + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); |
244 | 3 | ck_assert_msg(ret == TCP_CLIENT_HANDSHAKE_SIZE - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE), |
245 | 3 | "Failed to encrypt the outgoing handshake."); |
246 | | |
247 | 3 | ck_assert_msg(net_send(ns, logger, sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1, |
248 | 3 | &localhost, nullptr) == TCP_CLIENT_HANDSHAKE_SIZE - 1, |
249 | 3 | "Failed to send the first portion of the handshake to the TCP relay server."); |
250 | | |
251 | 3 | do_tcp_server_delay(tcp_s, mono_time, 50); |
252 | | |
253 | 3 | ck_assert_msg(net_send(ns, logger, sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1, &localhost, nullptr) == 1, |
254 | 3 | "Failed to send last byte of handshake."); |
255 | | |
256 | 3 | do_tcp_server_delay(tcp_s, mono_time, 50); |
257 | | |
258 | 3 | uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; |
259 | 3 | uint8_t response_plain[TCP_HANDSHAKE_PLAIN_SIZE]; |
260 | 3 | ck_assert_msg(net_recv(sec_c->ns, logger, sock, response, TCP_SERVER_HANDSHAKE_SIZE, &localhost) == TCP_SERVER_HANDSHAKE_SIZE, |
261 | 3 | "Failed to receive server handshake response."); |
262 | 3 | ret = decrypt_data(mem, tcp_server_public_key(tcp_s), f_secret_key, response, response + CRYPTO_NONCE_SIZE, |
263 | 3 | TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, response_plain); |
264 | 3 | ck_assert_msg(ret == TCP_HANDSHAKE_PLAIN_SIZE, "Failed to decrypt server handshake response."); |
265 | 3 | encrypt_precompute(response_plain, t_secret_key, sec_c->shared_key); |
266 | 3 | memcpy(sec_c->recv_nonce, response_plain + CRYPTO_SHARED_KEY_SIZE, CRYPTO_NONCE_SIZE); |
267 | 3 | sec_c->sock = sock; |
268 | 3 | return sec_c; |
269 | 3 | } |
270 | | |
271 | | static void kill_tcp_con(struct sec_TCP_con *con) |
272 | 3 | { |
273 | 3 | kill_sock(con->ns, con->sock); |
274 | 3 | free(con); |
275 | 3 | } |
276 | | |
277 | | static int write_packet_tcp_test_connection(const Logger *logger, const Memory *mem, struct sec_TCP_con *con, const uint8_t *data, |
278 | | uint16_t length) |
279 | 9 | { |
280 | 9 | const uint16_t packet_size = sizeof(uint16_t) + length + CRYPTO_MAC_SIZE; |
281 | 9 | VLA(uint8_t, packet, packet_size); |
282 | | |
283 | 9 | uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE); |
284 | 9 | memcpy(packet, &c_length, sizeof(uint16_t)); |
285 | 9 | int len = encrypt_data_symmetric(con->mem, con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); |
286 | | |
287 | 9 | if ((unsigned int)len != (packet_size - sizeof(uint16_t))) { |
288 | 0 | return -1; |
289 | 0 | } |
290 | | |
291 | 9 | increment_nonce(con->sent_nonce); |
292 | | |
293 | 9 | IP_Port localhost; |
294 | 9 | localhost.ip = get_loopback(); |
295 | 9 | localhost.port = 0; |
296 | | |
297 | 9 | ck_assert_msg(net_send(con->ns, logger, con->sock, packet, packet_size, &localhost, nullptr) == packet_size, |
298 | 9 | "Failed to send a packet."); |
299 | 9 | return 0; |
300 | 9 | } |
301 | | |
302 | | static int read_packet_sec_tcp(const Logger *logger, struct sec_TCP_con *con, uint8_t *data, uint16_t length) |
303 | 11 | { |
304 | 11 | IP_Port localhost; |
305 | 11 | localhost.ip = get_loopback(); |
306 | 11 | localhost.port = 0; |
307 | | |
308 | 11 | int rlen = net_recv(con->ns, logger, con->sock, data, length, &localhost); |
309 | 11 | ck_assert_msg(rlen == length, "Did not receive packet of correct length. Wanted %i, instead got %i", length, rlen); |
310 | 11 | rlen = decrypt_data_symmetric(con->mem, con->shared_key, con->recv_nonce, data + 2, length - 2, data); |
311 | 11 | ck_assert_msg(rlen != -1, "Failed to decrypt a received packet from the Relay server."); |
312 | 11 | increment_nonce(con->recv_nonce); |
313 | 11 | return rlen; |
314 | 11 | } |
315 | | |
316 | | static void test_some(void) |
317 | 1 | { |
318 | 1 | const Random *rng = os_random(); |
319 | 1 | ck_assert(rng != nullptr); |
320 | 1 | const Network *ns = os_network(); |
321 | 1 | ck_assert(ns != nullptr); |
322 | 1 | const Memory *mem = os_memory(); |
323 | 1 | ck_assert(mem != nullptr); |
324 | | |
325 | 1 | Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); |
326 | 1 | Logger *logger = logger_new(mem); |
327 | | |
328 | 1 | uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; |
329 | 1 | uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; |
330 | 1 | crypto_new_keypair(rng, self_public_key, self_secret_key); |
331 | 1 | TCP_Server *tcp_s = new_tcp_server(logger, mem, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr); |
332 | 1 | ck_assert_msg(tcp_s != nullptr, "Failed to create TCP relay server"); |
333 | 1 | ck_assert_msg(tcp_server_listen_count(tcp_s) == NUM_PORTS, "Failed to bind to all ports."); |
334 | | |
335 | 1 | struct sec_TCP_con *con1 = new_tcp_con(logger, mem, rng, ns, tcp_s, mono_time); |
336 | 1 | struct sec_TCP_con *con2 = new_tcp_con(logger, mem, rng, ns, tcp_s, mono_time); |
337 | 1 | struct sec_TCP_con *con3 = new_tcp_con(logger, mem, rng, ns, tcp_s, mono_time); |
338 | | |
339 | 1 | uint8_t requ_p[1 + CRYPTO_PUBLIC_KEY_SIZE]; |
340 | 1 | requ_p[0] = TCP_PACKET_ROUTING_REQUEST; |
341 | | |
342 | | // Sending wrong public keys to test server response. |
343 | 1 | memcpy(requ_p + 1, con3->public_key, CRYPTO_PUBLIC_KEY_SIZE); |
344 | 1 | write_packet_tcp_test_connection(logger, mem, con1, requ_p, sizeof(requ_p)); |
345 | 1 | memcpy(requ_p + 1, con1->public_key, CRYPTO_PUBLIC_KEY_SIZE); |
346 | 1 | write_packet_tcp_test_connection(logger, mem, con3, requ_p, sizeof(requ_p)); |
347 | | |
348 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
349 | | |
350 | | // Testing response from connection 1 |
351 | 1 | const size_t max_packet_size = 4096; |
352 | 1 | uint8_t *data = (uint8_t *)malloc(max_packet_size); |
353 | 1 | int len = read_packet_sec_tcp(logger, con1, data, 2 + 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE); |
354 | 1 | ck_assert_msg(len == 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE, "Wrong response packet length of %d.", len); |
355 | 1 | ck_assert_msg(data[0] == TCP_PACKET_ROUTING_RESPONSE, "Wrong response packet id of %d.", data[0]); |
356 | 1 | ck_assert_msg(data[1] == 16, "Server didn't refuse connection using wrong public key."); |
357 | 1 | ck_assert_msg(pk_equal(data + 2, con3->public_key), "Key in response packet wrong."); |
358 | | |
359 | | // Connection 3 |
360 | 1 | len = read_packet_sec_tcp(logger, con3, data, 2 + 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE); |
361 | 1 | ck_assert_msg(len == 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE, "Wrong response packet length of %d.", len); |
362 | 1 | ck_assert_msg(data[0] == TCP_PACKET_ROUTING_RESPONSE, "Wrong response packet id of %d.", data[0]); |
363 | 1 | ck_assert_msg(data[1] == 16, "Server didn't refuse connection using wrong public key."); |
364 | 1 | ck_assert_msg(pk_equal(data + 2, con1->public_key), "Key in response packet wrong."); |
365 | | |
366 | 1 | const uint8_t test_packet[512] = {16, 17, 16, 86, 99, 127, 255, 189, 78}; // What is this packet???? |
367 | | |
368 | 1 | write_packet_tcp_test_connection(logger, mem, con3, test_packet, sizeof(test_packet)); |
369 | 1 | write_packet_tcp_test_connection(logger, mem, con3, test_packet, sizeof(test_packet)); |
370 | 1 | write_packet_tcp_test_connection(logger, mem, con3, test_packet, sizeof(test_packet)); |
371 | | |
372 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
373 | | |
374 | 1 | len = read_packet_sec_tcp(logger, con1, data, 2 + 2 + CRYPTO_MAC_SIZE); |
375 | 1 | ck_assert_msg(len == 2, "wrong len %d", len); |
376 | 1 | ck_assert_msg(data[0] == TCP_PACKET_CONNECTION_NOTIFICATION, "wrong packet id %u", data[0]); |
377 | 1 | ck_assert_msg(data[1] == 16, "wrong peer id %u", data[1]); |
378 | 1 | len = read_packet_sec_tcp(logger, con3, data, 2 + 2 + CRYPTO_MAC_SIZE); |
379 | 1 | ck_assert_msg(len == 2, "wrong len %d", len); |
380 | 1 | ck_assert_msg(data[0] == TCP_PACKET_CONNECTION_NOTIFICATION, "wrong packet id %u", data[0]); |
381 | 1 | ck_assert_msg(data[1] == 16, "wrong peer id %u", data[1]); |
382 | 1 | len = read_packet_sec_tcp(logger, con1, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE); |
383 | 1 | ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len); |
384 | 1 | ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1], |
385 | 1 | data[sizeof(test_packet) - 2], data[sizeof(test_packet) - 1]); |
386 | 1 | len = read_packet_sec_tcp(logger, con1, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE); |
387 | 1 | ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len); |
388 | 1 | ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1], |
389 | 1 | data[sizeof(test_packet) - 2], data[sizeof(test_packet) - 1]); |
390 | 1 | len = read_packet_sec_tcp(logger, con1, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE); |
391 | 1 | ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len); |
392 | 1 | ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1], |
393 | 1 | data[sizeof(test_packet) - 2], data[sizeof(test_packet) - 1]); |
394 | 1 | write_packet_tcp_test_connection(logger, mem, con1, test_packet, sizeof(test_packet)); |
395 | 1 | write_packet_tcp_test_connection(logger, mem, con1, test_packet, sizeof(test_packet)); |
396 | 1 | write_packet_tcp_test_connection(logger, mem, con1, test_packet, sizeof(test_packet)); |
397 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
398 | 1 | len = read_packet_sec_tcp(logger, con3, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE); |
399 | 1 | ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len); |
400 | 1 | ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1], |
401 | 1 | data[sizeof(test_packet) - 2], data[sizeof(test_packet) - 1]); |
402 | 1 | len = read_packet_sec_tcp(logger, con3, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE); |
403 | 1 | ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len); |
404 | 1 | ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1], |
405 | 1 | data[sizeof(test_packet) - 2], data[sizeof(test_packet) - 1]); |
406 | 1 | len = read_packet_sec_tcp(logger, con3, data, 2 + sizeof(test_packet) + CRYPTO_MAC_SIZE); |
407 | 1 | ck_assert_msg(len == sizeof(test_packet), "wrong len %d", len); |
408 | 1 | ck_assert_msg(memcmp(data, test_packet, sizeof(test_packet)) == 0, "packet is wrong %u %u %u %u", data[0], data[1], |
409 | 1 | data[sizeof(test_packet) - 2], data[sizeof(test_packet) - 1]); |
410 | | |
411 | 1 | const uint8_t ping_packet[1 + sizeof(uint64_t)] = {TCP_PACKET_PING, 8, 6, 9, 67}; |
412 | 1 | write_packet_tcp_test_connection(logger, mem, con1, ping_packet, sizeof(ping_packet)); |
413 | | |
414 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
415 | | |
416 | 1 | len = read_packet_sec_tcp(logger, con1, data, 2 + sizeof(ping_packet) + CRYPTO_MAC_SIZE); |
417 | 1 | ck_assert_msg(len == sizeof(ping_packet), "wrong len %d", len); |
418 | 1 | ck_assert_msg(data[0] == TCP_PACKET_PONG, "wrong packet id %u", data[0]); |
419 | 1 | ck_assert_msg(memcmp(ping_packet + 1, data + 1, sizeof(uint64_t)) == 0, "wrong packet data"); |
420 | | |
421 | 1 | free(data); |
422 | | |
423 | | // Kill off the connections |
424 | 1 | kill_tcp_server(tcp_s); |
425 | 1 | kill_tcp_con(con1); |
426 | 1 | kill_tcp_con(con2); |
427 | 1 | kill_tcp_con(con3); |
428 | | |
429 | 1 | logger_kill(logger); |
430 | 1 | mono_time_free(mem, mono_time); |
431 | 1 | } |
432 | | |
433 | | static int response_callback_good; |
434 | | static uint8_t response_callback_connection_id; |
435 | | static uint8_t response_callback_public_key[CRYPTO_PUBLIC_KEY_SIZE]; |
436 | | static int response_callback(void *object, uint8_t connection_id, const uint8_t *public_key) |
437 | 1 | { |
438 | 1 | if (set_tcp_connection_number((TCP_Client_Connection *)(void *)((char *)object - 2), connection_id, 7) != 0) { |
439 | 0 | return 1; |
440 | 0 | } |
441 | | |
442 | 1 | response_callback_connection_id = connection_id; |
443 | 1 | memcpy(response_callback_public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); |
444 | 1 | response_callback_good++; |
445 | 1 | return 0; |
446 | 1 | } |
447 | | static int status_callback_good; |
448 | | static uint8_t status_callback_connection_id; |
449 | | static uint8_t status_callback_status; |
450 | | static int status_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t status) |
451 | 2 | { |
452 | 2 | if (object != (void *)2) { |
453 | 0 | return 1; |
454 | 0 | } |
455 | | |
456 | 2 | if (number != 7) { |
457 | 0 | return 1; |
458 | 0 | } |
459 | | |
460 | 2 | status_callback_connection_id = connection_id; |
461 | 2 | status_callback_status = status; |
462 | 2 | status_callback_good++; |
463 | 2 | return 0; |
464 | 2 | } |
465 | | static int data_callback_good; |
466 | | static int data_callback(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data, uint16_t length, |
467 | | void *userdata) |
468 | 1 | { |
469 | 1 | if (object != (void *)3) { |
470 | 0 | return 1; |
471 | 0 | } |
472 | | |
473 | 1 | if (number != 7) { |
474 | 0 | return 1; |
475 | 0 | } |
476 | | |
477 | 1 | if (length != 5) { |
478 | 0 | return 1; |
479 | 0 | } |
480 | | |
481 | 1 | if (data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4 && data[4] == 5) { |
482 | 1 | data_callback_good++; |
483 | 1 | return 0; |
484 | 1 | } |
485 | | |
486 | 0 | return 1; |
487 | 1 | } |
488 | | |
489 | | static int oob_data_callback_good; |
490 | | static uint8_t oob_pubkey[CRYPTO_PUBLIC_KEY_SIZE]; |
491 | | static int oob_data_callback(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length, |
492 | | void *userdata) |
493 | 1 | { |
494 | 1 | if (object != (void *)4) { |
495 | 0 | return 1; |
496 | 0 | } |
497 | | |
498 | 1 | if (length != 5) { |
499 | 0 | return 1; |
500 | 0 | } |
501 | | |
502 | 1 | if (!pk_equal(public_key, oob_pubkey)) { |
503 | 0 | return 1; |
504 | 0 | } |
505 | | |
506 | 1 | if (data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4 && data[4] == 5) { |
507 | 1 | oob_data_callback_good++; |
508 | 1 | return 0; |
509 | 1 | } |
510 | | |
511 | 0 | return 1; |
512 | 1 | } |
513 | | |
514 | | static void test_client(void) |
515 | 1 | { |
516 | 1 | const Random *rng = os_random(); |
517 | 1 | ck_assert(rng != nullptr); |
518 | 1 | const Network *ns = os_network(); |
519 | 1 | ck_assert(ns != nullptr); |
520 | 1 | const Memory *mem = os_memory(); |
521 | 1 | ck_assert(mem != nullptr); |
522 | | |
523 | 1 | Logger *logger = logger_new(mem); |
524 | 1 | Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); |
525 | | |
526 | 1 | uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; |
527 | 1 | uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; |
528 | 1 | crypto_new_keypair(rng, self_public_key, self_secret_key); |
529 | 1 | TCP_Server *tcp_s = new_tcp_server(logger, mem, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr); |
530 | 1 | ck_assert_msg(tcp_s != nullptr, "Failed to create a TCP relay server."); |
531 | 1 | ck_assert_msg(tcp_server_listen_count(tcp_s) == NUM_PORTS, "Failed to bind the relay server to all ports."); |
532 | | |
533 | 1 | uint8_t f_public_key[CRYPTO_PUBLIC_KEY_SIZE]; |
534 | 1 | uint8_t f_secret_key[CRYPTO_SECRET_KEY_SIZE]; |
535 | 1 | crypto_new_keypair(rng, f_public_key, f_secret_key); |
536 | 1 | IP_Port ip_port_tcp_s; |
537 | | |
538 | 1 | ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); |
539 | 1 | ip_port_tcp_s.ip = get_loopback(); |
540 | | |
541 | 1 | TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr, nullptr); |
542 | 1 | ck_assert_msg(conn != nullptr, "Failed to create a TCP client connection."); |
543 | | // TCP sockets might need a moment before they can be written to. |
544 | 1 | c_sleep(50); |
545 | 1 | do_tcp_connection(logger, mono_time, conn, nullptr); |
546 | | |
547 | | // The connection status should be unconfirmed here because we have finished |
548 | | // sending our data and are awaiting a response. |
549 | 1 | ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_UNCONFIRMED, "Wrong connection status. Expected: %u, is: %u.", |
550 | 1 | (unsigned int)TCP_CLIENT_UNCONFIRMED, tcp_con_status(conn)); |
551 | | |
552 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); // Now let the server handle requests... |
553 | | |
554 | 1 | const uint8_t loop_size = 3; |
555 | | |
556 | 4 | for (uint8_t i = 0; i < loop_size; i++) { |
557 | 3 | mono_time_update(mono_time); |
558 | 3 | do_tcp_connection(logger, mono_time, conn, nullptr); // Run the connection loop. |
559 | | |
560 | | // The status of the connection should continue to be TCP_CLIENT_CONFIRMED after multiple subsequent do_tcp_connection() calls. |
561 | 3 | ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_CONFIRMED, "Wrong connection status. Expected: %u, is: %u", |
562 | 3 | (unsigned int)TCP_CLIENT_CONFIRMED, tcp_con_status(conn)); |
563 | | |
564 | 3 | c_sleep(i == loop_size - 1 ? 0 : 500); // Sleep for 500ms on all except third loop. |
565 | 3 | } |
566 | | |
567 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
568 | | |
569 | | // And still after the server runs again. |
570 | 1 | ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %u, is: %u", (unsigned int)TCP_CLIENT_CONFIRMED, |
571 | 1 | tcp_con_status(conn)); |
572 | | |
573 | 1 | uint8_t f2_public_key[CRYPTO_PUBLIC_KEY_SIZE]; |
574 | 1 | uint8_t f2_secret_key[CRYPTO_SECRET_KEY_SIZE]; |
575 | 1 | crypto_new_keypair(rng, f2_public_key, f2_secret_key); |
576 | 1 | ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); |
577 | 1 | TCP_Client_Connection *conn2 = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f2_public_key, |
578 | 1 | f2_secret_key, nullptr, nullptr); |
579 | 1 | ck_assert_msg(conn2 != nullptr, "Failed to create a second TCP client connection."); |
580 | 1 | c_sleep(50); |
581 | | |
582 | | // The client should call this function (defined earlier) during the routing process. |
583 | 1 | routing_response_handler(conn, response_callback, (char *)conn + 2); |
584 | | // The client should call this function when it receives a connection notification. |
585 | 1 | routing_status_handler(conn, status_callback, (void *)2); |
586 | | // The client should call this function when |
587 | 1 | routing_data_handler(conn, data_callback, (void *)3); |
588 | | // The client should call this function when sending out of band packets. |
589 | 1 | oob_data_handler(conn, oob_data_callback, (void *)4); |
590 | | |
591 | | // These integers will increment per successful callback. |
592 | 1 | oob_data_callback_good = response_callback_good = status_callback_good = data_callback_good = 0; |
593 | | |
594 | 1 | do_tcp_connection(logger, mono_time, conn, nullptr); |
595 | 1 | do_tcp_connection(logger, mono_time, conn2, nullptr); |
596 | | |
597 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
598 | | |
599 | 1 | do_tcp_connection(logger, mono_time, conn, nullptr); |
600 | 1 | do_tcp_connection(logger, mono_time, conn2, nullptr); |
601 | 1 | c_sleep(50); |
602 | | |
603 | 1 | const uint8_t data[5] = {1, 2, 3, 4, 5}; |
604 | 1 | memcpy(oob_pubkey, f2_public_key, CRYPTO_PUBLIC_KEY_SIZE); |
605 | 1 | send_oob_packet(logger, conn2, f_public_key, data, 5); |
606 | 1 | send_routing_request(logger, conn, f2_public_key); |
607 | 1 | send_routing_request(logger, conn2, f_public_key); |
608 | | |
609 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
610 | | |
611 | 1 | do_tcp_connection(logger, mono_time, conn, nullptr); |
612 | 1 | do_tcp_connection(logger, mono_time, conn2, nullptr); |
613 | | |
614 | | // All callback methods save data should have run during the above network prodding. |
615 | 1 | ck_assert_msg(oob_data_callback_good == 1, "OOB callback not called"); |
616 | 1 | ck_assert_msg(response_callback_good == 1, "Response callback not called."); |
617 | 1 | ck_assert_msg(pk_equal(response_callback_public_key, f2_public_key), "Wrong public key."); |
618 | 1 | ck_assert_msg(status_callback_good == 1, "Status callback not called."); |
619 | 1 | ck_assert_msg(status_callback_status == 2, "Wrong status callback status."); |
620 | 1 | ck_assert_msg(status_callback_connection_id == response_callback_connection_id, |
621 | 1 | "Status and response callback connection IDs are not equal."); |
622 | | |
623 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
624 | | |
625 | 1 | ck_assert_msg(send_data(logger, conn2, 0, data, 5) == 1, "Failed a send_data() call."); |
626 | | |
627 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
628 | | |
629 | 1 | do_tcp_connection(logger, mono_time, conn, nullptr); |
630 | 1 | do_tcp_connection(logger, mono_time, conn2, nullptr); |
631 | 1 | ck_assert_msg(data_callback_good == 1, "Data callback was not called."); |
632 | 1 | status_callback_good = 0; |
633 | 1 | send_disconnect_request(logger, conn2, 0); |
634 | | |
635 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
636 | | |
637 | 1 | do_tcp_connection(logger, mono_time, conn, nullptr); |
638 | 1 | do_tcp_connection(logger, mono_time, conn2, nullptr); |
639 | 1 | ck_assert_msg(status_callback_good == 1, "Status callback not called"); |
640 | 1 | ck_assert_msg(status_callback_status == 1, "Wrong status callback status."); |
641 | | |
642 | | // Kill off all connections and servers. |
643 | 1 | kill_tcp_server(tcp_s); |
644 | 1 | kill_tcp_connection(conn); |
645 | 1 | kill_tcp_connection(conn2); |
646 | | |
647 | 1 | logger_kill(logger); |
648 | 1 | mono_time_free(mem, mono_time); |
649 | 1 | } |
650 | | |
651 | | // Test how the client handles servers that don't respond. |
652 | | static void test_client_invalid(void) |
653 | 1 | { |
654 | 1 | const Random *rng = os_random(); |
655 | 1 | ck_assert(rng != nullptr); |
656 | 1 | const Network *ns = os_network(); |
657 | 1 | ck_assert(ns != nullptr); |
658 | 1 | const Memory *mem = os_memory(); |
659 | 1 | ck_assert(mem != nullptr); |
660 | | |
661 | 1 | Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); |
662 | 1 | Logger *logger = logger_new(mem); |
663 | | |
664 | 1 | uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; |
665 | 1 | uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; |
666 | 1 | crypto_new_keypair(rng, self_public_key, self_secret_key); |
667 | | |
668 | 1 | uint8_t f_public_key[CRYPTO_PUBLIC_KEY_SIZE]; |
669 | 1 | uint8_t f_secret_key[CRYPTO_SECRET_KEY_SIZE]; |
670 | 1 | crypto_new_keypair(rng, f_public_key, f_secret_key); |
671 | 1 | IP_Port ip_port_tcp_s; |
672 | | |
673 | 1 | ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); |
674 | 1 | ip_port_tcp_s.ip = get_loopback(); |
675 | 1 | TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, |
676 | 1 | self_public_key, f_public_key, f_secret_key, nullptr, nullptr); |
677 | 1 | ck_assert_msg(conn != nullptr, "Failed to create a TCP client connection."); |
678 | | |
679 | | // Run the client's main loop but not the server. |
680 | 1 | mono_time_update(mono_time); |
681 | 1 | do_tcp_connection(logger, mono_time, conn, nullptr); |
682 | 1 | c_sleep(50); |
683 | | |
684 | | // After 50ms of no response... |
685 | 1 | ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_CONNECTING, "Wrong status. Expected: %u, is: %u.", |
686 | 1 | (unsigned int)TCP_CLIENT_CONNECTING, tcp_con_status(conn)); |
687 | | // After 5s... |
688 | 1 | c_sleep(5000); |
689 | 1 | mono_time_update(mono_time); |
690 | 1 | do_tcp_connection(logger, mono_time, conn, nullptr); |
691 | 1 | ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_CONNECTING, "Wrong status. Expected: %u, is: %u.", |
692 | 1 | (unsigned int)TCP_CLIENT_CONNECTING, tcp_con_status(conn)); |
693 | | // 11s... (Should wait for 10 before giving up.) |
694 | 1 | c_sleep(6000); |
695 | 1 | mono_time_update(mono_time); |
696 | 1 | do_tcp_connection(logger, mono_time, conn, nullptr); |
697 | 1 | ck_assert_msg(tcp_con_status(conn) == TCP_CLIENT_DISCONNECTED, "Wrong status. Expected: %u, is: %u.", |
698 | 1 | (unsigned int)TCP_CLIENT_DISCONNECTED, tcp_con_status(conn)); |
699 | | |
700 | 1 | kill_tcp_connection(conn); |
701 | | |
702 | 1 | logger_kill(logger); |
703 | 1 | mono_time_free(mem, mono_time); |
704 | 1 | } |
705 | | |
706 | | #include "../toxcore/TCP_connection.h" |
707 | | |
708 | | static bool tcp_data_callback_called; |
709 | | static int tcp_data_callback(void *object, int id, const uint8_t *data, uint16_t length, void *userdata) |
710 | 2 | { |
711 | 2 | if (object != (void *)120397) { |
712 | 0 | return -1; |
713 | 0 | } |
714 | | |
715 | 2 | if (id != 123) { |
716 | 0 | return -1; |
717 | 0 | } |
718 | | |
719 | 2 | if (length != 6) { |
720 | 0 | return -1; |
721 | 0 | } |
722 | | |
723 | 2 | if (memcmp(data, "Gentoo", length) != 0) { |
724 | 0 | return -1; |
725 | 0 | } |
726 | | |
727 | 2 | tcp_data_callback_called = 1; |
728 | 2 | return 0; |
729 | 2 | } |
730 | | |
731 | | static void test_tcp_connection(void) |
732 | 1 | { |
733 | 1 | const Random *rng = os_random(); |
734 | 1 | ck_assert(rng != nullptr); |
735 | 1 | const Network *ns = os_network(); |
736 | 1 | ck_assert(ns != nullptr); |
737 | 1 | const Memory *mem = os_memory(); |
738 | 1 | ck_assert(mem != nullptr); |
739 | | |
740 | 1 | Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); |
741 | 1 | Logger *logger = logger_new(mem); |
742 | | |
743 | 1 | Net_Profile *tcp_np = netprof_new(logger, mem); |
744 | 1 | ck_assert(tcp_np != nullptr); |
745 | | |
746 | 1 | tcp_data_callback_called = 0; |
747 | 1 | uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; |
748 | 1 | uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; |
749 | 1 | crypto_new_keypair(rng, self_public_key, self_secret_key); |
750 | 1 | TCP_Server *tcp_s = new_tcp_server(logger, mem, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr); |
751 | 1 | ck_assert_msg(pk_equal(tcp_server_public_key(tcp_s), self_public_key), "Wrong public key"); |
752 | | |
753 | 1 | TCP_Proxy_Info proxy_info; |
754 | 1 | proxy_info.proxy_type = TCP_PROXY_NONE; |
755 | 1 | crypto_new_keypair(rng, self_public_key, self_secret_key); |
756 | 1 | TCP_Connections *tc_1 = new_tcp_connections(logger, mem, rng, ns, mono_time, self_secret_key, &proxy_info, tcp_np); |
757 | 1 | ck_assert_msg(tc_1 != nullptr, "Failed to create TCP connections"); |
758 | 1 | ck_assert_msg(pk_equal(tcp_connections_public_key(tc_1), self_public_key), "Wrong public key"); |
759 | | |
760 | 1 | crypto_new_keypair(rng, self_public_key, self_secret_key); |
761 | 1 | TCP_Connections *tc_2 = new_tcp_connections(logger, mem, rng, ns, mono_time, self_secret_key, &proxy_info, tcp_np); |
762 | 1 | ck_assert_msg(tc_2 != nullptr, "Failed to create TCP connections"); |
763 | 1 | ck_assert_msg(pk_equal(tcp_connections_public_key(tc_2), self_public_key), "Wrong public key"); |
764 | | |
765 | 1 | IP_Port ip_port_tcp_s; |
766 | | |
767 | 1 | ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); |
768 | 1 | ip_port_tcp_s.ip = get_loopback(); |
769 | | |
770 | 1 | int connection = new_tcp_connection_to(tc_1, tcp_connections_public_key(tc_2), 123); |
771 | 1 | ck_assert_msg(connection == 0, "Connection id wrong"); |
772 | 1 | ck_assert_msg(add_tcp_relay_connection(tc_1, connection, &ip_port_tcp_s, tcp_server_public_key(tcp_s)) == 0, |
773 | 1 | "Could not add tcp relay to connection\n"); |
774 | | |
775 | 1 | ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); |
776 | 1 | connection = new_tcp_connection_to(tc_2, tcp_connections_public_key(tc_1), 123); |
777 | 1 | ck_assert_msg(connection == 0, "Connection id wrong"); |
778 | 1 | ck_assert_msg(add_tcp_relay_connection(tc_2, connection, &ip_port_tcp_s, tcp_server_public_key(tcp_s)) == 0, |
779 | 1 | "Could not add tcp relay to connection\n"); |
780 | | |
781 | 1 | ck_assert_msg(new_tcp_connection_to(tc_2, tcp_connections_public_key(tc_1), 123) == -1, |
782 | 1 | "Managed to read same connection\n"); |
783 | | |
784 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
785 | | |
786 | 1 | do_tcp_connections(logger, tc_1, nullptr); |
787 | 1 | do_tcp_connections(logger, tc_2, nullptr); |
788 | | |
789 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
790 | | |
791 | 1 | do_tcp_connections(logger, tc_1, nullptr); |
792 | 1 | do_tcp_connections(logger, tc_2, nullptr); |
793 | | |
794 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
795 | | |
796 | 1 | do_tcp_connections(logger, tc_1, nullptr); |
797 | 1 | do_tcp_connections(logger, tc_2, nullptr); |
798 | | |
799 | 1 | int ret = send_packet_tcp_connection(tc_1, 0, (const uint8_t *)"Gentoo", 6); |
800 | 1 | ck_assert_msg(ret == 0, "could not send packet."); |
801 | 1 | set_packet_tcp_connection_callback(tc_2, &tcp_data_callback, (void *) 120397); |
802 | | |
803 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
804 | | |
805 | 1 | do_tcp_connections(logger, tc_1, nullptr); |
806 | 1 | do_tcp_connections(logger, tc_2, nullptr); |
807 | | |
808 | 1 | ck_assert_msg(tcp_data_callback_called, "could not recv packet."); |
809 | 1 | ck_assert_msg(tcp_connection_to_online_tcp_relays(tc_1, 0) == 1, "Wrong number of connected relays"); |
810 | 1 | ck_assert_msg(kill_tcp_connection_to(tc_1, 0) == 0, "could not kill connection to\n"); |
811 | | |
812 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
813 | | |
814 | 1 | do_tcp_connections(logger, tc_1, nullptr); |
815 | 1 | do_tcp_connections(logger, tc_2, nullptr); |
816 | | |
817 | 1 | ck_assert_msg(send_packet_tcp_connection(tc_1, 0, (const uint8_t *)"Gentoo", 6) == -1, "could send packet."); |
818 | 1 | ck_assert_msg(kill_tcp_connection_to(tc_2, 0) == 0, "could not kill connection to\n"); |
819 | | |
820 | 1 | kill_tcp_server(tcp_s); |
821 | 1 | kill_tcp_connections(tc_1); |
822 | 1 | kill_tcp_connections(tc_2); |
823 | | |
824 | 1 | netprof_kill(mem, tcp_np); |
825 | | |
826 | 1 | logger_kill(logger); |
827 | 1 | mono_time_free(mem, mono_time); |
828 | 1 | } |
829 | | |
830 | | static bool tcp_oobdata_callback_called; |
831 | | static int tcp_oobdata_callback(void *object, const uint8_t *public_key, unsigned int id, const uint8_t *data, |
832 | | uint16_t length, void *userdata) |
833 | 1 | { |
834 | 1 | const TCP_Connections *tcp_c = (const TCP_Connections *)object; |
835 | | |
836 | 1 | if (length != 6) { |
837 | 0 | return -1; |
838 | 0 | } |
839 | | |
840 | 1 | if (memcmp(data, "Gentoo", length) != 0) { |
841 | 0 | return -1; |
842 | 0 | } |
843 | | |
844 | 1 | if (tcp_send_oob_packet(tcp_c, id, public_key, data, length) == 0) { |
845 | 1 | tcp_oobdata_callback_called = 1; |
846 | 1 | } |
847 | | |
848 | 1 | return 0; |
849 | 1 | } |
850 | | |
851 | | static void test_tcp_connection2(void) |
852 | 1 | { |
853 | 1 | const Random *rng = os_random(); |
854 | 1 | ck_assert(rng != nullptr); |
855 | 1 | const Network *ns = os_network(); |
856 | 1 | ck_assert(ns != nullptr); |
857 | 1 | const Memory *mem = os_memory(); |
858 | 1 | ck_assert(mem != nullptr); |
859 | | |
860 | 1 | Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); |
861 | 1 | Logger *logger = logger_new(mem); |
862 | | |
863 | 1 | Net_Profile *tcp_np = netprof_new(logger, mem); |
864 | 1 | ck_assert(tcp_np != nullptr); |
865 | | |
866 | 1 | tcp_oobdata_callback_called = 0; |
867 | 1 | tcp_data_callback_called = 0; |
868 | | |
869 | 1 | uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; |
870 | 1 | uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; |
871 | 1 | crypto_new_keypair(rng, self_public_key, self_secret_key); |
872 | 1 | TCP_Server *tcp_s = new_tcp_server(logger, mem, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr); |
873 | 1 | ck_assert_msg(pk_equal(tcp_server_public_key(tcp_s), self_public_key), "Wrong public key"); |
874 | | |
875 | 1 | TCP_Proxy_Info proxy_info; |
876 | 1 | proxy_info.proxy_type = TCP_PROXY_NONE; |
877 | 1 | crypto_new_keypair(rng, self_public_key, self_secret_key); |
878 | 1 | TCP_Connections *tc_1 = new_tcp_connections(logger, mem, rng, ns, mono_time, self_secret_key, &proxy_info, tcp_np); |
879 | 1 | ck_assert_msg(tc_1 != nullptr, "Failed to create TCP connections"); |
880 | 1 | ck_assert_msg(pk_equal(tcp_connections_public_key(tc_1), self_public_key), "Wrong public key"); |
881 | | |
882 | 1 | crypto_new_keypair(rng, self_public_key, self_secret_key); |
883 | 1 | TCP_Connections *tc_2 = new_tcp_connections(logger, mem, rng, ns, mono_time, self_secret_key, &proxy_info, tcp_np); |
884 | 1 | ck_assert_msg(tc_2 != nullptr, "Failed to create TCP connections"); |
885 | 1 | ck_assert_msg(pk_equal(tcp_connections_public_key(tc_2), self_public_key), "Wrong public key"); |
886 | | |
887 | 1 | IP_Port ip_port_tcp_s; |
888 | | |
889 | 1 | ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); |
890 | 1 | ip_port_tcp_s.ip = get_loopback(); |
891 | | |
892 | 1 | int connection = new_tcp_connection_to(tc_1, tcp_connections_public_key(tc_2), 123); |
893 | 1 | ck_assert_msg(connection == 0, "Connection id wrong"); |
894 | 1 | ck_assert_msg(add_tcp_relay_connection(tc_1, connection, &ip_port_tcp_s, tcp_server_public_key(tcp_s)) == 0, |
895 | 1 | "Could not add tcp relay to connection\n"); |
896 | | |
897 | 1 | ck_assert_msg(add_tcp_relay_global(tc_2, &ip_port_tcp_s, tcp_server_public_key(tcp_s)) == 0, |
898 | 1 | "Could not add global relay"); |
899 | | |
900 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
901 | | |
902 | 1 | do_tcp_connections(logger, tc_1, nullptr); |
903 | 1 | do_tcp_connections(logger, tc_2, nullptr); |
904 | | |
905 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
906 | | |
907 | 1 | do_tcp_connections(logger, tc_1, nullptr); |
908 | 1 | do_tcp_connections(logger, tc_2, nullptr); |
909 | | |
910 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
911 | | |
912 | 1 | do_tcp_connections(logger, tc_1, nullptr); |
913 | 1 | do_tcp_connections(logger, tc_2, nullptr); |
914 | | |
915 | 1 | int ret = send_packet_tcp_connection(tc_1, 0, (const uint8_t *)"Gentoo", 6); |
916 | 1 | ck_assert_msg(ret == 0, "could not send packet."); |
917 | 1 | set_oob_packet_tcp_connection_callback(tc_2, &tcp_oobdata_callback, tc_2); |
918 | 1 | set_packet_tcp_connection_callback(tc_1, &tcp_data_callback, (void *) 120397); |
919 | | |
920 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
921 | | |
922 | 1 | do_tcp_connections(logger, tc_1, nullptr); |
923 | 1 | do_tcp_connections(logger, tc_2, nullptr); |
924 | | |
925 | 1 | ck_assert_msg(tcp_oobdata_callback_called, "could not recv packet."); |
926 | | |
927 | 1 | do_tcp_server_delay(tcp_s, mono_time, 50); |
928 | | |
929 | 1 | do_tcp_connections(logger, tc_1, nullptr); |
930 | 1 | do_tcp_connections(logger, tc_2, nullptr); |
931 | | |
932 | 1 | ck_assert_msg(tcp_data_callback_called, "could not recv packet."); |
933 | 1 | ck_assert_msg(kill_tcp_connection_to(tc_1, 0) == 0, "could not kill connection to\n"); |
934 | | |
935 | 1 | netprof_kill(mem, tcp_np); |
936 | | |
937 | 1 | kill_tcp_server(tcp_s); |
938 | 1 | kill_tcp_connections(tc_1); |
939 | 1 | kill_tcp_connections(tc_2); |
940 | | |
941 | 1 | logger_kill(logger); |
942 | 1 | mono_time_free(mem, mono_time); |
943 | 1 | } |
944 | | |
945 | | static void tcp_suite(void) |
946 | 1 | { |
947 | 1 | test_basic(); |
948 | 1 | test_some(); |
949 | 1 | test_client(); |
950 | 1 | test_client_invalid(); |
951 | 1 | test_tcp_connection(); |
952 | 1 | test_tcp_connection2(); |
953 | 1 | } |
954 | | |
955 | | int main(void) |
956 | 84 | { |
957 | 84 | setvbuf(stdout, nullptr, _IONBF, 0); |
958 | 84 | tcp_suite(); |
959 | 84 | return 0; |
960 | 84 | } |