Skip to main content

tailtalk_packets/
headers.rs

1use 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}