1
//! Different kinds of messages that can be encoded in channel cells.
2

            
3
use super::{BoxedCellBody, CELL_DATA_LEN, ChanCmd, RawCellBody};
4
use std::net::{IpAddr, Ipv4Addr};
5
use tor_basic_utils::skip_fmt;
6
use tor_bytes::{self, EncodeError, EncodeResult, Error, Readable, Reader, Result, Writer};
7
use tor_memquota::derive_deftly_template_HasMemoryCost;
8
use tor_units::IntegerMilliseconds;
9

            
10
use caret::caret_int;
11
use derive_deftly::Deftly;
12
use educe::Educe;
13

            
14
/// Trait for the 'bodies' of channel messages.
15
pub trait Body: Readable {
16
    /// Decode a channel cell body from a provided reader.
17
4845
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
18
4845
        r.extract()
19
4845
    }
20
    /// Consume this message and encode its body onto `w`.
21
    ///
22
    /// Does not encode anything _but_ the cell body, and does not pad
23
    /// to the cell length.
24
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()>;
25
}
26

            
27
crate::restrict::restricted_msg! {
28
/// Decoded message from a channel.
29
///
30
/// A ChanMsg is an item received on a channel -- a message from
31
/// another Tor client or relay that we are connected to directly over
32
/// a TLS connection.
33
#[derive(Clone, Debug, Deftly)]
34
#[derive_deftly(HasMemoryCost)]
35
#[non_exhaustive]
36
@omit_from "avoid_conflict_with_a_blanket_implementation"
37
pub enum AnyChanMsg : ChanMsg {
38
    /// A Padding message
39
    Padding,
40
    /// Variable-length padding message
41
    Vpadding,
42
    /// (Deprecated) TAP-based cell to create a new circuit.
43
    Create,
44
    /// (Mostly deprecated) HMAC-based cell to create a new circuit.
45
    CreateFast,
46
    /// Cell to create a new circuit
47
    Create2,
48
    /// (Deprecated) Answer to a Create cell
49
    Created,
50
    /// (Mostly Deprecated) Answer to a CreateFast cell
51
    CreatedFast,
52
    /// Answer to a Create2 cell
53
    Created2,
54
    /// A message sent along a circuit, likely to a more-distant relay.
55
    Relay,
56
    /// A message sent along a circuit (limited supply)
57
    RelayEarly,
58
    /// Tear down a circuit
59
    Destroy,
60
    /// Part of channel negotiation: describes our position on the network
61
    Netinfo,
62
    /// Part of channel negotiation: describes what link protocol versions
63
    /// we support
64
    Versions,
65
    /// Negotiates what kind of channel padding to send
66
    PaddingNegotiate,
67
    /// Part of channel negotiation: additional certificates not in the
68
    /// TLS handshake
69
    Certs,
70
    /// Part of channel negotiation: additional random material to be used
71
    /// as part of authentication
72
    AuthChallenge,
73
    /// Part of channel negotiation: used to authenticate relays when they
74
    /// initiate the channel.
75
    Authenticate,
76
    _ =>
77
    /// Any cell whose command we don't recognize
78
    Unrecognized,
79
}
80
}
81

            
82
/// A Padding message is a fixed-length message on a channel that is
83
/// ignored.
84
///
85
/// Padding message can be used to disguise the true amount of data on a
86
/// channel, or as a "keep-alive".
87
///
88
/// The correct response to a padding cell is to drop it and do nothing.
89
#[derive(Clone, Debug, Default, Deftly)]
90
#[derive_deftly(HasMemoryCost)]
91
#[non_exhaustive]
92
pub struct Padding {}
93
impl Padding {
94
    /// Create a new fixed-length padding cell
95
285
    pub fn new() -> Self {
96
285
        Padding {}
97
285
    }
98
}
99
impl Body for Padding {
100
8
    fn encode_onto<W: Writer + ?Sized>(self, _w: &mut W) -> EncodeResult<()> {
101
8
        Ok(())
102
8
    }
103
}
104
impl Readable for Padding {
105
171
    fn take_from(_b: &mut Reader<'_>) -> Result<Self> {
106
171
        Ok(Padding {})
107
171
    }
108
}
109

            
110
/// A VPadding message is a variable-length padding message.
111
///
112
/// The correct response to a padding cell is to drop it and do nothing.
113
#[derive(Clone, Debug, Deftly)]
114
#[derive_deftly(HasMemoryCost)]
115
pub struct Vpadding {
116
    /// How much padding to send in this cell's body.
117
    len: u16,
118
}
119
impl Vpadding {
120
    /// Return a new vpadding cell with given length.
121
114
    pub fn new(len: u16) -> Self {
122
114
        Vpadding { len }
123
114
    }
124
}
125
impl Body for Vpadding {
126
8
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
127
8
        w.write_zeros(self.len as usize);
128
8
        Ok(())
129
8
    }
130
}
131
impl Readable for Vpadding {
132
342
    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
133
342
        if b.remaining() > u16::MAX as usize {
134
            return Err(Error::InvalidMessage(
135
                "Too many bytes in VPADDING cell".into(),
136
            ));
137
342
        }
138
342
        Ok(Vpadding {
139
342
            len: b.remaining() as u16,
140
342
        })
141
342
    }
