### Hello, Iroh Example Source: https://docs.iroh.computer/languages/python A basic example demonstrating how to bind an Iroh endpoint, print its ID, and advertise a specific ALPN. This serves as a starting point for Iroh applications. ```python import asyncio import iroh ALPN = b"hello-iroh/0" async def main(): iroh.iroh_ffi.uniffi_set_event_loop(asyncio.get_running_loop()) ep = await iroh.Endpoint.bind( iroh.EndpointOptions(preset=iroh.preset_n0(), alpns=[ALPN]) ) print("endpoint id:", ep.id()) asyncio.run(main()) ``` -------------------------------- ### Hello, Iroh Example Source: https://docs.iroh.computer/languages/javascript A basic example demonstrating how to create an Iroh endpoint and log its ID. This snippet shows the fundamental setup for using Iroh in a Node.js application. ```javascript import { Endpoint } from '@number0/iroh' const ALPN = Array.from(Buffer.from('hello-iroh/0')) const ep = await Endpoint.bind({ alpns: [ALPN] }) console.log('endpoint id:', ep.id().toString()) await ep.close() ``` -------------------------------- ### Clone Repository and Run Net Diagnostics Example Source: https://docs.iroh.computer/iroh-services/net-diagnostics/quickstart Clone the iroh-services repository and execute the net_diagnostics example. This client connects to iroh services, enables diagnostics for your project, and listens for incoming diagnostic requests. ```bash git clone https://github.com/n0-computer/iroh-services.git cd iroh-services cargo run --example net_diagnostics ``` -------------------------------- ### Minimal Iroh Docs Protocol Setup Source: https://docs.iroh.computer/protocols/documents This Rust code demonstrates the minimal setup for iroh-docs, initializing an endpoint, in-memory stores for blobs, and spawning the gossip and docs protocols. It then registers these protocols on a router. ```rust use iroh::{endpoint::presets, protocol::Router, Endpoint}; use iroh_blobs::{store::mem::MemStore, BlobsProtocol, ALPN as BLOBS_ALPN}; use iroh_docs::{protocol::Docs, ALPN as DOCS_ALPN}; use iroh_gossip::{net::Gossip, ALPN as GOSSIP_ALPN}; #[tokio::main] async fn main() -> anyhow::Result<()> { // create an iroh endpoint that includes the standard address lookup // mechanisms we've built at number0 let endpoint = Endpoint::bind(presets::N0).await?; // build the blobs store (in-memory here; use FsStore::load for persistence) let blobs = MemStore::default(); // build the gossip protocol let gossip = Gossip::builder().spawn(endpoint.clone()); // build the docs protocol // use Docs::persistent(path) for on-disk storage instead let docs = Docs::memory() .spawn(endpoint.clone(), (*blobs).clone(), gossip.clone()) .await?; // register all three protocols on the router let _router = Router::builder(endpoint.clone()) .accept(BLOBS_ALPN, BlobsProtocol::new(&blobs, None)) .accept(GOSSIP_ALPN, gossip) .accept(DOCS_ALPN, docs.clone()) .spawn(); // docs is ready — see the next sections for how to use it Ok(()) } ``` -------------------------------- ### Receive File Command Example Source: https://docs.iroh.computer/protocols/blobs Example command to receive a file using the iroh-blobs tool, requiring a ticket and a destination filename. ```sh $ cargo run -- receive blobabvojvy[...] file.txt Starting download. Finished download. Copying to destination. Finished copying. Shutting down. ``` -------------------------------- ### Clone Iroh Examples Repository Source: https://docs.iroh.computer/protocols/automerge Clone the iroh-examples repository to access the iroh-automerge integration code. Navigate into the example directory. ```bash git clone https://github.com/n0-computer/iroh-examples cd iroh-examples/iroh-automerge ``` -------------------------------- ### Run callme demo: Server/Listen Mode Source: https://docs.iroh.computer/protocols/streaming Starts the callme CLI client in server mode to listen for incoming peer connections. Ensure you are in the callme/callme-cli directory. ```bash git clone https://github.com/n0-computer/callme.git # Terminal A: run the CLI in server/listen mode cd callme/callme-cli cargo run --release -- --listen ``` -------------------------------- ### Server-Side Request Handling Source: https://docs.iroh.computer/protocols/rpc Example of a server function that accepts incoming connections, deserializes requests, and handles them. This snippet shows handling a 'Get' request. ```rust async fn server(connection: Connection, store: BTreeMap) -> Result<()> { while let Ok((send, recv)) = connection.accept_bi().await { let request = recv.read_to_end(1024).await?; let request: Request = postcard::from_bytes(&request)?; match request { Request::Get(GetRequest { key }) => { let response = store.get(key); let response = postcard::to_stdvec(&response)?; send.write_all(&response).await?; send.finish(); } ... } } } ``` -------------------------------- ### Send File Command Example Source: https://docs.iroh.computer/protocols/blobs Example command to send a file using the iroh-blobs tool. This command analyzes the file and outputs a ticket for retrieval. ```sh $ cargo run -- send ./file.txt Indexing file. File analyzed. Fetch this file by running: cargo run -- receive blobabvojvy[...] file.txt ``` -------------------------------- ### Start Accept Side with Router Source: https://docs.iroh.computer/protocols/writing-a-protocol Initializes an iroh Endpoint and creates a Router to listen for incoming connections. The router is spawned to start the accept loop. ```rust async fn start_accept_side() -> anyhow::Result { let endpoint = iroh::Endpoint::bind(iroh::endpoint::presets::N0).await?; let router = iroh::protocol::Router::builder(endpoint) .spawn(); Ok(router) } ``` -------------------------------- ### Install Clap Crate for CLI Source: https://docs.iroh.computer/examples/chat This command installs the `clap` crate, a popular Rust library for parsing command-line arguments, which is used to build the chat application's CLI. ```bash cargo add clap --features derive ``` -------------------------------- ### Install Iroh JavaScript Bindings Source: https://docs.iroh.computer/languages/javascript Install the `@number0/iroh` package using npm. Requires Node.js 20.3.0 or newer. Prebuilt N-API binaries are available for various platforms. ```bash npm install @number0/iroh ``` -------------------------------- ### Initialize Kotlin Project for Ping Pong Source: https://docs.iroh.computer/connect-two-endpoints Provides instructions for setting up a Gradle project in Kotlin and adding the Iroh dependency. This is the initial setup for a Kotlin ping program. ```bash # scaffold a Gradle project, then add the iroh dependency: # dependencies { implementation("computer.iroh:iroh:1.0.0") } # (Maven Central — requires mavenCentral() in your repositories block) # work in a Main.kt with `fun main(...)` ``` -------------------------------- ### Sender Example in Kotlin Source: https://docs.iroh.computer/connect-two-endpoints This Kotlin snippet shows how to implement the sender. It binds an endpoint, establishes a connection, sends 'hello', waits for the echo, and measures the time taken. ```kotlin suspend fun sender(ticketStr: String) { val ep = Endpoint.bind(EndpointOptions(preset = presetN0())) val addr = EndpointTicket.parse(ticketStr).endpointAddr() val conn = ep.connect(addr, ALPN) val bi = conn.openBi() val ms = measureTimeMillis { bi.send().writeAll("hello".toByteArray()) bi.send().finish() bi.recv().readToEnd(1024u) } println("ping took: $ms ms") ep.shutdown() } ``` -------------------------------- ### Initialize Python Project for Ping Pong Source: https://docs.iroh.computer/connect-two-endpoints Creates a new Python project directory, sets up a virtual environment, and installs the Iroh library. This prepares the environment for the Python ping program. ```bash mkdir ping-pong && cd ping-pong python -m venv .venv && source .venv/bin/activate pip install iroh # work in main.py ``` -------------------------------- ### Main Function to Run Protocol Source: https://docs.iroh.computer/protocols/writing-a-protocol This function demonstrates starting the accepting side of a protocol, connecting to it, and then gracefully shutting down the accepting side. It ensures all connections are closed properly. ```rust #[tokio::main] async fn main() -> Result<()> { let router = start_accept_side().await?; let endpoint_addr = router.endpoint().addr().await?; connect_side(endpoint_addr).await?; // This makes sure the endpoint in the router is closed properly and connections close gracefully router.shutdown().await?; Ok(()) } ``` -------------------------------- ### Install irpc Crate Source: https://docs.iroh.computer/protocols/rpc Add the irpc crate to your project dependencies using cargo. ```bash cargo add irpc ``` -------------------------------- ### Call a Service In-Process Source: https://docs.iroh.computer/protocols/rpc Example of how to call a service using a client sender and a oneshot channel for the response. This demonstrates the cumbersome nature without a client wrapper. ```rust let (tx, rx) = oneshot::channel(); client.send(Request::Get { key: "a".to_string(), response: tx }).await?; let res = rx.await?; ``` -------------------------------- ### Hello, iroh Example Source: https://docs.iroh.computer/languages/rust A basic Rust program that binds an Iroh endpoint using the N0 preset, waits for connectivity, and prints the endpoint ID. Run with `cargo run`. ```rust use anyhow::Result; use iroh::{Endpoint, endpoint::presets}; #[tokio::main] async fn main() -> Result<()> { let endpoint = Endpoint::bind(presets::N0).await?; endpoint.online().await; println!("endpoint id: {}", endpoint.id()); Ok(()) } ``` -------------------------------- ### Run Sender and Receiver in JavaScript Source: https://docs.iroh.computer/connect-two-endpoints Start the receiver using Node.js and then run the sender with the ticket copied from the receiver's output. ```bash # terminal 1 node main.mjs receiver # terminal 2 node main.mjs sender ``` -------------------------------- ### Add iroh-docs Dependency Source: https://docs.iroh.computer/protocols/documents Install the iroh-docs crate using Cargo. This is the first step to include its functionality in your project. ```bash cargo add iroh-docs ``` -------------------------------- ### Initialize Rust Project for Ping Pong Source: https://docs.iroh.computer/connect-two-endpoints Sets up a new Rust project and adds necessary Iroh and networking dependencies. This is the starting point for the Rust ping program. ```bash cargo init ping-pong cd ping-pong cargo add iroh iroh-ping iroh-tickets anyhow tracing-subscriber cargo add tokio --features full # work in src/main.rs ``` -------------------------------- ### Add Iroh Dependencies Source: https://docs.iroh.computer/examples/chat Install necessary dependencies for the chat application, including iroh, tokio for async runtime, anyhow for error handling, and rand for randomness. ```bash cargo add iroh tokio anyhow rand ``` -------------------------------- ### Sender Example in Python Source: https://docs.iroh.computer/connect-two-endpoints This Python snippet demonstrates the sender functionality. It binds an endpoint, connects to the receiver's address, sends 'hello', awaits the echo, and measures the round-trip time. ```python async def sender(ticket_str): iroh.iroh_ffi.uniffi_set_event_loop(asyncio.get_running_loop()) ep = await iroh.Endpoint.bind(iroh.EndpointOptions()) addr = iroh.EndpointTicket.parse(ticket_str).endpoint_addr() conn = await ep.connect(addr, list(ALPN)) bi = await conn.open_bi() start = time.monotonic() await bi.send().write_all(list(b"hello")) await bi.send().finish() await bi.recv().read_to_end(1024) print(f"ping took: {(time.monotonic() - start) * 1000:.2f} ms") await ep.close() ``` -------------------------------- ### Sender Example in JavaScript Source: https://docs.iroh.computer/connect-two-endpoints This JavaScript code demonstrates the sender's functionality. It binds an endpoint, connects to the receiver, sends 'hello', receives the echo, and logs the round-trip time. ```javascript async function sender(ticketStr) { const ep = await Endpoint.bind() const addr = EndpointTicket.fromString(ticketStr).endpointAddr() const conn = await ep.connect(addr, ALPN) const bi = await conn.openBi() const start = performance.now() await bi.send.writeAll(Array.from(Buffer.from('hello'))) await bi.send.finish() await bi.recv.readToEnd(1024) console.log(`ping took: ${(performance.now() - start).toFixed(2)} ms`) await ep.close() } ``` -------------------------------- ### Run iroh-ping Sender Source: https://docs.iroh.computer/quickstart Compiles and runs the sender example for iroh-ping. Replace with the ticket obtained from the receiver to establish a connection and measure round-trip time. ```bash cargo run --example quickstart sender ``` -------------------------------- ### Start Second Automerge Endpoint and Connect Source: https://docs.iroh.computer/protocols/automerge In a second terminal, run the application again, providing the Endpoint ID of the first instance. This initiates a connection and data synchronization. ```bash # Second Terminal > cargo run -- --remote-id lkpz2uw6jf7qahl7oo6qc46qad5ysszhtdzqyotkb3pwtd7sv3va Running Endpoint Id: gcq5e7mcsvwgtxfvbu7w7rkikxhfudbqt5yvl34f47qlmsyuy7wa > ``` -------------------------------- ### Perform Remote Get Request Source: https://docs.iroh.computer/protocols/rpc Example of a client function to perform a 'Get' request across a process boundary using a connection and postcard for serialization. ```rust async fn get_remote(connection: Connection, key: String) -> Result> { let (send, recv) = connection.open_bi().await?; send.write_all(postcard::to_stdvec(GetRequest { key })?).await?; let res = recv.read_to_end(1024).await?; let res = postcard::from_bytes(&res)?; Ok(res) } ``` -------------------------------- ### Initialize Project and Add Dependencies Source: https://docs.iroh.computer/protocols/blobs Set up a new Rust project and add necessary dependencies for file transfer. ```bash cargo init file-transfer cd file-transfer cargo add iroh iroh-blobs tokio anyhow ``` -------------------------------- ### Initialize and Run CLI Application Source: https://docs.iroh.computer/examples/chat Sets up the Iroh endpoint, gossip service, and router. It then prints a ticket for joining the network and enters a loop to broadcast user messages. ```rust println!("> our endpoint id: {}", endpoint.id()); let gossip = Gossip::builder().spawn(endpoint.clone()); let router = Router::builder(endpoint.clone()) .accept(iroh_gossip::ALPN, gossip.clone()) .spawn(); // in our main file, after we create a topic `id`: // print a ticket that includes our own endpoint id and endpoint addresses let ticket = { // Get our address information, includes our // `EndpointId`, our `RelayUrl`, and any direct // addresses. let me = endpoint.addr(); let endpoints = vec![me]; Ticket { topic, endpoints } }; println!("> ticket to join us: {{ticket}}"); // join the gossip topic by connecting to known endpoints, if any let endpoint_ids = endpoints.iter().map(|p| p.id).collect(); if endpoints.is_empty() { println!("> waiting for endpoints to join us..."); } else { println!("> trying to connect to {} endpoints...", endpoints.len()); }; let (sender, receiver) = gossip.subscribe_and_join(topic, endpoint_ids).await?.split(); println!("> connected!"); // broadcast our name, if set if let Some(name) = args.name { let message = Message::new(MessageBody::AboutMe { from: endpoint.id(), name, }); sender.broadcast(message.to_vec().into()).await?; } // subscribe and print loop tokio::spawn(subscribe_loop(receiver)); // spawn an input thread that reads stdin // create a multi-provider, single-consumer channel let (line_tx, mut line_rx) = tokio::sync::mpsc::channel(1); // and pass the `sender` portion to the `input_loop` std::thread::spawn(move || input_loop(line_tx)); // broadcast each line we type println!("> type a message and hit enter to broadcast..."); // listen for lines that we have typed to be sent from `stdin` while let Some(text) = line_rx.recv().await { // create a message from the text let message = Message::new(MessageBody::Message { from: endpoint.id(), text: text.clone(), }); // broadcast the encoded message sender.broadcast(message.to_vec().into()).await?; // print to ourselves the text that we sent println!("> sent: {{text}}"); } router.shutdown().await?; Ok(()) } ``` -------------------------------- ### Setup Net Diagnostics Client Source: https://docs.iroh.computer/iroh-services/net-diagnostics/quickstart Sets up the Net Diagnostics client by building a Client, granting the GetAny capability, and spawning a ClientHost for the platform to dial back into the endpoint. Reads the API key from the environment variable. ```rust use anyhow::Result; use iroh::{Endpoint, protocol::Router}; use iroh_services::{ ApiSecret, Client, ClientHost, CLIENT_HOST_ALPN, API_SECRET_ENV_VAR_NAME, caps::NetDiagnosticsCap, }; async fn setup_net_diagnostics(endpoint: &Endpoint) -> Result { // Get your secret somehow, either from an environment variable or config file let secret = ApiSecret::from_env_var(API_SECRET_ENV_VAR_NAME)?; // The remote_id is the id of the endpoint we'll be sending the network // report to, derived from the secret's address let remote_id = secret.addr().id; // Build the client let client = Client::builder(endpoint) .api_secret(secret)? .build() .await?; // Grant the GetAny capability so the platform can request diagnostics // from this endpoint on demand let client2 = client.clone(); tokio::spawn(async move { client2 .grant_capability(remote_id, vec![NetDiagnosticsCap::GetAny]) .await .unwrap(); }); // Set up a ClientHost so the platform can dial back into this endpoint let host = ClientHost::new(endpoint); let router = Router::builder(endpoint.clone()) .accept(CLIENT_HOST_ALPN, host) .spawn(); Ok(router) } ``` -------------------------------- ### Client Wrapper for Convenience Source: https://docs.iroh.computer/protocols/rpc A newtype wrapper around the mpsc::Sender to provide a more convenient API for calling services. Includes an example for the 'get' method. ```rust struct Client(mpsc::Sender); impl Client { ... async fn get(&self, key: String) -> Result> { let (tx, rx) = oneshot::channel(); self.0.send(Request::Get { key, response: tx }).await?; Ok(rx.await??) } ... } ``` -------------------------------- ### Bind iroh Endpoint in Kotlin Source: https://docs.iroh.computer/languages/kotlin This snippet shows how to bind a new iroh endpoint with specified ALPNs. It prints the endpoint ID and then shuts it down. This is a fundamental example for starting with iroh in Kotlin. ```kotlin import computer.iroh.* import kotlinx.coroutines.runBlocking private val ALPN = "hello-iroh/0".toByteArray() fun main() = runBlocking { val ep = Endpoint.bind( EndpointOptions(preset = presetN0(), alpns = listOf(ALPN)), ) println("endpoint id: ${ep.id()}") ep.shutdown() } ``` -------------------------------- ### Install Iroh Python Package Source: https://docs.iroh.computer/languages/python Install the iroh Python package using pip. This command fetches and installs the prebuilt wheels for your platform. ```bash pip install iroh ``` -------------------------------- ### Full iroh-gossip Example Source: https://docs.iroh.computer/connecting/gossip Demonstrates setting up an iroh endpoint, router, and gossip protocol. It shows how to subscribe to a topic, join bootstrap peers, broadcast messages, and receive messages from other peers. Ensure you replace the placeholder bootstrap_peers with actual peer IDs. ```rust use iroh::{protocol::Router, Endpoint, EndpointId, endpoint::presets}; use iroh_gossip::{api::Event, Gossip, TopicId}; use n0_error::{Result, StdResultExt}; use n0_future::StreamExt; #[tokio::main] async fn main() -> Result<()> { // create an iroh endpoint that includes the standard address lookup mechanisms // we've built at number0 let endpoint = Endpoint::bind(presets::N0).await?; // build gossip protocol let gossip = Gossip::builder().spawn(endpoint.clone()); // setup router let router = Router::builder(endpoint) .accept(iroh_gossip::ALPN, gossip.clone()) .spawn(); // gossip swarms are centered around a shared "topic id", which is a 32 byte identifier let topic_id = TopicId::from_bytes([23u8; 32]); // and you need some bootstrap peers to join the swarm let bootstrap_peers = bootstrap_peers(); // then, you can subscribe to the topic and join your initial peers let (sender, mut receiver) = gossip .subscribe(topic_id, bootstrap_peers) .await? .split(); // you might want to wait until you joined at least one other peer: receiver.joined().await?; // then, you can broadcast messages to all other peers! sender.broadcast(b"hello world this is a gossip message".to_vec().into()).await?; // and read messages from others while let Some(event) = receiver.next().await { match event? { Event::Received(message) => { println!("received a message: {:?}", std::str::from_utf8(&message.content)); } _ => {} } } // clean shutdown makes sure that other peers are notified that you went offline router.shutdown().await.std_context("shutdown router")?; Ok(()) } fn bootstrap_peers() -> Vec { // insert your bootstrap peers here, or get them from your environment vec![] } ``` -------------------------------- ### Install iroh-doctor CLI Source: https://docs.iroh.computer/troubleshooting Install the `iroh-doctor` command-line tool using Cargo to help diagnose network connectivity issues. ```bash cargo install iroh-doctor ``` -------------------------------- ### Initialize Rust Project Source: https://docs.iroh.computer/examples/chat Initialize a new Rust project for the chat application and run the default 'hello world' code. ```bash cargo init iroh-gossip-chat cd iroh-gossip-chat cargo run ``` -------------------------------- ### Install Rust Source: https://docs.iroh.computer/quickstart Installs the Rust programming language and its package manager, Cargo. This is a prerequisite for building and running iroh projects. ```bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -------------------------------- ### Example Iroh Ticket Source: https://docs.iroh.computer/concepts/tickets This is an example of a long, base32-encoded ticket string that contains dialing information and optional application-specific data. ```text docaaacarwhmusoqf362j3jpzrehzkw3bqamcp2mmbhn3fmag3mzzfjp4beahj2v7aezhojvfqi5wltr4vxymgzqnctryyup327ct7iy4s5noxy6aaa ``` -------------------------------- ### Set up a router for blob connections Source: https://docs.iroh.computer/protocols/blobs Configures and spawns a router that accepts incoming blob connections and routes them to the blobs protocol. It also handles graceful shutdown. ```rs // For sending files we build a router that accepts blobs connections & // routes them to the blobs protocol. let router = Router::builder(endpoint) .accept(iroh_blobs::ALPN, blobs) .spawn(); tokio::signal::ctrl_c().await?; // Gracefully shut down the endpoint println!("Shutting down."); router.shutdown().await?; ``` -------------------------------- ### Run callme demo: Connect to Peer Source: https://docs.iroh.computer/protocols/streaming Connects the callme CLI client to another peer's address. Replace with the actual address. Ensure you are in the callme/callme-cli directory. ```bash cd callme/callme-cli cargo run --release -- --connect ``` -------------------------------- ### Initialize JavaScript Project for Ping Pong Source: https://docs.iroh.computer/connect-two-endpoints Sets up a new JavaScript project using npm, configures it to use ES modules, and installs the Iroh package. This prepares the environment for the JavaScript ping program. ```bash mkdir ping-pong && cd ping-pong npm init -y npm pkg set type=module npm install @number0/iroh # work in main.mjs ``` -------------------------------- ### Install iroh-blobs Dependency Source: https://docs.iroh.computer/protocols/blobs Add the iroh-blobs crate to your project's dependencies using Cargo. ```bash cargo add iroh-blobs ``` -------------------------------- ### Initialize Swift Project for Ping Pong Source: https://docs.iroh.computer/connect-two-endpoints Initializes a new Swift executable project and outlines the steps to add the Iroh-FFI library as a dependency in the Package.swift file. This is for setting up the Swift ping program. ```bash swift package init --type executable --name ping-pong cd ping-pong # add to Package.swift dependencies: # .package(url: "https://github.com/n0-computer/iroh-ffi", from: "1.0.0") # and to your target dependencies: # .product(name: "IrohLib", package: "iroh-ffi") # work in Sources/ping-pong/main.swift ``` -------------------------------- ### Connect Endpoint to Iroh Services (Kotlin) Source: https://docs.iroh.computer/iroh-services/quickstart Set up an Iroh endpoint, wait for it to be online, and then create the Iroh Services client, supplying your API secret and a descriptive name. ```kotlin import computer.iroh.* import kotlinx.coroutines.runBlocking fun main() = runBlocking { val endpoint = Endpoint.bind(EndpointOptions(preset = presetN0())) endpoint.online() val client = ServicesClient.create( endpoint, ServicesOptions(apiSecret = "YOUR_API_KEY", name = "my-endpoint"), ) // Your endpoint is now reporting metrics to Iroh Services! } ``` -------------------------------- ### Add futures-lite Crate Source: https://docs.iroh.computer/examples/chat Install the futures-lite crate to simplify handling asynchronous streams in your Rust project. ```bash cargo add futures-lite ``` -------------------------------- ### Add iroh-nym-transport Dependency Source: https://docs.iroh.computer/transports/nym Install the Nym transport crate for Iroh. This is the first step to enable Nym integration. ```bash cargo add iroh-nym-transport ``` -------------------------------- ### Add Additional Iroh Dependencies Source: https://docs.iroh.computer/languages/rust Install extra crates for tickets, common protocols, and async runtime support. ```bash cargo add iroh-tickets iroh-ping anyhow cargo add tokio --features full ``` -------------------------------- ### Configure endpoint with custom DNS server Source: https://docs.iroh.computer/connecting/dns-address-lookup This example shows how to configure an endpoint to use a custom DNS server for publishing and resolving records. It uses `PkarrPublisher` for publishing and `DnsAddressLookup` for resolving, both pointed to a custom server URL and domain. ```rust use iroh::{ Endpoint, address_lookup::{DnsAddressLookup, PkarrPublisher}, endpoint::presets, }; use url::Url; #[tokio::main] async fn main() -> anyhow::Result<()> { let pkarr_relay: Url = "https://my-dns-server.example/pkarr".parse()?; let origin_domain = "my-dns-server.example".to_string(); let endpoint = Endpoint::builder(presets::Minimal) .address_lookup(PkarrPublisher::builder(pkarr_relay)) .address_lookup(DnsAddressLookup::builder(origin_domain)) .bind() .await?; // your code here Ok(()) } ``` -------------------------------- ### Run iroh-ping Receiver Source: https://docs.iroh.computer/quickstart Compiles and runs the receiver example for iroh-ping. This will output a connection ticket that the sender will use. ```bash cargo run --example quickstart receiver ``` -------------------------------- ### Run Sender and Receiver in Rust Source: https://docs.iroh.computer/connect-two-endpoints Start the receiver in one terminal and the sender in another, using a ticket generated by the receiver. ```bash # terminal 1 cargo run -- receiver # terminal 2 cargo run -- sender ```