diff --git a/crates/tor-chanmgr/src/mgr.rs b/crates/tor-chanmgr/src/mgr.rs index b95cefb75..28b030390 100644 --- a/crates/tor-chanmgr/src/mgr.rs +++ b/crates/tor-chanmgr/src/mgr.rs @@ -12,7 +12,7 @@ use std::result::Result as StdResult; use std::sync::Arc; use std::time::Duration; use tor_error::internal; -use tor_linkspec::HasRelayIds; +use tor_linkspec::{HasRelayIds, RelayIds}; use tor_netdir::params::NetParameters; use tor_proto::channel::params::ChannelPaddingInstructionsUpdates; @@ -120,10 +120,13 @@ impl AbstractChanMgr { /// Helper: return the objects used to inform pending tasks /// about a newly open or failed channel. - fn setup_launch(&self) -> (map::ChannelState, Sending) { + fn setup_launch(&self, ids: RelayIds) -> (map::ChannelState, Sending) { let (snd, rcv) = oneshot::channel(); - let shared = rcv.shared(); - (map::ChannelState::Building(shared), snd) + let pending = rcv.shared(); + ( + map::ChannelState::Building(map::PendingEntry { ids, pending }), + snd, + ) } /// Get a channel whose identity is `ident`. @@ -143,6 +146,8 @@ impl AbstractChanMgr { ) -> Result<(CF::Channel, ChanProvenance)> { use ChannelUsage as CU; + // TODO pt-client: This is not yet used. + let chan = self.get_or_launch_internal(ident, target).await?; match usage { @@ -179,6 +184,8 @@ impl AbstractChanMgr { // TODO(nickm): It would be neat to use tor_retry instead. let mut last_err = None; + let ids = RelayIds::from_relay_ids(&target); + for _ in 0..N_ATTEMPTS { // First, see what state we're in, and what we should do // about it. @@ -196,19 +203,19 @@ impl AbstractChanMgr { } else { // Unusable channel. Move to the Building // state and launch a new channel. - let (newstate, send) = self.setup_launch(); + let (newstate, send) = self.setup_launch(ids.clone()); let action = Action::Launch(send); (Some(newstate), action) } } - Some(Building(ref pending)) => { + Some(Building(map::PendingEntry { ref pending, .. })) => { let action = Action::Wait(pending.clone()); (oldstate, action) } None => { // No channel. Move to the Building // state and launch a new channel. - let (newstate, send) = self.setup_launch(); + let (newstate, send) = self.setup_launch(ids.clone()); let action = Action::Launch(send); (Some(newstate), action) } diff --git a/crates/tor-chanmgr/src/mgr/map.rs b/crates/tor-chanmgr/src/mgr/map.rs index d76daa921..31a85477a 100644 --- a/crates/tor-chanmgr/src/mgr/map.rs +++ b/crates/tor-chanmgr/src/mgr/map.rs @@ -11,6 +11,8 @@ use std::sync::Arc; use tor_cell::chancell::msg::PaddingNegotiate; use tor_config::PaddingLevel; use tor_error::{internal, into_internal}; +use tor_linkspec::HasRelayIds; +use tor_linkspec::RelayIds; use tor_netdir::{params::NetParameters, params::CHANNEL_PADDING_TIMEOUT_UPPER_BOUND}; use tor_proto::channel::padding::Parameters as PaddingParameters; use tor_proto::channel::padding::ParametersBuilder as PaddingParametersBuilder; @@ -79,7 +81,7 @@ pub(crate) enum ChannelState { /// yielding it to the user. Open(OpenEntry), /// A channel that's getting built. - Building(Pending), + Building(PendingEntry), } /// An open channel entry. @@ -91,6 +93,35 @@ pub(crate) struct OpenEntry { pub(crate) max_unused_duration: Duration, } +/// An entry for a not-yet-build channel +#[derive(Clone)] +pub(crate) struct PendingEntry { + /// The keys of the relay to which we're trying to open a channel. + pub(crate) ids: RelayIds, + + /// A future we can clone and listen on to learn when this channel attempt + /// is successful or failed. + /// + /// This entry will be removed from the map (and possibly replaced with an + /// `OpenEntry`) _before_ this future becomes ready. + pub(crate) pending: Pending, +} + +impl HasRelayIds for ChannelState +where + C: HasRelayIds, +{ + fn identity( + &self, + key_type: tor_linkspec::RelayIdType, + ) -> Option> { + match self { + ChannelState::Open(OpenEntry { channel, .. }) => channel.identity(key_type), + ChannelState::Building(PendingEntry { ids, .. }) => ids.identity(key_type), + } + } +} + impl ChannelState { /// Create a new shallow copy of this ChannelState. #[cfg(test)]