LeastAuthority/winden

Cross compile magic-wormhole.rs into wasm and try it with minimal web client

Closed this issue · 7 comments

Cross compile magic-wormhole.rs into Wasm and try it with minimal web client.

Objective: Confirm, that rust library can work under WASM in Web Client without much additional development effort.

Secondary objective: Understand how much effort requires if we want to switch Winden from Go to Rust library.

cargo build --target wasm32-unknown-unknown --no-default-features --package magic-wormhole --features transit --features transfer works for me on the wasm branch. I'll try to rebase it onto master and see if it still works.

wasm-pack build does the same thing. It creates a pkg directory of wasm, js and other stuff in there. I tried Andy's magic-wormhole-wasm repo and could do some mailbox communication with it like getting a code etc. Couldn't transfer a file though and haven't investigated it yet but I think it may not be a huge issue.

I think it is talking to @piegamesde's servers at the moment. Andy's APIs are very minimal and meant to be a demo at this point and needs tons of work. The API directly reads the html input element to read filename etc. The major work required is to make it streaming the input. Right now, it reads the entire file into a JS ArrayBuffer into the memory.

We could use that app as a starting point. I am not a JS programmer, so need help with wasm/JS interface. The Go/wasm interface for winden is roughly:

NewClient(config: JSObject) -> *Client
Client_SendText(clientPtr: *Client, msgText: string) -> js.Promise fn(resolveFn, rejectFn)
Client_SendFile(clientPtr: *Client, fileName: string, fileJSVal: js.File) -> js.Promise fn(resolveFn(js.Object), rejectFn(error))
Client_RecvText(clientPtr: *Client, code: string) -> js.Promise fn(resolveFn(string), rejectFn(error))
Client_RecvFile(clientPtr: *Client, code: string) -> js.Promise fn(resolveFn(js.Object), reject(error))
Client_Free(clientPtr: *Client) -> ()

Right now, the rust/wasm interface is:

pub fn init() 
pub async fn send(file_input: web_sys::HtmlInputElement, output: web_sys::HtmlElement)
pub async fn receive(code: String, output: web_sys::HtmlElement) -> Option<JsValue>

/cc: @meejah @JustusFT

I don't know web stuff either, but you can just stub the JS bindings on the Rust and I'll fill in the implementation glue code.

Also rebasing/merging is a bit tricky because the code base has somewhat changed since. I propose cherry-picking and rewriting the relevant changes instead (the diff is not that large, mostly sprinkling in cfg attributes here and there). Also, the current code on the wasm branch will use WebSocket connections instead of TCP if and only if compiling for a WebAssembly target. We might want to discuss implementing first-class WebSocket support first. (Personally I don't see the point in using when it's not required, but I've seen people with different opinions on that)

+1 on websockets "only if necessary" (or asked I guess -- e.g. might be a fun command-line option for testing, debugging). If "masking" gets turned on there can be a ton of overhead (XOR on the entire stream) and in any case it's a lot more complex than TCP.

The major upside of WS even on the desktop is that it's guaranteed to be hassle free even with (stupidly) restrictive firewalls. The biggest downside IMO is the lack of any possibility for a direct connection.

The major upside of WS even on the desktop is that it's guaranteed to be hassle free even with (stupidly) restrictive firewalls. The biggest downside IMO is the lack of any possibility for a direct connection.

I don't think either of those things are true (maybe "sometimes" the first one).

To determine if a given stream is WS or "just TCP" you'd have to do DPI (deep packet inspection) -- do desktop firewalls do that? How would they do this on TLS streams? (Some weird corporate firewalls that MitM all TLS connections can, of course, but ...) That is, I think a given stream is just as likely to succeed no matter what bytes traverse it. The ports in use will make far more difference than the protocol bytes (but you can run WS or plain TCP on any port you like).

You absolutely can have a direct WebSocket connection -- just not from inside a browser.

Since Winden already switched to Rust (#141), we can close this now