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

            
23
use bitflags::bitflags;
24

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

            
29
#[cfg(feature = "flowctl-cc")]
30
#[cfg_attr(docsrs, doc(cfg(feature = "flowctl-cc")))]
31
use super::flow_ctrl::{Xoff, Xon};
32

            
33
#[cfg(feature = "hs")]
34
#[cfg_attr(docsrs, doc(cfg(feature = "hs")))]
35
pub use super::hs::{
36
    est_intro::EstablishIntro, EstablishRendezvous, IntroEstablished, Introduce1, Introduce2,
37
    IntroduceAck, Rendezvous1, Rendezvous2, RendezvousEstablished,
38
};
39
#[cfg(feature = "experimental-udp")]
40
#[cfg_attr(docsrs, doc(cfg(feature = "experimental-udp")))]
41
pub use super::udp::{ConnectUdp, ConnectedUdp, Datagram};
42

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

            
135
    _ =>
136
    /// An unrecognized command.
137
    Unrecognized,
138
    }
139
}
140

            
141
/// Internal: traits in common different cell bodies.
142
pub trait Body: Sized {
143
    /// Decode a relay cell body from a provided reader.
144
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self>;
145
    /// Encode the body of this cell into the end of a writer.
146
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()>;
147
}
148

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

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

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

            
219
impl Begin {
220
    /// Construct a new Begin cell
221
88
    pub fn new<F>(addr: &str, port: u16, flags: F) -> crate::Result<Self>
222
88
    where
223
88
        F: Into<BeginFlags>,
224
88
    {
225
88
        if !addr.is_ascii() {
226
2
            return Err(crate::Error::BadStreamAddress);
227
86
        }
228
86
        let mut addr = addr.to_string();
229
86
        addr.make_ascii_lowercase();
230
86
        Ok(Begin {
231
86
            addr: addr.into_bytes(),
232
86
            port,
233
86
            flags: flags.into(),
234
86
        })
235
88
    }
236

            
237
    /// Return the address requested in this message.
238
    pub fn addr(&self) -> &[u8] {
239
        &self.addr[..]
240
    }
241

            
242
    /// Return the port requested by this message.
243
    pub fn port(&self) -> u16 {
244
        self.port
245
    }
246

            
247
    /// Return the set of flags provided in this message.
248
    pub fn flags(&self) -> BeginFlags {
249
        self.flags
250
    }
251
}
252

            
253
impl Body for Begin {
254
2365
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
255
2310
        let addr = {
256
2365
            if r.peek(1)? == b"[" {
257
                // IPv6 address
258
110
                r.advance(1)?;
259
110
                let a = r.take_until(b']')?;
260
110
                let colon = r.take_u8()?;
261
110
                if colon != b':' {
262
55
                    return Err(Error::InvalidMessage("missing port in begin cell".into()));
263
55
                }
264
55
                a
265
            } else {
266
                // IPv4 address, or hostname.
267
2255
                r.take_until(b':')?
268
            }
269
        };
270
2310
        let port = r.take_until(0)?;
271
2310
        let flags = if r.remaining() >= 4 { r.take_u32()? } else { 0 };
272

            
273
2310
        if !addr.is_ascii() {
274
55
            return Err(Error::InvalidMessage(
275
55
                "target address in begin cell not ascii".into(),
276
55
            ));
277
2255
        }
278

            
279
2255
        let port = std::str::from_utf8(port)
280
2255
            .map_err(|_| Error::InvalidMessage("port in begin cell not utf8".into()))?;
281

            
282
2255
        let port = port
283
2255
            .parse()
284
2255
            .map_err(|_| Error::InvalidMessage("port in begin cell not a valid port".into()))?;
285

            
286
2255
        Ok(Begin {
287
2255
            addr: addr.into(),
288
2255
            port,
289
2255
            flags: flags.into(),
290
2255
        })
291
2365
    }
292
92
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
293
92
        if self.addr.contains(&b':') {
294
4
            w.write_u8(b'[');
295
4
            w.write_all(&self.addr[..]);
296
4
            w.write_u8(b']');
297
88
        } else {
298
88
            w.write_all(&self.addr[..]);
299
88
        }
300
92
        w.write_u8(b':');
301
92
        w.write_all(self.port.to_string().as_bytes());
302
92
        w.write_u8(0);
303
92
        if self.flags.bits() != 0 {
304
80
            w.write_u32(self.flags.bits());
305
84
        }
306
92
        Ok(())
307
92
    }
