ironrdp_pdu/rdp/capability_sets/
virtual_channel.rs1#[cfg(test)]
2mod tests;
3
4use bitflags::bitflags;
5use ironrdp_core::{
6 ensure_fixed_part_size, ensure_size, Decode, DecodeResult, Encode, EncodeResult, ReadCursor, WriteCursor,
7};
8
9const FLAGS_FIELD_SIZE: usize = 4;
10const CHUNK_SIZE_FIELD_SIZE: usize = 4;
11
12bitflags! {
13 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14 pub struct VirtualChannelFlags: u32 {
15 const NO_COMPRESSION = 0;
16 const COMPRESSION_SERVER_TO_CLIENT = 1;
17 const COMPRESSION_CLIENT_TO_SERVER_8K = 2;
18 }
19}
20
21#[derive(Debug, PartialEq, Eq, Clone)]
33pub struct VirtualChannel {
34 pub flags: VirtualChannelFlags,
35 pub chunk_size: Option<u32>,
36}
37
38impl VirtualChannel {
39 const NAME: &'static str = "VirtualChannel";
40
41 const FIXED_PART_SIZE: usize = FLAGS_FIELD_SIZE;
42}
43
44impl Encode for VirtualChannel {
45 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
46 ensure_size!(in: dst, size: self.size());
47
48 dst.write_u32(self.flags.bits());
49
50 if let Some(value) = self.chunk_size {
51 dst.write_u32(value);
52 }
53
54 Ok(())
55 }
56
57 fn name(&self) -> &'static str {
58 Self::NAME
59 }
60
61 fn size(&self) -> usize {
62 Self::FIXED_PART_SIZE + self.chunk_size.map(|_| CHUNK_SIZE_FIELD_SIZE).unwrap_or(0)
63 }
64}
65
66macro_rules! try_or_return {
67 ($expr:expr, $ret:expr) => {
68 match $expr {
69 Ok(v) => v,
70 Err(_) => return Ok($ret),
71 }
72 };
73}
74
75impl<'de> Decode<'de> for VirtualChannel {
76 fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
77 ensure_fixed_part_size!(in: src);
78
79 let flags = VirtualChannelFlags::from_bits_truncate(src.read_u32());
80
81 let mut virtual_channel_pdu = Self {
82 flags,
83 chunk_size: None,
84 };
85
86 virtual_channel_pdu.chunk_size = Some(try_or_return!(src.try_read_u32(), virtual_channel_pdu));
87
88 Ok(virtual_channel_pdu)
89 }
90}