1
//! Encoding and decoding for relay messages
2
//!
3
//! Relay messages are sent along circuits, inside RELAY or RELAY_EARLY
4
//! cells.
5

            
6
use super::flow_ctrl::{Xoff, Xon};
7
use super::{RelayCellFormat, RelayCmd};
8
use crate::chancell::CELL_DATA_LEN;
9
use crate::chancell::msg::{
10
    DestroyReason, HandshakeType, TAP_C_HANDSHAKE_LEN, TAP_S_HANDSHAKE_LEN,
11
};
12
use caret::caret_int;
13
use derive_deftly::Deftly;
14
use std::fmt::Write;
15
use std::net::{IpAddr, Ipv4Addr};
16
use std::num::NonZeroU8;
17
use tor_bytes::{EncodeError, EncodeResult, Error, Result};
18
use tor_bytes::{Readable, Reader, Writeable, Writer};
19
use tor_linkspec::EncodedLinkSpec;
20
use tor_llcrypto::pk::rsa::RsaIdentity;
21
use tor_llcrypto::util::ct::CtByteArray;
22
use tor_memquota::{derive_deftly_template_HasMemoryCost, memory_cost_structural_copy};
23

            
24
use bitflags::bitflags;
25

            
26
#[cfg(feature = "conflux")]
27
pub use super::conflux::{ConfluxLink, ConfluxLinked, ConfluxLinkedAck, ConfluxSwitch};
28

            
29
#[cfg(feature = "hs")]
30
pub use super::hs::{
31
    EstablishRendezvous, IntroEstablished, Introduce1, Introduce2, IntroduceAck, Rendezvous1,
32
    Rendezvous2, RendezvousEstablished, est_intro::EstablishIntro,
33
};
34
#[cfg(feature = "experimental-udp")]
35
pub use super::udp::{ConnectUdp, ConnectedUdp, Datagram};
36

            
37
crate::restrict::restricted_msg! {
38
/// A single parsed relay message, sent or received along a circuit
39
#[derive(Debug, Clone, Deftly)]
40
#[derive_deftly(HasMemoryCost)]
41
#[non_exhaustive]
42
@omit_from "avoid_conflict_with_a_blanket_implementation"
43
pub enum AnyRelayMsg : RelayMsg {
44
    /// Create a stream
45
    Begin,
46
    /// Send data on a stream
47
    Data,
48
    /// Close a stream
49
    End,
50
    /// Successful response to a Begin message
51
    Connected,
52
    /// For flow control
53
    Sendme,
54
    /// Extend a circuit to a new hop (deprecated)
55
    Extend,
56
    /// Successful response to an Extend message (deprecated)
57
    Extended,
58
    /// Extend a circuit to a new hop
59
    Extend2,
60
    /// Successful response to an Extend2 message
61
    Extended2,
62
    /// Partially close a circuit
63
    Truncate,
64
    /// Tell the client that a circuit has been partially closed
65
    Truncated,
66
    /// Used for padding
67
    Drop,
68
    /// Launch a DNS request
69
    Resolve,
70
    /// Response to a Resolve message
71
    Resolved,
72
    /// Start a directory stream
73
    BeginDir,
74
    /// Start a UDP stream.
75
    [feature = "experimental-udp"]
76
    ConnectUdp,
77
    /// Successful response to a ConnectUdp message
78
    [feature = "experimental-udp"]
79
    ConnectedUdp,
80
    /// UDP stream data
81
    [feature = "experimental-udp"]
82
    Datagram,
83
    /// Link circuits together at the receiving endpoint
84
    [feature = "conflux"]
85
    ConfluxLink,
86
    /// Confirm that the circuits were linked
87
    [feature = "conflux"]
88
    ConfluxLinked,
89
    /// Acknowledge the linkage of the circuits, for RTT measurement.
90
    [feature = "conflux"]
91
    ConfluxLinkedAck,
92
    /// Switch to another leg in an already linked circuit construction.
93
    [feature = "conflux"]
94
    ConfluxSwitch,
95
    /// Update a stream's transmit rate limit.
96
    Xon,
97
    /// Disable transmitting on a stream.
98
    Xoff,
99
    /// Establish Introduction
100
    [feature = "hs"]
101
    EstablishIntro,
102
    /// Establish Rendezvous
103
    [feature = "hs"]
104
    EstablishRendezvous,
105
    /// Introduce1 (client to introduction point)
106
    [feature = "hs"]
107
    Introduce1,
108
    /// Introduce2 (introduction point to service)
109
    [feature = "hs"]
110
    Introduce2,
111
    /// Rendezvous1 (service to rendezvous point)
112
    [feature = "hs"]
113
    Rendezvous1,
114
    /// Rendezvous2 (rendezvous point to client)
115
    [feature = "hs"]
116
    Rendezvous2,
117
    /// Acknowledgement for EstablishIntro.
118
    [feature = "hs"]
119
    IntroEstablished,
120
    /// Acknowledgment for EstablishRendezvous.
121
    [feature = "hs"]
122
    RendezvousEstablished,
123
    /// Acknowledgement for Introduce1.
124
    [feature = "hs"]
125
    IntroduceAck,
126

            
127
    _ =>
128
    /// An unrecognized command.
129
    Unrecognized,
130
    }
131
}
132

            
133
/// Internal: traits in common different cell bodies.
134
pub trait Body: Sized {
135
    /// Decode a relay cell body from a provided reader.
136
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self>;
137
    /// Encode the body of this cell into the end of a writer.
138
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()>;
139
}
140

            
141
bitflags! {
142
    /// A set of recognized flags that can be attached to a begin cell.
143
    ///
144
    /// For historical reasons, these flags are constructed so that 0
145
    /// is a reasonable default for all of them.
146
    #[derive(Clone, Copy, Debug)]
147
    pub struct BeginFlags : u32 {
148
        /// The client would accept a connection to an IPv6 address.
149
        const IPV6_OKAY = (1<<0);
150
        /// The client would not accept a connection to an IPv4 address.
151
        const IPV4_NOT_OKAY = (1<<1);
152
        /// The client would rather have a connection to an IPv6 address.
153
        const IPV6_PREFERRED = (1<<2);
154
    }
155
}
156
memory_cost_structural_copy!(BeginFlags);
157
impl From<u32> for BeginFlags {
158
4503
    fn from(v: u32) -> Self {
159
4503
        BeginFlags::from_bits_truncate(v)
160
4503
    }
161
}
162

            
163
/// A preference for IPv4 vs IPv6 addresses; usable as a nicer frontend for
164
/// BeginFlags.
165
#[derive(Clone, Default, Copy, Debug, Eq, PartialEq)]
166
#[non_exhaustive]
167
pub enum IpVersionPreference {
168
    /// Only IPv4 is allowed.
169
    Ipv4Only,
170
    /// IPv4 and IPv6 are both allowed, and IPv4 is preferred.
171
    #[default]
172
    Ipv4Preferred,
173
    /// IPv4 and IPv6 are both allowed, and IPv6 is preferred.
174
    Ipv6Preferred,
175
    /// Only IPv6 is allowed.
176
    Ipv6Only,
177
}
178
impl From<IpVersionPreference> for BeginFlags {
179
2394
    fn from(v: IpVersionPreference) -> Self {
180
        use IpVersionPreference::*;
181
2394
        match v {
182
            Ipv4Only => 0.into(),
183
2394
            Ipv4Preferred => BeginFlags::IPV6_OKAY,
184
            Ipv6Preferred => BeginFlags::IPV6_OKAY | BeginFlags::IPV6_PREFERRED,
185
            Ipv6Only => BeginFlags::IPV4_NOT_OKAY,
186
        }
187
2394
    }
188
}
189

            
190
/// A Begin message creates a new data stream.
191
///
192
/// Upon receiving a Begin message, relays should try to open a new stream
193
/// for the client, if their exit policy permits, and associate it with a
194
/// new TCP connection to the target address.
195
///
196
/// If the exit decides to reject the Begin message, or if the TCP
197
/// connection fails, the exit should send an End message.
198
///
199
/// Clients should reject these messages.
200
#[derive(Debug, Clone, Deftly)]
201
#[derive_deftly(HasMemoryCost)]
202
pub struct Begin {
203
    /// Ascii string describing target address
204
    addr: Vec<u8>,
205
    /// Target port
206
    port: u16,
207
    /// Flags that describe how to resolve the address
208
    flags: BeginFlags,
209
}
210

            
211
impl Begin {
212
    /// Construct a new Begin cell
213
132
    pub fn new<F>(addr: &str, port: u16, flags: F) -> crate::Result<Self>
214
132
    where
215
132
        F: Into<BeginFlags>,
216
    {
217
132
        if !addr.is_ascii() {
218
2
            return Err(crate::Error::BadStreamAddress);
219
130
        }
220
130
        let mut addr = addr.to_string();
221
130
        addr.make_ascii_lowercase();
222
130
        Ok(Begin {
223
130
            addr: addr.into_bytes(),
224
130
            port,
225
130
            flags: flags.into(),
226
130
        })
227
132
    }
228

            
229
    /// Return the address requested in this message.
230
    pub fn addr(&self) -> &[u8] {
231
        &self.addr[..]
232
    }
233

            
234
    /// Return the port requested by this message.
235
    pub fn port(&self) -> u16 {
236
        self.port
237
    }
238

            
239
    /// Return the set of flags provided in this message.
240
    pub fn flags(&self) -> BeginFlags {
241
        self.flags
242
    }
243
}
244

            
245
impl Body for Begin {
246
3705
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
247
3648
        let addr = {
248
3705
            if r.peek(1)? == b"[" {
249
                // IPv6 address
250
114
                r.advance(1)?;
251
114
                let a = r.take_until(b']')?;
252
114
                let colon = r.take_u8()?;
253
114
                if colon != b':' {
254
57
                    return Err(Error::InvalidMessage("missing port in begin cell".into()));
255
57
                }
256
57
                a
257
            } else {
258
                // IPv4 address, or hostname.
259
3591
                r.take_until(b':')?
260
            }
261
        };
262
3648
        let port = r.take_until(0)?;
263
3648
        let flags = if r.remaining() >= 4 { r.take_u32()? } else { 0 };
264

            
265
3648
        if !addr.is_ascii() {
266
57
            return Err(Error::InvalidMessage(
267
57
                "target address in begin cell not ascii".into(),
268
57
            ));
269
3591
        }
270

            
271
3591
        let port = std::str::from_utf8(port)
272
3591
            .map_err(|_| Error::InvalidMessage("port in begin cell not utf8".into()))?;
273

            
274
3591
        let port = port
275
3591
            .parse()
276
3591
            .map_err(|_| Error::InvalidMessage("port in begin cell not a valid port".into()))?;
277

            
278
3591
        Ok(Begin {
279
3591
            addr: addr.into(),
280
3591
            port,
281
3591
            flags: flags.into(),
282
3591
        })
283
3705
    }
