Skip to main content

tor_proto/client/
circuit.rs

1//! Multi-hop paths over the Tor network.
2//!
3//! Right now, we only implement "client circuits" -- also sometimes
4//! called "origin circuits".  A client circuit is one that is
5//! constructed by this Tor instance, and used in its own behalf to
6//! send data over the Tor network.
7//!
8//! Each circuit has multiple hops over the Tor network: each hop
9//! knows only the hop before and the hop after.  The client shares a
10//! separate set of keys with each hop.
11//!
12//! To build a circuit, first create a [crate::channel::Channel], then
13//! call its [crate::channel::Channel::new_tunnel] method.  This yields
14//! a [PendingClientTunnel] object that won't become live until you call
15//! one of the methods
16//! (typically [`PendingClientTunnel::create_firsthop`])
17//! that extends it to its first hop.  After you've
18//! done that, you can call [`ClientCirc::extend`] on the tunnel to
19//! build it into a multi-hop tunnel.  Finally, you can use
20//! [ClientTunnel::begin_stream] to get a Stream object that can be used
21//! for anonymized data.
22//!
23//! # Implementation
24//!
25//! Each open circuit has a corresponding Reactor object that runs in
26//! an asynchronous task, and manages incoming cells from the
27//! circuit's upstream channel.  These cells are either RELAY cells or
28//! DESTROY cells.  DESTROY cells are handled immediately.
29//! RELAY cells are either for a particular stream, in which case they
30//! get forwarded to a StreamReceiver object, or for no particular stream,
31//! in which case they are considered "meta" cells (like EXTENDED2)
32//! that should only get accepted if something is waiting for them.
33//!
34//! # Limitations
35//!
36//! This is client-only.
37
38pub(crate) mod halfcirc;
39
40#[cfg(feature = "hs-common")]
41pub mod handshake;
42#[cfg(not(feature = "hs-common"))]
43pub(crate) mod handshake;
44
45pub(crate) mod padding;
46
47pub(super) mod path;
48
49use crate::channel::Channel;
50use crate::circuit::circhop::{HopNegotiationType, HopSettings};
51use crate::circuit::{CircuitRxReceiver, celltypes::*};
52#[cfg(feature = "circ-padding-manual")]
53use crate::client::CircuitPadder;
54use crate::client::circuit::padding::{PaddingController, PaddingEventStream};
55use crate::client::reactor::{CircuitHandshake, CtrlCmd, CtrlMsg, Reactor};
56use crate::crypto::cell::HopNum;
57use crate::crypto::handshake::ntor_v3::NtorV3PublicKey;
58use crate::memquota::CircuitAccount;
59use crate::util::skew::ClockSkew;
60use crate::{Error, Result};
61use derive_deftly::Deftly;
62use educe::Educe;
63use path::HopDetail;
64use tor_cell::chancell::{
65    CircId,
66    msg::{self as chanmsg},
67};
68use tor_error::{bad_api_usage, internal, into_internal};
69use tor_linkspec::{CircTarget, LinkSpecType, OwnedChanTarget, RelayIdType};
70use tor_protover::named;
71use tor_rtcompat::DynTimeProvider;
72use web_time_compat::Instant;
73
74use crate::circuit::UniqId;
75
76use super::{ClientTunnel, TargetHop};
77
78use futures::channel::mpsc;
79use oneshot_fused_workaround as oneshot;
80
81use futures::FutureExt as _;
82use std::collections::HashMap;
83use std::sync::{Arc, Mutex};
84use tor_memquota::derive_deftly_template_HasMemoryCost;
85
86use crate::crypto::handshake::ntor::NtorPublicKey;
87
88pub use crate::crypto::binding::CircuitBinding;
89pub use path::{Path, PathEntry};
90
91// TODO: export this from the top-level instead (it's not client-specific).
92pub use crate::circuit::CircParameters;
93
94// TODO(relay): reexport this from somewhere else (it's not client-specific)
95pub use crate::util::timeout::TimeoutEstimator;
96
97/// A subclass of ChanMsg that can correctly arrive on a live client
98/// circuit (one where a CREATED* has been received).
99#[derive(Debug, Deftly)]
100#[allow(unreachable_pub)] // Only `pub` with feature `testing`; otherwise, visible in crate
101#[derive_deftly(HasMemoryCost)]
102#[derive_deftly(RestrictedChanMsgSet)]
103#[deftly(usage = "on an open client circuit")]
104pub(super) enum ClientCircChanMsg {
105    /// A relay cell telling us some kind of remote command from some
106    /// party on the circuit.
107    Relay(chanmsg::Relay),
108    /// A cell telling us to destroy the circuit.
109    Destroy(chanmsg::Destroy),
110    // Note: RelayEarly is not valid for clients!
111}
112
113#[derive(Debug)]
114/// A circuit that we have constructed over the Tor network.
115///
116/// # Circuit life cycle
117///
118/// `ClientCirc`s are created in an initially unusable state using [`Channel::new_tunnel`],
119/// which returns a [`PendingClientTunnel`].  To get a real (one-hop) tunnel from
120/// one of these, you invoke one of its `create_firsthop` methods (typically
121/// [`create_firsthop_fast()`](PendingClientTunnel::create_firsthop_fast) or
122/// [`create_firsthop()`](PendingClientTunnel::create_firsthop)).
123/// Then, to add more hops to the circuit, you can call
124/// [`extend()`](ClientCirc::extend) on it.
125///
126/// For higher-level APIs, see the `tor-circmgr` crate: the ones here in
127/// `tor-proto` are probably not what you need.
128///
129/// After a circuit is created, it will persist until it is closed in one of
130/// five ways:
131///    1. A remote error occurs.
132///    2. Some hop on the circuit sends a `DESTROY` message to tear down the
133///       circuit.
134///    3. The circuit's channel is closed.
135///    4. Someone calls [`ClientTunnel::terminate`] on the tunnel owning the circuit.
136///    5. The last reference to the `ClientCirc` is dropped. (Note that every stream
137///       on a `ClientCirc` keeps a reference to it, which will in turn keep the
138///       circuit from closing until all those streams have gone away.)
139///
140/// Note that in cases 1-4 the [`ClientCirc`] object itself will still exist: it
141/// will just be unusable for most purposes.  Most operations on it will fail
142/// with an error.
143//
144// Effectively, this struct contains two Arcs: one for `path` and one for
145// `control` (which surely has something Arc-like in it).  We cannot unify
146// these by putting a single Arc around the whole struct, and passing
147// an Arc strong reference to the `Reactor`, because then `control` would
148// not be dropped when the last user of the circuit goes away.  We could
149// make the reactor have a weak reference but weak references are more
150// expensive to dereference.
151//
152// Because of the above, cloning this struct is always going to involve
153// two atomic refcount changes/checks.  Wrapping it in another Arc would
154// be overkill.
155//
156pub struct ClientCirc {
157    /// Mutable state shared with the `Reactor`.
158    pub(super) mutable: Arc<TunnelMutableState>,
159    /// A unique identifier for this circuit.
160    unique_id: UniqId,
161    /// Channel to send control messages to the reactor.
162    pub(super) control: mpsc::UnboundedSender<CtrlMsg>,
163    /// Channel to send commands to the reactor.
164    pub(super) command: mpsc::UnboundedSender<CtrlCmd>,
165    /// A future that resolves to Cancelled once the reactor is shut down,
166    /// meaning that the circuit is closed.
167    #[cfg_attr(not(feature = "experimental-api"), allow(dead_code))]
168    reactor_closed_rx: futures::future::Shared<oneshot::Receiver<void::Void>>,
169    /// For testing purposes: the CircId, for use in peek_circid().
170    #[cfg(test)]
171    circid: CircId,
172    /// Memory quota account
173    pub(super) memquota: CircuitAccount,
174    /// Time provider
175    pub(super) time_provider: DynTimeProvider,
176    /// Indicate if this reactor is a multi path or not. This is flagged at the very first
177    /// LinkCircuit seen and never changed after.
178    ///
179    /// We can't just look at the number of legs because a multi path tunnel could have 1 leg only
180    /// because the other(s) have collapsed.
181    ///
182    /// This is very important because it allows to make a quick efficient safety check by the
183    /// circmgr higher level tunnel type without locking the mutable state or using the command
184    /// channel.
185    pub(super) is_multi_path: bool,
186}
187
188/// The mutable state of a tunnel, shared between [`ClientCirc`] and [`Reactor`].
189///
190/// NOTE(gabi): this mutex-inside-a-mutex might look suspicious,
191/// but it is currently the best option we have for sharing
192/// the circuit state with `ClientCirc` (and soon, with `ClientTunnel`).
193/// In practice, these mutexes won't be accessed very often
194/// (they're accessed for writing when a circuit is extended,
195/// and for reading by the various `ClientCirc` APIs),
196/// so they shouldn't really impact performance.
197///
198/// Alternatively, the circuit state information could be shared
199/// outside the reactor through a channel (passed to the reactor via a `CtrlCmd`),
200/// but in #1840 @opara notes that involves making the `ClientCirc` accessors
201/// (`ClientCirc::path`, `ClientCirc::binding_key`, etc.)
202/// asynchronous, which will significantly complicate their callsites,
203/// which would in turn need to be made async too.
204///
205/// We should revisit this decision at some point, and decide whether an async API
206/// would be preferable.
207#[derive(Debug, Default)]
208pub(super) struct TunnelMutableState(Mutex<HashMap<UniqId, Arc<MutableState>>>);
209
210impl TunnelMutableState {
211    /// Add the [`MutableState`] of a circuit.
212    pub(super) fn insert(&self, unique_id: UniqId, mutable: Arc<MutableState>) {
213        #[allow(unused)] // unused in non-debug builds
214        let state = self
215            .0
216            .lock()
217            .expect("lock poisoned")
218            .insert(unique_id, mutable);
219
220        debug_assert!(state.is_none());
221    }
222
223    /// Remove the [`MutableState`] of a circuit.
224    pub(super) fn remove(&self, unique_id: UniqId) {
225        #[allow(unused)] // unused in non-debug builds
226        let state = self.0.lock().expect("lock poisoned").remove(&unique_id);
227
228        debug_assert!(state.is_some());
229    }
230
231    /// Return a [`Path`] object describing all the circuits in this tunnel.
232    fn all_paths(&self) -> Vec<Arc<Path>> {
233        let lock = self.0.lock().expect("lock poisoned");
234        lock.values().map(|mutable| mutable.path()).collect()
235    }
236
237    /// Return a representation of the Paths for all the circuits in this tunnel,
238    /// as a map from each circuits' UniqId to its path.
239    ///
240    /// This is only exposed for the RPC subsystem, where it is documented that the
241    /// format of `UniqId` is not stable.
242    #[cfg(feature = "rpc")]
243    pub(super) fn tagged_paths(&self) -> HashMap<UniqId, Arc<Path>> {
244        let lock = self.0.lock().expect("lock poisoned");
245        lock.iter()
246            .map(|(id, mutable)| (*id, mutable.path()))
247            .collect()
248    }
249
250    /// Return a list of [`Path`] objects describing the only circuit in this tunnel.
251    ///
252    /// Returns an error if the tunnel has more than one tunnel.
253    //
254    // TODO: replace Itertools::exactly_one() with a stdlib equivalent when there is one.
255    //
256    // See issue #48919 <https://github.com/rust-lang/rust/issues/48919>
257    #[allow(unstable_name_collisions)]
258    fn single_path(&self) -> Result<Arc<Path>> {
259        use itertools::Itertools as _;
260
261        self.all_paths().into_iter().exactly_one().map_err(|_| {
262            bad_api_usage!("requested the single path of a multi-path tunnel?!").into()
263        })
264    }
265
266    /// Return a description of the first hop of this circuit.
267    ///
268    /// Returns an error if a circuit with the specified [`UniqId`] doesn't exist.
269    /// Returns `Ok(None)` if the specified circuit doesn't have any hops.
270    fn first_hop(&self, unique_id: UniqId) -> Result<Option<OwnedChanTarget>> {
271        let lock = self.0.lock().expect("lock poisoned");
272        let mutable = lock
273            .get(&unique_id)
274            .ok_or_else(|| bad_api_usage!("no circuit with unique ID {unique_id}"))?;
275
276        let first_hop = mutable.first_hop().map(|first_hop| match first_hop {
277            path::HopDetail::Relay(r) => r,
278            #[cfg(feature = "hs-common")]
279            path::HopDetail::Virtual => {
280                panic!("somehow made a circuit with a virtual first hop.")
281            }
282        });
283
284        Ok(first_hop)
285    }
286
287    /// Return the [`HopNum`] of the last hop of the specified circuit.
288    ///
289    /// Returns an error if a circuit with the specified [`UniqId`] doesn't exist.
290    ///
291    /// See [`MutableState::last_hop_num`].
292    pub(super) fn last_hop_num(&self, unique_id: UniqId) -> Result<Option<HopNum>> {
293        let lock = self.0.lock().expect("lock poisoned");
294        let mutable = lock
295            .get(&unique_id)
296            .ok_or_else(|| bad_api_usage!("no circuit with unique ID {unique_id}"))?;
297
298        Ok(mutable.last_hop_num())
299    }
300
301    /// Return the number of hops in the specified circuit.
302    ///
303    /// See [`MutableState::n_hops`].
304    fn n_hops(&self, unique_id: UniqId) -> Result<usize> {
305        let lock = self.0.lock().expect("lock poisoned");
306        let mutable = lock
307            .get(&unique_id)
308            .ok_or_else(|| bad_api_usage!("no circuit with unique ID {unique_id}"))?;
309
310        Ok(mutable.n_hops())
311    }
312}
313
314/// The mutable state of a circuit.
315#[derive(Educe, Default)]
316#[educe(Debug)]
317pub(super) struct MutableState(Mutex<CircuitState>);
318
319impl MutableState {
320    /// Add a hop to the path of this circuit.
321    pub(super) fn add_hop(&self, peer_id: HopDetail, binding: Option<CircuitBinding>) {
322        let mut mutable = self.0.lock().expect("poisoned lock");
323        Arc::make_mut(&mut mutable.path).push_hop(peer_id);
324        mutable.binding.push(binding);
325    }
326
327    /// Get a copy of the circuit's current [`path::Path`].
328    pub(super) fn path(&self) -> Arc<path::Path> {
329        let mutable = self.0.lock().expect("poisoned lock");
330        Arc::clone(&mutable.path)
331    }
332
333    /// Return the cryptographic material used to prove knowledge of a shared
334    /// secret with with `hop`.
335    pub(super) fn binding_key(&self, hop: HopNum) -> Option<CircuitBinding> {
336        let mutable = self.0.lock().expect("poisoned lock");
337
338        mutable.binding.get::<usize>(hop.into()).cloned().flatten()
339        // NOTE: I'm not thrilled to have to copy this information, but we use
340        // it very rarely, so it's not _that_ bad IMO.
341    }
342
343    /// Return a description of the first hop of this circuit.
344    fn first_hop(&self) -> Option<HopDetail> {
345        let mutable = self.0.lock().expect("poisoned lock");
346        mutable.path.first_hop()
347    }
348
349    /// Return the [`HopNum`] of the last hop of this circuit.
350    ///
351    /// NOTE: This function will return the [`HopNum`] of the hop
352    /// that is _currently_ the last. If there is an extend operation in progress,
353    /// the currently pending hop may or may not be counted, depending on whether
354    /// the extend operation finishes before this call is done.
355    fn last_hop_num(&self) -> Option<HopNum> {
356        let mutable = self.0.lock().expect("poisoned lock");
357        mutable.path.last_hop_num()
358    }
359
360    /// Return the number of hops in this circuit.
361    ///
362    /// NOTE: This function will currently return only the number of hops
363    /// _currently_ in the circuit. If there is an extend operation in progress,
364    /// the currently pending hop may or may not be counted, depending on whether
365    /// the extend operation finishes before this call is done.
366    fn n_hops(&self) -> usize {
367        let mutable = self.0.lock().expect("poisoned lock");
368        mutable.path.n_hops()
369    }
370}
371
372/// The shared state of a circuit.
373#[derive(Educe, Default)]
374#[educe(Debug)]
375pub(super) struct CircuitState {
376    /// Information about this circuit's path.
377    ///
378    /// This is stored in an Arc so that we can cheaply give a copy of it to
379    /// client code; when we need to add a hop (which is less frequent) we use
380    /// [`Arc::make_mut()`].
381    path: Arc<path::Path>,
382
383    /// Circuit binding keys [q.v.][`CircuitBinding`] information for each hop
384    /// in the circuit's path.
385    ///
386    /// NOTE: Right now, there is a `CircuitBinding` for every hop.  There's a
387    /// fair chance that this will change in the future, and I don't want other
388    /// code to assume that a `CircuitBinding` _must_ exist, so I'm making this
389    /// an `Option`.
390    #[educe(Debug(ignore))]
391    binding: Vec<Option<CircuitBinding>>,
392}
393
394/// A ClientCirc that needs to send a create cell and receive a created* cell.
395///
396/// To use one of these, call `create_firsthop_fast()` or `create_firsthop()`
397/// to negotiate the cryptographic handshake with the first hop.
398pub struct PendingClientTunnel {
399    /// A oneshot receiver on which we'll receive a CREATED* cell,
400    /// or a DESTROY cell.
401    recvcreated: oneshot::Receiver<CreateResponse>,
402    /// The ClientCirc object that we can expose on success.
403    circ: ClientCirc,
404}
405
406impl ClientCirc {
407    /// Convert this `ClientCirc` into a single circuit [`ClientTunnel`].
408    pub fn into_tunnel(self) -> Result<ClientTunnel> {
409        self.try_into()
410    }
411
412    /// Return a description of the first hop of this circuit.
413    ///
414    /// # Panics
415    ///
416    /// Panics if there is no first hop.  (This should be impossible outside of
417    /// the tor-proto crate, but within the crate it's possible to have a
418    /// circuit with no hops.)
419    pub fn first_hop(&self) -> Result<OwnedChanTarget> {
420        Ok(self
421            .mutable
422            .first_hop(self.unique_id)
423            .map_err(|_| Error::CircuitClosed)?
424            .expect("called first_hop on an un-constructed circuit"))
425    }
426
427    /// Return a description of the last hop of the tunnel.
428    ///
429    /// Return None if the last hop is virtual.
430    ///
431    /// # Panics
432    ///
433    /// Panics if there is no last hop.  (This should be impossible outside of
434    /// the tor-proto crate, but within the crate it's possible to have a
435    /// circuit with no hops.)
436    pub fn last_hop_info(&self) -> Result<Option<OwnedChanTarget>> {
437        let all_paths = self.all_paths();
438        let path = all_paths.first().ok_or_else(|| {
439            tor_error::bad_api_usage!("Called last_hop_info on an un-constructed tunnel")
440        })?;
441        Ok(path
442            .hops()
443            .last()
444            .expect("Called last_hop on an un-constructed circuit")
445            .as_chan_target()
446            .map(OwnedChanTarget::from_chan_target))
447    }
448
449    /// Return the [`HopNum`] of the last hop of this circuit.
450    ///
451    /// Returns an error if there is no last hop.  (This should be impossible outside of the
452    /// tor-proto crate, but within the crate it's possible to have a circuit with no hops.)
453    ///
454    /// NOTE: This function will return the [`HopNum`] of the hop
455    /// that is _currently_ the last. If there is an extend operation in progress,
456    /// the currently pending hop may or may not be counted, depending on whether
457    /// the extend operation finishes before this call is done.
458    pub fn last_hop_num(&self) -> Result<HopNum> {
459        Ok(self
460            .mutable
461            .last_hop_num(self.unique_id)?
462            .ok_or_else(|| internal!("no last hop index"))?)
463    }
464
465    /// Return a [`TargetHop`] representing precisely the last hop of the circuit as in set as a
466    /// HopLocation with its id and hop number.
467    ///
468    /// Return an error if there is no last hop.
469    pub fn last_hop(&self) -> Result<TargetHop> {
470        let hop_num = self
471            .mutable
472            .last_hop_num(self.unique_id)?
473            .ok_or_else(|| bad_api_usage!("no last hop"))?;
474        Ok((self.unique_id, hop_num).into())
475    }
476
477    /// Return a list of [`Path`] objects describing all the circuits in this tunnel.
478    ///
479    /// Note that these `Path`s are not automatically updated if the underlying
480    /// circuits are extended.
481    pub fn all_paths(&self) -> Vec<Arc<Path>> {
482        self.mutable.all_paths()
483    }
484
485    /// Return a list of [`Path`] objects describing the only circuit in this tunnel.
486    ///
487    /// Returns an error if the tunnel has more than one tunnel.
488    pub fn single_path(&self) -> Result<Arc<Path>> {
489        self.mutable.single_path()
490    }
491
492    /// Return the time at which this circuit last had any open streams.
493    ///
494    /// Returns `None` if this circuit has never had any open streams,
495    /// or if it currently has open streams.
496    ///
497    /// NOTE that the Instant returned by this method is not affected by
498    /// any runtime mocking; it is the output of an ordinary call to
499    /// `Instant::get()`.
500    pub async fn disused_since(&self) -> Result<Option<Instant>> {
501        let (tx, rx) = oneshot::channel();
502        self.command
503            .unbounded_send(CtrlCmd::GetTunnelActivity { sender: tx })
504            .map_err(|_| Error::CircuitClosed)?;
505
506        Ok(rx.await.map_err(|_| Error::CircuitClosed)?.disused_since())
507    }
508
509    /// Get the clock skew claimed by the first hop of the circuit.
510    ///
511    /// See [`Channel::clock_skew()`].
512    pub async fn first_hop_clock_skew(&self) -> Result<ClockSkew> {
513        let (tx, rx) = oneshot::channel();
514
515        self.control
516            .unbounded_send(CtrlMsg::FirstHopClockSkew { answer: tx })
517            .map_err(|_| Error::CircuitClosed)?;
518
519        Ok(rx.await.map_err(|_| Error::CircuitClosed)??)
520    }
521
522    /// Return a reference to this circuit's memory quota account
523    pub fn mq_account(&self) -> &CircuitAccount {
524        &self.memquota
525    }
526
527    /// Return the cryptographic material used to prove knowledge of a shared
528    /// secret with with `hop`.
529    ///
530    /// See [`CircuitBinding`] for more information on how this is used.
531    ///
532    /// Return None if we have no circuit binding information for the hop, or if
533    /// the hop does not exist.
534    #[cfg(feature = "hs-service")]
535    pub async fn binding_key(&self, hop: TargetHop) -> Result<Option<CircuitBinding>> {
536        let (sender, receiver) = oneshot::channel();
537        let msg = CtrlCmd::GetBindingKey { hop, done: sender };
538        self.command
539            .unbounded_send(msg)
540            .map_err(|_| Error::CircuitClosed)?;
541
542        receiver.await.map_err(|_| Error::CircuitClosed)?
543    }
544
545    /// Extend the circuit, via the most appropriate circuit extension handshake,
546    /// to the chosen `target` hop.
547    pub async fn extend<Tg>(&self, target: &Tg, params: CircParameters) -> Result<()>
548    where
549        Tg: CircTarget,
550    {
551        #![allow(deprecated)]
552
553        // For now we use the simplest decision-making mechanism:
554        // we use ntor_v3 whenever it is present; and otherwise we use ntor.
555        //
556        // This behavior is slightly different from C tor, which uses ntor v3
557        // only whenever it want to send any extension in the circuit message.
558        // But thanks to congestion control (named::FLOWCTRL_CC), we'll _always_
559        // want to use an extension if we can, and so it doesn't make too much
560        // sense to detect the case where we have no extensions.
561        //
562        // (As of April 2025, RELAY_NTORV3 is not yet listed as Required for relays
563        // on the tor network, and so we cannot simply assume that everybody has it.)
564        if target
565            .protovers()
566            .supports_named_subver(named::RELAY_NTORV3)
567        {
568            self.extend_ntor_v3(target, params).await
569        } else {
570            self.extend_ntor(target, params).await
571        }
572    }
573
574    /// Extend the circuit via the ntor handshake to a new target last
575    /// hop.
576    #[deprecated(since = "1.6.1", note = "Use extend instead.")]
577    pub async fn extend_ntor<Tg>(&self, target: &Tg, params: CircParameters) -> Result<()>
578    where
579        Tg: CircTarget,
580    {
581        let key = NtorPublicKey {
582            id: *target
583                .rsa_identity()
584                .ok_or(Error::MissingId(RelayIdType::Rsa))?,
585            pk: *target.ntor_onion_key(),
586        };
587        let mut linkspecs = target
588            .linkspecs()
589            .map_err(into_internal!("Could not encode linkspecs for extend_ntor"))?;
590        if !params.extend_by_ed25519_id {
591            linkspecs.retain(|ls| ls.lstype() != LinkSpecType::ED25519ID);
592        }
593
594        let (tx, rx) = oneshot::channel();
595
596        let peer_id = OwnedChanTarget::from_chan_target(target);
597        let settings = HopSettings::from_params_and_caps(
598            HopNegotiationType::None,
599            &params,
600            target.protovers(),
601        )?;
602        self.control
603            .unbounded_send(CtrlMsg::ExtendNtor {
604                peer_id,
605                public_key: key,
606                linkspecs,
607                settings,
608                done: tx,
609            })
610            .map_err(|_| Error::CircuitClosed)?;
611
612        rx.await.map_err(|_| Error::CircuitClosed)??;
613
614        Ok(())
615    }
616
617    /// Extend the circuit via the ntor handshake to a new target last
618    /// hop.
619    #[deprecated(since = "1.6.1", note = "Use extend instead.")]
620    pub async fn extend_ntor_v3<Tg>(&self, target: &Tg, params: CircParameters) -> Result<()>
621    where
622        Tg: CircTarget,
623    {
624        let key = NtorV3PublicKey {
625            id: *target
626                .ed_identity()
627                .ok_or(Error::MissingId(RelayIdType::Ed25519))?,
628            pk: *target.ntor_onion_key(),
629        };
630        let mut linkspecs = target
631            .linkspecs()
632            .map_err(into_internal!("Could not encode linkspecs for extend_ntor"))?;
633        if !params.extend_by_ed25519_id {
634            linkspecs.retain(|ls| ls.lstype() != LinkSpecType::ED25519ID);
635        }
636
637        let (tx, rx) = oneshot::channel();
638
639        let peer_id = OwnedChanTarget::from_chan_target(target);
640        let settings = HopSettings::from_params_and_caps(
641            HopNegotiationType::Full,
642            &params,
643            target.protovers(),
644        )?;
645        self.control
646            .unbounded_send(CtrlMsg::ExtendNtorV3 {
647                peer_id,
648                public_key: key,
649                linkspecs,
650                settings,
651                done: tx,
652            })
653            .map_err(|_| Error::CircuitClosed)?;
654
655        rx.await.map_err(|_| Error::CircuitClosed)??;
656
657        Ok(())
658    }
659
660    /// Extend this circuit by a single, "virtual" hop.
661    ///
662    /// A virtual hop is one for which we do not add an actual network connection
663    /// between separate hosts (such as Relays).  We only add a layer of
664    /// cryptography.
665    ///
666    /// This is used to implement onion services: the client and the service
667    /// both build a circuit to a single rendezvous point, and tell the
668    /// rendezvous point to relay traffic between their two circuits.  Having
669    /// completed a [`handshake`] out of band[^1], the parties each extend their
670    /// circuits by a single "virtual" encryption hop that represents their
671    /// shared cryptographic context.
672    ///
673    /// Protocol settings, capabilities, and parameters
674    /// are based on the `params` and `capabilities` arguments.
675    /// The `capabilities` argument should contains a set of capabilities that both
676    /// parties have agreed to use.  Only explicitly negotiable capabilities[^2] need
677    /// to be listed.
678    ///
679    /// Once a circuit has been extended in this way, it is an error to try to
680    /// extend it in any other way.
681    ///
682    /// [^1]: Technically, the handshake is only _mostly_ out of band: the
683    ///     client sends their half of the handshake in an ` message, and the
684    ///     service's response is inline in its `RENDEZVOUS2` message.
685    /// [^2]: That is to say, if a capability is always-on, then there is no need to list
686    ///     it.
687    //
688    // TODO hs: let's try to enforce the "you can't extend a circuit again once
689    // it has been extended this way" property.  We could do that with internal
690    // state, or some kind of a type state pattern.
691    #[cfg(feature = "hs-common")]
692    pub async fn extend_virtual(
693        &self,
694        protocol: handshake::RelayProtocol,
695        role: handshake::HandshakeRole,
696        seed: impl handshake::KeyGenerator,
697        params: &CircParameters,
698        capabilities: &tor_protover::Protocols,
699    ) -> Result<()> {
700        use self::handshake::BoxedClientLayer;
701
702        // TODO CGO: Possibly refactor this match into a separate method when we revisit this.
703        let negotiation_type = match protocol {
704            handshake::RelayProtocol::HsV3 => HopNegotiationType::HsV3,
705        };
706        let protocol = handshake::RelayCryptLayerProtocol::from(protocol);
707
708        let BoxedClientLayer { fwd, back, binding } =
709            protocol.construct_client_layers(role, seed)?;
710
711        let settings = HopSettings::from_params_and_caps(negotiation_type, params, capabilities)?;
712        let (tx, rx) = oneshot::channel();
713        let message = CtrlCmd::ExtendVirtual {
714            cell_crypto: (fwd, back, binding),
715            settings,
716            done: tx,
717        };
718
719        self.command
720            .unbounded_send(message)
721            .map_err(|_| Error::CircuitClosed)?;
722
723        rx.await.map_err(|_| Error::CircuitClosed)?
724    }
725
726    /// Install a [`CircuitPadder`] at the listed `hop`.
727    ///
728    /// Replaces any previous padder installed at that hop.
729    #[cfg(feature = "circ-padding-manual")]
730    pub async fn start_padding_at_hop(&self, hop: HopNum, padder: CircuitPadder) -> Result<()> {
731        self.set_padder_impl(crate::HopLocation::Hop((self.unique_id, hop)), Some(padder))
732            .await
733    }
734
735    /// Remove any [`CircuitPadder`] at the listed `hop`.
736    ///
737    /// Does nothing if there was not a padder installed there.
738    #[cfg(feature = "circ-padding-manual")]
739    pub async fn stop_padding_at_hop(&self, hop: HopNum) -> Result<()> {
740        self.set_padder_impl(crate::HopLocation::Hop((self.unique_id, hop)), None)
741            .await
742    }
743
744    /// Helper: replace the padder at `hop` with the provided `padder`, or with `None`.
745    #[cfg(feature = "circ-padding-manual")]
746    pub(super) async fn set_padder_impl(
747        &self,
748        hop: crate::HopLocation,
749        padder: Option<CircuitPadder>,
750    ) -> Result<()> {
751        let (tx, rx) = oneshot::channel();
752        let msg = CtrlCmd::SetPadder {
753            hop,
754            padder,
755            sender: tx,
756        };
757        self.command
758            .unbounded_send(msg)
759            .map_err(|_| Error::CircuitClosed)?;
760        rx.await.map_err(|_| Error::CircuitClosed)?
761    }
762
763    /// Return true if this circuit is closed and therefore unusable.
764    pub fn is_closing(&self) -> bool {
765        self.control.is_closed()
766    }
767
768    /// Return a process-unique identifier for this circuit.
769    pub fn unique_id(&self) -> UniqId {
770        self.unique_id
771    }
772
773    /// Return the number of hops in this circuit.
774    ///
775    /// NOTE: This function will currently return only the number of hops
776    /// _currently_ in the circuit. If there is an extend operation in progress,
777    /// the currently pending hop may or may not be counted, depending on whether
778    /// the extend operation finishes before this call is done.
779    pub fn n_hops(&self) -> Result<usize> {
780        self.mutable
781            .n_hops(self.unique_id)
782            .map_err(|_| Error::CircuitClosed)
783    }
784
785    /// Return a future that will resolve once this circuit has closed.
786    ///
787    /// Note that this method does not itself cause the circuit to shut down.
788    ///
789    /// TODO: Perhaps this should return some kind of status indication instead
790    /// of just ()
791    pub fn wait_for_close(
792        &self,
793    ) -> impl futures::Future<Output = ()> + Send + Sync + 'static + use<> {
794        self.reactor_closed_rx.clone().map(|_| ())
795    }
796}
797
798impl PendingClientTunnel {
799    /// Instantiate a new circuit object: used from Channel::new_tunnel().
800    ///
801    /// Does not send a CREATE* cell on its own.
802    #[allow(clippy::too_many_arguments)]
803    pub(crate) fn new(
804        circ_id: CircId,
805        channel: Arc<Channel>,
806        createdreceiver: oneshot::Receiver<CreateResponse>,
807        input: CircuitRxReceiver,
808        unique_id: UniqId,
809        runtime: DynTimeProvider,
810        memquota: CircuitAccount,
811        padding_ctrl: PaddingController,
812        padding_stream: PaddingEventStream,
813        timeouts: Arc<dyn TimeoutEstimator>,
814    ) -> (PendingClientTunnel, crate::client::reactor::Reactor) {
815        let time_provider = channel.time_provider().clone();
816        let (reactor, control_tx, command_tx, reactor_closed_rx, mutable) = Reactor::new(
817            channel,
818            circ_id,
819            unique_id,
820            input,
821            runtime,
822            memquota.clone(),
823            padding_ctrl,
824            padding_stream,
825            timeouts,
826        );
827
828        let circuit = ClientCirc {
829            mutable,
830            unique_id,
831            control: control_tx,
832            command: command_tx,
833            reactor_closed_rx: reactor_closed_rx.shared(),
834            #[cfg(test)]
835            circid: circ_id,
836            memquota,
837            time_provider,
838            is_multi_path: false,
839        };
840
841        let pending = PendingClientTunnel {
842            recvcreated: createdreceiver,
843            circ: circuit,
844        };
845        (pending, reactor)
846    }
847
848    /// Extract the process-unique identifier for this pending circuit.
849    pub fn peek_unique_id(&self) -> UniqId {
850        self.circ.unique_id
851    }
852
853    /// Use the (questionable!) CREATE_FAST handshake to connect to the
854    /// first hop of this circuit.
855    ///
856    /// There's no authentication in CRATE_FAST,
857    /// so we don't need to know whom we're connecting to: we're just
858    /// connecting to whichever relay the channel is for.
859    pub async fn create_firsthop_fast(self, params: CircParameters) -> Result<ClientTunnel> {
860        // We know nothing about this relay, so we assume it supports no protocol capabilities at all.
861        //
862        // TODO: If we had a consensus, we could assume it supported all required-relay-protocols.
863        // TODO prop364: When we implement CreateOneHop, we will want a Protocols argument here.
864        let protocols = tor_protover::Protocols::new();
865        let settings =
866            HopSettings::from_params_and_caps(HopNegotiationType::None, &params, &protocols)?;
867        let (tx, rx) = oneshot::channel();
868        self.circ
869            .control
870            .unbounded_send(CtrlMsg::Create {
871                recv_created: self.recvcreated,
872                handshake: CircuitHandshake::CreateFast,
873                settings,
874                done: tx,
875            })
876            .map_err(|_| Error::CircuitClosed)?;
877
878        rx.await.map_err(|_| Error::CircuitClosed)??;
879
880        self.circ.into_tunnel()
881    }
882
883    /// Use the most appropriate handshake to connect to the first hop of this circuit.
884    ///
885    /// Note that the provided 'target' must match the channel's target,
886    /// or the handshake will fail.
887    pub async fn create_firsthop<Tg>(
888        self,
889        target: &Tg,
890        params: CircParameters,
891    ) -> Result<ClientTunnel>
892    where
893        Tg: tor_linkspec::CircTarget,
894    {
895        #![allow(deprecated)]
896        // (See note in ClientCirc::extend.)
897        if target
898            .protovers()
899            .supports_named_subver(named::RELAY_NTORV3)
900        {
901            self.create_firsthop_ntor_v3(target, params).await
902        } else {
903            self.create_firsthop_ntor(target, params).await
904        }
905    }
906
907    /// Use the ntor handshake to connect to the first hop of this circuit.
908    ///
909    /// Note that the provided 'target' must match the channel's target,
910    /// or the handshake will fail.
911    #[deprecated(since = "1.6.1", note = "Use create_firsthop instead.")]
912    pub async fn create_firsthop_ntor<Tg>(
913        self,
914        target: &Tg,
915        params: CircParameters,
916    ) -> Result<ClientTunnel>
917    where
918        Tg: tor_linkspec::CircTarget,
919    {
920        let (tx, rx) = oneshot::channel();
921        let settings = HopSettings::from_params_and_caps(
922            HopNegotiationType::None,
923            &params,
924            target.protovers(),
925        )?;
926
927        self.circ
928            .control
929            .unbounded_send(CtrlMsg::Create {
930                recv_created: self.recvcreated,
931                handshake: CircuitHandshake::Ntor {
932                    public_key: NtorPublicKey {
933                        id: *target
934                            .rsa_identity()
935                            .ok_or(Error::MissingId(RelayIdType::Rsa))?,
936                        pk: *target.ntor_onion_key(),
937                    },
938                    ed_identity: *target
939                        .ed_identity()
940                        .ok_or(Error::MissingId(RelayIdType::Ed25519))?,
941                },
942                settings,
943                done: tx,
944            })
945            .map_err(|_| Error::CircuitClosed)?;
946
947        rx.await.map_err(|_| Error::CircuitClosed)??;
948
949        self.circ.into_tunnel()
950    }
951
952    /// Use the ntor_v3 handshake to connect to the first hop of this circuit.
953    ///
954    /// Assumes that the target supports ntor_v3. The caller should verify
955    /// this before calling this function, e.g. by validating that the target
956    /// has advertised ["Relay=4"](https://spec.torproject.org/tor-spec/subprotocol-versioning.html#relay).
957    ///
958    /// Note that the provided 'target' must match the channel's target,
959    /// or the handshake will fail.
960    #[deprecated(since = "1.6.1", note = "Use create_firsthop instead.")]
961    pub async fn create_firsthop_ntor_v3<Tg>(
962        self,
963        target: &Tg,
964        params: CircParameters,
965    ) -> Result<ClientTunnel>
966    where
967        Tg: tor_linkspec::CircTarget,
968    {
969        let settings = HopSettings::from_params_and_caps(
970            HopNegotiationType::Full,
971            &params,
972            target.protovers(),
973        )?;
974        let (tx, rx) = oneshot::channel();
975
976        self.circ
977            .control
978            .unbounded_send(CtrlMsg::Create {
979                recv_created: self.recvcreated,
980                handshake: CircuitHandshake::NtorV3 {
981                    public_key: NtorV3PublicKey {
982                        id: *target
983                            .ed_identity()
984                            .ok_or(Error::MissingId(RelayIdType::Ed25519))?,
985                        pk: *target.ntor_onion_key(),
986                    },
987                },
988                settings,
989                done: tx,
990            })
991            .map_err(|_| Error::CircuitClosed)?;
992
993        rx.await.map_err(|_| Error::CircuitClosed)??;
994
995        self.circ.into_tunnel()
996    }
997}
998
999#[cfg(test)]
1000pub(crate) mod test {
1001    // @@ begin test lint list maintained by maint/add_warning @@
1002    #![allow(clippy::bool_assert_comparison)]
1003    #![allow(clippy::clone_on_copy)]
1004    #![allow(clippy::dbg_macro)]
1005    #![allow(clippy::mixed_attributes_style)]
1006    #![allow(clippy::print_stderr)]
1007    #![allow(clippy::print_stdout)]
1008    #![allow(clippy::single_char_pattern)]
1009    #![allow(clippy::unwrap_used)]
1010    #![allow(clippy::unchecked_time_subtraction)]
1011    #![allow(clippy::useless_vec)]
1012    #![allow(clippy::needless_pass_by_value)]
1013    #![allow(clippy::string_slice)] // See arti#2571
1014    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
1015
1016    use super::*;
1017    use crate::channel::test::{CodecResult, new_reactor};
1018    use crate::circuit::CircuitRxSender;
1019    use crate::circuit::reactor::test::rmsg_to_ccmsg;
1020    use crate::circuit::test::fake_mpsc;
1021    use crate::client::circuit::padding::new_padding;
1022    use crate::client::stream::DataStream;
1023    use crate::congestion::params::CongestionControlParams;
1024    use crate::congestion::test_utils::params::build_cc_vegas_params;
1025    use crate::crypto::cell::RelayCellBody;
1026    use crate::crypto::handshake::ntor_v3::NtorV3Server;
1027    use crate::memquota::SpecificAccount as _;
1028    use crate::stream::flow_ctrl::params::FlowCtrlParameters;
1029    use crate::util::DummyTimeoutEstimator;
1030    use assert_matches::assert_matches;
1031    use chanmsg::{AnyChanMsg, Created2, CreatedFast};
1032    use futures::channel::mpsc::{Receiver, Sender};
1033    use futures::io::{AsyncReadExt, AsyncWriteExt};
1034    use futures::sink::SinkExt;
1035    use futures::stream::StreamExt;
1036    use hex_literal::hex;
1037    use std::collections::{HashMap, VecDeque};
1038    use std::fmt::Debug;
1039    use std::time::Duration;
1040    use tor_basic_utils::test_rng::testing_rng;
1041    use tor_cell::chancell::{AnyChanCell, BoxedCellBody, ChanCell, ChanCmd, msg as chanmsg};
1042    use tor_cell::relaycell::extend::{self as extend_ext, CircRequestExt, CircResponseExt};
1043    use tor_cell::relaycell::msg::SendmeTag;
1044    use tor_cell::relaycell::{
1045        AnyRelayMsgOuter, RelayCellFormat, RelayCmd, StreamId, msg as relaymsg, msg::AnyRelayMsg,
1046    };
1047    use tor_cell::relaycell::{RelayMsg, UnparsedRelayMsg};
1048    use tor_linkspec::OwnedCircTarget;
1049    use tor_rtcompat::Runtime;
1050    use tor_rtcompat::SpawnExt;
1051    use tracing::trace;
1052    use tracing_test::traced_test;
1053
1054    #[cfg(feature = "conflux")]
1055    use {
1056        crate::client::reactor::ConfluxHandshakeResult,
1057        crate::util::err::ConfluxHandshakeError,
1058        futures::future::FusedFuture,
1059        futures::lock::Mutex as AsyncMutex,
1060        std::pin::Pin,
1061        std::result::Result as StdResult,
1062        tor_cell::relaycell::conflux::{V1DesiredUx, V1LinkPayload, V1Nonce},
1063        tor_cell::relaycell::msg::ConfluxLink,
1064        tor_rtmock::MockRuntime,
1065    };
1066
1067    #[cfg(feature = "hs-service")]
1068    use crate::circuit::reactor::test::AllowAllStreamsFilter;
1069
1070    impl PendingClientTunnel {
1071        /// Testing only: Extract the circuit ID for this pending circuit.
1072        pub(crate) fn peek_circid(&self) -> CircId {
1073            self.circ.circid
1074        }
1075    }
1076
1077    impl ClientCirc {
1078        /// Testing only: Extract the circuit ID of this circuit.
1079        pub(crate) fn peek_circid(&self) -> CircId {
1080            self.circid
1081        }
1082    }
1083
1084    impl ClientTunnel {
1085        pub(crate) async fn resolve_last_hop(&self) -> TargetHop {
1086            let (sender, receiver) = oneshot::channel();
1087            let _ =
1088                self.as_single_circ()
1089                    .unwrap()
1090                    .command
1091                    .unbounded_send(CtrlCmd::ResolveTargetHop {
1092                        hop: TargetHop::LastHop,
1093                        done: sender,
1094                    });
1095            TargetHop::Hop(receiver.await.unwrap().unwrap())
1096        }
1097    }
1098
1099    // Example relay IDs and keys
1100    const EXAMPLE_SK: [u8; 32] =
1101        hex!("7789d92a89711a7e2874c61ea495452cfd48627b3ca2ea9546aafa5bf7b55803");
1102    const EXAMPLE_PK: [u8; 32] =
1103        hex!("395cb26b83b3cd4b91dba9913e562ae87d21ecdd56843da7ca939a6a69001253");
1104    const EXAMPLE_ED_ID: [u8; 32] = [6; 32];
1105    const EXAMPLE_RSA_ID: [u8; 20] = [10; 20];
1106
1107    /// return an example OwnedCircTarget that can get used for an ntor handshake.
1108    fn example_target() -> OwnedCircTarget {
1109        let mut builder = OwnedCircTarget::builder();
1110        builder
1111            .chan_target()
1112            .ed_identity(EXAMPLE_ED_ID.into())
1113            .rsa_identity(EXAMPLE_RSA_ID.into());
1114        builder
1115            .ntor_onion_key(EXAMPLE_PK.into())
1116            .protocols("FlowCtrl=1-2".parse().unwrap())
1117            .build()
1118            .unwrap()
1119    }
1120    fn example_ntor_key() -> crate::crypto::handshake::ntor::NtorSecretKey {
1121        crate::crypto::handshake::ntor::NtorSecretKey::new(
1122            EXAMPLE_SK.into(),
1123            EXAMPLE_PK.into(),
1124            EXAMPLE_RSA_ID.into(),
1125        )
1126    }
1127    fn example_ntor_v3_key() -> crate::crypto::handshake::ntor_v3::NtorV3SecretKey {
1128        crate::crypto::handshake::ntor_v3::NtorV3SecretKey::new(
1129            EXAMPLE_SK.into(),
1130            EXAMPLE_PK.into(),
1131            EXAMPLE_ED_ID.into(),
1132        )
1133    }
1134
1135    fn working_fake_channel<R: Runtime>(
1136        rt: &R,
1137    ) -> (Arc<Channel>, Receiver<AnyChanCell>, Sender<CodecResult>) {
1138        let (channel, chan_reactor, rx, tx) = new_reactor(rt.clone());
1139        rt.spawn(async {
1140            let _ignore = chan_reactor.run().await;
1141        })
1142        .unwrap();
1143        (channel, rx, tx)
1144    }
1145
1146    /// Which handshake type to use.
1147    #[derive(Copy, Clone)]
1148    enum HandshakeType {
1149        Fast,
1150        Ntor,
1151        NtorV3,
1152    }
1153
1154    #[allow(deprecated)]
1155    async fn test_create<R: Runtime>(rt: &R, handshake_type: HandshakeType, with_cc: bool) {
1156        // We want to try progressing from a pending circuit to a circuit
1157        // via a crate_fast handshake.
1158
1159        use crate::crypto::handshake::{ServerHandshake, fast::CreateFastServer, ntor::NtorServer};
1160
1161        let (chan, mut rx, _sink) = working_fake_channel(rt);
1162        let circid = CircId::new(128).unwrap();
1163        let (created_send, created_recv) = oneshot::channel();
1164        let (_circmsg_send, circmsg_recv) = fake_mpsc(64);
1165        let unique_id = UniqId::new(23, 17);
1166        let (padding_ctrl, padding_stream) = new_padding(DynTimeProvider::new(rt.clone()));
1167
1168        let (pending, reactor) = PendingClientTunnel::new(
1169            circid,
1170            chan,
1171            created_recv,
1172            circmsg_recv,
1173            unique_id,
1174            DynTimeProvider::new(rt.clone()),
1175            CircuitAccount::new_noop(),
1176            padding_ctrl,
1177            padding_stream,
1178            Arc::new(DummyTimeoutEstimator),
1179        );
1180
1181        rt.spawn(async {
1182            let _ignore = reactor.run().await;
1183        })
1184        .unwrap();
1185
1186        // Future to pretend to be a relay on the other end of the circuit.
1187        let simulate_relay_fut = async move {
1188            let mut rng = testing_rng();
1189            let create_cell = rx.next().await.unwrap();
1190            assert_eq!(create_cell.circid(), Some(circid));
1191            let reply = match handshake_type {
1192                HandshakeType::Fast => {
1193                    let cf = match create_cell.msg() {
1194                        AnyChanMsg::CreateFast(cf) => cf,
1195                        other => panic!("{:?}", other),
1196                    };
1197                    let (_, rep) = CreateFastServer::server(
1198                        &mut rng,
1199                        &mut |_: &()| Some(()),
1200                        &[()],
1201                        cf.handshake(),
1202                    )
1203                    .unwrap();
1204                    CreateResponse::CreatedFast(CreatedFast::new(rep))
1205                }
1206                HandshakeType::Ntor => {
1207                    let c2 = match create_cell.msg() {
1208                        AnyChanMsg::Create2(c2) => c2,
1209                        other => panic!("{:?}", other),
1210                    };
1211                    let (_, rep) = NtorServer::server(
1212                        &mut rng,
1213                        &mut |_: &()| Some(()),
1214                        &[example_ntor_key()],
1215                        c2.body(),
1216                    )
1217                    .unwrap();
1218                    CreateResponse::Created2(Created2::new(rep))
1219                }
1220                HandshakeType::NtorV3 => {
1221                    let c2 = match create_cell.msg() {
1222                        AnyChanMsg::Create2(c2) => c2,
1223                        other => panic!("{:?}", other),
1224                    };
1225                    let mut reply_fn = if with_cc {
1226                        |client_exts: &[CircRequestExt]| {
1227                            let _ = client_exts
1228                                .iter()
1229                                .find(|e| matches!(e, CircRequestExt::CcRequest(_)))
1230                                .expect("Client failed to request CC");
1231                            // This needs to be aligned to test_utils params
1232                            // value due to validation that needs it in range.
1233                            Some(vec![CircResponseExt::CcResponse(
1234                                extend_ext::CcResponse::new(31),
1235                            )])
1236                        }
1237                    } else {
1238                        |_: &_| Some(vec![])
1239                    };
1240                    let (_, rep) = NtorV3Server::server(
1241                        &mut rng,
1242                        &mut reply_fn,
1243                        &[example_ntor_v3_key()],
1244                        c2.body(),
1245                    )
1246                    .unwrap();
1247                    CreateResponse::Created2(Created2::new(rep))
1248                }
1249            };
1250            created_send.send(reply).unwrap();
1251        };
1252        // Future to pretend to be a client.
1253        let client_fut = async move {
1254            let target = example_target();
1255            let params = CircParameters::default();
1256            let ret = match handshake_type {
1257                HandshakeType::Fast => {
1258                    trace!("doing fast create");
1259                    pending.create_firsthop_fast(params).await
1260                }
1261                HandshakeType::Ntor => {
1262                    trace!("doing ntor create");
1263                    pending.create_firsthop_ntor(&target, params).await
1264                }
1265                HandshakeType::NtorV3 => {
1266                    let params = if with_cc {
1267                        // Setup CC vegas parameters.
1268                        CircParameters::new(
1269                            true,
1270                            build_cc_vegas_params(),
1271                            FlowCtrlParameters::defaults_for_tests(),
1272                        )
1273                    } else {
1274                        params
1275                    };
1276                    trace!("doing ntor_v3 create");
1277                    pending.create_firsthop_ntor_v3(&target, params).await
1278                }
1279            };
1280            trace!("create done: result {:?}", ret);
1281            ret
1282        };
1283
1284        let (circ, _) = futures::join!(client_fut, simulate_relay_fut);
1285
1286        let _circ = circ.unwrap();
1287
1288        // pfew!  We've build a circuit!  Let's make sure it has one hop.
1289        assert_eq!(_circ.n_hops().unwrap(), 1);
1290    }
1291
1292    #[traced_test]
1293    #[test]
1294    fn test_create_fast() {
1295        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
1296            test_create(&rt, HandshakeType::Fast, false).await;
1297        });
1298    }
1299    #[traced_test]
1300    #[test]
1301    fn test_create_ntor() {
1302        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
1303            test_create(&rt, HandshakeType::Ntor, false).await;
1304        });
1305    }
1306    #[traced_test]
1307    #[test]
1308    fn test_create_ntor_v3() {
1309        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
1310            test_create(&rt, HandshakeType::NtorV3, false).await;
1311        });
1312    }
1313    #[traced_test]
1314    #[test]
1315    #[cfg(feature = "flowctl-cc")]
1316    fn test_create_ntor_v3_with_cc() {
1317        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
1318            test_create(&rt, HandshakeType::NtorV3, true).await;
1319        });
1320    }
1321
1322    // An encryption layer that doesn't do any crypto.   Can be used
1323    // as inbound or outbound, but not both at once.
1324    pub(crate) struct DummyCrypto {
1325        counter_tag: [u8; 20],
1326        counter: u32,
1327        lasthop: bool,
1328    }
1329    impl DummyCrypto {
1330        fn next_tag(&mut self) -> SendmeTag {
1331            #![allow(clippy::identity_op)]
1332            self.counter_tag[0] = ((self.counter >> 0) & 255) as u8;
1333            self.counter_tag[1] = ((self.counter >> 8) & 255) as u8;
1334            self.counter_tag[2] = ((self.counter >> 16) & 255) as u8;
1335            self.counter_tag[3] = ((self.counter >> 24) & 255) as u8;
1336            self.counter += 1;
1337            self.counter_tag.into()
1338        }
1339    }
1340
1341    impl crate::crypto::cell::OutboundClientLayer for DummyCrypto {
1342        fn originate_for(&mut self, _cmd: ChanCmd, _cell: &mut RelayCellBody) -> SendmeTag {
1343            self.next_tag()
1344        }
1345        fn encrypt_outbound(&mut self, _cmd: ChanCmd, _cell: &mut RelayCellBody) {}
1346    }
1347    impl crate::crypto::cell::InboundClientLayer for DummyCrypto {
1348        fn decrypt_inbound(
1349            &mut self,
1350            _cmd: ChanCmd,
1351            _cell: &mut RelayCellBody,
1352        ) -> Option<SendmeTag> {
1353            if self.lasthop {
1354                Some(self.next_tag())
1355            } else {
1356                None
1357            }
1358        }
1359    }
1360    impl DummyCrypto {
1361        pub(crate) fn new(lasthop: bool) -> Self {
1362            DummyCrypto {
1363                counter_tag: [0; 20],
1364                counter: 0,
1365                lasthop,
1366            }
1367        }
1368    }
1369
1370    // Helper: set up a 3-hop circuit with no encryption, where the
1371    // next inbound message seems to come from hop next_msg_from
1372    async fn newtunnel_ext<R: Runtime>(
1373        rt: &R,
1374        unique_id: UniqId,
1375        chan: Arc<Channel>,
1376        hops: Vec<path::HopDetail>,
1377        next_msg_from: HopNum,
1378        params: CircParameters,
1379    ) -> (ClientTunnel, CircuitRxSender) {
1380        let circid = CircId::new(128).unwrap();
1381        let (_created_send, created_recv) = oneshot::channel();
1382        let (circmsg_send, circmsg_recv) = fake_mpsc(64);
1383        let (padding_ctrl, padding_stream) = new_padding(DynTimeProvider::new(rt.clone()));
1384
1385        let (pending, reactor) = PendingClientTunnel::new(
1386            circid,
1387            chan,
1388            created_recv,
1389            circmsg_recv,
1390            unique_id,
1391            DynTimeProvider::new(rt.clone()),
1392            CircuitAccount::new_noop(),
1393            padding_ctrl,
1394            padding_stream,
1395            Arc::new(DummyTimeoutEstimator),
1396        );
1397
1398        rt.spawn(async {
1399            let _ignore = reactor.run().await;
1400        })
1401        .unwrap();
1402        let PendingClientTunnel {
1403            circ,
1404            recvcreated: _,
1405        } = pending;
1406
1407        // TODO #1067: Support other formats
1408        let relay_cell_format = RelayCellFormat::V0;
1409
1410        let last_hop_num = u8::try_from(hops.len() - 1).unwrap();
1411        for (idx, peer_id) in hops.into_iter().enumerate() {
1412            let (tx, rx) = oneshot::channel();
1413            let idx = idx as u8;
1414
1415            circ.command
1416                .unbounded_send(CtrlCmd::AddFakeHop {
1417                    relay_cell_format,
1418                    fwd_lasthop: idx == last_hop_num,
1419                    rev_lasthop: idx == u8::from(next_msg_from),
1420                    peer_id,
1421                    params: params.clone(),
1422                    done: tx,
1423                })
1424                .unwrap();
1425            rx.await.unwrap().unwrap();
1426        }
1427        (circ.into_tunnel().unwrap(), circmsg_send)
1428    }
1429
1430    // Helper: set up a 3-hop circuit with no encryption, where the
1431    // next inbound message seems to come from hop next_msg_from
1432    async fn newtunnel<R: Runtime>(
1433        rt: &R,
1434        chan: Arc<Channel>,
1435    ) -> (Arc<ClientTunnel>, CircuitRxSender) {
1436        let hops = std::iter::repeat_with(|| {
1437            let peer_id = tor_linkspec::OwnedChanTarget::builder()
1438                .ed_identity([4; 32].into())
1439                .rsa_identity([5; 20].into())
1440                .build()
1441                .expect("Could not construct fake hop");
1442
1443            path::HopDetail::Relay(peer_id)
1444        })
1445        .take(3)
1446        .collect();
1447
1448        let unique_id = UniqId::new(23, 17);
1449        let (tunnel, circmsg_send) = newtunnel_ext(
1450            rt,
1451            unique_id,
1452            chan,
1453            hops,
1454            2.into(),
1455            CircParameters::default(),
1456        )
1457        .await;
1458
1459        (Arc::new(tunnel), circmsg_send)
1460    }
1461
1462    /// Create `n` distinct [`path::HopDetail`]s,
1463    /// with the specified `start_idx` for the dummy identities.
1464    fn hop_details(n: u8, start_idx: u8) -> Vec<path::HopDetail> {
1465        (0..n)
1466            .map(|idx| {
1467                let peer_id = tor_linkspec::OwnedChanTarget::builder()
1468                    .ed_identity([idx + start_idx; 32].into())
1469                    .rsa_identity([idx + start_idx + 1; 20].into())
1470                    .build()
1471                    .expect("Could not construct fake hop");
1472
1473                path::HopDetail::Relay(peer_id)
1474            })
1475            .collect()
1476    }
1477
1478    #[allow(deprecated)]
1479    async fn test_extend<R: Runtime>(rt: &R, handshake_type: HandshakeType) {
1480        use crate::crypto::handshake::{ServerHandshake, ntor::NtorServer};
1481
1482        let (chan, mut rx, _sink) = working_fake_channel(rt);
1483        let (tunnel, mut sink) = newtunnel(rt, chan).await;
1484        let circ = Arc::new(tunnel.as_single_circ().unwrap());
1485        let circid = circ.peek_circid();
1486        let params = CircParameters::default();
1487
1488        let extend_fut = async move {
1489            let target = example_target();
1490            match handshake_type {
1491                HandshakeType::Fast => panic!("Can't extend with Fast handshake"),
1492                HandshakeType::Ntor => circ.extend_ntor(&target, params).await.unwrap(),
1493                HandshakeType::NtorV3 => circ.extend_ntor_v3(&target, params).await.unwrap(),
1494            };
1495            circ // gotta keep the circ alive, or the reactor would exit.
1496        };
1497        let reply_fut = async move {
1498            // We've disabled encryption on this circuit, so we can just
1499            // read the extend2 cell.
1500            let (id, chmsg) = rx.next().await.unwrap().into_circid_and_msg();
1501            assert_eq!(id, Some(circid));
1502            let rmsg = match chmsg {
1503                AnyChanMsg::RelayEarly(r) => {
1504                    AnyRelayMsgOuter::decode_singleton(RelayCellFormat::V0, r.into_relay_body())
1505                        .unwrap()
1506                }
1507                other => panic!("{:?}", other),
1508            };
1509            let e2 = match rmsg.msg() {
1510                AnyRelayMsg::Extend2(e2) => e2,
1511                other => panic!("{:?}", other),
1512            };
1513            let mut rng = testing_rng();
1514            let reply = match handshake_type {
1515                HandshakeType::Fast => panic!("Can't extend with Fast handshake"),
1516                HandshakeType::Ntor => {
1517                    let (_keygen, reply) = NtorServer::server(
1518                        &mut rng,
1519                        &mut |_: &()| Some(()),
1520                        &[example_ntor_key()],
1521                        e2.handshake(),
1522                    )
1523                    .unwrap();
1524                    reply
1525                }
1526                HandshakeType::NtorV3 => {
1527                    let (_keygen, reply) = NtorV3Server::server(
1528                        &mut rng,
1529                        &mut |_: &[CircRequestExt]| Some(vec![]),
1530                        &[example_ntor_v3_key()],
1531                        e2.handshake(),
1532                    )
1533                    .unwrap();
1534                    reply
1535                }
1536            };
1537
1538            let extended2 = relaymsg::Extended2::new(reply).into();
1539            sink.send(rmsg_to_ccmsg(None, extended2, false))
1540                .await
1541                .unwrap();
1542            (sink, rx) // gotta keep the sink and receiver alive, or the reactor will exit.
1543        };
1544
1545        let (circ, (_sink, _rx)) = futures::join!(extend_fut, reply_fut);
1546
1547        // Did we really add another hop?
1548        assert_eq!(circ.n_hops().unwrap(), 4);
1549
1550        // Do the path accessors report a reasonable outcome?
1551        {
1552            let path = circ.single_path().unwrap();
1553            let path = path
1554                .all_hops()
1555                .filter_map(|hop| match hop {
1556                    path::HopDetail::Relay(r) => Some(r),
1557                    #[cfg(feature = "hs-common")]
1558                    path::HopDetail::Virtual => None,
1559                })
1560                .collect::<Vec<_>>();
1561
1562            assert_eq!(path.len(), 4);
1563            use tor_linkspec::HasRelayIds;
1564            assert_eq!(path[3].ed_identity(), example_target().ed_identity());
1565            assert_ne!(path[0].ed_identity(), example_target().ed_identity());
1566        }
1567        {
1568            let path = circ.single_path().unwrap();
1569            assert_eq!(path.n_hops(), 4);
1570            use tor_linkspec::HasRelayIds;
1571            assert_eq!(
1572                path.hops()[3].as_chan_target().unwrap().ed_identity(),
1573                example_target().ed_identity()
1574            );
1575            assert_ne!(
1576                path.hops()[0].as_chan_target().unwrap().ed_identity(),
1577                example_target().ed_identity()
1578            );
1579        }
1580    }
1581
1582    #[traced_test]
1583    #[test]
1584    fn test_extend_ntor() {
1585        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
1586            test_extend(&rt, HandshakeType::Ntor).await;
1587        });
1588    }
1589
1590    #[traced_test]
1591    #[test]
1592    fn test_extend_ntor_v3() {
1593        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
1594            test_extend(&rt, HandshakeType::NtorV3).await;
1595        });
1596    }
1597
1598    #[allow(deprecated)]
1599    async fn bad_extend_test_impl<R: Runtime>(
1600        rt: &R,
1601        reply_hop: HopNum,
1602        bad_reply: AnyChanMsg,
1603    ) -> Error {
1604        let (chan, mut rx, _sink) = working_fake_channel(rt);
1605        let hops = std::iter::repeat_with(|| {
1606            let peer_id = tor_linkspec::OwnedChanTarget::builder()
1607                .ed_identity([4; 32].into())
1608                .rsa_identity([5; 20].into())
1609                .build()
1610                .expect("Could not construct fake hop");
1611
1612            path::HopDetail::Relay(peer_id)
1613        })
1614        .take(3)
1615        .collect();
1616
1617        let unique_id = UniqId::new(23, 17);
1618        let (tunnel, mut sink) = newtunnel_ext(
1619            rt,
1620            unique_id,
1621            chan,
1622            hops,
1623            reply_hop,
1624            CircParameters::default(),
1625        )
1626        .await;
1627        let params = CircParameters::default();
1628
1629        let target = example_target();
1630        let reply_task_handle = rt
1631            .spawn_with_handle(async move {
1632                // Wait for a cell, and make sure it's EXTEND2.
1633                let (_circid, chanmsg) = rx.next().await.unwrap().into_circid_and_msg();
1634                let AnyChanMsg::RelayEarly(relay_early) = chanmsg else {
1635                    panic!("unexpected message {chanmsg:?}");
1636                };
1637                let relaymsg = UnparsedRelayMsg::from_singleton_body(
1638                    RelayCellFormat::V0,
1639                    relay_early.into_relay_body(),
1640                )
1641                .unwrap();
1642                assert_eq!(relaymsg.cmd(), RelayCmd::EXTEND2);
1643
1644                // Send back the "bad_reply."
1645                sink.send(bad_reply).await.unwrap();
1646                sink
1647            })
1648            .unwrap();
1649        let outcome = tunnel
1650            .as_single_circ()
1651            .unwrap()
1652            .extend_ntor(&target, params)
1653            .await;
1654        let _sink = reply_task_handle.await;
1655
1656        assert_eq!(tunnel.n_hops().unwrap(), 3);
1657        assert!(outcome.is_err());
1658        outcome.unwrap_err()
1659    }
1660
1661    #[traced_test]
1662    #[test]
1663    fn bad_extend_wronghop() {
1664        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
1665            let extended2 = relaymsg::Extended2::new(vec![]).into();
1666            let cc = rmsg_to_ccmsg(None, extended2, false);
1667
1668            let error = bad_extend_test_impl(&rt, 1.into(), cc).await;
1669            // This case shows up as a CircDestroy, since a message sent
1670            // from the wrong hop won't even be delivered to the extend
1671            // code's meta-handler.  Instead the unexpected message will cause
1672            // the circuit to get torn down.
1673            match error {
1674                Error::CircuitClosed => {}
1675                x => panic!("got other error: {}", x),
1676            }
1677        });
1678    }
1679
1680    #[traced_test]
1681    #[test]
1682    fn bad_extend_wrongtype() {
1683        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
1684            let extended = relaymsg::Extended::new(vec![7; 200]).into();
1685            let cc = rmsg_to_ccmsg(None, extended, false);
1686
1687            let error = bad_extend_test_impl(&rt, 2.into(), cc).await;
1688            match error {
1689                Error::BytesErr {
1690                    err: tor_bytes::Error::InvalidMessage(_),
1691                    object: "extended2 message",
1692                } => {}
1693                other => panic!("{:?}", other),
1694            }
1695        });
1696    }
1697
1698    #[traced_test]
1699    #[test]
1700    fn bad_extend_destroy() {
1701        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
1702            let cc = AnyChanMsg::Destroy(chanmsg::Destroy::new(4.into()));
1703            let error = bad_extend_test_impl(&rt, 2.into(), cc).await;
1704            match error {
1705                Error::CircuitClosed => {}
1706                other => panic!("{:?}", other),
1707            }
1708        });
1709    }
1710
1711    #[traced_test]
1712    #[test]
1713    fn bad_extend_crypto() {
1714        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
1715            let extended2 = relaymsg::Extended2::new(vec![99; 256]).into();
1716            let cc = rmsg_to_ccmsg(None, extended2, false);
1717            let error = bad_extend_test_impl(&rt, 2.into(), cc).await;
1718            assert_matches!(error, Error::BadCircHandshakeAuth);
1719        });
1720    }
1721
1722    #[traced_test]
1723    #[test]
1724    fn begindir() {
1725        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
1726            let (chan, mut rx, _sink) = working_fake_channel(&rt);
1727            let (tunnel, mut sink) = newtunnel(&rt, chan).await;
1728            let circ = tunnel.as_single_circ().unwrap();
1729            let circid = circ.peek_circid();
1730
1731            let begin_and_send_fut = async move {
1732                // Here we'll say we've got a circuit, and we want to
1733                // make a simple BEGINDIR request with it.
1734                let mut stream = tunnel.begin_dir_stream().await.unwrap();
1735                stream.write_all(b"HTTP/1.0 GET /\r\n").await.unwrap();
1736                stream.flush().await.unwrap();
1737                let mut buf = [0_u8; 1024];
1738                let n = stream.read(&mut buf).await.unwrap();
1739                assert_eq!(&buf[..n], b"HTTP/1.0 404 Not found\r\n");
1740                let n = stream.read(&mut buf).await.unwrap();
1741                assert_eq!(n, 0);
1742                stream
1743            };
1744            let reply_fut = async move {
1745                // We've disabled encryption on this circuit, so we can just
1746                // read the begindir cell.
1747                let (id, chmsg) = rx.next().await.unwrap().into_circid_and_msg();
1748                assert_eq!(id, Some(circid));
1749                let rmsg = match chmsg {
1750                    AnyChanMsg::Relay(r) => {
1751                        AnyRelayMsgOuter::decode_singleton(RelayCellFormat::V0, r.into_relay_body())
1752                            .unwrap()
1753                    }
1754                    other => panic!("{:?}", other),
1755                };
1756                let (streamid, rmsg) = rmsg.into_streamid_and_msg();
1757                assert_matches!(rmsg, AnyRelayMsg::BeginDir(_));
1758
1759                // Reply with a Connected cell to indicate success.
1760                let connected = relaymsg::Connected::new_empty().into();
1761                sink.send(rmsg_to_ccmsg(streamid, connected, false))
1762                    .await
1763                    .unwrap();
1764
1765                // Now read a DATA cell...
1766                let (id, chmsg) = rx.next().await.unwrap().into_circid_and_msg();
1767                assert_eq!(id, Some(circid));
1768                let rmsg = match chmsg {
1769                    AnyChanMsg::Relay(r) => {
1770                        AnyRelayMsgOuter::decode_singleton(RelayCellFormat::V0, r.into_relay_body())
1771                            .unwrap()
1772                    }
1773                    other => panic!("{:?}", other),
1774                };
1775                let (streamid_2, rmsg) = rmsg.into_streamid_and_msg();
1776                assert_eq!(streamid_2, streamid);
1777                if let AnyRelayMsg::Data(d) = rmsg {
1778                    assert_eq!(d.as_ref(), &b"HTTP/1.0 GET /\r\n"[..]);
1779                } else {
1780                    panic!();
1781                }
1782
1783                // Write another data cell in reply!
1784                let data = relaymsg::Data::new(b"HTTP/1.0 404 Not found\r\n")
1785                    .unwrap()
1786                    .into();
1787                sink.send(rmsg_to_ccmsg(streamid, data, false))
1788                    .await
1789                    .unwrap();
1790
1791                // Send an END cell to say that the conversation is over.
1792                let end = relaymsg::End::new_with_reason(relaymsg::EndReason::DONE).into();
1793                sink.send(rmsg_to_ccmsg(streamid, end, false))
1794                    .await
1795                    .unwrap();
1796
1797                (rx, sink) // gotta keep these alive, or the reactor will exit.
1798            };
1799
1800            let (_stream, (_rx, _sink)) = futures::join!(begin_and_send_fut, reply_fut);
1801        });
1802    }
1803
1804    // Test: close a stream, either by dropping it or by calling AsyncWriteExt::close.
1805    fn close_stream_helper(by_drop: bool) {
1806        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
1807            let (chan, mut rx, _sink) = working_fake_channel(&rt);
1808            let (tunnel, mut sink) = newtunnel(&rt, chan).await;
1809
1810            let stream_fut = async move {
1811                let stream = tunnel
1812                    .begin_stream("www.example.com", 80, None)
1813                    .await
1814                    .unwrap();
1815
1816                let (r, mut w) = stream.split();
1817                if by_drop {
1818                    // Drop the writer and the reader, which should close the stream.
1819                    drop(r);
1820                    drop(w);
1821                    (None, tunnel) // make sure to keep the circuit alive
1822                } else {
1823                    // Call close on the writer, while keeping the reader alive.
1824                    w.close().await.unwrap();
1825                    (Some(r), tunnel)
1826                }
1827            };
1828            let handler_fut = async {
1829                // Read the BEGIN message.
1830                let (_, msg) = rx.next().await.unwrap().into_circid_and_msg();
1831                let rmsg = match msg {
1832                    AnyChanMsg::Relay(r) => {
1833                        AnyRelayMsgOuter::decode_singleton(RelayCellFormat::V0, r.into_relay_body())
1834                            .unwrap()
1835                    }
1836                    other => panic!("{:?}", other),
1837                };
1838                let (streamid, rmsg) = rmsg.into_streamid_and_msg();
1839                assert_eq!(rmsg.cmd(), RelayCmd::BEGIN);
1840
1841                // Reply with a CONNECTED.
1842                let connected =
1843                    relaymsg::Connected::new_with_addr("10.0.0.1".parse().unwrap(), 1234).into();
1844                sink.send(rmsg_to_ccmsg(streamid, connected, false))
1845                    .await
1846                    .unwrap();
1847
1848                // Expect an END.
1849                let (_, msg) = rx.next().await.unwrap().into_circid_and_msg();
1850                let rmsg = match msg {
1851                    AnyChanMsg::Relay(r) => {
1852                        AnyRelayMsgOuter::decode_singleton(RelayCellFormat::V0, r.into_relay_body())
1853                            .unwrap()
1854                    }
1855                    other => panic!("{:?}", other),
1856                };
1857                let (_, rmsg) = rmsg.into_streamid_and_msg();
1858                assert_eq!(rmsg.cmd(), RelayCmd::END);
1859
1860                (rx, sink) // keep these alive or the reactor will exit.
1861            };
1862
1863            let ((_opt_reader, _circ), (_rx, _sink)) = futures::join!(stream_fut, handler_fut);
1864        });
1865    }
1866
1867    #[traced_test]
1868    #[test]
1869    fn drop_stream() {
1870        close_stream_helper(true);
1871    }
1872
1873    #[traced_test]
1874    #[test]
1875    fn close_stream() {
1876        close_stream_helper(false);
1877    }
1878
1879    #[traced_test]
1880    #[test]
1881    fn expire_halfstreams() {
1882        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
1883            let (chan, mut rx, _sink) = working_fake_channel(&rt);
1884            let (tunnel, mut sink) = newtunnel(&rt, chan).await;
1885
1886            let client_fut = async move {
1887                let stream = tunnel
1888                    .begin_stream("www.example.com", 80, None)
1889                    .await
1890                    .unwrap();
1891
1892                let (r, mut w) = stream.split();
1893                // Close the stream
1894                w.close().await.unwrap();
1895                (Some(r), tunnel)
1896            };
1897            let exit_fut = async {
1898                // Read the BEGIN message.
1899                let (_, msg) = rx.next().await.unwrap().into_circid_and_msg();
1900                let rmsg = match msg {
1901                    AnyChanMsg::Relay(r) => {
1902                        AnyRelayMsgOuter::decode_singleton(RelayCellFormat::V0, r.into_relay_body())
1903                            .unwrap()
1904                    }
1905                    other => panic!("{:?}", other),
1906                };
1907                let (streamid, rmsg) = rmsg.into_streamid_and_msg();
1908                assert_eq!(rmsg.cmd(), RelayCmd::BEGIN);
1909
1910                // Reply with a CONNECTED.
1911                let connected =
1912                    relaymsg::Connected::new_with_addr("10.0.0.1".parse().unwrap(), 1234).into();
1913                sink.send(rmsg_to_ccmsg(streamid, connected, false))
1914                    .await
1915                    .unwrap();
1916
1917                (rx, streamid, sink) // keep these alive or the reactor will exit.
1918            };
1919
1920            let ((_opt_reader, tunnel), (_rx, streamid, mut sink)) =
1921                futures::join!(client_fut, exit_fut);
1922
1923            // Progress all futures to ensure the reactor has a chance to notice
1924            // we closed the stream.
1925            rt.progress_until_stalled().await;
1926
1927            // The tunnel should remain open
1928            assert!(!tunnel.is_closed());
1929
1930            // Write some more data on the half-stream.
1931            // The half-stream hasn't expired yet, so it will simply be ignored.
1932            let data = relaymsg::Data::new(b"hello").unwrap();
1933            sink.send(rmsg_to_ccmsg(streamid, AnyRelayMsg::Data(data), false))
1934                .await
1935                .unwrap();
1936            rt.progress_until_stalled().await;
1937
1938            // This was not a protocol violation, so the tunnel is still alive.
1939            assert!(!tunnel.is_closed());
1940
1941            // Advance the time to cause the half-streams to get garbage collected.
1942            //
1943            // Advancing it by 2 * CBT ought to be enough, because the RTT estimator
1944            // won't yet have an estimate for the max_rtt.
1945            let stream_timeout = DummyTimeoutEstimator.circuit_build_timeout(3);
1946            rt.advance_by(2 * stream_timeout).await;
1947
1948            // Sending this cell is a protocol violation now
1949            // that the half-stream expired.
1950            let data = relaymsg::Data::new(b"hello").unwrap();
1951            sink.send(rmsg_to_ccmsg(streamid, AnyRelayMsg::Data(data), false))
1952                .await
1953                .unwrap();
1954            rt.progress_until_stalled().await;
1955
1956            // The tunnel shut down because of the proto violation.
1957            assert!(tunnel.is_closed());
1958        });
1959    }
1960
1961    // Set up a circuit and stream that expects some incoming SENDMEs.
1962    async fn setup_incoming_sendme_case<R: Runtime>(
1963        rt: &R,
1964        n_to_send: usize,
1965    ) -> (
1966        Arc<ClientTunnel>,
1967        DataStream,
1968        CircuitRxSender,
1969        Option<StreamId>,
1970        usize,
1971        Receiver<AnyChanCell>,
1972        Sender<CodecResult>,
1973    ) {
1974        let (chan, mut rx, sink2) = working_fake_channel(rt);
1975        let (tunnel, mut sink) = newtunnel(rt, chan).await;
1976        let circid = tunnel.as_single_circ().unwrap().peek_circid();
1977
1978        let begin_and_send_fut = {
1979            let tunnel = tunnel.clone();
1980            async move {
1981                // Take our circuit and make a stream on it.
1982                let mut stream = tunnel
1983                    .begin_stream("www.example.com", 443, None)
1984                    .await
1985                    .unwrap();
1986                let junk = [0_u8; 1024];
1987                let mut remaining = n_to_send;
1988                while remaining > 0 {
1989                    let n = std::cmp::min(remaining, junk.len());
1990                    stream.write_all(&junk[..n]).await.unwrap();
1991                    remaining -= n;
1992                }
1993                stream.flush().await.unwrap();
1994                stream
1995            }
1996        };
1997
1998        let receive_fut = async move {
1999            // Read the begin cell.
2000            let (_id, chmsg) = rx.next().await.unwrap().into_circid_and_msg();
2001            let rmsg = match chmsg {
2002                AnyChanMsg::Relay(r) => {
2003                    AnyRelayMsgOuter::decode_singleton(RelayCellFormat::V0, r.into_relay_body())
2004                        .unwrap()
2005                }
2006                other => panic!("{:?}", other),
2007            };
2008            let (streamid, rmsg) = rmsg.into_streamid_and_msg();
2009            assert_matches!(rmsg, AnyRelayMsg::Begin(_));
2010            // Reply with a connected cell...
2011            let connected = relaymsg::Connected::new_empty().into();
2012            sink.send(rmsg_to_ccmsg(streamid, connected, false))
2013                .await
2014                .unwrap();
2015            // Now read bytes from the stream until we have them all.
2016            let mut bytes_received = 0_usize;
2017            let mut cells_received = 0_usize;
2018            while bytes_received < n_to_send {
2019                // Read a data cell, and remember how much we got.
2020                let (id, chmsg) = rx.next().await.unwrap().into_circid_and_msg();
2021                assert_eq!(id, Some(circid));
2022
2023                let rmsg = match chmsg {
2024                    AnyChanMsg::Relay(r) => {
2025                        AnyRelayMsgOuter::decode_singleton(RelayCellFormat::V0, r.into_relay_body())
2026                            .unwrap()
2027                    }
2028                    other => panic!("{:?}", other),
2029                };
2030                let (streamid2, rmsg) = rmsg.into_streamid_and_msg();
2031                assert_eq!(streamid2, streamid);
2032                if let AnyRelayMsg::Data(dat) = rmsg {
2033                    cells_received += 1;
2034                    bytes_received += dat.as_ref().len();
2035                } else {
2036                    panic!();
2037                }
2038            }
2039
2040            (sink, streamid, cells_received, rx)
2041        };
2042
2043        let (stream, (sink, streamid, cells_received, rx)) =
2044            futures::join!(begin_and_send_fut, receive_fut);
2045
2046        (tunnel, stream, sink, streamid, cells_received, rx, sink2)
2047    }
2048
2049    #[traced_test]
2050    #[test]
2051    fn accept_valid_sendme() {
2052        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
2053            let (tunnel, _stream, mut sink, streamid, cells_received, _rx, _sink2) =
2054                setup_incoming_sendme_case(&rt, 300 * 498 + 3).await;
2055            let circ = tunnel.as_single_circ().unwrap();
2056
2057            assert_eq!(cells_received, 301);
2058
2059            // Make sure that the circuit is indeed expecting the right sendmes
2060            {
2061                let (tx, rx) = oneshot::channel();
2062                circ.command
2063                    .unbounded_send(CtrlCmd::QuerySendWindow {
2064                        hop: 2.into(),
2065                        leg: tunnel.unique_id(),
2066                        done: tx,
2067                    })
2068                    .unwrap();
2069                let (window, tags) = rx.await.unwrap().unwrap();
2070                assert_eq!(window, 1000 - 301);
2071                assert_eq!(tags.len(), 3);
2072                // 100
2073                assert_eq!(
2074                    tags[0],
2075                    SendmeTag::from(hex!("6400000000000000000000000000000000000000"))
2076                );
2077                // 200
2078                assert_eq!(
2079                    tags[1],
2080                    SendmeTag::from(hex!("c800000000000000000000000000000000000000"))
2081                );
2082                // 300
2083                assert_eq!(
2084                    tags[2],
2085                    SendmeTag::from(hex!("2c01000000000000000000000000000000000000"))
2086                );
2087            }
2088
2089            let reply_with_sendme_fut = async move {
2090                // make and send a circuit-level sendme.
2091                let c_sendme =
2092                    relaymsg::Sendme::new_tag(hex!("6400000000000000000000000000000000000000"))
2093                        .into();
2094                sink.send(rmsg_to_ccmsg(None, c_sendme, false))
2095                    .await
2096                    .unwrap();
2097
2098                // Make and send a stream-level sendme.
2099                let s_sendme = relaymsg::Sendme::new_empty().into();
2100                sink.send(rmsg_to_ccmsg(streamid, s_sendme, false))
2101                    .await
2102                    .unwrap();
2103
2104                sink
2105            };
2106
2107            let _sink = reply_with_sendme_fut.await;
2108
2109            rt.advance_until_stalled().await;
2110
2111            // Now make sure that the circuit is still happy, and its
2112            // window is updated.
2113            {
2114                let (tx, rx) = oneshot::channel();
2115                circ.command
2116                    .unbounded_send(CtrlCmd::QuerySendWindow {
2117                        hop: 2.into(),
2118                        leg: tunnel.unique_id(),
2119                        done: tx,
2120                    })
2121                    .unwrap();
2122                let (window, _tags) = rx.await.unwrap().unwrap();
2123                assert_eq!(window, 1000 - 201);
2124            }
2125        });
2126    }
2127
2128    #[traced_test]
2129    #[test]
2130    fn invalid_circ_sendme() {
2131        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
2132            // Same setup as accept_valid_sendme() test above but try giving
2133            // a sendme with the wrong tag.
2134
2135            let (tunnel, _stream, mut sink, _streamid, _cells_received, _rx, _sink2) =
2136                setup_incoming_sendme_case(&rt, 300 * 498 + 3).await;
2137
2138            let reply_with_sendme_fut = async move {
2139                // make and send a circuit-level sendme with a bad tag.
2140                let c_sendme =
2141                    relaymsg::Sendme::new_tag(hex!("FFFF0000000000000000000000000000000000FF"))
2142                        .into();
2143                sink.send(rmsg_to_ccmsg(None, c_sendme, false))
2144                    .await
2145                    .unwrap();
2146                sink
2147            };
2148
2149            let _sink = reply_with_sendme_fut.await;
2150
2151            // Check whether the reactor dies as a result of receiving invalid data.
2152            rt.advance_until_stalled().await;
2153            assert!(tunnel.is_closed());
2154        });
2155    }
2156
2157    #[traced_test]
2158    #[test]
2159    fn test_busy_stream_fairness() {
2160        // Number of streams to use.
2161        const N_STREAMS: usize = 3;
2162        // Number of cells (roughly) for each stream to send.
2163        const N_CELLS: usize = 20;
2164        // Number of bytes that *each* stream will send, and that we'll read
2165        // from the channel.
2166        const N_BYTES: usize = relaymsg::Data::MAXLEN_V0 * N_CELLS;
2167        // Ignoring cell granularity, with perfect fairness we'd expect
2168        // `N_BYTES/N_STREAMS` bytes from each stream.
2169        //
2170        // We currently allow for up to a full cell less than that.  This is
2171        // somewhat arbitrary and can be changed as needed, since we don't
2172        // provide any specific fairness guarantees.
2173        const MIN_EXPECTED_BYTES_PER_STREAM: usize =
2174            N_BYTES / N_STREAMS - relaymsg::Data::MAXLEN_V0;
2175
2176        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
2177            let (chan, mut rx, _sink) = working_fake_channel(&rt);
2178            let (tunnel, mut sink) = newtunnel(&rt, chan).await;
2179
2180            // Run clients in a single task, doing our own round-robin
2181            // scheduling of writes to the reactor. Conversely, if we were to
2182            // put each client in its own task, we would be at the mercy of
2183            // how fairly the runtime schedules the client tasks, which is outside
2184            // the scope of this test.
2185            rt.spawn({
2186                // Clone the circuit to keep it alive after writers have
2187                // finished with it.
2188                let tunnel = tunnel.clone();
2189                async move {
2190                    let mut clients = VecDeque::new();
2191                    struct Client {
2192                        stream: DataStream,
2193                        to_write: &'static [u8],
2194                    }
2195                    for _ in 0..N_STREAMS {
2196                        clients.push_back(Client {
2197                            stream: tunnel
2198                                .begin_stream("www.example.com", 80, None)
2199                                .await
2200                                .unwrap(),
2201                            to_write: &[0_u8; N_BYTES][..],
2202                        });
2203                    }
2204                    while let Some(mut client) = clients.pop_front() {
2205                        if client.to_write.is_empty() {
2206                            // Client is done. Don't put back in queue.
2207                            continue;
2208                        }
2209                        let written = client.stream.write(client.to_write).await.unwrap();
2210                        client.to_write = &client.to_write[written..];
2211                        clients.push_back(client);
2212                    }
2213                }
2214            })
2215            .unwrap();
2216
2217            let channel_handler_fut = async {
2218                let mut stream_bytes_received = HashMap::<StreamId, usize>::new();
2219                let mut total_bytes_received = 0;
2220
2221                loop {
2222                    let (_, msg) = rx.next().await.unwrap().into_circid_and_msg();
2223                    let rmsg = match msg {
2224                        AnyChanMsg::Relay(r) => AnyRelayMsgOuter::decode_singleton(
2225                            RelayCellFormat::V0,
2226                            r.into_relay_body(),
2227                        )
2228                        .unwrap(),
2229                        other => panic!("Unexpected chanmsg: {other:?}"),
2230                    };
2231                    let (streamid, rmsg) = rmsg.into_streamid_and_msg();
2232                    match rmsg.cmd() {
2233                        RelayCmd::BEGIN => {
2234                            // Add an entry for this stream.
2235                            let prev = stream_bytes_received.insert(streamid.unwrap(), 0);
2236                            assert_eq!(prev, None);
2237                            // Reply with a CONNECTED.
2238                            let connected = relaymsg::Connected::new_with_addr(
2239                                "10.0.0.1".parse().unwrap(),
2240                                1234,
2241                            )
2242                            .into();
2243                            sink.send(rmsg_to_ccmsg(streamid, connected, false))
2244                                .await
2245                                .unwrap();
2246                        }
2247                        RelayCmd::DATA => {
2248                            let data_msg = relaymsg::Data::try_from(rmsg).unwrap();
2249                            let nbytes = data_msg.as_ref().len();
2250                            total_bytes_received += nbytes;
2251                            let streamid = streamid.unwrap();
2252                            let stream_bytes = stream_bytes_received.get_mut(&streamid).unwrap();
2253                            *stream_bytes += nbytes;
2254                            if total_bytes_received >= N_BYTES {
2255                                break;
2256                            }
2257                        }
2258                        RelayCmd::END => {
2259                            // Stream is done. If fair scheduling is working as
2260                            // expected we *probably* shouldn't get here, but we
2261                            // can ignore it and save the failure until we
2262                            // actually have the final stats.
2263                            continue;
2264                        }
2265                        other => {
2266                            panic!("Unexpected command {other:?}");
2267                        }
2268                    }
2269                }
2270
2271                // Return our stats, along with the `rx` and `sink` to keep the
2272                // reactor alive (since clients could still be writing).
2273                (total_bytes_received, stream_bytes_received, rx, sink)
2274            };
2275
2276            let (total_bytes_received, stream_bytes_received, _rx, _sink) =
2277                channel_handler_fut.await;
2278            assert_eq!(stream_bytes_received.len(), N_STREAMS);
2279            for (sid, stream_bytes) in stream_bytes_received {
2280                assert!(
2281                    stream_bytes >= MIN_EXPECTED_BYTES_PER_STREAM,
2282                    "Only {stream_bytes} of {total_bytes_received} bytes received from {N_STREAMS} came from {sid:?}; expected at least {MIN_EXPECTED_BYTES_PER_STREAM}"
2283                );
2284            }
2285        });
2286    }
2287
2288    #[test]
2289    fn basic_params() {
2290        use super::CircParameters;
2291        let mut p = CircParameters::default();
2292        assert!(p.extend_by_ed25519_id);
2293
2294        p.extend_by_ed25519_id = false;
2295        assert!(!p.extend_by_ed25519_id);
2296    }
2297
2298    #[traced_test]
2299    #[test]
2300    #[cfg(feature = "hs-service")]
2301    fn allow_stream_requests_twice() {
2302        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
2303            let (chan, _rx, _sink) = working_fake_channel(&rt);
2304            let (tunnel, _send) = newtunnel(&rt, chan).await;
2305
2306            let _incoming = tunnel
2307                .allow_stream_requests(
2308                    &[tor_cell::relaycell::RelayCmd::BEGIN],
2309                    tunnel.resolve_last_hop().await,
2310                    AllowAllStreamsFilter,
2311                )
2312                .await
2313                .unwrap();
2314
2315            let incoming = tunnel
2316                .allow_stream_requests(
2317                    &[tor_cell::relaycell::RelayCmd::BEGIN],
2318                    tunnel.resolve_last_hop().await,
2319                    AllowAllStreamsFilter,
2320                )
2321                .await;
2322
2323            // There can only be one IncomingStream at a time on any given circuit.
2324            assert!(incoming.is_err());
2325        });
2326    }
2327
2328    #[traced_test]
2329    #[test]
2330    #[cfg(feature = "hs-service")]
2331    fn allow_stream_requests() {
2332        use tor_cell::relaycell::msg::BeginFlags;
2333
2334        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
2335            const TEST_DATA: &[u8] = b"ping";
2336
2337            let (chan, _rx, _sink) = working_fake_channel(&rt);
2338            let (tunnel, mut send) = newtunnel(&rt, chan).await;
2339
2340            let rfmt = RelayCellFormat::V0;
2341
2342            // A helper channel for coordinating the "client"/"service" interaction
2343            let (tx, rx) = oneshot::channel();
2344            let mut incoming = tunnel
2345                .allow_stream_requests(
2346                    &[tor_cell::relaycell::RelayCmd::BEGIN],
2347                    tunnel.resolve_last_hop().await,
2348                    AllowAllStreamsFilter,
2349                )
2350                .await
2351                .unwrap();
2352
2353            let simulate_service = async move {
2354                let stream = incoming.next().await.unwrap();
2355                let mut data_stream = stream
2356                    .accept_data(relaymsg::Connected::new_empty())
2357                    .await
2358                    .unwrap();
2359                // Notify the client task we're ready to accept DATA cells
2360                tx.send(()).unwrap();
2361
2362                // Read the data the client sent us
2363                let mut buf = [0_u8; TEST_DATA.len()];
2364                data_stream.read_exact(&mut buf).await.unwrap();
2365                assert_eq!(&buf, TEST_DATA);
2366
2367                tunnel
2368            };
2369
2370            let simulate_client = async move {
2371                let begin = relaymsg::Begin::new("localhost", 80, BeginFlags::IPV6_OKAY).unwrap();
2372                let body: BoxedCellBody =
2373                    AnyRelayMsgOuter::new(StreamId::new(12), AnyRelayMsg::Begin(begin))
2374                        .encode(rfmt, &mut testing_rng())
2375                        .unwrap();
2376                let begin_msg = chanmsg::Relay::from(body);
2377
2378                // Pretend to be a client at the other end of the circuit sending a begin cell
2379                send.send(AnyChanMsg::Relay(begin_msg)).await.unwrap();
2380
2381                // Wait until the service is ready to accept data
2382                // TODO: we shouldn't need to wait! This is needed because the service will reject
2383                // any DATA cells that aren't associated with a known stream. We need to wait until
2384                // the service receives our BEGIN cell (and the reactor updates hop.map with the
2385                // new stream).
2386                rx.await.unwrap();
2387                // Now send some data along the newly established circuit..
2388                let data = relaymsg::Data::new(TEST_DATA).unwrap();
2389                let body: BoxedCellBody =
2390                    AnyRelayMsgOuter::new(StreamId::new(12), AnyRelayMsg::Data(data))
2391                        .encode(rfmt, &mut testing_rng())
2392                        .unwrap();
2393                let data_msg = chanmsg::Relay::from(body);
2394
2395                send.send(AnyChanMsg::Relay(data_msg)).await.unwrap();
2396                send
2397            };
2398
2399            let (_circ, _send) = futures::join!(simulate_service, simulate_client);
2400        });
2401    }
2402
2403    #[traced_test]
2404    #[test]
2405    #[cfg(feature = "hs-service")]
2406    fn accept_stream_after_reject() {
2407        use tor_cell::relaycell::msg::AnyRelayMsg;
2408        use tor_cell::relaycell::msg::BeginFlags;
2409        use tor_cell::relaycell::msg::EndReason;
2410
2411        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
2412            const TEST_DATA: &[u8] = b"ping";
2413            const STREAM_COUNT: usize = 2;
2414            let rfmt = RelayCellFormat::V0;
2415
2416            let (chan, _rx, _sink) = working_fake_channel(&rt);
2417            let (tunnel, mut send) = newtunnel(&rt, chan).await;
2418
2419            // A helper channel for coordinating the "client"/"service" interaction
2420            let (mut tx, mut rx) = mpsc::channel(STREAM_COUNT);
2421
2422            let mut incoming = tunnel
2423                .allow_stream_requests(
2424                    &[tor_cell::relaycell::RelayCmd::BEGIN],
2425                    tunnel.resolve_last_hop().await,
2426                    AllowAllStreamsFilter,
2427                )
2428                .await
2429                .unwrap();
2430
2431            let simulate_service = async move {
2432                // Process 2 incoming streams
2433                for i in 0..STREAM_COUNT {
2434                    let stream = incoming.next().await.unwrap();
2435
2436                    // Reject the first one
2437                    if i == 0 {
2438                        stream
2439                            .reject(relaymsg::End::new_with_reason(EndReason::INTERNAL))
2440                            .await
2441                            .unwrap();
2442                        // Notify the client
2443                        tx.send(()).await.unwrap();
2444                        continue;
2445                    }
2446
2447                    let mut data_stream = stream
2448                        .accept_data(relaymsg::Connected::new_empty())
2449                        .await
2450                        .unwrap();
2451                    // Notify the client task we're ready to accept DATA cells
2452                    tx.send(()).await.unwrap();
2453
2454                    // Read the data the client sent us
2455                    let mut buf = [0_u8; TEST_DATA.len()];
2456                    data_stream.read_exact(&mut buf).await.unwrap();
2457                    assert_eq!(&buf, TEST_DATA);
2458                }
2459
2460                tunnel
2461            };
2462
2463            let simulate_client = async move {
2464                let begin = relaymsg::Begin::new("localhost", 80, BeginFlags::IPV6_OKAY).unwrap();
2465                let body: BoxedCellBody =
2466                    AnyRelayMsgOuter::new(StreamId::new(12), AnyRelayMsg::Begin(begin))
2467                        .encode(rfmt, &mut testing_rng())
2468                        .unwrap();
2469                let begin_msg = chanmsg::Relay::from(body);
2470
2471                // Pretend to be a client at the other end of the circuit sending 2 identical begin
2472                // cells (the first one will be rejected by the test service).
2473                for _ in 0..STREAM_COUNT {
2474                    send.send(AnyChanMsg::Relay(begin_msg.clone()))
2475                        .await
2476                        .unwrap();
2477
2478                    // Wait until the service rejects our request
2479                    rx.next().await.unwrap();
2480                }
2481
2482                // Now send some data along the newly established circuit..
2483                let data = relaymsg::Data::new(TEST_DATA).unwrap();
2484                let body: BoxedCellBody =
2485                    AnyRelayMsgOuter::new(StreamId::new(12), AnyRelayMsg::Data(data))
2486                        .encode(rfmt, &mut testing_rng())
2487                        .unwrap();
2488                let data_msg = chanmsg::Relay::from(body);
2489
2490                send.send(AnyChanMsg::Relay(data_msg)).await.unwrap();
2491                send
2492            };
2493
2494            let (_circ, _send) = futures::join!(simulate_service, simulate_client);
2495        });
2496    }
2497
2498    #[traced_test]
2499    #[test]
2500    #[cfg(feature = "hs-service")]
2501    fn incoming_stream_bad_hop() {
2502        use tor_cell::relaycell::msg::BeginFlags;
2503
2504        tor_rtcompat::test_with_all_runtimes!(|rt| async move {
2505            /// Expect the originator of the BEGIN cell to be hop 1.
2506            const EXPECTED_HOP: u8 = 1;
2507            let rfmt = RelayCellFormat::V0;
2508
2509            let (chan, _rx, _sink) = working_fake_channel(&rt);
2510            let (tunnel, mut send) = newtunnel(&rt, chan).await;
2511
2512            // Expect to receive incoming streams from hop EXPECTED_HOP
2513            let mut incoming = tunnel
2514                .allow_stream_requests(
2515                    &[tor_cell::relaycell::RelayCmd::BEGIN],
2516                    // Build the precise HopLocation with the underlying circuit.
2517                    (
2518                        tunnel.as_single_circ().unwrap().unique_id(),
2519                        EXPECTED_HOP.into(),
2520                    )
2521                        .into(),
2522                    AllowAllStreamsFilter,
2523                )
2524                .await
2525                .unwrap();
2526
2527            let simulate_service = async move {
2528                // The originator of the cell is actually the last hop on the circuit, not hop 1,
2529                // so we expect the reactor to shut down.
2530                assert!(incoming.next().await.is_none());
2531                tunnel
2532            };
2533
2534            let simulate_client = async move {
2535                let begin = relaymsg::Begin::new("localhost", 80, BeginFlags::IPV6_OKAY).unwrap();
2536                let body: BoxedCellBody =
2537                    AnyRelayMsgOuter::new(StreamId::new(12), AnyRelayMsg::Begin(begin))
2538                        .encode(rfmt, &mut testing_rng())
2539                        .unwrap();
2540                let begin_msg = chanmsg::Relay::from(body);
2541
2542                // Pretend to be a client at the other end of the circuit sending a begin cell
2543                send.send(AnyChanMsg::Relay(begin_msg)).await.unwrap();
2544
2545                send
2546            };
2547
2548            let (_circ, _send) = futures::join!(simulate_service, simulate_client);
2549        });
2550    }
2551
2552    #[traced_test]
2553    #[test]
2554    #[cfg(feature = "conflux")]
2555    fn multipath_circ_validation() {
2556        use std::error::Error as _;
2557
2558        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
2559            let params = CircParameters::default();
2560            let invalid_tunnels = [
2561                setup_bad_conflux_tunnel(&rt).await,
2562                setup_conflux_tunnel(&rt, true, params).await,
2563            ];
2564
2565            for tunnel in invalid_tunnels {
2566                let TestTunnelCtx {
2567                    tunnel: _tunnel,
2568                    circs: _circs,
2569                    conflux_link_rx,
2570                } = tunnel;
2571
2572                let conflux_hs_err = conflux_link_rx.await.unwrap().unwrap_err();
2573                let err_src = conflux_hs_err.source().unwrap();
2574
2575                // The two circuits don't end in the same hop (no join point),
2576                // so the reactor will refuse to link them
2577                assert!(
2578                    err_src
2579                        .to_string()
2580                        .contains("one more conflux circuits are invalid")
2581                );
2582            }
2583        });
2584    }
2585
2586    // TODO: this structure could be reused for the other tests,
2587    // to address nickm's comment:
2588    // https://gitlab.torproject.org/tpo/core/arti/-/merge_requests/3005#note_3202362
2589    #[derive(Debug)]
2590    #[allow(unused)]
2591    #[cfg(feature = "conflux")]
2592    struct TestCircuitCtx {
2593        chan_rx: Receiver<AnyChanCell>,
2594        chan_tx: Sender<std::result::Result<AnyChanCell, Error>>,
2595        circ_tx: CircuitRxSender,
2596        unique_id: UniqId,
2597    }
2598
2599    #[derive(Debug)]
2600    #[cfg(feature = "conflux")]
2601    struct TestTunnelCtx {
2602        tunnel: Arc<ClientTunnel>,
2603        circs: Vec<TestCircuitCtx>,
2604        conflux_link_rx: oneshot::Receiver<Result<ConfluxHandshakeResult>>,
2605    }
2606
2607    /// Wait for a LINK cell to arrive on the specified channel and return its payload.
2608    #[cfg(feature = "conflux")]
2609    async fn await_link_payload(rx: &mut Receiver<AnyChanCell>) -> ConfluxLink {
2610        // Wait for the LINK cell...
2611        let (_id, chmsg) = rx.next().await.unwrap().into_circid_and_msg();
2612        let rmsg = match chmsg {
2613            AnyChanMsg::Relay(r) => {
2614                AnyRelayMsgOuter::decode_singleton(RelayCellFormat::V0, r.into_relay_body())
2615                    .unwrap()
2616            }
2617            other => panic!("{:?}", other),
2618        };
2619        let (streamid, rmsg) = rmsg.into_streamid_and_msg();
2620
2621        let link = match rmsg {
2622            AnyRelayMsg::ConfluxLink(link) => link,
2623            _ => panic!("unexpected relay message {rmsg:?}"),
2624        };
2625
2626        assert!(streamid.is_none());
2627
2628        link
2629    }
2630
2631    #[cfg(feature = "conflux")]
2632    async fn setup_conflux_tunnel(
2633        rt: &MockRuntime,
2634        same_hops: bool,
2635        params: CircParameters,
2636    ) -> TestTunnelCtx {
2637        let hops1 = hop_details(3, 0);
2638        let hops2 = if same_hops {
2639            hops1.clone()
2640        } else {
2641            hop_details(3, 10)
2642        };
2643
2644        let (chan1, rx1, chan_sink1) = working_fake_channel(rt);
2645        let (mut tunnel1, sink1) = newtunnel_ext(
2646            rt,
2647            UniqId::new(1, 3),
2648            chan1,
2649            hops1,
2650            2.into(),
2651            params.clone(),
2652        )
2653        .await;
2654
2655        let (chan2, rx2, chan_sink2) = working_fake_channel(rt);
2656
2657        let (tunnel2, sink2) =
2658            newtunnel_ext(rt, UniqId::new(2, 4), chan2, hops2, 2.into(), params).await;
2659
2660        let (answer_tx, answer_rx) = oneshot::channel();
2661        tunnel2
2662            .as_single_circ()
2663            .unwrap()
2664            .command
2665            .unbounded_send(CtrlCmd::ShutdownAndReturnCircuit { answer: answer_tx })
2666            .unwrap();
2667
2668        let circuit = answer_rx.await.unwrap().unwrap();
2669        // The circuit should be shutting down its reactor
2670        rt.advance_until_stalled().await;
2671        assert!(tunnel2.is_closed());
2672
2673        let (conflux_link_tx, conflux_link_rx) = oneshot::channel();
2674        // Tell the first circuit to link with the second and form a multipath tunnel
2675        tunnel1
2676            .as_single_circ()
2677            .unwrap()
2678            .control
2679            .unbounded_send(CtrlMsg::LinkCircuits {
2680                circuits: vec![circuit],
2681                answer: conflux_link_tx,
2682            })
2683            .unwrap();
2684
2685        let circ_ctx1 = TestCircuitCtx {
2686            chan_rx: rx1,
2687            chan_tx: chan_sink1,
2688            circ_tx: sink1,
2689            unique_id: tunnel1.unique_id(),
2690        };
2691
2692        let circ_ctx2 = TestCircuitCtx {
2693            chan_rx: rx2,
2694            chan_tx: chan_sink2,
2695            circ_tx: sink2,
2696            unique_id: tunnel2.unique_id(),
2697        };
2698
2699        // TODO(conflux): nothing currently sets this,
2700        // so we need to manually set it.
2701        //
2702        // Instead of doing this, we should have a ClientCirc
2703        // API that sends CtrlMsg::Link circuits and sets this to true
2704        tunnel1.circ.is_multi_path = true;
2705        TestTunnelCtx {
2706            tunnel: Arc::new(tunnel1),
2707            circs: vec![circ_ctx1, circ_ctx2],
2708            conflux_link_rx,
2709        }
2710    }
2711
2712    #[cfg(feature = "conflux")]
2713    async fn setup_good_conflux_tunnel(
2714        rt: &MockRuntime,
2715        cc_params: CongestionControlParams,
2716    ) -> TestTunnelCtx {
2717        // Our 2 test circuits are identical, so they both have the same guards,
2718        // which technically violates the conflux set rule mentioned in prop354.
2719        // For testing purposes this is fine, but in production we'll need to ensure
2720        // the calling code prevents guard reuse (except in the case where
2721        // one of the guards happens to be Guard + Exit)
2722        let same_hops = true;
2723        let flow_ctrl_params = FlowCtrlParameters::defaults_for_tests();
2724        let params = CircParameters::new(true, cc_params, flow_ctrl_params);
2725        setup_conflux_tunnel(rt, same_hops, params).await
2726    }
2727
2728    #[cfg(feature = "conflux")]
2729    async fn setup_bad_conflux_tunnel(rt: &MockRuntime) -> TestTunnelCtx {
2730        // The two circuits don't share any hops,
2731        // so they won't end in the same hop (no join point),
2732        // causing the reactor to refuse to link them.
2733        let same_hops = false;
2734        let flow_ctrl_params = FlowCtrlParameters::defaults_for_tests();
2735        let params = CircParameters::new(true, build_cc_vegas_params(), flow_ctrl_params);
2736        setup_conflux_tunnel(rt, same_hops, params).await
2737    }
2738
2739    #[traced_test]
2740    #[test]
2741    #[cfg(feature = "conflux")]
2742    fn reject_conflux_linked_before_hs() {
2743        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
2744            let (chan, mut _rx, _sink) = working_fake_channel(&rt);
2745            let (tunnel, mut sink) = newtunnel(&rt, chan).await;
2746
2747            let nonce = V1Nonce::new(&mut testing_rng());
2748            let payload = V1LinkPayload::new(nonce, V1DesiredUx::NO_OPINION);
2749            // Send a LINKED cell
2750            let linked = relaymsg::ConfluxLinked::new(payload).into();
2751            sink.send(rmsg_to_ccmsg(None, linked, false)).await.unwrap();
2752
2753            rt.advance_until_stalled().await;
2754            assert!(tunnel.is_closed());
2755        });
2756    }
2757
2758    #[traced_test]
2759    #[test]
2760    #[cfg(feature = "conflux")]
2761    fn conflux_hs_timeout() {
2762        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
2763            let TestTunnelCtx {
2764                tunnel: _tunnel,
2765                circs,
2766                conflux_link_rx,
2767            } = setup_good_conflux_tunnel(&rt, build_cc_vegas_params()).await;
2768
2769            let [mut circ1, _circ2]: [TestCircuitCtx; 2] = circs.try_into().unwrap();
2770
2771            // Wait for the LINK cell
2772            let link = await_link_payload(&mut circ1.chan_rx).await;
2773
2774            // Send a LINK cell on the first leg...
2775            let linked = relaymsg::ConfluxLinked::new(link.payload().clone()).into();
2776            circ1
2777                .circ_tx
2778                .send(rmsg_to_ccmsg(None, linked, false))
2779                .await
2780                .unwrap();
2781
2782            // Do nothing, and wait for the handshake to timeout on the second leg
2783            rt.advance_by(Duration::from_secs(60)).await;
2784
2785            let conflux_hs_res = conflux_link_rx.await.unwrap().unwrap();
2786
2787            // Get the handshake results of each circuit
2788            let [res1, res2]: [StdResult<(), ConfluxHandshakeError>; 2] =
2789                conflux_hs_res.try_into().unwrap();
2790
2791            assert!(res1.is_ok());
2792
2793            let err = res2.unwrap_err();
2794            assert_matches!(err, ConfluxHandshakeError::Timeout);
2795        });
2796    }
2797
2798    #[traced_test]
2799    #[test]
2800    #[cfg(feature = "conflux")]
2801    fn conflux_bad_hs() {
2802        use crate::util::err::ConfluxHandshakeError;
2803
2804        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
2805            let nonce = V1Nonce::new(&mut testing_rng());
2806            let bad_link_payload = V1LinkPayload::new(nonce, V1DesiredUx::NO_OPINION);
2807            //let extended2 = relaymsg::Extended2::new(vec![]).into();
2808            let bad_hs_responses = [
2809                (
2810                    rmsg_to_ccmsg(
2811                        None,
2812                        relaymsg::ConfluxLinked::new(bad_link_payload.clone()).into(),
2813                        false,
2814                    ),
2815                    "Received CONFLUX_LINKED cell with mismatched nonce",
2816                ),
2817                (
2818                    rmsg_to_ccmsg(
2819                        None,
2820                        relaymsg::ConfluxLink::new(bad_link_payload).into(),
2821                        false,
2822                    ),
2823                    "Unexpected CONFLUX_LINK cell from hop #3 on client circuit",
2824                ),
2825                (
2826                    rmsg_to_ccmsg(None, relaymsg::ConfluxSwitch::new(0).into(), false),
2827                    "Received CONFLUX_SWITCH on unlinked circuit?!",
2828                ),
2829                // TODO: this currently causes the reactor to shut down immediately,
2830                // without sending a response on the handshake channel
2831                /*
2832                (
2833                    rmsg_to_ccmsg(None, extended2, false),
2834                    "Received CONFLUX_LINKED cell with mismatched nonce",
2835                ),
2836                */
2837            ];
2838
2839            for (bad_cell, expected_err) in bad_hs_responses {
2840                let TestTunnelCtx {
2841                    tunnel,
2842                    circs,
2843                    conflux_link_rx,
2844                } = setup_good_conflux_tunnel(&rt, build_cc_vegas_params()).await;
2845
2846                let [mut _circ1, mut circ2]: [TestCircuitCtx; 2] = circs.try_into().unwrap();
2847
2848                // Respond with a bogus cell on one of the legs
2849                circ2.circ_tx.send(bad_cell).await.unwrap();
2850
2851                let conflux_hs_res = conflux_link_rx.await.unwrap().unwrap();
2852                // Get the handshake results (the handshake results are reported early,
2853                // without waiting for the second circuit leg's handshake to timeout,
2854                // because this is a protocol violation causing the entire tunnel to shut down)
2855                let [res2]: [StdResult<(), ConfluxHandshakeError>; 1] =
2856                    conflux_hs_res.try_into().unwrap();
2857
2858                match res2.unwrap_err() {
2859                    ConfluxHandshakeError::Link(Error::CircProto(e)) => {
2860                        assert_eq!(e, expected_err);
2861                    }
2862                    e => panic!("unexpected error: {e:?}"),
2863                }
2864
2865                assert!(tunnel.is_closed());
2866            }
2867        });
2868    }
2869
2870    #[traced_test]
2871    #[test]
2872    #[cfg(feature = "conflux")]
2873    fn unexpected_conflux_cell() {
2874        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
2875            let nonce = V1Nonce::new(&mut testing_rng());
2876            let link_payload = V1LinkPayload::new(nonce, V1DesiredUx::NO_OPINION);
2877            let bad_cells = [
2878                rmsg_to_ccmsg(
2879                    None,
2880                    relaymsg::ConfluxLinked::new(link_payload.clone()).into(),
2881                    false,
2882                ),
2883                rmsg_to_ccmsg(
2884                    None,
2885                    relaymsg::ConfluxLink::new(link_payload.clone()).into(),
2886                    false,
2887                ),
2888                rmsg_to_ccmsg(None, relaymsg::ConfluxSwitch::new(0).into(), false),
2889            ];
2890
2891            for bad_cell in bad_cells {
2892                let (chan, mut _rx, _sink) = working_fake_channel(&rt);
2893                let (tunnel, mut sink) = newtunnel(&rt, chan).await;
2894
2895                sink.send(bad_cell).await.unwrap();
2896                rt.advance_until_stalled().await;
2897
2898                // Note: unfortunately we can't assert the circuit is
2899                // closing for the reason, because the reactor just logs
2900                // the error and then exits.
2901                assert!(tunnel.is_closed());
2902            }
2903        });
2904    }
2905
2906    #[traced_test]
2907    #[test]
2908    #[cfg(feature = "conflux")]
2909    fn conflux_bad_linked() {
2910        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
2911            let TestTunnelCtx {
2912                tunnel,
2913                circs,
2914                conflux_link_rx: _,
2915            } = setup_good_conflux_tunnel(&rt, build_cc_vegas_params()).await;
2916
2917            let [mut circ1, mut circ2]: [TestCircuitCtx; 2] = circs.try_into().unwrap();
2918
2919            let link = await_link_payload(&mut circ1.chan_rx).await;
2920
2921            // Send a LINK cell on the first leg...
2922            let linked = relaymsg::ConfluxLinked::new(link.payload().clone()).into();
2923            circ1
2924                .circ_tx
2925                .send(rmsg_to_ccmsg(None, linked, false))
2926                .await
2927                .unwrap();
2928
2929            // ...and two LINKED cells on the second
2930            let linked = relaymsg::ConfluxLinked::new(link.payload().clone()).into();
2931            circ2
2932                .circ_tx
2933                .send(rmsg_to_ccmsg(None, linked, false))
2934                .await
2935                .unwrap();
2936            let linked = relaymsg::ConfluxLinked::new(link.payload().clone()).into();
2937            circ2
2938                .circ_tx
2939                .send(rmsg_to_ccmsg(None, linked, false))
2940                .await
2941                .unwrap();
2942
2943            rt.advance_until_stalled().await;
2944
2945            // Receiving a LINKED cell on an already linked leg causes
2946            // the tunnel to be torn down
2947            assert!(tunnel.is_closed());
2948        });
2949    }
2950
2951    #[traced_test]
2952    #[test]
2953    #[cfg(feature = "conflux")]
2954    fn conflux_bad_switch() {
2955        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
2956            let cc_vegas_params = build_cc_vegas_params();
2957            let cwnd_init = cc_vegas_params.cwnd_params().cwnd_init();
2958            let bad_switch = [
2959                // SWITCH cells with seqno = 0 are not allowed
2960                relaymsg::ConfluxSwitch::new(0),
2961                // SWITCH cells with seqno > cc_init_cwnd are not allowed
2962                // on tunnels that have not received any data
2963                relaymsg::ConfluxSwitch::new(cwnd_init + 1),
2964            ];
2965
2966            for bad_cell in bad_switch {
2967                let TestTunnelCtx {
2968                    tunnel,
2969                    circs,
2970                    conflux_link_rx,
2971                } = setup_good_conflux_tunnel(&rt, cc_vegas_params.clone()).await;
2972
2973                let [mut circ1, mut circ2]: [TestCircuitCtx; 2] = circs.try_into().unwrap();
2974
2975                let link = await_link_payload(&mut circ1.chan_rx).await;
2976
2977                // Send a LINKED cell on both legs
2978                for circ in [&mut circ1, &mut circ2] {
2979                    let linked = relaymsg::ConfluxLinked::new(link.payload().clone()).into();
2980                    circ.circ_tx
2981                        .send(rmsg_to_ccmsg(None, linked, false))
2982                        .await
2983                        .unwrap();
2984                }
2985
2986                let conflux_hs_res = conflux_link_rx.await.unwrap().unwrap();
2987                assert!(conflux_hs_res.iter().all(|res| res.is_ok()));
2988
2989                // Now send a bad SWITCH cell on the first leg.
2990                // This will cause the tunnel reactor to shut down.
2991                let msg = rmsg_to_ccmsg(None, bad_cell.clone().into(), false);
2992                circ1.circ_tx.send(msg).await.unwrap();
2993
2994                // The tunnel should be shutting down
2995                rt.advance_until_stalled().await;
2996                assert!(tunnel.is_closed());
2997            }
2998        });
2999    }
3000
3001    #[traced_test]
3002    #[test]
3003    #[cfg(feature = "conflux")]
3004    fn conflux_consecutive_switch() {
3005        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
3006            let TestTunnelCtx {
3007                tunnel,
3008                circs,
3009                conflux_link_rx,
3010            } = setup_good_conflux_tunnel(&rt, build_cc_vegas_params()).await;
3011
3012            let [mut circ1, mut circ2]: [TestCircuitCtx; 2] = circs.try_into().unwrap();
3013
3014            let link = await_link_payload(&mut circ1.chan_rx).await;
3015
3016            // Send a LINKED cell on both legs
3017            for circ in [&mut circ1, &mut circ2] {
3018                let linked = relaymsg::ConfluxLinked::new(link.payload().clone()).into();
3019                circ.circ_tx
3020                    .send(rmsg_to_ccmsg(None, linked, false))
3021                    .await
3022                    .unwrap();
3023            }
3024
3025            let conflux_hs_res = conflux_link_rx.await.unwrap().unwrap();
3026            assert!(conflux_hs_res.iter().all(|res| res.is_ok()));
3027
3028            // Send a valid SWITCH cell on the first leg.
3029            let switch1 = relaymsg::ConfluxSwitch::new(10);
3030            let msg = rmsg_to_ccmsg(None, switch1.into(), false);
3031            circ1.circ_tx.send(msg).await.unwrap();
3032
3033            // The tunnel should not be shutting down
3034            rt.advance_until_stalled().await;
3035            assert!(!tunnel.is_closed());
3036
3037            // Send another valid SWITCH cell on the same leg.
3038            let switch2 = relaymsg::ConfluxSwitch::new(12);
3039            let msg = rmsg_to_ccmsg(None, switch2.into(), false);
3040            circ1.circ_tx.send(msg).await.unwrap();
3041
3042            // The tunnel should now be shutting down
3043            // (consecutive switches are not allowed)
3044            rt.advance_until_stalled().await;
3045            assert!(tunnel.is_closed());
3046        });
3047    }
3048
3049    // This test ensures CtrlMsg::ShutdownAndReturnCircuit returns an
3050    // error when called on a multi-path tunnel
3051    #[traced_test]
3052    #[test]
3053    #[cfg(feature = "conflux")]
3054    fn shutdown_and_return_circ_multipath() {
3055        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
3056            let TestTunnelCtx {
3057                tunnel,
3058                circs,
3059                conflux_link_rx: _,
3060            } = setup_good_conflux_tunnel(&rt, build_cc_vegas_params()).await;
3061
3062            rt.progress_until_stalled().await;
3063
3064            let (answer_tx, answer_rx) = oneshot::channel();
3065            tunnel
3066                .circ
3067                .command
3068                .unbounded_send(CtrlCmd::ShutdownAndReturnCircuit { answer: answer_tx })
3069                .unwrap();
3070
3071            // map explicitly returns () for clarity
3072            #[allow(clippy::unused_unit, clippy::semicolon_if_nothing_returned)]
3073            let err = answer_rx
3074                .await
3075                .unwrap()
3076                .map(|_| {
3077                    // Map to () so we can call unwrap
3078                    // (Circuit doesn't impl debug)
3079                    ()
3080                })
3081                .unwrap_err();
3082
3083            const MSG: &str = "not a single leg conflux set (got at least 2 elements when exactly one was expected)";
3084            assert!(err.to_string().contains(MSG), "{err}");
3085
3086            // The tunnel reactor should be shutting down,
3087            // regardless of the error
3088            rt.progress_until_stalled().await;
3089            assert!(tunnel.is_closed());
3090
3091            // Keep circs alive, to prevent the reactor
3092            // from shutting down prematurely
3093            drop(circs);
3094        });
3095    }
3096
3097    /// Run a conflux test endpoint.
3098    #[cfg(feature = "conflux")]
3099    #[derive(Debug)]
3100    enum ConfluxTestEndpoint<I: Iterator<Item = Option<Duration>>> {
3101        /// Pretend to be an exit relay.
3102        Relay(ConfluxExitState<I>),
3103        /// Client task.
3104        Client {
3105            /// Channel for receiving the outcome of the conflux handshakes.
3106            conflux_link_rx: oneshot::Receiver<Result<ConfluxHandshakeResult>>,
3107            /// The tunnel reactor handle
3108            tunnel: Arc<ClientTunnel>,
3109            /// Data to send on a stream.
3110            send_data: Vec<u8>,
3111            /// Data we expect to receive on a stream.
3112            recv_data: Vec<u8>,
3113        },
3114    }
3115
3116    /// Structure for returning the sinks, channels, etc. that must stay
3117    /// alive until the test is complete.
3118    #[allow(unused, clippy::large_enum_variant)]
3119    #[derive(Debug)]
3120    #[cfg(feature = "conflux")]
3121    enum ConfluxEndpointResult {
3122        Circuit {
3123            tunnel: Arc<ClientTunnel>,
3124            stream: DataStream,
3125        },
3126        Relay {
3127            circ: TestCircuitCtx,
3128        },
3129    }
3130
3131    /// Stream data, shared by all the mock exit endpoints.
3132    #[derive(Debug)]
3133    #[cfg(feature = "conflux")]
3134    struct ConfluxStreamState {
3135        /// The data received so far on this stream (at the exit).
3136        data_recvd: Vec<u8>,
3137        /// The total amount of data we expect to receive on this stream.
3138        expected_data_len: usize,
3139        /// Whether we have seen a BEGIN cell yet.
3140        begin_recvd: bool,
3141        /// Whether we have seen an END cell yet.
3142        end_recvd: bool,
3143        /// Whether we have sent an END cell yet.
3144        end_sent: bool,
3145    }
3146
3147    #[cfg(feature = "conflux")]
3148    impl ConfluxStreamState {
3149        fn new(expected_data_len: usize) -> Self {
3150            Self {
3151                data_recvd: vec![],
3152                expected_data_len,
3153                begin_recvd: false,
3154                end_recvd: false,
3155                end_sent: false,
3156            }
3157        }
3158    }
3159
3160    /// An object describing a SWITCH cell that we expect to receive
3161    /// in the mock exit
3162    #[derive(Debug)]
3163    #[cfg(feature = "conflux")]
3164    struct ExpectedSwitch {
3165        /// The number of cells we've seen on this leg so far,
3166        /// up to and including the SWITCH.
3167        cells_so_far: usize,
3168        /// The expected seqno in SWITCH cell,
3169        seqno: u32,
3170    }
3171
3172    /// Object dispatching cells for delivery on the appropriate
3173    /// leg in a multipath tunnel.
3174    ///
3175    /// Used to send out-of-order cells from the mock exit
3176    /// to the client under test.
3177    #[cfg(feature = "conflux")]
3178    struct CellDispatcher {
3179        /// Channels on which to send the [`CellToSend`] commands on.
3180        leg_tx: HashMap<UniqId, mpsc::Sender<CellToSend>>,
3181        /// The list of cells to send,
3182        cells_to_send: Vec<(UniqId, AnyRelayMsg)>,
3183    }
3184
3185    #[cfg(feature = "conflux")]
3186    impl CellDispatcher {
3187        async fn run(mut self) {
3188            while !self.cells_to_send.is_empty() {
3189                let (circ_id, cell) = self.cells_to_send.remove(0);
3190                let cell_tx = self.leg_tx.get_mut(&circ_id).unwrap();
3191                let (done_tx, done_rx) = oneshot::channel();
3192                cell_tx.send(CellToSend { done_tx, cell }).await.unwrap();
3193                // Wait for the cell to be sent before sending the next one.
3194                let () = done_rx.await.unwrap();
3195            }
3196        }
3197    }
3198
3199    /// A cell for the mock exit to send on one of its legs.
3200    #[cfg(feature = "conflux")]
3201    #[derive(Debug)]
3202    struct CellToSend {
3203        /// Channel for notifying the control task that the cell was sent.
3204        done_tx: oneshot::Sender<()>,
3205        /// The cell to send.
3206        cell: AnyRelayMsg,
3207    }
3208
3209    /// The state of a mock exit.
3210    #[derive(Debug)]
3211    #[cfg(feature = "conflux")]
3212    struct ConfluxExitState<I: Iterator<Item = Option<Duration>>> {
3213        /// The runtime, shared by the test client and mock exit tasks.
3214        ///
3215        /// The mutex prevents the client and mock exit tasks from calling
3216        /// functions like [`MockRuntime::advance_until_stalled`]
3217        /// or [`MockRuntime::progress_until_stalled]` concurrently,
3218        /// as this is not supported by the mock runtime.
3219        runtime: Arc<AsyncMutex<MockRuntime>>,
3220        /// The client view of the tunnel.
3221        tunnel: Arc<ClientTunnel>,
3222        /// The circuit test context.
3223        circ: TestCircuitCtx,
3224        /// The RTT delay to introduce just before each SENDME.
3225        ///
3226        /// Used to trigger the client to send a SWITCH.
3227        rtt_delays: I,
3228        /// State of the (only) expected stream on this tunnel,
3229        /// shared by all the mock exit endpoints.
3230        stream_state: Arc<Mutex<ConfluxStreamState>>,
3231        /// The number of cells after which to expect a SWITCH
3232        /// cell from the client.
3233        expect_switch: Vec<ExpectedSwitch>,
3234        /// Channel for receiving notifications from the other leg.
3235        event_rx: mpsc::Receiver<MockExitEvent>,
3236        /// Channel for sending notifications to the other leg.
3237        event_tx: mpsc::Sender<MockExitEvent>,
3238        /// Whether this circuit leg should act as the primary (sending) leg.
3239        is_sending_leg: bool,
3240        /// A channel for receiving cells to send on this stream.
3241        cells_rx: mpsc::Receiver<CellToSend>,
3242    }
3243
3244    #[cfg(feature = "conflux")]
3245    async fn good_exit_handshake(
3246        runtime: &Arc<AsyncMutex<MockRuntime>>,
3247        init_rtt_delay: Option<Duration>,
3248        rx: &mut Receiver<ChanCell<AnyChanMsg>>,
3249        sink: &mut CircuitRxSender,
3250    ) {
3251        // Wait for the LINK cell
3252        let link = await_link_payload(rx).await;
3253
3254        // Introduce an artificial delay, to make one circ have a better initial RTT
3255        // than the other
3256        if let Some(init_rtt_delay) = init_rtt_delay {
3257            runtime.lock().await.advance_by(init_rtt_delay).await;
3258        }
3259
3260        // Reply with a LINKED cell...
3261        let linked = relaymsg::ConfluxLinked::new(link.payload().clone()).into();
3262        sink.send(rmsg_to_ccmsg(None, linked, false)).await.unwrap();
3263
3264        // Wait for the client to respond with LINKED_ACK...
3265        let (_id, chmsg) = rx.next().await.unwrap().into_circid_and_msg();
3266        let rmsg = match chmsg {
3267            AnyChanMsg::Relay(r) => {
3268                AnyRelayMsgOuter::decode_singleton(RelayCellFormat::V0, r.into_relay_body())
3269                    .unwrap()
3270            }
3271            other => panic!("{other:?}"),
3272        };
3273        let (_streamid, rmsg) = rmsg.into_streamid_and_msg();
3274
3275        assert_matches!(rmsg, AnyRelayMsg::ConfluxLinkedAck(_));
3276    }
3277
3278    /// An event sent by one mock conflux leg to another.
3279    #[derive(Copy, Clone, Debug)]
3280    enum MockExitEvent {
3281        /// Inform the other leg we are done.
3282        Done,
3283        /// Inform the other leg a stream was opened.
3284        BeginRecvd(StreamId),
3285    }
3286
3287    #[cfg(feature = "conflux")]
3288    async fn run_mock_conflux_exit<I: Iterator<Item = Option<Duration>>>(
3289        state: ConfluxExitState<I>,
3290    ) -> ConfluxEndpointResult {
3291        let ConfluxExitState {
3292            runtime,
3293            tunnel,
3294            mut circ,
3295            rtt_delays,
3296            stream_state,
3297            mut expect_switch,
3298            mut event_tx,
3299            mut event_rx,
3300            is_sending_leg,
3301            mut cells_rx,
3302        } = state;
3303
3304        let mut rtt_delays = rtt_delays.into_iter();
3305
3306        // Expect the client to open a stream, and de-multiplex the received stream data
3307        let stream_len = stream_state.lock().unwrap().expected_data_len;
3308        let mut data_cells_received = 0_usize;
3309        let mut cell_count = 0_usize;
3310        let mut tags = vec![];
3311        let mut streamid = None;
3312        let mut done_writing = false;
3313
3314        loop {
3315            let should_exit = {
3316                let stream_state = stream_state.lock().unwrap();
3317                let done_reading = stream_state.data_recvd.len() >= stream_len;
3318
3319                (stream_state.begin_recvd || stream_state.end_recvd) && done_reading && done_writing
3320            };
3321
3322            if should_exit {
3323                break;
3324            }
3325
3326            use futures::select;
3327
3328            // Only start reading from the dispatcher channel after the stream is open
3329            // and we're ready to start sending cells.
3330            let mut next_cell = if streamid.is_some() && !done_writing {
3331                Box::pin(cells_rx.next().fuse())
3332                    as Pin<Box<dyn FusedFuture<Output = Option<CellToSend>> + Send>>
3333            } else {
3334                Box::pin(std::future::pending().fuse())
3335            };
3336
3337            // Wait for the BEGIN cell to arrive, or for the transfer to complete
3338            // (we need to bail if the other leg already completed);
3339            let res = select! {
3340                res = circ.chan_rx.next() => {
3341                    res.unwrap()
3342                },
3343                res = event_rx.next() => {
3344                    let Some(event) = res else {
3345                        break;
3346                    };
3347
3348                    match event {
3349                        MockExitEvent::Done => {
3350                            break;
3351                        },
3352                        MockExitEvent::BeginRecvd(id) => {
3353                            // The stream is now open (the other leg received the BEGIN),
3354                            // so we're reading to start reading cells from the cell dispatcher.
3355                            streamid = Some(id);
3356                            continue;
3357                        },
3358                    }
3359                }
3360                res = next_cell => {
3361                    if let Some(cell_to_send) = res {
3362                        let CellToSend { cell, done_tx } = cell_to_send;
3363
3364                        // SWITCH cells don't have a stream ID
3365                        let streamid = if matches!(cell, AnyRelayMsg::ConfluxSwitch(_)) {
3366                            None
3367                        } else {
3368                            streamid
3369                        };
3370
3371                        circ.circ_tx
3372                            .send(rmsg_to_ccmsg(streamid, cell, false))
3373                            .await
3374                            .unwrap();
3375
3376                        runtime.lock().await.advance_until_stalled().await;
3377                        done_tx.send(()).unwrap();
3378                    } else {
3379                        done_writing = true;
3380                    }
3381
3382                    continue;
3383                }
3384            };
3385
3386            let (_id, chmsg) = res.into_circid_and_msg();
3387            cell_count += 1;
3388            let rmsg = match chmsg {
3389                AnyChanMsg::Relay(r) => {
3390                    AnyRelayMsgOuter::decode_singleton(RelayCellFormat::V0, r.into_relay_body())
3391                        .unwrap()
3392                }
3393                other => panic!("{:?}", other),
3394            };
3395            let (new_streamid, rmsg) = rmsg.into_streamid_and_msg();
3396            if streamid.is_none() {
3397                streamid = new_streamid;
3398            }
3399
3400            let begin_recvd = stream_state.lock().unwrap().begin_recvd;
3401            let end_recvd = stream_state.lock().unwrap().end_recvd;
3402            match rmsg {
3403                AnyRelayMsg::Begin(_) if begin_recvd => {
3404                    panic!("client tried to open two streams?!");
3405                }
3406                AnyRelayMsg::Begin(_) if !begin_recvd => {
3407                    stream_state.lock().unwrap().begin_recvd = true;
3408                    // Reply with a connected cell...
3409                    let connected = relaymsg::Connected::new_empty().into();
3410                    circ.circ_tx
3411                        .send(rmsg_to_ccmsg(streamid, connected, false))
3412                        .await
3413                        .unwrap();
3414                    // Tell the other leg we received a BEGIN cell
3415                    event_tx
3416                        .send(MockExitEvent::BeginRecvd(streamid.unwrap()))
3417                        .await
3418                        .unwrap();
3419                }
3420                AnyRelayMsg::End(_) if !end_recvd => {
3421                    stream_state.lock().unwrap().end_recvd = true;
3422                    break;
3423                }
3424                AnyRelayMsg::End(_) if end_recvd => {
3425                    panic!("received two END cells for the same stream?!");
3426                }
3427                AnyRelayMsg::ConfluxSwitch(cell) => {
3428                    // Ensure we got the SWITCH after the expected number of cells
3429                    let expected = expect_switch.remove(0);
3430
3431                    assert_eq!(expected.cells_so_far, cell_count);
3432                    assert_eq!(expected.seqno, cell.seqno());
3433
3434                    // To keep the tests simple, we don't handle out of order cells,
3435                    // and simply sort the received data at the end.
3436                    // This ensures all the data was actually received,
3437                    // but it doesn't actually test that the SWITCH cells
3438                    // contain the appropriate seqnos.
3439                    continue;
3440                }
3441                AnyRelayMsg::Data(dat) => {
3442                    data_cells_received += 1;
3443                    stream_state
3444                        .lock()
3445                        .unwrap()
3446                        .data_recvd
3447                        .extend_from_slice(dat.as_ref());
3448
3449                    let is_next_cell_sendme = data_cells_received.is_multiple_of(31);
3450                    if is_next_cell_sendme {
3451                        if tags.is_empty() {
3452                            // Important: we need to make sure all the SENDMEs
3453                            // we sent so far have been processed by the reactor
3454                            // (otherwise the next QuerySendWindow call
3455                            // might return an outdated list of tags!)
3456                            runtime.lock().await.advance_until_stalled().await;
3457                            let (tx, rx) = oneshot::channel();
3458                            tunnel
3459                                .circ
3460                                .command
3461                                .unbounded_send(CtrlCmd::QuerySendWindow {
3462                                    hop: 2.into(),
3463                                    leg: circ.unique_id,
3464                                    done: tx,
3465                                })
3466                                .unwrap();
3467
3468                            // Get a fresh batch of tags.
3469                            let (_window, new_tags) = rx.await.unwrap().unwrap();
3470                            tags = new_tags;
3471                        }
3472
3473                        let tag = tags.remove(0);
3474
3475                        // Introduce an artificial delay, to make one circ have worse RTT
3476                        // than the other, and thus trigger a SWITCH
3477                        if let Some(rtt_delay) = rtt_delays.next().flatten() {
3478                            runtime.lock().await.advance_by(rtt_delay).await;
3479                        }
3480                        // Make and send a circuit-level SENDME
3481                        let sendme = relaymsg::Sendme::from(tag).into();
3482
3483                        circ.circ_tx
3484                            .send(rmsg_to_ccmsg(None, sendme, false))
3485                            .await
3486                            .unwrap();
3487                    }
3488                }
3489                _ => panic!("unexpected message {rmsg:?} on leg {}", circ.unique_id),
3490            }
3491        }
3492
3493        let end_recvd = stream_state.lock().unwrap().end_recvd;
3494
3495        // Close the stream if the other endpoint hasn't already done so
3496        if is_sending_leg && !end_recvd {
3497            let end = relaymsg::End::new_with_reason(relaymsg::EndReason::DONE).into();
3498            circ.circ_tx
3499                .send(rmsg_to_ccmsg(streamid, end, false))
3500                .await
3501                .unwrap();
3502            stream_state.lock().unwrap().end_sent = true;
3503        }
3504
3505        // This is allowed to fail, because the other leg might have exited first.
3506        let _ = event_tx.send(MockExitEvent::Done).await;
3507
3508        // Ensure we received all the switch cells we were expecting
3509        assert!(
3510            expect_switch.is_empty(),
3511            "expect_switch = {expect_switch:?}"
3512        );
3513
3514        ConfluxEndpointResult::Relay { circ }
3515    }
3516
3517    #[cfg(feature = "conflux")]
3518    async fn run_conflux_client(
3519        tunnel: Arc<ClientTunnel>,
3520        conflux_link_rx: oneshot::Receiver<Result<ConfluxHandshakeResult>>,
3521        send_data: Vec<u8>,
3522        recv_data: Vec<u8>,
3523    ) -> ConfluxEndpointResult {
3524        let res = conflux_link_rx.await;
3525
3526        let res = res.unwrap().unwrap();
3527        assert_eq!(res.len(), 2);
3528
3529        // All circuit legs have completed the conflux handshake,
3530        // so we now have a multipath tunnel
3531
3532        // Now we're ready to open a stream
3533        let mut stream = tunnel
3534            .begin_stream("www.example.com", 443, None)
3535            .await
3536            .unwrap();
3537
3538        stream.write_all(&send_data).await.unwrap();
3539        stream.flush().await.unwrap();
3540
3541        let mut recv: Vec<u8> = Vec::new();
3542        let recv_len = stream.read_to_end(&mut recv).await.unwrap();
3543        assert_eq!(recv_len, recv_data.len());
3544        assert_eq!(recv_data, recv);
3545
3546        ConfluxEndpointResult::Circuit { tunnel, stream }
3547    }
3548
3549    #[cfg(feature = "conflux")]
3550    async fn run_conflux_endpoint<I: Iterator<Item = Option<Duration>>>(
3551        endpoint: ConfluxTestEndpoint<I>,
3552    ) -> ConfluxEndpointResult {
3553        match endpoint {
3554            ConfluxTestEndpoint::Relay(state) => run_mock_conflux_exit(state).await,
3555            ConfluxTestEndpoint::Client {
3556                tunnel,
3557                conflux_link_rx,
3558                send_data,
3559                recv_data,
3560            } => run_conflux_client(tunnel, conflux_link_rx, send_data, recv_data).await,
3561        }
3562    }
3563
3564    // In this test, a `ConfluxTestEndpoint::Client` task creates a multipath tunnel
3565    // with 2 legs, opens a stream and sends 300 DATA cells on it.
3566    //
3567    // The test spawns two `ConfluxTestEndpoint::Relay` tasks (one for each leg),
3568    // which mock the behavior of an exit. The two relay tasks introduce
3569    // artificial delays before each SENDME sent to the client,
3570    // in order to trigger it to switch its sending leg predictably.
3571    //
3572    // The mock exit does not send any data on the stream.
3573    //
3574    // This test checks that the client sends SWITCH cells at the right time,
3575    // and that all the data it sent over the stream arrived at the exit.
3576    //
3577    // Note, however, that it doesn't check that the client sends the data in
3578    // the right order. For simplicity, the test concatenates the data received
3579    // on both legs, sorts it, and then compares it against the of the data sent
3580    // by the client (TODO: improve this)
3581    #[traced_test]
3582    #[test]
3583    #[cfg(feature = "conflux")]
3584    fn multipath_client_to_exit() {
3585        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
3586            /// The number of data cells to send.
3587            const NUM_CELLS: usize = 300;
3588            /// 498 bytes per DATA cell.
3589            const CELL_SIZE: usize = 498;
3590
3591            let TestTunnelCtx {
3592                tunnel,
3593                circs,
3594                conflux_link_rx,
3595            } = setup_good_conflux_tunnel(&rt, build_cc_vegas_params()).await;
3596            let [circ1, circ2]: [TestCircuitCtx; 2] = circs.try_into().unwrap();
3597
3598            // The stream data we're going to send over the conflux tunnel
3599            let mut send_data = (0..255_u8)
3600                .cycle()
3601                .take(NUM_CELLS * CELL_SIZE)
3602                .collect::<Vec<_>>();
3603            let stream_state = Arc::new(Mutex::new(ConfluxStreamState::new(send_data.len())));
3604
3605            let mut tasks = vec![];
3606
3607            // Channels used by the mock relays to notify each other
3608            // of various events.
3609            let (tx1, rx1) = mpsc::channel(1);
3610            let (tx2, rx2) = mpsc::channel(1);
3611
3612            // The 9 RTT delays to insert before each of the 9 SENDMEs
3613            // the exit will end up sending.
3614            //
3615            // Note: the first delay is the init_rtt delay (measured during the conflux HS).
3616            let circ1_rtt_delays = [
3617                // Initially, circ1 has better RTT, so we will start on this leg.
3618                Some(Duration::from_millis(100)),
3619                // But then its RTT takes a turn for the worse,
3620                // triggering a switch after the first SENDME is processed
3621                // (this happens after sending 123 DATA cells).
3622                Some(Duration::from_millis(500)),
3623                Some(Duration::from_millis(700)),
3624                Some(Duration::from_millis(900)),
3625                Some(Duration::from_millis(1100)),
3626                Some(Duration::from_millis(1300)),
3627                Some(Duration::from_millis(1500)),
3628                Some(Duration::from_millis(1700)),
3629                Some(Duration::from_millis(1900)),
3630                Some(Duration::from_millis(2100)),
3631            ]
3632            .into_iter();
3633
3634            let circ2_rtt_delays = [
3635                Some(Duration::from_millis(200)),
3636                Some(Duration::from_millis(400)),
3637                Some(Duration::from_millis(600)),
3638                Some(Duration::from_millis(800)),
3639                Some(Duration::from_millis(1000)),
3640                Some(Duration::from_millis(1200)),
3641                Some(Duration::from_millis(1400)),
3642                Some(Duration::from_millis(1600)),
3643                Some(Duration::from_millis(1800)),
3644                Some(Duration::from_millis(2000)),
3645            ]
3646            .into_iter();
3647
3648            let expected_switches1 = vec![ExpectedSwitch {
3649                // We start on this leg, and receive a BEGIN cell,
3650                // followed by (4 * 31 - 1) = 123 DATA cells.
3651                // Then it becomes blocked on CC, then finally the reactor
3652                // realizes it has some SENDMEs to process, and
3653                // then as a result of the new RTT measurement, we switch to circ1,
3654                // and then finally we switch back here, and get another SWITCH
3655                // as the 126th cell.
3656                cells_so_far: 126,
3657                // Leg 2 switches back to this leg after the 249th cell
3658                // (just before sending the 250th one):
3659                // seqno = 125 carried over from leg 1 (see the seqno of the
3660                // SWITCH expected on leg 2 below), plus 1 SWITCH, plus
3661                // 4 * 31 = 124 DATA cells after which the RTT of the first leg
3662                // is deemed favorable again.
3663                //
3664                // 249 - 125 (last_seq_sent of leg 1) = 124
3665                seqno: 124,
3666            }];
3667
3668            let expected_switches2 = vec![ExpectedSwitch {
3669                // The SWITCH is the first cell we received after the conflux HS
3670                // on this leg.
3671                cells_so_far: 1,
3672                // See explanation on the ExpectedSwitch from circ1 above.
3673                seqno: 125,
3674            }];
3675
3676            let relay_runtime = Arc::new(AsyncMutex::new(rt.clone()));
3677
3678            // Drop the senders and close the channels,
3679            // we have nothing to send in this test.
3680            let (_, cells_rx1) = mpsc::channel(1);
3681            let (_, cells_rx2) = mpsc::channel(1);
3682
3683            let relay1 = ConfluxExitState {
3684                runtime: Arc::clone(&relay_runtime),
3685                tunnel: Arc::clone(&tunnel),
3686                circ: circ1,
3687                rtt_delays: circ1_rtt_delays,
3688                stream_state: Arc::clone(&stream_state),
3689                expect_switch: expected_switches1,
3690                event_tx: tx1,
3691                event_rx: rx2,
3692                is_sending_leg: true,
3693                cells_rx: cells_rx1,
3694            };
3695
3696            let relay2 = ConfluxExitState {
3697                runtime: Arc::clone(&relay_runtime),
3698                tunnel: Arc::clone(&tunnel),
3699                circ: circ2,
3700                rtt_delays: circ2_rtt_delays,
3701                stream_state: Arc::clone(&stream_state),
3702                expect_switch: expected_switches2,
3703                event_tx: tx2,
3704                event_rx: rx1,
3705                is_sending_leg: false,
3706                cells_rx: cells_rx2,
3707            };
3708
3709            for mut mock_relay in [relay1, relay2] {
3710                let leg = mock_relay.circ.unique_id;
3711
3712                // Do the conflux handshake
3713                //
3714                // We do this outside of run_conflux_endpoint,
3715                // toa void running both handshakes at concurrently
3716                // (this gives more predictable RTT delays:
3717                // if both handshake tasks run at once, they race
3718                // to advance the mock runtime's clock)
3719                good_exit_handshake(
3720                    &relay_runtime,
3721                    mock_relay.rtt_delays.next().flatten(),
3722                    &mut mock_relay.circ.chan_rx,
3723                    &mut mock_relay.circ.circ_tx,
3724                )
3725                .await;
3726
3727                let relay = ConfluxTestEndpoint::Relay(mock_relay);
3728
3729                tasks.push(rt.spawn_join(format!("relay task {leg}"), run_conflux_endpoint(relay)));
3730            }
3731
3732            tasks.push(rt.spawn_join(
3733                "client task".to_string(),
3734                run_conflux_endpoint(ConfluxTestEndpoint::Client {
3735                    tunnel,
3736                    conflux_link_rx,
3737                    send_data: send_data.clone(),
3738                    recv_data: vec![],
3739                }),
3740            ));
3741            let _sinks = futures::future::join_all(tasks).await;
3742            let mut stream_state = stream_state.lock().unwrap();
3743            assert!(stream_state.begin_recvd);
3744
3745            stream_state.data_recvd.sort();
3746            send_data.sort();
3747            assert_eq!(stream_state.data_recvd, send_data);
3748        });
3749    }
3750
3751    // In this test, a `ConfluxTestEndpoint::Client` task creates a multipath tunnel
3752    // with 2 legs, opens a stream and reads from the stream until the stream is closed.
3753    //
3754    // The test spawns two `ConfluxTestEndpoint::Relay` tasks (one for each leg),
3755    // which mock the behavior of an exit. The two tasks send DATA and SWITCH
3756    // cells on the two circuit "legs" such that some cells arrive out of order.
3757    // This forces the client to buffer some cells, and then reorder them when
3758    // the missing cells finally arrive.
3759    //
3760    // The client does not send any data on the stream.
3761    #[cfg(feature = "conflux")]
3762    async fn run_multipath_exit_to_client_test(
3763        rt: MockRuntime,
3764        tunnel: TestTunnelCtx,
3765        cells_to_send: Vec<(UniqId, AnyRelayMsg)>,
3766        send_data: Vec<u8>,
3767        recv_data: Vec<u8>,
3768    ) -> Arc<Mutex<ConfluxStreamState>> {
3769        let TestTunnelCtx {
3770            tunnel,
3771            circs,
3772            conflux_link_rx,
3773        } = tunnel;
3774        let [circ1, circ2]: [TestCircuitCtx; 2] = circs.try_into().unwrap();
3775
3776        let stream_state = Arc::new(Mutex::new(ConfluxStreamState::new(send_data.len())));
3777
3778        let mut tasks = vec![];
3779        let relay_runtime = Arc::new(AsyncMutex::new(rt.clone()));
3780        let (cells_tx1, cells_rx1) = mpsc::channel(1);
3781        let (cells_tx2, cells_rx2) = mpsc::channel(1);
3782
3783        let dispatcher = CellDispatcher {
3784            leg_tx: [(circ1.unique_id, cells_tx1), (circ2.unique_id, cells_tx2)]
3785                .into_iter()
3786                .collect(),
3787            cells_to_send,
3788        };
3789
3790        // Channels used by the mock relays to notify each other
3791        // of various events.
3792        let (tx1, rx1) = mpsc::channel(1);
3793        let (tx2, rx2) = mpsc::channel(1);
3794
3795        let relay1 = ConfluxExitState {
3796            runtime: Arc::clone(&relay_runtime),
3797            tunnel: Arc::clone(&tunnel),
3798            circ: circ1,
3799            rtt_delays: [].into_iter(),
3800            stream_state: Arc::clone(&stream_state),
3801            // Expect no SWITCH cells from the client
3802            expect_switch: vec![],
3803            event_tx: tx1,
3804            event_rx: rx2,
3805            is_sending_leg: false,
3806            cells_rx: cells_rx1,
3807        };
3808
3809        let relay2 = ConfluxExitState {
3810            runtime: Arc::clone(&relay_runtime),
3811            tunnel: Arc::clone(&tunnel),
3812            circ: circ2,
3813            rtt_delays: [].into_iter(),
3814            stream_state: Arc::clone(&stream_state),
3815            // Expect no SWITCH cells from the client
3816            expect_switch: vec![],
3817            event_tx: tx2,
3818            event_rx: rx1,
3819            is_sending_leg: true,
3820            cells_rx: cells_rx2,
3821        };
3822
3823        // Run the cell dispatcher, which tells each exit leg task
3824        // what cells to write.
3825        //
3826        // This enables us to write out-of-order cells deterministically.
3827        rt.spawn(dispatcher.run()).unwrap();
3828
3829        for mut mock_relay in [relay1, relay2] {
3830            let leg = mock_relay.circ.unique_id;
3831
3832            good_exit_handshake(
3833                &relay_runtime,
3834                mock_relay.rtt_delays.next().flatten(),
3835                &mut mock_relay.circ.chan_rx,
3836                &mut mock_relay.circ.circ_tx,
3837            )
3838            .await;
3839
3840            let relay = ConfluxTestEndpoint::Relay(mock_relay);
3841
3842            tasks.push(rt.spawn_join(format!("relay task {leg}"), run_conflux_endpoint(relay)));
3843        }
3844
3845        tasks.push(rt.spawn_join(
3846            "client task".to_string(),
3847            run_conflux_endpoint(ConfluxTestEndpoint::Client {
3848                tunnel,
3849                conflux_link_rx,
3850                send_data: send_data.clone(),
3851                recv_data,
3852            }),
3853        ));
3854
3855        // Wait for all the tasks to complete
3856        let _sinks = futures::future::join_all(tasks).await;
3857
3858        stream_state
3859    }
3860
3861    #[traced_test]
3862    #[test]
3863    #[cfg(feature = "conflux")]
3864    fn multipath_exit_to_client() {
3865        // The data we expect the client to read from the stream
3866        const TO_SEND: &[u8] =
3867            b"But something about Buster Friendly irritated John Isidore, one specific thing";
3868
3869        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
3870            // The indices of the tunnel legs.
3871            const CIRC1: usize = 0;
3872            const CIRC2: usize = 1;
3873
3874            // The client receives the following cells, in the order indicated
3875            // by the t0-t8 "timestamps" (where C = CONNECTED, D = DATA, E = END,
3876            // S = SWITCH):
3877            //
3878            //  Leg 1 (CIRC1):   -----------D--------------------- D -- D -- C
3879            //                              |                      |    |    | \
3880            //                              |                      |    |    |  v
3881            //                              |                      |    |    | client
3882            //                              |                      |    |    |  ^
3883            //                              |                      |    |    |/
3884            //  Leg 2 (CIRC2): E - D -- D --\--- D* -- S (seqno=4)-/----/----/
3885            //                 |   |    |   |    |       |         |    |    |
3886            //                 |   |    |   |    |       |         |    |    |
3887            //                 |   |    |   |    |       |         |    |    |
3888            //  Time:          t8  t7   t6  t5   t4      t3        t2   t1  t0
3889            //
3890            //
3891            //  The cells marked with * are out of order.
3892            //
3893            // Note: t0 is the time when the client receives the first cell,
3894            // and t8 is the time when it receives the last one.
3895            // In other words, this test simulates a mock exit that "sent" the cells
3896            // in the order t0, t1, t2, t5, t4, t6, t7, t8
3897            let simple_switch = vec![
3898                (CIRC1, relaymsg::Data::new(&TO_SEND[0..5]).unwrap().into()),
3899                (CIRC1, relaymsg::Data::new(&TO_SEND[5..10]).unwrap().into()),
3900                // Switch to sending on the second leg
3901                (CIRC2, relaymsg::ConfluxSwitch::new(4).into()),
3902                // An out of order cell!
3903                (CIRC2, relaymsg::Data::new(&TO_SEND[20..30]).unwrap().into()),
3904                // The missing cell (as indicated by seqno = 4 from the switch cell above)
3905                // is finally arriving on leg1
3906                (CIRC1, relaymsg::Data::new(&TO_SEND[10..20]).unwrap().into()),
3907                (CIRC2, relaymsg::Data::new(&TO_SEND[30..40]).unwrap().into()),
3908                (CIRC2, relaymsg::Data::new(&TO_SEND[40..]).unwrap().into()),
3909            ];
3910
3911            //  Leg 1 (CIRC1): ---------------- D  ------D* --- S(seqno = 3) -- D - D ---------------------------- C
3912            //                                  |        |          |           |   |                              | \
3913            //                                  |        |          |           |   |                              |  v
3914            //                                  |        |          |           |   |                              |  client
3915            //                                  |        |          |           |   |                              |  ^
3916            //                                  |        |          |           |   |                              | /
3917            //  Leg 2 (CIRC2): E - S(seqno = 2) \ -- D --\----------\---------- \ --\--- D* -- D* - S(seqno = 3) --/
3918            //                 |        |       |    |   |          |           |   |    |     |         |         |
3919            //                 |        |       |    |   |          |           |   |    |     |         |         |
3920            //                 |        |       |    |   |          |           |   |    |     |         |         |
3921            //  Time:          t11      t10     t9   t8  t7         t6          t5  t4   t3    t2        t1        t0
3922            //  =====================================================================================================
3923            //  Leg 1 LSR:      8        8      8 7  7   7          6           3   2    1      1        1         1
3924            //  Leg 2 LSR:      9        8      6 6  6   5          5           5   5    5      4        3         0
3925            //  LSD:            9        8      8 7  6   5          5       5   3   2    1      1        1         1
3926            //                                    ^ OOO cell is delivered   ^ the OOO cells are delivered to the stream
3927            //
3928            //
3929            //  (LSR = last seq received, LSD = last seq delivered, both from the client's POV)
3930            //
3931            //
3932            // The client keeps track of the `last_seqno_received` (LSR) on each leg.
3933            // This is incremented for each cell that counts towards the seqnos (BEGIN, DATA, etc.)
3934            // that is received on the leg. The client also tracks the `last_seqno_delivered` (LSD),
3935            // which is the seqno of the last cell delivered to a stream
3936            // (this is global for the whole tunnel, whereas the LSR is different for each leg).
3937            //
3938            // When switching to leg `N`, the seqno in the switch is, from the POV of the sender,
3939            // the delta between the absolute seqno (i.e. the total number of cells[^1] sent)
3940            // and the value of this absolute seqno when leg `N` was last used.
3941            //
3942            // At the time of the first SWITCH from `t1`, the exit "sent" 3 cells:
3943            // a `CONNECTED` cell, which was received by the client at `t0`, and 2 `DATA` cells that
3944            // haven't been received yet. At this point, the exit decides to switch to leg 2,
3945            // on which it hasn't sent any cells yet, so the seqno is set to `3 - 0 = 3`.
3946            //
3947            // At `t6` when the exit sends the second switch (leg 2 -> leg 1), has "sent" 6 cells
3948            // (`C` plus the data cells that are received at `t1 - 5` and `t8`.
3949            // The seqno is `6 - 3 = 3`, because when it last sent on leg 1,
3950            // the absolute seqno was `3`.
3951            //
3952            // At `t10`, the absolute seqno is 8 (8 qualifying cells have been sent so far).
3953            // When the exit last sent on leg 2 (which we are switching to),
3954            // the absolute seqno was `6`, so the `SWITCH` cell will have `8 - 6 = 2` as the seqno.
3955            //
3956            // [^1]: only counting the cells that count towards sequence numbers
3957            let multiple_switches = vec![
3958                // Immediately switch to sending on the second leg
3959                // (indicating that we've already sent 3 cells (including the CONNECTED)
3960                (CIRC2, relaymsg::ConfluxSwitch::new(3).into()),
3961                // Two out of order cells!
3962                (CIRC2, relaymsg::Data::new(&TO_SEND[15..20]).unwrap().into()),
3963                (CIRC2, relaymsg::Data::new(&TO_SEND[20..30]).unwrap().into()),
3964                // The missing cells finally arrive on the first leg
3965                (CIRC1, relaymsg::Data::new(&TO_SEND[0..10]).unwrap().into()),
3966                (CIRC1, relaymsg::Data::new(&TO_SEND[10..15]).unwrap().into()),
3967                // Switch back to the first leg
3968                (CIRC1, relaymsg::ConfluxSwitch::new(3).into()),
3969                // OOO cell
3970                (CIRC1, relaymsg::Data::new(&TO_SEND[31..40]).unwrap().into()),
3971                // Missing cell is received
3972                (CIRC2, relaymsg::Data::new(&TO_SEND[30..31]).unwrap().into()),
3973                // The remaining cells are in-order
3974                (CIRC1, relaymsg::Data::new(&TO_SEND[40..]).unwrap().into()),
3975                // Switch right after we've sent all the data we had to send
3976                (CIRC2, relaymsg::ConfluxSwitch::new(2).into()),
3977            ];
3978
3979            // TODO: give these tests the ability to control when END cells are sent
3980            // (currently we have ensure the is_sending_leg is set to true
3981            // on the leg that ends up sending the last data cell).
3982            //
3983            // TODO: test the edge cases
3984            let tests = [simple_switch, multiple_switches];
3985
3986            for cells_to_send in tests {
3987                let tunnel = setup_good_conflux_tunnel(&rt, build_cc_vegas_params()).await;
3988                assert_eq!(tunnel.circs.len(), 2);
3989                let circ_ids = [tunnel.circs[0].unique_id, tunnel.circs[1].unique_id];
3990                let cells_to_send = cells_to_send
3991                    .into_iter()
3992                    .map(|(i, cell)| (circ_ids[i], cell))
3993                    .collect();
3994
3995                // The client won't be sending any DATA cells on this stream
3996                let send_data = vec![];
3997                let stream_state = run_multipath_exit_to_client_test(
3998                    rt.clone(),
3999                    tunnel,
4000                    cells_to_send,
4001                    send_data.clone(),
4002                    TO_SEND.into(),
4003                )
4004                .await;
4005                let stream_state = stream_state.lock().unwrap();
4006                assert!(stream_state.begin_recvd);
4007                // We don't expect the client to have sent anything
4008                assert!(stream_state.data_recvd.is_empty());
4009            }
4010        });
4011    }
4012
4013    #[traced_test]
4014    #[test]
4015    #[cfg(all(feature = "conflux", feature = "hs-service"))]
4016    fn conflux_incoming_stream() {
4017        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
4018            use std::error::Error as _;
4019
4020            const EXPECTED_HOP: u8 = 1;
4021
4022            let TestTunnelCtx {
4023                tunnel,
4024                circs,
4025                conflux_link_rx,
4026            } = setup_good_conflux_tunnel(&rt, build_cc_vegas_params()).await;
4027
4028            let [mut circ1, mut circ2]: [TestCircuitCtx; 2] = circs.try_into().unwrap();
4029
4030            let link = await_link_payload(&mut circ1.chan_rx).await;
4031            for circ in [&mut circ1, &mut circ2] {
4032                let linked = relaymsg::ConfluxLinked::new(link.payload().clone()).into();
4033                circ.circ_tx
4034                    .send(rmsg_to_ccmsg(None, linked, false))
4035                    .await
4036                    .unwrap();
4037            }
4038
4039            let conflux_hs_res = conflux_link_rx.await.unwrap().unwrap();
4040            assert!(conflux_hs_res.iter().all(|res| res.is_ok()));
4041
4042            // TODO(#2002): we don't currently support conflux for onion services
4043            let err = tunnel
4044                .allow_stream_requests(
4045                    &[tor_cell::relaycell::RelayCmd::BEGIN],
4046                    (tunnel.circ.unique_id(), EXPECTED_HOP.into()).into(),
4047                    AllowAllStreamsFilter,
4048                )
4049                .await
4050                // IncomingStream doesn't impl Debug, so we need to map to a different type
4051                .map(|_| ())
4052                .unwrap_err();
4053
4054            let err_src = err.source().unwrap().to_string();
4055            assert!(
4056                err_src.contains("Cannot allow stream requests on a multi-path tunnel"),
4057                "{err_src}"
4058            );
4059        });
4060    }
4061
4062    #[test]
4063    fn client_circ_chan_msg() {
4064        use tor_cell::chancell::msg::{self, AnyChanMsg};
4065        fn good(m: AnyChanMsg) {
4066            assert!(ClientCircChanMsg::try_from(m).is_ok());
4067        }
4068        fn bad(m: AnyChanMsg) {
4069            assert!(ClientCircChanMsg::try_from(m).is_err());
4070        }
4071
4072        good(msg::Destroy::new(2.into()).into());
4073        bad(msg::CreatedFast::new(&b"guaranteed in this world"[..]).into());
4074        bad(msg::Created2::new(&b"and the next"[..]).into());
4075        good(msg::Relay::new(&b"guaranteed guaranteed"[..]).into());
4076        bad(msg::AnyChanMsg::RelayEarly(
4077            msg::Relay::new(&b"for the world and its mother"[..]).into(),
4078        ));
4079        bad(msg::Versions::new([1, 2, 3]).unwrap().into());
4080    }
4081}