1
//! Owned variants of [`ChanTarget`] and [`CircTarget`].
2

            
3
use std::fmt::{self, Display};
4
use std::net::SocketAddr;
5
use tor_llcrypto::pk;
6

            
7
use crate::{ChanTarget, CircTarget};
8

            
9
/// OwnedChanTarget is a summary of a [`ChanTarget`] that owns all of its
10
/// members.
11
8
#[derive(Debug, Clone)]
12
pub struct OwnedChanTarget {
13
    /// Copy of the addresses from the underlying ChanTarget.
14
    addrs: Vec<SocketAddr>,
15
    /// Copy of the ed25519 id from the underlying ChanTarget.
16
    ed_identity: pk::ed25519::Ed25519Identity,
17
    /// Copy of the rsa id from the underlying ChanTarget.
18
    rsa_identity: pk::rsa::RsaIdentity,
19
}
20

            
21
impl ChanTarget for OwnedChanTarget {
22
22
    fn addrs(&self) -> &[SocketAddr] {
23
22
        &self.addrs[..]
24
22
    }
25
164854
    fn ed_identity(&self) -> &pk::ed25519::Ed25519Identity {
26
164854
        &self.ed_identity
27
164854
    }
28
22
    fn rsa_identity(&self) -> &pk::rsa::RsaIdentity {
29
22
        &self.rsa_identity
30
22
    }
31
}
32

            
33
impl OwnedChanTarget {
34
    /// Construct a new OwnedChanTarget from its parts.
35
    // TODO: Put this function behind a feature.
36
658
    pub fn new(
37
658
        addrs: Vec<SocketAddr>,
38
658
        ed_identity: pk::ed25519::Ed25519Identity,
39
658
        rsa_identity: pk::rsa::RsaIdentity,
40
658
    ) -> Self {
41
658
        Self {
42
658
            addrs,
43
658
            ed_identity,
44
658
            rsa_identity,
45
658
        }
46
658
    }
47

            
48
    /// Construct a OwnedChanTarget from a given ChanTarget.
49
10253
    pub fn from_chan_target<C>(target: &C) -> Self
50
10253
    where
51
10253
        C: ChanTarget + ?Sized,
52
10253
    {
53
10253
        OwnedChanTarget {
54
10253
            addrs: target.addrs().to_vec(),
55
10253
            ed_identity: *target.ed_identity(),
56
10253
            rsa_identity: *target.rsa_identity(),
57
10253
        }
58
10253
    }
59
}
60

            
61
/// Primarily for error reporting and logging
62
impl Display for OwnedChanTarget {
63
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64
        write!(f, "[")?;
65
        match &*self.addrs {
66
            [] => write!(f, "?")?,
67
            [a] => write!(f, "{}", a)?,
68
            [a, ..] => write!(f, "{}+", a)?,
69
        };
70
        write!(f, "{}", &self.ed_identity)?; // short enough to print
71
        write!(f, "]")?;
72
        Ok(())
73
    }
74
}
75

            
76
/// OwnedCircTarget is a summary of a [`CircTarget`] that owns all its
77
/// members.
78
4
#[derive(Debug, Clone)]
79
pub struct OwnedCircTarget {
80
    /// The fields from this object when considered as a ChanTarget.
81
    chan_target: OwnedChanTarget,
82
    /// The ntor key to use when extending to this CircTarget
83
    ntor_onion_key: pk::curve25519::PublicKey,
84
    /// The subprotocol versions that this CircTarget supports.
85
    protovers: tor_protover::Protocols,
86
}
87

            
88
impl OwnedCircTarget {
89
    /// Construct a new OwnedCircTarget from its parts.
90
    // TODO: Put this function behind a feature.
91
577
    pub fn new(
92
577
        chan_target: OwnedChanTarget,
93
577
        ntor_onion_key: pk::curve25519::PublicKey,
94
577
        protovers: tor_protover::Protocols,
95
577
    ) -> OwnedCircTarget {
96
577
        OwnedCircTarget {
97
577
            chan_target,
98
577
            ntor_onion_key,
99
577
            protovers,
100
577
        }
101
577
    }
102

            
103
    /// Construct an OwnedCircTarget from a given CircTarget.
104
10241
    pub fn from_circ_target<C>(target: &C) -> Self
105
10241
    where
106
10241
        C: CircTarget + ?Sized,
107
10241
    {
108
10241
        OwnedCircTarget {
109
10241
            chan_target: OwnedChanTarget::from_chan_target(target),
110
10241
            ntor_onion_key: *target.ntor_onion_key(),
111
10241
            // TODO: I don't like having to clone here.  Our underlying
112
10241
            // protovers parsing uses an Arc, IIRC.  Can we expose that here?
113
10241
            protovers: target.protovers().clone(),
114
10241
        }
115
10241
    }
116
}
117

            
118
/// Primarily for error reporting and logging
119
impl Display for OwnedCircTarget {
120
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121
        Display::fmt(&self.chan_target, f)
122
    }