284
136
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
285
136
        if self.addr.contains(&b':') {
286
4
            w.write_u8(b'[');
287
4
            w.write_all(&self.addr[..]);
288
4
            w.write_u8(b']');
289
132
        } else {
290
132
            w.write_all(&self.addr[..]);
291
132
        }
292
136
        w.write_u8(b':');
293
136
        w.write_all(self.port.to_string().as_bytes());
294
136
        w.write_u8(0);
295
136
        if self.flags.bits() != 0 {
296
124
            w.write_u32(self.flags.bits());
297
128
        }
298
136
        Ok(())
299
136
    }
300
}
301

            
302
/// A Data message represents data sent along a stream.
303
///
304
/// Upon receiving a Data message for a live stream, the client or
305
/// exit sends that data onto the associated TCP connection.
306
///
307
/// These messages hold between 1 and [Data::MAXLEN] bytes of data each;
308
/// they are the most numerous messages on the Tor network.
309
#[derive(Debug, Clone, Deftly)]
310
#[derive_deftly(HasMemoryCost)]
311
pub struct Data {
312
    /// Contents of the cell, to be sent on a specific stream
313
    ///
314
    /// INVARIANT: Holds between 1 and [`Data::MAXLEN`] bytes, inclusive.
315
    //
316
    // TODO: There's a good case to be made that this should be a BoxedCellBody
317
    // instead, to avoid allocations and copies.  But first probably we should
318
    // figure out how proposal 340 will work with this.  Possibly, we will wind
319
    // up using `bytes` or something.
320
    body: Vec<u8>,
321
}
322
impl Data {
323
    /// The longest allowable body length for a single V0 data cell.
324
    ///
325
    /// Relay command (1) + 'Recognized' (2) + StreamID (2) + Digest (4) + Length (2) = 11
326
    pub const MAXLEN_V0: usize = CELL_DATA_LEN - 11;
327

            
328
    /// The longest allowable body length for a single V1 data cell.
329
    ///
330
    /// Tag (16) + Relay command (1) + Length (2) + StreamID (2) = 21
331
    pub const MAXLEN_V1: usize = CELL_DATA_LEN - 21;
332

            
333
    /// The longest allowable body length for any data cell.
334
    ///
335
    /// Note that this value is too large to fit into a v1 relay cell;
336
    /// see [`MAXLEN_V1`](Data::MAXLEN_V1) if you are making a v1 data cell.
337
    ///
338
    pub const MAXLEN: usize = Data::MAXLEN_V0;
339

            
340
    /// Construct a new data cell.
341
    ///
342
    /// Returns an error if `inp` is longer than [`Data::MAXLEN`] bytes.
343
3135
    pub fn new(inp: &[u8]) -> crate::Result<Self> {
344
3135
        if inp.len() > Data::MAXLEN {
345
57
            return Err(crate::Error::CantEncode("Data message too long"));
346
3078
        }
347
3078
        if inp.is_empty() {
348
            return Err(crate::Error::CantEncode("Empty data message"));
349
3078
        }
350
3078
        Ok(Self::new_unchecked(inp.into()))
351
3135
    }
352

            
353
    /// Construct a new data cell, taking as many bytes from `inp`
354
    /// as possible.
355
    ///
356
    /// Return the data cell, and a slice holding any bytes that
357
    /// wouldn't fit (if any).
358
    ///
359
    /// Returns None if the input was empty.
360
122721
    pub fn try_split_from(version: RelayCellFormat, inp: &[u8]) -> Option<(Self, &[u8])> {
361
122721
        if inp.is_empty() {
362
            return None;
363
122721
        }
364
122721
        let upper_bound = Self::max_body_len(version);
365
122721
        let len = std::cmp::min(inp.len(), upper_bound);
366
122721
        let (data, remainder) = inp.split_at(len);
367
122721
        Some((Self::new_unchecked(data.into()), remainder))
368
122721
    }
369

            
370
    /// Construct a new data cell from a provided vector of bytes.
371
    ///
372
    /// The vector _must_ not have more than [`Data::MAXLEN`] bytes, and must
373
    /// not be empty.
374
125799
    fn new_unchecked(body: Vec<u8>) -> Self {
375
125799
        debug_assert!((1..=Data::MAXLEN).contains(&body.len()));
376
125799
        Data { body }
377
125799
    }
378

            
379
    /// Return the maximum allowable body length for a Data message
380
    /// using the provided `format`.
381
126141
    pub fn max_body_len(format: RelayCellFormat) -> usize {
382
126141
        match format {
383
126141
            RelayCellFormat::V0 => Self::MAXLEN_V0,
384
            RelayCellFormat::V1 => Self::MAXLEN_V1,
385
        }
386
126141
    }
387
}
388
impl From<Data> for Vec<u8> {
389
2508
    fn from(data: Data) -> Vec<u8> {
390
2508
        data.body
391
2508
    }
392
}
393
impl AsRef<[u8]> for Data {
394
144267
    fn as_ref(&self) -> &[u8] {
395
144267
        &self.body[..]
396
144267
    }
397
}
398

            
399
impl Body for Data {
400
114171
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
401
114171
        if r.remaining() == 0 {
402
            return Err(Error::InvalidMessage("Empty DATA message".into()));
403
114171
        }
404
        Ok(Data {
405
114171
            body: r.take(r.remaining())?.into(),
406
        })
407
114171
    }
