Implement GETINFO md/all

This commit is contained in:
rl1987 2018-05-25 13:37:12 +02:00
parent 3716ddf1b4
commit 25341245ae
3 changed files with 102 additions and 0 deletions

3
changes/feature8323 Normal file
View file

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

View file

@ -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";

View file

@ -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
};