Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions Cargo.lock

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

15 changes: 15 additions & 0 deletions crates/iron-remote-desktop/src/desktop_size.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use wasm_bindgen::prelude::wasm_bindgen;

#[wasm_bindgen]
#[derive(Clone, Copy)]
pub struct DesktopSize {
pub width: u16,
pub height: u16,
}

#[wasm_bindgen]
impl DesktopSize {
pub fn init(width: u16, height: u16) -> Self {
DesktopSize { width, height }
}
}
68 changes: 68 additions & 0 deletions crates/iron-remote-desktop/src/extension.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::JsValue;

#[macro_export]
macro_rules! extension_match {
( @ $jsval:expr, $value:ident, String, $operation:block ) => {{
if let Some($value) = $jsval.as_string() {
$operation
} else {
warn!("Unexpected value for extension {}", stringify!($ident));
}
}};
( @ $jsval:expr, $value:ident, f64, $operation:block ) => {{
if let Some($value) = $jsval.as_f64() {
$operation
} else {
warn!("Unexpected value for extension {}", stringify!($ident));
}
}};
( @ $jsval:expr, $value:ident, bool, $operation:block ) => {{
if let Some($value) = $jsval.as_bool() {
$operation
} else {
warn!("Unexpected value for extension {}", stringify!($ident));
}
}};
( @ $jsval:expr, $value:ident, JsValue, $operation:block ) => {{
let $value = $jsval;
$operation
}};

( match $ext:ident ; $( | $value:ident : $ty:ident | $operation:block ; )* ) => {
let ident = $ext.ident();

match ident {
$( stringify!($value) => $crate::extension_match!( @ $ext.into_value(), $value, $ty, $operation ), )*
unknown_extension => ::tracing::warn!("Unknown extension: {unknown_extension}"),
}
};
}
Comment on lines +4 to +40
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Helper macro to extract extension values. This is not strictly needed, but it’s less boilerplate in the consumer code.


#[wasm_bindgen]
pub struct Extension {
ident: String,
value: JsValue,
}

#[wasm_bindgen]
impl Extension {
#[wasm_bindgen(constructor)]
pub fn new(ident: String, value: JsValue) -> Self {
Self { ident, value }
}
}

impl Extension {
pub fn ident(&self) -> &str {
self.ident.as_str()
}

pub fn value(&self) -> &JsValue {
&self.value
}

pub fn into_value(self) -> JsValue {
self.value
}
}
27 changes: 8 additions & 19 deletions crates/iron-remote-desktop/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,18 @@
mod clipboard;
mod cursor;
mod desktop_size;
mod error;
mod extension;
mod input;
mod session;

pub use clipboard::{ClipboardContent, ClipboardTransaction};
pub use cursor::CursorStyle;
pub use desktop_size::DesktopSize;
pub use error::{IronError, IronErrorKind};
pub use extension::Extension;
pub use input::{DeviceEvent, InputTransaction};
pub use session::{Session, SessionBuilder, SessionTerminationInfo};
use wasm_bindgen::prelude::wasm_bindgen;

#[wasm_bindgen]
#[derive(Clone, Copy)]
pub struct DesktopSize {
pub width: u16,
pub height: u16,
}

#[wasm_bindgen]
impl DesktopSize {
pub fn init(width: u16, height: u16) -> Self {
DesktopSize { width, height }
}
}