408
4314
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
409
4314
        w.write_all(&self.body);
410
4314
        Ok(())
411
4314
    }
412
}
413

            
414
/// An End message tells the other end of the circuit to close a stream.
415
///
416
/// Note that End messages do not implement a true half-closed state,
417
/// so after sending an End message each party needs to wait a while
418
/// to be sure that the stream is completely dead.
419
#[derive(Debug, Clone, Deftly)]
420
#[derive_deftly(HasMemoryCost)]
421
pub struct End {
422
    /// Reason for closing the stream
423
    reason: EndReason,
424
    /// If the reason is EXITPOLICY, this holds the resolved address an
425
    /// associated TTL.  The TTL is set to MAX if none was given.
426
    addr: Option<(IpAddr, u32)>,
427
}
428

            
429
caret_int! {
430
    /// A declared reason for closing a stream
431
    #[derive(Deftly)]
432
    #[derive_deftly(HasMemoryCost)]
433
    pub struct EndReason(u8) {
434
        /// Closing a stream because of an unspecified reason.
435
        ///
436
        /// This is the only END reason that clients send.
437
        MISC = 1,
438
        /// Couldn't look up hostname.
439
        RESOLVEFAILED = 2,
440
        /// Remote host refused connection.
441
        CONNECTREFUSED = 3,
442
        /// Closing a stream because of an exit-policy violation.
443
        EXITPOLICY = 4,
444
        /// Circuit destroyed
445
        DESTROY = 5,
446
        /// Anonymized TCP connection was closed
447
        DONE = 6,
448
        /// Connection timed out, or OR timed out while connecting
449
        TIMEOUT = 7,
450
        /// No route to target destination.
451
        NOROUTE = 8,
452
        /// OR is entering hibernation and not handling requests
453
        HIBERNATING = 9,
454
        /// Internal error at the OR
455
        INTERNAL = 10,
456
        /// Ran out of resources to fulfill requests
457
        RESOURCELIMIT = 11,
458
        /// Connection unexpectedly reset
459
        CONNRESET = 12,
460
        /// Tor protocol violation
461
        TORPROTOCOL = 13,
462
        /// BEGIN_DIR cell at a non-directory-cache.
463
        NOTDIRECTORY = 14,
464
    }
465
}
466

            
467
impl tor_error::HasKind for EndReason {
468
    fn kind(&self) -> tor_error::ErrorKind {
469
        use EndReason as E;
470
        use tor_error::ErrorKind as EK;
471
        match *self {
472
            E::MISC => EK::RemoteStreamError,
473
            E::RESOLVEFAILED => EK::RemoteHostResolutionFailed,
474
            E::CONNECTREFUSED => EK::RemoteConnectionRefused,
475
            E::EXITPOLICY => EK::ExitPolicyRejected,
476
            E::DESTROY => EK::CircuitCollapse,
477
            E::DONE => EK::RemoteStreamClosed,
478
            E::TIMEOUT => EK::ExitTimeout,
479
            E::NOROUTE => EK::RemoteNetworkFailed,
480
            E::RESOURCELIMIT | E::HIBERNATING => EK::RelayTooBusy,
481
            E::INTERNAL | E::TORPROTOCOL | E::NOTDIRECTORY => EK::TorProtocolViolation,
482
            E::CONNRESET => EK::RemoteStreamReset,
483
            _ => EK::RemoteStreamError,
484
        }
485
    }
486
}
487

            
488
impl End {
489
    /// Make a new END_REASON_MISC message.
490
    ///
491
    /// Clients send this every time they decide to close a stream.
492
1767
    pub fn new_misc() -> Self {
493
1767
        End {
494
1767
            reason: EndReason::MISC,
495
1767
            addr: None,
496
1767
        }
497
1767
    }
498
    /// Make a new END message with the provided end reason.
499
1083
    pub fn new_with_reason(reason: EndReason) -> Self {
500
1083
        End { reason, addr: None }
501
1083
    }
502
    /// Make a new END message with END_REASON_EXITPOLICY, and the
503
    /// provided address and ttl.
504
171
    pub fn new_exitpolicy(addr: IpAddr, ttl: u32) -> Self {
505
171
        End {
506
171
            reason: EndReason::EXITPOLICY,
507
171
            addr: Some((addr, ttl)),
508
171
        }
509
171
    }
510
    /// Return the provided EndReason for this End cell.
511
684
    pub fn reason(&self) -> EndReason {
512
684
        self.reason
513
684
    }
514
}
515
impl Body for End {
516
1710
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
517
1710
        if r.remaining() == 0 {
518
57
            return Ok(End {
519
57
                reason: EndReason::MISC,
520
57
                addr: None,
521
57
            });
522
1653
        }
523
1653
        let reason = r.take_u8()?.into();
524
1653
        if reason == EndReason::EXITPOLICY {
525
171
            let addr = match r.remaining() {
526
114
                4 | 8 => IpAddr::V4(r.extract()?),
527
57
                16 | 20 => IpAddr::V6(r.extract()?),
528
                _ => {
529
                    // Ignores other message lengths.
530
                    return Ok(End { reason, addr: None });
531
                }
532
            };
533
171
            let ttl = if r.remaining() == 4 {
534
114
                r.take_u32()?
535
            } else {
536
57
                u32::MAX
537
            };
538
171
            Ok(End {
539
171
                reason,
540
171
                addr: Some((addr, ttl)),
541
171
            })
542
        } else {
543
1482
            Ok(End { reason, addr: None })
544
        }
545
1710
    }
