carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package relay
2
3import (
4 "net"
5 "sync"
6 "testing"
7 "time"
8)
9
10func TestRelayConnGatesEIPPorts(t *testing.T) {
11 inner := &fakePacketConn{}
12 ports := &portSet{m: map[int]bool{50000: true}}
13 eip := net.ParseIP("203.0.113.5")
14 now := time.Unix(1_800_000_000, 0)
15 clock := func() time.Time { return now }
16 var in int
17 c := newRelayConn(inner, &Binding{ID: Identity{"abc", "meet"}}, eip, ports, NewBucket(1<<40, clock), NewBucket(1<<40, clock),
18 func(_ Identity, n int) { in += n }, nil, func(*relayConn) {})
19 ok := &net.UDPAddr{IP: eip, Port: 50000}
20 bad := &net.UDPAddr{IP: eip, Port: 3478}
21 other := &net.UDPAddr{IP: net.ParseIP("198.51.100.9"), Port: 4444}
22 c.WriteTo([]byte("abc"), ok)
23 c.WriteTo([]byte("abc"), bad)
24 c.WriteTo([]byte("abcd"), other)
25 if len(inner.written) != 2 || in != 7 {
26 t.Fatalf("written=%d in=%d, want 2 packets and 7 bytes", len(inner.written), in)
27 }
28}
29
30func TestRelayConnBucketDrops(t *testing.T) {
31 inner := &fakePacketConn{}
32 now := time.Unix(1_800_000_000, 0)
33 clock := func() time.Time { return now }
34 c := newRelayConn(inner, &Binding{}, nil, &portSet{m: map[int]bool{}}, NewBucket(80, clock), NewBucket(1<<40, clock), func(Identity, int) {}, nil, func(*relayConn) {})
35 dst := &net.UDPAddr{IP: net.ParseIP("198.51.100.9"), Port: 4444}
36 c.WriteTo(make([]byte, 10), dst) // 10 bytes = the whole second
37 c.WriteTo(make([]byte, 1), dst)
38 if len(inner.written) != 1 {
39 t.Fatalf("written = %d, want 1 (second dropped by bucket)", len(inner.written))
40 }
41}
42
43func TestRelayConnBoxBucketRefusalDoesNotDebitApp(t *testing.T) {
44 now := time.Unix(1_800_000_000, 0)
45 clock := func() time.Time { return now }
46 appBucket := NewBucket(88, clock) // 11 bytes/s: exactly 1 byte of headroom after a 10-byte write
47 boxBucket := NewBucket(80, clock) // 10 bytes/s
48 inner := &fakePacketConn{}
49 c := newRelayConn(inner, &Binding{}, nil, &portSet{m: map[int]bool{}}, appBucket, boxBucket, func(Identity, int) {}, nil, func(*relayConn) {})
50 dst := &net.UDPAddr{IP: net.ParseIP("198.51.100.9"), Port: 4444}
51
52 c.WriteTo(make([]byte, 10), dst) // spends the whole second on both buckets: app 11->1, box 10->0
53 if len(inner.written) != 1 {
54 t.Fatalf("written = %d, want 1 after the first write", len(inner.written))
55 }
56
57 c.WriteTo(make([]byte, 1), dst) // box has 0 left: refused. With the bug, appBucket.Allow already spent app's last token here.
58 if len(inner.written) != 1 {
59 t.Fatalf("written = %d, want 1 (dropped by the box bucket)", len(inner.written))
60 }
61
62 // A fresh, effectively unlimited box bucket, but the SAME app bucket.
63 // If the earlier box refusal wrongly debited app (the bug), app is now
64 // at 0 and this write is refused too. Fixed, app still has its 1 token.
65 freshBox := NewBucket(1<<40, clock)
66 c2 := newRelayConn(inner, &Binding{}, nil, &portSet{m: map[int]bool{}}, appBucket, freshBox, func(Identity, int) {}, nil, func(*relayConn) {})
67 c2.WriteTo(make([]byte, 1), dst)
68 if len(inner.written) != 2 {
69 t.Fatalf("written = %d, want 2 (app bucket still had its last token after the box refusal)", len(inner.written))
70 }
71}
72
73func TestRelayConnCloseOnce(t *testing.T) {
74 n := 0
75 c := newRelayConn(&fakePacketConn{}, &Binding{}, nil, &portSet{m: map[int]bool{}}, nil, nil, nil, nil, func(*relayConn) { n++ })
76 c.Close()
77 c.Close()
78 if n != 1 {
79 t.Fatalf("onClose ran %d times", n)
80 }
81}
82
83func TestTypedSrc(t *testing.T) {
84 u := &net.UDPAddr{IP: net.ParseIP("192.0.2.1"), Port: 5000}
85 tc := &net.TCPAddr{IP: net.ParseIP("192.0.2.1"), Port: 5000}
86 if typedSrc(u) == typedSrc(tc) {
87 t.Fatal("udp and tcp with the same address must not collide")
88 }
89}
90
91// fakePacketConn records writes; ReadFrom blocks until Close.
92type fakePacketConn struct {
93 mu sync.Mutex
94 written [][]byte
95 closed chan struct{}
96 once sync.Once
97}
98
99func (f *fakePacketConn) init() { f.once.Do(func() { f.closed = make(chan struct{}) }) }
100func (f *fakePacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
101 f.init()
102 <-f.closed
103 return 0, nil, net.ErrClosed
104}
105func (f *fakePacketConn) WriteTo(b []byte, a net.Addr) (int, error) {
106 f.mu.Lock()
107 defer f.mu.Unlock()
108 f.written = append(f.written, append([]byte(nil), b...))
109 return len(b), nil
110}
111func (f *fakePacketConn) Close() error {
112 f.init()
113 select {
114 case <-f.closed:
115 default:
116 close(f.closed)
117 }
118 return nil
119}
120func (f *fakePacketConn) LocalAddr() net.Addr { return &net.UDPAddr{IP: net.IPv4zero, Port: 50000} }
121func (f *fakePacketConn) SetDeadline(time.Time) error { return nil }
122func (f *fakePacketConn) SetReadDeadline(time.Time) error { return nil }
123func (f *fakePacketConn) SetWriteDeadline(time.Time) error { return nil }
124