142
}
143

            
144
/// helper -- declare a fixed-width cell for handshake commands, in which
145
/// a fixed number of bytes matter and the rest are ignored
146
macro_rules! fixed_len_handshake {
147
    {
148
        $(#[$meta:meta])*
149
        $name:ident , $cmd:ident, $len:ident
150
    } => {
151
        $(#[$meta])*
152
        #[derive(Clone,Debug,Deftly)]
153
        #[derive_deftly(HasMemoryCost)]
154
        pub struct $name {
155
            handshake: Vec<u8>
156
        }
157
        impl $name {
158
            /// Create a new cell from a provided handshake.
159
44
            pub fn new<B>(handshake: B) -> Self
160
44
                where B: Into<Vec<u8>>
161
            {
162
44
                let handshake = handshake.into();
163
44
                $name { handshake }
164
44
            }
165
        }
166
        impl Body for $name {
167
16
            fn encode_onto<W: Writer + ?Sized>(self, w: &mut W)  -> EncodeResult<()> {
168
16
                w.write_all(&self.handshake[..]);
169
16
                Ok(())
170
16
            }
171
        }
172
        impl Readable for $name {
173
228
            fn take_from(b: &mut Reader<'_>) -> Result<Self> {
174
                Ok($name {
175
228
                    handshake: b.take($len)?.into(),
176
                })
177
228
            }
178
        }
179
    }
180
}
181

            
182
/// Number of bytes used for a TAP handshake by the initiator.
183
pub(crate) const TAP_C_HANDSHAKE_LEN: usize = 128 + 16 + 42;
184
/// Number of bytes used for a TAP handshake response
185
pub(crate) const TAP_S_HANDSHAKE_LEN: usize = 128 + 20;
186

            
187
/// Number of bytes used for a CREATE_FAST handshake by the initiator
188
const FAST_C_HANDSHAKE_LEN: usize = 20;
189
/// Number of bytes used for a CREATE_FAST handshake response
190
const FAST_S_HANDSHAKE_LEN: usize = 20 + 20;
191

            
192
fixed_len_handshake! {
193
    /// A Create message creates a circuit, using the TAP handshake.
194
    ///
195
    /// TAP is an obsolete handshake based on RSA-1024 and DH-1024.
196
    /// Relays respond to Create message with a Created reply on
197
    /// success, or a Destroy message on failure.
198
    ///
199
    /// In Tor today, Create is only used for the deprecated v2 onion
200
    /// service protocol.
201
    Create, CREATE, TAP_C_HANDSHAKE_LEN
202
}
203
fixed_len_handshake! {
204
    /// A Created message responds to a Created message, using the TAP
205
    /// handshake.
206
    ///
207
    /// TAP is an obsolete handshake based on RSA-1024 and DH-1024.
208
    Created, CREATED, TAP_S_HANDSHAKE_LEN
209
}
210
fixed_len_handshake! {
211
    /// A CreateFast message creates a circuit using no public-key crypto.
212
    ///
213
    /// CreateFast is safe only when used on an already-secure TLS
214
    /// connection.  It can only be used for the first hop of a circuit.
215
    ///
216
    /// Relays reply to a CreateFast message with CreatedFast on
217
    /// success, or a Destroy message on failure.
218
    ///
219
    /// This handshake was originally used for the first hop of every
220
    /// circuit.  Nowadays it is used for creating one-hop circuits
221
    /// when we don't know any onion key for the first hop.
222
    CreateFast, CREATE_FAST, FAST_C_HANDSHAKE_LEN
223
}
224
impl CreateFast {
225
    /// Return the content of this handshake
226
399
    pub fn handshake(&self) -> &[u8] {
227
399
        &self.handshake
228
399
    }
229
}
230
fixed_len_handshake! {
231
    /// A CreatedFast message responds to a CreateFast message
232
    ///
233
    /// Relays send this message back to indicate that the CrateFast handshake
234
    /// is complete.
235
    CreatedFast, CREATED_FAST, FAST_S_HANDSHAKE_LEN
236
}
237
impl CreatedFast {
238
    /// Consume this message and return the content of this handshake
239
399
    pub fn into_handshake(self) -> Vec<u8> {
240
399
        self.handshake
241
399
    }
242
}
243

            
244
caret_int! {
245
    /// Handshake type, corresponding to [`HTYPE` in
246
    /// tor-spec](https://spec.torproject.org/tor-spec/create-created-cells.html).
247
    #[derive(Deftly)]
248
    #[derive_deftly(HasMemoryCost)]
249
    pub struct HandshakeType(u16) {
250
        /// [TAP](https://spec.torproject.org/tor-spec/create-created-cells.html#TAP) -- the original Tor handshake.
251
        TAP = 0,
252

            
253
        // 1 is reserved
254

            
255
        /// [ntor](https://spec.torproject.org/tor-spec/create-created-cells.html#ntor) -- the ntor+curve25519+sha256 handshake.
256
        NTOR = 2,
257
        /// [ntor-v3](https://spec.torproject.org/tor-spec/create-created-cells.html#ntor-v3) -- ntor extended with extra data.
258
        NTOR_V3 = 3,
259
    }
260
}
261

            
262
/// A Create2 message create a circuit on the current channel.
263
///
264
/// To create a circuit, the client sends a Create2 cell containing a
265
/// handshake of a given type; the relay responds with a Created2 cell
266
/// containing a reply.
267
///
268
/// Currently, most Create2 cells contain a client-side instance of the
269
/// "ntor" handshake.
270
#[derive(Clone, Debug, Deftly)]
271
#[derive_deftly(HasMemoryCost)]
272
pub struct Create2 {
273
    /// Identifier for what kind of handshake this is.
274
    handshake_type: HandshakeType,
275
    /// Body of the handshake.
276
    handshake: Vec<u8>,
277
}
278
impl Body for Create2 {
279
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
280
4
        w.write_u16(self.handshake_type.into());
281
4
        let handshake_len = self
282
4
            .handshake
283
4
            .len()
284
4
            .try_into()
285
4
            .map_err(|_| EncodeError::BadLengthValue)?;
286
4
        w.write_u16(handshake_len);
287
4
        w.write_all(&self.handshake[..]);
288
4
        Ok(())
289
4
    }
290
}
291
impl Readable for Create2 {
292
57
    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
293
57
        let handshake_type = HandshakeType::from(b.take_u16()?);
294
57
        let hlen = b.take_u16()?;
295
57
        let handshake = b.take(hlen as usize)?.into();
296
57
        Ok(Create2 {
297
57
            handshake_type,
298
57
            handshake,
299
57
        })
300
57
    }
301
}
302
impl Create2 {
303
    /// Wrap a typed handshake as a Create2 message
304
52
    pub fn new<B>(handshake_type: HandshakeType, handshake: B) -> Self
305
52
    where
306
52
        B: Into<Vec<u8>>,
307
    {
308
52
        let handshake = handshake.into();
309
52
        Create2 {
310
52
            handshake_type,
311
52
            handshake,
312
52
        }
313
52
    }
314

            
315
    /// Return the type of this handshake.
316
57
    pub fn handshake_type(&self) -> HandshakeType {
317
57
        self.handshake_type
318
57
    }
319

            
320
    /// Return the body of this handshake.
321
1083
    pub fn body(&self) -> &[u8] {
322
1083
        &self.handshake[..]
323
1083
    }
324
}
325

            
326
/// A Created2 message completes a circuit-creation handshake.
327
///
328
/// When a relay receives a valid Create2 message that it can handle, it
329
/// establishes the circuit and replies with a Created2.
330
#[derive(Clone, Debug, Deftly)]
331
#[derive_deftly(HasMemoryCost)]
332
pub struct Created2 {
333
    /// Body of the handshake reply
334
    handshake: Vec<u8>,
335
}
336
impl Created2 {
337
    /// Create a new Created2 to hold a given handshake.
338
82
    pub fn new<B>(handshake: B) -> Self
339
82
    where
340
82
        B: Into<Vec<u8>>,
341
    {
342
82
        let handshake = handshake.into();
343
82
        Created2 { handshake }
344
82
    }
345
    /// Consume this created2 cell and return its body.
346
1083
    pub fn into_body(self) -> Vec<u8> {
347
1083
        self.handshake
348
1083
    }
349
}
350
impl Body for Created2 {
351
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
352
4
        let handshake_len = self
353
4
            .handshake
354
4
            .len()
355
4
            .try_into()
356
4
            .map_err(|_| EncodeError::BadLengthValue)?;
357
4
        w.write_u16(handshake_len);
358
4
        w.write_all(&self.handshake[..]);
359
4
        Ok(())
360
4
    }