308
}
309

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

            
336
    /// The longest allowable body length for a single V1 data cell.
337
    ///
338
    /// Tag (16) + Relay command (1) + Length (2) + StreamID (2) = 21
339
    pub const MAXLEN_V1: usize = CELL_DATA_LEN - 21;
340

            
341
    /// The longest allowable body length for any data cell.
342
    ///
343
    /// Note that this value is too large to fit into a v1 relay cell;
344
    /// see [`MAXLEN_V1`](Data::MAXLEN_V1) if you are making a v1 data cell.
345
    ///
346
    pub const MAXLEN: usize = Data::MAXLEN_V0;
347

            
348
    /// Construct a new data cell.
349
    ///
350
    /// Returns an error if `inp` is longer than [`Data::MAXLEN`] bytes.
351
1045
    pub fn new(inp: &[u8]) -> crate::Result<Self> {
352
1045
        if inp.len() > Data::MAXLEN {
353
55
            return Err(crate::Error::CantEncode("Data message too long"));
354
990
        }
355
990
        if inp.is_empty() {
356
            return Err(crate::Error::CantEncode("Empty data message"));
357
990
        }
358
990
        Ok(Self::new_unchecked(inp.into()))
359
1045
    }
360

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

            
378
    /// Construct a new data cell from a provided vector of bytes.
379
    ///
380
    /// The vector _must_ not have more than [`Data::MAXLEN`] bytes, and must
381
    /// not be empty.
382
113025
    fn new_unchecked(body: Vec<u8>) -> Self {
383
113025
        debug_assert!((1..=Data::MAXLEN).contains(&body.len()));
384
113025
        Data { body }
385
113025
    }
386

            
387
    /// Return the maximum allowable body length for a Data message
388
    /// using the provided `format`.
389
114125
    pub fn max_body_len(format: RelayCellFormat) -> usize {
390
114125
        match format {
391
114125
            RelayCellFormat::V0 => Self::MAXLEN_V0,
392
            RelayCellFormat::V1 => Self::MAXLEN_V1,
393
        }
394
114125
    }
395
}
396
impl From<Data> for Vec<u8> {
397
576
    fn from(data: Data) -> Vec<u8> {
398
576
        data.body
399
576
    }
400
}
401
impl AsRef<[u8]> for Data {
402
103895
    fn as_ref(&self) -> &[u8] {
403
103895
        &self.body[..]
404
103895
    }
405
}
406

            
407
impl Body for Data {
408
105985
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
409
105985
        if r.remaining() == 0 {
410
            return Err(Error::InvalidMessage("Empty DATA message".into()));
411
105985
        }
412
105985
        Ok(Data {
413
105985
            body: r.take(r.remaining())?.into(),
414
        })
415
105985
    }
416
4014
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
417
4014
        w.write_all(&self.body);
418
4014
        Ok(())
419
4014
    }
420
}
421

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

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

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

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

            
567
impl From<EndReason> for std::io::ErrorKind {
568
    fn from(e: EndReason) -> Self {
569
        use std::io::ErrorKind::*;
570
        match e {
571
            EndReason::RESOLVEFAILED => NotFound,
572
            EndReason::CONNECTREFUSED => ConnectionRefused,
573
            EndReason::EXITPOLICY => ConnectionRefused,
574
            EndReason::DESTROY => ConnectionAborted,
575
            EndReason::DONE => UnexpectedEof,
576
            EndReason::TIMEOUT => TimedOut,
577
            EndReason::HIBERNATING => ConnectionRefused,
578
            EndReason::RESOURCELIMIT => ConnectionRefused,
579
            EndReason::CONNRESET => ConnectionReset,
580
            EndReason::TORPROTOCOL => InvalidData,
581
            EndReason::NOTDIRECTORY => ConnectionRefused,
582
            EndReason::INTERNAL | EndReason::NOROUTE | EndReason::MISC => Other,
583
            _ => Other,
584
        }
585
    }
586
}
587

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

            
630
1210
        Ok(Connected {
631
1210
            addr: Some((addr, ttl)),
632
1210
        })
633
1980
    }
634
98
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
635
98
        if let Some((addr, ttl)) = self.addr {
636
48
            match addr {
637
44
                IpAddr::V4(v4) => w.write(&v4)?,
638
4
                IpAddr::V6(v6) => {
639
4
                    w.write_u32(0);
640
4
                    w.write_u8(6);
641
4
                    w.write(&v6)?;
642
                }
643
            }
644
48
            w.write_u32(ttl);
645
50
        }
