btrack_circuit.c (4540B)
1 /* Copyright (c) 2007-2021, The Tor Project, Inc. */ 2 /* See LICENSE for licensing information */ 3 4 /** 5 * \file btrack_circuit.c 6 * \brief Bootstrap tracker for origin circuits 7 * 8 * Track state changes of origin circuits, as published by the circuit 9 * subsystem. 10 **/ 11 12 #include "core/or/or.h" 13 14 #include "core/or/ocirc_event.h" 15 16 #include "feature/control/btrack_circuit.h" 17 #include "feature/control/control.h" 18 #include "lib/log/log.h" 19 20 /** Pair of a best origin circuit GID with its state or status */ 21 typedef struct btc_best_t { 22 uint32_t gid; 23 int val; 24 } btc_best_t; 25 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 }; 34 35 /** Reset cached "best" values */ 36 static void 37 btc_reset_bests(void) 38 { 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; 43 } 44 45 /** True if @a state is a "better" origin circuit state than @a best->val */ 46 static bool 47 btc_state_better(int state, const btc_best_t *best) 48 { 49 return state > best->val; 50 } 51 52 /** 53 * Definine an ordering on circuit status events 54 * 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. 58 **/ 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, 65 }; 66 #define N_CIRC_EVENT_ORDER \ 67 (sizeof(circ_event_order) / sizeof(circ_event_order[0])) 68 69 /** True if @a state is a "better" origin circuit event status than @a 70 best->val */ 71 static bool 72 btc_evtype_better(int state, const btc_best_t *best) 73 { 74 if (state < 0) 75 return false; 76 if (best->val < 0) 77 return true; 78 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]; 82 } 83 84 static bool 85 btc_update_state(const ocirc_state_msg_t *msg, btc_best_t *best, 86 const char *type) 87 { 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); 91 best->gid = msg->gid; 92 best->val = msg->state; 93 return true; 94 } 95 return false; 96 } 97 98 static bool 99 btc_update_evtype(const ocirc_cevent_msg_t *msg, btc_best_t *best, 100 const char *type) 101 { 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; 107 return true; 108 } 109 return false; 110 } 111 112 DECLARE_SUBSCRIBE(ocirc_state, btc_state_rcvr); 113 DECLARE_SUBSCRIBE(ocirc_cevent, btc_cevent_rcvr); 114 DECLARE_SUBSCRIBE(ocirc_chan, btc_chan_rcvr); 115 116 static void 117 btc_state_rcvr(const msg_t *msg, const ocirc_state_msg_t *arg) 118 { 119 (void)msg; 120 log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" state=%d onehop=%d", 121 arg->gid, arg->state, arg->onehop); 122 123 btc_update_state(arg, &best_any_state, "ANY"); 124 if (arg->onehop) 125 return; 126 btc_update_state(arg, &best_ap_state, "AP"); 127 } 128 129 static void 130 btc_cevent_rcvr(const msg_t *msg, const ocirc_cevent_msg_t *arg) 131 { 132 (void)msg; 133 log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" evtype=%d reason=%d onehop=%d", 134 arg->gid, arg->evtype, arg->reason, arg->onehop); 135 136 btc_update_evtype(arg, &best_any_evtype, "ANY"); 137 if (arg->onehop) 138 return; 139 btc_update_evtype(arg, &best_ap_evtype, "AP"); 140 } 141 142 static void 143 btc_chan_rcvr(const msg_t *msg, const ocirc_chan_msg_t *arg) 144 { 145 (void)msg; 146 log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" chan=%"PRIu64" onehop=%d", 147 arg->gid, arg->chan, arg->onehop); 148 } 149 150 int 151 btrack_circ_add_pubsub(pubsub_connector_t *connector) 152 { 153 if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_chan)) 154 return -1; 155 if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_cevent)) 156 return -1; 157 if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_state)) 158 return -1; 159 return 0; 160 } 161 162 void 163 btrack_circ_fini(void) 164 { 165 btc_reset_bests(); 166 }