292 lines
6.6 KiB
Go
292 lines
6.6 KiB
Go
package node
|
|
|
|
import (
|
|
"bytes"
|
|
"net/netip"
|
|
"testing"
|
|
)
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
type testUDPPacket struct {
|
|
Addr netip.AddrPort
|
|
Data []byte
|
|
}
|
|
|
|
type testUDPAddrPortWriter struct {
|
|
written []testUDPPacket
|
|
}
|
|
|
|
func (w *testUDPAddrPortWriter) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error) {
|
|
w.written = append(w.written, testUDPPacket{
|
|
Addr: addr,
|
|
Data: bytes.Clone(b),
|
|
})
|
|
return len(b), nil
|
|
}
|
|
|
|
func (w *testUDPAddrPortWriter) Written() []testUDPPacket {
|
|
out := w.written
|
|
w.written = []testUDPPacket{}
|
|
return out
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
type testPacket string
|
|
|
|
func (p testPacket) Marshal(b []byte) []byte {
|
|
b = b[:len(p)]
|
|
copy(b, []byte(p))
|
|
return b
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
func testConnWriter_getTestRoutes() (local, remote, relayLocal, relayRemote *peerRoute) {
|
|
localKeys := generateKeys()
|
|
remoteKeys := generateKeys()
|
|
|
|
local = &peerRoute{
|
|
IP: 2,
|
|
Up: true,
|
|
Relay: false,
|
|
PubSignKey: remoteKeys.PubSignKey,
|
|
ControlCipher: newControlCipher(localKeys.PrivKey, remoteKeys.PubKey),
|
|
DataCipher: newDataCipher(),
|
|
RemoteAddr: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 1, 1, 2}), 100),
|
|
}
|
|
|
|
remote = &peerRoute{
|
|
IP: 1,
|
|
Up: true,
|
|
Relay: false,
|
|
PubSignKey: localKeys.PubSignKey,
|
|
ControlCipher: newControlCipher(remoteKeys.PrivKey, localKeys.PubKey),
|
|
DataCipher: local.DataCipher,
|
|
RemoteAddr: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 1, 1, 1}), 100),
|
|
}
|
|
|
|
rLocalKeys := generateKeys()
|
|
rRemoteKeys := generateKeys()
|
|
|
|
relayLocal = &peerRoute{
|
|
IP: 3,
|
|
Up: true,
|
|
Relay: true,
|
|
Direct: true,
|
|
PubSignKey: rRemoteKeys.PubSignKey,
|
|
ControlCipher: newControlCipher(rLocalKeys.PrivKey, rRemoteKeys.PubKey),
|
|
DataCipher: newDataCipher(),
|
|
RemoteAddr: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 1, 1, 3}), 100),
|
|
}
|
|
|
|
relayRemote = &peerRoute{
|
|
IP: 1,
|
|
Up: true,
|
|
Relay: false,
|
|
Direct: true,
|
|
PubSignKey: rLocalKeys.PubSignKey,
|
|
ControlCipher: newControlCipher(rRemoteKeys.PrivKey, rLocalKeys.PubKey),
|
|
DataCipher: relayLocal.DataCipher,
|
|
RemoteAddr: netip.AddrPortFrom(netip.AddrFrom4([4]byte{1, 1, 1, 1}), 100),
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Testing if we can send a control packet directly to the remote route.
|
|
func TestConnWriter_SendControlPacket_direct(t *testing.T) {
|
|
route, rRoute, _, _ := testConnWriter_getTestRoutes()
|
|
route.Direct = true
|
|
|
|
writer := &testUDPAddrPortWriter{}
|
|
w := newConnWriter(writer, rRoute.IP)
|
|
in := testPacket("hello world!")
|
|
|
|
w.SendControlPacket(in, route)
|
|
out := writer.Written()
|
|
if len(out) != 1 {
|
|
t.Fatal(out)
|
|
}
|
|
|
|
if out[0].Addr != route.RemoteAddr {
|
|
t.Fatal(out[0])
|
|
}
|
|
|
|
dec, ok := rRoute.ControlCipher.Decrypt(out[0].Data, make([]byte, 1024))
|
|
if !ok {
|
|
t.Fatal(ok)
|
|
}
|
|
if string(dec) != string(in) {
|
|
t.Fatal(dec)
|
|
}
|
|
}
|
|
|
|
// Testing if we can relay a packet via an intermediary.
|
|
func TestConnWriter_SendControlPacket_relay(t *testing.T) {
|
|
route, rRoute, relay, rRelay := testConnWriter_getTestRoutes()
|
|
|
|
writer := &testUDPAddrPortWriter{}
|
|
w := newConnWriter(writer, rRoute.IP)
|
|
in := testPacket("hello world!")
|
|
|
|
w.RelayControlPacket(in, route, relay)
|
|
|
|
out := writer.Written()
|
|
if len(out) != 1 {
|
|
t.Fatal(out)
|
|
}
|
|
|
|
if out[0].Addr != relay.RemoteAddr {
|
|
t.Fatal(out[0])
|
|
}
|
|
|
|
dec, ok := rRelay.DataCipher.Decrypt(out[0].Data, make([]byte, 1024))
|
|
if !ok {
|
|
t.Fatal(ok)
|
|
}
|
|
|
|
dec2, ok := rRoute.ControlCipher.Decrypt(dec, make([]byte, 1024))
|
|
if !ok {
|
|
t.Fatal(ok)
|
|
}
|
|
|
|
if string(dec2) != string(in) {
|
|
t.Fatal(dec2)
|
|
}
|
|
}
|
|
|
|
// Testing that a nil relay doesn't cause an issue.
|
|
func TestConnWriter_SendControlPacket_relay_relayNil(t *testing.T) {
|
|
route, rRoute, _, _ := testConnWriter_getTestRoutes()
|
|
|
|
writer := &testUDPAddrPortWriter{}
|
|
w := newConnWriter(writer, rRoute.IP)
|
|
in := testPacket("hello world!")
|
|
|
|
w.RelayControlPacket(in, route, nil)
|
|
|
|
out := writer.Written()
|
|
if len(out) != 0 {
|
|
t.Fatal(out)
|
|
}
|
|
|
|
}
|
|
|
|
// Testing that we don't send anything if the relay isn't up.
|
|
func TestConnWriter_SendControlPacket_relay_relayNotUp(t *testing.T) {
|
|
route, rRoute, relay, _ := testConnWriter_getTestRoutes()
|
|
relay.Up = false
|
|
|
|
writer := &testUDPAddrPortWriter{}
|
|
w := newConnWriter(writer, rRoute.IP)
|
|
in := testPacket("hello world!")
|
|
|
|
w.RelayControlPacket(in, route, relay)
|
|
|
|
out := writer.Written()
|
|
if len(out) != 0 {
|
|
t.Fatal(out)
|
|
}
|
|
}
|
|
|
|
// Testing that we can send a data packet directly to a remote route.
|
|
func TestConnWriter_SendDataPacket_direct(t *testing.T) {
|
|
route, rRoute, _, _ := testConnWriter_getTestRoutes()
|
|
route.Direct = true
|
|
|
|
writer := &testUDPAddrPortWriter{}
|
|
w := newConnWriter(writer, rRoute.IP)
|
|
|
|
in := []byte("hello world!")
|
|
w.SendDataPacket(in, route, nil)
|
|
|
|
out := writer.Written()
|
|
if len(out) != 1 {
|
|
t.Fatal(out)
|
|
}
|
|
|
|
if out[0].Addr != route.RemoteAddr {
|
|
t.Fatal(out[0])
|
|
}
|
|
|
|
dec, ok := rRoute.DataCipher.Decrypt(out[0].Data, make([]byte, 1024))
|
|
if !ok {
|
|
t.Fatal(ok)
|
|
}
|
|
|
|
if !bytes.Equal(dec, in) {
|
|
t.Fatal(dec)
|
|
}
|
|
}
|
|
|
|
// Testing that we can relay a data packet via a relay.
|
|
func TestConnWriter_SendDataPacket_relay(t *testing.T) {
|
|
route, rRoute, relay, rRelay := testConnWriter_getTestRoutes()
|
|
|
|
writer := &testUDPAddrPortWriter{}
|
|
w := newConnWriter(writer, rRoute.IP)
|
|
in := []byte("Hello world!")
|
|
|
|
w.SendDataPacket(in, route, relay)
|
|
|
|
out := writer.Written()
|
|
if len(out) != 1 {
|
|
t.Fatal(out)
|
|
}
|
|
|
|
if out[0].Addr != relay.RemoteAddr {
|
|
t.Fatal(out[0])
|
|
}
|
|
|
|
dec, ok := rRelay.DataCipher.Decrypt(out[0].Data, make([]byte, 1024))
|
|
if !ok {
|
|
t.Fatal(ok)
|
|
}
|
|
|
|
dec2, ok := rRoute.DataCipher.Decrypt(dec, make([]byte, 1024))
|
|
if !ok {
|
|
t.Fatal(ok)
|
|
}
|
|
|
|
if !bytes.Equal(dec2, in) {
|
|
t.Fatal(dec2)
|
|
}
|
|
}
|
|
|
|
// Testing that we don't attempt to relay if the relay is nil.
|
|
func TestConnWriter_SendDataPacket_relay_relayNil(t *testing.T) {
|
|
route, rRoute, _, _ := testConnWriter_getTestRoutes()
|
|
|
|
writer := &testUDPAddrPortWriter{}
|
|
w := newConnWriter(writer, rRoute.IP)
|
|
in := []byte("Hello world!")
|
|
|
|
w.SendDataPacket(in, route, nil)
|
|
|
|
out := writer.Written()
|
|
if len(out) != 0 {
|
|
t.Fatal(out)
|
|
}
|
|
}
|
|
|
|
// Testing that we don't attempt to relay if the relay isn't up.
|
|
func TestConnWriter_SendDataPacket_relay_relayNotUp(t *testing.T) {
|
|
route, rRoute, relay, _ := testConnWriter_getTestRoutes()
|
|
relay.Up = false
|
|
|
|
writer := &testUDPAddrPortWriter{}
|
|
w := newConnWriter(writer, rRoute.IP)
|
|
in := []byte("Hello world!")
|
|
|
|
w.SendDataPacket(in, route, relay)
|
|
|
|
out := writer.Written()
|
|
if len(out) != 0 {
|
|
t.Fatal(out)
|
|
}
|
|
}
|