1 /* Copyright (c) 2007-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
5 * \file btrack_circuit.c
6 * \brief Bootstrap tracker for origin circuits
8 * Track state changes of origin circuits, as published by the circuit
12 #include "core/or/or.h"
14 #include "core/or/ocirc_event.h"
16 #include "feature/control/btrack_circuit.h"
17 #include "feature/control/control.h"
18 #include "lib/log/log.h"
20 /** Pair of a best origin circuit GID with its state or status */
21 typedef struct btc_best_t
{
26 /** GID and state of the best origin circuit we've seen so far */
27 static btc_best_t best_any_state
= { 0, -1 };
28 /** GID and state of the best application circuit we've seen so far */
29 static btc_best_t best_ap_state
= { 0, -1 };
30 /** GID and status of the best origin circuit we've seen so far */
31 static btc_best_t best_any_evtype
= { 0, -1 };
32 /** GID and status of the best application circuit we've seen so far */
33 static btc_best_t best_ap_evtype
= { 0, -1 };
35 /** Reset cached "best" values */
39 best_any_state
.gid
= best_ap_state
.gid
= 0;
40 best_any_state
.val
= best_ap_state
.val
= -1;
41 best_any_evtype
.gid
= best_ap_state
.gid
= 0;
42 best_any_evtype
.val
= best_ap_evtype
.val
= -1;
45 /** True if @a state is a "better" origin circuit state than @a best->val */
47 btc_state_better(int state
, const btc_best_t
*best
)
49 return state
> best
->val
;
53 * Definine an ordering on circuit status events
55 * The CIRC_EVENT_ constants aren't sorted in a useful order, so this
56 * array helps to decode them. This approach depends on the statuses
57 * being nonnegative and dense.
59 static int circ_event_order
[] = {
60 [CIRC_EVENT_FAILED
] = -1,
61 [CIRC_EVENT_CLOSED
] = -1,
62 [CIRC_EVENT_LAUNCHED
] = 1,
63 [CIRC_EVENT_EXTENDED
] = 2,
64 [CIRC_EVENT_BUILT
] = 3,
66 #define N_CIRC_EVENT_ORDER \
67 (sizeof(circ_event_order) / sizeof(circ_event_order[0]))
69 /** True if @a state is a "better" origin circuit event status than @a
72 btc_evtype_better(int state
, const btc_best_t
*best
)
79 tor_assert(state
>= 0 && (unsigned)state
< N_CIRC_EVENT_ORDER
);
80 tor_assert(best
->val
>= 0 && (unsigned)best
->val
< N_CIRC_EVENT_ORDER
);
81 return circ_event_order
[state
] > circ_event_order
[best
->val
];
85 btc_update_state(const ocirc_state_msg_t
*msg
, btc_best_t
*best
,
88 if (btc_state_better(msg
->state
, best
)) {
89 log_info(LD_BTRACK
, "CIRC BEST_%s state %d->%d gid=%"PRIu32
, type
,
90 best
->val
, msg
->state
, msg
->gid
);
92 best
->val
= msg
->state
;
99 btc_update_evtype(const ocirc_cevent_msg_t
*msg
, btc_best_t
*best
,
102 if (btc_evtype_better(msg
->evtype
, best
)) {
103 log_info(LD_BTRACK
, "CIRC BEST_%s evtype %d->%d gid=%"PRIu32
, type
,
104 best
->val
, msg
->evtype
, msg
->gid
);
105 best
->gid
= msg
->gid
;
106 best
->val
= msg
->evtype
;
112 DECLARE_SUBSCRIBE(ocirc_state
, btc_state_rcvr
);
113 DECLARE_SUBSCRIBE(ocirc_cevent
, btc_cevent_rcvr
);
114 DECLARE_SUBSCRIBE(ocirc_chan
, btc_chan_rcvr
);
117 btc_state_rcvr(const msg_t
*msg
, const ocirc_state_msg_t
*arg
)
120 log_debug(LD_BTRACK
, "CIRC gid=%"PRIu32
" state=%d onehop=%d",
121 arg
->gid
, arg
->state
, arg
->onehop
);
123 btc_update_state(arg
, &best_any_state
, "ANY");
126 btc_update_state(arg
, &best_ap_state
, "AP");
130 btc_cevent_rcvr(const msg_t
*msg
, const ocirc_cevent_msg_t
*arg
)
133 log_debug(LD_BTRACK
, "CIRC gid=%"PRIu32
" evtype=%d reason=%d onehop=%d",
134 arg
->gid
, arg
->evtype
, arg
->reason
, arg
->onehop
);
136 btc_update_evtype(arg
, &best_any_evtype
, "ANY");
139 btc_update_evtype(arg
, &best_ap_evtype
, "AP");
143 btc_chan_rcvr(const msg_t
*msg
, const ocirc_chan_msg_t
*arg
)
146 log_debug(LD_BTRACK
, "CIRC gid=%"PRIu32
" chan=%"PRIu64
" onehop=%d",
147 arg
->gid
, arg
->chan
, arg
->onehop
);
151 btrack_circ_add_pubsub(pubsub_connector_t
*connector
)
153 if (DISPATCH_ADD_SUB(connector
, ocirc
, ocirc_chan
))
155 if (DISPATCH_ADD_SUB(connector
, ocirc
, ocirc_cevent
))
157 if (DISPATCH_ADD_SUB(connector
, ocirc
, ocirc_state
))
163 btrack_circ_fini(void)