Skip to content

Commit

Permalink
feat: add support for dydynvc (#419)
Browse files Browse the repository at this point in the history
  • Loading branch information
Isaiah Becker-Mayer authored Mar 29, 2024
1 parent a1d8bb2 commit 1e53669
Show file tree
Hide file tree
Showing 60 changed files with 1,741 additions and 2,806 deletions.
8 changes: 7 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,22 @@ ironrdp-tls = { version = "0.1", path = "crates/ironrdp-tls" }
ironrdp-tokio = { version = "0.1", path = "crates/ironrdp-tokio" }
ironrdp = { version = "0.5", path = "crates/ironrdp" }

bitflags = "2.4"
expect-test = "1"
png = "0.17"
proptest = "1.4"
rstest = "0.18"
sspi = "0.11"
tracing = { version = "0.1", features = ["log"] }
thiserror = "1.0"
png = "0.17"
bitflags = "2.4"

# Note: we are trying to move away from using these crates.
# They are being kept around for now for legacy compatibility,
# but new usage should be avoided.
byteorder = "1.5"
lazy_static = "1.4" # prefer https://doc.rust-lang.org/std/sync/struct.OnceLock.html
num-derive = "0.4"
num-traits = "0.2"

[profile.dev]
opt-level = 1
Expand Down
5 changes: 3 additions & 2 deletions crates/ironrdp-ainput/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ doctest = false
test = false

[dependencies]
ironrdp-dvc.workspace = true
ironrdp-pdu.workspace = true
bitflags.workspace = true

num-derive = "0.4"
num-traits = "0.2"
num-derive.workspace = true # TODO: remove
num-traits.workspace = true # TODO: remove
3 changes: 3 additions & 0 deletions crates/ironrdp-ainput/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use bitflags::bitflags;
use ironrdp_dvc::DvcPduEncode;
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive as _, ToPrimitive as _};

Expand Down Expand Up @@ -136,6 +137,8 @@ impl PduEncode for ServerPdu {
}
}

impl DvcPduEncode for ServerPdu {}

