You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bring mobile (iOS/Android) iroh peer discovery to parity with desktop by feeding natively-discovered peers into an in-process iroh AddressLookup registered on the endpoint, so a mobile node can auto-dial a discovered iroh peer by node-id alone — exactly as desktop does today.
Scope reset (see ADR-016). This epic previously proposed a standards-compliant, general DNS-SD layer (browse/advertise arbitrary non-iroh services, custom TXT schema, dns-sd/avahi-browse interop). ADR-016 rejects that direction: iroh-http stays lean and iroh-only. advertise/browse remain scoped to iroh peers and continue to map onto the official iroh-mdns-address-lookup crate's advertise() / subscribe(). General DNS-SD, if ever wanted, belongs in a separate package outside iroh-http. Desktop is unchanged; the only remaining work is the mobile bridge below. The rejected general-DNS-SD spike is preserved on branch momics-spike-mdns-sd-addresslookup as the record of why.
Evidence / Motivation
Desktop already auto-dials by node-id.crates/iroh-http-discovery/src/lib.rs:115-122 builds an MdnsAddressLookup and registers it via ep.address_lookup().add(mdns), so iroh's dialer transparently resolves discovered peers by node-id. iroh core's discovery contract is exactly this AddressLookup (publish / resolve-by-node-id) — a targeted resolver that feeds the dialer (verified against iroh 1.0.1 src/address_lookup.rs:333).
Mobile stops at "report to JS".packages/iroh-http-tauri/src/mobile_mdns.rs bridges to NWBrowser/NWListener (iOS) and NsdManager (Android) and surfaces MobileDiscoveryEvent { node_id, addrs } (:97-104) up to the browse API. But nothing feeds those results back into an in-process AddressLookup on the endpoint. Result: on mobile, a discovered peer is only visible as a UI list entry — a subsequent fetch(nodeId) has no address to dial unless the app plumbs addrs through by hand. Desktop needs none of that.
Users: on iOS/Android, discovering an iroh peer over the LAN is enough to then fetch(nodeId) it — no manual address plumbing — matching desktop behaviour.
Existing callers: additive. The serviceName-scoped browse/advertise API and the MobileDiscoveryEvent surface are unchanged; this wires an internal auto-dial path.
Architecture: consistent "discovery feeds the dialer" model across all platforms; mobile joins desktop on iroh's native AddressLookup seam.
Implementation plan
Mobile AddressLookup bridge (Rust, tauri crate). Implement an impl iroh::AddressLookup whose resolve(node_id) yields an Item/EndpointAddr built from the addrs the native layer discovered for that node-id (the data already carried on MobileDiscoveryEvent). Drive it from the existing browse_poll event stream (maintain a node-id → addrs map, updated on discovered, evicted on expired).
Register it on the endpoint via ep.address_lookup().add(...) on mobile targets, the same call desktop makes — so iroh's dialer resolves discovered peers transparently.
Expiry mapping. Honour MobileDiscoveryEvent { kind: "expired" } so stale addrs are dropped from the lookup (desktop gets this from the mdns crate's DiscoveryEvent::Expired).
Keep the browse-to-JS surface intact — the bridge is additive; the discovery event stream to JS continues unchanged.
Honour the core→adapter ripple only if a shared type changes; the expectation is this is contained to the tauri crate (mobile_mdns.rs + endpoint wiring) since desktop already has the pattern.
Acceptance criteria
On iOS and Android, after browse discovers an iroh peer, fetch(nodeId) (or a dial by node-id) connects without the caller supplying addresses — parity with desktop.
Discovered peers are registered on the endpoint's AddressLookup; expired events remove them.
The existing serviceName-scoped browse/advertise API and MobileDiscoveryEvent surface are unchanged (additive only).
Summary
Bring mobile (iOS/Android) iroh peer discovery to parity with desktop by feeding natively-discovered peers into an in-process iroh
AddressLookupregistered on the endpoint, so a mobile node can auto-dial a discovered iroh peer by node-id alone — exactly as desktop does today.Evidence / Motivation
crates/iroh-http-discovery/src/lib.rs:115-122builds anMdnsAddressLookupand registers it viaep.address_lookup().add(mdns), so iroh's dialer transparently resolves discovered peers by node-id. iroh core's discovery contract is exactly thisAddressLookup(publish/resolve-by-node-id) — a targeted resolver that feeds the dialer (verified against iroh 1.0.1src/address_lookup.rs:333).packages/iroh-http-tauri/src/mobile_mdns.rsbridges to NWBrowser/NWListener (iOS) and NsdManager (Android) and surfacesMobileDiscoveryEvent { node_id, addrs }(:97-104) up to the browse API. But nothing feeds those results back into an in-processAddressLookupon the endpoint. Result: on mobile, a discovered peer is only visible as a UI list entry — a subsequentfetch(nodeId)has no address to dial unless the app plumbsaddrsthrough by hand. Desktop needs none of that.pkTXT is present.Impact
fetch(nodeId)it — no manual address plumbing — matching desktop behaviour.serviceName-scoped browse/advertise API and theMobileDiscoveryEventsurface are unchanged; this wires an internal auto-dial path.AddressLookupseam.Implementation plan
AddressLookupbridge (Rust, tauri crate). Implement animpl iroh::AddressLookupwhoseresolve(node_id)yields anItem/EndpointAddrbuilt from the addrs the native layer discovered for that node-id (the data already carried onMobileDiscoveryEvent). Drive it from the existingbrowse_pollevent stream (maintain a node-id → addrs map, updated ondiscovered, evicted onexpired).ep.address_lookup().add(...)on mobile targets, the same call desktop makes — so iroh's dialer resolves discovered peers transparently.MobileDiscoveryEvent { kind: "expired" }so stale addrs are dropped from the lookup (desktop gets this from the mdns crate'sDiscoveryEvent::Expired).Honour the core→adapter ripple only if a shared type changes; the expectation is this is contained to the tauri crate (
mobile_mdns.rs+ endpoint wiring) since desktop already has the pattern.Acceptance criteria
fetch(nodeId)(or a dial by node-id) connects without the caller supplying addresses — parity with desktop.AddressLookup;expiredevents remove them.serviceName-scoped browse/advertise API andMobileDiscoveryEventsurface are unchanged (additive only).fetch(nodeId)succeeds.advertise/browsestay iroh-node-scoped per ADR-016.Priority
P2 — important; mobile discovery is functionally incomplete without it.
Area
connectivity