546
118
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
547
118
        w.write_u8(self.reason.into());
548
118
        if let (EndReason::EXITPOLICY, Some((addr, ttl))) = (self.reason, self.addr) {
549
12
            match addr {
550
8
                IpAddr::V4(v4) => w.write(&v4)?,
551
4
                IpAddr::V6(v6) => w.write(&v6)?,
552
            }
553
12
            w.write_u32(ttl);
554
106
        }
555
118
        Ok(())
556
118
    }
557
}
558

            
559
impl From<EndReason> for std::io::ErrorKind {
560
    fn from(e: EndReason) -> Self {
561
        use std::io::ErrorKind::*;
562
        match e {
563
            EndReason::RESOLVEFAILED => NotFound,
564
            EndReason::CONNECTREFUSED => ConnectionRefused,
565
            EndReason::EXITPOLICY => ConnectionRefused,
566
            EndReason::DESTROY => ConnectionAborted,
567
            EndReason::DONE => UnexpectedEof,
568
            EndReason::TIMEOUT => TimedOut,
569
            EndReason::HIBERNATING => ConnectionRefused,
570
            EndReason::RESOURCELIMIT => ConnectionRefused,
571
            EndReason::CONNRESET => ConnectionReset,
572
            EndReason::TORPROTOCOL => InvalidData,
573
            EndReason::NOTDIRECTORY => ConnectionRefused,
574
            EndReason::INTERNAL | EndReason::NOROUTE | EndReason::MISC => Other,
575
            _ => Other,
576
        }
577
    }
578
}
579

            
580
/// A Connected message is a successful response to a Begin message
581
///
582
/// When an outgoing connection succeeds, the exit sends a Connected
583
/// back to the client.
584
///
585
/// Clients never send Connected messages.
586
#[derive(Debug, Clone, Deftly)]
587
#[derive_deftly(HasMemoryCost)]
588
pub struct Connected {
589
    /// Resolved address and TTL (time to live) in seconds
590
    addr: Option<(IpAddr, u32)>,
591
}
592
impl Connected {
593
    /// Construct a new empty connected cell.
594
1824
    pub fn new_empty() -> Self {
595
1824
        Connected { addr: None }
596
1824
    }
597
    /// Construct a connected cell with an address and a time-to-live value.
598
1938
    pub fn new_with_addr(addr: IpAddr, ttl: u32) -> Self {
599
1938
        Connected {
600
1938
            addr: Some((addr, ttl)),
601
1938
        }
602
1938
    }
603
}
604
impl Body for Connected {
605
3078
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
606
3078
        if r.remaining() == 0 {
607
1083
            return Ok(Connected { addr: None });
608
1995
        }
609
1995
        let ipv4 = r.take_u32()?;
610
1995
        let addr = if ipv4 == 0 {
611
114
            if r.take_u8()? != 6 {
612
57
                return Err(Error::InvalidMessage(
613
57
                    "Invalid address type in CONNECTED cell".into(),
614
57
                ));
615
57
            }
616
57
            IpAddr::V6(r.extract()?)
617
        } else {
618
1881
            IpAddr::V4(ipv4.into())
619
        };
620
1938
        let ttl = r.take_u32()?;
621

            
622
1938
        Ok(Connected {
623
1938
            addr: Some((addr, ttl)),
624
1938
        })
625
3078
    }
626
142
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
627
142
        if let Some((addr, ttl)) = self.addr {
628
72
            match addr {
629
68
                IpAddr::V4(v4) => w.write(&v4)?,
630
4
                IpAddr::V6(v6) => {
631
4
                    w.write_u32(0);
632
4
                    w.write_u8(6);
633
4
                    w.write(&v6)?;
634
                }
635
            }
636
72
            w.write_u32(ttl);
637
70
        }
638
142
        Ok(())
639
142
    }
