chanmgr: Require HasRelayIds for AbstractChannel::BuildSpec

This is mostly a testing only change for now too, but soon I'll use
it to deal with the fact that we need to know the IDs to actually
build a channel at all.
This commit is contained in:
Nick Mathewson 2022-10-14 13:01:22 -04:00
parent 71db8ebc2e
commit e51fdbfb1b
2 changed files with 50 additions and 24 deletions

View File

@ -63,7 +63,7 @@ pub(crate) trait AbstractChannelFactory {
/// The type of channel that this factory can build.
type Channel: AbstractChannel;
/// Type that explains how to build a channel.
type BuildSpec;
type BuildSpec: HasRelayIds;
/// Construct a new channel to the destination described at `target`.
///
@ -424,19 +424,38 @@ mod test {
)
}
#[derive(Clone, Debug)]
struct FakeBuildSpec(u32, char, Ed25519Identity);
impl HasRelayIds for FakeBuildSpec {
fn identity(
&self,
key_type: tor_linkspec::RelayIdType,
) -> Option<tor_linkspec::RelayIdRef<'_>> {
match key_type {
tor_linkspec::RelayIdType::Ed25519 => Some((&self.2).into()),
_ => None,
}
}
}
/// Helper to make a fake Ed identity from a u32.
fn u32_to_ed(n: u32) -> Ed25519Identity {
let mut bytes = [0; 32];
bytes[0..4].copy_from_slice(&n.to_be_bytes());
bytes.into()
}
#[async_trait]
impl<RT: Runtime> AbstractChannelFactory for FakeChannelFactory<RT> {
type Channel = FakeChannel;
type BuildSpec = (u32, char);
type BuildSpec = FakeBuildSpec;
async fn build_channel(&self, target: &Self::BuildSpec) -> Result<FakeChannel> {
yield_now().await;
let (ident, mood) = *target;
let ed_ident = {
let mut bytes = [0; 32];
bytes[0..4].copy_from_slice(&ident.to_be_bytes());
bytes.into()
};
let FakeBuildSpec(ident, mood, id) = *target;
let ed_ident = u32_to_ed(ident);
assert_eq!(ed_ident, id);
match mood {
// "X" means never connect.
'❌' | '🔥' => return Err(Error::UnusableTarget(bad_api_usage!("emoji"))),
@ -461,9 +480,9 @@ mod test {
fn connect_one_ok() {
test_with_one_runtime!(|runtime| async {
let mgr = new_test_abstract_chanmgr(runtime);
let target = (413, '!');
let target = FakeBuildSpec(413, '!', u32_to_ed(413));
let chan1 = mgr
.get_or_launch(413, target, CU::UserTraffic)
.get_or_launch(413, target.clone(), CU::UserTraffic)
.await
.unwrap()
.0;
@ -486,7 +505,7 @@ mod test {
let mgr = new_test_abstract_chanmgr(runtime);
// This is set up to always fail.
let target = (999, '❌');
let target = FakeBuildSpec(999, '❌', u32_to_ed(999));
let res1 = mgr.get_or_launch(999, target, CU::UserTraffic).await;
assert!(matches!(res1, Err(Error::UnusableTarget(_))));
@ -504,12 +523,12 @@ mod test {
// concurrently. Right now it seems that they don't actually
// interact.
let (ch3a, ch3b, ch44a, ch44b, ch86a, ch86b) = join!(
mgr.get_or_launch(3, (3, 'a'), CU::UserTraffic),
mgr.get_or_launch(3, (3, 'b'), CU::UserTraffic),
mgr.get_or_launch(44, (44, 'a'), CU::UserTraffic),
mgr.get_or_launch(44, (44, 'b'), CU::UserTraffic),
mgr.get_or_launch(86, (86, '❌'), CU::UserTraffic),
mgr.get_or_launch(86, (86, '🔥'), CU::UserTraffic),
mgr.get_or_launch(3, FakeBuildSpec(3, 'a', u32_to_ed(3)), CU::UserTraffic),
mgr.get_or_launch(3, FakeBuildSpec(3, 'b', u32_to_ed(3)), CU::UserTraffic),
mgr.get_or_launch(44, FakeBuildSpec(44, 'a', u32_to_ed(44)), CU::UserTraffic),
mgr.get_or_launch(44, FakeBuildSpec(44, 'b', u32_to_ed(44)), CU::UserTraffic),
mgr.get_or_launch(86, FakeBuildSpec(86, '❌', u32_to_ed(86)), CU::UserTraffic),
mgr.get_or_launch(86, FakeBuildSpec(86, '🔥', u32_to_ed(86)), CU::UserTraffic),
);
let ch3a = ch3a.unwrap();
let ch3b = ch3b.unwrap();
@ -533,9 +552,9 @@ mod test {
let mgr = new_test_abstract_chanmgr(runtime);
let (ch3, ch4, ch5) = join!(
mgr.get_or_launch(3, (3, 'a'), CU::UserTraffic),
mgr.get_or_launch(4, (4, 'a'), CU::UserTraffic),
mgr.get_or_launch(5, (5, 'a'), CU::UserTraffic),
mgr.get_or_launch(3, FakeBuildSpec(3, 'a', u32_to_ed(3)), CU::UserTraffic),
mgr.get_or_launch(4, FakeBuildSpec(4, 'a', u32_to_ed(4)), CU::UserTraffic),
mgr.get_or_launch(5, FakeBuildSpec(5, 'a', u32_to_ed(5)), CU::UserTraffic),
);
let ch3 = ch3.unwrap().0;
@ -546,7 +565,7 @@ mod test {
ch5.start_closing();
let ch3_new = mgr
.get_or_launch(3, (3, 'b'), CU::UserTraffic)
.get_or_launch(3, FakeBuildSpec(3, 'b', u32_to_ed(3)), CU::UserTraffic)
.await
.unwrap()
.0;

View File

@ -21,7 +21,7 @@ use itertools::{zip_eq, Itertools};
use tor_cell::chancell::msg::PaddingNegotiateCmd;
use tor_config::PaddingLevel;
use tor_linkspec::HasRelayIds;
use tor_linkspec::{HasRelayIds, RelayIds};
use tor_netdir::NetDir;
use tor_proto::channel::{Channel, CtrlMsg};
@ -121,7 +121,7 @@ struct FakeChannelFactory {
#[async_trait]
impl AbstractChannelFactory for FakeChannelFactory {
type Channel = Channel;
type BuildSpec = ();
type BuildSpec = tor_linkspec::RelayIds;
async fn build_channel(&self, _target: &Self::BuildSpec) -> Result<Self::Channel> {
Ok(self.channel.clone())
@ -152,13 +152,20 @@ async fn case(level: PaddingLevel, dormancy: Dormancy, usage: ChannelUsage) -> C
let (channel, recv) = Channel::new_fake();
let peer_id = channel.target().ed_identity().unwrap().clone();
let relay_ids = RelayIds::builder()
.ed_identity(peer_id.clone())
.build()
.unwrap();
let factory = FakeChannelFactory { channel };
let netparams = Arc::new(NetParameters::default());
let chanmgr = AbstractChanMgr::new(factory, &cconfig, dormancy, &netparams);
let (channel, _prov) = chanmgr.get_or_launch(peer_id, (), usage).await.unwrap();
let (channel, _prov) = chanmgr
.get_or_launch(peer_id, relay_ids, usage)
.await
.unwrap();
CaseContext {
channel,