1mod data_messages;
2mod header_messages;
3
4use ironrdp_core::{
5 cast_length, ensure_fixed_part_size, ensure_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult,
6 ReadCursor, WriteCursor,
7};
8use num_derive::{FromPrimitive, ToPrimitive};
9use num_traits::{FromPrimitive as _, ToPrimitive as _};
10
11use crate::rdp::capability_sets::{RfxCaps, RfxCapset};
12
13#[rustfmt::skip]
14pub use self::data_messages::{
15 ContextPdu, EntropyAlgorithm, FrameBeginPdu, FrameEndPdu, OperatingMode, Quant, RegionPdu, RfxRectangle, Tile,
16 TileSetPdu,
17};
18pub use self::header_messages::{ChannelsPdu, CodecVersionsPdu, RfxChannel, SyncPdu};
19
20const CODEC_ID: u8 = 1;
21const CHANNEL_ID_FOR_CONTEXT: u8 = 0xFF;
22const CHANNEL_ID_FOR_OTHER_VALUES: u8 = 0x00;
23
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub enum Block<'a> {
26 Tile(Tile<'a>),
27 Caps(RfxCaps),
28 CapabilitySet(RfxCapset),
29 Sync(SyncPdu),
30 CodecVersions(CodecVersionsPdu),
31 Channels(ChannelsPdu),
32 CodecChannel(CodecChannel<'a>),
33}
34
35impl Block<'_> {
36 const NAME: &'static str = "RfxBlock";
37
38 const FIXED_PART_SIZE: usize = BlockHeader::FIXED_PART_SIZE;
39
40 pub fn block_type(&self) -> BlockType {
41 match self {
42 Block::Tile(_) => BlockType::Tile,
43 Block::Caps(_) => BlockType::Capabilities,
44 Block::CapabilitySet(_) => BlockType::CapabilitySet,
45 Block::Sync(_) => BlockType::Sync,
46 Block::Channels(_) => BlockType::Channels,
47 Block::CodecVersions(_) => BlockType::CodecVersions,
48 Block::CodecChannel(CodecChannel::Context(_)) => BlockType::Context,
49 Block::CodecChannel(CodecChannel::FrameBegin(_)) => BlockType::FrameBegin,
50 Block::CodecChannel(CodecChannel::FrameEnd(_)) => BlockType::FrameEnd,
51 Block::CodecChannel(CodecChannel::Region(_)) => BlockType::Region,
52 Block::CodecChannel(CodecChannel::TileSet(_)) => BlockType::Extension,
53 }
54 }
55}
56
57impl Encode for Block<'_> {
58 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
59 ensure_size!(in: dst, size: self.size());
60
61 let ty = self.block_type();
62 let data_length = self.size();
63 BlockHeader { ty, data_length }.encode(dst)?;
64
65 if let Block::CodecChannel(ref c) = self {
66 let channel_id = c.channel_id();
67 CodecChannelHeader { channel_id }.encode(dst)?;
68 }
69
70 match self {
71 Block::Tile(t) => t.encode(dst),
72 Block::Caps(c) => c.encode(dst),
73 Block::CapabilitySet(c) => c.encode(dst),
74 Block::Sync(s) => s.encode(dst),
75 Block::Channels(c) => c.encode(dst),
76 Block::CodecVersions(c) => c.encode(dst),
77 Block::CodecChannel(CodecChannel::Context(c)) => c.encode(dst),
78 Block::CodecChannel(CodecChannel::FrameBegin(f)) => f.encode(dst),
79 Block::CodecChannel(CodecChannel::FrameEnd(f)) => f.encode(dst),
80 Block::CodecChannel(CodecChannel::Region(r)) => r.encode(dst),
81 Block::CodecChannel(CodecChannel::TileSet(t)) => t.encode(dst),
82 }
83 }
84
85 fn name(&self) -> &'static str {
86 Self::NAME
87 }
88
89 fn size(&self) -> usize {
90 Self::FIXED_PART_SIZE
91 + if matches!(self, Block::CodecChannel(_)) {
92 CodecChannelHeader::FIXED_PART_SIZE
93 } else {
94 0
95 }
96 + match self {
97 Block::Tile(t) => t.size(),
98 Block::Caps(c) => c.size(),
99 Block::CapabilitySet(c) => c.size(),
100 Block::Sync(s) => s.size(),
101 Block::Channels(c) => c.size(),
102 Block::CodecVersions(c) => c.size(),
103 Block::CodecChannel(CodecChannel::Context(c)) => c.size(),
104 Block::CodecChannel(CodecChannel::FrameBegin(f)) => f.size(),
105 Block::CodecChannel(CodecChannel::FrameEnd(f)) => f.size(),
106 Block::CodecChannel(CodecChannel::Region(r)) => r.size(),
107 Block::CodecChannel(CodecChannel::TileSet(t)) => t.size(),
108 }
109 }
110}
111
112impl<'de> Decode<'de> for Block<'de> {
113 fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
114 let header = BlockHeader::decode(src)?;
115 let mut len = header.size();
116 if header.ty.is_channel() {
117 let channel = CodecChannelHeader::decode(src)?;
118 let expected_id = if header.ty == BlockType::Context {
119 CHANNEL_ID_FOR_CONTEXT
120 } else {
121 CHANNEL_ID_FOR_OTHER_VALUES
122 };
123 if channel.channel_id != expected_id {
124 return Err(invalid_field_err!("channelId", "Invalid channel ID"));
125 }
126 len += channel.size();
127 }
128 let data_len = header
129 .data_length
130 .checked_sub(len)
131 .ok_or_else(|| invalid_field_err!("blockLen", "Invalid block length"))?;
132 ensure_size!(in: src, size: data_len);
133 let src = &mut ReadCursor::new(src.read_slice(data_len));
134 match header.ty {
135 BlockType::Tile => Ok(Self::Tile(Tile::decode(src)?)),
136 BlockType::Capabilities => Ok(Self::Caps(RfxCaps::decode(src)?)),
137 BlockType::CapabilitySet => Ok(Self::CapabilitySet(RfxCapset::decode(src)?)),
138 BlockType::Sync => Ok(Self::Sync(SyncPdu::decode(src)?)),
139 BlockType::Channels => Ok(Self::Channels(ChannelsPdu::decode(src)?)),
140 BlockType::CodecVersions => Ok(Self::CodecVersions(CodecVersionsPdu::decode(src)?)),
141 BlockType::Context => Ok(Self::CodecChannel(CodecChannel::Context(ContextPdu::decode(src)?))),
142 BlockType::FrameBegin => Ok(Self::CodecChannel(CodecChannel::FrameBegin(FrameBeginPdu::decode(
143 src,
144 )?))),
145 BlockType::FrameEnd => Ok(Self::CodecChannel(CodecChannel::FrameEnd(FrameEndPdu::decode(src)?))),
146 BlockType::Region => Ok(Self::CodecChannel(CodecChannel::Region(RegionPdu::decode(src)?))),
147 BlockType::Extension => Ok(Self::CodecChannel(CodecChannel::TileSet(TileSetPdu::decode(src)?))),
148 }
149 }
150}
151
152#[derive(Debug, Clone, PartialEq, Eq)]
153pub enum CodecChannel<'a> {
154 Context(ContextPdu),
155 FrameBegin(FrameBeginPdu),
156 FrameEnd(FrameEndPdu),
157 Region(RegionPdu),
158 TileSet(TileSetPdu<'a>),
159}
160
161impl CodecChannel<'_> {
162 fn channel_id(&self) -> u8 {
163 if matches!(self, CodecChannel::Context(_)) {
164 CHANNEL_ID_FOR_CONTEXT
165 } else {
166 CHANNEL_ID_FOR_OTHER_VALUES
167 }
168 }
169}
170
171#[derive(Debug, Clone, PartialEq, Eq)]
175pub struct BlockHeader {
176 pub ty: BlockType,
177 pub data_length: usize,
178}
179
180impl BlockHeader {
181 const NAME: &'static str = "RfxBlockHeader";
182
183 const FIXED_PART_SIZE: usize = 2 + 4 ;
184}
185
186impl Encode for BlockHeader {
187 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
188 ensure_fixed_part_size!(in: dst);
189
190 dst.write_u16(self.ty.to_u16().unwrap());
191 dst.write_u32(cast_length!("data len", self.data_length)?);
192
193 Ok(())
194 }
195
196 fn name(&self) -> &'static str {
197 Self::NAME
198 }
199
200 fn size(&self) -> usize {
201 Self::FIXED_PART_SIZE
202 }
203}
204
205impl<'de> Decode<'de> for BlockHeader {
206 fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
207 ensure_fixed_part_size!(in: src);
208
209 let ty = src.read_u16();
210 let ty = BlockType::from_u16(ty).ok_or_else(|| invalid_field_err!("blockType", "Invalid block type"))?;
211 let data_length = src.read_u32() as usize;
212 data_length
213 .checked_sub(Self::FIXED_PART_SIZE)
214 .ok_or_else(|| invalid_field_err!("blockLen", "Invalid block length"))?;
215
216 Ok(Self { ty, data_length })
217 }
218}
219
220#[derive(Debug, Clone, PartialEq, Eq)]
224pub struct CodecChannelHeader {
225 channel_id: u8,
226}
227
228impl CodecChannelHeader {
229 const NAME: &'static str = "CodecChannelHeader";
230
231 const FIXED_PART_SIZE: usize = 1 + 1 ;
232}
233
234impl Encode for CodecChannelHeader {
235 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
236 ensure_fixed_part_size!(in: dst);
237
238 dst.write_u8(CODEC_ID);
239 dst.write_u8(self.channel_id);
240
241 Ok(())
242 }
243
244 fn name(&self) -> &'static str {
245 Self::NAME
246 }
247
248 fn size(&self) -> usize {
249 Self::FIXED_PART_SIZE
250 }
251}
252
253impl Decode<'_> for CodecChannelHeader {
254 fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
255 ensure_fixed_part_size!(in: src);
256
257 let codec_id = src.read_u8();
258 if codec_id != CODEC_ID {
259 return Err(invalid_field_err!("codecId", "Invalid codec ID"));
260 }
261
262 let channel_id = src.read_u8();
263
264 Ok(Self { channel_id })
265 }
266}
267
268#[derive(Debug, Clone, PartialEq, Eq)]
272pub struct FrameAcknowledgePdu {
273 pub frame_id: u32,
274}
275
276impl FrameAcknowledgePdu {
277 const NAME: &'static str = "FrameAcknowledgePdu";
278
279 const FIXED_PART_SIZE: usize = 4 ;
280}
281
282impl Encode for FrameAcknowledgePdu {
283 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
284 ensure_fixed_part_size!(in: dst);
285
286 dst.write_u32(self.frame_id);
287
288 Ok(())
289 }
290
291 fn name(&self) -> &'static str {
292 Self::NAME
293 }
294
295 fn size(&self) -> usize {
296 Self::FIXED_PART_SIZE
297 }
298}
299
300impl<'de> Decode<'de> for FrameAcknowledgePdu {
301 fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
302 ensure_fixed_part_size!(in: src);
303
304 let frame_id = src.read_u32();
305
306 Ok(Self { frame_id })
307 }
308}
309
310#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
311#[repr(u16)]
312pub enum BlockType {
313 Tile = 0xCAC3,
314 Capabilities = 0xCBC0,
315 CapabilitySet = 0xCBC1,
316 Sync = 0xCCC0,
317 CodecVersions = 0xCCC1,
318 Channels = 0xCCC2,
319 Context = 0xCCC3,
320 FrameBegin = 0xCCC4,
321 FrameEnd = 0xCCC5,
322 Region = 0xCCC6,
323 Extension = 0xCCC7,
324}
325
326impl BlockType {
327 fn is_channel(&self) -> bool {
328 matches!(
329 self,
330 BlockType::Context | BlockType::FrameBegin | BlockType::FrameEnd | BlockType::Region | BlockType::Extension
331 )
332 }
333}