640
}
641

            
642
/// An authentication tag to use for circuit-level SENDME messages.
643
///
644
/// It is either a 20-byte tag (used with Tor1 encryption),
645
/// or a 16-byte tag (used with CGO encryption).
646
#[derive(Debug, Clone, Copy, Eq, PartialEq, Deftly)]
647
#[derive_deftly(HasMemoryCost)]
648
pub struct SendmeTag {
649
    /// The number of bytes present in the tag.
650
    /// Always equal to 16 or 20.
651
    ///
652
    /// We use a NonZeroU8 here so Rust can use its niche optimization.
653
    len: NonZeroU8,
654
    /// The actual contents of the tag.
655
    ///
656
    /// Tags above 20 bytes long are always an error.
657
    ///
658
    /// Unused bytes are always set to zero, so we can derive PartialEq.
659
    tag: CtByteArray<20>,
660
}
661
impl From<[u8; 20]> for SendmeTag {
662
    // In experimentation, these "inlines" were necessary for good generated asm.
663
    #[inline]
664
158828
    fn from(value: [u8; 20]) -> Self {
665
158828
        Self {
666
158828
            len: NonZeroU8::new(20).expect("20 was not nonzero?"),
667
158828
            tag: CtByteArray::from(value),
668
158828
        }
669
158828
    }
670
}
671
impl From<[u8; 16]> for SendmeTag {
672
    // In experimentation, these "inlines" were necessary for good generated asm.
673
    #[inline]
674
824
    fn from(value: [u8; 16]) -> Self {
675
824
        let mut tag = CtByteArray::from([0; 20]);
676
824
        tag.as_mut()[0..16].copy_from_slice(&value[..]);
677
824
        Self {
678
824
            len: NonZeroU8::new(16).expect("16 was not nonzero?"),
679
824
            tag,
680
824
        }
681
824
    }
682
}
683
impl AsRef<[u8]> for SendmeTag {
684
1543
    fn as_ref(&self) -> &[u8] {
685
1543
        &self.tag.as_ref()[0..usize::from(u8::from(self.len))]
686
1543
    }
687
}
688
/// An error from attempting to decode a SENDME tag.
689
#[derive(Clone, Debug, thiserror::Error)]
690
#[non_exhaustive]
691
#[error("Invalid size {} on SENDME tag", len)]
692
pub struct InvalidSendmeTag {
693
    /// The length of the invalid tag.
694
    len: usize,
695
}
696
impl From<InvalidSendmeTag> for tor_bytes::Error {
697
    fn from(_: InvalidSendmeTag) -> Self {
698
        tor_bytes::Error::BadLengthValue
699
    }
700
}
701

            
702
impl<'a> TryFrom<&'a [u8]> for SendmeTag {
703
    type Error = InvalidSendmeTag;
704

            
705
    // In experimentation, this "inline" was especially necessary for good generated asm.
706
    #[inline]
707
5027
    fn try_from(value: &'a [u8]) -> std::result::Result<Self, Self::Error> {
708
5027
        match value.len() {
709
            16 => {
710
512
                let a: [u8; 16] = value.try_into().expect("16 was not 16?");
711
512
                Ok(Self::from(a))
712
            }
713
            20 => {
714
4513
                let a: [u8; 20] = value.try_into().expect("20 was not 20?");
715
4513
                Ok(Self::from(a))
716
            }
717
2
            _ => Err(InvalidSendmeTag { len: value.len() }),
718
        }
719
5027
    }
720
}
721

            
722
/// A Sendme message is used to increase flow-control windows.
723
///
724
/// To avoid congestion, each Tor circuit and stream keeps track of a
725
/// number of data cells that it is willing to send.  It decrements
726
/// these numbers every time it sends a cell.  If these numbers reach
727
/// zero, then no more cells can be sent on the stream or circuit.
728
///
729
/// The only way to re-increment these numbers is by receiving a
730
/// Sendme cell from the other end of the circuit or stream.
731
///
732
/// For security, current circuit-level Sendme cells include an
733
/// authentication tag that proves knowledge of the cells that they are
734
/// acking.
735
///
736
/// See [tor-spec.txt](https://spec.torproject.org/tor-spec) for more
737
/// information; also see the source for `tor_proto::circuit::sendme`.
738
#[derive(Debug, Clone, Deftly)]
739
#[derive_deftly(HasMemoryCost)]
740
pub struct Sendme {
741
    /// A tag value authenticating the previously received data.
742
    tag: Option<SendmeTag>,
743
}
744
impl Sendme {
745
    /// Return a new empty sendme cell
746
    ///
747
    /// This format is used on streams, and on circuits without sendme
748
    /// authentication.
749
228
    pub fn new_empty() -> Self {
750
228
        Sendme { tag: None }
751
228
    }
752
    /// This format is used on circuits with sendme authentication.
753
342
    pub fn new_tag(x: [u8; 20]) -> Self {
754
342
        Sendme {
755
342
            tag: Some(x.into()),
756
342
        }
757
342
    }
758
    /// Consume this cell and return its authentication tag, if any
759
1254
    pub fn into_sendme_tag(self) -> Option<SendmeTag> {
760
1254
        self.tag
761
1254
    }
762
}
763
impl From<SendmeTag> for Sendme {
764
1026
    fn from(value: SendmeTag) -> Self {
765
1026
        Self { tag: Some(value) }
766
1026
    }
767
}
768
impl Body for Sendme {
769
1710
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
770
1710
        let tag = if r.remaining() == 0 {
771
285
            None
772
        } else {
773
1425
            let ver = r.take_u8()?;
774
1425
            match ver {
775
                0 => None,
776
                1 => {
777
1425
                    let dlen = r.take_u16()?;
778
1425
                    Some(r.take(dlen as usize)?.try_into()?)
779
                }
780
                _ => {
781
                    return Err(Error::InvalidMessage("Unrecognized SENDME version.".into()));
782
                }
783
            }
784
        };
785
1710
        Ok(Sendme { tag })
786
1710
    }
787
66
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
788
66
        match self.tag {
789
12
            None => (),
790
54
            Some(x) => {
791
54
                w.write_u8(1);
792
54
                let x = x.as_ref();
793
54
                let bodylen: u16 = x
794
54
                    .len()
795
54
                    .try_into()
796
54
                    .map_err(|_| EncodeError::BadLengthValue)?;
797
54
                w.write_u16(bodylen);
798
54
                w.write_all(x);
799
            }
800
        }
801
66
        Ok(())
802
66
    }
803
}
804

            
805
/// Extend was an obsolete circuit extension message format.
806
///
807
/// This format only handled IPv4 addresses, RSA identities, and the
808
/// TAP handshake.  Modern Tor clients use Extend2 instead.
809
#[derive(Debug, Clone, Deftly)]
810
#[derive_deftly(HasMemoryCost)]
811
pub struct Extend {
812
    /// Where to extend to (address)
813
    addr: Ipv4Addr,
814
    /// Where to extend to (port)
815
    port: u16,
816
    /// A TAP handshake to send
817
    handshake: Vec<u8>,
818
    /// The RSA identity of the target relay
819
    rsaid: RsaIdentity,
820
}
821
impl Extend {
822
    /// Construct a new (deprecated) extend cell
823
57
    pub fn new(addr: Ipv4Addr, port: u16, handshake: Vec<u8>, rsaid: RsaIdentity) -> Self {
824
57
        Extend {
825
57
            addr,
826
57
            port,
827
57
            handshake,
828
57
            rsaid,
829
57
        }
830
57
    }
831
}
832
impl Body for Extend {
833
57
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
834
57
        let addr = r.extract()?;
835
57
        let port = r.take_u16()?;
836
57
        let handshake = r.take(TAP_C_HANDSHAKE_LEN)?.into();
837
57
        let rsaid = r.extract()?;
838
57
        Ok(Extend {
839
57
            addr,
840
57
            port,
841
57
            handshake,
842
57
            rsaid,
843
57
        })
844
57
    }
845
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
846
4
        w.write(&self.addr)?;
847
4
        w.write_u16(self.port);
848
4
        w.write_all(&self.handshake[..]);
849
4
        w.write(&self.rsaid)?;
850
4
        Ok(())
851
4
    }
