Skip to content
Closed
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
129 changes: 75 additions & 54 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions crates/ironrdp-web/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ iron-remote-desktop.path = "../iron-remote-desktop"
# WASM
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
wasm-bindgen-derive = "0.3"
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I have tried to use wasm-bindgen convert module to be able to downcast from JsValue to an extension, but I have found that this module is unstable and gives different results each call (first call - fine, everything else - errors). This is a known issue: wasm-bindgen/wasm-bindgen#2231.
This crate fixes the issue.

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
78 changes: 78 additions & 0 deletions crates/ironrdp-web/src/extension.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::JsValue;
use wasm_bindgen_derive::try_from_js_option;

#[derive(wasm_bindgen_derive::TryFromJsValue)]
#[wasm_bindgen]
#[derive(Debug, Clone)]
pub struct DisplayControl(bool);

#[wasm_bindgen]
impl DisplayControl {
pub fn new(value: bool) -> Self {
Self(value)
}
}

impl DisplayControl {
pub fn into_inner(self) -> bool {
self.0
}
}

#[derive(wasm_bindgen_derive::TryFromJsValue)]
#[wasm_bindgen]
#[derive(Debug, Clone)]
pub struct Pcb(String);

#[wasm_bindgen]
impl Pcb {
pub fn new(value: String) -> Self {
Self(value)
}
}

impl Pcb {
pub fn into_inner(self) -> String {
self.0
}
}

#[derive(wasm_bindgen_derive::TryFromJsValue)]
#[wasm_bindgen]
#[derive(Debug, Clone)]
pub struct KdcProxyUrl(String);

#[wasm_bindgen]
impl KdcProxyUrl {
pub fn new(value: String) -> Self {
Self(value)
}
}

impl KdcProxyUrl {
pub fn into_inner(self) -> String {
self.0
}
}

#[derive(Debug, Clone)]
pub(crate) enum Extension {
DisplayControl(bool),
Pcb(String),
KdcProxyUrl(String),
}

impl Extension {
pub(crate) fn try_from_js_value(value: JsValue) -> Result<Self, anyhow::Error> {
if let Ok(Some(display_control)) = try_from_js_option::<DisplayControl>(value.clone()) {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

We have to clone every time since wasm_bindgen_derive doesn't have an API to take JsValue by reference

Ok(Self::DisplayControl(display_control.into_inner()))
} else if let Ok(Some(pcb)) = try_from_js_option::<Pcb>(value.clone()) {
Ok(Self::Pcb(pcb.into_inner()))
} else if let Ok(Some(kdc)) = try_from_js_option::<KdcProxyUrl>(value) {
Ok(Self::KdcProxyUrl(kdc.into_inner()))
} else {
anyhow::bail!("provided value is not a supported extension")
}
}
}
4 changes: 4 additions & 0 deletions crates/ironrdp-web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ extern crate chrono as _;
extern crate getrandom as _;
extern crate time as _;

// Required by wasm-bindgen-derive crate
extern crate alloc;

#[macro_use]
extern crate tracing;

Expand All @@ -17,6 +20,7 @@ use iron_remote_desktop::RemoteDesktopApi;
mod canvas;
mod clipboard;
mod error;
mod extension;
mod image;
mod input;
mod network_client;
Expand Down
21 changes: 6 additions & 15 deletions crates/ironrdp-web/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,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 All @@ -40,6 +39,7 @@ use crate::canvas::Canvas;
use crate::clipboard;
use crate::clipboard::{RdpClipboardTransaction, WasmClipboard, WasmClipboardBackend, WasmClipboardBackendMessage};
use crate::error::IronError;
use crate::extension::Extension;
use crate::image::extract_partial_image;
use crate::input::InputTransaction;
use crate::network_client::WasmNetworkClient;
Expand Down Expand Up @@ -208,15 +208,13 @@ impl iron_remote_desktop::SessionBuilder for SessionBuilder {
}

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),
match Extension::try_from_js_value(value) {
Ok(ext) => match ext {
Extension::KdcProxyUrl(kdc) => self.0.borrow_mut().kdc_proxy_url = Some(kdc),
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
}
Extension::DisplayControl(dc) => self.0.borrow_mut().use_display_control = dc,
},
Err(error) => error!(%error, "Unsupported extension value"),
Err(error) => error!(?error),
}

self.clone()
Expand Down Expand Up @@ -354,13 +352,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
28 changes: 0 additions & 28 deletions web-client/iron-remote-desktop-rdp/src/interfaces/Extension.ts

This file was deleted.

5 changes: 3 additions & 2 deletions web-client/iron-remote-desktop-rdp/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import init, {
ClipboardTransaction,
ClipboardContent,
} from '../../../crates/ironrdp-web/pkg/ironrdp_web';
import { Extension } from './interfaces/Extension';
import { preConnectionBlob, kdcProxyUrl, displayControl } from './services/ExtensionBuilders';