123
}
124

            
125
impl ChanTarget for OwnedCircTarget {
126
2
    fn addrs(&self) -> &[SocketAddr] {
127
2
        self.chan_target.addrs()
128
2
    }
129
164546
    fn ed_identity(&self) -> &pk::ed25519::Ed25519Identity {
130
164546
        self.chan_target.ed_identity()
131
164546
    }
132
2
    fn rsa_identity(&self) -> &pk::rsa::RsaIdentity {
133
2
        self.chan_target.rsa_identity()
134
2
    }
135
}
136

            
137
impl CircTarget for OwnedCircTarget {
138
2
    fn ntor_onion_key(&self) -> &pk::curve25519::PublicKey {
139
2
        &self.ntor_onion_key
140
2
    }
141
2
    fn protovers(&self) -> &tor_protover::Protocols {
142
2
        &self.protovers
143
2
    }
144
}
145

            
146
#[cfg(test)]
147
mod test {
148
    #![allow(clippy::unwrap_used)]
149
    use super::*;
150

            
151
    #[test]
152
    #[allow(clippy::redundant_clone)]
153
    fn chan_target() {
154
        let ti = OwnedChanTarget::new(
155
            vec!["127.0.0.1:11".parse().unwrap()],
156
            [42; 32].into(),
157
            [45; 20].into(),
158
        );
159

            
160
        let ti2 = OwnedChanTarget::from_chan_target(&ti);
161
        assert_eq!(ti.addrs(), ti2.addrs());
162
        assert_eq!(ti.ed_identity(), ti2.ed_identity());
163
        assert_eq!(ti.rsa_identity(), ti2.rsa_identity());
164

            
165
        assert_eq!(format!("{:?}", ti), format!("{:?}", ti2));
166
        assert_eq!(format!("{:?}", ti), format!("{:?}", ti.clone()));
167
    }
168

            
169
    #[test]
170
    #[allow(clippy::redundant_clone)]
171
    fn circ_target() {
172
        let ch = OwnedChanTarget::new(
173
            vec!["127.0.0.1:11".parse().unwrap()],
174
            [42; 32].into(),
175
            [45; 20].into(),
176
        );
177
        let ct = OwnedCircTarget::new(ch.clone(), [99; 32].into(), "FlowCtrl=7".parse().unwrap());
178

            
179
        assert_eq!(ct.addrs(), ch.addrs());
180
        assert_eq!(ct.rsa_identity(), ch.rsa_identity());
181
        assert_eq!(ct.ed_identity(), ch.ed_identity());
182
        assert_eq!(ct.ntor_onion_key().as_bytes(), &[99; 32]);
183
        assert_eq!(&ct.protovers().to_string(), "FlowCtrl=7");
184
        let ct2 = OwnedCircTarget::from_circ_target(&ct);
185
        assert_eq!(format!("{:?}", ct), format!("{:?}", ct2));
186
        assert_eq!(format!("{:?}", ct), format!("{:?}", ct.clone()));
187
    }
188
}