677 lines
20 KiB
Markdown
677 lines
20 KiB
Markdown
# QUIC Multi-Stream Integration Strategy
|
|
|
|
## Executive Summary
|
|
|
|
This document outlines the integration of QUIC (Quick UDP Internet Connections) multi-stream support into the Lean Agentic Learning System, with full compatibility for both native Rust and WebAssembly (WASM) targets using WebTransport.
|
|
|
|
## Research Background
|
|
|
|
### QUIC Protocol
|
|
|
|
**Definition**: QUIC is a modern transport protocol built on UDP that provides multiplexed streams, 0-RTT handshakes, and built-in encryption [1].
|
|
|
|
**Key Features**:
|
|
|
|
1. **Multiplexed Streams** [2]: Multiple independent streams over single connection
|
|
- No head-of-line blocking
|
|
- Stream-level flow control
|
|
- Bidirectional and unidirectional streams
|
|
|
|
2. **0-RTT Connection Establishment** [3]: Resume connections without handshake
|
|
- Reduced latency for repeat connections
|
|
- Cached connection state
|
|
|
|
3. **Built-in Security** [4]: TLS 1.3 integrated
|
|
- Encrypted by default
|
|
- Forward secrecy
|
|
- Connection migration
|
|
|
|
4. **Improved Loss Recovery** [5]: Better than TCP
|
|
- More accurate RTT estimation
|
|
- Pluggable congestion control
|
|
- Less bufferbloat
|
|
|
|
### WebTransport
|
|
|
|
**Definition**: WebTransport is the browser API for QUIC, enabling low-latency bidirectional communication [6].
|
|
|
|
**Advantages for WASM**:
|
|
- Works in browsers (HTTP/3)
|
|
- Multiple streams over single connection
|
|
- Unreliable datagrams for real-time data
|
|
- Better than WebSocket for many use cases
|
|
|
|
### References
|
|
|
|
[1] Iyengar, J., & Thomson, M. (2021). "QUIC: A UDP-Based Multiplexed and Secure Transport." RFC 9000.
|
|
|
|
[2] Bishop, M. (2021). "HTTP/3." RFC 9114.
|
|
|
|
[3] Thomson, M., & Turner, S. (2021). "Using TLS to Secure QUIC." RFC 9001.
|
|
|
|
[4] Kühlewind, M., & Trammell, B. (2021). "Applicability of the QUIC Transport Protocol." RFC 9308.
|
|
|
|
[5] Ware, R., et al. (2019). "QUIC Loss Detection and Congestion Control." draft-ietf-quic-recovery.
|
|
|
|
[6] W3C WebTransport Working Group. (2023). "WebTransport." W3C Candidate Recommendation.
|
|
|
|
## Integration Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ QUIC Multi-Stream Architecture │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌────────────────────────────────────────────────┐ │
|
|
│ │ Native (quinn-based) │ WASM (WebTransport) │ │
|
|
│ ├────────────────────────┼────────────────────────┤ │
|
|
│ │ │ │ │
|
|
│ │ ┌──────────────┐ │ ┌──────────────┐ │ │
|
|
│ │ │ quinn:: │ │ │ web_transport│ │ │
|
|
│ │ │ Connection │ │ │ ::Session │ │ │
|
|
│ │ └──────┬───────┘ │ └──────┬───────┘ │ │
|
|
│ │ │ │ │ │ │
|
|
│ │ ▼ │ ▼ │ │
|
|
│ │ ┌──────────────┐ │ ┌──────────────┐ │ │
|
|
│ │ │ Multiplexed │ │ │ Multiplexed │ │ │
|
|
│ │ │ Streams │ │ │ Streams │ │ │
|
|
│ │ └──────┬───────┘ │ └──────┬───────┘ │ │
|
|
│ └─────────┼─────────────┴─────────┼──────────────┘ │
|
|
│ │ │ │
|
|
│ └────────────┬───────────┘ │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ ┌──────────────────┐ │
|
|
│ │ Unified Stream │ │
|
|
│ │ Abstraction │ │
|
|
│ └────────┬─────────┘ │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ ┌──────────────────┐ │
|
|
│ │ Lean Agentic │ │
|
|
│ │ Learning System │ │
|
|
│ └──────────────────┘ │
|
|
│ │
|
|
└──────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Use Cases
|
|
|
|
### 1. Ultra-Low-Latency Streaming
|
|
|
|
**Problem**: Need minimal latency for real-time agent-to-agent communication.
|
|
|
|
**Solution**: Use QUIC's 0-RTT and multiplexed streams.
|
|
|
|
**Implementation**:
|
|
```rust
|
|
// Native
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
let connection = QuicConnection::connect("agent2.example.com:4433").await?;
|
|
|
|
// WASM
|
|
#[cfg(target_arch = "wasm32")]
|
|
let connection = QuicConnection::connect("https://agent2.example.com").await?;
|
|
|
|
// Open multiple streams for different data types
|
|
let control_stream = connection.open_bi_stream().await?;
|
|
let data_stream = connection.open_uni_stream().await?;
|
|
let metrics_stream = connection.open_uni_stream().await?;
|
|
|
|
// Send concurrently without head-of-line blocking
|
|
tokio::join!(
|
|
send_control_messages(&control_stream),
|
|
send_training_data(&data_stream),
|
|
send_metrics(&metrics_stream),
|
|
);
|
|
```
|
|
|
|
### 2. Browser-Based Agentic UI
|
|
|
|
**Problem**: Run agentic learning system in browser with server coordination.
|
|
|
|
**Solution**: Use WebTransport from WASM to connect to native server.
|
|
|
|
**Implementation**:
|
|
```rust
|
|
// Server (native Rust)
|
|
let server = QuicServer::bind("0.0.0.0:4433").await?;
|
|
|
|
while let Some(connection) = server.accept().await {
|
|
tokio::spawn(handle_client(connection));
|
|
}
|
|
|
|
// Browser (WASM)
|
|
let session = WebTransportSession::connect("https://server.example.com").await?;
|
|
let stream = session.open_bi_stream().await?;
|
|
|
|
// Real-time bidirectional communication
|
|
stream.send(AgenticRequest::Query(query)).await?;
|
|
let response = stream.recv().await?;
|
|
```
|
|
|
|
### 3. Multi-Modal Data Streaming
|
|
|
|
**Problem**: Stream different types of data (video, audio, telemetry) independently.
|
|
|
|
**Solution**: Dedicate QUIC stream per modality.
|
|
|
|
**Implementation**:
|
|
```rust
|
|
let connection = QuicConnection::new(endpoint);
|
|
|
|
// Separate streams for each modality
|
|
let video_stream = connection.open_uni_stream_with_priority(StreamPriority::High).await?;
|
|
let audio_stream = connection.open_uni_stream_with_priority(StreamPriority::High).await?;
|
|
let telemetry_stream = connection.open_uni_stream_with_priority(StreamPriority::Low).await?;
|
|
|
|
// Independent flow control per stream
|
|
tokio::join!(
|
|
stream_video(&video_stream, video_data),
|
|
stream_audio(&audio_stream, audio_data),
|
|
stream_telemetry(&telemetry_stream, telemetry_data),
|
|
);
|
|
```
|
|
|
|
## Technical Specifications
|
|
|
|
### API Design
|
|
|
|
```rust
|
|
/// Cross-platform QUIC abstraction
|
|
pub struct QuicConnection {
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
inner: quinn::Connection,
|
|
|
|
#[cfg(target_arch = "wasm32")]
|
|
inner: web_transport::Session,
|
|
}
|
|
|
|
pub struct QuicStream {
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
send: quinn::SendStream,
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
recv: quinn::RecvStream,
|
|
|
|
#[cfg(target_arch = "wasm32")]
|
|
inner: web_transport::BiStream,
|
|
}
|
|
|
|
pub enum StreamPriority {
|
|
Critical,
|
|
High,
|
|
Normal,
|
|
Low,
|
|
}
|
|
|
|
impl QuicConnection {
|
|
pub async fn connect(url: &str) -> Result<Self, Error>;
|
|
|
|
pub async fn open_bi_stream(&self) -> Result<QuicStream, Error>;
|
|
|
|
pub async fn open_uni_stream(&self) -> Result<QuicSendStream, Error>;
|
|
|
|
pub async fn open_bi_stream_with_priority(
|
|
&self,
|
|
priority: StreamPriority,
|
|
) -> Result<QuicStream, Error>;
|
|
|
|
pub async fn accept_bi_stream(&self) -> Result<QuicStream, Error>;
|
|
|
|
pub fn datagram(&self) -> DatagramChannel;
|
|
|
|
pub fn close(&self, error_code: u64, reason: &[u8]);
|
|
}
|
|
|
|
impl QuicStream {
|
|
pub async fn send(&mut self, data: &[u8]) -> Result<usize, Error>;
|
|
|
|
pub async fn recv(&mut self, buf: &mut [u8]) -> Result<usize, Error>;
|
|
|
|
pub async fn finish(&mut self) -> Result<(), Error>;
|
|
|
|
pub fn set_priority(&mut self, priority: StreamPriority);
|
|
}
|
|
```
|
|
|
|
### Performance Requirements
|
|
|
|
| Metric | Target | Rationale |
|
|
|--------|--------|-----------|
|
|
| 0-RTT connection | <1ms | Fast reconnection |
|
|
| Stream open latency | <100μs | Many concurrent streams |
|
|
| Throughput per stream | >100 MB/s | High-bandwidth data |
|
|
| Max concurrent streams | 1000+ | Scalability |
|
|
| Datagram latency | <1ms | Real-time events |
|
|
|
|
## Integration Points
|
|
|
|
### 1. Stream-Based Learning
|
|
|
|
**Location**: `src/lean_agentic/learning.rs`
|
|
|
|
**Enhancement**:
|
|
```rust
|
|
pub struct QuicStreamLearner {
|
|
connection: QuicConnection,
|
|
learner: StreamLearner,
|
|
}
|
|
|
|
impl QuicStreamLearner {
|
|
pub async fn learn_from_quic_stream(
|
|
&mut self,
|
|
stream: QuicStream,
|
|
) -> Result<(), Error> {
|
|
let mut buffer = vec![0u8; 4096];
|
|
|
|
loop {
|
|
let n = stream.recv(&mut buffer).await?;
|
|
if n == 0 {
|
|
break;
|
|
}
|
|
|
|
let message = parse_message(&buffer[..n])?;
|
|
self.learner.process_message(&message).await?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. Multi-Agent QUIC Coordination
|
|
|
|
**Location**: New module `src/lean_agentic/quic_multiagent.rs`
|
|
|
|
**Implementation**:
|
|
```rust
|
|
pub struct QuicMultiAgent {
|
|
agents: HashMap<AgentId, QuicConnection>,
|
|
coordinator: QuicServer,
|
|
}
|
|
|
|
impl QuicMultiAgent {
|
|
pub async fn coordinate(&mut self) -> Result<(), Error> {
|
|
// Each agent gets a dedicated stream
|
|
let mut agent_streams = Vec::new();
|
|
|
|
for (id, conn) in &self.agents {
|
|
let stream = conn.open_bi_stream().await?;
|
|
agent_streams.push((id, stream));
|
|
}
|
|
|
|
// Broadcast coordination messages
|
|
let coord_msg = self.compute_coordination();
|
|
|
|
for (id, stream) in &mut agent_streams {
|
|
stream.send(&coord_msg.serialize()).await?;
|
|
}
|
|
|
|
// Collect responses concurrently
|
|
let responses = futures::future::join_all(
|
|
agent_streams.iter_mut().map(|(id, stream)| async move {
|
|
let mut buf = vec![0u8; 4096];
|
|
let n = stream.recv(&mut buf).await?;
|
|
Ok::<_, Error>((*id, parse_response(&buf[..n])?))
|
|
})
|
|
).await;
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. WASM Client Integration
|
|
|
|
**Location**: `wasm/src/quic.rs`
|
|
|
|
**Implementation**:
|
|
```rust
|
|
#[wasm_bindgen]
|
|
pub struct WasmQuicClient {
|
|
session: WebTransportSession,
|
|
streams: Vec<QuicStream>,
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
impl WasmQuicClient {
|
|
#[wasm_bindgen(constructor)]
|
|
pub async fn connect(url: String) -> Result<WasmQuicClient, JsValue> {
|
|
let session = WebTransportSession::connect(&url)
|
|
.await
|
|
.map_err(|e| JsValue::from_str(&e.to_string()))?;
|
|
|
|
Ok(WasmQuicClient {
|
|
session,
|
|
streams: Vec::new(),
|
|
})
|
|
}
|
|
|
|
pub async fn open_stream(&mut self) -> Result<u32, JsValue> {
|
|
let stream = self.session.open_bi_stream()
|
|
.await
|
|
.map_err(|e| JsValue::from_str(&e.to_string()))?;
|
|
|
|
let stream_id = self.streams.len() as u32;
|
|
self.streams.push(stream);
|
|
|
|
Ok(stream_id)
|
|
}
|
|
|
|
pub async fn send(&mut self, stream_id: u32, data: &[u8]) -> Result<(), JsValue> {
|
|
let stream = self.streams.get_mut(stream_id as usize)
|
|
.ok_or_else(|| JsValue::from_str("Invalid stream ID"))?;
|
|
|
|
stream.send(data)
|
|
.await
|
|
.map_err(|e| JsValue::from_str(&e.to_string()))?;
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
```
|
|
|
|
## Implementation Phases
|
|
|
|
### Phase 1: Core QUIC Support (Week 1)
|
|
- [ ] Add quinn and web-transport dependencies
|
|
- [ ] Create unified QuicConnection abstraction
|
|
- [ ] Implement stream management
|
|
- [ ] Add TLS certificate handling
|
|
- [ ] Write unit tests
|
|
|
|
### Phase 2: WASM Integration (Week 2)
|
|
- [ ] Implement WebTransport bindings
|
|
- [ ] Create WASM client library
|
|
- [ ] Add browser demo
|
|
- [ ] Test cross-platform compatibility
|
|
- [ ] Write integration tests
|
|
|
|
### Phase 3: Advanced Features (Week 3)
|
|
- [ ] Add datagram support
|
|
- [ ] Implement stream prioritization
|
|
- [ ] Create connection migration
|
|
- [ ] Add congestion control tuning
|
|
- [ ] Benchmark performance
|
|
|
|
### Phase 4: Application Integration (Week 4)
|
|
- [ ] Integrate with Lean Agentic system
|
|
- [ ] Add multi-agent coordination
|
|
- [ ] Create real-world examples
|
|
- [ ] Write documentation
|
|
- [ ] Production hardening
|
|
|
|
## Dependencies
|
|
|
|
### Native (Cargo.toml)
|
|
|
|
```toml
|
|
[dependencies]
|
|
quinn = "0.10"
|
|
rustls = "0.21"
|
|
rcgen = "0.11" # Self-signed certs for testing
|
|
|
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
|
tokio = { version = "1.42", features = ["full"] }
|
|
```
|
|
|
|
### WASM (wasm/Cargo.toml)
|
|
|
|
```toml
|
|
[dependencies]
|
|
web-sys = { version = "0.3", features = [
|
|
"WebTransport",
|
|
"WebTransportBidirectionalStream",
|
|
"WebTransportDatagramDuplexStream",
|
|
] }
|
|
wasm-bindgen = "0.2"
|
|
wasm-bindgen-futures = "0.4"
|
|
```
|
|
|
|
## Benchmarking Strategy
|
|
|
|
### Native Benchmarks
|
|
|
|
```rust
|
|
#[bench]
|
|
fn bench_stream_open_latency(b: &mut Bencher) {
|
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
|
let connection = rt.block_on(setup_connection());
|
|
|
|
b.iter(|| {
|
|
rt.block_on(async {
|
|
connection.open_bi_stream().await.unwrap()
|
|
})
|
|
});
|
|
}
|
|
|
|
#[bench]
|
|
fn bench_throughput(b: &mut Bencher) {
|
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
|
let mut stream = rt.block_on(setup_stream());
|
|
let data = vec![0u8; 1024 * 1024]; // 1 MB
|
|
|
|
b.iter(|| {
|
|
rt.block_on(async {
|
|
stream.send(&data).await.unwrap()
|
|
})
|
|
});
|
|
}
|
|
```
|
|
|
|
### WASM Benchmarks
|
|
|
|
```javascript
|
|
// In WASM demo
|
|
async function benchmarkQuic() {
|
|
const client = await WasmQuicClient.connect('https://localhost:4433');
|
|
|
|
// Measure stream open latency
|
|
const start = performance.now();
|
|
const streamId = await client.open_stream();
|
|
const latency = performance.now() - start;
|
|
|
|
console.log(`Stream open latency: ${latency.toFixed(2)}ms`);
|
|
|
|
// Measure throughput
|
|
const data = new Uint8Array(1024 * 1024); // 1 MB
|
|
const throughputStart = performance.now();
|
|
|
|
for (let i = 0; i < 100; i++) {
|
|
await client.send(streamId, data);
|
|
}
|
|
|
|
const throughputTime = performance.now() - throughputStart;
|
|
const throughputMBps = (100 / throughputTime) * 1000;
|
|
|
|
console.log(`Throughput: ${throughputMBps.toFixed(2)} MB/s`);
|
|
}
|
|
```
|
|
|
|
## Security Considerations
|
|
|
|
### Certificate Management
|
|
|
|
```rust
|
|
// Native: Use rustls with proper certificates
|
|
let tls_config = rustls::ClientConfig::builder()
|
|
.with_safe_defaults()
|
|
.with_root_certificates(root_store)
|
|
.with_no_client_auth();
|
|
|
|
let client_config = quinn::ClientConfig::new(Arc::new(tls_config));
|
|
|
|
// WASM: Browser handles TLS automatically
|
|
// Just use HTTPS URLs
|
|
```
|
|
|
|
### Authentication
|
|
|
|
```rust
|
|
pub struct AuthenticatedQuicConnection {
|
|
connection: QuicConnection,
|
|
token: AuthToken,
|
|
}
|
|
|
|
impl AuthenticatedQuicConnection {
|
|
pub async fn connect_with_auth(
|
|
url: &str,
|
|
token: AuthToken,
|
|
) -> Result<Self, Error> {
|
|
let mut connection = QuicConnection::connect(url).await?;
|
|
|
|
// Send auth token on first stream
|
|
let mut auth_stream = connection.open_bi_stream().await?;
|
|
auth_stream.send(&token.serialize()).await?;
|
|
|
|
// Verify authentication
|
|
let mut response = vec![0u8; 1024];
|
|
let n = auth_stream.recv(&mut response).await?;
|
|
|
|
if &response[..n] != b"OK" {
|
|
return Err(Error::AuthenticationFailed);
|
|
}
|
|
|
|
Ok(Self { connection, token })
|
|
}
|
|
}
|
|
```
|
|
|
|
## Success Criteria
|
|
|
|
- [ ] 0-RTT connection establishment < 1ms
|
|
- [ ] Stream open latency < 100μs
|
|
- [ ] Throughput > 100 MB/s per stream
|
|
- [ ] Support 1000+ concurrent streams
|
|
- [ ] Works in all major browsers (Chrome, Firefox, Safari)
|
|
- [ ] Zero regressions in existing benchmarks
|
|
- [ ] Full documentation and examples
|
|
|
|
## Future Enhancements
|
|
|
|
1. **BBR Congestion Control**: Optimize for bandwidth-delay product
|
|
2. **Multipath QUIC**: Use multiple network paths
|
|
3. **Forward Error Correction**: Reduce retransmissions
|
|
4. **WebTransport Pooling**: Reuse connections across tabs
|
|
5. **P2P QUIC**: Direct peer-to-peer connections
|
|
|
|
## References
|
|
|
|
[1] RFC 9000: QUIC Transport Protocol
|
|
[2] RFC 9114: HTTP/3
|
|
[3] RFC 9001: Using TLS to Secure QUIC
|
|
[4] RFC 9308: Applicability of QUIC
|
|
[5] QUIC Loss Detection and Congestion Control
|
|
[6] W3C WebTransport Specification
|
|
|
|
## Appendix: Example Server
|
|
|
|
```rust
|
|
use quinn::{Endpoint, ServerConfig};
|
|
use std::sync::Arc;
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
// Generate self-signed certificate
|
|
let cert = rcgen::generate_simple_self_signed(vec!["localhost".into()])?;
|
|
let cert_der = cert.serialize_der()?;
|
|
let priv_key = cert.serialize_private_key_der();
|
|
|
|
let mut server_config = ServerConfig::with_single_cert(
|
|
vec![rustls::Certificate(cert_der)],
|
|
rustls::PrivateKey(priv_key),
|
|
)?;
|
|
|
|
// Configure transport
|
|
let mut transport_config = quinn::TransportConfig::default();
|
|
transport_config.max_concurrent_bidi_streams(1000u32.into());
|
|
server_config.transport = Arc::new(transport_config);
|
|
|
|
// Bind endpoint
|
|
let endpoint = Endpoint::server(server_config, "0.0.0.0:4433".parse()?)?;
|
|
|
|
println!("QUIC server listening on 0.0.0.0:4433");
|
|
|
|
// Accept connections
|
|
while let Some(connecting) = endpoint.accept().await {
|
|
tokio::spawn(async move {
|
|
let connection = connecting.await?;
|
|
|
|
loop {
|
|
let (mut send, mut recv) = connection.accept_bi().await?;
|
|
|
|
// Echo server
|
|
let mut buf = vec![0u8; 4096];
|
|
while let Some(n) = recv.read(&mut buf).await? {
|
|
send.write_all(&buf[..n]).await?;
|
|
}
|
|
|
|
send.finish().await?;
|
|
}
|
|
|
|
Ok::<_, anyhow::Error>(())
|
|
});
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
```
|
|
|
|
## Appendix: WASM Example
|
|
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>QUIC WASM Demo</title>
|
|
</head>
|
|
<body>
|
|
<h1>QUIC Multi-Stream Demo</h1>
|
|
<button id="connect">Connect</button>
|
|
<button id="send">Send Message</button>
|
|
<div id="status"></div>
|
|
<div id="messages"></div>
|
|
|
|
<script type="module">
|
|
import init, { WasmQuicClient } from './pkg/lean_agentic_quic.js';
|
|
|
|
async function main() {
|
|
await init();
|
|
|
|
let client = null;
|
|
let streamId = null;
|
|
|
|
document.getElementById('connect').onclick = async () => {
|
|
try {
|
|
client = await WasmQuicClient.connect('https://localhost:4433');
|
|
streamId = await client.open_stream();
|
|
|
|
document.getElementById('status').textContent = 'Connected!';
|
|
} catch (e) {
|
|
document.getElementById('status').textContent = `Error: ${e}`;
|
|
}
|
|
};
|
|
|
|
document.getElementById('send').onclick = async () => {
|
|
if (!client || streamId === null) {
|
|
alert('Not connected');
|
|
return;
|
|
}
|
|
|
|
const message = 'Hello from WASM via QUIC!';
|
|
const encoder = new TextEncoder();
|
|
const data = encoder.encode(message);
|
|
|
|
await client.send(streamId, data);
|
|
|
|
const messagesDiv = document.getElementById('messages');
|
|
messagesDiv.innerHTML += `<p>Sent: ${message}</p>`;
|
|
};
|
|
}
|
|
|
|
main();
|
|
</script>
|
|
</body>
|
|
</html>
|
|
```
|