1use super::flow_ctrl::{Xoff, Xon};
7use super::{RelayCellFormat, RelayCmd};
8use crate::chancell::msg::{
9 DestroyReason, HandshakeType, TAP_C_HANDSHAKE_LEN, TAP_S_HANDSHAKE_LEN,
10};
11use crate::chancell::CELL_DATA_LEN;
12use caret::caret_int;
13use derive_deftly::Deftly;
14use std::fmt::Write;
15use std::net::{IpAddr, Ipv4Addr};
16use std::num::NonZeroU8;
17use tor_bytes::{EncodeError, EncodeResult, Error, Result};
18use tor_bytes::{Readable, Reader, Writeable, Writer};
19use tor_linkspec::EncodedLinkSpec;
20use tor_llcrypto::pk::rsa::RsaIdentity;
21use tor_llcrypto::util::ct::CtByteArray;
22use tor_memquota::{derive_deftly_template_HasMemoryCost, memory_cost_structural_copy};
23
24use bitflags::bitflags;
25
26#[cfg(feature = "conflux")]
27#[cfg_attr(docsrs, doc(cfg(feature = "conflux")))]
28pub use super::conflux::{ConfluxLink, ConfluxLinked, ConfluxLinkedAck, ConfluxSwitch};
29
30#[cfg(feature = "hs")]
31#[cfg_attr(docsrs, doc(cfg(feature = "hs")))]
32pub use super::hs::{
33 est_intro::EstablishIntro, EstablishRendezvous, IntroEstablished, Introduce1, Introduce2,
34 IntroduceAck, Rendezvous1, Rendezvous2, RendezvousEstablished,
35};
36#[cfg(feature = "experimental-udp")]
37#[cfg_attr(docsrs, doc(cfg(feature = "experimental-udp")))]
38pub use super::udp::{ConnectUdp, ConnectedUdp, Datagram};
39
40crate::restrict::restricted_msg! {
41#[derive(Debug, Clone, Deftly)]
43#[derive_deftly(HasMemoryCost)]
44#[non_exhaustive]
45@omit_from "avoid_conflict_with_a_blanket_implementation"
46pub enum AnyRelayMsg : RelayMsg {
47 Begin,
49 Data,
51 End,
53 Connected,
55 Sendme,
57 Extend,
59 Extended,
61 Extend2,
63 Extended2,
65 Truncate,
67 Truncated,
69 Drop,
71 Resolve,
73 Resolved,
75 BeginDir,
77 [feature = "experimental-udp"]
79 ConnectUdp,
80 [feature = "experimental-udp"]
82 ConnectedUdp,
83 [feature = "experimental-udp"]
85 Datagram,
86 [feature = "conflux"]
88 ConfluxLink,
89 [feature = "conflux"]
91 ConfluxLinked,
92 [feature = "conflux"]
94 ConfluxLinkedAck,
95 [feature = "conflux"]
97 ConfluxSwitch,
98 Xon,
100 Xoff,
102 [feature = "hs"]
104 EstablishIntro,
105 [feature = "hs"]
107 EstablishRendezvous,
108 [feature = "hs"]
110 Introduce1,
111 [feature = "hs"]
113 Introduce2,
114 [feature = "hs"]
116 Rendezvous1,
117 [feature = "hs"]
119 Rendezvous2,
120 [feature = "hs"]
122 IntroEstablished,
123 [feature = "hs"]
125 RendezvousEstablished,
126 [feature = "hs"]
128 IntroduceAck,
129
130 _ =>
131 Unrecognized,
133 }
134}
135
136pub trait Body: Sized {
138 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self>;
140 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()>;
142}
143
144bitflags! {
145 #[derive(Clone, Copy, Debug)]
150 pub struct BeginFlags : u32 {
151 const IPV6_OKAY = (1<<0);
153 const IPV4_NOT_OKAY = (1<<1);
155 const IPV6_PREFERRED = (1<<2);
157 }
158}
159memory_cost_structural_copy!(BeginFlags);
160impl From<u32> for BeginFlags {
161 fn from(v: u32) -> Self {
162 BeginFlags::from_bits_truncate(v)
163 }
164}
165
166#[derive(Clone, Default, Copy, Debug, Eq, PartialEq)]
169#[non_exhaustive]
170pub enum IpVersionPreference {
171 Ipv4Only,
173 #[default]
175 Ipv4Preferred,
176 Ipv6Preferred,
178 Ipv6Only,
180}
181impl From<IpVersionPreference> for BeginFlags {
182 fn from(v: IpVersionPreference) -> Self {
183 use IpVersionPreference::*;
184 match v {
185 Ipv4Only => 0.into(),
186 Ipv4Preferred => BeginFlags::IPV6_OKAY,
187 Ipv6Preferred => BeginFlags::IPV6_OKAY | BeginFlags::IPV6_PREFERRED,
188 Ipv6Only => BeginFlags::IPV4_NOT_OKAY,
189 }
190 }
191}
192
193#[derive(Debug, Clone, Deftly)]
204#[derive_deftly(HasMemoryCost)]
205pub struct Begin {
206 addr: Vec<u8>,
208 port: u16,
210 flags: BeginFlags,
212}
213
214impl Begin {
215 pub fn new<F>(addr: &str, port: u16, flags: F) -> crate::Result<Self>
217 where
218 F: Into<BeginFlags>,
219 {
220 if !addr.is_ascii() {
221 return Err(crate::Error::BadStreamAddress);
222 }
223 let mut addr = addr.to_string();
224 addr.make_ascii_lowercase();
225 Ok(Begin {
226 addr: addr.into_bytes(),
227 port,
228 flags: flags.into(),
229 })
230 }
231
232 pub fn addr(&self) -> &[u8] {
234 &self.addr[..]
235 }
236
237 pub fn port(&self) -> u16 {
239 self.port
240 }
241
242 pub fn flags(&self) -> BeginFlags {
244 self.flags
245 }
246}
247
248impl Body for Begin {
249 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
250 let addr = {
251 if r.peek(1)? == b"[" {
252 r.advance(1)?;
254 let a = r.take_until(b']')?;
255 let colon = r.take_u8()?;
256 if colon != b':' {
257 return Err(Error::InvalidMessage("missing port in begin cell".into()));
258 }
259 a
260 } else {
261 r.take_until(b':')?
263 }
264 };
265 let port = r.take_until(0)?;
266 let flags = if r.remaining() >= 4 { r.take_u32()? } else { 0 };
267
268 if !addr.is_ascii() {
269 return Err(Error::InvalidMessage(
270 "target address in begin cell not ascii".into(),
271 ));
272 }
273
274 let port = std::str::from_utf8(port)
275 .map_err(|_| Error::InvalidMessage("port in begin cell not utf8".into()))?;
276
277 let port = port
278 .parse()
279 .map_err(|_| Error::InvalidMessage("port in begin cell not a valid port".into()))?;
280
281 Ok(Begin {
282 addr: addr.into(),
283 port,
284 flags: flags.into(),
285 })
286 }
287 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
288 if self.addr.contains(&b':') {
289 w.write_u8(b'[');
290 w.write_all(&self.addr[..]);
291 w.write_u8(b']');
292 } else {
293 w.write_all(&self.addr[..]);
294 }
295 w.write_u8(b':');
296 w.write_all(self.port.to_string().as_bytes());
297 w.write_u8(0);
298 if self.flags.bits() != 0 {
299 w.write_u32(self.flags.bits());
300 }
301 Ok(())
302 }
303}
304
305#[derive(Debug, Clone, Deftly)]
313#[derive_deftly(HasMemoryCost)]
314pub struct Data {
315 body: Vec<u8>,
324}
325impl Data {
326 pub const MAXLEN_V0: usize = CELL_DATA_LEN - 11;
330
331 pub const MAXLEN_V1: usize = CELL_DATA_LEN - 21;
335
336 pub const MAXLEN: usize = Data::MAXLEN_V0;
342
343 pub fn new(inp: &[u8]) -> crate::Result<Self> {
347 if inp.len() > Data::MAXLEN {
348 return Err(crate::Error::CantEncode("Data message too long"));
349 }
350 if inp.is_empty() {
351 return Err(crate::Error::CantEncode("Empty data message"));
352 }
353 Ok(Self::new_unchecked(inp.into()))
354 }
355
356 pub fn try_split_from(version: RelayCellFormat, inp: &[u8]) -> Option<(Self, &[u8])> {
364 if inp.is_empty() {
365 return None;
366 }
367 let upper_bound = Self::max_body_len(version);
368 let len = std::cmp::min(inp.len(), upper_bound);
369 let (data, remainder) = inp.split_at(len);
370 Some((Self::new_unchecked(data.into()), remainder))
371 }
372
373 fn new_unchecked(body: Vec<u8>) -> Self {
378 debug_assert!((1..=Data::MAXLEN).contains(&body.len()));
379 Data { body }
380 }
381
382 pub fn max_body_len(format: RelayCellFormat) -> usize {
385 match format {
386 RelayCellFormat::V0 => Self::MAXLEN_V0,
387 RelayCellFormat::V1 => Self::MAXLEN_V1,
388 }
389 }
390}
391impl From<Data> for Vec<u8> {
392 fn from(data: Data) -> Vec<u8> {
393 data.body
394 }
395}
396impl AsRef<[u8]> for Data {
397 fn as_ref(&self) -> &[u8] {
398 &self.body[..]
399 }
400}
401
402impl Body for Data {
403 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
404 if r.remaining() == 0 {
405 return Err(Error::InvalidMessage("Empty DATA message".into()));
406 }
407 Ok(Data {
408 body: r.take(r.remaining())?.into(),
409 })
410 }
411 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
412 w.write_all(&self.body);
413 Ok(())
414 }
415}
416
417#[derive(Debug, Clone, Deftly)]
423#[derive_deftly(HasMemoryCost)]
424pub struct End {
425 reason: EndReason,
427 addr: Option<(IpAddr, u32)>,
430}
431
432caret_int! {
433 #[derive(Deftly)]
435 #[derive_deftly(HasMemoryCost)]
436 pub struct EndReason(u8) {
437 MISC = 1,
441 RESOLVEFAILED = 2,
443 CONNECTREFUSED = 3,
445 EXITPOLICY = 4,
447 DESTROY = 5,
449 DONE = 6,
451 TIMEOUT = 7,
453 NOROUTE = 8,
455 HIBERNATING = 9,
457 INTERNAL = 10,
459 RESOURCELIMIT = 11,
461 CONNRESET = 12,
463 TORPROTOCOL = 13,
465 NOTDIRECTORY = 14,
467 }
468}
469
470impl tor_error::HasKind for EndReason {
471 fn kind(&self) -> tor_error::ErrorKind {
472 use tor_error::ErrorKind as EK;
473 use EndReason as E;
474 match *self {
475 E::MISC => EK::RemoteStreamError,
476 E::RESOLVEFAILED => EK::RemoteHostResolutionFailed,
477 E::CONNECTREFUSED => EK::RemoteConnectionRefused,
478 E::EXITPOLICY => EK::ExitPolicyRejected,
479 E::DESTROY => EK::CircuitCollapse,
480 E::DONE => EK::RemoteStreamClosed,
481 E::TIMEOUT => EK::ExitTimeout,
482 E::NOROUTE => EK::RemoteNetworkFailed,
483 E::RESOURCELIMIT | E::HIBERNATING => EK::RelayTooBusy,
484 E::INTERNAL | E::TORPROTOCOL | E::NOTDIRECTORY => EK::TorProtocolViolation,
485 E::CONNRESET => EK::RemoteStreamReset,
486 _ => EK::RemoteStreamError,
487 }
488 }
489}
490
491impl End {
492 pub fn new_misc() -> Self {
496 End {
497 reason: EndReason::MISC,
498 addr: None,
499 }
500 }
501 pub fn new_with_reason(reason: EndReason) -> Self {
503 End { reason, addr: None }
504 }
505 pub fn new_exitpolicy(addr: IpAddr, ttl: u32) -> Self {
508 End {
509 reason: EndReason::EXITPOLICY,
510 addr: Some((addr, ttl)),
511 }
512 }
513 pub fn reason(&self) -> EndReason {
515 self.reason
516 }
517}
518impl Body for End {
519 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
520 if r.remaining() == 0 {
521 return Ok(End {
522 reason: EndReason::MISC,
523 addr: None,
524 });
525 }
526 let reason = r.take_u8()?.into();
527 if reason == EndReason::EXITPOLICY {
528 let addr = match r.remaining() {
529 4 | 8 => IpAddr::V4(r.extract()?),
530 16 | 20 => IpAddr::V6(r.extract()?),
531 _ => {
532 return Ok(End { reason, addr: None });
534 }
535 };
536 let ttl = if r.remaining() == 4 {
537 r.take_u32()?
538 } else {
539 u32::MAX
540 };
541 Ok(End {
542 reason,
543 addr: Some((addr, ttl)),
544 })
545 } else {
546 Ok(End { reason, addr: None })
547 }
548 }
549 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
550 w.write_u8(self.reason.into());
551 if let (EndReason::EXITPOLICY, Some((addr, ttl))) = (self.reason, self.addr) {
552 match addr {
553 IpAddr::V4(v4) => w.write(&v4)?,
554 IpAddr::V6(v6) => w.write(&v6)?,
555 }
556 w.write_u32(ttl);
557 }
558 Ok(())
559 }
560}
561
562impl From<EndReason> for std::io::ErrorKind {
563 fn from(e: EndReason) -> Self {
564 use std::io::ErrorKind::*;
565 match e {
566 EndReason::RESOLVEFAILED => NotFound,
567 EndReason::CONNECTREFUSED => ConnectionRefused,
568 EndReason::EXITPOLICY => ConnectionRefused,
569 EndReason::DESTROY => ConnectionAborted,
570 EndReason::DONE => UnexpectedEof,
571 EndReason::TIMEOUT => TimedOut,
572 EndReason::HIBERNATING => ConnectionRefused,
573 EndReason::RESOURCELIMIT => ConnectionRefused,
574 EndReason::CONNRESET => ConnectionReset,
575 EndReason::TORPROTOCOL => InvalidData,
576 EndReason::NOTDIRECTORY => ConnectionRefused,
577 EndReason::INTERNAL | EndReason::NOROUTE | EndReason::MISC => Other,
578 _ => Other,
579 }
580 }
581}
582
583#[derive(Debug, Clone, Deftly)]
590#[derive_deftly(HasMemoryCost)]
591pub struct Connected {
592 addr: Option<(IpAddr, u32)>,
594}
595impl Connected {
596 pub fn new_empty() -> Self {
598 Connected { addr: None }
599 }
600 pub fn new_with_addr(addr: IpAddr, ttl: u32) -> Self {
602 Connected {
603 addr: Some((addr, ttl)),
604 }
605 }
606}
607impl Body for Connected {
608 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
609 if r.remaining() == 0 {
610 return Ok(Connected { addr: None });
611 }
612 let ipv4 = r.take_u32()?;
613 let addr = if ipv4 == 0 {
614 if r.take_u8()? != 6 {
615 return Err(Error::InvalidMessage(
616 "Invalid address type in CONNECTED cell".into(),
617 ));
618 }
619 IpAddr::V6(r.extract()?)
620 } else {
621 IpAddr::V4(ipv4.into())
622 };
623 let ttl = r.take_u32()?;
624
625 Ok(Connected {
626 addr: Some((addr, ttl)),
627 })
628 }
629 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
630 if let Some((addr, ttl)) = self.addr {
631 match addr {
632 IpAddr::V4(v4) => w.write(&v4)?,
633 IpAddr::V6(v6) => {
634 w.write_u32(0);
635 w.write_u8(6);
636 w.write(&v6)?;
637 }
638 }
639 w.write_u32(ttl);
640 }
641 Ok(())
642 }
643}
644
645#[derive(Debug, Clone, Copy, Eq, PartialEq, Deftly)]
650#[derive_deftly(HasMemoryCost)]
651pub struct SendmeTag {
652 len: NonZeroU8,
657 tag: CtByteArray<20>,
663}
664impl From<[u8; 20]> for SendmeTag {
665 #[inline]
667 fn from(value: [u8; 20]) -> Self {
668 Self {
669 len: NonZeroU8::new(20).expect("20 was not nonzero?"),
670 tag: CtByteArray::from(value),
671 }
672 }
673}
674impl From<[u8; 16]> for SendmeTag {
675 #[inline]
677 fn from(value: [u8; 16]) -> Self {
678 let mut tag = CtByteArray::from([0; 20]);
679 tag.as_mut()[0..16].copy_from_slice(&value[..]);
680 Self {
681 len: NonZeroU8::new(16).expect("16 was not nonzero?"),
682 tag,
683 }
684 }
685}
686impl AsRef<[u8]> for SendmeTag {
687 fn as_ref(&self) -> &[u8] {
688 &self.tag.as_ref()[0..usize::from(u8::from(self.len))]
689 }
690}
691#[derive(Clone, Debug, thiserror::Error)]
693#[non_exhaustive]
694#[error("Invalid size {} on SENDME tag", len)]
695pub struct InvalidSendmeTag {
696 len: usize,
698}
699impl From<InvalidSendmeTag> for tor_bytes::Error {
700 fn from(_: InvalidSendmeTag) -> Self {
701 tor_bytes::Error::BadLengthValue
702 }
703}
704
705impl<'a> TryFrom<&'a [u8]> for SendmeTag {
706 type Error = InvalidSendmeTag;
707
708 #[inline]
710 fn try_from(value: &'a [u8]) -> std::result::Result<Self, Self::Error> {
711 match value.len() {
712 16 => {
713 let a: [u8; 16] = value.try_into().expect("16 was not 16?");
714 Ok(Self::from(a))
715 }
716 20 => {
717 let a: [u8; 20] = value.try_into().expect("20 was not 20?");
718 Ok(Self::from(a))
719 }
720 _ => Err(InvalidSendmeTag { len: value.len() }),
721 }
722 }
723}
724
725#[derive(Debug, Clone, Deftly)]
742#[derive_deftly(HasMemoryCost)]
743pub struct Sendme {
744 tag: Option<SendmeTag>,
746}
747impl Sendme {
748 pub fn new_empty() -> Self {
753 Sendme { tag: None }
754 }
755 pub fn new_tag(x: [u8; 20]) -> Self {
757 Sendme {
758 tag: Some(x.into()),
759 }
760 }
761 pub fn into_sendme_tag(self) -> Option<SendmeTag> {
763 self.tag
764 }
765}
766impl From<SendmeTag> for Sendme {
767 fn from(value: SendmeTag) -> Self {
768 Self { tag: Some(value) }
769 }
770}
771impl Body for Sendme {
772 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
773 let tag = if r.remaining() == 0 {
774 None
775 } else {
776 let ver = r.take_u8()?;
777 match ver {
778 0 => None,
779 1 => {
780 let dlen = r.take_u16()?;
781 Some(r.take(dlen as usize)?.try_into()?)
782 }
783 _ => {
784 return Err(Error::InvalidMessage("Unrecognized SENDME version.".into()));
785 }
786 }
787 };
788 Ok(Sendme { tag })
789 }
790 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
791 match self.tag {
792 None => (),
793 Some(x) => {
794 w.write_u8(1);
795 let x = x.as_ref();
796 let bodylen: u16 = x
797 .len()
798 .try_into()
799 .map_err(|_| EncodeError::BadLengthValue)?;
800 w.write_u16(bodylen);
801 w.write_all(x);
802 }
803 }
804 Ok(())
805 }
806}
807
808#[derive(Debug, Clone, Deftly)]
813#[derive_deftly(HasMemoryCost)]
814pub struct Extend {
815 addr: Ipv4Addr,
817 port: u16,
819 handshake: Vec<u8>,
821 rsaid: RsaIdentity,
823}
824impl Extend {
825 pub fn new(addr: Ipv4Addr, port: u16, handshake: Vec<u8>, rsaid: RsaIdentity) -> Self {
827 Extend {
828 addr,
829 port,
830 handshake,
831 rsaid,
832 }
833 }
834}
835impl Body for Extend {
836 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
837 let addr = r.extract()?;
838 let port = r.take_u16()?;
839 let handshake = r.take(TAP_C_HANDSHAKE_LEN)?.into();
840 let rsaid = r.extract()?;
841 Ok(Extend {
842 addr,
843 port,
844 handshake,
845 rsaid,
846 })
847 }
848 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
849 w.write(&self.addr)?;
850 w.write_u16(self.port);
851 w.write_all(&self.handshake[..]);
852 w.write(&self.rsaid)?;
853 Ok(())
854 }
855}
856
857#[derive(Debug, Clone, Deftly)]
863#[derive_deftly(HasMemoryCost)]
864pub struct Extended {
865 handshake: Vec<u8>,
867}
868impl Extended {
869 pub fn new(handshake: Vec<u8>) -> Self {
871 Extended { handshake }
872 }
873}
874impl Body for Extended {
875 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
876 let handshake = r.take(TAP_S_HANDSHAKE_LEN)?.into();
877 Ok(Extended { handshake })
878 }
879 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
880 w.write_all(&self.handshake);
881 Ok(())
882 }
883}
884
885#[derive(Debug, Clone, Deftly)]
900#[derive_deftly(HasMemoryCost)]
901pub struct Extend2 {
902 linkspec: Vec<EncodedLinkSpec>,
908 handshake_type: HandshakeType,
910 handshake: Vec<u8>,
912}
913impl Extend2 {
914 pub fn new(
916 linkspec: Vec<EncodedLinkSpec>,
917 handshake_type: HandshakeType,
918 handshake: Vec<u8>,
919 ) -> Self {
920 Extend2 {
921 linkspec,
922 handshake_type,
923 handshake,
924 }
925 }
926
927 pub fn handshake_type(&self) -> HandshakeType {
929 self.handshake_type
930 }
931
932 pub fn handshake(&self) -> &[u8] {
934 &self.handshake[..]
935 }
936}
937
938impl Body for Extend2 {
939 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
940 let n = r.take_u8()?;
941 let linkspec = r.extract_n(n as usize)?;
942 let handshake_type = r.take_u16()?.into();
943 let hlen = r.take_u16()?;
944 let handshake = r.take(hlen as usize)?.into();
945 Ok(Extend2 {
946 linkspec,
947 handshake_type,
948 handshake,
949 })
950 }
951 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
952 let n_linkspecs: u8 = self
953 .linkspec
954 .len()
955 .try_into()
956 .map_err(|_| EncodeError::BadLengthValue)?;
957 w.write_u8(n_linkspecs);
958 for ls in &self.linkspec {
959 w.write(ls)?;
960 }
961 w.write_u16(self.handshake_type.into());
962 let handshake_len: u16 = self
963 .handshake
964 .len()
965 .try_into()
966 .map_err(|_| EncodeError::BadLengthValue)?;
967 w.write_u16(handshake_len);
968 w.write_all(&self.handshake[..]);
969 Ok(())
970 }
971}
972
973#[derive(Debug, Clone, Deftly)]
979#[derive_deftly(HasMemoryCost)]
980pub struct Extended2 {
981 handshake: Vec<u8>,
984}
985impl Extended2 {
986 pub fn new(handshake: Vec<u8>) -> Self {
988 Extended2 { handshake }
989 }
990 pub fn into_body(self) -> Vec<u8> {
992 self.handshake
993 }
994}
995impl Body for Extended2 {
996 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
997 let hlen = r.take_u16()?;
998 let handshake = r.take(hlen as usize)?;
999 Ok(Extended2 {
1000 handshake: handshake.into(),
1001 })
1002 }
1003 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1004 let handshake_len: u16 = self
1005 .handshake
1006 .len()
1007 .try_into()
1008 .map_err(|_| EncodeError::BadLengthValue)?;
1009 w.write_u16(handshake_len);
1010 w.write_all(&self.handshake[..]);
1011 Ok(())
1012 }
1013}
1014
1015#[derive(Debug, Clone, Deftly)]
1023#[derive_deftly(HasMemoryCost)]
1024pub struct Truncated {
1025 reason: DestroyReason,
1027}
1028impl Truncated {
1029 pub fn new(reason: DestroyReason) -> Self {
1031 Truncated { reason }
1032 }
1033 pub fn reason(self) -> DestroyReason {
1035 self.reason
1036 }
1037}
1038impl Body for Truncated {
1039 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
1040 Ok(Truncated {
1041 reason: r.take_u8()?.into(),
1042 })
1043 }
1044 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1045 w.write_u8(self.reason.into());
1046 Ok(())
1047 }
1048}
1049
1050#[derive(Debug, Clone, Deftly)]
1057#[derive_deftly(HasMemoryCost)]
1058pub struct Resolve {
1059 query: Vec<u8>,
1061}
1062impl Resolve {
1063 pub fn new(s: &str) -> Self {
1065 Resolve {
1066 query: s.as_bytes().into(),
1067 }
1068 }
1069 pub fn new_reverse(addr: &IpAddr) -> Self {
1071 let query = match addr {
1072 IpAddr::V4(v4) => {
1073 let [a, b, c, d] = v4.octets();
1074 format!("{}.{}.{}.{}.in-addr.arpa", d, c, b, a)
1075 }
1076 IpAddr::V6(v6) => {
1077 let mut s = String::with_capacity(72);
1078 for o in v6.octets().iter().rev() {
1079 let high_nybble = o >> 4;
1080 let low_nybble = o & 15;
1081 write!(s, "{:x}.{:x}.", low_nybble, high_nybble)
1082 .expect("write to string failed");
1083 }
1084 write!(s, "ip6.arpa").expect("write to string failed");
1085 s
1086 }
1087 };
1088 Resolve {
1089 query: query.into_bytes(),
1090 }
1091 }
1092}
1093impl Body for Resolve {
1094 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
1095 let query = r.take_until(0)?;
1096 Ok(Resolve {
1097 query: query.into(),
1098 })
1099 }
1100 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1101 w.write_all(&self.query[..]);
1102 w.write_u8(0);
1103 Ok(())
1104 }
1105}
1106
1107#[derive(Debug, Clone, Eq, PartialEq, Deftly)]
1109#[derive_deftly(HasMemoryCost)]
1110#[non_exhaustive]
1111pub enum ResolvedVal {
1112 Ip(IpAddr),
1114 Hostname(Vec<u8>),
1116 TransientError,
1118 NontransientError,
1120 Unrecognized(u8, Vec<u8>),
1122}
1123
1124const RES_HOSTNAME: u8 = 0;
1126const RES_IPV4: u8 = 4;
1128const RES_IPV6: u8 = 6;
1130const RES_ERR_TRANSIENT: u8 = 0xF0;
1132const RES_ERR_NONTRANSIENT: u8 = 0xF1;
1134
1135impl Readable for ResolvedVal {
1136 fn take_from(r: &mut Reader<'_>) -> Result<Self> {
1137 fn res_len(tp: u8) -> Option<usize> {
1140 match tp {
1141 RES_IPV4 => Some(4),
1142 RES_IPV6 => Some(16),
1143 _ => None,
1144 }
1145 }
1146 let tp = r.take_u8()?;
1147 let len = r.take_u8()? as usize;
1148 if let Some(expected_len) = res_len(tp) {
1149 if len != expected_len {
1150 return Err(Error::InvalidMessage(
1151 "Wrong length for RESOLVED answer".into(),
1152 ));
1153 }
1154 }
1155 Ok(match tp {
1156 RES_HOSTNAME => Self::Hostname(r.take(len)?.into()),
1157 RES_IPV4 => Self::Ip(IpAddr::V4(r.extract()?)),
1158 RES_IPV6 => Self::Ip(IpAddr::V6(r.extract()?)),
1159 RES_ERR_TRANSIENT => {
1160 r.advance(len)?;
1161 Self::TransientError
1162 }
1163 RES_ERR_NONTRANSIENT => {
1164 r.advance(len)?;
1165 Self::NontransientError
1166 }
1167 _ => Self::Unrecognized(tp, r.take(len)?.into()),
1168 })
1169 }
1170}
1171
1172impl Writeable for ResolvedVal {
1173 fn write_onto<B: Writer + ?Sized>(&self, w: &mut B) -> EncodeResult<()> {
1174 match self {
1175 Self::Hostname(h) => {
1176 w.write_u8(RES_HOSTNAME);
1177 let h_len: u8 = h
1178 .len()
1179 .try_into()
1180 .map_err(|_| EncodeError::BadLengthValue)?;
1181 w.write_u8(h_len);
1182 w.write_all(&h[..]);
1183 }
1184 Self::Ip(IpAddr::V4(a)) => {
1185 w.write_u8(RES_IPV4);
1186 w.write_u8(4); w.write(a)?;
1188 }
1189 Self::Ip(IpAddr::V6(a)) => {
1190 w.write_u8(RES_IPV6);
1191 w.write_u8(16); w.write(a)?;
1193 }
1194 Self::TransientError => {
1195 w.write_u8(RES_ERR_TRANSIENT);
1196 w.write_u8(0); }
1198 Self::NontransientError => {
1199 w.write_u8(RES_ERR_NONTRANSIENT);
1200 w.write_u8(0); }
1202 Self::Unrecognized(tp, v) => {
1203 w.write_u8(*tp);
1204 let v_len: u8 = v
1205 .len()
1206 .try_into()
1207 .map_err(|_| EncodeError::BadLengthValue)?;
1208 w.write_u8(v_len);
1209 w.write_all(&v[..]);
1210 }
1211 }
1212 Ok(())
1213 }
1214}
1215
1216#[derive(Debug, Clone, Deftly)]
1221#[derive_deftly(HasMemoryCost)]
1222pub struct Resolved {
1223 answers: Vec<(ResolvedVal, u32)>,
1225}
1226impl Resolved {
1227 pub fn new_empty() -> Self {
1229 Resolved {
1230 answers: Vec::new(),
1231 }
1232 }
1233 pub fn new_err(transient: bool, ttl: u32) -> Self {
1238 let mut res = Self::new_empty();
1239 let err = if transient {
1240 ResolvedVal::TransientError
1241 } else {
1242 ResolvedVal::NontransientError
1243 };
1244 res.add_answer(err, ttl);
1245 res
1246 }
1247 pub fn add_answer(&mut self, answer: ResolvedVal, ttl: u32) {
1249 self.answers.push((answer, ttl));
1250 }
1251
1252 pub fn into_answers(self) -> Vec<(ResolvedVal, u32)> {
1260 self.answers
1261 }
1262}
1263impl Body for Resolved {
1264 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
1265 let mut answers = Vec::new();
1266 while r.remaining() > 0 {
1267 let rv = r.extract()?;
1268 let ttl = r.take_u32()?;
1269 answers.push((rv, ttl));
1270 }
1271 Ok(Resolved { answers })
1272 }
1273 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1274 for (rv, ttl) in &self.answers {
1275 w.write(rv)?;
1276 w.write_u32(*ttl);
1277 }
1278 Ok(())
1279 }
1280}
1281
1282#[derive(Debug, Clone, Deftly)]
1286#[derive_deftly(HasMemoryCost)]
1287pub struct Unrecognized {
1288 cmd: RelayCmd,
1290 body: Vec<u8>,
1292}
1293
1294impl Unrecognized {
1295 pub fn new<B>(cmd: RelayCmd, body: B) -> Self
1297 where
1298 B: Into<Vec<u8>>,
1299 {
1300 let body = body.into();
1301 Unrecognized { cmd, body }
1302 }
1303
1304 pub fn cmd(&self) -> RelayCmd {
1306 self.cmd
1307 }
1308 pub fn decode_with_cmd(cmd: RelayCmd, r: &mut Reader<'_>) -> Result<Self> {
1310 let mut r = Unrecognized::decode_from_reader(r)?;
1311 r.cmd = cmd;
1312 Ok(r)
1313 }
1314}
1315
1316impl Body for Unrecognized {
1317 fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
1318 Ok(Unrecognized {
1319 cmd: 0.into(),
1320 body: r.take(r.remaining())?.into(),
1321 })
1322 }
1323 fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
1324 w.write_all(&self.body[..]);
1325 Ok(())
1326 }
1327}
1328
1329macro_rules! empty_body {
1331 {
1332 $(#[$meta:meta])*
1333 pub struct $name:ident {}
1334 } => {
1335 $(#[$meta])*
1336 #[derive(Clone,Debug,Default,derive_deftly::Deftly)]
1337 #[derive_deftly(tor_memquota::HasMemoryCost)]
1338 #[non_exhaustive]
1339 pub struct $name {}
1340 impl $crate::relaycell::msg::Body for $name {
1341 fn decode_from_reader(_r: &mut Reader<'_>) -> Result<Self> {
1342 Ok(Self::default())
1343 }
1344 fn encode_onto<W: Writer + ?Sized>(self, _w: &mut W) -> EncodeResult<()> {
1345 Ok(())
1346 }
1347 }
1348 }
1349}
1350pub(crate) use empty_body;
1351
1352empty_body! {
1353 pub struct Drop {}
1355}
1356empty_body! {
1357 pub struct Truncate {}
1359}
1360empty_body! {
1361 pub struct BeginDir {}
1363}
1364
1365macro_rules! msg_impl_relaymsg {
1375 ($($body:ident),* $(,)?) =>
1376 {paste::paste!{
1377 $(impl crate::relaycell::RelayMsg for $body {
1378 fn cmd(&self) -> crate::relaycell::RelayCmd { crate::relaycell::RelayCmd::[< $body:snake:upper >] }
1379 fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()> {
1380 crate::relaycell::msg::Body::encode_onto(self, w)
1381 }
1382 fn decode_from_reader(cmd: RelayCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
1383 if cmd != crate::relaycell::RelayCmd::[< $body:snake:upper >] {
1384 return Err(tor_bytes::Error::InvalidMessage(
1385 format!("Expected {} command; got {cmd}", stringify!([< $body:snake:upper >])).into()
1386 ));
1387 }
1388 crate::relaycell::msg::Body::decode_from_reader(r)
1389 }
1390 }
1391
1392 impl TryFrom<AnyRelayMsg> for $body {
1393 type Error = crate::Error;
1394 fn try_from(msg: AnyRelayMsg) -> crate::Result<$body> {
1395 use crate::relaycell::RelayMsg;
1396 match msg {
1397 AnyRelayMsg::$body(b) => Ok(b),
1398 _ => Err(crate::Error::CircProto(format!("Expected {}; got {}" ,
1399 stringify!([<$body:snake:upper>]),
1400 msg.cmd())) ),
1401 }
1402 }
1403 }
1404 )*
1405 }}
1406}
1407
1408msg_impl_relaymsg!(
1409 Begin, Data, End, Connected, Sendme, Extend, Extended, Extend2, Extended2, Truncate, Truncated,
1410 Drop, Resolve, Resolved, BeginDir,
1411);
1412
1413#[cfg(feature = "experimental-udp")]
1414msg_impl_relaymsg!(ConnectUdp, ConnectedUdp, Datagram);
1415
1416#[cfg(feature = "hs")]
1417msg_impl_relaymsg!(
1418 EstablishIntro,
1419 EstablishRendezvous,
1420 Introduce1,
1421 Introduce2,
1422 Rendezvous1,
1423 Rendezvous2,
1424 IntroEstablished,
1425 RendezvousEstablished,
1426 IntroduceAck,
1427);
1428
1429#[cfg(feature = "conflux")]
1430msg_impl_relaymsg!(ConfluxSwitch, ConfluxLink, ConfluxLinked, ConfluxLinkedAck);
1431
1432msg_impl_relaymsg!(Xon, Xoff);
1433
1434#[cfg(test)]
1435mod test {
1436 #![allow(clippy::bool_assert_comparison)]
1438 #![allow(clippy::clone_on_copy)]
1439 #![allow(clippy::dbg_macro)]
1440 #![allow(clippy::mixed_attributes_style)]
1441 #![allow(clippy::print_stderr)]
1442 #![allow(clippy::print_stdout)]
1443 #![allow(clippy::single_char_pattern)]
1444 #![allow(clippy::unwrap_used)]
1445 #![allow(clippy::unchecked_duration_subtraction)]
1446 #![allow(clippy::useless_vec)]
1447 #![allow(clippy::needless_pass_by_value)]
1448 use super::*;
1451
1452 #[test]
1453 fn sendme_tags() {
1454 let ts: Vec<SendmeTag> = vec![
1456 (*b"Yea, on the word of ").into(),
1457 (*b"a Bloom, ye shal").into(),
1458 (*b"l ere long enter int").into(),
1459 (*b"o the golden cit").into(),
1460 ];
1461
1462 for (i1, i2) in (0..4).zip(0..4) {
1463 if i1 == i2 {
1464 assert_eq!(ts[i1], ts[i2]);
1465 } else {
1466 assert_ne!(ts[i1], ts[i2]);
1467 }
1468 }
1469
1470 assert_eq!(ts[0].as_ref(), &b"Yea, on the word of "[..]);
1471 assert_eq!(ts[3].as_ref(), &b"o the golden cit"[..]);
1472
1473 assert_eq!(ts[1], b"a Bloom, ye shal"[..].try_into().unwrap());
1474 assert_eq!(ts[2], b"l ere long enter int"[..].try_into().unwrap());
1475
1476 assert!(matches!(
1478 SendmeTag::try_from(&b"o the golden ci"[..]),
1479 Err(InvalidSendmeTag { .. }),
1480 ));
1481 }
1482}