361
}
362
impl Readable for Created2 {
363
57
    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
364
57
        let hlen = b.take_u16()?;
365
57
        let handshake = b.take(hlen as usize)?.into();
366
57
        Ok(Created2 { handshake })
367
57
    }
368
}
369

            
370
/// A Relay cell - that is, one transmitted over a circuit.
371
///
372
/// Once a circuit has been established, relay cells can be sent over
373
/// it.  Clients can send relay cells to any relay on the circuit. Any
374
/// relay on the circuit can send relay cells to the client, either
375
/// directly (if it is the first hop), or indirectly through the
376
/// intermediate hops.
377
///
378
/// A different protocol is defined over the relay cells; it is implemented
379
/// in the [crate::relaycell] module.
380
#[derive(Clone, Educe, derive_more::From, Deftly)]
381
#[derive_deftly(HasMemoryCost)]
382
#[educe(Debug)]
383
pub struct Relay {
384
    /// The contents of the relay cell as encoded for transfer.
385
    ///
386
    /// TODO(nickm): It's nice that this is boxed, since we don't want to copy
387
    /// cell data all over the place. But unfortunately, there are some other
388
    /// places where we _don't_ Box things that we should, and more copies than
389
    /// necessary happen. We should refactor our data handling until we're mostly
390
    /// moving around pointers rather than copying data;  see ticket #7.
391
    #[educe(Debug(method = "skip_fmt"))]
392
    body: BoxedCellBody,
393
}
394
impl Relay {
395
    /// Construct a Relay message from a slice containing its contents.
396
40
    pub fn new<P>(body: P) -> Self
397
40
    where
398
40
        P: AsRef<[u8]>,
399
    {
400
40
        let body = body.as_ref();
401
40
        let mut r = [0_u8; CELL_DATA_LEN];
402
        // TODO: This will panic if body is too long, but that would be a
403
        // programming error anyway.
404
40
        r[..body.len()].copy_from_slice(body);
405
40
        Relay { body: Box::new(r) }
406
40
    }
407
    /// Construct a Relay message from its body.
408
57
    pub fn from_raw(body: RawCellBody) -> Self {
409
57
        Relay {
410
57
            body: Box::new(body),
411
57
        }
412
57
    }
413
    /// Consume this Relay message and return a BoxedCellBody for
414
    /// encryption/decryption.
415
130017
    pub fn into_relay_body(self) -> BoxedCellBody {
416
130017
        self.body
417
130017
    }
418
    /// Wrap this Relay message into a RelayMsg as a RELAY_EARLY cell.
419
57
    pub fn into_early(self) -> AnyChanMsg {
420
57
        AnyChanMsg::RelayEarly(RelayEarly(self))
421
57
    }
422
}
423
impl Body for Relay {
424
12
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
425
12
        w.write_all(&self.body[..]);
426
12
        Ok(())
427
12
    }
428
}
429
impl Readable for Relay {
430
342
    fn take_from(b: &mut Reader<'_>) -> Result<Self> {
431
342
        let mut body = Box::new([0_u8; CELL_DATA_LEN]);
432
342
        body.copy_from_slice(b.take(CELL_DATA_LEN)?);
433
342
        Ok(Relay { body })
434
342
    }
435
}
436

            
437
/// A Relay cell that is allowed to contain a CREATE message.
438
///
439
/// Only a limited number of these may be sent on each circuit.
440
#[derive(Clone, Debug, derive_more::Deref, derive_more::From, derive_more::Into, Deftly)]
441
#[derive_deftly(HasMemoryCost)]
442
pub struct RelayEarly(Relay);
443
impl Readable for RelayEarly {
444
57
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
445
57
        Ok(RelayEarly(Relay::take_from(r)?))
446
57
    }
447
}
448
impl Body for RelayEarly {
449
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
450
4
        self.0.encode_onto(w)
451
4
    }