852
}
853

            
854
/// Extended was an obsolete circuit extension message, sent in reply to
855
/// an Extend message.
856
///
857
/// Like Extend, the Extended message was only designed for the TAP
858
/// handshake.
859
#[derive(Debug, Clone, Deftly)]
860
#[derive_deftly(HasMemoryCost)]
861
pub struct Extended {
862
    /// Contents of the handshake sent in response to the EXTEND
863
    handshake: Vec<u8>,
864
}
865
impl Extended {
866
    /// Construct a new Extended message with the provided handshake
867
399
    pub fn new(handshake: Vec<u8>) -> Self {
868
399
        Extended { handshake }
869
399
    }
870
}
871
impl Body for Extended {
872
57
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
873
57
        let handshake = r.take(TAP_S_HANDSHAKE_LEN)?.into();
874
57
        Ok(Extended { handshake })
875
57
    }
876
16
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
877
16
        w.write_all(&self.handshake);
878
16
        Ok(())
879
16
    }
880
}
881

            
882
/// An Extend2 message tells the last relay in a circuit to extend to a new
883
/// hop.
884
///
885
/// When a relay (call it R) receives an Extend2 message, it tries to
886
/// find (or make) a channel to the other relay (R') described in the
887
/// list of link specifiers. (A link specifier can be an IP addresses
888
/// or a cryptographic identity).  Once R has such a channel, the
889
/// it packages the client's handshake data as a new Create2 message
890
/// R'.  If R' replies with a Created2 (success) message, R packages
891
/// that message's contents in an Extended message.
892
//
893
/// Unlike Extend messages, Extend2 messages can encode any handshake
894
/// type, and can describe relays in ways other than IPv4 addresses
895
/// and RSA identities.
896
#[derive(Debug, Clone, Deftly)]
897
#[derive_deftly(HasMemoryCost)]
898
pub struct Extend2 {
899
    /// A vector of "link specifiers"
900
    ///
901
    /// These link specifiers describe where to find the target relay
902
    /// that the recipient should extend to.  They include things like
903
    /// IP addresses and identity keys.
904
    linkspec: Vec<EncodedLinkSpec>,
905
    /// Type of handshake to be sent in a CREATE2 cell
906
    handshake_type: HandshakeType,
907
    /// Body of the handshake to be sent in a CREATE2 cell
908
    handshake: Vec<u8>,
909
}
910
impl Extend2 {
911
    /// Create a new Extend2 cell.
912
2109
    pub fn new(
913
2109
        linkspec: Vec<EncodedLinkSpec>,
914
2109
        handshake_type: HandshakeType,
915
2109
        handshake: Vec<u8>,
916
2109
    ) -> Self {
917
2109
        Extend2 {
918
2109
            linkspec,
919
2109
            handshake_type,
920
2109
            handshake,
921
2109
        }
922
2109
    }
923

            
924
    /// Return the type of this handshake.
925
57
    pub fn handshake_type(&self) -> HandshakeType {
926
57
        self.handshake_type
927
57
    }
928

            
929
    /// Return the inner handshake for this Extend2 cell.
930
741
    pub fn handshake(&self) -> &[u8] {
931
741
        &self.handshake[..]
932
741
    }
933

            
934
    /// Return a reference to the link specifiers in this cell.
935
    pub fn linkspecs(&self) -> &[EncodedLinkSpec] {
936
        &self.linkspec
937
    }
938
}
939

            
940
impl Body for Extend2 {
941
798
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
942
798
        let n = r.take_u8()?;
943
798
        let linkspec = r.extract_n(n as usize)?;
944
798
        let handshake_type = r.take_u16()?.into();
945
798
        let hlen = r.take_u16()?;
946
798
        let handshake = r.take(hlen as usize)?.into();
947
798
        Ok(Extend2 {
948
798
            linkspec,
949
798
            handshake_type,
950
798
            handshake,
951
798
        })
952
798
    }
953
76
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
954
76
        let n_linkspecs: u8 = self
955
76
            .linkspec
956
76
            .len()
957
76
            .try_into()
958
76
            .map_err(|_| EncodeError::BadLengthValue)?;
959
76
        w.write_u8(n_linkspecs);
960
228
        for ls in &self.linkspec {
961
152
            w.write(ls)?;
962
        }
963
76
        w.write_u16(self.handshake_type.into());
964
76
        let handshake_len: u16 = self
965
76
            .handshake
966
76
            .len()
967
76
            .try_into()
968
76
            .map_err(|_| EncodeError::BadLengthValue)?;
969
76
        w.write_u16(handshake_len);
970
76
        w.write_all(&self.handshake[..]);
971
76
        Ok(())
972
76
    }
973
}
974

            
975
/// Extended2 is a successful reply to an Extend2 message.
976
///
977
/// Extended2 messages are generated by the former last hop of a
978
/// circuit, to tell the client that they have successfully completed
979
/// a handshake on the client's behalf.
980
#[derive(Debug, Clone, Deftly)]
981
#[derive_deftly(HasMemoryCost)]
982
pub struct Extended2 {
983
    /// Contents of the CREATED2 cell that the new final hop sent in
984
    /// response
985
    handshake: Vec<u8>,
986
}
987
impl Extended2 {
988
    /// Construct a new Extended2 message with the provided handshake
989
1539
    pub fn new(handshake: Vec<u8>) -> Self {
990
1539
        Extended2 { handshake }
991
1539
    }
992
    /// Consume this extended2 cell and return its body.
993
1026
    pub fn into_body(self) -> Vec<u8> {
994
1026
        self.handshake
995
1026
    }
996
}
997
impl Body for Extended2 {
998
1197
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
999
1197
        let hlen = r.take_u16()?;
1197
        let handshake = r.take(hlen as usize)?;
1197
        Ok(Extended2 {
1197
            handshake: handshake.into(),
1197
        })
1197
    }
60
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
60
        let handshake_len: u16 = self
60
            .handshake
60
            .len()
60
            .try_into()
60
            .map_err(|_| EncodeError::BadLengthValue)?;
60
        w.write_u16(handshake_len);
60
        w.write_all(&self.handshake[..]);
60
        Ok(())
60
    }
}
/// A Truncated message is sent to the client when the remaining hops
/// of a circuit have gone away.
///
/// NOTE: Current Tor implementations often treat Truncated messages and
/// Destroy messages interchangeably.  Truncated was intended to be a
/// "soft" Destroy, that would leave the unaffected parts of a circuit
/// still usable.
#[derive(Debug, Clone, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Truncated {
    /// Reason for which this circuit was truncated.
    reason: DestroyReason,
}
impl Truncated {
    /// Construct a new truncated message.
57
    pub fn new(reason: DestroyReason) -> Self {
57
        Truncated { reason }
57
    }
    /// Get the provided reason to truncate the circuit.
    pub fn reason(self) -> DestroyReason {
        self.reason
    }
}
impl Body for Truncated {
57
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
        Ok(Truncated {
57
            reason: r.take_u8()?.into(),
        })
57
    }
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
4
        w.write_u8(self.reason.into());
4
        Ok(())
