tor_cell/relaycell/
msg.rs

1//! Encoding and decoding for relay messages
2//!
3//! Relay messages are sent along circuits, inside RELAY or RELAY_EARLY
4//! cells.
5
6use super::{RelayCellFormat, RelayCmd};
7use crate::chancell::msg::{
8    DestroyReason, HandshakeType, TAP_C_HANDSHAKE_LEN, TAP_S_HANDSHAKE_LEN,
9};
10use crate::chancell::CELL_DATA_LEN;
11use caret::caret_int;
12use derive_deftly::Deftly;
13use std::fmt::Write;
14use std::net::{IpAddr, Ipv4Addr};
15use std::num::NonZeroU8;
16use tor_bytes::{EncodeError, EncodeResult, Error, Result};
17use tor_bytes::{Readable, Reader, Writeable, Writer};
18use tor_linkspec::EncodedLinkSpec;
19use tor_llcrypto::pk::rsa::RsaIdentity;
20use tor_llcrypto::util::ct::CtByteArray;
21use tor_memquota::{derive_deftly_template_HasMemoryCost, memory_cost_structural_copy};
22
23use bitflags::bitflags;
24
25#[cfg(feature = "conflux")]
26#[cfg_attr(docsrs, doc(cfg(feature = "conflux")))]
27pub use super::conflux::{ConfluxLink, ConfluxLinked, ConfluxLinkedAck, ConfluxSwitch};
28
29#[cfg(feature = "hs")]
30#[cfg_attr(docsrs, doc(cfg(feature = "hs")))]
31pub use super::hs::{
32    est_intro::EstablishIntro, EstablishRendezvous, IntroEstablished, Introduce1, Introduce2,
33    IntroduceAck, Rendezvous1, Rendezvous2, RendezvousEstablished,
34};
35#[cfg(feature = "experimental-udp")]
36#[cfg_attr(docsrs, doc(cfg(feature = "experimental-udp")))]
37pub use super::udp::{ConnectUdp, ConnectedUdp, Datagram};
38
39crate::restrict::restricted_msg! {
40/// A single parsed relay message, sent or received along a circuit
41#[derive(Debug, Clone, Deftly)]
42#[derive_deftly(HasMemoryCost)]
43#[non_exhaustive]
44@omit_from "avoid_conflict_with_a_blanket_implementation"
45pub enum AnyRelayMsg : RelayMsg {
46    /// Create a stream
47    Begin,
48    /// Send data on a stream
49    Data,
50    /// Close a stream
51    End,
52    /// Successful response to a Begin message
53    Connected,
54    /// For flow control
55    Sendme,
56    /// Extend a circuit to a new hop (deprecated)
57    Extend,
58    /// Successful response to an Extend message (deprecated)
59    Extended,
60    /// Extend a circuit to a new hop
61    Extend2,
62    /// Successful response to an Extend2 message
63    Extended2,
64    /// Partially close a circuit
65    Truncate,
66    /// Tell the client that a circuit has been partially closed
67    Truncated,
68    /// Used for padding
69    Drop,
70    /// Launch a DNS request
71    Resolve,
72    /// Response to a Resolve message
73    Resolved,
74    /// Start a directory stream
75    BeginDir,
76    /// Start a UDP stream.
77    [feature = "experimental-udp"]
78    ConnectUdp,
79    /// Successful response to a ConnectUdp message
80    [feature = "experimental-udp"]
81    ConnectedUdp,
82    /// UDP stream data
83    [feature = "experimental-udp"]
84    Datagram,
85    /// Link circuits together at the receiving endpoint
86    [feature = "conflux"]
87    ConfluxLink,
88    /// Confirm that the circuits were linked
89    [feature = "conflux"]
90    ConfluxLinked,
91    /// Acknowledge the linkage of the circuits, for RTT measurement.
92    [feature = "conflux"]
93    ConfluxLinkedAck,
94    /// Switch to another leg in an already linked circuit construction.
95    [feature = "conflux"]
96    ConfluxSwitch,
97    /// Establish Introduction
98    [feature = "hs"]
99    EstablishIntro,
100    /// Establish Rendezvous
101    [feature = "hs"]
102    EstablishRendezvous,
103    /// Introduce1 (client to introduction point)
104    [feature = "hs"]
105    Introduce1,
106    /// Introduce2 (introduction point to service)
107    [feature = "hs"]
108    Introduce2,
109    /// Rendezvous1 (service to rendezvous point)
110    [feature = "hs"]
111    Rendezvous1,
112    /// Rendezvous2 (rendezvous point to client)
113    [feature = "hs"]
114    Rendezvous2,
115    /// Acknowledgement for EstablishIntro.
116    [feature = "hs"]
117    IntroEstablished,
118    /// Acknowledgment for EstablishRendezvous.
119    [feature = "hs"]
120    RendezvousEstablished,
121    /// Acknowledgement for Introduce1.
122    [feature = "hs"]
123    IntroduceAck,
124
125    _ =>
126    /// An unrecognized command.
127    Unrecognized,
128    }
129}
130
131/// Internal: traits in common different cell bodies.
132pub trait Body: Sized {
133    /// Decode a relay cell body from a provided reader.
134    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self>;
135    /// Encode the body of this cell into the end of a writer.
136    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()>;
137}
138
139bitflags! {
140    /// A set of recognized flags that can be attached to a begin cell.
141    ///
142    /// For historical reasons, these flags are constructed so that 0
143    /// is a reasonable default for all of them.
144    #[derive(Clone, Copy, Debug)]
145    pub struct BeginFlags : u32 {
146        /// The client would accept a connection to an IPv6 address.
147        const IPV6_OKAY = (1<<0);
148        /// The client would not accept a connection to an IPv4 address.
149        const IPV4_NOT_OKAY = (1<<1);
150        /// The client would rather have a connection to an IPv6 address.
151        const IPV6_PREFERRED = (1<<2);
152    }
153}
154memory_cost_structural_copy!(BeginFlags);
155impl From<u32> for BeginFlags {
156    fn from(v: u32) -> Self {
157        BeginFlags::from_bits_truncate(v)
158    }
159}
160
161/// A preference for IPv4 vs IPv6 addresses; usable as a nicer frontend for
162/// BeginFlags.
163#[derive(Clone, Default, Copy, Debug, Eq, PartialEq)]
164#[non_exhaustive]
165pub enum IpVersionPreference {
166    /// Only IPv4 is allowed.
167    Ipv4Only,
168    /// IPv4 and IPv6 are both allowed, and IPv4 is preferred.
169    #[default]
170    Ipv4Preferred,
171    /// IPv4 and IPv6 are both allowed, and IPv6 is preferred.
172    Ipv6Preferred,
173    /// Only IPv6 is allowed.
174    Ipv6Only,
175}
176impl From<IpVersionPreference> for BeginFlags {
177    fn from(v: IpVersionPreference) -> Self {
178        use IpVersionPreference::*;
179        match v {
180            Ipv4Only => 0.into(),
181            Ipv4Preferred => BeginFlags::IPV6_OKAY,
182            Ipv6Preferred => BeginFlags::IPV6_OKAY | BeginFlags::IPV6_PREFERRED,
183            Ipv6Only => BeginFlags::IPV4_NOT_OKAY,
184        }
185    }
186}
187
188/// A Begin message creates a new data stream.
189///
190/// Upon receiving a Begin message, relays should try to open a new stream
191/// for the client, if their exit policy permits, and associate it with a
192/// new TCP connection to the target address.
193///
194/// If the exit decides to reject the Begin message, or if the TCP
195/// connection fails, the exit should send an End message.
196///
197/// Clients should reject these messages.
198#[derive(Debug, Clone, Deftly)]
199#[derive_deftly(HasMemoryCost)]
200pub struct Begin {
201    /// Ascii string describing target address
202    addr: Vec<u8>,
203    /// Target port
204    port: u16,
205    /// Flags that describe how to resolve the address
206    flags: BeginFlags,
207}
208
209impl Begin {
210    /// Construct a new Begin cell
211    pub fn new<F>(addr: &str, port: u16, flags: F) -> crate::Result<Self>
212    where
213        F: Into<BeginFlags>,
214    {
215        if !addr.is_ascii() {
216            return Err(crate::Error::BadStreamAddress);
217        }
218        let mut addr = addr.to_string();
219        addr.make_ascii_lowercase();
220        Ok(Begin {
221            addr: addr.into_bytes(),
222            port,
223            flags: flags.into(),
224        })
225    }
226
227    /// Return the address requested in this message.
228    pub fn addr(&self) -> &[u8] {
229        &self.addr[..]
230    }
231
232    /// Return the port requested by this message.
233    pub fn port(&self) -> u16 {
234        self.port
235    }
236
237    /// Return the set of flags provided in this message.
238    pub fn flags(&self) -> BeginFlags {
239        self.flags
240    }
241}
242
243impl Body for Begin {
244    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
245        let addr = {
246            if r.peek(1)? == b"[" {
247                // IPv6 address
248                r.advance(1)?;
249                let a = r.take_until(b']')?;
250                let colon = r.take_u8()?;
251                if colon != b':' {
252                    return Err(Error::InvalidMessage("missing port in begin cell".into()));
253                }
254                a
255            } else {
256                // IPv4 address, or hostname.
257                r.take_until(b':')?
258            }
259        };
260        let port = r.take_until(0)?;
261        let flags = if r.remaining() >= 4 { r.take_u32()? } else { 0 };
262
263        if !addr.is_ascii() {
264            return Err(Error::InvalidMessage(
265                "target address in begin cell not ascii".into(),
266            ));
267        }
268
269        let port = std::str::from_utf8(port)
270            .map_err(|_| Error::InvalidMessage("port in begin cell not utf8".into()))?;
271
272        let port = port
273            .parse()
274            .map_err(|_| Error::InvalidMessage("port in begin cell not a valid port".into()))?;
275
276        Ok(Begin {
277            addr: addr.into(),
278            port,
279            flags: flags.into(),
280        })
281    }
282    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
283        if self.addr.contains(&b':') {
284            w.write_u8(b'[');
285            w.write_all(&self.addr[..]);
286            w.write_u8(b']');
287        } else {
288            w.write_all(&self.addr[..]);
289        }
290        w.write_u8(b':');
291        w.write_all(self.port.to_string().as_bytes());
292        w.write_u8(0);
293        if self.flags.bits() != 0 {
294            w.write_u32(self.flags.bits());
295        }
296        Ok(())
297    }
298}
299
300/// A Data message represents data sent along a stream.
301///
302/// Upon receiving a Data message for a live stream, the client or
303/// exit sends that data onto the associated TCP connection.
304///
305/// These messages hold between 1 and [Data::MAXLEN] bytes of data each;
306/// they are the most numerous messages on the Tor network.
307#[derive(Debug, Clone, Deftly)]
308#[derive_deftly(HasMemoryCost)]
309pub struct Data {
310    /// Contents of the cell, to be sent on a specific stream
311    ///
312    /// INVARIANT: Holds between 1 and [`Data::MAXLEN`] bytes, inclusive.
313    //
314    // TODO: There's a good case to be made that this should be a BoxedCellBody
315    // instead, to avoid allocations and copies.  But first probably we should
316    // figure out how proposal 340 will work with this.  Possibly, we will wind
317    // up using `bytes` or something.
318    body: Vec<u8>,
319}
320impl Data {
321    /// The longest allowable body length for a single V0 data cell.
322    ///
323    /// Relay command (1) + 'Recognized' (2) + StreamID (2) + Digest (4) + Length (2) = 11
324    pub const MAXLEN_V0: usize = CELL_DATA_LEN - 11;
325
326    /// The longest allowable body length for a single V1 data cell.
327    ///
328    /// Tag (16) + Relay command (1) + Length (2) + StreamID (2) = 21
329    pub const MAXLEN_V1: usize = CELL_DATA_LEN - 21;
330
331    /// The longest allowable body length for any data cell.
332    ///
333    /// Note that this value is too large to fit into a v1 relay cell;
334    /// see [`MAXLEN_V1`](Data::MAXLEN_V1) if you are making a v1 data cell.
335    ///
336    pub const MAXLEN: usize = Data::MAXLEN_V0;
337
338    /// Construct a new data cell.
339    ///
340    /// Returns an error if `inp` is longer than [`Data::MAXLEN`] bytes.
341    pub fn new(inp: &[u8]) -> crate::Result<Self> {
342        if inp.len() > Data::MAXLEN {
343            return Err(crate::Error::CantEncode("Data message too long"));
344        }
345        if inp.is_empty() {
346            return Err(crate::Error::CantEncode("Empty data message"));
347        }
348        Ok(Self::new_unchecked(inp.into()))
349    }
350
351    /// Construct a new data cell, taking as many bytes from `inp`
352    /// as possible.
353    ///
354    /// Return the data cell, and a slice holding any bytes that
355    /// wouldn't fit (if any).
356    ///
357    /// Returns None if the input was empty.
358    pub fn try_split_from(version: RelayCellFormat, inp: &[u8]) -> Option<(Self, &[u8])> {
359        if inp.is_empty() {
360            return None;
361        }
362        let upper_bound = Self::max_body_len(version);
363        let len = std::cmp::min(inp.len(), upper_bound);
364        let (data, remainder) = inp.split_at(len);
365        Some((Self::new_unchecked(data.into()), remainder))
366    }
367
368    /// Construct a new data cell from a provided vector of bytes.
369    ///
370    /// The vector _must_ not have more than [`Data::MAXLEN`] bytes, and must
371    /// not be empty.
372    fn new_unchecked(body: Vec<u8>) -> Self {
373        debug_assert!((1..=Data::MAXLEN).contains(&body.len()));
374        Data { body }
375    }
376
377    /// Return the maximum allowable body length for a Data message
378    /// using the provided `format`.
379    pub fn max_body_len(format: RelayCellFormat) -> usize {
380        match format {
381            RelayCellFormat::V0 => Self::MAXLEN_V0,
382            RelayCellFormat::V1 => Self::MAXLEN_V1,
383        }
384    }
385}
386impl From<Data> for Vec<u8> {
387    fn from(data: Data) -> Vec<u8> {
388        data.body
389    }
390}
391impl AsRef<[u8]> for Data {
392    fn as_ref(&self) -> &[u8] {
393        &self.body[..]
394    }
395}
396
397impl Body for Data {
398    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
399        if r.remaining() == 0 {
400            return Err(Error::InvalidMessage("Empty DATA message".into()));
401        }
402        Ok(Data {
403            body: r.take(r.remaining())?.into(),
404        })
405    }
406    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
407        w.write_all(&self.body);
408        Ok(())
409    }
410}
411
412/// An End message tells the other end of the circuit to close a stream.
413///
414/// Note that End messages do not implement a true half-closed state,
415/// so after sending an End message each party needs to wait a while
416/// to be sure that the stream is completely dead.
417#[derive(Debug, Clone, Deftly)]
418#[derive_deftly(HasMemoryCost)]
419pub struct End {
420    /// Reason for closing the stream
421    reason: EndReason,
422    /// If the reason is EXITPOLICY, this holds the resolved address an
423    /// associated TTL.  The TTL is set to MAX if none was given.
424    addr: Option<(IpAddr, u32)>,
425}
426
427caret_int! {
428    /// A declared reason for closing a stream
429    #[derive(Deftly)]
430    #[derive_deftly(HasMemoryCost)]
431    pub struct EndReason(u8) {
432        /// Closing a stream because of an unspecified reason.
433        ///
434        /// This is the only END reason that clients send.
435        MISC = 1,
436        /// Couldn't look up hostname.
437        RESOLVEFAILED = 2,
438        /// Remote host refused connection.
439        CONNECTREFUSED = 3,
440        /// Closing a stream because of an exit-policy violation.
441        EXITPOLICY = 4,
442        /// Circuit destroyed
443        DESTROY = 5,
444        /// Anonymized TCP connection was closed
445        DONE = 6,
446        /// Connection timed out, or OR timed out while connecting
447        TIMEOUT = 7,
448        /// No route to target destination.
449        NOROUTE = 8,
450        /// OR is entering hibernation and not handling requests
451        HIBERNATING = 9,
452        /// Internal error at the OR
453        INTERNAL = 10,
454        /// Ran out of resources to fulfill requests
455        RESOURCELIMIT = 11,
456        /// Connection unexpectedly reset
457        CONNRESET = 12,
458        /// Tor protocol violation
459        TORPROTOCOL = 13,
460        /// BEGIN_DIR cell at a non-directory-cache.
461        NOTDIRECTORY = 14,
462    }
463}
464
465impl tor_error::HasKind for EndReason {
466    fn kind(&self) -> tor_error::ErrorKind {
467        use tor_error::ErrorKind as EK;
468        use EndReason as E;
469        match *self {
470            E::MISC => EK::RemoteStreamError,
471            E::RESOLVEFAILED => EK::RemoteHostResolutionFailed,
472            E::CONNECTREFUSED => EK::RemoteConnectionRefused,
473            E::EXITPOLICY => EK::ExitPolicyRejected,
474            E::DESTROY => EK::CircuitCollapse,
475            E::DONE => EK::RemoteStreamClosed,
476            E::TIMEOUT => EK::ExitTimeout,
477            E::NOROUTE => EK::RemoteNetworkFailed,
478            E::RESOURCELIMIT | E::HIBERNATING => EK::RelayTooBusy,
479            E::INTERNAL | E::TORPROTOCOL | E::NOTDIRECTORY => EK::TorProtocolViolation,
480            E::CONNRESET => EK::RemoteStreamReset,
481            _ => EK::RemoteStreamError,
482        }
483    }
484}
485
486impl End {
487    /// Make a new END_REASON_MISC message.
488    ///
489    /// Clients send this every time they decide to close a stream.
490    pub fn new_misc() -> Self {
491        End {
492            reason: EndReason::MISC,
493            addr: None,
494        }
495    }
496    /// Make a new END message with the provided end reason.
497    pub fn new_with_reason(reason: EndReason) -> Self {
498        End { reason, addr: None }
499    }
500    /// Make a new END message with END_REASON_EXITPOLICY, and the
501    /// provided address and ttl.
502    pub fn new_exitpolicy(addr: IpAddr, ttl: u32) -> Self {
503        End {
504            reason: EndReason::EXITPOLICY,
505            addr: Some((addr, ttl)),
506        }
507    }
508    /// Return the provided EndReason for this End cell.
509    pub fn reason(&self) -> EndReason {
510        self.reason
511    }
512}
513impl Body for End {
514    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
515        if r.remaining() == 0 {
516            return Ok(End {
517                reason: EndReason::MISC,
518                addr: None,
519            });
520        }
521        let reason = r.take_u8()?.into();
522        if reason == EndReason::EXITPOLICY {
523            let addr = match r.remaining() {
524                4 | 8 => IpAddr::V4(r.extract()?),
525                16 | 20 => IpAddr::V6(r.extract()?),
526                _ => {
527                    // Ignores other message lengths.
528                    return Ok(End { reason, addr: None });
529                }
530            };
531            let ttl = if r.remaining() == 4 {
532                r.take_u32()?
533            } else {
534                u32::MAX
535            };
536            Ok(End {
537                reason,
538                addr: Some((addr, ttl)),
539            })
540        } else {
541            Ok(End { reason, addr: None })
542        }
543    }
544    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
545        w.write_u8(self.reason.into());
546        if let (EndReason::EXITPOLICY, Some((addr, ttl))) = (self.reason, self.addr) {
547            match addr {
548                IpAddr::V4(v4) => w.write(&v4)?,
549                IpAddr::V6(v6) => w.write(&v6)?,
550            }
551            w.write_u32(ttl);
552        }
553        Ok(())
554    }
555}
556
557impl From<EndReason> for std::io::ErrorKind {
558    fn from(e: EndReason) -> Self {
559        use std::io::ErrorKind::*;
560        match e {
561            EndReason::RESOLVEFAILED => NotFound,
562            EndReason::CONNECTREFUSED => ConnectionRefused,
563            EndReason::EXITPOLICY => ConnectionRefused,
564            EndReason::DESTROY => ConnectionAborted,
565            EndReason::DONE => UnexpectedEof,
566            EndReason::TIMEOUT => TimedOut,
567            EndReason::HIBERNATING => ConnectionRefused,
568            EndReason::RESOURCELIMIT => ConnectionRefused,
569            EndReason::CONNRESET => ConnectionReset,
570            EndReason::TORPROTOCOL => InvalidData,
571            EndReason::NOTDIRECTORY => ConnectionRefused,
572            EndReason::INTERNAL | EndReason::NOROUTE | EndReason::MISC => Other,
573            _ => Other,
574        }
575    }
576}
577
578/// A Connected message is a successful response to a Begin message
579///
580/// When an outgoing connection succeeds, the exit sends a Connected
581/// back to the client.
582///
583/// Clients never send Connected messages.
584#[derive(Debug, Clone, Deftly)]
585#[derive_deftly(HasMemoryCost)]
586pub struct Connected {
587    /// Resolved address and TTL (time to live) in seconds
588    addr: Option<(IpAddr, u32)>,
589}
590impl Connected {
591    /// Construct a new empty connected cell.
592    pub fn new_empty() -> Self {
593        Connected { addr: None }
594    }
595    /// Construct a connected cell with an address and a time-to-live value.
596    pub fn new_with_addr(addr: IpAddr, ttl: u32) -> Self {
597        Connected {
598            addr: Some((addr, ttl)),
599        }
600    }
601}
602impl Body for Connected {
603    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
604        if r.remaining() == 0 {
605            return Ok(Connected { addr: None });
606        }
607        let ipv4 = r.take_u32()?;
608        let addr = if ipv4 == 0 {
609            if r.take_u8()? != 6 {
610                return Err(Error::InvalidMessage(
611                    "Invalid address type in CONNECTED cell".into(),
612                ));
613            }
614            IpAddr::V6(r.extract()?)
615        } else {
616            IpAddr::V4(ipv4.into())
617        };
618        let ttl = r.take_u32()?;
619
620        Ok(Connected {
621            addr: Some((addr, ttl)),
622        })
623    }
624    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
625        if let Some((addr, ttl)) = self.addr {
626            match addr {
627                IpAddr::V4(v4) => w.write(&v4)?,
628                IpAddr::V6(v6) => {
629                    w.write_u32(0);
630                    w.write_u8(6);
631                    w.write(&v6)?;
632                }
633            }
634            w.write_u32(ttl);
635        }
636        Ok(())
637    }
638}
639
640/// An authentication tag to use for circuit-level SENDME messages.
641///
642/// It is either a 20-byte tag (used with Tor1 encryption),
643/// or a 16-byte tag (used with CGO encryption).
644#[derive(Debug, Clone, Copy, Eq, PartialEq, Deftly)]
645#[derive_deftly(HasMemoryCost)]
646pub struct SendmeTag {
647    /// The number of bytes present in the tag.
648    /// Always equal to 16 or 20.
649    ///
650    /// We use a NonZeroU8 here so Rust can use its niche optimization.
651    len: NonZeroU8,
652    /// The actual contents of the tag.
653    ///
654    /// Tags above 20 bytes long are always an error.
655    ///
656    /// Unused bytes are always set to zero, so we can derive PartialEq.
657    tag: CtByteArray<20>,
658}
659impl From<[u8; 20]> for SendmeTag {
660    // In experimentation, these "inlines" were necessary for good generated asm.
661    #[inline]
662    fn from(value: [u8; 20]) -> Self {
663        Self {
664            len: NonZeroU8::new(20).expect("20 was not nonzero?"),
665            tag: CtByteArray::from(value),
666        }
667    }
668}
669impl From<[u8; 16]> for SendmeTag {
670    // In experimentation, these "inlines" were necessary for good generated asm.
671    #[inline]
672    fn from(value: [u8; 16]) -> Self {
673        let mut tag = CtByteArray::from([0; 20]);
674        tag.as_mut()[0..16].copy_from_slice(&value[..]);
675        Self {
676            len: NonZeroU8::new(16).expect("16 was not nonzero?"),
677            tag,
678        }
679    }
680}
681impl AsRef<[u8]> for SendmeTag {
682    fn as_ref(&self) -> &[u8] {
683        &self.tag.as_ref()[0..usize::from(u8::from(self.len))]
684    }
685}
686/// An error from attempting to decode a SENDME tag.
687#[derive(Clone, Debug, thiserror::Error)]
688#[non_exhaustive]
689#[error("Invalid size {} on SENDME tag", len)]
690pub struct InvalidSendmeTag {
691    /// The length of the invalid tag.
692    len: usize,
693}
694impl From<InvalidSendmeTag> for tor_bytes::Error {
695    fn from(_: InvalidSendmeTag) -> Self {
696        tor_bytes::Error::BadLengthValue
697    }
698}
699
700impl<'a> TryFrom<&'a [u8]> for SendmeTag {
701    type Error = InvalidSendmeTag;
702
703    // In experimentation, this "inline" was especially necessary for good generated asm.
704    #[inline]
705    fn try_from(value: &'a [u8]) -> std::result::Result<Self, Self::Error> {
706        match value.len() {
707            16 => {
708                let a: [u8; 16] = value.try_into().expect("16 was not 16?");
709                Ok(Self::from(a))
710            }
711            20 => {
712                let a: [u8; 20] = value.try_into().expect("20 was not 20?");
713                Ok(Self::from(a))
714            }
715            _ => Err(InvalidSendmeTag { len: value.len() }),
716        }
717    }
718}
719
720/// A Sendme message is used to increase flow-control windows.
721///
722/// To avoid congestion, each Tor circuit and stream keeps track of a
723/// number of data cells that it is willing to send.  It decrements
724/// these numbers every time it sends a cell.  If these numbers reach
725/// zero, then no more cells can be sent on the stream or circuit.
726///
727/// The only way to re-increment these numbers is by receiving a
728/// Sendme cell from the other end of the circuit or stream.
729///
730/// For security, current circuit-level Sendme cells include an
731/// authentication tag that proves knowledge of the cells that they are
732/// acking.
733///
734/// See [tor-spec.txt](https://spec.torproject.org/tor-spec) for more
735/// information; also see the source for `tor_proto::circuit::sendme`.
736#[derive(Debug, Clone, Deftly)]
737#[derive_deftly(HasMemoryCost)]
738pub struct Sendme {
739    /// A tag value authenticating the previously received data.
740    tag: Option<SendmeTag>,
741}
742impl Sendme {
743    /// Return a new empty sendme cell
744    ///
745    /// This format is used on streams, and on circuits without sendme
746    /// authentication.
747    pub fn new_empty() -> Self {
748        Sendme { tag: None }
749    }
750    /// This format is used on circuits with sendme authentication.
751    pub fn new_tag(x: [u8; 20]) -> Self {
752        Sendme {
753            tag: Some(x.into()),
754        }
755    }
756    /// Consume this cell and return its authentication tag, if any
757    pub fn into_sendme_tag(self) -> Option<SendmeTag> {
758        self.tag
759    }
760}
761impl From<SendmeTag> for Sendme {
762    fn from(value: SendmeTag) -> Self {
763        Self { tag: Some(value) }
764    }
765}
766impl Body for Sendme {
767    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
768        let tag = if r.remaining() == 0 {
769            None
770        } else {
771            let ver = r.take_u8()?;
772            match ver {
773                0 => None,
774                1 => {
775                    let dlen = r.take_u16()?;
776                    Some(r.take(dlen as usize)?.try_into()?)
777                }
778                _ => {
779                    return Err(Error::InvalidMessage("Unrecognized SENDME version.".into()));
780                }
781            }
782        };
783        Ok(Sendme { tag })
784    }
785    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
786        match self.tag {
787            None => (),
788            Some(x) => {
789                w.write_u8(1);
790                let x = x.as_ref();
791                let bodylen: u16 = x
792                    .len()
793                    .try_into()
794                    .map_err(|_| EncodeError::BadLengthValue)?;
795                w.write_u16(bodylen);
796                w.write_all(x);
797            }
798        }
799        Ok(())
800    }
801}
802
803/// Extend was an obsolete circuit extension message format.
804///
805/// This format only handled IPv4 addresses, RSA identities, and the
806/// TAP handshake.  Modern Tor clients use Extend2 instead.
807#[derive(Debug, Clone, Deftly)]
808#[derive_deftly(HasMemoryCost)]
809pub struct Extend {
810    /// Where to extend to (address)
811    addr: Ipv4Addr,
812    /// Where to extend to (port)
813    port: u16,
814    /// A TAP handshake to send
815    handshake: Vec<u8>,
816    /// The RSA identity of the target relay
817    rsaid: RsaIdentity,
818}
819impl Extend {
820    /// Construct a new (deprecated) extend cell
821    pub fn new(addr: Ipv4Addr, port: u16, handshake: Vec<u8>, rsaid: RsaIdentity) -> Self {
822        Extend {
823            addr,
824            port,
825            handshake,
826            rsaid,
827        }
828    }
829}
830impl Body for Extend {
831    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
832        let addr = r.extract()?;
833        let port = r.take_u16()?;
834        let handshake = r.take(TAP_C_HANDSHAKE_LEN)?.into();
835        let rsaid = r.extract()?;
836        Ok(Extend {
837            addr,
838            port,
839            handshake,
840            rsaid,
841        })
842    }
843    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
844        w.write(&self.addr)?;
845        w.write_u16(self.port);
846        w.write_all(&self.handshake[..]);
847        w.write(&self.rsaid)?;
848        Ok(())
849    }
850}
851
852/// Extended was an obsolete circuit extension message, sent in reply to
853/// an Extend message.
854///
855/// Like Extend, the Extended message was only designed for the TAP
856/// handshake.
857#[derive(Debug, Clone, Deftly)]
858#[derive_deftly(HasMemoryCost)]
859pub struct Extended {
860    /// Contents of the handshake sent in response to the EXTEND
861    handshake: Vec<u8>,
862}
863impl Extended {
864    /// Construct a new Extended message with the provided handshake
865    pub fn new(handshake: Vec<u8>) -> Self {
866        Extended { handshake }
867    }
868}
869impl Body for Extended {
870    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
871        let handshake = r.take(TAP_S_HANDSHAKE_LEN)?.into();
872        Ok(Extended { handshake })
873    }
874    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
875        w.write_all(&self.handshake);
876        Ok(())
877    }
878}
879
880/// An Extend2 message tells the last relay in a circuit to extend to a new
881/// hop.
882///
883/// When a relay (call it R) receives an Extend2 message, it tries to
884/// find (or make) a channel to the other relay (R') described in the
885/// list of link specifiers. (A link specifier can be an IP addresses
886/// or a cryptographic identity).  Once R has such a channel, the
887/// it packages the client's handshake data as a new Create2 message
888/// R'.  If R' replies with a Created2 (success) message, R packages
889/// that message's contents in an Extended message.
890//
891/// Unlike Extend messages, Extend2 messages can encode any handshake
892/// type, and can describe relays in ways other than IPv4 addresses
893/// and RSA identities.
894#[derive(Debug, Clone, Deftly)]
895#[derive_deftly(HasMemoryCost)]
896pub struct Extend2 {
897    /// A vector of "link specifiers"
898    ///
899    /// These link specifiers describe where to find the target relay
900    /// that the recipient should extend to.  They include things like
901    /// IP addresses and identity keys.
902    linkspec: Vec<EncodedLinkSpec>,
903    /// Type of handshake to be sent in a CREATE2 cell
904    handshake_type: HandshakeType,
905    /// Body of the handshake to be sent in a CREATE2 cell
906    handshake: Vec<u8>,
907}
908impl Extend2 {
909    /// Create a new Extend2 cell.
910    pub fn new(
911        linkspec: Vec<EncodedLinkSpec>,
912        handshake_type: HandshakeType,
913        handshake: Vec<u8>,
914    ) -> Self {
915        Extend2 {
916            linkspec,
917            handshake_type,
918            handshake,
919        }
920    }
921
922    /// Return the type of this handshake.
923    pub fn handshake_type(&self) -> HandshakeType {
924        self.handshake_type
925    }
926
927    /// Return the inner handshake for this Extend2 cell.
928    pub fn handshake(&self) -> &[u8] {
929        &self.handshake[..]
930    }
931}
932
933impl Body for Extend2 {
934    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
935        let n = r.take_u8()?;
936        let linkspec = r.extract_n(n as usize)?;
937        let handshake_type = r.take_u16()?.into();
938        let hlen = r.take_u16()?;
939        let handshake = r.take(hlen as usize)?.into();
940        Ok(Extend2 {
941            linkspec,
942            handshake_type,
943            handshake,
944        })
945    }
946    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
947        let n_linkspecs: u8 = self
948            .linkspec
949            .len()
950            .try_into()
951            .map_err(|_| EncodeError::BadLengthValue)?;
952        w.write_u8(n_linkspecs);
953        for ls in &self.linkspec {
954            w.write(ls)?;
955        }
956        w.write_u16(self.handshake_type.into());
957        let handshake_len: u16 = self
958            .handshake
959            .len()
960            .try_into()
961            .map_err(|_| EncodeError::BadLengthValue)?;
962        w.write_u16(handshake_len);
963        w.write_all(&self.handshake[..]);
964        Ok(())
965    }
966}
967
968/// Extended2 is a successful reply to an Extend2 message.
969///
970/// Extended2 messages are generated by the former last hop of a
971/// circuit, to tell the client that they have successfully completed
972/// a handshake on the client's behalf.
973#[derive(Debug, Clone, Deftly)]
974#[derive_deftly(HasMemoryCost)]
975pub struct Extended2 {
976    /// Contents of the CREATED2 cell that the new final hop sent in
977    /// response
978    handshake: Vec<u8>,
979}
980impl Extended2 {
981    /// Construct a new Extended2 message with the provided handshake
982    pub fn new(handshake: Vec<u8>) -> Self {
983        Extended2 { handshake }
984    }
985    /// Consume this extended2 cell and return its body.
986    pub fn into_body(self) -> Vec<u8> {
987        self.handshake
988    }
989}
990impl Body for Extended2 {
991    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
992        let hlen = r.take_u16()?;
993        let handshake = r.take(hlen as usize)?;
994        Ok(Extended2 {
995            handshake: handshake.into(),
996        })
997    }
998    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
999        let handshake_len: u16 = self
1000            .handshake
1001            .len()
1002            .try_into()
1003            .map_err(|_| EncodeError::BadLengthValue)?;
1004        w.write_u16(handshake_len);
1005        w.write_all(&self.handshake[..]);
1006        Ok(())
1007    }
1008}
1009
1010/// A Truncated message is sent to the client when the remaining hops
1011/// of a circuit have gone away.
1012///
1013/// NOTE: Current Tor implementations often treat Truncated messages and
1014/// Destroy messages interchangeably.  Truncated was intended to be a
1015/// "soft" Destroy, that would leave the unaffected parts of a circuit
1016/// still usable.
1017#[derive(Debug, Clone, Deftly)]
1018#[derive_deftly(HasMemoryCost)]
1019pub struct Truncated {
1020    /// Reason for which this circuit was truncated.
1021    reason: DestroyReason,
1022}
1023impl Truncated {
1024    /// Construct a new truncated message.
1025    pub fn new(reason: DestroyReason) -> Self {
1026        Truncated { reason }
1027    }
1028    /// Get the provided reason to truncate the circuit.
1029    pub fn reason(self) -> DestroyReason {
1030        self.reason
1031    }
1032}
1033impl Body for Truncated {
1034    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
1035        Ok(Truncated {
1036            reason: r.take_u8()?.into(),
1037        })
1038    }
1039    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1040        w.write_u8(self.reason.into());
1041        Ok(())
1042    }
1043}
1044
1045/// A Resolve message launches a DNS lookup stream.
1046///
1047/// A client sends a Resolve message when it wants to perform a DNS
1048/// lookup _without_ connecting to the resulting address.  On success
1049/// the exit responds with a Resolved message; on failure it responds
1050/// with an End message.
1051#[derive(Debug, Clone, Deftly)]
1052#[derive_deftly(HasMemoryCost)]
1053pub struct Resolve {
1054    /// Ascii-encoded address to resolve
1055    query: Vec<u8>,
1056}
1057impl Resolve {
1058    /// Construct a new resolve message to look up a hostname.
1059    pub fn new(s: &str) -> Self {
1060        Resolve {
1061            query: s.as_bytes().into(),
1062        }
1063    }
1064    /// Construct a new resolve message to do a reverse lookup on an address
1065    pub fn new_reverse(addr: &IpAddr) -> Self {
1066        let query = match addr {
1067            IpAddr::V4(v4) => {
1068                let [a, b, c, d] = v4.octets();
1069                format!("{}.{}.{}.{}.in-addr.arpa", d, c, b, a)
1070            }
1071            IpAddr::V6(v6) => {
1072                let mut s = String::with_capacity(72);
1073                for o in v6.octets().iter().rev() {
1074                    let high_nybble = o >> 4;
1075                    let low_nybble = o & 15;
1076                    write!(s, "{:x}.{:x}.", low_nybble, high_nybble).unwrap();
1077                }
1078                write!(s, "ip6.arpa").unwrap();
1079                s
1080            }
1081        };
1082        Resolve {
1083            query: query.into_bytes(),
1084        }
1085    }
1086}
1087impl Body for Resolve {
1088    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
1089        let query = r.take_until(0)?;
1090        Ok(Resolve {
1091            query: query.into(),
1092        })
1093    }
1094    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1095        w.write_all(&self.query[..]);
1096        w.write_u8(0);
1097        Ok(())
1098    }
1099}
1100
1101/// Possible response to a DNS lookup
1102#[derive(Debug, Clone, Eq, PartialEq, Deftly)]
1103#[derive_deftly(HasMemoryCost)]
1104#[non_exhaustive]
1105pub enum ResolvedVal {
1106    /// We found an IP address
1107    Ip(IpAddr),
1108    /// We found a hostname
1109    Hostname(Vec<u8>),
1110    /// Error; try again
1111    TransientError,
1112    /// Error; don't try again
1113    NontransientError,
1114    /// A DNS lookup response that we didn't recognize
1115    Unrecognized(u8, Vec<u8>),
1116}
1117
1118/// Indicates a hostname response
1119const RES_HOSTNAME: u8 = 0;
1120/// Indicates an IPv4 response
1121const RES_IPV4: u8 = 4;
1122/// Indicates an IPv6 response
1123const RES_IPV6: u8 = 6;
1124/// Transient error (okay to try again)
1125const RES_ERR_TRANSIENT: u8 = 0xF0;
1126/// Non-transient error (don't try again)
1127const RES_ERR_NONTRANSIENT: u8 = 0xF1;
1128
1129impl Readable for ResolvedVal {
1130    fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1131        /// Helper: return the expected length of a resolved answer with
1132        /// a given type, if there is a particular expected length.
1133        fn res_len(tp: u8) -> Option<usize> {
1134            match tp {
1135                RES_IPV4 => Some(4),
1136                RES_IPV6 => Some(16),
1137                _ => None,
1138            }
1139        }
1140        let tp = r.take_u8()?;
1141        let len = r.take_u8()? as usize;
1142        if let Some(expected_len) = res_len(tp) {
1143            if len != expected_len {
1144                return Err(Error::InvalidMessage(
1145                    "Wrong length for RESOLVED answer".into(),
1146                ));
1147            }
1148        }
1149        Ok(match tp {
1150            RES_HOSTNAME => Self::Hostname(r.take(len)?.into()),
1151            RES_IPV4 => Self::Ip(IpAddr::V4(r.extract()?)),
1152            RES_IPV6 => Self::Ip(IpAddr::V6(r.extract()?)),
1153            RES_ERR_TRANSIENT => {
1154                r.advance(len)?;
1155                Self::TransientError
1156            }
1157            RES_ERR_NONTRANSIENT => {
1158                r.advance(len)?;
1159                Self::NontransientError
1160            }
1161            _ => Self::Unrecognized(tp, r.take(len)?.into()),
1162        })
1163    }
1164}
1165
1166impl Writeable for ResolvedVal {
1167    fn write_onto<B: Writer + ?Sized>(&self, w: &mut B) -> EncodeResult<()> {
1168        match self {
1169            Self::Hostname(h) => {
1170                w.write_u8(RES_HOSTNAME);
1171                let h_len: u8 = h
1172                    .len()
1173                    .try_into()
1174                    .map_err(|_| EncodeError::BadLengthValue)?;
1175                w.write_u8(h_len);
1176                w.write_all(&h[..]);
1177            }
1178            Self::Ip(IpAddr::V4(a)) => {
1179                w.write_u8(RES_IPV4);
1180                w.write_u8(4); // length
1181                w.write(a)?;
1182            }
1183            Self::Ip(IpAddr::V6(a)) => {
1184                w.write_u8(RES_IPV6);
1185                w.write_u8(16); // length
1186                w.write(a)?;
1187            }
1188            Self::TransientError => {
1189                w.write_u8(RES_ERR_TRANSIENT);
1190                w.write_u8(0); // length
1191            }
1192            Self::NontransientError => {
1193                w.write_u8(RES_ERR_NONTRANSIENT);
1194                w.write_u8(0); // length
1195            }
1196            Self::Unrecognized(tp, v) => {
1197                w.write_u8(*tp);
1198                let v_len: u8 = v
1199                    .len()
1200                    .try_into()
1201                    .map_err(|_| EncodeError::BadLengthValue)?;
1202                w.write_u8(v_len);
1203                w.write_all(&v[..]);
1204            }
1205        }
1206        Ok(())
1207    }
1208}
1209
1210/// A Resolved message is a successful reply to a Resolve message.
1211///
1212/// The Resolved message contains a list of zero or more addresses,
1213/// and their associated times-to-live in seconds.
1214#[derive(Debug, Clone, Deftly)]
1215#[derive_deftly(HasMemoryCost)]
1216pub struct Resolved {
1217    /// List of addresses and their associated time-to-live values.
1218    answers: Vec<(ResolvedVal, u32)>,
1219}
1220impl Resolved {
1221    /// Return a new empty Resolved object with no answers.
1222    pub fn new_empty() -> Self {
1223        Resolved {
1224            answers: Vec::new(),
1225        }
1226    }
1227    /// Return a new Resolved object reporting a name lookup error.
1228    ///
1229    /// TODO: Is getting no answer an error; or it is represented by
1230    /// a list of no answers?
1231    pub fn new_err(transient: bool, ttl: u32) -> Self {
1232        let mut res = Self::new_empty();
1233        let err = if transient {
1234            ResolvedVal::TransientError
1235        } else {
1236            ResolvedVal::NontransientError
1237        };
1238        res.add_answer(err, ttl);
1239        res
1240    }
1241    /// Add a single answer to this Resolved message
1242    pub fn add_answer(&mut self, answer: ResolvedVal, ttl: u32) {
1243        self.answers.push((answer, ttl));
1244    }
1245
1246    /// Consume this Resolved message, returning a vector of the
1247    /// answers and TTL values that it contains.
1248    ///
1249    /// Note that actually relying on these TTL values can be
1250    /// dangerous in practice, since the relay that sent the cell
1251    /// could be lying in order to cause more lookups, or to get a
1252    /// false answer cached for longer.
1253    pub fn into_answers(self) -> Vec<(ResolvedVal, u32)> {
1254        self.answers
1255    }
1256}
1257impl Body for Resolved {
1258    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
1259        let mut answers = Vec::new();
1260        while r.remaining() > 0 {
1261            let rv = r.extract()?;
1262            let ttl = r.take_u32()?;
1263            answers.push((rv, ttl));
1264        }
1265        Ok(Resolved { answers })
1266    }
1267    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1268        for (rv, ttl) in &self.answers {
1269            w.write(rv)?;
1270            w.write_u32(*ttl);
1271        }
1272        Ok(())
1273    }
1274}
1275
1276/// A relay message that we didn't recognize
1277///
1278/// NOTE: Clients should generally reject these.
1279#[derive(Debug, Clone, Deftly)]
1280#[derive_deftly(HasMemoryCost)]
1281pub struct Unrecognized {
1282    /// Command that we didn't recognize
1283    cmd: RelayCmd,
1284    /// Body associated with that command
1285    body: Vec<u8>,
1286}
1287
1288impl Unrecognized {
1289    /// Create a new 'unrecognized' cell.
1290    pub fn new<B>(cmd: RelayCmd, body: B) -> Self
1291    where
1292        B: Into<Vec<u8>>,
1293    {
1294        let body = body.into();
1295        Unrecognized { cmd, body }
1296    }
1297
1298    /// Return the command associated with this message
1299    pub fn cmd(&self) -> RelayCmd {
1300        self.cmd
1301    }
1302    /// Decode this message, using a provided command.
1303    pub fn decode_with_cmd(cmd: RelayCmd, r: &mut Reader<'_>) -> Result<Self> {
1304        let mut r = Unrecognized::decode_from_reader(r)?;
1305        r.cmd = cmd;
1306        Ok(r)
1307    }
1308}
1309
1310impl Body for Unrecognized {
1311    fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
1312        Ok(Unrecognized {
1313            cmd: 0.into(),
1314            body: r.take(r.remaining())?.into(),
1315        })
1316    }
1317    fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1318        w.write_all(&self.body[..]);
1319        Ok(())
1320    }
1321}
1322
1323/// Declare a message type for a message with an empty body.
1324macro_rules! empty_body {
1325   {
1326       $(#[$meta:meta])*
1327       pub struct $name:ident {}
1328   } => {
1329       $(#[$meta])*
1330       #[derive(Clone,Debug,Default,derive_deftly::Deftly)]
1331       #[derive_deftly(tor_memquota::HasMemoryCost)]
1332       #[non_exhaustive]
1333       pub struct $name {}
1334       impl $crate::relaycell::msg::Body for $name {
1335           fn decode_from_reader(_r: &mut Reader<'_>) -> Result<Self> {
1336               Ok(Self::default())
1337           }
1338           fn encode_onto<W: Writer + ?Sized>(self, _w: &mut W) -> EncodeResult<()> {
1339               Ok(())
1340           }
1341       }
1342   }
1343}
1344pub(crate) use empty_body;
1345
1346empty_body! {
1347    /// A padding message, which is always ignored.
1348    pub struct Drop {}
1349}
1350empty_body! {
1351    /// Tells a circuit to close all downstream hops on the circuit.
1352    pub struct Truncate {}
1353}
1354empty_body! {
1355    /// Opens a new stream on a directory cache.
1356    pub struct BeginDir {}
1357}
1358
1359/// Helper: declare a RelayMsg implementation for a message type that has a
1360/// fixed command.
1361//
1362// TODO: It might be better to merge Body with RelayMsg, but that is complex,
1363// since their needs are _slightly_ different.
1364//
1365// TODO: If we *do* make the change above, then perhaps we should also implement
1366// our restricted enums in terms of this, so that there is only one instance of
1367// [<$body:snake:upper>]
1368macro_rules! msg_impl_relaymsg {
1369    ($($body:ident),* $(,)?) =>
1370    {paste::paste!{
1371       $(impl crate::relaycell::RelayMsg for $body {
1372            fn cmd(&self) -> crate::relaycell::RelayCmd { crate::relaycell::RelayCmd::[< $body:snake:upper >] }
1373            fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()> {
1374                crate::relaycell::msg::Body::encode_onto(self, w)
1375            }
1376            fn decode_from_reader(cmd: RelayCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
1377                if cmd != crate::relaycell::RelayCmd::[< $body:snake:upper >] {
1378                    return Err(tor_bytes::Error::InvalidMessage(
1379                        format!("Expected {} command; got {cmd}", stringify!([< $body:snake:upper >])).into()
1380                    ));
1381                }
1382                crate::relaycell::msg::Body::decode_from_reader(r)
1383            }
1384        }
1385
1386        impl TryFrom<AnyRelayMsg> for $body {
1387            type Error = crate::Error;
1388            fn try_from(msg: AnyRelayMsg) -> crate::Result<$body> {
1389                use crate::relaycell::RelayMsg;
1390                match msg {
1391                    AnyRelayMsg::$body(b) => Ok(b),
1392                    _ => Err(crate::Error::CircProto(format!("Expected {}; got {}" ,
1393                                                     stringify!([<$body:snake:upper>]),
1394                                                     msg.cmd())) ),
1395                }
1396            }
1397        }
1398        )*
1399    }}
1400}
1401
1402msg_impl_relaymsg!(
1403    Begin, Data, End, Connected, Sendme, Extend, Extended, Extend2, Extended2, Truncate, Truncated,
1404    Drop, Resolve, Resolved, BeginDir,
1405);
1406
1407#[cfg(feature = "experimental-udp")]
1408msg_impl_relaymsg!(ConnectUdp, ConnectedUdp, Datagram);
1409
1410#[cfg(feature = "hs")]
1411msg_impl_relaymsg!(
1412    EstablishIntro,
1413    EstablishRendezvous,
1414    Introduce1,
1415    Introduce2,
1416    Rendezvous1,
1417    Rendezvous2,
1418    IntroEstablished,
1419    RendezvousEstablished,
1420    IntroduceAck,
1421);
1422
1423#[cfg(feature = "conflux")]
1424msg_impl_relaymsg!(ConfluxSwitch, ConfluxLink, ConfluxLinked, ConfluxLinkedAck);
1425
1426#[cfg(test)]
1427mod test {
1428    // @@ begin test lint list maintained by maint/add_warning @@
1429    #![allow(clippy::bool_assert_comparison)]
1430    #![allow(clippy::clone_on_copy)]
1431    #![allow(clippy::dbg_macro)]
1432    #![allow(clippy::mixed_attributes_style)]
1433    #![allow(clippy::print_stderr)]
1434    #![allow(clippy::print_stdout)]
1435    #![allow(clippy::single_char_pattern)]
1436    #![allow(clippy::unwrap_used)]
1437    #![allow(clippy::unchecked_duration_subtraction)]
1438    #![allow(clippy::useless_vec)]
1439    #![allow(clippy::needless_pass_by_value)]
1440    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
1441
1442    use super::*;
1443
1444    #[test]
1445    fn sendme_tags() {
1446        // strings of 20 or 16 bytes.
1447        let ts: Vec<SendmeTag> = vec![
1448            (*b"Yea, on the word of ").into(),
1449            (*b"a Bloom, ye shal").into(),
1450            (*b"l ere long enter int").into(),
1451            (*b"o the golden cit").into(),
1452        ];
1453
1454        for (i1, i2) in (0..4).zip(0..4) {
1455            if i1 == i2 {
1456                assert_eq!(ts[i1], ts[i2]);
1457            } else {
1458                assert_ne!(ts[i1], ts[i2]);
1459            }
1460        }
1461
1462        assert_eq!(ts[0].as_ref(), &b"Yea, on the word of "[..]);
1463        assert_eq!(ts[3].as_ref(), &b"o the golden cit"[..]);
1464
1465        assert_eq!(ts[1], b"a Bloom, ye shal"[..].try_into().unwrap());
1466        assert_eq!(ts[2], b"l ere long enter int"[..].try_into().unwrap());
1467
1468        // 15 bytes long.
1469        assert!(matches!(
1470            SendmeTag::try_from(&b"o the golden ci"[..]),
1471            Err(InvalidSendmeTag { .. }),
1472        ));
1473    }
1474}