fix parsing

This commit is contained in:
Christien Rioux 2024-11-16 20:42:44 -05:00
parent a37b91dc37
commit 1349f753b6
8 changed files with 377 additions and 238 deletions

View File

@ -61,7 +61,10 @@ fn main() -> Result<(), String> {
let args = CmdlineArgs::parse();
let router_server = virtual_network::RouterServer::new();
let config =
Config::new(args.config_file).map_err(|e| format!("Error loading config: {}", e))?;
let router_server = virtual_network::RouterServer::new(config);
let _ss_tcp = if !args.no_tcp {
Some(
router_server

View File

@ -57,6 +57,7 @@ pub mod timeout;
pub mod timeout_or;
pub mod timestamp;
pub mod tools;
#[cfg(feature = "virtual-network")]
pub mod virtual_network;
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
pub mod wasm;
@ -249,7 +250,8 @@ pub use timeout_or::*;
pub use timestamp::*;
#[doc(inline)]
pub use tools::*;
#[cfg(feature = "virtual-network")]
pub use virtual_network::*;
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
pub use wasm::*;

View File

@ -124,6 +124,9 @@ pub enum ServerProcessorRequest {
protocol: VirtualProtocolType,
external_port: u16,
},
TXTQuery {
name: String,
},
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
@ -193,6 +196,9 @@ pub enum ServerProcessorReplyValue {
external_port: u16,
},
RemovePort,
TXTQuery {
result: Vec<String>,
},
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]

View File

@ -466,6 +466,15 @@ impl RouterClient {
Ok(())
}
pub async fn txt_query(self, name: String) -> VirtualNetworkResult<Vec<String>> {
let request = ServerProcessorRequest::TXTQuery { name };
let ServerProcessorReplyValue::TXTQuery { result } = self.perform_request(request).await?
else {
return Err(VirtualNetworkError::ResponseMismatch);
};
Ok(result)
}
//////////////////////////////////////////////////////////////////////////
// Private implementation

View File

@ -1,72 +1,32 @@
use super::*;
use ipnet::*;
use serde::*;
use std::ffi::OsStr;
use std::path::Path;
pub use ::config::ConfigError;
fn load_default_config() -> Result<::config::Config, ConfigError> {
let default_config = include_str!("default_config.yml");
::config::Config::builder()
.add_source(::config::File::from_str(
default_config,
::config::FileFormat::Yaml,
))
.build()
}
fn load_config(cfg: ::config::Config, config_file: &Path) -> Result<::config::Config, ConfigError> {
if let Some(config_file_str) = config_file.to_str() {
::config::Config::builder()
.add_source(cfg)
.add_source(::config::File::new(
config_file_str,
::config::FileFormat::Yaml,
))
.build()
} else {
Err(ConfigError::Message(
"config file path is not valid UTF-8".to_owned(),
))
}
}
const fn default_weight() -> f32 {
1.0f32
}
const PREDEFINED_CONFIG: &str = include_str!("predefined_config.yml");
const DEFAULT_CONFIG: &str = include_str!("default_config.yml");
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum WeightedList<T: fmt::Debug + Clone> {
List {
#[serde(flatten)]
value: Vec<Weighted<T>>,
},
Single {
#[serde(flatten)]
value: T,
},
Single(T),
List(Vec<Weighted<T>>),
}
impl<T: fmt::Debug + Clone> Default for WeightedList<T> {
fn default() -> Self {
Self::List(Vec::new())
}
}
#[derive(Debug, Clone, Default, Deserialize)]
pub struct Probability {
#[serde(flatten)]
probability: f32,
}
pub type Probability = f32;
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum Weighted<T: fmt::Debug + Clone> {
Weighted {
item: T,
weight: f32,
},
Unweighted {
#[serde(flatten)]
value: T,
},
Weighted(T, f32),
Unweighted(T),
}
#[derive(Debug, Clone, Deserialize)]
@ -121,7 +81,8 @@ pub enum Location {
#[derive(Debug, Clone, Deserialize)]
pub struct Network {
model: String,
#[serde(default)]
model: Option<String>,
#[serde(default)]
ipv4: Option<NetworkIpv4>,
#[serde(default)]
@ -152,7 +113,8 @@ pub struct NetworkGateway {
#[derive(Debug, Clone, Deserialize)]
pub struct Blueprint {
models: WeightedList<String>,
#[serde(default)]
model: WeightedList<String>,
#[serde(default)]
ipv4: Option<BlueprintIpv4>,
#[serde(default)]
@ -187,7 +149,9 @@ pub struct BlueprintGateway {
#[derive(Debug, Clone, Deserialize)]
pub struct Subnets {
#[serde(default)]
subnet4: Vec<Ipv4Net>,
#[serde(default)]
subnet6: Vec<Ipv6Net>,
}
@ -240,28 +204,65 @@ pub struct Allocation {
pub struct Config {
seed: Option<u32>,
default_network: String,
default_model: String,
#[serde(default)]
profiles: HashMap<String, Profile>,
#[serde(default)]
machines: HashMap<String, Machine>,
#[serde(default)]
templates: HashMap<String, Template>,
#[serde(default)]
networks: HashMap<String, Network>,
blueprint: HashMap<String, Network>,
#[serde(default)]
blueprints: HashMap<String, Blueprint>,
#[serde(default)]
allocations: HashMap<String, Allocation>,
#[serde(default)]
models: HashMap<String, Model>,
}
impl Config {
pub fn new(config_file: Option<&OsStr>) -> Result<Self, ConfigError> {
// Load the default config
let mut cfg = load_default_config()?;
// Merge in the config file if we have one
if let Some(config_file) = config_file {
let config_file_path = Path::new(config_file);
// If the user specifies a config file on the command line then it must exist
cfg = load_config(cfg, config_file_path)?;
}
pub fn new<P: AsRef<Path>>(config_file: Option<P>) -> Result<Self, ConfigError> {
let cfg = load_config(config_file)?;
// Generate config
cfg.try_deserialize()
}
}
fn load_default_config() -> Result<::config::Config, ConfigError> {
::config::Config::builder()
.add_source(::config::File::from_str(
PREDEFINED_CONFIG,
::config::FileFormat::Yaml,
))
.add_source(::config::File::from_str(
DEFAULT_CONFIG,
::config::FileFormat::Yaml,
))
.build()
}
fn load_config<P: AsRef<Path>>(
opt_config_file: Option<P>,
) -> Result<::config::Config, ConfigError> {
let Some(config_file) = opt_config_file else {
return load_default_config();
};
let config_path = config_file.as_ref();
let Some(config_file_str) = config_path.to_str() else {
return Err(ConfigError::Message(
"config file path is not valid UTF-8".to_owned(),
));
};
::config::Config::builder()
.add_source(::config::File::from_str(
PREDEFINED_CONFIG,
::config::FileFormat::Yaml,
))
.add_source(::config::File::new(
config_file_str,
::config::FileFormat::Yaml,
))
.build()
}

View File

@ -4,11 +4,15 @@
# line to choose a different test scenario. The same seed will
# generate the same configuration on all machines given the same
# configuration file.
seed: 0
# seed: 0
# The name of the predefined network to use by default (typically
# this is '$internet')
default_network: "$internet"
# default_network: "$internet"
# The name of the predefined performance model to use by default (typically
# this is '$lan')
# default_model: "$lan"
#################################################################
# Profiles
@ -18,22 +22,22 @@ default_network: "$internet"
# the VirtualRouter
profiles:
- bootstrap:
instances:
# two bootstrap machines
- machine: "bootstrap-1.veilid.net"
- machine: "bootstrap-2.veilid.net"
# pool of up to 4 relay-capable servers
- template: "bootrelay"
bootstrap:
instances:
# two bootstrap machines
- machine: "bootstrap-1.veilid.net"
- machine: "bootstrap-2.veilid.net"
# pool of up to 4 relay-capable servers
- template: "bootrelay"
# geographically disperse servers of various configurations
- server:
instances:
- template:
- "relayserver"
- "ipv4server"
- "ipv6server"
- "nat4home"
- "nat4+6home"
server:
instances:
- template:
- "relayserver"
- "ipv4server"
- "ipv6server"
- "nat4home"
- "nat4+6home"
#################################################################
# Machines
@ -42,20 +46,20 @@ profiles:
# can only be allocated one time
machines:
- bootstrap-1.veilid.net:
network: "boot"
address4: "170.64.128.16"
address6: "2a03:b0c0:2:dd::ddd:0010"
disable_capabilities:
["ROUT", "TUNL", "SGNL", "RLAY", "DIAL", "DHTV", "DHTW", "APPM"]
bootstrap: true
- bootstrap-2.veilid.net:
network: "boot"
address4: "170.64.128.17"
address6: "2a03:b0c0:2:dd::ddd:0011"
disable_capabilities:
["ROUT", "TUNL", "SGNL", "RLAY", "DIAL", "DHTV", "DHTW", "APPM"]
bootstrap: true
bootstrap-1.veilid.net:
network: "boot"
address4: "170.64.128.16"
address6: "2a03:b0c0:2:dd::ddd:0010"
disable_capabilities:
["ROUT", "TUNL", "SGNL", "RLAY", "DIAL", "DHTV", "DHTW", "APPM"]
bootstrap: true
bootstrap-2.veilid.net:
network: "boot"
address4: "170.64.128.17"
address6: "2a03:b0c0:2:dd::ddd:0011"
disable_capabilities:
["ROUT", "TUNL", "SGNL", "RLAY", "DIAL", "DHTV", "DHTW", "APPM"]
bootstrap: true
#################################################################
# Templates
@ -70,43 +74,46 @@ templates:
# - will have no capabilities disabled
# - will not use NAT, and be directly connected
# - limited to 4 machines
- bootrelay:
network: "boot"
machine_count: 4
bootrelay:
network: "boot"
machine_count: 4
# Servers on subnets within the 'internet' network
- relayserver:
blueprint: "direct"
machine_count: [1, 2, 3]
- ipv4server:
blueprint: "direct_ipv4_no_ipv6"
machine_count: [1, 2, 3]
- ipv6server:
blueprint: "direct_ipv6_no_ipv4"
machine_count: [1, 2, 3]
- nat4home:
blueprint: "nat_ipv4_no_ipv6"
machine_count: [1, 2, 3]
- nat4+6home:
blueprint: "nat_ipv4_direct_ipv6"
machine_count: [1, 2, 3]
relayserver:
blueprint: "direct"
machine_count: [1, 2, 3]
ipv4server:
blueprint: "direct_ipv4_no_ipv6"
machine_count: [1, 2, 3]
ipv6server:
blueprint: "direct_ipv6_no_ipv4"
machine_count: [1, 2, 3]
nat4home:
blueprint: "nat_ipv4_no_ipv6"
machine_count: [1, 2, 3]
nat4+6home:
blueprint: "nat_ipv4_direct_ipv6"
machine_count: [1, 2, 3]
#################################################################
# Networks
#
# Networks are
# Networks are a location where Machines can be allocated and represent
# a network segment with address allocations per address type
# and a gateway to another network. The performance characteristics of
# a network are defined by a performance Model
networks:
# Custom networks
- boot:
model: "$lan"
ipv4:
allocation: "boot"
ipv6:
allocation: "boot"
boot:
ipv4:
allocation: "boot"
ipv6:
allocation: "boot"
# Predefined networks
- $internet:
model: "$internet"
# # Predefined networks
# $internet:
# allocation: "$internet"
# model: "$internet"
#################################################################
# Blueprints
@ -116,43 +123,38 @@ networks:
blueprints:
# A subnet of the internet directly attached with no translation
# with both ipv4 and ipv6 networking
- direct:
models: "$lan"
ipv4:
prefix: 24
ipv6:
prefix: 64
direct:
ipv4:
prefix: 24
ipv6:
prefix: 64
# An ipv4-only subnet of the internet directly attached with no translation
- direct_ipv4_no_ipv6:
models: "$lan"
ipv4:
prefix: 24
direct_ipv4_no_ipv6:
ipv4:
prefix: 24
# An ipv6-only subnet of the internet directly attached with no translation
- direct_ipv6_no_ipv4:
models: "$lan"
ipv6:
prefix: 64
direct_ipv6_no_ipv4:
ipv6:
prefix: 64
# An ipv4-only subnet of the internet attached via NAT
- nat_ipv4_no_ipv6:
models: "$lan"
ipv4:
allocation: "$private"
prefix: 0
gateway:
translation: "PortRestricted"
upnp: 0.25
nat_ipv4_no_ipv6:
ipv4:
allocation: "$private"
prefix: 0
gateway:
translation: "port_restricted"
upnp: 0.25
# An ipv4 subnet of the internet attached via NAT and
# an ipv6 subnet of the internet directly attached with no translation
- nat_ipv4_direct_ipv6:
models: "$lan"
ipv4:
allocation: "$private"
prefix: 0
gateway:
translation: "PortRestricted"
upnp: 0.25
ipv6:
prefix: 56
nat_ipv4_direct_ipv6:
ipv4:
allocation: "$private"
prefix: 0
gateway:
translation: "port_restricted"
upnp: 0.25
ipv6:
prefix: 56
#################################################################
# Allocations
@ -165,58 +167,57 @@ blueprints:
allocations:
# Custom network allocations
- boot:
subnet4: ["170.64.128.0/24"]
subnet6: ["2a03:b0c0:2::/48"]
# Predefined networks
- $private:
subnet4: ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
subnet6: ["fc00::/7"]
- $cgnat:
subnet4: ["100.64.0.0/10"]
- $linklocal:
subnet4: ["169.254.0.0/16"]
subnet6: ["fe80::/10"]
- $localhost:
subnet4: ["127.0.0.0/8"]
subnet6: ["::1/128"]
- $ietf:
subnet4: ["192.0.0.0/24"]
- $cellnat:
subnet4: ["192.0.0.0/29"]
- $documentation:
subnet4: ["192.0.2.0/24", "198.51.100.0/24", "203.0.113.0/24"]
subnet6: ["2001:db8::/32", "3fff::/20"]
- $benchmark:
subnet4: ["198.18.0.0/15"]
- $mulitcast:
subnet4: ["224.0.0.0/4"]
- $mulitcasttest:
subnet4: ["233.252.0.0/24"]
subnet6: ["ff00::/8"]
- $unspecified:
subnet4: ["0.0.0.0/8"]
subnet6: ["::/128"]
- $reserved:
subnet4: ["192.88.99.0/24", "240.0.0.0/4"]
- $broadcast:
subnet4: ["255.255.255.255/32"]
- $mapped:
subnet6: ["::ffff:0:0/96", "::ffff:0:0:0/96"]
- $translation:
subnet6: ["64:ff9b::/96", "64:ff9b:1::/48"]
- $discard:
subnet6: ["100::/64"]
- $teredo:
subnet6: ["2001::/32"]
- $orchidv2:
subnet6: ["2001:20::/28"]
- $6to4:
subnet6: ["2002::/16"]
- $srv6:
subnet6: ["5f00::/16"]
boot:
subnet4: ["170.64.128.0/24"]
subnet6: ["2a03:b0c0:2::/48"]
# # Predefined networks
# $internet: {}
# $private:
# subnet4: ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
# subnet6: ["fc00::/7"]
# $cgnat:
# subnet4: ["100.64.0.0/10"]
# $linklocal:
# subnet4: ["169.254.0.0/16"]
# subnet6: ["fe80::/10"]
# $localhost:
# subnet4: ["127.0.0.0/8"]
# subnet6: ["::1/128"]
# $ietf:
# subnet4: ["192.0.0.0/24"]
# $cellnat:
# subnet4: ["192.0.0.0/29"]
# $documentation:
# subnet4: ["192.0.2.0/24", "198.51.100.0/24", "203.0.113.0/24"]
# subnet6: ["2001:db8::/32", "3fff::/20"]
# $benchmark:
# subnet4: ["198.18.0.0/15"]
# $mulitcast:
# subnet4: ["224.0.0.0/4"]
# $mulitcasttest:
# subnet4: ["233.252.0.0/24"]
# subnet6: ["ff00::/8"]
# $unspecified:
# subnet4: ["0.0.0.0/8"]
# subnet6: ["::/128"]
# $reserved:
# subnet4: ["192.88.99.0/24", "240.0.0.0/4"]
# $broadcast:
# subnet4: ["255.255.255.255/32"]
# $mapped:
# subnet6: ["::ffff:0:0/96", "::ffff:0:0:0/96"]
# $translation:
# subnet6: ["64:ff9b::/96", "64:ff9b:1::/48"]
# $discard:
# subnet6: ["100::/64"]
# $teredo:
# subnet6: ["2001::/32"]
# $orchidv2:
# subnet6: ["2001:20::/28"]
# $6to4:
# subnet6: ["2002::/16"]
# $srv6:
# subnet6: ["5f00::/16"]
#################################################################
# Models
#
@ -225,24 +226,24 @@ allocations:
# Distance is assigned over a circular probability and then
# mapped linearly as a multiplier to latency and loss
models:
# Predefined models
$lan:
latency:
mean: 0.0038
sigma: 0.001416
skew: 0.0009
min: 0.0015
max: 0.0075
loss: 0.0
$internet:
distance:
min: 0.04
max: 2.0
latency:
mean: 0.200
sigma: 0.080
skew: 0
min: 0.030
max: 0.400
loss: 0.01
# models:
# # Predefined models
# $lan:
# latency:
# mean: 0.0038
# sigma: 0.001416
# skew: 0.0009
# min: 0.0015
# max: 0.0075
# loss: 0.0
# $internet:
# distance:
# min: 0.04
# max: 2.0
# latency:
# mean: 0.200
# sigma: 0.080
# skew: 0
# min: 0.030
# max: 0.400
# loss: 0.01

View File

@ -1,5 +1,7 @@
mod config;
pub use config::*;
use super::*;
use async_tungstenite::accept_async;
use futures_codec::{Bytes, BytesCodec, FramedRead, FramedWrite};
@ -29,6 +31,7 @@ enum RunLoopEvent {
#[derive(Debug)]
struct RouterServerUnlockedInner {
config: Config,
new_client_sender: flume::Sender<SendPinBoxFuture<RunLoopEvent>>,
new_client_receiver: flume::Receiver<SendPinBoxFuture<RunLoopEvent>>,
}
@ -54,12 +57,13 @@ impl RouterServer {
// Public Interface
/// Create a router server for virtual networking
pub fn new() -> Self {
pub fn new(config: Config) -> Self {
// Make a channel to receive new clients
let (new_client_sender, new_client_receiver) = flume::unbounded();
Self {
unlocked_inner: Arc::new(RouterServerUnlockedInner {
config,
new_client_sender,
new_client_receiver,
}),
@ -416,12 +420,7 @@ impl RouterServer {
protocol,
external_port,
} => todo!(),
ServerProcessorRequest::TXTQuery { name } => todo!(),
}
}
}
impl Default for RouterServer {
fn default() -> Self {
Self::new()
}
}

View File

@ -0,0 +1,118 @@
---
# Random number seed used to generate all profile configurations
# for a test. The seed can be overriden on the VirtualRouter command
# line to choose a different test scenario. The same seed will
# generate the same configuration on all machines given the same
# configuration file.
seed: 0
# The name of the predefined network to use by default (typically
# this is '$internet')
default_network: "$internet"
# The name of the predefined performance model to use by default (typically
# this is '$')
default_model: "$lan"
#################################################################
# Networks
#
# Networks are a location where Machines can be allocated and represent
# a network segment with address allocations per address type
# and a gateway to another network. The performance characteristics of
# a network are defined by a performance Model
networks:
# Predefined networks
$internet:
allocation: "$internet"
model: "$internet"
#################################################################
# Allocations
#
# Allocations are partitions of the address space that networks
# can be assigned to. Machines on the networks will be given
# addresses within these ranges. If an allocation
# is not specified, an address -outside- any of the allocation
# will be used (on the 'public internet').
allocations:
# Predefined networks
$internet: {}
$private:
subnet4: ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
subnet6: ["fc00::/7"]
$cgnat:
subnet4: ["100.64.0.0/10"]
$linklocal:
subnet4: ["169.254.0.0/16"]
subnet6: ["fe80::/10"]
$localhost:
subnet4: ["127.0.0.0/8"]
subnet6: ["::1/128"]
$ietf:
subnet4: ["192.0.0.0/24"]
$cellnat:
subnet4: ["192.0.0.0/29"]
$documentation:
subnet4: ["192.0.2.0/24", "198.51.100.0/24", "203.0.113.0/24"]
subnet6: ["2001:db8::/32", "3fff::/20"]
$benchmark:
subnet4: ["198.18.0.0/15"]
$mulitcast:
subnet4: ["224.0.0.0/4"]
$mulitcasttest:
subnet4: ["233.252.0.0/24"]
subnet6: ["ff00::/8"]
$unspecified:
subnet4: ["0.0.0.0/8"]
subnet6: ["::/128"]
$reserved:
subnet4: ["192.88.99.0/24", "240.0.0.0/4"]
$broadcast:
subnet4: ["255.255.255.255/32"]
$mapped:
subnet6: ["::ffff:0:0/96", "::ffff:0:0:0/96"]
$translation:
subnet6: ["64:ff9b::/96", "64:ff9b:1::/48"]
$discard:
subnet6: ["100::/64"]
$teredo:
subnet6: ["2001::/32"]
$orchidv2:
subnet6: ["2001:20::/28"]
$6to4:
subnet6: ["2002::/16"]
$srv6:
subnet6: ["5f00::/16"]
#################################################################
# Models
#
# Performance models representing how a network behaves
# Latency models are a skewed normal distribution
# Distance is assigned over a circular probability and then
# mapped linearly as a multiplier to latency and loss
models:
# Predefined models
$lan:
latency:
mean: 0.0038
sigma: 0.001416
skew: 0.0009
min: 0.0015
max: 0.0075
loss: 0.0
$internet:
distance:
min: 0.04
max: 2.0
latency:
mean: 0.200
sigma: 0.080
skew: 0
min: 0.030
max: 0.400
loss: 0.01