cloudflare/cloudflared

Public

mirrored from https://github.com/cloudflare/cloudflaredAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
e2a8302bbca9804507e64d77feeecb04298260b5

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

connection/control.go

96lines · modecode

1package connection
2
3import (
4 "context"
5 "io"
6 "time"
7
8 "github.com/rs/zerolog"
9
10 tunnelpogs "github.com/cloudflare/cloudflared/tunnelrpc/pogs"
11)
12
13// RPCClientFunc derives a named tunnel rpc client that can then be used to register and unregister connections.
14type RPCClientFunc func(context.Context, io.ReadWriteCloser, *zerolog.Logger) NamedTunnelRPCClient
15
16type controlStream struct {
17 observer *Observer
18
19 connectedFuse ConnectedFuse
20 namedTunnelProperties *NamedTunnelProperties
21 connIndex uint8
22
23 newRPCClientFunc RPCClientFunc
24
25 gracefulShutdownC <-chan struct{}
26 gracePeriod time.Duration
27 stoppedGracefully bool
28}
29
30// ControlStreamHandler registers connections with origintunneld and initiates graceful shutdown.
31type ControlStreamHandler interface {
32 // ServeControlStream handles the control plane of the transport in the current goroutine calling this
33 ServeControlStream(ctx context.Context, rw io.ReadWriteCloser, connOptions *tunnelpogs.ConnectionOptions) error
34 // IsStopped tells whether the method above has finished
35 IsStopped() bool
36}
37
38// NewControlStream returns a new instance of ControlStreamHandler
39func NewControlStream(
40 observer *Observer,
41 connectedFuse ConnectedFuse,
42 namedTunnelConfig *NamedTunnelProperties,
43 connIndex uint8,
44 newRPCClientFunc RPCClientFunc,
45 gracefulShutdownC <-chan struct{},
46 gracePeriod time.Duration,
47) ControlStreamHandler {
48 if newRPCClientFunc == nil {
49 newRPCClientFunc = newRegistrationRPCClient
50 }
51 return &controlStream{
52 observer: observer,
53 connectedFuse: connectedFuse,
54 namedTunnelProperties: namedTunnelConfig,
55 newRPCClientFunc: newRPCClientFunc,
56 connIndex: connIndex,
57 gracefulShutdownC: gracefulShutdownC,
58 gracePeriod: gracePeriod,
59 }
60}
61
62func (c *controlStream) ServeControlStream(
63 ctx context.Context,
64 rw io.ReadWriteCloser,
65 connOptions *tunnelpogs.ConnectionOptions,
66) error {
67 rpcClient := c.newRPCClientFunc(ctx, rw, c.observer.log)
68
69 if err := rpcClient.RegisterConnection(ctx, c.namedTunnelProperties, connOptions, c.connIndex, c.observer); err != nil {
70 rpcClient.Close()
71 return err
72 }
73 c.connectedFuse.Connected()
74
75 c.waitForUnregister(ctx, rpcClient)
76 return nil
77}
78
79func (c *controlStream) waitForUnregister(ctx context.Context, rpcClient NamedTunnelRPCClient) {
80 // wait for connection termination or start of graceful shutdown
81 defer rpcClient.Close()
82 select {
83 case <-ctx.Done():
84 break
85 case <-c.gracefulShutdownC:
86 c.stoppedGracefully = true
87 }
88
89 c.observer.sendUnregisteringEvent(c.connIndex)
90 rpcClient.GracefulShutdown(ctx, c.gracePeriod)
91 c.observer.log.Info().Uint8(LogFieldConnIndex, c.connIndex).Msg("Unregistered tunnel connection")
92}
93
94func (c *controlStream) IsStopped() bool {
95 return c.stoppedGracefully
96}
97