9db748e8dd
* Improve SDK rustdoc and add ARCHITECTURE.md files - Rewrite lib.rs module docs with quick-start example and module overview - Add stream example and include_str! ARCHITECTURE.md to mixnet module - Add ARCHITECTURE.md for mixnet, client_pool, and stream modules - Add rustdoc to MixnetClientBuilder, MixnetClientSender, MixnetMessageSender - Add cancel safety and drop behavior annotations to async methods - Add TcpProxy deprecation notice pointing to stream module * Fix rustdoc errors and add stepwise comments to remaining examples Rustdoc fixes: - Add missing .unwrap() on connect_new example - Replace broken turbofish intra-doc link in MixnetClientBuilder - Fix NymProxyServer::new args in tcp_proxy example - Wrap BandwidthImporter example in scoped block to fix borrow-then-move - Change misleading "5-hop routing" to "multi-hop routing" - Fix copy-paste "forget me" in send_remember_me error message - Fix wrong cargo run command in stream_simple_read_write - Fix DecayWrapper description * Cut down doc comment length * Trimmed down SDK ARCHITECTURE files * Slim Rust SDK docs and rename opener to dialer - Merge tour page into SDK landing page, delete tour.mdx - Trim all three tutorials: cut boilerplate, duplicated code, and misplaced content - Make FFI page evergreen with Go and C++ snippets, link to repo examples - Rename "opener" to "dialer" in stream docs, source ARCHITECTURE.md, and rustdoc - Add reply-to-open arrow in stream mermaid diagram - Replace remaining Unicode dashes in mermaid flowchart * - elevate streams in rustdoc: examples on lib.rs, MixnetClient, open_stream, listener - add stream quick reference to mixnet ARCHITECTURE.md - add stream types to key types list in ARCHITECTURE.md - add docs.rs links for AsyncRead/AsyncWrite and stream submodule - tcp_proxy: replace bold deprecation with warning box * - replace individual example doc pages with GitHub-linked tables - add step-by-step inline comments to all SDK example source files - add doc comments to examples missing them (simple, surb_reply, builder, etc.) - expand mixnet tutorial with persistent identity and split_sender sections - add tcpproxy tutorial - rename "API Reference" to "TypeDoc Reference" in TS SDK sidebar - rename "Misc" to "Extras" in developer sidebar, move VPN CLI up - remove echo server from tools - update message-queue callout to reference actual modules - fix mixnet/examples redirect collision * Add missing mut to example code * Update ARCHITECTURE.md with LP Framing + stream examples with sequencing * Update doc comment in utils.rs * Standardise commenting style across Rust SDK examples * Fix inline doc examples and trim re-export boilerplate * Update sdk/rust/nym-sdk/examples/bandwidth.rs Co-authored-by: Simon Wicky <simon@nymtech.net> * Fix review comments --------- Co-authored-by: Simon Wicky <simon@nymtech.net>
88 lines
3.0 KiB
Rust
88 lines
3.0 KiB
Rust
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
//! Demonstrates the stream/message mode mutual exclusion guard.
|
|
//!
|
|
//! A `MixnetClient` operates in one of two modes: message mode (default)
|
|
//! or stream mode (activated by `open_stream()` or `listener()`). Once
|
|
//! stream mode is active, message-based methods like `send_plain_message`
|
|
//! return `Error::StreamModeActive`. This is a one-way transition — the
|
|
//! two modes share a single inbound channel from the gateway, so they
|
|
//! cannot coexist.
|
|
//!
|
|
//! This example shows:
|
|
//! - Using the message API before stream mode
|
|
//! - Activating stream mode via `listener()`
|
|
//! - Observing `StreamModeActive` errors on message sends
|
|
//! - `split_sender()` shares the mode flag (via `Arc<AtomicBool>`)
|
|
//!
|
|
//! Run with: cargo run --example stream_mode_guard
|
|
|
|
use nym_sdk::mixnet;
|
|
use nym_sdk::mixnet::MixnetMessageSender;
|
|
use nym_sdk::Error;
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
nym_bin_common::logging::setup_tracing_logger();
|
|
|
|
let mut client = mixnet::MixnetClient::connect_new().await.unwrap();
|
|
let our_address = *client.nym_address();
|
|
println!("Our client nym address is: {our_address}");
|
|
|
|
// Message-based API works before stream mode is activated.
|
|
println!("\nTesting message-based API (should work)");
|
|
client
|
|
.send_plain_message(our_address, "hello via message API")
|
|
.await
|
|
.unwrap();
|
|
println!("Message sent successfully via message-based API");
|
|
|
|
// Activate stream mode by creating a listener.
|
|
// This is a one-way transition — the two modes share a single inbound
|
|
// channel from the gateway, so they cannot coexist.
|
|
println!("\nActivating stream mode via listener()");
|
|
let _listener = client.listener().unwrap();
|
|
println!("Stream mode is now active");
|
|
|
|
// Message-based API now returns Error::StreamModeActive.
|
|
println!("\nTesting message-based API again (should fail)");
|
|
let result = client
|
|
.send_plain_message(our_address, "this should fail")
|
|
.await;
|
|
|
|
match result {
|
|
Err(Error::StreamModeActive) => {
|
|
println!("Got expected error: StreamModeActive");
|
|
}
|
|
Err(e) => {
|
|
println!("Got unexpected error: {e:?}");
|
|
}
|
|
Ok(()) => {
|
|
println!("ERROR: send() should have failed but succeeded!");
|
|
}
|
|
}
|
|
|
|
// split_sender() shares the mode flag (Arc<AtomicBool>),
|
|
// so it also returns StreamModeActive.
|
|
println!("\nTesting split_sender (shares stream_mode flag)");
|
|
let sender = client.split_sender();
|
|
let result = sender
|
|
.send_plain_message(our_address, "this should also fail")
|
|
.await;
|
|
|
|
match result {
|
|
Err(Error::StreamModeActive) => {
|
|
println!("Got expected error: StreamModeActive on split sender");
|
|
}
|
|
Err(e) => {
|
|
println!("Got unexpected error: {e:?}");
|
|
}
|
|
Ok(()) => {
|
|
println!("ERROR: split_sender.send() should have failed but succeeded!");
|
|
}
|
|
}
|
|
|
|
client.disconnect().await;
|
|
}
|