JetStream Iroh
Iroh is a peer-to-peer networking library that provides NAT traversal, hole punching, and relay fallback. JetStream integrates with Iroh to enable peer-to-peer RPC communication.
Features
- NAT Traversal: Automatic hole punching for direct peer-to-peer connections
- Relay Fallback: Falls back to relay servers when direct connection isnāt possible
- Discovery: Uses JetStreamās discovery service at
discovery.jetstream.rs - ALPN-based Protocol Negotiation: Each service defines its own protocol version
Example
Hereās a complete example of an echo service using Iroh transport:
#![cfg(feature = "iroh")]
use crate::echo_protocol::{EchoChannel, EchoService};
use jetstream::prelude::*;
use jetstream_macros::service;
use okstd::prelude::*;
#[service(tracing)]
pub trait Echo {
async fn square(&mut self, ctx: Context, i: u32) -> Result<String>;
}
#[derive(Debug, Clone)]
struct EchoServer;
impl Echo for EchoServer {
async fn square(&mut self, _ctx: Context, i: u32) -> Result<String> {
Ok((i * i).to_string())
}
}
#[okstd::main]
async fn main() {
// Initialize tracing subscriber
tracing_subscriber::fmt()
.with_max_level(tracing::Level::DEBUG)
.with_thread_ids(true)
.with_span_events(
tracing_subscriber::fmt::format::FmtSpan::ENTER
| tracing_subscriber::fmt::format::FmtSpan::EXIT,
)
.init();
// Build the server router with the echo service
let router = jetstream_iroh::server_builder(EchoService {
inner: EchoServer {},
})
.await
.unwrap();
// get our own address. At this point we have a running router
// that's ready to accept connections.
let addr = router.endpoint().node_addr();
// Build client transport and connect
let mut transport = jetstream_iroh::client_builder::<EchoChannel>(addr)
.await
.unwrap();
let mut ec = EchoChannel {
inner: Box::new(&mut transport),
};
for i in 0..10 {
let b = ec.square(Context::default(), i).await.unwrap();
println!("square response: {i} * {i} = {b}");
}
router.shutdown().await.unwrap();
}
Server Setup
To create an Iroh server, use the server_builder function:
#![allow(unused)]
fn main() {
use jetstream_iroh::server_builder;
let router = server_builder(EchoService { inner: EchoServer {} })
.await
.unwrap();
// Get the node address to share with clients
let addr = router.endpoint().node_addr();
}
Client Setup
To connect to an Iroh server, use the client_builder function:
#![allow(unused)]
fn main() {
use jetstream_iroh::client_builder;
let mut transport = client_builder::<EchoChannel>(addr)
.await
.unwrap();
}
Discovery
JetStream uses a custom discovery service for Iroh nodes. The discovery URL is:
https://discovery.jetstream.rs
This allows nodes to find each other using their public keys without needing to exchange IP addresses directly.
Feature Flag
To use Iroh transport, enable the iroh feature in your Cargo.toml:
[dependencies]
jetstream = { version = "10", features = ["iroh"] }
For more details, see the jetstream_iroh API documentation.