[tor-commits] [tor/master] continue refactoring directory API: remove initiate_command_rend

nickm at torproject.org nickm at torproject.org
Thu Apr 27 14:12:35 UTC 2017


commit a55bd00b0f41afca767a57e2da4a3dc6a26d2110
Author: Nick Mathewson <nickm at torproject.org>
Date:   Fri Apr 21 14:17:14 2017 -0400

    continue refactoring directory API: remove initiate_command_rend
    
    This commit mainly moves the responsibility for directory request
    construction one level higher.  It also allows a directory request
    to contain a pointer to a routerstatus, which will get turned into
    the correct contact information at the last minute.
---
 src/or/directory.c | 240 +++++++++++++++++++++++++++--------------------------
 src/or/directory.h |   3 +
 2 files changed, 127 insertions(+), 116 deletions(-)

diff --git a/src/or/directory.c b/src/or/directory.c
index d8aab26..ea3683d 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -63,7 +63,7 @@
  * multi-hop circuits for anonymity.
  *
  * Directory requests are launched by calling
- * directory_initiate_command_rend() or one of its numerous variants. This
+ * directory_initiate_request(). This
  * launch the connection, will construct an HTTP request with
  * directory_send_command(), send the and wait for a response.  The client
  * later handles the response with connection_dir_client_reached_eof(),
@@ -118,20 +118,6 @@ static void dir_microdesc_download_failed(smartlist_t *failed,
                                           int status_code);
 static int client_likes_consensus(networkstatus_t *v, const char *want_url);
 
-static void directory_initiate_command_rend(
-                                          const tor_addr_port_t *or_addr_port,
-                                          const tor_addr_port_t *dir_addr_port,
-                                          const char *digest,
-                                          uint8_t dir_purpose,
-                                          uint8_t router_purpose,
-                                          dir_indirection_t indirection,
-                                          const char *resource,
-                                          const char *payload,
-                                          size_t payload_len,
-                                          time_t if_modified_since,
-                                          const rend_data_t *rend_query,
-                                          circuit_guard_state_t *guard_state);
-
 static void connection_dir_close_consensus_fetches(
                    dir_connection_t *except_this_one, const char *resource);
 
