1use 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#[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 Begin,
48 Data,
50 End,
52 Connected,
54 Sendme,
56 Extend,
58 Extended,
60 Extend2,
62 Extended2,
64 Truncate,
66 Truncated,
68 Drop,
70 Resolve,
72 Resolved,
74 BeginDir,
76 [feature = "experimental-udp"]
78 ConnectUdp,
79 [feature = "experimental-udp"]
81 ConnectedUdp,
82 [feature = "experimental-udp"]
84 Datagram,
85 [feature = "conflux"]
87 ConfluxLink,
88 [feature = "conflux"]
90 ConfluxLinked,
91 [feature = "conflux"]
93 ConfluxLinkedAck,
94 [feature = "conflux"]
96 ConfluxSwitch,
97 [feature = "hs"]
99 EstablishIntro,
100 [feature = "hs"]
102 EstablishRendezvous,
103 [feature = "hs"]
105 Introduce1,
106 [feature = "hs"]
108 Introduce2,
109 [feature = "hs"]
111 Rendezvous1,
112 [feature = "hs"]
114 Rendezvous2,
115 [feature = "hs"]
117 IntroEstablished,
118 [feature = "hs"]
120 RendezvousEstablished,
121 [feature = "hs"]
123 IntroduceAck,
124
125 _ =>
126 Unrecognized,
128 }
129}
130
131pub trait Body: Sized {
133 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self>;
135 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()>;
137}
138
139bitflags! {
140 #[derive(Clone, Copy, Debug)]
145 pub struct BeginFlags : u32 {
146 const IPV6_OKAY = (1<<0);
148 const IPV4_NOT_OKAY = (1<<1);
150 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#[derive(Clone, Default, Copy, Debug, Eq, PartialEq)]
164#[non_exhaustive]
165pub enum IpVersionPreference {
166 Ipv4Only,
168 #[default]
170 Ipv4Preferred,
171 Ipv6Preferred,
173 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#[derive(Debug, Clone, Deftly)]
199#[derive_deftly(HasMemoryCost)]
200pub struct Begin {
201 addr: Vec<u8>,
203 port: u16,
205 flags: BeginFlags,
207}
208
209impl Begin {
210 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 pub fn addr(&self) -> &[u8] {
229 &self.addr[..]
230 }
231
232 pub fn port(&self) -> u16 {
234 self.port
235 }
236
237 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 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 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#[derive(Debug, Clone, Deftly)]
308#[derive_deftly(HasMemoryCost)]
309pub struct Data {
310 body: Vec<u8>,
319}
320impl Data {
321 pub const MAXLEN_V0: usize = CELL_DATA_LEN - 11;
325
326 pub const MAXLEN_V1: usize = CELL_DATA_LEN - 21;
330
331 pub const MAXLEN: usize = Data::MAXLEN_V0;
337
338 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 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 fn new_unchecked(body: Vec<u8>) -> Self {
373 debug_assert!((1..=Data::MAXLEN).contains(&body.len()));
374 Data { body }
375 }
376
377 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#[derive(Debug, Clone, Deftly)]
418#[derive_deftly(HasMemoryCost)]
419pub struct End {
420 reason: EndReason,
422 addr: Option<(IpAddr, u32)>,
425}
426
427caret_int! {
428 #[derive(Deftly)]
430 #[derive_deftly(HasMemoryCost)]
431 pub struct EndReason(u8) {
432 MISC = 1,
436 RESOLVEFAILED = 2,
438 CONNECTREFUSED = 3,
440 EXITPOLICY = 4,
442 DESTROY = 5,
444 DONE = 6,
446 TIMEOUT = 7,
448 NOROUTE = 8,
450 HIBERNATING = 9,
452 INTERNAL = 10,
454 RESOURCELIMIT = 11,
456 CONNRESET = 12,
458 TORPROTOCOL = 13,
460 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 pub fn new_misc() -> Self {
491 End {
492 reason: EndReason::MISC,
493 addr: None,
494 }
495 }
496 pub fn new_with_reason(reason: EndReason) -> Self {
498 End { reason, addr: None }
499 }
500 pub fn new_exitpolicy(addr: IpAddr, ttl: u32) -> Self {
503 End {
504 reason: EndReason::EXITPOLICY,
505 addr: Some((addr, ttl)),
506 }
507 }
508 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 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#[derive(Debug, Clone, Deftly)]
585#[derive_deftly(HasMemoryCost)]
586pub struct Connected {
587 addr: Option<(IpAddr, u32)>,
589}
590impl Connected {
591 pub fn new_empty() -> Self {
593 Connected { addr: None }
594 }
595 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#[derive(Debug, Clone, Copy, Eq, PartialEq, Deftly)]
645#[derive_deftly(HasMemoryCost)]
646pub struct SendmeTag {
647 len: NonZeroU8,
652 tag: CtByteArray<20>,
658}
659impl From<[u8; 20]> for SendmeTag {
660 #[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 #[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#[derive(Clone, Debug, thiserror::Error)]
688#[non_exhaustive]
689#[error("Invalid size {} on SENDME tag", len)]
690pub struct InvalidSendmeTag {
691 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 #[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#[derive(Debug, Clone, Deftly)]
737#[derive_deftly(HasMemoryCost)]
738pub struct Sendme {
739 tag: Option<SendmeTag>,
741}
742impl Sendme {
743 pub fn new_empty() -> Self {
748 Sendme { tag: None }
749 }
750 pub fn new_tag(x: [u8; 20]) -> Self {
752 Sendme {
753 tag: Some(x.into()),
754 }
755 }
756 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#[derive(Debug, Clone, Deftly)]
808#[derive_deftly(HasMemoryCost)]
809pub struct Extend {
810 addr: Ipv4Addr,
812 port: u16,
814 handshake: Vec<u8>,
816 rsaid: RsaIdentity,
818}
819impl Extend {
820 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#[derive(Debug, Clone, Deftly)]
858#[derive_deftly(HasMemoryCost)]
859pub struct Extended {
860 handshake: Vec<u8>,
862}
863impl Extended {
864 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#[derive(Debug, Clone, Deftly)]
895#[derive_deftly(HasMemoryCost)]
896pub struct Extend2 {
897 linkspec: Vec<EncodedLinkSpec>,
903 handshake_type: HandshakeType,
905 handshake: Vec<u8>,
907}
908impl Extend2 {
909 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 pub fn handshake_type(&self) -> HandshakeType {
924 self.handshake_type
925 }
926
927 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#[derive(Debug, Clone, Deftly)]
974#[derive_deftly(HasMemoryCost)]
975pub struct Extended2 {
976 handshake: Vec<u8>,
979}
980impl Extended2 {
981 pub fn new(handshake: Vec<u8>) -> Self {
983 Extended2 { handshake }
984 }
985 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#[derive(Debug, Clone, Deftly)]
1018#[derive_deftly(HasMemoryCost)]
1019pub struct Truncated {
1020 reason: DestroyReason,
1022}
1023impl Truncated {
1024 pub fn new(reason: DestroyReason) -> Self {
1026 Truncated { reason }
1027 }
1028 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#[derive(Debug, Clone, Deftly)]
1052#[derive_deftly(HasMemoryCost)]
1053pub struct Resolve {
1054 query: Vec<u8>,
1056}
1057impl Resolve {
1058 pub fn new(s: &str) -> Self {
1060 Resolve {
1061 query: s.as_bytes().into(),
1062 }
1063 }
1064 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)
1077 .expect("write to string failed");
1078 }
1079 write!(s, "ip6.arpa").expect("write to string failed");
1080 s
1081 }
1082 };
1083 Resolve {
1084 query: query.into_bytes(),
1085 }
1086 }
1087}
1088impl Body for Resolve {
1089 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
1090 let query = r.take_until(0)?;
1091 Ok(Resolve {
1092 query: query.into(),
1093 })
1094 }
1095 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1096 w.write_all(&self.query[..]);
1097 w.write_u8(0);
1098 Ok(())
1099 }
1100}
1101
1102#[derive(Debug, Clone, Eq, PartialEq, Deftly)]
1104#[derive_deftly(HasMemoryCost)]
1105#[non_exhaustive]
1106pub enum ResolvedVal {
1107 Ip(IpAddr),
1109 Hostname(Vec<u8>),
1111 TransientError,
1113 NontransientError,
1115 Unrecognized(u8, Vec<u8>),
1117}
1118
1119const RES_HOSTNAME: u8 = 0;
1121const RES_IPV4: u8 = 4;
1123const RES_IPV6: u8 = 6;
1125const RES_ERR_TRANSIENT: u8 = 0xF0;
1127const RES_ERR_NONTRANSIENT: u8 = 0xF1;
1129
1130impl Readable for ResolvedVal {
1131 fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1132 fn res_len(tp: u8) -> Option<usize> {
1135 match tp {
1136 RES_IPV4 => Some(4),
1137 RES_IPV6 => Some(16),
1138 _ => None,
1139 }
1140 }
1141 let tp = r.take_u8()?;
1142 let len = r.take_u8()? as usize;
1143 if let Some(expected_len) = res_len(tp) {
1144 if len != expected_len {
1145 return Err(Error::InvalidMessage(
1146 "Wrong length for RESOLVED answer".into(),
1147 ));
1148 }
1149 }
1150 Ok(match tp {
1151 RES_HOSTNAME => Self::Hostname(r.take(len)?.into()),
1152 RES_IPV4 => Self::Ip(IpAddr::V4(r.extract()?)),
1153 RES_IPV6 => Self::Ip(IpAddr::V6(r.extract()?)),
1154 RES_ERR_TRANSIENT => {
1155 r.advance(len)?;
1156 Self::TransientError
1157 }
1158 RES_ERR_NONTRANSIENT => {
1159 r.advance(len)?;
1160 Self::NontransientError
1161 }
1162 _ => Self::Unrecognized(tp, r.take(len)?.into()),
1163 })
1164 }
1165}
1166
1167impl Writeable for ResolvedVal {
1168 fn write_onto<B: Writer + ?Sized>(&self, w: &mut B) -> EncodeResult<()> {
1169 match self {
1170 Self::Hostname(h) => {
1171 w.write_u8(RES_HOSTNAME);
1172 let h_len: u8 = h
1173 .len()
1174 .try_into()
1175 .map_err(|_| EncodeError::BadLengthValue)?;
1176 w.write_u8(h_len);
1177 w.write_all(&h[..]);
1178 }
1179 Self::Ip(IpAddr::V4(a)) => {
1180 w.write_u8(RES_IPV4);
1181 w.write_u8(4); w.write(a)?;
1183 }
1184 Self::Ip(IpAddr::V6(a)) => {
1185 w.write_u8(RES_IPV6);
1186 w.write_u8(16); w.write(a)?;
1188 }
1189 Self::TransientError => {
1190 w.write_u8(RES_ERR_TRANSIENT);
1191 w.write_u8(0); }
1193 Self::NontransientError => {
1194 w.write_u8(RES_ERR_NONTRANSIENT);
1195 w.write_u8(0); }
1197 Self::Unrecognized(tp, v) => {
1198 w.write_u8(*tp);
1199 let v_len: u8 = v
1200 .len()
1201 .try_into()
1202 .map_err(|_| EncodeError::BadLengthValue)?;
1203 w.write_u8(v_len);
1204 w.write_all(&v[..]);
1205 }
1206 }
1207 Ok(())
1208 }
1209}
1210
1211#[derive(Debug, Clone, Deftly)]
1216#[derive_deftly(HasMemoryCost)]
1217pub struct Resolved {
1218 answers: Vec<(ResolvedVal, u32)>,
1220}
1221impl Resolved {
1222 pub fn new_empty() -> Self {
1224 Resolved {
1225 answers: Vec::new(),
1226 }
1227 }
1228 pub fn new_err(transient: bool, ttl: u32) -> Self {
1233 let mut res = Self::new_empty();
1234 let err = if transient {
1235 ResolvedVal::TransientError
1236 } else {
1237 ResolvedVal::NontransientError
1238 };
1239 res.add_answer(err, ttl);
1240 res
1241 }
1242 pub fn add_answer(&mut self, answer: ResolvedVal, ttl: u32) {
1244 self.answers.push((answer, ttl));
1245 }
1246
1247 pub fn into_answers(self) -> Vec<(ResolvedVal, u32)> {
1255 self.answers
1256 }
1257}
1258impl Body for Resolved {
1259 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
1260 let mut answers = Vec::new();
1261 while r.remaining() > 0 {
1262 let rv = r.extract()?;
1263 let ttl = r.take_u32()?;
1264 answers.push((rv, ttl));
1265 }
1266 Ok(Resolved { answers })
1267 }
1268 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1269 for (rv, ttl) in &self.answers {
1270 w.write(rv)?;
1271 w.write_u32(*ttl);
1272 }
1273 Ok(())
1274 }
1275}
1276
1277#[derive(Debug, Clone, Deftly)]
1281#[derive_deftly(HasMemoryCost)]
1282pub struct Unrecognized {
1283 cmd: RelayCmd,
1285 body: Vec<u8>,
1287}
1288
1289impl Unrecognized {
1290 pub fn new<B>(cmd: RelayCmd, body: B) -> Self
1292 where
1293 B: Into<Vec<u8>>,
1294 {
1295 let body = body.into();
1296 Unrecognized { cmd, body }
1297 }
1298
1299 pub fn cmd(&self) -> RelayCmd {
1301 self.cmd
1302 }
1303 pub fn decode_with_cmd(cmd: RelayCmd, r: &mut Reader<'_>) -> Result<Self> {
1305 let mut r = Unrecognized::decode_from_reader(r)?;
1306 r.cmd = cmd;
1307 Ok(r)
1308 }
1309}
1310
1311impl Body for Unrecognized {
1312 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
1313 Ok(Unrecognized {
1314 cmd: 0.into(),
1315 body: r.take(r.remaining())?.into(),
1316 })
1317 }
1318 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1319 w.write_all(&self.body[..]);
1320 Ok(())
1321 }
1322}
1323
1324macro_rules! empty_body {
1326 {
1327 $(#[$meta:meta])*
1328 pub struct $name:ident {}
1329 } => {
1330 $(#[$meta])*
1331 #[derive(Clone,Debug,Default,derive_deftly::Deftly)]
1332 #[derive_deftly(tor_memquota::HasMemoryCost)]
1333 #[non_exhaustive]
1334 pub struct $name {}
1335 impl $crate::relaycell::msg::Body for $name {
1336 fn decode_from_reader(_r: &mut Reader<'_>) -> Result<Self> {
1337 Ok(Self::default())
1338 }
1339 fn encode_onto<W: Writer + ?Sized>(self, _w: &mut W) -> EncodeResult<()> {
1340 Ok(())
1341 }
1342 }
1343 }
1344}
1345pub(crate) use empty_body;
1346
1347empty_body! {
1348 pub struct Drop {}
1350}
1351empty_body! {
1352 pub struct Truncate {}
1354}
1355empty_body! {
1356 pub struct BeginDir {}
1358}
1359
1360macro_rules! msg_impl_relaymsg {
1370 ($($body:ident),* $(,)?) =>
1371 {paste::paste!{
1372 $(impl crate::relaycell::RelayMsg for $body {
1373 fn cmd(&self) -> crate::relaycell::RelayCmd { crate::relaycell::RelayCmd::[< $body:snake:upper >] }
1374 fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()> {
1375 crate::relaycell::msg::Body::encode_onto(self, w)
1376 }
1377 fn decode_from_reader(cmd: RelayCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
1378 if cmd != crate::relaycell::RelayCmd::[< $body:snake:upper >] {
1379 return Err(tor_bytes::Error::InvalidMessage(
1380 format!("Expected {} command; got {cmd}", stringify!([< $body:snake:upper >])).into()
1381 ));
1382 }
1383 crate::relaycell::msg::Body::decode_from_reader(r)
1384 }
1385 }
1386
1387 impl TryFrom<AnyRelayMsg> for $body {
1388 type Error = crate::Error;
1389 fn try_from(msg: AnyRelayMsg) -> crate::Result<$body> {
1390 use crate::relaycell::RelayMsg;
1391 match msg {
1392 AnyRelayMsg::$body(b) => Ok(b),
1393 _ => Err(crate::Error::CircProto(format!("Expected {}; got {}" ,
1394 stringify!([<$body:snake:upper>]),
1395 msg.cmd())) ),
1396 }
1397 }
1398 }
1399 )*
1400 }}
1401}
1402
1403msg_impl_relaymsg!(
1404 Begin, Data, End, Connected, Sendme, Extend, Extended, Extend2, Extended2, Truncate, Truncated,
1405 Drop, Resolve, Resolved, BeginDir,
1406);
1407
1408#[cfg(feature = "experimental-udp")]
1409msg_impl_relaymsg!(ConnectUdp, ConnectedUdp, Datagram);
1410
1411#[cfg(feature = "hs")]
1412msg_impl_relaymsg!(
1413 EstablishIntro,
1414 EstablishRendezvous,
1415 Introduce1,
1416 Introduce2,
1417 Rendezvous1,
1418 Rendezvous2,
1419 IntroEstablished,
1420 RendezvousEstablished,
1421 IntroduceAck,
1422);
1423
1424#[cfg(feature = "conflux")]
1425msg_impl_relaymsg!(ConfluxSwitch, ConfluxLink, ConfluxLinked, ConfluxLinkedAck);
1426
1427#[cfg(test)]
1428mod test {
1429 #![allow(clippy::bool_assert_comparison)]
1431 #![allow(clippy::clone_on_copy)]
1432 #![allow(clippy::dbg_macro)]
1433 #![allow(clippy::mixed_attributes_style)]
1434 #![allow(clippy::print_stderr)]
1435 #![allow(clippy::print_stdout)]
1436 #![allow(clippy::single_char_pattern)]
1437 #![allow(clippy::unwrap_used)]
1438 #![allow(clippy::unchecked_duration_subtraction)]
1439 #![allow(clippy::useless_vec)]
1440 #![allow(clippy::needless_pass_by_value)]
1441 use super::*;
1444
1445 #[test]
1446 fn sendme_tags() {
1447 let ts: Vec<SendmeTag> = vec![
1449 (*b"Yea, on the word of ").into(),
1450 (*b"a Bloom, ye shal").into(),
1451 (*b"l ere long enter int").into(),
1452 (*b"o the golden cit").into(),
1453 ];
1454
1455 for (i1, i2) in (0..4).zip(0..4) {
1456 if i1 == i2 {
1457 assert_eq!(ts[i1], ts[i2]);
1458 } else {
1459 assert_ne!(ts[i1], ts[i2]);
1460 }
1461 }
1462
1463 assert_eq!(ts[0].as_ref(), &b"Yea, on the word of "[..]);
1464 assert_eq!(ts[3].as_ref(), &b"o the golden cit"[..]);
1465
1466 assert_eq!(ts[1], b"a Bloom, ye shal"[..].try_into().unwrap());
1467 assert_eq!(ts[2], b"l ere long enter int"[..].try_into().unwrap());
1468
1469 assert!(matches!(
1471 SendmeTag::try_from(&b"o the golden ci"[..]),
1472 Err(InvalidSendmeTag { .. }),
1473 ));
1474 }
1475}