[WIP] WTransport

This commit is contained in:
Alex Emmet 2026-03-04 17:12:22 +01:00
commit f379a0c015
3 changed files with 31 additions and 49 deletions

11
Cargo.lock generated
View file

@ -1171,7 +1171,7 @@ dependencies = [
[[package]] [[package]]
name = "epsilon-core" name = "epsilon-core"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/Tensamin/Epsilon.git#4bdd32b44a77ac980cede20a1d401004f52e4a29" source = "git+https://github.com/Tensamin/Epsilon.git#fb490bac71a652ecd705875baab910b753430164"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"quinn", "quinn",
@ -1183,7 +1183,7 @@ dependencies = [
[[package]] [[package]]
name = "epsilon-native" name = "epsilon-native"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/Tensamin/Epsilon.git#4bdd32b44a77ac980cede20a1d401004f52e4a29" source = "git+https://github.com/Tensamin/Epsilon.git#fb490bac71a652ecd705875baab910b753430164"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -1196,6 +1196,7 @@ dependencies = [
"thiserror 2.0.18", "thiserror 2.0.18",
"tokio", "tokio",
"wtransport", "wtransport",
"wtransport-proto",
] ]
[[package]] [[package]]
@ -2752,9 +2753,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.44" version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -2842,6 +2843,7 @@ version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10b99e0098aa4082912d4c649628623db6aba77335e4f4569ff5083a6448b32e" checksum = "10b99e0098aa4082912d4c649628623db6aba77335e4f4569ff5083a6448b32e"
dependencies = [ dependencies = [
"aws-lc-rs",
"pem", "pem",
"ring", "ring",
"rustls-pki-types", "rustls-pki-types",
@ -4921,6 +4923,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202"
dependencies = [ dependencies = [
"asn1-rs", "asn1-rs",
"aws-lc-rs",
"data-encoding", "data-encoding",
"der-parser", "der-parser",
"lazy_static", "lazy_static",

View file

@ -7,9 +7,11 @@ use crate::sql::sql::initialize_db;
use crate::sql::sql::print_users; use crate::sql::sql::print_users;
use crate::util::crypto_helper::load_public_key; use crate::util::crypto_helper::load_public_key;
use crate::util::crypto_helper::load_secret_key; use crate::util::crypto_helper::load_secret_key;
use crate::util::logger::PrintType;
use crate::util::logger::startup; use crate::util::logger::startup;
use dotenv::dotenv; use dotenv::dotenv;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use rustls::crypto::aws_lc_rs::default_provider;
use std::env; use std::env;
static PRIVATE_KEY: Lazy<String> = Lazy::new(|| env::var("PRIVATE_KEY").unwrap()); static PRIVATE_KEY: Lazy<String> = Lazy::new(|| env::var("PRIVATE_KEY").unwrap());
@ -23,13 +25,20 @@ pub fn get_public_key() -> x448::PublicKey {
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
if let Err(_) = default_provider().install_default() {
println!("Error loading Provider");
return;
}
dotenv().ok(); dotenv().ok();
startup(); startup();
log_in!("Incoming messages"); log_in!("Incoming messages");
log_out!("Outgoing messages"); log_out!("Outgoing messages");
tokio::spawn(async move { tokio::spawn(async move {
let _ = omikron_connection::start(9187).await; match omikron_connection::start(9187).await {
Err(e) => log_err!(0, PrintType::General, "{:?}", e),
_ => {}
}
}); });
log!("Started"); log!("Started");

View file

@ -6,22 +6,14 @@ use crate::{
sql::{self, get_by_user_id, get_by_username, get_iota_by_id, get_omikron_by_id}, sql::{self, get_by_user_id, get_by_username, get_iota_by_id, get_omikron_by_id},
user_online_tracker::{self}, user_online_tracker::{self},
}, },
util::{ util::{crypto_helper::encrypt, file_util::load_file_vec, logger::PrintType},
crypto_helper::encrypt,
file_util::{load_file_buf, load_file_vec},
logger::PrintType,
},
}; };
use base64::{Engine as _, engine::general_purpose::STANDARD}; use base64::{Engine as _, engine::general_purpose::STANDARD};
use dashmap::DashMap; use dashmap::DashMap;
use epsilon_core::{CommunicationType, CommunicationValue, DataTypes, DataValue}; use epsilon_core::{CommunicationType, CommunicationValue, DataTypes, DataValue};
use epsilon_native::{Host, Receiver, Sender}; use epsilon_native::{Host, Receiver, Sender};
use quinn::crypto::rustls::QuicServerConfig;
use quinn::{Endpoint, ServerConfig};
use rand::{Rng, distributions::Alphanumeric}; use rand::{Rng, distributions::Alphanumeric};
use rustls::{ServerConfig as CryptoConfig, crypto::aws_lc_rs};
use std::{ use std::{
net::SocketAddr,
sync::Arc, sync::Arc,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
@ -152,7 +144,7 @@ impl OmikronConnection {
// Main Handler Loop // Main Handler Loop
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
pub async fn handle(self: Arc<Self>, mut receiver: Receiver) { pub async fn handle(self: Arc<Self>, receiver: Receiver) {
log_in!( log_in!(
self.id as i64, self.id as i64,
PrintType::Omega, PrintType::Omega,
@ -227,7 +219,8 @@ impl OmikronConnection {
async fn handle_unauthenticated(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> { async fn handle_unauthenticated(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> {
if !cv.is_type(CommunicationType::identification) { if !cv.is_type(CommunicationType::identification) {
self.send_error_response(cv.get_id(), CommunicationType::error_not_authenticated) let _ = self
.send_error_response(cv.get_id(), CommunicationType::error_not_authenticated)
.await; .await;
return Err(OmikronError::NotAuthenticated); return Err(OmikronError::NotAuthenticated);
} }
@ -280,7 +273,8 @@ impl OmikronConnection {
async fn handle_identified(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> { async fn handle_identified(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> {
if !cv.is_type(CommunicationType::challenge_response) { if !cv.is_type(CommunicationType::challenge_response) {
self.send_error_response(cv.get_id(), CommunicationType::error_not_authenticated) let _ = self
.send_error_response(cv.get_id(), CommunicationType::error_not_authenticated)
.await; .await;
return Err(OmikronError::NotAuthenticated); return Err(OmikronError::NotAuthenticated);
} }
@ -306,7 +300,8 @@ impl OmikronConnection {
log_in!(omikron_id, PrintType::Omega, "Omikron authenticated"); log_in!(omikron_id, PrintType::Omega, "Omikron authenticated");
Ok(()) Ok(())
} else { } else {
self.send_error_response(cv.get_id(), CommunicationType::error_invalid_challenge) let _ = self
.send_error_response(cv.get_id(), CommunicationType::error_invalid_challenge)
.await; .await;
Err(OmikronError::AuthenticationFailed) Err(OmikronError::AuthenticationFailed)
} }
@ -1087,12 +1082,6 @@ impl OmikronConnection {
} }
} }
fn arc_self(self: Arc<Self>) -> Arc<Self> {
// This is a bit of a hack - in practice you'd store the Arc in the struct
// or use weak references. For now, we rely on the caller having the Arc.
panic!("Use the Arc<OmikronConnection> directly")
}
// Public API for external use // Public API for external use
pub async fn is_authenticated(self: Arc<Self>) -> bool { pub async fn is_authenticated(self: Arc<Self>) -> bool {
self.state.read().await.is_authenticated() self.state.read().await.is_authenticated()
@ -1112,13 +1101,13 @@ impl OmikronConnection {
// ============================================================================ // ============================================================================
pub async fn start(port: u16) -> Result<(), Box<dyn std::error::Error>> { pub async fn start(port: u16) -> Result<(), Box<dyn std::error::Error>> {
let _ = aws_lc_rs::default_provider().install_default(); let cert_pem = load_file_vec("certs", "cert.pem")
.map_err(|e| format!("Failed to load certificate: {}", e))?;
let key_pem = load_file_vec("certs", "key.pem")
.map_err(|e| format!("Failed to load private key: {}", e))?;
let tls_cfg = load_tls().expect("TLS config failed"); log!("OmikronServer starting on port {}", port);
let server_crypto = quinn::crypto::rustls::QuicServerConfig::try_from(tls_cfg)?; let mut host: Host = epsilon_native::host(port, cert_pem, key_pem).await?;
let server_cfg = ServerConfig::with_crypto(Arc::new(server_crypto));
let mut host: Host = epsilon_native::host(port, server_cfg).await?;
log!("OmikronServer listening on port {}", port); log!("OmikronServer listening on port {}", port);
while let Some((sender, receiver)) = host.next().await { while let Some((sender, receiver)) = host.next().await {
@ -1130,22 +1119,3 @@ pub async fn start(port: u16) -> Result<(), Box<dyn std::error::Error>> {
Ok(()) Ok(())
} }
fn load_tls() -> Option<CryptoConfig> {
let _ = aws_lc_rs::default_provider().install_default();
let mut cert_pem = load_file_buf("certs", "cert.pem").ok()?;
let cert_chain = rustls_pemfile::certs(&mut cert_pem)
.collect::<Result<Vec<_>, _>>()
.ok()?;
let key_pem = load_file_vec("certs", "key.pem").ok()?;
let key_der = rustls_pemfile::private_key(&mut &*key_pem).ok()??;
let cfg = CryptoConfig::builder()
.with_no_client_auth()
.with_single_cert(cert_chain, key_der)
.ok()?;
Some(cfg)
}