cloudflare/cloudflared

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
2021.11.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

edgediscovery/edgediscovery.go

135lines · modecode

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