1 /* Copyright (c) 2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
6 * \brief Conflux circuit pool management
9 #define TOR_CONFLUX_PRIVATE
10 #define CONFLUX_CELL_PRIVATE
12 #include "core/or/or.h"
14 #include "app/config/config.h"
16 #include "core/or/circuitbuild.h"
17 #include "core/or/circuitlist.h"
18 #include "core/or/circuitstats.h"
19 #include "core/or/circuituse.h"
20 #include "core/or/congestion_control_st.h"
21 #include "core/or/conflux.h"
22 #include "core/or/conflux_cell.h"
23 #include "trunnel/conflux.h"
24 #include "core/or/conflux_params.h"
25 #include "core/or/conflux_pool.h"
26 #include "core/or/conflux_util.h"
27 #include "core/or/relay.h"
28 #include "core/or/connection_edge.h"
29 #include "core/or/edge_connection_st.h"
31 #include "core/or/crypt_path_st.h"
32 #include "core/or/or_circuit_st.h"
33 #include "core/or/origin_circuit_st.h"
34 #include "core/or/extend_info_st.h"
35 #include "core/or/conflux_st.h"
37 #include "feature/nodelist/nodelist.h"
38 #include "feature/client/bridges.h"
39 #include "app/config/config.h"
41 #include "lib/crypt_ops/crypto_rand.h"
42 #include "lib/crypt_ops/crypto_util.h"
44 /* Indicate if we are shutting down. This is used so we avoid recovering a
45 * conflux set on total shutdown. */
46 static bool shutting_down
= false;
48 /** The pool of client-side conflux_t that are built, linked, and ready
49 * to be used. Indexed by nonce. */
50 static digest256map_t
*client_linked_pool
;
52 /** The pool of origin unlinked_circuits_t indexed by nonce. */
53 static digest256map_t
*client_unlinked_pool
;
55 /** The pool of relay conflux_t indexed by nonce. We call these "server"
56 * because they could be onion-service side too (even though we likely will
57 * only implement onion service conflux in Arti). The code is littered with
58 * asserts to ensure there are no origin circuits in here for now, too. */
59 static digest256map_t
*server_linked_pool
;
61 /** The pool of relay unlinked_circuits_t indexed by nonce. */
62 static digest256map_t
*server_unlinked_pool
;
64 /* A leg is essentially a circuit for a conflux set. We use this object for the
66 typedef struct leg_t
{
67 /* The circuit of the leg. */
70 /* The LINK cell content which is used to put the information back in the
71 * conflux_t object once all legs have linked and validate the ack. */
72 conflux_cell_link_t
*link
;
74 /* Indicate if the leg has received the LINKED or the LINKED_ACK cell
75 * depending on its side of the circuit. When all legs are linked, we then
76 * finalize the conflux_t object and move it to the linked pool. */
79 /* What time did we send the LINK/LINKED (depending on which side) so we can
80 * calculate the RTT. */
81 uint64_t link_sent_usec
;
83 /* The RTT value in usec takend from the LINK <--> LINKED round trip. */
87 /* Object used to track unlinked circuits which are kept in the unlinked pool
88 * until they are linked and moved to the linked pool and global circuit set.
90 typedef struct unlinked_circuits_t
{
91 /* If true, indicate that this unlinked set is client side as in the legs are
92 * origin circuits. Else, it is on the exit side and thus or circuits. */
95 /* If true, indicate if the conflux_t is related to a linked set. */
96 bool is_for_linked_set
;
98 /* Conflux object that will be set in each leg once all linked. */
103 } unlinked_circuits_t
;
105 /** Error code used when linking circuits. Based on those, we decide to
106 * relaunch or not. */
107 typedef enum link_circ_err_t
{
108 /* Linking was successful. */
109 ERR_LINK_CIRC_OK
= 0,
110 /* The RTT was not acceptable. */
111 ERR_LINK_CIRC_BAD_RTT
= 1,
112 /* The leg can't be found. */
113 ERR_LINK_CIRC_MISSING_LEG
= 2,
114 /* The set can't be found. */
115 ERR_LINK_CIRC_MISSING_SET
= 3,
116 /* Invalid leg as in not pass validation. */
117 ERR_LINK_CIRC_INVALID_LEG
= 4,
120 #ifdef TOR_UNIT_TESTS
122 get_unlinked_pool(bool is_client
)
124 return is_client
? client_unlinked_pool
: server_unlinked_pool
;
128 get_linked_pool(bool is_client
)
130 return is_client
? client_linked_pool
: server_linked_pool
;
134 /* For unit tests only: please treat these exactly as the defines in the
136 STATIC
uint8_t DEFAULT_CLIENT_UX
= CONFLUX_UX_HIGH_THROUGHPUT
;
137 STATIC
uint8_t DEFAULT_EXIT_UX
= CONFLUX_UX_MIN_LATENCY
;
139 /** Helper: Format at 8 bytes the nonce for logging. */
140 static inline const char *
141 fmt_nonce(const uint8_t *nonce
)
143 return hex_str((char *) nonce
, 8);
147 * Return the conflux algorithm for a desired UX value.
150 conflux_choose_algorithm(uint8_t desired_ux
)
152 switch (desired_ux
) {
153 case CONFLUX_UX_NO_OPINION
:
154 return CONFLUX_ALG_LOWRTT
;
155 case CONFLUX_UX_MIN_LATENCY
:
156 return CONFLUX_ALG_MINRTT
;
157 case CONFLUX_UX_HIGH_THROUGHPUT
:
158 return CONFLUX_ALG_LOWRTT
;
159 /* For now, we have no low mem algs, so use minRTT since it should
160 * switch less and thus use less mem */
161 /* TODO-329-TUNING: Pick better algs here*/
162 case CONFLUX_UX_LOW_MEM_THROUGHPUT
:
163 case CONFLUX_UX_LOW_MEM_LATENCY
:
164 return CONFLUX_ALG_MINRTT
;
166 /* Trunnel should protect us from this */
167 tor_assert_nonfatal_unreached();
168 return CONFLUX_ALG_LOWRTT
;
172 /** Return a newly allocated conflux_t object. */
176 conflux_t
*cfx
= tor_malloc_zero(sizeof(*cfx
));
178 cfx
->ooo_q
= smartlist_new();
179 cfx
->legs
= smartlist_new();
185 conflux_free_(conflux_t
*cfx
)
190 tor_assert(cfx
->legs
);
191 tor_assert(cfx
->ooo_q
);
193 SMARTLIST_FOREACH_BEGIN(cfx
->legs
, conflux_leg_t
*, leg
) {
194 SMARTLIST_DEL_CURRENT(cfx
->legs
, leg
);
196 } SMARTLIST_FOREACH_END(leg
);
197 smartlist_free(cfx
->legs
);
199 SMARTLIST_FOREACH(cfx
->ooo_q
, conflux_cell_t
*, cell
, tor_free(cell
));
200 smartlist_free(cfx
->ooo_q
);
202 memwipe(cfx
->nonce
, 0, sizeof(cfx
->nonce
));
206 /** Wrapper for the free function, set the cfx pointer to NULL after free */
207 #define conflux_free(cfx) \
208 FREE_AND_NULL(conflux_t, conflux_free_, cfx)
210 /** Helper: Free function for the digest256map_free(). */
212 free_conflux_void_(void *ptr
)
214 conflux_t
*cfx
= (conflux_t
*)ptr
;
218 /** Return a newly allocated leg object containing the given circuit and link
219 * pointer (no copy). */
221 leg_new(circuit_t
*circ
, conflux_cell_link_t
*link
)
223 leg_t
*leg
= tor_malloc_zero(sizeof(*leg
));
229 /** Free the given leg object. Passing NULL is safe. */
237 tor_free(leg
->circ
->conflux_pending_nonce
);
238 leg
->circ
->conflux_pending_nonce
= NULL
;
244 /** Return a newly allocated unlinked set object for the given nonce. A new
245 * conflux object is also created. */
246 static unlinked_circuits_t
*
247 unlinked_new(const uint8_t *nonce
, bool is_client
)
249 unlinked_circuits_t
*unlinked
= tor_malloc_zero(sizeof(*unlinked
));
250 unlinked
->cfx
= conflux_new();
251 unlinked
->legs
= smartlist_new();
252 unlinked
->is_client
= is_client
;
253 memcpy(unlinked
->cfx
->nonce
, nonce
, sizeof(unlinked
->cfx
->nonce
));
258 /** Free the given unlinked object. */
260 unlinked_free(unlinked_circuits_t
*unlinked
)
265 tor_assert(unlinked
->legs
);
267 /* This cfx is pointing to a linked set. */
268 if (!unlinked
->is_for_linked_set
) {
269 conflux_free(unlinked
->cfx
);
271 SMARTLIST_FOREACH(unlinked
->legs
, leg_t
*, leg
, leg_free(leg
));
272 smartlist_free(unlinked
->legs
);
276 /** Add the given unlinked object to the unlinked pool. */
278 unlinked_pool_add(unlinked_circuits_t
*unlinked
, bool is_client
)
280 tor_assert(unlinked
);
282 digest256map_set(client_unlinked_pool
, unlinked
->cfx
->nonce
, unlinked
);
284 digest256map_set(server_unlinked_pool
, unlinked
->cfx
->nonce
, unlinked
);
288 /** Delete the given unlinked object from the unlinked pool. */
290 unlinked_pool_del(unlinked_circuits_t
*unlinked
, bool is_client
)
292 tor_assert(unlinked
);
295 digest256map_remove(client_unlinked_pool
, unlinked
->cfx
->nonce
);
297 digest256map_remove(server_unlinked_pool
, unlinked
->cfx
->nonce
);
301 /** Return an unlinked object for the given nonce else NULL. */
302 static unlinked_circuits_t
*
303 unlinked_pool_get(const uint8_t *nonce
, bool is_client
)
307 return digest256map_get(client_unlinked_pool
, nonce
);
309 return digest256map_get(server_unlinked_pool
, nonce
);
313 /** Delete from the pool and free the given unlinked object. */
315 unlinked_pool_del_and_free(unlinked_circuits_t
*unlinked
, bool is_client
)
317 tor_assert(unlinked
);
318 unlinked_pool_del(unlinked
, is_client
);
319 unlinked_free(unlinked
);
322 /** Add the given conflux object to the linked conflux set. */
324 linked_pool_add(conflux_t
*cfx
, bool is_client
)
328 digest256map_set(client_linked_pool
, cfx
->nonce
, cfx
);
330 digest256map_set(server_linked_pool
, cfx
->nonce
, cfx
);
334 /** Delete from the linked conflux set the given nonce. */
336 linked_pool_del(const uint8_t *nonce
, bool is_client
)
340 digest256map_remove(client_linked_pool
, nonce
);
342 digest256map_remove(server_linked_pool
, nonce
);
346 /** Return a conflux_t object for the given nonce from the linked set. */
348 linked_pool_get(const uint8_t *nonce
, bool is_client
)
352 return digest256map_get(client_linked_pool
, nonce
);
354 return digest256map_get(server_linked_pool
, nonce
);
358 /** Add the given leg to the given unlinked object. */
360 unlinked_leg_add(unlinked_circuits_t
*unlinked
, leg_t
*leg
)
362 tor_assert(unlinked
);
365 smartlist_add(unlinked
->legs
, leg
);
368 /** Return an unlinked leg for the given unlinked object and for the given
370 static inline leg_t
*
371 leg_find(const unlinked_circuits_t
*unlinked
, const circuit_t
*circ
)
373 SMARTLIST_FOREACH_BEGIN(unlinked
->legs
, leg_t
*, leg
) {
374 if (leg
->circ
== circ
) {
377 } SMARTLIST_FOREACH_END(leg
);
381 /** Return the given circuit leg from its unlinked set (if any). */
383 unlinked_leg_find(const circuit_t
*circ
, bool is_client
)
385 unlinked_circuits_t
*unlinked
=
386 unlinked_pool_get(circ
->conflux_pending_nonce
, is_client
);
390 return leg_find(unlinked
, circ
);
394 unlinked_leg_del_and_free(unlinked_circuits_t
*unlinked
,
395 const circuit_t
*circ
)
398 tor_assert(unlinked
);
400 SMARTLIST_FOREACH_BEGIN(unlinked
->legs
, leg_t
*, leg
) {
401 if (leg
->circ
== circ
) {
402 SMARTLIST_DEL_CURRENT(unlinked
->legs
, leg
);
406 } SMARTLIST_FOREACH_END(leg
);
410 * Ensure that the given circuit has no attached streams.
412 * This validation function is called at various stages for
413 * unlinked circuits, to make sure they have no streams.
416 validate_circ_has_no_streams(circuit_t
*circ
)
418 if (CIRCUIT_IS_ORIGIN(circ
)) {
419 origin_circuit_t
*ocirc
= TO_ORIGIN_CIRCUIT(circ
);
420 if (BUG(ocirc
->p_streams
)) {
422 "Unlinked Conflux circuit %u has attached streams.",
423 ocirc
->global_identifier
);
424 ocirc
->p_streams
= NULL
;
426 if (BUG(ocirc
->half_streams
)) {
428 "Unlinked conflux circ %u has half streams.",
429 ocirc
->global_identifier
);
430 ocirc
->half_streams
= NULL
;
433 or_circuit_t
*orcirc
= TO_OR_CIRCUIT(circ
);
434 if (BUG(orcirc
->n_streams
)) {
436 "Unlinked conflux circuit has attached streams.");
437 orcirc
->n_streams
= NULL
;
439 if (BUG(orcirc
->resolving_streams
)) {
441 "Unlinked conflux circuit has resolving streams.");
442 orcirc
->resolving_streams
= NULL
;
447 /** Return true iff the legs in the given unlinked set are valid and coherent
448 * to be a linked set. */
450 validate_unlinked_legs(unlinked_circuits_t
*unlinked
)
454 uint8_t *nonce
= NULL
;
456 tor_assert(unlinked
);
458 SMARTLIST_FOREACH_BEGIN(unlinked
->legs
, const leg_t
*, leg
) {
460 nonce
= leg
->link
->nonce
;
461 version
= leg
->link
->version
;
463 /* Version and nonce must match in all legs. */
464 valid
&= (leg
->link
->version
== version
&&
465 tor_memeq(leg
->link
->nonce
, nonce
, sizeof(leg
->link
->nonce
)));
468 // If the other ends last sent sequence number is higher than the
469 // last sequence number we delivered, we have data loss, and cannot link.
470 if (leg
->link
->last_seqno_sent
> unlinked
->cfx
->last_seq_delivered
) {
471 log_fn(unlinked
->is_client
? LOG_NOTICE
: LOG_PROTOCOL_WARN
, LD_CIRC
,
472 "Data loss detected while trying to add a conflux leg.");
475 // TODO-329-ARTI: Instead of closing the set here, we could
476 // immediately send a SWITCH cell and re-send the missing data.
477 // To do this, though, we would need to constantly buffer at least
478 // a cwnd worth of sent data to retransmit. We're not going to try
479 // this in C-Tor, but arti could consider it.
481 validate_circ_has_no_streams(leg
->circ
);
482 } SMARTLIST_FOREACH_END(leg
);
484 /* Note that if no legs, it validates. */
489 /** Add up a new leg to the given conflux object. */
491 cfx_add_leg(conflux_t
*cfx
, leg_t
*leg
)
495 tor_assert(leg
->link
);
497 /* Big trouble if we add a leg to the wrong set. */
498 tor_assert(tor_memeq(cfx
->nonce
, leg
->link
->nonce
, sizeof(cfx
->nonce
)));
500 conflux_leg_t
*cleg
= tor_malloc_zero(sizeof(*cleg
));
501 cleg
->circ
= leg
->circ
;
502 // TODO-329-ARTI: Blindly copying the values from the cell. Is this correct?
503 // I think no... When adding new legs, switching to this leg is
504 // likely to break, unless the sender tracks what link cell it sent..
505 // Is that the best option? Or should we use the max of our legs, here?
506 // (It seems the other side will have no idea what our current maxes
507 /// are, so this option seems better right now)
508 cleg
->last_seq_recv
= leg
->link
->last_seqno_sent
;
509 cleg
->last_seq_sent
= leg
->link
->last_seqno_recv
;
510 cleg
->circ_rtts_usec
= leg
->rtt_usec
;
511 cleg
->linked_sent_usec
= leg
->link_sent_usec
;
513 cfx
->params
.alg
= conflux_choose_algorithm(leg
->link
->desired_ux
);
515 /* Add leg to given conflux. */
516 smartlist_add(cfx
->legs
, cleg
);
518 /* Ensure the new circuit has no streams. */
519 validate_circ_has_no_streams(leg
->circ
);
521 /* If this is not the first leg, get the first leg, and get
522 * the reference streams from it. */
523 if (CONFLUX_NUM_LEGS(cfx
) > 0) {
524 conflux_leg_t
*first_leg
= smartlist_get(cfx
->legs
, 0);
525 if (CIRCUIT_IS_ORIGIN(first_leg
->circ
)) {
526 origin_circuit_t
*old_circ
= TO_ORIGIN_CIRCUIT(first_leg
->circ
);
527 origin_circuit_t
*new_circ
= TO_ORIGIN_CIRCUIT(leg
->circ
);
529 new_circ
->p_streams
= old_circ
->p_streams
;
530 new_circ
->half_streams
= old_circ
->half_streams
;
531 /* Sync all legs with the new stream(s). */
532 conflux_sync_circ_fields(cfx
, old_circ
);
534 or_circuit_t
*old_circ
= TO_OR_CIRCUIT(first_leg
->circ
);
535 or_circuit_t
*new_circ
= TO_OR_CIRCUIT(leg
->circ
);
536 new_circ
->n_streams
= old_circ
->n_streams
;
537 new_circ
->resolving_streams
= old_circ
->resolving_streams
;
541 if (CIRCUIT_IS_ORIGIN(cleg
->circ
)) {
542 tor_assert_nonfatal(cleg
->circ
->purpose
==
543 CIRCUIT_PURPOSE_CONFLUX_UNLINKED
);
544 circuit_change_purpose(cleg
->circ
, CIRCUIT_PURPOSE_CONFLUX_LINKED
);
546 conflux_validate_stream_lists(cfx
);
550 * Clean up a circuit from its conflux_t object.
552 * Return true if closing this circuit should tear down the entire set,
556 cfx_del_leg(conflux_t
*cfx
, const circuit_t
*circ
)
559 bool full_teardown
= false;
564 leg
= conflux_get_leg(cfx
, circ
);
569 // If the circuit still has inflight data, teardown
570 const struct congestion_control_t
*cc
= circuit_ccontrol(circ
);
572 tor_assert(cc
->sendme_inc
);
573 if (cc
->inflight
>= cc
->sendme_inc
) {
574 full_teardown
= true;
575 log_info(LD_CIRC
, "Conflux current circuit has closed with "
576 "data in flight, tearing down entire set.");
579 /* Remove it from the cfx. */
580 smartlist_remove(cfx
->legs
, leg
);
582 /* After removal, if this leg had the highest sent (or recv)
583 * sequence number, it was in active use by us (or the other side).
584 * We need to tear down the entire set. */
585 // TODO-329-ARTI: If we support resumption, we don't need this.
586 if (CONFLUX_NUM_LEGS(cfx
) > 0) {
587 if (conflux_get_max_seq_sent(cfx
) < leg
->last_seq_sent
||
588 conflux_get_max_seq_recv(cfx
) < leg
->last_seq_recv
) {
589 full_teardown
= true;
590 log_info(LD_CIRC
, "Conflux sequence number check failed, "
591 "tearing down entire set.");
595 /* Cleanup any reference to leg. */
596 if (cfx
->curr_leg
== leg
) {
597 cfx
->curr_leg
= NULL
;
598 full_teardown
= true;
599 log_info(LD_CIRC
, "Conflux current circuit has closed, "
600 "tearing down entire set.");
602 if (cfx
->prev_leg
== leg
) {
603 cfx
->prev_leg
= NULL
;
609 return full_teardown
;
612 /** Close the circuit of each legs of the given unlinked object. */
614 unlinked_close_all_legs(unlinked_circuits_t
*unlinked
)
616 smartlist_t
*circ_to_close
= NULL
;
618 tor_assert(unlinked
);
620 /* Small optimization here, avoid this work if no legs. */
621 if (smartlist_len(unlinked
->legs
) == 0) {
625 /* We will iterate over all legs and put the circuit in its own list and then
626 * mark them for close. The unlinked object gets freed opportunistically once
627 * there is no more legs attached to it and so we can't hold a reference
628 * while closing circuits. */
629 circ_to_close
= smartlist_new();
631 SMARTLIST_FOREACH(unlinked
->legs
, leg_t
*, leg
,
632 smartlist_add(circ_to_close
, leg
->circ
));
635 /* The leg gets cleaned up in the circuit close. */
636 SMARTLIST_FOREACH_BEGIN(circ_to_close
, circuit_t
*, circ
) {
637 if (CIRCUIT_IS_ORIGIN(circ
)) {
638 tor_assert_nonfatal(circ
->purpose
== CIRCUIT_PURPOSE_CONFLUX_UNLINKED
);
640 if (!circ
->marked_for_close
) {
641 circuit_mark_for_close(circ
, END_CIRC_REASON_INTERNAL
);
643 } SMARTLIST_FOREACH_END(circ
);
645 /* Drop the list and ignore its content, we don't have ownership. */
646 smartlist_free(circ_to_close
);
649 /** Either closee all legs of the given unlinked set or delete it from the pool
650 * and free its memory.
652 * Important: The unlinked object is freed opportunistically when legs are
653 * removed until the point none remains. And so, it is only safe to free the
654 * object if no more legs exist.
657 unlinked_close_or_free(unlinked_circuits_t
*unlinked
)
663 /* If we have legs, the circuit close will trigger the unlinked object to be
664 * opportunistically freed. Else, we do it explicitly. */
665 if (smartlist_len(unlinked
->legs
) > 0) {
666 unlinked_close_all_legs(unlinked
);
668 unlinked_pool_del_and_free(unlinked
, unlinked
->is_client
);
670 /* Either the unlinked object has been freed or the last leg close will free
671 * it so from this point on, nullify for safety reasons. */
675 /** Upon an error condition or a close of an in-use circuit, we must close all
676 * linked and unlinked circuits associated with a set. When the last leg of
677 * each set is closed, the set is removed from the pool. */
679 conflux_mark_all_for_close(const uint8_t *nonce
, bool is_client
, int reason
)
681 /* It is possible that for a nonce we have both an unlinked set and a linked
682 * set. This happens if there is a recovery leg launched for an existing
685 /* Close the unlinked set. */
686 unlinked_circuits_t
*unlinked
= unlinked_pool_get(nonce
, is_client
);
688 unlinked_close_or_free(unlinked
);
690 /* In case it gets freed, be safe here. */
693 /* Close the linked set. It will free itself upon the close of
695 conflux_t
*linked
= linked_pool_get(nonce
, is_client
);
697 if (linked
->in_full_teardown
) {
700 linked
->in_full_teardown
= true;
702 smartlist_t
*circ_to_close
= smartlist_new();
704 SMARTLIST_FOREACH(linked
->legs
, conflux_leg_t
*, leg
,
705 smartlist_add(circ_to_close
, leg
->circ
));
707 SMARTLIST_FOREACH(circ_to_close
, circuit_t
*, circ
,
708 circuit_mark_for_close(circ
, reason
));
710 /* Drop the list and ignore its content, we don't have ownership. */
711 smartlist_free(circ_to_close
);
715 /** Helper: Free function taking a void pointer for the digest256map_free. */
717 free_unlinked_void_(void *ptr
)
719 unlinked_circuits_t
*unlinked
= ptr
;
720 unlinked_pool_del_and_free(unlinked
, unlinked
->is_client
);
723 /** Attempt to finalize the unlinked set to become a linked set and be put in
726 * If this finalized successfully, the given unlinked object is freed. */
727 static link_circ_err_t
728 try_finalize_set(unlinked_circuits_t
*unlinked
)
730 link_circ_err_t err
= ERR_LINK_CIRC_OK
;
733 tor_assert(unlinked
);
734 tor_assert(unlinked
->legs
);
735 tor_assert(unlinked
->cfx
);
736 tor_assert(unlinked
->cfx
->legs
);
738 /* Without legs, this is not ready to become a linked set. */
739 if (BUG(smartlist_len(unlinked
->legs
) == 0)) {
740 err
= ERR_LINK_CIRC_MISSING_LEG
;
744 /* If there are too many legs, we can't link. */
745 if (smartlist_len(unlinked
->legs
) +
746 smartlist_len(unlinked
->cfx
->legs
) > conflux_params_get_max_legs_set()) {
747 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
748 "Conflux set has too many legs to link. "
749 "Rejecting this circuit.");
750 conflux_log_set(LOG_PROTOCOL_WARN
, unlinked
->cfx
, unlinked
->is_client
);
751 err
= ERR_LINK_CIRC_INVALID_LEG
;
755 /* Validate that all legs are coherent and parameters match. On failure, we
756 * teardown the whole unlinked set because this means we either have a code
757 * flow problem or the Exit is trying to trick us. */
758 if (!validate_unlinked_legs(unlinked
)) {
759 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
760 "Conflux unlinked set legs are not validating. Tearing it down.");
761 conflux_mark_all_for_close(unlinked
->cfx
->nonce
, unlinked
->is_client
,
762 END_CIRC_REASON_TORPROTOCOL
);
763 err
= ERR_LINK_CIRC_INVALID_LEG
;
767 /* Check all linked status. All need to be true in order to finalize the set
768 * and move it to the linked pool. */
769 SMARTLIST_FOREACH_BEGIN(unlinked
->legs
, const leg_t
*, leg
) {
770 /* We are still waiting on a leg. */
772 log_info(LD_CIRC
, "Can't finalize conflux set, still waiting on at "
773 "least one leg to link up.");
777 } SMARTLIST_FOREACH_END(leg
);
779 /* Finalize the cfx object by adding all legs into it. */
780 SMARTLIST_FOREACH_BEGIN(unlinked
->legs
, leg_t
*, leg
) {
781 /* Removing the leg from the list is important so we avoid ending up with a
782 * leg in the unlinked list that is set with LINKED purpose. */
783 SMARTLIST_DEL_CURRENT(unlinked
->legs
, leg
);
785 /* We are ready to attach the leg to the cfx object now. */
786 cfx_add_leg(unlinked
->cfx
, leg
);
788 /* Clean the pending nonce and set the conflux object in the circuit. */
789 leg
->circ
->conflux
= unlinked
->cfx
;
791 /* We are done with this leg object. */
793 } SMARTLIST_FOREACH_END(leg
);
795 is_client
= unlinked
->is_client
;
797 /* Add the conflux object to the linked pool. For an existing linked cfx
798 * object, we'll simply replace it with itself. */
799 linked_pool_add(unlinked
->cfx
, is_client
);
801 /* Remove it from the unlinked pool. */
802 unlinked_pool_del(unlinked
, is_client
);
804 /* We don't recover a leg when it is linked but if we would like to support
805 * session ressumption, this would be very important in order to allow new
806 * legs to be created/recovered. */
807 unlinked
->cfx
->num_leg_launch
= 0;
809 /* Nullify because we are about to free the unlinked object and the cfx has
810 * moved to all circuits. */
811 unlinked
->cfx
= NULL
;
812 unlinked_free(unlinked
);
815 "Successfully linked a conflux %s set which is now usable.",
816 is_client
? "client" : "relay");
822 /** Record the RTT for this client circuit.
824 * Return the RTT value. UINT64_MAX is returned if we couldn't find the initial
825 * measurement of when the cell was sent or if the leg is missing. */
827 record_rtt_client(const circuit_t
*circ
)
830 tor_assert(circ
->conflux_pending_nonce
);
831 tor_assert(CIRCUIT_IS_ORIGIN(circ
));
833 leg_t
*leg
= unlinked_leg_find(circ
, true);
835 if (BUG(!leg
|| leg
->link_sent_usec
== 0)) {
837 "Conflux: Trying to record client RTT without a timestamp");
841 uint64_t now
= monotime_absolute_usec();
842 tor_assert_nonfatal(now
>= leg
->link_sent_usec
);
843 leg
->rtt_usec
= now
- leg
->link_sent_usec
;
844 if (leg
->rtt_usec
== 0) {
845 log_warn(LD_CIRC
, "Clock appears stalled for conflux.");
846 // TODO-329-TUNING: For now, let's accept this case. We need to do
847 // tuning and clean up the tests such that they use RTT in order to
851 return leg
->rtt_usec
;
854 // Avoid using this leg until a timestamp comes in
856 leg
->rtt_usec
= UINT64_MAX
;
860 /** Record the RTT for this Exit circuit.
862 * Return the RTT value. UINT64_MAX is returned if we couldn't find the initial
863 * measurement of when the cell was sent or if the leg is missing. */
866 record_rtt_exit(const circuit_t
*circ
)
869 tor_assert(circ
->conflux
);
870 tor_assert(CIRCUIT_IS_ORCIRC(circ
));
872 conflux_leg_t
*leg
= conflux_get_leg(circ
->conflux
, circ
);
874 if (BUG(!leg
|| leg
->linked_sent_usec
== 0)) {
876 "Conflux: Trying to record exit RTT without a timestamp");
880 uint64_t now
= monotime_absolute_usec();
881 tor_assert_nonfatal(now
>= leg
->linked_sent_usec
);
882 leg
->circ_rtts_usec
= now
- leg
->linked_sent_usec
;
884 if (leg
->circ_rtts_usec
== 0) {
885 log_warn(LD_CIRC
, "Clock appears stalled for conflux.");
888 return leg
->circ_rtts_usec
;
892 leg
->circ_rtts_usec
= UINT64_MAX
;
896 /** For the given circuit, record the RTT from when the LINK or LINKED cell was
897 * sent that is this function works for either client or Exit.
899 * Return false if the RTT is too high for our standard else true. */
901 record_rtt(const circuit_t
*circ
, bool is_client
)
908 rtt_usec
= record_rtt_client(circ
);
910 if (rtt_usec
== UINT64_MAX
)
913 if (rtt_usec
>= get_circuit_build_timeout_ms()*1000) {
914 log_info(LD_CIRC
, "Conflux leg RTT is above circuit build time out "
915 "currently at %f msec. Relaunching.",
916 get_circuit_build_timeout_ms());
920 rtt_usec
= record_rtt_exit(circ
);
926 /** Link the given circuit within its unlinked set. This is called when either
927 * the LINKED or LINKED_ACK is received depending on which side of the circuit
930 * It attempts to finalize the unlinked set as well which, if successful, puts
931 * it in the linked pool. */
932 static link_circ_err_t
933 link_circuit(circuit_t
*circ
)
935 link_circ_err_t err
= ERR_LINK_CIRC_OK
;
936 unlinked_circuits_t
*unlinked
= NULL
;
937 bool is_client
= false;
940 if (CIRCUIT_IS_ORIGIN(circ
)) {
941 tor_assert_nonfatal(circ
->purpose
== CIRCUIT_PURPOSE_CONFLUX_UNLINKED
);
945 unlinked
= unlinked_pool_get(circ
->conflux_pending_nonce
, is_client
);
946 if (BUG(!unlinked
)) {
947 log_warn(LD_BUG
, "Failed to find the unlinked set %s when linking. "
949 fmt_nonce(circ
->conflux_pending_nonce
));
950 err
= ERR_LINK_CIRC_MISSING_SET
;
954 leg_t
*leg
= leg_find(unlinked
, circ
);
956 /* Failure to find the leg when linking a circuit is an important problem
957 * so log loudly and error. */
958 log_warn(LD_BUG
, "Failed to find leg for the unlinked set %s when "
959 "linking. Closing circuit.",
960 fmt_nonce(unlinked
->cfx
->nonce
));
961 err
= ERR_LINK_CIRC_MISSING_LEG
;
965 /* Successful link. Attempt to finalize the set in case this was the last
966 * LINKED or LINKED_ACK cell to receive. */
968 err
= try_finalize_set(unlinked
);
974 /** Launch a brand new set.
976 * Return true if all legs successfully launched or false if one failed. */
978 launch_new_set(int num_legs
)
980 uint8_t nonce
[DIGEST256_LEN
];
982 /* Brand new nonce for this set. */
983 crypto_rand((char *) nonce
, sizeof(nonce
));
985 /* Launch all legs. */
986 for (int i
= 0; i
< num_legs
; i
++) {
987 if (!conflux_launch_leg(nonce
)) {
988 /* This function cleans up entirely the unlinked set if a leg is unable
989 * to be launched. The recovery would be complex here. */
1000 static unlinked_circuits_t
*
1001 unlinked_get_or_create(const uint8_t *nonce
, bool is_client
)
1003 unlinked_circuits_t
*unlinked
;
1007 unlinked
= unlinked_pool_get(nonce
, is_client
);
1009 unlinked
= unlinked_new(nonce
, is_client
);
1011 /* If this is a leg of an existing linked set, use that conflux object
1012 * instead so all legs point to the same. It is put in the leg's circuit
1013 * once the link is confirmed. */
1014 conflux_t
*cfx
= linked_pool_get(nonce
, is_client
);
1016 conflux_free(unlinked
->cfx
);
1017 unlinked
->cfx
= cfx
;
1018 unlinked
->is_for_linked_set
= true;
1020 /* Add this set to the unlinked pool. */
1021 unlinked_pool_add(unlinked
, is_client
);
1028 * On the client side, we need to determine if there is already
1029 * an exit in use for this set, and if so, use that.
1031 * Otherwise, we return NULL and the exit is decided by the
1032 * circuitbuild.c code.
1034 static extend_info_t
*
1035 get_exit_for_nonce(const uint8_t *nonce
)
1037 extend_info_t
*exit
= NULL
;
1041 // First, check the linked pool for the nonce
1042 const conflux_t
*cfx
= linked_pool_get(nonce
, true);
1044 tor_assert(cfx
->legs
);
1045 /* Get the exit from the first leg */
1046 conflux_leg_t
*leg
= smartlist_get(cfx
->legs
, 0);
1048 tor_assert(leg
->circ
);
1049 tor_assert(TO_ORIGIN_CIRCUIT(leg
->circ
)->cpath
);
1050 exit
= TO_ORIGIN_CIRCUIT(leg
->circ
)->cpath
->prev
->extend_info
;
1053 unlinked_circuits_t
*unlinked
= NULL
;
1054 unlinked
= unlinked_pool_get(nonce
, true);
1057 tor_assert(unlinked
->legs
);
1058 if (smartlist_len(unlinked
->legs
) > 0) {
1059 /* Get the exit from the first leg */
1060 leg_t
*leg
= smartlist_get(unlinked
->legs
, 0);
1062 tor_assert(leg
->circ
);
1063 tor_assert(TO_ORIGIN_CIRCUIT(leg
->circ
)->cpath
);
1064 exit
= TO_ORIGIN_CIRCUIT(leg
->circ
)->cpath
->prev
->extend_info
;
1074 * Return the currently configured client UX.
1079 #ifdef TOR_UNIT_TESTS
1080 return DEFAULT_CLIENT_UX
;
1082 const or_options_t
*opt
= get_options();
1084 (void)DEFAULT_CLIENT_UX
;
1087 return opt
->ConfluxClientUX
;
1091 /** Return true iff the given conflux object is allowed to launch a new leg. If
1092 * the cfx object is NULL, then it is always allowed to launch a new leg. */
1094 launch_leg_is_allowed(const conflux_t
*cfx
)
1100 /* The maximum number of retry is the minimum number of legs we are allowed
1101 * per set plus the maximum amount of retries we are allowed to do. */
1102 unsigned int max_num_launch
=
1103 conflux_params_get_num_legs_set() +
1104 conflux_params_get_max_unlinked_leg_retry();
1106 /* Only log once per nonce if we've reached the maximum. */
1107 if (cfx
->num_leg_launch
== max_num_launch
) {
1108 log_info(LD_CIRC
, "Maximum number of leg launch reached for nonce %s",
1109 fmt_nonce(cfx
->nonce
));
1112 if (cfx
->num_leg_launch
>= max_num_launch
) {
1124 /** Launch a new conflux leg for the given nonce.
1126 * Return true on success else false which teardowns the entire unlinked set if
1129 conflux_launch_leg(const uint8_t *nonce
)
1131 int flags
= CIRCLAUNCH_NEED_UPTIME
| CIRCLAUNCH_NEED_CAPACITY
|
1132 CIRCLAUNCH_NEED_CONFLUX
;
1133 unlinked_circuits_t
*unlinked
= NULL
;
1134 extend_info_t
*exit
= NULL
;
1138 /* Get or create a new unlinked object for this leg. */
1139 unlinked
= unlinked_get_or_create(nonce
, true);
1140 tor_assert(unlinked
);
1142 /* If we have an existing linked set, validate the number of leg retries
1143 * before attempting the launch. */
1144 if (!launch_leg_is_allowed(unlinked
->cfx
)) {
1148 exit
= get_exit_for_nonce(nonce
);
1151 log_info(LD_CIRC
, "Launching conflux leg for nonce %s.", fmt_nonce(nonce
));
1153 log_info(LD_CIRC
, "Launching new conflux set for nonce %s.",
1157 /* Increase the retry count for this conflux object as in this nonce.
1158 * We must do this now, because some of the maze's early failure paths
1159 * call right back into this function for relaunch. */
1160 unlinked
->cfx
->num_leg_launch
++;
1162 origin_circuit_t
*circ
=
1163 circuit_establish_circuit_conflux(nonce
, CIRCUIT_PURPOSE_CONFLUX_UNLINKED
,
1168 tor_assert(TO_CIRCUIT(circ
)->conflux_pending_nonce
);
1170 /* At this point, the unlinked object has either a new conflux_t or the one
1171 * used by a linked set so it is fine to use the cfx from the unlinked object
1174 /* Get the max_seq_sent and recv from the linked pool, if it exists, and pass
1175 * to new link cell. */
1176 uint64_t last_seq_sent
= conflux_get_max_seq_sent(unlinked
->cfx
);
1177 uint64_t last_seq_recv
= unlinked
->cfx
->last_seq_delivered
;
1179 // TODO-329-ARTI: To support resumption/retransmit, the client should store
1180 // the last_seq_sent now, so that it can know how much data to retransmit to
1181 // the server after link. C-Tor will not be implementing this, but arti and
1182 // arti-relay could (if resumption seems worthwhile; it may not be worth the
1183 // memory storage there, either).
1185 /* We have a circuit, create the new leg and attach it to the set. */
1186 leg_t
*leg
= leg_new(TO_CIRCUIT(circ
),
1187 conflux_cell_new_link(nonce
,
1188 last_seq_sent
, last_seq_recv
,
1191 unlinked_leg_add(unlinked
, leg
);
1199 * Add the identity digest of the guard nodes of all legs of the conflux
1202 * This function checks both pending and linked conflux circuits.
1205 conflux_add_guards_to_exclude_list(const origin_circuit_t
*orig_circ
,
1206 smartlist_t
*excluded
)
1208 tor_assert(orig_circ
);
1209 tor_assert(excluded
);
1211 /* Ease our lives. */
1212 const circuit_t
*circ
= TO_CIRCUIT(orig_circ
);
1214 /* Ignore if this is not conflux related. */
1215 if (!CIRCUIT_IS_CONFLUX(circ
)) {
1219 /* When building a circuit, we should not have a conflux object
1220 * ourselves (though one may exist elsewhere). */
1221 tor_assert(!circ
->conflux
);
1223 /* Getting here without a nonce is a code flow issue. */
1224 if (BUG(!circ
->conflux_pending_nonce
)) {
1228 /* If there is only one bridge, then only issue a warn once that
1229 * at least two bridges are best for conflux. Exempt Snowflake
1231 if (get_options()->UseBridges
&& !conflux_can_exclude_used_bridges()) {
1232 /* Do not build any exclude lists; not enough bridges */
1236 /* A linked set exists, use it. */
1237 const conflux_t
*cfx
= linked_pool_get(circ
->conflux_pending_nonce
, true);
1239 CONFLUX_FOR_EACH_LEG_BEGIN(cfx
, leg
) {
1240 const origin_circuit_t
*ocirc
= CONST_TO_ORIGIN_CIRCUIT(leg
->circ
);
1241 smartlist_add(excluded
,
1242 tor_memdup(ocirc
->cpath
->extend_info
->identity_digest
,
1244 } CONFLUX_FOR_EACH_LEG_END(leg
);
1247 /* An unlinked set might exist for this nonce, if so, add the second hop of
1248 * the existing legs to the exclusion list. */
1249 unlinked_circuits_t
*unlinked
=
1250 unlinked_pool_get(circ
->conflux_pending_nonce
, true);
1252 tor_assert(unlinked
->is_client
);
1253 SMARTLIST_FOREACH_BEGIN(unlinked
->legs
, leg_t
*, leg
) {
1254 /* Convert to origin circ and get cpath */
1255 const origin_circuit_t
*ocirc
= CONST_TO_ORIGIN_CIRCUIT(leg
->circ
);
1256 smartlist_add(excluded
,
1257 tor_memdup(ocirc
->cpath
->extend_info
->identity_digest
,
1259 } SMARTLIST_FOREACH_END(leg
);
1264 * Add the identity digest of the middle nodes of all legs of the conflux
1267 * This function checks both pending and linked conflux circuits.
1269 * XXX: The add guard and middle could be merged since it is the exact same
1270 * code except for the cpath position and the identity digest vs node_t in
1271 * the list. We could use an extra param indicating guard or middle. */
1273 conflux_add_middles_to_exclude_list(const origin_circuit_t
*orig_circ
,
1274 smartlist_t
*excluded
)
1276 tor_assert(orig_circ
);
1277 tor_assert(excluded
);
1279 /* Ease our lives. */
1280 const circuit_t
*circ
= TO_CIRCUIT(orig_circ
);
1282 /* Ignore if this is not conflux related. */
1283 if (!CIRCUIT_IS_CONFLUX(circ
)) {
1287 /* When building a circuit, we should not have a conflux object
1288 * ourselves (though one may exist elsewhere). */
1289 tor_assert(!circ
->conflux
);
1291 /* Getting here without a nonce is a code flow issue. */
1292 if (BUG(!circ
->conflux_pending_nonce
)) {
1296 /* A linked set exists, use it. */
1297 const conflux_t
*cfx
= linked_pool_get(circ
->conflux_pending_nonce
, true);
1299 CONFLUX_FOR_EACH_LEG_BEGIN(cfx
, leg
) {
1300 const origin_circuit_t
*ocirc
= CONST_TO_ORIGIN_CIRCUIT(leg
->circ
);
1301 node_t
*node
= node_get_mutable_by_id(
1302 ocirc
->cpath
->next
->extend_info
->identity_digest
);
1304 smartlist_add(excluded
, node
);
1306 } CONFLUX_FOR_EACH_LEG_END(leg
);
1309 /* An unlinked set might exist for this nonce, if so, add the second hop of
1310 * the existing legs to the exclusion list. */
1311 unlinked_circuits_t
*unlinked
=
1312 unlinked_pool_get(circ
->conflux_pending_nonce
, true);
1314 tor_assert(unlinked
->is_client
);
1315 SMARTLIST_FOREACH_BEGIN(unlinked
->legs
, leg_t
*, leg
) {
1316 /* Convert to origin circ and get cpath */
1317 const origin_circuit_t
*ocirc
= CONST_TO_ORIGIN_CIRCUIT(leg
->circ
);
1318 node_t
*node
= node_get_mutable_by_id(
1319 ocirc
->cpath
->next
->extend_info
->identity_digest
);
1321 smartlist_add(excluded
, node
);
1323 } SMARTLIST_FOREACH_END(leg
);
1327 /** Return the number of unused client linked set. */
1329 count_client_usable_sets(void)
1333 DIGEST256MAP_FOREACH(client_linked_pool
, key
, conflux_t
*, cfx
) {
1334 conflux_leg_t
*leg
= smartlist_get(cfx
->legs
, 0);
1335 if (BUG(!leg
->circ
)) {
1336 log_warn(LD_BUG
, "Client conflux linked set leg without a circuit");
1340 /* The maze marks circuits used several different ways. If any of
1341 * them are marked for this leg, launch a new one. */
1342 if (!CONST_TO_ORIGIN_CIRCUIT(leg
->circ
)->unusable_for_new_conns
&&
1343 !CONST_TO_ORIGIN_CIRCUIT(leg
->circ
)->isolation_values_set
&&
1344 !leg
->circ
->timestamp_dirty
) {
1347 } DIGEST256MAP_FOREACH_END
;
1352 /** Determine if we need to launch new conflux circuits for our preemptive
1355 * This is called once a second from the mainloop from
1356 * circuit_predict_and_launch_new(). */
1358 conflux_predict_new(time_t now
)
1362 /* If conflux is disabled, or we have insufficient consensus exits,
1363 * don't prebuild. */
1364 if (!conflux_is_enabled(NULL
) ||
1365 router_have_consensus_path() != CONSENSUS_PATH_EXIT
) {
1369 /* Don't attempt to build a new set if we are above our allowed maximum of
1371 if (digest256map_size(client_linked_pool
) >=
1372 conflux_params_get_max_linked_set()) {
1376 /* Count the linked and unlinked to get the total number of sets we have
1378 int num_linked
= count_client_usable_sets();
1379 int num_unlinked
= digest256map_size(client_unlinked_pool
);
1380 int num_set
= num_unlinked
+ num_linked
;
1381 int max_prebuilt
= conflux_params_get_max_prebuilt();
1383 if (num_set
>= max_prebuilt
) {
1387 log_info(LD_CIRC
, "Preemptively launching new conflux circuit set(s). "
1388 "We have %d linked and %d unlinked.",
1389 num_linked
, num_unlinked
);
1391 for (int i
= 0; i
< (max_prebuilt
- num_set
); i
++) {
1392 if (!launch_new_set(conflux_params_get_num_legs_set())) {
1393 /* Failing once likely means we'll fail next attempt so stop for now and
1394 * we'll try later. */
1400 /** Return the first circuit from the linked pool that will work with the conn.
1401 * If no such circuit exists, return NULL. */
1403 conflux_get_circ_for_conn(const entry_connection_t
*conn
, time_t now
)
1405 /* Use conn to check the exit policy of the first circuit
1406 * of each set in the linked pool. */
1409 DIGEST256MAP_FOREACH(client_linked_pool
, key
, conflux_t
*, cfx
) {
1410 /* Get the first circuit of the set. */
1411 conflux_leg_t
*leg
= smartlist_get(cfx
->legs
, 0);
1413 tor_assert(leg
->circ
);
1415 /* Bug on these but we can recover. */
1416 if (BUG(leg
->circ
->purpose
!= CIRCUIT_PURPOSE_CONFLUX_LINKED
)) {
1419 if (BUG(!CIRCUIT_IS_ORIGIN(leg
->circ
))) {
1422 origin_circuit_t
*ocirc
= TO_ORIGIN_CIRCUIT(leg
->circ
);
1424 /* Make sure the connection conforms with the exit policy and the isolation
1425 * flags also allows it. */
1426 if (!circuit_is_acceptable(ocirc
, conn
, 1 /* Must be open */,
1427 CIRCUIT_PURPOSE_CONFLUX_LINKED
,
1428 1 /* Need uptime */,
1429 0 /* No need for internal */, now
)) {
1433 /* Found a circuit that works. */
1435 } DIGEST256MAP_FOREACH_END
;
1440 /** The given circuit is conflux pending and has closed. This deletes the leg
1441 * from the set, attempt to finalize it and relaunch a new leg. If the set is
1442 * empty after removing this leg, it is deleted. */
1444 unlinked_circuit_closed(circuit_t
*circ
)
1446 uint8_t nonce
[DIGEST256_LEN
];
1447 unlinked_circuits_t
*unlinked
= NULL
;
1448 bool is_client
= false;
1451 tor_assert(circ
->conflux_pending_nonce
);
1453 if (CIRCUIT_IS_ORIGIN(circ
)) {
1454 tor_assert_nonfatal(circ
->purpose
== CIRCUIT_PURPOSE_CONFLUX_UNLINKED
);
1458 unlinked
= unlinked_pool_get(circ
->conflux_pending_nonce
, is_client
);
1460 /* This circuit is part of set that has already been removed previously freed
1461 * by another leg closing. */
1466 /* We keep the nonce here because we will try to recover if we can and the
1467 * pending nonce will get nullified early. */
1468 memcpy(nonce
, circ
->conflux_pending_nonce
, sizeof(nonce
));
1470 log_info(LD_CIRC
, "Conflux unlinked circuit with nonce %s has closed",
1473 /* Remove leg from set. */
1474 unlinked_leg_del_and_free(unlinked
, circ
);
1475 /* The circuit pending nonce has been nullified at this point. */
1477 /* If no more legs, opportunistically free the unlinked set. */
1478 if (smartlist_len(unlinked
->legs
) == 0) {
1479 unlinked_pool_del_and_free(unlinked
, is_client
);
1480 } else if (!shutting_down
) {
1481 /* Launch a new leg for this set to recover. */
1482 if (CIRCUIT_IS_ORIGIN(circ
)) {
1483 conflux_launch_leg(nonce
);
1486 /* After this, it might have been freed. */
1489 /* Unlinked circuits should not have attached streams, but check
1490 * anyway, because The Maze. */
1491 validate_circ_has_no_streams(circ
);
1494 /** Update all stream pointers to point to this circuit.
1495 * This is used when a linked circuit is closed and we need to update the
1496 * streams to point to the remaining circuit
1499 linked_update_stream_backpointers(circuit_t
*circ
)
1502 tor_assert_nonfatal(circ
->conflux
);
1504 if (CIRCUIT_IS_ORIGIN(circ
)) {
1505 origin_circuit_t
*ocirc
= TO_ORIGIN_CIRCUIT(circ
);
1506 tor_assert_nonfatal(circ
->purpose
== CIRCUIT_PURPOSE_CONFLUX_LINKED
);
1507 /* Iterate over stream list using next_stream pointer, until null */
1508 for (edge_connection_t
*stream
= ocirc
->p_streams
; stream
;
1509 stream
= stream
->next_stream
) {
1510 /* Update the circuit pointer of each stream */
1511 stream
->on_circuit
= circ
;
1512 stream
->cpath_layer
= ocirc
->cpath
->prev
;
1515 or_circuit_t
*orcirc
= TO_OR_CIRCUIT(circ
);
1516 /* Iterate over stream list using next_stream pointer, until null */
1517 for (edge_connection_t
*stream
= orcirc
->n_streams
; stream
;
1518 stream
= stream
->next_stream
) {
1519 /* Update the circuit pointer of each stream */
1520 stream
->on_circuit
= circ
;
1522 /* Iterate over stream list using next_stream pointer, until null */
1523 for (edge_connection_t
*stream
= orcirc
->resolving_streams
; stream
;
1524 stream
= stream
->next_stream
) {
1525 /* Update the circuit pointer of each stream */
1526 stream
->on_circuit
= circ
;
1531 /** Nullify all streams of the given circuit. */
1533 linked_nullify_streams(circuit_t
*circ
)
1537 if (CIRCUIT_IS_ORIGIN(circ
)) {
1538 origin_circuit_t
*ocirc
= TO_ORIGIN_CIRCUIT(circ
);
1539 ocirc
->p_streams
= NULL
;
1540 ocirc
->half_streams
= NULL
;
1542 or_circuit_t
*orcirc
= TO_OR_CIRCUIT(circ
);
1543 orcirc
->n_streams
= NULL
;
1544 orcirc
->resolving_streams
= NULL
;
1548 /** The given circuit is already linked to a set and has been closed. Remove it
1549 * from the set and free the pool if no more legs. */
1551 linked_circuit_closed(circuit_t
*circ
)
1553 bool is_client
= false;
1554 bool full_teardown
= false;
1555 uint8_t nonce
[DIGEST256_LEN
] = {0};
1558 tor_assert(circ
->conflux
);
1560 if (CIRCUIT_IS_ORIGIN(circ
)) {
1561 tor_assert_nonfatal(circ
->purpose
== CIRCUIT_PURPOSE_CONFLUX_LINKED
);
1565 /* Unlink circuit from its conflux object. */
1566 full_teardown
= cfx_del_leg(circ
->conflux
, circ
);
1568 if (CONFLUX_NUM_LEGS(circ
->conflux
) == 0) {
1569 /* Last leg, remove conflux object from linked set. */
1570 linked_pool_del(circ
->conflux
->nonce
, is_client
);
1572 /* If there are other circuits, update streams backpointers and
1573 * nullify the stream lists. We do not free those streams in circuit_free_.
1574 * (They only get freed when the last circuit is freed). */
1575 conflux_leg_t
*leg
= smartlist_get(circ
->conflux
->legs
, 0);
1576 linked_update_stream_backpointers(leg
->circ
);
1577 linked_nullify_streams(circ
);
1580 /* Keep the nonce so we can use it through out the rest of the function in
1581 * case we nullify the conflux object before. Reason is that in the case of a
1582 * full teardown, this function becomes basically recursive and so we must
1583 * nullify the conflux object of this circuit now before the recursiveness
1584 * starts leading to all legs being removed and thus not noticing if we are
1585 * the last or the first.
1587 * Not the prettiest but that is the price to pay to live in the C-tor maze
1588 * and protected by ballrogs. */
1589 memcpy(nonce
, circ
->conflux
->nonce
, sizeof(nonce
));
1591 /* Nullify the conflux object from the circuit being closed iff we have more
1592 * legs. Reason being that the last leg needs to have the conflux object
1593 * attached to the circuit so it can be freed in conflux_circuit_free(). */
1594 if (CONFLUX_NUM_LEGS(circ
->conflux
) > 0) {
1595 circ
->conflux
= NULL
;
1598 /* If this was a teardown condition, we need to mark other circuits,
1599 * including any potential unlinked circuits, for close.
1601 * This call is recursive in the sense that linked_circuit_closed() will end
1602 * up being called for all legs and so by the time we come back here, the
1603 * linked is likely entirely gone. Thus why this is done last. */
1604 if (full_teardown
) {
1605 conflux_mark_all_for_close(nonce
, is_client
, END_CIRC_REASON_FINISHED
);
1609 /** The given circuit is being freed and it is a linked leg. Clean up and free
1610 * anything that has to do with this circuit.
1612 * After this call, the circuit should NOT be referenced anymore anywhere. */
1614 linked_circuit_free(circuit_t
*circ
, bool is_client
)
1617 tor_assert(circ
->conflux
);
1618 tor_assert(circ
->conflux
->legs
);
1619 tor_assert(circ
->conflux
->ooo_q
);
1622 tor_assert(circ
->purpose
== CIRCUIT_PURPOSE_CONFLUX_LINKED
);
1625 /* Circuit can be freed without being closed and so we try to delete this leg
1626 * so we can learn if this circuit is the last leg or not. */
1627 if (cfx_del_leg(circ
->conflux
, circ
)) {
1628 /* Check for instances of bug #40870, which we suspect happen
1629 * during exit. If any happen outside of exit, BUG and warn. */
1630 if (!circ
->conflux
->in_full_teardown
) {
1631 /* We should bug and warn if we're not in a shutdown process; that
1632 * means we got here somehow without a close. */
1633 if (BUG(!shutting_down
)) {
1635 "Conflux circuit %p being freed without being marked for "
1636 "full teardown via close, with shutdown state %d. "
1637 "Please report this.", circ
, shutting_down
);
1638 conflux_log_set(LOG_WARN
, circ
->conflux
, is_client
);
1640 circ
->conflux
->in_full_teardown
= true;
1644 if (CONFLUX_NUM_LEGS(circ
->conflux
) > 0) {
1645 /* The last leg will free the streams but until then, we nullify to avoid
1646 * use-after-free. */
1647 linked_nullify_streams(circ
);
1649 /* We are the last leg. */
1651 /* Remove from pool in case it is still lingering there else we'll end up
1652 * in a double free situation. */
1653 linked_pool_del(circ
->conflux
->nonce
, is_client
);
1655 /* If there is an unlinked circuit that was also created for this set, we
1656 * need to look for it, and tell it is no longer part of a linked set
1657 * anymore, so it can be freed properly, or can complete the link if it is
1658 * able to. Effectively, the conflux_t object lifetime is longer than
1659 * either the linked or unlinked sets by themselves. This is a situation we
1660 * could cover with handles, but so far, it is not clear they are an
1661 * obvious benefit for other cases than this one. */
1662 unlinked_circuits_t
*unlinked
=
1663 unlinked_pool_get(circ
->conflux
->nonce
, is_client
);
1665 tor_assert(unlinked
->is_for_linked_set
);
1666 unlinked
->is_for_linked_set
= false;
1668 /* We are the last one, clear the conflux object. If an unlinked object
1669 * has a reference to it, it won't get freed due to is_for_linked_set
1671 conflux_free(circ
->conflux
);
1676 /** The given circuit is being freed and it is an unlinked leg. Clean up and
1677 * free anything that has to do with this circuit.
1679 * After this call, the circuit should NOT be referenced anymore anywhere. */
1681 unlinked_circuit_free(circuit_t
*circ
, bool is_client
)
1684 tor_assert(circ
->conflux_pending_nonce
);
1686 tor_assert(circ
->purpose
== CIRCUIT_PURPOSE_CONFLUX_UNLINKED
);
1689 /* Cleanup circuit reference if a leg exists. This is possible if the circuit
1690 * was not marked for close before being freed. */
1691 leg_t
*leg
= unlinked_leg_find(circ
, is_client
);
1696 /* Null pointers are safe here. */
1697 tor_free(circ
->conflux_pending_nonce
);
1700 /** Circuit has been marked for close. */
1702 conflux_circuit_has_closed(circuit_t
*circ
)
1704 /* The unlinked case. If an unlinked set exists, we delete the leg and then
1705 * attempt to finalize it. After that, we'll launch a new leg to recover. */
1706 if (circ
->conflux_pending_nonce
) {
1707 unlinked_circuit_closed(circ
);
1708 } else if (circ
->conflux
) {
1709 linked_circuit_closed(circ
);
1713 /** Circuit with conflux purpose just opened. */
1715 conflux_circuit_has_opened(origin_circuit_t
*orig_circ
)
1717 circuit_t
*circ
= NULL
;
1720 tor_assert(orig_circ
);
1722 circ
= TO_CIRCUIT(orig_circ
);
1724 /* Extra safety layer so we never let a circuit opens if conflux is not
1726 if (!conflux_is_enabled(circ
)) {
1727 circuit_mark_for_close(circ
, END_CIRC_REASON_TORPROTOCOL
);
1728 static ratelim_t conflux_ratelim
= RATELIM_INIT(600);
1729 log_fn_ratelim(&conflux_ratelim
, LOG_NOTICE
, LD_CIRC
,
1730 "Conflux circuit opened without negotiating "
1731 "congestion control");
1735 /* Unrelated to conflux. */
1736 if (circ
->conflux_pending_nonce
== NULL
) {
1740 log_info(LD_CIRC
, "Conflux circuit has opened with nonce %s",
1741 fmt_nonce(circ
->conflux_pending_nonce
));
1743 leg
= unlinked_leg_find(circ
, true);
1745 log_warn(LD_CIRC
, "Unable to find conflux leg in unlinked set.");
1749 /* On failure here, the circuit is closed and thus the leg and unlinked set
1750 * will be cleaned up. */
1751 if (!conflux_cell_send_link(leg
->link
, orig_circ
)) {
1755 /* Mark the leg on when the LINK cell is sent. Used to timeout the circuit
1756 * for a minimum RTT when getting the LINKED. */
1757 leg
->link_sent_usec
= monotime_absolute_usec();
1760 validate_circ_has_no_streams(circ
);
1764 /** Process a CONFLUX_LINK cell which arrived on the given circuit. */
1766 conflux_process_link(circuit_t
*circ
, const cell_t
*cell
,
1767 const uint16_t cell_len
)
1769 unlinked_circuits_t
*unlinked
= NULL
;
1770 conflux_cell_link_t
*link
= NULL
;
1775 if (!conflux_is_enabled(circ
)) {
1776 circuit_mark_for_close(circ
, END_CIRC_REASON_TORPROTOCOL
);
1780 /* This cell can't be received on an origin circuit because only the endpoint
1781 * creating the circuit sends it. */
1782 if (CIRCUIT_IS_ORIGIN(circ
)) {
1783 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
1784 "Got a CONFLUX_LINK cell on an origin circuit. Closing circuit.");
1785 circuit_mark_for_close(circ
, END_CIRC_REASON_TORPROTOCOL
);
1789 if (!conflux_validate_source_hop(circ
, NULL
)) {
1790 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
1791 "Got a CONFLUX_LINK with further hops. Closing circuit.");
1792 circuit_mark_for_close(circ
, END_CIRC_REASON_TORPROTOCOL
);
1796 if (circ
->conflux_pending_nonce
) {
1797 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
1798 "Got a CONFLUX_LINK on a circuit with a pending nonce. "
1799 "Closing circuit.");
1800 circuit_mark_for_close(circ
, END_CIRC_REASON_TORPROTOCOL
);
1804 if (circ
->conflux
) {
1805 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
1806 "Got a CONFLUX_LINK on an already linked circuit "
1807 "Closing circuit.");
1808 circuit_mark_for_close(circ
, END_CIRC_REASON_TORPROTOCOL
);
1812 /* On errors, logging is emitted in this parsing function. */
1813 link
= conflux_cell_parse_link(cell
, cell_len
);
1815 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
, "Unable to parse "
1816 "CONFLUX_LINK cell. Closing circuit.");
1817 circuit_mark_for_close(circ
, END_CIRC_REASON_TORPROTOCOL
);
1821 log_info(LD_CIRC
, "Processing a CONFLUX_LINK for set %s",
1822 fmt_nonce(link
->nonce
));
1824 /* Consider this circuit a new leg. We'll now attempt to attach it to an
1825 * existing set or unlinked one. */
1826 leg_t
*leg
= leg_new(circ
, link
);
1827 unlinked
= unlinked_get_or_create(link
->nonce
, false);
1828 tor_assert(unlinked
);
1830 /* Attach leg to the unlinked set. */
1831 unlinked_leg_add(unlinked
, leg
);
1833 /* Set the circuit in a pending conflux state for the LINKED_ACK. */
1834 circ
->conflux_pending_nonce
= tor_memdup(leg
->link
->nonce
,
1835 sizeof(leg
->link
->nonce
));
1837 /* Mark when we send the LINKED. */
1838 leg
->link_sent_usec
= monotime_absolute_usec();
1841 uint64_t last_seq_sent
= conflux_get_max_seq_sent(unlinked
->cfx
);
1842 uint64_t last_seq_recv
= unlinked
->cfx
->last_seq_delivered
;
1844 // TODO-329-ARTI: To support resumption/retransmit, the server should
1845 // store the last_seq_sent now, so that it can know how much data
1846 // to retransmit to the server after link. C-Tor will not be implementing
1847 // this, but arti and arti-relay could (if resumption seems worthwhile;
1848 // it may not be worth the memory storage there, either).
1850 uint8_t nonce
[DIGEST256_LEN
];
1851 memcpy(nonce
, circ
->conflux_pending_nonce
, sizeof(nonce
));
1853 /* Link the circuit to the a conflux set immediately before the LINKED is
1854 * sent. Reason is that once the client sends the LINKED_ACK, there is a race
1855 * with the BEGIN cell that can be sent immediately after and arrive first.
1856 * And so, we need to sync the streams before that happens that is before we
1857 * receive the LINKED_ACK. */
1858 if (link_circuit(circ
) != ERR_LINK_CIRC_OK
) {
1859 circuit_mark_for_close(circ
, END_CIRC_REASON_TORPROTOCOL
);
1863 /* Exits should always request min latency from clients */
1864 conflux_cell_link_t
*linked
= conflux_cell_new_link(nonce
, last_seq_sent
,
1868 conflux_cell_send_linked(linked
, TO_OR_CIRCUIT(circ
));
1875 /** Process a CONFLUX_LINKED cell which arrived on the given circuit. */
1877 conflux_process_linked(circuit_t
*circ
, crypt_path_t
*layer_hint
,
1879 const uint16_t cell_len
)
1881 conflux_cell_link_t
*link
= NULL
;
1886 * There several ways a malicious exit could create problems when sending
1887 * back this LINKED cell.
1889 * 1. Using a different nonce that it knows about from another set. Accepting
1890 * it would mean a confirmation attack of linking sets to the same client.
1891 * To address that, the cell nonce MUST be matched with the circuit nonce.
1893 * 2. Re-Sending a LINKED cell on an already linked circuit could create side
1894 * channel attacks or unpredictable issues. Circuit is closed.
1896 * 3. Receiving a LINKED cell on a circuit that was not expecting it. Again,
1897 * as (2), can create side channel(s). Circuit is closed.
1899 * 4. Receiving a LINKED cell from the another hop other than the last one
1900 * (exit). Same as (2) and (3) in terms of issues. Circuit is closed.
1903 if (!conflux_is_enabled(circ
)) {
1904 circuit_mark_for_close(circ
, END_CIRC_REASON_TORPROTOCOL
);
1908 /* LINKED cell are in response to a LINK cell which are only sent on an
1909 * origin circuit and thus received on such.*/
1910 if (!CIRCUIT_IS_ORIGIN(circ
)) {
1911 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
1912 "Received CONFLUX_LINKED cell on a non origin circuit.");
1916 if (!circ
->conflux_pending_nonce
) {
1917 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
1918 "Received a CONFLUX_LINKED cell without having sent a "
1919 "CONFLUX_LINK cell. Closing circuit.");
1923 if (circ
->conflux
) {
1924 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
1925 "Received a CONFLUX_LINKED cell on a circuit that is already "
1926 "linked. Closing circuit.");
1930 if (!conflux_validate_source_hop(circ
, layer_hint
)) {
1931 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
1932 "Got a CONFLUX_LINKED from wrong hop on circuit. Closing circuit.");
1936 tor_assert_nonfatal(circ
->purpose
== CIRCUIT_PURPOSE_CONFLUX_UNLINKED
);
1938 /* On errors, logging is emitted in this parsing function. */
1939 link
= conflux_cell_parse_link(cell
, cell_len
);
1944 log_info(LD_CIRC
, "Processing a CONFLUX_LINKED for set %s",
1945 fmt_nonce(link
->nonce
));
1947 /* Make sure the cell nonce matches the one on the circuit that was
1948 * previously set by the CONFLUX_LINK cell. */
1949 if (tor_memneq(link
->nonce
, circ
->conflux_pending_nonce
,
1950 sizeof(*link
->nonce
))) {
1951 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
1952 "Received CONFLUX_LINKED but circuit nonce doesn't match "
1953 "cell nonce. Closing circuit.");
1957 /* Find the leg from the associated unlinked set. */
1958 leg_t
*leg
= unlinked_leg_find(circ
, true);
1960 log_warn(LD_CIRC
, "Received CONFLUX_LINKED but can't find "
1961 "associated leg. Closing circuit.");
1965 log_info(LD_CIRC
, "Successfully processed a CONFLUX_LINKED cell.");
1967 /* Free the old link, and store the new one. We need to validate
1968 * the one we get during finalize, not the one we sent. */
1969 tor_free(leg
->link
);
1972 /* Record the RTT for this circuit. On failure, it means the RTT was too
1973 * high, we relaunch to recover. */
1974 if (!record_rtt(circ
, true)) {
1978 /* The following will link the circuit with its set and attempt to finalize
1979 * the set if all expected legs have linked. On error, we close the circuit
1980 * because it means the unlinked set needs to be teardowned. */
1981 link_circ_err_t err
= link_circuit(circ
);
1983 case ERR_LINK_CIRC_OK
:
1984 /* Successfully linked. */
1986 case ERR_LINK_CIRC_INVALID_LEG
:
1987 case ERR_LINK_CIRC_MISSING_SET
:
1988 /* No relaunch if the leg is invalid or the set is not found as in the
1989 * nonce is unknown. */
1991 case ERR_LINK_CIRC_BAD_RTT
:
1992 case ERR_LINK_CIRC_MISSING_LEG
:
1996 /* We can send the ack only if we finalize. This will not cause issues,
1997 * because LINKED_ACK is exempted from multiplexing in
1998 * conflux_should_multiplex(). */
1999 if (!conflux_cell_send_linked_ack(TO_ORIGIN_CIRCUIT(circ
))) {
2000 /* On failure, the circuit is closed by the underlying function(s). */
2004 /* If this set is ready to use with a valid conflux set, try any pending
2006 if (circ
->conflux
) {
2007 connection_ap_attach_pending(1);
2010 /* This cell is now considered valid for clients. */
2011 circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ
), cell_len
);
2016 circuit_mark_for_close(circ
, END_CIRC_REASON_TORPROTOCOL
);
2022 /** Process a CONFLUX_LINKED_ACK cell which arrived on the given circuit. */
2024 conflux_process_linked_ack(circuit_t
*circ
)
2028 if (!conflux_is_enabled(circ
)) {
2032 if (CIRCUIT_IS_ORIGIN(circ
)) {
2033 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
2034 "Received CONFLUX_LINKED_ACK cell on an origin circuit. Closing.");
2038 if (!conflux_validate_source_hop(circ
, NULL
)) {
2039 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
2040 "Got a CONFLUX_LINKED_ACK with further hops. Closing circuit.");
2044 if (BUG(!circ
->conflux
)) {
2045 log_fn(LOG_PROTOCOL_WARN
, LD_CIRC
,
2046 "Received a CONFLUX_LINKED_ACK cell on a circuit that is not"
2047 "linked. Closing circuit.");
2051 log_info(LD_CIRC
, "Processing a CONFLUX_LINKED_ACK for set %s",
2052 fmt_nonce(circ
->conflux
->nonce
));
2054 /* Record the RTT for this circuit. This should not fail */
2055 if (BUG(!record_rtt(circ
, false))) {
2062 circuit_mark_for_close(circ
, END_CIRC_REASON_TORPROTOCOL
);
2065 /** Called when a circuit is freed.
2067 * It is possible a conflux circuit gets freed without being closed (for
2068 * instance SIGTERM) and so this callback is needed in order to finalize the
2071 conflux_circuit_about_to_free(circuit_t
*circ
)
2075 bool is_client
= CIRCUIT_IS_ORIGIN(circ
);
2077 if (circ
->conflux
) {
2078 linked_circuit_free(circ
, is_client
);
2079 } else if (circ
->conflux_pending_nonce
) {
2080 unlinked_circuit_free(circ
, is_client
);
2083 /* Whatever happens, nullify all conflux related pointers. */
2084 circ
->conflux
= NULL
;
2085 circ
->conflux_pending_nonce
= NULL
;
2088 /** Initialize the conflux pool subsystem. This is called by the subsys
2091 conflux_pool_init(void)
2093 if (!client_linked_pool
) {
2094 client_linked_pool
= digest256map_new();
2096 if (!client_unlinked_pool
) {
2097 client_unlinked_pool
= digest256map_new();
2099 if (!server_linked_pool
) {
2100 server_linked_pool
= digest256map_new();
2102 if (!server_unlinked_pool
) {
2103 server_unlinked_pool
= digest256map_new();
2108 * Return a description of all linked and unlinked circuits associated
2109 * with a conflux set.
2111 * For use in rare bug cases that are hard to diagnose.
2114 conflux_log_set(int loglevel
, const conflux_t
*cfx
, bool is_client
)
2120 "Conflux %s: %d linked, %d launched. Delivered: %"PRIu64
"; "
2121 "teardown: %d; Current: %p, Previous: %p",
2122 fmt_nonce(cfx
->nonce
), smartlist_len(cfx
->legs
),
2123 cfx
->num_leg_launch
,
2124 cfx
->last_seq_delivered
, cfx
->in_full_teardown
,
2125 cfx
->curr_leg
, cfx
->prev_leg
);
2127 // Log all linked legs
2129 CONFLUX_FOR_EACH_LEG_BEGIN(cfx
, leg
) {
2130 const struct congestion_control_t
*cc
= circuit_ccontrol(leg
->circ
);
2131 log_fn(loglevel
, LD_BUG
,
2132 " - Linked Leg %d purpose=%d; RTT %"PRIu64
", sent: %"PRIu64
2133 "; sent: %"PRIu64
", recv: %"PRIu64
", infl: %"PRIu64
", "
2134 "ptr: %p, idx: %d, marked: %d",
2135 legs
, leg
->circ
->purpose
, leg
->circ_rtts_usec
,
2136 leg
->linked_sent_usec
, leg
->last_seq_recv
,
2137 leg
->last_seq_sent
, cc
->inflight
, leg
->circ
,
2138 leg
->circ
->global_circuitlist_idx
,
2139 leg
->circ
->marked_for_close
);
2141 } CONFLUX_FOR_EACH_LEG_END(leg
);
2143 // Look up the nonce to see if we have any unlinked circuits.
2144 unlinked_circuits_t
*unlinked
= unlinked_pool_get(cfx
->nonce
, is_client
);
2146 // Log the number of legs and the is_for_linked_set status
2147 log_fn(loglevel
, LD_BUG
, " - Unlinked set: %d legs, for link: %d",
2148 smartlist_len(unlinked
->legs
), unlinked
->is_for_linked_set
);
2150 SMARTLIST_FOREACH_BEGIN(unlinked
->legs
, leg_t
*, leg
) {
2151 log_fn(loglevel
, LD_BUG
,
2152 " Unlinked Leg: %d purpose=%d; linked: %d, RTT %"PRIu64
", "
2153 "sent: %"PRIu64
" link ptr %p, circ ptr: %p, idx: %d, marked: %d",
2154 legs
, leg
->circ
->purpose
, leg
->linked
,
2155 leg
->rtt_usec
, leg
->link_sent_usec
,
2156 leg
->link
, leg
->circ
,
2157 leg
->circ
->global_circuitlist_idx
,
2158 leg
->circ
->marked_for_close
);
2160 } SMARTLIST_FOREACH_END(leg
);
2165 * Conflux needs a notification when tor_shutdown() begins, so that
2166 * when circuits are freed, new legs are not launched.
2168 * This needs a separate notification from conflux_pool_free_all(),
2169 * because circuits must be freed before that function.
2172 conflux_notify_shutdown(void)
2174 shutting_down
= true;
2177 #ifdef TOR_UNIT_TESTS
2179 * For unit tests: Clear the shutting down state so we resume building legs.
2182 conflux_clear_shutdown(void)
2184 shutting_down
= false;
2188 /** Free and clean up the conflux pool subsystem. This is called by the subsys
2189 * manager AFTER all circuits have been freed which implies that all objects in
2190 * the pools aren't referenced anymore. */
2192 conflux_pool_free_all(void)
2194 digest256map_free(client_linked_pool
, free_conflux_void_
);
2195 digest256map_free(server_linked_pool
, free_conflux_void_
);
2196 digest256map_free(client_unlinked_pool
, free_unlinked_void_
);
2197 digest256map_free(server_unlinked_pool
, free_unlinked_void_
);