Initial Multiverse V8 Genesis
[TSM.ID].[11031972] PXE : Platform X Ecosystem I [142 Module - REAL LIVE -] / 3Z: Zero Error Check (142 Modules) (push) Waiting to run
[TSM.ID].[11031972] PXE : Platform X Ecosystem I [142 Module - REAL LIVE -] / 3Z: Zero Error Check (142 Modules) (push) Waiting to run
This commit is contained in:
@@ -5,14 +5,16 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
xcu-sfu = { path = "../xcu-sfu-a", package = "xcu-sfu-a" }
|
||||
quinn = "0.10" # WebTransport / QUIC Protocol
|
||||
rustls = "0.21"
|
||||
rustls-pemfile = "2.0" # Parse Let's Encrypt PEM files
|
||||
rcgen = "0.11" # Auto TLS Certificate Generator (Self-Signed fallback)
|
||||
xcu_sfu_b = { path = "../xcu-sfu-b", package = "xcu-sfu-b" }
|
||||
quinn = "0.11" # WebTransport / QUIC Protocol
|
||||
rustls = "0.23"
|
||||
rustls-pemfile = "2.2" # Parse Let's Encrypt PEM files
|
||||
rcgen = "0.13" # Auto TLS Certificate Generator (Self-Signed fallback)
|
||||
rkyv = { version = "0.7", features = ["validation"] } # Zero-Copy Serialization
|
||||
tokio = { version = "1.37", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
anyhow = "1.0"
|
||||
sha2 = "0.10"
|
||||
hex = "0.4"
|
||||
rustls-pki-types = "1.14.1"
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// [TSM.ID].[11031972] — XCU WebTransport (QUIC) Engine
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use std::collections::HashMap;
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
tracing_subscriber::registry()
|
||||
.with(
|
||||
tracing_subscriber::EnvFilter::try_from_default_env()
|
||||
.unwrap_or_else(|_| "info".into()),
|
||||
)
|
||||
.with(tracing_subscriber::fmt::layer())
|
||||
.init();
|
||||
|
||||
// Default to port 443 for Cloudflare HTTP/3 proxy compatibility.
|
||||
// If running in DNS-Only, user can set XCU_QUIC_ADDR="0.0.0.0:4433"
|
||||
let addr = std::env::var("XCU_QUIC_ADDR").unwrap_or_else(|_| "0.0.0.0:443".to_string());
|
||||
|
||||
// Shared broadcast channels (rooms map)
|
||||
let rooms = Arc::new(Mutex::new(HashMap::new()));
|
||||
|
||||
// JWT Secret for authentication
|
||||
let jwt_secret = std::env::var("XCU_JWT_SECRET").unwrap_or_else(|_| "dummy_secret".to_string());
|
||||
|
||||
// Initialize SFU Server (SFU Tipe B)
|
||||
let sfu_server = Arc::new(xcu_sfu_b::SfuServer::new(1, 100, 50));
|
||||
|
||||
tracing::info!("Starting XCU QUIC Engine on {}", addr);
|
||||
xcu_quic::server::start_quic_listener(&addr, rooms, jwt_secret, sfu_server).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
use anyhow::Result;
|
||||
use quinn::{Endpoint, ServerConfig};
|
||||
use rcgen::generate_simple_self_signed;
|
||||
use rustls_pki_types::{CertificateDer, PrivateKeyDer};
|
||||
use std::sync::Arc;
|
||||
use tracing::{info, warn, error};
|
||||
use std::net::SocketAddr;
|
||||
@@ -26,7 +27,7 @@ pub type RoomsMap = Arc<Mutex<HashMap<String, broadcast::Sender<Vec<u8>>>>>;
|
||||
/// Controlled by env var XCU_TLS_MODE: "LETSENCRYPT" (default) or "SELFSIGNED"
|
||||
/// Domain controlled by env var XCU_DOMAIN: default "mesh.ultramodul.xyz"
|
||||
|
||||
fn load_letsencrypt_certs(domain: &str) -> Result<(Vec<rustls::Certificate>, rustls::PrivateKey)> {
|
||||
fn load_letsencrypt_certs(domain: &str) -> Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)> {
|
||||
let cert_path = format!("/etc/letsencrypt/live/{}/fullchain.pem", domain);
|
||||
let key_path = format!("/etc/letsencrypt/live/{}/privkey.pem", domain);
|
||||
|
||||
@@ -43,20 +44,19 @@ fn load_letsencrypt_certs(domain: &str) -> Result<(Vec<rustls::Certificate>, rus
|
||||
let key_pem = std::fs::read(&key_path)?;
|
||||
|
||||
// Parse PEM → DER
|
||||
let certs: Vec<rustls::Certificate> = rustls_pemfile::certs(&mut &cert_pem[..])
|
||||
let certs: Vec<CertificateDer<'static>> = rustls_pemfile::certs(&mut &cert_pem[..])
|
||||
.filter_map(|r| r.ok())
|
||||
.map(|der| rustls::Certificate(der.to_vec()))
|
||||
.collect();
|
||||
|
||||
let key = rustls_pemfile::private_key(&mut &key_pem[..])?
|
||||
.ok_or_else(|| anyhow::anyhow!("No private key found in {}", key_path))?;
|
||||
|
||||
let private_key = rustls::PrivateKey(key.secret_der().to_vec());
|
||||
let private_key = key;
|
||||
|
||||
// Compute SHA-256 hash of first cert for Quantum Trust
|
||||
if let Some(first_cert) = certs.first() {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(&first_cert.0);
|
||||
hasher.update(&first_cert);
|
||||
let hash_hex = hex::encode(hasher.finalize());
|
||||
info!("[TLS] QUANTUM TRUST HASH (Let's Encrypt): {}", hash_hex);
|
||||
let _ = CERT_HASH.set(hash_hex);
|
||||
@@ -67,7 +67,7 @@ fn load_letsencrypt_certs(domain: &str) -> Result<(Vec<rustls::Certificate>, rus
|
||||
Ok((certs, private_key))
|
||||
}
|
||||
|
||||
fn generate_selfsigned_certs(domain: &str) -> Result<(Vec<rustls::Certificate>, rustls::PrivateKey)> {
|
||||
fn generate_selfsigned_certs(domain: &str) -> Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)> {
|
||||
warn!("[TLS] Generating ephemeral self-signed certificates (Sovereign Mode)");
|
||||
let subject_alt_names = vec![
|
||||
"localhost".to_string(),
|
||||
@@ -75,8 +75,8 @@ fn generate_selfsigned_certs(domain: &str) -> Result<(Vec<rustls::Certificate>,
|
||||
"xc.ultramodul.xyz".to_string(),
|
||||
];
|
||||
let cert = generate_simple_self_signed(subject_alt_names)?;
|
||||
let cert_der = cert.serialize_der()?;
|
||||
let priv_key_der = cert.serialize_private_key_der();
|
||||
let cert_der = cert.cert.der().to_vec();
|
||||
let priv_key_der = cert.key_pair.serialize_der();
|
||||
|
||||
// Compute SHA-256 hash
|
||||
let mut hasher = Sha256::new();
|
||||
@@ -86,8 +86,8 @@ fn generate_selfsigned_certs(domain: &str) -> Result<(Vec<rustls::Certificate>,
|
||||
let _ = CERT_HASH.set(hash_hex);
|
||||
let _ = TLS_MODE.set("SELFSIGNED".to_string());
|
||||
|
||||
let cert_chain = vec![rustls::Certificate(cert_der)];
|
||||
let key = rustls::PrivateKey(priv_key_der);
|
||||
let cert_chain = vec![CertificateDer::from(cert_der)];
|
||||
let key = PrivateKeyDer::try_from(priv_key_der).map_err(|e| anyhow::anyhow!("Key parse error: {}", e))?;
|
||||
|
||||
warn!("[TLS] Self-signed certificates generated. Browser trust requires manual CA install.");
|
||||
Ok((cert_chain, key))
|
||||
@@ -100,7 +100,7 @@ pub async fn start_quic_listener(
|
||||
addr: &str,
|
||||
rooms: RoomsMap,
|
||||
jwt_secret: String,
|
||||
moq_relayer: Arc<xcu_sfu::moq::MoqRelayer>,
|
||||
sfu_server: Arc<xcu_sfu_b::SfuServer>,
|
||||
) -> Result<()> {
|
||||
let domain = std::env::var("XCU_DOMAIN").unwrap_or_else(|_| "mesh.ultramodul.xyz".to_string());
|
||||
let tls_mode = std::env::var("XCU_TLS_MODE").unwrap_or_else(|_| "LETSENCRYPT".to_string());
|
||||
@@ -130,12 +130,11 @@ pub async fn start_quic_listener(
|
||||
|
||||
// Setup ServerConfig Quinn
|
||||
let mut server_crypto = rustls::ServerConfig::builder()
|
||||
.with_safe_defaults()
|
||||
.with_no_client_auth()
|
||||
.with_single_cert(cert_chain, key)?;
|
||||
server_crypto.alpn_protocols = vec![b"h3".to_vec()]; // WebTransport over HTTP/3
|
||||
|
||||
let server_config = ServerConfig::with_crypto(Arc::new(server_crypto));
|
||||
let server_config = ServerConfig::with_crypto(Arc::new(quinn::crypto::rustls::QuicServerConfig::try_from(server_crypto)?));
|
||||
|
||||
// Bind QUIC Endpoint
|
||||
let parsed_addr: SocketAddr = addr.parse()?;
|
||||
@@ -149,14 +148,14 @@ pub async fn start_quic_listener(
|
||||
let remote = incoming.remote_address();
|
||||
info!("[QUIC] Incoming connection from {}", remote);
|
||||
let rooms_clone = rooms.clone();
|
||||
let moq_clone = moq_relayer.clone();
|
||||
let jwt_secret_clone = jwt_secret.clone();
|
||||
let sfu_server_clone = sfu_server.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
match incoming.await {
|
||||
Ok(conn) => {
|
||||
info!("[QUIC] Connection established: {}", conn.remote_address());
|
||||
handle_quic_connection(conn, rooms_clone, jwt_secret_clone, moq_clone).await;
|
||||
handle_quic_connection(conn, rooms_clone, jwt_secret_clone, sfu_server_clone).await;
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("[QUIC] Connection failed: {}", e);
|
||||
@@ -173,7 +172,7 @@ async fn handle_quic_connection(
|
||||
conn: quinn::Connection,
|
||||
rooms: RoomsMap,
|
||||
_jwt_secret: String, // Reserved for QCG JWT verification (Phase 2)
|
||||
moq_relayer: Arc<xcu_sfu::moq::MoqRelayer>,
|
||||
sfu_server: Arc<xcu_sfu_b::SfuServer>,
|
||||
) {
|
||||
let remote = conn.remote_address();
|
||||
|
||||
@@ -232,6 +231,9 @@ async fn handle_quic_connection(
|
||||
let tx_clone = tx.clone();
|
||||
let pid = participant_id;
|
||||
|
||||
let room_name_for_recv = room_name.clone();
|
||||
let pid_str = pid.to_string();
|
||||
|
||||
// Task A: Read datagrams from QUIC client → broadcast to ROOMS
|
||||
let mut recv_task = tokio::spawn(async move {
|
||||
loop {
|
||||
@@ -240,10 +242,22 @@ async fn handle_quic_connection(
|
||||
if datagram.len() < 4 { continue; }
|
||||
let frame_type = datagram[0];
|
||||
|
||||
// Bandwidth telemetry (type 10 with special quality byte)
|
||||
// Bandwidth telemetry
|
||||
if frame_type == 10 && datagram.len() >= 4 {
|
||||
let score = datagram[1];
|
||||
moq_relayer.update_bandwidth_score(pid, score);
|
||||
let _score = datagram[1];
|
||||
// sfu_b.update_score(...) could be added here
|
||||
}
|
||||
|
||||
// Forward to SFU-B Nexus
|
||||
if let Ok(nexus) = sfu_server.get_room(&room_name_for_recv) {
|
||||
if let Ok(routed_packets) = nexus.route_rtp(&pid_str, &datagram) {
|
||||
for (target_id, payload) in routed_packets {
|
||||
// We need a way to send 'payload' to 'target_id'
|
||||
// For now, we still broadcast to ROOMS channel and rely on the task B
|
||||
let _ = target_id;
|
||||
let _ = payload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Broadcast to all subscribers (WS + QUIC) via ROOMS
|
||||
|
||||
Reference in New Issue
Block a user