OSDN Git Service

d6f442f5b53fe8e067869c0f01fc8e960bc8a5ea
[bytom/vapor.git] / p2p / discover / dht / udp_test.go
1 package dht
2
3 import (
4         "bytes"
5         "net"
6         "reflect"
7         "testing"
8         "time"
9
10         "github.com/davecgh/go-spew/spew"
11         "github.com/vapor/common"
12         "github.com/vapor/errors"
13         "github.com/vapor/p2p/signlib"
14 )
15
16 func TestPacketCodec(t *testing.T) {
17         var testPackets = []struct {
18                 ptype      byte
19                 wantErr    error
20                 wantPacket interface{}
21         }{
22                 {
23                         ptype:   byte(pingPacket),
24                         wantErr: nil,
25                         wantPacket: &ping{
26                                 Version:    4,
27                                 From:       rpcEndpoint{net.ParseIP("127.0.0.1").To4(), 3322, 5544},
28                                 To:         rpcEndpoint{net.ParseIP("::1"), 2222, 3333},
29                                 Expiration: 1136239445,
30                                 Topics:     []Topic{"test topic"},
31                                 Rest:       []byte{},
32                         },
33                 },
34                 {
35                         ptype:   byte(pingPacket),
36                         wantErr: nil,
37                         wantPacket: &ping{
38                                 Version:    4,
39                                 From:       rpcEndpoint{net.ParseIP("127.0.0.1").To4(), 3322, 5544},
40                                 To:         rpcEndpoint{net.ParseIP("::1"), 2222, 3333},
41                                 Expiration: 1136239445,
42                                 Topics:     []Topic{"test topic"},
43                                 Rest:       []byte{0x01, 0x02},
44                         },
45                 },
46                 {
47                         ptype:   byte(pingPacket),
48                         wantErr: nil,
49                         wantPacket: &ping{
50                                 Version:    555,
51                                 From:       rpcEndpoint{net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 3322, 5544},
52                                 To:         rpcEndpoint{net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"), 2222, 33338},
53                                 Expiration: 1136239445,
54                                 Topics:     []Topic{"test topic"},
55                                 Rest:       []byte{0xC5, 0x01, 0x02, 0x03, 0x04, 0x05},
56                         },
57                 },
58                 {
59                         ptype:   byte(pongPacket),
60                         wantErr: nil,
61                         wantPacket: &pong{
62                                 To:          rpcEndpoint{net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"), 2222, 33338},
63                                 ReplyTok:    []byte("fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c954"),
64                                 Expiration:  1136239445,
65                                 WaitPeriods: []uint32{},
66                                 Rest:        []byte{0xC6, 0x01, 0x02, 0x03, 0xC2, 0x04, 0x05, 0x06},
67                         },
68                 },
69                 {
70                         ptype:   byte(findnodePacket),
71                         wantErr: nil,
72                         wantPacket: &findnode{
73                                 Target:     MustHexID("a2cb4c36765430f2e72564138c36f30fbc8af5a8bb91649822cd937dedbb8748"),
74                                 Expiration: 1136239445,
75                                 Rest:       []byte{0x82, 0x99, 0x99, 0x83, 0x99, 0x99, 0x99},
76                         },
77                 },
78                 {
79                         ptype:   byte(neighborsPacket),
80                         wantErr: nil,
81                         wantPacket: &neighbors{
82                                 Nodes: []rpcNode{
83                                         {
84                                                 ID:  MustHexID("a2cb4c36765430f2e72564138c36f30fbc8af5a8bb91649822cd937dedbb8748"),
85                                                 IP:  net.ParseIP("99.33.22.55").To4(),
86                                                 UDP: 4444,
87                                                 TCP: 4445,
88                                         },
89                                         {
90                                                 ID:  MustHexID("312c55512422cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d2095"),
91                                                 IP:  net.ParseIP("1.2.3.4").To4(),
92                                                 UDP: 1,
93                                                 TCP: 1,
94                                         },
95                                         {
96                                                 ID:  MustHexID("38643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c"),
97                                                 IP:  net.ParseIP("2001:db8:3c4d:15::abcd:ef12"),
98                                                 UDP: 3333,
99                                                 TCP: 3333,
100                                         },
101                                         {
102                                                 ID:  MustHexID("8dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2"),
103                                                 IP:  net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"),
104                                                 UDP: 999,
105                                                 TCP: 1000,
106                                         },
107                                 },
108                                 Expiration: 1136239445,
109                                 Rest:       []byte{0x01, 0x02, 0x03},
110                         },
111                 },
112                 {
113                         ptype:   byte(findnodeHashPacket),
114                         wantErr: nil,
115                         wantPacket: &findnodeHash{
116                                 Target:     common.Hash{0x0, 0x1, 0x2, 0x3},
117                                 Expiration: 1136239445,
118                                 Rest:       []byte{0x01, 0x02, 0x03},
119                         },
120                 },
121                 {
122                         ptype:   byte(topicRegisterPacket),
123                         wantErr: nil,
124                         wantPacket: &topicRegister{
125                                 Topics: []Topic{"test topic"},
126                                 Idx:    uint(0x01),
127                                 Pong:   []byte{0x01, 0x02, 0x03},
128                         },
129                 },
130                 {
131                         ptype:   byte(topicQueryPacket),
132                         wantErr: nil,
133                         wantPacket: &topicQuery{
134                                 Topic:      "test topic",
135                                 Expiration: 1136239445,
136                         },
137                 },
138                 {
139                         ptype:   byte(topicNodesPacket),
140                         wantErr: nil,
141                         wantPacket: &topicNodes{
142                                 Echo: common.Hash{0x00, 0x01, 0x02},
143                                 Nodes: []rpcNode{
144                                         {
145                                                 ID:  MustHexID("a2cb4c36765430f2e72564138c36f30fbc8af5a8bb91649822cd937dedbb8748"),
146                                                 IP:  net.ParseIP("99.33.22.55").To4(),
147                                                 UDP: 4444,
148                                                 TCP: 4445,
149                                         },
150                                         {
151                                                 ID:  MustHexID("312c55512422cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d2095"),
152                                                 IP:  net.ParseIP("1.2.3.4").To4(),
153                                                 UDP: 1,
154                                                 TCP: 1,
155                                         },
156                                         {
157                                                 ID:  MustHexID("38643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c"),
158                                                 IP:  net.ParseIP("2001:db8:3c4d:15::abcd:ef12"),
159                                                 UDP: 3333,
160                                                 TCP: 3333,
161                                         },
162                                         {
163                                                 ID:  MustHexID("8dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2"),
164                                                 IP:  net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"),
165                                                 UDP: 999,
166                                                 TCP: 1000,
167                                         },
168                                 },
169                         },
170                 },
171                 {
172                         ptype:      byte(topicNodesPacket + 1),
173                         wantErr:    errPacketType,
174                         wantPacket: &topicNodes{},
175                 },
176         }
177
178         privateKey, _ := signlib.NewPrivKey()
179         netID := uint64(0x12345)
180         for i, test := range testPackets {
181                 packet, h, err := encodePacket(privateKey, test.ptype, test.wantPacket, netID)
182                 if err != nil {
183                         t.Fatal(err)
184                 }
185
186                 var pkt ingressPacket
187                 if err := decodePacket(packet, &pkt, netID); err != nil {
188                         if errors.Root(err) != test.wantErr {
189                                 t.Errorf("index %d did not accept packet %s\n%v", i, packet, err)
190                         }
191                         continue
192                 }
193
194                 if !reflect.DeepEqual(pkt.hash, h) {
195                         t.Fatalf("packet hash err. got %x, want %x", pkt.hash, h)
196                 }
197
198                 if !reflect.DeepEqual(pkt.data, test.wantPacket) {
199                         t.Errorf("got %s\nwant %s", spew.Sdump(pkt.data), spew.Sdump(test.wantPacket))
200                 }
201         }
202 }
203
204 type testConn struct {
205         conn net.Conn
206 }
207
208 func (tc *testConn) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) {
209         n, err = tc.conn.Read(b)
210         return n, nil, err
211 }
212
213 func (tc *testConn) WriteToUDP(b []byte, addr *net.UDPAddr) (n int, err error) {
214         return tc.conn.Write(b)
215 }
216
217 func (tc *testConn) Close() error {
218         return tc.conn.Close()
219 }
220
221 func (tc *testConn) LocalAddr() net.Addr {
222         return tc.conn.LocalAddr()
223 }
224
225 type testNetWork struct {
226         read chan ingressPacket // ingress packets arrive here
227         IP   net.IP
228 }
229
230 func (tw *testNetWork) reqReadPacket(pkt ingressPacket) {
231         tw.read <- pkt
232 }
233
234 func (tw *testNetWork) selfIP() net.IP {
235         return tw.IP
236 }
237
238 func TestPacketTransport(t *testing.T) {
239         c1, c2 := net.Pipe()
240         inConn := &testConn{conn: c1}
241         realaddr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 40000}
242         toAddr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 40000}
243         inPrivKey, _ := signlib.NewPrivKey()
244         outPrivKey, _ := signlib.NewPrivKey()
245         netID := uint64(0x12345)
246
247         udpInput, err := listenUDP(inPrivKey, inConn, realaddr, netID)
248         if err != nil {
249                 t.Fatal(err)
250         }
251         node := &Node{ID: MustHexID("8dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2"),
252                 IP:  net.ParseIP("99.33.22.55").To4(),
253                 UDP: 4444,
254                 TCP: 4445,
255         }
256
257         udpInput.net = &testNetWork{read: make(chan ingressPacket, 100)}
258         go udpInput.readLoop()
259
260         outConn := &testConn{conn: c2}
261         udp, err := listenUDP(outPrivKey, outConn, realaddr, netID)
262         if err != nil {
263                 t.Fatal(err)
264         }
265         udp.net = &testNetWork{IP: node.IP}
266         var hash []byte
267
268         //test sendPing
269         hash = udp.sendPing(node, toAddr, nil)
270         pkts := receivePacket(udpInput)
271         if !bytes.Equal(pkts[0].hash, hash) {
272                 t.Fatal("pingPacket transport err")
273         }
274
275         //test sendFindnodeHash
276         target := common.Hash{0x01, 0x02}
277         udp.sendFindnodeHash(node, target)
278         pkts = receivePacket(udpInput)
279         if !bytes.Equal(pkts[0].data.(*findnodeHash).Target.Bytes(), target.Bytes()) {
280                 t.Fatal("findnodeHashPacket transport err")
281         }
282
283         //test sendNeighbours
284         nodes := []*Node{
285                 {
286                         ID:  MustHexID("a2cb4c36765430f2e72564138c36f30fbc8af5a8bb91649822cd937dedbb8748"),
287                         IP:  net.ParseIP("99.33.22.55").To4(),
288                         UDP: 4444,
289                         TCP: 4445,
290                 },
291                 {
292                         ID:  MustHexID("312c55512422cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d2095"),
293                         IP:  net.ParseIP("1.2.3.4").To4(),
294                         UDP: 1,
295                         TCP: 1,
296                 },
297                 {
298                         ID:  MustHexID("38643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c"),
299                         IP:  net.ParseIP("2001:db8:3c4d:15::abcd:ef12"),
300                         UDP: 3333,
301                         TCP: 3333,
302                 },
303                 {
304                         ID:  MustHexID("8dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2"),
305                         IP:  net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"),
306                         UDP: 999,
307                         TCP: 1000,
308                 },
309         }
310
311         udp.sendNeighbours(node, nodes)
312         pkts = receivePacket(udpInput)
313         var gotNodes []rpcNode
314         for _, pkt := range pkts {
315                 gotNodes = append(gotNodes, pkt.data.(*neighbors).Nodes[:]...)
316         }
317         for i := 0; i < len(nodes); i++ {
318                 if !reflect.DeepEqual(nodeToRPC(nodes[i]), gotNodes[i]) {
319                         t.Fatal("sendNeighboursPacket transport err")
320                 }
321         }
322
323         //test sendFindnode
324         targetNode := NodeID{0x01, 0x02, 0x03}
325         udp.sendFindnode(node, targetNode)
326         pkts = receivePacket(udpInput)
327         if pkts[0].data.(*findnode).Target != targetNode {
328                 t.Fatal("sendFindnode transport err")
329         }
330
331         //test sendTopicRegister
332         topics := []Topic{"topic1", "topic2", "topic3"}
333         idx := 0xff
334         pong := []byte{0x01, 0x02, 0x03}
335         udp.sendTopicRegister(node, topics, idx, pong)
336         pkts = receivePacket(udpInput)
337         if !bytes.Equal(pkts[0].data.(*topicRegister).Pong, pong) {
338                 t.Fatal("sendTopicRegister pong field err")
339         }
340         if pkts[0].data.(*topicRegister).Idx != uint(idx) {
341                 t.Fatal("sendTopicRegister idx field err")
342         }
343         if !reflect.DeepEqual(pkts[0].data.(*topicRegister).Topics, topics) {
344                 t.Fatal("sendTopicRegister topic field err")
345         }
346
347         //test sendTopicNodes
348         queryHash := common.Hash{0x01, 0x02, 0x03}
349         udp.sendTopicNodes(node, queryHash, nodes)
350         pkts = receivePacket(udpInput)
351         gotNodes = gotNodes[:0]
352         for _, pkt := range pkts {
353                 gotNodes = append(gotNodes, pkt.data.(*topicNodes).Nodes[:]...)
354         }
355
356         for i := 0; i < 2; i++ {
357                 if !reflect.DeepEqual(nodeToRPC(nodes[i]), gotNodes[i]) {
358                         t.Fatal("sendTopicNodes node field err")
359                 }
360         }
361
362         if pkts[0].data.(*topicNodes).Echo != queryHash {
363                 t.Fatal("sendTopicNodes echo field err")
364         }
365 }
366
367 func TestSendTopicNodes(t *testing.T) {
368         c1, c2 := net.Pipe()
369         inConn := &testConn{conn: c1}
370         realaddr := &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 40000}
371         inPrivKey, _ := signlib.NewPrivKey()
372         outPrivKey, _ := signlib.NewPrivKey()
373         netID := uint64(0x12345)
374
375         udpInput, err := listenUDP(inPrivKey, inConn, realaddr, netID)
376         if err != nil {
377                 t.Fatal(err)
378         }
379         node := &Node{ID: MustHexID("8dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2"),
380                 IP:  net.ParseIP("99.33.22.55").To4(),
381                 UDP: 4444,
382                 TCP: 4445,
383         }
384
385         udpInput.net = &testNetWork{read: make(chan ingressPacket, 100)}
386         go udpInput.readLoop()
387
388         outConn := &testConn{conn: c2}
389         udp, err := listenUDP(outPrivKey, outConn, realaddr, netID)
390         if err != nil {
391                 t.Fatal(err)
392         }
393         udp.net = &testNetWork{IP: node.IP}
394
395         //test sendTopicNodes
396         queryHash := common.Hash{0x01, 0x02, 0x03}
397         var nodes []*Node
398         var gotNodes []rpcNode
399         for i := 0; i < 100; i++ {
400                 node := &Node{
401                         ID:  MustHexID("a2cb4c36765430f2e72564138c36f30fbc8af5a8bb91649822cd937dedbb8748"),
402                         IP:  net.ParseIP("1.2.3.4").To4(),
403                         UDP: uint16(i),
404                         TCP: uint16(i),
405                 }
406                 nodes = append(nodes, node)
407         }
408         udp.sendTopicNodes(node, queryHash, nodes)
409         pkts := receivePacket(udpInput)
410         for _, pkt := range pkts {
411                 gotNodes = append(gotNodes, pkt.data.(*topicNodes).Nodes[:]...)
412         }
413         for i := 0; i < len(gotNodes); i++ {
414                 if !reflect.DeepEqual(nodeToRPC(nodes[i]), gotNodes[i]) {
415                         t.Fatal("sendTopicNodes node field err")
416                 }
417         }
418
419         nodes = nodes[:0]
420         gotNodes = gotNodes[:0]
421         udp.sendTopicNodes(node, queryHash, nodes)
422         pkts = receivePacket(udpInput)
423         for _, pkt := range pkts {
424                 gotNodes = append(gotNodes, pkt.data.(*topicNodes).Nodes[:]...)
425         }
426         for i := 0; i < len(gotNodes); i++ {
427                 if !reflect.DeepEqual(nodeToRPC(nodes[i]), gotNodes[i]) {
428                         t.Fatal("sendTopicNodes node field err")
429                 }
430         }
431 }
432
433 func receivePacket(udpInput *udp) []ingressPacket {
434         waitTicker := time.NewTimer(10 * time.Millisecond)
435         defer waitTicker.Stop()
436         var msgs []ingressPacket
437         for {
438                 select {
439                 case msg := <-udpInput.net.(*testNetWork).read:
440                         msgs = append(msgs, msg)
441                 case <-waitTicker.C:
442                         return msgs
443                 }
444         }
445         return msgs
446 }