impl<'de> PduDecode<'de> for ServerPdu {
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
ensure_fixed_part_size!(in: src);
Expand Down
4 changes: 2 additions & 2 deletions crates/ironrdp-client/src/rdp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ async fn connect(

let mut connector = connector::ClientConnector::new(config.connector.clone())
.with_server_addr(server_addr)
// .with_static_channel(ironrdp::dvc::DrdynvcClient::new()) // FIXME(#61): drdynvc is not working
.with_static_channel(ironrdp::dvc::DrdynvcClient::new())
.with_static_channel(rdpsnd::Rdpsnd::new())
.with_static_channel(rdpdr::Rdpdr::new(Box::new(NoopRdpdrBackend {}), "IronRDP".to_owned()).with_smartcard(0));

Expand Down Expand Up @@ -160,7 +160,7 @@ async fn active_session(
connection_result.desktop_size.height,
);

let mut active_stage = ActiveStage::new(connection_result, None);
let mut active_stage = ActiveStage::new(connection_result);

let disconnect_reason = 'outer: loop {
let outputs = tokio::select! {
Expand Down
4 changes: 2 additions & 2 deletions crates/ironrdp-cliprdr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ impl<R: Role> Cliprdr<R> {
/// implementation when user performs OS-specific copy command (e.g. `Ctrl+C` shortcut on
/// keyboard)
pub fn initiate_copy(&self, available_formats: &[ClipboardFormat]) -> PduResult<CliprdrSvcMessages<R>> {
let mut pdus = vec![];
let mut pdus = Vec::new();

match (self.state, R::is_server()) {
// When user initiates copy, we should send format list to server.
Expand Down Expand Up @@ -275,7 +275,7 @@ impl<R: Role> SvcProcessor for Cliprdr<R> {
if R::is_server() {
Ok(vec![self.capabilities()?, self.monitor_ready()?])
} else {
Ok(vec![])
Ok(Vec::new())
}
}

Expand Down
3 changes: 3 additions & 0 deletions crates/ironrdp-cliprdr/src/pdu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub use self::lock::*;
use bitflags::bitflags;
use ironrdp_pdu::cursor::{ReadCursor, WriteCursor};
use ironrdp_pdu::{ensure_fixed_part_size, invalid_message_err, PduDecode, PduEncode, PduResult};
use ironrdp_svc::SvcPduEncode;

const MSG_TYPE_MONITOR_READY: u16 = 0x0001;
const MSG_TYPE_FORMAT_LIST: u16 = 0x0002;
Expand Down Expand Up @@ -215,6 +216,8 @@ impl PduEncode for ClipboardPdu<'_> {
}
}

impl SvcPduEncode for ClipboardPdu<'_> {}

impl<'de> PduDecode<'de> for ClipboardPdu<'de> {
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
ensure_fixed_part_size!(in: src);
Expand Down
5 changes: 4 additions & 1 deletion crates/ironrdp-displaycontrol/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@ keywords.workspace = true
categories.workspace = true

[dependencies]
ironrdp-pdu.workspace = true
ironrdp-dvc.workspace = true
ironrdp-pdu.workspace = true
ironrdp-svc.workspace = true
tracing.workspace = true
50 changes: 50 additions & 0 deletions crates/ironrdp-displaycontrol/src/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use crate::{
pdu::{DisplayControlMonitorLayout, DisplayControlPdu, MonitorLayoutEntry},
CHANNEL_NAME,
};
use ironrdp_dvc::{encode_dvc_messages, DvcClientProcessor, DvcMessage, DvcProcessor};
use ironrdp_pdu::PduResult;
use ironrdp_svc::{impl_as_any, ChannelFlags, SvcMessage};
use tracing::debug;

/// A client for the Display Control Virtual Channel.
pub struct DisplayControlClient {}

impl_as_any!(DisplayControlClient);

impl DvcProcessor for DisplayControlClient {
fn channel_name(&self) -> &str {
CHANNEL_NAME
}

fn start(&mut self, _channel_id: u32) -> PduResult<Vec<DvcMessage>> {
Ok(Vec::new())
}

fn process(&mut self, _channel_id: u32, payload: &[u8]) -> PduResult<Vec<DvcMessage>> {
// TODO: We can parse the payload here for completeness sake,
// in practice we don't need to do anything with the payload.
debug!("Got Display PDU of length: {}", payload.len());
Ok(Vec::new())
}
}

impl DvcClientProcessor for DisplayControlClient {}

impl DisplayControlClient {
pub fn new() -> Self {
Self {}
}

/// Fully encodes a [`MonitorLayoutPdu`] with the given monitors.
pub fn encode_monitors(&self, channel_id: u32, monitors: Vec<MonitorLayoutEntry>) -> PduResult<Vec<SvcMessage>> {
let pdu: DisplayControlPdu = DisplayControlMonitorLayout::new(&monitors)?.into();
encode_dvc_messages(channel_id, vec![Box::new(pdu)], ChannelFlags::empty())
}
}

impl Default for DisplayControlClient {
fn default() -> Self {
Self::new()
}
}
4 changes: 4 additions & 0 deletions crates/ironrdp-displaycontrol/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#![doc = include_str!("../README.md")]

pub const CHANNEL_NAME: &str = "Microsoft::Windows::RDS::DisplayControl";

pub mod client;
pub mod pdu;
pub mod server;
26 changes: 26 additions & 0 deletions crates/ironrdp-displaycontrol/src/pdu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//!
//! [1]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpedisp/d2954508-f487-48bc-8731-39743e0854a9
use ironrdp_dvc::DvcPduEncode;
use ironrdp_pdu::cursor::{ReadCursor, WriteCursor};
use ironrdp_pdu::{ensure_fixed_part_size, invalid_message_err, PduDecode, PduEncode, PduResult};

Expand Down Expand Up @@ -73,6 +74,8 @@ impl PduEncode for DisplayControlPdu {
}
}

impl DvcPduEncode for DisplayControlPdu {}

impl<'de> PduDecode<'de> for DisplayControlPdu {
fn decode(src: &mut ReadCursor<'de>) -> PduResult<Self> {
ensure_fixed_part_size!(in: src);
Expand All @@ -99,12 +102,28 @@ impl<'de> PduDecode<'de> for DisplayControlPdu {
}
}

impl From<DisplayControlCapabilities> for DisplayControlPdu {
fn from(caps: DisplayControlCapabilities) -> Self {
Self::Caps(caps)
}
}

impl From<DisplayControlMonitorLayout> for DisplayControlPdu {
fn from(layout: DisplayControlMonitorLayout) -> Self {
Self::MonitorLayout(layout)
}
}

/// 2.2.2.1 DISPLAYCONTROL_CAPS_PDU
///
/// Display control channel capabilities PDU.
///
/// INVARIANTS:
/// 0 <= max_num_monitors <= MAX_SUPPORTED_MONITORS
/// 0 <= max_monitor_area_factor_a <= MAX_MONITOR_AREA_FACTOR
/// 0 <= max_monitor_area_factor_b <= MAX_MONITOR_AREA_FACTOR
///
/// [2.2.2.1]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpedisp/8989a211-984e-4ecc-80f3-60694fc4b476
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DisplayControlCapabilities {
max_num_monitors: u32,
Expand Down Expand Up @@ -179,10 +198,14 @@ impl<'de> PduDecode<'de> for DisplayControlCapabilities {
}
}

/// [2.2.2.2] DISPLAYCONTROL_MONITOR_LAYOUT_PDU
///
/// Sent from client to server to notify about new monitor layout (e.g screen resize).
///
/// INVARIANTS:
/// 0 <= monitors.length() <= MAX_SUPPORTED_MONITORS
///
/// [2.2.2.2]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpedisp/22741217-12a0-4fb8-b5a0-df43905aaf06
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DisplayControlMonitorLayout {
monitors: Vec<MonitorLayoutEntry>,
Expand Down Expand Up @@ -280,6 +303,9 @@ impl<'de> PduDecode<'de> for DisplayControlMonitorLayout {
}
}

/// [2.2.2.2.1] DISPLAYCONTROL_MONITOR_LAYOUT_PDU
///
/// [2.2.2.2.2]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpedisp/ea2de591-9203-42cd-9908-be7a55237d1c
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MonitorLayoutEntry {
is_primary: bool,
Expand Down
40 changes: 40 additions & 0 deletions crates/ironrdp-displaycontrol/src/server.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use ironrdp_dvc::{DvcMessage, DvcProcessor, DvcServerProcessor};
use ironrdp_pdu::{decode, PduResult};
use ironrdp_svc::impl_as_any;
use tracing::debug;

use crate::{
pdu::{DisplayControlCapabilities, DisplayControlPdu},
CHANNEL_NAME,
};

/// A server for the Display Control Virtual Channel.
pub struct DisplayControlServer {}

impl_as_any!(DisplayControlServer);

impl DvcProcessor for DisplayControlServer {
fn channel_name(&self) -> &str {
CHANNEL_NAME
}

fn start(&mut self, _channel_id: u32) -> PduResult<Vec<DvcMessage>> {
let pdu: DisplayControlPdu = DisplayControlCapabilities::new(1, 3840, 2400)?.into();

Ok(vec![Box::new(pdu)])
}

fn process(&mut self, _channel_id: u32, payload: &[u8]) -> PduResult<Vec<DvcMessage>> {
match decode(payload)? {
DisplayControlPdu::MonitorLayout(layout) => {
debug!(?layout);
}
DisplayControlPdu::Caps(caps) => {
debug!(?caps);
}
}
Ok(Vec::new())
}
}

impl DvcServerProcessor for DisplayControlServer {}
Loading

0 comments on commit 1e53669

Please sign in to comment.