a7d8613c9d
* Feature/multi surbs (#1796) * bunch of wip with focus on serialization * Being able to send normal data (NO SURBS yet) to yourself again * Fixed RepliableMessage deserialization * Recovering data from surb messages * Extracted common code in sphinx payload construction * Cleanup within received buffer * requesting, sending and using additional reply surbs * Following discussion with @simonwicky, removing sender proof and decreasing size of sender tag * Made sender tag more easily configurable * Refactoring of message creation * Propagating reply surb acks but not retransmitting them yet * Surb retransmissions * requesting additional surbs from the retransmission flow * correctly determining the point of requesting additional surbs * Ability to use socks5 (and network requester) with surbs * Improved surbs retranmsission reliability * naive way of not over-requesting surbs * wip on tag storage * Improved error propagation for message construction * Requesting more surbs for stale entries * Better controlling the point of having to request additional surbs * Using pseudorandom sender tag instead of a hardcoded one * First cleanup round in MessageHandler * Error cleanup and if simplification * Assigned a more permanent name to the ReplyController * Removed PendingReply redundant type * Made socks5 client less eager to over-send reply surbs * 'anonymous' field on socks5 client to decide whether to use surbs or attach address * Dead code and import removal in client-core * Updating ClientRequest variants * Adjusted decision threshold for requesting more surbs * Native client cleanup * Made socks5 client usage of surbs configurable * Restored statistics in network requester * Validator-api compiles once again * Further improved surb request logic * boxing the recipient in controller requests * Removal of hardcoded values in favour of propagating them from the config * more validation during surb requests * Fixed ClientRequest::Send deserialization * Added length checks for request deserialization * post-merge formatting * Unit tests once again compile and pass * controlling retransmission_reply_surb_request_size from config * More Recipient boxing action * Requesting additional reply surbs for retransmission BEFORE dipping below the threshold * Making clippy generally happier * Wasm client compiles (but might not yet work correctly) * 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 * 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> * real_traffic_stream: reduce frequency of status print (#1794) * Properly defined unnamed errors * Dealing with previously ignored errors * logging improvements * Removed old example code Co-authored-by: Jon Häggblad <jon.haggblad@gmail.com> * Missing changelog entry for multi-surbs (#1802) * Making anonymous sender tag human readable (#1801) * Created wrapper with string serialization for AnonymousSenderTag * Using Display implementation of AnonymousSenderTag for logs * Using Display implementation of MessageRecoveryError when logging (#1803) * Using Display implementation of MessageRecoveryError when logging * Updated changelog * Defined socks5 client startup flag to enable reply-surb communication (#1804) * Feature/persistent surbs data (#1835) * prototyping wip * Implemented ReplyStorageBackend trait for the sql-backed storage * Storing correct surb threshold * using correct database path * Starting surb persistent storage in native and socks5 clients * loading or creating fresh surb storage in socks5 and native clients * making clippy happier + fixing config templates * Creating status table on database rotation * Completed the 'Empty' ReplyStorageBackend * feature locking wasm-incompatible bits and pieces * Feature/develop resync (#1844) * 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> * Making native client wait for shutdown * Marking dead test code * Feature/multi surbs invalidation (#1858) * Cleaned up RealMessagesController constructor * introduced config field for maximum_reply_surb_age * Handling edge-case reply-surb failures * invalidating old reply surbs * Removing old reply keys from cache * Invalidating old reply keys * missing config changes * logging created tag details * Fixed clippy warning in test code * Saving reply key timestamp on data flush (#1867) * Remove panic if ReconstructedMessagesReceiver is closed (#1868) Instead log error and return because presumably the shutdown procedure has started * Feature/multi surbs basic wasm interface (#1846) * Added builder to wasm client * missing wasm_bindgen macros * Added constructor macro on GatewayEndpointConfig * Attempting to use updated wasm client api * Removing dead code * Exposed other messages types in wasm client * cleanup in js-example * Changed 'self_address' to be a method call * Removed needless borrow when cloning an Arc * Improving arguments in 'on_message' callback * fixed wasm-client dependency/features * Reverted hard requirement for gateway protocol presence (#1875) * Feature/prioritise surb retransmission (#1883) * Improved error messages + removed redundant variants * Improved estimation of 'expected_forward_delay' * Removed old wasm-specific startup code * Removed old unused reply-related code * hacky and temporary way of buffering retransmission data * offloading retransmission reply handling to ReplyController * fixed linter errors + rebuffering retransmission data on failure * Removed unused fields from wasm client debug config * Chore/v1.2.0 update (#2666) * 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 * feat(wallet): buy page bootstrap * feat(wallet-buy): tutorial * feat(explorer-api): add route to fetch nym terms&cdts * Revert "feat(explorer-api): add route to fetch nym terms&cdts" This reverts commit 876f752697d89061b1904e1ddd1d5bcb7045dc5c. * feat(wallet-buy-nym): buy page new ui * fix(wallet-buy-nym): signature output * feat(wallet-buy-nym): update signature modal ui * 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) * feat(wallet): add link to nym exchange interface * update nym connect error text (#1809) * refactor(wallet): clean code * set flag to false * Fix wait_for_signal_and_error on win (#1811) * Use config URLs in clients before the env values (#1813) * 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 * Feature/dkg integration tests (#1815) * DKG contract e2e test * Refactor to the same format as other contracts * Vk share tests * State tests * Dealings tests * Dealer tests * Api dkg tests * Fix path to contract after refactor * Fix test target clippy * 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 * 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 * Fix a few errors in socks5 client and network-requester (backport) (#1824) * Fix two unwraps in socks5 and network-requester * Make sure client task never sends shutdown signal * nym-connect: update lock file * fix(wallet): typo * avoid mix tokens pools * fix(wallet): typo * fix(wallet): buy tutorial ui responsivness * 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 * Node family management (#1670) * Family management messages * Add family queries * Add queries to client * Layer assignment message * Paged family queries, annotate mixnodes with family * Add layer assignments to epoch operations * Remove family layer peristence * Add NotImplemented error for kick Co-authored-by: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com> * Fixed layer distribution skewness check (#1766) * client: add --no-cover and update --fastmode (#1831) * adding a oversaturaded bonding more modal * Use better naming on gateway credential handling (#1834) * Fix comment in configuration file (#1836) * common/task: extract out spawn_with_report_error (#1837) * nym-connect/changelog: add note about disconnect fix * Feature/simplify credential binary (#1841) * Expose name of standard directories * Use one command instead of two * nym-connect: append error to failed message (#1839) * nym-connect: append error to failed message * changelog: add note * Fix clippy * remove extra checks to display vesting schedule(#1826) * Set explorer to use rpc.nymtech.net * update versions for platfrom, nym-connect and nym-wallet to v1.1.2 * changed nym-connect version to 1.1.1 * Modifying changelog for v1.1.2 * changed nym-connect version to 1.1.2 * update nym-connect CHANGELOG * Updated changelog for wallet * Feature/wallet content updates (#1825) * fix up balance screen * fix up app bar and nym logo alignment * fix up delegation action icon font weight * fix up bond page * Corrected env variable name in workflows * Use config URLs in clients before the env values (#1813) * Feature/dkg integration tests (#1815) * DKG contract e2e test * Refactor to the same format as other contracts * Vk share tests * State tests * Dealings tests * Dealer tests * Api dkg tests * Fix path to contract after refactor * Fix test target clippy * Node family management (#1670) * Family management messages * Add family queries * Add queries to client * Layer assignment message * Paged family queries, annotate mixnodes with family * Add layer assignments to epoch operations * Remove family layer peristence * Add NotImplemented error for kick Co-authored-by: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com> * Fixed layer distribution skewness check (#1766) * Use better naming on gateway credential handling (#1834) * Fix comment in configuration file (#1836) * nym-connect/changelog: add note about disconnect fix * Feature/simplify credential binary (#1841) * Expose name of standard directories * Use one command instead of two * Fix clippy * feat(wallet): buy page bootstrap * feat(wallet-buy): tutorial * feat(explorer-api): add route to fetch nym terms&cdts * Revert "feat(explorer-api): add route to fetch nym terms&cdts" This reverts commit 876f752697d89061b1904e1ddd1d5bcb7045dc5c. * feat(wallet-buy-nym): buy page new ui * fix(wallet-buy-nym): signature output * feat(wallet-buy-nym): update signature modal ui * feat(wallet): add link to nym exchange interface * refactor(wallet): clean code * fix(wallet): typo * fix(wallet): typo * fix(wallet): buy tutorial ui responsivness * update versions for platfrom, nym-connect and nym-wallet to v1.1.2 * changed nym-connect version to 1.1.1 * Modifying changelog for v1.1.2 * changed nym-connect version to 1.1.2 * update nym-connect CHANGELOG * Updated changelog for wallet * Resolve merge conflicts * Update qa-qwerty.env * Fixed URL to branch * changed ubuntu-latest on GH actions to ubuntu-20.04 * docs: updated changelog for contracts release v1.1.2 and updated versions of mixnet and vesting contracts as well * Add ignore to dkg expensive tests (#1856) * introduce minimize button in custom title bar (#1843) * refresh balance after sending tokens (#1857) * Feature/fix client multi cred consume (#1859) * Mark consumed credentials in the db * Add signature log * Fix wasm mock Storage trait * Fix clippy * Feature/verify bte proof (#1866) * Update lock file * Include bte public key verification * Wallet - Buy, copy changes (#1855) * use mix_id for account to get correct pending cost event (#1869) * use mix_id for account to get correct pending cost event * Properly add consumed to table (#1870) * nym-connect: update Cargo.lock to 1.1.2 * Clients: save init results to JSON (#1865) * clients: output results of init to json * Remove leftover dbg * Tidy * Fix nym-connect * Client: dedup setup gateway during init (#1871) * clients: dedup gateway setup logic * nym-connect: extract out print_save_config * Feature/dkg state to disk (#1872) * Add PersistentState * Save and load state to/from disk * If in progress, don't continually write the same state * Fix tests and add serde one * Update changelog * Fix clippy * network-requester: return error on socket close (#1876) * network-requester: return error when the socket closes * changelog: add note * clients: further deduplicate init code (#1873) * client-core: move init helpers to module * WIP * socks5: return error instead of terminate in init * Extract out reuse_existing_gateway_config * rustfmt * Remove comment out code * nym-connect: use setup_gateway * Linebreak * changelog: update * Tweak log * rustfmt * client: pick from old lanes probabilisticlly (#1877) * Pick from old lanes probabilisticly * changelog: update * clients: dont panic in base client gateway client handling (#1878) * client-core: fix some panics related to gateway-client * changelog: update * fix * changelog: fix wording * Use default mainnet values when nothing is specified (#1884) 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: pierre <dommerc.pierre@gmail.com> 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> Co-authored-by: Drazen Urch <drazen@urch.eu> Co-authored-by: durch <durch@users.noreply.github.com> Co-authored-by: Tommy Verrall <60836166+tommyv1987@users.noreply.github.com> 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> Co-authored-by: pierre <dommerc.pierre@gmail.com> Co-authored-by: Drazen Urch <drazen@urch.eu> Co-authored-by: durch <durch@users.noreply.github.com> Co-authored-by: Tommy Verrall <60836166+tommyv1987@users.noreply.github.com>
492 lines
17 KiB
Rust
492 lines
17 KiB
Rust
// Copyright 2020-2022 - Nym Technologies SA <contact@nymtech.net>
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
use nymsphinx_addressing::clients::{Recipient, RecipientFormattingError};
|
|
use std::convert::TryFrom;
|
|
use thiserror::Error;
|
|
|
|
pub type ConnectionId = u64;
|
|
pub type RemoteAddress = String;
|
|
|
|
#[repr(u8)]
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub enum RequestFlag {
|
|
Connect = 0,
|
|
Send = 1,
|
|
}
|
|
|
|
impl TryFrom<u8> for RequestFlag {
|
|
type Error = RequestError;
|
|
|
|
fn try_from(value: u8) -> Result<RequestFlag, RequestError> {
|
|
match value {
|
|
_ if value == (RequestFlag::Connect as u8) => Ok(Self::Connect),
|
|
_ if value == (RequestFlag::Send as u8) => Ok(Self::Send),
|
|
_ => Err(RequestError::UnknownRequestFlag),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum RequestError {
|
|
#[error("not enough bytes to recover the length of the address")]
|
|
AddressLengthTooShort,
|
|
|
|
#[error("not enough bytes to recover the address")]
|
|
AddressTooShort,
|
|
|
|
#[error("not enough bytes to recover the connection id")]
|
|
ConnectionIdTooShort,
|
|
|
|
#[error("no data provided")]
|
|
NoData,
|
|
|
|
#[error("request of unknown type")]
|
|
UnknownRequestFlag,
|
|
|
|
#[error("too short return address")]
|
|
ReturnAddressTooShort,
|
|
|
|
#[error("malformed return address - {0}")]
|
|
MalformedReturnAddress(RecipientFormattingError),
|
|
}
|
|
|
|
impl RequestError {
|
|
pub fn is_malformed_return(&self) -> bool {
|
|
matches!(self, RequestError::MalformedReturnAddress(_))
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ConnectRequest {
|
|
// TODO: is connection_id redundant now?
|
|
pub conn_id: ConnectionId,
|
|
pub remote_addr: RemoteAddress,
|
|
pub return_address: Option<Recipient>,
|
|
}
|
|
|
|
/// A request from a SOCKS5 client that a Nym Socks5 service provider should
|
|
/// take an action for an application using a (probably local) Nym Socks5 proxy.
|
|
#[derive(Debug)]
|
|
pub enum Request {
|
|
/// Start a new TCP connection to the specified `RemoteAddress` and send
|
|
/// the request data up the connection.
|
|
/// All responses produced on this `ConnectionId` should come back to the specified `Recipient`
|
|
Connect(Box<ConnectRequest>),
|
|
|
|
/// Re-use an existing TCP connection, sending more request data up it.
|
|
Send(ConnectionId, Vec<u8>, bool),
|
|
}
|
|
|
|
impl Request {
|
|
/// Construct a new Request::Connect instance
|
|
pub fn new_connect(
|
|
conn_id: ConnectionId,
|
|
remote_addr: RemoteAddress,
|
|
return_address: Option<Recipient>,
|
|
) -> Request {
|
|
Request::Connect(Box::new(ConnectRequest {
|
|
conn_id,
|
|
remote_addr,
|
|
return_address,
|
|
}))
|
|
}
|
|
|
|
/// Construct a new Request::Send instance
|
|
pub fn new_send(conn_id: ConnectionId, data: Vec<u8>, local_closed: bool) -> Request {
|
|
Request::Send(conn_id, data, local_closed)
|
|
}
|
|
|
|
/// Deserialize the request type, connection id, destination address and port,
|
|
/// and the request body from bytes.
|
|
///
|
|
// TODO: this was already inaccurate
|
|
// /// Serialized bytes looks like this:
|
|
// ///
|
|
// /// --------------------------------------------------------------------------------------
|
|
// /// request_flag | connection_id | address_length | remote_address_bytes | request_data |
|
|
// /// 1 | 8 | 2 | address_length | ... |
|
|
// /// --------------------------------------------------------------------------------------
|
|
///
|
|
/// The request_flag tells us whether this is a new connection request (`new_connect`),
|
|
/// an already-established connection we should send up (`new_send`), or
|
|
/// a request to close an established connection (`new_close`).
|
|
pub fn try_from_bytes(b: &[u8]) -> Result<Request, RequestError> {
|
|
// each request needs to at least contain flag and ConnectionId
|
|
if b.is_empty() {
|
|
return Err(RequestError::NoData);
|
|
}
|
|
|
|
if b.len() < 9 {
|
|
return Err(RequestError::ConnectionIdTooShort);
|
|
}
|
|
let connection_id = u64::from_be_bytes([b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8]]);
|
|
match RequestFlag::try_from(b[0])? {
|
|
RequestFlag::Connect => {
|
|
let connect_request_bytes = &b[9..];
|
|
|
|
// we need to be able to read at least 2 bytes that specify address length
|
|
if connect_request_bytes.len() < 2 {
|
|
return Err(RequestError::AddressLengthTooShort);
|
|
}
|
|
|
|
let address_length =
|
|
u16::from_be_bytes([connect_request_bytes[0], connect_request_bytes[1]])
|
|
as usize;
|
|
|
|
if connect_request_bytes.len() < 2 + address_length {
|
|
return Err(RequestError::AddressTooShort);
|
|
}
|
|
|
|
let address_start = 2;
|
|
let address_end = address_start + address_length;
|
|
let address_bytes = &connect_request_bytes[address_start..address_end];
|
|
let remote_address = String::from_utf8_lossy(address_bytes).to_string();
|
|
|
|
// just a temporary reference to mid-slice for ease of use
|
|
let recipient_data_bytes = &connect_request_bytes[address_end..];
|
|
|
|
let return_address = if recipient_data_bytes.is_empty() {
|
|
None
|
|
} else {
|
|
if recipient_data_bytes.len() != Recipient::LEN {
|
|
return Err(RequestError::ReturnAddressTooShort);
|
|
}
|
|
|
|
let mut return_bytes = [0u8; Recipient::LEN];
|
|
return_bytes.copy_from_slice(&recipient_data_bytes[..Recipient::LEN]);
|
|
Some(
|
|
Recipient::try_from_bytes(return_bytes)
|
|
.map_err(RequestError::MalformedReturnAddress)?,
|
|
)
|
|
};
|
|
|
|
Ok(Request::new_connect(
|
|
connection_id,
|
|
remote_address,
|
|
return_address,
|
|
))
|
|
}
|
|
RequestFlag::Send => {
|
|
let local_closed = b[9] != 0;
|
|
let data = b[10..].to_vec();
|
|
|
|
Ok(Request::Send(connection_id, data, local_closed))
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Serialize a Socks5 request into bytes, so that it can be packed inside
|
|
/// a Sphinx packet, sent through the mixnet, and deserialized by the Socks5
|
|
/// service provider which will make the request.
|
|
pub fn into_bytes(self) -> Vec<u8> {
|
|
match self {
|
|
// connect is: CONN_FLAG || CONN_ID || REMOTE_LEN || REMOTE || RETURN
|
|
Request::Connect(req) => {
|
|
let remote_address_bytes = req.remote_addr.into_bytes();
|
|
let remote_address_bytes_len = remote_address_bytes.len() as u16;
|
|
|
|
let iter = std::iter::once(RequestFlag::Connect as u8)
|
|
.chain(req.conn_id.to_be_bytes().into_iter())
|
|
.chain(remote_address_bytes_len.to_be_bytes().into_iter())
|
|
.chain(remote_address_bytes.into_iter());
|
|
|
|
if let Some(return_address) = req.return_address {
|
|
iter.chain(return_address.to_bytes().into_iter()).collect()
|
|
} else {
|
|
iter.collect()
|
|
}
|
|
}
|
|
Request::Send(conn_id, data, local_closed) => std::iter::once(RequestFlag::Send as u8)
|
|
.chain(conn_id.to_be_bytes().into_iter())
|
|
.chain(std::iter::once(local_closed as u8))
|
|
.chain(data.into_iter())
|
|
.collect(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod request_deserialization_tests {
|
|
use super::*;
|
|
|
|
mod all_request_types {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn returns_error_when_zero_bytes() {
|
|
let request_bytes = Vec::new();
|
|
match Request::try_from_bytes(&request_bytes).unwrap_err() {
|
|
RequestError::NoData => {}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn returns_error_when_connection_id_too_short() {
|
|
let request_bytes = [RequestFlag::Connect as u8, 1, 2, 3, 4, 5, 6, 7].to_vec(); // 7 bytes connection id
|
|
match Request::try_from_bytes(&request_bytes).unwrap_err() {
|
|
RequestError::ConnectionIdTooShort => {}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod sending_data_over_a_new_connection {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn returns_error_when_address_length_is_too_short() {
|
|
let request_bytes1 = [RequestFlag::Connect as u8, 1, 2, 3, 4, 5, 6, 7, 8].to_vec(); // 8 bytes connection id, 0 bytes address length (2 were expected)
|
|
let request_bytes2 = [RequestFlag::Connect as u8, 1, 2, 3, 4, 5, 6, 7, 8, 0].to_vec(); // 8 bytes connection id, 1 bytes address length (2 were expected)
|
|
|
|
match Request::try_from_bytes(&request_bytes1).unwrap_err() {
|
|
RequestError::AddressLengthTooShort => {}
|
|
_ => unreachable!(),
|
|
}
|
|
|
|
match Request::try_from_bytes(&request_bytes2).unwrap_err() {
|
|
RequestError::AddressLengthTooShort => {}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn returns_error_when_address_too_short_for_given_address_length() {
|
|
let request_bytes = [RequestFlag::Connect as u8, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1].to_vec(); // 8 bytes connection id, 2 bytes address length, missing address
|
|
match Request::try_from_bytes(&request_bytes).unwrap_err() {
|
|
RequestError::AddressTooShort => {}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn returns_error_for_when_return_address_is_too_short() {
|
|
// this one has "foo.com" remote address and correct 8 bytes of connection_id
|
|
let request_bytes_prefix = [
|
|
RequestFlag::Connect as u8,
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
8,
|
|
0,
|
|
7,
|
|
102,
|
|
111,
|
|
111,
|
|
46,
|
|
99,
|
|
111,
|
|
109,
|
|
];
|
|
|
|
let recipient = Recipient::try_from_base58_string("CytBseW6yFXUMzz4SGAKdNLGR7q3sJLLYxyBGvutNEQV.4QXYyEVc5fUDjmmi8PrHN9tdUFV4PCvSJE1278cHyvoe@4sBbL1ngf1vtNqykydQKTFh26sQCw888GpUqvPvyNB4f").unwrap();
|
|
let recipient_bytes = recipient.to_bytes();
|
|
|
|
// take only part of actual recipient
|
|
let request_bytes: Vec<_> = request_bytes_prefix
|
|
.iter()
|
|
.cloned()
|
|
.chain(recipient_bytes.iter().take(40).cloned())
|
|
.collect();
|
|
|
|
match Request::try_from_bytes(&request_bytes).unwrap_err() {
|
|
RequestError::ReturnAddressTooShort => {}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn returns_error_for_when_return_address_is_malformed() {
|
|
// this one has "foo.com" remote address and correct 8 bytes of connection_id
|
|
let request_bytes_prefix = [
|
|
RequestFlag::Connect as u8,
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
8,
|
|
0,
|
|
7,
|
|
102,
|
|
111,
|
|
111,
|
|
46,
|
|
99,
|
|
111,
|
|
109,
|
|
];
|
|
|
|
let recipient = Recipient::try_from_base58_string("CytBseW6yFXUMzz4SGAKdNLGR7q3sJLLYxyBGvutNEQV.4QXYyEVc5fUDjmmi8PrHN9tdUFV4PCvSJE1278cHyvoe@4sBbL1ngf1vtNqykydQKTFh26sQCw888GpUqvPvyNB4f").unwrap();
|
|
let mut recipient_bytes = recipient.to_bytes();
|
|
|
|
// mess up few bytes
|
|
recipient_bytes[0] = 255;
|
|
recipient_bytes[15] ^= 1;
|
|
recipient_bytes[31] ^= 1;
|
|
|
|
let request_bytes: Vec<_> = request_bytes_prefix
|
|
.iter()
|
|
.cloned()
|
|
.chain(recipient_bytes.into_iter())
|
|
.collect();
|
|
assert!(Request::try_from_bytes(&request_bytes)
|
|
.unwrap_err()
|
|
.is_malformed_return());
|
|
}
|
|
|
|
#[test]
|
|
fn works_when_request_is_sized_properly_even_without_data() {
|
|
// this one has "foo.com" remote address, correct 8 bytes of connection_id, and 0 bytes request data
|
|
let request_bytes = [
|
|
RequestFlag::Connect as u8,
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
8,
|
|
0,
|
|
7,
|
|
102,
|
|
111,
|
|
111,
|
|
46,
|
|
99,
|
|
111,
|
|
109,
|
|
]
|
|
.to_vec();
|
|
|
|
let recipient = Recipient::try_from_base58_string("CytBseW6yFXUMzz4SGAKdNLGR7q3sJLLYxyBGvutNEQV.4QXYyEVc5fUDjmmi8PrHN9tdUFV4PCvSJE1278cHyvoe@4sBbL1ngf1vtNqykydQKTFh26sQCw888GpUqvPvyNB4f").unwrap();
|
|
let recipient_bytes = recipient.to_bytes();
|
|
|
|
let request_bytes: Vec<_> = request_bytes
|
|
.into_iter()
|
|
.chain(recipient_bytes.into_iter())
|
|
.collect();
|
|
|
|
let request = Request::try_from_bytes(&request_bytes).unwrap();
|
|
match request {
|
|
Request::Connect(req) => {
|
|
assert_eq!("foo.com".to_string(), req.remote_addr);
|
|
assert_eq!(u64::from_be_bytes([1, 2, 3, 4, 5, 6, 7, 8]), req.conn_id);
|
|
assert_eq!(
|
|
req.return_address.unwrap().to_bytes().to_vec(),
|
|
recipient.to_bytes().to_vec()
|
|
);
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn works_when_request_is_sized_properly_and_has_data() {
|
|
// this one has a 1-byte remote address, correct 8 bytes of connection_id, and 3 bytes request data
|
|
let request_bytes = [
|
|
RequestFlag::Connect as u8,
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
8,
|
|
0,
|
|
7,
|
|
102,
|
|
111,
|
|
111,
|
|
46,
|
|
99,
|
|
111,
|
|
109,
|
|
]
|
|
.to_vec();
|
|
|
|
let recipient = Recipient::try_from_base58_string("CytBseW6yFXUMzz4SGAKdNLGR7q3sJLLYxyBGvutNEQV.4QXYyEVc5fUDjmmi8PrHN9tdUFV4PCvSJE1278cHyvoe@4sBbL1ngf1vtNqykydQKTFh26sQCw888GpUqvPvyNB4f").unwrap();
|
|
let recipient_bytes = recipient.to_bytes();
|
|
|
|
let request_bytes: Vec<_> = request_bytes
|
|
.into_iter()
|
|
.chain(recipient_bytes.into_iter())
|
|
.collect();
|
|
|
|
let request = Request::try_from_bytes(&request_bytes).unwrap();
|
|
match request {
|
|
Request::Connect(req) => {
|
|
assert_eq!("foo.com".to_string(), req.remote_addr);
|
|
assert_eq!(u64::from_be_bytes([1, 2, 3, 4, 5, 6, 7, 8]), req.conn_id);
|
|
assert_eq!(
|
|
req.return_address.unwrap().to_bytes().to_vec(),
|
|
recipient.to_bytes().to_vec()
|
|
);
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod sending_additional_data_over_an_existing_connection {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn works_when_request_is_sized_properly_even_without_data() {
|
|
// correct 8 bytes of connection_id, 1 byte of local_closed and 0 bytes request data
|
|
let request_bytes = [RequestFlag::Send as u8, 1, 2, 3, 4, 5, 6, 7, 8, 0].to_vec();
|
|
let request = Request::try_from_bytes(&request_bytes).unwrap();
|
|
match request {
|
|
Request::Send(conn_id, data, local_closed) => {
|
|
assert_eq!(u64::from_be_bytes([1, 2, 3, 4, 5, 6, 7, 8]), conn_id);
|
|
assert_eq!(Vec::<u8>::new(), data);
|
|
assert!(!local_closed)
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn works_when_request_is_sized_properly_and_has_data() {
|
|
// correct 8 bytes of connection_id, 1 byte of local_closed and 3 bytes request data (all 255)
|
|
let request_bytes = [
|
|
RequestFlag::Send as u8,
|
|
1,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
8,
|
|
0,
|
|
255,
|
|
255,
|
|
255,
|
|
]
|
|
.to_vec();
|
|
|
|
let request = Request::try_from_bytes(&request_bytes).unwrap();
|
|
match request {
|
|
Request::Send(conn_id, data, local_closed) => {
|
|
assert_eq!(u64::from_be_bytes([1, 2, 3, 4, 5, 6, 7, 8]), conn_id);
|
|
assert_eq!(vec![255, 255, 255], data);
|
|
assert!(!local_closed)
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
}
|