Transports

LAN, BLE, Iroh, WebRTC-carrier, and MoQ-carrier settings

OpenRTC keeps one Iroh endpoint and can replace its physical packet path when the environment allows.

TransportRole
iroh-lanNative direct LAN QUIC path
iroh-quicNative direct QUIC when available
iroh-relayBaseline relay path, including browser WASM
webrtcThe current Iroh connection is physically carried by WebRTC
bleNative BLE iroh custom transport path
moqThe current Iroh connection is physically carried by Draft 14 MoQ
import { OpenRTC } from 'openrtc/native';
import { createBridge } from 'openrtc-tauri/ipc';

const client = OpenRTC({
  apiKey: '<your public OpenRTC API key>',
  transports: {
    iroh: true,
    webrtc: true,
    relay: true,
    ble: true,
    optimizeFor: 'balanced',
    priority: ['iroh-lan', 'iroh-quic', 'webrtc', 'iroh-relay'],
  },
}, createBridge());

All fields are optional. Managed relay fallback is allowed by default, so most applications should omit transports entirely. A developer can disable relay for the whole app in the portal, while one client instance can opt out without changing the app policy:

const rtc = OpenRTC({
  apiKey,
  transports: { relay: false },
});

Direct-only mode removes Iroh relay addresses and relay-backed carrier routes. Native peers may still use Iroh LAN/direct QUIC. Browser peers normally require a relay-capable path, so a direct-only browser connection can correctly fail behind restrictive NATs.

Relay policy surfaces

SurfaceDefaultContract
TypeScript Transports.relaytrueSet false before activating an avenue to make that client direct-only.
Rust TransportConfig.relaytrueSet false before endpoint construction; sanitization removes Iroh relay, TURN, and MoQ routes.
WASM WasmClient.setRelay(enabled)trueAdvanced host binding; call before initIroh(). The high-level TypeScript client applies it automatically.
App manifest features.relaytrue for new and migrated appsServer ceiling. A client cannot raise it.
App manifest relay.maxPerHour600App-wide relay-capable gateway admissions per one-hour window; accepted values are 1–100000.
App manifest relay.uploadMbps25App-wide measured relay ingress ceiling; accepted values are 0.1–1000.
App manifest relay.downloadMbps25App-wide measured relay egress ceiling; accepted values are 0.1–1000.

The effective client policy is the intersection of the app manifest and local configuration. privacy: 'relay-only' requires effective relay access and the high-level client fails activation when that combination is impossible.

Use privacy: 'relay-only' only when the developer manifest enables relay use. Native hosts that compose extra application protocols register them with the Rust endpoint/router; there is no TypeScript ownership switch for that host integration.

ble: true is the complete application switch, not a provider installation. The published TypeScript packages do not export a custom-transport registration API. A native Tauri host may register a compile-time Rust NativeTransportInstaller before plugin setup; unsupported or ordinary public hosts report BLE unavailable and continue on the Iroh base route. The current BLE reference host is private and physical BLE acceptance has not produced current evidence, so BLE remains experimental rather than a public SDK support claim. OpenRTC performs capability exchange and route promotion automatically after admission when that host integration is present. Application code should use the same connection and stream APIs regardless of the active transport. The admitted base route remains usable until BLE replacement succeeds, and OpenRTC bounds retries to three attempts per current connection generation.

For a native host that adds an ALPN or composes Iroh Docs, Blobs, or Gossip on the same endpoint, see Custom Protocols. That extension changes router composition, not OpenRTC's ownership of peer lifecycle, admission, or retry.

Selection order

OpenRTC evaluates transport policy in a fixed order:

  1. Apply privacy as a hard filter.
  2. Remove routes unsupported by the local runtime or remote peer.
  3. Apply optimizeFor to proven, current-generation routes.
  4. Use priority as the exact tie-breaker and terminal fallback order.

The cross-platform default intent is iroh-lan, iroh-quic, webrtc, moq, then iroh-relay. Browser runtimes automatically skip native-only LAN and QUIC. A priority entry does not enable its mechanism; enable the WebRTC carrier, MoQ carrier, or native BLE provider separately.

When both Iroh carriers are enabled, Rust starts only the first mutually supported candidate. A bounded terminal failure advances to the next carrier; the carriers do not race and OpenRTC does not keep a long-lived TURN allocation or MoQ subscription warm by default.

lowest-latency uses existing passive RTT observations. Native route changes require at least a 20 ms improvement, five seconds of candidate stability, a 30-second hold on the current route, and samples no older than ten seconds. Browser carrier selection stays deterministic because starting an inactive carrier merely to measure it would add unnecessary traffic.

WebRTC and MoQ carriers

webrtc: true enables the custom WebRTC carrier. A moq object enables the custom MoQ carrier. In OpenRTC configuration and diagnostics these mechanisms are named only webrtc and moq; the retired identifiers iroh-webrtc and iroh-moq are not aliases. Both keep the public stream/channel/media APIs on the same logical Iroh connection and change only its physical packet path; neither has a separate application lifecycle or implementation selector.

MoQ additionally requires relayUrl. Supply a short-lived accessToken separately; do not place credentials in the URL. A relay that does not negotiate moq-transport-14 is incompatible.

In relay-only mode, an Iroh WebRTC carrier is eligible only with relay-only ICE. STUN and direct candidates are removed before the attempt. MoQ and the ordinary Iroh relay remain eligible. If no permitted route works, connection fails instead of silently revealing a direct peer address. This is peer-address privacy, not anonymity from service operators or account systems.

Hosted relay limits

The developer portal owns the app ceiling. “Managed relay fallback” can disable hosted relay use, “relay-capable admissions per app / hour” lowers the app-wide server grant rate, and the monthly app credit cap bounds all metered OpenRTC usage. A client may set relay: false; it cannot override a disabled app policy or raise either server limit.

New and migrated apps default to managed relay enabled with 600 relay-capable admissions per app per hour. The existing per-principal gateway safety limit continues to apply independently.

The server counts every gateway grant while the app manifest permits relay, even when a particular client later stays direct. This conservative boundary prevents a modified client from evading the developer's limit. To remove those admissions from the relay-capable bucket for the entire app, disable “Managed relay fallback” in the portal.

Managed Cloudflare TURN credentials use an opaque app tag. OpenRTC imports ingress, egress, and concurrent connections per app in closed five-minute UTC samples. A hosted OpenRTC relay must authenticate as the relay operator, verify the signed app/session context, enforce its byte-rate ceiling, and submit monotonic interval counters. MoQ is not labeled measured without an equivalent reliable meter.