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).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#[derive(Debug, Clone, Eq, PartialEq, Deftly)]
1103#[derive_deftly(HasMemoryCost)]
1104#[non_exhaustive]
1105pub enum ResolvedVal {
1106 Ip(IpAddr),
1108 Hostname(Vec<u8>),
1110 TransientError,
1112 NontransientError,
1114 Unrecognized(u8, Vec<u8>),
1116}
1117
1118const RES_HOSTNAME: u8 = 0;
1120const RES_IPV4: u8 = 4;
1122const RES_IPV6: u8 = 6;
1124const RES_ERR_TRANSIENT: u8 = 0xF0;
1126const RES_ERR_NONTRANSIENT: u8 = 0xF1;
1128
1129impl Readable for ResolvedVal {
1130 fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1131 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); w.write(a)?;
1182 }
1183 Self::Ip(IpAddr::V6(a)) => {
1184 w.write_u8(RES_IPV6);
1185 w.write_u8(16); w.write(a)?;
1187 }
1188 Self::TransientError => {
1189 w.write_u8(RES_ERR_TRANSIENT);
1190 w.write_u8(0); }
1192 Self::NontransientError => {
1193 w.write_u8(RES_ERR_NONTRANSIENT);
1194 w.write_u8(0); }
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#[derive(Debug, Clone, Deftly)]
1215#[derive_deftly(HasMemoryCost)]
1216pub struct Resolved {
1217 answers: Vec<(ResolvedVal, u32)>,
1219}
1220impl Resolved {
1221 pub fn new_empty() -> Self {
1223 Resolved {
1224 answers: Vec::new(),
1225 }
1226 }
1227 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 pub fn add_answer(&mut self, answer: ResolvedVal, ttl: u32) {
1243 self.answers.push((answer, ttl));
1244 }
1245
1246 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#[derive(Debug, Clone, Deftly)]
1280#[derive_deftly(HasMemoryCost)]
1281pub struct Unrecognized {
1282 cmd: RelayCmd,
1284 body: Vec<u8>,
1286}
1287
1288impl Unrecognized {
1289 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 pub fn cmd(&self) -> RelayCmd {
1300 self.cmd
1301 }
1302 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
1323macro_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 pub struct Drop {}
1349}
1350empty_body! {
1351 pub struct Truncate {}
1353}
1354empty_body! {
1355 pub struct BeginDir {}
1357}
1358
1359macro_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 #![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 use super::*;
1443
1444 #[test]
1445 fn sendme_tags() {
1446 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 assert!(matches!(
1470 SendmeTag::try_from(&b"o the golden ci"[..]),
1471 Err(InvalidSendmeTag { .. }),
1472 ));
1473 }
1474}