tailtalk_packets/
headers.rs1use crate::{
2 aarp::{AarpError, AarpPacket},
3 aep::{AepError, AepPacket},
4 atp::{AtpError, AtpPacket},
5 ddp::{DdpError, DdpPacket, DdpProtocolType},
6 ethertalk::{EtherTalkError, EtherTalkPhase2Frame, EtherTalkPhase2Type},
7};
8use thiserror::Error;
9
10#[derive(Debug)]
11pub enum NetHeader {
12 Aarp(AarpPacket),
13 Ddp(DdpPacket),
14}
15
16#[derive(Debug)]
17pub enum TransportHeader {
18 Aep(AepPacket),
19 Atp(AtpPacket),
20}
21
22#[derive(Debug)]
23pub struct AppleTalkHeaders {
24 pub link: EtherTalkPhase2Frame,
25 pub net: NetHeader,
26 pub transport: Option<TransportHeader>,
27 pub payload: Option<Box<[u8]>>,
28}
29
30#[derive(Error, Debug)]
31pub enum AppleTalkError {
32 #[error("invalid input buffer size - expected {expected:?} bytes but found {found:?}")]
33 InvalidSize { expected: usize, found: usize },
34 #[error("Exceeded maximum possible packet size of 65536")]
35 ExceededMax,
36 #[error("failed to encode/decode link header")]
37 LinkHeaderError(EtherTalkError),
38 #[error("failed to encode DDP header")]
39 DdpError(DdpError),
40 #[error("failed to encode/decode AARP header")]
41 AarpError(AarpError),
42 #[error("failed to encode AEP header")]
43 AepError(AepError),
44 #[error("failed to encode ATP header")]
45 AtpError(AtpError),
46}
47
48impl AppleTalkHeaders {
49 pub fn encode(mut self, buffer: &mut [u8]) -> Result<usize, AppleTalkError> {
50 let net_size = match self.net {
51 NetHeader::Ddp(_) => DdpPacket::LEN,
52 NetHeader::Aarp(_) => AarpPacket::LEN,
53 };
54 let transport_size = match self.transport {
55 Some(TransportHeader::Aep(ref pkt)) => pkt.len(),
56 Some(TransportHeader::Atp(_)) => AtpPacket::HEADER_LEN,
57 None => 0,
58 };
59 let total_len = EtherTalkPhase2Frame::LLC_LEN
60 + net_size
61 + transport_size
62 + self.payload.as_ref().map_or(0, |p| p.len());
63
64 if total_len >= u16::MAX as usize {
65 return Err(AppleTalkError::ExceededMax);
66 }
67 self.link.len = total_len as u16;
68
69 let mut pos = self
70 .link
71 .to_bytes(buffer)
72 .map_err(AppleTalkError::LinkHeaderError)?;
73
74 pos += match self.net {
75 NetHeader::Aarp(pkt) => pkt.to_bytes(&mut buffer[pos..]),
76 NetHeader::Ddp(pkt) => pkt
77 .to_bytes(&mut buffer[pos..])
78 .map_err(AppleTalkError::DdpError)?,
79 };
80
81 pos += match self.transport {
82 Some(TransportHeader::Aep(pkt)) => pkt
83 .to_bytes(&mut buffer[pos..])
84 .map_err(AppleTalkError::AepError)?,
85 Some(TransportHeader::Atp(pkt)) => pkt
86 .to_bytes(&mut buffer[pos..])
87 .map_err(AppleTalkError::AtpError)?,
88 None => 0,
89 };
90
91 if let Some(payload) = self.payload {
92 if buffer.len() - pos < payload.len() {
93 return Err(AppleTalkError::InvalidSize {
94 expected: pos + payload.len(),
95 found: buffer.len(),
96 });
97 }
98 buffer[pos..(pos + payload.len())].copy_from_slice(&payload);
99 pos += payload.len();
100 }
101
102 Ok(pos)
103 }
104
105 pub fn decode(pkt: &[u8]) -> Result<AppleTalkHeaders, AppleTalkError> {
106 let link = EtherTalkPhase2Frame::parse(pkt).map_err(AppleTalkError::LinkHeaderError)?;
107
108 let net = match link.protocol {
109 EtherTalkPhase2Type::Ddp => {
110 let ddp_pkt = DdpPacket::parse(&pkt[EtherTalkPhase2Frame::len()..])
111 .map_err(AppleTalkError::DdpError)?;
112 NetHeader::Ddp(ddp_pkt)
113 }
114 EtherTalkPhase2Type::Aarp => {
115 let aarp_pkt = AarpPacket::parse(&pkt[EtherTalkPhase2Frame::len()..])
116 .map_err(AppleTalkError::AarpError)?;
117 NetHeader::Aarp(aarp_pkt)
118 }
119 };
120
121 let (transport, payload) = match net {
122 NetHeader::Ddp(ref ddp) => match ddp.protocol_typ {
123 DdpProtocolType::Aep => (
124 Some(TransportHeader::Aep(
125 AepPacket::parse(&pkt[EtherTalkPhase2Frame::len() + DdpPacket::LEN..])
126 .map_err(AppleTalkError::AepError)?,
127 )),
128 None,
129 ),
130 DdpProtocolType::Atp => {
131 let offset = EtherTalkPhase2Frame::len() + DdpPacket::LEN;
132 let atp_pkt = AtpPacket::parse(&pkt[offset..])
133 .map_err(AppleTalkError::AtpError)?;
134 let payload_offset = offset + AtpPacket::HEADER_LEN;
135 let payload = if payload_offset < pkt.len() {
136 Some(pkt[payload_offset..].to_vec().into_boxed_slice())
137 } else {
138 None
139 };
140 (Some(TransportHeader::Atp(atp_pkt)), payload)
141 }
142 _ => (None, None),
143 },
144 _ => (None, None),
145 };
146
147 Ok(AppleTalkHeaders {
148 link,
149 net,
150 transport,
151 payload,
152 })
153 }
154}