452
}
453
impl RelayEarly {
454
    /// Consume this RelayEarly message and return a BoxedCellBody for
455
    /// encryption/decryption.
456
    //
457
    // (Since this method takes `self` by value, we can't take advantage of
458
    // Deref.)
459
2052
    pub fn into_relay_body(self) -> BoxedCellBody {
460
2052
        self.0.body
461
2052
    }
462
}
463

            
464
/// The Destroy message tears down a circuit.
465
///
466
/// On receiving a Destroy message, a Tor implementation should
467
/// tear down the associated circuit, and pass the destroy message
468
/// down the circuit to later/earlier hops on the circuit (if any).
469
#[derive(Clone, Debug, Deftly)]
470
#[derive_deftly(HasMemoryCost)]
471
pub struct Destroy {
472
    /// Reason code given for tearing down this circuit
473
    reason: DestroyReason,
474
}
475
impl Destroy {
476
    /// Create a new destroy cell.
477
4104
    pub fn new(reason: DestroyReason) -> Self {
478
4104
        Destroy { reason }
479
4104
    }
480
    /// Return the provided reason for destroying the circuit.
481
342
    pub fn reason(&self) -> DestroyReason {
482
342
        self.reason
483
342
    }
484
}
485
impl Body for Destroy {
486
20
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
487
20
        w.write_u8(self.reason.into());
488
20
        Ok(())
489
20
    }
490
}
491
impl Readable for Destroy {
492
456
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
493
456
        let reason = r.take_u8()?.into();
494
456
        Ok(Destroy { reason })
495
456
    }
496
}
497

            
498
caret_int! {
499
    /// Declared reason for ending a circuit.
500
    #[derive(Deftly)]
501
    #[derive_deftly(HasMemoryCost)]
502
    pub struct DestroyReason(u8) {
503
        /// No reason given.
504
        ///
505
        /// This is the only reason that clients send.
506
        NONE = 0,
507
        /// Protocol violation
508
        PROTOCOL = 1,
509
        /// Internal error.
510
        INTERNAL = 2,
511
        /// Client sent a TRUNCATE command.
512
        REQUESTED = 3,
513
        /// Relay is hibernating and not accepting requests
514
        HIBERNATING = 4,
515
        /// Ran out of memory, sockets, or circuit IDs
516
        RESOURCELIMIT = 5,
517
        /// Couldn't connect to relay.
518
        CONNECTFAILED = 6,
519
        /// Connected to a relay, but its OR identity wasn't as requested.
520
        OR_IDENTITY = 7,
521
        /// One of the OR channels carrying this circuit died.
522
        CHANNEL_CLOSED = 8,
523
        /// Circuit expired for being too dirty or old
524
        FINISHED = 9,
525
        /// Circuit construction took too long
526
        TIMEOUT = 10,
527
        /// Circuit was destroyed w/o client truncate (?)
528
        DESTROYED = 11,
529
        /// Request for unknown onion service
530
        NOSUCHSERVICE = 12
531
    }
532
}
533

            
534
impl DestroyReason {
535
    /// Return a human-readable string for this reason.
536
346
    pub fn human_str(&self) -> &'static str {
537
346
        match *self {
538
            DestroyReason::NONE => "No reason",
539
            DestroyReason::PROTOCOL => "Protocol violation",
540
            DestroyReason::INTERNAL => "Internal error",
541
            DestroyReason::REQUESTED => "Client sent a TRUNCATE command",
542
342
            DestroyReason::HIBERNATING => "Relay is hibernating and not accepting requests",
543
            DestroyReason::RESOURCELIMIT => "Relay ran out of resources",
544
2
            DestroyReason::CONNECTFAILED => "Couldn't connect to relay",
545
            DestroyReason::OR_IDENTITY => "Connected to relay with different OR identity",
546
            DestroyReason::CHANNEL_CLOSED => "The OR channels carrying this circuit died",
547
            DestroyReason::FINISHED => "Circuit expired for being too dirty or old",
548
            DestroyReason::TIMEOUT => "Circuit construction took too long",
549
            DestroyReason::DESTROYED => "Circuit was destroyed without client truncate",
550
            DestroyReason::NOSUCHSERVICE => "No such onion service",
551
2
            _ => "Unrecognized reason",
552
        }
553
346
    }
