Skip to content

Fix generic iOS DNS-SD advertise binding/blackholing the service port #366

Description

@momics

Workstream E of the PR #350 follow-up re-review. The iOS-specific generic DNS-SD advertise blocker found against head a77e9c9. Needs an iOS device to verify. Tracked under #361.

Summary

The generic DNS-SD advertise() API is contracted as "advertise an existing service on this port" (matching Android and desktop). The iOS implementation instead creates an NWListener on that port, taking over the socket. If the application's own service already owns the port, registration fails with an address conflict; if the port was free, the plugin advertises a listener whose newConnectionHandler immediately cancels every incoming connection — a blackhole that rejects every client rather than surfacing the caller's real service.

Evidence

Head a77e9c9. packages/iroh-http-tauri/ios/Sources/IrohHttpPlugin.swift:522-550 — generic advertise creates an NWListener bound to the advertised port and its newConnectionHandler cancels connections. Contrast the Android/desktop generic path, which publishes a record for an already-listening service without binding the socket (see #365 evidence for the cross-adapter generic path).

Impact

Generic advertise() on iOS is unusable for its stated purpose: either it fails to register (port already owned by the real service) or it advertises a black hole (port free → every client connection cancelled). Semantics diverge from Android/desktop and the spec.

Remediation

Use a Bonjour registration mechanism that publishes an existing service without taking over its socket (e.g. NetService/DNSServiceRegister-style advertisement of an external port), or redesign the iOS API so the plugin explicitly owns and forwards the service. Align the generic-advertise contract across all three platforms as part of #365's boundary definition.

Acceptance criteria

  1. On iOS, advertise() publishes a DNS-SD record for a service the application already listens on, without binding or hijacking the port.
  2. An integration test with a real server already listening on the advertised port shows: registration succeeds and a browsing peer can connect to the real service (no blackhole, no address conflict).
  3. Generic-advertise semantics match Android and desktop (consistent with the boundary encoding defined in Redesign discovery to source-scoped ownership with explicit terminal status #365).

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium prioritybugSomething isn't workingconnectivityPeer discovery and connection

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions