lb and ln are only initialised during run(); calling shutdown() before
run() panics on nil. Guard both fields before dereferencing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
netstack.ListenTCP requires a full host:port address; callers passing
the standard net.Listen form (":0" for any-interface ephemeral port)
would get ParseAddrPort error. Prepend "0.0.0.0" when the address
starts with ":" so the API matches Go's net.Listen behaviour.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each call to newIPN() starts an independent Go backend that calls
safesocket.Listen() to serve the ipnserver IPC channel. Because
memName was a global constant, the second instance would fail with
"addr unavailable" and log.Fatal the whole WASM process.
Use an atomic counter to give each listener a distinct name
(Tailscale-IPN-1, Tailscale-IPN-2, …). The connect() path is
unchanged: in the wasm/tsconnect build all LocalAPI calls go through
the in-process httptest handler, so connect() is never called.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>