1use core::mcs;
2use core::tpkt;
3use std::io::{Read, Write, Cursor};
4use model::error::{RdpResult, Error, RdpErrorKind, RdpError};
5use model::data::{Component, MessageOption, U32, DynOption, U16, DataType, Message, Array, Trame, Check, to_vec};
6use core::event::{RdpEvent, BitmapEvent};
7use num_enum::TryFromPrimitive;
8use std::convert::TryFrom;
9use core::capability::{Capability, capability_set};
10use core::capability;
11use core::gcc::KeyboardLayout;
12
13
14#[repr(u16)]
16#[derive(Copy, Clone, Eq, PartialEq, Debug, TryFromPrimitive)]
17enum PDUType {
18 PdutypeDemandactivepdu = 0x11,
19 PdutypeConfirmactivepdu = 0x13,
20 PdutypeDeactivateallpdu = 0x16,
21 PdutypeDatapdu = 0x17,
22 PdutypeServerRedirPkt = 0x1A
23}
24
25struct PDU {
29 pub pdu_type: PDUType,
30 pub message: Component
31}
32
33impl PDU {
34 pub fn from_stream(stream: &mut dyn Read) -> RdpResult<Self> {
36 let mut header = share_control_header(None, None, None);
37 header.read(stream)?;
38 PDU::from_control(&header)
39 }
40
41 pub fn from_control(control: &Component) -> RdpResult<Self> {
43 let pdu_type = cast!(DataType::U16, control["pduType"])?;
44 let mut pdu = match PDUType::try_from(pdu_type)? {
45 PDUType::PdutypeDemandactivepdu => ts_demand_active_pdu(),
46 PDUType::PdutypeDatapdu => share_data_header(None, None, None),
47 PDUType::PdutypeConfirmactivepdu => ts_confirm_active_pdu(None, None, None),
48 PDUType::PdutypeDeactivateallpdu => ts_deactivate_all_pdu(),
49 _ => return Err(Error::RdpError(RdpError::new(RdpErrorKind::NotImplemented, "GLOBAL: PDU not implemented")))
50 };
51 pdu.message.read(&mut Cursor::new(cast!(DataType::Slice, control["pduMessage"])?))?;
52 Ok(pdu)
53 }
54}
55
56fn ts_demand_active_pdu() -> PDU {
63 PDU {
64 pdu_type: PDUType::PdutypeDemandactivepdu,
65 message: component![
66 "shareId" => U32::LE(0),
67 "lengthSourceDescriptor" => DynOption::new(U16::LE(0), |length| MessageOption::Size("sourceDescriptor".to_string(), length.inner() as usize)),
68 "lengthCombinedCapabilities" => DynOption::new(U16::LE(0), |length| MessageOption::Size("capabilitySets".to_string(), length.inner() as usize - 4)),
69 "sourceDescriptor" => Vec::<u8>::new(),
70 "numberCapabilities" => U16::LE(0),
71 "pad2Octets" => U16::LE(0),
72 "capabilitySets" => Array::new(|| capability_set(None)),
73 "sessionId" => U32::LE(0)
74 ]
75 }
76}
77
78fn ts_confirm_active_pdu(share_id: Option<u32>, source: Option<Vec<u8>>, capabilities_set: Option<Array<Component>>) -> PDU {
83 let default_capabilities_set = capabilities_set.unwrap_or(Array::new(|| capability_set(None)));
84 let default_source = source.unwrap_or(vec![]);
85 PDU {
86 pdu_type: PDUType::PdutypeConfirmactivepdu,
87 message: component![
88 "shareId" => U32::LE(share_id.unwrap_or(0)),
89 "originatorId" => Check::new(U16::LE(0x03EA)),
90 "lengthSourceDescriptor" => DynOption::new(U16::LE(default_source.len() as u16), |length| MessageOption::Size("sourceDescriptor".to_string(), length.inner() as usize)),
91 "lengthCombinedCapabilities" => DynOption::new(U16::LE(default_capabilities_set.length() as u16 + 4), |length| MessageOption::Size("capabilitySets".to_string(), length.inner() as usize - 4)),
92 "sourceDescriptor" => default_source,
93 "numberCapabilities" => U16::LE(default_capabilities_set.inner().len() as u16),
94 "pad2Octets" => U16::LE(0),
95 "capabilitySets" => default_capabilities_set
96 ]
97 }
98}
99
100fn ts_deactivate_all_pdu() -> PDU {
104 PDU {
105 pdu_type: PDUType::PdutypeDeactivateallpdu,
106 message: component![
107 "shareId" => U32::LE(0),
108 "lengthSourceDescriptor" => DynOption::new(U16::LE(0), |length| MessageOption::Size("sourceDescriptor".to_string(), length.inner() as usize)),
109 "sourceDescriptor" => Vec::<u8>::new()
110 ]
111 }
112}
113
114fn share_data_header(share_id: Option<u32>, pdu_type_2: Option<PDUType2>, message: Option<Vec<u8>>) -> PDU {
116 let default_message = message.unwrap_or(vec![]);
117 PDU {
118 pdu_type: PDUType::PdutypeDatapdu,
119 message: component![
120 "shareId" => U32::LE(share_id.unwrap_or(0)),
121 "pad1" => 0 as u8,
122 "streamId" => 1 as u8,
123 "uncompressedLength" => DynOption::new(U16::LE(default_message.length() as u16 + 18), | size | MessageOption::Size("payload".to_string(), size.inner() as usize - 18)),
124 "pduType2" => pdu_type_2.unwrap_or(PDUType2::Pdutype2ArcStatusPdu) as u8,
125 "compressedType" => 0 as u8,
126 "compressedLength" => U16::LE(0),
127 "payload" => default_message
128 ]
129 }
130}
131
132
133fn share_control_header(pdu_type: Option<PDUType>, pdu_source: Option<u16>, message: Option<Vec<u8>>) -> Component {
136 let default_message = message.unwrap_or(vec![]);
137 component![
138 "totalLength" => DynOption::new(U16::LE(default_message.length() as u16 + 6), |total| MessageOption::Size("pduMessage".to_string(), total.inner() as usize - 6)),
139 "pduType" => U16::LE(pdu_type.unwrap_or(PDUType::PdutypeDemandactivepdu) as u16),
140 "PDUSource" => Some(U16::LE(pdu_source.unwrap_or(0))),
141 "pduMessage" => default_message
142 ]
143}
144
145#[derive(Debug, TryFromPrimitive, Copy, Clone, Eq, PartialEq)]
146#[repr(u8)]
147enum PDUType2 {
148 Pdutype2Update = 0x02,
149 Pdutype2Control = 0x14,
150 Pdutype2Pointer = 0x1B,
151 Pdutype2Input = 0x1C,
152 Pdutype2Synchronize = 0x1F,
153 Pdutype2RefreshRect = 0x21,
154 Pdutype2PlaySound = 0x22,
155 Pdutype2SuppressOutput = 0x23,
156 Pdutype2ShutdownRequest = 0x24,
157 Pdutype2ShutdownDenied = 0x25,
158 Pdutype2SaveSessionInfo = 0x26,
159 Pdutype2Fontlist = 0x27,
160 Pdutype2Fontmap = 0x28,
161 Pdutype2SetKeyboardIndicators = 0x29,
162 Pdutype2BitmapcachePersistentList = 0x2B,
163 Pdutype2BitmapcacheErrorPdu = 0x2C,
164 Pdutype2SetKeyboardImeStatus = 0x2D,
165 Pdutype2OffscrcacheErrorPdu = 0x2E,
166 Pdutype2SetErrorInfoPdu = 0x2F,
167 Pdutype2DrawninegridErrorPdu = 0x30,
168 Pdutype2DrawgdiplusErrorPdu = 0x31,
169 Pdutype2ArcStatusPdu = 0x32,
170 Pdutype2StatusInfoPdu = 0x36,
171 Pdutype2MonitorLayoutPdu = 0x37,
172 Unknown
173}
174
175struct DataPDU {
177 pdu_type: PDUType2,
178 message: Component
179}
180
181impl DataPDU {
182 pub fn from_pdu(data_pdu: &PDU) -> RdpResult<DataPDU> {
186 let pdu_type = PDUType2::try_from(cast!(DataType::U8, data_pdu.message["pduType2"])?)?;
187 let mut result = match pdu_type {
188 PDUType2::Pdutype2Synchronize => ts_synchronize_pdu(None),
189 PDUType2::Pdutype2Control => ts_control_pdu(None),
190 PDUType2::Pdutype2Fontlist => ts_font_list_pdu(),
191 PDUType2::Pdutype2Fontmap => ts_font_map_pdu(),
192 PDUType2::Pdutype2SetErrorInfoPdu => ts_set_error_info_pdu(),
193 _ => return Err(Error::RdpError(RdpError::new(RdpErrorKind::NotImplemented, &format!("GLOBAL: Data PDU parsing not implemented {:?}", pdu_type))))
194 };
195 result.message.read(&mut Cursor::new(cast!(DataType::Slice, data_pdu.message["payload"])?))?;
196 Ok(result)
197 }
198}
199
200fn ts_synchronize_pdu(target_user: Option<u16>) -> DataPDU {
204 DataPDU {
205 pdu_type: PDUType2::Pdutype2Synchronize,
206 message: component![
207 "messageType" => Check::new(U16::LE(1)),
208 "targetUser" => Some(U16::LE(target_user.unwrap_or(0)))
209 ]
210 }
211}
212
213fn ts_font_list_pdu() -> DataPDU {
217 DataPDU {
218 pdu_type: PDUType2::Pdutype2Fontlist,
219 message: component![
220 "numberFonts" => U16::LE(0),
221 "totalNumFonts" => U16::LE(0),
222 "listFlags" => U16::LE(0x0003),
223 "entrySize" => U16::LE(0x0032)
224 ]
225 }
226}
227
228fn ts_set_error_info_pdu() -> DataPDU {
232 DataPDU {
233 pdu_type: PDUType2::Pdutype2SetErrorInfoPdu,
234 message: component![
235 "errorInfo" => U32::LE(0)
236 ]
237 }
238}
239
240#[repr(u16)]
241#[allow(dead_code)]
242enum Action {
243 CtrlactionRequestControl = 0x0001,
244 CtrlactionGrantedControl = 0x0002,
245 CtrlactionDetach = 0x0003,
246 CtrlactionCooperate = 0x0004
247}
248
249fn ts_control_pdu(action: Option<Action>) -> DataPDU {
253 DataPDU {
254 pdu_type: PDUType2::Pdutype2Control,
255 message: component![
256 "action" => U16::LE(action.unwrap_or(Action::CtrlactionCooperate) as u16),
257 "grantId" => U16::LE(0),
258 "controlId" => U32::LE(0)
259 ]
260 }
261}
262
263fn ts_font_map_pdu() -> DataPDU {
267 DataPDU {
268 pdu_type: PDUType2::Pdutype2Fontmap,
269 message: component![
270 "numberEntries" => U16::LE(0),
271 "totalNumEntries" => U16::LE(0),
272 "mapFlags" => U16::LE(0x0003),
273 "entrySize" => U16::LE(0x0004)
274 ]
275 }
276}
277
278fn ts_input_pdu_data(events: Option<Array<Component>>) -> DataPDU {
280 let default_events = events.unwrap_or(Array::new(|| ts_input_event(None, None)));
281 DataPDU {
282 pdu_type: PDUType2::Pdutype2Input,
283 message: component![
284 "numEvents" => U16::LE(default_events.inner().len() as u16),
285 "pad2Octets" => U16::LE(0),
286 "slowPathInputEvents" => default_events
287 ]
288 }
289}
290
291fn ts_input_event(message_type: Option<InputEventType>, data: Option<Vec<u8>>) -> Component {
293 component![
294 "eventTime" => U32::LE(0),
295 "messageType" => U16::LE(message_type.unwrap_or(InputEventType::InputEventMouse) as u16),
296 "slowPathInputData" => data.unwrap_or(vec![])
297 ]
298}
299
300#[repr(u16)]
304pub enum InputEventType {
305 InputEventSync = 0x0000,
306 InputEventUnused = 0x0002,
307 InputEventScancode = 0x0004,
308 InputEventUnicode = 0x0005,
309 InputEventMouse = 0x8001,
310 InputEventMousex = 0x8002
311}
312
313pub struct TSInputEvent {
315 event_type: InputEventType,
316 message: Component
317}
318
319#[repr(u16)]
323pub enum PointerFlag {
324 PtrflagsHwheel = 0x0400,
325 PtrflagsWheel = 0x0200,
326 PtrflagsWheelNegative = 0x0100,
327 WheelRotationMask = 0x01FF,
328 PtrflagsMove = 0x0800,
329 PtrflagsDown = 0x8000,
330 PtrflagsButton1 = 0x1000,
331 PtrflagsButton2 = 0x2000,
332 PtrflagsButton3 = 0x4000
333}
334
335pub fn ts_pointer_event(flags: Option<u16>, x: Option<u16>, y: Option<u16>) -> TSInputEvent {
339 TSInputEvent {
340 event_type: InputEventType::InputEventMouse,
341 message : component![
342 "pointerFlags" => U16::LE(flags.unwrap_or(0)),
343 "xPos" => U16::LE(x.unwrap_or(0)),
344 "yPos" => U16::LE(y.unwrap_or(0))
345 ]
346 }
347}
348
349#[repr(u16)]
350pub enum KeyboardFlag {
351 KbdflagsExtended = 0x0100,
352 KbdflagsDown = 0x4000,
353 KbdflagsRelease = 0x8000
354}
355
356pub fn ts_keyboard_event(flags: Option<u16>, key_code: Option<u16>) -> TSInputEvent {
359 TSInputEvent {
360 event_type: InputEventType::InputEventScancode,
361 message: component![
362 "keyboardFlags" => U16::LE(flags.unwrap_or(0)),
363 "keyCode" => U16::LE(key_code.unwrap_or(0)),
364 "pad2Octets" => U16::LE(0)
365 ]
366 }
367}
368
369fn ts_fp_update() -> Component {
373 component![
374 "updateHeader" => DynOption::new(0 as u8, |header| {
375 if (header >> 4) & 0x2 as u8 == 0 as u8 {
376 MessageOption::SkipField("compressionFlags".to_string())
377 }
378 else {
379 MessageOption::None
380 }
381 }),
382 "compressionFlags" => 0 as u8,
383 "size" => DynOption::new(U16::LE(0), | size | MessageOption::Size("updateData".to_string(), size.inner() as usize)),
384 "updateData" => Vec::<u8>::new()
385 ]
386}
387
388
389#[repr(u8)]
390#[derive(Debug, TryFromPrimitive, Copy, Clone, Eq, PartialEq)]
391enum FastPathUpdateType {
392 FastpathUpdatetypeOrders = 0x0,
393 FastpathUpdatetypeBitmap = 0x1,
394 FastpathUpdatetypePalette = 0x2,
395 FastpathUpdatetypeSynchronize = 0x3,
396 FastpathUpdatetypeSurfcmds = 0x4,
397 FastpathUpdatetypePtrNull = 0x5,
398 FastpathUpdatetypePtrDefault = 0x6,
399 FastpathUpdatetypePtrPosition = 0x8,
400 FastpathUpdatetypeColor = 0x9,
401 FastpathUpdatetypeCached = 0xA,
402 FastpathUpdatetypePointer = 0xB,
403 Unknown
404}
405
406struct FastPathUpdate{
407 fp_type: FastPathUpdateType,
408 message: Component
409}
410
411impl FastPathUpdate {
412 fn from_fp(fast_path: &Component) -> RdpResult<FastPathUpdate> {
414 let fp_update_type = FastPathUpdateType::try_from(cast!(DataType::U8, fast_path["updateHeader"])? & 0xf)?;
415 let mut result = match fp_update_type {
416 FastPathUpdateType::FastpathUpdatetypeBitmap => ts_fp_update_bitmap(),
417 FastPathUpdateType::FastpathUpdatetypeColor => ts_colorpointerattribute(),
418 FastPathUpdateType::FastpathUpdatetypeSynchronize => ts_fp_update_synchronize(),
419 FastPathUpdateType::FastpathUpdatetypePtrNull => ts_fp_systempointerhiddenattribute(),
420 _ => return Err(Error::RdpError(RdpError::new(RdpErrorKind::NotImplemented, &format!("GLOBAL: Fast Path parsing not implemented {:?}", fp_update_type))))
421 };
422 result.message.read(&mut Cursor::new(cast!(DataType::Slice, fast_path["updateData"])?))?;
423 Ok(result)
424 }
425}
426
427fn ts_cd_header() -> Component {
428 component![
429 "cbCompFirstRowSize" => Check::new(U16::LE(0)),
430 "cbCompMainBodySize" => U16::LE(0),
431 "cbScanWidth" => U16::LE(0),
432 "cbUncompressedSize" => U16::LE(0)
433 ]
434}
435
436#[repr(u16)]
437enum BitmapFlag {
438 BitmapCompression = 0x0001,
439 NoBitmapCompressionHdr = 0x0400,
440}
441
442fn ts_bitmap_data() -> Component {
443 component![
444 "destLeft" => U16::LE(0),
445 "destTop" => U16::LE(0),
446 "destRight" => U16::LE(0),
447 "destBottom" => U16::LE(0),
448 "width" => U16::LE(0),
449 "height" => U16::LE(0),
450 "bitsPerPixel" => U16::LE(0),
451 "flags" => DynOption::new(U16::LE(0), |flags| {
452 if flags.inner() & BitmapFlag::BitmapCompression as u16 == 0 || flags.inner() & BitmapFlag::NoBitmapCompressionHdr as u16 != 0 {
453 MessageOption::SkipField("bitmapComprHdr".to_string())
454 }
455 else {
456 MessageOption::None
457 }
458 }),
459 "bitmapLength" => DynOption::new(U16::LE(0), | length | MessageOption::Size("bitmapDataStream".to_string(), length.inner() as usize)),
460 "bitmapComprHdr" => DynOption::new(ts_cd_header(), |header| MessageOption::Size("bitmapDataStream".to_string(), cast!(DataType::U16, header["cbCompMainBodySize"]).unwrap() as usize)),
461 "bitmapDataStream" => Vec::<u8>::new()
462 ]
463}
464
465fn ts_fp_update_bitmap() -> FastPathUpdate {
467 FastPathUpdate {
468 fp_type: FastPathUpdateType::FastpathUpdatetypeBitmap,
469 message: component![
470 "header" => Check::new(U16::LE(FastPathUpdateType::FastpathUpdatetypeBitmap as u16)),
471 "numberRectangles" => U16::LE(0),
472 "rectangles" => Array::new(|| ts_bitmap_data())
473 ]
474 }
475}
476
477fn ts_colorpointerattribute() -> FastPathUpdate {
481 FastPathUpdate {
482 fp_type: FastPathUpdateType::FastpathUpdatetypeColor,
483 message: component![
484 "cacheIndex " => U16::LE(0),
485 "hotSpot " => U32::LE(0),
486 "width" => U16::LE(0),
487 "height" => U16::LE(0),
488 "lengthAndMask" => DynOption::new(U16::LE(0), |length| MessageOption::Size("andMaskData".to_string(), length.inner() as usize)),
489 "lengthXorMask" => DynOption::new(U16::LE(0), |length| MessageOption::Size("xorMaskData".to_string(), length.inner() as usize)),
490 "xorMaskData" => Vec::<u8>::new(),
491 "andMaskData" => Vec::<u8>::new(),
492 "pad" => Some(0 as u8)
493 ]
494 }
495}
496
497fn ts_fp_update_synchronize() -> FastPathUpdate {
501 FastPathUpdate {
502 fp_type: FastPathUpdateType::FastpathUpdatetypeSynchronize,
503 message: component![]
504 }
505}
506
507fn ts_fp_systempointerhiddenattribute() -> FastPathUpdate {
511 FastPathUpdate {
512 fp_type: FastPathUpdateType::FastpathUpdatetypePtrNull,
513 message: component![]
514 }
515}
516
517enum ClientState {
518 DemandActivePDU,
520 SynchronizePDU,
522 ControlCooperate,
524 ControlGranted,
526 FontMap,
528 Data
531}
532
533pub struct Client {
534 state: ClientState,
536 user_id: u16,
538 channel_id: u16,
541 width: u16,
543 height: u16,
545 layout: KeyboardLayout,
547 share_id: Option<u32>,
550 server_capabilities: Vec<Capability>,
552 name: String
554}
555
556impl Client {
557 pub fn new(user_id: u16, channel_id: u16, width: u16, height: u16, layout: KeyboardLayout, name: &str) -> Client {
575 Client {
576 state: ClientState::DemandActivePDU,
577 server_capabilities: Vec::new(),
578 share_id: None,
579 user_id,
580 channel_id,
581 width,
582 height,
583 layout,
584 name: String::from(name)
585 }
586 }
587
588 fn read_demand_active_pdu(&mut self, stream: &mut dyn Read) -> RdpResult<bool> {
594 let pdu = PDU::from_stream(stream)?;
595 if pdu.pdu_type == PDUType::PdutypeDemandactivepdu {
596 for capability_set in cast!(DataType::Trame, pdu.message["capabilitySets"])?.iter() {
597 match Capability::from_capability_set(cast!(DataType::Component, capability_set)?) {
598 Ok(capability) => self.server_capabilities.push(capability),
599 Err(e) => println!("GLOBAL: {:?}", e)
600 }
601 }
602 self.share_id = Some(cast!(DataType::U32, pdu.message["shareId"])?);
603 return Ok(true)
604 }
605 return Ok(false)
606 }
607
608 fn read_synchronize_pdu(&mut self, stream: &mut dyn Read) -> RdpResult<bool> {
613 let pdu = PDU::from_stream(stream)?;
614 if pdu.pdu_type != PDUType::PdutypeDatapdu {
615 return Ok(false)
616 }
617 if DataPDU::from_pdu(&pdu)?.pdu_type != PDUType2::Pdutype2Synchronize {
618 return Ok(false)
619 }
620 Ok(true)
621 }
622
623 fn read_control_pdu(&mut self, stream: &mut dyn Read, action: Action) -> RdpResult<bool> {
627 let pdu = PDU::from_stream(stream)?;
628 if pdu.pdu_type != PDUType::PdutypeDatapdu {
629 return Ok(false)
630 }
631
632 let data_pdu = DataPDU::from_pdu(&pdu)?;
633 if data_pdu.pdu_type != PDUType2::Pdutype2Control {
634 return Ok(false)
635 }
636
637 if cast!(DataType::U16, data_pdu.message["action"])? != action as u16 {
638 return Err(Error::RdpError(RdpError::new(RdpErrorKind::UnexpectedType, "GLOBAL: bad message type")))
639 }
640
641 Ok(true)
642 }
643
644 fn read_font_map_pdu(&mut self, stream: &mut dyn Read) -> RdpResult<bool> {
648 let pdu = PDU::from_stream(stream)?;
649 if pdu.pdu_type != PDUType::PdutypeDatapdu {
650 return Ok(false)
651 }
652 if DataPDU::from_pdu(&pdu)?.pdu_type != PDUType2::Pdutype2Fontmap {
653 return Ok(false)
654 }
655 Ok(true)
656 }
657
658 fn read_data_pdu(&mut self, stream: &mut dyn Read) -> RdpResult<()> {
662 let mut message = Array::new(|| share_control_header(None, None, None));
664 message.read(stream)?;
665
666 for pdu in message.inner() {
667 let pdu = PDU::from_control(cast!(DataType::Component, pdu)?)?;
668
669 if pdu.pdu_type == PDUType::PdutypeDeactivateallpdu {
671 println!("GLOBAL: deactive/reactive sequence initiated");
672 self.state = ClientState::DemandActivePDU;
673 continue;
674 }
675 if pdu.pdu_type != PDUType::PdutypeDatapdu {
676 println!("GLOBAL: Ignore PDU {:?}", pdu.pdu_type);
677 continue;
678 }
679
680 match DataPDU::from_pdu(&pdu) {
681 Ok(data_pdu) => {
682 match data_pdu.pdu_type {
683 PDUType2::Pdutype2SetErrorInfoPdu => println!("GLOBAL: Receive error PDU from server {:?}", cast!(DataType::U32, data_pdu.message["errorInfo"])?),
684 _ => println!("GLOBAL: Data PDU not handle {:?}", data_pdu.pdu_type)
685 }
686 },
687 Err(e) => println!("GLOBAL: Parsing data PDU error {:?}", e)
688 };
689 }
690 Ok(())
691 }
692
693 fn read_fast_path<T>(&mut self, stream: &mut dyn Read, mut callback: T) -> RdpResult<()>
697 where T: FnMut(RdpEvent) {
698 let mut fp_messages = Array::new(|| ts_fp_update());
700 fp_messages.read(stream)?;
701
702 for fp_message in fp_messages.inner().iter() {
703 match FastPathUpdate::from_fp(cast!(DataType::Component, fp_message)?) {
704 Ok(order) => {
705 match order.fp_type {
706 FastPathUpdateType::FastpathUpdatetypeBitmap => {
707 for rectangle in cast!(DataType::Trame, order.message["rectangles"])? {
708 let bitmap = cast!(DataType::Component, rectangle)?;
709 callback(RdpEvent::Bitmap(
710 BitmapEvent {
711 dest_left: cast!(DataType::U16, bitmap["destLeft"])?,
712 dest_top: cast!(DataType::U16, bitmap["destTop"])?,
713 dest_right: cast!(DataType::U16, bitmap["destRight"])?,
714 dest_bottom: cast!(DataType::U16, bitmap["destBottom"])?,
715 width: cast!(DataType::U16, bitmap["width"])?,
716 height: cast!(DataType::U16, bitmap["height"])?,
717 bpp: cast!(DataType::U16, bitmap["bitsPerPixel"])?,
718 is_compress: cast!(DataType::U16, bitmap["flags"])? & BitmapFlag::BitmapCompression as u16 != 0,
719 data: cast!(DataType::Slice, bitmap["bitmapDataStream"])?.to_vec()
720 }
721 ));
722 }
723 },
724 FastPathUpdateType::FastpathUpdatetypeColor | FastPathUpdateType::FastpathUpdatetypePtrNull | FastPathUpdateType::FastpathUpdatetypeSynchronize => (),
726 _ => println!("GLOBAL: Fast Path order not handled {:?}", order.fp_type)
727 }
728 },
729 Err(e) => println!("GLOBAL: Unknown Fast Path order {:?}", e)
730 };
731 }
732
733 Ok(())
734 }
735
736 fn write_confirm_active_pdu<S: Read + Write>(&mut self, mcs: &mut mcs::Client<S>) -> RdpResult<()> {
739 let pdu = ts_confirm_active_pdu(self.share_id, Some(self.name.as_bytes().to_vec()), Some(Array::from_trame(
740 trame![
741 capability_set(Some(capability::ts_general_capability_set(Some(capability::GeneralExtraFlag::LongCredentialsSupported as u16 | capability::GeneralExtraFlag::NoBitmapCompressionHdr as u16 | capability::GeneralExtraFlag::EncSaltedChecksum as u16 | capability::GeneralExtraFlag::FastpathOutputSupported as u16)))),
742 capability_set(Some(capability::ts_bitmap_capability_set(Some(0x0018), Some(self.width), Some(self.height)))),
743 capability_set(Some(capability::ts_order_capability_set(Some(capability::OrderFlag::NEGOTIATEORDERSUPPORT as u16 | capability::OrderFlag::ZEROBOUNDSDELTASSUPPORT as u16)))),
744 capability_set(Some(capability::ts_bitmap_cache_capability_set())),
745 capability_set(Some(capability::ts_pointer_capability_set())),
746 capability_set(Some(capability::ts_sound_capability_set())),
747 capability_set(Some(capability::ts_input_capability_set(Some(capability::InputFlags::InputFlagScancodes as u16 | capability::InputFlags::InputFlagMousex as u16 | capability::InputFlags::InputFlagUnicode as u16), Some(self.layout)))),
748 capability_set(Some(capability::ts_brush_capability_set())),
749 capability_set(Some(capability::ts_glyph_capability_set())),
750 capability_set(Some(capability::ts_offscreen_capability_set())),
751 capability_set(Some(capability::ts_virtualchannel_capability_set())),
752 capability_set(Some(capability::ts_multifragment_update_capability_ts()))
753 ]
754 )));
755 self.write_pdu(pdu, mcs)
756 }
757
758 fn write_client_finalize<S: Read + Write>(&self, mcs: &mut mcs::Client<S>) -> RdpResult<()> {
761 self.write_data_pdu(ts_synchronize_pdu(Some(self.channel_id)), mcs)?;
762 self.write_data_pdu(ts_control_pdu(Some(Action::CtrlactionCooperate)), mcs)?;
763 self.write_data_pdu(ts_control_pdu(Some(Action::CtrlactionRequestControl)), mcs)?;
764 self.write_data_pdu(ts_font_list_pdu(), mcs)
765 }
766
767 fn write_pdu<S: Read + Write>(&self, message: PDU, mcs: &mut mcs::Client<S>) -> RdpResult<()> {
769 mcs.write(&"global".to_string(), share_control_header(Some(message.pdu_type), Some(self.user_id), Some(to_vec(&message.message))))
770 }
771
772 fn write_data_pdu<S: Read + Write>(&self, message: DataPDU, mcs: &mut mcs::Client<S>) -> RdpResult<()> {
774 self.write_pdu(share_data_header(self.share_id, Some(message.pdu_type), Some(to_vec(&message.message))), mcs)
775 }
776
777 pub fn write_input_event<S: Read + Write>(&self, event: TSInputEvent, mcs: &mut mcs::Client<S>) -> RdpResult<()> {
801 self.write_data_pdu(ts_input_pdu_data(Some(Array::from_trame(trame![ts_input_event(Some(event.event_type), Some(to_vec(&event.message)))]))), mcs)
802 }
803
804 pub fn read<S: Read + Write, T>(&mut self, payload: tpkt::Payload, mcs: &mut mcs::Client<S>, callback: T) -> RdpResult<()>
820 where T: FnMut(RdpEvent){
821 match self.state {
822 ClientState::DemandActivePDU => {
823 if self.read_demand_active_pdu(&mut try_let!(tpkt::Payload::Raw, payload)?)? {
824 self.write_confirm_active_pdu(mcs)?;
825 self.write_client_finalize(mcs)?;
826 self.state = ClientState::SynchronizePDU;
828 }
829 Ok(())
830 }
831 ClientState::SynchronizePDU => {
832 if self.read_synchronize_pdu(&mut try_let!(tpkt::Payload::Raw, payload)?)? {
833 self.state = ClientState::ControlCooperate;
835 }
836 Ok(())
837 },
838 ClientState::ControlCooperate => {
839 if self.read_control_pdu(&mut try_let!(tpkt::Payload::Raw, payload)?, Action::CtrlactionCooperate)? {
840 self.state = ClientState::ControlGranted;
842 }
843 Ok(())
844 },
845 ClientState::ControlGranted => {
846 if self.read_control_pdu(&mut try_let!(tpkt::Payload::Raw, payload)?, Action::CtrlactionGrantedControl)? {
847 self.state = ClientState::FontMap;
849 }
850 Ok(())
851 },
852 ClientState::FontMap => {
853 if self.read_font_map_pdu(&mut try_let!(tpkt::Payload::Raw, payload)?)? {
854 self.state = ClientState::Data;
856 }
857 Ok(())
858 },
859 ClientState::Data => {
860 match payload {
862 tpkt::Payload::Raw(mut stream) => self.read_data_pdu(&mut stream),
863 tpkt::Payload::FastPath(_sec_flag, mut stream) => self.read_fast_path(&mut stream, callback)
864 }
865 }
866 }
867 }
868}
869
870#[cfg(test)]
871mod test {
872 use super::*;
873
874 #[test]
876 fn test_demand_active_pdu() {
877 let mut stream = Cursor::new(vec![234, 3, 1, 0, 4, 0, 179, 1, 82, 68, 80, 0, 17, 0, 0, 0, 9, 0, 8, 0, 234, 3, 0, 0, 1, 0, 24, 0, 1, 0, 3, 0, 0, 2, 0, 0, 0, 0, 29, 4, 0, 0, 0, 0, 0, 0, 1, 1, 20, 0, 12, 0, 2, 0, 0, 0, 64, 6, 0, 0, 10, 0, 8, 0, 6, 0, 0, 0, 8, 0, 10, 0, 1, 0, 25, 0, 25, 0, 27, 0, 6, 0, 3, 0, 14, 0, 8, 0, 1, 0, 0, 0, 2, 0, 28, 0, 32, 0, 1, 0, 1, 0, 1, 0, 32, 3, 88, 2, 0, 0, 1, 0, 1, 0, 0, 30, 1, 0, 0, 0, 29, 0, 96, 0, 4, 185, 27, 141, 202, 15, 0, 79, 21, 88, 159, 174, 45, 26, 135, 226, 214, 0, 3, 0, 1, 1, 3, 18, 47, 119, 118, 114, 189, 99, 68, 175, 179, 183, 60, 156, 111, 120, 134, 0, 4, 0, 0, 0, 0, 0, 166, 81, 67, 156, 53, 53, 174, 66, 145, 12, 205, 252, 229, 118, 11, 88, 0, 4, 0, 0, 0, 0, 0, 212, 204, 68, 39, 138, 157, 116, 78, 128, 60, 14, 203, 238, 161, 156, 84, 0, 4, 0, 0, 0, 0, 0, 3, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 66, 15, 0, 1, 0, 20, 0, 0, 0, 1, 0, 0, 0, 170, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 161, 6, 6, 0, 64, 66, 15, 0, 64, 66, 15, 0, 1, 0, 0, 0, 0, 0, 0, 0, 18, 0, 8, 0, 1, 0, 0, 0, 13, 0, 88, 0, 117, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 8, 0, 255, 0, 0, 0, 24, 0, 11, 0, 2, 0, 0, 0, 3, 12, 0, 26, 0, 8, 0, 43, 72, 9, 0, 28, 0, 12, 0, 82, 0, 0, 0, 0, 0, 0, 0, 30, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
878 let mut pdu = ts_demand_active_pdu();
879 pdu.message.read(&mut stream).unwrap();
880 assert_eq!(cast!(DataType::U16, pdu.message["numberCapabilities"]).unwrap(), 17)
881 }
882
883 #[test]
885 fn test_confirm_active_pdu() {
886 let mut stream = Cursor::new(vec![]);
887 ts_confirm_active_pdu(Some(4), Some(b"rdp-rs".to_vec()), Some(Array::from_trame(trame![capability_set(Some(capability::ts_brush_capability_set()))]))).message.write(&mut stream).unwrap();
888 assert_eq!(stream.into_inner(), [4, 0, 0, 0, 234, 3, 6, 0, 12, 0, 114, 100, 112, 45, 114, 115, 1, 0, 0, 0, 15, 0, 8, 0, 0, 0, 0, 0]);
889 }
890
891 #[test]
892 fn test_share_control_header() {
893 let mut stream = Cursor::new(vec![]);
894 share_control_header(Some(PDUType::PdutypeConfirmactivepdu), Some(12), Some(to_vec(&ts_confirm_active_pdu(Some(4), Some(b"rdp-rs".to_vec()), Some(Array::from_trame(trame![capability_set(Some(capability::ts_brush_capability_set()))]))).message))).write(&mut stream).unwrap();
895
896 assert_eq!(stream.into_inner(), vec![34, 0, 19, 0, 12, 0, 4, 0, 0, 0, 234, 3, 6, 0, 12, 0, 114, 100, 112, 45, 114, 115, 1, 0, 0, 0, 15, 0, 8, 0, 0, 0, 0, 0])
897 }
898
899 #[test]
900 fn test_read_synchronize_pdu() {
901 let mut stream = Cursor::new(vec![22, 0, 23, 0, 234, 3, 234, 3, 1, 0, 0, 2, 22, 0, 31, 0, 0, 0, 1, 0, 0, 0]);
902 let mut global = Client::new(0,0, 800, 600, KeyboardLayout::US, "foo");
903 assert!(global.read_synchronize_pdu(&mut stream).unwrap())
904 }
905
906 #[test]
907 fn test_read_control_cooperate_pdu() {
908 let mut stream = Cursor::new(vec![26, 0, 23, 0, 234, 3, 234, 3, 1, 0, 0, 2, 26, 0, 20, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0]);
909 let mut global = Client::new(0,0, 800, 600, KeyboardLayout::US, "foo");
910 assert!(global.read_control_pdu(&mut stream, Action::CtrlactionCooperate).unwrap())
911 }
912
913 #[test]
914 fn test_read_control_granted_pdu() {
915 let mut stream = Cursor::new(vec![26, 0, 23, 0, 234, 3, 234, 3, 1, 0, 0, 2, 26, 0, 20, 0, 0, 0, 2, 0, 236, 3, 234, 3, 0, 0]);
916 let mut global = Client::new(0,0, 800, 600, KeyboardLayout::US, "foo");
917 assert!(global.read_control_pdu(&mut stream, Action::CtrlactionGrantedControl).unwrap())
918 }
919
920 #[test]
921 fn test_read_font_map_pdu() {
922 let mut stream = Cursor::new(vec![26, 0, 23, 0, 234, 3, 234, 3, 1, 0, 0, 2, 26, 0, 40, 0, 0, 0, 0, 0, 0, 0, 3, 0, 4, 0]);
923 let mut global = Client::new(0,0, 800, 600, KeyboardLayout::US, "foo");
924 assert!(global.read_font_map_pdu(&mut stream).unwrap())
925 }
926}