646
98
        Ok(())
647
98
    }
648
}
649

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

            
710
impl<'a> TryFrom<&'a [u8]> for SendmeTag {
711
    type Error = InvalidSendmeTag;
712

            
713
    // In experimentation, this "inline" was especially necessary for good generated asm.
714
    #[inline]
715
4083
    fn try_from(value: &'a [u8]) -> std::result::Result<Self, Self::Error> {
716
4083
        match value.len() {
717
            16 => {
718
498
                let a: [u8; 16] = value.try_into().expect("16 was not 16?");
719
498
                Ok(Self::from(a))
720
            }
721
            20 => {
722
3583
                let a: [u8; 20] = value.try_into().expect("20 was not 20?");
723
3583
                Ok(Self::from(a))
724
            }
725
2
            _ => Err(InvalidSendmeTag { len: value.len() }),
726
        }
727
4083
    }
728
}
729

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

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

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

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

            
932
    /// Return the type of this handshake.
933
55
    pub fn handshake_type(&self) -> HandshakeType {
934
55
        self.handshake_type
935
55
    }
936

            
937
    /// Return the inner handshake for this Extend2 cell.
938
495
    pub fn handshake(&self) -> &[u8] {
939
495
        &self.handshake[..]
940
495
    }
941
}
942

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

            
978
/// Extended2 is a successful reply to an Extend2 message.
979
///
980
/// Extended2 messages are generated by the former last hop of a
981
/// circuit, to tell the client that they have successfully completed
982
/// a handshake on the client's behalf.
983
#[derive(Debug, Clone, Deftly)]
984
#[derive_deftly(HasMemoryCost)]
985
pub struct Extended2 {
986
    /// Contents of the CREATED2 cell that the new final hop sent in
987
    /// response
988
    handshake: Vec<u8>,
989
}
990
impl Extended2 {
991
    /// Construct a new Extended2 message with the provided handshake
992
1045
    pub fn new(handshake: Vec<u8>) -> Self {
993
1045
        Extended2 { handshake }
994
1045
    }
995
    /// Consume this extended2 cell and return its body.
996
660
    pub fn into_body(self) -> Vec<u8> {
997
660
        self.handshake
998
660
    }
999
}
impl Body for Extended2 {
825
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
825
        let hlen = r.take_u16()?;
825
        let handshake = r.take(hlen as usize)?;
825
        Ok(Extended2 {
825
            handshake: handshake.into(),
825
        })
825
    }
44
    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
44
        let handshake_len: u16 = self
44
            .handshake
44
            .len()
44
            .try_into()
44
            .map_err(|_| EncodeError::BadLengthValue)?;
44
        w.write_u16(handshake_len);
44
        w.write_all(&self.handshake[..]);
44
        Ok(())
44
    }
}
/// 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.
55
    pub fn new(reason: DestroyReason) -> Self {
55
        Truncated { reason }
55
    }
    /// Get the provided reason to truncate the circuit.
    pub fn reason(self) -> DestroyReason {
        self.reason
    }
}
impl Body for Truncated {
55
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
55
        Ok(Truncated {
55
            reason: r.take_u8()?.into(),
        })
55
    }
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.
110
    pub fn new(s: &str) -> Self {
110
        Resolve {
110
            query: s.as_bytes().into(),
110
        }
110
    }
    /// Construct a new resolve message to do a reverse lookup on an address
