diff options
author | Nick Mathewson <nickm@torproject.org> | 2014-07-16 16:49:07 +0200 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2014-07-16 16:49:07 +0200 |
commit | 368ff2291b0b400e0ee908ad465ed6f0f56330ec (patch) | |
tree | 3fd5c286189de4eff5a6df1a0a194016a23585c5 | |
parent | f74a932e0b68205b180c6894b036ab3193144390 (diff) | |
parent | 8bbb217964a8d3a2d77a69f670a53ff65643ff27 (diff) | |
download | tor-368ff2291b0b400e0ee908ad465ed6f0f56330ec.tar.gz tor-368ff2291b0b400e0ee908ad465ed6f0f56330ec.zip |
Merge remote-tracking branch 'asn/bug12202'
-rw-r--r-- | src/or/entrynodes.c | 43 | ||||
-rw-r--r-- | src/or/entrynodes.h | 13 | ||||
-rw-r--r-- | src/test/test_entrynodes.c | 66 |
3 files changed, 112 insertions, 10 deletions
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index 3dcb8f70be..65a3ae3059 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -190,12 +190,16 @@ entry_is_time_to_retry(const entry_guard_t *e, time_t now) * If need_descriptor is true, only return the node if we currently have * a descriptor (routerinfo or microdesc) for it. */ -static INLINE const node_t * -entry_is_live(const entry_guard_t *e, int need_uptime, int need_capacity, - int assume_reachable, int need_descriptor, const char **msg) +STATIC INLINE const node_t * +entry_is_live(const entry_guard_t *e, entry_is_live_flags_t flags, const char **msg) { const node_t *node; const or_options_t *options = get_options(); + int need_uptime = (flags & ENTRY_NEED_UPTIME) != 0; + int need_capacity = (flags & ENTRY_NEED_CAPACITY) != 0; + const int assume_reachable = (flags & ENTRY_ASSUME_REACHABLE) != 0; + const int need_descriptor = (flags & ENTRY_NEED_DESCRIPTOR) != 0; + tor_assert(msg); if (e->path_bias_disabled) { @@ -257,12 +261,18 @@ num_live_entry_guards(int for_directory) { int n = 0; const char *msg; + /* Set the entry node attributes we are interested in. */ + entry_is_live_flags_t entry_flags = ENTRY_NEED_CAPACITY; + if (!for_directory) { + entry_flags |= ENTRY_NEED_DESCRIPTOR; + } + if (! entry_guards) return 0; SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { if (for_directory && !entry->is_dir_cache) continue; - if (entry_is_live(entry, 0, 1, 0, !for_directory, &msg)) + if (entry_is_live(entry, entry_flags, &msg)) ++n; } SMARTLIST_FOREACH_END(entry); return n; @@ -291,7 +301,7 @@ log_entry_guards(int severity) SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { const char *msg = NULL; - if (entry_is_live(e, 0, 1, 0, 0, &msg)) + if (entry_is_live(e, ENTRY_NEED_CAPACITY, &msg)) smartlist_add_asprintf(elements, "%s [%s] (up %s)", e->nickname, hex_str(e->identity, DIGEST_LEN), @@ -667,7 +677,7 @@ entry_guards_compute_status(const or_options_t *options, time_t now) SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { const char *reason = digestmap_get(reasons, entry->identity); const char *live_msg = ""; - const node_t *r = entry_is_live(entry, 0, 1, 0, 0, &live_msg); + const node_t *r = entry_is_live(entry, ENTRY_NEED_CAPACITY, &live_msg); log_info(LD_CIRC, "Summary: Entry %s [%s] is %s, %s%s%s, and %s%s.", entry->nickname, hex_str(entry->identity, DIGEST_LEN), @@ -785,7 +795,9 @@ entry_guard_register_connect_status(const char *digest, int succeeded, break; if (e->made_contact) { const char *msg; - const node_t *r = entry_is_live(e, 0, 1, 1, 0, &msg); + const node_t *r = entry_is_live(e, + ENTRY_NEED_CAPACITY | ENTRY_ASSUME_REACHABLE, + &msg); if (r && e->unreachable_since) { refuse_conn = 1; e->can_retry = 1; @@ -1029,7 +1041,19 @@ populate_live_entry_guards(smartlist_t *live_entry_guards, const int num_needed = decide_num_guards(options, for_directory); smartlist_t *exit_family = smartlist_new(); int retval = 0; - int need_descriptor = !for_directory; + entry_is_live_flags_t entry_flags = 0; + + { /* Set the flags we want our entry node to have */ + if (need_uptime) { + entry_flags |= ENTRY_NEED_UPTIME; + } + if (need_capacity) { + entry_flags |= ENTRY_NEED_CAPACITY; + } + if (!for_directory) { + entry_flags |= ENTRY_NEED_DESCRIPTOR; + } + } tor_assert(all_entry_guards); @@ -1039,8 +1063,7 @@ populate_live_entry_guards(smartlist_t *live_entry_guards, SMARTLIST_FOREACH_BEGIN(all_entry_guards, const entry_guard_t *, entry) { const char *msg; - node = entry_is_live(entry, need_uptime, need_capacity, 0, - need_descriptor, &msg); + node = entry_is_live(entry, entry_flags, &msg); if (!node) continue; /* down, no point */ if (for_directory) { diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h index d49ca508be..81f8b9c2a5 100644 --- a/src/or/entrynodes.h +++ b/src/or/entrynodes.h @@ -91,6 +91,19 @@ STATIC int populate_live_entry_guards(smartlist_t *live_entry_guards, STATIC int decide_num_guards(const or_options_t *options, int for_directory); STATIC void entry_guards_set_from_config(const or_options_t *options); + +/** Flags to be passed to entry_is_live() to indicate what kind of + * entry nodes we are looking for. */ +typedef enum { + ENTRY_NEED_UPTIME = 1<<0, + ENTRY_NEED_CAPACITY = 1<<1, + ENTRY_ASSUME_REACHABLE = 1<<2, + ENTRY_NEED_DESCRIPTOR = 1<<3, +} entry_is_live_flags_t; + +STATIC INLINE const node_t *entry_is_live(const entry_guard_t *e, + entry_is_live_flags_t flags, + const char **msg); #endif void remove_all_entry_guards(void); diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c index c9b8321c79..47d8bc3c74 100644 --- a/src/test/test_entrynodes.c +++ b/src/test/test_entrynodes.c @@ -544,6 +544,69 @@ test_entry_guards_set_from_config(void *arg) routerset_free(options->EntryNodes); } +/** XXX Do some tests that entry_is_live() */ +static void +test_entry_is_live(void *arg) +{ + smartlist_t *our_nodelist = NULL; + const smartlist_t *all_entry_guards = get_entry_guards(); + const node_t *test_node = NULL; + const entry_guard_t *test_entry = NULL; + const char *msg; + + (void) arg; + + /* The global entry guards smartlist should be empty now. */ + tt_int_op(smartlist_len(all_entry_guards), ==, 0); + + /* Walk the nodelist and add all nodes as entry guards. */ + our_nodelist = nodelist_get_list(); + tt_int_op(smartlist_len(our_nodelist), ==, NUMBER_OF_DESCRIPTORS); + + SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) { + const node_t *node_tmp; + node_tmp = add_an_entry_guard(node, 0, 1, 0, 0); + test_assert(node_tmp); + + tt_int_op(node->is_stable, ==, 0); + tt_int_op(node->is_fast, ==, 0); + } SMARTLIST_FOREACH_END(node); + + /* Make sure the nodes were added as entry guards. */ + tt_int_op(smartlist_len(all_entry_guards), ==, NUMBER_OF_DESCRIPTORS); + + /* Now get a random test entry that we will use for this unit test. */ + test_entry = smartlist_get(all_entry_guards, 3); /* chosen by fair dice roll */ + + /* Let's do some entry_is_live() tests! */ + + /* Require the node to be stable, but it's not. Should fail. + Also enable 'assume_reachable' because why not. */ + test_node = entry_is_live(test_entry, + ENTRY_NEED_UPTIME | ENTRY_ASSUME_REACHABLE, + &msg); + test_assert(!test_node); + + /* Require the node to be fast, but it's not. Should fail. */ + test_node = entry_is_live(test_entry, + ENTRY_NEED_CAPACITY | ENTRY_ASSUME_REACHABLE, + &msg); + test_assert(!test_node); + + /* Don't impose any restrictions on the node. Should succeed. */ + test_node = entry_is_live(test_entry, 0, &msg); + test_assert(test_node); + tt_ptr_op(test_node, ==, node_get_by_id(test_entry->identity)); + + /* Require descriptor for this node. It has one so it should succeed. */ + test_node = entry_is_live(test_entry, ENTRY_NEED_DESCRIPTOR, &msg); + test_assert(test_node); + tt_ptr_op(test_node, ==, node_get_by_id(test_entry->identity)); + + done: + ; /* XXX */ +} + static const struct testcase_setup_t fake_network = { fake_network_setup, fake_network_cleanup }; @@ -569,6 +632,9 @@ struct testcase_t entrynodes_tests[] = { { "entry_guards_set_from_config", test_entry_guards_set_from_config, TT_FORK, &fake_network, NULL }, + { "entry_is_live", + test_entry_is_live, + TT_FORK, &fake_network, NULL }, END_OF_TESTCASES }; |