From 9142a78c9feece4aac0ca5f762540fafe8598829 Mon Sep 17 00:00:00 2001 From: mihneabuz Date: Sun, 6 Aug 2023 16:33:21 +0300 Subject: [PATCH] qemu-rdp: display and input handlers --- qemu-rdp/Cargo.toml | 6 +-- qemu-rdp/src/main.rs | 8 ++-- qemu-rdp/src/server/display.rs | 77 +++++++++++++++------------------- qemu-rdp/src/server/input.rs | 60 ++++++++++++++------------ qemu-rdp/src/server/mod.rs | 7 ++-- 5 files changed, 78 insertions(+), 80 deletions(-) diff --git a/qemu-rdp/Cargo.toml b/qemu-rdp/Cargo.toml index ae96ad9..e210831 100644 --- a/qemu-rdp/Cargo.toml +++ b/qemu-rdp/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] qemu-display = { path = "../qemu-display" } -keycodemap = { path ="../keycodemap" } +keycodemap = { path = "../keycodemap" } bytes = "1.4" rustls = { version = "0.21" } rustls-pemfile = "1.0" @@ -18,5 +18,5 @@ anyhow = "1.0" zbus = { version = "3.0" } clap = { version = "3.2", features = ["derive"] } async-trait = "0.1" -ironrdp = { path = "../../IronRDP/crates/ironrdp" } -ironrdp-server = { path = "../../IronRDP/crates/ironrdp-server" } +# TODO: replace this with upstream after merge +ironrdp = { git = "https://github.com/mihneabuz/IronRDP.git", branch = "feature_server", features = ["server"] } diff --git a/qemu-rdp/src/main.rs b/qemu-rdp/src/main.rs index 00b15da..b0d9068 100644 --- a/qemu-rdp/src/main.rs +++ b/qemu-rdp/src/main.rs @@ -7,9 +7,11 @@ async fn main() -> Result<(), anyhow::Error> { let dbus = match args.dbus_address.take() { None => zbus::Connection::session().await, - Some(addr) => zbus::ConnectionBuilder::address(addr.as_str())? - .build() - .await + Some(addr) => { + zbus::ConnectionBuilder::address(addr.as_str())? + .build() + .await + } } .expect("Failed to connect to DBus"); diff --git a/qemu-rdp/src/server/display.rs b/qemu-rdp/src/server/display.rs index 56ab5b3..0dc0acc 100644 --- a/qemu-rdp/src/server/display.rs +++ b/qemu-rdp/src/server/display.rs @@ -2,14 +2,25 @@ use anyhow::Result; use ironrdp::connector::DesktopSize; use qemu_display::{Console, ConsoleListenerHandler, Cursor, MouseSet, Scanout, Update}; -use ironrdp_server::{BitmapUpdate, DisplayUpdate, PixelFormat, PixelOrder, RdpServerDisplay}; +use ironrdp::server::{BitmapUpdate, DisplayUpdate, PixelFormat, PixelOrder, RdpServerDisplay}; pub struct DisplayHandler { - dbus: zbus::Connection, console: Console, receiver: tokio::sync::mpsc::Receiver, } +impl DisplayHandler { + pub async fn connect(dbus: zbus::Connection) -> Result { + let (sender, receiver) = tokio::sync::mpsc::channel::(32); + let listener = Listener::new(sender); + + let console = Console::new(&dbus, 0).await?; + console.register_listener(listener).await?; + + Ok(Self { console, receiver }) + } +} + #[async_trait::async_trait] impl RdpServerDisplay for DisplayHandler { async fn size(&mut self) -> DesktopSize { @@ -42,12 +53,17 @@ impl Listener { #[async_trait::async_trait] impl ConsoleListenerHandler for Listener { async fn scanout(&mut self, scanout: Scanout) { + let format = match scanout.format { + 537_004_168 => PixelFormat::BgrA32, + _ => PixelFormat::RgbA32, + }; + let bitmap = DisplayUpdate::Bitmap(BitmapUpdate { top: 0, left: 0, width: scanout.width, height: scanout.height, - format: PixelFormat::RgbA32, + format, order: PixelOrder::TopToBottom, data: scanout.data, }); @@ -56,13 +72,18 @@ impl ConsoleListenerHandler for Listener { } async fn update(&mut self, update: Update) { + let format = match update.format { + 537_004_168 => PixelFormat::BgrA32, + _ => PixelFormat::RgbA32, + }; + let bitmap = DisplayUpdate::Bitmap(BitmapUpdate { // TODO: fix scary conversion - top: update.x as u32, - left: update.y as u32, + top: update.y as u32, + left: update.x as u32, width: update.w as u32, height: update.h as u32, - format: PixelFormat::RgbA32, + format, order: PixelOrder::TopToBottom, data: update.data, }); @@ -71,48 +92,16 @@ impl ConsoleListenerHandler for Listener { } #[cfg(unix)] - async fn scanout_dmabuf(&mut self, _scanout: qemu_display::ScanoutDMABUF) { - unimplemented!() - } + async fn scanout_dmabuf(&mut self, _scanout: qemu_display::ScanoutDMABUF) {} #[cfg(unix)] - async fn update_dmabuf(&mut self, _update: qemu_display::UpdateDMABUF) { - unimplemented!() - } - - async fn disable(&mut self) { - unimplemented!() - } - - async fn mouse_set(&mut self, _set: MouseSet) { - println!("MOUSE SET"); - } - - async fn cursor_define(&mut self, _cursor: Cursor) { - println!("CURSOR DEFINE"); - } - - fn disconnected(&mut self) { - println!("DISCONNECTED!"); - } + async fn update_dmabuf(&mut self, _update: qemu_display::UpdateDMABUF) {} + async fn disable(&mut self) {} + async fn mouse_set(&mut self, _set: MouseSet) {} + async fn cursor_define(&mut self, _cursor: Cursor) {} + fn disconnected(&mut self) {} fn interfaces(&self) -> Vec { vec![] } } - -impl DisplayHandler { - pub async fn connect(dbus: zbus::Connection) -> Result { - let (sender, receiver) = tokio::sync::mpsc::channel::(32); - let listener = Listener::new(sender); - - let console = Console::new(&dbus, 0).await?; - console.register_listener(listener).await?; - - Ok(Self { - dbus, - console, - receiver, - }) - } -} diff --git a/qemu-rdp/src/server/input.rs b/qemu-rdp/src/server/input.rs index aa6d917..ff33fa1 100644 --- a/qemu-rdp/src/server/input.rs +++ b/qemu-rdp/src/server/input.rs @@ -1,9 +1,9 @@ use qemu_display::{Console, KeyboardProxy, MouseButton, MouseProxy}; -use ironrdp_server::{KeyboardEvent, MouseEvent, RdpServerInputHandler}; +use ironrdp::server::{KeyboardEvent, MouseEvent, RdpServerInputHandler}; pub struct InputHandler<'a> { - dbus: zbus::Connection, + pos: (u16, u16), mouse: MouseProxy<'a>, keyboard: KeyboardProxy<'a>, } @@ -12,12 +12,11 @@ pub struct InputHandler<'a> { impl<'a> RdpServerInputHandler for InputHandler<'a> { async fn keyboard(&mut self, event: KeyboardEvent) { let result = match event { - KeyboardEvent::Pressed(code) => { - self.keyboard.press(code as u32).await - } - - KeyboardEvent::Released(code) => { - self.keyboard.release(code as u32).await + KeyboardEvent::Pressed { code, .. } => self.keyboard.press(code as u32).await, + KeyboardEvent::Released { code, .. } => self.keyboard.release(code as u32).await, + other => { + eprintln!("unhandled keyboard event: {:?}", other); + Ok(()) } }; @@ -28,23 +27,19 @@ impl<'a> RdpServerInputHandler for InputHandler<'a> { async fn mouse(&mut self, event: MouseEvent) { let result = match event { - MouseEvent::Move { x, y } => { - self.mouse.set_abs_position(x as u32, y as u32).await - } - MouseEvent::RightPressed => { - self.mouse.press(MouseButton::Right).await - } - MouseEvent::RightReleased => { - self.mouse.release(MouseButton::Right).await - } - MouseEvent::LeftPressed => { - self.mouse.press(MouseButton::Left).await - } - MouseEvent::LeftReleased => { - self.mouse.release(MouseButton::Left).await - } - MouseEvent::Scroll => { - unimplemented!() + MouseEvent::Move { x, y } => self.mouse_move(x, y).await, + MouseEvent::RightPressed => self.mouse.press(MouseButton::Right).await, + MouseEvent::RightReleased => self.mouse.release(MouseButton::Right).await, + MouseEvent::LeftPressed => self.mouse.press(MouseButton::Left).await, + MouseEvent::LeftReleased => self.mouse.release(MouseButton::Left).await, + MouseEvent::VerticalScroll { value } => { + let motion = if value > 0 { + MouseButton::WheelUp + } else { + MouseButton::WheelDown + }; + + self.mouse.press(motion).await } }; @@ -54,15 +49,26 @@ impl<'a> RdpServerInputHandler for InputHandler<'a> { } } - impl<'a> InputHandler<'a> { pub async fn connect(dbus: zbus::Connection) -> anyhow::Result> { let console = Console::new(&dbus, 0).await?; Ok(Self { - dbus, + pos: (0, 0), mouse: console.mouse, keyboard: console.keyboard, }) } + + pub async fn mouse_move(&mut self, x: u16, y: u16) -> Result<(), zbus::Error> { + if self.mouse.is_absolute().await.unwrap_or(true) { + self.mouse.set_abs_position(x.into(), y.into()).await + } else { + let (dx, dy) = (x as i32 - self.pos.0 as i32, y as i32 - self.pos.1 as i32); + let res = self.mouse.rel_motion(dx, dy).await; + self.pos = (x, y); + + res + } + } } diff --git a/qemu-rdp/src/server/mod.rs b/qemu-rdp/src/server/mod.rs index b322183..31f85df 100644 --- a/qemu-rdp/src/server/mod.rs +++ b/qemu-rdp/src/server/mod.rs @@ -4,11 +4,12 @@ mod input; use std::{fs::File, io::BufReader, sync::Arc}; use anyhow::Error; -use ironrdp_server::RdpServer; use rustls::ServerConfig; use rustls_pemfile::{certs, pkcs8_private_keys}; use tokio_rustls::TlsAcceptor; +use ironrdp::server::RdpServer; + use crate::args::ServerArgs; use display::DisplayHandler; @@ -37,8 +38,8 @@ impl Server { let mut server = RdpServer::builder() .with_addr((self.args.address, self.args.port)) - .with_ssl(tls.unwrap()) - .with_io_handler(handler) + .with_tls(tls.unwrap()) + .with_input_handler(handler) .with_display_handler(display) .build();