Merge branch 'maint-0.4.8'
[tor.git] / src / test / test_conflux_pool.c
blob05dc7b14ff98b3542f8cad085a42647e2251d7db
1 #define CHANNEL_OBJECT_PRIVATE
2 #define TOR_TIMERS_PRIVATE
3 #define TOR_CONFLUX_PRIVATE
4 #define CIRCUITLIST_PRIVATE
5 #define NETWORKSTATUS_PRIVATE
6 #define CRYPT_PATH_PRIVATE
7 #define RELAY_PRIVATE
8 #define CONNECTION_PRIVATE
9 #define TOR_CONGESTION_CONTROL_COMMON_PRIVATE
10 #define TOR_CONGESTION_CONTROL_PRIVATE
12 #include "core/or/or.h"
13 #include "test/test.h"
14 #include "test/log_test_helpers.h"
15 #include "lib/testsupport/testsupport.h"
16 #include "core/or/connection_or.h"
17 #include "core/or/channel.h"
18 #include "core/or/channeltls.h"
19 #include "core/or/crypt_path.h"
20 #include <event.h>
21 #include "lib/evloop/compat_libevent.h"
22 #include "lib/time/compat_time.h"
23 #include "lib/defs/time.h"
24 #include "core/or/relay.h"
25 #include "core/or/circuitlist.h"
26 #include "core/or/circuitstats.h"
27 #include "core/or/circuitbuild.h"
28 #include "core/or/circuituse.h"
29 #include "core/or/congestion_control_st.h"
30 #include "core/or/congestion_control_common.h"
31 #include "core/or/extendinfo.h"
32 #include "core/mainloop/netstatus.h"
33 #include "core/crypto/relay_crypto.h"
34 #include "core/or/protover.h"
35 #include "feature/nodelist/nodelist.h"
36 #include "app/config/config.h"
38 #include "feature/nodelist/routerstatus_st.h"
39 #include "feature/nodelist/networkstatus_st.h"
40 #include "feature/nodelist/node_st.h"
41 #include "core/or/cell_st.h"
42 #include "core/or/crypt_path_st.h"
43 #include "core/or/or_circuit_st.h"
44 #include "core/or/origin_circuit_st.h"
46 #include "core/mainloop/connection.h"
47 #include "core/or/connection_edge.h"
48 #include "core/or/edge_connection_st.h"
50 #include "test/fakecircs.h"
51 #include "test/rng_test_helpers.h"
52 #include "core/or/conflux_pool.h"
53 #include "core/or/conflux_util.h"
54 #include "core/or/conflux_params.h"
55 #include "core/or/conflux.h"
56 #include "core/or/conflux_st.h"
57 #include "trunnel/conflux.h"
58 #include "lib/crypt_ops/crypto_rand.h"
60 /* Start our monotime mocking at 1 second past whatever monotime_init()
61 * thought the actual wall clock time was, for platforms with bad resolution
62 * and weird timevalues during monotime_init() before mocking. */
63 #define MONOTIME_MOCK_START (monotime_absolute_nsec()+\
64 TOR_NSEC_PER_USEC*TOR_USEC_PER_SEC)
66 extern smartlist_t *connection_array;
67 void circuit_expire_old_circuits_clientside(void);
69 circid_t get_unique_circ_id_by_chan(channel_t *chan);
71 channel_t *new_fake_channel(void);
73 static void simulate_single_hop_extend(origin_circuit_t *client, int exit);
74 static void free_fake_origin_circuit(origin_circuit_t *circ);
75 static circuit_t * get_exit_circ(circuit_t *client_circ);
76 static circuit_t * get_client_circ(circuit_t *exit_circ);
77 static void simulate_circuit_build(circuit_t *client_circ);
79 static int64_t curr_mocked_time;
81 static channel_t dummy_channel;
83 static void
84 timers_advance_and_run(int64_t msec_update)
86 curr_mocked_time += msec_update*TOR_NSEC_PER_MSEC;
87 monotime_coarse_set_mock_time_nsec(curr_mocked_time);
88 monotime_set_mock_time_nsec(curr_mocked_time);
91 /* These lists of circuit endpoints send to eachother via
92 * circuit_package_relay_cell_mocked */
93 static smartlist_t *client_circs;
94 static smartlist_t *exit_circs;
95 static smartlist_t *client_streams;
96 static smartlist_t *exit_streams;
98 typedef struct {
99 circuit_t *client;
100 circuit_t *exit;
101 } circ_pair_t;
102 static smartlist_t *circ_pairs;
104 static void
105 simulate_circuit_built(circuit_t *client, circuit_t *exit)
107 circ_pair_t *pair = tor_malloc_zero(sizeof(circ_pair_t));
108 pair->client = client;
109 pair->exit = exit;
110 smartlist_add(circ_pairs, pair);
113 static origin_circuit_t *
114 circuit_establish_circuit_conflux_mock(const uint8_t *conflux_nonce,
115 uint8_t purpose, extend_info_t *exit_ei,
116 int flags)
118 (void)exit_ei;
119 (void)flags;
120 origin_circuit_t *circ = origin_circuit_init(purpose, flags);
121 circ->base_.conflux_pending_nonce = tor_memdup(conflux_nonce, DIGEST256_LEN);
122 circ->base_.purpose = CIRCUIT_PURPOSE_CONFLUX_UNLINKED;
123 smartlist_add(client_circs, circ);
125 // This also moves the clock forward as if these hops were opened..
126 // Not a problem, unless we want to accurately test buildtimeouts
127 simulate_single_hop_extend(circ, 0);
128 simulate_single_hop_extend(circ, 0);
129 simulate_single_hop_extend(circ, 1);
130 circ->cpath->prev->ccontrol = tor_malloc_zero(sizeof(congestion_control_t));
131 circ->cpath->prev->ccontrol->sendme_pending_timestamps = smartlist_new();
132 circ->cpath->prev->ccontrol->sendme_inc = 31;
134 return circ;
137 static void
138 free_fake_origin_circuit(origin_circuit_t *circ)
140 circuit_clear_cpath(circ);
141 tor_free(circ);
144 void dummy_nop_timer(void);
146 static int
147 circuit_package_relay_cell_mock(cell_t *cell, circuit_t *circ,
148 cell_direction_t cell_direction,
149 crypt_path_t *layer_hint, streamid_t on_stream,
150 const char *filename, int lineno);
152 static void
153 circuitmux_attach_circuit_mock(circuitmux_t *cmux, circuit_t *circ,
154 cell_direction_t direction);
156 static void
157 circuitmux_attach_circuit_mock(circuitmux_t *cmux, circuit_t *circ,
158 cell_direction_t direction)
160 (void)cmux;
161 (void)circ;
162 (void)direction;
164 return;
166 /* For use in the mock_net smartlist queue:
167 * this struct contains a circuit and a cell to
168 * deliver on it. */
169 typedef struct {
170 circuit_t *circ;
171 cell_t *cell;
172 } cell_delivery_t;
174 static smartlist_t *mock_cell_delivery = NULL;
176 static int
177 circuit_package_relay_cell_mock(cell_t *cell, circuit_t *circ,
178 cell_direction_t cell_direction,
179 crypt_path_t *layer_hint, streamid_t on_stream,
180 const char *filename, int lineno)
182 (void)cell; (void)on_stream; (void)filename; (void)lineno;
183 (void)cell_direction;
184 circuit_t *dest_circ = NULL;
186 // If we have a layer hint, we are sending to the exit. Look
187 // up the exit circ based on our circuit index in the smartlist
188 if (layer_hint) {
189 tor_assert(CIRCUIT_IS_ORIGIN(circ));
190 tt_int_op(cell_direction, OP_EQ, CELL_DIRECTION_OUT);
192 // Search the circ pairs list for the pair whose client is this circ,
193 // and set dest_circ to the exit circ in that pair
194 SMARTLIST_FOREACH_BEGIN(circ_pairs, circ_pair_t *, pair) {
195 if (pair->client == circ) {
196 dest_circ = pair->exit;
197 break;
199 } SMARTLIST_FOREACH_END(pair);
200 } else {
201 tt_int_op(cell_direction, OP_EQ, CELL_DIRECTION_IN);
203 // Search the circ pairs list for the pair whose exit is this circ,
204 // and set dest_circ to the client circ in that pair
205 SMARTLIST_FOREACH_BEGIN(circ_pairs, circ_pair_t *, pair) {
206 if (pair->exit == circ) {
207 dest_circ = pair->client;
208 break;
210 } SMARTLIST_FOREACH_END(pair);
213 cell_delivery_t *delivery = tor_malloc_zero(sizeof(cell_delivery_t));
214 delivery->circ = dest_circ;
215 delivery->cell = tor_memdup(cell, sizeof(cell_t));
216 smartlist_add(mock_cell_delivery, delivery);
217 done:
218 return 0;
221 /** Pull the next cell from the mock delivery queue and deliver it. */
222 static void
223 process_mock_cell_delivery(void)
225 relay_header_t rh;
227 cell_delivery_t *delivery = smartlist_pop_last(mock_cell_delivery);
228 tor_assert(delivery);
229 cell_t *cell = delivery->cell;
230 circuit_t *dest_circ = delivery->circ;
231 relay_header_unpack(&rh, cell->payload);
233 timers_advance_and_run(1);
235 switch (cell->payload[0]) {
236 case RELAY_COMMAND_CONFLUX_LINK:
237 tor_assert(!CIRCUIT_IS_ORIGIN(dest_circ));
238 conflux_process_link(dest_circ, cell, rh.length);
239 break;
240 case RELAY_COMMAND_CONFLUX_LINKED:
241 tor_assert(CIRCUIT_IS_ORIGIN(dest_circ));
242 conflux_process_linked(dest_circ,
243 TO_ORIGIN_CIRCUIT(dest_circ)->cpath->prev,
244 cell, rh.length);
245 break;
246 case RELAY_COMMAND_CONFLUX_LINKED_ACK:
247 tor_assert(!CIRCUIT_IS_ORIGIN(dest_circ));
248 conflux_process_linked_ack(dest_circ);
249 break;
250 case RELAY_COMMAND_CONFLUX_SWITCH:
251 // We only test the case where the switch is initiated by the client.
252 // It is symmetric, so this should not matter. If we ever want to test
253 // the case where the switch is initiated by the exit, we will need to
254 // get the cpath layer hint for the client.
255 tor_assert(!CIRCUIT_IS_ORIGIN(dest_circ));
256 conflux_process_switch_command(dest_circ, NULL, cell, &rh);
257 break;
260 tor_free(delivery);
261 tor_free(cell);
262 return;
265 static uint64_t
266 mock_monotime_absolute_usec(void)
268 return 100;
271 static int
272 channel_get_addr_if_possible_mock(const channel_t *chan, tor_addr_t *addr_out)
274 (void)chan;
275 tt_int_op(AF_INET,OP_EQ, tor_addr_parse(addr_out, "18.0.0.1"));
276 return 1;
278 done:
279 return 0;
282 static void
283 circuit_mark_for_close_mock(circuit_t *circ, int reason,
284 int line, const char *file)
286 (void)circ;
287 (void)reason;
288 (void)line;
289 (void)file;
291 log_info(LD_CIRC, "Marking circuit for close at %s:%d", file, line);
293 if (BUG(circ->marked_for_close)) {
294 log_warn(LD_BUG,
295 "Duplicate call to circuit_mark_for_close at %s:%d"
296 " (first at %s:%d)", file, line,
297 circ->marked_for_close_file, circ->marked_for_close);
298 return;
301 circ->marked_for_close = line;
302 circ->marked_for_close_file = file;
303 circ->marked_for_close_reason = reason;
305 if (CIRCUIT_IS_CONFLUX(circ)) {
306 conflux_circuit_has_closed(circ);
309 // Mark the other side for close too. No idea if this even improves things;
310 // We might also want to make this go through the cell queue as a destroy
311 if (CIRCUIT_IS_ORIGIN(circ)) {
312 circuit_t *exit_circ = get_exit_circ(circ);
313 if (!exit_circ->marked_for_close)
314 circuit_mark_for_close_mock(get_exit_circ(circ), reason, line, file);
315 } else {
316 circuit_t *client_circ = get_client_circ(circ);
317 if (!client_circ->marked_for_close)
318 circuit_mark_for_close_mock(get_client_circ(circ), reason, line, file);
321 // XXX: Should we do this?
322 //if (circuits_pending_close == NULL)
323 // circuits_pending_close = smartlist_new();
324 //smartlist_add(circuits_pending_close, circ);
327 static void
328 simulate_single_hop_extend(origin_circuit_t *client, int exit)
330 char whatevs_key[CPATH_KEY_MATERIAL_LEN];
331 char digest[DIGEST_LEN];
332 tor_addr_t addr;
334 // Advance time a tiny bit so we can calculate an RTT
335 curr_mocked_time += 10 * TOR_NSEC_PER_MSEC;
336 monotime_coarse_set_mock_time_nsec(curr_mocked_time);
337 monotime_set_mock_time_nsec(curr_mocked_time);
339 // Add a hop to cpath
340 crypt_path_t *hop = tor_malloc_zero(sizeof(crypt_path_t));
341 cpath_extend_linked_list(&client->cpath, hop);
343 hop->magic = CRYPT_PATH_MAGIC;
344 hop->state = CPATH_STATE_OPEN;
346 // add an extend info to indicate if this node supports padding or not.
347 // (set the first byte of the digest for our mocked node_get_by_id)
348 digest[0] = exit;
350 hop->extend_info = extend_info_new(
351 exit ? "exit" : "non-exit",
352 digest, NULL, NULL, NULL,
353 &addr, exit, NULL, exit);
355 cpath_init_circuit_crypto(hop, whatevs_key, sizeof(whatevs_key), 0, 0);
357 hop->package_window = circuit_initial_package_window();
358 hop->deliver_window = CIRCWINDOW_START;
361 static void
362 test_setup(void)
364 int64_t actual_mocked_monotime_start;
366 MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock);
367 MOCK(channel_get_addr_if_possible, channel_get_addr_if_possible_mock);
368 MOCK(circuit_establish_circuit_conflux,
369 circuit_establish_circuit_conflux_mock);
370 MOCK(circuit_package_relay_cell,
371 circuit_package_relay_cell_mock);
372 MOCK(circuit_mark_for_close_,
373 circuit_mark_for_close_mock);
374 MOCK(monotime_absolute_usec, mock_monotime_absolute_usec);
375 testing_enable_reproducible_rng();
377 monotime_init();
378 monotime_enable_test_mocking();
379 actual_mocked_monotime_start = MONOTIME_MOCK_START;
380 monotime_set_mock_time_nsec(actual_mocked_monotime_start);
381 monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start);
382 curr_mocked_time = actual_mocked_monotime_start;
384 client_circs = smartlist_new();
385 exit_circs = smartlist_new();
386 circ_pairs = smartlist_new();
387 mock_cell_delivery = smartlist_new();
388 dummy_channel.cmux = circuitmux_alloc();
390 get_circuit_build_times_mutable()->timeout_ms = 1000;
392 congestion_control_set_cc_enabled();
393 max_unlinked_leg_retry = UINT32_MAX;
396 static void
397 test_clear_circs(void)
399 conflux_notify_shutdown();
400 SMARTLIST_FOREACH(circ_pairs, circ_pair_t *, circ_pair, {
401 tor_free(circ_pair);
403 SMARTLIST_FOREACH(client_circs, circuit_t *, client_side, {
404 conflux_circuit_about_to_free(client_side);
405 circuit_free(client_side);
407 SMARTLIST_FOREACH(exit_circs, or_circuit_t *, relay_side, {
408 free_fake_orcirc(relay_side);
411 smartlist_clear(circ_pairs);
412 smartlist_clear(client_circs);
413 smartlist_clear(exit_circs);
415 if (client_streams) {
416 // Free each edge connection
417 SMARTLIST_FOREACH(client_streams, edge_connection_t *, edge_conn, {
418 connection_free_minimal(TO_CONN(edge_conn));
420 smartlist_free(client_streams);
423 if (exit_streams) {
424 // Free each edge connection
425 SMARTLIST_FOREACH(exit_streams, edge_connection_t *, edge_conn, {
426 connection_free_minimal(TO_CONN(edge_conn));
428 smartlist_free(exit_streams);
431 tor_assert(smartlist_len(mock_cell_delivery) == 0);
433 (void)free_fake_origin_circuit;
435 /* Clear shutdown flag so we can resume testing again. */
436 conflux_clear_shutdown();
439 static void
440 test_teardown(void)
442 conflux_pool_free_all();
443 smartlist_free(client_circs);
444 smartlist_free(exit_circs);
445 smartlist_free(mock_cell_delivery);
446 circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
447 circuitmux_free(dummy_channel.cmux);
448 testing_disable_reproducible_rng();
451 /* Test linking a conflux circuit */
452 static void
453 test_conflux_link(void *arg)
455 (void) arg;
456 test_setup();
458 launch_new_set(2);
460 // For each circuit in the client_circs list, we need to create an
461 // exit side circuit and simulate two extends
462 SMARTLIST_FOREACH(client_circs, circuit_t *, client_side, {
463 simulate_circuit_build(client_side);
465 /* Handle network activity*/
466 while (smartlist_len(mock_cell_delivery) > 0) {
467 process_mock_cell_delivery();
471 tt_int_op(smartlist_len(client_circs), OP_EQ, 2);
472 tt_int_op(smartlist_len(exit_circs), OP_EQ, 2);
474 // Test that the cells have all been delivered
475 tt_int_op(smartlist_len(mock_cell_delivery), OP_EQ, 0);
477 // Test that the client side circuits are linked
478 conflux_t *cfx = ((circuit_t*)smartlist_get(client_circs, 0))->conflux;
479 SMARTLIST_FOREACH_BEGIN(client_circs, circuit_t *, client_side) {
480 tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_CONFLUX_LINKED);
481 tt_ptr_op(client_side->conflux, OP_EQ, cfx);
482 tt_ptr_op(client_side->conflux_pending_nonce, OP_EQ, NULL);
483 } SMARTLIST_FOREACH_END(client_side);
485 // Test circuit teardown
486 SMARTLIST_FOREACH_BEGIN(client_circs, circuit_t *, client_side) {
487 circuit_mark_for_close(client_side, END_CIRC_REASON_FINISHED);
488 } SMARTLIST_FOREACH_END(client_side);
490 done:
491 test_clear_circs();
492 test_teardown();
495 static void
496 simulate_circuit_build(circuit_t *client_circ)
498 // Create a relay circuit, and simulate the extend and open
499 circuit_t *relay_side = NULL;
501 relay_side = (circuit_t*)new_fake_orcirc(&dummy_channel, &dummy_channel);
502 relay_side->purpose = CIRCUIT_PURPOSE_OR;
503 relay_side->n_chan = NULL; // No next hop
504 relay_side->ccontrol = tor_malloc_zero(sizeof(congestion_control_t));
505 relay_side->ccontrol->sendme_pending_timestamps = smartlist_new();
506 relay_side->ccontrol->sendme_inc = 31;
507 smartlist_add(exit_circs, relay_side);
508 simulate_circuit_built(client_circ, relay_side);
509 conflux_circuit_has_opened(TO_ORIGIN_CIRCUIT(client_circ));
512 static circuit_t *
513 simulate_close_retry(circuit_t *close, bool manual_launch)
515 // Find the dest pair for the circuit in the circ pair list,
516 // and close it too
517 circuit_t *dest = NULL;
518 uint8_t *nonce = NULL;
520 if (manual_launch) {
521 nonce = tor_memdup(close->conflux->nonce, DIGEST256_LEN);
524 SMARTLIST_FOREACH_BEGIN(circ_pairs, circ_pair_t *, pair) {
525 if (pair->client == close) {
526 dest = pair->exit;
527 SMARTLIST_DEL_CURRENT_KEEPORDER(circ_pairs, pair);
528 tor_free(pair);
529 } else if (pair->exit == close) {
530 // This function should not be called on the exit side..
531 tor_assert(0);
533 } SMARTLIST_FOREACH_END(pair);
535 tor_assert(dest);
536 log_info(LD_CIRC, "Simulating close of %p->%p, dest %p->%p",
537 close, close->conflux, dest, dest->conflux);
539 // Free all pending cells related to this close in mock_cell_delivery
540 SMARTLIST_FOREACH(mock_cell_delivery, cell_delivery_t *, cd, {
541 if (cd->circ == close || cd->circ == dest) {
542 SMARTLIST_DEL_CURRENT_KEEPORDER(mock_cell_delivery, cd);
543 tor_free(cd->cell);
544 tor_free(cd);
548 // When a circuit closes, both ends get notification,
549 // and the client will launch a new circuit. We need to find
550 // that circuit at the end of the list, and then simulate
551 // building it, and creating a relay circuit for it.
552 conflux_circuit_has_closed(close);
553 conflux_circuit_has_closed(dest);
555 //tor_assert(digest256map_size(get_unlinked_pool(true)) != 0);
557 // Find these legs in our circuit lists, and free them
558 tor_assert(CIRCUIT_IS_ORIGIN(close));
559 tor_assert(!CIRCUIT_IS_ORIGIN(dest));
560 SMARTLIST_FOREACH_BEGIN(client_circs, circuit_t *, client_side) {
561 if (client_side == close) {
562 SMARTLIST_DEL_CURRENT_KEEPORDER(client_circs, client_side);
563 conflux_circuit_about_to_free(client_side);
564 circuit_free(client_side);
566 } SMARTLIST_FOREACH_END(client_side);
567 SMARTLIST_FOREACH_BEGIN(exit_circs, or_circuit_t *, exit_side) {
568 if (exit_side == (or_circuit_t *)dest) {
569 SMARTLIST_DEL_CURRENT_KEEPORDER(exit_circs, exit_side);
570 free_fake_orcirc(exit_side);
572 } SMARTLIST_FOREACH_END(exit_side);
574 if (manual_launch) {
575 // Launch a new leg for this nonce
576 tor_assert(nonce);
577 conflux_launch_leg(nonce);
578 tor_free(nonce);
581 if (smartlist_len(client_circs) == 0) {
582 // No new circuit was launched
583 return NULL;
586 // At this point, a new circuit will have launched on the client
587 // list. Get that circuit from the end of the list and return it
588 circuit_t * circ = smartlist_get(client_circs,
589 smartlist_len(client_circs) - 1);
591 //tor_assert(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_UNLINKED);
593 return circ;
596 static void
597 test_retry(void)
599 log_info(LD_CIRC, "==========NEW RUN ===========");
600 launch_new_set(2);
602 tt_int_op(smartlist_len(client_circs), OP_EQ, 2);
603 circuit_t *client1 = smartlist_get(client_circs, 0);
604 circuit_t *client2 = smartlist_get(client_circs, 1);
606 get_circuit_build_times_mutable()->timeout_ms = 1000;
608 // Dice roll on which leg builds first
609 if (crypto_rand_int(2) == 0) {
610 simulate_circuit_build(client1);
611 simulate_circuit_build(client2);
612 } else {
613 simulate_circuit_build(client2);
614 simulate_circuit_build(client1);
617 while (smartlist_len(mock_cell_delivery) > 0) {
618 tt_int_op(smartlist_len(client_circs), OP_EQ, 2);
619 tt_int_op(smartlist_len(exit_circs), OP_EQ, 2);
620 tt_int_op(smartlist_len(circ_pairs), OP_EQ, 2);
622 if (crypto_rand_int(2) == 0) {
623 if (crypto_rand_int(2) == 0) {
624 if (client1->purpose != CIRCUIT_PURPOSE_CONFLUX_LINKED) {
625 client1 = simulate_close_retry(client1, false);
626 simulate_circuit_build(client1);
628 } else {
629 if (client2->purpose != CIRCUIT_PURPOSE_CONFLUX_LINKED) {
630 client2 = simulate_close_retry(client2, false);
631 simulate_circuit_build(client2);
636 process_mock_cell_delivery();
639 // Test that the cells have all been delivered
640 tt_int_op(smartlist_len(mock_cell_delivery), OP_EQ, 0);
641 tt_int_op(smartlist_len(client_circs), OP_EQ, 2);
642 tt_int_op(smartlist_len(exit_circs), OP_EQ, 2);
643 tt_int_op(smartlist_len(circ_pairs), OP_EQ, 2);
645 conflux_t *cfx = ((circuit_t *)smartlist_get(client_circs, 0))->conflux;
646 SMARTLIST_FOREACH_BEGIN(client_circs, circuit_t *, client_side) {
647 tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_CONFLUX_LINKED);
648 tt_ptr_op(client_side->conflux, OP_EQ, cfx);
649 tt_ptr_op(client_side->conflux_pending_nonce, OP_EQ, NULL);
650 } SMARTLIST_FOREACH_END(client_side);
652 tt_int_op(digest256map_size(get_linked_pool(true)), OP_EQ, 1);
653 tt_int_op(digest256map_size(get_unlinked_pool(true)), OP_EQ, 0);
654 tt_int_op(digest256map_size(get_unlinked_pool(false)), OP_EQ, 0);
655 tt_int_op(digest256map_size(get_linked_pool(false)), OP_EQ, 1);
657 cfx = ((circuit_t *)smartlist_get(exit_circs, 0))->conflux;
658 SMARTLIST_FOREACH_BEGIN(exit_circs, circuit_t *, exit_side) {
659 tt_ptr_op(exit_side->conflux, OP_EQ, cfx);
660 tt_ptr_op(exit_side->conflux_pending_nonce, OP_EQ, NULL);
661 } SMARTLIST_FOREACH_END(exit_side);
663 // Test circuit teardown
664 SMARTLIST_FOREACH_BEGIN(client_circs, circuit_t *, client_side) {
665 tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_CONFLUX_LINKED);
666 circuit_mark_for_close(client_side, END_CIRC_REASON_FINISHED);
667 } SMARTLIST_FOREACH_END(client_side);
669 tt_int_op(digest256map_size(get_linked_pool(true)), OP_EQ, 0);
670 tt_int_op(digest256map_size(get_unlinked_pool(true)), OP_EQ, 0);
671 tt_int_op(digest256map_size(get_unlinked_pool(false)), OP_EQ, 0);
672 tt_int_op(digest256map_size(get_linked_pool(false)), OP_EQ, 0);
674 test_clear_circs();
676 done:
677 return;
680 /* Test linking a conflux circuit with build failures */
681 static void
682 test_conflux_link_retry(void *arg)
684 (void) arg;
685 test_setup();
687 for (int i = 0; i < 500; i++) {
688 test_retry();
691 test_teardown();
694 #if 0
695 /* Test closing both circuits in the set before the link handshake completes
696 * on either leg, by closing circuits before process_mock_cell_delivery.
698 * XXX: This test currently fails because conflux keeps relaunching closed
699 * circuits. We need to set a limit on the number of times we relaunch a
700 * circuit before we can fix this test.
702 static void
703 test_conflux_link_fail(void *arg)
705 (void) arg;
706 test_setup();
708 launch_new_set(2);
710 tt_int_op(smartlist_len(client_circs), OP_EQ, 2);
711 circuit_t *client1 = smartlist_get(client_circs, 0);
712 circuit_t *client2 = smartlist_get(client_circs, 1);
714 get_circuit_build_times_mutable()->timeout_ms = 1000;
716 // Close both circuits before the link handshake completes
717 conflux_circuit_has_closed(client1);
718 conflux_circuit_has_closed(client2);
720 tt_int_op(digest256map_size(get_linked_pool(true)), OP_EQ, 0);
721 tt_int_op(digest256map_size(get_unlinked_pool(true)), OP_EQ, 0);
722 tt_int_op(digest256map_size(get_unlinked_pool(false)), OP_EQ, 0);
723 tt_int_op(digest256map_size(get_linked_pool(false)), OP_EQ, 0);
724 done:
725 test_clear_circs();
726 test_teardown();
728 #endif
730 // - Relink test:
731 // - More than 2 legs
732 // - Close one linked leg; relink
733 // - Test mismatching sequence numbers for link and data
734 // - This should destroy the whole set
735 // - RTT timeout relinking test
736 // - Three circuits; close 1; retry and link
737 static void
738 test_conflux_link_relink(void *arg)
740 (void) arg;
741 test_setup();
743 launch_new_set(3);
745 tt_int_op(smartlist_len(client_circs), OP_EQ, 3);
746 circuit_t *client1 = smartlist_get(client_circs, 0);
747 circuit_t *client2 = smartlist_get(client_circs, 1);
748 circuit_t *client3 = smartlist_get(client_circs, 2);
750 get_circuit_build_times_mutable()->timeout_ms = 1000;
752 simulate_circuit_build(client1);
753 simulate_circuit_build(client2);
754 simulate_circuit_build(client3);
756 while (smartlist_len(mock_cell_delivery) > 0) {
757 tt_int_op(smartlist_len(client_circs), OP_EQ, 3);
758 tt_int_op(smartlist_len(exit_circs), OP_EQ, 3);
759 tt_int_op(smartlist_len(circ_pairs), OP_EQ, 3);
761 process_mock_cell_delivery();
764 // Now test closing and relinking the third leg
765 client3 = simulate_close_retry(client3, true);
766 simulate_circuit_build(client3);
767 while (smartlist_len(mock_cell_delivery) > 0) {
768 tt_int_op(smartlist_len(client_circs), OP_EQ, 3);
769 tt_int_op(smartlist_len(exit_circs), OP_EQ, 3);
770 tt_int_op(smartlist_len(circ_pairs), OP_EQ, 3);
772 process_mock_cell_delivery();
775 tt_int_op(digest256map_size(get_linked_pool(true)), OP_EQ, 1);
776 tt_int_op(digest256map_size(get_unlinked_pool(true)), OP_EQ, 0);
777 tt_int_op(digest256map_size(get_unlinked_pool(false)), OP_EQ, 0);
778 tt_int_op(digest256map_size(get_linked_pool(false)), OP_EQ, 1);
780 // Now test closing all circuits and verify the conflux object is gone
781 simulate_close_retry(client1, false);
782 simulate_close_retry(client2, false);
783 simulate_close_retry(client3, false);
785 tt_int_op(digest256map_size(get_linked_pool(true)), OP_EQ, 0);
786 tt_int_op(digest256map_size(get_unlinked_pool(true)), OP_EQ, 0);
787 tt_int_op(digest256map_size(get_unlinked_pool(false)), OP_EQ, 0);
788 tt_int_op(digest256map_size(get_linked_pool(false)), OP_EQ, 0);
790 done:
791 test_clear_circs();
792 test_teardown();
795 #if 0
796 static void
797 test_conflux_close(void *arg)
799 (void) arg;
800 test_setup();
802 launch_new_set(2);
804 tt_int_op(smartlist_len(client_circs), OP_EQ, 2);
805 circuit_t *client1 = smartlist_get(client_circs, 0);
806 circuit_t *client2 = smartlist_get(client_circs, 1);
808 get_circuit_build_times_mutable()->timeout_ms = 1000;
810 simulate_circuit_build(client1);
811 simulate_circuit_build(client2);
813 while (smartlist_len(mock_cell_delivery) > 0) {
814 tt_int_op(smartlist_len(client_circs), OP_EQ, 2);
815 tt_int_op(smartlist_len(exit_circs), OP_EQ, 2);
816 tt_int_op(smartlist_len(circ_pairs), OP_EQ, 2);
818 process_mock_cell_delivery();
821 // There are actually 3 kinds of close: mark, mark+free,
822 // and purpose change. We need to test these in link_retry, but
823 // here our focus is on after the set is linked.
825 // Additionally, we can close on an unlinked leg, or a non-critical linked
826 // leg, or a critical linked leg that causes teardown
827 // And we can close on linked legs when there are unlinked legs, or not.
829 // And we can do this at the client, or the exit.
830 // And we can do this with a circuit that has streams, or not.
832 tt_int_op(digest256map_size(get_linked_pool(true)), OP_EQ, 0);
833 tt_int_op(digest256map_size(get_unlinked_pool(true)), OP_EQ, 0);
834 tt_int_op(digest256map_size(get_unlinked_pool(false)), OP_EQ, 0);
835 tt_int_op(digest256map_size(get_linked_pool(false)), OP_EQ, 0);
836 done:
837 test_clear_circs();
838 test_teardown();
840 #endif
842 // Test launching a new set and closing the first leg, but
843 // with mismatched sequence numbers (missing data)
844 // - Test this teardown with only linked circs, and with some
845 // unlinked circs
846 // Test mismatching sequence numbers for link and data:
847 // Test missing sent data from client (link cell mismatch):
848 // Test missing sent data from relay (linked cell mismatch):
850 static circuit_t *
851 get_exit_circ(circuit_t *client_circ)
853 circuit_t *exit_circ = NULL;
854 SMARTLIST_FOREACH_BEGIN(circ_pairs, circ_pair_t *, pair) {
855 if (pair->client == client_circ) {
856 exit_circ = pair->exit;
857 break;
859 } SMARTLIST_FOREACH_END(pair);
860 tor_assert(exit_circ);
861 return exit_circ;
864 static circuit_t *
865 get_client_circ(circuit_t *exit_circ)
867 circuit_t *client_circ = NULL;
868 SMARTLIST_FOREACH_BEGIN(circ_pairs, circ_pair_t *, pair) {
869 if (pair->exit == exit_circ) {
870 client_circ = pair->client;
871 break;
873 } SMARTLIST_FOREACH_END(pair);
874 tor_assert(client_circ);
875 return client_circ;
878 static edge_connection_t *
879 new_client_stream(origin_circuit_t *on_circ)
881 edge_connection_t *stream = edge_connection_new(CONN_TYPE_EXIT, AF_INET);
883 stream->stream_id = get_unique_stream_id_by_circ(on_circ);
884 stream->on_circuit = TO_CIRCUIT(on_circ);
885 stream->cpath_layer = on_circ->cpath->prev;
887 stream->next_stream = on_circ->p_streams;
888 on_circ->p_streams = stream;
889 conflux_update_p_streams(on_circ, stream);
891 smartlist_add(client_streams, stream);
893 return stream;
896 static edge_connection_t *
897 new_exit_stream(circuit_t *on_circ, streamid_t stream_id)
899 edge_connection_t *stream = edge_connection_new(CONN_TYPE_EXIT, AF_INET);
901 stream->stream_id = stream_id;
902 stream->on_circuit = on_circ;
904 stream->next_stream = TO_OR_CIRCUIT(on_circ)->n_streams;
905 conflux_update_n_streams(TO_OR_CIRCUIT(on_circ), stream);
907 smartlist_add(exit_streams, stream);
909 return stream;
912 static void
913 validate_stream_counts(circuit_t *circ, int expected)
915 int count = 0;
917 conflux_validate_stream_lists(circ->conflux);
919 if (CIRCUIT_IS_ORIGIN(circ)) {
920 origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
921 tor_assert_nonfatal(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED);
922 /* Iterate over stream list using next_stream pointer, until null */
923 for (edge_connection_t *stream = ocirc->p_streams; stream;
924 stream = stream->next_stream) {
925 count++;
927 } else {
928 or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
929 /* Iterate over stream list using next_stream pointer, until null */
930 for (edge_connection_t *stream = orcirc->n_streams; stream;
931 stream = stream->next_stream) {
932 count++;
935 tt_int_op(count, OP_EQ, expected);
937 done:
938 return;
941 // - Streams test
942 // - Attach streams
943 // - Fail one leg, free it, attach new leg, new stream
944 // - Fail both legs
945 // - Shutdown
946 // - With streams attached
947 static void
948 test_conflux_link_streams(void *arg)
950 (void) arg;
951 test_setup();
953 launch_new_set(2);
955 client_streams = smartlist_new();
956 exit_streams = smartlist_new();
958 tt_int_op(smartlist_len(client_circs), OP_EQ, 2);
959 circuit_t *client1 = smartlist_get(client_circs, 0);
960 circuit_t *client2 = smartlist_get(client_circs, 1);
962 get_circuit_build_times_mutable()->timeout_ms = 1000;
964 simulate_circuit_build(client1);
965 simulate_circuit_build(client2);
967 while (smartlist_len(mock_cell_delivery) > 0) {
968 tt_int_op(smartlist_len(client_circs), OP_EQ, 2);
969 tt_int_op(smartlist_len(exit_circs), OP_EQ, 2);
970 tt_int_op(smartlist_len(circ_pairs), OP_EQ, 2);
972 process_mock_cell_delivery();
975 // Attach a stream to the client1 circuit
976 new_client_stream(TO_ORIGIN_CIRCUIT(client1));
977 new_client_stream(TO_ORIGIN_CIRCUIT(client2));
978 new_client_stream(TO_ORIGIN_CIRCUIT(client1));
979 new_exit_stream(get_exit_circ(client2), 1);
980 new_exit_stream(get_exit_circ(client1), 1);
981 new_exit_stream(get_exit_circ(client1), 1);
983 // Test that we can close the first leg, and attach a new one
984 // with a new stream
985 client1 = simulate_close_retry(client1, true);
986 simulate_circuit_build(client1);
988 while (smartlist_len(mock_cell_delivery) > 0) {
989 tt_int_op(smartlist_len(client_circs), OP_EQ, 2);
990 tt_int_op(smartlist_len(exit_circs), OP_EQ, 2);
991 tt_int_op(smartlist_len(circ_pairs), OP_EQ, 2);
993 process_mock_cell_delivery();
996 tt_ptr_op(client1->conflux, OP_EQ, client2->conflux);
998 new_client_stream(TO_ORIGIN_CIRCUIT(client1));
999 new_exit_stream(get_exit_circ(client2), 1);
1001 // Use Ensure that there are four streams on each circuit
1002 validate_stream_counts(client1, 4);
1003 validate_stream_counts(client2, 4);
1004 validate_stream_counts(get_exit_circ(client1), 4);
1005 validate_stream_counts(get_exit_circ(client2), 4);
1007 // Test that we can close all streams on either circuit,
1008 // in any order
1009 circuit_detach_stream(get_exit_circ(client1),
1010 TO_OR_CIRCUIT(get_exit_circ(client1))->n_streams);
1011 validate_stream_counts(get_exit_circ(client2), 3);
1012 circuit_detach_stream(get_exit_circ(client2),
1013 TO_OR_CIRCUIT(get_exit_circ(client2))->n_streams->next_stream);
1014 validate_stream_counts(get_exit_circ(client1), 2);
1015 circuit_detach_stream(get_exit_circ(client1),
1016 TO_OR_CIRCUIT(get_exit_circ(client1))->n_streams);
1017 validate_stream_counts(get_exit_circ(client1), 1);
1018 circuit_detach_stream(get_exit_circ(client1),
1019 TO_OR_CIRCUIT(get_exit_circ(client1))->n_streams);
1020 validate_stream_counts(get_exit_circ(client1), 0);
1022 circuit_detach_stream(client1,
1023 TO_ORIGIN_CIRCUIT(client1)->p_streams->next_stream->
1024 next_stream->next_stream);
1025 circuit_detach_stream(client2,
1026 TO_ORIGIN_CIRCUIT(client2)->p_streams);
1027 circuit_detach_stream(client2,
1028 TO_ORIGIN_CIRCUIT(client2)->p_streams->next_stream);
1029 circuit_detach_stream(client2,
1030 TO_ORIGIN_CIRCUIT(client2)->p_streams);
1031 validate_stream_counts(client1, 0);
1032 validate_stream_counts(client2, 0);
1034 done:
1035 test_clear_circs();
1036 test_teardown();
1039 // Right now this does not involve congestion control.. But it could,
1040 // if we actually build and send real RELAY_DATA cells (and also handle them
1041 // and SENDME cells in the mocked cell delivery)
1042 static void
1043 send_fake_cell(circuit_t *client_circ)
1045 circuit_t *exit_circ = get_exit_circ(client_circ);
1046 conflux_leg_t *exit_leg = conflux_get_leg(exit_circ->conflux,
1047 exit_circ);
1049 TO_ORIGIN_CIRCUIT(client_circ)->cpath->prev->ccontrol->inflight++;
1050 conflux_note_cell_sent(client_circ->conflux, client_circ,
1051 RELAY_COMMAND_DATA);
1053 exit_leg->last_seq_recv++;
1054 exit_circ->conflux->last_seq_delivered++;
1057 static circuit_t *
1058 send_until_switch(circuit_t *client_circ)
1060 conflux_leg_t *client_leg = conflux_get_leg(client_circ->conflux,
1061 client_circ);
1062 circuit_t *exit_circ = get_exit_circ(client_circ);
1063 conflux_leg_t *exit_leg = conflux_get_leg(exit_circ->conflux,
1064 exit_circ);
1065 circuit_t *next_circ = client_circ;
1066 int i = 0;
1068 // XXX: This is a hack so the tests pass using cc->sendme_inc
1069 // (There is another hack in circuit_ready_to_send() that causes
1070 // us to block early below, and return NULL for next_circ)
1071 TO_ORIGIN_CIRCUIT(client_circ)->cpath->prev->ccontrol->sendme_inc = 0;
1073 while (client_circ == next_circ) {
1074 next_circ = conflux_decide_circ_for_send(client_circ->conflux, client_circ,
1075 RELAY_COMMAND_DATA);
1076 tor_assert(next_circ);
1077 send_fake_cell(next_circ);
1078 i++;
1081 // XXX: This too:
1082 TO_ORIGIN_CIRCUIT(client_circ)->cpath->prev->ccontrol->sendme_inc = 31;
1084 log_info(LD_CIRC, "Sent %d cells on client circ", i-1);
1085 process_mock_cell_delivery();
1087 circuit_t *new_client =
1088 (circuit_t*)conflux_decide_next_circ(client_circ->conflux);
1089 tt_ptr_op(new_client, OP_NE, client_circ);
1090 conflux_leg_t *new_client_leg = conflux_get_leg(new_client->conflux,
1091 new_client);
1092 circuit_t *new_exit = get_exit_circ(new_client);
1093 conflux_leg_t *new_exit_leg = conflux_get_leg(new_exit->conflux,
1094 new_exit);
1096 // Verify sequence numbers make sense
1097 tt_int_op(new_client_leg->last_seq_sent, OP_EQ, client_leg->last_seq_sent+1);
1098 tt_int_op(new_client_leg->last_seq_recv, OP_EQ, client_leg->last_seq_recv);
1099 tt_int_op(exit_leg->last_seq_sent, OP_EQ, new_exit_leg->last_seq_sent);
1100 tt_int_op(exit_leg->last_seq_recv+1, OP_EQ, new_exit_leg->last_seq_recv);
1102 tt_int_op(client_leg->last_seq_sent+1, OP_EQ, new_exit_leg->last_seq_recv);
1103 tt_int_op(client_leg->last_seq_recv, OP_EQ, new_exit_leg->last_seq_sent);
1105 done:
1106 return new_client;
1110 * This tests switching as well as the UDP optimization that attaches
1111 * a third circuit and closes the slowest one. (This optimization is not
1112 * implemented in C-Tor but must be supported at exits, for arti).
1114 static void
1115 test_conflux_switch(void *arg)
1117 (void) arg;
1118 test_setup();
1119 DEFAULT_EXIT_UX = CONFLUX_UX_HIGH_THROUGHPUT;
1121 launch_new_set(2);
1123 tt_int_op(smartlist_len(client_circs), OP_EQ, 2);
1124 circuit_t *client1 = smartlist_get(client_circs, 0);
1125 circuit_t *client2 = smartlist_get(client_circs, 1);
1126 get_circuit_build_times_mutable()->timeout_ms = 1000;
1128 simulate_circuit_build(client1);
1129 simulate_circuit_build(client2);
1131 circuit_t *exit1 = get_exit_circ(client1);
1132 circuit_t *exit2 = get_exit_circ(client2);
1133 circuit_t *next_circ = client1;
1135 while (smartlist_len(mock_cell_delivery) > 0) {
1136 tt_int_op(smartlist_len(client_circs), OP_EQ, 2);
1137 tt_int_op(smartlist_len(exit_circs), OP_EQ, 2);
1138 tt_int_op(smartlist_len(circ_pairs), OP_EQ, 2);
1140 process_mock_cell_delivery();
1143 // Check to make sure everything is linked`up
1144 tt_ptr_op(client1->conflux, OP_EQ, client2->conflux);
1145 tt_ptr_op(exit1->conflux, OP_EQ, exit2->conflux);
1146 tt_ptr_op(client1->conflux, OP_NE, NULL);
1147 tt_ptr_op(exit1->conflux, OP_NE, NULL);
1148 tt_int_op(smartlist_len(client1->conflux->legs), OP_EQ, 2);
1149 tt_int_op(smartlist_len(exit1->conflux->legs), OP_EQ, 2);
1150 tt_int_op(client1->purpose, OP_EQ, CIRCUIT_PURPOSE_CONFLUX_LINKED);
1151 tt_int_op(client2->purpose, OP_EQ, CIRCUIT_PURPOSE_CONFLUX_LINKED);
1153 tt_int_op(digest256map_size(get_linked_pool(true)), OP_EQ, 1);
1154 tt_int_op(digest256map_size(get_unlinked_pool(true)), OP_EQ, 0);
1155 tt_int_op(digest256map_size(get_unlinked_pool(false)), OP_EQ, 0);
1156 tt_int_op(digest256map_size(get_linked_pool(false)), OP_EQ, 1);
1157 tt_ptr_op(get_exit_circ(client1), OP_EQ, exit1);
1158 tt_ptr_op(get_exit_circ(client2), OP_EQ, exit2);
1160 // Give circuits approximately equal RTT:
1161 conflux_update_rtt(client1->conflux, client1, 100);
1162 conflux_update_rtt(client2->conflux, client2, 125);
1164 client1->conflux->params.alg = CONFLUX_ALG_LOWRTT;
1165 get_exit_circ(client1)->conflux->params.alg = CONFLUX_ALG_LOWRTT;
1166 TO_ORIGIN_CIRCUIT(client1)->cpath->prev->ccontrol->cwnd = 300;
1167 TO_ORIGIN_CIRCUIT(client2)->cpath->prev->ccontrol->cwnd = 300;
1169 // Keep sending fake cells until we decide to switch four times
1170 for (int i = 0; i < 4; i++) {
1171 next_circ = send_until_switch(next_circ);
1173 // XXX: This can't be set to 0 or we will decide we can switch immediately,
1174 // because the client1 has a lower RTT
1175 TO_ORIGIN_CIRCUIT(client1)->cpath->prev->ccontrol->inflight = 1;
1177 // Check to make sure everything is linked`up
1178 tt_ptr_op(client1->conflux, OP_EQ, client2->conflux);
1179 tt_ptr_op(exit1->conflux, OP_EQ, exit2->conflux);
1180 tt_ptr_op(client1->conflux, OP_NE, NULL);
1181 tt_ptr_op(exit1->conflux, OP_NE, NULL);
1182 tt_int_op(smartlist_len(client1->conflux->legs), OP_EQ, 2);
1183 tt_int_op(smartlist_len(exit1->conflux->legs), OP_EQ, 2);
1184 tt_int_op(client1->purpose, OP_EQ, CIRCUIT_PURPOSE_CONFLUX_LINKED);
1185 tt_int_op(client2->purpose, OP_EQ, CIRCUIT_PURPOSE_CONFLUX_LINKED);
1187 tt_int_op(digest256map_size(get_linked_pool(true)), OP_EQ, 1);
1188 tt_int_op(digest256map_size(get_unlinked_pool(true)), OP_EQ, 0);
1189 tt_int_op(digest256map_size(get_unlinked_pool(false)), OP_EQ, 0);
1190 tt_int_op(digest256map_size(get_linked_pool(false)), OP_EQ, 1);
1192 tt_ptr_op(get_exit_circ(client1), OP_EQ, exit1);
1193 tt_ptr_op(get_exit_circ(client2), OP_EQ, exit2);
1194 tt_ptr_op(next_circ, OP_EQ, client2);
1196 next_circ = send_until_switch(next_circ);
1198 // Check to make sure everything is linked`up
1199 tt_ptr_op(client1->conflux, OP_EQ, client2->conflux);
1200 tt_ptr_op(exit1->conflux, OP_EQ, exit2->conflux);
1201 tt_ptr_op(client1->conflux, OP_NE, NULL);
1202 tt_ptr_op(exit1->conflux, OP_NE, NULL);
1203 tt_int_op(smartlist_len(client1->conflux->legs), OP_EQ, 2);
1204 tt_int_op(smartlist_len(exit1->conflux->legs), OP_EQ, 2);
1205 tt_int_op(client1->purpose, OP_EQ, CIRCUIT_PURPOSE_CONFLUX_LINKED);
1206 tt_int_op(client2->purpose, OP_EQ, CIRCUIT_PURPOSE_CONFLUX_LINKED);
1208 tt_int_op(digest256map_size(get_linked_pool(true)), OP_EQ, 1);
1209 tt_int_op(digest256map_size(get_unlinked_pool(true)), OP_EQ, 0);
1210 tt_int_op(digest256map_size(get_unlinked_pool(false)), OP_EQ, 0);
1211 tt_int_op(digest256map_size(get_linked_pool(false)), OP_EQ, 1);
1213 tt_ptr_op(get_exit_circ(client1), OP_EQ, exit1);
1214 tt_ptr_op(get_exit_circ(client2), OP_EQ, exit2);
1215 tt_ptr_op(next_circ, OP_EQ, client1);
1217 TO_ORIGIN_CIRCUIT(client2)->cpath->prev->ccontrol->inflight = 0;
1220 // Try the UDP minRTT reconnect optimization a few times
1221 for (int i = 0; i < 500; i++) {
1222 tt_int_op(smartlist_len(client_circs), OP_EQ, 2);
1223 client1 = smartlist_get(client_circs, 0);
1224 client2 = smartlist_get(client_circs, 1);
1225 exit1 = get_exit_circ(client1);
1226 exit2 = get_exit_circ(client2);
1228 // Attach a third leg
1229 conflux_launch_leg(client1->conflux->nonce);
1231 // It should be added to the end of the local test list
1232 circuit_t *client3 = smartlist_get(client_circs,
1233 smartlist_len(client_circs)-1);
1234 simulate_circuit_build(client3);
1236 while (smartlist_len(mock_cell_delivery) > 0) {
1237 tt_int_op(smartlist_len(client_circs), OP_EQ, 3);
1238 tt_int_op(smartlist_len(exit_circs), OP_EQ, 3);
1239 tt_int_op(smartlist_len(circ_pairs), OP_EQ, 3);
1241 process_mock_cell_delivery();
1244 circuit_t *exit3 = get_exit_circ(client3);
1246 // Check to make sure everything is linked`up
1247 tt_ptr_op(client3->conflux, OP_EQ, client2->conflux);
1248 tt_ptr_op(exit3->conflux, OP_EQ, exit2->conflux);
1249 tt_ptr_op(client3->conflux, OP_NE, NULL);
1250 tt_ptr_op(exit3->conflux, OP_NE, NULL);
1251 tt_int_op(smartlist_len(client1->conflux->legs), OP_EQ, 3);
1252 tt_int_op(smartlist_len(exit1->conflux->legs), OP_EQ, 3);
1253 tt_int_op(client3->purpose, OP_EQ, CIRCUIT_PURPOSE_CONFLUX_LINKED);
1255 tt_int_op(digest256map_size(get_linked_pool(true)), OP_EQ, 1);
1256 tt_int_op(digest256map_size(get_unlinked_pool(true)), OP_EQ, 0);
1257 tt_int_op(digest256map_size(get_unlinked_pool(false)), OP_EQ, 0);
1258 tt_int_op(digest256map_size(get_linked_pool(false)), OP_EQ, 1);
1260 conflux_update_rtt(client3->conflux, client3,
1261 crypto_rand_int_range(90, 200));
1262 TO_ORIGIN_CIRCUIT(client3)->cpath->prev->ccontrol->cwnd = 300;
1264 circuit_t *circ_close = NULL;
1265 uint64_t max_rtt = 0;
1266 // Pick the leg with the highest RTT and close it
1267 tor_assert(client3);
1268 tor_assert(client3->conflux);
1269 tor_assert(client3->conflux->legs);
1270 CONFLUX_FOR_EACH_LEG_BEGIN(client3->conflux, leg) {
1271 if (client3->conflux->curr_leg == leg)
1272 continue;
1274 if (leg->circ_rtts_usec > max_rtt) {
1275 max_rtt = leg->circ_rtts_usec;
1276 circ_close = leg->circ;
1278 } CONFLUX_FOR_EACH_LEG_END(leg);
1280 // Let the second leg "send" all data and close it.
1281 tor_assert(circ_close);
1282 tor_assert(circ_close->conflux);
1283 tor_assert(circ_close->conflux->legs);
1284 CONFLUX_FOR_EACH_LEG_BEGIN(circ_close->conflux, leg) {
1285 TO_ORIGIN_CIRCUIT(leg->circ)->cpath->prev->ccontrol->inflight = 0;
1286 } CONFLUX_FOR_EACH_LEG_END(leg);
1288 // Close without manual launch (code will not relaunch for linked)
1289 simulate_close_retry(circ_close, false);
1291 tt_int_op(smartlist_len(mock_cell_delivery), OP_EQ, 0);
1292 tt_int_op(smartlist_len(client_circs), OP_EQ, 2);
1293 tt_int_op(smartlist_len(exit_circs), OP_EQ, 2);
1294 tt_int_op(smartlist_len(circ_pairs), OP_EQ, 2);
1296 // Send until we switch to the third leg
1297 next_circ = send_until_switch(next_circ);
1299 // Check to make sure everything is linked`up
1300 tt_ptr_op(next_circ->conflux, OP_NE, NULL);
1301 tt_int_op(smartlist_len(next_circ->conflux->legs), OP_EQ, 2);
1302 tt_int_op(next_circ->purpose, OP_EQ, CIRCUIT_PURPOSE_CONFLUX_LINKED);
1304 tt_int_op(digest256map_size(get_linked_pool(true)), OP_EQ, 1);
1305 tt_int_op(digest256map_size(get_unlinked_pool(true)), OP_EQ, 0);
1306 tt_int_op(digest256map_size(get_unlinked_pool(false)), OP_EQ, 0);
1307 tt_int_op(digest256map_size(get_linked_pool(false)), OP_EQ, 1);
1309 CONFLUX_FOR_EACH_LEG_BEGIN(next_circ->conflux, leg) {
1310 TO_ORIGIN_CIRCUIT(leg->circ)->cpath->prev->ccontrol->inflight = 0;
1311 } CONFLUX_FOR_EACH_LEG_END(leg);
1313 // send until we switch back to the first leg
1314 next_circ = send_until_switch(next_circ);
1316 // Check to make sure everything is linked`up
1317 tt_ptr_op(next_circ->conflux, OP_NE, NULL);
1318 tt_int_op(smartlist_len(next_circ->conflux->legs), OP_EQ, 2);
1319 tt_int_op(next_circ->purpose, OP_EQ, CIRCUIT_PURPOSE_CONFLUX_LINKED);
1321 tt_int_op(digest256map_size(get_linked_pool(true)), OP_EQ, 1);
1322 tt_int_op(digest256map_size(get_unlinked_pool(true)), OP_EQ, 0);
1323 tt_int_op(digest256map_size(get_unlinked_pool(false)), OP_EQ, 0);
1324 tt_int_op(digest256map_size(get_linked_pool(false)), OP_EQ, 1);
1327 done:
1328 test_clear_circs();
1329 test_teardown();
1330 return;
1333 struct testcase_t conflux_pool_tests[] = {
1334 { "link", test_conflux_link, TT_FORK, NULL, NULL },
1335 { "link_retry", test_conflux_link_retry, TT_FORK, NULL, NULL },
1336 { "link_relink", test_conflux_link_relink, TT_FORK, NULL, NULL },
1337 { "link_streams", test_conflux_link_streams, TT_FORK, NULL, NULL },
1338 { "switch", test_conflux_switch, TT_FORK, NULL, NULL },
1339 // XXX: These two currently fail, because they are not finished:
1340 //{ "link_fail", test_conflux_link_fail, TT_FORK, NULL, NULL },
1341 //{ "close", test_conflux_close, TT_FORK, NULL, NULL },
1342 END_OF_TESTCASES