1use bit_field::BitField as _;
2use bitflags::bitflags;
3use ironrdp_core::{
4 cast_length, ensure_fixed_part_size, ensure_size, invalid_field_err, other_err, Decode, DecodeResult, Encode,
5 EncodeResult, ReadCursor, WriteCursor,
6};
7use num_derive::{FromPrimitive, ToPrimitive};
8use num_traits::{FromPrimitive as _, ToPrimitive as _};
9
10use crate::fast_path::EncryptionFlags;
11use crate::input::{MousePdu, MouseRelPdu, MouseXPdu};
12use crate::per;
13
14#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct FastPathInputHeader {
17 pub flags: EncryptionFlags,
18 pub data_length: usize,
19 pub num_events: u8,
20}
21
22impl FastPathInputHeader {
23 const NAME: &'static str = "FastPathInputHeader";
24
25 const FIXED_PART_SIZE: usize = 1 ;
26}
27
28impl Encode for FastPathInputHeader {
29 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
30 ensure_size!(in: dst, size: self.size());
31
32 let mut header = 0u8;
33 header.set_bits(0..2, 0); if self.num_events < 16 {
35 header.set_bits(2..7, self.num_events);
36 }
37 header.set_bits(6..8, self.flags.bits());
38 dst.write_u8(header);
39
40 per::write_length(dst, cast_length!("len", self.data_length + self.size())?);
41 if self.num_events > 15 {
42 dst.write_u8(self.num_events);
43 }
44
45 Ok(())
46 }
47
48 fn name(&self) -> &'static str {
49 Self::NAME
50 }
51
52 fn size(&self) -> usize {
53 let num_events_length = if self.num_events < 16 { 0 } else { 1 };
54 Self::FIXED_PART_SIZE
55 + per::sizeof_length(self.data_length as u16 + num_events_length as u16 + 1)
56 + num_events_length
57 }
58}
59
60impl<'de> Decode<'de> for FastPathInputHeader {
61 fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
62 ensure_fixed_part_size!(in: src);
63
64 let header = src.read_u8();
65 let flags = EncryptionFlags::from_bits_truncate(header.get_bits(6..8));
66 let mut num_events = header.get_bits(2..6);
67 let (length, sizeof_length) = per::read_length(src).map_err(|e| other_err!("perLen", source: e))?;
68
69 if !flags.is_empty() {
70 return Err(invalid_field_err!("flags", "encryption not supported"));
71 }
72
73 let num_events_length = if num_events == 0 {
74 ensure_size!(in: src, size: 1);
75 num_events = src.read_u8();
76 1
77 } else {
78 0
79 };
80
81 let data_length = length as usize - sizeof_length - 1 - num_events_length;
82
83 Ok(FastPathInputHeader {
84 flags,
85 data_length,
86 num_events,
87 })
88 }
89}
90
91#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
92#[repr(u8)]
93pub enum FastpathInputEventType {
94 ScanCode = 0x0000,
95 Mouse = 0x0001,
96 MouseX = 0x0002,
97 Sync = 0x0003,
98 Unicode = 0x0004,
99 MouseRel = 0x0005,
100 QoeTimestamp = 0x0006,
101}
102
103#[derive(Debug, Clone, PartialEq, Eq)]
104pub enum FastPathInputEvent {
105 KeyboardEvent(KeyboardFlags, u8),
106 UnicodeKeyboardEvent(KeyboardFlags, u16),
107 MouseEvent(MousePdu),
108 MouseEventEx(MouseXPdu),
109 MouseEventRel(MouseRelPdu),
110 QoeEvent(u32),
111 SyncEvent(SynchronizeFlags),
112}
113
114impl FastPathInputEvent {
115 const NAME: &'static str = "FastPathInputEvent";
116
117 const FIXED_PART_SIZE: usize = 1 ;
118}
119
120impl Encode for FastPathInputEvent {
121 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
122 ensure_size!(in: dst, size: self.size());
123
124 let mut header = 0u8;
125 let (flags, code) = match self {
126 FastPathInputEvent::KeyboardEvent(flags, _) => (flags.bits(), FastpathInputEventType::ScanCode),
127 FastPathInputEvent::UnicodeKeyboardEvent(flags, _) => (flags.bits(), FastpathInputEventType::Unicode),
128 FastPathInputEvent::MouseEvent(_) => (0, FastpathInputEventType::Mouse),
129 FastPathInputEvent::MouseEventEx(_) => (0, FastpathInputEventType::MouseX),
130 FastPathInputEvent::MouseEventRel(_) => (0, FastpathInputEventType::MouseRel),
131 FastPathInputEvent::QoeEvent(_) => (0, FastpathInputEventType::QoeTimestamp),
132 FastPathInputEvent::SyncEvent(flags) => (flags.bits(), FastpathInputEventType::Sync),
133 };
134 header.set_bits(0..5, flags);
135 header.set_bits(5..8, code.to_u8().unwrap());
136 dst.write_u8(header);
137 match self {
138 FastPathInputEvent::KeyboardEvent(_, code) => {
139 dst.write_u8(*code);
140 }
141 FastPathInputEvent::UnicodeKeyboardEvent(_, code) => {
142 dst.write_u16(*code);
143 }
144 FastPathInputEvent::MouseEvent(pdu) => {
145 pdu.encode(dst)?;
146 }
147 FastPathInputEvent::MouseEventEx(pdu) => {
148 pdu.encode(dst)?;
149 }
150 FastPathInputEvent::QoeEvent(stamp) => {
151 dst.write_u32(*stamp);
152 }
153 _ => {}
154 };
155
156 Ok(())
157 }
158
159 fn name(&self) -> &'static str {
160 Self::NAME
161 }
162
163 fn size(&self) -> usize {
164 Self::FIXED_PART_SIZE
165 + match self {
166 FastPathInputEvent::KeyboardEvent(_, _) => 1,
167 FastPathInputEvent::UnicodeKeyboardEvent(_, _) => 2,
168 FastPathInputEvent::MouseEvent(pdu) => pdu.size(),
169 FastPathInputEvent::MouseEventEx(pdu) => pdu.size(),
170 FastPathInputEvent::MouseEventRel(pdu) => pdu.size(),
171 FastPathInputEvent::QoeEvent(_) => 4,
172 FastPathInputEvent::SyncEvent(_) => 0,
173 }
174 }
175}
176
177impl<'de> Decode<'de> for FastPathInputEvent {
178 fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
179 ensure_fixed_part_size!(in: src);
180
181 let header = src.read_u8();
182 let flags = header.get_bits(0..5);
183 let code = header.get_bits(5..8);
184 let code: FastpathInputEventType = FastpathInputEventType::from_u8(code)
185 .ok_or_else(|| invalid_field_err!("code", "input event code unsupported"))?;
186 let event = match code {
187 FastpathInputEventType::ScanCode => {
188 ensure_size!(in: src, size: 1);
189 let code = src.read_u8();
190 let flags = KeyboardFlags::from_bits(flags)
191 .ok_or_else(|| invalid_field_err!("flags", "input keyboard flags unsupported"))?;
192 FastPathInputEvent::KeyboardEvent(flags, code)
193 }
194 FastpathInputEventType::Mouse => {
195 let mouse_event = MousePdu::decode(src)?;
196 FastPathInputEvent::MouseEvent(mouse_event)
197 }
198 FastpathInputEventType::MouseX => {
199 let mouse_event = MouseXPdu::decode(src)?;
200 FastPathInputEvent::MouseEventEx(mouse_event)
201 }
202 FastpathInputEventType::MouseRel => {
203 let mouse_event = MouseRelPdu::decode(src)?;
204 FastPathInputEvent::MouseEventRel(mouse_event)
205 }
206 FastpathInputEventType::Sync => {
207 let flags = SynchronizeFlags::from_bits(flags)
208 .ok_or_else(|| invalid_field_err!("flags", "input synchronize flags unsupported"))?;
209 FastPathInputEvent::SyncEvent(flags)
210 }
211 FastpathInputEventType::Unicode => {
212 ensure_size!(in: src, size: 2);
213 let code = src.read_u16();
214 let flags = KeyboardFlags::from_bits(flags)
215 .ok_or_else(|| invalid_field_err!("flags", "input keyboard flags unsupported"))?;
216 FastPathInputEvent::UnicodeKeyboardEvent(flags, code)
217 }
218 FastpathInputEventType::QoeTimestamp => {
219 ensure_size!(in: src, size: 4);
220 let code = src.read_u32();
221 FastPathInputEvent::QoeEvent(code)
222 }
223 };
224 Ok(event)
225 }
226}
227
228bitflags! {
229 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
230 pub struct KeyboardFlags: u8 {
231 const RELEASE = 0x01;
232 const EXTENDED = 0x02;
233 const EXTENDED1 = 0x04;
234 }
235}
236
237bitflags! {
238 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
239 pub struct SynchronizeFlags: u8 {
240 const SCROLL_LOCK = 0x01;
241 const NUM_LOCK = 0x02;
242 const CAPS_LOCK = 0x04;
243 const KANA_LOCK = 0x08;
244 }
245}
246
247#[derive(Debug, Clone, PartialEq, Eq)]
248pub struct FastPathInput(pub Vec<FastPathInputEvent>);
249
250impl FastPathInput {
251 const NAME: &'static str = "FastPathInput";
252}
253
254impl Encode for FastPathInput {
255 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
256 ensure_size!(in: dst, size: self.size());
257
258 if self.0.is_empty() {
259 return Err(other_err!("Empty fast-path input"));
260 }
261
262 let data_length = self.0.iter().map(Encode::size).sum::<usize>();
263 let header = FastPathInputHeader {
264 num_events: self.0.len() as u8,
265 flags: EncryptionFlags::empty(),
266 data_length,
267 };
268 header.encode(dst)?;
269
270 for event in self.0.iter() {
271 event.encode(dst)?;
272 }
273
274 Ok(())
275 }
276
277 fn name(&self) -> &'static str {
278 Self::NAME
279 }
280
281 fn size(&self) -> usize {
282 let data_length = self.0.iter().map(Encode::size).sum::<usize>();
283 let header = FastPathInputHeader {
284 num_events: self.0.len() as u8,
285 flags: EncryptionFlags::empty(),
286 data_length,
287 };
288 header.size() + data_length
289 }
290}
291
292impl<'de> Decode<'de> for FastPathInput {
293 fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
294 let header = FastPathInputHeader::decode(src)?;
295 let events = (0..header.num_events)
296 .map(|_| FastPathInputEvent::decode(src))
297 .collect::<Result<Vec<_>, _>>()?;
298
299 Ok(Self(events))
300 }
301}