diff options
author | Nick Mathewson <nickm@torproject.org> | 2015-02-11 15:06:04 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2015-02-11 15:06:04 -0500 |
commit | caf28519d9a4f7f0a5fa36a0cd94fe9c0ee292dc (patch) | |
tree | db5e6003cc8cec5f27ba0e91449348518ea98455 | |
parent | 0c81dfa848da160b02818771626a425cd27b86bc (diff) | |
parent | 0899f51bc6abf535c6c55b81b98b959235b0f7c7 (diff) | |
download | tor-caf28519d9a4f7f0a5fa36a0cd94fe9c0ee292dc.tar.gz tor-caf28519d9a4f7f0a5fa36a0cd94fe9c0ee292dc.zip |
Merge branch 'bug12844'
Conflicts:
src/or/circuituse.c
src/test/include.am
src/test/test_entrynodes.c
-rw-r--r-- | changes/feature12844 | 5 | ||||
-rw-r--r-- | doc/tor.1.txt | 16 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 87 | ||||
-rw-r--r-- | src/or/circuitbuild.h | 3 | ||||
-rw-r--r-- | src/or/circuituse.c | 12 | ||||
-rw-r--r-- | src/or/config.c | 13 | ||||
-rw-r--r-- | src/or/or.h | 3 | ||||
-rw-r--r-- | src/or/routerlist.c | 2 | ||||
-rw-r--r-- | src/or/routerlist.h | 4 | ||||
-rw-r--r-- | src/test/include.am | 5 | ||||
-rw-r--r-- | src/test/test_entrynodes.c | 68 | ||||
-rw-r--r-- | src/test/test_hs.c | 80 | ||||
-rw-r--r-- | src/test/testhelper.c | 67 | ||||
-rw-r--r-- | src/test/testhelper.h | 10 |
14 files changed, 305 insertions, 70 deletions
diff --git a/changes/feature12844 b/changes/feature12844 new file mode 100644 index 0000000000..7b7276640a --- /dev/null +++ b/changes/feature12844 @@ -0,0 +1,5 @@ + o Minor features: + - Introduce the config option Tor2webRendezvousPoints, which + allows clients in Tor2webMode to select a specific Rendezvous + Point to be used in HS circuits. This might allow better + performance for Tor2Web nodes. Implements ticket #12844. diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 1349bf35b5..b646a4c6e0 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -1335,6 +1335,22 @@ The following options are useful only for clients (that is, if To enable this option the compile time flag --enable-tor2webmode must be specified. (Default: 0) +[[Tor2webRendezvousPoints]] **Tor2webRendezvousPoints** __node__,__node__,__...__:: + A list of identity fingerprints, nicknames, country codes and + address patterns of nodes that are allowed to be used as RPs + in HS circuits; any other nodes will not be used as RPs. + (Example: + Tor2webRendezvousPoints Fastyfasty, ABCD1234CDEF5678ABCD1234CDEF5678ABCD1234, \{cc}, 255.254.0.0/8) + + + + This feature can only be used if Tor2webMode is also enabled. + + + ExcludeNodes have higher priority than Tor2webRendezvousPoints, + which means that nodes specified in ExcludeNodes will not be + picked as RPs. + + + If no nodes in Tor2webRendezvousPoints are currently available for + use, Tor will choose a random node when building HS circuits. + [[UseMicrodescriptors]] **UseMicrodescriptors** **0**|**1**|**auto**:: Microdescriptors are a smaller version of the information that Tor needs in order to build its circuits. Using microdescriptors makes Tor clients diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index fa5a2f5242..57056b2a66 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1737,6 +1737,83 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) return NULL; } +#if defined(ENABLE_TOR2WEB_MODE) || defined(TOR_UNIT_TESTS) +/* The config option Tor2webRendezvousPoints has been set and we need + * to pick an RP out of that set. Make sure that the RP we choose is + * alive, and return it. Return NULL if no usable RP could be found in + * Tor2webRendezvousPoints. */ +STATIC const node_t * +pick_tor2web_rendezvous_node(router_crn_flags_t flags, + const or_options_t *options) +{ + const node_t *rp_node = NULL; + const int allow_invalid = (flags & CRN_ALLOW_INVALID) != 0; + const int need_desc = (flags & CRN_NEED_DESC) != 0; + + smartlist_t *whitelisted_live_rps = smartlist_new(); + smartlist_t *all_live_nodes = smartlist_new(); + + tor_assert(options->Tor2webRendezvousPoints); + + /* Add all running nodes to all_live_nodes */ + router_add_running_nodes_to_smartlist(all_live_nodes, + allow_invalid, + 0, 0, 0, + need_desc); + + /* Filter all_live_nodes to only add live *and* whitelisted RPs to + * the list whitelisted_live_rps. */ + SMARTLIST_FOREACH_BEGIN(all_live_nodes, node_t *, live_node) { + if (routerset_contains_node(options->Tor2webRendezvousPoints, live_node)) { + smartlist_add(whitelisted_live_rps, live_node); + } + } SMARTLIST_FOREACH_END(live_node); + + /* Honor ExcludeNodes */ + if (options->ExcludeNodes) { + routerset_subtract_nodes(whitelisted_live_rps, options->ExcludeNodes); + } + + /* Now pick randomly amongst the whitelisted RPs. No need to waste time + doing bandwidth load balancing, for most use cases + 'whitelisted_live_rps' contains a single OR anyway. */ + rp_node = smartlist_choose(whitelisted_live_rps); + + if (!rp_node) { + log_warn(LD_REND, "Could not find a Rendezvous Point that suits " + "the purposes of Tor2webRendezvousPoints. Choosing random one."); + } + + smartlist_free(whitelisted_live_rps); + smartlist_free(all_live_nodes); + + return rp_node; +} +#endif + +/* Pick a Rendezvous Point for our HS circuits according to <b>flags</b>. */ +static const node_t * +pick_rendezvous_node(router_crn_flags_t flags) +{ + const or_options_t *options = get_options(); + + if (options->AllowInvalid_ & ALLOW_INVALID_RENDEZVOUS) + flags |= CRN_ALLOW_INVALID; + +#ifdef ENABLE_TOR2WEB_MODE + /* The user wants us to pick specific RPs. */ + if (options->Tor2webRendezvousPoints) { + const node_t *tor2web_rp = pick_tor2web_rendezvous_node(flags, options); + if (tor2web_rp) { + return tor2web_rp; + } + /* Else, if no tor2web RP was found, fall back to choosing a random node */ + } +#endif + + return router_choose_random_node(NULL, options->ExcludeNodes, flags); +} + /** Return a pointer to a suitable router to be the exit node for the * circuit of purpose <b>purpose</b> that we're about to build (or NULL * if no router is suitable). @@ -1767,9 +1844,13 @@ choose_good_exit_server(uint8_t purpose, else return choose_good_exit_server_general(need_uptime,need_capacity); case CIRCUIT_PURPOSE_C_ESTABLISH_REND: - if (options->AllowInvalid_ & ALLOW_INVALID_RENDEZVOUS) - flags |= CRN_ALLOW_INVALID; - return router_choose_random_node(NULL, options->ExcludeNodes, flags); + { + /* Pick a new RP */ + const node_t *rendezvous_node = pick_rendezvous_node(flags); + log_info(LD_REND, "Picked new RP: %s", + safe_str_client(node_describe(rendezvous_node))); + return rendezvous_node; + } } log_warn(LD_BUG,"Unhandled purpose %d", purpose); tor_fragile_assert(); diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h index c72016d530..ddf86416fc 100644 --- a/src/or/circuitbuild.h +++ b/src/or/circuitbuild.h @@ -61,6 +61,9 @@ const node_t *choose_good_entry_server(uint8_t purpose, #ifdef CIRCUITBUILD_PRIVATE STATIC circid_t get_unique_circ_id_by_chan(channel_t *chan); +STATIC const node_t *pick_tor2web_rendezvous_node(router_crn_flags_t flags, + const or_options_t *options); + #endif #endif diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 612b536bad..c463b0a40f 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -1677,6 +1677,7 @@ circuit_launch_by_extend_info(uint8_t purpose, origin_circuit_t *circ; int onehop_tunnel = (flags & CIRCLAUNCH_ONEHOP_TUNNEL) != 0; int have_path = have_enough_path_info(! (flags & CIRCLAUNCH_IS_INTERNAL) ); + int need_specific_rp = 0; if (!onehop_tunnel && (!router_have_minimum_dir_info() || !have_path)) { log_debug(LD_CIRC,"Haven't %s yet; canceling " @@ -1687,8 +1688,17 @@ circuit_launch_by_extend_info(uint8_t purpose, return NULL; } + /* If Tor2webRendezvousPoints is enabled and we are dealing with an + RP circuit, we want a specific RP node so we shouldn't canibalize + an already existing circuit. */ + if (get_options()->Tor2webRendezvousPoints && + purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND) { + need_specific_rp = 1; + } + if ((extend_info || purpose != CIRCUIT_PURPOSE_C_GENERAL) && - purpose != CIRCUIT_PURPOSE_TESTING && !onehop_tunnel) { + purpose != CIRCUIT_PURPOSE_TESTING && + !onehop_tunnel && !need_specific_rp) { /* see if there are appropriate circs available to cannibalize. */ /* XXX if we're planning to add a hop, perhaps we want to look for * internal circs rather than exit circs? -RD */ diff --git a/src/or/config.c b/src/or/config.c index de0baa40d9..ad4fd45846 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -80,6 +80,7 @@ static config_abbrev_t option_abbrevs_[] = { PLURAL(AuthDirRejectCC), PLURAL(EntryNode), PLURAL(ExcludeNode), + PLURAL(Tor2webRendezvousPoint), PLURAL(FirewallPort), PLURAL(LongLivedPort), PLURAL(HiddenServiceNode), @@ -404,6 +405,7 @@ static config_var_t option_vars_[] = { V(TestSocks, BOOL, "0"), V(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"), V(Tor2webMode, BOOL, "0"), + V(Tor2webRendezvousPoints, ROUTERSET, NULL), V(TLSECGroup, STRING, NULL), V(TrackHostExits, CSV, NULL), V(TrackHostExitsExpire, INTERVAL, "30 minutes"), @@ -1262,7 +1264,8 @@ options_need_geoip_info(const or_options_t *options, const char **reason_out) routerset_needs_geoip(options->EntryNodes) || routerset_needs_geoip(options->ExitNodes) || routerset_needs_geoip(options->ExcludeExitNodes) || - routerset_needs_geoip(options->ExcludeNodes); + routerset_needs_geoip(options->ExcludeNodes) || + routerset_needs_geoip(options->Tor2webRendezvousPoints); if (routerset_usage && reason_out) { *reason_out = "We've been configured to use (or avoid) nodes in certain " @@ -1395,7 +1398,7 @@ options_act(const or_options_t *old_options) log_err(LD_CONFIG, "This copy of Tor was not compiled to run in " "'tor2web mode'. It cannot be run with the Tor2webMode torrc " "option enabled. To enable Tor2webMode recompile with the " - "--enable-tor2webmode option."); + "--enable-tor2web-mode option."); return -1; } #endif @@ -1651,6 +1654,8 @@ options_act(const or_options_t *old_options) options->ExcludeExitNodes) || !routerset_equal(old_options->EntryNodes, options->EntryNodes) || !routerset_equal(old_options->ExitNodes, options->ExitNodes) || + !routerset_equal(old_options->Tor2webRendezvousPoints, + options->Tor2webRendezvousPoints) || options->StrictNodes != old_options->StrictNodes) { log_info(LD_CIRC, "Changed to using entry guards or bridges, or changed " @@ -3057,6 +3062,10 @@ options_validate(or_options_t *old_options, or_options_t *options, options->UseEntryGuards = 0; } + if (options->Tor2webRendezvousPoints && !options->Tor2webMode) { + REJECT("Tor2webRendezvousPoints cannot be set without Tor2webMode."); + } + if (!(options->UseEntryGuards) && (options->RendConfigLines != NULL)) { log_warn(LD_CONFIG, diff --git a/src/or/or.h b/src/or/or.h index 5d70798d8e..560f5ff5b7 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3567,6 +3567,9 @@ typedef struct { * circuits.) */ int Tor2webMode; + /** A routerset that should be used when picking RPs for HS circuits. */ + routerset_t *Tor2webRendezvousPoints; + /** Close hidden service client circuits immediately when they reach * the normal circuit-build timeout, even if they have already sent * an INTRODUCE1 cell on its way to the service. */ diff --git a/src/or/routerlist.c b/src/or/routerlist.c index fe92ac0050..64c43c298b 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -1775,7 +1775,7 @@ routerlist_add_node_and_family(smartlist_t *sl, const routerinfo_t *router) /** Add every suitable node from our nodelist to <b>sl</b>, so that * we can pick a node for a circuit. */ -static void +void router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid, int need_uptime, int need_capacity, int need_guard, int need_desc) diff --git a/src/or/routerlist.h b/src/or/routerlist.h index f106ca2316..78c3fbb880 100644 --- a/src/or/routerlist.h +++ b/src/or/routerlist.h @@ -58,6 +58,10 @@ const routerstatus_t *router_pick_fallback_dirserver(dirinfo_type_t type, int router_get_my_share_of_directory_requests(double *v3_share_out); void router_reset_status_download_failures(void); int routers_have_same_or_addrs(const routerinfo_t *r1, const routerinfo_t *r2); +void router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid, + int need_uptime, int need_capacity, + int need_guard, int need_desc); + const routerinfo_t *routerlist_find_my_routerinfo(void); uint32_t router_get_advertised_bandwidth(const routerinfo_t *router); uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router); diff --git a/src/test/include.am b/src/test/include.am index 595be0b7c2..71041b1237 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -62,6 +62,7 @@ src_test_test_SOURCES = \ src/test/test_threads.c \ src/test/test_util.c \ src/test/testing_common.c \ + src/test/testhelper.c \ src/ext/tinytest.c src_test_test_slow_SOURCES = \ @@ -119,10 +120,12 @@ src_test_test_workqueue_LDADD = src/or/libtor-testing.a \ noinst_HEADERS+= \ src/test/fakechans.h \ src/test/test.h \ + src/test/testhelper.h \ src/test/test_descriptors.inc \ src/test/example_extrainfo.inc \ src/test/failing_routerdescs.inc \ - src/test/ed25519_vectors.inc + src/test/ed25519_vectors.inc \ + src/test/test_descriptors.inc noinst_PROGRAMS+= src/test/test-ntor-cl src_test_test_ntor_cl_SOURCES = src/test/test_ntor_cl.c diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c index 19071a1550..5f2051c48f 100644 --- a/src/test/test_entrynodes.c +++ b/src/test/test_entrynodes.c @@ -18,7 +18,7 @@ #include "statefile.h" #include "config.h" -#include "test_descriptors.inc" +#include "testhelper.h" /* TODO: * choose_random_entry() test with state set. @@ -37,62 +37,6 @@ get_or_state_replacement(void) return dummy_state; } -/* NOP replacement for router_descriptor_is_older_than() */ -static int -router_descriptor_is_older_than_replacement(const routerinfo_t *router, - int seconds) -{ - (void) router; - (void) seconds; - return 0; -} - -/* Number of descriptors contained in test_descriptors.txt. */ -#define NUMBER_OF_DESCRIPTORS 8 - -/** Parse a file containing router descriptors and load them to our - routerlist. This function is used to setup an artificial network - so that we can conduct entry guard tests. */ -static void -setup_fake_routerlist(void) -{ - int retval; - routerlist_t *our_routerlist = NULL; - smartlist_t *our_nodelist = NULL; - - /* Read the file that contains our test descriptors. */ - - /* We need to mock this function otherwise the descriptors will not - accepted as they are too old. */ - MOCK(router_descriptor_is_older_than, - router_descriptor_is_older_than_replacement); - - /* Load all the test descriptors to the routerlist. */ - retval = router_load_routers_from_string(TEST_DESCRIPTORS, - NULL, SAVED_IN_JOURNAL, - NULL, 0, NULL); - tt_int_op(retval, OP_EQ, NUMBER_OF_DESCRIPTORS); - - /* Sanity checking of routerlist and nodelist. */ - our_routerlist = router_get_routerlist(); - tt_int_op(smartlist_len(our_routerlist->routers), OP_EQ, - NUMBER_OF_DESCRIPTORS); - routerlist_assert_ok(our_routerlist); - - our_nodelist = nodelist_get_list(); - tt_int_op(smartlist_len(our_nodelist), OP_EQ, NUMBER_OF_DESCRIPTORS); - - /* Mark all routers as non-guards but up and running! */ - SMARTLIST_FOREACH_BEGIN(our_nodelist, node_t *, node) { - node->is_running = 1; - node->is_valid = 1; - node->is_possible_guard = 0; - } SMARTLIST_FOREACH_END(node); - - done: - UNMOCK(router_descriptor_is_older_than); -} - /* Unittest cleanup function: Cleanup the fake network. */ static int fake_network_cleanup(const struct testcase_t *testcase, void *ptr) @@ -120,7 +64,7 @@ fake_network_setup(const struct testcase_t *testcase) get_or_state_replacement); /* Setup fake routerlist. */ - setup_fake_routerlist(); + helper_setup_fake_routerlist(); /* Return anything but NULL (it's interpreted as test fail) */ return dummy_state; @@ -197,7 +141,7 @@ populate_live_entry_guards_test_helper(int num_needed) /* Walk the nodelist and add all nodes as entry guards. */ our_nodelist = nodelist_get_list(); - tt_int_op(smartlist_len(our_nodelist), OP_EQ, NUMBER_OF_DESCRIPTORS); + tt_int_op(smartlist_len(our_nodelist), OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS); SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { const node_t *node_tmp; @@ -206,7 +150,7 @@ populate_live_entry_guards_test_helper(int num_needed) } SMARTLIST_FOREACH_END(node); /* Make sure the nodes were added as entry guards. */ - tt_int_op(smartlist_len(all_entry_guards), OP_EQ, NUMBER_OF_DESCRIPTORS); + tt_int_op(smartlist_len(all_entry_guards), OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS); /* Ensure that all the possible entry guards are enough to satisfy us. */ tt_int_op(smartlist_len(all_entry_guards), OP_GE, num_needed); @@ -647,7 +591,7 @@ test_entry_is_live(void *arg) /* Walk the nodelist and add all nodes as entry guards. */ our_nodelist = nodelist_get_list(); - tt_int_op(smartlist_len(our_nodelist), OP_EQ, NUMBER_OF_DESCRIPTORS); + tt_int_op(smartlist_len(our_nodelist), OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS); SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { const node_t *node_tmp; @@ -659,7 +603,7 @@ test_entry_is_live(void *arg) } SMARTLIST_FOREACH_END(node); /* Make sure the nodes were added as entry guards. */ - tt_int_op(smartlist_len(all_entry_guards), OP_EQ, NUMBER_OF_DESCRIPTORS); + tt_int_op(smartlist_len(all_entry_guards), OP_EQ, HELPER_NUMBER_OF_DESCRIPTORS); /* Now get a random test entry that we will use for this unit test. */ which_node = 3; /* (chosen by fair dice roll) */ diff --git a/src/test/test_hs.c b/src/test/test_hs.c index 0246eaf648..e70ca5ee96 100644 --- a/src/test/test_hs.c +++ b/src/test/test_hs.c @@ -7,9 +7,15 @@ **/ #define CONTROL_PRIVATE +#define CIRCUITBUILD_PRIVATE + #include "or.h" #include "test.h" #include "control.h" +#include "testhelper.h" +#include "config.h" +#include "routerset.h" +#include "circuitbuild.h" /* mock ID digest and longname for node that's in nodelist */ #define HSDIR_EXIST_ID "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" \ @@ -123,9 +129,83 @@ test_hs_desc_event(void *arg) tor_free(received_msg); } +/* Make sure we always pick the right RP, given a well formatted + * Tor2webRendezvousPoints value. */ +static void +test_pick_tor2web_rendezvous_node(void *arg) +{ + or_options_t *options = get_options_mutable(); + const node_t *chosen_rp = NULL; + router_crn_flags_t flags = CRN_NEED_DESC; + int retval, i; + const char *tor2web_rendezvous_str = "test003r"; + + (void) arg; + + /* Setup fake routerlist. */ + helper_setup_fake_routerlist(); + + /* Parse Tor2webRendezvousPoints as a routerset. */ + options->Tor2webRendezvousPoints = routerset_new(); + retval = routerset_parse(options->Tor2webRendezvousPoints, + tor2web_rendezvous_str, + "test_tor2web_rp"); + tt_int_op(retval, >=, 0); + + /* Pick rendezvous point. Make sure the correct one is + picked. Repeat many times to make sure it works properly. */ + for (i = 0; i < 50 ; i++) { + chosen_rp = pick_tor2web_rendezvous_node(flags, options); + tt_assert(chosen_rp); + tt_str_op(chosen_rp->ri->nickname, ==, tor2web_rendezvous_str); + } + + done: + routerset_free(options->Tor2webRendezvousPoints); +} + +/* Make sure we never pick an RP if Tor2webRendezvousPoints doesn't + * correspond to an actual node. */ +static void +test_pick_bad_tor2web_rendezvous_node(void *arg) +{ + or_options_t *options = get_options_mutable(); + const node_t *chosen_rp = NULL; + router_crn_flags_t flags = CRN_NEED_DESC; + int retval, i; + const char *tor2web_rendezvous_str = "dummy"; + + (void) arg; + + /* Setup fake routerlist. */ + helper_setup_fake_routerlist(); + + /* Parse Tor2webRendezvousPoints as a routerset. */ + options->Tor2webRendezvousPoints = routerset_new(); + retval = routerset_parse(options->Tor2webRendezvousPoints, + tor2web_rendezvous_str, + "test_tor2web_rp"); + tt_int_op(retval, >=, 0); + + /* Pick rendezvous point. Since Tor2webRendezvousPoints was set to a + dummy value, we shouldn't find any eligible RPs. */ + for (i = 0; i < 50 ; i++) { + chosen_rp = pick_tor2web_rendezvous_node(flags, options); + tt_assert(!chosen_rp); + } + + done: + routerset_free(options->Tor2webRendezvousPoints); +} + struct testcase_t hs_tests[] = { { "hs_desc_event", test_hs_desc_event, TT_FORK, NULL, NULL }, + { "pick_tor2web_rendezvous_node", test_pick_tor2web_rendezvous_node, TT_FORK, + NULL, NULL }, + { "pick_bad_tor2web_rendezvous_node", + test_pick_bad_tor2web_rendezvous_node, TT_FORK, + NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/testhelper.c b/src/test/testhelper.c new file mode 100644 index 0000000000..8bbc192a6c --- /dev/null +++ b/src/test/testhelper.c @@ -0,0 +1,67 @@ +/* Copyright (c) 2014, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define ROUTERLIST_PRIVATE + +#include "or.h" +#include "routerlist.h" +#include "testhelper.h" +#include "nodelist.h" + +#include "test.h" + +#include "test_descriptors.inc" + +/* NOP replacement for router_descriptor_is_older_than() */ +static int +router_descriptor_is_older_than_replacement(const routerinfo_t *router, + int seconds) +{ + (void) router; + (void) seconds; + return 0; +} + +/** Parse a file containing router descriptors and load them to our + routerlist. This function is used to setup an artificial network + so that we can conduct tests on it. */ +void +helper_setup_fake_routerlist(void) +{ + int retval; + routerlist_t *our_routerlist = NULL; + smartlist_t *our_nodelist = NULL; + + /* Read the file that contains our test descriptors. */ + + /* We need to mock this function otherwise the descriptors will not + accepted as they are too old. */ + MOCK(router_descriptor_is_older_than, + router_descriptor_is_older_than_replacement); + + /* Load all the test descriptors to the routerlist. */ + retval = router_load_routers_from_string(TEST_DESCRIPTORS, + NULL, SAVED_IN_JOURNAL, + NULL, 0, NULL); + tt_int_op(retval, ==, HELPER_NUMBER_OF_DESCRIPTORS); + + /* Sanity checking of routerlist and nodelist. */ + our_routerlist = router_get_routerlist(); + tt_int_op(smartlist_len(our_routerlist->routers), ==, + HELPER_NUMBER_OF_DESCRIPTORS); + routerlist_assert_ok(our_routerlist); + + our_nodelist = nodelist_get_list(); + tt_int_op(smartlist_len(our_nodelist), ==, HELPER_NUMBER_OF_DESCRIPTORS); + + /* Mark all routers as non-guards but up and running! */ + SMARTLIST_FOREACH_BEGIN(our_nodelist, node_t *, node) { + node->is_running = 1; + node->is_valid = 1; + node->is_possible_guard = 0; + } SMARTLIST_FOREACH_END(node); + + done: + UNMOCK(router_descriptor_is_older_than); +} + diff --git a/src/test/testhelper.h b/src/test/testhelper.h new file mode 100644 index 0000000000..6b1bde6822 --- /dev/null +++ b/src/test/testhelper.h @@ -0,0 +1,10 @@ +#ifndef TOR_TEST_HELPER_H +#define TOR_TEST_HELPER_H + +/* Number of descriptors contained in test_descriptors.txt. */ +#define HELPER_NUMBER_OF_DESCRIPTORS 8 + +void helper_setup_fake_routerlist(void); + +#endif + |