[tor-commits] [tor/master] Expose consensus download statuses on the control port

nickm at torproject.org nickm at torproject.org
Thu Jun 30 17:43:09 UTC 2016


commit 8cf9fe5ba63c1c2b711d852b61e734c48cf482b5
Author: Andrea Shepard <andrea at torproject.org>
Date:   Mon Jun 27 16:38:37 2016 +0000

    Expose consensus download statuses on the control port
---
 src/or/control.c       | 176 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/or/networkstatus.c |  46 +++++++++++++
 src/or/networkstatus.h |   7 ++
 3 files changed, 229 insertions(+)

diff --git a/src/or/control.c b/src/or/control.c
index 6e5dcf6..35a949f 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -190,6 +190,8 @@ static void set_cached_network_liveness(int liveness);
 
 static void flush_queued_events_cb(evutil_socket_t fd, short what, void *arg);
 
+static char * download_status_to_string(const download_status_t *dl);
+
 /** Given a control event code for a message event, return the corresponding
  * log severity. */
 static inline int
@@ -2051,6 +2053,166 @@ getinfo_helper_dir(control_connection_t *control_conn,
   return 0;
 }
 
+/** Turn a download_status_t into a human-readable description in a newly
+ * allocated string. */
+
+static char *
+download_status_to_string(const download_status_t *dl)
+{
+  char *rv = NULL, *tmp;
+  char tbuf[ISO_TIME_LEN+1];
+  const char *schedule_str, *want_authority_str;
+  const char *increment_on_str, *backoff_str;
+
+  if (dl) {
+    /* Get some substrings of the eventual output ready */
+    format_iso_time(tbuf, dl->next_attempt_at);
+
+    switch (dl->schedule) {
+      case DL_SCHED_GENERIC:
+        schedule_str = "DL_SCHED_GENERIC";
+        break;
+      case DL_SCHED_CONSENSUS:
+        schedule_str = "DL_SCHED_CONSENSUS";
+        break;
+      case DL_SCHED_BRIDGE:
+        schedule_str = "DL_SCHED_BRIDGE";
+        break;
+      default:
+        schedule_str = "unknown";
+        break;
+    }
+
+    switch (dl->want_authority) {
+      case DL_WANT_ANY_DIRSERVER:
+        want_authority_str = "DL_WANT_ANY_DIRSERVER";
+        break;
+      case DL_WANT_AUTHORITY:
+        want_authority_str = "DL_WANT_AUTHORITY";
+        break;
+      default:
+        want_authority_str = "unknown";
+        break;
+    }
+
+    switch (dl->increment_on) {
+      case DL_SCHED_INCREMENT_FAILURE:
+        increment_on_str = "DL_SCHED_INCREMENT_FAILURE";
+        break;
+      case DL_SCHED_INCREMENT_ATTEMPT:
+        increment_on_str = "DL_SCHED_INCREMENT_ATTEMPT";
+        break;
+      default:
+        increment_on_str = "unknown";
+        break;
+    }
+
+    switch (dl->backoff) {
+      case DL_SCHED_DETERMINISTIC:
+        backoff_str = "DL_SCHED_DETERMINISTIC";
+        break;
+      case DL_SCHED_RANDOM_EXPONENTIAL:
+        backoff_str = "DL_SCHED_RANDOM_EXPONENTIAL";
+        break;
+      default:
+        backoff_str = "unknown";
+        break;
+    }
+
+    /* Now assemble them */
+    tor_asprintf(&tmp,
+                 "next-attempt-at %s\n"
+                 "n-download-failures %u\n"
+                 "n-download-attempts %u\n"
+                 "schedule %s\n"
+                 "want-authority %s\n"
+                 "increment-on %s\n"
+                 "backoff %s\n",
+                 tbuf,
+                 dl->n_download_failures,
+                 dl->n_download_attempts,
+                 schedule_str,
+                 want_authority_str,
+                 increment_on_str,
+                 backoff_str);
+
+    if (dl->backoff == DL_SCHED_RANDOM_EXPONENTIAL) {
+      /* Additional fields become relevant in random-exponential mode */
+      tor_asprintf(&rv,
+                   "%s"
+                   "last-backoff-position %u\n"
+                   "last-delay-used %d\n",
+                   tmp,
+                   dl->last_backoff_position,
+                   dl->last_delay_used);
+      tor_free(tmp);
+    } else {
+      /* That was it */
+      rv = tmp;
+    }
+  }
+
+  return rv;
+}
+
+/** Implementation helper for GETINFO: knows the answers for questions about
+ * download status information. */
+static int
+getinfo_helper_downloads(control_connection_t *control_conn,
+                   const char *question, char **answer,
+                   const char **errmsg)
+{
+  const char *flavor;
+  download_status_t *dl_to_emit = NULL;
+
+  /* Assert args are sane */
+  tor_assert(control_conn != NULL);
+  tor_assert(question != NULL);
+  tor_assert(answer != NULL);
+  tor_assert(errmsg != NULL);
+
+  /* We check for this later to see if we should supply a default */
+  *errmsg = NULL;
+
+  /* Are we after networkstatus downloads? */
+  if (!strcmpstart(question, "downloads/networkstatus/")) {
+    flavor = question + strlen("downloads/networkstatus/");
+    /*
+     * We get the one for the current bootstrapped status by default, or
+     * take an extra /bootstrap or /running suffix
+     */
+    if (strcmp(flavor, "ns") == 0) {
+      dl_to_emit = networkstatus_get_dl_status_by_flavor(FLAV_NS);
+    } else if (strcmp(flavor, "ns/bootstrap") == 0) {
+      dl_to_emit = networkstatus_get_dl_status_by_flavor_bootstrap(FLAV_NS);
+    } else if (strcmp(flavor, "ns/running") == 0 ) {
+      dl_to_emit = networkstatus_get_dl_status_by_flavor_running(FLAV_NS);
+    } else if (strcmp(flavor, "microdesc") == 0) {
+      dl_to_emit = networkstatus_get_dl_status_by_flavor(FLAV_MICRODESC);
+    } else if (strcmp(flavor, "microdesc/bootstrap") == 0) {
+      dl_to_emit =
+        networkstatus_get_dl_status_by_flavor_bootstrap(FLAV_MICRODESC);
+    } else if (strcmp(flavor, "microdesc/running") == 0) {
+      dl_to_emit =
+        networkstatus_get_dl_status_by_flavor_running(FLAV_MICRODESC);
+    } else {
+      *errmsg = "Unknown flavor";
+    }
+  }
+
+  if (dl_to_emit) {
+    *answer = download_status_to_string(dl_to_emit);
+
+    return 0;
+  } else {
+    if (!(*errmsg)) {
+      *errmsg = "Unknown error";
+    }
+
+    return -1;
+  }
+}
+
 /** Allocate and return a description of <b>circ</b>'s current status,
  * including its path (if any). */
 static char *
