#![forbid(unsafe_code)]
#![cfg(feature = "nym")]
pub mod acquire;
pub use zingo_netutils::exit::{BlankExitNodeId, ExitNodeId};
pub(crate) use crate::destination::health::fault_domain;
pub mod driver;
mod mode;
pub mod probe;
pub(crate) mod quartet;
pub mod provision;
pub mod route;
pub mod speed;
pub(crate) mod pools;
pub mod supervisor;
pub mod sweep;
pub use acquire::TransportError;
pub use driver::{MixnetStartPolicy, MixnetStatus, ProvisionStrategy};
pub(crate) use driver::{StatusPublisher, status_publisher};
pub use mode::Indicator;
pub(crate) use mode::MixnetSlot;
pub(crate) use mode::StandingClient;
pub use route::{
MixnetNotReady, MixnetRoute, TransmitPolicy, resolve_mixnet_only_route, resolve_send_route,
};
pub use zingo_netutils::conduit::MixnetConduit;
pub use supervisor::{DeathReport, MixnetProxy, MixnetProxyError};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct MixnetTiming {
pub attach_readiness_budget: std::time::Duration,
pub mixnet_round_trip_bound: std::time::Duration,
pub client_rotation_min: std::time::Duration,
pub client_rotation_max: std::time::Duration,
}
pub fn mixnet_timing() -> MixnetTiming {
MixnetTiming {
attach_readiness_budget: zingo_netutils::time::ATTACH_READINESS_BUDGET,
mixnet_round_trip_bound: zingo_netutils::time::MIXNET_ROUND_TRIP_BOUND,
client_rotation_min: zingo_netutils::time::CLIENT_ROTATION_MIN,
client_rotation_max: zingo_netutils::time::CLIENT_ROTATION_MAX,
}
}
pub(crate) fn socks5_transmit_stage(
error: &zingo_netutils::Socks5TransmitError,
) -> zingo_net_diag::NetOpStage {
use zingo_net_diag::NetOpStage;
use zingo_netutils::Socks5TransmitError;
match error {
Socks5TransmitError::ProxyUnreachable { .. } => NetOpStage::LocalProxyConnect,
Socks5TransmitError::TunnelRefused { .. } => NetOpStage::SocksHandshake,
Socks5TransmitError::TunnelTransport { .. } => NetOpStage::TunnelTransport,
Socks5TransmitError::Rpc { .. } | Socks5TransmitError::Rejected(_) => {
NetOpStage::RemoteHttp
}
Socks5TransmitError::TimedOut { after, .. } => NetOpStage::TimedOut {
after_ms: after.as_millis() as u64,
},
Socks5TransmitError::InsecureScheme { .. } => NetOpStage::RouteResolution,
}
}
pub(crate) fn socks5_transmit_failure(
error: &zingo_netutils::Socks5TransmitError,
target: impl Into<String>,
) -> zingo_net_diag::NetOpFailure {
zingo_net_diag::NetOpFailure::from_error(socks5_transmit_stage(error), target, error)
}
#[cfg(all(test, feature = "nym"))]
mod classifier_tests {
use super::socks5_transmit_stage;
use zingo_net_diag::NetOpStage;
use zingo_netutils::{ProxyDialFailure, Socks5TransmitError, TunnelFailure};
#[test]
fn every_variant_classifies_by_type_alone() {
let io = || std::io::Error::from(std::io::ErrorKind::ConnectionRefused);
let table: Vec<(Socks5TransmitError, NetOpStage)> = vec![
(
Socks5TransmitError::ProxyUnreachable {
proxy: "127.0.0.1:1080".into(),
elapsed: std::time::Duration::from_secs(1),
source: ProxyDialFailure::Io(io()),
},
NetOpStage::LocalProxyConnect,
),
(
Socks5TransmitError::TunnelRefused {
destination: "zec.rocks:443".into(),
elapsed: std::time::Duration::from_secs(1),
source: TunnelFailure::TimedOut,
},
NetOpStage::SocksHandshake,
),
(
Socks5TransmitError::TunnelTransport {
destination: "zec.rocks:443".into(),
detail: "tls handshake eof".into(),
source: None,
},
NetOpStage::TunnelTransport,
),
(
Socks5TransmitError::Rpc {
destination: "zec.rocks:443".into(),
status: zingo_netutils::Status::unavailable("overloaded"),
},
NetOpStage::RemoteHttp,
),
(
Socks5TransmitError::TimedOut {
destination: "zec.rocks:443".into(),
after: std::time::Duration::from_secs(25),
},
NetOpStage::TimedOut { after_ms: 25_000 },
),
(
Socks5TransmitError::InsecureScheme {
indexer: "http://zec.rocks:9067".into(),
},
NetOpStage::RouteResolution,
),
];
for (error, expected) in table {
assert_eq!(socks5_transmit_stage(&error), expected, "error: {error}");
}
}
}