d6599b2933
* started todo list for rework * startd long todo list * startd long todo list * remove ts docs from ts sdk dir * started new docs draft * rearranged code example dir structure * modified code component filepaths * first pass rust sdk * small shift typescript org * updated todo list * consolidating images folders in one place * first pass @ operator docs * gen updates * sdk in its own dir * first pass developers structure * first pass network structure * structure * add licensing * moved old docs -> old_docs dir for clarity when devving * moving around new docs - think this is the final dir structure * updated todo list * new autodoc version (#4781) * Update rework_todo.md * quick first sketch of landing page * rework of structure of developers * added arch and concepts stubs * add new bits to todo list * new list * tweak to overview * mixnet node overview * tweak overview * first pass new arch * first pass concepts * first pass traffic * more network docs * moved some chain files to the dev portal stubs * removed old reference to archive * note to client * concepts 2nd pass * crypto first proper pass, sphinx * stub for not p2p * structure change * traffic 2nd pass * misc * hid root index * overhaul arch * overhaul arch * add links + tweaks * update todo list * updating nyx section * added zknym docs * added zknym docs * note on where to find deployed info * smart contracts done * started moving integrations docs over from ts sdk * pass @ integration page * todo for the tldr overview * added ffi stub files * updated todo list * move sdks to developers * initial pass at new clients overview for developers * rework intro * add echo serv to tools * sidebar autocollapse * integration overview work + tools * concepts overview for devporta * stub * more for networking pages * added to concepts in dev portal * updated arch * crypto overview page * typo fix * add credential stub * first pass concepts done * start reorg of rust sdk docs * reorg + added FFI table * added no scroll to inline code * finished ffi overview page * first pass @ rest of rust sdk doc * first pass ffi * tweaks * added testnet example + note to custom topology example overview * stripped unnecessary stuff from TS * tweaks to ffi * updated faq * first pass tcpproxy * commit before moving image dir * moved images/ to correct place * started on client redo * chain first pass * moved cli wallet out of tools * first pass new ws client * new chain info, left todo links in * links * more links * chain registry * added echo server to tools * rust sdk links * ts sdk links * final linkchecks * redo acks diagram as mermaid * add mermaid flow diagram * added links for codecs + full flow diagram * removed todo * remove forced dark mode * diagram + concepts overview * small correction re tcpproxy ffi * remove diagram title * new sock5 diagram, minor client docs tweaks * diagrams * change order in list * added note for standalone: can be accessed via sdk * tweaks * replaced old diagram with mermaid * fixed link * hardcoded import version for the moment * update deps * remove test component * recreated tools dir * remove tools dir moved to wrong palce * prebuild and predev script for autodoc commands * make script own command instead of prebuild * made code blocks sh * updated autogenerated docs * temp * auto commit generated command files * add link to autodoc generated files * updated autodoc for committing changing else exit * auto commit generated command files * updated readme * make subcommand headers smaller * removed mdbook related scripts * update readme * update readme * removed backups of root meta.json * cherry pick yana commits + some extra config in theme * update readme * update theme: width of page and padding * some more themeing * changed erroneous note * docs redirects first pass * tweaking * new pages + rest of redirects for old docs/ * brought in archive + done rewrites for devportal * cherry pick yana landingpage * tweaked landing page component * changed theme of mermaid diagram to match everything else * updated todo list * [DOCs]: Operators rework to next.js (#4930) * initialise operators guides v2 * new introduction page * add variables csv and page * add baseurl to allow short path * add sandbox page * added building from source page * add binary pages * add preliminary steps * clean preliminary steps dir * syntax edit * syntax edit * add configuration page * create new proxy configuration page * create new proxy configuration page * create bonding.mdx page * correct images path * syntax edit * add new validator setup page * add api setup page * add nyx configuration page * add nym node and maintenance pages * finish maintenance and add nymvisor conf page * add manual upgrade page * add nymvisor upgrade page * add performance testing page and dir * add node api check page * add explore nym scripts page * add testing pages * fix menu issue by moving snippets to coomponents * add all troubleshooting pages * add general faq page * add nym node faq page * add nyx faq page * revamp legal forum to community counsel and add all pages * rewire relative paths to new structure * simplify setup and remove lock file * syntax fix * rm package.json * re add package.json, rm package-lock.json * removed old books from commit * address review comments --------- Co-authored-by: mfahampshire <maxhampshire@pm.me> Co-authored-by: mx <33262279+mfahampshire@users.noreply.github.com> * tweak client links * also moved matrix images to correct place * Max/fix links new docs framework (#4989) * tweak client links * standardise images in public/ * old images move to public/archive * rename overview to more descriptive * links (#4990) * links * removed todos * updated todo list * minor themeing * operator redirects * pick yana's edits: remove specified callout theming * added todo comments for old ts sdk redirects * [new/docs/operators]: Create archive section - PR ready to merge (#5004) * [new-docs/operators] : Fix callout syntax (#5006) * fix callout syntax from color to type * correct callout from danger to warning * update footer * updated footer * finalised rewrites * tweaks to clients and reintroduced old examples page * update todo * Max/individual command autodocs (#5015) * auto commit generated command files * added to autodoc.sh: build all binaries before running * autodoc move individual command outputs to components * Max/individual command autodocs (#5018) * updated autodoc script * updated autodoc script for fix + reintroduced gitignore file for generated markdown * auto commit generated command files * auto commit generated command files * added command-outputs to autodoc script * fix merge conflicts * repush components * remove old docs dirs * auto commit generated command files * auto commit generated command files * updated messages paradigm with the standalone proxies * [NEW-DOCs/operators]: Command output, accordion, api scraping & all final tasks (#5026) * add custom scripts, create prebuild to import data to pages * update after latest prebuild * auto commit generated command files * add accordion component * add changbelog page * add node_api_check outputs * finish all command outputs * more accordions beautifications * finish accordion * PR ready to go * address review comments --------- Co-authored-by: mfahampshire <maxhampshire@pm.me> * Adjust padding * Fix responsive design * cherry pick yana landingpage flex update * reremove old docs * added dependencies to readme * pushing build attempt changes * fix merge errors, path errors, dump uselss dinosaurs - BUILT THE F*N DOCS w success * moved prebuild to its own script * generate timenow * auto commit generated command files * remove comment * auto commit generated command files * auto commit generated command files * auto commit generated command files * build from new configs * add mdx type as explicit dep * remove rc from version in package * change predev script * update readme with scripts * update general info * add license * auto commit generated command files * add updated components * removed old examples page for the moment * remove old list will reintroduce hidden behind gitignore for future * reintroduce todo list behind gitignore * added standalone tcpproxy binary info * nothing change for redeploy test * make build standalone * updated readme * working on new cd * remove export * updated ci/cd for docs * added ci script for dist * hide text on laptop wide screen * add pnpm to ci/cd * add pnpm version to ci/cd * add default dir to ci/cd * change path to script * update projct name ci * lint ci branch ignore * add basePath to next.config.js * update doc rewrites * revert basePath addition * update basePath * add mobile styles * fix responsive style * remove old ts sdk docs workflow * temp remove autodoc from workspace * update sidebar for clarity: crypto = cryptography * ignore documentation in pr-validation workflow --------- Co-authored-by: Yana <yanok87@users.noreply.github.com> Co-authored-by: import this <97586125+serinko@users.noreply.github.com> Co-authored-by: fmtabbara <fmtabbara@hotmail.co.uk>
155 lines
7.2 KiB
Plaintext
155 lines
7.2 KiB
Plaintext
# Multi Connection Example
|
|
|
|
This example starts off several Tcp connections on a loop to a remote endpoint: in this case the `TcpListener` behind the `NymProxyServer` instance on the echo server found in
|
|
[`nym/tools/echo-server/`](https://github.com/nymtech/nym/tree/develop/tools/echo-server). It pipes a few messages to it, logs the replies, and keeps track of the number of replies received per connection.
|
|
|
|
> You can find this code [here](https://github.com/nymtech/nym/blob/develop/sdk/rust/nym-sdk/examples/tcp_proxy_multistream.rs)
|
|
|
|
```rust
|
|
use nym_sdk::mixnet::Recipient;
|
|
use nym_sdk::tcp_proxy;
|
|
use rand::rngs::SmallRng;
|
|
use rand::Rng;
|
|
use rand::SeedableRng;
|
|
use serde::{Deserialize, Serialize};
|
|
use std::env;
|
|
use tokio::io::AsyncWriteExt;
|
|
use tokio::net::TcpStream;
|
|
use tokio::signal;
|
|
use tokio_stream::StreamExt;
|
|
use tokio_util::codec;
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
struct ExampleMessage {
|
|
message_id: i8,
|
|
message_bytes: Vec<u8>,
|
|
tcp_conn: i8,
|
|
}
|
|
|
|
// To run:
|
|
// - run the echo server with `cargo run`
|
|
// - run this example with `cargo run --example tcp_proxy_multistream -- <ECHO_SERVER_NYM_ADDRESS> <ENV_FILE_PATH> <CLIENT_PORT>` e.g.
|
|
// cargo run --example tcp_proxy_multistream -- DMHyxo8n6sKWHHTVvjRVDxDSMX8gYXRU1AQ6UpwsrWiB.6STYCWGWyRxqn2juWdgjMkAMsT9EaAzPpLWq5zkS68MB@CJG5zTcmoLijmDrtAiLV9PZHxNz8LQu6hmgA89V2RxxL ../../../envs/canary.env 8080
|
|
#[tokio::main]
|
|
async fn main() -> anyhow::Result<()> {
|
|
let server_address = env::args().nth(1).expect("Server address not provided");
|
|
let server: Recipient =
|
|
Recipient::try_from_base58_string(&server_address).expect("Invalid server address");
|
|
|
|
// Comment this out to just see println! statements from this example.
|
|
// Nym client logging is very informative but quite verbose.
|
|
// The Message Decay related logging gives you an ideas of the internals of the proxy message ordering: you need to switch
|
|
// to DEBUG to see the contents of the msg buffer, sphinx packet chunking, etc.
|
|
tracing_subscriber::fmt()
|
|
.with_max_level(tracing::Level::INFO)
|
|
.init();
|
|
|
|
let env_path = env::args().nth(2).expect("Env file not specified");
|
|
let env = env_path.to_string();
|
|
|
|
let listen_port = env::args().nth(3).expect("Port not specified");
|
|
|
|
// Within the TcpProxyClient, individual client shutdown is triggered by the timeout.
|
|
let proxy_client =
|
|
tcp_proxy::NymProxyClient::new(server, "127.0.0.1", &listen_port, 45, Some(env)).await?;
|
|
|
|
tokio::spawn(async move {
|
|
proxy_client.run().await?;
|
|
Ok::<(), anyhow::Error>(())
|
|
});
|
|
|
|
println!("waiting for everything to be set up..");
|
|
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
|
println!("done. sending bytes");
|
|
|
|
// In the info traces you will see the different session IDs being set up, one for each TcpStream.
|
|
for i in 0..4 {
|
|
let conn_id = i;
|
|
println!("Starting TCP connection {}", conn_id);
|
|
let local_tcp_addr = format!("127.0.0.1:{}", listen_port.clone());
|
|
tokio::spawn(async move {
|
|
// Now the client and server proxies are running we can create and pipe traffic to/from
|
|
// a socket on the same port as our ProxyClient instance as if we were just communicating
|
|
// between a client and host via a normal TcpStream - albeit with a decent amount of additional latency.
|
|
//
|
|
// The assumption regarding integration is that you know what you're sending, and will do proper
|
|
// framing before and after, know what data types you're expecting; the proxies are just piping bytes
|
|
// back and forth using tokio's `Bytecodec` under the hood.
|
|
|
|
let stream = TcpStream::connect(local_tcp_addr).await?;
|
|
let (read, mut write) = stream.into_split();
|
|
|
|
// Lets just send a bunch of messages to the server with variable delays between them, with a message and tcp connection ids to keep track of ordering on the server side (for illustrative purposes **only**; keeping track of anonymous replies is handled by the proxy under the hood with Single Use Reply Blocks (SURBs); for this illustration we want some kind of app-level message id, but irl most of the time you'll probably be parsing on e.g. the incoming response type instead)
|
|
tokio::spawn(async move {
|
|
for i in 0..4 {
|
|
let mut rng = SmallRng::from_entropy();
|
|
let delay: f64 = rng.gen_range(2.5..5.0);
|
|
tokio::time::sleep(tokio::time::Duration::from_secs_f64(delay)).await;
|
|
let random_bytes = gen_bytes_fixed(i as usize);
|
|
let msg = ExampleMessage {
|
|
message_id: i,
|
|
message_bytes: random_bytes,
|
|
tcp_conn: conn_id,
|
|
};
|
|
let serialised = bincode::serialize(&msg)?;
|
|
write
|
|
.write_all(&serialised)
|
|
.await
|
|
.expect("couldn't write to stream");
|
|
println!(
|
|
">> client sent {}: {} bytes on conn {}",
|
|
&i,
|
|
msg.message_bytes.len(),
|
|
&conn_id
|
|
);
|
|
}
|
|
Ok::<(), anyhow::Error>(())
|
|
});
|
|
|
|
tokio::spawn(async move {
|
|
let mut reply_counter = 0;
|
|
let codec = codec::BytesCodec::new();
|
|
let mut framed_read = codec::FramedRead::new(read, codec);
|
|
while let Some(Ok(bytes)) = framed_read.next().await {
|
|
match bincode::deserialize::<ExampleMessage>(&bytes) {
|
|
Ok(msg) => {
|
|
println!(
|
|
"<< client received {}: {} bytes on conn {}",
|
|
msg.message_id,
|
|
msg.message_bytes.len(),
|
|
msg.tcp_conn
|
|
);
|
|
reply_counter += 1;
|
|
println!(
|
|
"tcp connection {} replies received {}/4",
|
|
msg.tcp_conn, reply_counter
|
|
);
|
|
}
|
|
Err(e) => {
|
|
println!("<< client received something that wasn't an example message of {} bytes. error: {}", bytes.len(), e);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
Ok::<(), anyhow::Error>(())
|
|
});
|
|
let mut rng = SmallRng::from_entropy();
|
|
let delay: f64 = rng.gen_range(4.5..7.0);
|
|
tokio::time::sleep(tokio::time::Duration::from_secs_f64(delay)).await;
|
|
}
|
|
|
|
// Once timeout is passed, you can either wait for graceful shutdown or just hard stop it.
|
|
signal::ctrl_c().await?;
|
|
println!("CTRL+C received, shutting down");
|
|
Ok(())
|
|
}
|
|
|
|
// emulate a series of small messages followed by a closing larger one
|
|
fn gen_bytes_fixed(i: usize) -> Vec<u8> {
|
|
let amounts = [10, 15, 50, 1000];
|
|
let len = amounts[i];
|
|
let mut rng = rand::thread_rng();
|
|
(0..len).map(|_| rng.gen::<u8>()).collect()
|
|
}
|
|
```
|