Browse Source

Enable trivial "download by descriptor digest" functionality.

svn:r5250
Nick Mathewson 18 years ago
parent
commit
6101468cbe
5 changed files with 78 additions and 26 deletions
  1. 12 2
      doc/dir-spec.txt
  2. 27 5
      src/or/directory.c
  3. 14 14
      src/or/dirserv.c
  4. 3 1
      src/or/or.h
  5. 22 4
      src/or/routerlist.c

+ 12 - 2
doc/dir-spec.txt

@@ -175,10 +175,18 @@ $Id$
    fingerprint of <F> should be available at:
       http://<hostname>/tor/server/fp/<F>.z
 
-   The most recent descriptors for servers have fingerprints <F1>,<F2>,<F3>
+   The most recent descriptors for servers with fingerprints <F1>,<F2>,<F3>
    should be available at:
       http://<hostname>/tor/server/fp/<F1>+<F2>+<F3>.z
 
+   The descriptor for a server whose digest (in hex) is <D> should be
+   available at:
+      http://<hostname>/tor/server/d/<D>.z
+
+   The most recent descriptors with digests <D1>,<D2>,<D3> should be
+   available at:
+      http://<hostname>/tor/server/d/<D1>+<D2>+<D3>.z
+
    The most recent descriptor for this server should be at:
       http://<hostname>/tor/server/authority.z
 
@@ -371,10 +379,12 @@ $Id$
       fetch a new one if it was published in the last 2 hours. (??)
 
     - Describe what we do with old server versions.
-    
+
     - If we have less than 16 to download, do not download unless 10 minutes
       have passed since last download.
 
+    - Which descriptors do directory servers remember?
+
 6. Remaining issues
 
    Client-knowledge partitioning is worrisome.  Most versions of this don't

+ 27 - 5
src/or/directory.c

@@ -316,7 +316,7 @@ connection_dir_download_networkstatus_failed(connection_t *conn)
      * failed, and possibly retry them later.*/
     smartlist_t *failed = smartlist_create();
     dir_split_resource_into_fingerprints(conn->requested_resource+3,
-                                         failed, NULL);
+                                         failed, NULL, 0);
     if (smartlist_len(failed)) {
       dir_networkstatus_download_failed(failed);
       SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp));
@@ -956,7 +956,7 @@ connection_dir_client_reached_eof(connection_t *conn)
         !strcmpstart(conn->requested_resource,"fp/")) {
       which = smartlist_create();
       dir_split_resource_into_fingerprints(conn->requested_resource+3,
-                                           which, NULL);
+                                           which, NULL, 0);
     }
     cp = body;
     while (*cp) {
@@ -993,7 +993,7 @@ connection_dir_client_reached_eof(connection_t *conn)
         !strcmpstart(conn->requested_resource,"fp/")) {
       which = smartlist_create();
       dir_split_resource_into_fingerprints(conn->requested_resource+3,
-                                           which, NULL);
+                                           which, NULL, 0);
       n_asked_for = smartlist_len(which);
     }
     if (status_code != 200) {
@@ -1653,11 +1653,14 @@ dir_routerdesc_download_failed(smartlist_t *failed)
 /* Given a directory <b>resource</b> request generated by us, containing zero
  * or more strings separated by plus signs, followed optionally by ".z", store
  * the strings, in order, into <b>fp_out</b>.  If <b>compressed_out</b> is
- * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0.
+ * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0.  If
+ * decode_hex is true, then delete all elements that aren't hex digests, and
+ * decode the rest.
  */
 int
 dir_split_resource_into_fingerprints(const char *resource,
-                                     smartlist_t *fp_out, int *compressed_out)
+                                     smartlist_t *fp_out, int *compressed_out,
+                                     int decode_hex)
 {
   smartlist_split_string(fp_out, resource, "+", 0, 0);
   if (compressed_out)
@@ -1671,6 +1674,25 @@ dir_split_resource_into_fingerprints(const char *resource,
         *compressed_out = 1;
     }
   }
+  if (decode_hex) {
+    int i;
+    char *cp, *d;
+    for (i = 0; i < smartlist_len(fp_out); ++i) {
+      cp = smartlist_get(fp_out, i);
+      if (strlen(cp) != HEX_DIGEST_LEN) {
+        smartlist_del(fp_out, i--);
+        continue;
+      }
+      d = tor_malloc_zero(DIGEST_LEN);
+      if (base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0) {
+        tor_free(d);
+        smartlist_del(fp_out, i--);
+        continue;
+      }
+      tor_free(cp);
+      smartlist_set(fp_out, i, d);
+    }
+  }
   return 0;
 }
 

+ 14 - 14
src/or/dirserv.c

