summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/hs_service.c105
-rw-r--r--src/or/hs_service.h2
-rw-r--r--src/or/main.c30
3 files changed, 131 insertions, 6 deletions
diff --git a/src/or/hs_service.c b/src/or/hs_service.c
index 5fde42ddbb..a890389cad 100644
--- a/src/or/hs_service.c
+++ b/src/or/hs_service.c
@@ -11,6 +11,7 @@
#include "or.h"
#include "circuitlist.h"
#include "config.h"
+#include "nodelist.h"
#include "relay.h"
#include "rendservice.h"
#include "router.h"
@@ -24,6 +25,15 @@
#include "hs/cell_establish_intro.h"
#include "hs/cell_common.h"
+/* Helper macro. Iterate over every service in the global map. The var is the
+ * name of the service pointer. */
+#define FOR_EACH_SERVICE_BEGIN(var) \
+ STMT_BEGIN \
+ hs_service_t **var##_iter, *var; \
+ HT_FOREACH(var##_iter, hs_service_ht, hs_service_map) { \
+ var = *var##_iter;
+#define FOR_EACH_SERVICE_END } STMT_END ;
+
/* Onion service directory file names. */
static const char *fname_keyfile_prefix = "hs_ed25519";
static const char *fname_hostname = "hostname";
@@ -510,6 +520,78 @@ load_service_keys(hs_service_t *service)
return ret;
}
+/* Scheduled event run from the main loop. Make sure all our services are up
+ * to date and ready for the other scheduled events. This includes looking at
+ * the introduction points status and descriptor rotation time. */
+static void
+run_housekeeping_event(time_t now)
+{
+ (void) now;
+}
+
+/* Scheduled event run from the main loop. Make sure all descriptors are up to
+ * date. Once this returns, each service descriptor needs to be considered for
+ * new introduction circuits and then for upload. */
+static void
+run_build_descriptor_event(time_t now)
+{
+ (void) now;
+ /* For v2 services, this step happens in the upload event. */
+
+ /* Run v3+ events. */
+ FOR_EACH_SERVICE_BEGIN(service) {
+ /* XXX: Actually build descriptors. */
+ (void) service;
+ } FOR_EACH_SERVICE_END;
+}
+
+/* Scheduled event run from the main loop. Make sure we have all the circuits
+ * we need for each service. */
+static void
+run_build_circuit_event(time_t now)
+{
+ (void) now;
+
+ /* Make sure we can actually have enough information to build internal
+ * circuits as required by services. */
+ if (router_have_consensus_path() == CONSENSUS_PATH_UNKNOWN) {
+ return;
+ }
+
+ /* Run v2 check. */
+ if (num_rend_services() > 0) {
+ rend_consider_services_intro_points();
+ }
+ /* Run v3+ check. */
+ FOR_EACH_SERVICE_BEGIN(service) {
+ /* XXX: Check every service for validity of circuits. */
+ (void) service;
+ } FOR_EACH_SERVICE_END;
+}
+
+/* Scheduled event run from the main loop. Try to upload the descriptor for
+ * each service. */
+static void
+run_upload_descriptor_event(time_t now)
+{
+ /* v2 services use the same function for descriptor creation and upload so
+ * we do everything here because the intro circuits were checked before. */
+ if (num_rend_services() > 0) {
+ rend_consider_services_upload(now);
+ rend_consider_descriptor_republication();
+ }
+
+ /* Run v3+ check. */
+ FOR_EACH_SERVICE_BEGIN(service) {
+ /* XXX: Upload if needed the descriptor(s). Update next upload time. */
+ (void) service;
+ } FOR_EACH_SERVICE_END;
+}
+
+/* ========== */
+/* Public API */
+/* ========== */
+
/* Load and/or generate keys for all onion services including the client
* authorization if any. Return 0 on success, -1 on failure. */
int
@@ -619,6 +701,29 @@ hs_service_free(hs_service_t *service)
tor_free(service);
}
+/* Periodic callback. Entry point from the main loop to the HS service
+ * subsystem. This is call every second. This is skipped if tor can't build a
+ * circuit or the network is disabled. */
+void
+hs_service_run_scheduled_events(time_t now)
+{
+ /* First thing we'll do here is to make sure our services are in a
+ * quiescent state for the scheduled events. */
+ run_housekeeping_event(now);
+
+ /* Order matters here. We first make sure the descriptor object for each
+ * service contains the latest data. Once done, we check if we need to open
+ * new introduction circuit. Finally, we try to upload the descriptor for
+ * each service. */
+
+ /* Make sure descriptors are up to date. */
+ run_build_descriptor_event(now);
+ /* Make sure services have enough circuits. */
+ run_build_circuit_event(now);
+ /* Upload the descriptors if needed/possible. */
+ run_upload_descriptor_event(now);
+}
+
/* Initialize the service HS subsystem. */
void
hs_service_init(void)
diff --git a/src/or/hs_service.h b/src/or/hs_service.h
index ad95a20ed8..493329e22f 100644
--- a/src/or/hs_service.h
+++ b/src/or/hs_service.h
@@ -223,6 +223,8 @@ void hs_service_free(hs_service_t *service);
void hs_service_stage_services(const smartlist_t *service_list);
int hs_service_load_all_keys(void);
+void hs_service_run_scheduled_events(time_t now);
+
/* These functions are only used by unit tests and we need to expose them else
* hs_service.o ends up with no symbols in libor.a which makes clang throw a
* warning at compile time. See #21825. */
diff --git a/src/or/main.c b/src/or/main.c
index dc23184961..a45e64929f 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1194,6 +1194,7 @@ CALLBACK(heartbeat);
CALLBACK(clean_consdiffmgr);
CALLBACK(reset_padding_counts);
CALLBACK(check_canonical_channels);
+CALLBACK(hs_service);
#undef CALLBACK
@@ -1229,6 +1230,7 @@ static periodic_event_item_t periodic_events[] = {
CALLBACK(clean_consdiffmgr),
CALLBACK(reset_padding_counts),
CALLBACK(check_canonical_channels),
+ CALLBACK(hs_service),
END_OF_PERIODIC_EVENTS
};
#undef CALLBACK
@@ -1461,12 +1463,6 @@ run_scheduled_events(time_t now)
/* 6. And remove any marked circuits... */
circuit_close_all_marked();
- /* 7. And upload service descriptors if necessary. */
- if (have_completed_a_circuit() && !net_is_disabled()) {
- rend_consider_services_upload(now);
- rend_consider_descriptor_republication();
- }
-
/* 8. and blow away any connections that need to die. have to do this now,
* because if we marked a conn for close and left its socket -1, then
* we'll pass it to poll/select and bad things will happen.
@@ -2101,6 +2097,28 @@ clean_consdiffmgr_callback(time_t now, const or_options_t *options)
return CDM_CLEAN_CALLBACK_INTERVAL;
}
+/*
+ * Periodic callback: Run scheduled events for HS service. This is called
+ * every second.
+ */
+static int
+hs_service_callback(time_t now, const or_options_t *options)
+{
+ (void) options;
+
+ /* We need to at least be able to build circuits and that we actually have
+ * a working network. */
+ if (!have_completed_a_circuit() || net_is_disabled()) {
+ goto end;
+ }
+
+ hs_service_run_scheduled_events(now);
+
+ end:
+ /* Every 1 second. */
+ return 1;
+}
+
/** Timer: used to invoke second_elapsed_callback() once per second. */
static periodic_timer_t *second_timer = NULL;
/** Number of libevent errors in the last second: we die if we get too many. */