554
}
555

            
556
/// The netinfo message ends channel negotiation.
557
///
558
/// It tells the other party on the channel our view of the current time,
559
/// our own list of public addresses, and our view of its address.
560
///
561
/// When we get a netinfo cell, we can start creating circuits on a
562
/// channel and sending data.
563
#[derive(Clone, Debug, Deftly)]
564
#[derive_deftly(HasMemoryCost)]
565
pub struct Netinfo {
566
    /// Time when this cell was sent, or 0 if this cell is sent by a client.
567
    ///
568
    /// TODO-SPEC(nickm): Y2038 issue here.  Better add a new handshake version
569
    /// to solve it.  See
570
    /// [torspec#80](https://gitlab.torproject.org/tpo/core/torspec/-/issues/80).
571
    timestamp: u32,
572
    /// Observed address for party that did not send the netinfo cell.
573
    their_addr: Option<IpAddr>,
574
    /// Canonical addresses for the party that did send the netinfo cell.
575
    my_addr: Vec<IpAddr>,
576
}
577
/// helper: encode a single address in the form that netinfo messages expect
578
76
fn enc_one_netinfo_addr<W: Writer + ?Sized>(w: &mut W, addr: &IpAddr) {
579
76
    match addr {
580
68
        IpAddr::V4(ipv4) => {
581
68
            w.write_u8(0x04); // type.
582
68
            w.write_u8(4); // length.
583
68
            w.write_all(&ipv4.octets()[..]);
584
68
        }
585
8
        IpAddr::V6(ipv6) => {
586
8
            w.write_u8(0x06); // type.
587
8
            w.write_u8(16); // length.
588
8
            w.write_all(&ipv6.octets()[..]);
589
8
        }
590
    }
591
76
}
592
/// helper: take an address as encoded in a netinfo message
593
1254
fn take_one_netinfo_addr(r: &mut Reader<'_>) -> Result<Option<IpAddr>> {
594
1254
    let atype = r.take_u8()?;
595
1254
    let alen = r.take_u8()?;
596
1254
    let abody = r.take(alen as usize)?;
597
1254
    match (atype, alen) {
598
        (0x04, 4) => {
599
855
            let bytes = [abody[0], abody[1], abody[2], abody[3]];
600
855
            Ok(Some(IpAddr::V4(bytes.into())))
601
        }
602
        (0x06, 16) => {
603
            // TODO(nickm) is there a better way?
604
171
            let mut bytes = [0_u8; 16];
605
171
            bytes.copy_from_slice(abody);
606
171
            Ok(Some(IpAddr::V6(bytes.into())))
607
        }
608
228
        (_, _) => Ok(None),
609
    }
610
1254
}
611
impl Netinfo {
612
    /// Construct a new Netinfo to be sent by a client.
613
228
    pub fn from_client(their_addr: Option<IpAddr>) -> Self {
614
228
        Netinfo {
615
228
            timestamp: 0, // clients don't report their timestamps.
616
228
            their_addr,
617
228
            my_addr: Vec::new(), // clients don't report their addrs.
618
228
        }
619
228
    }
620
    /// Construct a new Netinfo to be sent by a relay
621
6
    pub fn from_relay<V>(timestamp: u32, their_addr: Option<IpAddr>, my_addrs: V) -> Self
622
6
    where
623
6
        V: Into<Vec<IpAddr>>,
624
    {
625
6
        let my_addr = my_addrs.into();
626
6
        Netinfo {
627
6
            timestamp,
628
6
            their_addr,
629
6
            my_addr,
630
6
        }
631
6
    }
632
    /// Return the time reported in this NETINFO cell.
633
228
    pub fn timestamp(&self) -> Option<std::time::SystemTime> {
634
        use std::time::{Duration, SystemTime};
635
228
        if self.timestamp == 0 {
636
57
            None
637
        } else {
638
171
            Some(SystemTime::UNIX_EPOCH + Duration::from_secs(self.timestamp.into()))
639
        }
640
228
    }
641

            
642
    /// Return a reference to the their address field.
643
    ///
644
    /// None is returned if their address is 0.0.0.0/:: (unspecified).
645
114
    pub fn their_addr(&self) -> Option<&IpAddr> {
646
114
        self.their_addr.as_ref()
647
114
    }
648

            
649
    /// Return a reference to the my address field.
650
114
    pub fn my_addrs(&self) -> &[IpAddr] {
651
114
        &self.my_addr
652
114
    }
653
}
654
impl Body for Netinfo {
655
64
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
656
64
        w.write_u32(self.timestamp);
657
64
        let their_addr = self
658
64
            .their_addr
659
64
            .unwrap_or_else(|| Ipv4Addr::UNSPECIFIED.into());
660
64
        enc_one_netinfo_addr(w, &their_addr);
661
64
        let n_addrs: u8 = self
662
64
            .my_addr
663
64
            .len()
664
64
            .try_into()
665
64
            .map_err(|_| EncodeError::BadLengthValue)?;
666
64
        w.write_u8(n_addrs);
667
76
        for addr in &self.my_addr {
668
12
            enc_one_netinfo_addr(w, addr);
669
12
        }
670
64
        Ok(())
671
64
    }
672
}
673
impl Readable for Netinfo {
674
627
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
675
627
        let timestamp = r.take_u32()?;
676
636
        let their_addr = take_one_netinfo_addr(r)?.filter(|a| !a.is_unspecified());
677
627
        let my_n_addrs = r.take_u8()?;
678
627
        let mut my_addr = Vec::with_capacity(my_n_addrs as usize);
679
627
        for _ in 0..my_n_addrs {
680
627
            if let Some(a) = take_one_netinfo_addr(r)? {
681
513
                my_addr.push(a);
682
513
            }
683
        }
684
627
        Ok(Netinfo {
685
627
            timestamp,
686
627
            their_addr,
687
627
            my_addr,
688
627
        })
689
627
    }
690
}
691

            
692
/// A Versions message begins channel negotiation.
693
///
694
/// Every channel must begin by sending a Versions message.  This message
695
/// lists the link protocol versions that this Tor implementation supports.
696
///
697
/// Note that we should never actually send Versions cells using the
698
/// usual channel cell encoding: Versions cells _always_ use two-byte
699
/// circuit IDs, whereas all the other cell types use four-byte
700
/// circuit IDs [assuming a non-obsolete version is negotiated].
701
#[derive(Clone, Debug, Deftly)]
702
#[derive_deftly(HasMemoryCost)]
703
pub struct Versions {
704
    /// List of supported link protocol versions
705
    versions: Vec<u16>,
706
}
707
impl Versions {
708
    /// Construct a new Versions message using a provided list of link
709
    /// protocols.
710
    ///
711
    /// Returns an error if the list of versions is too long.
712
58
    pub fn new<B>(vs: B) -> crate::Result<Self>
713
58
    where
714
58
        B: Into<Vec<u16>>,
715
    {
716
58
        let versions = vs.into();
717
58
        if versions.len() < (u16::MAX / 2) as usize {
718
58
            Ok(Self { versions })
719
        } else {
720
            Err(crate::Error::CantEncode("Too many versions"))
721
        }
722
58
    }
723
    /// Encode this VERSIONS cell in the manner expected for a handshake.
724
    ///
725
    /// (That's different from a standard cell encoding, since we
726
    /// have not negotiated versions yet, and so our circuit-ID length
727
    /// is an obsolete 2 bytes).
728
1425
    pub fn encode_for_handshake(self) -> EncodeResult<Vec<u8>> {
729
1425
        let mut v = Vec::new();
730
1425
        v.write_u16(0); // obsolete circuit ID length.
731
1425
        v.write_u8(ChanCmd::VERSIONS.into());
732
1425
        v.write_u16((self.versions.len() * 2) as u16); // message length.
733
1425
        self.encode_onto(&mut v)?;
734
1425
        Ok(v)
735
1425
    }
736
    /// Return the best (numerically highest) link protocol that is
737
    /// shared by this versions cell and my_protos.
738
912
    pub fn best_shared_link_protocol(&self, my_protos: &[u16]) -> Option<u16> {
739
        // NOTE: this implementation is quadratic, but it shouldn't matter
740
        // much so long as my_protos is small.
741
912
        let p = my_protos
742
912
            .iter()
743
2011
            .filter(|p| self.versions.contains(p))
744
1555
            .fold(0_u16, |a, b| u16::max(a, *b));
745
912
        if p == 0 { None } else { Some(p) }
746
912
    }
747
}
748
impl Body for Versions {
749
1539
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
750
4104
        for v in &self.versions {
751
2565
            w.write_u16(*v);
752
2565
        }
753
1539
        Ok(())
754
1539
    }
