Skip to main content

Reactor

Struct Reactor 

Source
pub(super) struct Reactor<R: Runtime, M: Mockable> {
Show 14 fields imm: Arc<Immutable<R, M>>, dir_provider: Arc<dyn NetDirProvider>, inner: Arc<Mutex<Inner>>, ipt_watcher: IptsPublisherView, config_rx: Receiver<Arc<OnionServiceConfig>>, key_dirs_rx: FileEventReceiver, key_dirs_tx: FileEventSender, publish_status_rx: Receiver<PublishStatus>, publish_status_tx: Sender<PublishStatus>, upload_task_complete_rx: Receiver<TimePeriodUploadResult>, upload_task_complete_tx: Sender<TimePeriodUploadResult>, shutdown_tx: Sender<Void>, path_resolver: Arc<CfgPathResolver>, update_from_pow_manager_rx: Receiver<TimePeriod>,
}
Expand description

A reactor for the HsDir Publisher

The entrypoint is Reactor::run.

Fields§

§imm: Arc<Immutable<R, M>>

The immutable, shared inner state.

§dir_provider: Arc<dyn NetDirProvider>

A source for new network directories that we use to determine our HsDirs.

§inner: Arc<Mutex<Inner>>

The mutable inner state,

§ipt_watcher: IptsPublisherView

A channel for receiving IPT change notifications.

§config_rx: Receiver<Arc<OnionServiceConfig>>

A channel for receiving onion service config change notifications.

§key_dirs_rx: FileEventReceiver

A channel for receiving restricted discovery key_dirs change notifications.

§key_dirs_tx: FileEventSender

A channel for sending restricted discovery key_dirs change notifications.

A copy of this sender is handed out to every FileWatcher created.

§publish_status_rx: Receiver<PublishStatus>

A channel for receiving updates regarding our PublishStatus.

The main loop of the reactor watches for updates on this channel.

When the PublishStatus changes to UploadScheduled, we can start publishing descriptors.

If the PublishStatus is AwaitingIpts, publishing is paused until we receive a notification on ipt_watcher telling us the IPT manager has established some introduction points.

§publish_status_tx: Sender<PublishStatus>

A sender for updating our PublishStatus.

When our PublishStatus changes to UploadScheduled, we can start publishing descriptors.

§upload_task_complete_rx: Receiver<TimePeriodUploadResult>

A channel for sending upload completion notifications.

This channel is polled in the main loop of the reactor.

§upload_task_complete_tx: Sender<TimePeriodUploadResult>

A channel for receiving upload completion notifications.

A copy of this sender is handed to each upload task.

§shutdown_tx: Sender<Void>

A sender for notifying any pending upload tasks that the reactor is shutting down.

Receivers can use this channel to find out when reactor is dropped.

This is currently only used in upload_for_time_period. Any future background tasks can also use this channel to detect if the reactor is dropped.

Closing this channel will cause any pending upload tasks to be dropped.

§path_resolver: Arc<CfgPathResolver>

Path resolver for configuration files.

§update_from_pow_manager_rx: Receiver<TimePeriod>

Queue on which we receive messages from the PowManager telling us that a seed has rotated and thus we need to republish the descriptor for a particular time period.

Implementations§

Source§

impl<R: Runtime, M: Mockable> Reactor<R, M>

Source

pub(super) fn new( runtime: R, nickname: HsNickname, dir_provider: Arc<dyn NetDirProvider>, mockable: M, config: &OnionServiceConfig, ipt_watcher: IptsPublisherView, config_rx: Receiver<Arc<OnionServiceConfig>>, status_tx: PublisherStatusSender, keymgr: Arc<KeyMgr>, path_resolver: Arc<CfgPathResolver>, pow_manager: Arc<PowManagerGeneric<R, RendRequest>>, update_from_pow_manager_rx: Receiver<TimePeriod>, ) -> Self

Create a new Reactor.

Source

