/work/auto_tests/onion_test.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include <stdlib.h> |
2 | | #include <string.h> |
3 | | |
4 | | #include "../testing/misc_tools.h" |
5 | | #include "../toxcore/mono_time.h" |
6 | | #include "../toxcore/network.h" |
7 | | #include "../toxcore/onion.h" |
8 | | #include "../toxcore/onion_announce.h" |
9 | | #include "../toxcore/onion_client.h" |
10 | | #include "../toxcore/os_memory.h" |
11 | | #include "../toxcore/os_random.h" |
12 | | #include "auto_test_support.h" |
13 | | #include "check_compat.h" |
14 | | |
15 | | #ifndef USE_IPV6 |
16 | | #define USE_IPV6 1 |
17 | | #endif |
18 | | |
19 | | static inline IP get_loopback(void) |
20 | 136 | { |
21 | 136 | IP ip; |
22 | | #if USE_IPV6 |
23 | | ip.family = net_family_ipv6(); |
24 | | ip.ip.v6 = get_ip6_loopback(); |
25 | | #else |
26 | 136 | ip.family = net_family_ipv4(); |
27 | 136 | ip.ip.v4 = get_ip4_loopback(); |
28 | 136 | #endif |
29 | 136 | return ip; |
30 | 136 | } |
31 | | static void do_onion(Mono_Time *mono_time, Onion *onion) |
32 | 28 | { |
33 | 28 | mono_time_update(mono_time); |
34 | | |
35 | 28 | networking_poll(onion->net, nullptr); |
36 | 28 | do_dht(onion->dht); |
37 | 28 | } |
38 | | |
39 | | static int handled_test_1; |
40 | | static int handle_test_1(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata) |
41 | 1 | { |
42 | 1 | const Onion *onion = (const Onion *)object; |
43 | | |
44 | 1 | const char req_message[] = "Install Gentoo"; |
45 | 1 | uint8_t req_packet[1 + sizeof(req_message)]; |
46 | 1 | req_packet[0] = NET_PACKET_ANNOUNCE_REQUEST; |
47 | 1 | memcpy(req_packet + 1, req_message, sizeof(req_message)); |
48 | | |
49 | 1 | if (memcmp(packet, req_packet, sizeof(req_packet)) != 0) { |
50 | 0 | return 1; |
51 | 0 | } |
52 | | |
53 | 1 | const char res_message[] = "install gentoo"; |
54 | 1 | uint8_t res_packet[1 + sizeof(res_message)]; |
55 | 1 | res_packet[0] = NET_PACKET_ANNOUNCE_RESPONSE; |
56 | 1 | memcpy(res_packet + 1, res_message, sizeof(res_message)); |
57 | | |
58 | 1 | if (send_onion_response(onion->log, onion->net, source, res_packet, sizeof(res_packet), |
59 | 1 | packet + sizeof(res_packet)) == -1) { |
60 | 0 | return 1; |
61 | 0 | } |
62 | | |
63 | 1 | handled_test_1 = 1; |
64 | 1 | return 0; |
65 | 1 | } |
66 | | |
67 | | static int handled_test_2; |
68 | | static int handle_test_2(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata) |
69 | 1 | { |
70 | 1 | const char res_message[] = "install gentoo"; |
71 | 1 | uint8_t res_packet[1 + sizeof(res_message)]; |
72 | 1 | res_packet[0] = NET_PACKET_ANNOUNCE_RESPONSE; |
73 | 1 | memcpy(res_packet + 1, res_message, sizeof(res_message)); |
74 | | |
75 | 1 | if (length != sizeof(res_packet)) { |
76 | 0 | return 1; |
77 | 0 | } |
78 | | |
79 | 1 | if (memcmp(packet, res_packet, sizeof(res_packet)) != 0) { |
80 | 0 | return 1; |
81 | 0 | } |
82 | | |
83 | 1 | handled_test_2 = 1; |
84 | 1 | return 0; |
85 | 1 | } |
86 | | #if 0 |
87 | | void print_client_id(uint8_t *client_id, uint32_t length) |
88 | | { |
89 | | uint32_t j; |
90 | | |
91 | | for (j = 0; j < length; j++) { |
92 | | printf("%02X", client_id[j]); |
93 | | } |
94 | | |
95 | | printf("\n"); |
96 | | } |
97 | | #endif |
98 | | static uint8_t sb_data[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; |
99 | | static int handled_test_3; |
100 | | static uint8_t test_3_pub_key[CRYPTO_PUBLIC_KEY_SIZE]; |
101 | | static uint8_t test_3_ping_id[CRYPTO_SHA256_SIZE]; |
102 | | static int handle_test_3(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata) |
103 | 0 | { |
104 | 0 | const Onion *onion = (const Onion *)object; |
105 | |
|
106 | 0 | if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) { |
107 | 0 | return 1; |
108 | 0 | } |
109 | | |
110 | 0 | uint8_t plain[2 + CRYPTO_SHA256_SIZE]; |
111 | | #if 0 |
112 | | print_client_id(packet, length); |
113 | | #endif |
114 | 0 | int len = decrypt_data(onion->mem, test_3_pub_key, dht_get_self_secret_key(onion->dht), |
115 | 0 | packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, |
116 | 0 | packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE, |
117 | 0 | 2 + CRYPTO_SHA256_SIZE + CRYPTO_MAC_SIZE, plain); |
118 | |
|
119 | 0 | if (len == -1) { |
120 | 0 | return 1; |
121 | 0 | } |
122 | | |
123 | 0 | if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) { |
124 | 0 | return 1; |
125 | 0 | } |
126 | | |
127 | 0 | memcpy(test_3_ping_id, plain + 1, CRYPTO_SHA256_SIZE); |
128 | | #if 0 |
129 | | print_client_id(test_3_ping_id, sizeof(test_3_ping_id)); |
130 | | #endif |
131 | 0 | handled_test_3 = 1; |
132 | 0 | return 0; |
133 | 0 | } |
134 | | |
135 | | /* TODO: DEPRECATE */ |
136 | | static int handle_test_3_old(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, |
137 | | void *userdata) |
138 | 2 | { |
139 | 2 | const Onion *onion = (const Onion *)object; |
140 | | |
141 | 2 | if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) { |
142 | 0 | return 1; |
143 | 0 | } |
144 | | |
145 | 2 | uint8_t plain[2 + CRYPTO_SHA256_SIZE]; |
146 | | #if 0 |
147 | | print_client_id(packet, length); |
148 | | #endif |
149 | 2 | int len = decrypt_data(onion->mem, test_3_pub_key, dht_get_self_secret_key(onion->dht), |
150 | 2 | packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, |
151 | 2 | packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE, |
152 | 2 | 1 + CRYPTO_SHA256_SIZE + CRYPTO_MAC_SIZE, plain); |
153 | | |
154 | 2 | if (len == -1) { |
155 | 0 | return 1; |
156 | 0 | } |
157 | | |
158 | 2 | if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) { |
159 | 0 | return 1; |
160 | 0 | } |
161 | | |
162 | 2 | memcpy(test_3_ping_id, plain + 1, CRYPTO_SHA256_SIZE); |
163 | | #if 0 |
164 | | print_client_id(test_3_ping_id, sizeof(test_3_ping_id)); |
165 | | #endif |
166 | 2 | handled_test_3 = 1; |
167 | 2 | return 0; |
168 | 2 | } |
169 | | |
170 | | static uint8_t nonce[CRYPTO_NONCE_SIZE]; |
171 | | static int handled_test_4; |
172 | | static int handle_test_4(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata) |
173 | 1 | { |
174 | 1 | const Onion *onion = (const Onion *)object; |
175 | | |
176 | 1 | if (length != (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + sizeof("Install gentoo") + |
177 | 1 | CRYPTO_MAC_SIZE)) { |
178 | 0 | return 1; |
179 | 0 | } |
180 | | |
181 | 1 | uint8_t plain[sizeof("Install gentoo")] = {0}; |
182 | | |
183 | 1 | if (memcmp(nonce, packet + 1, CRYPTO_NONCE_SIZE) != 0) { |
184 | 0 | return 1; |
185 | 0 | } |
186 | | |
187 | 1 | int len = decrypt_data(onion->mem, packet + 1 + CRYPTO_NONCE_SIZE, dht_get_self_secret_key(onion->dht), packet + 1, |
188 | 1 | packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, sizeof("Install gentoo") + CRYPTO_MAC_SIZE, plain); |
189 | | |
190 | 1 | if (len == -1) { |
191 | 0 | return 1; |
192 | 0 | } |
193 | | |
194 | 1 | if (memcmp(plain, "Install gentoo", sizeof("Install gentoo")) != 0) { |
195 | 0 | return 1; |
196 | 0 | } |
197 | | |
198 | 1 | handled_test_4 = 1; |
199 | 1 | return 0; |
200 | 1 | } |
201 | | |
202 | | /** Create and send a onion packet. |
203 | | * |
204 | | * Use Onion_Path path to send data of length to dest. |
205 | | * Maximum length of data is ONION_MAX_DATA_SIZE. |
206 | | */ |
207 | | static void send_onion_packet(const Networking_Core *net, const Memory *mem, const Random *rng, const Onion_Path *path, const IP_Port *dest, const uint8_t *data, uint16_t length) |
208 | 1 | { |
209 | 1 | uint8_t packet[ONION_MAX_PACKET_SIZE]; |
210 | 1 | const int len = create_onion_packet(mem, rng, packet, sizeof(packet), path, dest, data, length); |
211 | 1 | ck_assert_msg(len != -1, "failed to create onion packet"); |
212 | 1 | ck_assert_msg(sendpacket(net, &path->ip_port1, packet, len) == len, "failed to send onion packet"); |
213 | 1 | } |
214 | | |
215 | | /** Initialize networking. |
216 | | * Added for reverse compatibility with old new_networking calls. |
217 | | */ |
218 | | static Networking_Core *new_networking(const Logger *log, const Memory *mem, const Network *ns, const IP *ip, uint16_t port) |
219 | 53 | { |
220 | 53 | return new_networking_ex(log, mem, ns, ip, port, port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM), nullptr); |
221 | 53 | } |
222 | | |
223 | | static void test_basic(void) |
224 | 1 | { |
225 | 1 | uint32_t index[] = { 1, 2, 3 }; |
226 | 1 | const Network *ns = os_network(); |
227 | 1 | ck_assert(ns != nullptr); |
228 | 1 | const Memory *mem = os_memory(); |
229 | 1 | ck_assert(mem != nullptr); |
230 | 1 | const Random *rng = os_random(); |
231 | 1 | ck_assert(rng != nullptr); |
232 | | |
233 | 1 | Logger *log1 = logger_new(mem); |
234 | 1 | logger_callback_log(log1, print_debug_logger, nullptr, &index[0]); |
235 | 1 | Logger *log2 = logger_new(mem); |
236 | 1 | logger_callback_log(log2, print_debug_logger, nullptr, &index[1]); |
237 | | |
238 | 1 | Mono_Time *mono_time1 = mono_time_new(mem, nullptr, nullptr); |
239 | 1 | Mono_Time *mono_time2 = mono_time_new(mem, nullptr, nullptr); |
240 | | |
241 | 1 | IP ip = get_loopback(); |
242 | 1 | Networking_Core *net1 = new_networking(log1, mem, ns, &ip, 36567); |
243 | 1 | Onion *onion1 = new_onion(log1, mem, mono_time1, rng, new_dht(log1, mem, rng, ns, mono_time1, net1, true, false), net1); |
244 | 1 | Networking_Core *net2 = new_networking(log2, mem, ns, &ip, 36568); |
245 | 1 | Onion *onion2 = new_onion(log2, mem, mono_time2, rng, new_dht(log2, mem, rng, ns, mono_time2, net2, true, false), net2); |
246 | 1 | ck_assert_msg((onion1 != nullptr) && (onion2 != nullptr), "Onion failed initializing."); |
247 | 1 | networking_registerhandler(onion2->net, NET_PACKET_ANNOUNCE_REQUEST, &handle_test_1, onion2); |
248 | | |
249 | 1 | IP_Port on1 = {ip, net_port(onion1->net)}; |
250 | 1 | Node_format n1; |
251 | 1 | memcpy(n1.public_key, dht_get_self_public_key(onion1->dht), CRYPTO_PUBLIC_KEY_SIZE); |
252 | 1 | n1.ip_port = on1; |
253 | | |
254 | 1 | IP_Port on2 = {ip, net_port(onion2->net)}; |
255 | 1 | Node_format n2; |
256 | 1 | memcpy(n2.public_key, dht_get_self_public_key(onion2->dht), CRYPTO_PUBLIC_KEY_SIZE); |
257 | 1 | n2.ip_port = on2; |
258 | | |
259 | 1 | const char req_message[] = "Install Gentoo"; |
260 | 1 | uint8_t req_packet[1 + sizeof(req_message)]; |
261 | 1 | req_packet[0] = NET_PACKET_ANNOUNCE_REQUEST; |
262 | 1 | memcpy(req_packet + 1, req_message, sizeof(req_message)); |
263 | | |
264 | 1 | Node_format nodes[4]; |
265 | 1 | nodes[0] = n1; |
266 | 1 | nodes[1] = n2; |
267 | 1 | nodes[2] = n1; |
268 | 1 | nodes[3] = n2; |
269 | 1 | Onion_Path path; |
270 | 1 | create_onion_path(rng, onion1->dht, &path, nodes); |
271 | 1 | send_onion_packet(onion1->net, onion1->mem, rng, &path, &nodes[3].ip_port, req_packet, sizeof(req_packet)); |
272 | | |
273 | 1 | handled_test_1 = 0; |
274 | | |
275 | 2 | do { |
276 | 2 | do_onion(mono_time1, onion1); |
277 | 2 | do_onion(mono_time2, onion2); |
278 | 2 | } while (handled_test_1 == 0); |
279 | | |
280 | 1 | networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_test_2, onion1); |
281 | 1 | handled_test_2 = 0; |
282 | | |
283 | 2 | do { |
284 | 2 | do_onion(mono_time1, onion1); |
285 | 2 | do_onion(mono_time2, onion2); |
286 | 2 | } while (handled_test_2 == 0); |
287 | | |
288 | 1 | Onion_Announce *onion1_a = new_onion_announce(log1, mem, rng, mono_time1, onion1->dht, onion1->net); |
289 | 1 | Onion_Announce *onion2_a = new_onion_announce(log2, mem, rng, mono_time2, onion2->dht, onion2->net); |
290 | 1 | networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_test_3, onion1); |
291 | 1 | networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE_OLD, &handle_test_3_old, onion1); |
292 | 1 | ck_assert_msg((onion1_a != nullptr) && (onion2_a != nullptr), "Onion_Announce failed initializing."); |
293 | 1 | const uint8_t zeroes[64] = {0}; |
294 | 1 | random_bytes(rng, sb_data, sizeof(sb_data)); |
295 | 1 | uint64_t s; |
296 | 1 | memcpy(&s, sb_data, sizeof(uint64_t)); |
297 | 1 | memcpy(test_3_pub_key, nodes[3].public_key, CRYPTO_PUBLIC_KEY_SIZE); |
298 | 1 | int ret = send_announce_request(log1, onion1->mem, onion1->net, rng, &path, &nodes[3], |
299 | 1 | dht_get_self_public_key(onion1->dht), |
300 | 1 | dht_get_self_secret_key(onion1->dht), |
301 | 1 | zeroes, |
302 | 1 | dht_get_self_public_key(onion1->dht), |
303 | 1 | dht_get_self_public_key(onion1->dht), s); |
304 | 1 | ck_assert_msg(ret == 0, "Failed to create/send onion announce_request packet."); |
305 | 1 | handled_test_3 = 0; |
306 | | |
307 | 4 | do { |
308 | 4 | do_onion(mono_time1, onion1); |
309 | 4 | do_onion(mono_time2, onion2); |
310 | 4 | c_sleep(50); |
311 | 4 | } while (handled_test_3 == 0); |
312 | | |
313 | 1 | printf("test 3 complete\n"); |
314 | | |
315 | 1 | random_bytes(rng, sb_data, sizeof(sb_data)); |
316 | 1 | memcpy(&s, sb_data, sizeof(uint64_t)); |
317 | 1 | memcpy(onion_announce_entry_public_key(onion2_a, 1), dht_get_self_public_key(onion2->dht), CRYPTO_PUBLIC_KEY_SIZE); |
318 | 1 | onion_announce_entry_set_time(onion2_a, 1, mono_time_get(mono_time2)); |
319 | 1 | networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1); |
320 | 1 | send_announce_request(log1, onion1->mem, onion1->net, rng, &path, &nodes[3], |
321 | 1 | dht_get_self_public_key(onion1->dht), |
322 | 1 | dht_get_self_secret_key(onion1->dht), |
323 | 1 | test_3_ping_id, |
324 | 1 | dht_get_self_public_key(onion1->dht), |
325 | 1 | dht_get_self_public_key(onion1->dht), s); |
326 | | |
327 | 2 | do { |
328 | 2 | do_onion(mono_time1, onion1); |
329 | 2 | do_onion(mono_time2, onion2); |
330 | 2 | c_sleep(50); |
331 | 2 | } while (memcmp(onion_announce_entry_public_key(onion2_a, ONION_ANNOUNCE_MAX_ENTRIES - 2), |
332 | 2 | dht_get_self_public_key(onion1->dht), |
333 | 2 | CRYPTO_PUBLIC_KEY_SIZE) != 0); |
334 | | |
335 | 1 | c_sleep(1000); |
336 | 1 | Logger *log3 = logger_new(mem); |
337 | 1 | logger_callback_log(log3, print_debug_logger, nullptr, &index[2]); |
338 | | |
339 | 1 | Mono_Time *mono_time3 = mono_time_new(mem, nullptr, nullptr); |
340 | | |
341 | 1 | Networking_Core *net3 = new_networking(log3, mem, ns, &ip, 36569); |
342 | 1 | Onion *onion3 = new_onion(log3, mem, mono_time3, rng, new_dht(log3, mem, rng, ns, mono_time3, net3, true, false), net3); |
343 | 1 | ck_assert_msg((onion3 != nullptr), "Onion failed initializing."); |
344 | | |
345 | 1 | random_nonce(rng, nonce); |
346 | 1 | ret = send_data_request(log3, onion3->mem, onion3->net, rng, &path, &nodes[3].ip_port, |
347 | 1 | dht_get_self_public_key(onion1->dht), |
348 | 1 | dht_get_self_public_key(onion1->dht), |
349 | 1 | nonce, (const uint8_t *)"Install gentoo", sizeof("Install gentoo")); |
350 | 1 | ck_assert_msg(ret == 0, "Failed to create/send onion data_request packet."); |
351 | 1 | handled_test_4 = 0; |
352 | | |
353 | 4 | do { |
354 | 4 | do_onion(mono_time1, onion1); |
355 | 4 | do_onion(mono_time2, onion2); |
356 | 4 | c_sleep(50); |
357 | 4 | } while (handled_test_4 == 0); |
358 | | |
359 | 1 | printf("test 4 complete\n"); |
360 | | |
361 | 1 | kill_onion_announce(onion2_a); |
362 | 1 | kill_onion_announce(onion1_a); |
363 | | |
364 | 1 | { |
365 | 1 | Onion *onion = onion3; |
366 | | |
367 | 1 | Networking_Core *net = onion->net; |
368 | 1 | DHT *dht = onion->dht; |
369 | 1 | kill_onion(onion); |
370 | 1 | kill_dht(dht); |
371 | 1 | kill_networking(net); |
372 | 1 | mono_time_free(mem, mono_time3); |
373 | 1 | logger_kill(log3); |
374 | 1 | } |
375 | | |
376 | 1 | { |
377 | 1 | Onion *onion = onion2; |
378 | | |
379 | 1 | Networking_Core *net = onion->net; |
380 | 1 | DHT *dht = onion->dht; |
381 | 1 | kill_onion(onion); |
382 | 1 | kill_dht(dht); |
383 | 1 | kill_networking(net); |
384 | 1 | mono_time_free(mem, mono_time2); |
385 | 1 | logger_kill(log2); |
386 | 1 | } |
387 | | |
388 | 1 | { |
389 | 1 | Onion *onion = onion1; |
390 | | |
391 | 1 | Networking_Core *net = onion->net; |
392 | 1 | DHT *dht = onion->dht; |
393 | 1 | kill_onion(onion); |
394 | 1 | kill_dht(dht); |
395 | 1 | kill_networking(net); |
396 | 1 | mono_time_free(mem, mono_time1); |
397 | 1 | logger_kill(log1); |
398 | 1 | } |
399 | 1 | } |
400 | | |
401 | | typedef struct { |
402 | | Logger *log; |
403 | | Mono_Time *mono_time; |
404 | | Net_Crypto *nc; |
405 | | Net_Profile *tcp_np; |
406 | | Onion *onion; |
407 | | Onion_Announce *onion_a; |
408 | | Onion_Client *onion_c; |
409 | | } Onions; |
410 | | |
411 | | static Onions *new_onions(const Memory *mem, const Random *rng, uint16_t port, uint32_t *index) |
412 | 50 | { |
413 | 50 | IP ip = get_loopback(); |
414 | 50 | ip.ip.v6.uint8[15] = 1; |
415 | 50 | const Network *ns = os_network(); |
416 | 50 | Onions *on = (Onions *)malloc(sizeof(Onions)); |
417 | | |
418 | 50 | if (!on) { |
419 | 0 | return nullptr; |
420 | 0 | } |
421 | | |
422 | 50 | on->log = logger_new(mem); |
423 | | |
424 | 50 | if (!on->log) { |
425 | 0 | free(on); |
426 | 0 | return nullptr; |
427 | 0 | } |
428 | | |
429 | 50 | logger_callback_log(on->log, print_debug_logger, nullptr, index); |
430 | | |
431 | 50 | on->mono_time = mono_time_new(mem, nullptr, nullptr); |
432 | | |
433 | 50 | if (!on->mono_time) { |
434 | 0 | logger_kill(on->log); |
435 | 0 | free(on); |
436 | 0 | return nullptr; |
437 | 0 | } |
438 | | |
439 | 50 | Networking_Core *net = new_networking(on->log, mem, ns, &ip, port); |
440 | | |
441 | 50 | if (!net) { |
442 | 0 | mono_time_free(mem, on->mono_time); |
443 | 0 | logger_kill(on->log); |
444 | 0 | free(on); |
445 | 0 | return nullptr; |
446 | 0 | } |
447 | | |
448 | 50 | DHT *dht = new_dht(on->log, mem, rng, ns, on->mono_time, net, true, false); |
449 | | |
450 | 50 | if (!dht) { |
451 | 0 | kill_networking(net); |
452 | 0 | mono_time_free(mem, on->mono_time); |
453 | 0 | logger_kill(on->log); |
454 | 0 | free(on); |
455 | 0 | return nullptr; |
456 | 0 | } |
457 | | |
458 | 50 | on->onion = new_onion(on->log, mem, on->mono_time, rng, dht, net); |
459 | | |
460 | 50 | if (!on->onion) { |
461 | 0 | kill_dht(dht); |
462 | 0 | kill_networking(net); |
463 | 0 | mono_time_free(mem, on->mono_time); |
464 | 0 | logger_kill(on->log); |
465 | 0 | free(on); |
466 | 0 | return nullptr; |
467 | 0 | } |
468 | | |
469 | 50 | on->onion_a = new_onion_announce(on->log, mem, rng, on->mono_time, dht, net); |
470 | | |
471 | 50 | if (!on->onion_a) { |
472 | 0 | kill_onion(on->onion); |
473 | 0 | kill_dht(dht); |
474 | 0 | kill_networking(net); |
475 | 0 | mono_time_free(mem, on->mono_time); |
476 | 0 | logger_kill(on->log); |
477 | 0 | free(on); |
478 | 0 | return nullptr; |
479 | 0 | } |
480 | | |
481 | 50 | on->tcp_np = netprof_new(on->log, mem); |
482 | | |
483 | 50 | if (!on->tcp_np) { |
484 | 0 | kill_onion_announce(on->onion_a); |
485 | 0 | kill_onion(on->onion); |
486 | 0 | kill_dht(dht); |
487 | 0 | kill_networking(net); |
488 | 0 | mono_time_free(mem, on->mono_time); |
489 | 0 | logger_kill(on->log); |
490 | 0 | free(on); |
491 | 0 | return nullptr; |
492 | 0 | } |
493 | | |
494 | 50 | TCP_Proxy_Info inf = {{{{0}}}}; |
495 | 50 | on->nc = new_net_crypto(on->log, mem, rng, ns, on->mono_time, net, dht, &auto_test_dht_funcs, &inf, on->tcp_np); |
496 | 50 | on->onion_c = new_onion_client(on->log, mem, rng, on->mono_time, on->nc, dht, net); |
497 | | |
498 | 50 | if (!on->onion_c) { |
499 | 0 | netprof_kill(mem, on->tcp_np); |
500 | 0 | kill_onion_announce(on->onion_a); |
501 | 0 | kill_onion(on->onion); |
502 | 0 | kill_dht(dht); |
503 | 0 | kill_networking(net); |
504 | 0 | mono_time_free(mem, on->mono_time); |
505 | 0 | logger_kill(on->log); |
506 | 0 | free(on); |
507 | 0 | return nullptr; |
508 | 0 | } |
509 | | |
510 | 50 | return on; |
511 | 50 | } |
512 | | |
513 | | static void do_onions(Onions *on) |
514 | 6.15k | { |
515 | 6.15k | mono_time_update(on->mono_time); |
516 | | |
517 | 6.15k | networking_poll(on->onion->net, nullptr); |
518 | 6.15k | do_dht(on->onion->dht); |
519 | 6.15k | do_onion_client(on->onion_c); |
520 | 6.15k | } |
521 | | |
522 | | static void kill_onions(const Memory *mem, Onions *on) |
523 | 50 | { |
524 | 50 | Networking_Core *net = on->onion->net; |
525 | 50 | DHT *dht = on->onion->dht; |
526 | 50 | Net_Crypto *c = on->nc; |
527 | 50 | kill_onion_client(on->onion_c); |
528 | 50 | kill_onion_announce(on->onion_a); |
529 | 50 | kill_onion(on->onion); |
530 | 50 | kill_net_crypto(c); |
531 | 50 | netprof_kill(mem, on->tcp_np); |
532 | 50 | kill_dht(dht); |
533 | 50 | kill_networking(net); |
534 | 50 | mono_time_free(mem, on->mono_time); |
535 | 50 | logger_kill(on->log); |
536 | 50 | free(on); |
537 | 50 | } |
538 | | |
539 | 6.42k | #define NUM_ONIONS 50 |
540 | 13 | #define NUM_FIRST 7 |
541 | 11 | #define NUM_LAST 37 |
542 | | |
543 | | static bool first_ip, last_ip; |
544 | | static void dht_ip_callback(void *object, int32_t number, const IP_Port *ip_port) |
545 | 2 | { |
546 | 2 | if (NUM_FIRST == number) { |
547 | 1 | first_ip = 1; |
548 | 1 | return; |
549 | 1 | } |
550 | | |
551 | 1 | if (NUM_LAST == number) { |
552 | 1 | last_ip = 1; |
553 | 1 | return; |
554 | 1 | } |
555 | | |
556 | 0 | ck_abort_msg("Error."); |
557 | 0 | } |
558 | | |
559 | | static bool first, last; |
560 | | static uint8_t first_dht_pk[CRYPTO_PUBLIC_KEY_SIZE]; |
561 | | static uint8_t last_dht_pk[CRYPTO_PUBLIC_KEY_SIZE]; |
562 | | |
563 | | static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key, void *userdata) |
564 | 3 | { |
565 | 3 | if ((NUM_FIRST == number && !first) || (NUM_LAST == number && !last)) { |
566 | 2 | Onions *on = (Onions *)object; |
567 | 2 | uint32_t token = 0; |
568 | 2 | int ret = dht_addfriend(on->onion->dht, dht_public_key, &dht_ip_callback, object, number, &token); |
569 | 2 | ck_assert_msg(ret == 0, "dht_addfriend() did not return 0"); |
570 | 2 | ck_assert_msg(token == 1, "Count not 1, count is %u", token); |
571 | | |
572 | 2 | if (NUM_FIRST == number && !first) { |
573 | 1 | first = 1; |
574 | | |
575 | 1 | if (memcmp(dht_public_key, last_dht_pk, CRYPTO_PUBLIC_KEY_SIZE) != 0) { |
576 | 0 | ck_abort_msg("Error wrong dht key."); |
577 | 0 | } |
578 | | |
579 | 1 | return; |
580 | 1 | } |
581 | | |
582 | 1 | if (NUM_LAST == number && !last) { |
583 | 1 | last = 1; |
584 | | |
585 | 1 | if (memcmp(dht_public_key, first_dht_pk, CRYPTO_PUBLIC_KEY_SIZE) != 0) { |
586 | 0 | ck_abort_msg("Error wrong dht key."); |
587 | 0 | } |
588 | | |
589 | 1 | return; |
590 | 1 | } |
591 | | |
592 | 0 | ck_abort_msg("Error."); |
593 | 0 | } |
594 | 3 | } |
595 | | |
596 | | static void test_announce(void) |
597 | 1 | { |
598 | 1 | uint32_t index[NUM_ONIONS]; |
599 | 1 | Onions *onions[NUM_ONIONS]; |
600 | 1 | const Random *rng = os_random(); |
601 | 1 | ck_assert(rng != nullptr); |
602 | 1 | const Memory *mem = os_memory(); |
603 | 1 | ck_assert(mem != nullptr); |
604 | | |
605 | 51 | for (uint32_t i = 0; i < NUM_ONIONS; ++i) { |
606 | 50 | index[i] = i + 1; |
607 | 50 | onions[i] = new_onions(mem, rng, i + 36655, &index[i]); |
608 | 50 | ck_assert_msg(onions[i] != nullptr, "Failed to create onions. %u", i); |
609 | 50 | } |
610 | | |
611 | 1 | IP ip = get_loopback(); |
612 | | |
613 | 48 | for (uint32_t i = 3; i < NUM_ONIONS; ++i) { |
614 | 47 | IP_Port ip_port = {ip, net_port(onions[i - 1]->onion->net)}; |
615 | 47 | dht_bootstrap(onions[i]->onion->dht, &ip_port, dht_get_self_public_key(onions[i - 1]->onion->dht)); |
616 | 47 | IP_Port ip_port1 = {ip, net_port(onions[i - 2]->onion->net)}; |
617 | 47 | dht_bootstrap(onions[i]->onion->dht, &ip_port1, dht_get_self_public_key(onions[i - 2]->onion->dht)); |
618 | 47 | IP_Port ip_port2 = {ip, net_port(onions[i - 3]->onion->net)}; |
619 | 47 | dht_bootstrap(onions[i]->onion->dht, &ip_port2, dht_get_self_public_key(onions[i - 3]->onion->dht)); |
620 | 47 | } |
621 | | |
622 | 1 | uint32_t connected = 0; |
623 | | |
624 | 3 | do { |
625 | 3 | connected = 0; |
626 | | |
627 | 153 | for (uint32_t i = 0; i < NUM_ONIONS; ++i) { |
628 | 150 | do_onions(onions[i]); |
629 | 150 | connected += dht_isconnected(onions[i]->onion->dht); |
630 | 150 | } |
631 | | |
632 | 3 | c_sleep(50); |
633 | 3 | } while (connected != NUM_ONIONS); |
634 | | |
635 | 1 | printf("connected\n"); |
636 | | |
637 | 51 | for (uint32_t i = 0; i < 25 * 2; ++i) { |
638 | 2.55k | for (uint32_t j = 0; j < NUM_ONIONS; ++j) { |
639 | 2.50k | do_onions(onions[j]); |
640 | 2.50k | } |
641 | | |
642 | 50 | c_sleep(50); |
643 | 50 | } |
644 | | |
645 | 1 | memcpy(first_dht_pk, dht_get_self_public_key(onions[NUM_FIRST]->onion->dht), CRYPTO_PUBLIC_KEY_SIZE); |
646 | 1 | memcpy(last_dht_pk, dht_get_self_public_key(onions[NUM_LAST]->onion->dht), CRYPTO_PUBLIC_KEY_SIZE); |
647 | | |
648 | 1 | printf("adding friend\n"); |
649 | 1 | int frnum_f = onion_addfriend(onions[NUM_FIRST]->onion_c, |
650 | 1 | nc_get_self_public_key(onions[NUM_LAST]->nc)); |
651 | 1 | int frnum = onion_addfriend(onions[NUM_LAST]->onion_c, |
652 | 1 | nc_get_self_public_key(onions[NUM_FIRST]->nc)); |
653 | | |
654 | 1 | onion_dht_pk_callback(onions[NUM_FIRST]->onion_c, frnum_f, &dht_pk_callback, onions[NUM_FIRST], NUM_FIRST); |
655 | 1 | onion_dht_pk_callback(onions[NUM_LAST]->onion_c, frnum, &dht_pk_callback, onions[NUM_LAST], NUM_LAST); |
656 | | |
657 | 1 | IP_Port ip_port; |
658 | | |
659 | 59 | do { |
660 | 3.00k | for (uint32_t i = 0; i < NUM_ONIONS; ++i) { |
661 | 2.95k | do_onions(onions[i]); |
662 | 2.95k | } |
663 | | |
664 | 59 | c_sleep(50); |
665 | 59 | } while (!first || !last); |
666 | | |
667 | 1 | printf("Waiting for ips\n"); |
668 | | |
669 | 11 | do { |
670 | 561 | for (uint32_t i = 0; i < NUM_ONIONS; ++i) { |
671 | 550 | do_onions(onions[i]); |
672 | 550 | } |
673 | | |
674 | 11 | c_sleep(50); |
675 | 11 | } while (!first_ip || !last_ip); |
676 | | |
677 | 1 | onion_getfriendip(onions[NUM_LAST]->onion_c, frnum, &ip_port); |
678 | 1 | ck_assert_msg(ip_port.port == net_port(onions[NUM_FIRST]->onion->net), "Port in returned ip not correct."); |
679 | | |
680 | 51 | for (uint32_t i = 0; i < NUM_ONIONS; ++i) { |
681 | 50 | kill_onions(mem, onions[i]); |
682 | 50 | } |
683 | 1 | } |
684 | | |
685 | | int main(void) |
686 | 84 | { |
687 | 84 | setvbuf(stdout, nullptr, _IONBF, 0); |
688 | | |
689 | 84 | test_basic(); |
690 | 84 | test_announce(); |
691 | | |
692 | 84 | return 0; |
693 | 84 | } |