@@ -2490,6 +2652,20 @@ static const getinfo_item_t getinfo_items[] = {
   DOC("config/defaults",
       "List of default values for configuration options. "
       "See also config/names"),
+  PREFIX("downloads/networkstatus/", downloads,
+         "Download statuses for networkstatus objects"),
+  DOC("downloads/networkstatus/ns",
+      "Download status for current-mode networkstatus download"),
+  DOC("downloads/networkstatus/ns/bootstrap",
+      "Download status for bootstrap-time networkstatus download"),
+  DOC("downloads/networkstatus/ns/running",
+      "Download status for run-time networkstatus download"),
+  DOC("downloads/networkstatus/microdesc",
+      "Download status for current-mode microdesc download"),
+  DOC("downloads/networkstatus/microdesc/bootstrap",
+      "Download status for bootstrap-time microdesc download"),
+  DOC("downloads/networkstatus/microdesc/running",
+      "Download status for run-time microdesc download"),
   ITEM("info/names", misc,
        "List of GETINFO options, types, and documentation."),
   ITEM("events/names", misc,
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 3471288..45688b1 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -1179,6 +1179,52 @@ consensus_is_waiting_for_certs(void)
     ? 1 : 0;
 }
 
+/** Look up the currently active (depending on bootstrap status) download
+ * status for this consensus flavor and return a pointer to it.
+ */
+download_status_t *
+networkstatus_get_dl_status_by_flavor(consensus_flavor_t flavor)
+{
+  download_status_t *dl = NULL;
+  const int we_are_bootstrapping =
+    networkstatus_consensus_is_bootstrapping(time(NULL));
+
+  if (flavor <= N_CONSENSUS_FLAVORS) {
+    dl = &((we_are_bootstrapping ?
+           consensus_bootstrap_dl_status : consensus_dl_status)[flavor]);
+  }
+
+  return dl;
+}
+
+/** Look up the bootstrap download status for this consensus flavor
+ * and return a pointer to it. */
+download_status_t *
+networkstatus_get_dl_status_by_flavor_bootstrap(consensus_flavor_t flavor)
+{
+  download_status_t *dl = NULL;
+
+  if (flavor <= N_CONSENSUS_FLAVORS) {
+    dl = &(consensus_bootstrap_dl_status[flavor]);
+  }
+
+  return dl;
+}
+
+/** Look up the running (non-bootstrap) download status for this consensus
+ * flavor and return a pointer to it. */
+download_status_t *
+networkstatus_get_dl_status_by_flavor_running(consensus_flavor_t flavor)
+{
+  download_status_t *dl = NULL;
+
+  if (flavor <= N_CONSENSUS_FLAVORS) {
+    dl = &(consensus_dl_status[flavor]);
+  }
+
+  return dl;
+}
+
 /** Return the most recent consensus that we have downloaded, or NULL if we
  * don't have one. */
 networkstatus_t *
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index aee6641..752ddf8 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -38,6 +38,13 @@ routerstatus_t *networkstatus_vote_find_mutable_entry(networkstatus_t *ns,
 int networkstatus_vote_find_entry_idx(networkstatus_t *ns,
                                       const char *digest, int *found_out);
 
+download_status_t * networkstatus_get_dl_status_by_flavor(
+                                            consensus_flavor_t flavor);
+download_status_t * networkstatus_get_dl_status_by_flavor_bootstrap(
+                                            consensus_flavor_t flavor);
+download_status_t * networkstatus_get_dl_status_by_flavor_running(
+                                            consensus_flavor_t flavor);
+
 MOCK_DECL(download_status_t *,router_get_dl_status_by_descriptor_digest,
           (const char *d));
 





More information about the tor-commits mailing list