Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3aaed5aa37 | |||
| a6570d085c | |||
| 9b549e838c | |||
| f1f302a71c | |||
| d3ad14e87d | |||
| d90eda116f | |||
| 0c51e6537d | |||
| c0575a31b5 | |||
| fa92923ead |
Generated
+13
-137
@@ -14,16 +14,6 @@ dependencies = [
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "addr"
|
||||
version = "0.15.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a93b8a41dbe230ad5087cc721f8d41611de654542180586b315d9f4cf6b72bef"
|
||||
dependencies = [
|
||||
"psl",
|
||||
"psl-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.24.2"
|
||||
@@ -1369,19 +1359,6 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"unicode-width 0.2.1",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.16.0"
|
||||
@@ -3895,7 +3872,7 @@ version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70a646d946d06bedbbc4cac4c218acf4bbf2d87757a784857025f4d447e4e1cd"
|
||||
dependencies = [
|
||||
"console 0.16.0",
|
||||
"console",
|
||||
"portable-atomic",
|
||||
"unicode-width 0.2.1",
|
||||
"unit-prefix",
|
||||
@@ -5751,52 +5728,55 @@ dependencies = [
|
||||
name = "nym-gateway"
|
||||
version = "1.1.36"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"bincode",
|
||||
"bip39",
|
||||
"bs58",
|
||||
"bytes",
|
||||
"dashmap",
|
||||
"defguard_wireguard_rs",
|
||||
"etherparse",
|
||||
"fastrand 2.3.0",
|
||||
"futures",
|
||||
"ipnetwork",
|
||||
"mock_instant",
|
||||
"nym-api-requests",
|
||||
"nym-authenticator-requests",
|
||||
"nym-bin-common",
|
||||
"nym-client-core",
|
||||
"nym-credential-verification",
|
||||
"nym-credentials",
|
||||
"nym-credentials-interface",
|
||||
"nym-crypto",
|
||||
"nym-exit-policy",
|
||||
"nym-gateway-requests",
|
||||
"nym-gateway-stats-storage",
|
||||
"nym-gateway-storage",
|
||||
"nym-id",
|
||||
"nym-ip-packet-router",
|
||||
"nym-ip-packet-requests",
|
||||
"nym-mixnet-client",
|
||||
"nym-mixnode-common",
|
||||
"nym-network-defaults",
|
||||
"nym-network-requester",
|
||||
"nym-node-metrics",
|
||||
"nym-sdk",
|
||||
"nym-service-provider-requests-common",
|
||||
"nym-service-providers-common",
|
||||
"nym-socks5-proxy-helpers",
|
||||
"nym-socks5-requests",
|
||||
"nym-sphinx",
|
||||
"nym-statistics-common",
|
||||
"nym-task",
|
||||
"nym-topology",
|
||||
"nym-types",
|
||||
"nym-tun",
|
||||
"nym-validator-client",
|
||||
"nym-wireguard",
|
||||
"nym-wireguard-private-metadata-server",
|
||||
"nym-wireguard-types",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"sha2 0.10.9",
|
||||
"thiserror 2.0.12",
|
||||
"time",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-tun",
|
||||
"tokio-tungstenite",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
@@ -6038,49 +6018,6 @@ dependencies = [
|
||||
"tokio-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-ip-packet-router"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"bincode",
|
||||
"bs58",
|
||||
"bytes",
|
||||
"clap",
|
||||
"etherparse",
|
||||
"futures",
|
||||
"log",
|
||||
"nym-bin-common",
|
||||
"nym-client-core",
|
||||
"nym-config",
|
||||
"nym-crypto",
|
||||
"nym-exit-policy",
|
||||
"nym-id",
|
||||
"nym-ip-packet-requests",
|
||||
"nym-network-defaults",
|
||||
"nym-network-requester",
|
||||
"nym-sdk",
|
||||
"nym-service-provider-requests-common",
|
||||
"nym-service-providers-common",
|
||||
"nym-sphinx",
|
||||
"nym-task",
|
||||
"nym-tun",
|
||||
"nym-types",
|
||||
"nym-wireguard",
|
||||
"nym-wireguard-types",
|
||||
"rand 0.8.5",
|
||||
"reqwest 0.12.22",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.12",
|
||||
"time",
|
||||
"tokio",
|
||||
"tokio-tun",
|
||||
"tokio-util",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-ledger"
|
||||
version = "0.1.0"
|
||||
@@ -6231,56 +6168,6 @@ dependencies = [
|
||||
"utoipa-swagger-ui",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-network-requester"
|
||||
version = "1.1.62"
|
||||
dependencies = [
|
||||
"addr",
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"bs58",
|
||||
"clap",
|
||||
"dirs",
|
||||
"futures",
|
||||
"humantime-serde",
|
||||
"ipnetwork",
|
||||
"log",
|
||||
"nym-async-file-watcher",
|
||||
"nym-bin-common",
|
||||
"nym-client-core",
|
||||
"nym-client-websocket-requests",
|
||||
"nym-config",
|
||||
"nym-credential-storage",
|
||||
"nym-credentials",
|
||||
"nym-crypto",
|
||||
"nym-exit-policy",
|
||||
"nym-id",
|
||||
"nym-network-defaults",
|
||||
"nym-ordered-buffer",
|
||||
"nym-sdk",
|
||||
"nym-service-providers-common",
|
||||
"nym-socks5-proxy-helpers",
|
||||
"nym-socks5-requests",
|
||||
"nym-sphinx",
|
||||
"nym-task",
|
||||
"nym-types",
|
||||
"publicsuffix",
|
||||
"rand 0.8.5",
|
||||
"regex",
|
||||
"reqwest 0.12.22",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"tap",
|
||||
"tempfile",
|
||||
"thiserror 2.0.12",
|
||||
"time",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"url",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nym-node"
|
||||
version = "1.17.0"
|
||||
@@ -6319,10 +6206,8 @@ dependencies = [
|
||||
"nym-gateway-stats-storage",
|
||||
"nym-http-api-client",
|
||||
"nym-http-api-common",
|
||||
"nym-ip-packet-router",
|
||||
"nym-metrics",
|
||||
"nym-mixnet-client",
|
||||
"nym-network-requester",
|
||||
"nym-node-metrics",
|
||||
"nym-node-requests",
|
||||
"nym-noise",
|
||||
@@ -8302,15 +8187,6 @@ dependencies = [
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psl"
|
||||
version = "2.1.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45f621acfbd2ca5670eee9a95270747dfa9a29e63e1937d7e6a1ac6994331966"
|
||||
dependencies = [
|
||||
"psl-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psl-types"
|
||||
version = "2.0.11"
|
||||
@@ -10317,7 +10193,7 @@ dependencies = [
|
||||
"bip39",
|
||||
"bs58",
|
||||
"clap",
|
||||
"console 0.16.0",
|
||||
"console",
|
||||
"cw-utils",
|
||||
"dkg-bypass-contract",
|
||||
"humantime",
|
||||
@@ -11984,7 +11860,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-result 0.3.4",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
|
||||
@@ -132,8 +132,6 @@ members = [
|
||||
"sdk/ffi/shared",
|
||||
"sdk/rust/nym-sdk",
|
||||
"service-providers/common",
|
||||
"service-providers/ip-packet-router",
|
||||
"service-providers/network-requester",
|
||||
"sqlx-pool-guard",
|
||||
"tools/echo-server",
|
||||
"tools/internal/contract-state-importer/importer-cli",
|
||||
@@ -168,8 +166,6 @@ default-members = [
|
||||
"nym-statistics-api",
|
||||
"nym-validator-rewarder",
|
||||
"nyx-chain-watcher",
|
||||
"service-providers/ip-packet-router",
|
||||
"service-providers/network-requester",
|
||||
"tools/nymvisor",
|
||||
]
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct BinaryBuildInformation {
|
||||
/// Provides the name of the binary, i.e. the content of `CARGO_PKG_NAME` environmental variable.
|
||||
pub binary_name: &'static str,
|
||||
|
||||
@@ -355,10 +355,9 @@ impl SocksClient {
|
||||
TransmissionLane::ConnectionId(self.connection_id),
|
||||
self.packet_type,
|
||||
);
|
||||
self.input_sender
|
||||
.send(input_message)
|
||||
.await
|
||||
.expect("InputMessageReceiver has stopped receiving!");
|
||||
if self.input_sender.send(input_message).await.is_err() {
|
||||
error!("InputMessageReceiver has stopped receiving!")
|
||||
}
|
||||
}
|
||||
|
||||
async fn send_connect_to_mixnet_with_return_address(&mut self, remote_address: RemoteAddress) {
|
||||
@@ -378,10 +377,9 @@ impl SocksClient {
|
||||
TransmissionLane::ConnectionId(self.connection_id),
|
||||
self.packet_type,
|
||||
);
|
||||
self.input_sender
|
||||
.send(input_message)
|
||||
.await
|
||||
.expect("InputMessageReceiver has stopped receiving!");
|
||||
if self.input_sender.send(input_message).await.is_err() {
|
||||
error!("InputMessageReceiver has stopped receiving!")
|
||||
}
|
||||
}
|
||||
|
||||
async fn send_connect_to_mixnet(&mut self, remote_address: RemoteAddress) {
|
||||
|
||||
+21
-10
@@ -19,9 +19,9 @@ rust-version = "1.77"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
bincode = { workspace = true }
|
||||
async-trait = { workspace = true }
|
||||
bincode = { workspace = true }
|
||||
bytes = { workspace = true }
|
||||
bip39 = { workspace = true }
|
||||
bs58 = { workspace = true }
|
||||
dashmap = { workspace = true }
|
||||
@@ -30,7 +30,6 @@ futures = { workspace = true }
|
||||
ipnetwork = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
sha2 = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
time = { workspace = true }
|
||||
tokio = { workspace = true, features = [
|
||||
@@ -49,7 +48,7 @@ zeroize = { workspace = true }
|
||||
|
||||
|
||||
# internal
|
||||
nym-api-requests = { path = "../nym-api/nym-api-requests" }
|
||||
nym-bin-common = { path = "../common/bin-common" }
|
||||
nym-credentials = { path = "../common/credentials" }
|
||||
nym-credentials-interface = { path = "../common/credentials-interface" }
|
||||
nym-credential-verification = { path = "../common/credential-verification" }
|
||||
@@ -58,31 +57,43 @@ nym-gateway-storage = { path = "../common/gateway-storage" }
|
||||
nym-gateway-stats-storage = { path = "../common/gateway-stats-storage" }
|
||||
nym-gateway-requests = { path = "../common/gateway-requests" }
|
||||
nym-mixnet-client = { path = "../common/client-libs/mixnet-client" }
|
||||
nym-mixnode-common = { path = "../common/mixnode-common" }
|
||||
nym-network-defaults = { path = "../common/network-defaults" }
|
||||
nym-network-requester = { path = "../service-providers/network-requester" }
|
||||
nym-sdk = { path = "../sdk/rust/nym-sdk" }
|
||||
nym-sphinx = { path = "../common/nymsphinx" }
|
||||
nym-statistics-common = { path = "../common/statistics" }
|
||||
nym-task = { path = "../common/task" }
|
||||
nym-topology = { path = "../common/topology" }
|
||||
nym-types = { path = "../common/types" }
|
||||
nym-validator-client = { path = "../common/client-libs/validator-client" }
|
||||
nym-ip-packet-router = { path = "../service-providers/ip-packet-router" }
|
||||
nym-node-metrics = { path = "../nym-node/nym-node-metrics" }
|
||||
|
||||
nym-wireguard = { path = "../common/wireguard" }
|
||||
nym-wireguard-private-metadata-server = { path = "../common/wireguard-private-metadata/server" }
|
||||
nym-wireguard-types = { path = "../common/wireguard-types", default-features = false }
|
||||
|
||||
nym-authenticator-requests = { path = "../common/authenticator-requests" }
|
||||
nym-client-core = { path = "../common/client-core", features = ["cli"] }
|
||||
nym-id = { path = "../common/nym-id" }
|
||||
nym-service-provider-requests-common = { path = "../common/service-provider-requests-common" }
|
||||
|
||||
|
||||
defguard_wireguard_rs = { workspace = true }
|
||||
|
||||
nym-service-providers-common = { path = "../service-providers/common" }
|
||||
|
||||
# authenticator specific
|
||||
nym-authenticator-requests = { path = "../common/authenticator-requests" }
|
||||
|
||||
# network-requester specific
|
||||
nym-socks5-proxy-helpers = { path = "../common/socks5/proxy-helpers" }
|
||||
nym-socks5-requests = { path = "../common/socks5/requests" }
|
||||
nym-exit-policy = { path = "../common/exit-policy", features = ["client"] }
|
||||
|
||||
# ipr specific
|
||||
nym-ip-packet-requests = { path = "../common/ip-packet-requests" }
|
||||
etherparse = { workspace = true }
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
tokio-tun.workspace = true
|
||||
nym-tun = { path = "../common/tun" }
|
||||
|
||||
[dev-dependencies]
|
||||
nym-gateway-storage = { path = "../common/gateway-storage", features = ["mock"] }
|
||||
nym-wireguard = { path = "../common/wireguard", features = ["mock"] }
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::net::SocketAddr;
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Config {
|
||||
pub gateway: Gateway,
|
||||
|
||||
@@ -40,7 +40,7 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Gateway {
|
||||
/// Indicates whether this gateway is accepting only zk-nym credentials for accessing the mixnet
|
||||
/// or if it also accepts non-paying clients
|
||||
@@ -57,7 +57,7 @@ pub struct Gateway {
|
||||
pub nyxd_urls: Vec<Url>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct NetworkRequester {
|
||||
/// Specifies whether network requester service is enabled in this process.
|
||||
pub enabled: bool,
|
||||
@@ -70,7 +70,7 @@ impl Default for NetworkRequester {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct IpPacketRouter {
|
||||
/// Specifies whether ip packet router service is enabled in this process.
|
||||
pub enabled: bool,
|
||||
@@ -83,7 +83,7 @@ impl Default for IpPacketRouter {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Debug {
|
||||
/// Defines maximum delay between client bandwidth information being flushed to the persistent storage.
|
||||
pub client_bandwidth_max_flushing_rate: Duration,
|
||||
@@ -106,7 +106,7 @@ pub struct Debug {
|
||||
pub max_request_timestamp_skew: Duration,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ZkNymTicketHandlerDebug {
|
||||
/// Specifies the multiplier for revoking a malformed/double-spent ticket
|
||||
/// (if it has to go all the way to the nym-api for verification)
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
pub use crate::node::client_handling::websocket::connection_handler::authenticated::RequestHandlingError;
|
||||
use crate::node::internal_service_providers::authenticator::error::AuthenticatorError;
|
||||
use crate::node::internal_service_providers::network_requester::error::NetworkRequesterError;
|
||||
use crate::service_providers::ip_packet_router::error::IpPacketRouterError;
|
||||
use nym_client_core::error::ClientCoreError;
|
||||
use nym_gateway_stats_storage::error::StatsStorageError;
|
||||
use nym_gateway_storage::error::GatewayStorageError;
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
use nym_network_requester::error::{ClientCoreError, NetworkRequesterError};
|
||||
use nym_validator_client::nyxd::error::NyxdError;
|
||||
use nym_validator_client::nyxd::{AccountId, Coin};
|
||||
use nym_validator_client::ValidatorClientError;
|
||||
use std::net::IpAddr;
|
||||
use thiserror::Error;
|
||||
|
||||
pub use crate::node::client_handling::websocket::connection_handler::authenticated::RequestHandlingError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum GatewayError {
|
||||
#[error("the configured version of the gateway ({config_version}) is incompatible with the binary version ({binary_version})")]
|
||||
|
||||
@@ -11,4 +11,6 @@ pub mod node;
|
||||
pub use error::GatewayError;
|
||||
pub use node::GatewayTasksBuilder;
|
||||
|
||||
pub use node::internal_service_providers as service_providers;
|
||||
pub use node::internal_service_providers::authenticator as nym_authenticator;
|
||||
pub use node::internal_service_providers::network_requester as nym_network_requester;
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::node::client_handling::websocket::message_receiver::{
|
||||
MixMessageReceiver, MixMessageSender,
|
||||
};
|
||||
use futures::StreamExt;
|
||||
use nym_network_requester::{GatewayPacketRouter, PacketRouter};
|
||||
use nym_client_core::client::mix_traffic::transceiver::{GatewayPacketRouter, PacketRouter};
|
||||
use nym_sphinx::addressing::clients::Recipient;
|
||||
use nym_sphinx::DestinationAddressBytes;
|
||||
use nym_task::TaskClient;
|
||||
|
||||
+3
-5
@@ -1,11 +1,9 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use crate::service_providers::ip_packet_router::error::IpPacketRouterError;
|
||||
use nym_sdk::mixnet::{AnonymousSenderTag, Recipient};
|
||||
|
||||
use crate::error::{IpPacketRouterError, Result};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub(crate) enum ConnectedClientId {
|
||||
@@ -14,7 +12,7 @@ pub(crate) enum ConnectedClientId {
|
||||
}
|
||||
|
||||
impl ConnectedClientId {
|
||||
pub(crate) fn into_nym_address(self) -> Result<Recipient> {
|
||||
pub(crate) fn into_nym_address(self) -> Result<Recipient, IpPacketRouterError> {
|
||||
match self {
|
||||
ConnectedClientId::NymAddress(nym_address) => Ok(*nym_address),
|
||||
ConnectedClientId::AnonymousSenderTag(_) => Err(IpPacketRouterError::InvalidReplyTo),
|
||||
+19
-23
@@ -1,8 +1,11 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::service_providers::ip_packet_router::{
|
||||
clients::ConnectedClientId, constants::CLIENT_HANDLER_ACTIVITY_TIMEOUT,
|
||||
error::IpPacketRouterError, messages::ClientVersion,
|
||||
util::create_message::create_input_message,
|
||||
};
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use nym_ip_packet_requests::{
|
||||
codec::{IprPacket, MultiIpPacketCodec},
|
||||
@@ -13,19 +16,13 @@ use nym_ip_packet_requests::{
|
||||
use nym_sdk::mixnet::{
|
||||
InputMessage, MixnetClientSender, MixnetMessageSender, MixnetMessageSinkTranslator,
|
||||
};
|
||||
use std::time::Duration;
|
||||
use tokio::{
|
||||
sync::{mpsc, oneshot},
|
||||
time::{interval, Interval},
|
||||
};
|
||||
use tokio_util::codec::Encoder;
|
||||
|
||||
use crate::{
|
||||
clients::ConnectedClientId,
|
||||
constants::CLIENT_HANDLER_ACTIVITY_TIMEOUT,
|
||||
error::{IpPacketRouterError, Result},
|
||||
messages::ClientVersion,
|
||||
};
|
||||
|
||||
// Data flow
|
||||
// Out: mixnet_listener -> decode -> handle_packet -> write_to_tun
|
||||
// In: tun_listener -> [connected_client_handler -> encode] -> mixnet_sender
|
||||
@@ -69,8 +66,8 @@ impl ConnectedClientHandler {
|
||||
oneshot::Sender<()>,
|
||||
tokio::task::JoinHandle<()>,
|
||||
) {
|
||||
log::debug!("Starting connected client handler for: {client_id}");
|
||||
log::debug!("client version: {client_version:?}");
|
||||
tracing::debug!("Starting connected client handler for: {client_id}");
|
||||
tracing::debug!("client version: {client_version:?}");
|
||||
let (close_tx, close_rx) = oneshot::channel();
|
||||
let (forward_from_tun_tx, forward_from_tun_rx) = mpsc::unbounded_channel();
|
||||
|
||||
@@ -101,14 +98,14 @@ impl ConnectedClientHandler {
|
||||
|
||||
let handle = tokio::spawn(async move {
|
||||
if let Err(err) = connected_client_handler.run().await {
|
||||
log::error!("connected client handler has failed: {err}")
|
||||
tracing::error!("connected client handler has failed: {err}")
|
||||
}
|
||||
});
|
||||
|
||||
(forward_from_tun_tx, close_tx, handle)
|
||||
}
|
||||
|
||||
fn bundle_packet(&mut self, packet: IprPacket) -> Result<Option<Bytes>> {
|
||||
fn bundle_packet(&mut self, packet: IprPacket) -> Result<Option<Bytes>, IpPacketRouterError> {
|
||||
let mut bundled_packets = BytesMut::new();
|
||||
self.packet_bundler
|
||||
.encode(packet, &mut bundled_packets)
|
||||
@@ -120,7 +117,7 @@ impl ConnectedClientHandler {
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_packet(&mut self, packet: IprPacket) -> Result<()> {
|
||||
async fn handle_packet(&mut self, packet: IprPacket) -> Result<(), IpPacketRouterError> {
|
||||
self.activity_timeout.reset();
|
||||
|
||||
let bundled_packets = match self.bundle_packet(packet)? {
|
||||
@@ -145,37 +142,37 @@ impl ConnectedClientHandler {
|
||||
})
|
||||
}
|
||||
|
||||
async fn run(mut self) -> Result<()> {
|
||||
async fn run(mut self) -> Result<(), IpPacketRouterError> {
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = &mut self.close_rx => {
|
||||
log::info!("client handler stopping: received close: {}", self.sent_by);
|
||||
tracing::info!("client handler stopping: received close: {}", self.sent_by);
|
||||
break;
|
||||
},
|
||||
_ = self.activity_timeout.tick() => {
|
||||
log::info!("client handler stopping: activity timeout: {}", self.sent_by);
|
||||
tracing::info!("client handler stopping: activity timeout: {}", self.sent_by);
|
||||
break;
|
||||
},
|
||||
_ = self.payload_topup_interval.tick() => {
|
||||
if let Err(err) = self.handle_packet(IprPacket::Flush).await {
|
||||
log::error!("client handler: failed to handle packet: {err}");
|
||||
tracing::error!("client handler: failed to handle packet: {err}");
|
||||
}
|
||||
},
|
||||
packet = self.forward_from_tun_rx.recv() => match packet {
|
||||
Some(packet) => {
|
||||
if let Err(err) = self.handle_packet(IprPacket::from(packet)).await {
|
||||
log::error!("client handler: failed to handle packet: {err}");
|
||||
tracing::error!("client handler: failed to handle packet: {err}");
|
||||
}
|
||||
},
|
||||
None => {
|
||||
log::info!("client handler stopping: tun channel closed");
|
||||
tracing::info!("client handler stopping: tun channel closed");
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
log::debug!("ConnectedClientHandler: exiting");
|
||||
tracing::debug!("ConnectedClientHandler: exiting");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -210,8 +207,7 @@ impl MixnetMessageSinkTranslator for ToIprDataResponse {
|
||||
|
||||
// Wrap the response packet in a mixnet input message
|
||||
let input_message =
|
||||
crate::util::create_message::create_input_message(&self.send_to, response_packet)
|
||||
.with_max_retransmissions(0);
|
||||
create_input_message(&self.send_to, response_packet).with_max_retransmissions(0);
|
||||
|
||||
Ok(input_message)
|
||||
}
|
||||
+18
-22
@@ -1,24 +1,20 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use super::ConnectedClientId;
|
||||
use crate::service_providers::ip_packet_router::{
|
||||
constants::CLIENT_MIXNET_INACTIVITY_TIMEOUT, error::IpPacketRouterError, tun_listener,
|
||||
util::generate_new_ip,
|
||||
};
|
||||
use nym_ip_packet_requests::IpPair;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||
sync::Arc,
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use nym_ip_packet_requests::IpPair;
|
||||
use tokio::sync::{mpsc, oneshot, RwLock};
|
||||
|
||||
use crate::{
|
||||
constants::CLIENT_MIXNET_INACTIVITY_TIMEOUT,
|
||||
error::{IpPacketRouterError, Result},
|
||||
tun_listener,
|
||||
};
|
||||
|
||||
use super::ConnectedClientId;
|
||||
|
||||
pub(crate) struct ConnectedClients {
|
||||
// The set of connected clients
|
||||
clients_ipv4_mapping: HashMap<Ipv4Addr, ConnectedClient>,
|
||||
@@ -61,7 +57,7 @@ impl ConnectedClients {
|
||||
|
||||
pub(crate) fn disconnect_client(&mut self, client_id: &ConnectedClientId) {
|
||||
if let Some(ips) = self.lookup_ip_from_client_id(client_id) {
|
||||
log::debug!("Disconnect client that requested to do so: {ips}");
|
||||
tracing::debug!("Disconnect client that requested to do so: {ips}");
|
||||
self.disconnect_client_handle(ips);
|
||||
}
|
||||
}
|
||||
@@ -72,7 +68,7 @@ impl ConnectedClients {
|
||||
self.tun_listener_connected_client_tx
|
||||
.send(ConnectedClientEvent::Disconnect(DisconnectEvent(ips)))
|
||||
.inspect_err(|err| {
|
||||
log::error!("Failed to send disconnect event: {err}");
|
||||
tracing::error!("Failed to send disconnect event: {err}");
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
@@ -117,7 +113,7 @@ impl ConnectedClients {
|
||||
handle: Arc::new(handle),
|
||||
};
|
||||
|
||||
log::info!("Inserting {} and {}", ips.ipv4, ips.ipv6);
|
||||
tracing::info!("Inserting {} and {}", ips.ipv4, ips.ipv6);
|
||||
self.clients_ipv4_mapping.insert(ips.ipv4, client.clone());
|
||||
self.clients_ipv6_mapping.insert(ips.ipv6, client);
|
||||
|
||||
@@ -129,12 +125,15 @@ impl ConnectedClients {
|
||||
forward_from_tun_tx,
|
||||
})))
|
||||
.inspect_err(|err| {
|
||||
log::error!("Failed to send connected client event: {err}");
|
||||
tracing::error!("Failed to send connected client event: {err}");
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
|
||||
pub(crate) async fn update_activity(&mut self, ips: &IpPair) -> Result<()> {
|
||||
pub(crate) async fn update_activity(
|
||||
&mut self,
|
||||
ips: &IpPair,
|
||||
) -> Result<(), IpPacketRouterError> {
|
||||
if let Some(client) = self.clients_ipv4_mapping.get(&ips.ipv4) {
|
||||
*client.last_activity.write().await = Instant::now();
|
||||
Ok(())
|
||||
@@ -181,7 +180,7 @@ impl ConnectedClients {
|
||||
stopped_clients: Vec<(IpPair, ConnectedClientId)>,
|
||||
) {
|
||||
for (ips, _) in &stopped_clients {
|
||||
log::info!("Disconnect stopped client: {ips}");
|
||||
tracing::info!("Disconnect stopped client: {ips}");
|
||||
self.disconnect_client_handle(*ips);
|
||||
}
|
||||
}
|
||||
@@ -191,16 +190,13 @@ impl ConnectedClients {
|
||||
inactive_clients: Vec<(IpPair, ConnectedClientId)>,
|
||||
) {
|
||||
for (ips, _) in &inactive_clients {
|
||||
log::info!("Disconnect inactive client: {ips}");
|
||||
tracing::info!("Disconnect inactive client: {ips}");
|
||||
self.disconnect_client_handle(*ips);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn find_new_ip(&self) -> Option<IpPair> {
|
||||
crate::util::generate_new_ip::find_new_ips(
|
||||
&self.clients_ipv4_mapping,
|
||||
&self.clients_ipv6_mapping,
|
||||
)
|
||||
generate_new_ip::find_new_ips(&self.clients_ipv4_mapping, &self.clients_ipv6_mapping)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,7 +238,7 @@ impl ConnectedClient {
|
||||
|
||||
impl Drop for CloseTx {
|
||||
fn drop(&mut self) {
|
||||
log::debug!("signal to close client: {}", self.client_id);
|
||||
tracing::debug!("signal to close client: {}", self.client_id);
|
||||
if let Some(close_tx) = self.inner.take() {
|
||||
close_tx.send(()).ok();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_network_defaults::mainnet;
|
||||
use url::Url;
|
||||
|
||||
mod persistence;
|
||||
|
||||
pub use crate::service_providers::ip_packet_router::config::persistence::IpPacketRouterPaths;
|
||||
pub use nym_client_core::config::Config as BaseClientConfig;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Config {
|
||||
pub base: BaseClientConfig,
|
||||
|
||||
pub ip_packet_router: IpPacketRouter,
|
||||
|
||||
pub storage_paths: IpPacketRouterPaths,
|
||||
|
||||
pub logging: LoggingSettings,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn validate(&self) -> bool {
|
||||
// no other sections have explicit requirements (yet)
|
||||
self.base.validate()
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn set_no_poisson_process(&mut self) {
|
||||
self.base.set_no_poisson_process()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct IpPacketRouter {
|
||||
/// Disable Poisson sending rate.
|
||||
pub disable_poisson_rate: bool,
|
||||
|
||||
/// Specifies the url for an upstream source of the exit policy used by this node.
|
||||
pub upstream_exit_policy_url: Option<Url>,
|
||||
}
|
||||
|
||||
impl Default for IpPacketRouter {
|
||||
fn default() -> Self {
|
||||
IpPacketRouter {
|
||||
disable_poisson_rate: true,
|
||||
#[allow(clippy::expect_used)]
|
||||
upstream_exit_policy_url: Some(
|
||||
mainnet::EXIT_POLICY_URL
|
||||
.parse()
|
||||
.expect("invalid default exit policy URL"),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-9
@@ -1,5 +1,5 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::net::SocketAddr;
|
||||
|
||||
@@ -75,12 +75,6 @@ pub enum IpPacketRouterError {
|
||||
source: PolicyError,
|
||||
},
|
||||
|
||||
#[error("the url provided for the upstream exit policy source is malformed: {source}")]
|
||||
MalformedExitPolicyUpstreamUrl {
|
||||
#[source]
|
||||
source: reqwest::Error,
|
||||
},
|
||||
|
||||
#[error("can't setup an exit policy without any upstream urls")]
|
||||
NoUpstreamExitPolicy,
|
||||
|
||||
@@ -117,5 +111,3 @@ pub enum IpPacketRouterError {
|
||||
#[error("failed to deserialize protocol: {source}")]
|
||||
FailedToDeserializeProtocol { source: ProtocolError },
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, IpPacketRouterError>;
|
||||
+4
-5
@@ -5,6 +5,9 @@ mod v6;
|
||||
mod v7;
|
||||
mod v8;
|
||||
|
||||
use super::ClientVersion;
|
||||
use crate::service_providers::ip_packet_router::clients::ConnectedClientId;
|
||||
use crate::service_providers::ip_packet_router::error::IpPacketRouterError;
|
||||
use nym_ip_packet_requests::{
|
||||
v6::request::IpPacketRequest as IpPacketRequestV6,
|
||||
v7::request::IpPacketRequest as IpPacketRequestV7,
|
||||
@@ -14,10 +17,6 @@ use nym_sdk::mixnet::ReconstructedMessage;
|
||||
use nym_service_provider_requests_common::{Protocol, ServiceProviderType};
|
||||
use std::fmt;
|
||||
|
||||
use crate::{clients::ConnectedClientId, error::IpPacketRouterError};
|
||||
|
||||
use super::ClientVersion;
|
||||
|
||||
// The internal representation of the request after deserialization, valid for all versions
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub(crate) enum IpPacketRequest {
|
||||
@@ -130,7 +129,7 @@ impl TryFrom<&ReconstructedMessage> for IpPacketRequest {
|
||||
Ok(IpPacketRequest::from((request_v8, sender_tag)))
|
||||
}
|
||||
_ => {
|
||||
log::info!("Received packet with invalid version: v{request_version}");
|
||||
tracing::info!("Received packet with invalid version: v{request_version}");
|
||||
Err(IpPacketRouterError::InvalidPacketVersion(request_version))
|
||||
}
|
||||
}
|
||||
+3
-6
@@ -12,12 +12,9 @@ use nym_ip_packet_requests::{
|
||||
v8::response::IpPacketResponse as IpPacketResponseV8, IpPair,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
clients::ConnectedClientId,
|
||||
error::{IpPacketRouterError, Result},
|
||||
};
|
||||
|
||||
use super::ClientVersion;
|
||||
use crate::service_providers::ip_packet_router::clients::ConnectedClientId;
|
||||
use crate::service_providers::ip_packet_router::error::IpPacketRouterError;
|
||||
|
||||
pub(crate) struct VersionedResponse {
|
||||
pub(crate) version: ClientVersion,
|
||||
@@ -124,7 +121,7 @@ pub(crate) struct HealthResponse {
|
||||
}
|
||||
|
||||
impl VersionedResponse {
|
||||
pub(crate) fn try_into_bytes(self) -> Result<Vec<u8>> {
|
||||
pub(crate) fn try_into_bytes(self) -> Result<Vec<u8>, IpPacketRouterError> {
|
||||
match self.version {
|
||||
ClientVersion::V6 => IpPacketResponseV6::try_from(self)?.to_bytes(),
|
||||
ClientVersion::V7 => IpPacketResponseV7::try_from(self)?.to_bytes(),
|
||||
+6
-8
@@ -1,6 +1,12 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use super::{
|
||||
DisconnectFailureReason, DisconnectResponse, DynamicConnectFailureReason,
|
||||
DynamicConnectResponse, DynamicConnectSuccess, HealthResponse, InfoLevel, InfoResponseReply,
|
||||
Response, StaticConnectFailureReason, StaticConnectResponse, VersionedResponse,
|
||||
};
|
||||
use crate::service_providers::ip_packet_router::error::IpPacketRouterError;
|
||||
use nym_ip_packet_requests::v6::response::{
|
||||
DisconnectFailureReason as DisconnectFailureReasonV6,
|
||||
DisconnectResponse as DisconnectResponseV6,
|
||||
@@ -17,14 +23,6 @@ use nym_ip_packet_requests::v6::response::{
|
||||
StaticConnectResponseReply as StaticConnectResponseReplyV6,
|
||||
};
|
||||
|
||||
use crate::error::IpPacketRouterError;
|
||||
|
||||
use super::{
|
||||
DisconnectFailureReason, DisconnectResponse, DynamicConnectFailureReason,
|
||||
DynamicConnectResponse, DynamicConnectSuccess, HealthResponse, InfoLevel, InfoResponseReply,
|
||||
Response, StaticConnectFailureReason, StaticConnectResponse, VersionedResponse,
|
||||
};
|
||||
|
||||
impl TryFrom<VersionedResponse> for IpPacketResponseV6 {
|
||||
type Error = IpPacketRouterError;
|
||||
|
||||
+6
-8
@@ -1,6 +1,12 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use super::{
|
||||
DisconnectFailureReason, DisconnectResponse, DynamicConnectFailureReason,
|
||||
DynamicConnectResponse, DynamicConnectSuccess, HealthResponse, InfoLevel, InfoResponseReply,
|
||||
Response, StaticConnectFailureReason, StaticConnectResponse, VersionedResponse,
|
||||
};
|
||||
use crate::service_providers::ip_packet_router::error::IpPacketRouterError;
|
||||
use nym_ip_packet_requests::v7::response::{
|
||||
DisconnectFailureReason as DisconnectFailureReasonV7,
|
||||
DisconnectResponse as DisconnectResponseV7,
|
||||
@@ -17,14 +23,6 @@ use nym_ip_packet_requests::v7::response::{
|
||||
StaticConnectResponseReply as StaticConnectResponseReplyV7,
|
||||
};
|
||||
|
||||
use crate::error::IpPacketRouterError;
|
||||
|
||||
use super::{
|
||||
DisconnectFailureReason, DisconnectResponse, DynamicConnectFailureReason,
|
||||
DynamicConnectResponse, DynamicConnectSuccess, HealthResponse, InfoLevel, InfoResponseReply,
|
||||
Response, StaticConnectFailureReason, StaticConnectResponse, VersionedResponse,
|
||||
};
|
||||
|
||||
impl TryFrom<VersionedResponse> for IpPacketResponseV7 {
|
||||
type Error = IpPacketRouterError;
|
||||
|
||||
+6
-8
@@ -1,6 +1,12 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use super::{
|
||||
DisconnectFailureReason, DisconnectResponse, DynamicConnectFailureReason,
|
||||
DynamicConnectResponse, DynamicConnectSuccess, HealthResponse, InfoLevel, InfoResponseReply,
|
||||
Response, VersionedResponse,
|
||||
};
|
||||
use crate::service_providers::ip_packet_router::error::IpPacketRouterError;
|
||||
use nym_ip_packet_requests::v8::response::{
|
||||
ConnectFailureReason as ConnectFailureReasonV8, ConnectResponse as ConnectResponseV8,
|
||||
ConnectResponseReply as ConnectResponseReplyV8, ConnectSuccess as ConnectSuccessV8,
|
||||
@@ -13,14 +19,6 @@ use nym_ip_packet_requests::v8::response::{
|
||||
PongResponse as PongResponseV8,
|
||||
};
|
||||
|
||||
use crate::error::IpPacketRouterError;
|
||||
|
||||
use super::{
|
||||
DisconnectFailureReason, DisconnectResponse, DynamicConnectFailureReason,
|
||||
DynamicConnectResponse, DynamicConnectSuccess, HealthResponse, InfoLevel, InfoResponseReply,
|
||||
Response, VersionedResponse,
|
||||
};
|
||||
|
||||
impl TryFrom<VersionedResponse> for IpPacketResponseV8 {
|
||||
type Error = IpPacketRouterError;
|
||||
|
||||
+3
-1
@@ -5,7 +5,9 @@ use nym_client_core::{config::disk_persistence::CommonClientPaths, TopologyProvi
|
||||
use nym_sdk::{GatewayTransceiver, NymNetworkDetails};
|
||||
use nym_task::TaskClient;
|
||||
|
||||
use crate::{config::BaseClientConfig, error::IpPacketRouterError};
|
||||
use crate::service_providers::ip_packet_router::{
|
||||
config::BaseClientConfig, error::IpPacketRouterError,
|
||||
};
|
||||
|
||||
// Helper function to create the mixnet client.
|
||||
// This is NOT in the SDK since we don't want to expose any of the client-core config types.
|
||||
+44
-39
@@ -1,5 +1,5 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use futures::StreamExt;
|
||||
use nym_ip_packet_requests::codec::MultiIpPacketCodec;
|
||||
@@ -10,11 +10,11 @@ use std::{net::SocketAddr, time::Duration};
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio_util::codec::FramedRead;
|
||||
|
||||
use crate::{
|
||||
use crate::service_providers::ip_packet_router::{
|
||||
clients::{ConnectedClientHandler, ConnectedClients},
|
||||
config::Config,
|
||||
constants::DISCONNECT_TIMER_INTERVAL,
|
||||
error::{IpPacketRouterError, Result},
|
||||
error::IpPacketRouterError,
|
||||
messages::{
|
||||
request::{
|
||||
ControlRequest, DataRequest, DisconnectRequest, DynamicConnectRequest, HealthRequest,
|
||||
@@ -28,11 +28,14 @@ use crate::{
|
||||
ClientVersion,
|
||||
},
|
||||
request_filter::RequestFilter,
|
||||
util::parse_ip::ParsedPacket,
|
||||
util::{
|
||||
create_message::create_input_message,
|
||||
parse_ip::{parse_packet, ParsedPacket},
|
||||
},
|
||||
};
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
type TunDevice = crate::non_linux_dummy::DummyDevice;
|
||||
type TunDevice = crate::service_providers::ip_packet_router::non_linux_dummy::DummyDevice;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
type TunDevice = tokio_tun::Tun;
|
||||
@@ -66,7 +69,7 @@ impl MixnetListener {
|
||||
ip_packet: &[u8],
|
||||
version: ClientVersion,
|
||||
) -> PacketHandleResult {
|
||||
log::trace!("Received data request");
|
||||
tracing::trace!("Received data request");
|
||||
|
||||
// We don't forward packets that we are not able to parse. BUT, there might be a good
|
||||
// reason to still forward them.
|
||||
@@ -77,10 +80,10 @@ impl MixnetListener {
|
||||
src_addr,
|
||||
dst_addr,
|
||||
dst,
|
||||
} = crate::util::parse_ip::parse_packet(ip_packet)?;
|
||||
} = parse_packet(ip_packet)?;
|
||||
|
||||
let dst_str = dst.map_or(dst_addr.to_string(), |dst| dst.to_string());
|
||||
log::debug!("Received packet: {packet_type}: {src_addr} -> {dst_str}");
|
||||
tracing::debug!("Received packet: {packet_type}: {src_addr} -> {dst_str}");
|
||||
|
||||
if let Some(connected_client) = self.connected_clients.get_client_from_ip_mut(&src_addr) {
|
||||
// Keep track of activity so we can disconnect inactive clients
|
||||
@@ -98,7 +101,7 @@ impl MixnetListener {
|
||||
.map_err(|_| IpPacketRouterError::FailedToWritePacketToTun)?;
|
||||
Ok(None)
|
||||
} else {
|
||||
log::debug!("Denied filter check: {dst}");
|
||||
tracing::debug!("Denied filter check: {dst}");
|
||||
Ok(Some(VersionedResponse {
|
||||
version,
|
||||
reply_to: connected_client.client_id.clone(),
|
||||
@@ -115,7 +118,7 @@ impl MixnetListener {
|
||||
}
|
||||
} else {
|
||||
// If the client is not connected, just drop the packet silently
|
||||
log::debug!("dropping packet from mixnet: no registered client for packet with source: {src_addr}");
|
||||
tracing::debug!("dropping packet from mixnet: no registered client for packet with source: {src_addr}");
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
@@ -123,7 +126,7 @@ impl MixnetListener {
|
||||
async fn on_data_request(
|
||||
&mut self,
|
||||
data_request: DataRequest,
|
||||
) -> Result<Vec<PacketHandleResult>> {
|
||||
) -> Result<Vec<PacketHandleResult>, IpPacketRouterError> {
|
||||
let mut responses = Vec::new();
|
||||
let decoder = MultiIpPacketCodec::new();
|
||||
let mut framed_reader = FramedRead::new(data_request.ip_packets.as_ref(), decoder);
|
||||
@@ -144,7 +147,7 @@ impl MixnetListener {
|
||||
&mut self,
|
||||
connect_request: StaticConnectRequest,
|
||||
) -> PacketHandleResult {
|
||||
log::info!(
|
||||
tracing::info!(
|
||||
"Received static connect request from {}",
|
||||
connect_request.sent_by
|
||||
);
|
||||
@@ -166,14 +169,14 @@ impl MixnetListener {
|
||||
|
||||
let response = match (is_ip_taken, is_client_id_taken) {
|
||||
(true, true) => {
|
||||
log::info!("Connecting an already connected client");
|
||||
tracing::info!("Connecting an already connected client");
|
||||
if self
|
||||
.connected_clients
|
||||
.update_activity(&requested_ips)
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
log::error!("Failed to update activity for client");
|
||||
tracing::error!("Failed to update activity for client");
|
||||
};
|
||||
Response::StaticConnect {
|
||||
request_id,
|
||||
@@ -181,7 +184,7 @@ impl MixnetListener {
|
||||
}
|
||||
}
|
||||
(false, false) => {
|
||||
log::info!("Connecting a new client");
|
||||
tracing::info!("Connecting a new client");
|
||||
|
||||
// Spawn the ConnectedClientHandler for the new client
|
||||
let (forward_from_tun_tx, close_tx, handle) = ConnectedClientHandler::start(
|
||||
@@ -205,14 +208,14 @@ impl MixnetListener {
|
||||
}
|
||||
}
|
||||
(true, false) => {
|
||||
log::info!("Requested IP is not available");
|
||||
tracing::info!("Requested IP is not available");
|
||||
Response::StaticConnect {
|
||||
request_id,
|
||||
reply: StaticConnectFailureReason::RequestedIpAlreadyInUse.into(),
|
||||
}
|
||||
}
|
||||
(false, true) => {
|
||||
log::info!("Nym address is already registered");
|
||||
tracing::info!("Nym address is already registered");
|
||||
Response::StaticConnect {
|
||||
request_id,
|
||||
reply: StaticConnectFailureReason::ClientAlreadyConnected.into(),
|
||||
@@ -231,7 +234,7 @@ impl MixnetListener {
|
||||
&mut self,
|
||||
connect_request: DynamicConnectRequest,
|
||||
) -> PacketHandleResult {
|
||||
log::info!(
|
||||
tracing::info!(
|
||||
"Received dynamic connect request from {}",
|
||||
connect_request.sent_by
|
||||
);
|
||||
@@ -245,7 +248,7 @@ impl MixnetListener {
|
||||
.unwrap_or(nym_ip_packet_requests::codec::BUFFER_TIMEOUT);
|
||||
|
||||
if let Some(ips) = self.connected_clients.lookup_ip_from_client_id(&reply_to) {
|
||||
log::debug!("Reconnecting to the previous session");
|
||||
tracing::debug!("Reconnecting to the previous session");
|
||||
return Ok(Some(VersionedResponse {
|
||||
version,
|
||||
reply_to,
|
||||
@@ -257,7 +260,7 @@ impl MixnetListener {
|
||||
}
|
||||
|
||||
let Some(new_ips) = self.connected_clients.find_new_ip() else {
|
||||
log::info!("No available IP address");
|
||||
tracing::info!("No available IP address");
|
||||
return Ok(Some(VersionedResponse {
|
||||
version,
|
||||
reply_to,
|
||||
@@ -299,7 +302,7 @@ impl MixnetListener {
|
||||
&mut self,
|
||||
disconnect_request: DisconnectRequest,
|
||||
) -> PacketHandleResult {
|
||||
log::info!(
|
||||
tracing::info!(
|
||||
"Received disconnect request from {}",
|
||||
disconnect_request.sent_by
|
||||
);
|
||||
@@ -310,7 +313,7 @@ impl MixnetListener {
|
||||
|
||||
// Check if the client is connected
|
||||
if !self.connected_clients.is_client_connected(&client_id) {
|
||||
log::info!("Client {client_id} is not connected, cannot disconnect");
|
||||
tracing::info!("Client {client_id} is not connected, cannot disconnect");
|
||||
return Ok(Some(VersionedResponse {
|
||||
version,
|
||||
reply_to: client_id,
|
||||
@@ -322,7 +325,7 @@ impl MixnetListener {
|
||||
}
|
||||
|
||||
// Disconnect the client
|
||||
log::info!("Disconnecting client {client_id}");
|
||||
tracing::info!("Disconnecting client {client_id}");
|
||||
self.connected_clients.disconnect_client(&client_id);
|
||||
|
||||
Ok(Some(VersionedResponse {
|
||||
@@ -383,8 +386,8 @@ impl MixnetListener {
|
||||
async fn on_reconstructed_message(
|
||||
&mut self,
|
||||
reconstructed: ReconstructedMessage,
|
||||
) -> Result<Vec<PacketHandleResult>> {
|
||||
log::debug!(
|
||||
) -> Result<Vec<PacketHandleResult>, IpPacketRouterError> {
|
||||
tracing::debug!(
|
||||
"Received message with sender_tag: {}",
|
||||
reconstructed
|
||||
.sender_tag
|
||||
@@ -395,13 +398,13 @@ impl MixnetListener {
|
||||
// First deserialize the request
|
||||
let request = match IpPacketRequest::try_from(&reconstructed) {
|
||||
Err(IpPacketRouterError::InvalidPacketVersion(version)) => {
|
||||
log::debug!("Received packet with invalid version: v{version}");
|
||||
tracing::debug!("Received packet with invalid version: v{version}");
|
||||
return Ok(vec![self.on_version_mismatch(version, &reconstructed)]);
|
||||
}
|
||||
req => req,
|
||||
}?;
|
||||
|
||||
log::debug!("Received request: {request}");
|
||||
tracing::debug!("Received request: {request}");
|
||||
|
||||
match request {
|
||||
IpPacketRequest::Data(request) => self.on_data_request(request).await,
|
||||
@@ -417,7 +420,7 @@ impl MixnetListener {
|
||||
//for (ip, nym_address) in stopped_clients.iter().chain(disconnected_clients.iter()) {
|
||||
// let response = IpPacketResponse::new_unrequested_disconnect(...)
|
||||
// if let Err(err) = self.handle_response(response).await {
|
||||
// log::error!("Failed to send disconnect response: {err}");
|
||||
// tracing::error!("Failed to send disconnect response: {err}");
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -429,11 +432,13 @@ impl MixnetListener {
|
||||
|
||||
// When an incoming mixnet message triggers a response that we send back, such as during
|
||||
// connect handshake.
|
||||
async fn handle_response(&self, response: VersionedResponse) -> Result<()> {
|
||||
async fn handle_response(
|
||||
&self,
|
||||
response: VersionedResponse,
|
||||
) -> Result<(), IpPacketRouterError> {
|
||||
let send_to = response.reply_to.clone();
|
||||
let response_bytes = response.try_into_bytes()?;
|
||||
let input_message =
|
||||
crate::util::create_message::create_input_message(&send_to, response_bytes);
|
||||
let input_message = create_input_message(&send_to, response_bytes);
|
||||
|
||||
self.mixnet_client.send(input_message).await.map_err(|err| {
|
||||
IpPacketRouterError::FailedToSendPacketToMixnet {
|
||||
@@ -449,27 +454,27 @@ impl MixnetListener {
|
||||
match response {
|
||||
Ok(Some(response)) => {
|
||||
if let Err(err) = self.handle_response(response).await {
|
||||
log::error!("Mixnet listener failed to handle response: {err}");
|
||||
tracing::error!("Mixnet listener failed to handle response: {err}");
|
||||
}
|
||||
}
|
||||
Ok(None) => {
|
||||
continue;
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("Error handling mixnet message: {err}");
|
||||
tracing::error!("Error handling mixnet message: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn run(mut self) -> Result<()> {
|
||||
pub(crate) async fn run(mut self) -> Result<(), IpPacketRouterError> {
|
||||
let mut task_client = self.task_handle.fork("main_loop");
|
||||
let mut disconnect_timer = tokio::time::interval(DISCONNECT_TIMER_INTERVAL);
|
||||
|
||||
while !task_client.is_shutdown() {
|
||||
tokio::select! {
|
||||
_ = task_client.recv() => {
|
||||
log::debug!("IpPacketRouter [main loop]: received shutdown");
|
||||
tracing::debug!("IpPacketRouter [main loop]: received shutdown");
|
||||
},
|
||||
_ = disconnect_timer.tick() => {
|
||||
self.handle_disconnect_timer().await;
|
||||
@@ -479,21 +484,21 @@ impl MixnetListener {
|
||||
match self.on_reconstructed_message(msg).await {
|
||||
Ok(responses) => self.handle_responses(responses).await,
|
||||
Err(err) => {
|
||||
log::error!("Error handling reconstructed mixnet message: {err}");
|
||||
tracing::error!("Error handling reconstructed mixnet message: {err}");
|
||||
}
|
||||
|
||||
};
|
||||
} else {
|
||||
log::trace!("IpPacketRouter [main loop]: stopping since channel closed");
|
||||
tracing::trace!("IpPacketRouter [main loop]: stopping since channel closed");
|
||||
break;
|
||||
};
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
log::debug!("IpPacketRouter: stopping");
|
||||
tracing::debug!("IpPacketRouter: stopping");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type PacketHandleResult = Result<Option<VersionedResponse>>;
|
||||
pub(crate) type PacketHandleResult = Result<Option<VersionedResponse>, IpPacketRouterError>;
|
||||
+26
-8
@@ -4,8 +4,9 @@
|
||||
#![cfg_attr(not(target_os = "linux"), allow(dead_code))]
|
||||
#![cfg_attr(not(target_os = "linux"), allow(unused_imports))]
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use crate::node::internal_service_providers::ip_packet_router::{
|
||||
error::IpPacketRouterError, request_filter::RequestFilter,
|
||||
};
|
||||
use futures::channel::oneshot;
|
||||
use nym_client_core::{
|
||||
client::mix_traffic::transceiver::GatewayTransceiver, HardcodedTopologyProvider,
|
||||
@@ -13,8 +14,23 @@ use nym_client_core::{
|
||||
};
|
||||
use nym_sdk::mixnet::Recipient;
|
||||
use nym_task::{TaskClient, TaskHandle};
|
||||
use std::path::Path;
|
||||
|
||||
use crate::{config::Config, error::IpPacketRouterError, request_filter::RequestFilter};
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
pub mod request_filter;
|
||||
|
||||
pub(crate) mod messages;
|
||||
pub(crate) mod non_linux_dummy;
|
||||
|
||||
mod clients;
|
||||
mod constants;
|
||||
mod mixnet_client;
|
||||
mod mixnet_listener;
|
||||
mod tun_listener;
|
||||
mod util;
|
||||
|
||||
pub use config::Config;
|
||||
|
||||
pub struct OnStartData {
|
||||
// to add more fields as required
|
||||
@@ -115,7 +131,9 @@ impl IpPacketRouter {
|
||||
pub async fn run_service_provider(self) -> Result<(), IpPacketRouterError> {
|
||||
// for debugging purposes, don't crash in debug builds on non-linux platforms
|
||||
if cfg!(debug_assertions) {
|
||||
log::error!("ip packet router service provider is not yet supported on this platform");
|
||||
tracing::error!(
|
||||
"ip packet router service provider is not yet supported on this platform"
|
||||
);
|
||||
Ok(())
|
||||
} else {
|
||||
todo!("service provider is not yet supported on this platform")
|
||||
@@ -126,14 +144,14 @@ impl IpPacketRouter {
|
||||
pub async fn run_service_provider(self) -> Result<(), IpPacketRouterError> {
|
||||
// Used to notify tasks to shutdown. Not all tasks fully supports this (yet).
|
||||
|
||||
use crate::{
|
||||
use crate::service_providers::ip_packet_router::{
|
||||
clients::ConnectedClients, mixnet_listener::MixnetListener,
|
||||
request_filter::RequestFilter, tun_listener::TunListener,
|
||||
};
|
||||
let task_handle: TaskHandle = self.shutdown.map(Into::into).unwrap_or_default();
|
||||
|
||||
// Connect to the mixnet
|
||||
let mixnet_client = crate::mixnet_client::create_mixnet_client(
|
||||
let mixnet_client = mixnet_client::create_mixnet_client(
|
||||
&self.config.base,
|
||||
task_handle.get_handle().named("nym_sdk::MixnetClient[IPR]"),
|
||||
self.custom_gateway_transceiver,
|
||||
@@ -180,8 +198,8 @@ impl IpPacketRouter {
|
||||
connected_clients,
|
||||
};
|
||||
|
||||
log::info!("The address of this client is: {self_address}");
|
||||
log::info!("All systems go. Press CTRL-C to stop the server.");
|
||||
tracing::info!("The address of this client is: {self_address}");
|
||||
tracing::info!("All systems go. Press CTRL-C to stop the server.");
|
||||
|
||||
if let Some(on_start) = self.on_start {
|
||||
if on_start
|
||||
+3
-9
@@ -1,12 +1,10 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use crate::error::IpPacketRouterError;
|
||||
use crate::service_providers::ip_packet_router::error::IpPacketRouterError;
|
||||
use nym_exit_policy::client::get_exit_policy;
|
||||
use nym_exit_policy::ExitPolicy;
|
||||
use reqwest::IntoUrl;
|
||||
use std::net::SocketAddr;
|
||||
use url::Url;
|
||||
|
||||
pub struct ExitPolicyRequestFilter {
|
||||
@@ -16,11 +14,7 @@ pub struct ExitPolicyRequestFilter {
|
||||
}
|
||||
|
||||
impl ExitPolicyRequestFilter {
|
||||
pub(crate) async fn new_upstream(url: impl IntoUrl) -> Result<Self, IpPacketRouterError> {
|
||||
let url = url
|
||||
.into_url()
|
||||
.map_err(|source| IpPacketRouterError::MalformedExitPolicyUpstreamUrl { source })?;
|
||||
|
||||
pub(crate) async fn new_upstream(url: Url) -> Result<Self, IpPacketRouterError> {
|
||||
Ok(ExitPolicyRequestFilter {
|
||||
upstream: Some(url.clone()),
|
||||
policy: get_exit_policy(url).await?,
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::error::IpPacketRouterError;
|
||||
use crate::request_filter::exit_policy::ExitPolicyRequestFilter;
|
||||
use log::{info, warn};
|
||||
use crate::service_providers::ip_packet_router::error::IpPacketRouterError;
|
||||
use crate::service_providers::ip_packet_router::request_filter::exit_policy::ExitPolicyRequestFilter;
|
||||
use crate::service_providers::ip_packet_router::Config;
|
||||
use std::{net::SocketAddr, sync::Arc};
|
||||
use tracing::{info, warn};
|
||||
|
||||
pub mod exit_policy;
|
||||
|
||||
+24
-22
@@ -1,17 +1,17 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_ip_packet_requests::IpPair;
|
||||
use nym_task::TaskClient;
|
||||
use std::collections::HashMap;
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
#[cfg(target_os = "linux")]
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use crate::clients::{ConnectEvent, ConnectedClientEvent, DisconnectEvent};
|
||||
use crate::{error::Result, util::parse_ip::parse_dst_addr};
|
||||
use crate::node::internal_service_providers::ip_packet_router::clients::{
|
||||
ConnectEvent, ConnectedClientEvent, DisconnectEvent,
|
||||
};
|
||||
use crate::service_providers::ip_packet_router::error::IpPacketRouterError;
|
||||
|
||||
// The TUN listener keeps a local map of the connected clients that has its state updated by the
|
||||
// mixnet listener. Basically it's just so that we don't have to have mutexes around shared state.
|
||||
@@ -50,7 +50,7 @@ impl ConnectedClientsListener {
|
||||
ips,
|
||||
forward_from_tun_tx,
|
||||
} = *connected_event;
|
||||
log::trace!("Connect client: {ips}");
|
||||
tracing::trace!("Connect client: {ips}");
|
||||
self.clients_ipv4.insert(
|
||||
ips.ipv4,
|
||||
ConnectedClientMirror {
|
||||
@@ -67,7 +67,7 @@ impl ConnectedClientsListener {
|
||||
);
|
||||
}
|
||||
ConnectedClientEvent::Disconnect(DisconnectEvent(ips)) => {
|
||||
log::trace!("Disconnect client: {ips}");
|
||||
tracing::trace!("Disconnect client: {ips}");
|
||||
self.clients_ipv4.remove(&ips.ipv4);
|
||||
self.clients_ipv6.remove(&ips.ipv6);
|
||||
}
|
||||
@@ -79,15 +79,17 @@ impl ConnectedClientsListener {
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) struct TunListener {
|
||||
pub(crate) tun_reader: tokio::io::ReadHalf<tokio_tun::Tun>,
|
||||
pub(crate) task_client: TaskClient,
|
||||
pub(crate) task_client: nym_task::TaskClient,
|
||||
pub(crate) connected_clients: ConnectedClientsListener,
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
impl TunListener {
|
||||
async fn handle_packet(&mut self, buf: &[u8], len: usize) -> Result<()> {
|
||||
let Some(dst_addr) = parse_dst_addr(&buf[..len]) else {
|
||||
log::warn!("Failed to parse packet");
|
||||
async fn handle_packet(&mut self, buf: &[u8], len: usize) -> Result<(), IpPacketRouterError> {
|
||||
let Some(dst_addr) =
|
||||
crate::service_providers::ip_packet_router::util::parse_ip::parse_dst_addr(&buf[..len])
|
||||
else {
|
||||
tracing::warn!("Failed to parse packet");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
@@ -98,12 +100,12 @@ impl TunListener {
|
||||
{
|
||||
let packet = buf[..len].to_vec();
|
||||
if forward_from_tun_tx.send(packet).is_err() {
|
||||
log::warn!("Failed to forward packet to connected client {dst_addr}: disconnecting it from tun listener");
|
||||
tracing::warn!("Failed to forward packet to connected client {dst_addr}: disconnecting it from tun listener");
|
||||
self.connected_clients
|
||||
.update(ConnectedClientEvent::Disconnect(DisconnectEvent(*ips)));
|
||||
}
|
||||
} else {
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"dropping packet from network: no registered client for destination: {dst_addr}"
|
||||
);
|
||||
}
|
||||
@@ -111,42 +113,42 @@ impl TunListener {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn run(mut self) -> Result<()> {
|
||||
async fn run(mut self) -> Result<(), IpPacketRouterError> {
|
||||
let mut buf = [0u8; 65535];
|
||||
while !self.task_client.is_shutdown() {
|
||||
tokio::select! {
|
||||
_ = self.task_client.recv() => {
|
||||
log::trace!("TunListener: received shutdown");
|
||||
tracing::trace!("TunListener: received shutdown");
|
||||
},
|
||||
// TODO: ConnectedClientsListener::update should poll the channel instead
|
||||
event = self.connected_clients.connected_client_rx.recv() => match event {
|
||||
Some(event) => self.connected_clients.update(event),
|
||||
None => {
|
||||
log::error!("TunListener: connected client channel closed");
|
||||
tracing::error!("TunListener: connected client channel closed");
|
||||
break;
|
||||
},
|
||||
},
|
||||
len = self.tun_reader.read(&mut buf) => match len {
|
||||
Ok(len) => {
|
||||
if let Err(err) = self.handle_packet(&buf, len).await {
|
||||
log::error!("tun: failed to handle packet: {err}");
|
||||
tracing::error!("tun: failed to handle packet: {err}");
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
log::warn!("iface: read error: {err}");
|
||||
tracing::warn!("iface: read error: {err}");
|
||||
// break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
log::debug!("TunListener: stopping");
|
||||
tracing::debug!("TunListener: stopping");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn start(self) {
|
||||
tokio::spawn(async move {
|
||||
if let Err(err) = self.run().await {
|
||||
log::error!("tun listener router has failed: {err}")
|
||||
tracing::error!("tun listener router has failed: {err}")
|
||||
}
|
||||
});
|
||||
}
|
||||
+1
-2
@@ -1,8 +1,7 @@
|
||||
use crate::service_providers::ip_packet_router::clients::ConnectedClientId;
|
||||
use nym_sdk::mixnet::InputMessage;
|
||||
use nym_task::connections::TransmissionLane;
|
||||
|
||||
use crate::clients::ConnectedClientId;
|
||||
|
||||
pub(crate) fn create_input_message(
|
||||
recipient: &ConnectedClientId,
|
||||
response_packet: Vec<u8>,
|
||||
+4
-5
@@ -1,7 +1,6 @@
|
||||
use crate::service_providers::ip_packet_router::error::IpPacketRouterError;
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||
|
||||
use crate::error::IpPacketRouterError;
|
||||
|
||||
pub(crate) struct ParsedPacket<'a> {
|
||||
pub(crate) packet_type: &'a str,
|
||||
pub(crate) src_addr: IpAddr,
|
||||
@@ -11,7 +10,7 @@ pub(crate) struct ParsedPacket<'a> {
|
||||
|
||||
pub(crate) fn parse_packet(packet: &[u8]) -> Result<ParsedPacket<'_>, IpPacketRouterError> {
|
||||
let headers = etherparse::SlicedPacket::from_ip(packet).map_err(|err| {
|
||||
log::warn!("Unable to parse incoming data as IP packet: {err}");
|
||||
tracing::warn!("Unable to parse incoming data as IP packet: {err}");
|
||||
IpPacketRouterError::PacketParseFailed { source: err }
|
||||
})?;
|
||||
|
||||
@@ -22,7 +21,7 @@ pub(crate) fn parse_packet(packet: &[u8]) -> Result<ParsedPacket<'_>, IpPacketRo
|
||||
Some(etherparse::TransportSlice::Icmpv6(_)) => ("icmpv6", None),
|
||||
Some(etherparse::TransportSlice::Unknown(_)) => ("unknown", None),
|
||||
None => {
|
||||
log::warn!("Received packet missing transport header");
|
||||
tracing::warn!("Received packet missing transport header");
|
||||
return Err(IpPacketRouterError::PacketMissingTransportHeader);
|
||||
}
|
||||
};
|
||||
@@ -41,7 +40,7 @@ pub(crate) fn parse_packet(packet: &[u8]) -> Result<ParsedPacket<'_>, IpPacketRo
|
||||
(src_addr, dst_addr, dst)
|
||||
}
|
||||
None => {
|
||||
log::warn!("Received packet missing IP header");
|
||||
tracing::warn!("Received packet missing IP header");
|
||||
return Err(IpPacketRouterError::PacketMissingIpHeader);
|
||||
}
|
||||
};
|
||||
@@ -6,35 +6,54 @@ use crate::node::client_handling::websocket::message_receiver::{
|
||||
MixMessageReceiver, MixMessageSender,
|
||||
};
|
||||
use crate::node::internal_service_providers::authenticator::Authenticator;
|
||||
use crate::node::internal_service_providers::network_requester::{
|
||||
error::NetworkRequesterError, NRServiceProviderBuilder,
|
||||
};
|
||||
use crate::service_providers::ip_packet_router::{error::IpPacketRouterError, IpPacketRouter};
|
||||
use crate::GatewayError;
|
||||
use async_trait::async_trait;
|
||||
use futures::channel::{mpsc, oneshot};
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
use nym_ip_packet_router::IpPacketRouter;
|
||||
use nym_mixnet_client::forwarder::MixForwardingSender;
|
||||
use nym_network_requester::error::NetworkRequesterError;
|
||||
use nym_network_requester::NRServiceProviderBuilder;
|
||||
use nym_sdk::mixnet::Recipient;
|
||||
use nym_sdk::{GatewayTransceiver, LocalGateway, PacketRouter};
|
||||
use nym_task::TaskClient;
|
||||
use std::fmt::Display;
|
||||
use tokio::task::JoinHandle;
|
||||
use tracing::error;
|
||||
|
||||
pub use nym_client_core::{
|
||||
client::{
|
||||
base_client::{
|
||||
non_wasm_helpers::{setup_fs_gateways_storage, setup_fs_reply_surb_backend},
|
||||
storage::{
|
||||
gateways_storage::{
|
||||
CustomGatewayDetails, GatewayDetails, GatewayRegistration, RemoteGatewayDetails,
|
||||
},
|
||||
helpers::{set_active_gateway, store_gateway_details},
|
||||
GatewaysDetailsStore, OnDiskGatewaysDetails, OnDiskPersistent,
|
||||
},
|
||||
},
|
||||
key_manager::persistence::OnDiskKeys,
|
||||
mix_traffic::transceiver::*,
|
||||
},
|
||||
error::ClientCoreError,
|
||||
};
|
||||
|
||||
pub mod authenticator;
|
||||
pub mod ip_packet_router;
|
||||
pub mod network_requester;
|
||||
|
||||
pub trait LocalRecipient {
|
||||
fn address(&self) -> Recipient;
|
||||
}
|
||||
|
||||
impl LocalRecipient for nym_network_requester::core::OnStartData {
|
||||
impl LocalRecipient for network_requester::OnStartData {
|
||||
fn address(&self) -> Recipient {
|
||||
self.address
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalRecipient for nym_ip_packet_router::OnStartData {
|
||||
impl LocalRecipient for ip_packet_router::OnStartData {
|
||||
fn address(&self) -> Recipient {
|
||||
self.address
|
||||
}
|
||||
@@ -58,7 +77,7 @@ pub trait RunnableServiceProvider {
|
||||
#[async_trait]
|
||||
impl RunnableServiceProvider for NRServiceProviderBuilder {
|
||||
const NAME: &'static str = "network requester";
|
||||
type OnStartData = nym_network_requester::core::OnStartData;
|
||||
type OnStartData = network_requester::OnStartData;
|
||||
type Error = NetworkRequesterError;
|
||||
|
||||
async fn run_service_provider(self) -> Result<(), Self::Error> {
|
||||
@@ -69,7 +88,7 @@ impl RunnableServiceProvider for NRServiceProviderBuilder {
|
||||
#[async_trait]
|
||||
impl RunnableServiceProvider for IpPacketRouter {
|
||||
const NAME: &'static str = "ip router";
|
||||
type OnStartData = nym_ip_packet_router::OnStartData;
|
||||
type OnStartData = ip_packet_router::OnStartData;
|
||||
type Error = IpPacketRouterError;
|
||||
|
||||
async fn run_service_provider(self) -> Result<(), Self::Error> {
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use nym_network_defaults::mainnet;
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
|
||||
pub use nym_client_core::config::Config as BaseClientConfig;
|
||||
pub use persistence::NetworkRequesterPaths;
|
||||
|
||||
mod persistence;
|
||||
|
||||
pub const DEFAULT_STANDARD_LIST_UPDATE_INTERVAL: Duration = Duration::from_secs(30 * 60);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Config {
|
||||
pub base: BaseClientConfig,
|
||||
|
||||
pub network_requester: NetworkRequester,
|
||||
|
||||
pub storage_paths: NetworkRequesterPaths,
|
||||
|
||||
pub network_requester_debug: Debug,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
// this is a false positive, this method is actually called when used as a library
|
||||
// but clippy complains about it when building the binary
|
||||
#[must_use]
|
||||
pub fn with_data_directory<P: AsRef<Path>>(mut self, data_directory: P) -> Self {
|
||||
self.storage_paths = NetworkRequesterPaths::new_base(data_directory);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> bool {
|
||||
// no other sections have explicit requirements (yet)
|
||||
self.base.validate()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_open_proxy(mut self, open_proxy: bool) -> Self {
|
||||
self.network_requester.open_proxy = open_proxy;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct NetworkRequester {
|
||||
/// specifies whether this network requester should run in 'open-proxy' mode
|
||||
/// and thus would attempt to resolve **ANY** request it receives.
|
||||
pub open_proxy: bool,
|
||||
|
||||
/// Disable Poisson sending rate.
|
||||
/// This is equivalent to setting debug.traffic.disable_main_poisson_packet_distribution = true,
|
||||
pub disable_poisson_rate: bool,
|
||||
|
||||
/// Specifies the url for an upstream source of the exit policy used by this node.
|
||||
pub upstream_exit_policy_url: Option<Url>,
|
||||
}
|
||||
|
||||
#[allow(clippy::expect_used)]
|
||||
impl Default for NetworkRequester {
|
||||
fn default() -> Self {
|
||||
NetworkRequester {
|
||||
open_proxy: false,
|
||||
disable_poisson_rate: true,
|
||||
upstream_exit_policy_url: Some(
|
||||
mainnet::EXIT_POLICY_URL
|
||||
.parse()
|
||||
.expect("invalid default exit policy URL"),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Debug {
|
||||
/// Defines how often the standard allow list should get updated
|
||||
/// Deprecated
|
||||
pub standard_list_update_interval: Duration,
|
||||
}
|
||||
|
||||
impl Default for Debug {
|
||||
fn default() -> Self {
|
||||
Debug {
|
||||
standard_list_update_interval: DEFAULT_STANDARD_LIST_UPDATE_INTERVAL,
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -1,12 +1,10 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_client_core::config::disk_persistence::CommonClientPaths;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::Path;
|
||||
|
||||
pub mod old;
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
|
||||
pub struct NetworkRequesterPaths {
|
||||
#[serde(flatten)]
|
||||
+67
-45
@@ -1,16 +1,17 @@
|
||||
// Copyright 2020-2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::{BaseClientConfig, Config};
|
||||
use crate::error::NetworkRequesterError;
|
||||
use crate::reply::MixnetMessage;
|
||||
use crate::request_filter::RequestFilter;
|
||||
use crate::{reply, socks5};
|
||||
use crate::node::internal_service_providers::network_requester::config::{
|
||||
BaseClientConfig, Config,
|
||||
};
|
||||
use crate::node::internal_service_providers::network_requester::error::NetworkRequesterError;
|
||||
use crate::node::internal_service_providers::network_requester::reply::MixnetMessage;
|
||||
use crate::node::internal_service_providers::network_requester::request_filter::RequestFilter;
|
||||
use crate::node::internal_service_providers::network_requester::{reply, socks5};
|
||||
use async_trait::async_trait;
|
||||
use futures::channel::{mpsc, oneshot};
|
||||
use futures::stream::StreamExt;
|
||||
use log::{debug, warn};
|
||||
use nym_bin_common::bin_info_owned;
|
||||
use nym_bin_common::build_information::BinaryBuildInformation;
|
||||
use nym_client_core::client::mix_traffic::transceiver::GatewayTransceiver;
|
||||
use nym_client_core::config::disk_persistence::CommonClientPaths;
|
||||
use nym_client_core::HardcodedTopologyProvider;
|
||||
@@ -38,6 +39,7 @@ use nym_task::manager::TaskHandle;
|
||||
use nym_task::TaskClient;
|
||||
use std::path::Path;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use tracing::{debug, error, warn};
|
||||
|
||||
// Since it's an atomic, it's safe to be kept static and shared across threads
|
||||
static ACTIVE_PROXIES: AtomicUsize = AtomicUsize::new(0);
|
||||
@@ -69,6 +71,7 @@ pub struct NRServiceProviderBuilder {
|
||||
custom_gateway_transceiver: Option<Box<dyn GatewayTransceiver + Send + Sync>>,
|
||||
shutdown: Option<TaskClient>,
|
||||
on_start: Option<oneshot::Sender<OnStartData>>,
|
||||
binary_build_information: BinaryBuildInformation,
|
||||
}
|
||||
|
||||
pub struct NRServiceProvider {
|
||||
@@ -77,6 +80,7 @@ pub struct NRServiceProvider {
|
||||
|
||||
mixnet_client: nym_sdk::mixnet::MixnetClient,
|
||||
controller_sender: ControllerSender,
|
||||
binary_build_information: BinaryBuildInformation,
|
||||
|
||||
mix_input_sender: MixProxySender<MixnetMessage>,
|
||||
shutdown: TaskHandle,
|
||||
@@ -92,15 +96,14 @@ impl ServiceProvider<Socks5Request> for NRServiceProvider {
|
||||
request: Request<Socks5Request>,
|
||||
) -> Result<(), Self::ServiceProviderError> {
|
||||
// TODO: this should perhaps be parallelised
|
||||
log::debug!("on_request {:?}", request);
|
||||
tracing::debug!("on_request {:?}", request);
|
||||
if let Some(response) = self.handle_request(sender, request).await? {
|
||||
// TODO: this (i.e. `reply::MixnetAddress`) should be incorporated into the actual interface
|
||||
if let Some(return_address) = reply::MixnetAddress::new(None, sender) {
|
||||
let msg = MixnetMessage::new_provider_response(return_address, 0, response);
|
||||
self.mix_input_sender
|
||||
.send(msg)
|
||||
.await
|
||||
.expect("InputMessageReceiver has stopped receiving!");
|
||||
if self.mix_input_sender.send(msg).await.is_err() {
|
||||
error!("InputMessageReceiver has stopped receiving!");
|
||||
}
|
||||
} else {
|
||||
warn!("currently we can only send generic replies via reply surbs and we haven't got any : (")
|
||||
}
|
||||
@@ -113,7 +116,7 @@ impl ServiceProvider<Socks5Request> for NRServiceProvider {
|
||||
) -> Result<BinaryInformation, Self::ServiceProviderError> {
|
||||
Ok(BinaryInformation {
|
||||
binary_name: env!("CARGO_PKG_NAME").to_string(),
|
||||
build_information: bin_info_owned!(),
|
||||
build_information: self.binary_build_information.to_owned(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -123,12 +126,12 @@ impl ServiceProvider<Socks5Request> for NRServiceProvider {
|
||||
request: Socks5Request,
|
||||
interface_version: ProviderInterfaceVersion,
|
||||
) -> Result<Option<Socks5Response>, Self::ServiceProviderError> {
|
||||
log::debug!("handle_provider_data_request {:?}", request);
|
||||
tracing::debug!("handle_provider_data_request {:?}", request);
|
||||
|
||||
// TODO: streamline this a bit more
|
||||
let request_version = RequestVersion::new(interface_version, request.protocol_version);
|
||||
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"received request of version {:?} (interface) / {:?} (socks5)",
|
||||
interface_version,
|
||||
request.protocol_version
|
||||
@@ -148,7 +151,10 @@ impl ServiceProvider<Socks5Request> for NRServiceProvider {
|
||||
}
|
||||
|
||||
impl NRServiceProviderBuilder {
|
||||
pub fn new(config: Config) -> NRServiceProviderBuilder {
|
||||
pub fn new(
|
||||
config: Config,
|
||||
binary_build_information: BinaryBuildInformation,
|
||||
) -> NRServiceProviderBuilder {
|
||||
NRServiceProviderBuilder {
|
||||
config,
|
||||
wait_for_gateway: false,
|
||||
@@ -156,6 +162,7 @@ impl NRServiceProviderBuilder {
|
||||
custom_gateway_transceiver: None,
|
||||
shutdown: None,
|
||||
on_start: None,
|
||||
binary_build_information,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,12 +291,13 @@ impl NRServiceProviderBuilder {
|
||||
request_filter: request_filter.clone(),
|
||||
mixnet_client,
|
||||
controller_sender,
|
||||
binary_build_information: self.binary_build_information,
|
||||
mix_input_sender,
|
||||
shutdown,
|
||||
};
|
||||
|
||||
log::info!("The address of this client is: {self_address}");
|
||||
log::info!("All systems go. Press CTRL-C to stop the server.");
|
||||
tracing::info!("The address of this client is: {self_address}");
|
||||
tracing::info!("All systems go. Press CTRL-C to stop the server.");
|
||||
|
||||
if let Some(on_start) = self.on_start {
|
||||
if on_start
|
||||
@@ -317,7 +325,7 @@ impl NRServiceProvider {
|
||||
msg = self.mixnet_client.next() => match msg {
|
||||
Some(msg) => self.on_message(msg).await,
|
||||
None => {
|
||||
log::trace!("NRServiceProvider::run: Stopping since channel closed");
|
||||
tracing::trace!("NRServiceProvider::run: Stopping since channel closed");
|
||||
break;
|
||||
}
|
||||
},
|
||||
@@ -333,7 +341,7 @@ impl NRServiceProvider {
|
||||
Ok(req) => req,
|
||||
Err(err) => {
|
||||
// TODO: or should it even be further lowered to debug/trace?
|
||||
log::warn!("Failed to deserialize received message: {err}");
|
||||
tracing::warn!("Failed to deserialize received message: {err}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -342,7 +350,7 @@ impl NRServiceProvider {
|
||||
// TODO: again, should it be a warning?
|
||||
// we should also probably log some information regarding the origin of the request
|
||||
// so that it would be easier to debug it
|
||||
log::warn!("failed to resolve the received request: {err}");
|
||||
tracing::warn!("failed to resolve the received request: {err}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,9 +366,12 @@ impl NRServiceProvider {
|
||||
socks5_msg = mix_input_reader.recv() => {
|
||||
if let Some(msg) = socks5_msg {
|
||||
let response_message = msg.into_input_message(packet_type);
|
||||
mixnet_client_sender.send(response_message).await.unwrap();
|
||||
if mixnet_client_sender.send(response_message).await.is_err() {
|
||||
error!("failed to send response - channel is closed");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
log::error!("Exiting: channel closed!");
|
||||
tracing::error!("Exiting: channel closed!");
|
||||
break;
|
||||
}
|
||||
},
|
||||
@@ -389,7 +400,7 @@ impl NRServiceProvider {
|
||||
{
|
||||
Ok(conn) => conn,
|
||||
Err(err) => {
|
||||
log::error!("error while connecting to {remote_addr}: {err}",);
|
||||
tracing::error!("error while connecting to {remote_addr}: {err}",);
|
||||
shutdown.disarm();
|
||||
|
||||
// inform the remote that the connection is closed before it even was established
|
||||
@@ -400,10 +411,9 @@ impl NRServiceProvider {
|
||||
SocketData::new(0, connection_id, true, Vec::new()),
|
||||
);
|
||||
|
||||
mix_input_sender
|
||||
.send(mixnet_message)
|
||||
.await
|
||||
.expect("InputMessageReceiver has stopped receiving!");
|
||||
if mix_input_sender.send(mixnet_message).await.is_err() {
|
||||
error!("InputMessageReceiver has stopped receiving!")
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -411,15 +421,19 @@ impl NRServiceProvider {
|
||||
|
||||
// Connect implies it's a fresh connection - register it with our controller
|
||||
let (mix_sender, mix_receiver) = mpsc::unbounded();
|
||||
controller_sender
|
||||
if controller_sender
|
||||
.unbounded_send(ControllerCommand::Insert {
|
||||
connection_id,
|
||||
connection_sender: mix_sender,
|
||||
})
|
||||
.unwrap();
|
||||
.is_err()
|
||||
{
|
||||
error!("failed to insert new proxy info - the channel is closed!");
|
||||
return;
|
||||
}
|
||||
|
||||
let old_count = ACTIVE_PROXIES.fetch_add(1, Ordering::SeqCst);
|
||||
log::info!(
|
||||
tracing::info!(
|
||||
"Starting proxy for {remote_addr} (currently there are {} proxies being handled)",
|
||||
old_count + 1
|
||||
);
|
||||
@@ -436,12 +450,15 @@ impl NRServiceProvider {
|
||||
.await;
|
||||
|
||||
// proxy is done - remove the access channel from the controller
|
||||
controller_sender
|
||||
if controller_sender
|
||||
.unbounded_send(ControllerCommand::Remove { connection_id })
|
||||
.unwrap();
|
||||
.is_err()
|
||||
{
|
||||
error!("failed to send controller remove request - the channel is closed")
|
||||
}
|
||||
|
||||
let old_count = ACTIVE_PROXIES.fetch_sub(1, Ordering::SeqCst);
|
||||
log::info!(
|
||||
tracing::info!(
|
||||
"Proxy for {remote_addr} is finished (currently there are {} proxies being handled)",
|
||||
old_count - 1
|
||||
);
|
||||
@@ -456,7 +473,7 @@ impl NRServiceProvider {
|
||||
let Some(return_address) =
|
||||
reply::MixnetAddress::new(connect_req.return_address, sender_tag)
|
||||
else {
|
||||
log::warn!(
|
||||
tracing::warn!(
|
||||
"attempted to start connection with no way of returning data back to the sender"
|
||||
);
|
||||
return;
|
||||
@@ -483,7 +500,7 @@ impl NRServiceProvider {
|
||||
tokio::spawn(async move {
|
||||
if !request_filter.check_address(&remote_addr).await {
|
||||
let log_msg = format!("Domain {remote_addr:?} failed filter check");
|
||||
log::info!("{log_msg}");
|
||||
tracing::info!("{log_msg}");
|
||||
let error_msg = MixnetMessage::new_connection_error(
|
||||
return_address,
|
||||
remote_version,
|
||||
@@ -491,11 +508,12 @@ impl NRServiceProvider {
|
||||
log_msg,
|
||||
);
|
||||
|
||||
mix_input_sender_clone
|
||||
.send(error_msg)
|
||||
.await
|
||||
.expect("InputMessageReceiver has stopped receiving!");
|
||||
shutdown.disarm();
|
||||
if mix_input_sender_clone.send(error_msg).await.is_err() {
|
||||
// don't disarm the shutdown, do cause global shutdown here!
|
||||
error!("InputMessageReceiver has stopped receiving!");
|
||||
} else {
|
||||
shutdown.disarm();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -516,9 +534,13 @@ impl NRServiceProvider {
|
||||
}
|
||||
|
||||
fn handle_proxy_send(&mut self, req: SendRequest) {
|
||||
self.controller_sender
|
||||
if self
|
||||
.controller_sender
|
||||
.unbounded_send(ControllerCommand::new_send(req.data))
|
||||
.unwrap()
|
||||
.is_err()
|
||||
{
|
||||
error!("failed to handle proxy send request - the channel is closed")
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_query(
|
||||
-6
@@ -58,12 +58,6 @@ pub enum NetworkRequesterError {
|
||||
source: PolicyError,
|
||||
},
|
||||
|
||||
#[error("the url provided for the upstream exit policy source is malformed: {source}")]
|
||||
MalformedExitPolicyUpstreamUrl {
|
||||
#[source]
|
||||
source: reqwest::Error,
|
||||
},
|
||||
|
||||
#[error("can't setup an exit policy without any upstream urls")]
|
||||
NoUpstreamExitPolicy,
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
pub mod config;
|
||||
pub mod core;
|
||||
pub mod error;
|
||||
mod reply;
|
||||
pub mod request_filter;
|
||||
mod socks5;
|
||||
|
||||
pub use config::Config;
|
||||
pub use core::{NRServiceProvider, NRServiceProviderBuilder, OnStartData};
|
||||
pub use request_filter::RequestFilter;
|
||||
+4
-9
@@ -1,14 +1,13 @@
|
||||
// Copyright 2023-2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::error::NetworkRequesterError;
|
||||
use log::trace;
|
||||
use crate::node::internal_service_providers::network_requester::config::Config;
|
||||
use crate::node::internal_service_providers::network_requester::error::NetworkRequesterError;
|
||||
use nym_exit_policy::client::get_exit_policy;
|
||||
use nym_exit_policy::ExitPolicy;
|
||||
use nym_socks5_requests::RemoteAddress;
|
||||
use reqwest::IntoUrl;
|
||||
use tokio::net::lookup_host;
|
||||
use tracing::trace;
|
||||
use url::Url;
|
||||
|
||||
pub struct ExitPolicyRequestFilter {
|
||||
@@ -23,11 +22,7 @@ impl From<ExitPolicy> for ExitPolicyRequestFilter {
|
||||
}
|
||||
|
||||
impl ExitPolicyRequestFilter {
|
||||
pub(crate) async fn new_upstream(url: impl IntoUrl) -> Result<Self, NetworkRequesterError> {
|
||||
let url = url
|
||||
.into_url()
|
||||
.map_err(|source| NetworkRequesterError::MalformedExitPolicyUpstreamUrl { source })?;
|
||||
|
||||
pub(crate) async fn new_upstream(url: Url) -> Result<Self, NetworkRequesterError> {
|
||||
Ok(ExitPolicyRequestFilter {
|
||||
upstream: Some(url.clone()),
|
||||
policy: get_exit_policy(url).await?,
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::error::NetworkRequesterError;
|
||||
use log::warn;
|
||||
use crate::node::internal_service_providers::network_requester::config::Config;
|
||||
use crate::node::internal_service_providers::network_requester::error::NetworkRequesterError;
|
||||
use nym_socks5_requests::RemoteAddress;
|
||||
use std::sync::Arc;
|
||||
use tracing::warn;
|
||||
|
||||
pub mod exit_policy;
|
||||
|
||||
+7
-3
@@ -1,8 +1,8 @@
|
||||
// Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::reply;
|
||||
use crate::reply::MixnetMessage;
|
||||
use crate::node::internal_service_providers::network_requester::reply;
|
||||
use crate::node::internal_service_providers::network_requester::reply::MixnetMessage;
|
||||
use nym_service_providers_common::interface::RequestVersion;
|
||||
use nym_socks5_proxy_helpers::connection_controller::ConnectionReceiver;
|
||||
use nym_socks5_proxy_helpers::proxy_runner::{MixProxySender, ProxyRunner};
|
||||
@@ -12,6 +12,7 @@ use nym_task::connections::LaneQueueLengths;
|
||||
use nym_task::TaskClient;
|
||||
use std::io;
|
||||
use tokio::net::TcpStream;
|
||||
use tracing::error;
|
||||
|
||||
/// An outbound TCP connection between the Socks5 service provider, which makes
|
||||
/// requests on behalf of users and returns the responses through
|
||||
@@ -49,7 +50,10 @@ impl Connection {
|
||||
lane_queue_lengths: LaneQueueLengths,
|
||||
shutdown: TaskClient,
|
||||
) {
|
||||
let stream = self.conn.take().unwrap();
|
||||
let Some(stream) = self.conn.take() else {
|
||||
error!("the proxy is being run for the second time");
|
||||
return;
|
||||
};
|
||||
let remote_source_address = "???".to_string(); // we don't know ip address of requester
|
||||
let connection_id = self.id;
|
||||
let return_address = self.return_address.clone();
|
||||
+20
-14
@@ -4,19 +4,21 @@
|
||||
use crate::config::Config;
|
||||
use crate::error::GatewayError;
|
||||
use crate::node::client_handling::websocket;
|
||||
use crate::node::internal_service_providers::authenticator::{self, Authenticator};
|
||||
use crate::node::internal_service_providers::ip_packet_router::{self, IpPacketRouter};
|
||||
use crate::node::internal_service_providers::network_requester::{self, NRServiceProviderBuilder};
|
||||
use crate::node::internal_service_providers::{
|
||||
authenticator, ExitServiceProviders, ServiceProviderBeingBuilt, SpMessageRouterBuilder,
|
||||
ExitServiceProviders, ServiceProviderBeingBuilt, SpMessageRouterBuilder,
|
||||
};
|
||||
use crate::node::stale_data_cleaner::StaleMessagesCleaner;
|
||||
use futures::channel::oneshot;
|
||||
use nym_bin_common::build_information::BinaryBuildInformation;
|
||||
use nym_credential_verification::ecash::{
|
||||
credential_sender::CredentialHandlerConfig, EcashManager,
|
||||
};
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_ip_packet_router::IpPacketRouter;
|
||||
use nym_mixnet_client::forwarder::MixForwardingSender;
|
||||
use nym_network_defaults::NymNetworkDetails;
|
||||
use nym_network_requester::NRServiceProviderBuilder;
|
||||
use nym_node_metrics::events::MetricEventsSender;
|
||||
use nym_node_metrics::NymNodeMetrics;
|
||||
use nym_task::{ShutdownToken, TaskClient};
|
||||
@@ -32,10 +34,9 @@ use tracing::*;
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
pub(crate) mod client_handling;
|
||||
pub(crate) mod internal_service_providers;
|
||||
pub mod internal_service_providers;
|
||||
mod stale_data_cleaner;
|
||||
|
||||
use crate::node::internal_service_providers::authenticator::Authenticator;
|
||||
pub use client_handling::active_clients::ActiveClientsStore;
|
||||
pub use nym_gateway_stats_storage::PersistentStatsStorage;
|
||||
pub use nym_gateway_storage::{
|
||||
@@ -47,14 +48,14 @@ pub use nym_sdk::{NymApiTopologyProvider, NymApiTopologyProviderConfig, UserAgen
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LocalNetworkRequesterOpts {
|
||||
pub config: nym_network_requester::Config,
|
||||
pub config: network_requester::Config,
|
||||
|
||||
pub custom_mixnet_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LocalIpPacketRouterOpts {
|
||||
pub config: nym_ip_packet_router::Config,
|
||||
pub config: ip_packet_router::Config,
|
||||
|
||||
pub custom_mixnet_path: Option<PathBuf>,
|
||||
}
|
||||
@@ -69,6 +70,8 @@ pub struct LocalAuthenticatorOpts {
|
||||
pub struct GatewayTasksBuilder {
|
||||
config: Config,
|
||||
|
||||
binary_build_information: BinaryBuildInformation,
|
||||
|
||||
network_requester_opts: Option<LocalNetworkRequesterOpts>,
|
||||
|
||||
ip_packet_router_opts: Option<LocalIpPacketRouterOpts>,
|
||||
@@ -121,11 +124,13 @@ impl GatewayTasksBuilder {
|
||||
metrics_sender: MetricEventsSender,
|
||||
metrics: NymNodeMetrics,
|
||||
mnemonic: Arc<Zeroizing<bip39::Mnemonic>>,
|
||||
binary_build_information: BinaryBuildInformation,
|
||||
legacy_task_client: TaskClient,
|
||||
shutdown_token: ShutdownToken,
|
||||
) -> GatewayTasksBuilder {
|
||||
GatewayTasksBuilder {
|
||||
config,
|
||||
binary_build_information,
|
||||
network_requester_opts: None,
|
||||
ip_packet_router_opts: None,
|
||||
authenticator_opts: None,
|
||||
@@ -296,13 +301,14 @@ impl GatewayTasksBuilder {
|
||||
let transceiver = message_router_builder.gateway_transceiver();
|
||||
|
||||
let (on_start_tx, on_start_rx) = oneshot::channel();
|
||||
let mut nr_builder = NRServiceProviderBuilder::new(nr_opts.config.clone())
|
||||
.with_shutdown(self.legacy_task_client.fork("network_requester_sp"))
|
||||
.with_custom_gateway_transceiver(transceiver)
|
||||
.with_wait_for_gateway(true)
|
||||
.with_minimum_gateway_performance(0)
|
||||
.with_custom_topology_provider(topology_provider)
|
||||
.with_on_start(on_start_tx);
|
||||
let mut nr_builder =
|
||||
NRServiceProviderBuilder::new(nr_opts.config.clone(), self.binary_build_information)
|
||||
.with_shutdown(self.legacy_task_client.fork("network_requester_sp"))
|
||||
.with_custom_gateway_transceiver(transceiver)
|
||||
.with_wait_for_gateway(true)
|
||||
.with_minimum_gateway_performance(0)
|
||||
.with_custom_topology_provider(topology_provider)
|
||||
.with_on_start(on_start_tx);
|
||||
|
||||
if let Some(custom_mixnet) = &nr_opts.custom_mixnet_path {
|
||||
nr_builder = nr_builder.with_stored_topology(custom_mixnet)?
|
||||
|
||||
@@ -100,10 +100,7 @@ nym-node-requests = { path = "nym-node-requests", default-features = false, feat
|
||||
] }
|
||||
nym-node-metrics = { path = "nym-node-metrics" }
|
||||
|
||||
# nodes:
|
||||
nym-gateway = { path = "../gateway" }
|
||||
nym-network-requester = { path = "../service-providers/network-requester" }
|
||||
nym-ip-packet-router = { path = "../service-providers/ip-packet-router" }
|
||||
|
||||
|
||||
# throughput tester to recreate lioness
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::cli::helpers::ConfigArgs;
|
||||
use crate::config::upgrade_helpers::try_load_current_config;
|
||||
use crate::node::helpers::load_ed25519_identity_public_key;
|
||||
use crate::node::ServiceProvidersData;
|
||||
use nym_network_requester::{CustomGatewayDetails, GatewayDetails, GatewayRegistration};
|
||||
use nym_gateway::service_providers::{CustomGatewayDetails, GatewayDetails, GatewayRegistration};
|
||||
use std::fs;
|
||||
|
||||
#[derive(Debug, clap::Args)]
|
||||
|
||||
@@ -8,6 +8,8 @@ use nym_gateway::node::{
|
||||
LocalAuthenticatorOpts, LocalIpPacketRouterOpts, LocalNetworkRequesterOpts,
|
||||
};
|
||||
use nym_gateway::nym_authenticator;
|
||||
use nym_gateway::nym_network_requester;
|
||||
use nym_gateway::service_providers::ip_packet_router;
|
||||
|
||||
// a temporary solution until further refactoring is made
|
||||
fn ephemeral_gateway_config(config: &Config) -> nym_gateway::config::Config {
|
||||
@@ -117,7 +119,6 @@ pub fn gateway_tasks_config(config: &Config) -> GatewayTasksConfig {
|
||||
.to_common_client_paths(),
|
||||
},
|
||||
network_requester_debug: Default::default(),
|
||||
logging: config.logging,
|
||||
},
|
||||
custom_mixnet_path: None,
|
||||
};
|
||||
@@ -136,12 +137,12 @@ pub fn gateway_tasks_config(config: &Config) -> GatewayTasksConfig {
|
||||
.unwrap();
|
||||
|
||||
let mut ipr_opts = LocalIpPacketRouterOpts {
|
||||
config: nym_ip_packet_router::Config {
|
||||
config: ip_packet_router::Config {
|
||||
base: nym_client_core_config_types::Config {
|
||||
client: base_client_config(config),
|
||||
debug: config.service_providers.ip_packet_router.debug.client_debug,
|
||||
},
|
||||
ip_packet_router: nym_ip_packet_router::config::IpPacketRouter {
|
||||
ip_packet_router: ip_packet_router::config::IpPacketRouter {
|
||||
disable_poisson_rate: config
|
||||
.service_providers
|
||||
.ip_packet_router
|
||||
@@ -151,7 +152,7 @@ pub fn gateway_tasks_config(config: &Config) -> GatewayTasksConfig {
|
||||
config.service_providers.upstream_exit_policy_url.clone(),
|
||||
),
|
||||
},
|
||||
storage_paths: nym_ip_packet_router::config::IpPacketRouterPaths {
|
||||
storage_paths: ip_packet_router::config::IpPacketRouterPaths {
|
||||
common_paths: config
|
||||
.service_providers
|
||||
.storage_paths
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::{config::*, error::KeyIOFailure};
|
||||
use nym_client_core_config_types::DebugConfig as ClientDebugConfig;
|
||||
use nym_config::serde_helpers::de_maybe_port;
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use nym_network_requester::{
|
||||
use nym_gateway::service_providers::{
|
||||
set_active_gateway, setup_fs_gateways_storage, store_gateway_details, CustomGatewayDetails,
|
||||
GatewayDetails,
|
||||
};
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
use crate::node::http::error::NymNodeHttpError;
|
||||
use crate::wireguard::error::WireguardError;
|
||||
use nym_gateway::service_providers::ClientCoreError;
|
||||
use nym_http_api_client::HttpClientError;
|
||||
use nym_ip_packet_router::error::ClientCoreError;
|
||||
use nym_validator_client::nyxd::error::NyxdError;
|
||||
use nym_validator_client::ValidatorClientError;
|
||||
use std::io;
|
||||
|
||||
@@ -41,12 +41,12 @@ use crate::node::shared_network::{
|
||||
use nym_bin_common::bin_info;
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use nym_gateway::node::{ActiveClientsStore, GatewayTasksBuilder};
|
||||
use nym_mixnet_client::client::ActiveConnections;
|
||||
use nym_mixnet_client::forwarder::MixForwardingSender;
|
||||
use nym_network_requester::{
|
||||
use nym_gateway::service_providers::{
|
||||
set_active_gateway, setup_fs_gateways_storage, store_gateway_details, CustomGatewayDetails,
|
||||
GatewayDetails, GatewayRegistration,
|
||||
};
|
||||
use nym_mixnet_client::client::ActiveConnections;
|
||||
use nym_mixnet_client::forwarder::MixForwardingSender;
|
||||
use nym_node_metrics::events::MetricEventsSender;
|
||||
use nym_node_metrics::NymNodeMetrics;
|
||||
use nym_node_requests::api::v1::node::models::{AnnouncePorts, NodeDescription};
|
||||
@@ -624,6 +624,7 @@ impl NymNode {
|
||||
metrics_sender,
|
||||
self.metrics.clone(),
|
||||
self.entry_gateway.mnemonic.clone(),
|
||||
bin_info!(),
|
||||
legacy_task_client,
|
||||
shutdown_token,
|
||||
);
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
[package]
|
||||
name = "nym-ip-packet-router"
|
||||
version = "0.1.0"
|
||||
authors.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
documentation.workspace = true
|
||||
edition.workspace = true
|
||||
license = "GPL-3.0"
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
bincode = { workspace = true }
|
||||
bs58 = { workspace = true }
|
||||
bytes = { workspace = true }
|
||||
clap.workspace = true
|
||||
etherparse = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
log = { workspace = true }
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["clap", "basic_tracing"] }
|
||||
nym-client-core = { path = "../../common/client-core" }
|
||||
nym-config = { path = "../../common/config" }
|
||||
nym-crypto = { path = "../../common/crypto" }
|
||||
nym-exit-policy = { path = "../../common/exit-policy" }
|
||||
nym-id = { path = "../../common/nym-id" }
|
||||
nym-ip-packet-requests = { path = "../../common/ip-packet-requests" }
|
||||
nym-network-defaults = { path = "../../common/network-defaults" }
|
||||
nym-network-requester = { path = "../network-requester" }
|
||||
nym-sdk = { path = "../../sdk/rust/nym-sdk" }
|
||||
nym-service-provider-requests-common = { path = "../../common/service-provider-requests-common" }
|
||||
nym-service-providers-common = { path = "../common" }
|
||||
nym-sphinx = { path = "../../common/nymsphinx" }
|
||||
nym-task = { path = "../../common/task" }
|
||||
nym-tun = { path = "../../common/tun" }
|
||||
nym-types = { path = "../../common/types" }
|
||||
nym-wireguard = { path = "../../common/wireguard" }
|
||||
nym-wireguard-types = { path = "../../common/wireguard-types" }
|
||||
rand = { workspace = true }
|
||||
reqwest.workspace = true
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
time = { workspace = true }
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "net", "io-util", "macros"] }
|
||||
tokio-util = { workspace = true, features = ["codec"] }
|
||||
url.workspace = true
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
tokio-tun.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
async-trait.workspace = true
|
||||
@@ -1,30 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::cli::CliIpPacketRouterClient;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_add_gateway::{add_gateway, CommonClientAddGatewayArgs};
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientAddGatewayArgs,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientAddGatewayArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientAddGatewayArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), IpPacketRouterError> {
|
||||
let output = args.output;
|
||||
let res = add_gateway::<CliIpPacketRouterClient, _>(args, None).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
use clap::Args;
|
||||
use nym_bin_common::bin_info_owned;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
|
||||
#[derive(Args)]
|
||||
pub(crate) struct BuildInfo {
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
pub(crate) fn execute(args: BuildInfo) {
|
||||
println!("{}", args.output.format(&bin_info_owned!()))
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::cli::CliIpPacketRouterClient;
|
||||
use nym_client_core::cli_helpers::client_import_coin_index_signatures::{
|
||||
import_coin_index_signatures, CommonClientImportCoinIndexSignaturesArgs,
|
||||
};
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
|
||||
pub(crate) async fn execute(
|
||||
args: CommonClientImportCoinIndexSignaturesArgs,
|
||||
) -> Result<(), IpPacketRouterError> {
|
||||
import_coin_index_signatures::<CliIpPacketRouterClient, _>(args).await?;
|
||||
println!("successfully imported coin index signatures!");
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::cli::CliIpPacketRouterClient;
|
||||
use nym_client_core::cli_helpers::client_import_credential::{
|
||||
import_credential, CommonClientImportTicketBookArgs,
|
||||
};
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
|
||||
pub async fn execute(args: CommonClientImportTicketBookArgs) -> Result<(), IpPacketRouterError> {
|
||||
import_credential::<CliIpPacketRouterClient, _>(args).await?;
|
||||
println!("successfully imported credential!");
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::cli::CliIpPacketRouterClient;
|
||||
use nym_client_core::cli_helpers::client_import_expiration_date_signatures::{
|
||||
import_expiration_date_signatures, CommonClientImportExpirationDateSignaturesArgs,
|
||||
};
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
|
||||
pub(crate) async fn execute(
|
||||
args: CommonClientImportExpirationDateSignaturesArgs,
|
||||
) -> Result<(), IpPacketRouterError> {
|
||||
import_expiration_date_signatures::<CliIpPacketRouterClient, _>(args).await?;
|
||||
println!("successfully imported expiration date signatures!");
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::cli::CliIpPacketRouterClient;
|
||||
use nym_client_core::cli_helpers::client_import_master_verification_key::{
|
||||
import_master_verification_key, CommonClientImportMasterVerificationKeyArgs,
|
||||
};
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
|
||||
pub(crate) async fn execute(
|
||||
args: CommonClientImportMasterVerificationKeyArgs,
|
||||
) -> Result<(), IpPacketRouterError> {
|
||||
import_master_verification_key::<CliIpPacketRouterClient, _>(args).await?;
|
||||
println!("successfully imported master verification key!");
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use clap::{Args, Subcommand};
|
||||
use nym_client_core::cli_helpers::client_import_coin_index_signatures::CommonClientImportCoinIndexSignaturesArgs;
|
||||
use nym_client_core::cli_helpers::client_import_credential::CommonClientImportTicketBookArgs;
|
||||
use nym_client_core::cli_helpers::client_import_expiration_date_signatures::CommonClientImportExpirationDateSignaturesArgs;
|
||||
use nym_client_core::cli_helpers::client_import_master_verification_key::CommonClientImportMasterVerificationKeyArgs;
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
|
||||
pub(crate) mod import_coin_index_signatures;
|
||||
pub(crate) mod import_credential;
|
||||
pub(crate) mod import_expiration_date_signatures;
|
||||
pub(crate) mod import_master_verification_key;
|
||||
pub(crate) mod show_ticketbooks;
|
||||
|
||||
#[derive(Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
pub struct Ecash {
|
||||
#[clap(subcommand)]
|
||||
pub command: EcashCommands,
|
||||
}
|
||||
|
||||
impl Ecash {
|
||||
pub async fn execute(self) -> Result<(), IpPacketRouterError> {
|
||||
match self.command {
|
||||
EcashCommands::ShowTicketBooks(args) => show_ticketbooks::execute(args).await?,
|
||||
EcashCommands::ImportTicketBook(args) => import_credential::execute(args).await?,
|
||||
EcashCommands::ImportCoinIndexSignatures(args) => {
|
||||
import_coin_index_signatures::execute(args).await?
|
||||
}
|
||||
EcashCommands::ImportExpirationDateSignatures(args) => {
|
||||
import_expiration_date_signatures::execute(args).await?
|
||||
}
|
||||
EcashCommands::ImportMasterVerificationKey(args) => {
|
||||
import_master_verification_key::execute(args).await?
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
pub enum EcashCommands {
|
||||
/// Display information associated with the imported ticketbooks,
|
||||
ShowTicketBooks(show_ticketbooks::Args),
|
||||
|
||||
/// Import a pre-generated ticketbook
|
||||
ImportTicketBook(CommonClientImportTicketBookArgs),
|
||||
|
||||
/// Import coin index signatures needed for ticketbooks
|
||||
ImportCoinIndexSignatures(CommonClientImportCoinIndexSignaturesArgs),
|
||||
|
||||
/// Import expiration date signatures needed for ticketbooks
|
||||
ImportExpirationDateSignatures(CommonClientImportExpirationDateSignaturesArgs),
|
||||
|
||||
/// Import master verification key needed for ticketbooks
|
||||
ImportMasterVerificationKey(CommonClientImportMasterVerificationKeyArgs),
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::cli::CliIpPacketRouterClient;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_show_ticketbooks::{
|
||||
show_ticketbooks, CommonShowTicketbooksArgs,
|
||||
};
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonShowTicketbooksArgs,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonShowTicketbooksArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonShowTicketbooksArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn execute(args: Args) -> Result<(), IpPacketRouterError> {
|
||||
let output = args.output;
|
||||
let res = show_ticketbooks::<CliIpPacketRouterClient, _>(args).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
use crate::cli::{override_config, CliIpPacketRouterClient, OverrideConfig};
|
||||
use clap::Args;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_init::{
|
||||
initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient,
|
||||
};
|
||||
use nym_ip_packet_router::{
|
||||
config::{default_config_directory, default_config_filepath, default_data_directory, Config},
|
||||
error::IpPacketRouterError,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use std::{fmt::Display, fs, path::PathBuf};
|
||||
|
||||
impl InitialisableClient for CliIpPacketRouterClient {
|
||||
type InitArgs = Init;
|
||||
|
||||
fn initialise_storage_paths(id: &str) -> Result<(), Self::Error> {
|
||||
fs::create_dir_all(default_data_directory(id))?;
|
||||
fs::create_dir_all(default_config_directory(id))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn default_config_path(id: &str) -> PathBuf {
|
||||
default_config_filepath(id)
|
||||
}
|
||||
|
||||
fn construct_config(init_args: &Self::InitArgs) -> Self::Config {
|
||||
override_config(
|
||||
Config::new(&init_args.common_args.id),
|
||||
OverrideConfig::from(init_args.clone()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Args, Clone, Debug)]
|
||||
pub(crate) struct Init {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientInitArgs,
|
||||
|
||||
#[clap(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl From<Init> for OverrideConfig {
|
||||
fn from(init_config: Init) -> Self {
|
||||
OverrideConfig {
|
||||
nym_apis: init_config.common_args.nym_apis,
|
||||
nyxd_urls: init_config.common_args.nyxd_urls,
|
||||
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientInitArgs> for Init {
|
||||
fn as_ref(&self) -> &CommonClientInitArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct InitResults {
|
||||
#[serde(flatten)]
|
||||
client_core: nym_client_core::init::types::InitResults,
|
||||
client_address: String,
|
||||
}
|
||||
|
||||
impl InitResults {
|
||||
fn new(res: InitResultsWithConfig<Config>) -> Self {
|
||||
Self {
|
||||
client_address: res.init_results.address.to_string(),
|
||||
client_core: res.init_results,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for InitResults {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "{}", self.client_core)?;
|
||||
write!(
|
||||
f,
|
||||
"Address of this ip-packet-router: {}",
|
||||
self.client_address
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Init) -> Result<(), IpPacketRouterError> {
|
||||
eprintln!("Initialising client...");
|
||||
|
||||
let output = args.output;
|
||||
let res = initialise_client::<CliIpPacketRouterClient>(args, None).await?;
|
||||
|
||||
let init_results = InitResults::new(res);
|
||||
println!("{}", output.format(&init_results));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::cli::CliIpPacketRouterClient;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_list_gateways::{
|
||||
list_gateways, CommonClientListGatewaysArgs,
|
||||
};
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientListGatewaysArgs,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientListGatewaysArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientListGatewaysArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), IpPacketRouterError> {
|
||||
let output = args.output;
|
||||
let res = list_gateways::<CliIpPacketRouterClient, _>(args).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
use crate::cli::ecash::Ecash;
|
||||
use clap::{CommandFactory, Parser, Subcommand};
|
||||
use log::error;
|
||||
use nym_bin_common::bin_info;
|
||||
use nym_bin_common::completions::{fig_generate, ArgShell};
|
||||
use nym_client_core::cli_helpers::CliClient;
|
||||
use nym_ip_packet_router::config::helpers::{try_upgrade_config, try_upgrade_config_by_id};
|
||||
use nym_ip_packet_router::config::{BaseClientConfig, Config};
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
mod add_gateway;
|
||||
mod build_info;
|
||||
pub mod ecash;
|
||||
mod init;
|
||||
mod list_gateways;
|
||||
mod run;
|
||||
mod sign;
|
||||
mod switch_gateway;
|
||||
|
||||
pub(crate) struct CliIpPacketRouterClient;
|
||||
|
||||
impl CliClient for CliIpPacketRouterClient {
|
||||
const NAME: &'static str = "ip packet router";
|
||||
type Error = IpPacketRouterError;
|
||||
type Config = Config;
|
||||
|
||||
async fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> {
|
||||
try_upgrade_config(id).await
|
||||
}
|
||||
|
||||
async fn try_load_current_config(id: &str) -> Result<Self::Config, Self::Error> {
|
||||
try_load_current_config(id).await
|
||||
}
|
||||
}
|
||||
|
||||
fn pretty_build_info_static() -> &'static str {
|
||||
static PRETTY_BUILD_INFORMATION: OnceLock<String> = OnceLock::new();
|
||||
PRETTY_BUILD_INFORMATION.get_or_init(|| bin_info!().pretty_print())
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author = "Nymtech", version, about, long_version = pretty_build_info_static())]
|
||||
pub(crate) struct Cli {
|
||||
/// Path pointing to an env file that configures the client.
|
||||
#[arg(short, long)]
|
||||
pub(crate) config_env_file: Option<std::path::PathBuf>,
|
||||
|
||||
/// Flag used for disabling the printed banner in tty.
|
||||
#[arg(long)]
|
||||
pub(crate) no_banner: bool,
|
||||
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Subcommand)]
|
||||
pub(crate) enum Commands {
|
||||
/// Initialize a network-requester. Do this first!
|
||||
Init(init::Init),
|
||||
|
||||
/// Run the network requester with the provided configuration and optionally override
|
||||
/// parameters.
|
||||
Run(run::Run),
|
||||
|
||||
/// Ecash-related functionalities
|
||||
Ecash(Ecash),
|
||||
|
||||
/// List all registered with gateways
|
||||
ListGateways(list_gateways::Args),
|
||||
|
||||
/// Add new gateway to this client
|
||||
AddGateway(add_gateway::Args),
|
||||
|
||||
/// Change the currently active gateway. Note that you must have already registered with the new gateway!
|
||||
SwitchGateway(switch_gateway::Args),
|
||||
|
||||
/// Sign to prove ownership of this network requester
|
||||
Sign(sign::Sign),
|
||||
|
||||
/// Show build information of this binary
|
||||
BuildInfo(build_info::BuildInfo),
|
||||
|
||||
/// Generate shell completions
|
||||
Completions(ArgShell),
|
||||
|
||||
/// Generate Fig specification
|
||||
GenerateFigSpec,
|
||||
}
|
||||
|
||||
// Configuration that can be overridden.
|
||||
pub(crate) struct OverrideConfig {
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
nyxd_urls: Option<Vec<url::Url>>,
|
||||
enabled_credentials_mode: Option<bool>,
|
||||
}
|
||||
|
||||
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
|
||||
// disable poisson rate in the BASE client if the IPR option is enabled
|
||||
if config.ip_packet_router.disable_poisson_rate {
|
||||
log::info!("Disabling poisson rate for ip packet router");
|
||||
config.set_no_poisson_process();
|
||||
}
|
||||
|
||||
config
|
||||
.with_optional_base_custom_env(
|
||||
BaseClientConfig::with_custom_nym_apis,
|
||||
args.nym_apis,
|
||||
nym_network_defaults::var_names::NYM_API,
|
||||
nym_config::parse_urls,
|
||||
)
|
||||
.with_optional_base_custom_env(
|
||||
BaseClientConfig::with_custom_nyxd,
|
||||
args.nyxd_urls,
|
||||
nym_network_defaults::var_names::NYXD,
|
||||
nym_config::parse_urls,
|
||||
)
|
||||
.with_optional_base(
|
||||
BaseClientConfig::with_disabled_credentials,
|
||||
args.enabled_credentials_mode.map(|b| !b),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Cli) -> Result<(), IpPacketRouterError> {
|
||||
let bin_name = "nym-ip-packet-router";
|
||||
|
||||
match args.command {
|
||||
Commands::Init(m) => init::execute(m).await?,
|
||||
Commands::Run(m) => run::execute(&m).await?,
|
||||
Commands::Ecash(ecash) => ecash.execute().await?,
|
||||
Commands::ListGateways(args) => list_gateways::execute(args).await?,
|
||||
Commands::AddGateway(args) => add_gateway::execute(args).await?,
|
||||
Commands::SwitchGateway(args) => switch_gateway::execute(args).await?,
|
||||
Commands::Sign(m) => sign::execute(&m).await?,
|
||||
Commands::BuildInfo(m) => build_info::execute(m),
|
||||
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
|
||||
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn try_load_current_config(id: &str) -> Result<Config, IpPacketRouterError> {
|
||||
// try to load the config as is
|
||||
if let Ok(cfg) = Config::read_from_default_path(id) {
|
||||
return if !cfg.validate() {
|
||||
Err(IpPacketRouterError::ConfigValidationFailure)
|
||||
} else {
|
||||
Ok(cfg)
|
||||
};
|
||||
}
|
||||
|
||||
// we couldn't load it - try upgrading it from older revisions
|
||||
try_upgrade_config_by_id(id).await?;
|
||||
|
||||
let config = match Config::read_from_default_path(id) {
|
||||
Ok(cfg) => cfg,
|
||||
Err(err) => {
|
||||
error!("Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})");
|
||||
return Err(IpPacketRouterError::FailedToLoadConfig(id.to_string()));
|
||||
}
|
||||
};
|
||||
|
||||
if !config.validate() {
|
||||
return Err(IpPacketRouterError::ConfigValidationFailure);
|
||||
}
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
use crate::cli::try_load_current_config;
|
||||
use crate::cli::{override_config, OverrideConfig};
|
||||
use clap::Args;
|
||||
use nym_client_core::cli_helpers::client_run::CommonClientRunArgs;
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
#[derive(Args, Clone)]
|
||||
pub(crate) struct Run {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientRunArgs,
|
||||
}
|
||||
|
||||
impl From<Run> for OverrideConfig {
|
||||
fn from(run_config: Run) -> Self {
|
||||
OverrideConfig {
|
||||
nym_apis: None,
|
||||
nyxd_urls: run_config.common_args.nyxd_urls,
|
||||
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: &Run) -> Result<(), IpPacketRouterError> {
|
||||
let mut config = try_load_current_config(&args.common_args.id).await?;
|
||||
config = override_config(config, OverrideConfig::from(args.clone()));
|
||||
log::debug!("Using config: {config:#?}");
|
||||
|
||||
log::info!("Starting ip packet router service provider");
|
||||
let mut server = nym_ip_packet_router::IpPacketRouter::new(config);
|
||||
if let Some(custom_mixnet) = &args.common_args.custom_mixnet {
|
||||
server = server.with_stored_topology(custom_mixnet)?
|
||||
}
|
||||
|
||||
server.run_service_provider().await
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
use crate::cli::try_load_current_config;
|
||||
use clap::Args;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
|
||||
use nym_client_core::error::ClientCoreError;
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
use nym_types::helpers::ConsoleSigningOutput;
|
||||
|
||||
#[derive(Args, Clone)]
|
||||
pub(crate) struct Sign {
|
||||
/// The id of the mixnode you want to sign with
|
||||
#[arg(long)]
|
||||
id: String,
|
||||
|
||||
/// Signs a transaction-specific payload, that is going to be sent to the smart contract, with your identity key
|
||||
#[arg(long)]
|
||||
contract_msg: String,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
fn print_signed_contract_msg(
|
||||
private_key: &ed25519::PrivateKey,
|
||||
raw_msg: &str,
|
||||
output: OutputFormat,
|
||||
) {
|
||||
let trimmed = raw_msg.trim();
|
||||
eprintln!(">>> attempting to sign {trimmed}");
|
||||
|
||||
let Ok(decoded) = bs58::decode(trimmed).into_vec() else {
|
||||
println!("it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters");
|
||||
return;
|
||||
};
|
||||
|
||||
eprintln!(">>> decoding the message...");
|
||||
|
||||
// we don't really care about what particular information is embedded inside of it,
|
||||
// we just want to know if user correctly copied the string, i.e. whether it's a valid bs58 encoded json
|
||||
if serde_json::from_slice::<serde_json::Value>(&decoded).is_err() {
|
||||
println!("it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters");
|
||||
return;
|
||||
};
|
||||
|
||||
// if this is a valid json, it MUST be a valid string
|
||||
let decoded_string = String::from_utf8(decoded.clone()).unwrap();
|
||||
let signature = private_key.sign(&decoded).to_base58_string();
|
||||
|
||||
let sign_output = ConsoleSigningOutput::new(decoded_string, signature);
|
||||
println!("{}", output.format(&sign_output));
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: &Sign) -> Result<(), IpPacketRouterError> {
|
||||
let config = try_load_current_config(&args.id).await?;
|
||||
|
||||
let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys);
|
||||
let identity_keypair = key_store.load_identity_keypair().map_err(|source| {
|
||||
IpPacketRouterError::ClientCoreError(ClientCoreError::KeyStoreError {
|
||||
source: Box::new(source),
|
||||
})
|
||||
})?;
|
||||
|
||||
print_signed_contract_msg(
|
||||
identity_keypair.private_key(),
|
||||
&args.contract_msg,
|
||||
args.output,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::cli::CliIpPacketRouterClient;
|
||||
use nym_client_core::cli_helpers::client_switch_gateway::{
|
||||
switch_gateway, CommonClientSwitchGatewaysArgs,
|
||||
};
|
||||
use nym_ip_packet_router::error::IpPacketRouterError;
|
||||
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientSwitchGatewaysArgs,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientSwitchGatewaysArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientSwitchGatewaysArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), IpPacketRouterError> {
|
||||
switch_gateway::<CliIpPacketRouterClient, _>(args).await
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::config::default_config_filepath;
|
||||
use crate::config::old_config_v1::ConfigV1;
|
||||
use crate::config::old_config_v2::ConfigV2;
|
||||
use crate::error::IpPacketRouterError;
|
||||
use log::{info, trace};
|
||||
use nym_client_core::cli_helpers::CliClientConfig;
|
||||
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
||||
use std::path::Path;
|
||||
|
||||
async fn try_upgrade_v1_config<P: AsRef<Path>>(
|
||||
config_path: P,
|
||||
) -> Result<bool, IpPacketRouterError> {
|
||||
// explicitly load it as v1 (which is incompatible with the current one)
|
||||
let Ok(old_config) = ConfigV1::read_from_toml_file(config_path.as_ref()) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||
return Ok(false);
|
||||
};
|
||||
info!("It seems the client is using v1 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let old_paths = old_config.storage_paths.clone();
|
||||
let updated_step1: ConfigV2 = old_config.try_into()?;
|
||||
|
||||
v1_1_33::migrate_gateway_details(
|
||||
&old_paths.common_paths,
|
||||
&updated_step1.storage_paths.common_paths,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let updated = updated_step1.try_upgrade()?;
|
||||
|
||||
updated.save_to(config_path)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
async fn try_upgrade_v2_config<P: AsRef<Path>>(
|
||||
config_path: P,
|
||||
) -> Result<bool, IpPacketRouterError> {
|
||||
// explicitly load it as v2 (which is incompatible with the current one)
|
||||
let Ok(old_config) = ConfigV2::read_from_toml_file(config_path.as_ref()) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||
return Ok(false);
|
||||
};
|
||||
info!("It seems the client is using v2 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated = old_config.try_upgrade()?;
|
||||
|
||||
updated.save_to(config_path)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub async fn try_upgrade_config<P: AsRef<Path>>(config_path: P) -> Result<(), IpPacketRouterError> {
|
||||
trace!("Attempting to upgrade config");
|
||||
if try_upgrade_v1_config(config_path.as_ref()).await? {
|
||||
return Ok(());
|
||||
}
|
||||
if try_upgrade_v2_config(config_path).await? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn try_upgrade_config_by_id(id: &str) -> Result<(), IpPacketRouterError> {
|
||||
try_upgrade_config(default_config_filepath(id)).await
|
||||
}
|
||||
@@ -1,211 +0,0 @@
|
||||
pub use nym_client_core::config::Config as BaseClientConfig;
|
||||
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::{cli_helpers::CliClientConfig, config::disk_persistence::CommonClientPaths};
|
||||
use nym_config::{
|
||||
defaults::mainnet, must_get_home, save_formatted_config_to_file,
|
||||
serde_helpers::de_maybe_stringified, NymConfigTemplate, OptionalSet, DEFAULT_CONFIG_DIR,
|
||||
DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR,
|
||||
};
|
||||
use nym_service_providers_common::DEFAULT_SERVICE_PROVIDERS_DIR;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
io,
|
||||
path::{Path, PathBuf},
|
||||
str::FromStr,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
pub use crate::config::persistence::IpPacketRouterPaths;
|
||||
|
||||
use self::template::CONFIG_TEMPLATE;
|
||||
|
||||
pub mod helpers;
|
||||
pub mod old_config_v1;
|
||||
pub mod old_config_v2;
|
||||
mod persistence;
|
||||
mod template;
|
||||
|
||||
const DEFAULT_IP_PACKET_ROUTER_DIR: &str = "ip-packet-router";
|
||||
|
||||
/// Derive default path to ip packet routers' config directory.
|
||||
/// It should get resolved to `$HOME/.nym/service-providers/ip-packet-router/<id>/config`
|
||||
pub fn default_config_directory<P: AsRef<Path>>(id: P) -> PathBuf {
|
||||
must_get_home()
|
||||
.join(NYM_DIR)
|
||||
.join(DEFAULT_SERVICE_PROVIDERS_DIR)
|
||||
.join(DEFAULT_IP_PACKET_ROUTER_DIR)
|
||||
.join(id)
|
||||
.join(DEFAULT_CONFIG_DIR)
|
||||
}
|
||||
|
||||
/// Derive default path to ip packet routers' config file.
|
||||
/// It should get resolved to `$HOME/.nym/service-providers/ip-packet-router/<id>/config/config.toml`
|
||||
pub fn default_config_filepath<P: AsRef<Path>>(id: P) -> PathBuf {
|
||||
default_config_directory(id).join(DEFAULT_CONFIG_FILENAME)
|
||||
}
|
||||
|
||||
/// Derive default path to network requester's data directory where files, such as keys, are stored.
|
||||
/// It should get resolved to `$HOME/.nym/service-providers/network-requester/<id>/data`
|
||||
pub fn default_data_directory<P: AsRef<Path>>(id: P) -> PathBuf {
|
||||
must_get_home()
|
||||
.join(NYM_DIR)
|
||||
.join(DEFAULT_SERVICE_PROVIDERS_DIR)
|
||||
.join(DEFAULT_IP_PACKET_ROUTER_DIR)
|
||||
.join(id)
|
||||
.join(DEFAULT_DATA_DIR)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Config {
|
||||
#[serde(flatten)]
|
||||
pub base: BaseClientConfig,
|
||||
|
||||
#[serde(default)]
|
||||
pub ip_packet_router: IpPacketRouter,
|
||||
|
||||
pub storage_paths: IpPacketRouterPaths,
|
||||
|
||||
pub logging: LoggingSettings,
|
||||
}
|
||||
|
||||
impl NymConfigTemplate for Config {
|
||||
fn template(&self) -> &'static str {
|
||||
CONFIG_TEMPLATE
|
||||
}
|
||||
}
|
||||
|
||||
impl CliClientConfig for Config {
|
||||
fn common_paths(&self) -> &CommonClientPaths {
|
||||
&self.storage_paths.common_paths
|
||||
}
|
||||
|
||||
fn core_config(&self) -> &BaseClientConfig {
|
||||
&self.base
|
||||
}
|
||||
|
||||
fn default_store_location(&self) -> PathBuf {
|
||||
self.default_location()
|
||||
}
|
||||
|
||||
fn save_to<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
|
||||
save_formatted_config_to_file(self, path)
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new<S: AsRef<str>>(id: S) -> Self {
|
||||
Config {
|
||||
base: BaseClientConfig::new(id.as_ref(), env!("CARGO_PKG_VERSION")),
|
||||
ip_packet_router: Default::default(),
|
||||
storage_paths: IpPacketRouterPaths::new_base(default_data_directory(id.as_ref())),
|
||||
logging: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_data_directory<P: AsRef<Path>>(mut self, data_directory: P) -> Self {
|
||||
self.storage_paths = IpPacketRouterPaths::new_base(data_directory);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||
nym_config::read_config_from_toml_file(path)
|
||||
}
|
||||
|
||||
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
||||
Self::read_from_toml_file(default_config_filepath(id))
|
||||
}
|
||||
|
||||
pub fn default_location(&self) -> PathBuf {
|
||||
default_config_filepath(&self.base.client.id)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn save_to_default_location(&self) -> io::Result<()> {
|
||||
let config_save_location: PathBuf = self.default_location();
|
||||
save_formatted_config_to_file(self, config_save_location)
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> bool {
|
||||
// no other sections have explicit requirements (yet)
|
||||
self.base.validate()
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn set_no_poisson_process(&mut self) {
|
||||
self.base.set_no_poisson_process()
|
||||
}
|
||||
|
||||
// poor man's 'builder' method
|
||||
#[allow(unused)]
|
||||
pub fn with_base<F, T>(mut self, f: F, val: T) -> Self
|
||||
where
|
||||
F: Fn(BaseClientConfig, T) -> BaseClientConfig,
|
||||
{
|
||||
self.base = f(self.base, val);
|
||||
self
|
||||
}
|
||||
|
||||
// helper methods to use `OptionalSet` trait. Those are defined due to very... ehm. 'specific' structure of this config
|
||||
// (plz, lets refactor it)
|
||||
pub fn with_optional_base<F, T>(mut self, f: F, val: Option<T>) -> Self
|
||||
where
|
||||
F: Fn(BaseClientConfig, T) -> BaseClientConfig,
|
||||
{
|
||||
self.base = self.base.with_optional(f, val);
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_optional_base_env<F, T>(mut self, f: F, val: Option<T>, env_var: &str) -> Self
|
||||
where
|
||||
F: Fn(BaseClientConfig, T) -> BaseClientConfig,
|
||||
T: FromStr,
|
||||
<T as FromStr>::Err: std::fmt::Debug,
|
||||
{
|
||||
self.base = self.base.with_optional_env(f, val, env_var);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_optional_base_custom_env<F, T, G>(
|
||||
mut self,
|
||||
f: F,
|
||||
val: Option<T>,
|
||||
env_var: &str,
|
||||
parser: G,
|
||||
) -> Self
|
||||
where
|
||||
F: Fn(BaseClientConfig, T) -> BaseClientConfig,
|
||||
G: Fn(&str) -> T,
|
||||
{
|
||||
self.base = self.base.with_optional_custom_env(f, val, env_var, parser);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct IpPacketRouter {
|
||||
/// Disable Poisson sending rate.
|
||||
pub disable_poisson_rate: bool,
|
||||
|
||||
/// Specifies the url for an upstream source of the exit policy used by this node.
|
||||
#[serde(deserialize_with = "de_maybe_stringified")]
|
||||
pub upstream_exit_policy_url: Option<Url>,
|
||||
}
|
||||
|
||||
impl Default for IpPacketRouter {
|
||||
fn default() -> Self {
|
||||
IpPacketRouter {
|
||||
disable_poisson_rate: true,
|
||||
#[allow(clippy::expect_used)]
|
||||
upstream_exit_policy_url: Some(
|
||||
mainnet::EXIT_POLICY_URL
|
||||
.parse()
|
||||
.expect("invalid default exit policy URL"),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::config::persistence::IpPacketRouterPaths;
|
||||
use crate::config::{default_config_filepath, IpPacketRouter};
|
||||
use crate::error::IpPacketRouterError;
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::config::disk_persistence::old_v1_1_33::CommonClientPathsV1_1_33;
|
||||
use nym_client_core::config::old_config_v1_1_33::ConfigV1_1_33 as BaseConfigV1_1_33;
|
||||
use nym_config::read_config_from_toml_file;
|
||||
use nym_config::serde_helpers::de_maybe_stringified;
|
||||
use nym_network_defaults::mainnet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use url::Url;
|
||||
|
||||
use super::old_config_v2::ConfigV2;
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Eq, Serialize, Clone)]
|
||||
pub struct IpPacketRouterPathsV1 {
|
||||
#[serde(flatten)]
|
||||
pub common_paths: CommonClientPathsV1_1_33,
|
||||
|
||||
/// Location of the file containing our description
|
||||
pub ip_packet_router_description: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfigV1 {
|
||||
#[serde(flatten)]
|
||||
pub base: BaseConfigV1_1_33,
|
||||
|
||||
#[serde(default)]
|
||||
pub ip_packet_router: IpPacketRouterV1,
|
||||
|
||||
pub storage_paths: IpPacketRouterPathsV1,
|
||||
|
||||
pub logging: LoggingSettings,
|
||||
}
|
||||
|
||||
impl TryFrom<ConfigV1> for ConfigV2 {
|
||||
type Error = IpPacketRouterError;
|
||||
|
||||
fn try_from(value: ConfigV1) -> Result<Self, Self::Error> {
|
||||
Ok(ConfigV2 {
|
||||
base: value.base.into(),
|
||||
ip_packet_router: value.ip_packet_router.into(),
|
||||
storage_paths: IpPacketRouterPaths {
|
||||
common_paths: value.storage_paths.common_paths.upgrade_default()?,
|
||||
ip_packet_router_description: value.storage_paths.ip_packet_router_description,
|
||||
},
|
||||
logging: value.logging,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigV1 {
|
||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||
read_config_from_toml_file(path)
|
||||
}
|
||||
|
||||
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
||||
Self::read_from_toml_file(default_config_filepath(id))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct IpPacketRouterV1 {
|
||||
/// Disable Poisson sending rate.
|
||||
pub disable_poisson_rate: bool,
|
||||
|
||||
/// Specifies the url for an upstream source of the exit policy used by this node.
|
||||
#[serde(deserialize_with = "de_maybe_stringified")]
|
||||
pub upstream_exit_policy_url: Option<Url>,
|
||||
}
|
||||
|
||||
impl Default for IpPacketRouterV1 {
|
||||
fn default() -> Self {
|
||||
IpPacketRouterV1 {
|
||||
disable_poisson_rate: true,
|
||||
#[allow(clippy::expect_used)]
|
||||
upstream_exit_policy_url: Some(
|
||||
mainnet::EXIT_POLICY_URL
|
||||
.parse()
|
||||
.expect("invalid default exit policy URL"),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IpPacketRouterV1> for IpPacketRouter {
|
||||
fn from(value: IpPacketRouterV1) -> Self {
|
||||
IpPacketRouter {
|
||||
disable_poisson_rate: value.disable_poisson_rate,
|
||||
upstream_exit_policy_url: value.upstream_exit_policy_url,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
use std::{io, path::Path};
|
||||
|
||||
use crate::{config::Config, error::IpPacketRouterError};
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::config::old_config_v1_1_54::ConfigV1_1_54 as BaseConfigV1_1_54;
|
||||
use nym_config::read_config_from_toml_file;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{default_config_filepath, IpPacketRouter, IpPacketRouterPaths};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfigV2 {
|
||||
#[serde(flatten)]
|
||||
pub base: BaseConfigV1_1_54,
|
||||
|
||||
#[serde(default)]
|
||||
pub ip_packet_router: IpPacketRouter,
|
||||
|
||||
pub storage_paths: IpPacketRouterPaths,
|
||||
|
||||
pub logging: LoggingSettings,
|
||||
}
|
||||
|
||||
impl ConfigV2 {
|
||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||
read_config_from_toml_file(path)
|
||||
}
|
||||
|
||||
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
||||
Self::read_from_toml_file(default_config_filepath(id))
|
||||
}
|
||||
|
||||
pub fn try_upgrade(self) -> Result<Config, IpPacketRouterError> {
|
||||
Ok(Config {
|
||||
base: self.base.into(),
|
||||
ip_packet_router: self.ip_packet_router,
|
||||
storage_paths: self.storage_paths,
|
||||
logging: self.logging,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
pub(crate) const CONFIG_TEMPLATE: &str =
|
||||
// While using normal toml marshalling would have been way simpler with less overhead,
|
||||
// I think it's useful to have comments attached to the saved config file to explain behaviour of
|
||||
// particular fields.
|
||||
// Note: any changes to the template must be reflected in the appropriate structs.
|
||||
r#"
|
||||
# This is a TOML config file.
|
||||
# For more information, see https://github.com/toml-lang/toml
|
||||
|
||||
##### main base client config options #####
|
||||
|
||||
[client]
|
||||
# Version of the client for which this configuration was created.
|
||||
version = '{{ client.version }}'
|
||||
|
||||
# Human readable ID of this particular client.
|
||||
id = '{{ client.id }}'
|
||||
|
||||
# Indicates whether this client is running in a disabled credentials mode, thus attempting
|
||||
# to claim bandwidth without presenting bandwidth credentials.
|
||||
disabled_credentials_mode = {{ client.disabled_credentials_mode }}
|
||||
|
||||
# Addresses to nyxd validators via which the client can communicate with the chain.
|
||||
nyxd_urls = [
|
||||
{{#each client.nyxd_urls }}
|
||||
'{{this}}',
|
||||
{{/each}}
|
||||
]
|
||||
|
||||
# Addresses to APIs running on validator from which the client gets the view of the network.
|
||||
nym_api_urls = [
|
||||
{{#each client.nym_api_urls }}
|
||||
'{{this}}',
|
||||
{{/each}}
|
||||
]
|
||||
|
||||
[storage_paths]
|
||||
|
||||
# Path to file containing private identity key.
|
||||
keys.private_identity_key_file = '{{ storage_paths.keys.private_identity_key_file }}'
|
||||
|
||||
# Path to file containing public identity key.
|
||||
keys.public_identity_key_file = '{{ storage_paths.keys.public_identity_key_file }}'
|
||||
|
||||
# Path to file containing private encryption key.
|
||||
keys.private_encryption_key_file = '{{ storage_paths.keys.private_encryption_key_file }}'
|
||||
|
||||
# Path to file containing public encryption key.
|
||||
keys.public_encryption_key_file = '{{ storage_paths.keys.public_encryption_key_file }}'
|
||||
|
||||
# Path to file containing key used for encrypting and decrypting the content of an
|
||||
# acknowledgement so that nobody besides the client knows which packet it refers to.
|
||||
keys.ack_key_file = '{{ storage_paths.keys.ack_key_file }}'
|
||||
|
||||
# Path to the database containing bandwidth credentials
|
||||
credentials_database = '{{ storage_paths.credentials_database }}'
|
||||
|
||||
# Path to the persistent store for received reply surbs, unused encryption keys and used sender tags.
|
||||
reply_surb_database = '{{ storage_paths.reply_surb_database }}'
|
||||
|
||||
# Path to the file containing information about gateways used by this client,
|
||||
# i.e. details such as their public keys, owner addresses or the network information.
|
||||
gateway_registrations = '{{ storage_paths.gateway_registrations }}'
|
||||
|
||||
# Location of the file containing our allow.list
|
||||
allowed_list_location = '{{ storage_paths.allowed_list_location }}'
|
||||
|
||||
# Location of the file containing our unknown.list
|
||||
unknown_list_location = '{{ storage_paths.unknown_list_location }}'
|
||||
|
||||
# Path to file containing description of this network-requester.
|
||||
ip_packet_router_description = '{{ storage_paths.ip_packet_router_description }}'
|
||||
|
||||
|
||||
##### logging configuration options #####
|
||||
|
||||
[logging]
|
||||
|
||||
# TODO
|
||||
|
||||
|
||||
##### debug configuration options #####
|
||||
# The following options should not be modified unless you know EXACTLY what you are doing
|
||||
# as if set incorrectly, they may impact your anonymity.
|
||||
|
||||
[debug]
|
||||
|
||||
[debug.acknowledgements]
|
||||
average_ack_delay = '{{ debug.acknowledgements.average_ack_delay }}'
|
||||
|
||||
[debug.cover_traffic]
|
||||
loop_cover_traffic_average_delay = '{{ debug.cover_traffic.loop_cover_traffic_average_delay }}'
|
||||
|
||||
"#;
|
||||
@@ -1,26 +0,0 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
#![warn(clippy::expect_used)]
|
||||
#![warn(clippy::unwrap_used)]
|
||||
#![warn(clippy::panic)]
|
||||
#![cfg_attr(not(target_os = "linux"), allow(dead_code))]
|
||||
#![cfg_attr(not(target_os = "linux"), allow(unused_imports))]
|
||||
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
pub mod request_filter;
|
||||
|
||||
pub(crate) mod messages;
|
||||
pub(crate) mod non_linux_dummy;
|
||||
|
||||
mod clients;
|
||||
mod constants;
|
||||
mod ip_packet_router;
|
||||
mod mixnet_client;
|
||||
mod mixnet_listener;
|
||||
mod tun_listener;
|
||||
mod util;
|
||||
|
||||
pub use crate::config::Config;
|
||||
pub use ip_packet_router::{IpPacketRouter, OnStartData};
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
mod cli;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
use clap::Parser;
|
||||
|
||||
let args = cli::Cli::parse();
|
||||
nym_bin_common::logging::setup_tracing_logger();
|
||||
nym_network_defaults::setup_env(args.config_env_file.as_ref());
|
||||
|
||||
if !args.no_banner {
|
||||
nym_bin_common::logging::maybe_print_banner(clap::crate_name!(), clap::crate_version!());
|
||||
}
|
||||
|
||||
cli::execute(args).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
fn main() {
|
||||
println!("This binary is currently only supported on linux");
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
# Copyright 2020 - Nym Technologies SA <contact@nymtech.net>
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
[package]
|
||||
name = "nym-network-requester"
|
||||
license = "GPL-3.0"
|
||||
version = "1.1.62"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version = "1.70"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
name = "nym_network_requester"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
addr = { workspace = true }
|
||||
async-trait = { workspace = true }
|
||||
bs58 = { workspace = true }
|
||||
clap = { workspace = true, features = ["cargo", "derive"]}
|
||||
dirs = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
humantime-serde = { workspace = true }
|
||||
ipnetwork = { workspace = true }
|
||||
log = { workspace = true }
|
||||
publicsuffix = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
regex = { workspace = true }
|
||||
reqwest = { workspace = true, features = ["json"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "chrono"]}
|
||||
tap = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true, features = [ "net", "rt-multi-thread", "macros" ] }
|
||||
tokio-tungstenite = { workspace = true }
|
||||
url = { workspace = true }
|
||||
time = { workspace = true }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
# internal
|
||||
nym-async-file-watcher = { path = "../../common/async-file-watcher" }
|
||||
nym-bin-common = { path = "../../common/bin-common", features = ["output_format", "clap", "basic_tracing"] }
|
||||
nym-client-core = { path = "../../common/client-core", features = ["cli", "fs-gateways-storage", "fs-surb-storage"] }
|
||||
nym-client-websocket-requests = { path = "../../clients/native/websocket-requests" }
|
||||
nym-config = { path = "../../common/config" }
|
||||
nym-credentials = { path = "../../common/credentials" }
|
||||
nym-credential-storage = { path = "../../common/credential-storage" }
|
||||
nym-crypto = { path = "../../common/crypto" }
|
||||
nym-network-defaults = { path = "../../common/network-defaults" }
|
||||
nym-ordered-buffer = { path = "../../common/socks5/ordered-buffer" }
|
||||
nym-sdk = { path = "../../sdk/rust/nym-sdk" }
|
||||
nym-service-providers-common = { path = "../common" }
|
||||
nym-socks5-proxy-helpers = { path = "../../common/socks5/proxy-helpers" }
|
||||
nym-socks5-requests = { path = "../../common/socks5/requests" }
|
||||
nym-sphinx = { path = "../../common/nymsphinx" }
|
||||
nym-task = { path = "../../common/task" }
|
||||
nym-types = { path = "../../common/types" }
|
||||
nym-exit-policy = { path = "../../common/exit-policy", features = ["client"] }
|
||||
nym-id = { path = "../../common/nym-id" }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = { workspace = true }
|
||||
@@ -1,42 +0,0 @@
|
||||
Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
|
||||
SPDX-License-Identifier: GPL-3.0-only
|
||||
-->
|
||||
|
||||
## License
|
||||
|
||||
Copyright (C) 2022 Nym Technologies SA <contact@nymtech.net>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
## Network requester
|
||||
|
||||
The network requester is used to interpret socks5 client messages that need to
|
||||
be proxied to a running service i.e. a host and a port.
|
||||
|
||||
If you have a service that you want to expose to the mixnet, you'd need to
|
||||
first run the native client and provide the client address to your users that
|
||||
will use it in their socks5 configuration.
|
||||
|
||||
After starting the native client, start the network requester and configure it,
|
||||
setting your service's endpoint in
|
||||
`${HOME}/.nym/service-providers/network-requester/allowed.list`
|
||||
|
||||
Running in `open-proxy` mode allows any traffic to be proxied by the network
|
||||
requester.
|
||||
|
||||
### Statistics service
|
||||
The network requester can be ran as a gatherer of statistics for all
|
||||
the services it proxies. For that, run the binary with the
|
||||
`enable-statistics` flag enabled. Anonymized statistics are then sent to
|
||||
a central server, through the mixnet.
|
||||
@@ -1,2 +0,0 @@
|
||||
[release]
|
||||
address = "0.0.0.0"
|
||||
@@ -1,74 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use nym_sdk::mixnet::{
|
||||
IncludedSurbs, MixnetClient, MixnetMessageSender, Recipient, ReconstructedMessage,
|
||||
};
|
||||
use nym_service_providers_common::interface::{
|
||||
ProviderInterfaceVersion, Request, Response, ResponseContent,
|
||||
};
|
||||
use nym_socks5_requests::{QueryRequest, Socks5ProtocolVersion, Socks5Request, Socks5Response};
|
||||
|
||||
fn parse_response(received: Vec<ReconstructedMessage>) -> Socks5Response {
|
||||
assert_eq!(received.len(), 1);
|
||||
let response: Response<Socks5Request> = Response::try_from_bytes(&received[0].message).unwrap();
|
||||
match response.content {
|
||||
ResponseContent::Control(control) => panic!("unexpected control response: {control:?}"),
|
||||
ResponseContent::ProviderData(data) => data,
|
||||
}
|
||||
}
|
||||
|
||||
async fn wait_for_response(client: &mut MixnetClient) -> Socks5Response {
|
||||
loop {
|
||||
let next = client.wait_for_messages().await.unwrap();
|
||||
if !next.is_empty() {
|
||||
return parse_response(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
//nym_bin_common::logging::setup_logging();
|
||||
let mut client = MixnetClient::connect_new().await.unwrap();
|
||||
let provider: Recipient = "AN8eLxYWFitCkMn92zim3PrPszxJZDYyFFKP7qnnAAew.8UAxL3LwQBis6WpM3GGXaqKGaVdnLCpGJWumHT6KNdTH@77TSuVU8d1oXKbPzjec2xh4i3Wj5WwUyy9Lr36sm8gZm".parse().unwrap();
|
||||
|
||||
let open_proxy_request = Request::new_provider_data(
|
||||
ProviderInterfaceVersion::new_current(),
|
||||
Socks5Request::new_query(
|
||||
Socks5ProtocolVersion::new_current(),
|
||||
QueryRequest::OpenProxy,
|
||||
),
|
||||
);
|
||||
let description_request = Request::new_provider_data(
|
||||
ProviderInterfaceVersion::new_current(),
|
||||
Socks5Request::new_query(
|
||||
Socks5ProtocolVersion::new_current(),
|
||||
QueryRequest::Description,
|
||||
),
|
||||
);
|
||||
println!("Sending 'OpenProxy' query...");
|
||||
client
|
||||
.send_message(
|
||||
provider,
|
||||
open_proxy_request.into_bytes(),
|
||||
IncludedSurbs::new(10),
|
||||
)
|
||||
.await?;
|
||||
let response = wait_for_response(&mut client).await;
|
||||
println!("response to 'OpenProxy' query: {response:#?}");
|
||||
|
||||
println!("Sending 'Description' query...");
|
||||
client
|
||||
.send_message(
|
||||
provider,
|
||||
description_request.into_bytes(),
|
||||
IncludedSurbs::none(),
|
||||
)
|
||||
.await?;
|
||||
let response = wait_for_response(&mut client).await;
|
||||
println!("response to 'Description' query: {response:#?}");
|
||||
|
||||
client.disconnect().await;
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::cli::CliNetworkRequesterClient;
|
||||
use crate::error::NetworkRequesterError;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_add_gateway::{add_gateway, CommonClientAddGatewayArgs};
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientAddGatewayArgs,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientAddGatewayArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientAddGatewayArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), NetworkRequesterError> {
|
||||
let output = args.output;
|
||||
let res = add_gateway::<CliNetworkRequesterClient, _>(args, None).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use clap::Args;
|
||||
use nym_bin_common::bin_info_owned;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
|
||||
#[derive(Args)]
|
||||
pub(crate) struct BuildInfo {
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
pub(crate) fn execute(args: BuildInfo) {
|
||||
println!("{}", args.output.format(&bin_info_owned!()))
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::cli::CliNetworkRequesterClient;
|
||||
use crate::error::NetworkRequesterError;
|
||||
use nym_client_core::cli_helpers::client_import_coin_index_signatures::{
|
||||
import_coin_index_signatures, CommonClientImportCoinIndexSignaturesArgs,
|
||||
};
|
||||
|
||||
pub(crate) async fn execute(
|
||||
args: CommonClientImportCoinIndexSignaturesArgs,
|
||||
) -> Result<(), NetworkRequesterError> {
|
||||
import_coin_index_signatures::<CliNetworkRequesterClient, _>(args).await?;
|
||||
println!("successfully imported coin index signatures!");
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::cli::CliNetworkRequesterClient;
|
||||
use crate::error::NetworkRequesterError;
|
||||
use nym_client_core::cli_helpers::client_import_credential::{
|
||||
import_credential, CommonClientImportTicketBookArgs,
|
||||
};
|
||||
|
||||
pub async fn execute(args: CommonClientImportTicketBookArgs) -> Result<(), NetworkRequesterError> {
|
||||
import_credential::<CliNetworkRequesterClient, _>(args).await?;
|
||||
println!("successfully imported credential!");
|
||||
Ok(())
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::cli::CliNetworkRequesterClient;
|
||||
use crate::error::NetworkRequesterError;
|
||||
use nym_client_core::cli_helpers::client_import_expiration_date_signatures::{
|
||||
import_expiration_date_signatures, CommonClientImportExpirationDateSignaturesArgs,
|
||||
};
|
||||
|
||||
pub(crate) async fn execute(
|
||||
args: CommonClientImportExpirationDateSignaturesArgs,
|
||||
) -> Result<(), NetworkRequesterError> {
|
||||
import_expiration_date_signatures::<CliNetworkRequesterClient, _>(args).await?;
|
||||
println!("successfully imported expiration date signatures!");
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::cli::CliNetworkRequesterClient;
|
||||
use crate::error::NetworkRequesterError;
|
||||
use nym_client_core::cli_helpers::client_import_master_verification_key::{
|
||||
import_master_verification_key, CommonClientImportMasterVerificationKeyArgs,
|
||||
};
|
||||
|
||||
pub(crate) async fn execute(
|
||||
args: CommonClientImportMasterVerificationKeyArgs,
|
||||
) -> Result<(), NetworkRequesterError> {
|
||||
import_master_verification_key::<CliNetworkRequesterClient, _>(args).await?;
|
||||
println!("successfully imported master verification key!");
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::NetworkRequesterError;
|
||||
use clap::{Args, Subcommand};
|
||||
use nym_client_core::cli_helpers::client_import_coin_index_signatures::CommonClientImportCoinIndexSignaturesArgs;
|
||||
use nym_client_core::cli_helpers::client_import_credential::CommonClientImportTicketBookArgs;
|
||||
use nym_client_core::cli_helpers::client_import_expiration_date_signatures::CommonClientImportExpirationDateSignaturesArgs;
|
||||
use nym_client_core::cli_helpers::client_import_master_verification_key::CommonClientImportMasterVerificationKeyArgs;
|
||||
|
||||
pub(crate) mod import_coin_index_signatures;
|
||||
pub(crate) mod import_credential;
|
||||
pub(crate) mod import_expiration_date_signatures;
|
||||
pub(crate) mod import_master_verification_key;
|
||||
pub(crate) mod show_ticketbooks;
|
||||
|
||||
#[derive(Args)]
|
||||
#[clap(args_conflicts_with_subcommands = true, subcommand_required = true)]
|
||||
pub struct Ecash {
|
||||
#[clap(subcommand)]
|
||||
pub command: EcashCommands,
|
||||
}
|
||||
|
||||
impl Ecash {
|
||||
pub async fn execute(self) -> Result<(), NetworkRequesterError> {
|
||||
match self.command {
|
||||
EcashCommands::ShowTicketBooks(args) => show_ticketbooks::execute(args).await?,
|
||||
EcashCommands::ImportTicketBook(args) => import_credential::execute(args).await?,
|
||||
EcashCommands::ImportCoinIndexSignatures(args) => {
|
||||
import_coin_index_signatures::execute(args).await?
|
||||
}
|
||||
EcashCommands::ImportExpirationDateSignatures(args) => {
|
||||
import_expiration_date_signatures::execute(args).await?
|
||||
}
|
||||
EcashCommands::ImportMasterVerificationKey(args) => {
|
||||
import_master_verification_key::execute(args).await?
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
pub enum EcashCommands {
|
||||
/// Display information associated with the imported ticketbooks,
|
||||
ShowTicketBooks(show_ticketbooks::Args),
|
||||
|
||||
/// Import a pre-generated ticketbook
|
||||
ImportTicketBook(CommonClientImportTicketBookArgs),
|
||||
|
||||
/// Import coin index signatures needed for ticketbooks
|
||||
ImportCoinIndexSignatures(CommonClientImportCoinIndexSignaturesArgs),
|
||||
|
||||
/// Import expiration date signatures needed for ticketbooks
|
||||
ImportExpirationDateSignatures(CommonClientImportExpirationDateSignaturesArgs),
|
||||
|
||||
/// Import master verification key needed for ticketbooks
|
||||
ImportMasterVerificationKey(CommonClientImportMasterVerificationKeyArgs),
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::cli::CliNetworkRequesterClient;
|
||||
use crate::error::NetworkRequesterError;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_show_ticketbooks::{
|
||||
show_ticketbooks, CommonShowTicketbooksArgs,
|
||||
};
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonShowTicketbooksArgs,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonShowTicketbooksArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonShowTicketbooksArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), NetworkRequesterError> {
|
||||
let output = args.output;
|
||||
let res = show_ticketbooks::<CliNetworkRequesterClient, _>(args).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::cli::CliNetworkRequesterClient;
|
||||
use crate::config::{default_config_directory, default_config_filepath, default_data_directory};
|
||||
use crate::{
|
||||
cli::{override_config, OverrideConfig},
|
||||
config::Config,
|
||||
error::NetworkRequesterError,
|
||||
};
|
||||
use clap::Args;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_init::{
|
||||
initialise_client, CommonClientInitArgs, InitResultsWithConfig, InitialisableClient,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use std::fmt::Display;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
impl InitialisableClient for CliNetworkRequesterClient {
|
||||
type InitArgs = Init;
|
||||
|
||||
fn initialise_storage_paths(id: &str) -> Result<(), Self::Error> {
|
||||
fs::create_dir_all(default_data_directory(id))?;
|
||||
fs::create_dir_all(default_config_directory(id))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn default_config_path(id: &str) -> PathBuf {
|
||||
default_config_filepath(id)
|
||||
}
|
||||
|
||||
fn construct_config(init_args: &Self::InitArgs) -> Self::Config {
|
||||
override_config(
|
||||
Config::new(&init_args.common_args.id),
|
||||
OverrideConfig::from(init_args.clone()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Args, Clone, Debug)]
|
||||
pub(crate) struct Init {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientInitArgs,
|
||||
|
||||
/// Specifies whether this network requester should run in 'open-proxy' mode
|
||||
#[clap(long)]
|
||||
open_proxy: Option<bool>,
|
||||
|
||||
#[clap(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl From<Init> for OverrideConfig {
|
||||
fn from(init_config: Init) -> Self {
|
||||
OverrideConfig {
|
||||
nym_apis: init_config.common_args.nym_apis,
|
||||
fastmode: init_config.common_args.fastmode,
|
||||
no_cover: init_config.common_args.no_cover,
|
||||
medium_toggle: false,
|
||||
nyxd_urls: init_config.common_args.nyxd_urls,
|
||||
enabled_credentials_mode: init_config.common_args.enabled_credentials_mode,
|
||||
open_proxy: init_config.open_proxy,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientInitArgs> for Init {
|
||||
fn as_ref(&self) -> &CommonClientInitArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct InitResults {
|
||||
#[serde(flatten)]
|
||||
client_core: nym_client_core::init::types::InitResults,
|
||||
client_address: String,
|
||||
}
|
||||
|
||||
impl InitResults {
|
||||
fn new(res: InitResultsWithConfig<Config>) -> Self {
|
||||
Self {
|
||||
client_address: res.init_results.address.to_string(),
|
||||
client_core: res.init_results,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for InitResults {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "{}", self.client_core)?;
|
||||
write!(
|
||||
f,
|
||||
"Address of this network-requester: {}",
|
||||
self.client_address
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Init) -> Result<(), NetworkRequesterError> {
|
||||
eprintln!("Initialising client...");
|
||||
|
||||
let output = args.output;
|
||||
let res = initialise_client::<CliNetworkRequesterClient>(args, None).await?;
|
||||
|
||||
let init_results = InitResults::new(res);
|
||||
println!("{}", output.format(&init_results));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::cli::CliNetworkRequesterClient;
|
||||
use crate::error::NetworkRequesterError;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::cli_helpers::client_list_gateways::{
|
||||
list_gateways, CommonClientListGatewaysArgs,
|
||||
};
|
||||
|
||||
#[derive(clap::Args)]
|
||||
pub(crate) struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientListGatewaysArgs,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientListGatewaysArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientListGatewaysArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), NetworkRequesterError> {
|
||||
let output = args.output;
|
||||
let res = list_gateways::<CliNetworkRequesterClient, _>(args).await?;
|
||||
|
||||
println!("{}", output.format(&res));
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::cli::ecash::Ecash;
|
||||
use crate::config::helpers::try_upgrade_config_by_id;
|
||||
use crate::{
|
||||
config::{BaseClientConfig, Config},
|
||||
error::NetworkRequesterError,
|
||||
};
|
||||
use clap::{CommandFactory, Parser, Subcommand};
|
||||
use log::error;
|
||||
use nym_bin_common::bin_info;
|
||||
use nym_bin_common::completions::{fig_generate, ArgShell};
|
||||
use nym_client_core::cli_helpers::CliClient;
|
||||
use nym_config::OptionalSet;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
mod add_gateway;
|
||||
mod build_info;
|
||||
pub mod ecash;
|
||||
mod init;
|
||||
mod list_gateways;
|
||||
mod run;
|
||||
mod sign;
|
||||
mod switch_gateway;
|
||||
|
||||
pub(crate) struct CliNetworkRequesterClient;
|
||||
|
||||
impl CliClient for CliNetworkRequesterClient {
|
||||
const NAME: &'static str = "network requester";
|
||||
type Error = NetworkRequesterError;
|
||||
type Config = Config;
|
||||
|
||||
async fn try_upgrade_outdated_config(id: &str) -> Result<(), Self::Error> {
|
||||
try_upgrade_config_by_id(id).await
|
||||
}
|
||||
|
||||
async fn try_load_current_config(id: &str) -> Result<Self::Config, Self::Error> {
|
||||
try_load_current_config(id).await
|
||||
}
|
||||
}
|
||||
|
||||
fn pretty_build_info_static() -> &'static str {
|
||||
static PRETTY_BUILD_INFORMATION: OnceLock<String> = OnceLock::new();
|
||||
PRETTY_BUILD_INFORMATION.get_or_init(|| bin_info!().pretty_print())
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author = "Nymtech", version, about, long_version = pretty_build_info_static())]
|
||||
pub(crate) struct Cli {
|
||||
/// Path pointing to an env file that configures the client.
|
||||
#[arg(short, long)]
|
||||
pub(crate) config_env_file: Option<std::path::PathBuf>,
|
||||
|
||||
/// Flag used for disabling the printed banner in tty.
|
||||
#[arg(long)]
|
||||
pub(crate) no_banner: bool,
|
||||
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Subcommand)]
|
||||
pub(crate) enum Commands {
|
||||
/// Initialize a network-requester. Do this first!
|
||||
Init(init::Init),
|
||||
|
||||
/// Run the network requester with the provided configuration and optionally override
|
||||
/// parameters.
|
||||
Run(run::Run),
|
||||
|
||||
/// Ecash-related functionalities
|
||||
Ecash(Ecash),
|
||||
|
||||
/// Sign to prove ownership of this network requester
|
||||
Sign(sign::Sign),
|
||||
|
||||
/// List all registered with gateways
|
||||
ListGateways(list_gateways::Args),
|
||||
|
||||
/// Add new gateway to this client
|
||||
AddGateway(add_gateway::Args),
|
||||
|
||||
/// Change the currently active gateway. Note that you must have already registered with the new gateway!
|
||||
SwitchGateway(switch_gateway::Args),
|
||||
|
||||
/// Show build information of this binary
|
||||
BuildInfo(build_info::BuildInfo),
|
||||
|
||||
/// Generate shell completions
|
||||
Completions(ArgShell),
|
||||
|
||||
/// Generate Fig specification
|
||||
GenerateFigSpec,
|
||||
}
|
||||
|
||||
// Configuration that can be overridden.
|
||||
pub(crate) struct OverrideConfig {
|
||||
nym_apis: Option<Vec<url::Url>>,
|
||||
fastmode: bool,
|
||||
no_cover: bool,
|
||||
medium_toggle: bool,
|
||||
nyxd_urls: Option<Vec<url::Url>>,
|
||||
enabled_credentials_mode: Option<bool>,
|
||||
|
||||
open_proxy: Option<bool>,
|
||||
}
|
||||
|
||||
// NOTE: make sure this is in sync with `gateway/src/helpers.rs::override_network_requester_config`
|
||||
pub(crate) fn override_config(mut config: Config, args: OverrideConfig) -> Config {
|
||||
// in the old code we had calls to `assert` thus panicking
|
||||
config
|
||||
.base
|
||||
.try_apply_traffic_modes(
|
||||
config.network_requester.disable_poisson_rate,
|
||||
args.medium_toggle,
|
||||
args.fastmode,
|
||||
args.no_cover,
|
||||
)
|
||||
.expect("failed to apply traffic modes");
|
||||
|
||||
config
|
||||
.with_optional_base_custom_env(
|
||||
BaseClientConfig::with_custom_nym_apis,
|
||||
args.nym_apis,
|
||||
nym_network_defaults::var_names::NYM_API,
|
||||
nym_config::parse_urls,
|
||||
)
|
||||
.with_optional_base_custom_env(
|
||||
BaseClientConfig::with_custom_nyxd,
|
||||
args.nyxd_urls,
|
||||
nym_network_defaults::var_names::NYXD,
|
||||
nym_config::parse_urls,
|
||||
)
|
||||
.with_optional_base(
|
||||
BaseClientConfig::with_disabled_credentials,
|
||||
args.enabled_credentials_mode.map(|b| !b),
|
||||
)
|
||||
.with_optional(Config::with_open_proxy, args.open_proxy)
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Cli) -> Result<(), NetworkRequesterError> {
|
||||
let bin_name = "nym-network-requester";
|
||||
|
||||
match args.command {
|
||||
Commands::Init(m) => init::execute(m).await?,
|
||||
Commands::Run(m) => run::execute(&m).await?,
|
||||
Commands::Ecash(ecash) => ecash.execute().await?,
|
||||
Commands::Sign(m) => sign::execute(&m).await?,
|
||||
Commands::ListGateways(args) => list_gateways::execute(args).await?,
|
||||
Commands::AddGateway(args) => add_gateway::execute(args).await?,
|
||||
Commands::SwitchGateway(args) => switch_gateway::execute(args).await?,
|
||||
Commands::BuildInfo(m) => build_info::execute(m),
|
||||
Commands::Completions(s) => s.generate(&mut Cli::command(), bin_name),
|
||||
Commands::GenerateFigSpec => fig_generate(&mut Cli::command(), bin_name),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn try_load_current_config(id: &str) -> Result<Config, NetworkRequesterError> {
|
||||
// try to load the config as is
|
||||
if let Ok(cfg) = Config::read_from_default_path(id) {
|
||||
return if !cfg.validate() {
|
||||
Err(NetworkRequesterError::ConfigValidationFailure)
|
||||
} else {
|
||||
Ok(cfg)
|
||||
};
|
||||
}
|
||||
|
||||
// we couldn't load it - try upgrading it from older revisions
|
||||
try_upgrade_config_by_id(id).await?;
|
||||
|
||||
let config = match Config::read_from_default_path(id) {
|
||||
Ok(cfg) => cfg,
|
||||
Err(err) => {
|
||||
error!("Failed to load config for {id}. Are you sure you have run `init` before? (Error was: {err})");
|
||||
return Err(NetworkRequesterError::FailedToLoadConfig(id.to_string()));
|
||||
}
|
||||
};
|
||||
|
||||
if !config.validate() {
|
||||
return Err(NetworkRequesterError::ConfigValidationFailure);
|
||||
}
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn verify_cli() {
|
||||
Cli::command().debug_assert();
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::cli::try_load_current_config;
|
||||
use crate::{
|
||||
cli::{override_config, OverrideConfig},
|
||||
error::NetworkRequesterError,
|
||||
};
|
||||
use clap::Args;
|
||||
use nym_client_core::cli_helpers::client_run::CommonClientRunArgs;
|
||||
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
#[derive(Args, Clone)]
|
||||
pub(crate) struct Run {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientRunArgs,
|
||||
|
||||
/// Specifies whether this network requester should run in 'open-proxy' mode
|
||||
#[arg(long)]
|
||||
open_proxy: Option<bool>,
|
||||
|
||||
/// Enable medium mixnet traffic, for experiments only.
|
||||
/// This includes things like disabling cover traffic, no per hop delays, etc.
|
||||
#[arg(
|
||||
long,
|
||||
hide = true,
|
||||
conflicts_with = "no_cover",
|
||||
conflicts_with = "fastmode"
|
||||
)]
|
||||
medium_toggle: bool,
|
||||
}
|
||||
|
||||
impl From<Run> for OverrideConfig {
|
||||
fn from(run_config: Run) -> Self {
|
||||
OverrideConfig {
|
||||
nym_apis: None,
|
||||
fastmode: run_config.common_args.fastmode,
|
||||
no_cover: run_config.common_args.no_cover,
|
||||
medium_toggle: run_config.medium_toggle,
|
||||
nyxd_urls: run_config.common_args.nyxd_urls,
|
||||
enabled_credentials_mode: run_config.common_args.enabled_credentials_mode,
|
||||
open_proxy: run_config.open_proxy,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: &Run) -> Result<(), NetworkRequesterError> {
|
||||
let mut config = try_load_current_config(&args.common_args.id).await?;
|
||||
config = override_config(config, OverrideConfig::from(args.clone()));
|
||||
log::debug!("Using config: {config:#?}");
|
||||
|
||||
if config.network_requester.open_proxy {
|
||||
println!(
|
||||
"\n\nYOU HAVE STARTED IN 'OPEN PROXY' MODE. ANYONE WITH YOUR CLIENT ADDRESS \
|
||||
CAN MAKE REQUESTS FROM YOUR MACHINE. PLEASE QUIT IF YOU DON'T UNDERSTAND WHAT \
|
||||
YOU'RE DOING.\n\n"
|
||||
);
|
||||
}
|
||||
|
||||
log::info!("Starting socks5 service provider");
|
||||
let mut server = crate::core::NRServiceProviderBuilder::new(config);
|
||||
if let Some(custom_mixnet) = &args.common_args.custom_mixnet {
|
||||
server = server.with_stored_topology(custom_mixnet)?
|
||||
}
|
||||
|
||||
server.run_service_provider().await
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::cli::try_load_current_config;
|
||||
use crate::error::NetworkRequesterError;
|
||||
use clap::Args;
|
||||
use nym_bin_common::output_format::OutputFormat;
|
||||
use nym_client_core::client::key_manager::persistence::OnDiskKeys;
|
||||
use nym_client_core::error::ClientCoreError;
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use nym_types::helpers::ConsoleSigningOutput;
|
||||
|
||||
#[derive(Args, Clone)]
|
||||
pub(crate) struct Sign {
|
||||
/// The id of the mixnode you want to sign with
|
||||
#[arg(long)]
|
||||
id: String,
|
||||
|
||||
/// Signs a transaction-specific payload, that is going to be sent to the smart contract, with your identity key
|
||||
#[arg(long)]
|
||||
contract_msg: String,
|
||||
|
||||
#[arg(short, long, default_value_t = OutputFormat::default())]
|
||||
output: OutputFormat,
|
||||
}
|
||||
|
||||
fn print_signed_contract_msg(
|
||||
private_key: &ed25519::PrivateKey,
|
||||
raw_msg: &str,
|
||||
output: OutputFormat,
|
||||
) {
|
||||
let trimmed = raw_msg.trim();
|
||||
eprintln!(">>> attempting to sign {trimmed}");
|
||||
|
||||
let Ok(decoded) = bs58::decode(trimmed).into_vec() else {
|
||||
println!("it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters");
|
||||
return;
|
||||
};
|
||||
|
||||
eprintln!(">>> decoding the message...");
|
||||
|
||||
// we don't really care about what particular information is embedded inside of it,
|
||||
// we just want to know if user correctly copied the string, i.e. whether it's a valid bs58 encoded json
|
||||
if serde_json::from_slice::<serde_json::Value>(&decoded).is_err() {
|
||||
println!("it seems you have incorrectly copied the message to sign. Make sure you didn't accidentally skip any characters");
|
||||
return;
|
||||
};
|
||||
|
||||
// if this is a valid json, it MUST be a valid string
|
||||
let decoded_string = String::from_utf8(decoded.clone()).unwrap();
|
||||
let signature = private_key.sign(&decoded).to_base58_string();
|
||||
|
||||
let sign_output = ConsoleSigningOutput::new(decoded_string, signature);
|
||||
println!("{}", output.format(&sign_output));
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: &Sign) -> Result<(), NetworkRequesterError> {
|
||||
let config = try_load_current_config(&args.id).await?;
|
||||
|
||||
let key_store = OnDiskKeys::new(config.storage_paths.common_paths.keys);
|
||||
let identity_keypair = key_store.load_identity_keypair().map_err(|source| {
|
||||
NetworkRequesterError::ClientCoreError(ClientCoreError::KeyStoreError {
|
||||
source: Box::new(source),
|
||||
})
|
||||
})?;
|
||||
|
||||
print_signed_contract_msg(
|
||||
identity_keypair.private_key(),
|
||||
&args.contract_msg,
|
||||
args.output,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::cli::CliNetworkRequesterClient;
|
||||
use crate::error::NetworkRequesterError;
|
||||
use nym_client_core::cli_helpers::client_switch_gateway::{
|
||||
switch_gateway, CommonClientSwitchGatewaysArgs,
|
||||
};
|
||||
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
pub struct Args {
|
||||
#[command(flatten)]
|
||||
common_args: CommonClientSwitchGatewaysArgs,
|
||||
}
|
||||
|
||||
impl AsRef<CommonClientSwitchGatewaysArgs> for Args {
|
||||
fn as_ref(&self) -> &CommonClientSwitchGatewaysArgs {
|
||||
&self.common_args
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn execute(args: Args) -> Result<(), NetworkRequesterError> {
|
||||
switch_gateway::<CliNetworkRequesterClient, _>(args).await
|
||||
}
|
||||
@@ -1,216 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::default_config_filepath;
|
||||
use crate::config::old::v6::ConfigV6;
|
||||
use crate::config::old_config_v1_1_13::OldConfigV1;
|
||||
use crate::config::old_config_v1_1_20::ConfigV2;
|
||||
use crate::config::old_config_v1_1_20_2::ConfigV3;
|
||||
use crate::config::old_config_v1_1_33::ConfigV4;
|
||||
use crate::config::old_config_v1_1_54::ConfigV5;
|
||||
use crate::config::Config;
|
||||
use crate::error::NetworkRequesterError;
|
||||
use log::{info, trace};
|
||||
use nym_client_core::cli_helpers::CliClientConfig;
|
||||
use nym_client_core::client::base_client::storage::migration_helpers::v1_1_33;
|
||||
use std::path::Path;
|
||||
|
||||
async fn try_upgrade_v1_config<P: AsRef<Path>>(
|
||||
config_path: P,
|
||||
) -> Result<bool, NetworkRequesterError> {
|
||||
trace!("Trying to load as v1.1.13 config");
|
||||
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
|
||||
|
||||
// explicitly load it as v1.1.13 (which is incompatible with the next step, i.e. 1.1.19)
|
||||
let Ok(old_config) = OldConfigV1::load_from_filepath(config_path.as_ref()) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||
return Ok(false);
|
||||
};
|
||||
info!("It seems the client is using <= v1.1.13 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated_step1: ConfigV2 = old_config.into();
|
||||
let updated_step2: ConfigV3 = updated_step1.into();
|
||||
let (updated_step3, gateway_config) = updated_step2.upgrade()?;
|
||||
let old_paths = updated_step3.storage_paths.clone();
|
||||
let updated_step4 = updated_step3.try_upgrade()?;
|
||||
|
||||
v1_1_33::migrate_gateway_details(
|
||||
&old_paths.common_paths,
|
||||
&updated_step4.storage_paths.common_paths,
|
||||
Some(gateway_config),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let updated_step5: ConfigV6 = updated_step4.into();
|
||||
let updated: Config = updated_step5.into();
|
||||
|
||||
updated.save_to(config_path)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
async fn try_upgrade_v2_config<P: AsRef<Path>>(
|
||||
config_path: P,
|
||||
) -> Result<bool, NetworkRequesterError> {
|
||||
trace!("Trying to load as v1.1.20 config");
|
||||
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
|
||||
|
||||
// explicitly load it as v1.1.20 (which is incompatible with the current one, i.e. +1.1.21)
|
||||
let Ok(old_config) = ConfigV2::load_from_filepath(config_path.as_ref()) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||
return Ok(false);
|
||||
};
|
||||
|
||||
info!("It seems the client is using <= v1.1.20 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated_step1: ConfigV3 = old_config.into();
|
||||
let (updated_step2, gateway_config) = updated_step1.upgrade()?;
|
||||
let old_paths = updated_step2.storage_paths.clone();
|
||||
let updated_step3 = updated_step2.try_upgrade()?;
|
||||
|
||||
v1_1_33::migrate_gateway_details(
|
||||
&old_paths.common_paths,
|
||||
&updated_step3.storage_paths.common_paths,
|
||||
Some(gateway_config),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let updated_step4: ConfigV6 = updated_step3.into();
|
||||
let updated: Config = updated_step4.into();
|
||||
|
||||
updated.save_to(config_path)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
async fn try_upgrade_v3_config<P: AsRef<Path>>(
|
||||
config_path: P,
|
||||
) -> Result<bool, NetworkRequesterError> {
|
||||
trace!("Trying to load as v1.1.20_2 config");
|
||||
|
||||
// explicitly load it as v1.1.20_2 (which is incompatible with the current one, i.e. +1.1.21)
|
||||
let Ok(old_config) = ConfigV3::read_from_toml_file(config_path.as_ref()) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||
return Ok(false);
|
||||
};
|
||||
info!("It seems the client is using <= v1.1.20_2 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let (updated_step1, gateway_config) = old_config.upgrade()?;
|
||||
let old_paths = updated_step1.storage_paths.clone();
|
||||
let updated_step2 = updated_step1.try_upgrade()?;
|
||||
|
||||
v1_1_33::migrate_gateway_details(
|
||||
&old_paths.common_paths,
|
||||
&updated_step2.storage_paths.common_paths,
|
||||
Some(gateway_config),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let updated_step3: ConfigV6 = updated_step2.into();
|
||||
let updated: Config = updated_step3.into();
|
||||
|
||||
updated.save_to(config_path)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
async fn try_upgrade_v4_config<P: AsRef<Path>>(
|
||||
config_path: P,
|
||||
) -> Result<bool, NetworkRequesterError> {
|
||||
trace!("Trying to load as v1.1.33 config");
|
||||
|
||||
// explicitly load it as v1.1.33 (which is incompatible with the current one, i.e. +1.1.34)
|
||||
let Ok(old_config) = ConfigV4::read_from_toml_file(config_path.as_ref()) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||
return Ok(false);
|
||||
};
|
||||
info!("It seems the client is using <= v1.1.33 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let old_paths = old_config.storage_paths.clone();
|
||||
let updated_step1 = old_config.try_upgrade()?;
|
||||
|
||||
v1_1_33::migrate_gateway_details(
|
||||
&old_paths.common_paths,
|
||||
&updated_step1.storage_paths.common_paths,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let updated_step2: ConfigV6 = updated_step1.into();
|
||||
let updated: Config = updated_step2.into();
|
||||
|
||||
updated.save_to(config_path)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
async fn try_upgrade_v5_config<P: AsRef<Path>>(
|
||||
config_path: P,
|
||||
) -> Result<bool, NetworkRequesterError> {
|
||||
// explicitly load it as v5 (which is incompatible with the current one)
|
||||
let Ok(old_config) = ConfigV5::read_from_toml_file(config_path.as_ref()) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||
return Ok(false);
|
||||
};
|
||||
info!("It seems the client is using <= v5 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated_step1: ConfigV6 = old_config.into();
|
||||
let updated: Config = updated_step1.into();
|
||||
updated.save_to(config_path)?;
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
async fn try_upgrade_v6_config<P: AsRef<Path>>(
|
||||
config_path: P,
|
||||
) -> Result<bool, NetworkRequesterError> {
|
||||
// explicitly load it as v6 (which is incompatible with the current one)
|
||||
let Ok(old_config) = ConfigV6::read_from_toml_file(config_path.as_ref()) else {
|
||||
// if we failed to load it, there might have been nothing to upgrade
|
||||
// or maybe it was an even older file. in either way. just ignore it and carry on with our day
|
||||
return Ok(false);
|
||||
};
|
||||
info!("It seems the client is using <= v6 config template.");
|
||||
info!("It is going to get updated to the current specification.");
|
||||
|
||||
let updated: Config = old_config.into();
|
||||
updated.save_to(config_path)?;
|
||||
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub async fn try_upgrade_config<P: AsRef<Path>>(
|
||||
config_path: P,
|
||||
) -> Result<(), NetworkRequesterError> {
|
||||
trace!("Attempting to upgrade config");
|
||||
if try_upgrade_v1_config(config_path.as_ref()).await? {
|
||||
return Ok(());
|
||||
}
|
||||
if try_upgrade_v2_config(config_path.as_ref()).await? {
|
||||
return Ok(());
|
||||
}
|
||||
if try_upgrade_v3_config(config_path.as_ref()).await? {
|
||||
return Ok(());
|
||||
}
|
||||
if try_upgrade_v4_config(config_path.as_ref()).await? {
|
||||
return Ok(());
|
||||
}
|
||||
if try_upgrade_v5_config(config_path.as_ref()).await? {
|
||||
return Ok(());
|
||||
}
|
||||
if try_upgrade_v6_config(config_path).await? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn try_upgrade_config_by_id(id: &str) -> Result<(), NetworkRequesterError> {
|
||||
try_upgrade_config(default_config_filepath(id)).await
|
||||
}
|
||||
@@ -1,251 +0,0 @@
|
||||
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::config::template::CONFIG_TEMPLATE;
|
||||
use nym_bin_common::logging::LoggingSettings;
|
||||
use nym_client_core::cli_helpers::CliClientConfig;
|
||||
use nym_client_core::config::disk_persistence::CommonClientPaths;
|
||||
use nym_config::{
|
||||
must_get_home, read_config_from_toml_file, save_formatted_config_to_file,
|
||||
serde_helpers::de_maybe_stringified, NymConfigTemplate, OptionalSet, DEFAULT_CONFIG_DIR,
|
||||
DEFAULT_CONFIG_FILENAME, DEFAULT_DATA_DIR, NYM_DIR,
|
||||
};
|
||||
use nym_network_defaults::mainnet;
|
||||
use nym_service_providers_common::DEFAULT_SERVICE_PROVIDERS_DIR;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
|
||||
pub use crate::config::persistence::NetworkRequesterPaths;
|
||||
pub use nym_client_core::config::Config as BaseClientConfig;
|
||||
|
||||
pub mod helpers;
|
||||
pub mod old;
|
||||
mod persistence;
|
||||
mod template;
|
||||
|
||||
// aliases for backwards compatibility
|
||||
pub use old::v1 as old_config_v1_1_13;
|
||||
pub use old::v2 as old_config_v1_1_20;
|
||||
pub use old::v3 as old_config_v1_1_20_2;
|
||||
pub use old::v4 as old_config_v1_1_33;
|
||||
pub use old::v5 as old_config_v1_1_54;
|
||||
|
||||
const DEFAULT_NETWORK_REQUESTERS_DIR: &str = "network-requester";
|
||||
|
||||
pub const DEFAULT_STANDARD_LIST_UPDATE_INTERVAL: Duration = Duration::from_secs(30 * 60);
|
||||
|
||||
/// Derive default path to network requester's config directory.
|
||||
/// It should get resolved to `$HOME/.nym/service-providers/network-requester/<id>/config`
|
||||
pub fn default_config_directory<P: AsRef<Path>>(id: P) -> PathBuf {
|
||||
must_get_home()
|
||||
.join(NYM_DIR)
|
||||
.join(DEFAULT_SERVICE_PROVIDERS_DIR)
|
||||
.join(DEFAULT_NETWORK_REQUESTERS_DIR)
|
||||
.join(id)
|
||||
.join(DEFAULT_CONFIG_DIR)
|
||||
}
|
||||
|
||||
/// Derive default path to network requester's config file.
|
||||
/// It should get resolved to `$HOME/.nym/service-providers/network-requester/<id>/config/config.toml`
|
||||
pub fn default_config_filepath<P: AsRef<Path>>(id: P) -> PathBuf {
|
||||
default_config_directory(id).join(DEFAULT_CONFIG_FILENAME)
|
||||
}
|
||||
|
||||
/// Derive default path to network requester's data directory where files, such as keys, are stored.
|
||||
/// It should get resolved to `$HOME/.nym/service-providers/network-requester/<id>/data`
|
||||
pub fn default_data_directory<P: AsRef<Path>>(id: P) -> PathBuf {
|
||||
must_get_home()
|
||||
.join(NYM_DIR)
|
||||
.join(DEFAULT_SERVICE_PROVIDERS_DIR)
|
||||
.join(DEFAULT_NETWORK_REQUESTERS_DIR)
|
||||
.join(id)
|
||||
.join(DEFAULT_DATA_DIR)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Config {
|
||||
#[serde(flatten)]
|
||||
pub base: BaseClientConfig,
|
||||
|
||||
#[serde(default)]
|
||||
pub network_requester: NetworkRequester,
|
||||
|
||||
pub storage_paths: NetworkRequesterPaths,
|
||||
|
||||
#[serde(default)]
|
||||
pub network_requester_debug: Debug,
|
||||
|
||||
pub logging: LoggingSettings,
|
||||
}
|
||||
|
||||
impl NymConfigTemplate for Config {
|
||||
fn template(&self) -> &'static str {
|
||||
CONFIG_TEMPLATE
|
||||
}
|
||||
}
|
||||
|
||||
impl CliClientConfig for Config {
|
||||
fn common_paths(&self) -> &CommonClientPaths {
|
||||
&self.storage_paths.common_paths
|
||||
}
|
||||
|
||||
fn core_config(&self) -> &BaseClientConfig {
|
||||
&self.base
|
||||
}
|
||||
|
||||
fn default_store_location(&self) -> PathBuf {
|
||||
self.default_location()
|
||||
}
|
||||
|
||||
fn save_to<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
|
||||
save_formatted_config_to_file(self, path)
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new<S: AsRef<str>>(id: S) -> Self {
|
||||
Config {
|
||||
base: BaseClientConfig::new(id.as_ref(), env!("CARGO_PKG_VERSION")),
|
||||
network_requester: Default::default(),
|
||||
storage_paths: NetworkRequesterPaths::new_base(default_data_directory(id.as_ref())),
|
||||
network_requester_debug: Default::default(),
|
||||
logging: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
// this is a false positive, this method is actually called when used as a library
|
||||
// but clippy complains about it when building the binary
|
||||
#[allow(unused)]
|
||||
pub fn with_data_directory<P: AsRef<Path>>(mut self, data_directory: P) -> Self {
|
||||
self.storage_paths = NetworkRequesterPaths::new_base(data_directory);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn read_from_toml_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
|
||||
read_config_from_toml_file(path)
|
||||
}
|
||||
|
||||
pub fn read_from_default_path<P: AsRef<Path>>(id: P) -> io::Result<Self> {
|
||||
Self::read_from_toml_file(default_config_filepath(id))
|
||||
}
|
||||
|
||||
pub fn default_location(&self) -> PathBuf {
|
||||
default_config_filepath(&self.base.client.id)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn save_to_default_location(&self) -> io::Result<()> {
|
||||
let config_save_location: PathBuf = self.default_location();
|
||||
save_formatted_config_to_file(self, config_save_location)
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> bool {
|
||||
// no other sections have explicit requirements (yet)
|
||||
self.base.validate()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_open_proxy(mut self, open_proxy: bool) -> Self {
|
||||
self.network_requester.open_proxy = open_proxy;
|
||||
self
|
||||
}
|
||||
|
||||
// poor man's 'builder' method
|
||||
#[allow(unused)]
|
||||
pub fn with_base<F, T>(mut self, f: F, val: T) -> Self
|
||||
where
|
||||
F: Fn(BaseClientConfig, T) -> BaseClientConfig,
|
||||
{
|
||||
self.base = f(self.base, val);
|
||||
self
|
||||
}
|
||||
|
||||
// helper methods to use `OptionalSet` trait. Those are defined due to very... ehm. 'specific' structure of this config
|
||||
// (plz, lets refactor it)
|
||||
pub fn with_optional_base<F, T>(mut self, f: F, val: Option<T>) -> Self
|
||||
where
|
||||
F: Fn(BaseClientConfig, T) -> BaseClientConfig,
|
||||
{
|
||||
self.base = self.base.with_optional(f, val);
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_optional_base_env<F, T>(mut self, f: F, val: Option<T>, env_var: &str) -> Self
|
||||
where
|
||||
F: Fn(BaseClientConfig, T) -> BaseClientConfig,
|
||||
T: FromStr,
|
||||
<T as FromStr>::Err: std::fmt::Debug,
|
||||
{
|
||||
self.base = self.base.with_optional_env(f, val, env_var);
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn with_optional_base_custom_env<F, T, G>(
|
||||
mut self,
|
||||
f: F,
|
||||
val: Option<T>,
|
||||
env_var: &str,
|
||||
parser: G,
|
||||
) -> Self
|
||||
where
|
||||
F: Fn(BaseClientConfig, T) -> BaseClientConfig,
|
||||
G: Fn(&str) -> T,
|
||||
{
|
||||
self.base = self.base.with_optional_custom_env(f, val, env_var, parser);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default)]
|
||||
pub struct NetworkRequester {
|
||||
/// specifies whether this network requester should run in 'open-proxy' mode
|
||||
/// and thus would attempt to resolve **ANY** request it receives.
|
||||
pub open_proxy: bool,
|
||||
|
||||
/// Disable Poisson sending rate.
|
||||
/// This is equivalent to setting debug.traffic.disable_main_poisson_packet_distribution = true,
|
||||
pub disable_poisson_rate: bool,
|
||||
|
||||
/// Specifies the url for an upstream source of the exit policy used by this node.
|
||||
#[serde(deserialize_with = "de_maybe_stringified")]
|
||||
pub upstream_exit_policy_url: Option<Url>,
|
||||
}
|
||||
|
||||
impl Default for NetworkRequester {
|
||||
fn default() -> Self {
|
||||
NetworkRequester {
|
||||
open_proxy: false,
|
||||
disable_poisson_rate: true,
|
||||
upstream_exit_policy_url: Some(
|
||||
mainnet::EXIT_POLICY_URL
|
||||
.parse()
|
||||
.expect("invalid default exit policy URL"),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct Debug {
|
||||
/// Defines how often the standard allow list should get updated
|
||||
/// Deprecated
|
||||
#[serde(with = "humantime_serde")]
|
||||
pub standard_list_update_interval: Duration,
|
||||
}
|
||||
|
||||
impl Default for Debug {
|
||||
fn default() -> Self {
|
||||
Debug {
|
||||
standard_list_update_interval: DEFAULT_STANDARD_LIST_UPDATE_INTERVAL,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod v1;
|
||||
pub mod v2;
|
||||
pub mod v3;
|
||||
pub mod v4;
|
||||
pub mod v5;
|
||||
pub mod v6;
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::config::old_config_v1_1_20::ConfigV2;
|
||||
use nym_client_core::config::old_config_v1_1_13::OldConfigV1_1_13 as OldBaseConfigV1_1_13;
|
||||
use nym_config::legacy_helpers::nym_config::MigrationNymConfig;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct OldConfigV1 {
|
||||
#[serde(flatten)]
|
||||
pub base: OldBaseConfigV1_1_13<OldConfigV1>,
|
||||
}
|
||||
|
||||
impl MigrationNymConfig for OldConfigV1 {
|
||||
fn default_root_directory() -> PathBuf {
|
||||
dirs::home_dir()
|
||||
.expect("Failed to evaluate $HOME value")
|
||||
.join(".nym")
|
||||
.join("../../../..")
|
||||
.join("network-requester")
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OldConfigV1> for ConfigV2 {
|
||||
fn from(value: OldConfigV1) -> Self {
|
||||
ConfigV2 {
|
||||
base: value.base.into(),
|
||||
network_requester: Default::default(),
|
||||
network_requester_debug: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user