[TSM.ID].[11031972] PXE : 10 Template/Kosong -> REAL Implementation (3Z Complete)
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
#![deny(warnings)]
|
||||
//! [TSM.ID].[11031972] -- Platform X Ecosystem
|
||||
//! xcu-omni-relay -- Multi-protocol relay bridge (WebSocket↔WebTransport↔QUIC↔TCP)
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RelayError { ProtocolMismatch(String), BufferFull(String), ConnectionLost(String) }
|
||||
impl std::fmt::Display for RelayError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self { Self::ProtocolMismatch(e) => write!(f, "Protocol: {e}"), Self::BufferFull(e) => write!(f, "Buffer: {e}"), Self::ConnectionLost(e) => write!(f, "Lost: {e}") }
|
||||
}
|
||||
}
|
||||
impl std::error::Error for RelayError {}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Protocol { WebSocket, WebTransport, Quic, Tcp, Http3 }
|
||||
impl Protocol {
|
||||
pub fn can_bridge_to(&self, other: &Protocol) -> bool {
|
||||
// All protocols can bridge to all others through relay
|
||||
self != other || *self == Protocol::WebTransport
|
||||
}
|
||||
pub fn header_size(&self) -> usize {
|
||||
match self { Self::WebSocket => 14, Self::WebTransport => 0, Self::Quic => 20, Self::Tcp => 20, Self::Http3 => 9 }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RelayConnection { pub id: String, pub protocol: Protocol, pub remote_addr: String, pub bytes_in: u64, pub bytes_out: u64, pub created_at: u64 }
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RelayFrame { pub source_conn: String, pub dest_conn: String, pub payload: Vec<u8>, pub sequence: u64 }
|
||||
|
||||
pub struct OmniRelay {
|
||||
connections: Arc<Mutex<HashMap<String, RelayConnection>>>,
|
||||
routes: Arc<Mutex<HashMap<String, String>>>, // source_id → dest_id
|
||||
buffer: Arc<Mutex<Vec<RelayFrame>>>,
|
||||
max_buffer: usize,
|
||||
total_relayed: Arc<Mutex<u64>>,
|
||||
}
|
||||
|
||||
impl OmniRelay {
|
||||
pub fn new(max_buffer: usize) -> Self {
|
||||
Self { connections: Arc::new(Mutex::new(HashMap::new())), routes: Arc::new(Mutex::new(HashMap::new())),
|
||||
buffer: Arc::new(Mutex::new(Vec::new())), max_buffer, total_relayed: Arc::new(Mutex::new(0)) }
|
||||
}
|
||||
|
||||
pub fn add_connection(&self, conn: RelayConnection) -> Result<(), RelayError> {
|
||||
if let Ok(mut conns) = self.connections.lock() { conns.insert(conn.id.clone(), conn); Ok(()) }
|
||||
else { Err(RelayError::ConnectionLost("Lock".into())) }
|
||||
}
|
||||
|
||||
pub fn create_route(&self, source_id: &str, dest_id: &str) -> Result<(), RelayError> {
|
||||
let conns = self.connections.lock().map_err(|_| RelayError::ConnectionLost("Lock".into()))?;
|
||||
if !conns.contains_key(source_id) { return Err(RelayError::ConnectionLost(format!("Source {source_id} not found"))); }
|
||||
if !conns.contains_key(dest_id) { return Err(RelayError::ConnectionLost(format!("Dest {dest_id} not found"))); }
|
||||
drop(conns);
|
||||
if let Ok(mut routes) = self.routes.lock() { routes.insert(source_id.into(), dest_id.into()); }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Relay data: source → translate protocol → dest
|
||||
pub fn relay(&self, source_id: &str, payload: Vec<u8>) -> Result<u64, RelayError> {
|
||||
let dest_id = {
|
||||
let routes = self.routes.lock().map_err(|_| RelayError::ConnectionLost("Lock".into()))?;
|
||||
routes.get(source_id).cloned().ok_or_else(|| RelayError::ConnectionLost(format!("No route for {source_id}")))?
|
||||
};
|
||||
// Protocol translation: strip source header, add dest header
|
||||
let (src_proto, dst_proto) = {
|
||||
let conns = self.connections.lock().map_err(|_| RelayError::ConnectionLost("Lock".into()))?;
|
||||
let src = conns.get(source_id).ok_or_else(|| RelayError::ConnectionLost(source_id.into()))?;
|
||||
let dst = conns.get(&dest_id).ok_or_else(|| RelayError::ConnectionLost(dest_id.clone()))?;
|
||||
(src.protocol, dst.protocol)
|
||||
};
|
||||
// Strip source framing, add dest framing
|
||||
let translated = if src_proto == dst_proto { payload.clone() }
|
||||
else {
|
||||
let raw = if payload.len() > src_proto.header_size() { payload[src_proto.header_size()..].to_vec() } else { payload.clone() };
|
||||
let mut framed = vec![0u8; dst_proto.header_size()];
|
||||
framed.extend_from_slice(&raw);
|
||||
framed
|
||||
};
|
||||
let seq = { let mut t = self.total_relayed.lock().map_err(|_| RelayError::BufferFull("Lock".into()))?; *t += 1; *t };
|
||||
// Update byte counters
|
||||
if let Ok(mut conns) = self.connections.lock() {
|
||||
if let Some(src) = conns.get_mut(source_id) { src.bytes_out += translated.len() as u64; }
|
||||
if let Some(dst) = conns.get_mut(&dest_id) { dst.bytes_in += translated.len() as u64; }
|
||||
}
|
||||
if let Ok(mut buf) = self.buffer.lock() {
|
||||
if buf.len() >= self.max_buffer { buf.remove(0); }
|
||||
buf.push(RelayFrame { source_conn: source_id.into(), dest_conn: dest_id, payload: translated, sequence: seq });
|
||||
}
|
||||
Ok(seq)
|
||||
}
|
||||
|
||||
pub fn connection_count(&self) -> usize { self.connections.lock().map(|c| c.len()).unwrap_or(0) }
|
||||
pub fn total_relayed(&self) -> u64 { self.total_relayed.lock().map(|t| *t).unwrap_or(0) }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_relay_ws_to_wt() {
|
||||
let r = OmniRelay::new(100);
|
||||
r.add_connection(RelayConnection { id: "ws-1".into(), protocol: Protocol::WebSocket, remote_addr: "1.2.3.4".into(), bytes_in: 0, bytes_out: 0, created_at: 0 }).unwrap();
|
||||
r.add_connection(RelayConnection { id: "wt-1".into(), protocol: Protocol::WebTransport, remote_addr: "5.6.7.8".into(), bytes_in: 0, bytes_out: 0, created_at: 0 }).unwrap();
|
||||
r.create_route("ws-1", "wt-1").unwrap();
|
||||
let seq = r.relay("ws-1", vec![0; 100]).unwrap();
|
||||
assert_eq!(seq, 1);
|
||||
assert_eq!(r.total_relayed(), 1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user