Add config and basic architecture for QUIC
This commit is contained in:
10
.idea/.gitignore
generated
vendored
Normal file
10
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Ignored default folder with query files
|
||||||
|
/queries/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
4
.idea/encodings.xml
generated
Normal file
4
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
||||||
6
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
6
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/quic_ecs_dt.iml" filepath="$PROJECT_DIR$/.idea/quic_ecs_dt.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/prettier.xml
generated
Normal file
6
.idea/prettier.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="PrettierConfiguration">
|
||||||
|
<option name="myConfigurationMode" value="AUTOMATIC" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
12
.idea/quic_ecs_dt.iml
generated
Normal file
12
.idea/quic_ecs_dt.iml
generated
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="EMPTY_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/simulator/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/substrate/src" isTestSource="false" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
27
Cargo.toml
27
Cargo.toml
@@ -1,3 +1,30 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
members = ["simulator", "substrate"]
|
members = ["simulator", "substrate"]
|
||||||
|
|
||||||
|
# Enable a small amount of optimization in the dev profile.
|
||||||
|
[profile.dev]
|
||||||
|
opt-level = 1
|
||||||
|
|
||||||
|
# Enable a large amount of optimization in the dev profile for dependencies.
|
||||||
|
[profile.dev.package."*"]
|
||||||
|
opt-level = 3
|
||||||
|
|
||||||
|
# Enable more optimization in the release profile at the cost of compile time.
|
||||||
|
[profile.release]
|
||||||
|
# Compile the entire crate as one unit.
|
||||||
|
# Slows compile times, marginal improvements.
|
||||||
|
codegen-units = 1
|
||||||
|
# Do a second optimization pass over the entire program, including dependencies.
|
||||||
|
# Slows compile times, marginal improvements.
|
||||||
|
lto = "thin"
|
||||||
|
|
||||||
|
# Optimize for size in the wasm-release profile to reduce load times and bandwidth usage on web.
|
||||||
|
[profile.wasm-release]
|
||||||
|
# Default to release profile values.
|
||||||
|
inherits = "release"
|
||||||
|
# Optimize with size in mind (also try "z", sometimes it is better).
|
||||||
|
# Slightly slows compile times, great improvements to file size and runtime performance.
|
||||||
|
opt-level = "s"
|
||||||
|
# Strip all debugging information from the binary to slightly reduce file size.
|
||||||
|
strip = "debuginfo"
|
||||||
|
|||||||
@@ -4,3 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
thiserror = "2"
|
||||||
|
anyhow = "1"
|
||||||
|
bevy = "0.18"
|
||||||
|
game_sockets = { git = "https://github.com/VALERE91/game_sockets.git"}
|
||||||
@@ -4,3 +4,13 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bevy = "0.18"
|
||||||
|
thiserror = "2"
|
||||||
|
anyhow = "1"
|
||||||
|
tracing-subscriber = "0.3"
|
||||||
|
quinn = { version = "0.11" }
|
||||||
|
rustls = { version = "0.23" }
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
uuid = { version = "1.23", features = ["v4"] }
|
||||||
|
figment = { version = "0.10", features = ["toml", "env"] }
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
49
substrate/src/config.rs
Normal file
49
substrate/src/config.rs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
use bevy::prelude::Resource;
|
||||||
|
use figment::Figment;
|
||||||
|
use figment::providers::{Env, Format, Serialized, Toml};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Resource, Serialize, Deserialize)]
|
||||||
|
pub struct AppConfig {
|
||||||
|
pub network: QuicConfig,
|
||||||
|
pub simulation: SimulationConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct SimulationConfig {
|
||||||
|
pub tick_rate_hz: u32,
|
||||||
|
pub max_entities: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct QuicConfig {
|
||||||
|
pub server_port: u16,
|
||||||
|
pub server_interface: String,
|
||||||
|
pub server_cert: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AppConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
network : QuicConfig {
|
||||||
|
server_port: 9000,
|
||||||
|
server_interface: "0.0.0.0".to_string(),
|
||||||
|
server_cert: "cert.pem".to_string(),
|
||||||
|
},
|
||||||
|
simulation: SimulationConfig {
|
||||||
|
tick_rate_hz: 60,
|
||||||
|
max_entities: 10000,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppConfig {
|
||||||
|
pub fn load(config_file: &str) -> Result<Self, figment::Error> {
|
||||||
|
Figment::new()
|
||||||
|
.merge(Serialized::defaults(Self::default())) // compiled-in defaults
|
||||||
|
.merge(Toml::file(config_file)) // config file
|
||||||
|
.merge(Env::prefixed("APP_")) // env overrides, e.g. APP_NETWORK__PORT=9000
|
||||||
|
.extract()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,17 @@
|
|||||||
|
mod transport;
|
||||||
|
mod config;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use crate::config::AppConfig;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!");
|
let config = AppConfig::load("config.toml").expect("Failed to load config");
|
||||||
}
|
println!("{:?}", config);
|
||||||
|
|
||||||
|
App::new()
|
||||||
|
.insert_resource(config)
|
||||||
|
.add_plugins(MinimalPlugins)
|
||||||
|
.add_plugins(transport::ecs::EcsQuicTransportPlugin{})
|
||||||
|
.run();
|
||||||
|
}
|
||||||
69
substrate/src/transport/ecs.rs
Normal file
69
substrate/src/transport/ecs.rs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use tokio::sync::mpsc;
|
||||||
|
use crate::config::QuicConfig;
|
||||||
|
use crate::transport::QuicMessage;
|
||||||
|
use crate::transport::server::run_substrate_server;
|
||||||
|
|
||||||
|
const T1_CAPACITY: usize = 1024;
|
||||||
|
const T2_CAPACITY: usize = 512;
|
||||||
|
const T3_CAPACITY: usize = 256;
|
||||||
|
|
||||||
|
pub struct EcsQuicTransportPlugin{}
|
||||||
|
|
||||||
|
#[derive(Resource)]
|
||||||
|
struct BridgeReceivers {
|
||||||
|
t1: Mutex<mpsc::Receiver<QuicMessage>>,
|
||||||
|
t2: Mutex<mpsc::Receiver<QuicMessage>>,
|
||||||
|
t3: Mutex<mpsc::Receiver<QuicMessage>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ingest_system(bridge: Res<BridgeReceivers>){
|
||||||
|
let mut t1 = bridge.t1.lock().unwrap();
|
||||||
|
// Tier 1: drain up to N messages, drop the rest
|
||||||
|
for _ in 0..T1_CAPACITY {
|
||||||
|
match t1.try_recv() {
|
||||||
|
Ok(msg) => { /* write RawSensorData */ }
|
||||||
|
Err(_) => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// T2/T3: drain completely, these are low volume
|
||||||
|
let mut t2 = bridge.t2.lock().unwrap();
|
||||||
|
while let Ok(msg) = t2.try_recv() { /* ... */ }
|
||||||
|
|
||||||
|
let mut t3 = bridge.t3.lock().unwrap();
|
||||||
|
while let Ok(msg) = t3.try_recv() { /* ... */ }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Plugin for EcsQuicTransportPlugin{
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
// Create the channels for multi-thread communication
|
||||||
|
let (t1_tx, t1_rx) =
|
||||||
|
mpsc::channel::<QuicMessage>(T1_CAPACITY);
|
||||||
|
let (t2_tx, t2_rx) =
|
||||||
|
mpsc::channel::<QuicMessage>(T2_CAPACITY);
|
||||||
|
let (t3_tx, t3_rx) =
|
||||||
|
mpsc::channel::<QuicMessage>(T3_CAPACITY);
|
||||||
|
|
||||||
|
let quic_handle = std::thread::spawn(move || {
|
||||||
|
let rt = tokio::runtime::Builder::new_multi_thread()
|
||||||
|
.worker_threads(2)
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
rt.block_on(async move {
|
||||||
|
run_substrate_server(t1_tx, t2_tx, t3_tx).await;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.insert_resource(BridgeReceivers {
|
||||||
|
t1: Mutex::new(t1_rx),
|
||||||
|
t2: Mutex::new(t2_rx),
|
||||||
|
t3: Mutex::new(t3_rx),
|
||||||
|
});
|
||||||
|
|
||||||
|
app.add_systems(PreUpdate, ingest_system);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
substrate/src/transport/mod.rs
Normal file
11
substrate/src/transport/mod.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
pub mod ecs;
|
||||||
|
mod server;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Copy, PartialEq)]
|
||||||
|
pub struct QuicMessage{
|
||||||
|
pub device_id: uuid::Uuid,
|
||||||
|
pub data_stream_id: u16,
|
||||||
|
pub raw_value: f64,
|
||||||
|
pub timestamp_us: u64,
|
||||||
|
pub sequence_number: u32,
|
||||||
|
}
|
||||||
8
substrate/src/transport/server.rs
Normal file
8
substrate/src/transport/server.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use tokio::sync::mpsc::Sender;
|
||||||
|
use crate::transport::QuicMessage;
|
||||||
|
|
||||||
|
pub async fn run_substrate_server(t1_tx: Sender<QuicMessage>,
|
||||||
|
t2_tx: Sender<QuicMessage>,
|
||||||
|
t3_tx: Sender<QuicMessage>) {
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user