Skip to content

iOS advertises a port-less direct address → peers reject it ("invalid socket address syntax") #346

Description

@momics

Summary

On real hardware, an iOS iroh-http node advertises a direct address with no port, so any peer that tries to dial it by that direct address fails to parse it. During the cross-device interop pass, every Android→iOS request failed at dial time with invalid direct address "192.168.50.227": invalid socket address syntax. iOS→Android worked (Android's address is well-formed), so this is specific to the address iOS publishes/derives.

Evidence

On-device interop pass, iPhone 12 Pro (iOS 26.5.2, pk jgx7h4nts7hw5rrpsfdfrjilp6dgtlu7pezpyaqrcq3rebdmnsva, LAN 192.168.50.227) ↔ Nokia 7.2 (Android, pk hplvecpuhm7z6opfsttj32qd3mgawfhsu363ieu4g74crobiy2qq), integration branch momics-interop-device-integration.

Android-as-client interop JSON (IROH_INTEROP_LOG, reproduced identically across two runs):

{"summary":{"total":104,"passed":0,"failed":104},
 "cases":[
   {"id":"self-loopback","ok":false,"status":200,"error":"bodyExact: expected \"hello\", got \"\""},
   {"id":"status-200","ok":false,"status":null,"error":"invalid direct address \"192.168.50.227\": invalid socket address syntax"},
   ... every remaining case: same "invalid direct address" error ...
 ]}
  • self-loopback (Android→Android) reaches status:200 — transport fine; that empty body is a separate issue (Tauri Android: serve() response bodies arrive empty (Android System WebView returns no body stream) #338).
  • Every case targeting the iOS peer fails with invalid direct address "192.168.50.227": invalid socket address syntax. The address is a bare IPv4 with no :port.
  • The iPhone's real QUIC socket IS bound to a port — iOS syslog: symptomsd NetworkStatistics: Unexpected UDP local address on flow … now 192.168.50.227:59234 for eu.momics.iroh-http-tauri-example-app. So the socket is 192.168.50.227:59234, but the address handed to dialers is port-less (port 0 / stripped).
  • Matches the earlier Verify DNS-SD discovery on real iOS and Android devices #334 code finding: "iOS re-emit snapshot is txt+addrs only, port always 0."

Evidence log archived in session artifact files/device-pass/android-evidence.log (full IROH_INTEROP JSON ×2 + pipe errors).

Impact

P1 — blocks all cross-device connectivity to iOS nodes on the LAN path. No peer can dial an iOS iroh-http node via its advertised direct address; the address fails SocketAddr parsing before a connection is even attempted. iOS is effectively undiallable over direct LAN addresses (it can still act as a client, and relay/hole-punch paths that don't use this address may differ). Surfaced by the #340 interop harness on real hardware; would not appear in simulator/desktop-only testing.

Remediation

Investigate where the iOS node's direct addresses are collected/serialized and why the port is 0/absent:

  • Confirm whether the port is lost when iOS enumerates local interface addresses (the re-emit snapshot carries addrs with port = 0), vs. lost in how we build the NodeAddr / direct-address list handed to iroh.
  • The bound QUIC socket clearly has a real port (:59234 in syslog); ensure that bound port is propagated into every published/derived direct address (DNS-SD TXT/SRV and any in-process address list), not defaulted to 0.
  • Add a guard/log: reject or warn on any direct address with port 0 before it reaches the dialer, so this fails loudly instead of as an opaque parse error.

Acceptance criteria

  • An iOS node's advertised/derived direct addresses all carry the real bound UDP port (never 0).
  • Cross-device interop pass: Android→iOS cases no longer fail with invalid socket address syntax; the suite proceeds to real per-case results (transport reaches the iOS responder).
  • Regression coverage for the address-construction path asserting port ≠ 0 for a bound endpoint.

Priority

P1 — blocks users or breaks protocol

Area

connectivity

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High prioritybugSomething isn't workingconnectivityPeer discovery and connection

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions