diff --git a/src/or/hs_common.c b/src/or/hs_common.c
index 75339df6cd..3bf423f855 100644
--- a/src/or/hs_common.c
+++ b/src/or/hs_common.c
@@ -276,6 +276,14 @@ hs_get_next_time_period_num(time_t now)
return hs_get_time_period_num(now) + 1;
}
+/* Get the number of the _previous_ HS time period, given that the current
+ * time is now. */
+uint64_t
+hs_get_previous_time_period_num(time_t now)
+{
+ return hs_get_time_period_num(now) - 1;
+}
+
/* Return the start time of the upcoming time period based on now. */
time_t
hs_get_start_time_of_next_time_period(time_t now)
diff --git a/src/or/hs_common.h b/src/or/hs_common.h
index a85e86a0c4..f09bbe94dd 100644
--- a/src/or/hs_common.h
+++ b/src/or/hs_common.h
@@ -195,6 +195,7 @@ void hs_get_subcredential(const ed25519_public_key_t *identity_pk,
const ed25519_public_key_t *blinded_pk,
uint8_t *subcred_out);
+uint64_t hs_get_previous_time_period_num(time_t now);
uint64_t hs_get_time_period_num(time_t now);
uint64_t hs_get_next_time_period_num(time_t now);
time_t hs_get_start_time_of_next_time_period(time_t now);
diff --git a/src/or/hs_descriptor.h b/src/or/hs_descriptor.h
index 3e82746c35..61e7a28c2e 100644
--- a/src/or/hs_descriptor.h
+++ b/src/or/hs_descriptor.h
@@ -33,8 +33,11 @@ struct link_specifier_t;
* which is 720 minutes or 43200 seconds. */
#define HS_DESC_MAX_LIFETIME (12 * 60 * 60)
/* Lifetime of certificate in the descriptor. This defines the lifetime of the
- * descriptor signing key and the cross certification cert of that key. */
-#define HS_DESC_CERT_LIFETIME (36 * 60 * 60)
+ * descriptor signing key and the cross certification cert of that key. It is
+ * set to 54 hours because a descriptor can be around for 48 hours and because
+ * consensuses are used after the hour, add an extra 6 hours to give some time
+ * for the service to stop using it. */
+#define HS_DESC_CERT_LIFETIME (54 * 60 * 60)
/* Length of the salt needed for the encrypted section of a descriptor. */
#define HS_DESC_ENCRYPTED_SALT_LEN 16
/* Length of the secret input needed for the KDF construction which derives
diff --git a/src/or/hs_service.c b/src/or/hs_service.c
index 62b8ecf7fc..8cdf95d193 100644
--- a/src/or/hs_service.c
+++ b/src/or/hs_service.c
@@ -23,6 +23,7 @@
#include "router.h"
#include "routerkeys.h"
#include "routerlist.h"
+#include "shared_random_state.h"
#include "statefile.h"
#include "hs_circuit.h"
@@ -769,7 +770,6 @@ move_hs_state(hs_service_t *src_service, hs_service_t *dst_service)
/* Let's do a shallow copy */
dst->intro_circ_retry_started_time = src->intro_circ_retry_started_time;
dst->num_intro_circ_launched = src->num_intro_circ_launched;
- dst->in_overlap_period = src->in_overlap_period;
dst->replay_cache_rend_cookie = src->replay_cache_rend_cookie;
src->replay_cache_rend_cookie = NULL; /* steal pointer reference */
@@ -1366,27 +1366,80 @@ build_service_descriptor(hs_service_t *service, time_t now,
service_descriptor_free(desc);
}
+/* Build both descriptors for the given service that has just booted up.
+ * Because it's a special case, it deserves its special function ;). */
+static void
+build_descriptors_for_new_service(hs_service_t *service, time_t now)
+{
+ uint64_t current_desc_tp, next_desc_tp;
+
+ tor_assert(service);
+ /* These are the conditions for a new service. */
+ tor_assert(!service->desc_current);
+ tor_assert(!service->desc_next);
+
+ /*
+ * +------------------------------------------------------------------+
+ * | |
+ * | 00:00 12:00 00:00 12:00 00:00 12:00 |
+ * | SRV#1 TP#1 SRV#2 TP#2 SRV#3 TP#3 |
+ * | |
+ * | $==========|-----------$===========|-----------$===========| |
+ * | ^ ^ |
+ * | A B |
+ * +------------------------------------------------------------------+
+ *
+ * Case A: The service boots up before a new time period, the current time
+ * period is thus TP#1 and the next is TP#2 which for both we have access to
+ * their SRVs.
+ *
+ * Case B: The service boots up inside TP#2, we can't use the TP#3 for the
+ * next descriptor because we don't have the SRV#3 so the current should be
+ * TP#1 and next TP#2.
+ */
+
+ if (hs_time_between_tp_and_srv(NULL, now)) {
+ /* Case B from the above, inside of the new time period. */
+ current_desc_tp = hs_get_previous_time_period_num(0); /* TP#1 */
+ next_desc_tp = hs_get_time_period_num(0); /* TP#2 */
+ } else {
+ /* Case A from the above, outside of the new time period. */
+ current_desc_tp = hs_get_time_period_num(0); /* TP#1 */
+ next_desc_tp = hs_get_next_time_period_num(0); /* TP#2 */
+ }
+
+ /* Build descriptors. */
+ build_service_descriptor(service, now, current_desc_tp,
+ &service->desc_current);
+ build_service_descriptor(service, now, next_desc_tp,
+ &service->desc_next);
+ log_info(LD_REND, "Hidden service %s has just started. Both descriptors "
+ "built. Now scheduled for upload.",
+ safe_str_client(service->onion_address));
+}
+
/* Build descriptors for each service if needed. There are conditions to build
* a descriptor which are details in the function. */
STATIC void
build_all_descriptors(time_t now)
{
FOR_EACH_SERVICE_BEGIN(service) {
- if (service->desc_current == NULL) {
- /* This means we just booted up because else this descriptor will never
- * be NULL as it should always point to the descriptor that was in
- * desc_next after rotation. */
- build_service_descriptor(service, now, hs_get_time_period_num(0),
- &service->desc_current);
- log_info(LD_REND, "Hidden service %s current descriptor successfully "
- "built. Now scheduled for upload.",
- safe_str_client(service->onion_address));
+ /* A service booting up will have both descriptors to NULL. No other cases
+ * makes both descriptor non existent. */
+ if (service->desc_current == NULL && service->desc_next == NULL) {
+ build_descriptors_for_new_service(service, now);
+ continue;
}
- /* A next descriptor to NULL indicate that we need to build a fresh one if
- * we are in the overlap period for the _next_ time period since it means
- * we either just booted or we just rotated our descriptors. */
- if (hs_overlap_mode_is_active(NULL, now) && service->desc_next == NULL) {
+
+ /* Reaching this point means we are pass bootup so at runtime. We should
+ * *never* have an empty current descriptor. If the next descriptor is
+ * empty, we'll try to build it for the next time period. This only
+ * happens when we rotate meaning that we are guaranteed to have a new SRV
+ * at that point for the next time period. */
+ tor_assert(service->desc_current);
+
+ if (service->desc_next == NULL) {
build_service_descriptor(service, now, hs_get_next_time_period_num(0),
&service->desc_next);
log_info(LD_REND, "Hidden service %s next descriptor successfully "
@@ -1716,10 +1769,62 @@ cleanup_intro_points(hs_service_t *service, time_t now)
} FOR_EACH_DESCRIPTOR_END;
}
-/** We just entered overlap period and we need to rotate our service
- * descriptors */
+/* Set the next rotation time of the descriptors for the given service for the
+ * time now. */
static void
-rotate_service_descriptors(hs_service_t *service)
+set_rotation_time(hs_service_t *service, time_t now)
+{
+ time_t valid_after;
+ const networkstatus_t *ns = networkstatus_get_live_consensus(now);
+ if (ns) {
+ valid_after = ns->valid_after;
+ } else {
+ valid_after = now;
+ }
+
+ tor_assert(service);
+ service->state.next_rotation_time =
+ sr_state_get_start_time_of_current_protocol_run(valid_after) +
+ sr_state_get_protocol_run_duration();
+
+ {
+ char fmt_time[ISO_TIME_LEN + 1];
+ format_local_iso_time(fmt_time, service->state.next_rotation_time);
+ log_info(LD_REND, "Next descriptor rotation time set to %s for %s",
+ fmt_time, safe_str_client(service->onion_address));
+ }
+}
+
+/* Return true iff the service should rotate its descriptor. The time now is
+ * only used to fetch the live consensus and if none can be found, this
+ * returns false. */
+static unsigned int
+should_rotate_descriptors(hs_service_t *service, time_t now)
+{
+ const networkstatus_t *ns;
+
+ tor_assert(service);
+
+ ns = networkstatus_get_live_consensus(now);
+ if (ns == NULL) {
+ goto no_rotation;
+ }
+
+ if (ns->valid_after >= service->state.next_rotation_time) {
+ goto rotation;
+ }
+
+ no_rotation:
+ return 0;
+ rotation:
+ return 1;
+}
+
+/* Rotate the service descriptors of the given service. The current descriptor
+ * will be freed, the next one put in as the current and finally the next
+ * descriptor pointer is NULLified. */
+static void
+rotate_service_descriptors(hs_service_t *service, time_t now)
{
if (service->desc_current) {
/* Close all IP circuits for the descriptor. */
@@ -1732,37 +1837,13 @@ rotate_service_descriptors(hs_service_t *service)
* a descriptor creation for it. */
service->desc_current = service->desc_next;
service->desc_next = NULL;
+
+ /* We've just rotated, set the next time for the rotation. */
+ set_rotation_time(service, now);
}
-/** Return true if service **just** entered overlap mode. */
-static int
-service_just_entered_overlap_mode(const hs_service_t *service,
- int overlap_mode_is_active)
-{
- if (overlap_mode_is_active && !service->state.in_overlap_period) {
- return 1;
- }
-
- return 0;
-}
-
-/** Return true if service **just** left overlap mode. */
-static int
-service_just_left_overlap_mode(const hs_service_t *service,
- int overlap_mode_is_active)
-{
- if (!overlap_mode_is_active && service->state.in_overlap_period) {
- return 1;
- }
-
- return 0;
-}
-
-/* Rotate descriptors for each service if needed. If we are just entering or
- * leaving the overlap period, rotate them that is point the previous
- * descriptor to the current and cleanup the previous one. A non existing
- * current descriptor will trigger a descriptor build for the next time
- * period. */
+/* Rotate descriptors for each service if needed. A non existing current
+ * descriptor will trigger a descriptor build for the next time period. */
STATIC void
rotate_all_descriptors(time_t now)
{
@@ -1770,56 +1851,26 @@ rotate_all_descriptors(time_t now)
* be wise, to rotate service descriptors independently to hide that all
* those descriptors are on the same tor instance */
- int overlap_mode_is_active = hs_overlap_mode_is_active(NULL, now);
-
FOR_EACH_SERVICE_BEGIN(service) {
- int service_entered_overlap = service_just_entered_overlap_mode(service,
- overlap_mode_is_active);
- int service_left_overlap = service_just_left_overlap_mode(service,
- overlap_mode_is_active);
- /* This should not be possible */
- if (BUG(service_entered_overlap && service_left_overlap)) {
- return;
+
+ /* Note for a service booting up: Both descriptors are NULL in that case
+ * so this function might return true if we are in the timeframe for a
+ * rotation leading to basically swapping two NULL pointers which is
+ * harmless. However, the side effect is that triggering a rotation will
+ * update the service state and avoid doing anymore rotations after the
+ * two descriptors have been built. */
+ if (!should_rotate_descriptors(service, now)) {
+ continue;
}
- /* No changes in overlap mode: nothing to do here */
- if (!service_entered_overlap && !service_left_overlap) {
- return;
- }
+ tor_assert(service->desc_current);
+ tor_assert(service->desc_next);
- /* To get down there means that some change happened to overlap mode */
- tor_assert(service_entered_overlap || service_left_overlap);
+ log_info(LD_REND, "Time to rotate our descriptors (%p / %p) for %s",
+ service->desc_current, service->desc_next,
+ safe_str_client(service->onion_address));
- /* Update the overlap marks on this service */
- if (service_entered_overlap) {
- /* It's the first time the service encounters the overlap period so flag
- * it in order to make sure we don't rotate at next check. */
- service->state.in_overlap_period = 1;
- } else if (service_left_overlap) {
- service->state.in_overlap_period = 0;
- }
-
- if (service_entered_overlap) {
- /* We just entered overlap period: recompute all HSDir indices. We need
- * to do this otherwise nodes can get stuck with old HSDir indices until
- * we fetch a new consensus, and we might need to reupload our desc
- * before that. */
- /* XXX find a better place than rotate_all_descriptors() to do this */
- nodelist_recompute_all_hsdir_indices();
- }
-
- /* If we just entered or left overlap mode, rotate our descriptors */
- log_info(LD_REND, "We just %s overlap period. About to rotate %s "
- "descriptors (%p / %p).",
- service_entered_overlap ? "entered" : "left",
- safe_str_client(service->onion_address),
- service->desc_current, service->desc_next);
-
- /* If we have a next descriptor lined up, rotate the descriptors so that it
- * becomes current. */
- if (service->desc_next) {
- rotate_service_descriptors(service);
- }
+ rotate_service_descriptors(service, now);
} FOR_EACH_SERVICE_END;
}
@@ -1833,6 +1884,17 @@ run_housekeeping_event(time_t now)
* simply moving things around or removing uneeded elements. */
FOR_EACH_SERVICE_BEGIN(service) {
+
+ /* If the service is starting off, set the rotation time. We can't do that
+ * at configure time because the get_options() needs to be set for setting
+ * that time that uses the voting interval. */
+ if (service->state.next_rotation_time == 0) {
+ /* Set the next rotation time of the descriptors. If it's Oct 25th
+ * 23:47:00, the next rotation time is when the next SRV is computed
+ * which is at Oct 26th 00:00:00 that is in 13 minutes. */
+ set_rotation_time(service, now);
+ }
+
/* Cleanup invalid intro points from the service descriptor. */
cleanup_intro_points(service, now);
@@ -2504,9 +2566,8 @@ run_upload_descriptor_event(time_t now)
* accurate because all circuits have been established. */
build_desc_intro_points(service, desc, now);
- /* If the service is in the overlap period and this descriptor is the
- * next one, it has to be uploaded for the next time period meaning
- * we'll use the next node_t hsdir_index to pick the HSDirs. */
+ /* The next descriptor needs the next time period for computing the
+ * corresponding hashring. */
if (desc == service->desc_next) {
for_next_period = 1;
}
@@ -3091,6 +3152,7 @@ hs_service_new(const or_options_t *options)
/* Allocate the CLIENT_PK replay cache in service state. */
service->state.replay_cache_rend_cookie =
replaycache_new(REND_REPLAY_TIME_INTERVAL, REND_REPLAY_TIME_INTERVAL);
+
return service;
}
diff --git a/src/or/hs_service.h b/src/or/hs_service.h
index 317b9d795d..7a392d7420 100644
--- a/src/or/hs_service.h
+++ b/src/or/hs_service.h
@@ -196,16 +196,16 @@ typedef struct hs_service_state_t {
* should never go over MAX_INTRO_CIRCS_PER_PERIOD. */
unsigned int num_intro_circ_launched;
- /* Indicate that the service has entered the overlap period. We use this
- * flag to check for descriptor rotation. */
- unsigned int in_overlap_period : 1;
-
/* Replay cache tracking the REND_COOKIE found in INTRODUCE2 cell to detect
* repeats. Clients may send INTRODUCE1 cells for the same rendezvous point
* through two or more different introduction points; when they do, this
* keeps us from launching multiple simultaneous attempts to connect to the
* same rend point. */
replaycache_t *replay_cache_rend_cookie;
+
+ /* When is the next time we should rotate our descriptors. This is has to be
+ * done at the start time of the next SRV protocol run. */
+ time_t next_rotation_time;
} hs_service_state_t;
/* Representation of a service running on this tor instance. */
@@ -229,8 +229,7 @@ typedef struct hs_service_t {
/* Current descriptor. */
hs_service_descriptor_t *desc_current;
- /* Next descriptor that we need for the overlap period for which we have to
- * keep two sets of opened introduction point circuits. */
+ /* Next descriptor. */
hs_service_descriptor_t *desc_next;
/* XXX: Credential (client auth.) #20700. */
diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c
index 675c45ea80..ab8b943346 100644
--- a/src/test/test_hs_common.c
+++ b/src/test/test_hs_common.c
@@ -250,117 +250,6 @@ test_start_time_of_next_time_period(void *arg)
;
}
-/** Test that our HS overlap period functions work properly. */
-static void
-test_desc_overlap_period(void *arg)
-{
- (void) arg;
- int retval;
- time_t now = time(NULL);
- networkstatus_t *dummy_consensus = NULL;
-
- /* First try with a consensus just inside the overlap period */
- dummy_consensus = tor_malloc_zero(sizeof(networkstatus_t));
- retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:00:00 UTC",
- &dummy_consensus->valid_after);
- tt_int_op(retval, OP_EQ, 0);
-
- retval = hs_overlap_mode_is_active(dummy_consensus, now);
- tt_int_op(retval, OP_EQ, 1);
-
- /* Now increase the valid_after so that it goes to 11:00:00 UTC. Overlap
- period is still active. */
- dummy_consensus->valid_after += 3600*11;
- retval = hs_overlap_mode_is_active(dummy_consensus, now);
- tt_int_op(retval, OP_EQ, 1);
-
- /* Now increase the valid_after so that it goes to 11:59:59 UTC. Overlap
- period is still active. */
- dummy_consensus->valid_after += 3599;
- retval = hs_overlap_mode_is_active(dummy_consensus, now);
- tt_int_op(retval, OP_EQ, 1);
-
- /* Now increase the valid_after so that it drifts to noon, and check that
- overlap mode is not active anymore. */
- dummy_consensus->valid_after += 1;
- retval = hs_overlap_mode_is_active(dummy_consensus, now);
- tt_int_op(retval, OP_EQ, 0);
-
- /* Check that overlap mode is also inactive at 23:59:59 UTC */
- retval = parse_rfc1123_time("Wed, 13 Apr 2016 23:59:59 UTC",
- &dummy_consensus->valid_after);
- tt_int_op(retval, OP_EQ, 0);
- retval = hs_overlap_mode_is_active(dummy_consensus, now);
- tt_int_op(retval, OP_EQ, 0);
-
- done:
- tor_free(dummy_consensus);
-}
-
-/* Test the overlap period functions on a testnet with altered voting
- * schedule */
-static void
-test_desc_overlap_period_testnet(void *arg)
-{
- int retval;
- time_t now = approx_time();
- networkstatus_t *dummy_consensus = NULL;
- or_options_t *options = get_options_mutable();
-
- (void) arg;
-
- /* Set the testnet option and a 10-second voting interval */
- options->TestingTorNetwork = 1;
- options->V3AuthVotingInterval = 10;
- options->TestingV3AuthInitialVotingInterval = 10;
-
- dummy_consensus = tor_malloc_zero(sizeof(networkstatus_t));
-
- /* A 10-second voting interval means that the lengths of an SRV run and of a
- * time period are both 10*24 seconds (4 minutes). The SRV gets published at
- * 00:00:00 and the TP starts at 00:02:00 (rotation offset: 2 mins). Those
- * two minutes between SRV publish and TP start is the overlap period
- * window. Let's test it: */
- retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:00:00 UTC",
- &dummy_consensus->valid_after);
- tt_int_op(retval, OP_EQ, 0);
- retval = hs_overlap_mode_is_active(dummy_consensus, now);
- tt_int_op(retval, OP_EQ, 1);
-
- retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:01:59 UTC",
- &dummy_consensus->valid_after);
- tt_int_op(retval, OP_EQ, 0);
- retval = hs_overlap_mode_is_active(dummy_consensus, now);
- tt_int_op(retval, OP_EQ, 1);
-
- retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:02:00 UTC",
- &dummy_consensus->valid_after);
- tt_int_op(retval, OP_EQ, 0);
- retval = hs_overlap_mode_is_active(dummy_consensus, now);
- tt_int_op(retval, OP_EQ, 0);
-
- retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:04:00 UTC",
- &dummy_consensus->valid_after);
- tt_int_op(retval, OP_EQ, 0);
- retval = hs_overlap_mode_is_active(dummy_consensus, now);
- tt_int_op(retval, OP_EQ, 1);
-
- retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:05:59 UTC",
- &dummy_consensus->valid_after);
- tt_int_op(retval, OP_EQ, 0);
- retval = hs_overlap_mode_is_active(dummy_consensus, now);
- tt_int_op(retval, OP_EQ, 1);
-
- retval = parse_rfc1123_time("Wed, 13 Apr 2016 00:06:00 UTC",
- &dummy_consensus->valid_after);
- tt_int_op(retval, OP_EQ, 0);
- retval = hs_overlap_mode_is_active(dummy_consensus, now);
- tt_int_op(retval, OP_EQ, 0);
-
- done:
- tor_free(dummy_consensus);
-}
-
static void
helper_add_hsdir_to_networkstatus(networkstatus_t *ns,
int identity_idx,
@@ -860,10 +749,6 @@ struct testcase_t hs_common_tests[] = {
NULL, NULL },
{ "start_time_of_next_time_period", test_start_time_of_next_time_period,
TT_FORK, NULL, NULL },
- { "desc_overlap_period", test_desc_overlap_period, TT_FORK,
- NULL, NULL },
- { "desc_overlap_period_testnet", test_desc_overlap_period_testnet, TT_FORK,
- NULL, NULL },
{ "responsible_hsdirs", test_responsible_hsdirs, TT_FORK,
NULL, NULL },
{ "desc_reupload_logic", test_desc_reupload_logic, TT_FORK,
diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c
index 357fade049..874056567c 100644
--- a/src/test/test_hs_service.c
+++ b/src/test/test_hs_service.c
@@ -45,6 +45,7 @@
#include "main.h"
#include "rendservice.h"
#include "statefile.h"
+#include "shared_random_state.h"
/* Trunnel */
#include "hs/cell_establish_intro.h"
@@ -98,17 +99,6 @@ mock_relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ,
return 0;
}
-/* Mock function that always return true so we can test the descriptor
- * creation of the next time period deterministically. */
-static int
-mock_hs_overlap_mode_is_active_true(const networkstatus_t *consensus,
- time_t now)
-{
- (void) consensus;
- (void) now;
- return 1;
-}
-
/* Helper: from a set of options in conf, configure a service which will add
* it to the staging list of the HS subsytem. */
static int
@@ -942,12 +932,12 @@ test_service_event(void *arg)
UNMOCK(circuit_mark_for_close_);
}
-/** Test that we rotate descriptors correctly in overlap period */
+/** Test that we rotate descriptors correctly. */
static void
test_rotate_descriptors(void *arg)
{
int ret;
- time_t now = time(NULL);
+ time_t next_rotation_time;
hs_service_t *service;
hs_service_descriptor_t *desc_next;
hs_service_intro_point_t *ip;
@@ -959,10 +949,11 @@ test_rotate_descriptors(void *arg)
MOCK(networkstatus_get_live_consensus,
mock_networkstatus_get_live_consensus);
- /* Setup the valid_after time to be 13:00 UTC, not in overlap period. The
- * overlap check doesn't care about the year. */
+ /* Descriptor rotation happens with a consensus with a new SRV. */
+
ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
&mock_ns.valid_after);
+ tt_int_op(ret, OP_EQ, 0);
ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
&mock_ns.fresh_until);
tt_int_op(ret, OP_EQ, 0);
@@ -973,63 +964,48 @@ test_rotate_descriptors(void *arg)
ip = helper_create_service_ip();
service_intro_point_add(service->desc_current->intro_points.map, ip);
- /* Nothing should happen because we are not in the overlap period. */
- rotate_all_descriptors(now);
- tt_int_op(service->state.in_overlap_period, OP_EQ, 0);
+ /* Tweak our service next rotation time so we can use a custom time. */
+ service->state.next_rotation_time = next_rotation_time =
+ mock_ns.valid_after + (11 * 60 * 60);
+
+ /* Nothing should happen, we are not at a new SRV. Our next rotation time
+ * should be untouched. */
+ rotate_all_descriptors(mock_ns.valid_after);
+ tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time);
tt_assert(service->desc_current);
tt_int_op(digest256map_size(service->desc_current->intro_points.map),
OP_EQ, 1);
- /* Entering an overlap period. */
- ret = parse_rfc1123_time("Sat, 26 Oct 1985 01:00:00 UTC",
+ /* Going right after a new SRV. */
+ ret = parse_rfc1123_time("Sat, 27 Oct 1985 01:00:00 UTC",
&mock_ns.valid_after);
- ret = parse_rfc1123_time("Sat, 26 Oct 1985 02:00:00 UTC",
+ tt_int_op(ret, OP_EQ, 0);
+ ret = parse_rfc1123_time("Sat, 27 Oct 1985 02:00:00 UTC",
&mock_ns.fresh_until);
tt_int_op(ret, OP_EQ, 0);
+
desc_next = service_descriptor_new();
- desc_next->next_upload_time = 42; /* Our marker to recognize it. */
service->desc_next = desc_next;
- /* We should have our state flagged to be in the overlap period, our current
- * descriptor cleaned up and the next descriptor becoming the current. */
- rotate_all_descriptors(now);
- tt_int_op(service->state.in_overlap_period, OP_EQ, 1);
+ /* Note down what to expect for the next rotation time which is 01:00 + 23h
+ * meaning 00:00:00. */
+ next_rotation_time = mock_ns.valid_after + (23 * 60 * 60);
+ /* We should have our next rotation time modified, our current descriptor
+ * cleaned up and the next descriptor becoming the current. */
+ rotate_all_descriptors(mock_ns.valid_after);
+ tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time);
tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next));
tt_int_op(digest256map_size(service->desc_current->intro_points.map),
OP_EQ, 0);
tt_assert(service->desc_next == NULL);
+
/* A second time should do nothing. */
- rotate_all_descriptors(now);
- tt_int_op(service->state.in_overlap_period, OP_EQ, 1);
+ rotate_all_descriptors(mock_ns.valid_after);
+ tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time);
tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next));
tt_int_op(digest256map_size(service->desc_current->intro_points.map),
OP_EQ, 0);
tt_assert(service->desc_next == NULL);
- /* Now let's re-create desc_next and get out of overlap period. We should
- test that desc_current gets replaced by desc_next, and desc_next becomes
- NULL. */
- desc_next = service_descriptor_new();
- desc_next->next_upload_time = 240; /* Our marker to recognize it. */
- service->desc_next = desc_next;
-
- /* Going out of the overlap period. */
- ret = parse_rfc1123_time("Sat, 26 Oct 1985 12:00:00 UTC",
- &mock_ns.valid_after);
- ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
- &mock_ns.fresh_until);
- /* This should reset the state and not touch the current descriptor. */
- tt_int_op(ret, OP_EQ, 0);
- rotate_all_descriptors(now);
- tt_int_op(service->state.in_overlap_period, OP_EQ, 0);
- tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next));
- tt_assert(service->desc_next == NULL);
-
- /* Calling rotate_all_descriptors() another time should do nothing */
- rotate_all_descriptors(now);
- tt_int_op(service->state.in_overlap_period, OP_EQ, 0);
- tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next));
- tt_assert(service->desc_next == NULL);
-
done:
hs_free_all();
UNMOCK(circuit_mark_for_close_);
@@ -1050,7 +1026,6 @@ test_build_update_descriptors(void *arg)
(void) arg;
hs_init();
- MOCK(hs_overlap_mode_is_active, mock_hs_overlap_mode_is_active_true);
MOCK(get_or_state,
get_or_state_replacement);
MOCK(networkstatus_get_live_consensus,
@@ -1196,7 +1171,6 @@ test_build_update_descriptors(void *arg)
done:
hs_free_all();
nodelist_free_all();
- UNMOCK(hs_overlap_mode_is_active);
}
static void
@@ -1209,7 +1183,6 @@ test_upload_descriptors(void *arg)
(void) arg;
hs_init();
- MOCK(hs_overlap_mode_is_active, mock_hs_overlap_mode_is_active_true);
MOCK(get_or_state,
get_or_state_replacement);
MOCK(networkstatus_get_live_consensus,
@@ -1253,7 +1226,6 @@ test_upload_descriptors(void *arg)
done:
hs_free_all();
- UNMOCK(hs_overlap_mode_is_active);
UNMOCK(get_or_state);
}