Skip to main content

tor_chanmgr/
mgr.rs

1//! Abstract implementation of a channel manager
2
3use crate::factory::BootstrapReporter;
4use crate::mgr::state::{ChannelForTarget, PendingChannelHandle};
5use crate::{ChanProvenance, ChannelConfig, ChannelUsage, Dormancy, Error, Result};
6
7use async_trait::async_trait;
8use futures::future::Shared;
9use oneshot_fused_workaround as oneshot;
10use std::result::Result as StdResult;
11use std::sync::Arc;
12use std::time::Duration;
13use tor_error::{error_report, internal};
14use tor_linkspec::{HasChanMethod, HasRelayIds};
15use tor_netdir::params::NetParameters;
16use tor_proto::channel::kist::KistParams;
17use tor_proto::channel::params::ChannelPaddingInstructionsUpdates;
18use tor_proto::memquota::{ChannelAccount, SpecificAccount as _, ToplevelAccount};
19use tracing::{instrument, trace};
20
21#[cfg(feature = "relay")]
22use {safelog::Sensitive, std::net::SocketAddr, tor_proto::RelayChannelAuthMaterial};
23
24mod select;
25mod state;
26
27/// Trait to describe as much of a
28/// [`Channel`](tor_proto::channel::Channel) as `AbstractChanMgr`
29/// needs to use.
30pub(crate) trait AbstractChannel: HasRelayIds {
31    /// Return true iff this channel is considered canonical by us.
32    fn is_canonical(&self) -> bool;
33    /// Return true if we think the peer considers this channel as canonical.
34    fn is_canonical_to_peer(&self) -> bool;
35    /// Return true if this channel is usable.
36    ///
37    /// A channel might be unusable because it is closed, because it has
38    /// hit a bug, or for some other reason.  We don't return unusable
39    /// channels back to the user.
40    fn is_usable(&self) -> bool;
41    /// Return the amount of time a channel has not been in use.
42    /// Return None if the channel is currently in use.
43    fn duration_unused(&self) -> Option<Duration>;
44
45    /// Reparameterize this channel according to the provided `ChannelPaddingInstructionsUpdates`
46    ///
47    /// The changed parameters may not be implemented "immediately",
48    /// but this will be done "reasonably soon".
49    fn reparameterize(
50        &self,
51        updates: Arc<ChannelPaddingInstructionsUpdates>,
52    ) -> tor_proto::Result<()>;
53
54    /// Update the KIST parameters.
55    ///
56    /// The changed parameters may not be implemented "immediately",
57    /// but this will be done "reasonably soon".
58    fn reparameterize_kist(&self, kist_params: KistParams) -> tor_proto::Result<()>;
59
60    /// Specify that this channel should do activities related to channel padding
61    ///
62    /// See [`Channel::engage_padding_activities`]
63    ///
64    /// [`Channel::engage_padding_activities`]: tor_proto::channel::Channel::engage_padding_activities
65    fn engage_padding_activities(&self);
66}
67
68/// Trait to describe how channels-like objects are created.
69///
70/// This differs from [`ChannelFactory`](crate::factory::ChannelFactory) in that
71/// it's a purely crate-internal type that we use to decouple the
72/// AbstractChanMgr code from actual "what is a channel" concerns.
73#[async_trait]
74pub(crate) trait AbstractChannelFactory {
75    /// The type of channel that this factory can build.
76    type Channel: AbstractChannel;
77    /// Type that explains how to build an outgoing channel.
78    type BuildSpec: HasRelayIds + HasChanMethod;
79    /// The type of byte stream that's required to build channels for incoming connections.
80    type Stream;
81
82    /// Construct a new channel to the destination described at `target`.
83    ///
84    /// This function must take care of all timeouts, error detection,
85    /// and so on.
86    ///
87    /// It should not retry; that is handled at a higher level.
88    async fn build_channel(
89        &self,
90        target: &Self::BuildSpec,
91        reporter: BootstrapReporter,
92        memquota: ChannelAccount,
93    ) -> Result<Arc<Self::Channel>>;
94
95    /// Construct a new channel for an incoming connection.
96    #[cfg(feature = "relay")]
97    async fn build_channel_using_incoming(
98        &self,
99        peer: Sensitive<std::net::SocketAddr>,
100        stream: Self::Stream,
101        memquota: ChannelAccount,
102    ) -> Result<Arc<Self::Channel>>;
103}
104
105/// This is the configuration for a [`ChanMgr`](crate::ChanMgr) given to the constructor.
106#[derive(Default)]
107pub struct ChanMgrConfig {
108    /// Channel configuration which usually comes from a configuration file.
109    pub(crate) cfg: ChannelConfig,
110    /// Relay authentication key material for relay channels.
111    #[cfg(feature = "relay")]
112    pub(crate) auth_material: Option<Arc<RelayChannelAuthMaterial>>,
113    /// Our address(es). When building outgoing channel, we need our addresses in order to send
114    /// them in the NETINFO cell. It will also be used to validate initiator channel target.
115    #[cfg(feature = "relay")]
116    pub(crate) my_addrs: Vec<SocketAddr>,
117    // TODO: Would be good to add more things such as NetParameters and Dormancy maybe?
118}
119
120impl ChanMgrConfig {
121    /// Constructor.
122    pub fn new(cfg: ChannelConfig) -> Self {
123        Self {
124            cfg,
125            #[cfg(feature = "relay")]
126            auth_material: None,
127            #[cfg(feature = "relay")]
128            my_addrs: Vec::new(),
129        }
130    }
131
132    /// Set the relay channel authentication key material and return itself.
133    #[cfg(feature = "relay")]
134    pub fn with_auth_material(mut self, auth_material: Arc<RelayChannelAuthMaterial>) -> Self {
135        self.auth_material = Some(auth_material);
136        self
137    }
138
139    /// Set our addresses that we advertise to the world.
140    #[cfg(feature = "relay")]
141    pub fn with_my_addrs(mut self, my_addrs: Vec<SocketAddr>) -> Self {
142        self.my_addrs = my_addrs;
143        self
144    }
145}
146
147/// A type- and network-agnostic implementation for [`ChanMgr`](crate::ChanMgr).
148///
149/// This type does the work of keeping track of open channels and pending
150/// channel requests, launching requests as needed, waiting for pending
151/// requests, and so forth.
152///
153/// The actual job of launching connections is deferred to an
154/// `AbstractChannelFactory` type.
155pub(crate) struct AbstractChanMgr<CF: AbstractChannelFactory> {
156    /// All internal state held by this channel manager.
157    ///
158    /// The most important part is the map from relay identity to channel, or
159    /// to pending channel status.
160    pub(crate) channels: state::MgrState<CF>,
161
162    /// A bootstrap reporter to give out when building channels.
163    pub(crate) reporter: BootstrapReporter,
164
165    /// The memory quota account that every channel will be a child of
166    pub(crate) memquota: ToplevelAccount,
167
168    /// Metrics counters / gauges / histograms.
169    #[cfg(feature = "metrics")]
170    pub(crate) metrics: ChanMgrMetrics,
171}
172
173/// Struct to hold all the metrics counters / gauges / histograms we use.
174///
175/// We create these and store them in the [`AbstractChanMgr`] in order to avoid
176/// the performance hit associated with re-registering counters.
177#[cfg(feature = "metrics")]
178pub(crate) struct ChanMgrMetrics {
179    /// Number of inbound channels successfully built.
180    pub(crate) inbound_channels_built_success: metrics::Counter,
181    /// Number of inbound channels that we tried to build but had an [`Error::UnusableTarget`] error.
182    pub(crate) inbound_channels_built_failure_unusable_target: metrics::Counter,
183    /// Number of inbound channels that we tried to build but had an [`Error::PendingFailed`] error.
184    pub(crate) inbound_channels_built_failure_pending_failed: metrics::Counter,
185    /// Number of inbound channels that we tried to build but had an [`Error::ChanTimeout`] error.
186    pub(crate) inbound_channels_built_failure_chan_timeout: metrics::Counter,
187    /// Number of inbound channels that we tried to build but had an [`Error::Proto`] error.
188    pub(crate) inbound_channels_built_failure_proto: metrics::Counter,
189    /// Number of inbound channels that we tried to build but had an [`Error::Io`] error.
190    pub(crate) inbound_channels_built_failure_io: metrics::Counter,
191    /// Number of inbound channels that we tried to build but had an [`Error::Connect`] error.
192    pub(crate) inbound_channels_built_failure_connect: metrics::Counter,
193    /// Number of inbound channels that we tried to build but had an [`Error::Spawn`] error.
194    pub(crate) inbound_channels_built_failure_spawn: metrics::Counter,
195    /// Number of inbound channels that we tried to build but had an [`Error::MissingId`] error.
196    pub(crate) inbound_channels_built_failure_missing_id: metrics::Counter,
197    /// Number of inbound channels that we tried to build but had an [`Error::IdentityConflict`] error.
198    pub(crate) inbound_channels_built_failure_identity_conflict: metrics::Counter,
199    /// Number of inbound channels that we tried to build but had an [`Error::NoSuchTransport`] error.
200    pub(crate) inbound_channels_built_failure_no_such_transport: metrics::Counter,
201    /// Number of inbound channels that we tried to build but had an [`Error::RequestCancelled`] error.
202    pub(crate) inbound_channels_built_failure_request_cancelled: metrics::Counter,
203    /// Number of inbound channels that we tried to build but had an [`Error::Pt`] error.
204    pub(crate) inbound_channels_built_failure_pt: metrics::Counter,
205    /// Number of inbound channels that we tried to build but had an [`Error::Memquota`] error.
206    pub(crate) inbound_channels_built_failure_memquota: metrics::Counter,
207    /// Number of inbound channels that we tried to build but had an [`Error::Internal`] error.
208    pub(crate) inbound_channels_built_failure_internal: metrics::Counter,
209}
210
211#[cfg(feature = "metrics")]
212impl ChanMgrMetrics {
213    /// Create a new instance of [`ChanMgrMetrics`].
214    pub(crate) fn new() -> Self {
215        ChanMgrMetrics {
216            inbound_channels_built_success: metrics::counter!(
217                description: "Total number of channels built",
218                unit: metrics::Unit::Count,
219                "arti_chanmgr_channels_built",
220                "result" => "success",
221                "direction" => "inbound",
222            ),
223            inbound_channels_built_failure_unusable_target: metrics::counter!(
224                description: "Total number of channels built",
225                unit: metrics::Unit::Count,
226                "arti_chanmgr_channels_built",
227                "result" => "failure",
228                "direction" => "inbound",
229                "error" => "unusable_target",
230            ),
231            inbound_channels_built_failure_pending_failed: metrics::counter!(
232                description: "Total number of channels built",
233                unit: metrics::Unit::Count,
234                "arti_chanmgr_channels_built",
235                "result" => "failure",
236                "direction" => "inbound",
237                "error" => "pending_failed",
238            ),
239            inbound_channels_built_failure_chan_timeout: metrics::counter!(
240                description: "Total number of channels built",
241                unit: metrics::Unit::Count,
242                "arti_chanmgr_channels_built",
243                "result" => "failure",
244                "direction" => "inbound",
245                "error" => "chan_timeout",
246            ),
247            inbound_channels_built_failure_proto: metrics::counter!(
248                description: "Total number of channels built",
249                unit: metrics::Unit::Count,
250                "arti_chanmgr_channels_built",
251                "result" => "failure",
252                "direction" => "inbound",
253                "error" => "proto",
254            ),
255            inbound_channels_built_failure_io: metrics::counter!(
256                description: "Total number of channels built",
257                unit: metrics::Unit::Count,
258                "arti_chanmgr_channels_built",
259                "result" => "failure",
260                "direction" => "inbound",
261                "error" => "io",
262            ),
263            inbound_channels_built_failure_connect: metrics::counter!(
264                description: "Total number of channels built",
265                unit: metrics::Unit::Count,
266                "arti_chanmgr_channels_built",
267                "result" => "failure",
268                "direction" => "inbound",
269                "error" => "connect",
270            ),
271            inbound_channels_built_failure_spawn: metrics::counter!(
272                description: "Total number of channels built",
273                unit: metrics::Unit::Count,
274                "arti_chanmgr_channels_built",
275                "result" => "failure",
276                "direction" => "inbound",
277                "error" => "spawn",
278            ),
279            inbound_channels_built_failure_missing_id: metrics::counter!(
280                description: "Total number of channels built",
281                unit: metrics::Unit::Count,
282                "arti_chanmgr_channels_built",
283                "result" => "failure",
284                "direction" => "inbound",
285                "error" => "missing_id",
286            ),
287            inbound_channels_built_failure_identity_conflict: metrics::counter!(
288                description: "Total number of channels built",
289                unit: metrics::Unit::Count,
290                "arti_chanmgr_channels_built",
291                "result" => "failure",
292                "direction" => "inbound",
293                "error" => "identity_conflict",
294            ),
295            inbound_channels_built_failure_no_such_transport: metrics::counter!(
296                description: "Total number of channels built",
297                unit: metrics::Unit::Count,
298                "arti_chanmgr_channels_built",
299                "result" => "failure",
300                "direction" => "inbound",
301                "error" => "no_such_transport",
302            ),
303            inbound_channels_built_failure_request_cancelled: metrics::counter!(
304                description: "Total number of channels built",
305                unit: metrics::Unit::Count,
306                "arti_chanmgr_channels_built",
307                "result" => "failure",
308                "direction" => "inbound",
309                "error" => "request_cancelled",
310            ),
311            inbound_channels_built_failure_pt: metrics::counter!(
312                description: "Total number of channels built",
313                unit: metrics::Unit::Count,
314                "arti_chanmgr_channels_built",
315                "result" => "failure",
316                "direction" => "inbound",
317                "error" => "pt",
318            ),
319            inbound_channels_built_failure_memquota: metrics::counter!(
320                description: "Total number of channels built",
321                unit: metrics::Unit::Count,
322                "arti_chanmgr_channels_built",
323                "result" => "failure",
324                "direction" => "inbound",
325                "error" => "memquota",
326            ),
327            inbound_channels_built_failure_internal: metrics::counter!(
328                description: "Total number of channels built",
329                unit: metrics::Unit::Count,
330                "arti_chanmgr_channels_built",
331                "result" => "failure",
332                "direction" => "inbound",
333                "error" => "internal",
334            ),
335        }
336    }
337
338    /// Increment the correct inbound_channels_built counter for the given result.
339    pub(crate) fn increment_inbound_channels_built<R>(&self, result: &Result<R>) {
340        match result {
341            Ok(_) => self.inbound_channels_built_success.increment(1),
342            Err(Error::UnusableTarget(_)) => self
343                .inbound_channels_built_failure_unusable_target
344                .increment(1),
345            Err(Error::PendingFailed { .. }) => self
346                .inbound_channels_built_failure_pending_failed
347                .increment(1),
348            Err(Error::ChanTimeout { .. }) => self
349                .inbound_channels_built_failure_chan_timeout
350                .increment(1),
351            Err(Error::Proto { .. }) => self.inbound_channels_built_failure_proto.increment(1),
352            Err(Error::Io { .. }) => self.inbound_channels_built_failure_io.increment(1),
353            Err(Error::Connect { .. }) => self.inbound_channels_built_failure_connect.increment(1),
354            Err(Error::Spawn { .. }) => self.inbound_channels_built_failure_spawn.increment(1),
355            Err(Error::MissingId) => self.inbound_channels_built_failure_missing_id.increment(1),
356            Err(Error::IdentityConflict) => self
357                .inbound_channels_built_failure_identity_conflict
358                .increment(1),
359            Err(Error::NoSuchTransport(_)) => self
360                .inbound_channels_built_failure_no_such_transport
361                .increment(1),
362            Err(Error::RequestCancelled) => self
363                .inbound_channels_built_failure_request_cancelled
364                .increment(1),
365            Err(Error::Pt(_)) => self.inbound_channels_built_failure_pt.increment(1),
366            Err(Error::Memquota(_)) => self.inbound_channels_built_failure_memquota.increment(1),
367            Err(Error::Internal(_)) => self.inbound_channels_built_failure_internal.increment(1),
368        }
369    }
370}
371
372/// Type alias for a future that we wait on to see when a pending
373/// channel is done or failed.
374type Pending = Shared<oneshot::Receiver<Result<()>>>;
375
376/// Type alias for the sender we notify when we complete a channel (or fail to
377/// complete it).
378type Sending = oneshot::Sender<Result<()>>;
379
380/// Keeps a pending launch entry and its waiters in sync.
381///
382/// Every exit path from a launch attempt must either remove the pending entry
383/// or upgrade it to an open channel, and must notify all waiters with the
384/// outcome. This guard makes cancellation and early returns follow the same
385/// cleanup path as ordinary failures.
386struct PendingLaunchGuard<'a, CF: AbstractChannelFactory> {
387    /// Channel state used to remove or upgrade the pending entry.
388    channels: &'a state::MgrState<CF>,
389    /// Handle to the pending entry, if it has not yet been removed.
390    handle: Option<PendingChannelHandle>,
391    /// Sender used to notify tasks waiting on this launch.
392    send: Option<Sending>,
393    /// Result to report to the waiters if the launch ends here.
394    result: Result<()>,
395}
396
397impl<'a, CF: AbstractChannelFactory> PendingLaunchGuard<'a, CF> {
398    /// Create a new guard for a pending launch.
399    fn new(channels: &'a state::MgrState<CF>, handle: PendingChannelHandle, send: Sending) -> Self {
400        Self {
401            channels,
402            handle: Some(handle),
403            send: Some(send),
404            result: Err(Error::RequestCancelled),
405        }
406    }
407
408    /// Record the result that should be reported to any waiters.
409    fn note_result(&mut self, result: Result<()>) {
410        self.result = result;
411    }
412
413    /// Replace the pending channel with an open one.
414    fn upgrade_pending_channel_to_open(&mut self, channel: Arc<CF::Channel>) -> Result<()> {
415        let handle = self
416            .handle
417            .take()
418            .expect("pending launch guard lost its handle before upgrade");
419        self.channels
420            .upgrade_pending_channel_to_open(handle, channel)
421    }
422}
423
424impl<'a, CF: AbstractChannelFactory> Drop for PendingLaunchGuard<'a, CF> {
425    fn drop(&mut self) {
426        if let Some(handle) = self.handle.take() {
427            if let Err(e) = self.channels.remove_pending_channel(handle) {
428                // Just log an error if we're unable to remove it, since there's
429                // nothing else we can do here, and returning the error would
430                // hide the actual error that we care about (the channel build
431                // failure).
432                #[allow(clippy::missing_docs_in_private_items)]
433                const MSG: &str = "Unable to remove the pending channel";
434                error_report!(internal!("{e}"), "{}", MSG);
435            }
436        }
437
438        if let Some(send) = self.send.take() {
439            // It's okay if all the receivers went away:
440            // that means that nobody was waiting for this channel.
441            let _ignore_err = send.send(self.result.clone());
442        }
443    }
444}
445
446impl<CF: AbstractChannelFactory + Clone> AbstractChanMgr<CF> {
447    /// Make a new empty channel manager.
448    pub(crate) fn new(
449        connector: CF,
450        config: ChannelConfig,
451        dormancy: Dormancy,
452        netparams: &NetParameters,
453        reporter: BootstrapReporter,
454        memquota: ToplevelAccount,
455    ) -> Self {
456        AbstractChanMgr {
457            channels: state::MgrState::new(connector, config, dormancy, netparams),
458            reporter,
459            memquota,
460            #[cfg(feature = "metrics")]
461            metrics: ChanMgrMetrics::new(),
462        }
463    }
464
465    /// Run a function to modify the channel builder in this object.
466    #[allow(unused)]
467    pub(crate) fn with_mut_builder<F>(&self, func: F)
468    where
469        F: FnOnce(&mut CF),
470    {
471        self.channels.with_mut_builder(func);
472    }
473
474    /// Remove every unusable entry from this channel manager.
475    #[cfg(test)]
476    pub(crate) fn remove_unusable_entries(&self) -> Result<()> {
477        self.channels.remove_unusable()
478    }
479
480    /// Build a channel for an incoming stream. See
481    /// [`ChanMgr::handle_incoming`](crate::ChanMgr::handle_incoming).
482    #[cfg(feature = "relay")]
483    pub(crate) async fn handle_incoming(
484        &self,
485        src: Sensitive<std::net::SocketAddr>,
486        stream: CF::Stream,
487    ) -> Result<Arc<CF::Channel>> {
488        let chan_builder = self.channels.builder();
489        let memquota = ChannelAccount::new(&self.memquota)?;
490        let channel = chan_builder
491            .build_channel_using_incoming(src, stream, memquota)
492            .await?;
493        // Add it to our list.
494        self.channels.add_open(channel.clone())?;
495        Ok(channel)
496    }
497
498    /// Get a channel corresponding to the identities of `target`.
499    ///
500    /// If a usable channel exists with that identity, return it.
501    ///
502    /// If no such channel exists already, and none is in progress,
503    /// launch a new request using `target`.
504    ///
505    /// If no such channel exists already, but we have one that's in
506    /// progress, wait for it to succeed or fail.
507    #[instrument(skip_all, level = "trace")]
508    pub(crate) async fn get_or_launch(
509        &self,
510        target: CF::BuildSpec,
511        usage: ChannelUsage,
512    ) -> Result<(Arc<CF::Channel>, ChanProvenance)> {
513        use ChannelUsage as CU;
514
515        let chan = self.get_or_launch_internal(target).await?;
516
517        match usage {
518            CU::Dir | CU::UselessCircuit => {}
519            CU::UserTraffic => chan.0.engage_padding_activities(),
520        }
521
522        Ok(chan)
523    }
524
525    /// Get a channel whose identity is `ident` - internal implementation
526    #[instrument(skip_all, level = "trace")]
527    async fn get_or_launch_internal(
528        &self,
529        target: CF::BuildSpec,
530    ) -> Result<(Arc<CF::Channel>, ChanProvenance)> {
531        /// How many times do we try?
532        const N_ATTEMPTS: usize = 2;
533        let mut attempts_so_far = 0;
534        let mut final_attempt = false;
535        let mut provenance = ChanProvenance::Preexisting;
536
537        // TODO(nickm): It would be neat to use tor_retry instead.
538        let mut last_err = None;
539
540        while attempts_so_far < N_ATTEMPTS || final_attempt {
541            attempts_so_far += 1;
542
543            // For each attempt, we _first_ look at the state of the channel map
544            // to decide on an `Action`, and _then_ we execute that action.
545
546            // First, see what state we're in, and what we should do about it.
547            let action = self.choose_action(&target, final_attempt)?;
548
549            // We are done deciding on our Action! It's time act based on the
550            // Action that we chose.
551            match action {
552                // If this happens, we were trying to make one final check of our state, but
553                // we would have had to make additional attempts.
554                None => {
555                    if !final_attempt {
556                        return Err(Error::Internal(internal!(
557                            "No action returned while not on final attempt"
558                        )));
559                    }
560                    break;
561                }
562                // Easy case: we have an error or a channel to return.
563                Some(Action::Return(v)) => {
564                    trace!("Returning existing channel");
565                    return v.map(|chan| (chan, provenance));
566                }
567                // There's an in-progress channel.  Wait for it.
568                Some(Action::Wait(pend)) => {
569                    trace!("Waiting for in-progress channel");
570                    match pend.await {
571                        Ok(Ok(())) => {
572                            // We were waiting for a channel, and it succeeded, or it
573                            // got cancelled.  But it might have gotten more
574                            // identities while negotiating than it had when it was
575                            // launched, or it might have failed to get all the
576                            // identities we want. Check for this.
577                            final_attempt = true;
578                            provenance = ChanProvenance::NewlyCreated;
579                            last_err.get_or_insert(Error::RequestCancelled);
580                        }
581                        Ok(Err(e)) => {
582                            last_err = Some(e);
583                        }
584                        Err(_) => {
585                            last_err =
586                                Some(Error::Internal(internal!("channel build task disappeared")));
587                        }
588                    }
589                }
590                // We need to launch a channel.
591                Some(Action::Launch((handle, send))) => {
592                    trace!("Launching channel");
593                    let connector = self.channels.builder();
594                    let mut launch = PendingLaunchGuard::new(&self.channels, handle, send);
595                    let memquota = match ChannelAccount::new(&self.memquota) {
596                        Ok(memquota) => memquota,
597                        Err(e) => {
598                            let e: Error = e.into();
599                            launch.note_result(Err(e.clone()));
600                            return Err(e);
601                        }
602                    };
603
604                    let outcome = connector
605                        .build_channel(&target, self.reporter.clone(), memquota)
606                        .await;
607
608                    match outcome {
609                        Ok(ref chan) => {
610                            // Replace the pending channel with the newly built channel.
611                            match launch.upgrade_pending_channel_to_open(Arc::clone(chan)) {
612                                Ok(()) => launch.note_result(Ok(())),
613                                Err(e) => {
614                                    launch.note_result(Err(e.clone()));
615                                    return Err(e);
616                                }
617                            }
618                        }
619                        Err(_) => {
620                            launch.note_result(outcome.clone().map(|_| ()));
621                        }
622                    }
623
624                    match outcome {
625                        Ok(chan) => {
626                            return Ok((chan, ChanProvenance::NewlyCreated));
627                        }
628                        Err(e) => last_err = Some(e),
629                    }
630                }
631            }
632
633            // End of this attempt. We will try again...
634        }
635
636        Err(last_err.unwrap_or_else(|| Error::Internal(internal!("no error was set!?"))))
637    }
638
639    /// Helper: based on our internal state, decide which action to take when
640    /// asked for a channel, and update our internal state accordingly.
641    ///
642    /// If `final_attempt` is true, then we will not pick any action that does
643    /// not result in an immediate result. If we would pick such an action, we
644    /// instead return `Ok(None)`.  (We could instead have the caller detect
645    /// such actions, but it's less efficient to construct them, insert them,
646    /// and immediately revert them.)
647    #[instrument(skip_all, level = "trace")]
648    fn choose_action(
649        &self,
650        target: &CF::BuildSpec,
651        final_attempt: bool,
652    ) -> Result<Option<Action<CF::Channel>>> {
653        // don't create new channels on the final attempt
654        let response = self.channels.request_channel(
655            target,
656            /* add_new_entry_if_not_found= */ !final_attempt,
657        );
658
659        match response {
660            Ok(Some(ChannelForTarget::Open(channel))) => Ok(Some(Action::Return(Ok(channel)))),
661            Ok(Some(ChannelForTarget::Pending(pending))) => {
662                if !final_attempt {
663                    Ok(Some(Action::Wait(pending)))
664                } else {
665                    // don't return a pending channel on the final attempt
666                    Ok(None)
667                }
668            }
669            Ok(Some(ChannelForTarget::NewEntry((handle, send)))) => {
670                // do not drop the handle if refactoring; see `PendingChannelHandle` for details
671                Ok(Some(Action::Launch((handle, send))))
672            }
673            Ok(None) => Ok(None),
674            Err(e @ Error::IdentityConflict) => Ok(Some(Action::Return(Err(e)))),
675            Err(e) => Err(e),
676        }
677    }
678
679    /// Update the netdir
680    pub(crate) fn update_netparams(
681        &self,
682        netparams: Arc<dyn AsRef<NetParameters>>,
683    ) -> StdResult<(), tor_error::Bug> {
684        self.channels.reconfigure_general(None, None, netparams)
685    }
686
687    /// Notifies the chanmgr to be dormant like dormancy
688    pub(crate) fn set_dormancy(
689        &self,
690        dormancy: Dormancy,
691        netparams: Arc<dyn AsRef<NetParameters>>,
692    ) -> StdResult<(), tor_error::Bug> {
693        self.channels
694            .reconfigure_general(None, Some(dormancy), netparams)
695    }
696
697    /// Reconfigure all channels
698    pub(crate) fn reconfigure(
699        &self,
700        config: &ChannelConfig,
701        netparams: Arc<dyn AsRef<NetParameters>>,
702    ) -> StdResult<(), tor_error::Bug> {
703        self.channels
704            .reconfigure_general(Some(config), None, netparams)
705    }
706
707    /// Expire any channels that have been unused longer than
708    /// their maximum unused duration assigned during creation.
709    ///
710    /// Return a duration from now until next channel expires.
711    ///
712    /// If all channels are in use or there are no open channels,
713    /// return 180 seconds which is the minimum value of
714    /// max_unused_duration.
715    pub(crate) fn expire_channels(&self) -> Duration {
716        self.channels.expire_channels()
717    }
718
719    /// Test only: return the open usable channels with a given `ident`.
720    #[cfg(test)]
721    pub(crate) fn get_nowait<'a, T>(&self, ident: T) -> Vec<Arc<CF::Channel>>
722    where
723        T: Into<tor_linkspec::RelayIdRef<'a>>,
724    {
725        use state::ChannelState::*;
726        self.channels
727            .with_channels(|channel_map| {
728                channel_map
729                    .by_id(ident)
730                    .filter_map(|entry| match entry {
731                        Open(ent) if ent.channel.is_usable() => Some(Arc::clone(&ent.channel)),
732                        _ => None,
733                    })
734                    .collect()
735            })
736            .expect("Poisoned lock")
737    }
738}
739
740/// Possible actions that we'll decide to take when asked for a channel.
741#[allow(clippy::large_enum_variant)]
742enum Action<C: AbstractChannel> {
743    /// We found no channel.  We're going to launch a new one,
744    /// then tell everybody about it.
745    Launch((PendingChannelHandle, Sending)),
746    /// We found an in-progress attempt at making a channel.
747    /// We're going to wait for it to finish.
748    Wait(Pending),
749    /// We found a usable channel.  We're going to return it.
750    Return(Result<Arc<C>>),
751}
752
753#[cfg(test)]
754mod test {
755    // @@ begin test lint list maintained by maint/add_warning @@
756    #![allow(clippy::bool_assert_comparison)]
757    #![allow(clippy::clone_on_copy)]
758    #![allow(clippy::dbg_macro)]
759    #![allow(clippy::mixed_attributes_style)]
760    #![allow(clippy::print_stderr)]
761    #![allow(clippy::print_stdout)]
762    #![allow(clippy::single_char_pattern)]
763    #![allow(clippy::unwrap_used)]
764    #![allow(clippy::unchecked_time_subtraction)]
765    #![allow(clippy::useless_vec)]
766    #![allow(clippy::needless_pass_by_value)]
767    #![allow(clippy::string_slice)] // See arti#2571
768    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
769    use super::*;
770    use crate::Error;
771
772    use futures::{join, poll};
773    use std::error::Error as StdError;
774    use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
775    use std::sync::Arc;
776    use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
777    use std::time::Duration;
778    use tor_error::bad_api_usage;
779    use tor_linkspec::ChannelMethod;
780    use tor_llcrypto::pk::ed25519::Ed25519Identity;
781    use tor_memquota::ArcMemoryQuotaTrackerExt as _;
782
783    use crate::ChannelUsage as CU;
784    use tor_rtcompat::{Runtime, task::yield_now, test_with_one_runtime};
785
786    // Two distinct addresses we can use in tests.
787    const ADDR_A: SocketAddr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 443));
788    const ADDR_B: SocketAddr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(2, 2, 2, 2), 443));
789
790    #[derive(Clone)]
791    struct FakeChannelFactory<RT> {
792        runtime: RT,
793        build_attempts: Arc<AtomicUsize>,
794    }
795
796    #[derive(Clone, Debug)]
797    struct FakeChannel {
798        ed_ident: Ed25519Identity,
799        mood: char,
800        closing: Arc<AtomicBool>,
801        detect_reuse: Arc<char>,
802        // last_params: Option<ChannelPaddingInstructionsUpdates>,
803    }
804
805    impl PartialEq for FakeChannel {
806        fn eq(&self, other: &Self) -> bool {
807            Arc::ptr_eq(&self.detect_reuse, &other.detect_reuse)
808        }
809    }
810
811    impl AbstractChannel for FakeChannel {
812        fn is_canonical(&self) -> bool {
813            unimplemented!()
814        }
815        fn is_canonical_to_peer(&self) -> bool {
816            unimplemented!()
817        }
818        fn is_usable(&self) -> bool {
819            !self.closing.load(Ordering::SeqCst)
820        }
821        fn duration_unused(&self) -> Option<Duration> {
822            None
823        }
824        fn reparameterize(
825            &self,
826            _updates: Arc<ChannelPaddingInstructionsUpdates>,
827        ) -> tor_proto::Result<()> {
828            // *self.last_params.lock().unwrap() = Some((*updates).clone());
829            match self.mood {
830                // Build succeeds, but installing the channel into the manager fails.
831                'r' => Err(tor_proto::Error::ChanProto(
832                    "synthetic reparameterize failure".into(),
833                )),
834                _ => Ok(()),
835            }
836        }
837        fn reparameterize_kist(&self, _kist_params: KistParams) -> tor_proto::Result<()> {
838            Ok(())
839        }
840        fn engage_padding_activities(&self) {}
841    }
842
843    impl HasRelayIds for FakeChannel {
844        fn identity(
845            &self,
846            key_type: tor_linkspec::RelayIdType,
847        ) -> Option<tor_linkspec::RelayIdRef<'_>> {
848            match key_type {
849                tor_linkspec::RelayIdType::Ed25519 => Some((&self.ed_ident).into()),
850                _ => None,
851            }
852        }
853    }
854
855    impl FakeChannel {
856        fn start_closing(&self) {
857            self.closing.store(true, Ordering::SeqCst);
858        }
859    }
860
861    impl<RT: Runtime> FakeChannelFactory<RT> {
862        fn new(runtime: RT, build_attempts: Arc<AtomicUsize>) -> Self {
863            FakeChannelFactory {
864                runtime,
865                build_attempts,
866            }
867        }
868    }
869
870    fn new_test_abstract_chanmgr<R: Runtime>(runtime: R) -> AbstractChanMgr<FakeChannelFactory<R>> {
871        new_test_abstract_chanmgr_and_build_attempts(runtime).0
872    }
873
874    fn new_test_abstract_chanmgr_and_build_attempts<R: Runtime>(
875        runtime: R,
876    ) -> (AbstractChanMgr<FakeChannelFactory<R>>, Arc<AtomicUsize>) {
877        let build_attempts = Arc::new(AtomicUsize::new(0));
878        let cf = FakeChannelFactory::new(runtime, Arc::clone(&build_attempts));
879        let mgr = AbstractChanMgr::new(
880            cf,
881            Default::default(),
882            Default::default(),
883            &Default::default(),
884            BootstrapReporter::fake(),
885            ToplevelAccount::new_noop(),
886        );
887        (mgr, build_attempts)
888    }
889
890    #[derive(Clone, Debug)]
891    struct FakeBuildSpec(u32, char, Ed25519Identity, SocketAddr);
892
893    impl HasRelayIds for FakeBuildSpec {
894        fn identity(
895            &self,
896            key_type: tor_linkspec::RelayIdType,
897        ) -> Option<tor_linkspec::RelayIdRef<'_>> {
898            match key_type {
899                tor_linkspec::RelayIdType::Ed25519 => Some((&self.2).into()),
900                _ => None,
901            }
902        }
903    }
904
905    impl HasChanMethod for FakeBuildSpec {
906        fn chan_method(&self) -> ChannelMethod {
907            ChannelMethod::Direct(vec![self.3.clone()])
908        }
909    }
910
911    /// Helper to make a fake Ed identity from a u32.
912    fn u32_to_ed(n: u32) -> Ed25519Identity {
913        let mut bytes = [0; 32];
914        bytes[0..4].copy_from_slice(&n.to_be_bytes());
915        bytes.into()
916    }
917
918    /// Return true if `needle` appears anywhere in `err`'s error chain.
919    fn error_contains(err: &Error, needle: &str) -> bool {
920        let mut source: Option<&(dyn StdError + 'static)> = Some(err);
921        while let Some(err) = source {
922            if err.to_string().contains(needle) || format!("{err:?}").contains(needle) {
923                return true;
924            }
925            source = err.source();
926        }
927        false
928    }
929
930    #[async_trait]
931    impl<RT: Runtime> AbstractChannelFactory for FakeChannelFactory<RT> {
932        type Channel = FakeChannel;
933        type BuildSpec = FakeBuildSpec;
934        type Stream = ();
935
936        async fn build_channel(
937            &self,
938            target: &Self::BuildSpec,
939            _reporter: BootstrapReporter,
940            _memquota: ChannelAccount,
941        ) -> Result<Arc<FakeChannel>> {
942            self.build_attempts.fetch_add(1, Ordering::SeqCst);
943            yield_now().await;
944            let FakeBuildSpec(ident, mood, id, _addr) = *target;
945            let ed_ident = u32_to_ed(ident);
946            assert_eq!(ed_ident, id);
947            match mood {
948                // "X" means never connect.
949                '❌' | '🔥' => return Err(Error::UnusableTarget(bad_api_usage!("emoji"))),
950                // "zzz" means wait for 15 seconds then succeed.
951                '💤' => {
952                    self.runtime.sleep(Duration::new(15, 0)).await;
953                }
954                _ => {}
955            }
956            Ok(Arc::new(FakeChannel {
957                ed_ident,
958                mood,
959                closing: Arc::new(AtomicBool::new(false)),
960                detect_reuse: Default::default(),
961                // last_params: None,
962            }))
963        }
964
965        #[cfg(feature = "relay")]
966        async fn build_channel_using_incoming(
967            &self,
968            _peer: Sensitive<std::net::SocketAddr>,
969            _stream: Self::Stream,
970            _memquota: ChannelAccount,
971        ) -> Result<Arc<Self::Channel>> {
972            unimplemented!()
973        }
974    }
975
976    #[test]
977    fn connect_one_ok() {
978        test_with_one_runtime!(|runtime| async {
979            let mgr = new_test_abstract_chanmgr(runtime);
980            let target = FakeBuildSpec(413, '!', u32_to_ed(413), ADDR_A);
981            let chan1 = mgr
982                .get_or_launch(target.clone(), CU::UserTraffic)
983                .await
984                .unwrap()
985                .0;
986            let chan2 = mgr.get_or_launch(target, CU::UserTraffic).await.unwrap().0;
987
988            assert_eq!(chan1, chan2);
989            assert_eq!(mgr.get_nowait(&u32_to_ed(413)), vec![chan1]);
990        });
991    }
992
993    #[test]
994    fn connect_one_fail() {
995        test_with_one_runtime!(|runtime| async {
996            let mgr = new_test_abstract_chanmgr(runtime);
997
998            // This is set up to always fail.
999            let target = FakeBuildSpec(999, '❌', u32_to_ed(999), ADDR_A);
1000            let res1 = mgr.get_or_launch(target, CU::UserTraffic).await;
1001            assert!(matches!(res1, Err(Error::UnusableTarget(_))));
1002
1003            assert!(mgr.get_nowait(&u32_to_ed(999)).is_empty());
1004        });
1005    }
1006
1007    #[test]
1008    fn connect_different_address() {
1009        test_with_one_runtime!(|runtime| async {
1010            let mgr = new_test_abstract_chanmgr(runtime);
1011
1012            // Two targets that have different addresses.
1013            let target1 = FakeBuildSpec(413, '!', u32_to_ed(413), ADDR_A);
1014            let mut target2 = target1.clone();
1015            target2.3 = ADDR_B;
1016
1017            let chan1 = mgr.get_or_launch(target1, CU::UserTraffic).await.unwrap().0;
1018            let chan2 = mgr.get_or_launch(target2, CU::UserTraffic).await.unwrap().0;
1019
1020            // Even with different addresses, the original channel is returned.
1021            assert_eq!(chan1, chan2);
1022            assert_eq!(mgr.get_nowait(&u32_to_ed(413)), vec![chan1]);
1023        });
1024    }
1025
1026    #[test]
1027    fn test_concurrent() {
1028        test_with_one_runtime!(|runtime| async {
1029            let mgr = new_test_abstract_chanmgr(runtime);
1030
1031            let usage = CU::UserTraffic;
1032
1033            // TODO(nickm): figure out how to make these actually run
1034            // concurrently. Right now it seems that they don't actually
1035            // interact.
1036            let (ch3a, ch3b, ch44a, ch44b, ch50a, ch50b, ch86a, ch86b) = join!(
1037                mgr.get_or_launch(FakeBuildSpec(3, 'a', u32_to_ed(3), ADDR_A), usage),
1038                mgr.get_or_launch(FakeBuildSpec(3, 'b', u32_to_ed(3), ADDR_A), usage),
1039                mgr.get_or_launch(FakeBuildSpec(44, 'a', u32_to_ed(44), ADDR_A), usage),
1040                mgr.get_or_launch(FakeBuildSpec(44, 'b', u32_to_ed(44), ADDR_A), usage),
1041                mgr.get_or_launch(FakeBuildSpec(50, 'a', u32_to_ed(50), ADDR_A), usage),
1042                mgr.get_or_launch(FakeBuildSpec(50, 'b', u32_to_ed(50), ADDR_B), usage),
1043                mgr.get_or_launch(FakeBuildSpec(86, '❌', u32_to_ed(86), ADDR_A), usage),
1044                mgr.get_or_launch(FakeBuildSpec(86, '🔥', u32_to_ed(86), ADDR_A), usage),
1045            );
1046            let ch3a = ch3a.unwrap();
1047            let ch3b = ch3b.unwrap();
1048            let ch44a = ch44a.unwrap();
1049            let ch44b = ch44b.unwrap();
1050            let ch50a = ch50a.unwrap();
1051            let ch50b = ch50b.unwrap();
1052            let err_a = ch86a.unwrap_err();
1053            let err_b = ch86b.unwrap_err();
1054
1055            assert_eq!(ch3a, ch3b);
1056            assert_eq!(ch44a, ch44b);
1057            assert_eq!(ch50a, ch50b);
1058            assert_ne!(ch44a, ch3a);
1059
1060            assert!(matches!(err_a, Error::UnusableTarget(_)));
1061            assert!(matches!(err_b, Error::UnusableTarget(_)));
1062        });
1063    }
1064
1065    #[test]
1066    fn dropped_launch_reports_request_cancelled_to_waiters() {
1067        test_with_one_runtime!(|runtime| async {
1068            let mgr = new_test_abstract_chanmgr(runtime);
1069            let target = FakeBuildSpec(777, '💤', u32_to_ed(777), ADDR_A);
1070            let usage = CU::UserTraffic;
1071
1072            let mut owner1 = Box::pin(mgr.get_or_launch(target.clone(), usage));
1073            assert!(poll!(&mut owner1).is_pending());
1074
1075            let mut waiter = Box::pin(mgr.get_or_launch(target.clone(), usage));
1076            assert!(poll!(&mut waiter).is_pending());
1077
1078            drop(owner1);
1079
1080            let mut owner2 = Box::pin(mgr.get_or_launch(target, usage));
1081            assert!(poll!(&mut owner2).is_pending());
1082
1083            assert!(poll!(&mut waiter).is_pending());
1084
1085            drop(owner2);
1086
1087            let waiter = waiter.await;
1088            assert!(
1089                matches!(&waiter, Err(Error::RequestCancelled)),
1090                "{waiter:?}"
1091            );
1092            if let Err(ref err) = waiter {
1093                assert!(!error_contains(err, "channel build task disappeared"));
1094            }
1095        });
1096    }
1097
1098    #[test]
1099    fn failed_upgrade_reports_original_error_without_owner_retry() {
1100        test_with_one_runtime!(|runtime| async {
1101            let (mgr, build_attempts) = new_test_abstract_chanmgr_and_build_attempts(runtime);
1102            let target = FakeBuildSpec(778, 'r', u32_to_ed(778), ADDR_A);
1103            let usage = CU::UserTraffic;
1104
1105            let mut owner = Box::pin(mgr.get_or_launch(target.clone(), usage));
1106            assert!(poll!(&mut owner).is_pending());
1107
1108            let mut waiter = Box::pin(mgr.get_or_launch(target.clone(), usage));
1109            assert!(poll!(&mut waiter).is_pending());
1110
1111            let owner = owner.await;
1112            assert!(matches!(&owner, Err(Error::Internal(_))), "{owner:?}");
1113            if let Err(ref err) = owner {
1114                assert!(error_contains(err, "failure on new channel"));
1115                assert!(!error_contains(err, "channel build task disappeared"));
1116            }
1117
1118            assert_eq!(build_attempts.load(Ordering::SeqCst), 1);
1119            assert!(mgr.get_nowait(&u32_to_ed(778)).is_empty());
1120
1121            let waiter = waiter.await;
1122            assert!(matches!(&waiter, Err(Error::Internal(_))), "{waiter:?}");
1123            if let Err(ref err) = waiter {
1124                assert!(error_contains(err, "failure on new channel"));
1125                assert!(!error_contains(err, "channel build task disappeared"));
1126            }
1127        });
1128    }
1129
1130    #[test]
1131    fn unusable_entries() {
1132        test_with_one_runtime!(|runtime| async {
1133            let mgr = new_test_abstract_chanmgr(runtime);
1134
1135            let (ch3, ch4, ch5) = join!(
1136                mgr.get_or_launch(FakeBuildSpec(3, 'a', u32_to_ed(3), ADDR_A), CU::UserTraffic),
1137                mgr.get_or_launch(FakeBuildSpec(4, 'a', u32_to_ed(4), ADDR_A), CU::UserTraffic),
1138                mgr.get_or_launch(FakeBuildSpec(5, 'a', u32_to_ed(5), ADDR_A), CU::UserTraffic),
1139            );
1140
1141            let ch3 = ch3.unwrap().0;
1142            let _ch4 = ch4.unwrap();
1143            let ch5 = ch5.unwrap().0;
1144
1145            ch3.start_closing();
1146            ch5.start_closing();
1147
1148            let ch3_new = mgr
1149                .get_or_launch(FakeBuildSpec(3, 'b', u32_to_ed(3), ADDR_A), CU::UserTraffic)
1150                .await
1151                .unwrap()
1152                .0;
1153            assert_ne!(ch3, ch3_new);
1154            assert_eq!(ch3_new.mood, 'b');
1155
1156            mgr.remove_unusable_entries().unwrap();
1157
1158            assert!(!mgr.get_nowait(&u32_to_ed(3)).is_empty());
1159            assert!(!mgr.get_nowait(&u32_to_ed(4)).is_empty());
1160            assert!(mgr.get_nowait(&u32_to_ed(5)).is_empty());
1161        });
1162    }
1163}