755
}
756
impl Readable for Versions {
757
1026
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
758
1026
        let mut versions = Vec::new();
759
3363
        while r.remaining() > 0 {
760
2337
            versions.push(r.take_u16()?);
761
        }
762
1026
        Ok(Versions { versions })
763
1026
    }
764
}
765

            
766
caret_int! {
767
    /// A ChanCmd is the type of a channel cell.  The value of the ChanCmd
768
    /// indicates the meaning of the cell, and (possibly) its length.
769
    #[derive(Deftly)]
770
    #[derive_deftly(HasMemoryCost)]
771
    pub struct PaddingNegotiateCmd(u8) {
772
        /// Start padding
773
        START = 2,
774

            
775
        /// Stop padding
776
        STOP = 1,
777
    }
778
}
779

            
780
/// A PaddingNegotiate message is used to negotiate channel padding.
781
///
782
/// Sent by a client to its guard node,
783
/// to instruct the relay to enable/disable channel padding.
784
/// (Not relevant for channels used only for directory lookups,
785
/// nor inter-relay channels.)
786
/// See `padding-spec.txt`, section 2.2.
787
///
788
/// This message is constructed in the channel manager and transmitted by the reactor.
789
///
790
/// The `Default` impl is the same as [`start_default()`](PaddingNegotiate::start_default`)
791
#[derive(Clone, Debug, Eq, PartialEq, Deftly)]
792
#[derive_deftly(HasMemoryCost)]
793
pub struct PaddingNegotiate {
794
    /// Whether to start or stop padding
795
    command: PaddingNegotiateCmd,
796
    /// Suggested lower-bound value for inter-packet timeout in msec.
797
    // TODO(nickm) is that right?
798
    ito_low_ms: u16,
799
    /// Suggested upper-bound value for inter-packet timeout in msec.
800
    // TODO(nickm) is that right?
801
    ito_high_ms: u16,
802
}
803
impl PaddingNegotiate {
804
    /// Create a new PADDING_NEGOTIATE START message requesting consensus timing parameters.
805
    ///
806
    /// This message restores the state to the one which exists at channel startup.
807
10545
    pub fn start_default() -> Self {
808
        // Tor Spec section 7.3, padding-spec section 2.5.
809
10545
        Self {
810
10545
            command: PaddingNegotiateCmd::START,
811
10545
            ito_low_ms: 0,
812
10545
            ito_high_ms: 0,
813
10545
        }
814
10545
    }
815

            
816
    /// Create a new PADDING_NEGOTIATE START message.
817
57
    pub fn start(ito_low: IntegerMilliseconds<u16>, ito_high: IntegerMilliseconds<u16>) -> Self {
818
        // Tor Spec section 7.3
819
57
        Self {
820
57
            command: PaddingNegotiateCmd::START,
821
57
            ito_low_ms: ito_low.as_millis(),
822
57
            ito_high_ms: ito_high.as_millis(),
823
57
        }
824
57
    }
825

            
826
    /// Create a new PADDING_NEGOTIATE STOP message.
827
2679
    pub fn stop() -> Self {
828
        // Tor Spec section 7.3
829
2679
        Self {
830
2679
            command: PaddingNegotiateCmd::STOP,
831
2679
            ito_low_ms: 0,
832
2679
            ito_high_ms: 0,
833
2679
        }
834
2679
    }
835

            
836
    /// Construct from the three fields: command, low_ms, high_ms, as a tuple
837
    ///
838
    /// For testing only
839
    #[cfg(feature = "testing")]
840
1368
    pub fn from_raw(command: PaddingNegotiateCmd, ito_low_ms: u16, ito_high_ms: u16) -> Self {
841
1368
        PaddingNegotiate {
842
1368
            command,
843
1368
            ito_low_ms,
844
1368
            ito_high_ms,
845
1368
        }
846
1368
    }
847
}
848
impl Default for PaddingNegotiate {
849
5415
    fn default() -> Self {
850
5415
        Self::start_default()
851
5415
    }
852
}
853

            
854
impl Body for PaddingNegotiate {
855
8
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
856
8
        w.write_u8(0); // version
857
8
        w.write_u8(self.command.get());
858
8
        w.write_u16(self.ito_low_ms);
859
8
        w.write_u16(self.ito_high_ms);
860
8
        Ok(())
861
8
    }
862
}
863
impl Readable for PaddingNegotiate {
864
171
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
865
171
        let v = r.take_u8()?;
866
171
        if v != 0 {
867
57
            return Err(Error::InvalidMessage(
868
57
                "Unrecognized padding negotiation version".into(),
869
57
            ));
870
114
        }
871
114
        let command = r.take_u8()?.into();
872
114
        let ito_low_ms = r.take_u16()?;
873
114
        let ito_high_ms = r.take_u16()?;
874
114
        Ok(PaddingNegotiate {
875
114
            command,
876
114
            ito_low_ms,
877
114
            ito_high_ms,
878
114
        })
879
171
    }