pub(super) async fn run(self) -> Result<(), FatalError>

Start the reactor.

Under normal circumstances, this function runs indefinitely.

Note: this also spawns the “reminder task” that we use to reschedule uploads whenever an upload fails or is rate-limited.

Source

async fn run_once(&mut self) -> Result<ShutdownStatus, FatalError>

Run one iteration of the reactor loop.

Source

fn status(&self) -> PublishStatus

Returns the current status of the publisher

Source

fn handle_upload_results(&self, results: TimePeriodUploadResult)

Handle a batch of upload outcomes, possibly updating the status of the descriptor for the corresponding HSDirs.

Source

async fn handle_consensus_change( &mut self, netdir: Arc<NetDir>, ) -> Result<(), FatalError>

Maybe update our list of HsDirs.

Source

fn recompute_hs_dirs(&self) -> Result<(), FatalError>

Recompute the HsDirs for all relevant time periods.

Source

fn compute_time_periods( &self, netdir: &Arc<NetDir>, time_periods: &[TimePeriodContext], ) -> Result<Vec<TimePeriodContext>, FatalError>

Compute the TimePeriodContexts for the time periods from the specified NetDir.

The specified time_periods are used to preserve the DescriptorStatus of the HsDirs where possible.

Source

fn replace_netdir(&self, new_netdir: Arc<NetDir>) -> Option<Arc<NetDir>>

Replace the old netdir with the new, returning the old.

Source

fn replace_config_if_changed( &self, new_config: Arc<OnionServiceConfigPublisherView>, ) -> bool

Replace our view of the service config with new_config if new_config contains changes that would cause us to generate a new descriptor.

Source

fn update_file_watcher(&self)

Recreate the FileWatcher for watching the restricted discovery key_dirs.

Source

fn note_ipt_change(&self) -> PublishStatus

Read the intro points from ipt_watcher, and decide whether we’re ready to start uploading.

Source

async fn handle_ipt_change( &mut self, update: Option<Result<(), FatalError>>, ) -> Result<ShutdownStatus, FatalError>

Update our list of introduction points.

Source

async fn update_publish_status_unless_waiting( &mut self, new_state: PublishStatus, ) -> Result<(), FatalError>

Update the PublishStatus of the reactor with new_state, unless the current state is AwaitingIpts.

Source

async fn update_publish_status_unless_rate_lim( &mut self, new_state: PublishStatus, ) -> Result<(), FatalError>

Update the PublishStatus of the reactor with new_state, unless the current state is RateLimited.

Source

async fn update_publish_status( &mut self, new_state: PublishStatus, ) -> Result<(), Bug>

Unconditionally update the PublishStatus of the reactor with new_state.

Source

fn upload_result_to_svc_status(&self) -> Result<(), FatalError>

Update the onion svc status based on the results of the last descriptor uploads.

Source

async fn handle_svc_config_change( &mut self, config: &OnionServiceConfig, ) -> Result<(), FatalError>

Update the descriptors based on the config change.

Source

async fn handle_key_dirs_change( &mut self, event: FileEvent, ) -> Result<(), FatalError>

Update the descriptors based on a restricted discovery key_dirs change.

If the authorized clients from the RestrictedDiscoveryConfig have changed, this marks the descriptor as dirty for all time periods, and schedules a reupload.

Source

fn update_authorized_clients_if_changed(&mut self) -> bool

Recreate the authorized_clients based on the current config.

Returns true if the authorized clients have changed.

Source

fn read_authorized_clients( config: &RestrictedDiscoveryConfig, path_resolver: &CfgPathResolver, ) -> Option<Arc<BTreeMap<HsClientNickname, HsClientDescEncKey>>>

Read the authorized RestrictedDiscoveryKeys from config.

Source

fn mark_all_dirty(&self)

Mark the descriptor dirty for all time periods.

Source

fn mark_dirty(&self, period: &TimePeriod) -> bool

Mark the descriptor dirty for the specified time period.

