internal/link and internal/link/direct were a single-implementation
abstraction layer where directLink mechanically proxied every method to
transport.Transport — only Features() lived above transport.Transport,
and even that was a Features() alias. Six layers of plumbing for zero
behavioural value.
Drop the layer entirely:
- muxconn.Conn now takes a transport.Transport directly.
- server.Server and client.Client store transport.Transport, call
transport.New, and expose Features() through transport.Transport's
built-in method.
- server.Config and client.Config lose their Link string field.
- session.Config loses Link + validateLink + ErrLinkRequired/ErrUnsupportedLink.
- config.File and config.Profile lose the link YAML key.
- pkg/olcrtc/tunnel.Config loses Link.
- mobile drops defaultLink, SetLink, and mobileConfig.link.
Two e2e tests that exercised link.New directly are renamed to call
transport.New (TestTransportCreatesAllProviderTransportCombinations and
TestTransportConnectsFastProviderTransportMatrix); behaviour is unchanged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace the hand-rolled multiplexer (internal/mux) with xtaci/smux v2
running on top of the existing KCP-reliable vp8channel transport.
- Add internal/muxconn: io.ReadWriteCloser adapter bridging link.Link
(message-oriented) into the byte-stream smux expects; applies AEAD
on every write and inverts it on every received message
- Rewrite client: smux.Client session over muxconn; OpenStream per
SOCKS5 connection; reconnect handler tears down and rebuilds session
- Rewrite server: smux.Server session; AcceptStream loop dispatches
each stream to a proxy handler; tolerates session bounces on reconnect
- Delete internal/mux: all sequence/reorder/buffer logic is now
handled by smux + KCP