⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 routerlist.c

📁 关于tor匿名通信的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 * <b>status</b>.  Additionally, try to have a non-expired certificate for
 * every V3 authority in trusted_dir_servers.  Don't fetch certificates we
 * already have.
 **/
void
authority_certs_fetch_missing(networkstatus_t *status, time_t now)
{
  digestmap_t *pending;
  smartlist_t *missing_digests;
  char *resource = NULL;
  cert_list_t *cl;
  const int cache = directory_caches_dir_info(get_options());

  if (should_delay_dir_fetches(get_options()))
    return;

  pending = digestmap_new();
  missing_digests = smartlist_create();

  list_pending_downloads(pending, DIR_PURPOSE_FETCH_CERTIFICATE, "fp/");
  if (status) {
    SMARTLIST_FOREACH(status->voters, networkstatus_voter_info_t *, voter,
      {
        if (tor_digest_is_zero(voter->signing_key_digest))
          continue; /* This authority never signed this consensus, so don't
                     * go looking for a cert with key digest 0000000000. */
        if (!cache &&
            !trusteddirserver_get_by_v3_auth_digest(voter->identity_digest))
          continue; /* We are not a cache, and we don't know this authority.*/
        cl = get_cert_list(voter->identity_digest);
        if (authority_cert_get_by_digests(voter->identity_digest,
                                          voter->signing_key_digest)) {
          download_status_reset(&cl->dl_status);
          continue;
        }
        if (download_status_is_ready(&cl->dl_status, now,
                                     MAX_CERT_DL_FAILURES)) {
          log_notice(LD_DIR, "We're missing a certificate from authority "
                     "with signing key %s: launching request.",
                     hex_str(voter->signing_key_digest, DIGEST_LEN));
          smartlist_add(missing_digests, voter->identity_digest);
        }
      });
  }
  SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
    {
      int found = 0;
      if (!(ds->type & V3_AUTHORITY))
        continue;
      if (smartlist_digest_isin(missing_digests, ds->v3_identity_digest))
        continue;
      cl = get_cert_list(ds->v3_identity_digest);
      SMARTLIST_FOREACH(cl->certs, authority_cert_t *, cert,
        {
          if (!ftime_definitely_after(now, cert->expires)) {
            /* It's not expired, and we weren't looking for something to
             * verify a consensus with.  Call it done. */
            download_status_reset(&cl->dl_status);
            found = 1;
            break;
          }
        });
      if (!found && download_status_is_ready(&cl->dl_status, now,
                                             MAX_CERT_DL_FAILURES)) {
        log_notice(LD_DIR, "No current certificate known for authority %s; "
                   "launching request.", ds->nickname);
        smartlist_add(missing_digests, ds->v3_identity_digest);
      }
    });

  if (!smartlist_len(missing_digests)) {
    goto done;
  } else {
    smartlist_t *fps = smartlist_create();
    smartlist_add(fps, tor_strdup("fp/"));
    SMARTLIST_FOREACH(missing_digests, const char *, d, {
        char *fp;
        if (digestmap_get(pending, d))
          continue;
        fp = tor_malloc(HEX_DIGEST_LEN+2);
        base16_encode(fp, HEX_DIGEST_LEN+1, d, DIGEST_LEN);
        fp[HEX_DIGEST_LEN] = '+';
        fp[HEX_DIGEST_LEN+1] = '\0';
        smartlist_add(fps, fp);
      });
    if (smartlist_len(fps) == 1) {
      /* we didn't add any: they were all pending */
      SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp));
      smartlist_free(fps);
      goto done;
    }
    resource = smartlist_join_strings(fps, "", 0, NULL);
    resource[strlen(resource)-1] = '\0';
    SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp));
    smartlist_free(fps);
  }
  directory_get_from_dirserver(DIR_PURPOSE_FETCH_CERTIFICATE, 0,
                               resource, 1);

 done:
  tor_free(resource);
  smartlist_free(missing_digests);
  digestmap_free(pending, NULL);
}

/* Router descriptor storage.
 *
 * Routerdescs are stored in a big file, named "cached-descriptors".  As new
 * routerdescs arrive, we append them to a journal file named
 * "cached-descriptors.new".
 *
 * From time to time, we replace "cached-descriptors" with a new file
 * containing only the live, non-superseded descriptors, and clear
 * cached-routers.new.
 *
 * On startup, we read both files.
 */

/** Helper: return 1 iff the router log is so big we want to rebuild the
 * store. */
