Commit 6101468c authored by Nick Mathewson's avatar Nick Mathewson 🐘
Browse files

Enable trivial "download by descriptor digest" functionality.


svn:r5250
parent 998cf8d6
Loading
Loading
Loading
Loading
+11 −1
Changes for doc/dir-spec.txt: 11 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -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

@@ -375,6 +383,8 @@ $Id$
    - 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
Changes for src/or/directory.c: 27 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -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
Changes for src/or/dirserv.c: 14 added lines, 14 removed lines.
Original line number Diff line number Diff line
@@ -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/fp/")) {
    smartlist_t *hexdigests = smartlist_create();
  } else if (!strcmpstart(key, "/tor/server/d/")) {
    smartlist_t *digests = smartlist_create();
    key += strlen("/tor/server/fp/");
    dir_split_resource_into_fingerprints(key, hexdigests, NULL);
    SMARTLIST_FOREACH(hexdigests, char *, cp,
    dir_split_resource_into_fingerprints(key, digests, NULL, 1);
    key += strlen("/tor/server/d/");
    SMARTLIST_FOREACH(digests, const char *, d,
       {
                        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);
         routerinfo_t *ri = router_get_by_descriptor_digest(d);
         if (ri)
           smartlist_add(descs_out,ri);
       });
    smartlist_free(hexdigests);
    SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
    smartlist_free(digests);
  } else if (!strcmpstart(key, "/tor/server/fp/")) {
    smartlist_t *digests = smartlist_create();
    key += strlen("/tor/server/fp/");
    dir_split_resource_into_fingerprints(key, digests, NULL, 1);
    SMARTLIST_FOREACH(digests, const char *, d,
       {
         if (router_digest_is_me(d)) {
+3 −1
Changes for src/or/or.h: 3 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -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
Changes for src/or/routerlist.c: 22 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -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;
}