[tor-commits] [tor/master] Add router descriptor download status queries to GETINFO

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


commit 8798ca4be299855a9a87a48df772081e06e9040c
Author: Andrea Shepard <andrea at torproject.org>
Date:   Tue Jun 28 02:21:39 2016 +0000

    Add router descriptor download status queries to GETINFO
---
 src/or/control.c       | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/or/networkstatus.c | 37 +++++++++++++++++++++++++++++++++
 src/or/networkstatus.h |  1 +
 3 files changed, 94 insertions(+)

diff --git a/src/or/control.c b/src/or/control.c
index a45b5f9..7b8699d 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -2307,6 +2307,52 @@ getinfo_helper_downloads_cert(const char *fp_sk_req,
   }
 }
 
+/** Handle the routerdesc download cases for getinfo_helper_downloads() */
+static void
+getinfo_helper_downloads_desc(const char *desc_req,
+                              download_status_t **dl_to_emit,
+                              smartlist_t **digest_list,
+                              const char **errmsg)
+{
+  char desc_digest[DIGEST_LEN];
+  /*
+   * Two cases to handle here:
+   *
+   * Case 1: desc_req = "descs"
+   *   - Emit a list of all router descriptor digests, which we get by
+   *     calling router_get_descriptor_digests(); this can return NULL
+   *     if we have no current ns-flavor consensus.
+   *
+   * Case 2: desc_req = <fp>
+   *   - Check on the specified fingerprint and emit its download_status_t
+   *     using router_get_dl_status_by_descriptor_digest().
+   */
+
+  if (strcmp(desc_req, "descs") == 0) {
+    *digest_list = router_get_descriptor_digests();
+    if (!(*digest_list)) {
+      *errmsg = "We don't seem to have a networkstatus-flavored consensus";
+    }
+    /*
+     * Microdescs don't use the download_status_t mechanism, so we don't
+     * answer queries about their downloads here; see microdesc.c.
+     */
+  } else if (strlen(desc_req) == HEX_DIGEST_LEN) {
+    if (base16_decode(desc_digest, DIGEST_LEN,
+                      desc_req, strlen(desc_req)) == DIGEST_LEN) {
+      /* Okay we got a digest-shaped thing; try asking for it */
+      *dl_to_emit = router_get_dl_status_by_descriptor_digest(desc_digest);
+      if (!(*dl_to_emit)) {
+        *errmsg = "No such descriptor digest found";
+      }
+    } else {
+      *errmsg = "That didn't look like a digest";
+    }
+  } else {
+    *errmsg = "Unknown router descriptor download status query";
+  }
+}
+
 /** Implementation helper for GETINFO: knows the answers for questions about
  * download status information. */
 static int
@@ -2335,6 +2381,10 @@ getinfo_helper_downloads(control_connection_t *control_conn,
     getinfo_helper_downloads_cert(
         question + strlen("downloads/cert/"),
         &dl_to_emit, &digest_list, errmsg);
+  } else if (!strcmpstart(question, "downloads/desc/")) {
+    getinfo_helper_downloads_desc(
+        question + strlen("downloads/desc/"),
+        &dl_to_emit, &digest_list, errmsg);
   } else {
     *errmsg = "Unknown download status query";
   }
@@ -2826,6 +2876,12 @@ static const getinfo_item_t getinfo_items[] = {
   DOC("downloads/cert/fp/<fp>/<sk>",
       "Download status for <fp> with signing key <sk>; corresponds "
       "to /fp-sk/ URLs on directory server."),
+  PREFIX("downloads/desc/", downloads,
+         "Download statuses for router descriptors, by descriptor digest"),
+  DOC("downloads/desc/descs",
+      "Return a list of known router descriptor digests"),
+  DOC("downloads/desc/<desc>",
+      "Return a download status for a given descriptor digest"),
   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 45688b1..a582b85 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -659,6 +659,43 @@ router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus,
                                                           consensus, digest);
 }
 
+/** Return a smartlist of all router descriptor digests in a consensus */
+static smartlist_t *
+router_get_descriptor_digests_in_consensus(networkstatus_t *consensus)
+{
+  smartlist_t *result = smartlist_new();
+  digestmap_iter_t *i;
+  const char *digest;
+  void *rs;
+  char *digest_tmp;
+
+  for (i = digestmap_iter_init(consensus->desc_digest_map);
+       !(digestmap_iter_done(i));
+       i = digestmap_iter_next(consensus->desc_digest_map, i)) {
+    digestmap_iter_get(i, &digest, &rs);
+    digest_tmp = tor_malloc(DIGEST_LEN);
+    memcpy(digest_tmp, digest, DIGEST_LEN);
+    smartlist_add(result, digest_tmp);
+  }
+
+  return result;
+}
+
+/** Return a smartlist of all router descriptor digests in the current
+ * consensus */
+smartlist_t *
+router_get_descriptor_digests(void)
+{
+  smartlist_t *result = NULL;
+
+  if (current_ns_consensus) {
+    result =
+      router_get_descriptor_digests_in_consensus(current_ns_consensus);
+  }
+
+  return result;
+}
+
 /** Given the digest of a router descriptor, return its current download
  * status, or NULL if the digest is unrecognized. */
 MOCK_IMPL(download_status_t *,
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index 752ddf8..6d5d05a 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -45,6 +45,7 @@ download_status_t * networkstatus_get_dl_status_by_flavor_bootstrap(
 download_status_t * networkstatus_get_dl_status_by_flavor_running(
                                             consensus_flavor_t flavor);
 
+smartlist_t * router_get_descriptor_digests(void);
 MOCK_DECL(download_status_t *,router_get_dl_status_by_descriptor_digest,
           (const char *d));
 





More information about the tor-commits mailing list