Browse Source

Merge remote-tracking branch 'rl1987/feature8323_squashed2'

Nick Mathewson 6 years ago
parent
commit
5746e210b8
3 changed files with 102 additions and 0 deletions
  1. 3 0
      changes/feature8323
  2. 23 0
      src/or/control.c
  3. 76 0
      src/test/test_controller.c

+ 3 - 0
changes/feature8323

@@ -0,0 +1,3 @@
+  o Minor features (controller):
+    - Implement 'GETINFO md/all' controller command to enable
+      getting all known microdesriptors. Closes ticket 8323.

+ 23 - 0
src/or/control.c

@@ -2207,6 +2207,27 @@ getinfo_helper_dir(control_connection_t *control_conn,
         return -1;
       }
     }
+  } else if (!strcmp(question, "md/all")) {
+    const smartlist_t *nodes = nodelist_get_list();
+    tor_assert(nodes);
+
+    if (smartlist_len(nodes) == 0) {
+      *answer = tor_strdup("");
+      return 0;
+    }
+
+    smartlist_t *microdescs = smartlist_new();
+
+    SMARTLIST_FOREACH_BEGIN(nodes, node_t *, n) {
+      if (n->md && n->md->body) {
+        char *copy = tor_strndup(n->md->body, n->md->bodylen);
+        smartlist_add(microdescs, copy);
+      }
+    } SMARTLIST_FOREACH_END(n);
+
+    *answer = smartlist_join_strings(microdescs, "", 0, NULL);
+    SMARTLIST_FOREACH(microdescs, char *, md, tor_free(md));
+    smartlist_free(microdescs);
   } else if (!strcmpstart(question, "md/id/")) {
     const node_t *node = node_get_by_hex_id(question+strlen("md/id/"), 0);
     const microdesc_t *md = NULL;
@@ -3241,6 +3262,7 @@ static const getinfo_item_t getinfo_items[] = {
   ITEM("desc/download-enabled", dir,
        "Do we try to download router descriptors?"),
   ITEM("desc/all-recent-extrainfo-hack", dir, NULL), /* Hack. */
+  ITEM("md/all", dir, "All known microdescriptors."),
   PREFIX("md/id/", dir, "Microdescriptors by ID"),
   PREFIX("md/name/", dir, "Microdescriptors by name"),
   ITEM("md/download-enabled", dir,
@@ -3400,6 +3422,7 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len,
                          SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
   SMARTLIST_FOREACH_BEGIN(questions, const char *, q) {
     const char *errmsg = NULL;
+
     if (handle_getinfo_helper(conn, q, &ans, &errmsg) < 0) {
       if (!errmsg)
         errmsg = "Internal error";

+ 76 - 0
src/test/test_controller.c

@@ -10,6 +10,7 @@
 #include "networkstatus.h"
 #include "rendservice.h"
 #include "routerlist.h"
+#include "nodelist.h"
 #include "test.h"
 #include "test_helpers.h"
 
@@ -1525,6 +1526,80 @@ test_current_time(void *arg)
   return;
 }
 
+static size_t n_nodelist_get_list = 0;
+static smartlist_t *nodes = NULL;
+
+static smartlist_t *
+mock_nodelist_get_list(void)
+{
+  n_nodelist_get_list++;
+  tor_assert(nodes);
+
+  return nodes;
+}
+
+static void
+test_getinfo_md_all(void *arg)
+{
+  char *answer = NULL;
+  const char *errmsg = NULL;
+  int retval = 0;
+
+  (void)arg;
+
+  node_t *node1 = tor_malloc(sizeof(node_t));
+  memset(node1, 0, sizeof(node_t));
+  node1->md = tor_malloc(sizeof(microdesc_t));
+  memset(node1->md, 0, sizeof(microdesc_t));
+  node1->md->body = tor_strdup("md1\n");
+  node1->md->bodylen = 4;
+
+  node_t *node2 = tor_malloc(sizeof(node_t));
+  memset(node2, 0, sizeof(node_t));
+  node2->md = tor_malloc(sizeof(microdesc_t));
+  memset(node2->md, 0, sizeof(microdesc_t));
+  node2->md->body = tor_strdup("md2\n");
+  node2->md->bodylen = 4;
+
+  MOCK(nodelist_get_list, mock_nodelist_get_list);
+
+  nodes = smartlist_new();
+
+  retval = getinfo_helper_dir(NULL, "md/all", &answer, &errmsg);
+
+  tt_int_op(n_nodelist_get_list, OP_EQ, 1);
+  tt_int_op(retval, OP_EQ, 0);
+  tt_assert(answer != NULL);
+  tt_assert(errmsg == NULL);
+  tt_str_op(answer, OP_EQ, "");
+
+  tor_free(answer);
+
+  smartlist_add(nodes, node1);
+  smartlist_add(nodes, node2);
+
+  retval = getinfo_helper_dir(NULL, "md/all", &answer, &errmsg);
+
+  tt_int_op(n_nodelist_get_list, OP_EQ, 2);
+  tt_int_op(retval, OP_EQ, 0);
+  tt_assert(answer != NULL);
+  tt_assert(errmsg == NULL);
+
+  tt_str_op(answer, OP_EQ, "md1\nmd2\n");
+
+ done:
+  UNMOCK(nodelist_get_list);
+  tor_free(node1->md->body);
+  tor_free(node1->md);
+  tor_free(node1);
+  tor_free(node2->md->body);
+  tor_free(node2->md);
+  tor_free(node2);
+  tor_free(answer);
+  smartlist_free(nodes);
+  return;
+}
+
 struct testcase_t controller_tests[] = {
   { "add_onion_helper_keyarg_v2", test_add_onion_helper_keyarg_v2, 0,
     NULL, NULL },
@@ -1542,6 +1617,7 @@ struct testcase_t controller_tests[] = {
   { "download_status_desc", test_download_status_desc, 0, NULL, NULL },
   { "download_status_bridge", test_download_status_bridge, 0, NULL, NULL },
   { "current_time", test_current_time, 0, NULL, NULL },
+  { "getinfo_md_all", test_getinfo_md_all, 0, NULL, NULL },
   END_OF_TESTCASES
 };