Skip to content

QUIC Bridge

QuicBridgeClient + QuicBridgeServer

Rust Feature Transport

Cross-host substrate primitive that ferries bytes between two AdaptiveRing instances via QUIC streams. Encrypts the wire (TLS via rustls), multiplexes streams within one connection, manages congestion control.

Gated behind the quic-bridge Cargo feature. Enabling pulls quinn + rcgen + rustls + tokio as regular dependencies.

Data path: burst-batched egress, chunked ingress

A per-slot stream write (one write_all await per 64-byte item) serializes the bridge on reactor latency - microseconds per item regardless of wire speed - so the client BURST-DRAINS the ring: every already-available slot (up to EGRESS_BATCH_SLOTS = 256, 16 KiB) is copied into one contiguous buffer and handed to quinn in a single write. The 64-byte memcpy per slot is noise next to the TLS record processing the bytes pay anyway (quinn copies into its send queue and encrypts in user space; no zero-copy egress exists through an encrypting transport). A lone item still ships immediately - batching never waits for items that have not arrived, so request/response traffic is not penalized.

The server mirrors this with chunked stream reads: each read takes whatever the stream has buffered, complete 64-byte slots push into the consumer ring as they assemble, and a partial slot carries to the next read.

Frame format

Each connection carries one uni-directional stream. The stream starts with an 8-byte big-endian item count N, followed by N * ADAPTIVE_SPSC_PAYLOAD_BYTES (64-byte) slot payloads.

API

QuicBridgeClient

CallBehavior
QuicBridgeClient::new(producer_ring, server_addr, client_config, bind_addr)Construct. producer_ring: Arc<AdaptiveRing>.
client.run(n_items, server_name) -> Result<(), QuicBridgeError>Connect, ship n_items slots, finish the stream.

QuicBridgeServer

CallBehavior
QuicBridgeServer::bind(consumer_ring, addr, server_config)Bind. consumer_ring: Arc<AdaptiveRing>.
server.local_addr() -> Result<SocketAddr, std::io::Error>Bound address (useful when 0.0.0.0:0 was passed).
server.accept_one() -> Result<u64, QuicBridgeError>Accept one connection, drain its uni stream, return item count.

Helpers

HelperBehavior
make_self_signed_pair(sni_name) -> Result<(ServerConfig, ClientConfig), QuicBridgeError>Build a single-host / demo TLS config pair in one process.
generate_self_signed_cert(sni_name) -> Result<(Vec<u8>, Vec<u8>), QuicBridgeError>Cross-host building block: (cert_der, pkcs8_key_der) as raw bytes to ship between hosts.
make_server_config_from_der(cert_der, key_der)Rebuild the server config from shipped DER bytes.
make_client_config_from_der(cert_der)Client config trusting exactly that cert; pass the SNI string the cert names to connect.
install_default_crypto_provider()Idempotent rustls ring backend install for binary entrypoints.

Error type

QuicBridgeError:

  • Tls(String) - rcgen / rustls setup failed.
  • Quic(String) - QUIC connection or stream error.
  • Io(std::io::Error) - stdlib I/O error binding the endpoint.

E2E proof

examples/quic_bridge_e2e.rs runs producer-side AdaptiveRing -> QuicBridgeClient -> QUIC -> QuicBridgeServer -> consumer-side AdaptiveRing on 127.0.0.1 (100,000 items, integrity verified).

examples/bridge_lan.rs runs the same chain between two PHYSICAL hosts with the cert shipped as DER bytes: 1,000,000 items each direction with strict sequence assertions, plus a ping/pong round-trip mode. Measured numbers live in docs/LAN_BRIDGE_PERFORMANCE.md .

References

  • AdaptiveRing - the producer/consumer ring type.
  • TcpBridge - plain-TCP sibling for trusted networks where TLS overhead is wasted.