ironrdp_pdu/
x224.rs

1use std::borrow::Cow;
2
3use ironrdp_core::{
4    ensure_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult, IntoOwned, ReadCursor, WriteCursor,
5};
6
7use crate::tpdu::{TpduCode, TpduHeader};
8use crate::tpkt::TpktHeader;
9use crate::{impl_x224_pdu_borrowing, Pdu};
10
11pub trait X224Pdu<'de>: Sized {
12    const X224_NAME: &'static str;
13
14    const TPDU_CODE: TpduCode;
15
16    fn x224_body_encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()>;
17
18    fn x224_body_decode(src: &mut ReadCursor<'de>, tpkt: &TpktHeader, tpdu: &TpduHeader) -> DecodeResult<Self>;
19
20    fn tpdu_header_variable_part_size(&self) -> usize;
21
22    fn tpdu_user_data_size(&self) -> usize;
23}
24
25impl<'de, T> Pdu for T
26where
27    T: X224Pdu<'de>,
28{
29    const NAME: &'static str = T::X224_NAME;
30}
31
32#[derive(Debug, Eq, PartialEq)]
33pub struct X224<T>(pub T);
34
35impl<'de, T> Encode for X224<T>
36where
37    T: X224Pdu<'de>,
38{
39    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
40        let packet_length = self.size();
41
42        ensure_size!(in: dst, size: packet_length);
43
44        TpktHeader {
45            packet_length: u16::try_from(packet_length).unwrap(),
46        }
47        .write(dst)?;
48
49        TpduHeader {
50            li: u8::try_from(T::TPDU_CODE.header_fixed_part_size() + self.0.tpdu_header_variable_part_size() - 1)
51                .unwrap(),
52            code: T::TPDU_CODE,
53        }
54        .write(dst)?;
55
56        self.0.x224_body_encode(dst)
57    }
58
59    fn name(&self) -> &'static str {
60        T::X224_NAME
61    }
62
63    fn size(&self) -> usize {
64        TpktHeader::SIZE
65            + T::TPDU_CODE.header_fixed_part_size()
66            + self.0.tpdu_header_variable_part_size()
67            + self.0.tpdu_user_data_size()
68    }
69}
70
71impl<'de, T> Decode<'de> for X224<T>
72where
73    T: X224Pdu<'de>,
74{
75    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
76        let tpkt = TpktHeader::read(src)?;
77
78        ensure_size!(in: src, size: tpkt.packet_length().saturating_sub(TpktHeader::SIZE));
79
80        let tpdu = TpduHeader::read(src, &tpkt)?;
81        tpdu.code.check_expected(T::TPDU_CODE)?;
82
83        if tpdu.size() < tpdu.fixed_part_size() {
84            return Err(invalid_field_err(
85                "TpduHeader",
86                "li",
87                "fixed part bigger than total header size",
88            ));
89        }
90
91        T::x224_body_decode(src, &tpkt, &tpdu).map(X224)
92    }
93}
94
95pub struct X224Data<'a> {
96    pub data: Cow<'a, [u8]>,
97}
98
99impl_x224_pdu_borrowing!(X224Data<'_>, OwnedX224Data);
100
101impl IntoOwned for X224Data<'_> {
102    type Owned = OwnedX224Data;
103
104    fn into_owned(self) -> Self::Owned {
105        X224Data {
106            data: Cow::Owned(self.data.into_owned()),
107        }
108    }
109}
110
111impl<'de> X224Pdu<'de> for X224Data<'de> {
112    const X224_NAME: &'static str = "X.224 Data";
113
114    const TPDU_CODE: TpduCode = TpduCode::DATA;
115
116    fn x224_body_encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
117        ensure_size!(in: dst, size: self.data.len());
118        dst.write_slice(&self.data);
119
120        Ok(())
121    }
122
123    fn x224_body_decode(src: &mut ReadCursor<'de>, tpkt: &TpktHeader, tpdu: &TpduHeader) -> DecodeResult<Self> {
124        let user_data_size = user_data_size(tpkt, tpdu);
125
126        ensure_size!(in: src, size: user_data_size);
127        let data = src.read_slice(user_data_size);
128
129        Ok(Self {
130            data: Cow::Borrowed(data),
131        })
132    }
133
134    fn tpdu_header_variable_part_size(&self) -> usize {
135        0
136    }
137
138    fn tpdu_user_data_size(&self) -> usize {
139        self.data.len()
140    }
141}
142
143pub fn user_data_size(tpkt: &TpktHeader, tpdu: &TpduHeader) -> usize {
144    tpkt.packet_length() - TpktHeader::SIZE - tpdu.size()
145}