static int
router_should_rebuild_store(desc_store_t *store)
{
  if (store->store_len > (1<<16))
    return (store->journal_len > store->store_len / 2 ||
            store->bytes_dropped > store->store_len / 2);
  else
    return store->journal_len > (1<<15);
}

static INLINE desc_store_t *
desc_get_store(routerlist_t *rl, signed_descriptor_t *sd)
{
  if (sd->is_extrainfo)
    return &rl->extrainfo_store;
  else
    return &rl->desc_store;
}

/** Add the signed_descriptor_t in <b>desc</b> to the router
 * journal; change its saved_location to SAVED_IN_JOURNAL and set its
 * offset appropriately. */
static int
signed_desc_append_to_journal(signed_descriptor_t *desc,
                              desc_store_t *store)
{
  char *fname = get_datadir_fname_suffix(store->fname_base, ".new");
  const char *body = signed_descriptor_get_body_impl(desc,1);
  size_t len = desc->signed_descriptor_len + desc->annotations_len;

  tor_assert(len == strlen(body));

  if (append_bytes_to_file(fname, body, len, 1)) {
    log_warn(LD_FS, "Unable to store router descriptor");
    tor_free(fname);
    return -1;
  }
  desc->saved_location = SAVED_IN_JOURNAL;
  tor_free(fname);

  desc->saved_offset = store->journal_len;
  store->journal_len += len;

  return 0;
}

/** Sorting helper: return &lt;0, 0, or &gt;0 depending on whether the
 * signed_descriptor_t* in *<b>a</b> is older, the same age as, or newer than
 * the signed_descriptor_t* in *<b>b</b>. */
static int
_compare_signed_descriptors_by_age(const void **_a, const void **_b)
{
  const signed_descriptor_t *r1 = *_a, *r2 = *_b;
  return (int)(r1->published_on - r2->published_on);
}

/** If the journal is too long, or if <b>force</b> is true, then atomically
 * replace the router store with the routers currently in our routerlist, and
 * clear the journal.  Return 0 on success, -1 on failure.
 *
 * If <b>extrainfo</b> is true, rebuild the extrainfo store; else rebuild the
 * router descriptor store.
 */
