ironrdp_pdu/gcc/
cluster_data.rs1use std::io;
2
3use bitflags::bitflags;
4use ironrdp_core::{
5 ensure_fixed_part_size, invalid_field_err, Decode, DecodeResult, Encode, EncodeResult, ReadCursor, WriteCursor,
6};
7use num_derive::{FromPrimitive, ToPrimitive};
8use num_traits::{FromPrimitive as _, ToPrimitive as _};
9use thiserror::Error;
10
11const REDIRECTION_VERSION_MASK: u32 = 0x0000_003C;
12
13const FLAGS_SIZE: usize = 4;
14const REDIRECTED_SESSION_ID_SIZE: usize = 4;
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct ClientClusterData {
18 pub flags: RedirectionFlags,
19 pub redirection_version: RedirectionVersion,
20 pub redirected_session_id: u32,
21}
22
23impl ClientClusterData {
24 const NAME: &'static str = "ClientClusterData";
25
26 const FIXED_PART_SIZE: usize = FLAGS_SIZE + REDIRECTED_SESSION_ID_SIZE;
27}
28
29impl Encode for ClientClusterData {
30 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
31 ensure_fixed_part_size!(in: dst);
32
33 let flags_with_version = self.flags.bits() | (self.redirection_version.to_u32().unwrap() << 2);
34
35 dst.write_u32(flags_with_version);
36 dst.write_u32(self.redirected_session_id);
37
38 Ok(())
39 }
40
41 fn name(&self) -> &'static str {
42 Self::NAME
43 }
44
45 fn size(&self) -> usize {
46 Self::FIXED_PART_SIZE
47 }
48}
49
50impl<'de> Decode<'de> for ClientClusterData {
51 fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
52 ensure_fixed_part_size!(in: src);
53
54 let flags_with_version = src.read_u32();
55 let redirected_session_id = src.read_u32();
56
57 let flags = RedirectionFlags::from_bits(flags_with_version & !REDIRECTION_VERSION_MASK)
58 .ok_or_else(|| invalid_field_err!("flags", "invalid redirection flags"))?;
59 let redirection_version =
60 RedirectionVersion::from_u8(((flags_with_version & REDIRECTION_VERSION_MASK) >> 2) as u8)
61 .ok_or_else(|| invalid_field_err!("redirVersion", "invalid redirection version"))?;
62
63 Ok(Self {
64 flags,
65 redirection_version,
66 redirected_session_id,
67 })
68 }
69}
70
71bitflags! {
72 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
73 pub struct RedirectionFlags: u32 {
74 const REDIRECTION_SUPPORTED = 0x0000_0001;
75 const REDIRECTED_SESSION_FIELD_VALID = 0x0000_0002;
76 const REDIRECTED_SMARTCARD = 0x0000_0040;
77 }
78}
79
80#[derive(Debug, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
81pub enum RedirectionVersion {
82 V1 = 0,
83 V2 = 1,
84 V3 = 2,
85 V4 = 3,
86 V5 = 4,
87 V6 = 5,
88}
89
90#[derive(Debug, Error)]
91pub enum ClusterDataError {
92 #[error("IO error")]
93 IOError(#[from] io::Error),
94 #[error("invalid redirection flags field")]
95 InvalidRedirectionFlags,
96}