2020-02-06 00:55:26 +00:00
|
|
|
package edgediscovery
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net"
|
|
|
|
"testing"
|
|
|
|
|
2020-11-25 06:55:13 +00:00
|
|
|
"github.com/rs/zerolog"
|
2020-02-06 00:55:26 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2021-08-06 13:31:22 +00:00
|
|
|
|
|
|
|
"github.com/cloudflare/cloudflared/edgediscovery/allregions"
|
2020-02-06 00:55:26 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2022-05-20 21:51:36 +00:00
|
|
|
testLogger = zerolog.Nop()
|
|
|
|
v4Addrs = []*allregions.EdgeAddr{&addr0, &addr1, &addr2, &addr3}
|
|
|
|
v6Addrs = []*allregions.EdgeAddr{&addr4, &addr5, &addr6, &addr7}
|
|
|
|
addr0 = allregions.EdgeAddr{
|
2021-08-06 13:31:22 +00:00
|
|
|
TCP: &net.TCPAddr{
|
2022-05-20 21:51:36 +00:00
|
|
|
IP: net.ParseIP("123.4.5.0"),
|
2021-08-06 13:31:22 +00:00
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
|
|
|
UDP: &net.UDPAddr{
|
2022-05-20 21:51:36 +00:00
|
|
|
IP: net.ParseIP("123.4.5.0"),
|
2021-08-06 13:31:22 +00:00
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
2022-05-20 21:51:36 +00:00
|
|
|
IPVersion: allregions.V4,
|
2020-02-06 00:55:26 +00:00
|
|
|
}
|
2021-08-06 13:31:22 +00:00
|
|
|
addr1 = allregions.EdgeAddr{
|
|
|
|
TCP: &net.TCPAddr{
|
2022-05-20 21:51:36 +00:00
|
|
|
IP: net.ParseIP("123.4.5.1"),
|
2021-08-06 13:31:22 +00:00
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
|
|
|
UDP: &net.UDPAddr{
|
2022-05-20 21:51:36 +00:00
|
|
|
IP: net.ParseIP("123.4.5.1"),
|
2021-08-06 13:31:22 +00:00
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
2022-05-20 21:51:36 +00:00
|
|
|
IPVersion: allregions.V4,
|
2020-02-06 00:55:26 +00:00
|
|
|
}
|
2021-08-06 13:31:22 +00:00
|
|
|
addr2 = allregions.EdgeAddr{
|
|
|
|
TCP: &net.TCPAddr{
|
2022-05-20 21:51:36 +00:00
|
|
|
IP: net.ParseIP("123.4.5.2"),
|
2021-08-06 13:31:22 +00:00
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
|
|
|
UDP: &net.UDPAddr{
|
2022-05-20 21:51:36 +00:00
|
|
|
IP: net.ParseIP("123.4.5.2"),
|
2021-08-06 13:31:22 +00:00
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
2022-05-20 21:51:36 +00:00
|
|
|
IPVersion: allregions.V4,
|
2020-02-06 00:55:26 +00:00
|
|
|
}
|
2021-08-06 13:31:22 +00:00
|
|
|
addr3 = allregions.EdgeAddr{
|
|
|
|
TCP: &net.TCPAddr{
|
2022-05-20 21:51:36 +00:00
|
|
|
IP: net.ParseIP("123.4.5.3"),
|
2022-05-20 21:51:36 +00:00
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
|
|
|
UDP: &net.UDPAddr{
|
2022-05-20 21:51:36 +00:00
|
|
|
IP: net.ParseIP("123.4.5.3"),
|
2022-05-20 21:51:36 +00:00
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
2022-05-20 21:51:36 +00:00
|
|
|
IPVersion: allregions.V4,
|
|
|
|
}
|
|
|
|
addr4 = allregions.EdgeAddr{
|
|
|
|
TCP: &net.TCPAddr{
|
|
|
|
IP: net.ParseIP("2606:4700:a0::1"),
|
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
|
|
|
UDP: &net.UDPAddr{
|
|
|
|
IP: net.ParseIP("2606:4700:a0::1"),
|
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
|
|
|
IPVersion: allregions.V6,
|
|
|
|
}
|
|
|
|
addr5 = allregions.EdgeAddr{
|
|
|
|
TCP: &net.TCPAddr{
|
|
|
|
IP: net.ParseIP("2606:4700:a0::2"),
|
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
|
|
|
UDP: &net.UDPAddr{
|
|
|
|
IP: net.ParseIP("2606:4700:a0::2"),
|
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
|
|
|
IPVersion: allregions.V6,
|
|
|
|
}
|
|
|
|
addr6 = allregions.EdgeAddr{
|
|
|
|
TCP: &net.TCPAddr{
|
|
|
|
IP: net.ParseIP("2606:4700:a0::3"),
|
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
|
|
|
UDP: &net.UDPAddr{
|
|
|
|
IP: net.ParseIP("2606:4700:a0::3"),
|
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
|
|
|
IPVersion: allregions.V6,
|
|
|
|
}
|
|
|
|
addr7 = allregions.EdgeAddr{
|
|
|
|
TCP: &net.TCPAddr{
|
|
|
|
IP: net.ParseIP("2606:4700:a0::4"),
|
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
|
|
|
UDP: &net.UDPAddr{
|
|
|
|
IP: net.ParseIP("2606:4700:a0::4"),
|
|
|
|
Port: 8000,
|
|
|
|
Zone: "",
|
|
|
|
},
|
|
|
|
IPVersion: allregions.V6,
|
2020-02-06 00:55:26 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestGiveBack(t *testing.T) {
|
2021-08-06 13:31:22 +00:00
|
|
|
edge := MockEdge(&testLogger, []*allregions.EdgeAddr{&addr0, &addr1, &addr2, &addr3})
|
2020-02-06 00:55:26 +00:00
|
|
|
|
|
|
|
// Give this connection an address
|
|
|
|
assert.Equal(t, 4, edge.AvailableAddrs())
|
|
|
|
const connID = 0
|
|
|
|
addr, err := edge.GetAddr(connID)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotNil(t, addr)
|
|
|
|
assert.Equal(t, 3, edge.AvailableAddrs())
|
|
|
|
|
|
|
|
// Get it back
|
2022-05-20 21:51:36 +00:00
|
|
|
edge.GiveBack(addr, false)
|
2020-02-06 00:55:26 +00:00
|
|
|
assert.Equal(t, 4, edge.AvailableAddrs())
|
|
|
|
}
|
2020-03-16 20:49:04 +00:00
|
|
|
|
|
|
|
func TestRPCAndProxyShareSingleEdgeIP(t *testing.T) {
|
|
|
|
// Make an edge with a single IP
|
2021-08-06 13:31:22 +00:00
|
|
|
edge := MockEdge(&testLogger, []*allregions.EdgeAddr{&addr0})
|
2020-03-16 20:49:04 +00:00
|
|
|
tunnelConnID := 0
|
|
|
|
|
|
|
|
// Use the IP for a tunnel
|
|
|
|
addrTunnel, err := edge.GetAddr(tunnelConnID)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
// Ensure the IP can be used for RPC too
|
|
|
|
addrRPC, err := edge.GetAddrForRPC()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, addrTunnel, addrRPC)
|
|
|
|
}
|
|
|
|
|
2020-02-06 00:55:26 +00:00
|
|
|
func TestGetAddrForRPC(t *testing.T) {
|
2021-08-06 13:31:22 +00:00
|
|
|
edge := MockEdge(&testLogger, []*allregions.EdgeAddr{&addr0, &addr1, &addr2, &addr3})
|
2020-02-06 00:55:26 +00:00
|
|
|
|
|
|
|
// Get a connection
|
|
|
|
assert.Equal(t, 4, edge.AvailableAddrs())
|
|
|
|
addr, err := edge.GetAddrForRPC()
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotNil(t, addr)
|
|
|
|
|
|
|
|
// Using an address for RPC shouldn't consume it
|
|
|
|
assert.Equal(t, 4, edge.AvailableAddrs())
|
|
|
|
|
|
|
|
// Get it back
|
2022-05-20 21:51:36 +00:00
|
|
|
edge.GiveBack(addr, false)
|
2020-02-06 00:55:26 +00:00
|
|
|
assert.Equal(t, 4, edge.AvailableAddrs())
|
|
|
|
}
|
|
|
|
|
2020-04-27 19:25:37 +00:00
|
|
|
func TestOnePerRegion(t *testing.T) {
|
|
|
|
// Make an edge with only one address
|
2021-08-06 13:31:22 +00:00
|
|
|
edge := MockEdge(&testLogger, []*allregions.EdgeAddr{&addr0, &addr1})
|
2020-04-27 19:25:37 +00:00
|
|
|
|
|
|
|
// Use the only address
|
|
|
|
const connID = 0
|
|
|
|
a1, err := edge.GetAddr(connID)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotNil(t, a1)
|
|
|
|
|
|
|
|
// if the first address is bad, get the second one
|
2022-05-20 21:51:36 +00:00
|
|
|
a2, err := edge.GetDifferentAddr(connID, false)
|
2020-04-27 19:25:37 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotNil(t, a2)
|
|
|
|
assert.NotEqual(t, a1, a2)
|
|
|
|
|
|
|
|
// now that second one is bad, get the first one again
|
2022-05-20 21:51:36 +00:00
|
|
|
a3, err := edge.GetDifferentAddr(connID, false)
|
2020-04-27 19:25:37 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, a1, a3)
|
|
|
|
}
|
|
|
|
|
2020-02-06 00:55:26 +00:00
|
|
|
func TestOnlyOneAddrLeft(t *testing.T) {
|
|
|
|
// Make an edge with only one address
|
2021-08-06 13:31:22 +00:00
|
|
|
edge := MockEdge(&testLogger, []*allregions.EdgeAddr{&addr0})
|
2020-02-06 00:55:26 +00:00
|
|
|
|
|
|
|
// Use the only address
|
|
|
|
const connID = 0
|
|
|
|
addr, err := edge.GetAddr(connID)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotNil(t, addr)
|
|
|
|
|
|
|
|
// If that edge address is "bad", there's no alternative address.
|
2022-05-20 21:51:36 +00:00
|
|
|
_, err = edge.GetDifferentAddr(connID, false)
|
2020-02-06 00:55:26 +00:00
|
|
|
assert.Error(t, err)
|
2020-04-27 19:25:37 +00:00
|
|
|
|
|
|
|
// previously bad address should become available again on next iteration.
|
2022-05-20 21:51:36 +00:00
|
|
|
addr, err = edge.GetDifferentAddr(connID, false)
|
2020-04-27 19:25:37 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotNil(t, addr)
|
2020-02-06 00:55:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestNoAddrsLeft(t *testing.T) {
|
|
|
|
// Make an edge with no addresses
|
2021-08-06 13:31:22 +00:00
|
|
|
edge := MockEdge(&testLogger, []*allregions.EdgeAddr{})
|
2020-02-06 00:55:26 +00:00
|
|
|
|
|
|
|
_, err := edge.GetAddr(2)
|
|
|
|
assert.Error(t, err)
|
|
|
|
_, err = edge.GetAddrForRPC()
|
|
|
|
assert.Error(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetAddr(t *testing.T) {
|
2021-08-06 13:31:22 +00:00
|
|
|
edge := MockEdge(&testLogger, []*allregions.EdgeAddr{&addr0, &addr1, &addr2, &addr3})
|
2020-02-06 00:55:26 +00:00
|
|
|
|
|
|
|
// Give this connection an address
|
|
|
|
const connID = 0
|
|
|
|
addr, err := edge.GetAddr(connID)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotNil(t, addr)
|
|
|
|
|
|
|
|
// If the same connection requests another address, it should get the same one.
|
|
|
|
addr2, err := edge.GetAddr(connID)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, addr, addr2)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetDifferentAddr(t *testing.T) {
|
2021-08-06 13:31:22 +00:00
|
|
|
edge := MockEdge(&testLogger, []*allregions.EdgeAddr{&addr0, &addr1, &addr2, &addr3})
|
2020-02-06 00:55:26 +00:00
|
|
|
|
|
|
|
// Give this connection an address
|
|
|
|
assert.Equal(t, 4, edge.AvailableAddrs())
|
|
|
|
const connID = 0
|
|
|
|
addr, err := edge.GetAddr(connID)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotNil(t, addr)
|
|
|
|
assert.Equal(t, 3, edge.AvailableAddrs())
|
|
|
|
|
|
|
|
// If the same connection requests another address, it should get the same one.
|
2022-05-20 21:51:36 +00:00
|
|
|
addr2, err := edge.GetDifferentAddr(connID, false)
|
2020-02-06 00:55:26 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotEqual(t, addr, addr2)
|
|
|
|
assert.Equal(t, 3, edge.AvailableAddrs())
|
|
|
|
}
|
2022-05-20 21:51:36 +00:00
|
|
|
|
|
|
|
// MockEdge creates a Cloudflare Edge from arbitrary TCP addresses. Used for testing.
|
|
|
|
func MockEdge(log *zerolog.Logger, addrs []*allregions.EdgeAddr) *Edge {
|
|
|
|
regions := allregions.NewNoResolve(addrs)
|
|
|
|
return &Edge{
|
|
|
|
log: log,
|
|
|
|
regions: regions,
|
|
|
|
}
|
|
|
|
}
|