Loading crates/arti-client/src/client.rs +43 −16 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ use crate::address::IntoTorAddr; use crate::config::{ClientAddrConfig, TorClientConfig}; use tor_circmgr::{IsolationToken, TargetPort}; use tor_circmgr::{IsolationToken, StreamIsolationBuilder, TargetPort}; use tor_dirmgr::DirEvent; use tor_persist::{FsStateMgr, StateMgr}; use tor_proto::circuit::{ClientCirc, IpVersionPreference}; Loading Loading @@ -36,6 +36,8 @@ use tracing::{debug, error, info, warn}; pub struct TorClient<R: Runtime> { /// Asynchronous runtime object. runtime: R, /// Default isolation token for streams through this client. client_isolation: IsolationToken, /// Circuit manager for keeping our circuits up to date and building /// them on-demand. circmgr: Arc<tor_circmgr::CircMgr<R>>, Loading @@ -46,12 +48,12 @@ pub struct TorClient<R: Runtime> { } /// Preferences for how to route a stream over the Tor network. #[derive(Debug, Clone)] #[derive(Debug, Clone, Default)] pub struct ConnectPrefs { /// What kind of IPv6/IPv4 we'd prefer, and how strongly. ip_ver_pref: IpVersionPreference, /// Id of the isolation group the connection should be part of isolation_group: IsolationToken, isolation_group: Option<IsolationToken>, } impl ConnectPrefs { Loading Loading @@ -114,28 +116,19 @@ impl ConnectPrefs { /// Indicate which other connections might use the same circuit /// as this one. pub fn set_isolation_group(&mut self, isolation_group: IsolationToken) -> &mut Self { self.isolation_group = isolation_group; self.isolation_group = Some(isolation_group); self } /// Return a u64 to describe which connections might use /// Return a token to describe which connections might use /// the same circuit as this one. fn isolation_group(&self) -> IsolationToken { fn isolation_group(&self) -> Option<IsolationToken> { self.isolation_group } // TODO: Add some way to be IPFlexible, and require exit to support both. } impl Default for ConnectPrefs { fn default() -> Self { ConnectPrefs { ip_ver_pref: Default::default(), isolation_group: IsolationToken::no_isolation(), } } } impl<R: Runtime> TorClient<R> { /// Bootstrap a network connection configured by `dir_cfg` and `circ_cfg`. /// Loading Loading @@ -190,14 +183,35 @@ impl<R: Runtime> TorClient<R> { Arc::downgrade(&dirmgr), ))?; let client_isolation = IsolationToken::new(); Ok(TorClient { runtime, client_isolation, circmgr, dirmgr, addrcfg: addr_cfg, }) } /// Return a new isolated `TorClient` instance. /// /// The two `TorClient`s will share some internal state, but their /// streams will haver share circuits with one another. /// /// Use this function when you want separate parts of your program to /// each have a TorClient handle, but where you don't want their /// activities to be linkable to one another over the Tor network. /// /// Calling this function is usually preferable to creating a /// completely separate TorClient instance, since it can share its /// internals with the existing `TorClient`. pub fn isolated_client(&self) -> TorClient<R> { let mut result = self.clone(); result.client_isolation = IsolationToken::new(); result } /// Launch an anonymized connection to the provided address and /// port over the Tor network. /// Loading Loading @@ -303,9 +317,22 @@ impl<R: Runtime> TorClient<R> { flags: &ConnectPrefs, ) -> Result<Arc<ClientCirc>> { let dir = self.dirmgr.netdir(); let isolation = { let mut b = StreamIsolationBuilder::new(); // Always consider our client_isolation. b.owner_token(self.client_isolation); // Consider stream isolation too, if it's set. if let Some(tok) = flags.isolation_group() { b.stream_token(tok); } // Failure should be impossible with this builder. b.build().expect("Failed to construct StreamIsolation") }; let circ = self .circmgr .get_or_launch_exit(dir.as_ref().into(), exit_ports, flags.isolation_group()) .get_or_launch_exit(dir.as_ref().into(), exit_ports, isolation) .await .map_err(|_| Error::Internal("Unable to launch circuit"))?; drop(dir); // This decreases the refcount on the netdir. Loading crates/tor-circmgr/src/lib.rs +3 −6 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ mod timeouts; mod usage; pub use err::Error; pub use usage::{IsolationToken, TargetPort}; pub use usage::{IsolationToken, StreamIsolation, StreamIsolationBuilder, TargetPort}; pub use config::{ CircMgrConfig, CircMgrConfigBuilder, CircuitTiming, CircuitTimingBuilder, PathConfig, Loading Loading @@ -254,14 +254,11 @@ impl<R: Runtime> CircMgr<R> { &self, netdir: DirInfo<'_>, // TODO: This has to be a NetDir. ports: &[TargetPort], isolation_group: IsolationToken, isolation: StreamIsolation, ) -> Result<Arc<ClientCirc>> { self.expire_circuits(); let ports = ports.iter().map(Clone::clone).collect(); let usage = TargetCircUsage::Exit { ports, isolation_group, }; let usage = TargetCircUsage::Exit { ports, isolation }; self.mgr.get_or_launch(&usage, netdir).await } Loading crates/tor-circmgr/src/usage.rs +88 −33 Original line number Diff line number Diff line Loading @@ -103,6 +103,43 @@ impl IsolationToken { } } /// A set of information about how a stream should be isolated. /// /// If two streams are isolated from one another, they may not share /// a circuit. #[derive(Copy, Clone, Eq, Debug, PartialEq, derive_builder::Builder)] pub struct StreamIsolation { /// Any isolation token set on the stream. #[builder(default = "IsolationToken::no_isolation()")] stream_token: IsolationToken, /// Any additional isolation token set on an object that "owns" this /// stream. This is typically owned by a `TorClient`. #[builder(default = "IsolationToken::no_isolation()")] owner_token: IsolationToken, } impl StreamIsolation { /// Construct a new StreamIsolation with no isolation enabled. pub fn no_isolation() -> Self { StreamIsolationBuilder::new() .build() .expect("Bug constructing StreamIsolation") } /// Return a new StreamIsolationBuilder for constructing /// StreamIsolation objects. pub fn builder() -> StreamIsolationBuilder { StreamIsolationBuilder::new() } } impl StreamIsolationBuilder { /// Construct a builder with no items set. pub fn new() -> Self { StreamIsolationBuilder::default() } } impl ExitPolicy { /// Make a new exit policy from a given Relay. pub(crate) fn from_relay(relay: &Relay<'_>) -> Self { Loading Loading @@ -140,7 +177,7 @@ pub(crate) enum TargetCircUsage { /// to support any particular port, but it still needs to be an exit. ports: Vec<TargetPort>, /// Isolation group the circuit shall be part of isolation_group: IsolationToken, isolation: StreamIsolation, }, /// For a circuit is only used for the purpose of building it. TimeoutTesting, Loading @@ -160,7 +197,7 @@ pub(crate) enum SupportedCircUsage { policy: ExitPolicy, /// Isolation group the circuit is part of. None when the circuit is not yet assigned to an /// isolation group. isolation_group: Option<IsolationToken>, isolation: Option<StreamIsolation>, }, /// This circuit is not suitable for any usage. NoUsage, Loading Loading @@ -188,7 +225,7 @@ impl TargetCircUsage { } TargetCircUsage::Exit { ports: p, isolation_group, isolation, } => { let (path, mon, usable) = ExitPathBuilder::from_target_ports(p.clone()) .pick_path(rng, netdir, guards, config)?; Loading @@ -199,7 +236,7 @@ impl TargetCircUsage { path, SupportedCircUsage::Exit { policy, isolation_group: Some(*isolation_group), isolation: Some(*isolation), }, mon, usable, Loading @@ -212,7 +249,7 @@ impl TargetCircUsage { let usage = match policy { Some(policy) if policy.allows_some_port() => SupportedCircUsage::Exit { policy, isolation_group: None, isolation: None, }, _ => SupportedCircUsage::NoUsage, }; Loading @@ -233,11 +270,11 @@ impl crate::mgr::AbstractSpec for SupportedCircUsage { ( Exit { policy: p1, isolation_group: i1, isolation: i1, }, TargetCircUsage::Exit { ports: p2, isolation_group: i2, isolation: i2, }, ) => { i1.map(|i1| i1 == *i2).unwrap_or(true) Loading @@ -255,13 +292,10 @@ impl crate::mgr::AbstractSpec for SupportedCircUsage { (Dir, TargetCircUsage::Dir) => Ok(()), ( Exit { isolation_group: ref mut i1, .. }, TargetCircUsage::Exit { isolation_group: i2, isolation: ref mut i1, .. }, TargetCircUsage::Exit { isolation: i2, .. }, ) if i1.map(|i1| i1 == *i2).unwrap_or(true) => { *i1 = Some(*i2); Ok(()) Loading Loading @@ -335,42 +369,50 @@ mod test { v4: Arc::new("accept 80,443".parse().unwrap()), v6: Arc::new("accept 23".parse().unwrap()), }; let isolation_group = IsolationToken::new(); let isolation_group_2 = IsolationToken::new(); let tok1 = IsolationToken::new(); let tok2 = IsolationToken::new(); let isolation = StreamIsolationBuilder::new() .owner_token(tok1) .build() .unwrap(); let isolation2 = StreamIsolationBuilder::new() .owner_token(tok2) .build() .unwrap(); let supp_dir = SupportedCircUsage::Dir; let targ_dir = TargetCircUsage::Dir; let supp_exit = SupportedCircUsage::Exit { policy: policy.clone(), isolation_group: Some(isolation_group), isolation: Some(isolation), }; let supp_exit_iso2 = SupportedCircUsage::Exit { policy: policy.clone(), isolation_group: Some(isolation_group_2), isolation: Some(isolation2), }; let supp_exit_no_iso = SupportedCircUsage::Exit { policy, isolation_group: None, isolation: None, }; let targ_80_v4 = TargetCircUsage::Exit { ports: vec![TargetPort::ipv4(80)], isolation_group, isolation, }; let targ_80_v4_iso2 = TargetCircUsage::Exit { ports: vec![TargetPort::ipv4(80)], isolation_group: isolation_group_2, isolation: isolation2, }; let targ_80_23_v4 = TargetCircUsage::Exit { ports: vec![TargetPort::ipv4(80), TargetPort::ipv4(23)], isolation_group, isolation, }; let targ_80_23_mixed = TargetCircUsage::Exit { ports: vec![TargetPort::ipv4(80), TargetPort::ipv6(23)], isolation_group, isolation, }; let targ_999_v6 = TargetCircUsage::Exit { ports: vec![TargetPort::ipv6(999)], isolation_group, isolation, }; assert!(supp_dir.supports(&targ_dir)); Loading @@ -397,30 +439,38 @@ mod test { v6: Arc::new("accept 23".parse().unwrap()), }; let isolation_group = IsolationToken::new(); let isolation_group_2 = IsolationToken::new(); let tok1 = IsolationToken::new(); let tok2 = IsolationToken::new(); let isolation = StreamIsolationBuilder::new() .owner_token(tok1) .build() .unwrap(); let isolation2 = StreamIsolationBuilder::new() .owner_token(tok2) .build() .unwrap(); let supp_dir = SupportedCircUsage::Dir; let targ_dir = TargetCircUsage::Dir; let supp_exit = SupportedCircUsage::Exit { policy: policy.clone(), isolation_group: Some(isolation_group), isolation: Some(isolation), }; let supp_exit_iso2 = SupportedCircUsage::Exit { policy: policy.clone(), isolation_group: Some(isolation_group_2), isolation: Some(isolation2), }; let supp_exit_no_iso = SupportedCircUsage::Exit { policy, isolation_group: None, isolation: None, }; let targ_exit = TargetCircUsage::Exit { ports: vec![TargetPort::ipv4(80)], isolation_group, isolation, }; let targ_exit_iso2 = TargetCircUsage::Exit { ports: vec![TargetPort::ipv4(80)], isolation_group: isolation_group_2, isolation: isolation2, }; // not allowed, do nothing Loading Loading @@ -486,10 +536,15 @@ mod test { assert!(matches!(u_dir, SupportedCircUsage::Dir)); assert_eq!(p_dir.len(), 1); let isolation_group = IsolationToken::new(); let tok1 = IsolationToken::new(); let isolation = StreamIsolationBuilder::new() .owner_token(tok1) .build() .unwrap(); let exit_usage = TargetCircUsage::Exit { ports: vec![TargetPort::ipv4(995)], isolation_group, isolation, }; let (p_exit, u_exit, _, _) = exit_usage .build_path(&mut rng, di, guards, &config) Loading @@ -497,9 +552,9 @@ mod test { assert!(matches!( u_exit, SupportedCircUsage::Exit { isolation_group: iso, isolation: iso, .. } if iso == Some(isolation_group) } if iso == Some(isolation) )); assert!(u_exit.supports(&exit_usage)); assert_eq!(p_exit.len(), 3); Loading Loading
crates/arti-client/src/client.rs +43 −16 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ use crate::address::IntoTorAddr; use crate::config::{ClientAddrConfig, TorClientConfig}; use tor_circmgr::{IsolationToken, TargetPort}; use tor_circmgr::{IsolationToken, StreamIsolationBuilder, TargetPort}; use tor_dirmgr::DirEvent; use tor_persist::{FsStateMgr, StateMgr}; use tor_proto::circuit::{ClientCirc, IpVersionPreference}; Loading Loading @@ -36,6 +36,8 @@ use tracing::{debug, error, info, warn}; pub struct TorClient<R: Runtime> { /// Asynchronous runtime object. runtime: R, /// Default isolation token for streams through this client. client_isolation: IsolationToken, /// Circuit manager for keeping our circuits up to date and building /// them on-demand. circmgr: Arc<tor_circmgr::CircMgr<R>>, Loading @@ -46,12 +48,12 @@ pub struct TorClient<R: Runtime> { } /// Preferences for how to route a stream over the Tor network. #[derive(Debug, Clone)] #[derive(Debug, Clone, Default)] pub struct ConnectPrefs { /// What kind of IPv6/IPv4 we'd prefer, and how strongly. ip_ver_pref: IpVersionPreference, /// Id of the isolation group the connection should be part of isolation_group: IsolationToken, isolation_group: Option<IsolationToken>, } impl ConnectPrefs { Loading Loading @@ -114,28 +116,19 @@ impl ConnectPrefs { /// Indicate which other connections might use the same circuit /// as this one. pub fn set_isolation_group(&mut self, isolation_group: IsolationToken) -> &mut Self { self.isolation_group = isolation_group; self.isolation_group = Some(isolation_group); self } /// Return a u64 to describe which connections might use /// Return a token to describe which connections might use /// the same circuit as this one. fn isolation_group(&self) -> IsolationToken { fn isolation_group(&self) -> Option<IsolationToken> { self.isolation_group } // TODO: Add some way to be IPFlexible, and require exit to support both. } impl Default for ConnectPrefs { fn default() -> Self { ConnectPrefs { ip_ver_pref: Default::default(), isolation_group: IsolationToken::no_isolation(), } } } impl<R: Runtime> TorClient<R> { /// Bootstrap a network connection configured by `dir_cfg` and `circ_cfg`. /// Loading Loading @@ -190,14 +183,35 @@ impl<R: Runtime> TorClient<R> { Arc::downgrade(&dirmgr), ))?; let client_isolation = IsolationToken::new(); Ok(TorClient { runtime, client_isolation, circmgr, dirmgr, addrcfg: addr_cfg, }) } /// Return a new isolated `TorClient` instance. /// /// The two `TorClient`s will share some internal state, but their /// streams will haver share circuits with one another. /// /// Use this function when you want separate parts of your program to /// each have a TorClient handle, but where you don't want their /// activities to be linkable to one another over the Tor network. /// /// Calling this function is usually preferable to creating a /// completely separate TorClient instance, since it can share its /// internals with the existing `TorClient`. pub fn isolated_client(&self) -> TorClient<R> { let mut result = self.clone(); result.client_isolation = IsolationToken::new(); result } /// Launch an anonymized connection to the provided address and /// port over the Tor network. /// Loading Loading @@ -303,9 +317,22 @@ impl<R: Runtime> TorClient<R> { flags: &ConnectPrefs, ) -> Result<Arc<ClientCirc>> { let dir = self.dirmgr.netdir(); let isolation = { let mut b = StreamIsolationBuilder::new(); // Always consider our client_isolation. b.owner_token(self.client_isolation); // Consider stream isolation too, if it's set. if let Some(tok) = flags.isolation_group() { b.stream_token(tok); } // Failure should be impossible with this builder. b.build().expect("Failed to construct StreamIsolation") }; let circ = self .circmgr .get_or_launch_exit(dir.as_ref().into(), exit_ports, flags.isolation_group()) .get_or_launch_exit(dir.as_ref().into(), exit_ports, isolation) .await .map_err(|_| Error::Internal("Unable to launch circuit"))?; drop(dir); // This decreases the refcount on the netdir. Loading
crates/tor-circmgr/src/lib.rs +3 −6 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ mod timeouts; mod usage; pub use err::Error; pub use usage::{IsolationToken, TargetPort}; pub use usage::{IsolationToken, StreamIsolation, StreamIsolationBuilder, TargetPort}; pub use config::{ CircMgrConfig, CircMgrConfigBuilder, CircuitTiming, CircuitTimingBuilder, PathConfig, Loading Loading @@ -254,14 +254,11 @@ impl<R: Runtime> CircMgr<R> { &self, netdir: DirInfo<'_>, // TODO: This has to be a NetDir. ports: &[TargetPort], isolation_group: IsolationToken, isolation: StreamIsolation, ) -> Result<Arc<ClientCirc>> { self.expire_circuits(); let ports = ports.iter().map(Clone::clone).collect(); let usage = TargetCircUsage::Exit { ports, isolation_group, }; let usage = TargetCircUsage::Exit { ports, isolation }; self.mgr.get_or_launch(&usage, netdir).await } Loading
crates/tor-circmgr/src/usage.rs +88 −33 Original line number Diff line number Diff line Loading @@ -103,6 +103,43 @@ impl IsolationToken { } } /// A set of information about how a stream should be isolated. /// /// If two streams are isolated from one another, they may not share /// a circuit. #[derive(Copy, Clone, Eq, Debug, PartialEq, derive_builder::Builder)] pub struct StreamIsolation { /// Any isolation token set on the stream. #[builder(default = "IsolationToken::no_isolation()")] stream_token: IsolationToken, /// Any additional isolation token set on an object that "owns" this /// stream. This is typically owned by a `TorClient`. #[builder(default = "IsolationToken::no_isolation()")] owner_token: IsolationToken, } impl StreamIsolation { /// Construct a new StreamIsolation with no isolation enabled. pub fn no_isolation() -> Self { StreamIsolationBuilder::new() .build() .expect("Bug constructing StreamIsolation") } /// Return a new StreamIsolationBuilder for constructing /// StreamIsolation objects. pub fn builder() -> StreamIsolationBuilder { StreamIsolationBuilder::new() } } impl StreamIsolationBuilder { /// Construct a builder with no items set. pub fn new() -> Self { StreamIsolationBuilder::default() } } impl ExitPolicy { /// Make a new exit policy from a given Relay. pub(crate) fn from_relay(relay: &Relay<'_>) -> Self { Loading Loading @@ -140,7 +177,7 @@ pub(crate) enum TargetCircUsage { /// to support any particular port, but it still needs to be an exit. ports: Vec<TargetPort>, /// Isolation group the circuit shall be part of isolation_group: IsolationToken, isolation: StreamIsolation, }, /// For a circuit is only used for the purpose of building it. TimeoutTesting, Loading @@ -160,7 +197,7 @@ pub(crate) enum SupportedCircUsage { policy: ExitPolicy, /// Isolation group the circuit is part of. None when the circuit is not yet assigned to an /// isolation group. isolation_group: Option<IsolationToken>, isolation: Option<StreamIsolation>, }, /// This circuit is not suitable for any usage. NoUsage, Loading Loading @@ -188,7 +225,7 @@ impl TargetCircUsage { } TargetCircUsage::Exit { ports: p, isolation_group, isolation, } => { let (path, mon, usable) = ExitPathBuilder::from_target_ports(p.clone()) .pick_path(rng, netdir, guards, config)?; Loading @@ -199,7 +236,7 @@ impl TargetCircUsage { path, SupportedCircUsage::Exit { policy, isolation_group: Some(*isolation_group), isolation: Some(*isolation), }, mon, usable, Loading @@ -212,7 +249,7 @@ impl TargetCircUsage { let usage = match policy { Some(policy) if policy.allows_some_port() => SupportedCircUsage::Exit { policy, isolation_group: None, isolation: None, }, _ => SupportedCircUsage::NoUsage, }; Loading @@ -233,11 +270,11 @@ impl crate::mgr::AbstractSpec for SupportedCircUsage { ( Exit { policy: p1, isolation_group: i1, isolation: i1, }, TargetCircUsage::Exit { ports: p2, isolation_group: i2, isolation: i2, }, ) => { i1.map(|i1| i1 == *i2).unwrap_or(true) Loading @@ -255,13 +292,10 @@ impl crate::mgr::AbstractSpec for SupportedCircUsage { (Dir, TargetCircUsage::Dir) => Ok(()), ( Exit { isolation_group: ref mut i1, .. }, TargetCircUsage::Exit { isolation_group: i2, isolation: ref mut i1, .. }, TargetCircUsage::Exit { isolation: i2, .. }, ) if i1.map(|i1| i1 == *i2).unwrap_or(true) => { *i1 = Some(*i2); Ok(()) Loading Loading @@ -335,42 +369,50 @@ mod test { v4: Arc::new("accept 80,443".parse().unwrap()), v6: Arc::new("accept 23".parse().unwrap()), }; let isolation_group = IsolationToken::new(); let isolation_group_2 = IsolationToken::new(); let tok1 = IsolationToken::new(); let tok2 = IsolationToken::new(); let isolation = StreamIsolationBuilder::new() .owner_token(tok1) .build() .unwrap(); let isolation2 = StreamIsolationBuilder::new() .owner_token(tok2) .build() .unwrap(); let supp_dir = SupportedCircUsage::Dir; let targ_dir = TargetCircUsage::Dir; let supp_exit = SupportedCircUsage::Exit { policy: policy.clone(), isolation_group: Some(isolation_group), isolation: Some(isolation), }; let supp_exit_iso2 = SupportedCircUsage::Exit { policy: policy.clone(), isolation_group: Some(isolation_group_2), isolation: Some(isolation2), }; let supp_exit_no_iso = SupportedCircUsage::Exit { policy, isolation_group: None, isolation: None, }; let targ_80_v4 = TargetCircUsage::Exit { ports: vec![TargetPort::ipv4(80)], isolation_group, isolation, }; let targ_80_v4_iso2 = TargetCircUsage::Exit { ports: vec![TargetPort::ipv4(80)], isolation_group: isolation_group_2, isolation: isolation2, }; let targ_80_23_v4 = TargetCircUsage::Exit { ports: vec![TargetPort::ipv4(80), TargetPort::ipv4(23)], isolation_group, isolation, }; let targ_80_23_mixed = TargetCircUsage::Exit { ports: vec![TargetPort::ipv4(80), TargetPort::ipv6(23)], isolation_group, isolation, }; let targ_999_v6 = TargetCircUsage::Exit { ports: vec![TargetPort::ipv6(999)], isolation_group, isolation, }; assert!(supp_dir.supports(&targ_dir)); Loading @@ -397,30 +439,38 @@ mod test { v6: Arc::new("accept 23".parse().unwrap()), }; let isolation_group = IsolationToken::new(); let isolation_group_2 = IsolationToken::new(); let tok1 = IsolationToken::new(); let tok2 = IsolationToken::new(); let isolation = StreamIsolationBuilder::new() .owner_token(tok1) .build() .unwrap(); let isolation2 = StreamIsolationBuilder::new() .owner_token(tok2) .build() .unwrap(); let supp_dir = SupportedCircUsage::Dir; let targ_dir = TargetCircUsage::Dir; let supp_exit = SupportedCircUsage::Exit { policy: policy.clone(), isolation_group: Some(isolation_group), isolation: Some(isolation), }; let supp_exit_iso2 = SupportedCircUsage::Exit { policy: policy.clone(), isolation_group: Some(isolation_group_2), isolation: Some(isolation2), }; let supp_exit_no_iso = SupportedCircUsage::Exit { policy, isolation_group: None, isolation: None, }; let targ_exit = TargetCircUsage::Exit { ports: vec![TargetPort::ipv4(80)], isolation_group, isolation, }; let targ_exit_iso2 = TargetCircUsage::Exit { ports: vec![TargetPort::ipv4(80)], isolation_group: isolation_group_2, isolation: isolation2, }; // not allowed, do nothing Loading Loading @@ -486,10 +536,15 @@ mod test { assert!(matches!(u_dir, SupportedCircUsage::Dir)); assert_eq!(p_dir.len(), 1); let isolation_group = IsolationToken::new(); let tok1 = IsolationToken::new(); let isolation = StreamIsolationBuilder::new() .owner_token(tok1) .build() .unwrap(); let exit_usage = TargetCircUsage::Exit { ports: vec![TargetPort::ipv4(995)], isolation_group, isolation, }; let (p_exit, u_exit, _, _) = exit_usage .build_path(&mut rng, di, guards, &config) Loading @@ -497,9 +552,9 @@ mod test { assert!(matches!( u_exit, SupportedCircUsage::Exit { isolation_group: iso, isolation: iso, .. } if iso == Some(isolation_group) } if iso == Some(isolation) )); assert!(u_exit.supports(&exit_usage)); assert_eq!(p_exit.len(), 3); Loading