export default {
init,
Expand All @@ -24,5 +24,6 @@ export default {
ClipboardContent,
Session,
SessionTerminationInfo,
Extension,
};

export { preConnectionBlob, kdcProxyUrl, displayControl };
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { DisplayControl, KdcProxyUrl, Pcb } from '../../../../crates/ironrdp-web/pkg';

export function preConnectionBlob(value: string): Pcb {
return Pcb.new(value);
}

export function displayControl(value: boolean): DisplayControl {
return DisplayControl.new(value);
}

export function kdcProxyUrl(value: string): KdcProxyUrl {
return KdcProxyUrl.new(value);
}
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
21 changes: 6 additions & 15 deletions web-client/iron-remote-desktop/src/services/ConfigBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import type { DesktopSize } from '../interfaces/DesktopSize';
import { Config } from './Config';
import type { ExtensionValue } from '../interfaces/ExtensionValue';

type ExtensionConstructor = (ident: string, value: unknown) => ExtensionValue;
import type { Extension } from '../interfaces/Extension';

/**
* Builder class for creating Config objects with a fluent interface.
Expand All @@ -19,8 +17,6 @@ type ExtensionConstructor = (ident: string, value: unknown) => ExtensionValue;
* ```
*/
export class ConfigBuilder {
private extensionConstructor: ExtensionConstructor;

private username: string = '';
private password: string = '';
private destination: string = '';
Expand All @@ -29,16 +25,12 @@ export class ConfigBuilder {
private authToken: string = '';
private desktopSize?: DesktopSize;

private extensions: ExtensionValue[] = [];
private extensions: Extension[] = [];

/**
* Creates a new ConfigBuilder instance.
*
* @param extensionConstructor - Function that creates extension values from identifiers and values.
*/
constructor(extensionConstructor: ExtensionConstructor) {
this.extensionConstructor = extensionConstructor;
}
constructor() {}

/**
* Optional parameter
Expand Down Expand Up @@ -109,12 +101,11 @@ export class ConfigBuilder {
/**
* Optional parameter
*
* @param ident - The identifier for the extension
* @param value - The value for the extension
* @param value - The extension value
* @returns The builder instance for method chaining
*/
withExtension(ident: string, value: unknown): ConfigBuilder {
this.extensions.push(this.extensionConstructor(ident, value));
withExtension(value: Extension): ConfigBuilder {
this.extensions.push(value);
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export class RemoteDesktopService {
}

configBuilder(): ConfigBuilder {
return new ConfigBuilder(this.module.Extension.init);
return new ConfigBuilder();
}

connect(config: Config): Observable<NewSessionInfo> {
Expand Down
7 changes: 4 additions & 3 deletions web-client/iron-svelte-client/src/lib/login/login.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { currentSession, userInteractionService } from '../../services/session.service';
import { catchError, filter } from 'rxjs/operators';
import type { UserInteraction, NewSessionInfo } from '../../../static/iron-remote-desktop';
import { preConnectionBlob, displayControl, kdcProxyUrl } from '../../../static/iron-remote-desktop-rdp';
import { from, of } from 'rxjs';
import { toast } from '$lib/messages/message-store';
import { showLogin } from '$lib/login/login-store';
Expand Down Expand Up @@ -125,14 +126,14 @@
.withServerDomain(domain)
.withAuthToken(authtoken)
.withDesktopSize(desktopSize)
.withExtension('DisplayControl', true);
.withExtension(displayControl(true));

if (pcb !== '') {
configBuilder.withExtension('Pcb', pcb);
configBuilder.withExtension(preConnectionBlob(pcb));
}

if (kdc_proxy_url !== '') {
configBuilder.withExtension('KdcProxyUrl', kdc_proxy_url);
configBuilder.withExtension(kdcProxyUrl(kdc_proxy_url));
}
const config = configBuilder.build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { setCurrentSessionActive, userInteractionService } from '../../services/session.service';
import type { UserInteraction } from '../../../static/iron-remote-desktop';
import IronRdp from '../../../static/iron-remote-desktop-rdp';
import { preConnectionBlob, displayControl, kdcProxyUrl } from '../../../static/iron-remote-desktop-rdp';

let uiService: UserInteraction;
let cursorOverrideActive = false;
Expand Down Expand Up @@ -45,14 +46,14 @@
.withServerDomain(domain)
.withAuthToken(authtoken)
.withDesktopSize(desktopSize)
.withExtension('DisplayControl', true);
.withExtension(displayControl(true));

if (pcb !== '') {
configBuilder.withExtension('Pcb', pcb);
configBuilder.withExtension(preConnectionBlob(pcb));
}

if (kdc_proxy_url !== '') {
configBuilder.withExtension('KdcProxyUrl', kdc_proxy_url);
configBuilder.withExtension(kdcProxyUrl(kdc_proxy_url));
}
const config = configBuilder.build();

Expand Down
Loading