static int
router_rebuild_store(int force, desc_store_t *store)
{
  smartlist_t *chunk_list = NULL;
  char *fname = NULL, *fname_tmp = NULL;
  int r = -1;
  off_t offset = 0;
  smartlist_t *signed_descriptors = NULL;
  int nocache=0;
  size_t total_expected_len = 0;
  int had_any;

  if (!force && !router_should_rebuild_store(store))
    return 0;
  if (!routerlist)
    return 0;

  if (store->type == EXTRAINFO_STORE)
    had_any = !eimap_isempty(routerlist->extra_info_map);
  else
    had_any = (smartlist_len(routerlist->routers)+
               smartlist_len(routerlist->old_routers))>0;

  /* Don't save deadweight. */
  routerlist_remove_old_routers();

  log_info(LD_DIR, "Rebuilding %s cache", store->description);

  fname = get_datadir_fname(store->fname_base);
  fname_tmp = get_datadir_fname_suffix(store->fname_base, ".tmp");

  chunk_list = smartlist_create();

  /* We sort the routers by age to enhance locality on disk. */
  signed_descriptors = smartlist_create();
  if (store->type == EXTRAINFO_STORE) {
    eimap_iter_t *iter;
    for (iter = eimap_iter_init(routerlist->extra_info_map);
         !eimap_iter_done(iter);
         iter = eimap_iter_next(routerlist->extra_info_map, iter)) {
      const char *key;
      extrainfo_t *ei;
      eimap_iter_get(iter, &key, &ei);
      smartlist_add(signed_descriptors, &ei->cache_info);
    }
  } else {
    SMARTLIST_FOREACH(routerlist->old_routers, signed_descriptor_t *, sd,
                      smartlist_add(signed_descriptors, sd));
    SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
                      smartlist_add(signed_descriptors, &ri->cache_info));
  }

  smartlist_sort(signed_descriptors, _compare_signed_descriptors_by_age);

  /* Now, add the appropriate members to chunk_list */
  SMARTLIST_FOREACH(signed_descriptors, signed_descriptor_t *, sd,
    {
      sized_chunk_t *c;
      const char *body = signed_descriptor_get_body_impl(sd, 1);
      if (!body) {
        log_warn(LD_BUG, "No descriptor available for router.");
        goto done;
      }
      if (sd->do_not_cache) {
        ++nocache;
        continue;
      }
      c = tor_malloc(sizeof(sized_chunk_t));
      c->bytes = body;
      c->len = sd->signed_descriptor_len + sd->annotations_len;
      total_expected_len += c->len;
      smartlist_add(chunk_list, c);
    });

  if (write_chunks_to_file(fname_tmp, chunk_list, 1)<0) {
    log_warn(LD_FS, "Error writing router store to disk.");
    goto done;
  }

  /* Our mmap is now invalid. */
  if (store->mmap) {
    tor_munmap_file(store->mmap);
    store->mmap = NULL;
  }

  if (replace_file(fname_tmp, fname)<0) {
    log_warn(LD_FS, "Error replacing old router store: %s", strerror(errno));
    goto done;
  }

  errno = 0;
  store->mmap = tor_mmap_file(fname);
  if (! store->mmap) {
    if (errno == ERANGE) {
      /* empty store.*/
      if (total_expected_len) {
        log_warn(LD_FS, "We wrote some bytes to a new descriptor file at '%s',"
                 " but when we went to mmap it, it was empty!", fname);
      } else if (had_any) {
        log_info(LD_FS, "We just removed every descriptor in '%s'.  This is "
                 "okay if we're just starting up after a long time. "
                 "Otherwise, it's a bug.", fname);
      }
    } else {
      log_warn(LD_FS, "Unable to mmap new descriptor file at '%s'.",fname);
    }
  }

  log_info(LD_DIR, "Reconstructing pointers into cache");

  offset = 0;
  SMARTLIST_FOREACH(signed_descriptors, signed_descriptor_t *, sd,
    {
      if (sd->do_not_cache)
        continue;
      sd->saved_location = SAVED_IN_CACHE;
      if (store->mmap) {
        tor_free(sd->signed_descriptor_body); // sets it to null
        sd->saved_offset = offset;
      }
      offset += sd->signed_descriptor_len + sd->annotations_len;
      signed_descriptor_get_body(sd); /* reconstruct and assert */
    });

  tor_free(fname);
  fname = get_datadir_fname_suffix(store->fname_base, ".new");
  write_str_to_file(fname, "", 1);

  r = 0;
  store->store_len = (size_t) offset;
  store->journal_len = 0;
  store->bytes_dropped = 0;
 done:
  if (signed_descriptors)
    smartlist_free(signed_descriptors);
  tor_free(fname);
  tor_free(fname_tmp);
  SMARTLIST_FOREACH(chunk_list, sized_chunk_t *, c, tor_free(c));
  smartlist_free(chunk_list);

  return r;
}

/** Helper: Reload a cache file and its associated journal, setting metadata
 * appropriately.  If <b>extrainfo</b> is true, reload the extrainfo store;
 * else reload the router descriptor store. */
static int
router_reload_router_list_impl(desc_store_t *store)
{
  char *fname = NULL, *altname = NULL, *contents = NULL;
  struct stat st;
  int read_from_old_location = 0;
  int extrainfo = (store->type == EXTRAINFO_STORE);
  time_t now = time(NULL);
  store->journal_len = store->store_len = 0;

  fname = get_datadir_fname(store->fname_base);
  if (store->fname_alt_base)
    altname = get_datadir_fname(store->fname_alt_base);

  if (store->mmap) /* get rid of it first */
    tor_munmap_file(store->mmap);
  store->mmap = NULL;

  store->mmap = tor_mmap_file(fname);
  if (!store->mmap && altname && file_status(altname) == FN_FILE) {
    read_from_old_location = 1;
    log_notice(LD_DIR, "Couldn't read %s; trying to load routers from old "
               "location %s.", fname, altname);
    if ((store->mmap = tor_mmap_file(altname)))
      read_from_old_location = 1;
  }
  if (altname && !read_from_old_location) {
    remove_file_if_very_old(altname, now);
  }
  if (store->mmap) {
    store->store_len = store->mmap->size;
    if (extrainfo)
      router_load_extrainfo_from_string(store->mmap->data,
                                        store->mmap->data+store->mmap->size,
                                        SAVED_IN_CACHE, NULL, 0);
    else
      router_load_routers_from_string(store->mmap->data,
                                      store->mmap->data+store->mmap->size,
                                      SAVED_IN_CACHE, NULL, 0, NULL);
  }

  tor_free(fname);
  fname = get_datadir_fname_suffix(store->fname_base, ".new");
  if (file_status(fname) == FN_FILE)
    contents = read_file_to_str(fname, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
  if (read_from_old_location) {
    tor_free(altname);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -