Skip to content

Adopt the synthetic wasi:sockets surface + routing hooks from polymorph-iroh into wasi-shims #74

Description

@lann

Context

polymorph-iroh retired jco — deltic is their JS leg on main (their #40/#41) — and their upstream-iroh experiments run on a consumer-side synthetic-network provider written in our embedder conventions (experiments/iroh-relay-ws/host/sockets.ts, 438 lines): queue-backed UdpSocket + datagram streams, four routing hooks (registerBridge/registerAddrRoute/socketByLocalPort/pushDatagram), typed WitError stubs for tcp/ip-name-lookup, spread-after-wasiShims() overrides.

This issue tracks adopting the socket surface + hooks into wasi-shims as a sockets() fragment, reversing the earlier "sockets out of deltic" ruling if/when we choose to. The transports/bridges (relay DatagramPipe, WebRTC overlay, address-allocation policy) stay theirs regardless.

Why adopt (when we do)

  • They're the flagship deltic consumer now; the surface is generic WASI (any tokio/libc guest doing UDP over virtual transports), and a second implementation already exists — the question is only who maintains it. Spec-shaped surface with a library-grade state model is our competence; their transports are theirs.
  • Their implementation is experiment-grade in three ways a library must fix: module-global state (bridges/routes/port maps as module-level maps — two synthetic networks in one process collide; adoption = instance-scoped SyntheticNetwork), lifecycle gaps (empty Symbol.dispose, no socketsByPort cleanup, ephemeral-port wraparound), and a bridge-specific overlayOwner field baked into the socket class.
  • Testing division stays clean post-exam-retirement: deltic ships the fragment with self-contained pins (extend wasi-shims/tests/testdata/blocking-guest.wat with a UDP echo through a test bridge); no consumer artifacts in our gates; their experiments consume the fragment in their repo.

Sequencing / prerequisites

  1. First (their side, unblocked by deltic#71): on their next deltic pin bump, their tier-(c) Pollable/poll/monotonic-clock overrides (~200 lines) should be deleted in favor of the wasi-shims parking kernel — theirs are async functions that suspend on every call (no sync fast paths, pin-(j) hop each time), and their duck-typed PollableLike seam exists only because two Pollable classes coexist. Recorded as IROH-2 in upstream-consumer-findings.md; filing upstream is the operator's call.
  2. Then adopt the socket surface + hooks here, coordinated so they swap once (kernel + fragment together), not twice.

Scope sketch (~a day when picked up)

  • wasi-shims/src/sockets.ts: instance-scoped SyntheticNetwork (owns routes/ports/queues) + sockets({network}) fragment; udp real (kernel Pollables via the public constructor seam), tcp + ip-name-lookup as typed WitError stubs; hooks as methods on the network instance.
  • Fixes by construction: dispose cleanup, port-collision behavior, fast paths (inherited from the kernel), extension point replacing overlayOwner.
  • Pins: UDP echo through a test bridge driven by the blocking-guest fixture; hook routing (port vs addr precedence); multi-tenant isolation (two networks, no crosstalk).
  • Contract: embedder-api WASI-examination note; consumers.md row.

Not in scope

p3 wasi:sockets providers (real UDP over Deno.listenDatagram, the direct-path leg) — that's #4.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestp2Minor bugs; desirable lower-priority features

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions