From 43ef098aada4e68f7f9d5a5907f023530215a5b3 Mon Sep 17 00:00:00 2001 From: Mark Sinclair Date: Mon, 7 Nov 2022 16:11:13 +0000 Subject: [PATCH] Add utilities to handle text and binary payloads for mixnet messages --- .../webassembly/src/binary_message_helper.rs | 83 +++++++++++++++++++ clients/webassembly/src/client/mod.rs | 23 +++-- clients/webassembly/src/lib.rs | 2 + 3 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 clients/webassembly/src/binary_message_helper.rs diff --git a/clients/webassembly/src/binary_message_helper.rs b/clients/webassembly/src/binary_message_helper.rs new file mode 100644 index 0000000000..96844be62c --- /dev/null +++ b/clients/webassembly/src/binary_message_helper.rs @@ -0,0 +1,83 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use wasm_bindgen::prelude::*; +use wasm_bindgen::JsCast; +use serde::{Serialize, Deserialize}; + +#[wasm_bindgen(typescript_custom_section)] +const TS_DEFS: &'static str = r#" +export interface BinaryMessage { + kind: number, + payload: Uint8Array; +} + +export interface StringMessage { + kind: number, + payload: string; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "BinaryMessage")] + pub type IBinaryMessage; + #[wasm_bindgen(typescript_type = "StringMessage")] + pub type IStringMessage; +} + +#[derive(Serialize, Deserialize)] +pub struct BinaryMessage { + pub kind: u8, + pub payload: Vec, +} + +#[derive(Serialize, Deserialize)] +pub struct StringMessage { + pub kind: u8, + pub payload: String, +} + +/// Create a new binary message with a user-specified `kind`. +#[wasm_bindgen] +pub fn create_binary_message(kind: u8, payload: Vec) -> Vec { + vec![vec![kind], payload].concat() +} + +/// Create a new message with a UTF-8 encoded string `payload` and a user-specified `kind`. +#[wasm_bindgen] +pub fn create_binary_message_from_string(kind: u8, payload: String) -> Vec { + vec!(vec![kind], payload.into_bytes()).concat() +} + +/// Parse the `kind` and byte array `payload` from a byte array +#[wasm_bindgen] +pub async fn parse_binary_message(message: Vec) -> Result { + if message.len() < 2 { + return Err(JsError::new("Could not parse message, as less than 2 bytes long")); + } + + let kind = message[0]; + let payload = &message[1..]; + + Ok(serde_wasm_bindgen::to_value(&BinaryMessage { + kind, + payload: payload.to_vec(), + }).unwrap().unchecked_into::()) +} + +/// Parse the `kind` and UTF-8 string `payload` from a byte array +#[wasm_bindgen] +pub async fn parse_string_message(message: Vec) -> Result { + if message.len() < 2 { + return Err(JsError::new("Could not parse message, as less than 2 bytes long")); + } + + let kind = message[0]; + let payload = String::from_utf8_lossy(&message[1..]).into_owned(); + + Ok(serde_wasm_bindgen::to_value(&StringMessage { + kind, + payload, + }).unwrap().unchecked_into::()) +} diff --git a/clients/webassembly/src/client/mod.rs b/clients/webassembly/src/client/mod.rs index 967f0323ff..c7765cf919 100644 --- a/clients/webassembly/src/client/mod.rs +++ b/clients/webassembly/src/client/mod.rs @@ -26,7 +26,7 @@ use nymsphinx::params::PacketSize; use rand::rngs::OsRng; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::spawn_local; -use wasm_utils::{console_log, console_warn}; +use wasm_utils::console_log; pub mod config; @@ -45,6 +45,7 @@ pub struct NymClient { // callbacks on_message: Option, + on_binary_message: Option, on_gateway_connect: Option, } @@ -56,6 +57,7 @@ impl NymClient { config, key_manager: Self::setup_key_manager(), on_message: None, + on_binary_message: None, on_gateway_connect: None, input_tx: None, } @@ -73,8 +75,11 @@ impl NymClient { self.on_message = Some(on_message); } + pub fn set_on_binary_message(&mut self, on_binary_message: js_sys::Function) { + self.on_binary_message = Some(on_binary_message); + } + pub fn set_on_gateway_connect(&mut self, on_connect: js_sys::Function) { - console_log!("setting on connect..."); self.on_gateway_connect = Some(on_connect) } @@ -267,6 +272,7 @@ impl NymClient { received_buffer_request_sender: ReceivedBufferRequestSender, ) { let on_message = self.on_message.take(); + let on_binary_message = self.on_binary_message.take(); spawn_local(async move { let (reconstructed_sender, mut reconstructed_receiver) = mpsc::unbounded(); @@ -281,8 +287,14 @@ impl NymClient { let this = JsValue::null(); while let Some(reconstructed) = reconstructed_receiver.next().await { - if let Some(ref callback) = on_message { - for msg in reconstructed { + for msg in reconstructed { + if let Some(ref callback_binary) = on_binary_message { + let arg1 = serde_wasm_bindgen::to_value(&msg.message).unwrap(); + callback_binary + .call1(&this, &arg1) + .expect("on binary message failed!"); + } + if let Some(ref callback) = on_message { if msg.reply_surb.is_some() { console_log!("the received message contained a reply-surb that we do not know how to handle (yet)") } @@ -290,9 +302,6 @@ impl NymClient { let arg1 = serde_wasm_bindgen::to_value(&stringified).unwrap(); callback.call1(&this, &arg1).expect("on message failed!"); } - } else { - console_warn!("no on_message callback was specified. the received message content is getting dropped"); - console_log!("the raw messages: {:?}", reconstructed) } } }); diff --git a/clients/webassembly/src/lib.rs b/clients/webassembly/src/lib.rs index fd18bec107..869b675829 100644 --- a/clients/webassembly/src/lib.rs +++ b/clients/webassembly/src/lib.rs @@ -3,6 +3,8 @@ use wasm_bindgen::prelude::*; +#[cfg(target_arch = "wasm32")] +pub mod binary_message_helper; #[cfg(target_arch = "wasm32")] mod client; #[cfg(target_arch = "wasm32")]