880
}
881

            
882
/// A single certificate in a Certs cell.
883
///
884
/// The formats used here are implemented in tor-cert. Ed25519Cert is the
885
/// most common.
886
#[derive(Clone, Debug, Deftly)]
887
#[derive_deftly(HasMemoryCost)]
888
struct TorCert {
889
    /// Type code for this certificate.
890
    certtype: u8,
891
    /// Encoded certificate
892
    cert: Vec<u8>,
893
}
894
/// encode a single TorCert `c` onto a Writer `w`.
895
20
fn enc_one_tor_cert<W: Writer + ?Sized>(w: &mut W, c: &TorCert) -> EncodeResult<()> {
896
20
    w.write_u8(c.certtype);
897
20
    let cert_len: u16 = c
898
20
        .cert
899
20
        .len()
900
20
        .try_into()
901
20
        .map_err(|_| EncodeError::BadLengthValue)?;
902
20
    w.write_u16(cert_len);
903
20
    w.write_all(&c.cert[..]);
904
20
    Ok(())
905
20
}
906
/// Try to extract a TorCert from the reader `r`.
907
627
fn take_one_tor_cert(r: &mut Reader<'_>) -> Result<TorCert> {
908
627
    let certtype = r.take_u8()?;
909
570
    let certlen = r.take_u16()?;
910
570
    let cert = r.take(certlen as usize)?;
911
570
    Ok(TorCert {
912
570
        certtype,
913
570
        cert: cert.into(),
914
570
    })
915
627
}
916
/// A Certs message is used as part of the channel handshake to send
917
/// additional certificates.
918
///
919
/// These certificates are not presented as part of the TLS handshake.
920
/// Originally this was meant to make Tor TLS handshakes look "normal", but
921
/// nowadays it serves less purpose, especially now that we have TLS 1.3.
922
///
923
/// Every relay sends this message as part of channel negotiation;
924
/// clients do not send them.
925
#[derive(Clone, Debug, Deftly)]
926
#[derive_deftly(HasMemoryCost)]
927
pub struct Certs {
928
    /// The certificates in this cell
929
    certs: Vec<TorCert>,
930
}
931
impl Certs {
932
    /// Return a new empty certs cell.
933
1311
    pub fn new_empty() -> Self {
934
1311
        Certs { certs: Vec::new() }
935
1311
    }
936
    /// Add a new encoded certificate to this cell.
937
    ///
938
    /// Does not check anything about the well-formedness of the certificate.
939
68
    pub fn push_cert_body<B>(&mut self, certtype: tor_cert::CertType, cert: B)
940
68
    where
941
68
        B: Into<Vec<u8>>,
942
    {
943
68
        let certtype = certtype.into();
944
68
        let cert = cert.into();
945
68
        self.certs.push(TorCert { certtype, cert });
946
68
    }
947

            
948
    /// Return the body of the certificate tagged with 'tp', if any.
949
2223
    pub fn cert_body(&self, tp: tor_cert::CertType) -> Option<&[u8]> {
950
2223
        let tp: u8 = tp.into();
951
2223
        self.certs
952
2223
            .iter()
953
5967
            .find(|c| c.certtype == tp)
954
2256
            .map(|c| &c.cert[..])
955
2223
    }
956

            
957
    /// Look for a certificate of type 'tp' in this cell; return it if
958
    /// there is one.
959
1368
    pub fn parse_ed_cert(&self, tp: tor_cert::CertType) -> crate::Result<tor_cert::KeyUnknownCert> {
960
1368
        let body = self
961
1368
            .cert_body(tp)
962
1371
            .ok_or_else(|| crate::Error::ChanProto(format!("Missing {} certificate", tp)))?;
963

            
964
1197
        let cert = tor_cert::Ed25519Cert::decode(body).map_err(|be| crate::Error::BytesErr {
965
57
            err: be,
966
            parsed: "ed25519 certificate",
967
58
        })?;
968
1140
        if cert.peek_cert_type() != tp {
969
            return Err(crate::Error::ChanProto(format!(
970
                "Found a {} certificate labeled as {}",
971
                cert.peek_cert_type(),
972
                tp
973
            )));
974
1140
        }
975

            
976
1140
        Ok(cert)
977
1368
    }
978
}
979

            
980
impl Body for Certs {
981
16
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
982
16
        let n_certs: u8 = self
983
16
            .certs
984
16
            .len()
985
16
            .try_into()
986
16
            .map_err(|_| EncodeError::BadLengthValue)?;
987
16
        w.write_u8(n_certs);
988
36
        for c in &self.certs {
989
20
            enc_one_tor_cert(w, c)?;
990
        }
991
16
        Ok(())
992
16
    }