pub fn iron_init(log_level: &str) {
// When the `console_error_panic_hook` feature is enabled, we can call the
Expand Down Expand Up @@ -229,8 +218,8 @@ macro_rules! export {
self.0.supports_unicode_keyboard_shortcuts()
}

pub fn extension_call(value: JsValue) -> Result<JsValue, IronError> {
<<$api as RemoteDesktopApi>::Session>::extension_call(value).map_err(IronError)
pub fn extension_call(ext: $crate::Extension) -> Result<JsValue, IronError> {
<<$api as RemoteDesktopApi>::Session>::extension_call(ext).map_err(IronError)
}
}

Expand Down Expand Up @@ -295,8 +284,8 @@ macro_rules! export {
Self(self.0.force_clipboard_update_callback(callback))
}

pub fn extension(&self, value: JsValue) -> Self {
Self(self.0.extension(value))
pub fn extension(&self, ext: $crate::Extension) -> Self {
Self(self.0.extension(ext))
}

pub async fn connect(&self) -> Result<Session, IronError> {
Expand Down
6 changes: 3 additions & 3 deletions crates/iron-remote-desktop/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use web_sys::{js_sys, HtmlCanvasElement};
use crate::clipboard::ClipboardTransaction;
use crate::error::IronError;
use crate::input::InputTransaction;
use crate::DesktopSize;
use crate::{DesktopSize, Extension};

pub trait SessionBuilder {
type Session: Session;
Expand Down Expand Up @@ -38,7 +38,7 @@ pub trait SessionBuilder {
#[must_use]
fn force_clipboard_update_callback(&self, callback: js_sys::Function) -> Self;
#[must_use]
fn extension(&self, value: JsValue) -> Self;
fn extension(&self, ext: Extension) -> Self;
#[expect(async_fn_in_trait)]
async fn connect(&self) -> Result<Self::Session, Self::Error>;
}
Expand Down Expand Up @@ -74,7 +74,7 @@ pub trait Session {
physical_height: Option<u32>,
);
fn supports_unicode_keyboard_shortcuts(&self) -> bool;
fn extension_call(value: JsValue) -> Result<JsValue, Self::Error>;
fn extension_call(ext: Extension) -> Result<JsValue, Self::Error>;
}

pub trait SessionTerminationInfo {
Expand Down
2 changes: 0 additions & 2 deletions crates/ironrdp-web/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ web-sys = { version = "0.3", features = ["HtmlCanvasElement"] }
js-sys = "0.3"
gloo-net = { version = "0.6", default-features = false, features = ["websocket", "http", "io-util"] }
gloo-timers = { version = "0.3", default-features = false, features = ["futures"] }
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.6"

# Rendering
softbuffer = { version = "0.4", default-features = false }
Expand Down
40 changes: 14 additions & 26 deletions crates/ironrdp-web/src/session.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
// https://github.com/rustwasm/wasm-bindgen/issues/4080
#![allow(non_snake_case)]

use core::cell::RefCell;
use core::num::NonZeroU32;
use core::time::Duration;
Expand All @@ -14,7 +11,7 @@ use futures_util::io::{ReadHalf, WriteHalf};
use futures_util::{select, AsyncWriteExt as _, FutureExt as _, StreamExt as _};
use gloo_net::websocket;
use gloo_net::websocket::futures::WebSocket;
use iron_remote_desktop::{CursorStyle, DesktopSize, IronErrorKind};
use iron_remote_desktop::{CursorStyle, DesktopSize, Extension, IronErrorKind};
use ironrdp::cliprdr::backend::ClipboardMessage;
use ironrdp::cliprdr::CliprdrClient;
use ironrdp::connector::connection_activation::ConnectionActivationState;
Expand All @@ -30,7 +27,6 @@ use ironrdp::session::{fast_path, ActiveStage, ActiveStageOutput, GracefulDiscon
use ironrdp_core::WriteBuf;
use ironrdp_futures::{single_sequence_step_read, FramedWrite};
use rgb::AsPixels as _;
use serde::{Deserialize, Serialize};
use tap::prelude::*;
use wasm_bindgen::JsValue;
use wasm_bindgen_futures::spawn_local;
Expand Down Expand Up @@ -207,16 +203,12 @@ impl iron_remote_desktop::SessionBuilder for SessionBuilder {
self.clone()
}

fn extension(&self, value: JsValue) -> Self {
match serde_wasm_bindgen::from_value::<Extension>(value) {
Ok(value) => match value {
Extension::KdcProxyUrl(kdc_proxy_url) => self.0.borrow_mut().kdc_proxy_url = Some(kdc_proxy_url),
Extension::Pcb(pcb) => self.0.borrow_mut().pcb = Some(pcb),
Extension::DisplayControl(use_display_control) => {
self.0.borrow_mut().use_display_control = use_display_control
}
},
Err(error) => error!(%error, "Unsupported extension value"),
fn extension(&self, ext: Extension) -> Self {
iron_remote_desktop::extension_match! {
match ext;
|pcb: String| { self.0.borrow_mut().pcb = Some(pcb) };
|kdc_proxy_url: String| { self.0.borrow_mut().kdc_proxy_url = Some(kdc_proxy_url) };
|display_control: bool| { self.0.borrow_mut().use_display_control = display_control };
}
Comment on lines +207 to 212
Copy link
Copy Markdown
Member Author

@CBenoit Benoît Cortier (CBenoit) Apr 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We directly use JsValue API without any smart trick.
No extra dependency required for that.
For now there is no extension requiring to pass an "object", but if we had one, we could use the Reflect module of js_sys, that we already depend on, to get the individual fields.


self.clone()
Expand Down Expand Up @@ -354,13 +346,6 @@ impl iron_remote_desktop::SessionBuilder for SessionBuilder {
}
}

#[derive(Debug, Serialize, Deserialize)]
enum Extension {
KdcProxyUrl(String),
Pcb(String),
DisplayControl(bool),
}

pub(crate) type FastPathInputEvents = smallvec::SmallVec<[FastPathInputEvent; 2]>;

#[derive(Debug)]
Expand Down Expand Up @@ -813,13 +798,16 @@ impl iron_remote_desktop::Session for Session {
}

fn supports_unicode_keyboard_shortcuts(&self) -> bool {
// RDP does not support Unicode keyboard shortcuts (When key combinations are executed, only
// plain scancode events are allowed to function correctly).
// RDP does not support Unicode keyboard shortcuts.
// When key combinations are executed, only plain scancode events are allowed to function correctly.
false
}

fn extension_call(_value: JsValue) -> Result<JsValue, Self::Error> {
Ok(JsValue::null())
fn extension_call(ext: Extension) -> Result<JsValue, Self::Error> {
Err(
IronError::from(anyhow::Error::msg(format!("unknown extension: {}", ext.ident())))
.with_kind(IronErrorKind::General),
)
}
}

Expand Down
28 changes: 0 additions & 28 deletions web-client/iron-remote-desktop-rdp/src/interfaces/Extension.ts

This file was deleted.

14 changes: 13 additions & 1 deletion web-client/iron-remote-desktop-rdp/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import init, {
SessionTerminationInfo,
ClipboardTransaction,
ClipboardContent,
Extension,
} from '../../../crates/ironrdp-web/pkg/ironrdp_web';
import { Extension } from './interfaces/Extension';

export default {
init,
Expand All @@ -26,3 +26,15 @@ export default {
SessionTerminationInfo,
Extension,
};

export function preConnectionBlob(pcb: string): Extension {
return new Extension('pcb', pcb);
}

export function displayControl(enable: boolean): Extension {
return new Extension('display_control', enable);
}

export function kdcProxyUrl(url: string): Extension {
return new Extension('kdc_proxy_url', url);
}
6 changes: 1 addition & 5 deletions web-client/iron-remote-desktop/src/interfaces/Extension.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
import type { ExtensionValue } from './ExtensionValue';

export interface Extension {
init(ident: string, value: unknown): ExtensionValue;
}
export type Extension = unknown;

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import type { SessionBuilder } from './SessionBuilder';
import type { SessionTerminationInfo } from './SessionTerminationInfo';
import type { ClipboardTransaction } from './ClipboardTransaction';
import type { ClipboardContent } from './ClipboardContent';
import type { Extension } from './Extension';

export interface RemoteDesktopModule {
init: () => Promise<unknown>;
Expand All @@ -21,5 +20,4 @@ export interface RemoteDesktopModule {
SessionTerminationInfo: SessionTerminationInfo;
ClipboardTransaction: ClipboardTransaction;
ClipboardContent: ClipboardContent;
Extension: Extension;
}
6 changes: 3 additions & 3 deletions web-client/iron-remote-desktop/src/services/Config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { DesktopSize } from '../interfaces/DesktopSize';
import type { ExtensionValue } from '../interfaces/ExtensionValue';
import type { Extension } from '../interfaces/Extension';

export class Config {
readonly username: string;
Expand All @@ -9,15 +9,15 @@ export class Config {
readonly serverDomain: string;
readonly authToken: string;
readonly desktopSize?: DesktopSize;
readonly extensions: ExtensionValue[];
readonly extensions: Extension[];

constructor(
userData: { username: string; password: string },
proxyData: { address: string; authToken: string },
configOptions: {
destination: string;
serverDomain: string;
extensions: ExtensionValue[];
extensions: Extension[];
desktopSize?: DesktopSize;
},
) {
Expand Down
Loading
Loading