Skip to content

Commit f287e16

Browse files
authored
refactor: rework extension API for iron-remote-desktop (#762)
1 parent 45884c5 commit f287e16

17 files changed

Lines changed: 159 additions & 143 deletions

File tree

Cargo.lock

Lines changed: 0 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use wasm_bindgen::prelude::wasm_bindgen;
2+
3+
#[wasm_bindgen]
4+
#[derive(Clone, Copy)]
5+
pub struct DesktopSize {
6+
pub width: u16,
7+
pub height: u16,
8+
}
9+
10+
#[wasm_bindgen]
11+
impl DesktopSize {
12+
pub fn init(width: u16, height: u16) -> Self {
13+
DesktopSize { width, height }
14+
}
15+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use wasm_bindgen::prelude::wasm_bindgen;
2+
use wasm_bindgen::JsValue;
3+
4+
#[macro_export]
5+
macro_rules! extension_match {
6+
( @ $jsval:expr, $value:ident, String, $operation:block ) => {{
7+
if let Some($value) = $jsval.as_string() {
8+
$operation
9+
} else {
10+
warn!("Unexpected value for extension {}", stringify!($ident));
11+
}
12+
}};
13+
( @ $jsval:expr, $value:ident, f64, $operation:block ) => {{
14+
if let Some($value) = $jsval.as_f64() {
15+
$operation
16+
} else {
17+
warn!("Unexpected value for extension {}", stringify!($ident));
18+
}
19+
}};
20+
( @ $jsval:expr, $value:ident, bool, $operation:block ) => {{
21+
if let Some($value) = $jsval.as_bool() {
22+
$operation
23+
} else {
24+
warn!("Unexpected value for extension {}", stringify!($ident));
25+
}
26+
}};
27+
( @ $jsval:expr, $value:ident, JsValue, $operation:block ) => {{
28+
let $value = $jsval;
29+
$operation
30+
}};
31+
32+
( match $ext:ident ; $( | $value:ident : $ty:ident | $operation:block ; )* ) => {
33+
let ident = $ext.ident();
34+
35+
match ident {
36+
$( stringify!($value) => $crate::extension_match!( @ $ext.into_value(), $value, $ty, $operation ), )*
37+
unknown_extension => ::tracing::warn!("Unknown extension: {unknown_extension}"),
38+
}
39+
};
40+
}
41+
42+
#[wasm_bindgen]
43+
pub struct Extension {
44+
ident: String,
45+
value: JsValue,
46+
}
47+
48+
#[wasm_bindgen]
49+
impl Extension {
50+
#[wasm_bindgen(constructor)]
51+
pub fn new(ident: String, value: JsValue) -> Self {
52+
Self { ident, value }
53+
}
54+
}
55+
56+
impl Extension {
57+
pub fn ident(&self) -> &str {
58+
self.ident.as_str()
59+
}
60+
61+
pub fn value(&self) -> &JsValue {
62+
&self.value
63+
}
64+
65+
pub fn into_value(self) -> JsValue {
66+
self.value
67+
}
68+
}

crates/iron-remote-desktop/src/lib.rs

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,18 @@
11
mod clipboard;
22
mod cursor;
3+
mod desktop_size;
34
mod error;
5+
mod extension;
46
mod input;
57
mod session;
68

79
pub use clipboard::{ClipboardContent, ClipboardTransaction};
810
pub use cursor::CursorStyle;
11+
pub use desktop_size::DesktopSize;
912
pub use error::{IronError, IronErrorKind};
13+
pub use extension::Extension;
1014
pub use input::{DeviceEvent, InputTransaction};
1115
pub use session::{Session, SessionBuilder, SessionTerminationInfo};
12-
use wasm_bindgen::prelude::wasm_bindgen;
13-
14-
#[wasm_bindgen]
15-
#[derive(Clone, Copy)]
16-
pub struct DesktopSize {
17-
pub width: u16,
18-
pub height: u16,
19-
}
20-
21-
#[wasm_bindgen]
22-
impl DesktopSize {
23-
pub fn init(width: u16, height: u16) -> Self {
24-
DesktopSize { width, height }
25-
}
26-
}
2716

2817
pub trait RemoteDesktopApi {
2918
type Session: Session;
@@ -194,8 +183,8 @@ macro_rules! export {
194183
self.0.supports_unicode_keyboard_shortcuts()
195184
}
196185

197-
pub fn extension_call(value: JsValue) -> Result<JsValue, IronError> {
198-
<<$api as RemoteDesktopApi>::Session>::extension_call(value).map_err(IronError)
186+
pub fn extension_call(ext: $crate::Extension) -> Result<JsValue, IronError> {
187+
<<$api as RemoteDesktopApi>::Session>::extension_call(ext).map_err(IronError)
199188
}
200189
}
201190

@@ -260,8 +249,8 @@ macro_rules! export {
260249
Self(self.0.force_clipboard_update_callback(callback))
261250
}
262251

263-
pub fn extension(&self, value: JsValue) -> Self {
264-
Self(self.0.extension(value))
252+
pub fn extension(&self, ext: $crate::Extension) -> Self {
253+
Self(self.0.extension(ext))
265254
}
266255

267256
pub async fn connect(&self) -> Result<Session, IronError> {

crates/iron-remote-desktop/src/session.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use web_sys::{js_sys, HtmlCanvasElement};
44
use crate::clipboard::ClipboardTransaction;
55
use crate::error::IronError;
66
use crate::input::InputTransaction;
7-
use crate::DesktopSize;
7+
use crate::{DesktopSize, Extension};
88

99
pub trait SessionBuilder {
1010
type Session: Session;
@@ -38,7 +38,7 @@ pub trait SessionBuilder {
3838
#[must_use]
3939
fn force_clipboard_update_callback(&self, callback: js_sys::Function) -> Self;
4040
#[must_use]
41-
fn extension(&self, value: JsValue) -> Self;
41+
fn extension(&self, ext: Extension) -> Self;
4242
#[expect(async_fn_in_trait)]
4343
async fn connect(&self) -> Result<Self::Session, Self::Error>;
4444
}
@@ -74,7 +74,7 @@ pub trait Session {
7474
physical_height: Option<u32>,
7575
);
7676
fn supports_unicode_keyboard_shortcuts(&self) -> bool;
77-
fn extension_call(value: JsValue) -> Result<JsValue, Self::Error>;
77+
fn extension_call(ext: Extension) -> Result<JsValue, Self::Error>;
7878
}
7979

8080
pub trait SessionTerminationInfo {

crates/ironrdp-web/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ web-sys = { version = "0.3", features = ["HtmlCanvasElement"] }
4646
js-sys = "0.3"
4747
gloo-net = { version = "0.6", default-features = false, features = ["websocket", "http", "io-util"] }
4848
gloo-timers = { version = "0.3", default-features = false, features = ["futures"] }
49-
serde = { version = "1.0", features = ["derive"] }
50-
serde-wasm-bindgen = "0.6"
5149

5250
# Rendering
5351
softbuffer = { version = "0.4", default-features = false }

crates/ironrdp-web/src/session.rs

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
// https://github.com/rustwasm/wasm-bindgen/issues/4080
2-
#![allow(non_snake_case)]
3-
41
use core::cell::RefCell;
52
use core::num::NonZeroU32;
63
use core::time::Duration;
@@ -15,7 +12,7 @@ use futures_util::io::{ReadHalf, WriteHalf};
1512
use futures_util::{select, AsyncWriteExt as _, FutureExt as _, StreamExt as _};
1613
use gloo_net::websocket;
1714
use gloo_net::websocket::futures::WebSocket;
18-
use iron_remote_desktop::{CursorStyle, DesktopSize, IronErrorKind};
15+
use iron_remote_desktop::{CursorStyle, DesktopSize, Extension, IronErrorKind};
1916
use ironrdp::cliprdr::backend::ClipboardMessage;
2017
use ironrdp::cliprdr::CliprdrClient;
2118
use ironrdp::connector::connection_activation::ConnectionActivationState;
@@ -31,7 +28,6 @@ use ironrdp::session::{fast_path, ActiveStage, ActiveStageOutput, GracefulDiscon
3128
use ironrdp_core::WriteBuf;
3229
use ironrdp_futures::{single_sequence_step_read, FramedWrite};
3330
use rgb::AsPixels as _;
34-
use serde::{Deserialize, Serialize};
3531
use tap::prelude::*;
3632
use wasm_bindgen::JsValue;
3733
use wasm_bindgen_futures::spawn_local;
@@ -208,16 +204,12 @@ impl iron_remote_desktop::SessionBuilder for SessionBuilder {
208204
self.clone()
209205
}
210206

211-
fn extension(&self, value: JsValue) -> Self {
212-
match serde_wasm_bindgen::from_value::<Extension>(value) {
213-
Ok(value) => match value {
214-
Extension::KdcProxyUrl(kdc_proxy_url) => self.0.borrow_mut().kdc_proxy_url = Some(kdc_proxy_url),
215-
Extension::Pcb(pcb) => self.0.borrow_mut().pcb = Some(pcb),
216-
Extension::DisplayControl(use_display_control) => {
217-
self.0.borrow_mut().use_display_control = use_display_control
218-
}
219-
},
220-
Err(error) => error!(%error, "Unsupported extension value"),
207+
fn extension(&self, ext: Extension) -> Self {
208+
iron_remote_desktop::extension_match! {
209+
match ext;
210+
|pcb: String| { self.0.borrow_mut().pcb = Some(pcb) };
211+
|kdc_proxy_url: String| { self.0.borrow_mut().kdc_proxy_url = Some(kdc_proxy_url) };
212+
|display_control: bool| { self.0.borrow_mut().use_display_control = display_control };
221213
}
222214

223215
self.clone()
@@ -355,13 +347,6 @@ impl iron_remote_desktop::SessionBuilder for SessionBuilder {
355347
}
356348
}
357349

358-
#[derive(Debug, Serialize, Deserialize)]
359-
enum Extension {
360-
KdcProxyUrl(String),
361-
Pcb(String),
362-
DisplayControl(bool),
363-
}
364-
365350
pub(crate) type FastPathInputEvents = smallvec::SmallVec<[FastPathInputEvent; 2]>;
366351

367352
#[derive(Debug)]
@@ -814,13 +799,16 @@ impl iron_remote_desktop::Session for Session {
814799
}
815800

816801
fn supports_unicode_keyboard_shortcuts(&self) -> bool {
817-
// RDP does not support Unicode keyboard shortcuts (When key combinations are executed, only
818-
// plain scancode events are allowed to function correctly).
802+
// RDP does not support Unicode keyboard shortcuts.
803+
// When key combinations are executed, only plain scancode events are allowed to function correctly.
819804
false
820805
}
821806

822-
fn extension_call(_value: JsValue) -> Result<JsValue, Self::Error> {
823-
Ok(JsValue::null())
807+
fn extension_call(ext: Extension) -> Result<JsValue, Self::Error> {
808+
Err(
809+
IronError::from(anyhow::Error::msg(format!("unknown extension: {}", ext.ident())))
810+
.with_kind(IronErrorKind::General),
811+
)
824812
}
825813
}
826814

web-client/iron-remote-desktop-rdp/src/interfaces/Extension.ts

Lines changed: 0 additions & 28 deletions
This file was deleted.

web-client/iron-remote-desktop-rdp/src/main.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import init, {
99
SessionTerminationInfo,
1010
ClipboardTransaction,
1111
ClipboardContent,
12+
Extension,
1213
} from '../../../crates/ironrdp-web/pkg/ironrdp_web';
13-
import { Extension } from './interfaces/Extension';
1414

1515
export default {
1616
init,
@@ -26,3 +26,15 @@ export default {
2626
SessionTerminationInfo,
2727
Extension,
2828
};
29+
30+
export function preConnectionBlob(pcb: string): Extension {
31+
return new Extension('pcb', pcb);
32+
}
33+
34+
export function displayControl(enable: boolean): Extension {
35+
return new Extension('display_control', enable);
36+
}
37+
38+
export function kdcProxyUrl(url: string): Extension {
39+
return new Extension('kdc_proxy_url', url);
40+
}
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
1-
import type { ExtensionValue } from './ExtensionValue';
2-
3-
export interface Extension {
4-
init(ident: string, value: unknown): ExtensionValue;
5-
}
1+
export type Extension = unknown;

0 commit comments

Comments
 (0)