4
    }
}
/// A Resolve message launches a DNS lookup stream.
///
/// A client sends a Resolve message when it wants to perform a DNS
/// lookup _without_ connecting to the resulting address.  On success
/// the exit responds with a Resolved message; on failure it responds
/// with an End message.
#[derive(Debug, Clone, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Resolve {
    /// Ascii-encoded address to resolve
    query: Vec<u8>,
}
impl Resolve {
    /// Construct a new resolve message to look up a hostname.
114
    pub fn new(s: &str) -> Self {
114
        Resolve {
114
            query: s.as_bytes().into(),
114
        }
114
    }
    /// Construct a new resolve message to do a reverse lookup on an address
114
    pub fn new_reverse(addr: &IpAddr) -> Self {
114
        let query = match addr {
57
            IpAddr::V4(v4) => {
57
                let [a, b, c, d] = v4.octets();
57
                format!("{}.{}.{}.{}.in-addr.arpa", d, c, b, a)
            }
57
            IpAddr::V6(v6) => {
57
                let mut s = String::with_capacity(72);
912
                for o in v6.octets().iter().rev() {
912
                    let high_nybble = o >> 4;
912
                    let low_nybble = o & 15;
912
                    write!(s, "{:x}.{:x}.", low_nybble, high_nybble)
912
                        .expect("write to string failed");
912
                }
57
                write!(s, "ip6.arpa").expect("write to string failed");
57
                s
            }
        };
114
        Resolve {
114
            query: query.into_bytes(),
114
        }
114
    }
}
impl Body for Resolve {
171
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
171
        let query = r.take_until(0)?;
171
        Ok(Resolve {
171
            query: query.into(),
171
        })
171
    }
14
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
14
        w.write_all(&self.query[..]);
14
        w.write_u8(0);
14
        Ok(())
14
    }
}
/// Possible response to a DNS lookup
#[derive(Debug, Clone, Eq, PartialEq, Deftly)]
#[derive_deftly(HasMemoryCost)]
#[non_exhaustive]
pub enum ResolvedVal {
    /// We found an IP address
    Ip(IpAddr),
    /// We found a hostname
    Hostname(Vec<u8>),
    /// Error; try again
    TransientError,
    /// Error; don't try again
    NontransientError,
    /// A DNS lookup response that we didn't recognize
    Unrecognized(u8, Vec<u8>),
}
/// Indicates a hostname response
const RES_HOSTNAME: u8 = 0;
/// Indicates an IPv4 response
const RES_IPV4: u8 = 4;
/// Indicates an IPv6 response
const RES_IPV6: u8 = 6;
/// Transient error (okay to try again)
const RES_ERR_TRANSIENT: u8 = 0xF0;
/// Non-transient error (don't try again)
const RES_ERR_NONTRANSIENT: u8 = 0xF1;
impl Readable for ResolvedVal {
513
    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
        /// Helper: return the expected length of a resolved answer with
        /// a given type, if there is a particular expected length.
513
        fn res_len(tp: u8) -> Option<usize> {
513
            match tp {
171
                RES_IPV4 => Some(4),
114
                RES_IPV6 => Some(16),
228
                _ => None,
            }
513
        }
513
        let tp = r.take_u8()?;
513
        let len = r.take_u8()? as usize;
513
        if let Some(expected_len) = res_len(tp) {
285
            if len != expected_len {
57
                return Err(Error::InvalidMessage(
57
                    "Wrong length for RESOLVED answer".into(),
57
                ));
228
            }
228
        }
456
        Ok(match tp {
57
            RES_HOSTNAME => Self::Hostname(r.take(len)?.into()),
114
            RES_IPV4 => Self::Ip(IpAddr::V4(r.extract()?)),
114
            RES_IPV6 => Self::Ip(IpAddr::V6(r.extract()?)),
            RES_ERR_TRANSIENT => {
57
                r.advance(len)?;
57
                Self::TransientError
            }
            RES_ERR_NONTRANSIENT => {
57
                r.advance(len)?;
57
                Self::NontransientError
            }
57
            _ => Self::Unrecognized(tp, r.take(len)?.into()),
        })
513
    }
}
impl Writeable for ResolvedVal {
28
    fn write_onto<B: Writer + ?Sized>(&self, w: &mut B) -> EncodeResult<()> {
12
        match self {
4
            Self::Hostname(h) => {
4
                w.write_u8(RES_HOSTNAME);
4
                let h_len: u8 = h
4
                    .len()
4
                    .try_into()
4
                    .map_err(|_| EncodeError::BadLengthValue)?;
4
                w.write_u8(h_len);
4
                w.write_all(&h[..]);
            }
8
            Self::Ip(IpAddr::V4(a)) => {
8
                w.write_u8(RES_IPV4);
8
                w.write_u8(4); // length
8
                w.write(a)?;
            }
4
            Self::Ip(IpAddr::V6(a)) => {
4
                w.write_u8(RES_IPV6);
4
                w.write_u8(16); // length
4
                w.write(a)?;
            }
4
            Self::TransientError => {
4
                w.write_u8(RES_ERR_TRANSIENT);
4
                w.write_u8(0); // length
4
            }
4
            Self::NontransientError => {
4
                w.write_u8(RES_ERR_NONTRANSIENT);
4
                w.write_u8(0); // length
4
            }
4
            Self::Unrecognized(tp, v) => {
4
                w.write_u8(*tp);
4
                let v_len: u8 = v
4
                    .len()
4
                    .try_into()
4
                    .map_err(|_| EncodeError::BadLengthValue)?;
4
                w.write_u8(v_len);
4
                w.write_all(&v[..]);
            }
        }
28
        Ok(())
28
    }
}
/// A Resolved message is a successful reply to a Resolve message.
///
/// The Resolved message contains a list of zero or more addresses,
/// and their associated times-to-live in seconds.
#[derive(Debug, Clone, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Resolved {
    /// List of addresses and their associated time-to-live values.
    answers: Vec<(ResolvedVal, u32)>,
}
impl Resolved {
    /// Return a new empty Resolved object with no answers.
399
    pub fn new_empty() -> Self {
399
        Resolved {
399
            answers: Vec::new(),
399
        }
399
    }
    /// Return a new Resolved object reporting a name lookup error.
    ///
    /// TODO: Is getting no answer an error; or it is represented by
    /// a list of no answers?
114
    pub fn new_err(transient: bool, ttl: u32) -> Self {
114
        let mut res = Self::new_empty();
114
        let err = if transient {
57
            ResolvedVal::TransientError
        } else {
57
            ResolvedVal::NontransientError
        };
114
        res.add_answer(err, ttl);
114
        res
114
    }
    /// Add a single answer to this Resolved message
399
    pub fn add_answer(&mut self, answer: ResolvedVal, ttl: u32) {
399
        self.answers.push((answer, ttl));
399
    }
    /// Consume this Resolved message, returning a vector of the
    /// answers and TTL values that it contains.
    ///
    /// Note that actually relying on these TTL values can be
    /// dangerous in practice, since the relay that sent the cell
    /// could be lying in order to cause more lookups, or to get a
    /// false answer cached for longer.
57
    pub fn into_answers(self) -> Vec<(ResolvedVal, u32)> {
57
        self.answers
57
    }
}
impl Body for Resolved {
513
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
513
        let mut answers = Vec::new();
969
        while r.remaining() > 0 {
513
            let rv = r.extract()?;
456
            let ttl = r.take_u32()?;
456
            answers.push((rv, ttl));
        }
456
        Ok(Resolved { answers })
513
    }
