Wire up the userspace networking primitives to the JS bridge so
browser callers can initiate outbound and receive inbound traffic
over the Tailscale network:
- ipn.dial(network, addr) wraps a tsdial UserDial into a JS Conn
with read/write/close/localAddr/remoteAddr.
- ipn.listen(network, addr) wraps a netstack ListenPacket into a
JS PacketConn with readFrom/writeTo/close/localAddr.
- ipn.listenICMP("icmp4"|"icmp6"|"icmp") creates a raw ICMP
endpoint on the underlying gVisor stack and wraps it as a
PacketConn for sending/receiving ping traffic.
To support listenICMP, netstack.Impl gains a Stack() accessor that
returns the underlying *stack.Stack so jsIPN can call NewEndpoint
with icmp.ProtocolNumber4/6.
Binary I/O uses js.CopyBytesToGo / js.CopyBytesToJS to move bytes
across the syscall/js boundary without base64 round-trips.
After 1d93bdce2 ("control/controlclient: remove x/net/http2, use
net/http"), the noise control client uses net/http's Transport with
Protocols.SetUnencryptedHTTP2(true). The nethttpomithttp2 build tag
strips the bundled HTTP/2 implementation from net/http, so at runtime
the control client fails the first register request with "http:
Transport does not support unencrypted HTTP/2" and the wasm never
connects.
Drop the tag so the bundled HTTP/2 ships in the wasm binary.