@@ -566,20 +552,19 @@ MOCK_IMPL(void, directory_get_from_dirserver, (
         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;
+        directory_request_t *req = directory_request_new(dir_purpose);
         /* 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);
-        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);
+        directory_request_set_or_addr_port(req, &or_ap);
+        directory_request_set_directory_id_digest(req,
+                                            ri->cache_info.identity_digest);
+        directory_request_set_router_purpose(req, router_purpose);
+        directory_request_set_resource(req, resource);
+        directory_request_set_if_modified_since(req, if_modified_since);
+        directory_request_set_guard_state(req, guard_state);
+        directory_initiate_request(req);
+        directory_request_free(req);
       } else {
         if (guard_state) {
           entry_guard_cancel(&guard_state);
@@ -792,61 +777,29 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
                                              const rend_data_t *rend_query,
                                            circuit_guard_state_t *guard_state)
 {
-  const or_options_t *options = get_options();
-  const node_t *node;
-  tor_addr_port_t use_or_ap, use_dir_ap;
-  const int anonymized_connection = dirind_is_anon(indirection);
-
-  tor_assert(status != NULL);
-
-  node = node_get_by_id(status->identity_digest);
-
-  /* XXX The below check is wrong: !node means it's not in the consensus,
-   * but we haven't checked if we have a descriptor for it -- and also,
-   * we only care about the descriptor if it's a begindir-style anonymized
-   * connection. */
-  if (!node && anonymized_connection) {
-    log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
-             "don't have its router descriptor.",
-             routerstatus_describe(status));
-    return;
-  }
-
-  if (options->ExcludeNodes && options->StrictNodes &&
-      routerset_contains_routerstatus(options->ExcludeNodes, status, -1)) {
-    log_warn(LD_DIR, "Wanted to contact directory mirror %s for %s, but "
-             "it's in our ExcludedNodes list and StrictNodes is set. "
-             "Skipping. This choice might make your Tor not work.",
-             routerstatus_describe(status),
-             dir_conn_purpose_to_string(dir_purpose));
-    return;
-  }
+  directory_request_t *req = directory_request_new(dir_purpose);
+  directory_request_set_routerstatus(req, status);
+  directory_request_set_router_purpose(req, router_purpose);
+  directory_request_set_indirection(req, indirection);
 
-  /* At this point, if we are a client making a direct connection to a
-   * directory server, we have selected a server that has at least one address
-   * allowed by ClientUseIPv4/6 and Reachable{"",OR,Dir}Addresses. This
-   * selection uses the preference in ClientPreferIPv6{OR,Dir}Port, if
-   * possible. (If UseBridges is set, clients always use IPv6, and prefer it
-   * by default.)
-   *
-   * Now choose an address that we can use to connect to the directory server.
-   */
-  if (directory_choose_address_routerstatus(status, indirection, &use_or_ap,
-                                            &use_dir_ap) < 0) {
-    return;
-  }
+  if (resource)
+    directory_request_set_resource(req, resource);
+  if (payload)
+    directory_request_set_payload(req, payload, payload_len);
+  if (if_modified_since)
+    directory_request_set_if_modified_since(req, if_modified_since);
+  if (rend_query)
+    directory_request_set_rend_query(req, rend_query);
+  if (guard_state)
+    directory_request_set_guard_state(req, guard_state);
 
   /* We don't retry the alternate OR/Dir address for the same directory if
    * the address we choose fails (#6772).
    * Instead, we'll retry another directory on failure. */
 
-  directory_initiate_command_rend(&use_or_ap, &use_dir_ap,
-                                  status->identity_digest,
-                                  dir_purpose, router_purpose,
-                                  indirection, resource,
-                                  payload, payload_len, if_modified_since,
-                                  rend_query,
-                                  guard_state);
+  directory_initiate_request(req);
+
+  directory_request_free(req);
 }
 
 /** Launch a new connection to the directory server <b>status</b> to
@@ -1161,17 +1114,31 @@ directory_initiate_command(const tor_addr_t *or_addr, uint16_t or_port,
     dir_ap.port = dir_port = 0;
   }
 
-  directory_initiate_command_rend(&or_ap, &dir_ap,
-                             digest, dir_purpose,
-                             router_purpose, indirection,
-                             resource, payload, payload_len,
-                             if_modified_since, NULL, NULL);
+  directory_request_t *req = directory_request_new(dir_purpose);
+  directory_request_set_or_addr_port(req, &or_ap);
+  directory_request_set_dir_addr_port(req, &dir_ap);
+  directory_request_set_directory_id_digest(req, digest);
+
+  directory_request_set_router_purpose(req, router_purpose);
+  directory_request_set_indirection(req, indirection);
+  if (resource)
+    directory_request_set_resource(req, resource);
+  if (payload)
+    directory_request_set_payload(req, payload, payload_len);
+  if (if_modified_since)
+    directory_request_set_if_modified_since(req, if_modified_since);
+
+  directory_initiate_request(req);
+  directory_request_free(req);
 }
 
 struct directory_request_t {
   tor_addr_port_t or_addr_port;
   tor_addr_port_t dir_addr_port;
   char digest[DIGEST_LEN];
+
+  const routerstatus_t *routerstatus;
+
   uint8_t dir_purpose;
   uint8_t router_purpose;
   dir_indirection_t indirection;
@@ -1192,6 +1159,10 @@ directory_request_new(uint8_t dir_purpose)
   tor_assert(dir_purpose != DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2);
 
   directory_request_t *result = tor_malloc_zero(sizeof(*result));
+  tor_addr_make_null(&result->or_addr_port.addr, AF_INET);
+  result->or_addr_port.port = 0;
+  tor_addr_make_null(&result->dir_addr_port.addr, AF_INET);
+  result->dir_addr_port.port = 0;
   result->dir_purpose = dir_purpose;
   result->router_purpose = ROUTER_PURPOSE_GENERAL;
   result->indirection = DIRIND_ONEHOP;
@@ -1279,48 +1250,87 @@ directory_request_set_guard_state(directory_request_t *req,
   req->guard_state = state;
 }
 
-/** Same as directory_initiate_command(), but accepts rendezvous data to
- * fetch a hidden service descriptor, and takes its address & port arguments
- * as tor_addr_port_t. */
-static void
-directory_initiate_command_rend(const tor_addr_port_t *or_addr_port,
-                                const tor_addr_port_t *dir_addr_port,
-                                const char *digest,
-                                uint8_t dir_purpose,
-                                uint8_t router_purpose,
-                                dir_indirection_t indirection,
-                                const char *resource,
-                                const char *payload,
-                                size_t payload_len,
-                                time_t if_modified_since,
-                                const rend_data_t *rend_query,
-                                circuit_guard_state_t *guard_state)
+static int
+directory_request_is_dir_specified(const directory_request_t *req)
 {
-  directory_request_t *r = directory_request_new(dir_purpose);
-  directory_request_set_or_addr_port(r, or_addr_port);
-  directory_request_set_dir_addr_port(r, dir_addr_port);
-  directory_request_set_directory_id_digest(r, digest);
-  directory_request_set_router_purpose(r, router_purpose);
-  directory_request_set_indirection(r, indirection);
-  if (resource)
-    directory_request_set_resource(r, resource);
-  if (payload)
-    directory_request_set_payload(r, payload, payload_len);
-  if (if_modified_since)
-    directory_request_set_if_modified_since(r, if_modified_since);
-  if (rend_query)
-    directory_request_set_rend_query(r, rend_query);
-  if (guard_state)
-    directory_request_set_guard_state(r, guard_state);
+  return (req->or_addr_port.port || req->dir_addr_port.port) &&
+    ! tor_digest_is_zero(req->digest);
+}
+void
+directory_request_set_routerstatus(directory_request_t *req,
+                                   const routerstatus_t *status)
+{
+  req->routerstatus = status;
+}
+static int
+directory_request_set_dir_from_routerstatus(directory_request_t *req)
+
+{
+  const routerstatus_t *status = req->routerstatus;
+  if (status == NULL)
+    return -1;
+  const or_options_t *options = get_options();
+  const node_t *node;
+  tor_addr_port_t use_or_ap, use_dir_ap;
+  const int anonymized_connection = dirind_is_anon(req->indirection);
+
+  tor_assert(status != NULL);
 
-  directory_initiate_request(r);
+  node = node_get_by_id(status->identity_digest);
 
-  directory_request_free(r);
+  /* XXX The below check is wrong: !node means it's not in the consensus,
+   * but we haven't checked if we have a descriptor for it -- and also,
+   * we only care about the descriptor if it's a begindir-style anonymized
+   * connection. */
+  if (!node && anonymized_connection) {
+    log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
+             "don't have its router descriptor.",
+             routerstatus_describe(status));
+    return -1;
+  }
+
+  if (options->ExcludeNodes && options->StrictNodes &&
+      routerset_contains_routerstatus(options->ExcludeNodes, status, -1)) {
+    log_warn(LD_DIR, "Wanted to contact directory mirror %s for %s, but "
+             "it's in our ExcludedNodes list and StrictNodes is set. "
+             "Skipping. This choice might make your Tor not work.",
+             routerstatus_describe(status),
+             dir_conn_purpose_to_string(req->dir_purpose));
+    return -1;
+  }
+
+    /* At this point, if we are a client making a direct connection to a
+   * directory server, we have selected a server that has at least one address
+   * allowed by ClientUseIPv4/6 and Reachable{"",OR,Dir}Addresses. This
+   * selection uses the preference in ClientPreferIPv6{OR,Dir}Port, if
+   * possible. (If UseBridges is set, clients always use IPv6, and prefer it
+   * by default.)
+   *
+   * Now choose an address that we can use to connect to the directory server.
+   */
+  if (directory_choose_address_routerstatus(status,
+                                            req->indirection, &use_or_ap,
+                                            &use_dir_ap) < 0) {
+    return -1;
+  }
+
+  directory_request_set_or_addr_port(req, &use_or_ap);
+  directory_request_set_dir_addr_port(req, &use_dir_ap);
+  directory_request_set_directory_id_digest(req, status->identity_digest);
+  return 0;
 }
 
 void
 directory_initiate_request(directory_request_t *request)
 {
+  tor_assert(request);
+  if (request->routerstatus) {
+    tor_assert_nonfatal(! directory_request_is_dir_specified(request));
+    if (directory_request_set_dir_from_routerstatus(request) < 0) {
+      return;
+    }
+  }
+
   const tor_addr_port_t *or_addr_port = &request->or_addr_port;
   const tor_addr_port_t *dir_addr_port = &request->dir_addr_port;
   const char *digest = request->digest;
@@ -1334,8 +1344,6 @@ directory_initiate_request(directory_request_t *request)
   const rend_data_t *rend_query = request->rend_query;
   circuit_guard_state_t *guard_state = request->guard_state;
 
-  tor_assert(or_addr_port);
-  tor_assert(dir_addr_port);
   tor_assert(or_addr_port->port || dir_addr_port->port);
   tor_assert(digest);
 
diff --git a/src/or/directory.h b/src/or/directory.h
index 18fe550..5d27767 100644
--- a/src/or/directory.h
+++ b/src/or/directory.h
@@ -66,6 +66,9 @@ void directory_request_set_rend_query(directory_request_t *req,
 void directory_request_set_guard_state(directory_request_t *req,
                                        struct circuit_guard_state_t *state);
 
+void directory_request_set_routerstatus(directory_request_t *req,
+                                        const routerstatus_t *rs);
+
 MOCK_DECL(void, directory_initiate_command_routerstatus,
                 (const routerstatus_t *status,
                  uint8_t dir_purpose,





More information about the tor-commits mailing list