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