cloudflare/cloudflared

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
2021.1.2

Branches

Tags

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

Clone

HTTPS

Download ZIP

edgediscovery/edgediscovery.go

137lines · modecode

1package edgediscovery
2
3import (
4 "fmt"
5 "net"
6 "sync"
7
8 "github.com/cloudflare/cloudflared/edgediscovery/allregions"
9 "github.com/rs/zerolog"
10)
11
12const (
13 LogFieldAddress = "address"
14 LogFieldConnIndex = "connIndex"
15)
16
17var errNoAddressesLeft = fmt.Errorf("there are no free edge addresses left")
18
19// Edge finds addresses on the Cloudflare edge and hands them out to connections.
20type Edge struct {
21 regions *allregions.Regions
22 sync.Mutex
23 log *zerolog.Logger
24}
25
26// ------------------------------------
27// Constructors
28// ------------------------------------
29
30// ResolveEdge runs the initial discovery of the Cloudflare edge, finding Addrs that can be allocated
31// to connections.
32func ResolveEdge(log *zerolog.Logger) (*Edge, error) {
33 regions, err := allregions.ResolveEdge(log)
34 if err != nil {
35 return new(Edge), err
36 }
37 return &Edge{
38 log: log,
39 regions: regions,
40 }, nil
41}
42
43// StaticEdge creates a list of edge addresses from the list of hostnames. Mainly used for testing connectivity.
44func StaticEdge(log *zerolog.Logger, hostnames []string) (*Edge, error) {
45 regions, err := allregions.StaticEdge(hostnames, log)
46 if err != nil {
47 return new(Edge), err
48 }
49 return &Edge{
50 log: log,
51 regions: regions,
52 }, nil
53}
54
55// MockEdge creates a Cloudflare Edge from arbitrary TCP addresses. Used for testing.
56func MockEdge(log *zerolog.Logger, addrs []*net.TCPAddr) *Edge {
57 regions := allregions.NewNoResolve(addrs)
58 return &Edge{
59 log: log,
60 regions: regions,
61 }
62}
63
64// ------------------------------------
65// Methods
66// ------------------------------------
67
68// GetAddrForRPC gives this connection an edge Addr.
69func (ed *Edge) GetAddrForRPC() (*net.TCPAddr, error) {
70 ed.Lock()
71 defer ed.Unlock()
72 addr := ed.regions.GetAnyAddress()
73 if addr == nil {
74 return nil, errNoAddressesLeft
75 }
76 return addr, nil
77}
78
79// GetAddr gives this proxy connection an edge Addr. Prefer Addrs this connection has already used.
80func (ed *Edge) GetAddr(connIndex int) (*net.TCPAddr, error) {
81 log := ed.log.With().Int(LogFieldConnIndex, connIndex).Logger()
82
83 ed.Lock()
84 defer ed.Unlock()
85
86 // If this connection has already used an edge addr, return it.
87 if addr := ed.regions.AddrUsedBy(connIndex); addr != nil {
88 log.Debug().Msg("edgediscovery - GetAddr: Returning same address back to proxy connection")
89 return addr, nil
90 }
91
92 // Otherwise, give it an unused one
93 addr := ed.regions.GetUnusedAddr(nil, connIndex)
94 if addr == nil {
95 log.Debug().Msg("edgediscovery - GetAddr: No addresses left to give proxy connection")
96 return nil, errNoAddressesLeft
97 }
98 log.Debug().Str(LogFieldAddress, addr.String()).Msg("edgediscovery - GetAddr: Giving connection its new address")
99 return addr, nil
100}
101
102// GetDifferentAddr gives back the proxy connection's edge Addr and uses a new one.
103func (ed *Edge) GetDifferentAddr(connIndex int) (*net.TCPAddr, error) {
104 log := ed.log.With().Int(LogFieldConnIndex, connIndex).Logger()
105
106 ed.Lock()
107 defer ed.Unlock()
108
109 oldAddr := ed.regions.AddrUsedBy(connIndex)
110 if oldAddr != nil {
111 ed.regions.GiveBack(oldAddr)
112 }
113 addr := ed.regions.GetUnusedAddr(oldAddr, connIndex)
114 if addr == nil {
115 log.Debug().Msg("edgediscovery - GetDifferentAddr: No addresses left to give proxy connection")
116 // note: if oldAddr were not nil, it will become available on the next iteration
117 return nil, errNoAddressesLeft
118 }
119 log.Debug().Str(LogFieldAddress, addr.String()).Msg("edgediscovery - GetDifferentAddr: Giving connection its new address")
120 return addr, nil
121}
122
123// AvailableAddrs returns how many unused addresses there are left.
124func (ed *Edge) AvailableAddrs() int {
125 ed.Lock()
126 defer ed.Unlock()
127 return ed.regions.AvailableAddrs()
128}
129
130// GiveBack the address so that other connections can use it.
131// Returns true if the address is in this edge.
132func (ed *Edge) GiveBack(addr *net.TCPAddr) bool {
133 ed.Lock()
134 defer ed.Unlock()
135 ed.log.Debug().Msg("edgediscovery - GiveBack: Address now unused")
136 return ed.regions.GiveBack(addr)
137}
138