Returns true if the specified period is still relevant, and false otherwise.

Source

async fn upload_all(&mut self) -> Result<(), FatalError>

Try to upload our descriptor to the HsDirs that need it.

If we’ve recently uploaded some descriptors, we return immediately and schedule the upload to happen after UPLOAD_RATE_LIM_THRESHOLD.

Failed uploads are retried (see upload_descriptor_with_retries).

If restricted discovery mode is enabled and there are no authorized clients, we abort the upload and set our status to State::Broken. For each current time period, we spawn a task that uploads the descriptor to all the HsDirs on the HsDir ring of that time period. Each task shuts down on completion, or when the reactor is dropped.

Each task reports its upload results (TimePeriodUploadResult) via the upload_task_complete_tx channel. The results are received and processed in the main loop of the reactor.

Returns an error if it fails to spawn a task, or if an internal error occurs.

Source

async fn upload_for_time_period( hs_dirs: Vec<RelayIds>, netdir: &Arc<NetDir>, config: Arc<OnionServiceConfigPublisherView>, params: HsDirParams, imm: Arc<Immutable<R, M>>, ipt_upload_view: IptsPublisherUploadView, authorized_clients: Option<Arc<BTreeMap<HsClientNickname, HsClientDescEncKey>>>, upload_task_complete_tx: Sender<TimePeriodUploadResult>, shutdown_rx: Receiver<Void>, ) -> Result<(), FatalError>

Upload the descriptor for the time period specified in params.

Failed uploads are retried (see upload_descriptor_with_retries).

Source

async fn upload_descriptor( hsdesc: String, netdir: &Arc<NetDir>, hsdir: &Relay<'_>, imm: Arc<Immutable<R, M>>, ) -> Result<(), UploadError>

Upload a descriptor to the specified HSDir.

If an upload fails, this returns an Err. This function does not handle retries. It is up to the caller to retry on failure.

This function does not handle timeouts.

Source

async fn upload_descriptor_with_retries( hsdesc: String, netdir: &Arc<NetDir>, hsdir: &Relay<'_>, ed_id: &str, rsa_id: &str, imm: Arc<Immutable<R, M>>, ) -> Result<(), DescUploadRetryError>

Upload a descriptor to the specified HSDir, retrying if appropriate.

Any failed uploads are retried according to a PublisherBackoffSchedule. Each failed upload is retried until it succeeds, or until the overall timeout specified by BackoffSchedule::overall_timeout elapses. Individual attempts are timed out according to the BackoffSchedule::single_attempt_timeout. This function gives up after the overall timeout elapses, declaring the upload a failure, and never retrying it again.

See also BackoffSchedule.

Source

async fn start_rate_limit(&mut self, delay: Duration) -> Result<(), Bug>

Stop publishing descriptors until the specified delay elapses.

Source

async fn expire_rate_limit(&mut self) -> Result<(), Bug>

Handle the upload rate-limit being lifted.

Source

fn authorized_clients( &self, ) -> Result<Option<Arc<BTreeMap<HsClientNickname, HsClientDescEncKey>>>, FatalError>

Return the authorized clients, if restricted mode is enabled.

Returns Ok(None) if restricted discovery mode is disabled.

Returns an error if restricted discovery mode is enabled, but the client list is empty.

Auto Trait Implementations§

§

impl<R, M> !Freeze for Reactor<R, M>

§

impl<R, M> !RefUnwindSafe for Reactor<R, M>

§

impl<R, M> Send for Reactor<R, M>

§

impl<R, M> Sync for Reactor<R, M>

§

impl<R, M> Unpin for Reactor<R, M>

§

impl<R, M> UnsafeUnpin for Reactor<R, M>

§

impl<R, M> !UnwindSafe for Reactor<R, M>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Sync + Send>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> PossiblyOption<T> for T

Source§

fn to_option(self) -> Option<T>

Convert this object into an Option<T>
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more