Browse Source

More progress on bridge implementation with prop271 guards

Here we handle most (all?) of the remaining tasks, and fix some
bugs, in the prop271 bridge implementation.

  * We record bridge identities as we learn them.
  * We only call deprecated functions from bridges.c when the
    deprecated guard algorithm is in use.
  * We update any_bridge_descriptors_known() and
    num_bridges_usable() to work correctly with the new backend
    code. (Previously, they called into the guard selection logic.
  * We update bridge directory fetches to work with the new
    guard code.
  * We remove some erroneous assertions where we assumed that we'd
    never load a guard that wasn't for the current selection.

Also, we fix a couple of typos.
Nick Mathewson 7 years ago
parent
commit
3bcbbea350
3 changed files with 71 additions and 30 deletions
  1. 26 8
      src/or/bridges.c
  2. 19 10
      src/or/directory.c
  3. 26 12
      src/or/entrynodes.c

+ 26 - 8
src/or/bridges.c

@@ -279,7 +279,8 @@ learned_router_identity(const tor_addr_t *addr, uint16_t port,
                hex_str(digest, DIGEST_LEN), fmt_addrport(addr, port),
                transport_info ? transport_info : "");
     tor_free(transport_info);
-    // XXXX prop271 here. we will need to update the guard info too.
+    entry_guard_learned_bridge_identity(&bridge->addrport_configured,
+                                        (const uint8_t *)digest);
   }
 }
 
@@ -741,16 +742,21 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
                    fmt_and_decorate_addr(&bridge->addr),
                    (int) bridge->port);
       }
-      // XXXX prop271 here we will need to update the guard info too.
-      add_bridge_as_entry_guard(get_guard_selection_info(), node);
+      if (get_options()->UseDeprecatedGuardAlgorithm) {
+        add_bridge_as_entry_guard(get_guard_selection_info(), node);
+      } else {
+        entry_guard_learned_bridge_identity(&bridge->addrport_configured,
+                               (const uint8_t*)ri->cache_info.identity_digest);
+      }
 
       log_notice(LD_DIR, "new bridge descriptor '%s' (%s): %s", ri->nickname,
                  from_cache ? "cached" : "fresh", router_describe(ri));
       /* set entry->made_contact so if it goes down we don't drop it from
        * our entry node list */
-      // XXXX prop271 use new interface here when we hit bridges?
-      entry_guard_register_connect_status(ri->cache_info.identity_digest,
-                                          1, 0, now);
+      if (get_options()->UseDeprecatedGuardAlgorithm) {
+        entry_guard_register_connect_status(ri->cache_info.identity_digest,
+                                            1, 0, now);
+      }
       if (first) {
         routerlist_retry_directory_downloads(now);
       }
@@ -768,8 +774,20 @@ int
 any_bridge_descriptors_known(void)
 {
   tor_assert(get_options()->UseBridges);
-  // XXXX prop271 this needs to get fixed. -- bridges
-  return choose_random_entry(NULL) != NULL;
+
+  if (!bridge_list)
+    return 0;
+
+  SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) {
+    const node_t *node;
+    if (!tor_digest_is_zero(bridge->identity) &&
+        (node = node_get_by_id(bridge->identity)) != NULL &&
+        node->ri) {
+      return 1;
+    }
+  } SMARTLIST_FOREACH_END(bridge);
+
+  return 0;
 }
 
 /** Return a smartlist containing all bridge identity digests */

+ 19 - 10
src/or/directory.c

