Tor  0.4.7.0-alpha-dev
btrack_circuit.c
Go to the documentation of this file.
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 
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
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 }
static btc_best_t best_ap_evtype
static int circ_event_order[]
static btc_best_t best_ap_state
static bool btc_state_better(int state, const btc_best_t *best)
static btc_best_t best_any_evtype
static btc_best_t best_any_state
static bool btc_evtype_better(int state, const btc_best_t *best)
static void btc_reset_bests(void)
Header file for btrack_circuit.c.
Header file for control.c.
Headers for log.c.
#define LD_BTRACK
Definition: log.h:119
Header file for ocirc_event.c.
Master header file for Tor-specific functionality.
struct pubsub_connector_t pubsub_connector_t
#define DISPATCH_ADD_SUB(connector, channel, messagename)
#define DECLARE_SUBSCRIBE(messagename, hookfn)
Definition: msgtypes.h:50
#define tor_assert(expr)
Definition: util_bug.h:102