cloudflare/cloudflared

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
2020.4.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

edgediscovery/edgediscovery.go

143lines · modecode

1package edgediscovery
2
3import (
4 "fmt"
5 "net"
6 "sync"
7
8 "github.com/cloudflare/cloudflared/edgediscovery/allregions"
9
10 "github.com/sirupsen/logrus"
11)
12
13const (
14 subsystem = "edgediscovery"
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 logger *logrus.Entry
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(l *logrus.Logger) (*Edge, error) {
33 logger := l.WithField("subsystem", subsystem)
34 regions, err := allregions.ResolveEdge(logger)
35 if err != nil {
36 return new(Edge), err
37 }
38 return &Edge{
39 logger: logger,
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(l *logrus.Logger, hostnames []string) (*Edge, error) {
46 logger := l.WithField("subsystem", subsystem)
47 regions, err := allregions.StaticEdge(hostnames)
48 if err != nil {
49 return new(Edge), err
50 }
51 return &Edge{
52 logger: logger,
53 regions: regions,
54 }, nil
55}
56
57// MockEdge creates a Cloudflare Edge from arbitrary TCP addresses. Used for testing.
58func MockEdge(l *logrus.Logger, addrs []*net.TCPAddr) *Edge {
59 logger := l.WithField("subsystem", subsystem)
60 regions := allregions.NewNoResolve(addrs)
61 return &Edge{
62 logger: logger,
63 regions: regions,
64 }
65}
66
67// ------------------------------------
68// Methods
69// ------------------------------------
70
71// GetAddrForRPC gives this connection an edge Addr.
72func (ed *Edge) GetAddrForRPC() (*net.TCPAddr, error) {
73 ed.Lock()
74 defer ed.Unlock()
75 addr := ed.regions.GetAnyAddress()
76 if addr == nil {
77 return nil, errNoAddressesLeft
78 }
79 return addr, nil
80}
81
82// GetAddr gives this proxy connection an edge Addr. Prefer Addrs this connection has already used.
83func (ed *Edge) GetAddr(connID int) (*net.TCPAddr, error) {
84 ed.Lock()
85 defer ed.Unlock()
86 logger := ed.logger.WithFields(logrus.Fields{
87 "connID": connID,
88 "function": "GetAddr",
89 })
90
91 // If this connection has already used an edge addr, return it.
92 if addr := ed.regions.AddrUsedBy(connID); addr != nil {
93 logger.Debug("Returning same address back to proxy connection")
94 return addr, nil
95 }
96
97 // Otherwise, give it an unused one
98 addr := ed.regions.GetUnusedAddr(nil, connID)
99 if addr == nil {
100 logger.Debug("No addresses left to give proxy connection")
101 return nil, errNoAddressesLeft
102 }
103 logger.Debug("Giving connection its new address")
104 return addr, nil
105}
106
107// GetDifferentAddr gives back the proxy connection's edge Addr and uses a new one.
108func (ed *Edge) GetDifferentAddr(connID int) (*net.TCPAddr, error) {
109 ed.Lock()
110 defer ed.Unlock()
111 logger := ed.logger.WithFields(logrus.Fields{
112 "connID": connID,
113 "function": "GetDifferentAddr",
114 })
115
116 oldAddr := ed.regions.AddrUsedBy(connID)
117 if oldAddr != nil {
118 ed.regions.GiveBack(oldAddr)
119 }
120 addr := ed.regions.GetUnusedAddr(oldAddr, connID)
121 if addr == nil {
122 logger.Debug("No addresses left to give proxy connection")
123 return nil, errNoAddressesLeft
124 }
125 logger.Debug("Giving connection its new address")
126 return addr, nil
127}
128
129// AvailableAddrs returns how many unused addresses there are left.
130func (ed *Edge) AvailableAddrs() int {
131 ed.Lock()
132 defer ed.Unlock()
133 return ed.regions.AvailableAddrs()
134}
135
136// GiveBack the address so that other connections can use it.
137// Returns true if the address is in this edge.
138func (ed *Edge) GiveBack(addr *net.TCPAddr) bool {
139 ed.Lock()
140 defer ed.Unlock()
141 ed.logger.WithField("function", "GiveBack").Debug("Address now unused")
142 return ed.regions.GiveBack(addr)
143}
144