@@ -560,26 +560,35 @@ MOCK_IMPL(void, directory_get_from_dirserver, (
        * sort of dir fetch we'll be doing, so it won't return a bridge
        * that can't answer our question.
        */
-      // XXXX prop271 update this for bridge support.
-      const node_t *node = choose_random_dirguard(type);
+      const node_t *node = guards_choose_dirguard(type,
+                                                  &guard_state);
       if (node && node->ri) {
         /* every bridge has a routerinfo. */
         routerinfo_t *ri = node->ri;
         /* clients always make OR connections to bridges */
         tor_addr_port_t or_ap;
+        tor_addr_port_t nil_dir_ap;
         /* we are willing to use a non-preferred address if we need to */
         fascist_firewall_choose_address_node(node, FIREWALL_OR_CONNECTION, 0,
                                              &or_ap);
-        directory_initiate_command(&or_ap.addr, or_ap.port,
-                                   NULL, 0, /*no dirport*/
-                                   ri->cache_info.identity_digest,
-                                   dir_purpose,
-                                   router_purpose,
-                                   DIRIND_ONEHOP,
-                                   resource, NULL, 0, if_modified_since);
-      } else
+        tor_addr_make_null(&nil_dir_ap.addr, AF_INET);
+        nil_dir_ap.port = 0;
+        directory_initiate_command_rend(&or_ap,
+                                        &nil_dir_ap,
+                                        ri->cache_info.identity_digest,
+                                        dir_purpose,
+                                        router_purpose,
+                                        DIRIND_ONEHOP,
+                                        resource, NULL, 0, if_modified_since,
+                                        NULL, guard_state);
+      } else {
+        if (guard_state) {
+          entry_guard_cancel(&guard_state);
+        }
         log_notice(LD_DIR, "Ignoring directory request, since no bridge "
                            "nodes are available yet.");
+      }
+
       return;
     } else {
       if (prefer_authority || (type & BRIDGE_DIRINFO)) {

+ 26 - 12
src/or/entrynodes.c

@@ -271,7 +271,7 @@ create_initial_guard_context(void)
   tor_assert(name); // "name" can only be NULL if we had an old name.
   tor_assert(type != GS_TYPE_INFER);
   log_notice(LD_GUARD, "Starting with guard context \"%s\"", name);
-  curr_guard_context = get_guard_selection_by_name_and_type(name, type);
+  curr_guard_context = get_guard_selection_by_name(name, type, 1);
 }
 
 /** Get current default guard_selection_t, creating it if necessary */
@@ -1234,13 +1234,10 @@ node_passes_guard_filter(const or_options_t *options, guard_selection_t *gs,
                          const node_t *node)
 {
   /* XXXX prop271 remote the gs option; it is unused, and sometimes NULL. */
+  (void)gs;
 
   /* NOTE: Make sure that this function stays in sync with
    * options_transition_affects_entry_guards */
-
-  tor_assert(! options->UseBridges);
-
-  (void)gs;
   if (routerset_contains_node(options->ExcludeNodes, node))
     return 0;
 
@@ -1265,7 +1262,6 @@ static int
 bridge_passes_guard_filter(const or_options_t *options,
                            const bridge_info_t *bridge)
 {
-  tor_assert(options->UseBridges);
   tor_assert(bridge);
   if (!bridge)
     return 0;
@@ -1765,7 +1761,7 @@ select_entry_guard_for_circuit(guard_selection_t *gs, unsigned *state_out)
 
 /**
  * Note that we failed to connect to or build circuits through <b>guard</b>.
- * Use with a guard returned by select_entry_guards_for_circuit().
+ * Use with a guard returned by select_entry_guard_for_circuit().
  */
 STATIC void
 entry_guards_note_guard_failure(guard_selection_t *gs,
@@ -3818,12 +3814,30 @@ choose_random_dirguard(dirinfo_type_t type)
 int
 num_bridges_usable(void)
 {
-  tor_assert(get_options()->UseDeprecatedGuardAlgorithm);
-
   int n_options = 0;
-  tor_assert(get_options()->UseBridges);
-  (void) choose_random_entry_impl(get_guard_selection_info(),
-                                  NULL, 0, 0, &n_options);
+
+  if (get_options()->UseDeprecatedGuardAlgorithm) {
+
+    tor_assert(get_options()->UseBridges);
+    (void) choose_random_entry_impl(get_guard_selection_info(),
+                                    NULL, 0, 0, &n_options);
+  } else {
+    /* XXXX prop271 Is this quite right? */
+    tor_assert(get_options()->UseBridges);
+    guard_selection_t *gs  = get_guard_selection_info();
+    tor_assert(gs->type == GS_TYPE_BRIDGE);
+
+    SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) {
+      if (guard->is_reachable == GUARD_REACHABLE_NO)
+        continue;
+      if (tor_digest_is_zero(guard->identity))
+        continue;
+      const node_t *node = node_get_by_id(guard->identity);
+      if (node && node->ri)
+        ++n_options;
+    } SMARTLIST_FOREACH_END(guard);
+  }
+
   return n_options;
 }