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