nym_bridges/lib.rs
1// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
2// SPDX-License-Identifier: GPL-3.0-only
3
4//! Nym Transport Bridges library.
5//!
6//! This crate provides the transport and configuration primitives used by Nym bridge runners and
7//! tooling.
8//!
9//! The primary responsibilities are:
10//! - server-side transport configuration for QUIC and TLS listeners,
11//! - client-side transport parameters derived from server configuration,
12//! - forwarding/session/connection building blocks for bridge implementations.
13//!
14//! The repository binaries (for example, `nym-bridge` and `bridge-cfg`) use this crate as their
15//! shared core.
16//!
17//! # Shared Types Crate
18//!
19//! This crate re-exports [`nym-bridges-types`](https://docs.rs/nym-bridges-types) as [`types`].
20//!
21//! These shared types can be consumed directly when integrating across crates or language bindings.
22//!
23//! # Example: Simple Client Connection Establishment
24//!
25//! ```rust no_run
26//! # #[tokio::main]
27//! # async fn main() -> Result<(),anyhow::Error>{
28//! use anyhow::anyhow;
29//! use nym_bridges::connection::{BridgeConn, SOCKET_OPEN_NOP};
30//! use nym_bridges::config::parse_persisted_config_json;
31//! use nym_bridges::forward::UdpForwarder;
32//! use tokio_util::sync::CancellationToken;
33//!
34//! let client_config_str = r#"{"version":"0","transports":[{"transport_type":"quic_plain","args":{"addresses":["139.162.33.226:4443","[2400:8901::2000:faff:fea6:87f2]:4443"],"host":"netdna.bootstrapcdn.com","id_pubkey":"9JC91ZiszhIn3n4FG+MDYE/lYwhGdpHGWQTKUqGl+sE="}}]}"#;
35//! let shutdown_token = CancellationToken::new();
36//! let entry_bridge_params = parse_persisted_config_json(client_config_str)?;
37//! let transport_params = entry_bridge_params
38//! .transports
39//! .first()
40//! .ok_or(anyhow!("no config provided"))?;
41//!
42//! let bridge_conn = BridgeConn::try_connect(
43//! transport_params.clone(),
44//! shutdown_token.clone(),
45//! #[cfg(any(target_os = "linux", target_os = "android"))]
46//! SOCKET_OPEN_NOP,
47//! )
48//! .await?;
49//!
50//! let remote_addr = bridge_conn.endpoint();
51//! let (listen_addr, join_handle) = UdpForwarder::launch_initiator(
52//! bridge_conn,
53//! None,
54//! None,
55//! shutdown_token.clone(),
56//! )
57//! .await?;
58//!
59//! # Ok::<(), anyhow::Error>(())
60//! # }
61//! ```
62//!
63//! # Example: Parse and Convert Configuration
64//!
65//! ```
66//! use nym_bridges::config::PersistedServerConfig;
67//! use nym_bridges::types::PersistedClientConfig;
68//!
69//! let server_toml = r#"
70//! public_ips = ["192.168.0.1", "fe80::1"]
71//!
72//! [forward]
73//! address = "[::1]:51822"
74//!
75//! [[transports]]
76//! transport_type = "quic_plain"
77//!
78//! [transports.args]
79//! stateless_retry = false
80//! listen = "[::]:4443"
81//! identity_key = "fditK5JfNM/88mLWd3ccbLasSrHA5dw1wj+/+1bfGWk="
82//! "#;
83//!
84//! let server_cfg = PersistedServerConfig::parse(server_toml)?;
85//! let client_cfg = PersistedClientConfig::try_from(&server_cfg)?;
86//! assert_eq!(client_cfg.version, "0");
87//! # Ok::<(), anyhow::Error>(())
88//! ```
89
90/// Persisted server/client configuration types and conversion from server transport config to
91/// client connection parameters.
92pub mod config;
93/// Runtime components for creating connections over configured transports.
94pub mod connection;
95/// Crate-specific error types.
96pub mod error;
97/// Runtime components for forwarding client traffic over established transport connections.
98pub mod forward;
99/// Stored state and config for established connection.
100pub mod session;
101/// Protocol-specific transport implementations.
102pub mod transport;
103// mod stats;
104
105pub use nym_bridges_types as types;
106
107#[allow(unused)]
108#[cfg(test)]
109pub(crate) mod test_utils {
110 use std::env;
111 use std::str::FromStr;
112 use std::sync::Once;
113 use tracing_subscriber::filter::LevelFilter;
114
115 static SUBSCRIBER_INIT: Once = Once::new();
116
117 #[allow(unused)]
118 pub fn init_subscriber(maybe_level: Option<LevelFilter>) {
119 SUBSCRIBER_INIT.call_once(|| {
120 let lf = maybe_level.unwrap_or_else(|| {
121 let level = env::var("RUST_LOG_LEVEL").unwrap_or("error".into());
122 LevelFilter::from_str(&level).unwrap()
123 });
124
125 tracing_subscriber::fmt().with_max_level(lf).init();
126 });
127 }
128}