From adfc3abd04e6d96d896e4ef16cbbd7710924586c Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Fri, 17 Jan 2025 14:50:24 -0500 Subject: [PATCH] [skip ci] add features --- veilid-core/Cargo.toml | 1 + veilid-core/src/veilid_api/tests/fixtures.rs | 5 + veilid-core/src/veilid_config.rs | 42 ++++++- veilid-server/Cargo.toml | 3 + veilid-server/src/settings.rs | 112 +++++++++++++++++- veilid-tools/Cargo.toml | 6 +- veilid-tools/src/bin/virtual_router/README.md | 27 +++++ 7 files changed, 185 insertions(+), 11 deletions(-) create mode 100644 veilid-tools/src/bin/virtual_router/README.md diff --git a/veilid-core/Cargo.toml b/veilid-core/Cargo.toml index 661e43ff..a89264a0 100644 --- a/veilid-core/Cargo.toml +++ b/veilid-core/Cargo.toml @@ -57,6 +57,7 @@ debug-locks = ["veilid-tools/debug-locks"] unstable-blockstore = [] unstable-tunnels = [] virtual-network = ["veilid-tools/virtual-network"] +virtual-network-server = ["veilid-tools/virtual-network-server"] # GeoIP geolocation = ["maxminddb", "reqwest"] diff --git a/veilid-core/src/veilid_api/tests/fixtures.rs b/veilid-core/src/veilid_api/tests/fixtures.rs index 8ba61d49..a71075d1 100644 --- a/veilid-core/src/veilid_api/tests/fixtures.rs +++ b/veilid-core/src/veilid_api/tests/fixtures.rs @@ -241,6 +241,11 @@ pub fn fix_veilidconfiginner() -> VeilidConfigInner { privacy: VeilidConfigPrivacy { country_code_denylist: vec![CountryCode([b'N', b'Z'])], }, + #[cfg(feature = "virtual-network")] + virtual_network: VeilidConfigVirtualNetwork { + enabled: false, + server_address: "".to_owned(), + }, }, } } diff --git a/veilid-core/src/veilid_config.rs b/veilid-core/src/veilid_config.rs index c8af1986..1a1a454e 100644 --- a/veilid-core/src/veilid_config.rs +++ b/veilid-core/src/veilid_config.rs @@ -188,7 +188,6 @@ impl Default for VeilidConfigTCP { /// #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))] - pub struct VeilidConfigWS { pub connect: bool, pub listen: bool, @@ -234,7 +233,6 @@ impl Default for VeilidConfigWS { /// #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))] - pub struct VeilidConfigWSS { pub connect: bool, pub listen: bool, @@ -267,7 +265,6 @@ impl Default for VeilidConfigWSS { /// #[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))] - pub struct VeilidConfigProtocol { pub udp: VeilidConfigUDP, pub tcp: VeilidConfigTCP, @@ -297,6 +294,21 @@ impl Default for VeilidConfigPrivacy { } } +/// Virtual networking client support for testing/simulation purposes +/// +/// ```yaml +/// virtual_network: +/// enabled: false +/// server_address: "" +/// ``` +#[cfg(feature = "virtual-network")] +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +#[cfg_attr(target_arch = "wasm32", derive(Tsify))] +pub struct VeilidConfigVirtualNetwork { + pub enabled: bool, + pub server_address: String, +} + /// Configure TLS. /// /// ```yaml @@ -323,7 +335,10 @@ impl Default for VeilidConfigTLS { } } -#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), allow(unused_variables))] +#[cfg_attr( + all(target_arch = "wasm32", target_os = "unknown"), + allow(unused_variables) +)] pub fn get_default_ssl_directory( program_name: &str, organization: &str, @@ -527,6 +542,8 @@ pub struct VeilidConfigNetwork { pub protocol: VeilidConfigProtocol, #[cfg(feature = "geolocation")] pub privacy: VeilidConfigPrivacy, + #[cfg(feature = "virtual-network")] + pub virtual_network: VeilidConfigVirtualNetwork, } impl Default for VeilidConfigNetwork { @@ -553,6 +570,8 @@ impl Default for VeilidConfigNetwork { protocol: VeilidConfigProtocol::default(), #[cfg(feature = "geolocation")] privacy: VeilidConfigPrivacy::default(), + #[cfg(feature = "virtual-network")] + virtual_network: VeilidConfigVirtualNetwork::default(), } } } @@ -564,7 +583,10 @@ pub struct VeilidConfigTableStore { pub delete: bool, } -#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), allow(unused_variables))] +#[cfg_attr( + all(target_arch = "wasm32", target_os = "unknown"), + allow(unused_variables) +)] fn get_default_store_path( program_name: &str, organization: &str, @@ -635,7 +657,10 @@ pub struct VeilidConfigCapabilities { #[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema)] #[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), derive(Tsify))] -#[cfg_attr(all(target_arch = "wasm32", target_os = "unknown"), tsify(namespace, from_wasm_abi))] +#[cfg_attr( + all(target_arch = "wasm32", target_os = "unknown"), + tsify(namespace, from_wasm_abi) +)] pub enum VeilidConfigLogLevel { Off, Error, @@ -998,6 +1023,11 @@ impl VeilidConfig { get_config!(inner.network.protocol.wss.url); #[cfg(feature = "geolocation")] get_config!(inner.network.privacy.country_code_denylist); + #[cfg(feature = "virtual-network")] + { + get_config!(inner.network.virtual_network.enabled); + get_config!(inner.network.virtual_network.server_address); + } Ok(()) }) } diff --git a/veilid-server/Cargo.toml b/veilid-server/Cargo.toml index 9dab6247..8322e347 100644 --- a/veilid-server/Cargo.toml +++ b/veilid-server/Cargo.toml @@ -19,6 +19,9 @@ path = "src/main.rs" default = ["rt-tokio", "veilid-core/default", "otlp-tonic"] default-async-std = ["rt-async-std", "veilid-core/default-async-std"] +virtual-network = ["veilid-core/virtual-network"] +virtual-network-server = ["veilid-core/virtual-network-server"] + crypto-test = ["rt-tokio", "veilid-core/crypto-test"] crypto-test-none = ["rt-tokio", "veilid-core/crypto-test-none"] diff --git a/veilid-server/src/settings.rs b/veilid-server/src/settings.rs index 501f74e3..1397daaf 100644 --- a/veilid-server/src/settings.rs +++ b/veilid-server/src/settings.rs @@ -40,6 +40,29 @@ pub fn load_default_config() -> EyreResult { country_code_denylist: [] "#; + #[cfg(not(feature = "virtual-network"))] + let virtual_network_section = ""; + #[cfg(feature = "virtual-network")] + let virtual_network_section = r#" + virtual_network: + enabled: false + server_address: '' + "#; + + #[cfg(not(feature = "virtual-network-server"))] + let virtual_network_server_section = ""; + #[cfg(feature = "virtual-network-server")] + let virtual_network_server_section = r#" + virtual_network_server: + enabled: false + tcp: + listen: true + listen_address: 'localhost:5149' + ws: + listen: true + listen_address: 'localhost:5148' + "#; + let mut default_config = String::from( r#"--- daemon: @@ -84,6 +107,7 @@ logging: enabled: false testing: subnode_index: 0 +%VIRTUAL_NETWORK_SERVER_SECTION% core: capabilities: disable: [] @@ -196,6 +220,7 @@ core: listen_address: ':5150' path: 'ws' # url: '' + %VIRTUAL_NETWORK_SECTION% %PRIVACY_SECTION% "#, ) @@ -227,7 +252,12 @@ core: "%REMOTE_MAX_SUBKEY_CACHE_MEMORY_MB%", &Settings::get_default_remote_max_subkey_cache_memory_mb().to_string(), ) - .replace("%PRIVACY_SECTION%", privacy_section); + .replace("%PRIVACY_SECTION%", privacy_section) + .replace("%VIRTUAL_NETWORK_SECTION%", virtual_network_section) + .replace( + "%VIRTUAL_NETWORK_SERVER_SECTION%", + virtual_network_server_section, + ); let dek_password = if let Some(dek_password) = std::env::var_os("DEK_PASSWORD") { dek_password @@ -679,11 +709,42 @@ pub struct Network { pub protocol: Protocol, #[cfg(feature = "geolocation")] pub privacy: Privacy, + #[cfg(feature = "virtual-network")] + pub virtual_network: VirtualNetwork, +} + +#[cfg(feature = "virtual-network")] +#[derive(Debug, Deserialize, Serialize)] +pub struct VirtualNetwork { + pub enabled: bool, + pub server_address: String, +} + +#[cfg(feature = "virtual-network-server")] +#[derive(Debug, Deserialize, Serialize)] +pub struct VirtualNetworkServer { + pub enabled: bool, + pub tcp: VirtualNetworkServerTcp, + pub ws: VirtualNetworkServerWs, +} +#[cfg(feature = "virtual-network-server")] +#[derive(Debug, Deserialize, Serialize)] +pub struct VirtualNetworkServerTcp { + pub listen: bool, + pub listen_address: NamedSocketAddrs, +} +#[cfg(feature = "virtual-network-server")] +#[derive(Debug, Deserialize, Serialize)] +pub struct VirtualNetworkServerWs { + pub listen: bool, + pub listen_address: NamedSocketAddrs, } #[derive(Debug, Deserialize, Serialize)] pub struct Testing { pub subnode_index: u16, + #[cfg(feature = "virtual-network-server")] + pub virtual_network_server: VirtualNetworkServer, } #[derive(Debug, Deserialize, Serialize)] @@ -1062,6 +1123,20 @@ impl Settings { set_config_value!(inner.logging.perfetto.path, value); set_config_value!(inner.logging.console.enabled, value); set_config_value!(inner.testing.subnode_index, value); + #[cfg(feature = "virtual-network-server")] + { + set_config_value!(inner.testing.virtual_network_server.enabled, value); + set_config_value!(inner.testing.virtual_network_server.tcp.listen, value); + set_config_value!( + inner.testing.virtual_network_server.tcp.listen_address, + value + ); + set_config_value!(inner.testing.virtual_network_server.ws.listen, value); + set_config_value!( + inner.testing.virtual_network_server.ws.listen_address, + value + ); + } set_config_value!(inner.core.capabilities.disable, value); set_config_value!(inner.core.protected_store.allow_insecure_fallback, value); set_config_value!( @@ -1184,6 +1259,12 @@ impl Settings { set_config_value!(inner.core.network.protocol.wss.url, value); #[cfg(feature = "geolocation")] set_config_value!(inner.core.network.privacy.country_code_denylist, value); + #[cfg(feature = "virtual-network")] + { + set_config_value!(inner.core.network.virtual_network.enabled, value); + set_config_value!(inner.core.network.virtual_network.server_address, value); + } + Err(eyre!("settings key '{key}' not found")) } @@ -1572,6 +1653,15 @@ impl Settings { "network.privacy.country_code_denylist" => Ok(Box::new( inner.core.network.privacy.country_code_denylist.clone(), )), + #[cfg(feature = "virtual-network")] + "network.virtual_network.enabled" => { + Ok(Box::new(inner.core.network.virtual_network.enabled)) + } + #[cfg(feature = "virtual-network")] + "network.virtual_network.server_address" => Ok(Box::new( + inner.core.network.virtual_network.server_address.clone(), + )), + _ => Err(VeilidAPIError::generic(format!( "config key '{}' doesn't exist", key @@ -1639,7 +1729,20 @@ mod tests { assert_eq!(s.logging.perfetto.path, ""); assert!(!s.logging.console.enabled); assert_eq!(s.testing.subnode_index, 0); - + #[cfg(feature = "virtual-network-server")] + { + assert_eq!(s.testing.virtual_network_server.enabled, false); + assert_eq!(s.testing.virtual_network_server.tcp.listen, false); + assert_eq!( + s.testing.virtual_network_server.tcp.listen_address, + "localhost:5149" + ); + assert_eq!(s.testing.virtual_network_server.ws.listen, false); + assert_eq!( + s.testing.virtual_network_server.ws.listen_address, + "localhost:5148" + ); + } assert_eq!( s.core.table_store.directory, Settings::get_default_table_store_directory() @@ -1814,5 +1917,10 @@ mod tests { // #[cfg(feature = "geolocation")] assert_eq!(s.core.network.privacy.country_code_denylist, &[]); + #[cfg(feature = "virtual-network")] + { + assert_eq!(s.core.network.virtual_network.enabled, false); + assert_eq!(s.core.network.virtual_network.server_address, ""); + } } } diff --git a/veilid-tools/Cargo.toml b/veilid-tools/Cargo.toml index 9c73b2c2..d2820aec 100644 --- a/veilid-tools/Cargo.toml +++ b/veilid-tools/Cargo.toml @@ -19,7 +19,7 @@ path = "src/lib.rs" [[bin]] name = "virtual_router" path = "src/bin/virtual_router/main.rs" -required-features = ["virtual-router"] +required-features = ["virtual-router-bin"] [features] default = ["rt-tokio", "virtual-network", "virtual-network-server"] @@ -51,7 +51,6 @@ debug-locks = [] virtual-network = [] virtual-network-server = [ "dep:async-tungstenite", - "dep:clap", "dep:indent", "dep:ipnet", "dep:serde_yaml", @@ -59,9 +58,10 @@ virtual-network-server = [ "dep:ws_stream_tungstenite", "dep:rand_chacha", ] -virtual-router = [ +virtual-router-bin = [ "tracing", "virtual-network-server", + "dep:clap", "dep:time", "dep:bugsalot", ] diff --git a/veilid-tools/src/bin/virtual_router/README.md b/veilid-tools/src/bin/virtual_router/README.md new file mode 100644 index 00000000..36105d2e --- /dev/null +++ b/veilid-tools/src/bin/virtual_router/README.md @@ -0,0 +1,27 @@ +# Veilid VirtualRouter + +VirtualRouter is a virtual networking router (`RouterServer`) standalone application built specifically for Veilid applications. + +## RouterServer Concepts + +`RouterServer` is a is a deterministic network simulator with an 'infrastructure as code' language for defining whole 'Internets', in terms of a few primitive components: + +* `Allocation` - sets of IPv4 and IPv6 addresses that are used for a common function. For example, '192.168.0.0/16' is an allocation for IPv4 private addresses. +* `Machine` - an instance storing a single Veilid node's state, including its connection/socket tables, IP addresses and interfaces. +* `Network` - an instance storing a single `Network`'s allocations, to which one or more machines may belong. `Network`s also specify how they are connected together, including to the 'Internet', and how translation and gateway routing is performed. +* `Template` - instructions for creating `Machine`s, along with limits on how many `Machine`s per `Network` can be created, and which `Network`s or `Blueprint`s they are connected to. +* `Blueprint` - instructions for creating `Network`s, along with limits on how many `Network`s can be created. +* `Profiles` - a set of `Machine`s and `Template`s to use when attaching a Veilid application to the RouterServer. + +Applications can connect to VirtualRouter over TCP or WebSockets, see the `--help` for more details. + +Applications can also host a `RouterServer` inside their own process for fully encapsulated simulation and testing, connected via a `flume` channel. + +## Example + +To run VirtualRouter: + +``` +cargo run --bin virtual_router --features=virtual-router-bin +``` +