Skip to content

Commit 887e486

Browse files
committed
TUN-7057: Remove dependency github.com/gorilla/mux
1 parent 645e227 commit 887e486

File tree

28 files changed

+295
-3479
lines changed

28 files changed

+295
-3479
lines changed

carrier/websocket.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/gorilla/websocket"
1010
"github.com/rs/zerolog"
1111

12+
"github.com/cloudflare/cloudflared/stream"
1213
"github.com/cloudflare/cloudflared/token"
1314
cfwebsocket "github.com/cloudflare/cloudflared/websocket"
1415
)
@@ -37,7 +38,7 @@ func (ws *Websocket) ServeStream(options *StartOptions, conn io.ReadWriter) erro
3738
}
3839
defer wsConn.Close()
3940

40-
cfwebsocket.Stream(wsConn, conn, ws.log)
41+
stream.Pipe(wsConn, conn, ws.log)
4142
return nil
4243
}
4344

connection/connection_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/rs/zerolog"
1212

13+
"github.com/cloudflare/cloudflared/stream"
1314
"github.com/cloudflare/cloudflared/tracing"
1415
tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
1516
"github.com/cloudflare/cloudflared/websocket"
@@ -140,7 +141,7 @@ func wsEchoEndpoint(w ResponseWriter, r *http.Request) error {
140141
}()
141142

