cloudflare/cloudflared

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
2021.5.5

Branches

Tags

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

Clone

HTTPS

Download ZIP

edgediscovery/edgediscovery.go

138lines · modecode

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