Beispiel #1
0
static void
test_rend_cache_decrement_allocation(void *data)
{
  (void)data;

  // Test when the cache has enough allocations
  rend_cache_total_allocation = 10;
  rend_cache_decrement_allocation(3);
  tt_int_op(rend_cache_total_allocation, OP_EQ, 7);

  // Test when there are not enough allocations
  rend_cache_total_allocation = 1;
  setup_full_capture_of_logs(LOG_WARN);
  rend_cache_decrement_allocation(2);
  tt_int_op(rend_cache_total_allocation, OP_EQ, 0);
  expect_single_log_msg_containing(
                    "Underflow in rend_cache_decrement_allocation");
  teardown_capture_of_logs();

  // And again
  rend_cache_decrement_allocation(2);
  tt_int_op(rend_cache_total_allocation, OP_EQ, 0);

 done:
  teardown_capture_of_logs();
}
Beispiel #2
0
static void
test_rend_cache_decrement_allocation(void *data)
{
  (void)data;

  // Test when the cache has enough allocations
  rend_cache_total_allocation = 10;
  rend_cache_decrement_allocation(3);
  tt_int_op(rend_cache_total_allocation, OP_EQ, 7);

  // Test when there are not enough allocations
  rend_cache_total_allocation = 1;
  rend_cache_decrement_allocation(2);
  tt_int_op(rend_cache_total_allocation, OP_EQ, 0);

  // And again
  rend_cache_decrement_allocation(2);
  tt_int_op(rend_cache_total_allocation, OP_EQ, 0);

 done:
  (void)0;
}
Beispiel #3
0
/** Helper: free storage held by a single service descriptor cache entry. */
STATIC void
rend_cache_entry_free_(rend_cache_entry_t *e)
{
  if (!e)
    return;
  rend_cache_decrement_allocation(rend_cache_entry_allocation(e));
  /* We are about to remove a descriptor from the cache so remove the entry
   * in the failure cache. */
  rend_cache_failure_remove(e->parsed);
  rend_service_descriptor_free(e->parsed);
  tor_free(e->desc);
  tor_free(e);
}
Beispiel #4
0
/* Try to store a valid version 3 descriptor in the directory cache. Return 0
 * on success else a negative value is returned indicating that we have a
 * newer version in our cache. On error, caller is responsible to free the
 * given descriptor desc. */
static int
cache_store_v3_as_dir(hs_cache_dir_descriptor_t *desc)
{
  hs_cache_dir_descriptor_t *cache_entry;

  tor_assert(desc);

  /* Verify if we have an entry in the cache for that key and if yes, check
   * if we should replace it? */
  cache_entry = lookup_v3_desc_as_dir(desc->key);
  if (cache_entry != NULL) {
    /* Only replace descriptor if revision-counter is greater than the one
     * in our cache */
    if (cache_entry->plaintext_data->revision_counter >=
        desc->plaintext_data->revision_counter) {
      log_info(LD_REND, "Descriptor revision counter in our cache is "
               "greater or equal than the one we received (%d/%d). "
               "Rejecting!",
               (int)cache_entry->plaintext_data->revision_counter,
               (int)desc->plaintext_data->revision_counter);
      goto err;
    }
    /* We now know that the descriptor we just received is a new one so
     * remove the entry we currently have from our cache so we can then
     * store the new one. */
    remove_v3_desc_as_dir(cache_entry);
    rend_cache_decrement_allocation(cache_get_dir_entry_size(cache_entry));
    cache_dir_desc_free(cache_entry);
  }
  /* Store the descriptor we just got. We are sure here that either we
   * don't have the entry or we have a newer descriptor and the old one
   * has been removed from the cache. */
  store_v3_desc_as_dir(desc);

  /* Update our total cache size with this entry for the OOM. This uses the
   * old HS protocol cache subsystem for which we are tied with. */
  rend_cache_increment_allocation(cache_get_dir_entry_size(desc));

  /* XXX: Update HS statistics. We should have specific stats for v3. */

  return 0;

 err:
  return -1;
}
Beispiel #5
0
/* Clean the v3 cache by removing any entry that has expired using the
 * <b>global_cutoff</b> value. If <b>global_cutoff</b> is 0, the cleaning
 * process will use the lifetime found in the plaintext data section. Return
 * the number of bytes cleaned. */
STATIC size_t
cache_clean_v3_as_dir(time_t now, time_t global_cutoff)
{
  size_t bytes_removed = 0;

  /* Code flow error if this ever happens. */
  tor_assert(global_cutoff >= 0);

  if (!hs_cache_v3_dir) { /* No cache to clean. Just return. */
    return 0;
  }

  DIGEST256MAP_FOREACH_MODIFY(hs_cache_v3_dir, key,
                              hs_cache_dir_descriptor_t *, entry) {
    size_t entry_size;
    time_t cutoff = global_cutoff;
    if (!cutoff) {
      /* Cutoff is the lifetime of the entry found in the descriptor. */
      cutoff = now - entry->plaintext_data->lifetime_sec;
    }

    /* If the entry has been created _after_ the cutoff, not expired so
     * continue to the next entry in our v3 cache. */
    if (entry->created_ts > cutoff) {
      continue;
    }
    /* Here, our entry has expired, remove and free. */
    MAP_DEL_CURRENT(key);
    entry_size = cache_get_dir_entry_size(entry);
    bytes_removed += entry_size;
    /* Entry is not in the cache anymore, destroy it. */
    cache_dir_desc_free(entry);
    /* Update our cache entry allocation size for the OOM. */
    rend_cache_decrement_allocation(entry_size);
    /* Logging. */
    {
      char key_b64[BASE64_DIGEST256_LEN + 1];
      digest256_to_base64(key_b64, (const char *) key);
      log_info(LD_REND, "Removing v3 descriptor '%s' from HSDir cache",
               safe_str_client(key_b64));
    }
  } DIGEST256MAP_FOREACH_END;