ironrdp_pdu/codecs/rfx/
header_messages.rs

1use ironrdp_core::{
2    cast_length, ensure_fixed_part_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult, ReadCursor,
3    WriteCursor,
4};
5
6const SYNC_MAGIC: u32 = 0xCACC_ACCA;
7const SYNC_VERSION: u16 = 0x0100;
8const CODECS_NUMBER: u8 = 1;
9const CODEC_ID: u8 = 1;
10const CODEC_VERSION: u16 = 0x0100;
11const CHANNEL_ID: u8 = 0;
12
13// [2.2.2.2.1] TS_RFX_SYNC
14//
15// [2.2.2.2.1]: https://learn.microsoft.com/pt-br/openspecs/windows_protocols/ms-rdprfx/f01b81b6-1a8f-49fd-9543-081fbc8e1831
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct SyncPdu;
18
19impl SyncPdu {
20    const NAME: &'static str = "RfxSync";
21
22    const FIXED_PART_SIZE: usize = 4 /* magic */ + 2 /* version */;
23}
24
25impl Encode for SyncPdu {
26    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
27        ensure_fixed_part_size!(in: dst);
28
29        dst.write_u32(SYNC_MAGIC);
30        dst.write_u16(SYNC_VERSION);
31
32        Ok(())
33    }
34
35    fn name(&self) -> &'static str {
36        Self::NAME
37    }
38
39    fn size(&self) -> usize {
40        Self::FIXED_PART_SIZE
41    }
42}
43
44impl<'de> Decode<'de> for SyncPdu {
45    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
46        ensure_fixed_part_size!(in: src);
47
48        let magic = src.read_u32();
49        if magic != SYNC_MAGIC {
50            return Err(invalid_field_err!("magic", "Invalid sync magic"));
51        }
52        let version = src.read_u16();
53        if version != SYNC_VERSION {
54            return Err(invalid_field_err!("version", "Invalid sync version"));
55        }
56
57        Ok(Self)
58    }
59}
60
61/// [2.2.2.2.2] TS_RFX_CODEC_VERSIONS
62///
63/// [2.2.2.2.2]: https://learn.microsoft.com/pt-br/openspecs/windows_protocols/ms-rdprfx/2650e6c2-faf7-4858-b169-828db842b663
64#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct CodecVersionsPdu;
66
67impl CodecVersionsPdu {
68    const NAME: &'static str = "RfxCodecVersions";
69
70    const FIXED_PART_SIZE: usize = 1 /* numCodecs */ + CodecVersion::FIXED_PART_SIZE /* codecs */;
71}
72
73impl Encode for CodecVersionsPdu {
74    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
75        ensure_fixed_part_size!(in: dst);
76
77        dst.write_u8(CODECS_NUMBER);
78        CodecVersion.encode(dst)?;
79
80        Ok(())
81    }
82
83    fn name(&self) -> &'static str {
84        Self::NAME
85    }
86
87    fn size(&self) -> usize {
88        Self::FIXED_PART_SIZE
89    }
90}
91
92impl<'de> Decode<'de> for CodecVersionsPdu {
93    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
94        ensure_fixed_part_size!(in: src);
95
96        let codec_number = src.read_u8();
97        if codec_number != CODECS_NUMBER {
98            return Err(invalid_field_err!("codec_number", "Invalid codec number"));
99        }
100
101        let _codec_version = CodecVersion::decode(src)?;
102
103        Ok(Self)
104    }
105}
106
107/// [2.2.2.2.3] TS_RFX_CHANNELS
108///
109/// [2.2.2.2.3]: https://learn.microsoft.com/pt-br/openspecs/windows_protocols/ms-rdprfx/c6efba0b-f59e-4d8e-8d76-840c41edce5b
110#[derive(Debug, Clone, PartialEq, Eq)]
111pub struct ChannelsPdu(pub Vec<RfxChannel>);
112
113impl ChannelsPdu {
114    const NAME: &'static str = "RfxChannels";
115
116    const FIXED_PART_SIZE: usize = 1 /* numChannels */;
117}
118
119impl Encode for ChannelsPdu {
120    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
121        ensure_fixed_part_size!(in: dst);
122
123        dst.write_u8(cast_length!("num_channels", self.0.len())?);
124        for channel in &self.0 {
125            channel.encode(dst)?;
126        }
127
128        Ok(())
129    }
130
131    fn name(&self) -> &'static str {
132        Self::NAME
133    }
134
135    fn size(&self) -> usize {
136        Self::FIXED_PART_SIZE + self.0.iter().map(|channel| channel.size()).sum::<usize>()
137    }
138}
139
140impl<'de> Decode<'de> for ChannelsPdu {
141    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
142        ensure_fixed_part_size!(in: src);
143
144        let num_channels = src.read_u8();
145        let channels = (0..num_channels)
146            .map(|_| RfxChannel::decode(src))
147            .collect::<DecodeResult<Vec<_>>>()?;
148
149        Ok(Self(channels))
150    }
151}
152
153/// [2.2.2.1.3] TS_RFX_CHANNELT
154///
155/// [2.2.2.1.3]: https://learn.microsoft.com/pt-br/openspecs/windows_protocols/ms-rdprfx/4060f07e-9d73-454d-841e-131a93aca675
156#[derive(Debug, Copy, Clone, PartialEq, Eq)]
157pub struct RfxChannel {
158    pub width: i16,
159    pub height: i16,
160}
161
162impl RfxChannel {
163    const NAME: &'static str = "RfxChannel";
164
165    const FIXED_PART_SIZE: usize = 1 /* channelId */ + 2 /* width */ + 2 /* height */;
166}
167
168impl Encode for RfxChannel {
169    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
170        ensure_fixed_part_size!(in: dst);
171
172        dst.write_u8(CHANNEL_ID);
173        dst.write_i16(self.width);
174        dst.write_i16(self.height);
175
176        Ok(())
177    }
178
179    fn name(&self) -> &'static str {
180        Self::NAME
181    }
182
183    fn size(&self) -> usize {
184        Self::FIXED_PART_SIZE
185    }
186}
187
188impl<'de> Decode<'de> for RfxChannel {
189    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
190        ensure_fixed_part_size!(in: src);
191
192        let channel_id = src.read_u8();
193        if channel_id != CHANNEL_ID {
194            return Err(invalid_field_err!("channelId", "Invalid channel ID"));
195        }
196
197        let width = src.read_i16();
198        let height = src.read_i16();
199
200        Ok(Self { width, height })
201    }
202}
203
204/// [2.2.2.1.4] TS_RFX_CODEC_VERSIONT
205///
206/// [2.2.2.1.4] https://learn.microsoft.com/pt-br/openspecs/windows_protocols/ms-rdprfx/024fee4a-197d-479e-a68f-861933a34b06
207#[derive(Debug, Clone, PartialEq)]
208struct CodecVersion;
209
210impl CodecVersion {
211    const NAME: &'static str = "RfxCodecVersion";
212
213    const FIXED_PART_SIZE: usize = 1 /* codecId */ + 2 /* codecVersion */;
214}
215
216impl Encode for CodecVersion {
217    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
218        ensure_fixed_part_size!(in: dst);
219
220        dst.write_u8(CODEC_ID);
221        dst.write_u16(CODEC_VERSION);
222
223        Ok(())
224    }
225
226    fn name(&self) -> &'static str {
227        Self::NAME
228    }
229
230    fn size(&self) -> usize {
231        Self::FIXED_PART_SIZE
232    }
233}
234
235impl<'de> Decode<'de> for CodecVersion {
236    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
237        ensure_fixed_part_size!(in: src);
238
239        let codec_id = src.read_u8();
240        if codec_id != CODEC_ID {
241            return Err(invalid_field_err!("codec_id", "Invalid codec ID"));
242        }
243        let codec_version = src.read_u16();
244        if codec_version != CODEC_VERSION {
245            return Err(invalid_field_err!("codec_version", "Invalid codec version"));
246        }
247
248        Ok(Self)
249    }
250}