pick_hsdir_v3(const ed25519_public_key_t *onion_identity_pk)
{
int retval;
+ unsigned int is_new_tp = 0;
char base64_blinded_pubkey[ED25519_BASE64_LEN + 1];
uint64_t current_time_period = hs_get_time_period_num(0);
smartlist_t *responsible_hsdirs;
}
/* Get responsible hsdirs of service for this time period */
- hs_get_responsible_hsdirs(&blinded_pubkey, current_time_period, 0, 1,
- responsible_hsdirs);
+ is_new_tp = hs_time_between_tp_and_srv(NULL, time(NULL));
+ hs_get_responsible_hsdirs(&blinded_pubkey, current_time_period,
+ is_new_tp, 1, responsible_hsdirs);
log_debug(LD_REND, "Found %d responsible HSDirs and about to pick one.",
smartlist_len(responsible_hsdirs));
* would have to do it thousands of times in a row, we always cache the
* computer disaster SRV (and its corresponding time period num) in case we
* want to reuse it soon after. We need to cache two SRVs, one for each active
- * time period (in case of overlap mode).
+ * time period.
*/
static uint8_t cached_disaster_srv[2][DIGEST256_LEN];
static uint64_t cached_time_period_nums[2] = {0};
memwipe(param, 0, sizeof(param));
}
-/* Return true if overlap mode is active given the date in consensus. If
- * consensus is NULL, then we use the latest live consensus we can find. */
+/* Return true if we are currently in the time segment between a new time
+ * period and a new SRV (in the real network that happens between 12:00 and
+ * 00:00 UTC). Here is a diagram showing exactly when this returns true:
+ *
+ * +------------------------------------------------------------------+
+ * | |
+ * | 00:00 12:00 00:00 12:00 00:00 12:00 |
+ * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 |
+ * | |
+ * | $==========|-----------$===========|-----------$===========| |
+ * | ^^^^^^^^^^^^ ^^^^^^^^^^^^ |
+ * | |
+ * +------------------------------------------------------------------+
+ */
MOCK_IMPL(int,
-hs_overlap_mode_is_active, (const networkstatus_t *consensus, time_t now))
+hs_time_between_tp_and_srv, (const networkstatus_t *consensus, time_t now))
{
time_t valid_after;
time_t srv_start_time, tp_start_time;
}
}
- /* We consider to be in overlap mode when we are in the period of time
- * between a fresh SRV and the beginning of the new time period (in the
- * normal network this is between 00:00 (inclusive) and 12:00 UTC
- * (exclusive)) */
+ /* Get start time of next TP and of current SRV protocol run, and check if we
+ * are between them. */
valid_after = consensus->valid_after;
- srv_start_time =sr_state_get_start_time_of_current_protocol_run(valid_after);
+ srv_start_time =
+ sr_state_get_start_time_of_current_protocol_run(valid_after);
tp_start_time = hs_get_start_time_of_next_time_period(srv_start_time);
if (valid_after >= srv_start_time && valid_after < tp_start_time) {
- return 1;
+ return 0;
}
- return 0;
+ return 1;
}
/* Return 1 if any virtual port in ports needs a circuit with good uptime.
/* For a given blinded key and time period number, get the responsible HSDir
* and put their routerstatus_t object in the responsible_dirs list. If
* is_next_period is true, the next hsdir_index of the node_t is used. If
- * is_client is true, the spread fetch consensus parameter is used else the
- * spread store is used which is only for upload. This function can't fail but
- * it is possible that the responsible_dirs list contains fewer nodes than
+ * 'for_fetching' is true, the spread fetch consensus parameter is used else
+ * the spread store is used which is only for upload. This function can't fail
+ * but it is possible that the responsible_dirs list contains fewer nodes than
* expected.
*
* This function goes over the latest consensus routerstatus list and sorts it
* node. All of this makes it a bit CPU intensive so use it wisely. */
void
hs_get_responsible_hsdirs(const ed25519_public_key_t *blinded_pk,
- uint64_t time_period_num, int is_next_period,
- int is_client, smartlist_t *responsible_dirs)
+ uint64_t time_period_num, int is_new_tp,
+ int for_fetching, smartlist_t *responsible_dirs)
{
smartlist_t *sorted_nodes;
/* The compare function used for the smartlist bsearch. We have two
/* First thing we have to do is sort all node_t by hsdir_index. The
* is_next_period tells us if we want the current or the next one. Set the
* bsearch compare function also while we are at it. */
- if (is_client) {
+ if (for_fetching) {
smartlist_sort(sorted_nodes, compare_node_fetch_hsdir_index);
cmp_fct = compare_digest_to_fetch_hsdir_index;
- } else if (is_next_period) {
+ } else if (is_new_tp) {
smartlist_sort(sorted_nodes, compare_node_store_second_hsdir_index);
cmp_fct = compare_digest_to_store_second_hsdir_index;
} else {
uint8_t hs_index[DIGEST256_LEN] = {0};
/* Number of node to add to the responsible dirs list depends on if we are
* trying to fetch or store. A client always fetches. */
- int n_to_add = (is_client) ? hs_get_hsdir_spread_fetch() :
- hs_get_hsdir_spread_store();
+ int n_to_add = (for_fetching) ? hs_get_hsdir_spread_fetch() :
+ hs_get_hsdir_spread_store();
/* Get the index that we should use to select the node. */
hs_build_hs_index(replica, blinded_pk, time_period_num, hs_index);
/* Hidden service directory index used in a node_t which is set once we set
* the consensus. */
typedef struct hsdir_index_t {
- /* Index to use when fetching a descriptor. */
+ /* HSDir index to use when fetching a descriptor. */
uint8_t fetch[DIGEST256_LEN];
- /* Index to store the first and second descriptor. */
+ /* HSDir index used by services to store their first and second
+ * descriptor. The first descriptor is the one that uses older TP and SRV
+ * values than the second one. */
uint8_t store_first[DIGEST256_LEN];
uint8_t store_second[DIGEST256_LEN];
} hsdir_index_t;
link_specifier_t *hs_link_specifier_dup(const link_specifier_t *lspec);
-MOCK_DECL(int, hs_overlap_mode_is_active,
+MOCK_DECL(int, hs_time_between_tp_and_srv,
(const networkstatus_t *consensus, time_t now));
uint8_t *hs_get_current_srv(uint64_t time_period_num,
int32_t hs_get_hsdir_spread_store(void);
void hs_get_responsible_hsdirs(const ed25519_public_key_t *blinded_pk,
- uint64_t time_period_num, int is_next_period,
- int is_client, smartlist_t *responsible_dirs);
+ uint64_t time_period_num, int is_next_period,
+ int for_fetching, smartlist_t *responsible_dirs);
routerstatus_t *hs_pick_hsdir(smartlist_t *responsible_dirs,
const char *req_key_str);
* if PublishHidServDescriptors is false. */
STATIC void
upload_descriptor_to_all(const hs_service_t *service,
- hs_service_descriptor_t *desc, int for_next_period)
+ hs_service_descriptor_t *desc)
{
+ unsigned int is_new_tp = 0;
smartlist_t *responsible_dirs = NULL;
tor_assert(service);
tor_assert(desc);
+ /* Do we have a new TP that is are we between a new time period and the next
+ * SRV creation? */
+ is_new_tp = hs_time_between_tp_and_srv(NULL, approx_time());
/* Get our list of responsible HSDir. */
responsible_dirs = smartlist_new();
/* The parameter 0 means that we aren't a client so tell the function to use
* the spread store consensus paremeter. */
hs_get_responsible_hsdirs(&desc->blinded_kp.pubkey, desc->time_period_num,
- for_next_period, 0, responsible_dirs);
+ is_new_tp, 0, responsible_dirs);
/** Clear list of previous hsdirs since we are about to upload to a new
* list. Let's keep it up to date. */
/* Run v3+ check. */
FOR_EACH_SERVICE_BEGIN(service) {
FOR_EACH_DESCRIPTOR_BEGIN(service, desc) {
- int for_next_period = 0;
-
/* If we were asked to re-examine the hash ring, and it changed, then
schedule an upload */
if (consider_republishing_hs_descriptors &&
* accurate because all circuits have been established. */
build_desc_intro_points(service, desc, now);
- /* The next descriptor needs the next time period for computing the
- * corresponding hashring. */
- if (desc == service->desc_next) {
- for_next_period = 1;
- }
- upload_descriptor_to_all(service, desc, for_next_period);
+ upload_descriptor_to_all(service, desc);
} FOR_EACH_DESCRIPTOR_END;
} FOR_EACH_SERVICE_END;
write_address_to_file(const hs_service_t *service, const char *fname_);
STATIC void upload_descriptor_to_all(const hs_service_t *service,
- hs_service_descriptor_t *desc,
- int for_next_period);
+ hs_service_descriptor_t *desc);
STATIC void service_desc_schedule_upload(hs_service_descriptor_t *desc,
time_t now,
/* We always use the current time period for fetching descs */
fetch_tp = current_time_period_num;
- /* Now extract the needed SRVs and time periods for building hsdir indices */
- if (!hs_overlap_mode_is_active(ns, now)) {
+ if (hs_time_between_tp_and_srv(ns, now)) {
fetch_srv = hs_get_current_srv(fetch_tp, ns);
store_first_tp = hs_get_previous_time_period_num(0);
}
/* Now let's upload our desc to all hsdirs */
- upload_descriptor_to_all(service, desc, 0);
+ upload_descriptor_to_all(service, desc);
/* Check that previous hsdirs were populated */
tt_int_op(smartlist_len(desc->previous_hsdirs), OP_EQ, 6);
tt_int_op(smartlist_len(desc->previous_hsdirs), OP_EQ, 6);
/* Now order another upload and see that we keep having 6 prev hsdirs */
- upload_descriptor_to_all(service, desc, 0);
+ upload_descriptor_to_all(service, desc);
/* Check that previous hsdirs were populated */
tt_int_op(smartlist_len(desc->previous_hsdirs), OP_EQ, 6);
tt_int_op(smartlist_len(desc->previous_hsdirs), OP_EQ, 0);
/* Now reupload again: see that the prev hsdir set got populated again. */
- upload_descriptor_to_all(service, desc, 0);
+ upload_descriptor_to_all(service, desc);
tt_int_op(smartlist_len(desc->previous_hsdirs), OP_EQ, 6);
done:
done: ;
}
+static void
+test_time_between_tp_and_srv(void *arg)
+{
+ int ret;
+ networkstatus_t ns;
+ (void) arg;
+
+ /* This function should be returning true where "^" are:
+ *
+ * +------------------------------------------------------------------+
+ * | |
+ * | 00:00 12:00 00:00 12:00 00:00 12:00 |
+ * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 |
+ * | |
+ * | $==========|-----------$===========|-----------$===========| |
+ * | ^^^^^^^^^^^^ ^^^^^^^^^^^^ |
+ * | |
+ * +------------------------------------------------------------------+
+ */
+
+ ret = parse_rfc1123_time("Sat, 26 Oct 1985 00:00:00 UTC", &ns.valid_after);
+ tt_int_op(ret, OP_EQ, 0);
+ ret = hs_time_between_tp_and_srv(&ns, 0);
+ tt_int_op(ret, OP_EQ, 0);
+
+ ret = parse_rfc1123_time("Sat, 26 Oct 1985 11:00:00 UTC", &ns.valid_after);
+ tt_int_op(ret, OP_EQ, 0);
+ ret = hs_time_between_tp_and_srv(&ns, 0);
+ tt_int_op(ret, OP_EQ, 0);
+
+ ret = parse_rfc1123_time("Sat, 26 Oct 1985 12:00:00 UTC", &ns.valid_after);
+ tt_int_op(ret, OP_EQ, 0);
+ ret = hs_time_between_tp_and_srv(&ns, 0);
+ tt_int_op(ret, OP_EQ, 1);
+
+ ret = parse_rfc1123_time("Sat, 26 Oct 1985 23:00:00 UTC", &ns.valid_after);
+ tt_int_op(ret, OP_EQ, 0);
+ ret = hs_time_between_tp_and_srv(&ns, 0);
+ tt_int_op(ret, OP_EQ, 1);
+
+ ret = parse_rfc1123_time("Sat, 26 Oct 1985 00:00:00 UTC", &ns.valid_after);
+ tt_int_op(ret, OP_EQ, 0);
+ ret = hs_time_between_tp_and_srv(&ns, 0);
+ tt_int_op(ret, OP_EQ, 0);
+
+ done:
+ ;
+}
+
struct testcase_t hs_common_tests[] = {
{ "build_address", test_build_address, TT_FORK,
NULL, NULL },
NULL, NULL },
{ "parse_extended_hostname", test_parse_extended_hostname, TT_FORK,
NULL, NULL },
+ { "time_between_tp_and_srv", test_time_between_tp_and_srv, TT_FORK,
+ NULL, NULL },
END_OF_TESTCASES
};