319 lines
7.2 KiB
Go
319 lines
7.2 KiB
Go
package peer
|
|
|
|
/*
|
|
type mockIfWriter struct {
|
|
Written [][]byte
|
|
}
|
|
|
|
func (w *mockIfWriter) Write(b []byte) (int, error) {
|
|
w.Written = append(w.Written, bytes.Clone(b))
|
|
return len(b), nil
|
|
}
|
|
|
|
type mockEncryptedPacket struct {
|
|
Packet []byte
|
|
Route *peerRoute
|
|
}
|
|
|
|
type mockEncryptedPacketSender struct {
|
|
Sent []mockEncryptedPacket
|
|
}
|
|
|
|
func (m *mockEncryptedPacketSender) SendEncryptedDataPacket(pkt []byte, route *peerRoute) {
|
|
m.Sent = append(m.Sent, mockEncryptedPacket{
|
|
Packet: bytes.Clone(pkt),
|
|
Route: route,
|
|
})
|
|
}
|
|
|
|
type mockControlMsgHandler struct {
|
|
Messages []any
|
|
}
|
|
|
|
func (m *mockControlMsgHandler) HandleControlMsg(pkt any) {
|
|
m.Messages = append(m.Messages, pkt)
|
|
}
|
|
|
|
type udpPipe struct {
|
|
packets chan []byte
|
|
}
|
|
|
|
func newUDPPipe() *udpPipe {
|
|
return &udpPipe{make(chan []byte, 1024)}
|
|
}
|
|
|
|
func (p *udpPipe) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error) {
|
|
p.packets <- bytes.Clone(b)
|
|
return len(b), nil
|
|
}
|
|
|
|
func (p *udpPipe) ReadFromUDPAddrPort(b []byte) (n int, addr netip.AddrPort, err error) {
|
|
packet := <-p.packets
|
|
copy(b, packet)
|
|
return len(packet), netip.AddrPort{}, nil
|
|
}
|
|
|
|
type connReaderTestHarness struct {
|
|
Pipe *udpPipe
|
|
R *connReader
|
|
WRemote *connWriter
|
|
WRelayRemote *connWriter
|
|
Remote *peerRoute
|
|
RelayRemote *peerRoute
|
|
IFace *mockIfWriter
|
|
Sender *mockEncryptedPacketSender
|
|
Super *mockControlMsgHandler
|
|
}
|
|
|
|
// Peer 2 is indirect, peer 3 is direct.
|
|
func newConnReadeTestHarness() (h connReaderTestHarness) {
|
|
pipe := newUDPPipe()
|
|
routes := [256]*atomic.Pointer[peerRoute]{}
|
|
for i := range routes {
|
|
routes[i] = &atomic.Pointer[peerRoute]{}
|
|
routes[i].Store(&peerRoute{})
|
|
}
|
|
|
|
local, remote, relayLocal, relayRemote := testConnWriter_getTestRoutes()
|
|
routes[2].Store(local)
|
|
routes[3].Store(relayLocal)
|
|
|
|
h.Pipe = pipe
|
|
h.WRemote = newConnWriter(pipe, 2)
|
|
h.WRelayRemote = newConnWriter(pipe, 3)
|
|
|
|
h.Remote = remote
|
|
h.RelayRemote = relayRemote
|
|
h.IFace = &mockIfWriter{}
|
|
h.Sender = &mockEncryptedPacketSender{}
|
|
h.Super = &mockControlMsgHandler{}
|
|
h.R = newConnReader(
|
|
pipe,
|
|
h.IFace,
|
|
h.Sender,
|
|
h.Super,
|
|
1,
|
|
routes)
|
|
return h
|
|
}
|
|
|
|
// Testing that we can receive a control packet.
|
|
func TestConnReader_handleControlPacket(t *testing.T) {
|
|
h := newConnReadeTestHarness()
|
|
|
|
pkt := synPacket{TraceID: 1234}
|
|
|
|
h.WRemote.SendControlPacket(pkt, h.Remote)
|
|
|
|
h.R.handleNextPacket()
|
|
|
|
if len(h.Super.Messages) != 1 {
|
|
t.Fatal(h.Super.Messages)
|
|
}
|
|
|
|
msg := h.Super.Messages[0].(controlMsg[synPacket])
|
|
if !reflect.DeepEqual(pkt, msg.Packet) {
|
|
t.Fatal(msg.Packet)
|
|
}
|
|
}
|
|
|
|
// Testing that a short packet is ignored.
|
|
func TestConnReader_handleNextPacket_short(t *testing.T) {
|
|
h := newConnReadeTestHarness()
|
|
|
|
h.Pipe.WriteToUDPAddrPort([]byte{1, 2, 3}, netip.AddrPort{})
|
|
h.R.handleNextPacket()
|
|
|
|
if len(h.Super.Messages) != 0 {
|
|
t.Fatal(h.Super.Messages)
|
|
}
|
|
}
|
|
|
|
// Testing that a packet with an unexpected stream ID is ignored.
|
|
func TestConnReader_handleNextPacket_unknownStreamID(t *testing.T) {
|
|
h := newConnReadeTestHarness()
|
|
|
|
pkt := synPacket{TraceID: 1234}
|
|
|
|
encrypted := h.WRemote.encryptControlPacket(pkt, h.Remote)
|
|
var header header
|
|
header.Parse(encrypted)
|
|
header.StreamID = 100
|
|
header.Marshal(encrypted)
|
|
|
|
h.WRemote.writeTo(encrypted, netip.AddrPort{})
|
|
h.R.handleNextPacket()
|
|
if len(h.Super.Messages) != 0 {
|
|
t.Fatal(h.Super.Messages)
|
|
}
|
|
}
|
|
|
|
// Testing that control packet without matching control cipher is ignored.
|
|
func TestConnReader_handleControlPacket_noCipher(t *testing.T) {
|
|
h := newConnReadeTestHarness()
|
|
|
|
pkt := synPacket{TraceID: 1234}
|
|
|
|
encrypted := h.WRemote.encryptControlPacket(pkt, h.Remote)
|
|
var header header
|
|
header.Parse(encrypted)
|
|
header.SourceIP = 10
|
|
header.Marshal(encrypted)
|
|
|
|
h.WRemote.writeTo(encrypted, netip.AddrPort{})
|
|
h.R.handleNextPacket()
|
|
if len(h.Super.Messages) != 0 {
|
|
t.Fatal(h.Super.Messages)
|
|
}
|
|
}
|
|
|
|
// Testing that control packet with incrrect destination IP is ignored.
|
|
func TestConnReader_handleControlPacket_incorrectDest(t *testing.T) {
|
|
h := newConnReadeTestHarness()
|
|
|
|
pkt := synPacket{TraceID: 1234}
|
|
|
|
encrypted := h.WRemote.encryptControlPacket(pkt, h.Remote)
|
|
var header header
|
|
header.Parse(encrypted)
|
|
header.DestIP++
|
|
header.Marshal(encrypted)
|
|
|
|
h.WRemote.writeTo(encrypted, netip.AddrPort{})
|
|
h.R.handleNextPacket()
|
|
if len(h.Super.Messages) != 0 {
|
|
t.Fatal(h.Super.Messages)
|
|
}
|
|
}
|
|
|
|
// Testing that modified control packet is ignored.
|
|
func TestConnReader_handleControlPacket_modified(t *testing.T) {
|
|
h := newConnReadeTestHarness()
|
|
|
|
pkt := synPacket{TraceID: 1234}
|
|
|
|
encrypted := h.WRemote.encryptControlPacket(pkt, h.Remote)
|
|
encrypted[len(encrypted)-1]++
|
|
|
|
h.WRemote.writeTo(encrypted, netip.AddrPort{})
|
|
h.R.handleNextPacket()
|
|
if len(h.Super.Messages) != 0 {
|
|
t.Fatal(h.Super.Messages)
|
|
}
|
|
}
|
|
|
|
type emptyPacket struct{}
|
|
|
|
func (p emptyPacket) Marshal(buf []byte) []byte {
|
|
return buf[:0]
|
|
}
|
|
|
|
// Testing that an empty control packet is ignored.
|
|
func TestConnReader_handleControlPacket_empty(t *testing.T) {
|
|
h := newConnReadeTestHarness()
|
|
|
|
pkt := emptyPacket{}
|
|
|
|
encrypted := h.WRemote.encryptControlPacket(pkt, h.Remote)
|
|
h.WRemote.writeTo(encrypted, netip.AddrPort{})
|
|
h.R.handleNextPacket()
|
|
if len(h.Super.Messages) != 0 {
|
|
t.Fatal(h.Super.Messages)
|
|
}
|
|
}
|
|
|
|
// Testing that a duplicate control packet is ignored.
|
|
func TestConnReader_handleControlPacket_duplicate(t *testing.T) {
|
|
h := newConnReadeTestHarness()
|
|
|
|
pkt := synPacket{TraceID: 1234}
|
|
|
|
log.Printf("%d", h.WRemote.counters[1])
|
|
h.WRemote.SendControlPacket(pkt, h.Remote)
|
|
log.Printf("%d", h.WRemote.counters[1])
|
|
|
|
// Rewind the counter.
|
|
h.WRemote.counters[1] = h.WRemote.counters[1] - 1
|
|
log.Printf("%d", h.WRemote.counters[1])
|
|
h.WRemote.SendControlPacket(pkt, h.Remote)
|
|
|
|
h.R.handleNextPacket()
|
|
h.R.handleNextPacket()
|
|
|
|
if len(h.Super.Messages) != 1 {
|
|
t.Fatal(h.Super.Messages)
|
|
}
|
|
|
|
msg := h.Super.Messages[0].(controlMsg[synPacket])
|
|
if !reflect.DeepEqual(pkt, msg.Packet) {
|
|
t.Fatal(msg.Packet)
|
|
}
|
|
}
|
|
|
|
type invalidPacket struct {
|
|
}
|
|
|
|
func (p invalidPacket) Marshal(b []byte) []byte {
|
|
out := b[:256]
|
|
clear(out)
|
|
return out
|
|
}
|
|
|
|
// Testing that an invalid control packet is ignored (fails to parse).
|
|
func TestConnReader_handleControlPacket_cantParse(t *testing.T) {
|
|
h := newConnReadeTestHarness()
|
|
|
|
pkt := invalidPacket{}
|
|
|
|
encrypted := h.WRemote.encryptControlPacket(pkt, h.Remote)
|
|
h.WRemote.writeTo(encrypted, netip.AddrPort{})
|
|
h.R.handleNextPacket()
|
|
if len(h.Super.Messages) != 0 {
|
|
t.Fatal(h.Super.Messages)
|
|
}
|
|
}
|
|
|
|
// Testing that we can receive a data packet.
|
|
func TestConnReader_handleDataPacket(t *testing.T) {
|
|
h := newConnReadeTestHarness()
|
|
|
|
pkt := make([]byte, 1024)
|
|
rand.Read(pkt)
|
|
|
|
h.WRemote.SendDataPacket(pkt, h.Remote)
|
|
|
|
h.R.handleNextPacket()
|
|
|
|
if len(h.IFace.Written) != 1 {
|
|
t.Fatal(h.IFace.Written)
|
|
}
|
|
|
|
if !bytes.Equal(pkt, h.IFace.Written[0]) {
|
|
t.Fatal(h.IFace.Written)
|
|
}
|
|
}
|
|
|
|
// Testing that data packet is ignored if route isn't up.
|
|
func TestConnReader_handleDataPacket_routeDown(t *testing.T) {
|
|
h := newConnReadeTestHarness()
|
|
|
|
pkt := make([]byte, 1024)
|
|
rand.Read(pkt)
|
|
|
|
h.WRemote.SendDataPacket(pkt, h.Remote)
|
|
route := h.R.routes[2].Load()
|
|
route.Up = false
|
|
|
|
h.R.handleNextPacket()
|
|
|
|
if len(h.IFace.Written) != 0 {
|
|
t.Fatal(h.IFace.Written)
|
|
}
|
|
}
|
|
*/
|
|
// Testing that a duplicate data packet is ignored.
|
|
|
|
// Testing that we send a relayed data packet.
|
|
|
|
// Testing that a relayed data packet is ignored if destination isn't up.
|