ironrdp_pdu/rdp/
vc.rs

1pub mod dvc;
2
3#[cfg(test)]
4mod tests;
5
6use std::{io, str};
7
8use bitflags::bitflags;
9use ironrdp_core::{ensure_fixed_part_size, Decode, DecodeResult, Encode, EncodeResult, ReadCursor, WriteCursor};
10use thiserror::Error;
11
12use crate::PduError;
13
14const CHANNEL_PDU_HEADER_SIZE: usize = 8;
15
16/// Channel PDU Header (CHANNEL_PDU_HEADER)
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct ChannelPduHeader {
19    /// The total length in bytes of the uncompressed channel data, excluding this header
20    ///
21    /// The data can span multiple Virtual Channel PDUs and the individual chunks will need to be
22    /// reassembled in that case (section 3.1.5.2.2 of MS-RDPBCGR).
23    pub length: u32,
24    pub flags: ChannelControlFlags,
25}
26
27impl ChannelPduHeader {
28    const NAME: &'static str = "ChannelPduHeader";
29
30    const FIXED_PART_SIZE: usize = CHANNEL_PDU_HEADER_SIZE;
31}
32
33impl Encode for ChannelPduHeader {
34    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
35        ensure_fixed_part_size!(in: dst);
36
37        dst.write_u32(self.length);
38        dst.write_u32(self.flags.bits());
39        Ok(())
40    }
41
42    fn name(&self) -> &'static str {
43        Self::NAME
44    }
45
46    fn size(&self) -> usize {
47        Self::FIXED_PART_SIZE
48    }
49}
50
51impl<'de> Decode<'de> for ChannelPduHeader {
52    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
53        ensure_fixed_part_size!(in: src);
54
55        let total_length = src.read_u32();
56        let flags = ChannelControlFlags::from_bits_truncate(src.read_u32());
57        Ok(Self {
58            length: total_length,
59            flags,
60        })
61    }
62}
63
64bitflags! {
65    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
66    pub struct ChannelControlFlags: u32 {
67        const FLAG_FIRST = 0x0000_0001;
68        const FLAG_LAST = 0x0000_0002;
69        const FLAG_SHOW_PROTOCOL = 0x0000_0010;
70        const FLAG_SUSPEND = 0x0000_0020;
71        const FLAG_RESUME  = 0x0000_0040;
72        const FLAG_SHADOW_PERSISTENT = 0x0000_0080;
73        const PACKET_COMPRESSED = 0x0020_0000;
74        const PACKET_AT_FRONT = 0x0040_0000;
75        const PACKET_FLUSHED = 0x0080_0000;
76        const COMPRESSION_TYPE_MASK = 0x000F_0000;
77    }
78}
79
80#[derive(Debug, Error)]
81pub enum ChannelError {
82    #[error("IO error")]
83    IOError(#[from] io::Error),
84    #[error("from UTF-8 error")]
85    FromUtf8Error(#[from] std::string::FromUtf8Error),
86    #[error("invalid channel PDU header")]
87    InvalidChannelPduHeader,
88    #[error("invalid channel total data length")]
89    InvalidChannelTotalDataLength,
90    #[error("invalid DVC PDU type")]
91    InvalidDvcPduType,
92    #[error("invalid DVC id length value")]
93    InvalidDVChannelIdLength,
94    #[error("invalid DVC data length value")]
95    InvalidDvcDataLength,
96    #[error("invalid DVC capabilities version")]
97    InvalidDvcCapabilitiesVersion,
98    #[error("invalid DVC message size")]
99    InvalidDvcMessageSize,
100    #[error("invalid DVC total message size: actual ({actual}) > expected ({expected})")]
101    InvalidDvcTotalMessageSize { actual: usize, expected: usize },
102    #[error("PDU error: {0}")]
103    Pdu(PduError),
104}
105
106impl From<PduError> for ChannelError {
107    fn from(e: PduError) -> Self {
108        Self::Pdu(e)
109    }
110}
111
112impl From<ChannelError> for io::Error {
113    fn from(e: ChannelError) -> io::Error {
114        io::Error::other(format!("Virtual channel error: {e}"))
115    }
116}