1// Copyright (c) 2013-2014 The btcsuite developers
2// Use of this source code is governed by an ISC
3// license that can be found in the LICENSE file.
4
5package addrmgr_test
6
7import (
8	"errors"
9	"fmt"
10	"net"
11	"reflect"
12	"testing"
13	"time"
14
15	"github.com/btcsuite/btcd/addrmgr"
16	"github.com/btcsuite/btcd/wire"
17)
18
19// naTest is used to describe a test to be performed against the NetAddressKey
20// method.
21type naTest struct {
22	in   wire.NetAddress
23	want string
24}
25
26// naTests houses all of the tests to be performed against the NetAddressKey
27// method.
28var naTests = make([]naTest, 0)
29
30// Put some IP in here for convenience. Points to google.
31var someIP = "173.194.115.66"
32
33// addNaTests
34func addNaTests() {
35	// IPv4
36	// Localhost
37	addNaTest("127.0.0.1", 8333, "127.0.0.1:8333")
38	addNaTest("127.0.0.1", 8334, "127.0.0.1:8334")
39
40	// Class A
41	addNaTest("1.0.0.1", 8333, "1.0.0.1:8333")
42	addNaTest("2.2.2.2", 8334, "2.2.2.2:8334")
43	addNaTest("27.253.252.251", 8335, "27.253.252.251:8335")
44	addNaTest("123.3.2.1", 8336, "123.3.2.1:8336")
45
46	// Private Class A
47	addNaTest("10.0.0.1", 8333, "10.0.0.1:8333")
48	addNaTest("10.1.1.1", 8334, "10.1.1.1:8334")
49	addNaTest("10.2.2.2", 8335, "10.2.2.2:8335")
50	addNaTest("10.10.10.10", 8336, "10.10.10.10:8336")
51
52	// Class B
53	addNaTest("128.0.0.1", 8333, "128.0.0.1:8333")
54	addNaTest("129.1.1.1", 8334, "129.1.1.1:8334")
55	addNaTest("180.2.2.2", 8335, "180.2.2.2:8335")
56	addNaTest("191.10.10.10", 8336, "191.10.10.10:8336")
57
58	// Private Class B
59	addNaTest("172.16.0.1", 8333, "172.16.0.1:8333")
60	addNaTest("172.16.1.1", 8334, "172.16.1.1:8334")
61	addNaTest("172.16.2.2", 8335, "172.16.2.2:8335")
62	addNaTest("172.16.172.172", 8336, "172.16.172.172:8336")
63
64	// Class C
65	addNaTest("193.0.0.1", 8333, "193.0.0.1:8333")
66	addNaTest("200.1.1.1", 8334, "200.1.1.1:8334")
67	addNaTest("205.2.2.2", 8335, "205.2.2.2:8335")
68	addNaTest("223.10.10.10", 8336, "223.10.10.10:8336")
69
70	// Private Class C
71	addNaTest("192.168.0.1", 8333, "192.168.0.1:8333")
72	addNaTest("192.168.1.1", 8334, "192.168.1.1:8334")
73	addNaTest("192.168.2.2", 8335, "192.168.2.2:8335")
74	addNaTest("192.168.192.192", 8336, "192.168.192.192:8336")
75
76	// IPv6
77	// Localhost
78	addNaTest("::1", 8333, "[::1]:8333")
79	addNaTest("fe80::1", 8334, "[fe80::1]:8334")
80
81	// Link-local
82	addNaTest("fe80::1:1", 8333, "[fe80::1:1]:8333")
83	addNaTest("fe91::2:2", 8334, "[fe91::2:2]:8334")
84	addNaTest("fea2::3:3", 8335, "[fea2::3:3]:8335")
85	addNaTest("feb3::4:4", 8336, "[feb3::4:4]:8336")
86
87	// Site-local
88	addNaTest("fec0::1:1", 8333, "[fec0::1:1]:8333")
89	addNaTest("fed1::2:2", 8334, "[fed1::2:2]:8334")
90	addNaTest("fee2::3:3", 8335, "[fee2::3:3]:8335")
91	addNaTest("fef3::4:4", 8336, "[fef3::4:4]:8336")
92}
93
94func addNaTest(ip string, port uint16, want string) {
95	nip := net.ParseIP(ip)
96	na := *wire.NewNetAddressIPPort(nip, port, wire.SFNodeNetwork)
97	test := naTest{na, want}
98	naTests = append(naTests, test)
99}
100
101func lookupFunc(host string) ([]net.IP, error) {
102	return nil, errors.New("not implemented")
103}
104
105func TestStartStop(t *testing.T) {
106	n := addrmgr.New("teststartstop", lookupFunc)
107	n.Start()
108	err := n.Stop()
109	if err != nil {
110		t.Fatalf("Address Manager failed to stop: %v", err)
111	}
112}
113
114func TestAddAddressByIP(t *testing.T) {
115	fmtErr := fmt.Errorf("")
116	addrErr := &net.AddrError{}
117	var tests = []struct {
118		addrIP string
119		err    error
120	}{
121		{
122			someIP + ":8333",
123			nil,
124		},
125		{
126			someIP,
127			addrErr,
128		},
129		{
130			someIP[:12] + ":8333",
131			fmtErr,
132		},
133		{
134			someIP + ":abcd",
135			fmtErr,
136		},
137	}
138
139	amgr := addrmgr.New("testaddressbyip", nil)
140	for i, test := range tests {
141		err := amgr.AddAddressByIP(test.addrIP)
142		if test.err != nil && err == nil {
143			t.Errorf("TestGood test %d failed expected an error and got none", i)
144			continue
145		}
146		if test.err == nil && err != nil {
147			t.Errorf("TestGood test %d failed expected no error and got one", i)
148			continue
149		}
150		if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
151			t.Errorf("TestGood test %d failed got %v, want %v", i,
152				reflect.TypeOf(err), reflect.TypeOf(test.err))
153			continue
154		}
155	}
156}
157
158func TestAddLocalAddress(t *testing.T) {
159	var tests = []struct {
160		address  wire.NetAddress
161		priority addrmgr.AddressPriority
162		valid    bool
163	}{
164		{
165			wire.NetAddress{IP: net.ParseIP("192.168.0.100")},
166			addrmgr.InterfacePrio,
167			false,
168		},
169		{
170			wire.NetAddress{IP: net.ParseIP("204.124.1.1")},
171			addrmgr.InterfacePrio,
172			true,
173		},
174		{
175			wire.NetAddress{IP: net.ParseIP("204.124.1.1")},
176			addrmgr.BoundPrio,
177			true,
178		},
179		{
180			wire.NetAddress{IP: net.ParseIP("::1")},
181			addrmgr.InterfacePrio,
182			false,
183		},
184		{
185			wire.NetAddress{IP: net.ParseIP("fe80::1")},
186			addrmgr.InterfacePrio,
187			false,
188		},
189		{
190			wire.NetAddress{IP: net.ParseIP("2620:100::1")},
191			addrmgr.InterfacePrio,
192			true,
193		},
194	}
195	amgr := addrmgr.New("testaddlocaladdress", nil)
196	for x, test := range tests {
197		result := amgr.AddLocalAddress(&test.address, test.priority)
198		if result == nil && !test.valid {
199			t.Errorf("TestAddLocalAddress test #%d failed: %s should have "+
200				"been accepted", x, test.address.IP)
201			continue
202		}
203		if result != nil && test.valid {
204			t.Errorf("TestAddLocalAddress test #%d failed: %s should not have "+
205				"been accepted", x, test.address.IP)
206			continue
207		}
208	}
209}
210
211func TestAttempt(t *testing.T) {
212	n := addrmgr.New("testattempt", lookupFunc)
213
214	// Add a new address and get it
215	err := n.AddAddressByIP(someIP + ":8333")
216	if err != nil {
217		t.Fatalf("Adding address failed: %v", err)
218	}
219	ka := n.GetAddress()
220
221	if !ka.LastAttempt().IsZero() {
222		t.Errorf("Address should not have attempts, but does")
223	}
224
225	na := ka.NetAddress()
226	n.Attempt(na)
227
228	if ka.LastAttempt().IsZero() {
229		t.Errorf("Address should have an attempt, but does not")
230	}
231}
232
233func TestConnected(t *testing.T) {
234	n := addrmgr.New("testconnected", lookupFunc)
235
236	// Add a new address and get it
237	err := n.AddAddressByIP(someIP + ":8333")
238	if err != nil {
239		t.Fatalf("Adding address failed: %v", err)
240	}
241	ka := n.GetAddress()
242	na := ka.NetAddress()
243	// make it an hour ago
244	na.Timestamp = time.Unix(time.Now().Add(time.Hour*-1).Unix(), 0)
245
246	n.Connected(na)
247
248	if !ka.NetAddress().Timestamp.After(na.Timestamp) {
249		t.Errorf("Address should have a new timestamp, but does not")
250	}
251}
252
253func TestNeedMoreAddresses(t *testing.T) {
254	n := addrmgr.New("testneedmoreaddresses", lookupFunc)
255	addrsToAdd := 1500
256	b := n.NeedMoreAddresses()
257	if !b {
258		t.Errorf("Expected that we need more addresses")
259	}
260	addrs := make([]*wire.NetAddress, addrsToAdd)
261
262	var err error
263	for i := 0; i < addrsToAdd; i++ {
264		s := fmt.Sprintf("%d.%d.173.147:8333", i/128+60, i%128+60)
265		addrs[i], err = n.DeserializeNetAddress(s, wire.SFNodeNetwork)
266		if err != nil {
267			t.Errorf("Failed to turn %s into an address: %v", s, err)
268		}
269	}
270
271	srcAddr := wire.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
272
273	n.AddAddresses(addrs, srcAddr)
274	numAddrs := n.NumAddresses()
275	if numAddrs > addrsToAdd {
276		t.Errorf("Number of addresses is too many %d vs %d", numAddrs, addrsToAdd)
277	}
278
279	b = n.NeedMoreAddresses()
280	if b {
281		t.Errorf("Expected that we don't need more addresses")
282	}
283}
284
285func TestGood(t *testing.T) {
286	n := addrmgr.New("testgood", lookupFunc)
287	addrsToAdd := 64 * 64
288	addrs := make([]*wire.NetAddress, addrsToAdd)
289
290	var err error
291	for i := 0; i < addrsToAdd; i++ {
292		s := fmt.Sprintf("%d.173.147.%d:8333", i/64+60, i%64+60)
293		addrs[i], err = n.DeserializeNetAddress(s, wire.SFNodeNetwork)
294		if err != nil {
295			t.Errorf("Failed to turn %s into an address: %v", s, err)
296		}
297	}
298
299	srcAddr := wire.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
300
301	n.AddAddresses(addrs, srcAddr)
302	for _, addr := range addrs {
303		n.Good(addr)
304	}
305
306	numAddrs := n.NumAddresses()
307	if numAddrs >= addrsToAdd {
308		t.Errorf("Number of addresses is too many: %d vs %d", numAddrs, addrsToAdd)
309	}
310
311	numCache := len(n.AddressCache())
312	if numCache >= numAddrs/4 {
313		t.Errorf("Number of addresses in cache: got %d, want %d", numCache, numAddrs/4)
314	}
315}
316
317func TestGetAddress(t *testing.T) {
318	n := addrmgr.New("testgetaddress", lookupFunc)
319
320	// Get an address from an empty set (should error)
321	if rv := n.GetAddress(); rv != nil {
322		t.Errorf("GetAddress failed: got: %v want: %v\n", rv, nil)
323	}
324
325	// Add a new address and get it
326	err := n.AddAddressByIP(someIP + ":8333")
327	if err != nil {
328		t.Fatalf("Adding address failed: %v", err)
329	}
330	ka := n.GetAddress()
331	if ka == nil {
332		t.Fatalf("Did not get an address where there is one in the pool")
333	}
334	if ka.NetAddress().IP.String() != someIP {
335		t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().IP.String(), someIP)
336	}
337
338	// Mark this as a good address and get it
339	n.Good(ka.NetAddress())
340	ka = n.GetAddress()
341	if ka == nil {
342		t.Fatalf("Did not get an address where there is one in the pool")
343	}
344	if ka.NetAddress().IP.String() != someIP {
345		t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().IP.String(), someIP)
346	}
347
348	numAddrs := n.NumAddresses()
349	if numAddrs != 1 {
350		t.Errorf("Wrong number of addresses: got %d, want %d", numAddrs, 1)
351	}
352}
353
354func TestGetBestLocalAddress(t *testing.T) {
355	localAddrs := []wire.NetAddress{
356		{IP: net.ParseIP("192.168.0.100")},
357		{IP: net.ParseIP("::1")},
358		{IP: net.ParseIP("fe80::1")},
359		{IP: net.ParseIP("2001:470::1")},
360	}
361
362	var tests = []struct {
363		remoteAddr wire.NetAddress
364		want0      wire.NetAddress
365		want1      wire.NetAddress
366		want2      wire.NetAddress
367		want3      wire.NetAddress
368	}{
369		{
370			// Remote connection from public IPv4
371			wire.NetAddress{IP: net.ParseIP("204.124.8.1")},
372			wire.NetAddress{IP: net.IPv4zero},
373			wire.NetAddress{IP: net.IPv4zero},
374			wire.NetAddress{IP: net.ParseIP("204.124.8.100")},
375			wire.NetAddress{IP: net.ParseIP("fd87:d87e:eb43:25::1")},
376		},
377		{
378			// Remote connection from private IPv4
379			wire.NetAddress{IP: net.ParseIP("172.16.0.254")},
380			wire.NetAddress{IP: net.IPv4zero},
381			wire.NetAddress{IP: net.IPv4zero},
382			wire.NetAddress{IP: net.IPv4zero},
383			wire.NetAddress{IP: net.IPv4zero},
384		},
385		{
386			// Remote connection from public IPv6
387			wire.NetAddress{IP: net.ParseIP("2602:100:abcd::102")},
388			wire.NetAddress{IP: net.IPv6zero},
389			wire.NetAddress{IP: net.ParseIP("2001:470::1")},
390			wire.NetAddress{IP: net.ParseIP("2001:470::1")},
391			wire.NetAddress{IP: net.ParseIP("2001:470::1")},
392		},
393		/* XXX
394		{
395			// Remote connection from Tor
396			wire.NetAddress{IP: net.ParseIP("fd87:d87e:eb43::100")},
397			wire.NetAddress{IP: net.IPv4zero},
398			wire.NetAddress{IP: net.ParseIP("204.124.8.100")},
399			wire.NetAddress{IP: net.ParseIP("fd87:d87e:eb43:25::1")},
400		},
401		*/
402	}
403
404	amgr := addrmgr.New("testgetbestlocaladdress", nil)
405
406	// Test against default when there's no address
407	for x, test := range tests {
408		got := amgr.GetBestLocalAddress(&test.remoteAddr)
409		if !test.want0.IP.Equal(got.IP) {
410			t.Errorf("TestGetBestLocalAddress test1 #%d failed for remote address %s: want %s got %s",
411				x, test.remoteAddr.IP, test.want1.IP, got.IP)
412			continue
413		}
414	}
415
416	for _, localAddr := range localAddrs {
417		amgr.AddLocalAddress(&localAddr, addrmgr.InterfacePrio)
418	}
419
420	// Test against want1
421	for x, test := range tests {
422		got := amgr.GetBestLocalAddress(&test.remoteAddr)
423		if !test.want1.IP.Equal(got.IP) {
424			t.Errorf("TestGetBestLocalAddress test1 #%d failed for remote address %s: want %s got %s",
425				x, test.remoteAddr.IP, test.want1.IP, got.IP)
426			continue
427		}
428	}
429
430	// Add a public IP to the list of local addresses.
431	localAddr := wire.NetAddress{IP: net.ParseIP("204.124.8.100")}
432	amgr.AddLocalAddress(&localAddr, addrmgr.InterfacePrio)
433
434	// Test against want2
435	for x, test := range tests {
436		got := amgr.GetBestLocalAddress(&test.remoteAddr)
437		if !test.want2.IP.Equal(got.IP) {
438			t.Errorf("TestGetBestLocalAddress test2 #%d failed for remote address %s: want %s got %s",
439				x, test.remoteAddr.IP, test.want2.IP, got.IP)
440			continue
441		}
442	}
443	/*
444		// Add a Tor generated IP address
445		localAddr = wire.NetAddress{IP: net.ParseIP("fd87:d87e:eb43:25::1")}
446		amgr.AddLocalAddress(&localAddr, addrmgr.ManualPrio)
447
448		// Test against want3
449		for x, test := range tests {
450			got := amgr.GetBestLocalAddress(&test.remoteAddr)
451			if !test.want3.IP.Equal(got.IP) {
452				t.Errorf("TestGetBestLocalAddress test3 #%d failed for remote address %s: want %s got %s",
453					x, test.remoteAddr.IP, test.want3.IP, got.IP)
454				continue
455			}
456		}
457	*/
458}
459
460func TestNetAddressKey(t *testing.T) {
461	addNaTests()
462
463	t.Logf("Running %d tests", len(naTests))
464	for i, test := range naTests {
465		key := addrmgr.NetAddressKey(&test.in)
466		if key != test.want {
467			t.Errorf("NetAddressKey #%d\n got: %s want: %s", i, key, test.want)
468			continue
469		}
470	}
471
472}
473