993
}
994
impl Readable for Certs {
995
570
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
996
570
        let n = r.take_u8()?;
997
570
        let mut certs = Vec::new();
998
570
        for _ in 0..n {
999
627
            certs.push(take_one_tor_cert(r)?);
        }
513
        Ok(Certs { certs })
570
    }
}
/// Length of the body for an authentication challenge
const CHALLENGE_LEN: usize = 32;
/// An AuthChallenge message is part of negotiation, sent by
/// responders to initiators.
///
/// The AuthChallenge cell is used to ensure that some unpredictable material
/// has been sent on the channel, and to tell the initiator what
/// authentication methods will be accepted.
///
/// Clients can safely ignore this message: they don't need to authenticate.
#[derive(Clone, Debug, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct AuthChallenge {
    /// Random challenge to be used in generating response
    challenge: [u8; CHALLENGE_LEN],
    /// List of permitted authentication methods
    methods: Vec<u16>,
}
impl AuthChallenge {
    /// Construct a new AuthChallenge cell with a given challenge
    /// value (chosen randomly) and a set of acceptable authentication methods.
14
    pub fn new<B, M>(challenge: B, methods: M) -> Self
14
    where
14
        B: Into<[u8; CHALLENGE_LEN]>,
14
        M: Into<Vec<u16>>,
    {
14
        AuthChallenge {
14
            challenge: challenge.into(),
14
            methods: methods.into(),
14
        }
14
    }
    /// Return a reference to the list of methods.
    pub fn methods(&self) -> &[u16] {
        &self.methods
    }
}
impl Body for AuthChallenge {
16
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
16
        w.write_all(&self.challenge[..]);
16
        let n_methods = self
16
            .methods
16
            .len()
16
            .try_into()
16
            .map_err(|_| EncodeError::BadLengthValue)?;
16
        w.write_u16(n_methods);
36
        for m in self.methods {
20
            w.write_u16(m);
20
        }
16
        Ok(())
16
    }
}
impl Readable for AuthChallenge {
741
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
        //let challenge = r.take(CHALLENGE_LEN)?.into();
741
        let challenge = r.extract()?;
741
        let n_methods = r.take_u16()?;
741
        let mut methods = Vec::new();
741
        for _ in 0..n_methods {
1083
            methods.push(r.take_u16()?);
        }
741
        Ok(AuthChallenge { challenge, methods })
741
    }
}
/// Part of negotiation: sent by initiators to responders.
///
/// The Authenticate cell proves the initiator's identity to the
/// responder, even if TLS client authentication was not used.
///
/// Clients do not use this.
#[derive(Clone, Debug, Deftly, Eq, PartialEq)]
#[derive_deftly(HasMemoryCost)]
pub struct Authenticate {
    /// Authentication method in use
    authtype: u16,
    /// Encoded authentication object
    auth: Vec<u8>,
}
impl Authenticate {
    /// Create a new Authenticate message from a given type and body.
2
    pub fn new<B>(authtype: u16, body: B) -> Self
2
    where
2
        B: Into<Vec<u8>>,
    {
2
        Authenticate {
2
            authtype,
2
            auth: body.into(),
2
        }
2
    }
}
impl Body for Authenticate {
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
4
        w.write_u16(self.authtype);
4
        let authlen = self
4
            .auth
4
            .len()
4
            .try_into()
4
            .map_err(|_| EncodeError::BadLengthValue)?;
4
        w.write_u16(authlen);
4
        w.write_all(&self.auth[..]);
4
        Ok(())
4
    }
}
impl Readable for Authenticate {
57
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
57
        let authtype = r.take_u16()?;
57
        let authlen = r.take_u16()?;
57
        let auth = r.take(authlen as usize)?.into();
57
        Ok(Authenticate { authtype, auth })
57
    }
}
/// Holds any message whose command we don't recognize.
///
/// Well-behaved Tor implementations are required to ignore commands
/// like this.
///
/// TODO: I believe that this is not a risky case of Postel's law,
/// since it is only for channels, but we should be careful here.
#[derive(Clone, Debug, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Unrecognized {
    /// The channel command that we got with this cell
    cmd: ChanCmd,
    /// The contents of the cell
    content: Vec<u8>,
}
impl Unrecognized {
    /// Construct a new cell of arbitrary or unrecognized type.
6
    pub fn new<B>(cmd: ChanCmd, content: B) -> Self
6
    where
6
        B: Into<Vec<u8>>,
    {
6
        let content = content.into();
6
        Unrecognized { cmd, content }
6
    }
    /// Return the command from this cell.
228
    pub fn cmd(&self) -> ChanCmd {
228
        self.cmd
228
    }
    /// Take an unrecognized cell's body from a reader `r`, and apply
    /// the given command to it.
228
    pub fn decode_with_cmd(cmd: ChanCmd, r: &mut Reader<'_>) -> Result<Unrecognized> {
228
        let mut u = Unrecognized::take_from(r)?;
228
        u.cmd = cmd;
228
        Ok(u)
228
    }
}
impl Body for Unrecognized {
12
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
12
        w.write_all(&self.content[..]);
12
        Ok(())
12
    }
}
impl Readable for Unrecognized {
228
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
        Ok(Unrecognized {
228
            cmd: 0.into(),
228
            content: r.take(r.remaining())?.into(),
        })
228
    }
}
/// Helper: declare a From<> implementation from message types for
/// cells that don't take a circid.
macro_rules! msg_into_cell {
    ($body:ident) => {
        impl From<$body> for super::AnyChanCell {
114
            fn from(body: $body) -> super::AnyChanCell {
114
                super::AnyChanCell {
114
                    circid: None,
114
                    msg: body.into(),
114
                }
114
            }
        }
    };
}
msg_into_cell!(Padding);
msg_into_cell!(Vpadding);
msg_into_cell!(Netinfo);
msg_into_cell!(Versions);
msg_into_cell!(PaddingNegotiate);
msg_into_cell!(Certs);
msg_into_cell!(AuthChallenge);
msg_into_cell!(Authenticate);
/// Helper: declare a ChanMsg implementation for a message type that has a
/// fixed command.
//
// TODO: It might be better to merge Body with ChanMsg, but that is complex,
// since their needs are _slightly_ different.
//
// TODO: If we *do* make the change above, then perhaps we should also implement
// our restricted enums in terms of this, so that there is only one instance of
// [<$body:snake:upper>]
macro_rules! msg_impl_chanmsg {
    ($($body:ident,)*) =>
    {paste::paste!{
       $(impl crate::chancell::ChanMsg for $body {
14250
            fn cmd(&self) -> crate::chancell::ChanCmd { crate::chancell::ChanCmd::[< $body:snake:upper >] }
12
            fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()> {
12
                crate::chancell::msg::Body::encode_onto(self, w)
12
            }
969
            fn decode_from_reader(cmd: ChanCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
969
                if cmd != crate::chancell::ChanCmd::[< $body:snake:upper >] {
                    return Err(tor_bytes::Error::InvalidMessage(
                        format!("Expected {} command; got {cmd}", stringify!([< $body:snake:upper >])).into()
                    ));
969
                }
969
                crate::chancell::msg::Body::decode_from_reader(r)
969
            }
        })*
    }}
}
// We implement ChanMsg for every body type, so that you can write code that does
// e.g. ChanCell<Relay>.
msg_impl_chanmsg!(
    Padding,
    Vpadding,
    Create,
    CreateFast,
    Create2,
    Created,
    CreatedFast,
    Created2,
    Relay,
    RelayEarly,
    Destroy,
    Netinfo,
    Versions,
    PaddingNegotiate,
    Certs,
    AuthChallenge,
    Authenticate,
);
#[cfg(test)]
mod test {
    // @@ begin test lint list maintained by maint/add_warning @@
    #![allow(clippy::bool_assert_comparison)]
    #![allow(clippy::clone_on_copy)]
    #![allow(clippy::dbg_macro)]
    #![allow(clippy::mixed_attributes_style)]
    #![allow(clippy::print_stderr)]
    #![allow(clippy::print_stdout)]
    #![allow(clippy::single_char_pattern)]
    #![allow(clippy::unwrap_used)]
    #![allow(clippy::unchecked_time_subtraction)]
    #![allow(clippy::useless_vec)]
    #![allow(clippy::needless_pass_by_value)]
    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
    use super::*;
    #[test]
    fn destroy_reason() {
        let r1 = DestroyReason::CONNECTFAILED;
        assert_eq!(r1.human_str(), "Couldn't connect to relay");
        let r2 = DestroyReason::from(200); // not a specified number.
        assert_eq!(r2.human_str(), "Unrecognized reason");
    }
}