142143
originConn := &echoPipe{reader: readPipe, writer: writePipe}
143-
websocket.Stream(wsConn, originConn, &log)
144+
stream.Pipe(wsConn, originConn, &log)
144145
cancel()
145146
wsConn.Close()
146147
return nil
@@ -178,7 +179,7 @@ func wsFlakyEndpoint(w ResponseWriter, r *http.Request) error {
178179

179180
closedAfter := time.Millisecond * time.Duration(rand.Intn(50))
180181
originConn := &flakyConn{closeAt: time.Now().Add(closedAfter)}
181-
websocket.Stream(wsConn, originConn, &log)
182+
stream.Pipe(wsConn, originConn, &log)
182183
cancel()
183184
wsConn.Close()
184185
return nil

go.mod

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ require (
1515
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3
1616
github.com/google/gopacket v1.1.19
1717
github.com/google/uuid v1.3.0
18-
github.com/gorilla/mux v1.8.0
1918
github.com/gorilla/websocket v1.4.2
2019
github.com/json-iterator/go v1.1.12
2120
github.com/lucas-clemente/quic-go v0.28.1
@@ -36,10 +35,10 @@ require (
3635
go.opentelemetry.io/proto/otlp v0.15.0
3736
go.uber.org/automaxprocs v1.4.0
3837
golang.org/x/crypto v0.2.0
39-
golang.org/x/net v0.2.0
38+
golang.org/x/net v0.4.0
4039
golang.org/x/sync v0.1.0
41-
golang.org/x/sys v0.2.0
42-
golang.org/x/term v0.2.0
40+
golang.org/x/sys v0.3.0
41+
golang.org/x/term v0.3.0
4342
google.golang.org/protobuf v1.28.0
4443
gopkg.in/coreos/go-oidc.v2 v2.2.1
4544
gopkg.in/natefinch/lumberjack.v2 v2.0.0
@@ -91,7 +90,7 @@ require (
9190
github.com/russross/blackfriday/v2 v2.1.0 // indirect
9291
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
9392
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 // indirect
94-
golang.org/x/text v0.4.0 // indirect
93+
golang.org/x/text v0.5.0 // indirect
9594
golang.org/x/tools v0.1.12 // indirect
9695
google.golang.org/appengine v1.6.7 // indirect
9796
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90 // indirect

go.sum

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,6 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR
357357
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
358358
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
359359
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
360-
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
361360
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
362361
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
363362
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
@@ -744,8 +743,8 @@ golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su
744743
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
745744
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
746745
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
747-
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
748-
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
746+
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
747+
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
749748
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
750749
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
751750
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -869,13 +868,13 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
869868
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
870869
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
871870
golang.org/x/sys v0.0.0-20220808155132-1c4a2a72c664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
872-
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
873-
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
871+
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
872+
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
874873
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
875874
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
876875
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
877-
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
878-
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
876+
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
877+
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
879878
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
880879
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
881880
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -885,8 +884,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
885884
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
886885
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
887886
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
888-
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
889-
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
887+
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
888+
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
890889
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
891890
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
892891
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

ingress/origin_connection.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/cloudflare/cloudflared/ipaccess"
1111
"github.com/cloudflare/cloudflared/socks"
12+
"github.com/cloudflare/cloudflared/stream"
1213
"github.com/cloudflare/cloudflared/websocket"
1314
)
1415

@@ -25,7 +26,7 @@ type streamHandlerFunc func(originConn io.ReadWriter, remoteConn net.Conn, log *
2526
// DefaultStreamHandler is an implementation of streamHandlerFunc that
2627
// performs a two way io.Copy between originConn and remoteConn.
2728
func DefaultStreamHandler(originConn io.ReadWriter, remoteConn net.Conn, log *zerolog.Logger) {
28-
websocket.Stream(originConn, remoteConn, log)
29+
stream.Pipe(originConn, remoteConn, log)
2930
}
3031

3132
// tcpConnection is an OriginConnection that directly streams to raw TCP.
@@ -34,7 +35,7 @@ type tcpConnection struct {
3435
}
3536

3637
func (tc *tcpConnection) Stream(ctx context.Context, tunnelConn io.ReadWriter, log *zerolog.Logger) {
37-
websocket.Stream(tunnelConn, tc.conn, log)
38+
stream.Pipe(tunnelConn, tc.conn, log)
3839
}
3940

4041
func (tc *tcpConnection) Close() {

ingress/origin_connection_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
"github.com/cloudflare/cloudflared/logger"
2424
"github.com/cloudflare/cloudflared/socks"
25+
"github.com/cloudflare/cloudflared/stream"
2526
"github.com/cloudflare/cloudflared/websocket"
2627
)
2728

@@ -50,6 +51,7 @@ func TestStreamTCPConnection(t *testing.T) {
5051
errGroup, ctx := errgroup.WithContext(ctx)
5152
errGroup.Go(func() error {
5253
_, err := eyeballConn.Write(testMessage)
54+
require.NoError(t, err)
5355

5456
readBuffer := make([]byte, len(testResponse))
5557
_, err = eyeballConn.Read(readBuffer)
@@ -158,7 +160,7 @@ func TestSocksStreamWSOverTCPConnection(t *testing.T) {
158160
require.NoError(t, err)
159161
defer wsForwarderInConn.Close()
160162

161-
websocket.Stream(wsForwarderInConn, &wsEyeball{wsForwarderOutConn}, testLogger)
163+
stream.Pipe(wsForwarderInConn, &wsEyeball{wsForwarderOutConn}, testLogger)
162164
return nil
163165
})
164166

metrics/metrics.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"sync"
1111
"time"
1212

13-
"github.com/gorilla/mux"
1413
"github.com/prometheus/client_golang/prometheus"
1514
"github.com/prometheus/client_golang/prometheus/promhttp"
1615
"github.com/rs/zerolog"
@@ -37,10 +36,8 @@ type orchestrator interface {
3736
func newMetricsHandler(
3837
config Config,
3938
log *zerolog.Logger,
40-
) *mux.Router {
41-
router := mux.NewRouter()
42-
router.PathPrefix("/debug/").Handler(http.DefaultServeMux)
43-
39+
) *http.ServeMux {
40+
router := http.NewServeMux()
4441
router.Handle("/metrics", promhttp.Handler())
4542
router.HandleFunc("/healthcheck", func(w http.ResponseWriter, r *http.Request) {
4643
_, _ = fmt.Fprintf(w, "OK\n")

proxy/proxy.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ import (
1616
"github.com/cloudflare/cloudflared/cfio"
1717
"github.com/cloudflare/cloudflared/connection"
1818
"github.com/cloudflare/cloudflared/ingress"
19+
"github.com/cloudflare/cloudflared/stream"
1920
"github.com/cloudflare/cloudflared/tracing"
2021
tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
21-
"github.com/cloudflare/cloudflared/websocket"
2222
)
2323

2424
const (
@@ -257,7 +257,7 @@ func (p *Proxy) proxyHTTPRequest(
257257
reader: tr.Request.Body,
258258
}
259259

260-
websocket.Stream(eyeballStream, rwc, p.log)
260+
stream.Pipe(eyeballStream, rwc, p.log)
261261
return nil
262262
}
263263

stream/stream.go

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package stream
2+
3+
import (
4+
"encoding/hex"
5+
"fmt"
6+
"io"
7+
"runtime/debug"
8+
"sync/atomic"
9+
"time"
10+
11+
"github.com/getsentry/raven-go"
12+
"github.com/pkg/errors"
13+
"github.com/rs/zerolog"
14+
15+
"github.com/cloudflare/cloudflared/cfio"
16+
)
17+
18+
type bidirectionalStreamStatus struct {
19+
doneChan chan struct{}
20+
anyDone uint32
21+
}
22+
23+
func newBiStreamStatus() *bidirectionalStreamStatus {
24+
return &bidirectionalStreamStatus{
25+
doneChan: make(chan struct{}, 2),
26+
anyDone: 0,
27+
}
28+
}
29+
30+
func (s *bidirectionalStreamStatus) markUniStreamDone() {
31+
atomic.StoreUint32(&s.anyDone, 1)
32+
s.doneChan <- struct{}{}
33+
}
34+
35+
func (s *bidirectionalStreamStatus) waitAnyDone() {
36+
<-s.doneChan
37+
}
38+
func (s *bidirectionalStreamStatus) isAnyDone() bool {
39+
return atomic.LoadUint32(&s.anyDone) > 0
40+
}
41+
42+
// Pipe copies copy data to & from provided io.ReadWriters.
43+
func Pipe(tunnelConn, originConn io.ReadWriter, log *zerolog.Logger) {
44+
status := newBiStreamStatus()
45+
46+
go unidirectionalStream(tunnelConn, originConn, "origin->tunnel", status, log)
47+
go unidirectionalStream(originConn, tunnelConn, "tunnel->origin", status, log)
48+
49+
// If one side is done, we are done.
50+
status.waitAnyDone()
51+
}
52+
53+
func unidirectionalStream(dst io.Writer, src io.Reader, dir string, status *bidirectionalStreamStatus, log *zerolog.Logger) {
54+
defer func() {
55+
// The bidirectional streaming spawns 2 goroutines to stream each direction.
56+
// If any ends, the callstack returns, meaning the Tunnel request/stream (depending on http2 vs quic) will
57+
// close. In such case, if the other direction did not stop (due to application level stopping, e.g., if a
58+
// server/origin listens forever until closure), it may read/write from the underlying ReadWriter (backed by
59+
// the Edge<->cloudflared transport) in an unexpected state.
60+
// Because of this, we set this recover() logic.
61+
if r := recover(); r != nil {
62+
if status.isAnyDone() {
63+
// We handle such unexpected errors only when we detect that one side of the streaming is done.
64+
log.Debug().Msgf("Gracefully handled error %v in Streaming for %s, error %s", r, dir, debug.Stack())
65+
} else {
66+
// Otherwise, this is unexpected, but we prevent the program from crashing anyway.
67+
log.Warn().Msgf("Gracefully handled unexpected error %v in Streaming for %s, error %s", r, dir, debug.Stack())
68+
69+
tags := make(map[string]string)
70+
tags["root"] = "websocket.stream"
71+
tags["dir"] = dir
72+
switch rval := r.(type) {
73+
case error:
74+
raven.CaptureError(rval, tags)
75+
default:
76+
rvalStr := fmt.Sprint(rval)
77+
raven.CaptureMessage(rvalStr, tags)
78+
}
79+
}
80+
}
81+
}()
82+
83+
_, err := copyData(dst, src, dir)
84+
if err != nil {
85+
log.Debug().Msgf("%s copy: %v", dir, err)
86+
}
87+
status.markUniStreamDone()
88+
}
89+
90+
// when set to true, enables logging of content copied to/from origin and tunnel
91+
const debugCopy = false
92+
93+
func copyData(dst io.Writer, src io.Reader, dir string) (written int64, err error) {
94+
if debugCopy {
95+
// copyBuffer is based on stdio Copy implementation but shows copied data
96+
copyBuffer := func(dst io.Writer, src io.Reader, dir string) (written int64, err error) {
97+
var buf []byte
98+
size := 32 * 1024
99+
buf = make([]byte, size)
100+
for {
101+
t := time.Now()
102+
nr, er := src.Read(buf)
103+
if nr > 0 {
104+
fmt.Println(dir, t.UnixNano(), "\n"+hex.Dump(buf[0:nr]))
105+
nw, ew := dst.Write(buf[0:nr])
106+
if nw < 0 || nr < nw {
107+
nw = 0
108+
if ew == nil {
109+
ew = errors.New("invalid write")
110+
}
111+
}
112+
written += int64(nw)
113+
if ew != nil {
114+
err = ew
115+
break
116+
}
117+
if nr != nw {
118+
err = io.ErrShortWrite
119+
break
120+
}
121+
}
122+
if er != nil {
123+
if er != io.EOF {
124+
err = er
125+
}
126+
break
127+
}
128+
}
129+
return written, err
130+
}
131+
return copyBuffer(dst, src, dir)
132+
} else {
133+
return cfio.Copy(dst, src)
134+
}
135+
}

vendor/github.com/gorilla/mux/AUTHORS

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)