ironrdp_pdu/rdp/capability_sets/
virtual_channel.rs

1#[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/// The VirtualChannel structure is used to advertise virtual channel support characteristics. This capability is sent by both client and server.
22///
23/// # Fields
24///
25/// * `flags` - virtual channel compression flags
26/// * `chunk_size` - when sent from server to client, this field contains the maximum allowed size of a virtual channel chunk and MUST be greater than or equal to 1600 and less than or equal to 16256.
27///   When sent from client to server, the value in this field is ignored by the server. This value is not verified in IronRDP and MUST be verified on the caller's side
28///
29/// # MSDN
30///
31/// * [Virtual Channel Capability Set](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/a8593178-80c0-4b80-876c-cb77e62cecfc)
32#[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}