mirror of
https://github.com/tailscale/tailscale.git
synced 2026-06-11 21:02:39 +08:00
WARNING: this is an unreviewed prototype; please do not assume this works or is correct Bring the tsnet2 skeleton from the previous commit to a passing TestTsnet2EndToEnd integration test (~8s on a recent Linux box). Architecture follows PLAN.tsnet2.md: - cmd/tsnet2d/daemon/ stands up wgengine + magicsock + netstack + ipnlocal.LocalBackend + localapi.NewHandler exactly the way tsnet/tsnet.go does, against the daemon's state dir. - The daemon listens on a Unix socket. Each conn opens with a 1-byte channel-kind handshake (control / localapi / datapath / accept). - Control channel: newline-delimited JSON RPC for Start, Up, Close, TailscaleIPs, CertDomains, RegisterListener, UnregisterListener. - LocalAPI channel: the daemon wraps the conn in a one-shot net.Listener and serves http.Server.Serve on it with the localapi handler — preserves Hijacker/Flusher semantics for streaming endpoints. Server.LocalClient() returns *local.Client with Dial pointed at this channel so WhoIs / Status / WatchIPNBus etc. all work for free. - Datapath channel: outbound dial flows. Client writes a one-line JSON header, daemon UserDials, then bytes are spliced and tee'd into the traffic logger. - Accept channel (parked-worker model): each tsnet2 listener pre- parks K accept-channel conns; the daemon's GetTCPHandlerForFlow hands inbound netstack flows to the next parked slot, writes a metadata header, and streams cleartext bytes. Chose this over the daemon-dials-back-to-app pattern in PLAN.tsnet2.md because it avoids requiring the app to bind a second socket. - tsnet2/traffic emits the JSONL schema from the plan (open/data/ close) with WhoIs enrichment on inbound opens and 16 KiB payload chunking on data records. Deferred (per plan v2): ListenPacket/UDP, ListenFunnel, ListenService, Loopback, fallback TCP handlers (registered as a no-op for API compat), peercred auth on the Unix socket (TODO), daemon-restart re-registration of listeners. Server struct keeps its mutable state behind a plain pointer field guarded by a package-level mutex so the value-type Server stays copy-friendly — the smoke test reflects over *Server and would trip the vet lock-copy check if we embedded sync.Mutex/sync.Once directly. |
||
|---|---|---|
| .. | ||
| internal/clientsock | ||
| proto | ||
| traffic | ||
| conn.go | ||
| doc.go | ||
| integration_test.go | ||
| listener.go | ||
| localclient.go | ||
| tsnet2_test.go | ||
| tsnet2.go | ||