LCOV - code coverage report
Current view: top level - feature/control - btrack_circuit.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 49 53 92.5 %
Date: 2021-11-24 03:28:48 Functions: 13 13 100.0 %

          Line data    Source code
       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         235 : btc_reset_bests(void)
      38             : {
      39         235 :   best_any_state.gid = best_ap_state.gid = 0;
      40         235 :   best_any_state.val = best_ap_state.val = -1;
      41         235 :   best_any_evtype.gid = best_ap_state.gid = 0;
      42         235 :   best_any_evtype.val = best_ap_evtype.val = -1;
      43         235 : }
      44             : 
      45             : /** True if @a state is a "better" origin circuit state than @a best->val */
      46             : static bool
      47           2 : btc_state_better(int state, const btc_best_t *best)
      48             : {
      49           2 :   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           2 : btc_evtype_better(int state, const btc_best_t *best)
      73             : {
      74           2 :   if (state < 0)
      75             :     return false;
      76           2 :   if (best->val < 0)
      77             :     return true;
      78             : 
      79           0 :   tor_assert(state >= 0 && (unsigned)state < N_CIRC_EVENT_ORDER);
      80           0 :   tor_assert(best->val >= 0 && (unsigned)best->val < N_CIRC_EVENT_ORDER);
      81           0 :   return circ_event_order[state] > circ_event_order[best->val];
      82             : }
      83             : 
      84             : static bool
      85           2 : btc_update_state(const ocirc_state_msg_t *msg, btc_best_t *best,
      86             :                  const char *type)
      87             : {
      88           2 :   if (btc_state_better(msg->state, best)) {
      89           2 :     log_info(LD_BTRACK, "CIRC BEST_%s state %d->%d gid=%"PRIu32, type,
      90             :              best->val, msg->state, msg->gid);
      91           2 :     best->gid = msg->gid;
      92           2 :     best->val = msg->state;
      93           2 :     return true;
      94             :   }
      95             :   return false;
      96             : }
      97             : 
      98             : static bool
      99           2 : btc_update_evtype(const ocirc_cevent_msg_t *msg, btc_best_t *best,
     100             :                   const char *type)
     101             : {
     102           2 :   if (btc_evtype_better(msg->evtype, best)) {
     103           2 :     log_info(LD_BTRACK, "CIRC BEST_%s evtype %d->%d gid=%"PRIu32, type,
     104             :              best->val, msg->evtype, msg->gid);
     105           2 :     best->gid = msg->gid;
     106           2 :     best->val = msg->evtype;
     107           2 :     return true;
     108             :   }
     109             :   return false;
     110             : }
     111             : 
     112           1 : DECLARE_SUBSCRIBE(ocirc_state, btc_state_rcvr);
     113           1 : DECLARE_SUBSCRIBE(ocirc_cevent, btc_cevent_rcvr);
     114           8 : DECLARE_SUBSCRIBE(ocirc_chan, btc_chan_rcvr);
     115             : 
     116             : static void
     117           1 : btc_state_rcvr(const msg_t *msg, const ocirc_state_msg_t *arg)
     118             : {
     119           1 :   (void)msg;
     120           1 :   log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" state=%d onehop=%d",
     121             :             arg->gid, arg->state, arg->onehop);
     122             : 
     123           1 :   btc_update_state(arg, &best_any_state, "ANY");
     124           1 :   if (arg->onehop)
     125             :     return;
     126           1 :   btc_update_state(arg, &best_ap_state, "AP");
     127             : }
     128             : 
     129             : static void
     130           1 : btc_cevent_rcvr(const msg_t *msg, const ocirc_cevent_msg_t *arg)
     131             : {
     132           1 :   (void)msg;
     133           1 :   log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" evtype=%d reason=%d onehop=%d",
     134             :             arg->gid, arg->evtype, arg->reason, arg->onehop);
     135             : 
     136           1 :   btc_update_evtype(arg, &best_any_evtype, "ANY");
     137           1 :   if (arg->onehop)
     138             :     return;
     139           1 :   btc_update_evtype(arg, &best_ap_evtype, "AP");
     140             : }
     141             : 
     142             : static void
     143           8 : btc_chan_rcvr(const msg_t *msg, const ocirc_chan_msg_t *arg)
     144             : {
     145           8 :   (void)msg;
     146           8 :   log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" chan=%"PRIu64" onehop=%d",
     147             :             arg->gid, arg->chan, arg->onehop);
     148           8 : }
     149             : 
     150             : int
     151         245 : btrack_circ_add_pubsub(pubsub_connector_t *connector)
     152             : {
     153         245 :   if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_chan))
     154             :     return -1;
     155         245 :   if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_cevent))
     156             :     return -1;
     157         245 :   if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_state))
     158           0 :     return -1;
     159             :   return 0;
     160             : }
     161             : 
     162             : void
     163         235 : btrack_circ_fini(void)
     164             : {
     165         235 :   btc_reset_bests();
     166         235 : }

Generated by: LCOV version 1.14