28
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
56
        for (rv, ttl) in &self.answers {
28
            w.write(rv)?;
28
            w.write_u32(*ttl);
        }
28
        Ok(())
28
    }
}
/// A relay message that we didn't recognize
///
/// NOTE: Clients should generally reject these.
#[derive(Debug, Clone, Deftly)]
#[derive_deftly(HasMemoryCost)]
pub struct Unrecognized {
    /// Command that we didn't recognize
    cmd: RelayCmd,
    /// Body associated with that command
    body: Vec<u8>,
}
impl Unrecognized {
    /// Create a new 'unrecognized' cell.
2
    pub fn new<B>(cmd: RelayCmd, body: B) -> Self
2
    where
2
        B: Into<Vec<u8>>,
    {
2
        let body = body.into();
2
        Unrecognized { cmd, body }
2
    }
    /// Return the command associated with this message
57
    pub fn cmd(&self) -> RelayCmd {
57
        self.cmd
57
    }
    /// Decode this message, using a provided command.
57
    pub fn decode_with_cmd(cmd: RelayCmd, r: &mut Reader<'_>) -> Result<Self> {
57
        let mut r = Unrecognized::decode_from_reader(r)?;
57
        r.cmd = cmd;
57
        Ok(r)
57
    }
}
impl Body for Unrecognized {
57
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
        Ok(Unrecognized {
57
            cmd: 0.into(),
57
            body: r.take(r.remaining())?.into(),
        })
57
    }
4
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
4
        w.write_all(&self.body[..]);
4
        Ok(())
4
    }
}
/// Declare a message type for a message with an empty body.
macro_rules! empty_body {
   {
       $(#[$meta:meta])*
       pub struct $name:ident {}
   } => {
       $(#[$meta])*
       #[derive(Clone,Debug,Default,derive_deftly::Deftly)]
       #[derive_deftly(tor_memquota::HasMemoryCost)]
       #[non_exhaustive]
       pub struct $name {}
       impl $crate::relaycell::msg::Body for $name {
1197
           fn decode_from_reader(_r: &mut Reader<'_>) -> Result<Self> {
1197
               Ok(Self::default())
1197
           }
90
           fn encode_onto<W: Writer + ?Sized>(self, _w: &mut W) -> EncodeResult<()> {
90
               Ok(())
90
           }
       }
   }
}
#[allow(unused_imports)] // TODO #1060
pub(crate) use empty_body;
empty_body! {
    /// A padding message, which is always ignored.
    pub struct Drop {}
}
empty_body! {
    /// Tells a circuit to close all downstream hops on the circuit.
    pub struct Truncate {}
}
empty_body! {
    /// Opens a new stream on a directory cache.
    pub struct BeginDir {}
}
/// Helper: declare a RelayMsg implementation for a message type that has a
/// fixed command.
//
// TODO: It might be better to merge Body with RelayMsg, 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_relaymsg {
    ($($body:ident),* $(,)?) =>
    {paste::paste!{
       $(impl crate::relaycell::RelayMsg for $body {
            fn cmd(&self) -> crate::relaycell::RelayCmd { crate::relaycell::RelayCmd::[< $body:snake:upper >] }
            fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()> {
                crate::relaycell::msg::Body::encode_onto(self, w)
            }
6840
            fn decode_from_reader(cmd: RelayCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
6840
                if cmd != crate::relaycell::RelayCmd::[< $body:snake:upper >] {
342
                    return Err(tor_bytes::Error::InvalidMessage(
342
                        format!("Expected {} command; got {cmd}", stringify!([< $body:snake:upper >])).into()
342
                    ));
6498
                }
6498
                crate::relaycell::msg::Body::decode_from_reader(r)
6840
            }
        }
        impl TryFrom<AnyRelayMsg> for $body {
            type Error = crate::Error;
6840
            fn try_from(msg: AnyRelayMsg) -> crate::Result<$body> {
                use crate::relaycell::RelayMsg;
6840
                match msg {
6840
                    AnyRelayMsg::$body(b) => Ok(b),
                    _ => Err(crate::Error::CircProto(format!("Expected {}; got {}" ,
                                                     stringify!([<$body:snake:upper>]),
                                                     msg.cmd())) ),
                }
6840
            }
        }
        )*
    }}
}
msg_impl_relaymsg!(
    Begin, Data, End, Connected, Sendme, Extend, Extended, Extend2, Extended2, Truncate, Truncated,
    Drop, Resolve, Resolved, BeginDir,
);
#[cfg(feature = "experimental-udp")]
msg_impl_relaymsg!(ConnectUdp, ConnectedUdp, Datagram);
#[cfg(feature = "hs")]
msg_impl_relaymsg!(
    EstablishIntro,
    EstablishRendezvous,
    Introduce1,
    Introduce2,
    Rendezvous1,
    Rendezvous2,
    IntroEstablished,
    RendezvousEstablished,
    IntroduceAck,
);
#[cfg(feature = "conflux")]
msg_impl_relaymsg!(ConfluxSwitch, ConfluxLink, ConfluxLinked, ConfluxLinkedAck);
msg_impl_relaymsg!(Xon, Xoff);
#[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 sendme_tags() {
        // strings of 20 or 16 bytes.
        let ts: Vec<SendmeTag> = vec![
            (*b"Yea, on the word of ").into(),
            (*b"a Bloom, ye shal").into(),
            (*b"l ere long enter int").into(),
            (*b"o the golden cit").into(),
        ];
        for (i1, i2) in (0..4).zip(0..4) {
            if i1 == i2 {
                assert_eq!(ts[i1], ts[i2]);
            } else {
                assert_ne!(ts[i1], ts[i2]);
            }
        }
        assert_eq!(ts[0].as_ref(), &b"Yea, on the word of "[..]);
        assert_eq!(ts[3].as_ref(), &b"o the golden cit"[..]);
        assert_eq!(ts[1], b"a Bloom, ye shal"[..].try_into().unwrap());
        assert_eq!(ts[2], b"l ere long enter int"[..].try_into().unwrap());
        // 15 bytes long.
        assert!(matches!(
            SendmeTag::try_from(&b"o the golden ci"[..]),
            Err(InvalidSendmeTag { .. }),
        ));
    }
}