diff options
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/hs_service.c | 105 | ||||
-rw-r--r-- | src/or/hs_service.h | 2 | ||||
-rw-r--r-- | src/or/main.c | 30 |
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. */ |