diff --git a/Dockerfile b/Dockerfile index 14d5d06677fa1..80412f4c66b48 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,7 +46,7 @@ RUN go install \ gvisor.dev/gvisor/pkg/tcpip/stack \ golang.org/x/crypto/ssh \ golang.org/x/crypto/acme \ - nhooyr.io/websocket \ + github.com/coder/websocket \ github.com/mdlayher/netlink COPY . . diff --git a/cmd/derper/websocket.go b/cmd/derper/websocket.go index 3f0c4bd0e4e26..25ddfb292dbb0 100644 --- a/cmd/derper/websocket.go +++ b/cmd/derper/websocket.go @@ -10,9 +10,8 @@ import ( "net/http" "strings" - "nhooyr.io/websocket" + "github.com/coder/websocket" "tailscale.com/derp" - "tailscale.com/net/wsconn" ) var counterWebSocketAccepts = expvar.NewInt("derp_websocket_accepts") @@ -50,7 +49,7 @@ func addWebSocketSupport(s *derp.Server, base http.Handler) http.Handler { return } counterWebSocketAccepts.Add(1) - wc := wsconn.NetConn(r.Context(), c, websocket.MessageBinary) + wc := websocket.NetConn(r.Context(), c, websocket.MessageBinary) brw := bufio.NewReadWriter(bufio.NewReader(wc), bufio.NewWriter(wc)) s.Accept(r.Context(), wc, brw, r.RemoteAddr) }) diff --git a/control/controlhttp/client_js.go b/control/controlhttp/client_js.go index 5a4b4d08b1b29..c4eb323f8ca04 100644 --- a/control/controlhttp/client_js.go +++ b/control/controlhttp/client_js.go @@ -10,9 +10,8 @@ import ( "net" "net/url" - "nhooyr.io/websocket" + "github.com/coder/websocket" "tailscale.com/control/controlbase" - "tailscale.com/net/wsconn" ) // Variant of Dial that tunnels the request over WebSockets, since we cannot do @@ -51,7 +50,7 @@ func (d *Dialer) Dial(ctx context.Context) (*ClientConn, error) { if err != nil { return nil, err } - netConn := wsconn.NetConn(context.Background(), wsConn, websocket.MessageBinary) + netConn := websocket.NetConn(context.Background(), wsConn, websocket.MessageBinary) cbConn, err := cont(ctx, netConn) if err != nil { netConn.Close() diff --git a/control/controlhttp/server.go b/control/controlhttp/server.go index d49e32c1da14c..940680f6b4a62 100644 --- a/control/controlhttp/server.go +++ b/control/controlhttp/server.go @@ -14,10 +14,9 @@ import ( "strings" "time" - "nhooyr.io/websocket" + "github.com/coder/websocket" "tailscale.com/control/controlbase" "tailscale.com/net/netutil" - "tailscale.com/net/wsconn" "tailscale.com/types/key" ) @@ -146,7 +145,7 @@ func acceptWebsocket(ctx context.Context, w http.ResponseWriter, r *http.Request return nil, fmt.Errorf("decoding base64 handshake parameter: %v", err) } - conn := wsconn.NetConn(ctx, c, websocket.MessageBinary) + conn := websocket.NetConn(ctx, c, websocket.MessageBinary) nc, err := controlbase.Server(ctx, conn, private, init) if err != nil { conn.Close() diff --git a/derp/derphttp/derphttp_test.go b/derp/derphttp/derphttp_test.go index 01ee561db0e22..13e8c95599e7d 100644 --- a/derp/derphttp/derphttp_test.go +++ b/derp/derphttp/derphttp_test.go @@ -15,9 +15,8 @@ import ( "testing" "time" - "nhooyr.io/websocket" + "github.com/coder/websocket" "tailscale.com/derp" - "tailscale.com/net/wsconn" "tailscale.com/types/key" ) @@ -229,7 +228,7 @@ func TestHTTP2OnlyServer(t *testing.T) { return } defer c.Close(websocket.StatusInternalError, "closing") - wc := wsconn.NetConn(context.Background(), c, websocket.MessageBinary) + wc := websocket.NetConn(context.Background(), c, websocket.MessageBinary) brw := bufio.NewReadWriter(bufio.NewReader(wc), bufio.NewWriter(wc)) s.Accept(context.Background(), wc, brw, r.RemoteAddr) })) @@ -289,7 +288,7 @@ func TestForceWebsockets(t *testing.T) { return } defer c.Close(websocket.StatusInternalError, "closing") - wc := wsconn.NetConn(context.Background(), c, websocket.MessageBinary) + wc := websocket.NetConn(context.Background(), c, websocket.MessageBinary) brw := bufio.NewReadWriter(bufio.NewReader(wc), bufio.NewWriter(wc)) s.Accept(context.Background(), wc, brw, r.RemoteAddr) })) diff --git a/derp/derphttp/websocket.go b/derp/derphttp/websocket.go index 005d16914802c..89c281b3dd432 100644 --- a/derp/derphttp/websocket.go +++ b/derp/derphttp/websocket.go @@ -11,8 +11,7 @@ import ( "net" "net/http" - "nhooyr.io/websocket" - "tailscale.com/net/wsconn" + "github.com/coder/websocket" ) func init() { @@ -35,6 +34,6 @@ func dialWebsocket(ctx context.Context, urlStr string, tlsConfig *tls.Config, ht return nil, err } // log.Printf("websocket: connected to %v", urlStr) - netConn := wsconn.NetConn(context.Background(), c, websocket.MessageBinary) + netConn := websocket.NetConn(context.Background(), c, websocket.MessageBinary) return netConn, nil } diff --git a/derp/derphttp/websocket_js.go b/derp/derphttp/websocket_js.go index 5f0ff3f4a042a..07c09f8d95d96 100644 --- a/derp/derphttp/websocket_js.go +++ b/derp/derphttp/websocket_js.go @@ -12,8 +12,7 @@ import ( "net" "net/http" - "nhooyr.io/websocket" - "tailscale.com/net/wsconn" + "github.com/coder/websocket" ) func init() { @@ -29,6 +28,6 @@ func dialWebsocket(ctx context.Context, urlStr string, _ *tls.Config, _ http.Hea return nil, err } log.Printf("websocket: connected to %v", urlStr) - netConn := wsconn.NetConn(context.Background(), c, websocket.MessageBinary) + netConn := websocket.NetConn(context.Background(), c, websocket.MessageBinary) return netConn, nil } diff --git a/go.mod b/go.mod index 71607e2425f05..4bebe5f1aedb5 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module tailscale.com -go 1.22.1 +go 1.22.8 require ( filippo.io/mkcert v1.4.4 @@ -14,6 +14,7 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.64 github.com/aws/aws-sdk-go-v2/service/s3 v1.33.0 github.com/aws/aws-sdk-go-v2/service/ssm v1.36.3 + github.com/coder/websocket v1.8.12 github.com/coreos/go-iptables v0.6.0 github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf github.com/creack/pty v1.1.18 @@ -94,7 +95,6 @@ require ( k8s.io/api v0.27.2 k8s.io/apimachinery v0.27.2 k8s.io/client-go v0.27.2 - nhooyr.io/websocket v1.8.7 sigs.k8s.io/controller-runtime v0.15.0 sigs.k8s.io/yaml v1.3.0 software.sslmate.com/src/go-pkcs12 v0.2.0 diff --git a/go.sum b/go.sum index 4c6ee062a1500..cb0470bed43f0 100644 --- a/go.sum +++ b/go.sum @@ -213,6 +213,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo= +github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -303,10 +305,6 @@ github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrt github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/github/fakeca v0.1.0 h1:Km/MVOFvclqxPM9dZBC4+QE564nU4gz4iZ0D9pMw28I= github.com/github/fakeca v0.1.0/go.mod h1:+bormgoGMMuamOscx7N91aOuUST7wdaJ2rNjeohylyo= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= @@ -352,13 +350,6 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= -github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= @@ -395,12 +386,6 @@ github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80 github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= @@ -541,8 +526,6 @@ github.com/goreleaser/fileglob v0.3.1 h1:OTFDWqUUHjQazk2N5GdUqEbqT/grBnRARaAXsV0 github.com/goreleaser/fileglob v0.3.1/go.mod h1:kNcPrPzjCp+Ox3jmXLU5QEsjhqrtLBm6OnXAif8KRl8= github.com/goreleaser/nfpm v1.10.3 h1:NzpWKKzSFr7JOn55XN0SskyFOjP6BkvRt3JujoX8fws= github.com/goreleaser/nfpm v1.10.3/go.mod h1:EEC7YD5wi+ol0MiAshpgPANBOkjXDl7wqTLVk68OBsk= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= @@ -646,7 +629,6 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX github.com/jsimonetti/rtnetlink v1.3.2 h1:dcn0uWkfxycEEyNy0IGfx3GrhQ38LH7odjxAghimsVI= github.com/jsimonetti/rtnetlink v1.3.2/go.mod h1:BBu4jZCpTjP6Gk0/wfrO8qcqymnN3g0hoFqObRmUo6U= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -675,7 +657,6 @@ github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkHAIKE/contextcheck v1.1.4 h1:B6zAaLhOEEcjvUgIYEqystmnFk1Oemn8bvJhbt0GMb8= github.com/kkHAIKE/contextcheck v1.1.4/go.mod h1:1+i/gWqokIa+dm31mqGLZhZJ7Uh44DJGZVmr6QRBNJg= -github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= @@ -712,8 +693,6 @@ github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUc github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= github.com/ldez/tagliatelle v0.5.0 h1:epgfuYt9v0CG3fms0pEgIMNPuFf/LpPIfjk4kyqSioo= github.com/ldez/tagliatelle v0.5.0/go.mod h1:rj1HmWiL1MiKQuOONhd09iySTEkUuE/8+5jtPYz9xa4= -github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -1113,10 +1092,6 @@ github.com/u-root/u-root v0.11.0 h1:6gCZLOeRyevw7gbTwMj3fKxnr9+yHFlgF3N7udUVNO8= github.com/u-root/u-root v0.11.0/go.mod h1:DBkDtiZyONk9hzVEdB/PWI9B4TxDkElWlVTHseglrZY= github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 h1:YcojQL98T/OO+rybuzn2+5KrD5dBwXIvYBvQ2cD3Avg= github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= -github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= @@ -1773,8 +1748,6 @@ mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jC mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7/go.mod h1:HGC5lll35J70Y5v7vCGb9oLhHoScFwkHDJm/05RdSTc= mvdan.cc/unparam v0.0.0-20230312165513-e84e2d14e3b8 h1:VuJo4Mt0EVPychre4fNlDWDuE5AjXtPJpRUWqZDQhaI= mvdan.cc/unparam v0.0.0-20230312165513-e84e2d14e3b8/go.mod h1:Oh/d7dEtzsNHGOq1Cdv8aMm3KdKhVvPbRQcM8WFpBR8= -nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= -nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= diff --git a/net/wsconn/wsconn.go b/net/wsconn/wsconn.go deleted file mode 100644 index 697b66ddde472..0000000000000 --- a/net/wsconn/wsconn.go +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright (c) Tailscale Inc & AUTHORS -// SPDX-License-Identifier: BSD-3-Clause - -// Package wsconn contains an adapter type that turns -// a websocket connection into a net.Conn. It a temporary fork of the -// netconn.go file from the nhooyr.io/websocket package while we wait for -// https://github.com/nhooyr/websocket/pull/350 to be merged. -package wsconn - -import ( - "context" - "fmt" - "io" - "math" - "net" - "os" - "sync" - "sync/atomic" - "time" - - "nhooyr.io/websocket" -) - -// NetConn converts a *websocket.Conn into a net.Conn. -// -// It's for tunneling arbitrary protocols over WebSockets. -// Few users of the library will need this but it's tricky to implement -// correctly and so provided in the library. -// See https://github.com/nhooyr/websocket/issues/100. -// -// Every Write to the net.Conn will correspond to a message write of -// the given type on *websocket.Conn. -// -// The passed ctx bounds the lifetime of the net.Conn. If cancelled, -// all reads and writes on the net.Conn will be cancelled. -// -// If a message is read that is not of the correct type, the connection -// will be closed with StatusUnsupportedData and an error will be returned. -// -// Close will close the *websocket.Conn with StatusNormalClosure. -// -// When a deadline is hit, the connection will be closed. This is -// different from most net.Conn implementations where only the -// reading/writing goroutines are interrupted but the connection is kept alive. -// -// The Addr methods will return a mock net.Addr that returns "websocket" for Network -// and "websocket/unknown-addr" for String. -// -// A received StatusNormalClosure or StatusGoingAway close frame will be translated to -// io.EOF when reading. -func NetConn(ctx context.Context, c *websocket.Conn, msgType websocket.MessageType) net.Conn { - nc := &netConn{ - c: c, - msgType: msgType, - } - - var writeCancel context.CancelFunc - nc.writeContext, writeCancel = context.WithCancel(ctx) - nc.writeTimer = time.AfterFunc(math.MaxInt64, func() { - nc.afterWriteDeadline.Store(true) - if nc.writing.Load() { - writeCancel() - } - }) - if !nc.writeTimer.Stop() { - <-nc.writeTimer.C - } - - var readCancel context.CancelFunc - nc.readContext, readCancel = context.WithCancel(ctx) - nc.readTimer = time.AfterFunc(math.MaxInt64, func() { - nc.afterReadDeadline.Store(true) - if nc.reading.Load() { - readCancel() - } - }) - if !nc.readTimer.Stop() { - <-nc.readTimer.C - } - - return nc -} - -type netConn struct { - c *websocket.Conn - msgType websocket.MessageType - - writeTimer *time.Timer - writeContext context.Context - writing atomic.Bool - afterWriteDeadline atomic.Bool - - readTimer *time.Timer - readContext context.Context - reading atomic.Bool - afterReadDeadline atomic.Bool - - readMu sync.Mutex - eofed bool - reader io.Reader -} - -var _ net.Conn = &netConn{} - -func (c *netConn) Close() error { - return c.c.Close(websocket.StatusNormalClosure, "") -} - -func (c *netConn) Write(p []byte) (int, error) { - if c.afterWriteDeadline.Load() { - return 0, os.ErrDeadlineExceeded - } - - if swapped := c.writing.CompareAndSwap(false, true); !swapped { - panic("Concurrent writes not allowed") - } - defer c.writing.Store(false) - - err := c.c.Write(c.writeContext, c.msgType, p) - if err != nil { - return 0, err - } - - return len(p), nil -} - -func (c *netConn) Read(p []byte) (int, error) { - if c.afterReadDeadline.Load() { - return 0, os.ErrDeadlineExceeded - } - - c.readMu.Lock() - defer c.readMu.Unlock() - if swapped := c.reading.CompareAndSwap(false, true); !swapped { - panic("Concurrent reads not allowed") - } - defer c.reading.Store(false) - - if c.eofed { - return 0, io.EOF - } - - if c.reader == nil { - typ, r, err := c.c.Reader(c.readContext) - if err != nil { - switch websocket.CloseStatus(err) { - case websocket.StatusNormalClosure, websocket.StatusGoingAway: - c.eofed = true - return 0, io.EOF - } - return 0, err - } - if typ != c.msgType { - err := fmt.Errorf("unexpected frame type read (expected %v): %v", c.msgType, typ) - c.c.Close(websocket.StatusUnsupportedData, err.Error()) - return 0, err - } - c.reader = r - } - - n, err := c.reader.Read(p) - if err == io.EOF { - c.reader = nil - err = nil - } - return n, err -} - -type websocketAddr struct { -} - -func (a websocketAddr) Network() string { - return "websocket" -} - -func (a websocketAddr) String() string { - return "websocket/unknown-addr" -} - -func (c *netConn) RemoteAddr() net.Addr { - return websocketAddr{} -} - -func (c *netConn) LocalAddr() net.Addr { - return websocketAddr{} -} - -func (c *netConn) SetDeadline(t time.Time) error { - c.SetWriteDeadline(t) - c.SetReadDeadline(t) - return nil -} - -func (c *netConn) SetWriteDeadline(t time.Time) error { - if t.IsZero() { - c.writeTimer.Stop() - } else { - c.writeTimer.Reset(time.Until(t)) - } - c.afterWriteDeadline.Store(false) - return nil -} - -func (c *netConn) SetReadDeadline(t time.Time) error { - if t.IsZero() { - c.readTimer.Stop() - } else { - c.readTimer.Reset(time.Until(t)) - } - c.afterReadDeadline.Store(false) - return nil -} diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index d9eb2cd12d206..c753a7266b916 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -39,7 +39,6 @@ import ( "golang.org/x/net/icmp" "golang.org/x/net/ipv4" "golang.org/x/net/ipv6" - "nhooyr.io/websocket" "tailscale.com/cmd/testwrapper/flakytest" "tailscale.com/derp" "tailscale.com/derp/derphttp" @@ -51,7 +50,6 @@ import ( "tailscale.com/net/ping" "tailscale.com/net/stun/stuntest" "tailscale.com/net/tstun" - "tailscale.com/net/wsconn" "tailscale.com/tailcfg" "tailscale.com/tstest" "tailscale.com/tstest/natlab" @@ -68,6 +66,8 @@ import ( "tailscale.com/wgengine/wgcfg" "tailscale.com/wgengine/wgcfg/nmcfg" "tailscale.com/wgengine/wglog" + + "github.com/coder/websocket" ) func init() { @@ -2927,7 +2927,7 @@ func addWebSocketSupport(s *derp.Server, base http.Handler) http.Handler { c.Close(websocket.StatusPolicyViolation, "client must speak the derp subprotocol") return } - wc := wsconn.NetConn(r.Context(), c, websocket.MessageBinary) + wc := websocket.NetConn(r.Context(), c, websocket.MessageBinary) brw := bufio.NewReadWriter(bufio.NewReader(wc), bufio.NewWriter(wc)) s.Accept(r.Context(), wc, brw, r.RemoteAddr) })