|
|
|
|
@ -29,7 +29,7 @@ type testClient struct { |
|
|
|
|
|
|
|
|
|
func newTestClient(t *testing.T, vni uint32, serverEndpoint netip.AddrPort, local key.DiscoPrivate, remote, server key.DiscoPublic) *testClient { |
|
|
|
|
rAddr := &net.UDPAddr{IP: serverEndpoint.Addr().AsSlice(), Port: int(serverEndpoint.Port())} |
|
|
|
|
uc, err := net.DialUDP("udp4", nil, rAddr) |
|
|
|
|
uc, err := net.DialUDP("udp", nil, rAddr) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
@ -180,85 +180,101 @@ func TestServer(t *testing.T) { |
|
|
|
|
discoA := key.NewDisco() |
|
|
|
|
discoB := key.NewDisco() |
|
|
|
|
|
|
|
|
|
ipv4LoopbackAddr := netip.MustParseAddr("127.0.0.1") |
|
|
|
|
|
|
|
|
|
server, _, err := NewServer(t.Logf, 0, []netip.Addr{ipv4LoopbackAddr}) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
cases := []struct { |
|
|
|
|
name string |
|
|
|
|
overrideAddrs []netip.Addr |
|
|
|
|
}{ |
|
|
|
|
{ |
|
|
|
|
name: "over ipv4", |
|
|
|
|
overrideAddrs: []netip.Addr{netip.MustParseAddr("127.0.0.1")}, |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
name: "over ipv6", |
|
|
|
|
overrideAddrs: []netip.Addr{netip.MustParseAddr("::1")}, |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
defer server.Close() |
|
|
|
|
|
|
|
|
|
endpoint, err := server.AllocateEndpoint(discoA.Public(), discoB.Public()) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
dupEndpoint, err := server.AllocateEndpoint(discoA.Public(), discoB.Public()) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
for _, tt := range cases { |
|
|
|
|
t.Run(tt.name, func(t *testing.T) { |
|
|
|
|
server, err := NewServer(t.Logf, 0, tt.overrideAddrs) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
defer server.Close() |
|
|
|
|
|
|
|
|
|
// We expect the same endpoint details pre-handshake.
|
|
|
|
|
if diff := cmp.Diff(dupEndpoint, endpoint, cmpopts.EquateComparable(netip.AddrPort{}, key.DiscoPublic{})); diff != "" { |
|
|
|
|
t.Fatalf("wrong dupEndpoint (-got +want)\n%s", diff) |
|
|
|
|
} |
|
|
|
|
endpoint, err := server.AllocateEndpoint(discoA.Public(), discoB.Public()) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
dupEndpoint, err := server.AllocateEndpoint(discoA.Public(), discoB.Public()) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if len(endpoint.AddrPorts) != 1 { |
|
|
|
|
t.Fatalf("unexpected endpoint.AddrPorts: %v", endpoint.AddrPorts) |
|
|
|
|
} |
|
|
|
|
tcA := newTestClient(t, endpoint.VNI, endpoint.AddrPorts[0], discoA, discoB.Public(), endpoint.ServerDisco) |
|
|
|
|
defer tcA.close() |
|
|
|
|
tcB := newTestClient(t, endpoint.VNI, endpoint.AddrPorts[0], discoB, discoA.Public(), endpoint.ServerDisco) |
|
|
|
|
defer tcB.close() |
|
|
|
|
// We expect the same endpoint details pre-handshake.
|
|
|
|
|
if diff := cmp.Diff(dupEndpoint, endpoint, cmpopts.EquateComparable(netip.AddrPort{}, key.DiscoPublic{})); diff != "" { |
|
|
|
|
t.Fatalf("wrong dupEndpoint (-got +want)\n%s", diff) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tcA.handshake(t) |
|
|
|
|
tcB.handshake(t) |
|
|
|
|
if len(endpoint.AddrPorts) != 1 { |
|
|
|
|
t.Fatalf("unexpected endpoint.AddrPorts: %v", endpoint.AddrPorts) |
|
|
|
|
} |
|
|
|
|
tcA := newTestClient(t, endpoint.VNI, endpoint.AddrPorts[0], discoA, discoB.Public(), endpoint.ServerDisco) |
|
|
|
|
defer tcA.close() |
|
|
|
|
tcB := newTestClient(t, endpoint.VNI, endpoint.AddrPorts[0], discoB, discoA.Public(), endpoint.ServerDisco) |
|
|
|
|
defer tcB.close() |
|
|
|
|
|
|
|
|
|
dupEndpoint, err = server.AllocateEndpoint(discoA.Public(), discoB.Public()) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
// We expect the same endpoint details post-handshake.
|
|
|
|
|
if diff := cmp.Diff(dupEndpoint, endpoint, cmpopts.EquateComparable(netip.AddrPort{}, key.DiscoPublic{})); diff != "" { |
|
|
|
|
t.Fatalf("wrong dupEndpoint (-got +want)\n%s", diff) |
|
|
|
|
} |
|
|
|
|
tcA.handshake(t) |
|
|
|
|
tcB.handshake(t) |
|
|
|
|
|
|
|
|
|
txToB := []byte{1, 2, 3} |
|
|
|
|
tcA.writeDataPkt(t, txToB) |
|
|
|
|
rxFromA := tcB.readDataPkt(t) |
|
|
|
|
if !bytes.Equal(txToB, rxFromA) { |
|
|
|
|
t.Fatal("unexpected msg A->B") |
|
|
|
|
} |
|
|
|
|
dupEndpoint, err = server.AllocateEndpoint(discoA.Public(), discoB.Public()) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatal(err) |
|
|
|
|
} |
|
|
|
|
// We expect the same endpoint details post-handshake.
|
|
|
|
|
if diff := cmp.Diff(dupEndpoint, endpoint, cmpopts.EquateComparable(netip.AddrPort{}, key.DiscoPublic{})); diff != "" { |
|
|
|
|
t.Fatalf("wrong dupEndpoint (-got +want)\n%s", diff) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
txToA := []byte{4, 5, 6} |
|
|
|
|
tcB.writeDataPkt(t, txToA) |
|
|
|
|
rxFromB := tcA.readDataPkt(t) |
|
|
|
|
if !bytes.Equal(txToA, rxFromB) { |
|
|
|
|
t.Fatal("unexpected msg B->A") |
|
|
|
|
} |
|
|
|
|
txToB := []byte{1, 2, 3} |
|
|
|
|
tcA.writeDataPkt(t, txToB) |
|
|
|
|
rxFromA := tcB.readDataPkt(t) |
|
|
|
|
if !bytes.Equal(txToB, rxFromA) { |
|
|
|
|
t.Fatal("unexpected msg A->B") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tcAOnNewPort := newTestClient(t, endpoint.VNI, endpoint.AddrPorts[0], discoA, discoB.Public(), endpoint.ServerDisco) |
|
|
|
|
tcAOnNewPort.handshakeGeneration = tcA.handshakeGeneration + 1 |
|
|
|
|
defer tcAOnNewPort.close() |
|
|
|
|
txToA := []byte{4, 5, 6} |
|
|
|
|
tcB.writeDataPkt(t, txToA) |
|
|
|
|
rxFromB := tcA.readDataPkt(t) |
|
|
|
|
if !bytes.Equal(txToA, rxFromB) { |
|
|
|
|
t.Fatal("unexpected msg B->A") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Handshake client A on a new source IP:port, verify we receive packets on the new binding
|
|
|
|
|
tcAOnNewPort.handshake(t) |
|
|
|
|
txToAOnNewPort := []byte{7, 8, 9} |
|
|
|
|
tcB.writeDataPkt(t, txToAOnNewPort) |
|
|
|
|
rxFromB = tcAOnNewPort.readDataPkt(t) |
|
|
|
|
if !bytes.Equal(txToAOnNewPort, rxFromB) { |
|
|
|
|
t.Fatal("unexpected msg B->A") |
|
|
|
|
} |
|
|
|
|
tcAOnNewPort := newTestClient(t, endpoint.VNI, endpoint.AddrPorts[0], discoA, discoB.Public(), endpoint.ServerDisco) |
|
|
|
|
tcAOnNewPort.handshakeGeneration = tcA.handshakeGeneration + 1 |
|
|
|
|
defer tcAOnNewPort.close() |
|
|
|
|
|
|
|
|
|
// Handshake client A on a new source IP:port, verify we receive packets on the new binding
|
|
|
|
|
tcAOnNewPort.handshake(t) |
|
|
|
|
txToAOnNewPort := []byte{7, 8, 9} |
|
|
|
|
tcB.writeDataPkt(t, txToAOnNewPort) |
|
|
|
|
rxFromB = tcAOnNewPort.readDataPkt(t) |
|
|
|
|
if !bytes.Equal(txToAOnNewPort, rxFromB) { |
|
|
|
|
t.Fatal("unexpected msg B->A") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
tcBOnNewPort := newTestClient(t, endpoint.VNI, endpoint.AddrPorts[0], discoB, discoA.Public(), endpoint.ServerDisco) |
|
|
|
|
tcBOnNewPort.handshakeGeneration = tcB.handshakeGeneration + 1 |
|
|
|
|
defer tcBOnNewPort.close() |
|
|
|
|
tcBOnNewPort := newTestClient(t, endpoint.VNI, endpoint.AddrPorts[0], discoB, discoA.Public(), endpoint.ServerDisco) |
|
|
|
|
tcBOnNewPort.handshakeGeneration = tcB.handshakeGeneration + 1 |
|
|
|
|
defer tcBOnNewPort.close() |
|
|
|
|
|
|
|
|
|
// Handshake client B on a new source IP:port, verify we receive packets on the new binding
|
|
|
|
|
tcBOnNewPort.handshake(t) |
|
|
|
|
txToBOnNewPort := []byte{7, 8, 9} |
|
|
|
|
tcAOnNewPort.writeDataPkt(t, txToBOnNewPort) |
|
|
|
|
rxFromA = tcBOnNewPort.readDataPkt(t) |
|
|
|
|
if !bytes.Equal(txToBOnNewPort, rxFromA) { |
|
|
|
|
t.Fatal("unexpected msg A->B") |
|
|
|
|
// Handshake client B on a new source IP:port, verify we receive packets on the new binding
|
|
|
|
|
tcBOnNewPort.handshake(t) |
|
|
|
|
txToBOnNewPort := []byte{7, 8, 9} |
|
|
|
|
tcAOnNewPort.writeDataPkt(t, txToBOnNewPort) |
|
|
|
|
rxFromA = tcBOnNewPort.readDataPkt(t) |
|
|
|
|
if !bytes.Equal(txToBOnNewPort, rxFromA) { |
|
|
|
|
t.Fatal("unexpected msg A->B") |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|