123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- /* Copyright (c) 2007-2019, The Tor Project, Inc. */
- /* See LICENSE for licensing information */
- /**
- * \file btrack_circuit.c
- * \brief Bootstrap tracker for origin circuits
- *
- * Track state changes of origin circuits, as published by the circuit
- * subsystem.
- **/
- #include "core/or/or.h"
- #include "core/or/ocirc_event.h"
- #include "feature/control/btrack_circuit.h"
- #include "feature/control/control.h"
- #include "lib/log/log.h"
- /** Pair of a best origin circuit GID with its state or status */
- typedef struct btc_best_t {
- uint32_t gid;
- int val;
- } btc_best_t;
- /** GID and state of the best origin circuit we've seen so far */
- static btc_best_t best_any_state = { 0, -1 };
- /** GID and state of the best application circuit we've seen so far */
- static btc_best_t best_ap_state = { 0, -1 };
- /** GID and status of the best origin circuit we've seen so far */
- static btc_best_t best_any_evtype = { 0, -1 };
- /** GID and status of the best application circuit we've seen so far */
- static btc_best_t best_ap_evtype = { 0, -1 };
- /** Reset cached "best" values */
- static void
- btc_reset_bests(void)
- {
- best_any_state.gid = best_ap_state.gid = 0;
- best_any_state.val = best_ap_state.val = -1;
- best_any_evtype.gid = best_ap_state.gid = 0;
- best_any_evtype.val = best_ap_evtype.val = -1;
- }
- /** True if @a state is a "better" origin circuit state than @a best->val */
- static bool
- btc_state_better(int state, const btc_best_t *best)
- {
- return state > best->val;
- }
- /**
- * Definine an ordering on circuit status events
- *
- * The CIRC_EVENT_ constants aren't sorted in a useful order, so this
- * array helps to decode them. This approach depends on the statuses
- * being nonnegative and dense.
- **/
- static int circ_event_order[] = {
- [CIRC_EVENT_FAILED] = -1,
- [CIRC_EVENT_CLOSED] = -1,
- [CIRC_EVENT_LAUNCHED] = 1,
- [CIRC_EVENT_EXTENDED] = 2,
- [CIRC_EVENT_BUILT] = 3,
- };
- #define N_CIRC_EVENT_ORDER \
- (sizeof(circ_event_order) / sizeof(circ_event_order[0]))
- /** True if @a state is a "better" origin circuit event status than @a
- best->val */
- static bool
- btc_evtype_better(int state, const btc_best_t *best)
- {
- if (state < 0)
- return false;
- if (best->val < 0)
- return true;
- tor_assert(state >= 0 && (unsigned)state < N_CIRC_EVENT_ORDER);
- tor_assert(best->val >= 0 && (unsigned)best->val < N_CIRC_EVENT_ORDER);
- return circ_event_order[state] > circ_event_order[best->val];
- }
- static bool
- btc_update_state(const ocirc_state_msg_t *msg, btc_best_t *best,
- const char *type)
- {
- if (btc_state_better(msg->state, best)) {
- log_info(LD_BTRACK, "CIRC BEST_%s state %d->%d gid=%"PRIu32, type,
- best->val, msg->state, msg->gid);
- best->gid = msg->gid;
- best->val = msg->state;
- return true;
- }
- return false;
- }
- static bool
- btc_update_evtype(const ocirc_cevent_msg_t *msg, btc_best_t *best,
- const char *type)
- {
- if (btc_evtype_better(msg->evtype, best)) {
- log_info(LD_BTRACK, "CIRC BEST_%s evtype %d->%d gid=%"PRIu32, type,
- best->val, msg->evtype, msg->gid);
- best->gid = msg->gid;
- best->val = msg->evtype;
- return true;
- }
- return false;
- }
- DECLARE_SUBSCRIBE(ocirc_state, btc_state_rcvr);
- DECLARE_SUBSCRIBE(ocirc_cevent, btc_cevent_rcvr);
- DECLARE_SUBSCRIBE(ocirc_chan, btc_chan_rcvr);
- static void
- btc_state_rcvr(const msg_t *msg, const ocirc_state_msg_t *arg)
- {
- (void)msg;
- log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" state=%d onehop=%d",
- arg->gid, arg->state, arg->onehop);
- btc_update_state(arg, &best_any_state, "ANY");
- if (arg->onehop)
- return;
- btc_update_state(arg, &best_ap_state, "AP");
- }
- static void
- btc_cevent_rcvr(const msg_t *msg, const ocirc_cevent_msg_t *arg)
- {
- (void)msg;
- log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" evtype=%d reason=%d onehop=%d",
- arg->gid, arg->evtype, arg->reason, arg->onehop);
- btc_update_evtype(arg, &best_any_evtype, "ANY");
- if (arg->onehop)
- return;
- btc_update_evtype(arg, &best_ap_evtype, "AP");
- }
- static void
- btc_chan_rcvr(const msg_t *msg, const ocirc_chan_msg_t *arg)
- {
- (void)msg;
- log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" chan=%"PRIu64" onehop=%d",
- arg->gid, arg->chan, arg->onehop);
- }
- int
- btrack_circ_add_pubsub(pubsub_connector_t *connector)
- {
- if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_chan))
- return -1;
- if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_cevent))
- return -1;
- if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_state))
- return -1;
- return 0;
- }
- void
- btrack_circ_fini(void)
- {
- btc_reset_bests();
- }
|