Commit b0ae6a33 authored by Taylor Yu's avatar Taylor Yu
Browse files

Add bootstrap tracker subsystem

Add a tracker for bootstrap progress, tracking events related to
origin circuit and ORCONN states.  This uses the ocirc_event and
orconn_event publish-subscribe subsystems.

Part of ticket 27167.
parent b0f97463
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@

#include "core/or/ocirc_event_sys.h"
#include "core/or/orconn_event_sys.h"
#include "feature/control/btrack_sys.h"
#include "lib/compress/compress_sys.h"
#include "lib/crypt_ops/crypto_sys.h"
#include "lib/err/torerr_sys.h"
@@ -39,6 +40,7 @@ const subsys_fns_t *tor_subsystems[] = {
  &sys_tortls, /* -50 */
  &sys_orconn_event, /* -40 */
  &sys_ocirc_event, /* -39 */
  &sys_btrack, /* -30 */
};

const unsigned n_tor_subsystems = ARRAY_LENGTH(tor_subsystems);
+8 −0
Original line number Diff line number Diff line
@@ -63,6 +63,10 @@ LIBTOR_APP_A_SOURCES = \
	src/feature/client/dnsserv.c		\
	src/feature/client/entrynodes.c		\
	src/feature/client/transports.c		\
	src/feature/control/btrack.c		\
	src/feature/control/btrack_circuit.c	\
	src/feature/control/btrack_orconn.c	\
	src/feature/control/btrack_orconn_maps.c	\
	src/feature/control/control.c		\
	src/feature/control/control_bootstrap.c	\
	src/feature/control/fmt_serverstatus.c  \
@@ -274,6 +278,10 @@ noinst_HEADERS += \
	src/feature/client/dnsserv.h			\
	src/feature/client/entrynodes.h			\
	src/feature/client/transports.h			\
	src/feature/control/btrack_circuit.h		\
	src/feature/control/btrack_orconn.h		\
	src/feature/control/btrack_orconn_maps.h	\
	src/feature/control/btrack_sys.h		\
	src/feature/control/control.h			\
	src/feature/control/control_connection_st.h	\
	src/feature/control/fmt_serverstatus.h		\
+53 −0
Original line number Diff line number Diff line
/* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */

/**
 * \file btrack.c
 * \brief Bootstrap trackers
 *
 * Initializes and shuts down the specific bootstrap trackers.  These
 * trackers help the reporting of bootstrap progress by maintaining
 * state information about various subsystems within tor.  When the
 * correct state changes happen, these trackers emit controller
 * events.
 *
 * These trackers avoid referring directly to the internals of state
 * objects of other subsystems.
 *
 * btrack_circuit.c contains the tracker for origin circuits.
 *
 * btrack_orconn.c contains the tracker for OR connections.
 *
 * Eventually there will be a tracker for directory downloads as well.
 **/

#include "feature/control/btrack_circuit.h"
#include "feature/control/btrack_orconn.h"
#include "feature/control/btrack_sys.h"
#include "lib/subsys/subsys.h"

static int
btrack_init(void)
{
  if (btrack_orconn_init())
    return -1;
  if (btrack_circ_init())
    return -1;

  return 0;
}

static void
btrack_fini(void)
{
  btrack_orconn_fini();
  btrack_circ_fini();
}

const subsys_fns_t sys_btrack = {
  .name = "btrack",
  .supported = true,
  .level = -30,
  .initialize = btrack_init,
  .shutdown = btrack_fini,
};
+164 −0
Original line number Diff line number Diff line
/* Copyright (c) 2007-2018, 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;
}

static void
btc_state_rcvr(const ocirc_state_msg_t *msg)
{
  log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" state=%d onehop=%d",
            msg->gid, msg->state, msg->onehop);

  btc_update_state(msg, &best_any_state, "ANY");
  if (msg->onehop)
    return;
  btc_update_state(msg, &best_ap_state, "AP");
}

static void
btc_cevent_rcvr(const ocirc_cevent_msg_t *msg)
{
  log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" evtype=%d reason=%d onehop=%d",
            msg->gid, msg->evtype, msg->reason, msg->onehop);

  btc_update_evtype(msg, &best_any_evtype, "ANY");
  if (msg->onehop)
    return;
  btc_update_evtype(msg, &best_ap_evtype, "AP");
}

static void
btc_event_rcvr(const ocirc_event_msg_t *msg)
{
  switch (msg->type) {
  case OCIRC_MSGTYPE_STATE:
    return btc_state_rcvr(&msg->u.state);
  case OCIRC_MSGTYPE_CHAN:
    log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" chan=%"PRIu64" onehop=%d",
              msg->u.chan.gid, msg->u.chan.chan, msg->u.chan.onehop);
    break;
  case OCIRC_MSGTYPE_CEVENT:
    return btc_cevent_rcvr(&msg->u.cevent);
  default:
    break;
  }
}

int
btrack_circ_init(void)
{
  ocirc_event_subscribe(btc_event_rcvr);
  return 0;
}

void
btrack_circ_fini(void)
{
  btc_reset_bests();
}
+15 −0
Original line number Diff line number Diff line
/* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */

/**
 * \file btrack_circuit.h
 * \brief Header file for btrack_circuit.c
 **/

#ifndef TOR_BTRACK_CIRCUIT_H
#define TOR_BTRACK_CIRCUIT_H

int btrack_circ_init(void);
void btrack_circ_fini(void);

#endif  /* defined(TOR_BTRACK_CIRCUIT_H) */
Loading