@@ -1361,7 +1361,7 @@ dirserv_get_networkstatus_v2(smartlist_t *result,
       log_fn(LOG_WARN, "Client requested 'all' network status objects; we have none.");
   } else if (!strcmpstart(key, "fp/")) {
     smartlist_t *hexdigests = smartlist_create();
-    dir_split_resource_into_fingerprints(key+3, hexdigests, NULL);
+    dir_split_resource_into_fingerprints(key+3, hexdigests, NULL, 0);
     SMARTLIST_FOREACH(hexdigests, char *, cp,
         {
           cached_dir_t *cached;
@@ -1403,22 +1403,22 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key)
     routerinfo_t *ri = router_get_my_routerinfo();
     if (ri)
       smartlist_add(descs_out, ri);
+  } else if (!strcmpstart(key, "/tor/server/d/")) {
+    smartlist_t *digests = smartlist_create();
+    dir_split_resource_into_fingerprints(key, digests, NULL, 1);
+    key += strlen("/tor/server/d/");
+    SMARTLIST_FOREACH(digests, const char *, d,
+       {
+         routerinfo_t *ri = router_get_by_descriptor_digest(d);
+         if (ri)
+           smartlist_add(descs_out,ri);
+       });
+    SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
+    smartlist_free(digests);
   } else if (!strcmpstart(key, "/tor/server/fp/")) {
-    smartlist_t *hexdigests = smartlist_create();
     smartlist_t *digests = smartlist_create();
     key += strlen("/tor/server/fp/");
-    dir_split_resource_into_fingerprints(key, hexdigests, NULL);
-    SMARTLIST_FOREACH(hexdigests, char *, cp,
-                      {
-                        char *d;
-                        if (strlen(cp) != HEX_DIGEST_LEN)
-                          continue;
-                        d = tor_malloc_zero(DIGEST_LEN);
-                        base16_decode(d, DIGEST_LEN, cp, HEX_DIGEST_LEN);
-                        tor_free(cp);
-                        smartlist_add(digests, d);
-                      });
-    smartlist_free(hexdigests);
+    dir_split_resource_into_fingerprints(key, digests, NULL, 1);
     SMARTLIST_FOREACH(digests, const char *, d,
        {
          if (router_digest_is_me(d)) {

+ 3 - 1
src/or/or.h

@@ -1754,7 +1754,8 @@ void connection_dir_request_failed(connection_t *conn);
 void parse_dir_policy(void);
 void free_dir_policy(void);
 int dir_split_resource_into_fingerprints(const char *resource,
-                               smartlist_t *fp_out, int *compresseed_out);
+                                    smartlist_t *fp_out, int *compresseed_out,
+                                    int decode_hex);
 
 /********************************* dirserv.c ***************************/
 
@@ -2130,6 +2131,7 @@ routerinfo_t *router_get_by_nickname(const char *nickname,
                                      int warn_if_unnamed);
 routerinfo_t *router_get_by_hexdigest(const char *hexdigest);
 routerinfo_t *router_get_by_digest(const char *digest);
+routerinfo_t *router_get_by_descriptor_digest(const char *digest);
 int router_digest_is_trusted_dir(const char *digest);
 void router_get_routerlist(routerlist_t **prouterlist);
 void routerlist_reset_warnings(void);

+ 22 - 4
src/or/routerlist.c

@@ -1005,6 +1005,25 @@ router_get_by_digest(const char *digest)
   return NULL;
 }
 
+
+/** Return the router in our routerlist whose 20-byte descriptor
+ * is <b>digest</b>.  Return NULL if no such router is known. */
+routerinfo_t *
+router_get_by_descriptor_digest(const char *digest)
+{
+  tor_assert(digest);
+
+  if (!routerlist) return NULL;
+
+  SMARTLIST_FOREACH(routerlist->routers, routerinfo_t*, router,
+  {
+    if (0 == memcmp(router->signed_descriptor_digest, digest, DIGEST_LEN))
+      return router;
+  });
+
+  return NULL;
+}
+
 /** Set *<b>prouterlist</b> to the current list of all known routers. */
 void
 router_get_routerlist(routerlist_t **prouterlist)
@@ -2625,7 +2644,7 @@ router_list_downloadable(void)
       if (!strcmpstart(conn->requested_resource, "all"))
         n_downloadable = 0;
       dir_split_resource_into_fingerprints(conn->requested_resource,
-                                           downloading, NULL);
+                                           downloading, NULL, 1);
     }
   }
 
@@ -2635,11 +2654,9 @@ router_list_downloadable(void)
   smartlist_sort_strings(downloading);
   */
   if (n_downloadable) {
-    SMARTLIST_FOREACH(downloading, const char *, dl,
+    SMARTLIST_FOREACH(downloading, const char *, d,
     {
-      char d[DIGEST_LEN];
       local_routerstatus_t *rs;
-      base16_decode(d, DIGEST_LEN, dl, strlen(dl));
       if ((rs = router_get_combined_status_by_digest(d)) && rs->should_download) {
         rs->should_download = 0;
         --n_downloadable;
@@ -2919,3 +2936,4 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
   /* Otherwise, the difference is cosmetic. */
   return 1;
 }
+