return NULL;
}
+/** Return a bitmask of the roles this tor instance is configured for using
+ * the given options. */
+static int
+get_my_roles(const or_options_t *options)
+{
+ tor_assert(options);
+
+ int roles = 0;
+ int is_bridge = options->BridgeRelay;
+ int is_client = any_client_port_set(options);
+ int is_relay = server_mode(options);
+ int is_dirauth = authdir_mode_v3(options);
+ int is_bridgeauth = authdir_mode_bridge(options);
+ int is_hidden_service = !!hs_service_get_num_services() ||
+ !!rend_num_services();
+
+ if (is_bridge) roles |= PERIODIC_EVENT_ROLE_BRIDGE;
+ if (is_client) roles |= PERIODIC_EVENT_ROLE_CLIENT;
+ if (is_relay) roles |= PERIODIC_EVENT_ROLE_RELAY;
+ if (is_dirauth) roles |= PERIODIC_EVENT_ROLE_DIRAUTH;
+ if (is_bridgeauth) roles |= PERIODIC_EVENT_ROLE_BRIDGEAUTH;
+ if (is_hidden_service) roles |= PERIODIC_EVENT_ROLE_HS_SERVICE;
+
+ return roles;
+}
+
/** Event to run initialize_periodic_events_cb */
static struct event *initialize_periodic_events_event = NULL;
(void) fd;
(void) events;
(void) data;
+
+ int roles = get_my_roles(get_options());
+
tor_event_free(initialize_periodic_events_event);
- int i;
- for (i = 0; periodic_events[i].name; ++i) {
- periodic_event_launch(&periodic_events[i]);
+
+ for (int i = 0; periodic_events[i].name; ++i) {
+ periodic_event_item_t *item = &periodic_events[i];
+ if (item->roles & roles && !periodic_event_is_enabled(item)) {
+ periodic_event_launch(item);
+ log_debug(LD_GENERAL, "Launching periodic event %s", item->name);
+ }
}
}
tor_assert(periodic_events_initialized == 0);
periodic_events_initialized = 1;
+ /* Set up all periodic events. We'll launch them by roles. */
int i;
for (i = 0; periodic_events[i].name; ++i) {
periodic_event_setup(&periodic_events[i]);
* XXXX If we need this elsewhere at any point, we should make it nonstatic
* XXXX and move it into another file.
*/
-static int
+int
any_client_port_set(const or_options_t *options)
{
return (options->SocksPort_set ||
#define vote_routerstatus_free(rs) \
FREE_AND_NULL(vote_routerstatus_t, vote_routerstatus_free_, (rs))
+int any_client_port_set(const or_options_t *options);
+
#ifdef NETWORKSTATUS_PRIVATE
#ifdef TOR_UNIT_TESTS
STATIC int networkstatus_set_current_consensus_from_ns(networkstatus_t *c,
void
periodic_event_reschedule(periodic_event_item_t *event)
{
- periodic_event_set_interval(event, 1);
+ /* Don't reschedule a disabled event. */
+ if (periodic_event_is_enabled(event)) {
+ periodic_event_set_interval(event, 1);
+ }
}
/** Initializes the libevent backend for a periodic event. */
log_err(LD_BUG, "periodic_event_launch without periodic_event_setup");
tor_assert(0);
}
+ /* Event already enabled? This is a bug */
+ if (periodic_event_is_enabled(event)) {
+ log_err(LD_BUG, "periodic_event_launch on an already enabled event");
+ tor_assert(0);
+ }
// Initial dispatch
periodic_event_dispatch(event->ev, event);
+ event->enabled = 1;
}
/** Release all storage associated with <b>event</b> */
return;
mainloop_event_free(event->ev);
event->last_action_time = 0;
+ event->enabled = 0;
}
/* Bitmask of roles define above for which this event applies. */
uint32_t roles;
+ /* Indicate that this event has been enabled that is scheduled. */
+ unsigned int enabled : 1;
} periodic_event_item_t;
/** events will get their interval from first execution */
-#define PERIODIC_EVENT(fn, r) { fn##_callback, 0, NULL, #fn, r }
-#define END_OF_PERIODIC_EVENTS { NULL, 0, NULL, NULL, 0 }
+#define PERIODIC_EVENT(fn, r) { fn##_callback, 0, NULL, #fn, r, 0 }
+#define END_OF_PERIODIC_EVENTS { NULL, 0, NULL, NULL, 0, 0 }
+
+/* Return true iff the given event was setup before thus is enabled to be
+ * scheduled. */
+static inline int
+periodic_event_is_enabled(const periodic_event_item_t *item)
+{
+ return item->enabled;
+}
void periodic_event_launch(periodic_event_item_t *event);
void periodic_event_setup(periodic_event_item_t *event);