stunner: re-do how Stunner works
It used to make assumptions based on having Anycast IPs that are super near. Now we're intentionally going to a bunch of different distant IPs to measure latency. Also, optimize how the hairpin detection works. No need to STUN on that socket. Just use that separate socket for sending, once we know the other UDP4 socket's endpoint. The trick is: make our test probe also a STUN packet, so it fits through magicsock's existing STUN routing. This drops netcheck from ~5 seconds to ~250-500ms. Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
committed by
Brad Fitzpatrick
parent
4affea2691
commit
01b4bec33f
@@ -138,9 +138,8 @@ type Options struct {
|
||||
// Zero means to pick one automatically.
|
||||
Port uint16
|
||||
|
||||
// STUN, if non-empty, specifies alternate STUN servers for testing.
|
||||
// If empty, the production DERP servers are used.
|
||||
STUN []string
|
||||
// DERPs, if non-nil, is used instead of derpmap.Prod.
|
||||
DERPs *derpmap.World
|
||||
|
||||
// EndpointsFunc optionally provides a func to be called when
|
||||
// endpoints change. The called func does not own the slice.
|
||||
@@ -202,11 +201,11 @@ func Listen(opts Options) (*Conn, error) {
|
||||
derpRecvCh: make(chan derpReadResult),
|
||||
udpRecvCh: make(chan udpReadResult),
|
||||
derpTLSConfig: opts.derpTLSConfig,
|
||||
derps: derpmap.Prod(),
|
||||
derps: opts.DERPs,
|
||||
}
|
||||
c.linkState, _ = getLinkState()
|
||||
if len(opts.STUN) > 0 {
|
||||
c.derps = derpmap.NewTestWorld(opts.STUN...)
|
||||
if c.derps == nil {
|
||||
c.derps = derpmap.Prod()
|
||||
}
|
||||
c.netChecker = &netcheck.Client{
|
||||
DERP: c.derps,
|
||||
|
||||
@@ -32,7 +32,6 @@ import (
|
||||
)
|
||||
|
||||
func TestListen(t *testing.T) {
|
||||
// TODO(crawshaw): when offline this test spends a while trying to connect to real derp servers.
|
||||
|
||||
epCh := make(chan string, 16)
|
||||
epFunc := func(endpoints []string) {
|
||||
@@ -47,7 +46,7 @@ func TestListen(t *testing.T) {
|
||||
port := pickPort(t)
|
||||
conn, err := Listen(Options{
|
||||
Port: port,
|
||||
STUN: []string{stunAddr},
|
||||
DERPs: derpmap.NewTestWorld(stunAddr),
|
||||
EndpointsFunc: epFunc,
|
||||
Logf: t.Logf,
|
||||
})
|
||||
@@ -157,7 +156,7 @@ func serveSTUN(t *testing.T) (addr string, cleanupFn func()) {
|
||||
}
|
||||
|
||||
stunAddr := pc.LocalAddr().String()
|
||||
stunAddr = strings.Replace(stunAddr, "0.0.0.0:", "localhost:", 1)
|
||||
stunAddr = strings.Replace(stunAddr, "0.0.0.0:", "127.0.0.1:", 1)
|
||||
|
||||
doneCh := make(chan struct{})
|
||||
go runSTUN(t, pc, &stats, doneCh)
|
||||
@@ -343,8 +342,8 @@ func TestTwoDevicePing(t *testing.T) {
|
||||
|
||||
epCh1 := make(chan []string, 16)
|
||||
conn1, err := Listen(Options{
|
||||
Logf: logger.WithPrefix(t.Logf, "conn1: "),
|
||||
STUN: []string{stunAddr},
|
||||
Logf: logger.WithPrefix(t.Logf, "conn1: "),
|
||||
DERPs: derps,
|
||||
EndpointsFunc: func(eps []string) {
|
||||
epCh1 <- eps
|
||||
},
|
||||
@@ -353,13 +352,12 @@ func TestTwoDevicePing(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
conn1.derps = derps
|
||||
defer conn1.Close()
|
||||
|
||||
epCh2 := make(chan []string, 16)
|
||||
conn2, err := Listen(Options{
|
||||
Logf: logger.WithPrefix(t.Logf, "conn2: "),
|
||||
STUN: []string{stunAddr},
|
||||
Logf: logger.WithPrefix(t.Logf, "conn2: "),
|
||||
DERPs: derps,
|
||||
EndpointsFunc: func(eps []string) {
|
||||
epCh2 <- eps
|
||||
},
|
||||
@@ -368,7 +366,6 @@ func TestTwoDevicePing(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
conn2.derps = derps
|
||||
defer conn2.Close()
|
||||
|
||||
ports := []uint16{conn1.LocalPort(), conn2.LocalPort()}
|
||||
|
||||
Reference in New Issue
Block a user