4578cda0ae
* Network-requester: throttle inbound connections (#1789) * Return and handle ClientRequest::LaneQueueLenghts * Pass lane queue lengths to inbound future * Remove unused self reference * Request lane queue lengths periodically for all open connections * Add timeouts * Rename to ConnectionCommandSender and Receiver * Rename to client_connection_tx/rx * Fix wasm build * Replace bool with enum * rust: bump required version to 1.65 in some crates that need it * Add step to release GH actions (#1792) * feat: add a release step to nym contracts GH action * feat: add shrinking the size of wasm * Possibilty to change gateway ws listener (#1779) * add: set gatewayListener * Update types.ts * Update worker.ts * Update contracts-build.yml * real_traffic_stream: reduce frequency of status print (#1794) * Update wallet and connect lock files (#1793) * client-core: add warning when delay multiplier is larger than 1 * Fix decrypting stored received msg (#1786) * Fix decrypting stored received msg * rustfmt * Moving binary message recovery to separate function Co-authored-by: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com> * Feature/use expect instead of panicking (#1797) * Implementation of 'Debug' on 'RealMessage' * expect with failed channel name instead of throwing empty panics * Introduced Debug trait constraint in ProxyRunner * Derive Debug for socks5_requests::Message * Make connection_id optional in ClientRequest::Send (#1798) * changelog: add missing entry for fixing message decrypt in gateway-client * websocket-requests: fix length check before deserialize (#1799) * Fix export dkg contract addr (#1800) * Export dkg contract for mainnet when no config file present * Remove redundant env files * nym-cli: improve error reporting/handling and changed `vesting-schedule` queries to use query client instead of signing client * Feature/gateway client protocol version (#1795) * Introducing concept of gateway protocol version * Remove version-based gateway filtering * Fixed the unit test * grammar * Set build on latest release on schedule event * Added nightly build workflow on second latest release * socks5: if any task panics, signal all other tasks to shutdown (#1805) * socks5: signal shutdown on error * Mark as success * Tidy * Reduce wait to 5 sec * Replace unwrap with expect * Two more unwraps * Update changelog * client-core: less frequent status logging (#1806) * Feature/nym connect UI updates (#1784) * create custom titlebar * create help page * create generic modal component * create separate connection time component * link to shipyard docs * move timer to separate component and update connection status component usage * use separate component for copying ip and port details * only show infomodal once after connection * set service provider on tauri side * Emit events when stopped * listen and unlisten for tauri events * connect: add trace log to get_services * Add back CI notifications * Update README Co-authored-by: Jon Häggblad <jon.haggblad@gmail.com> Co-authored-by: Mark Sinclair <14054343+mmsinclair@users.noreply.github.com> * Use default serde value for upgrade (#1807) * fix ui overflow bug (#1808) * update nym connect error text (#1809) * set flag to false * Fix wait_for_signal_and_error on win (#1811) * Add socks5-client changes to nym-connect changelog * Fix links in nym-connect changelog * More entries in nym-connect CHANGELOG * Fix typo in changelog * Update CHANGELOG.md * Experiment/client refactoring (#1814) * experimenting with extracting more common client code * drying up the wasm client * allowing some dead code for the time being * fixed formatting in nym-connect * made socks5 client inside nym-connect immutable * made clippy a bit happier * hidden away target locking for recv timeout * New transactions for increasing amount of pledged tokens * unit tests * Added an option to pledge extra tokens through the vesting contract * Introduced wallet endpoints for new operations * Using updated pledge cap in the vesting contract * Bumping version numbers * Changelog for v1.1.1 * Bumping final version numbers for 1.1.1 * Bumping nym-cli version, missed it last time * socks5-client: SOCKS4a support (#1822) * socks5-client: SOCKS4a support * Tidy * Fix a few errors in socks5 client and network-requester (#1823) * Fix two unwraps in socks5 and network-requester * Make sure client task never sends shutdown signal * Fix panic on getting socks version * wip * connecting to the back and making the requests work * display details modal * logs removal * Feature/pledge more (#1679) * New transactions for increasing amount of pledged tokens * unit tests * Added an option to pledge extra tokens through the vesting contract * Introduced wallet endpoints for new operations * Using updated pledge cap in the vesting contract * Changelog update * nym-connect: update lock file * avoid mix tokens pools * amount error * envs/mainnet: update to latest mixnet contract and nymd validator url * validator-api: add missing shortform for --config-env-file (#1830) * gateway-client: handle shutdown listener (#1829) * WIP * WIP: try another approach * WIP * Reworked * Tidy * fix * validator-api: remove storage dependency in contract cache (#1685) * validator-api: remove storage dependency in contract cache * validator-client: update detailed routes * contract_cache: forward to new endpoints for compat * Move reward_estimate * client: add --no-cover and update --fastmode (#1831) * adding a oversaturaded bonding more modal * common/task: extract out spawn_with_report_error (#1837) * stop panic on failed buffer request * Compilable wasm client * Enabled hard error on lack of gateway-client protocol version * Missing generic parameter for ClientCoreError in BackendError * Removed unused imports * Additional wasm feature locking Co-authored-by: Jon Häggblad <jon.haggblad@gmail.com> Co-authored-by: Fran Arbanas <arbanasfran@gmail.com> Co-authored-by: cgi-bin/ <6095048+sven-hash@users.noreply.github.com> Co-authored-by: Mark Sinclair <14054343+mmsinclair@users.noreply.github.com> Co-authored-by: Bogdan-Ștefan Neacşu <bogdan@nymtech.net> Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com> Co-authored-by: Raphaël Walther <raphael@nymtech.net> Co-authored-by: Fouad <fmtabbara@hotmail.co.uk> Co-authored-by: Gala <calero.vg@gmail.com> Co-authored-by: Dave Hrycyszyn <futurechimp@users.noreply.github.com>
199 lines
7.3 KiB
Rust
199 lines
7.3 KiB
Rust
// Copyright 2021-2022 - Nym Technologies SA <contact@nymtech.net>
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
use self::config::Config;
|
|
use crate::client::response_pusher::ResponsePusher;
|
|
use client_connections::TransmissionLane;
|
|
use client_core::client::base_client::{BaseClientBuilder, ClientInput, ClientOutput};
|
|
use client_core::client::replies::reply_storage::browser_backend;
|
|
use client_core::client::{inbound_messages::InputMessage, key_manager::KeyManager};
|
|
use crypto::asymmetric::identity;
|
|
use nymsphinx::addressing::clients::Recipient;
|
|
use rand::rngs::OsRng;
|
|
use task::ShutdownNotifier;
|
|
use wasm_bindgen::prelude::*;
|
|
use wasm_utils::{console_error, console_log};
|
|
|
|
pub mod config;
|
|
mod response_pusher;
|
|
|
|
#[wasm_bindgen]
|
|
pub struct NymClient {
|
|
config: Config,
|
|
|
|
/// KeyManager object containing smart pointers to all relevant keys used by the client.
|
|
// due to disgusting workaround I had to wrap the below in an Option
|
|
// so that the interface wouldn't change (i.e. both `start` and `new` would still return a `NymClient`)
|
|
key_manager: Option<KeyManager>,
|
|
self_address: Option<String>,
|
|
storage_backend: Option<browser_backend::Backend>,
|
|
|
|
// TODO: this should be stored somewhere persistently
|
|
// received_keys: HashSet<SURBEncryptionKey>,
|
|
/// Channel used for transforming 'raw' messages into sphinx packets and sending them
|
|
/// through the mix network.
|
|
client_input: Option<ClientInput>,
|
|
|
|
// callbacks
|
|
on_message: Option<js_sys::Function>,
|
|
on_binary_message: Option<js_sys::Function>,
|
|
on_gateway_connect: Option<js_sys::Function>,
|
|
|
|
// even though we don't use graceful shutdowns, other components rely on existence of this struct
|
|
// and if it's dropped, everything will start going offline
|
|
_shutdown: Option<ShutdownNotifier>,
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
impl NymClient {
|
|
#[wasm_bindgen(constructor)]
|
|
pub fn new(config: Config) -> Self {
|
|
Self {
|
|
storage_backend: Some(Self::setup_reply_surb_storage_backend(&config)),
|
|
config,
|
|
key_manager: Some(Self::setup_key_manager()),
|
|
on_message: None,
|
|
on_binary_message: None,
|
|
on_gateway_connect: None,
|
|
client_input: None,
|
|
self_address: None,
|
|
_shutdown: None,
|
|
}
|
|
}
|
|
|
|
// TODO: once we make keys persistent, we'll require some kind of `init` method to generate
|
|
// a prior shared keypair between the client and the gateway
|
|
|
|
// perhaps this should be public?
|
|
fn setup_key_manager() -> KeyManager {
|
|
let mut rng = OsRng;
|
|
// for time being generate new keys each time...
|
|
console_log!("generated new set of keys");
|
|
KeyManager::new(&mut rng)
|
|
}
|
|
|
|
// don't get too excited about the name, under the hood it's just a big fat placeholder
|
|
// with no persistence
|
|
fn setup_reply_surb_storage_backend(config: &Config) -> browser_backend::Backend {
|
|
browser_backend::Backend::new(
|
|
config.debug.minimum_reply_surb_storage_threshold,
|
|
config.debug.maximum_reply_surb_storage_threshold,
|
|
)
|
|
}
|
|
|
|
pub fn set_on_message(&mut self, on_message: js_sys::Function) {
|
|
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) {
|
|
self.on_gateway_connect = Some(on_connect)
|
|
}
|
|
|
|
fn as_mix_recipient(&self) -> Recipient {
|
|
// another disgusting (and hopefully temporary) workaround
|
|
let key_manager_ref = self
|
|
.key_manager
|
|
.as_ref()
|
|
.expect("attempting to call 'as_mix_recipient' after 'start'");
|
|
|
|
Recipient::new(
|
|
*key_manager_ref.identity_keypair().public_key(),
|
|
*key_manager_ref.encryption_keypair().public_key(),
|
|
identity::PublicKey::from_base58_string(&self.config.gateway_endpoint.gateway_id)
|
|
.expect("no gateway has been selected"),
|
|
)
|
|
}
|
|
|
|
pub fn self_address(&self) -> String {
|
|
if let Some(address) = &self.self_address {
|
|
address.clone()
|
|
} else {
|
|
self.as_mix_recipient().to_string()
|
|
}
|
|
}
|
|
|
|
// Right now it's impossible to have async exported functions to take `&mut self` rather than mut self
|
|
// TODO: try Rc<RefCell<Self>> approach?
|
|
pub async fn send_message(self, message: String, recipient: String) -> Self {
|
|
console_log!("Sending {} to {}", message, recipient);
|
|
|
|
let message_bytes = message.into_bytes();
|
|
self.send_binary_message(message_bytes, recipient).await
|
|
}
|
|
|
|
pub async fn send_binary_message(self, message: Vec<u8>, recipient: String) -> Self {
|
|
console_log!("Sending {} bytes to {}", message.len(), recipient);
|
|
|
|
let recipient = Recipient::try_from_base58_string(recipient).unwrap();
|
|
let lane = TransmissionLane::General;
|
|
|
|
let input_msg = InputMessage::new_regular(recipient, message, lane);
|
|
|
|
self.client_input
|
|
.as_ref()
|
|
.expect("start method was not called before!")
|
|
.input_sender
|
|
.send(input_msg)
|
|
.await
|
|
.expect("InputMessageReceiver has stopped receiving!");
|
|
|
|
self
|
|
}
|
|
|
|
fn start_reconstructed_pusher(
|
|
client_output: ClientOutput,
|
|
on_message: Option<js_sys::Function>,
|
|
on_binary_message: Option<js_sys::Function>,
|
|
) {
|
|
ResponsePusher::new(client_output, on_message, on_binary_message).start()
|
|
}
|
|
|
|
pub async fn start(mut self) -> NymClient {
|
|
console_log!("Starting the wasm client");
|
|
|
|
let base_builder = BaseClientBuilder::new(
|
|
&self.config.gateway_endpoint,
|
|
&self.config.debug,
|
|
self.key_manager.take().unwrap(),
|
|
None,
|
|
self.storage_backend.take().unwrap(),
|
|
true,
|
|
vec![self.config.validator_api_url.clone()],
|
|
);
|
|
|
|
self.self_address = Some(base_builder.as_mix_recipient().to_string());
|
|
let mut started_client = match base_builder.start_base().await {
|
|
Ok(base_client) => base_client,
|
|
Err(err) => {
|
|
console_error!("failed to start base client components - {}", err);
|
|
// proper error handling is left here as an exercise for the reader (hi Mark : ))
|
|
panic!("failed to start base client components - {err}")
|
|
}
|
|
};
|
|
match self.on_gateway_connect.as_ref() {
|
|
Some(callback) => {
|
|
callback
|
|
.call0(&JsValue::null())
|
|
.expect("on connect callback failed!");
|
|
}
|
|
None => console_log!("Gateway connection established - no callback specified"),
|
|
};
|
|
|
|
// those should be moved to a completely different struct, but I don't want to break compatibility for now
|
|
let client_input = started_client.client_input.register_producer();
|
|
let client_output = started_client.client_output.register_consumer();
|
|
|
|
let on_message = self.on_message.take();
|
|
let on_binary_message = self.on_binary_message.take();
|
|
Self::start_reconstructed_pusher(client_output, on_message, on_binary_message);
|
|
self.client_input = Some(client_input);
|
|
self._shutdown = Some(started_client.shutdown_notifier);
|
|
|
|
self
|
|
}
|
|
}
|