110
    pub fn new_reverse(addr: &IpAddr) -> Self {
110
        let query = match addr {
55
            IpAddr::V4(v4) => {
55
                let [a, b, c, d] = v4.octets();
55
                format!("{}.{}.{}.{}.in-addr.arpa", d, c, b, a)
            }
55
            IpAddr::V6(v6) => {
55
                let mut s = String::with_capacity(72);
880
                for o in v6.octets().iter().rev() {
880
                    let high_nybble = o >> 4;
880
                    let low_nybble = o & 15;
880
                    write!(s, "{:x}.{:x}.", low_nybble, high_nybble)
880
                        .expect("write to string failed");
880
                }
55
                write!(s, "ip6.arpa").expect("write to string failed");
55
                s
            }
        };
110
        Resolve {
110
            query: query.into_bytes(),
110
        }
110
    }
}
impl Body for Resolve {
165
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
165
        let query = r.take_until(0)?;
165
        Ok(Resolve {
165
            query: query.into(),
165
        })
165
    }
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 {
495
    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.
495
        fn res_len(tp: u8) -> Option<usize> {
495
            match tp {
165
                RES_IPV4 => Some(4),
110
                RES_IPV6 => Some(16),
220
                _ => None,
            }
495
        }
495
        let tp = r.take_u8()?;
495
        let len = r.take_u8()? as usize;
495
        if let Some(expected_len) = res_len(tp) {
275
            if len != expected_len {
55
                return Err(Error::InvalidMessage(
55
                    "Wrong length for RESOLVED answer".into(),
55
                ));
220
            }
220
        }
440
        Ok(match tp {
55
            RES_HOSTNAME => Self::Hostname(r.take(len)?.into()),
110
            RES_IPV4 => Self::Ip(IpAddr::V4(r.extract()?)),
110
            RES_IPV6 => Self::Ip(IpAddr::V6(r.extract()?)),
            RES_ERR_TRANSIENT => {
55
                r.advance(len)?;
55
                Self::TransientError
            }
            RES_ERR_NONTRANSIENT => {
55
                r.advance(len)?;
55
                Self::NontransientError
            }
55
            _ => Self::Unrecognized(tp, r.take(len)?.into()),
        })
495
    }
}
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.
385
    pub fn new_empty() -> Self {
385
        Resolved {
385
            answers: Vec::new(),
385
        }
385
    }
    /// 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?
110
    pub fn new_err(transient: bool, ttl: u32) -> Self {
110
        let mut res = Self::new_empty();
110
        let err = if transient {
55
            ResolvedVal::TransientError
        } else {
55
            ResolvedVal::NontransientError
        };
110
        res.add_answer(err, ttl);
110
        res
110
    }
    /// Add a single answer to this Resolved message
385
    pub fn add_answer(&mut self, answer: ResolvedVal, ttl: u32) {
385
        self.answers.push((answer, ttl));
385
    }
    /// 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.
55
    pub fn into_answers(self) -> Vec<(ResolvedVal, u32)> {
55
        self.answers
55
    }
}
impl Body for Resolved {
495
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
495
        let mut answers = Vec::new();
935
        while r.remaining() > 0 {
495
            let rv = r.extract()?;
440
            let ttl = r.take_u32()?;
440
            answers.push((rv, ttl));
        }
440
        Ok(Resolved { answers })
495
    }
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
    {
2
        let body = body.into();
2
        Unrecognized { cmd, body }
2
    }
    /// Return the command associated with this message
55
    pub fn cmd(&self) -> RelayCmd {
55
        self.cmd
55
    }
    /// Decode this message, using a provided command.
55
    pub fn decode_with_cmd(cmd: RelayCmd, r: &mut Reader<'_>) -> Result<Self> {
55
        let mut r = Unrecognized::decode_from_reader(r)?;
55
        r.cmd = cmd;
55
        Ok(r)
55
    }
}
impl Body for Unrecognized {
55
    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
55
        Ok(Unrecognized {
55
            cmd: 0.into(),
55
            body: r.take(r.remaining())?.into(),
        })
55
    }
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 {
605
           fn decode_from_reader(_r: &mut Reader<'_>) -> Result<Self> {
605
               Ok(Self::default())
605
           }
54
           fn encode_onto<W: Writer + ?Sized>(self, _w: &mut W) -> EncodeResult<()> {
54
               Ok(())
54
           }
       }
   }
}
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)
            }
3410
            fn decode_from_reader(cmd: RelayCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
3410
                if cmd != crate::relaycell::RelayCmd::[< $body:snake:upper >] {
220
                    return Err(tor_bytes::Error::InvalidMessage(
220
                        format!("Expected {} command; got {cmd}", stringify!([< $body:snake:upper >])).into()
220
                    ));
3190
                }
3190
                crate::relaycell::msg::Body::decode_from_reader(r)
3410
            }
        }
        impl TryFrom<AnyRelayMsg> for $body {
            type Error = crate::Error;
4400
            fn try_from(msg: AnyRelayMsg) -> crate::Result<$body> {
                use crate::relaycell::RelayMsg;
4400
                match msg {
4400
                    AnyRelayMsg::$body(b) => Ok(b),
                    _ => Err(crate::Error::CircProto(format!("Expected {}; got {}" ,
                                                     stringify!([<$body:snake:upper>]),
                                                     msg.cmd())) ),
                }
4400
            }
        }
        )*
    }}
}
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);
#[cfg(feature = "flowctl-cc")]
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_duration_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 { .. }),
        ));
    }
}