github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/p2p/discover/udp_test.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package discover 18 19 import ( 20 "bytes" 21 "crypto/ecdsa" 22 "encoding/binary" 23 "encoding/hex" 24 "errors" 25 "fmt" 26 "io" 27 "math/rand" 28 "net" 29 "path/filepath" 30 "reflect" 31 "runtime" 32 "sync" 33 "testing" 34 "time" 35 36 "github.com/davecgh/go-spew/spew" 37 "github.com/ethereumproject/go-ethereum/common" 38 "github.com/ethereumproject/go-ethereum/crypto" 39 "github.com/ethereumproject/go-ethereum/rlp" 40 ) 41 42 func init() { 43 spew.Config.DisableMethods = true 44 } 45 46 // This test checks that isPacketTooBig correctly identifies 47 // errors that result from receiving a UDP packet larger 48 // than the supplied receive buffer. 49 func TestIsPacketTooBig(t *testing.T) { 50 listener, err := net.ListenPacket("udp", "127.0.0.1:0") 51 if err != nil { 52 t.Fatal(err) 53 } 54 defer listener.Close() 55 sender, err := net.Dial("udp", listener.LocalAddr().String()) 56 if err != nil { 57 t.Fatal(err) 58 } 59 defer sender.Close() 60 61 sendN := 1800 62 recvN := 300 63 for i := 0; i < 20; i++ { 64 go func() { 65 buf := make([]byte, sendN) 66 for i := range buf { 67 buf[i] = byte(i) 68 } 69 sender.Write(buf) 70 }() 71 72 buf := make([]byte, recvN) 73 listener.SetDeadline(time.Now().Add(1 * time.Second)) 74 n, _, err := listener.ReadFrom(buf) 75 if err != nil { 76 if nerr, ok := err.(net.Error); ok && nerr.Timeout() { 77 continue 78 } 79 if !isPacketTooBig(err) { 80 t.Fatal("unexpected read error:", spew.Sdump(err)) 81 } 82 continue 83 } 84 if n != recvN { 85 t.Fatalf("short read: %d, want %d", n, recvN) 86 } 87 for i := range buf { 88 if buf[i] != byte(i) { 89 t.Fatalf("error in pattern") 90 break 91 } 92 } 93 } 94 } 95 96 // shared test variables 97 var ( 98 futureExp = uint64(time.Now().Add(10 * time.Hour).Unix()) 99 testTarget = NodeID{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1} 100 testRemote = rpcEndpoint{IP: net.ParseIP("1.1.1.1").To4(), UDP: 1, TCP: 2} 101 testLocalAnnounced = rpcEndpoint{IP: net.ParseIP("2.2.2.2").To4(), UDP: 3, TCP: 4} 102 testLocal = rpcEndpoint{IP: net.ParseIP("3.3.3.3").To4(), UDP: 5, TCP: 6} 103 ) 104 105 type udpTest struct { 106 t *testing.T 107 pipe *dgramPipe 108 table *Table 109 udp *udp 110 sent [][]byte 111 localkey, remotekey *ecdsa.PrivateKey 112 remoteaddr *net.UDPAddr 113 } 114 115 func newUDPTest(t *testing.T) *udpTest { 116 test := &udpTest{ 117 t: t, 118 pipe: newpipe(), 119 localkey: newkey(), 120 remotekey: newkey(), 121 remoteaddr: &net.UDPAddr{IP: net.IP{10, 2, 3, 4}, Port: 30303}, // must come from "reserved" address to be valid since findNode tests use reserved address enodes 122 } 123 test.table, test.udp, _ = newUDP(test.localkey, test.pipe, nil, "") 124 <-test.table.initDone 125 return test 126 } 127 128 // handles a packet as if it had been sent to the transport. 129 func (test *udpTest) packetIn(wantError error, ptype byte, data packet) error { 130 enc, err := encodePacket(test.remotekey, ptype, data) 131 if err != nil { 132 return test.errorf("packet (%d) encode error: %v", ptype, err) 133 } 134 test.sent = append(test.sent, enc) 135 if err = test.udp.handlePacket(test.remoteaddr, enc); err != wantError { 136 return test.errorf("error mismatch: got %q, want %q", err, wantError) 137 } 138 return nil 139 } 140 141 // waits for a packet to be sent by the transport. 142 // validate should have type func(*udpTest, X) error, where X is a packet type. 143 func (test *udpTest) waitPacketOut(validate interface{}) error { 144 dgram := test.pipe.waitPacketOut() 145 p, _, _, err := decodePacket(dgram) 146 if err != nil { 147 return test.errorf("sent packet decode error: %v", err) 148 } 149 fn := reflect.ValueOf(validate) 150 exptype := fn.Type().In(0) 151 if reflect.TypeOf(p) != exptype { 152 return test.errorf("sent packet type mismatch, got: %v, want: %v", reflect.TypeOf(p), exptype) 153 } 154 fn.Call([]reflect.Value{reflect.ValueOf(p)}) 155 return nil 156 } 157 158 func (test *udpTest) errorf(format string, args ...interface{}) error { 159 _, file, line, ok := runtime.Caller(2) // errorf + waitPacketOut 160 if ok { 161 file = filepath.Base(file) 162 } else { 163 file = "???" 164 line = 1 165 } 166 err := fmt.Errorf(format, args...) 167 fmt.Printf("\t%s:%d: %v\n", file, line, err) 168 test.t.Fail() 169 return err 170 } 171 172 func TestUDP_packetErrors(t *testing.T) { 173 test := newUDPTest(t) 174 defer test.table.Close() 175 176 test.packetIn(errExpired, pingPacket, &ping{From: testRemote, To: testLocalAnnounced, Version: Version}) 177 test.packetIn(errUnsolicitedReply, pongPacket, &pong{ReplyTok: []byte{}, Expiration: futureExp}) 178 test.packetIn(errUnknownNode, findnodePacket, &findnode{Expiration: futureExp}) 179 test.packetIn(errUnsolicitedReply, neighborsPacket, &neighbors{Expiration: futureExp}) 180 } 181 182 func TestUDP_pingTimeout(t *testing.T) { 183 t.Parallel() 184 test := newUDPTest(t) 185 defer test.table.Close() 186 187 toaddr := &net.UDPAddr{IP: net.ParseIP("1.2.3.4"), Port: 2222} 188 toid := NodeID{1, 2, 3, 4} 189 if err := test.udp.ping(toid, toaddr); err != errTimeout { 190 t.Error("expected timeout error, got", err) 191 } 192 } 193 194 func TestUDP_responseTimeouts(t *testing.T) { 195 t.Parallel() 196 test := newUDPTest(t) 197 defer test.table.Close() 198 199 rand.Seed(time.Now().UnixNano()) 200 randomDuration := func(max time.Duration) time.Duration { 201 return time.Duration(rand.Int63n(int64(max))) 202 } 203 204 var ( 205 nReqs = 200 206 nTimeouts = 0 // number of requests with ptype > 128 207 nilErr = make(chan error, nReqs) // for requests that get a reply 208 timeoutErr = make(chan error, nReqs) // for requests that time out 209 ) 210 for i := 0; i < nReqs; i++ { 211 // Create a matcher for a random request in udp.loop. Requests 212 // with ptype <= 128 will not get a reply and should time out. 213 // For all other requests, a reply is scheduled to arrive 214 // within the timeout window. 215 p := &pending{ 216 ptype: byte(rand.Intn(255)), 217 callback: func(interface{}) bool { return true }, 218 } 219 binary.BigEndian.PutUint64(p.from[:], uint64(i)) 220 if p.ptype <= 128 { 221 p.errc = timeoutErr 222 test.udp.addpending <- p 223 nTimeouts++ 224 } else { 225 p.errc = nilErr 226 test.udp.addpending <- p 227 time.AfterFunc(randomDuration(60*time.Millisecond), func() { 228 if !test.udp.handleReply(p.from, p.ptype, nil) { 229 t.Logf("not matched: %v", p) 230 } 231 }) 232 } 233 time.Sleep(randomDuration(30 * time.Millisecond)) 234 } 235 236 // Check that all timeouts were delivered and that the rest got nil errors. 237 // The replies must be delivered. 238 var ( 239 recvDeadline = time.After(20 * time.Second) 240 nTimeoutsRecv, nNil = 0, 0 241 ) 242 for i := 0; i < nReqs; i++ { 243 select { 244 case err := <-timeoutErr: 245 if err != errTimeout { 246 t.Fatalf("got non-timeout error on timeoutErr %d: %v", i, err) 247 } 248 nTimeoutsRecv++ 249 case err := <-nilErr: 250 if err != nil { 251 t.Fatalf("got non-nil error on nilErr %d: %v", i, err) 252 } 253 nNil++ 254 case <-recvDeadline: 255 t.Fatalf("exceeded recv deadline") 256 } 257 } 258 if nTimeoutsRecv != nTimeouts { 259 t.Errorf("wrong number of timeout errors received: got %d, want %d", nTimeoutsRecv, nTimeouts) 260 } 261 if nNil != nReqs-nTimeouts { 262 t.Errorf("wrong number of successful replies: got %d, want %d", nNil, nReqs-nTimeouts) 263 } 264 } 265 266 func TestUDP_findnodeTimeout(t *testing.T) { 267 t.Parallel() 268 test := newUDPTest(t) 269 defer test.table.Close() 270 271 toaddr := &net.UDPAddr{IP: net.ParseIP("1.2.3.4"), Port: 2222} 272 toid := NodeID{1, 2, 3, 4} 273 target := NodeID{4, 5, 6, 7} 274 result, err := test.udp.findnode(toid, toaddr, target) 275 if err != errTimeout { 276 t.Error("expected timeout error, got", err) 277 } 278 if len(result) > 0 { 279 t.Error("expected empty result, got", result) 280 } 281 } 282 283 func TestUDP_findnode(t *testing.T) { 284 test := newUDPTest(t) 285 defer test.table.Close() 286 287 // put a few nodes into the table. their exact 288 // distribution shouldn't matter much, altough we need to 289 // take care not to overflow any bucket. 290 nodes := make([]*Node, bucketSize) 291 for i := range nodes { 292 nodes[i] = nodeAtDistance(test.table.self.sha, i+2) 293 } 294 test.table.stuff(nodes) 295 296 // ensure there's a bond with the test node, 297 // findnode won't be accepted otherwise. 298 test.table.db.updateNode(NewNode( 299 PubkeyID(&test.remotekey.PublicKey), 300 test.remoteaddr.IP, 301 uint16(test.remoteaddr.Port), 302 99, 303 )) 304 // check that closest neighbors are returned. 305 test.packetIn(nil, findnodePacket, &findnode{Target: testTarget, Expiration: futureExp}) 306 expected := test.table.closest(testTarget) 307 308 waitNeighbors := func(want []*Node) { 309 test.waitPacketOut(func(p *neighbors) { 310 if len(p.Nodes) != len(want) { 311 t.Errorf("wrong number of results: got %d, want %d", len(p.Nodes), bucketSize) 312 } 313 for i := range p.Nodes { 314 if p.Nodes[i].ID != want[i].ID { 315 t.Errorf("result mismatch at %d:\n got: %v\n want: %v", i, p.Nodes[i], expected.Nodes[i]) 316 } 317 } 318 }) 319 } 320 waitNeighbors(expected.Nodes[:maxNeighbors]) 321 waitNeighbors(expected.Nodes[maxNeighbors:]) 322 } 323 324 func TestUDP_findnodeMultiReply(t *testing.T) { 325 test := newUDPTest(t) 326 defer test.table.Close() 327 328 // queue a pending findnode request 329 resultc, errc := make(chan []*Node), make(chan error) 330 go func() { 331 rid := PubkeyID(&test.remotekey.PublicKey) 332 ns, err := test.udp.findnode(rid, test.remoteaddr, testTarget) 333 if err != nil && len(ns) == 0 { 334 errc <- err 335 } else { 336 resultc <- ns 337 } 338 }() 339 340 // wait for the findnode to be sent. 341 // after it is sent, the transport is waiting for a reply 342 test.waitPacketOut(func(p *findnode) { 343 if p.Target != testTarget { 344 t.Errorf("wrong target: got %v, want %v", p.Target, testTarget) 345 } 346 }) 347 348 // send the reply as two packets. 349 list := []*Node{ 350 MustParseNode("enode://ba85011c70bcc5c04d8607d3a0ed29aa6179c092cbdda10d5d32684fb33ed01bd94f588ca8f91ac48318087dcb02eaf36773a7a453f0eedd6742af668097b29c@10.0.1.16:30303?discport=30304"), 351 MustParseNode("enode://81fa361d25f157cd421c60dcc28d8dac5ef6a89476633339c5df30287474520caca09627da18543d9079b5b288698b542d56167aa5c09111e55acdbbdf2ef799@10.0.1.16:30303"), 352 MustParseNode("enode://9bffefd833d53fac8e652415f4973bee289e8b1a5c6c4cbe70abf817ce8a64cee11b823b66a987f51aaa9fba0d6a91b3e6bf0d5a5d1042de8e9eeea057b217f8@10.0.1.36:30301?discport=17"), 353 MustParseNode("enode://1b5b4aa662d7cb44a7221bfba67302590b643028197a7d5214790f3bac7aaa4a3241be9e83c09cf1f6c69d007c634faae3dc1b1221793e8446c0b3a09de65960@10.0.1.16:30303"), 354 } 355 rpclist := make([]rpcNode, len(list)) 356 for i := range list { 357 rpclist[i] = nodeToRPC(list[i]) 358 } 359 test.packetIn(nil, neighborsPacket, &neighbors{Expiration: futureExp, Nodes: rpclist[:2]}) 360 test.packetIn(nil, neighborsPacket, &neighbors{Expiration: futureExp, Nodes: rpclist[2:]}) 361 362 // check that the sent neighbors are all returned by findnode 363 select { 364 case result := <-resultc: 365 want := append(list[:2], list[3:]...) 366 if !reflect.DeepEqual(result, want) { 367 t.Errorf("neighbors mismatch:\n got: %v\n want: %v", result, want) 368 } 369 case err := <-errc: 370 t.Errorf("findnode error: %v", err) 371 case <-time.After(5 * time.Second): 372 t.Error("findnode did not return within 5 seconds") 373 } 374 } 375 376 func TestUDP_successfulPing(t *testing.T) { 377 test := newUDPTest(t) 378 added := make(chan *Node, 1) 379 test.table.nodeAddedHook = func(n *Node) { added <- n } 380 defer test.table.Close() 381 382 // The remote side sends a ping packet to initiate the exchange. 383 go test.packetIn(nil, pingPacket, &ping{From: testRemote, To: testLocalAnnounced, Version: Version, Expiration: futureExp}) 384 385 // the ping is replied to. 386 test.waitPacketOut(func(p *pong) { 387 pinghash := test.sent[0][:macSize] 388 if !bytes.Equal(p.ReplyTok, pinghash) { 389 t.Errorf("got pong.ReplyTok %x, want %x", p.ReplyTok, pinghash) 390 } 391 wantTo := rpcEndpoint{ 392 // The mirrored UDP address is the UDP packet sender 393 IP: test.remoteaddr.IP, UDP: uint16(test.remoteaddr.Port), 394 // The mirrored TCP port is the one from the ping packet 395 TCP: testRemote.TCP, 396 } 397 if !reflect.DeepEqual(p.To, wantTo) { 398 t.Errorf("got pong.To %v, want %v", p.To, wantTo) 399 } 400 }) 401 402 // remote is unknown, the table pings back. 403 test.waitPacketOut(func(p *ping) error { 404 if !reflect.DeepEqual(p.From, test.udp.ourEndpoint) { 405 t.Errorf("got ping.From %v, want %v", p.From, test.udp.ourEndpoint) 406 } 407 wantTo := rpcEndpoint{ 408 // The mirrored UDP address is the UDP packet sender. 409 IP: test.remoteaddr.IP, UDP: uint16(test.remoteaddr.Port), 410 TCP: 0, 411 } 412 if !reflect.DeepEqual(p.To, wantTo) { 413 t.Errorf("got ping.To %v, want %v", p.To, wantTo) 414 } 415 return nil 416 }) 417 test.packetIn(nil, pongPacket, &pong{Expiration: futureExp}) 418 419 // the node should be added to the table shortly after getting the 420 // pong packet. 421 select { 422 case n := <-added: 423 rid := PubkeyID(&test.remotekey.PublicKey) 424 if n.ID != rid { 425 t.Errorf("node has wrong ID: got %v, want %v", n.ID, rid) 426 } 427 if !bytes.Equal(n.IP, test.remoteaddr.IP) { 428 t.Errorf("node has wrong IP: got %v, want: %v", n.IP, test.remoteaddr.IP) 429 } 430 if int(n.UDP) != test.remoteaddr.Port { 431 t.Errorf("node has wrong UDP port: got %v, want: %v", n.UDP, test.remoteaddr.Port) 432 } 433 if n.TCP != testRemote.TCP { 434 t.Errorf("node has wrong TCP port: got %v, want: %v", n.TCP, testRemote.TCP) 435 } 436 case <-time.After(2 * time.Second): 437 t.Errorf("node was not added within 2 seconds") 438 } 439 } 440 441 var testPackets = []struct { 442 input string 443 wantPacket interface{} 444 }{ 445 { 446 input: "71dbda3a79554728d4f94411e42ee1f8b0d561c10e1e5f5893367948c6a7d70bb87b235fa28a77070271b6c164a2dce8c7e13a5739b53b5e96f2e5acb0e458a02902f5965d55ecbeb2ebb6cabb8b2b232896a36b737666c55265ad0a68412f250001ea04cb847f000001820cfa8215a8d790000000000000000000000000000000018208ae820d058443b9a355", 447 wantPacket: &ping{ 448 Version: 4, 449 From: rpcEndpoint{net.ParseIP("127.0.0.1").To4(), 3322, 5544}, 450 To: rpcEndpoint{net.ParseIP("::1"), 2222, 3333}, 451 Expiration: 1136239445, 452 Rest: []rlp.RawValue{}, 453 }, 454 }, 455 { 456 input: "e9614ccfd9fc3e74360018522d30e1419a143407ffcce748de3e22116b7e8dc92ff74788c0b6663aaa3d67d641936511c8f8d6ad8698b820a7cf9e1be7155e9a241f556658c55428ec0563514365799a4be2be5a685a80971ddcfa80cb422cdd0101ec04cb847f000001820cfa8215a8d790000000000000000000000000000000018208ae820d058443b9a3550102", 457 wantPacket: &ping{ 458 Version: 4, 459 From: rpcEndpoint{net.ParseIP("127.0.0.1").To4(), 3322, 5544}, 460 To: rpcEndpoint{net.ParseIP("::1"), 2222, 3333}, 461 Expiration: 1136239445, 462 Rest: []rlp.RawValue{{0x01}, {0x02}}, 463 }, 464 }, 465 { 466 input: "577be4349c4dd26768081f58de4c6f375a7a22f3f7adda654d1428637412c3d7fe917cadc56d4e5e7ffae1dbe3efffb9849feb71b262de37977e7c7a44e677295680e9e38ab26bee2fcbae207fba3ff3d74069a50b902a82c9903ed37cc993c50001f83e82022bd79020010db83c4d001500000000abcdef12820cfa8215a8d79020010db885a308d313198a2e037073488208ae82823a8443b9a355c5010203040531b9019afde696e582a78fa8d95ea13ce3297d4afb8ba6433e4154caa5ac6431af1b80ba76023fa4090c408f6b4bc3701562c031041d4702971d102c9ab7fa5eed4cd6bab8f7af956f7d565ee1917084a95398b6a21eac920fe3dd1345ec0a7ef39367ee69ddf092cbfe5b93e5e568ebc491983c09c76d922dc3", 467 wantPacket: &ping{ 468 Version: 555, 469 From: rpcEndpoint{net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 3322, 5544}, 470 To: rpcEndpoint{net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"), 2222, 33338}, 471 Expiration: 1136239445, 472 Rest: []rlp.RawValue{{0xC5, 0x01, 0x02, 0x03, 0x04, 0x05}}, 473 }, 474 }, 475 { 476 input: "09b2428d83348d27cdf7064ad9024f526cebc19e4958f0fdad87c15eb598dd61d08423e0bf66b2069869e1724125f820d851c136684082774f870e614d95a2855d000f05d1648b2d5945470bc187c2d2216fbe870f43ed0909009882e176a46b0102f846d79020010db885a308d313198a2e037073488208ae82823aa0fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c9548443b9a355c6010203c2040506a0c969a58f6f9095004c0177a6b47f451530cab38966a25cca5cb58f055542124e", 477 wantPacket: &pong{ 478 To: rpcEndpoint{net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"), 2222, 33338}, 479 ReplyTok: common.Hex2Bytes("fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c954"), 480 Expiration: 1136239445, 481 Rest: []rlp.RawValue{{0xC6, 0x01, 0x02, 0x03, 0xC2, 0x04, 0x05}, {0x06}}, 482 }, 483 }, 484 { 485 input: "c7c44041b9f7c7e41934417ebac9a8e1a4c6298f74553f2fcfdcae6ed6fe53163eb3d2b52e39fe91831b8a927bf4fc222c3902202027e5e9eb812195f95d20061ef5cd31d502e47ecb61183f74a504fe04c51e73df81f25c4d506b26db4517490103f84eb840ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31387574077f301b421bc84df7266c44e9e6d569fc56be00812904767bf5ccd1fc7f8443b9a35582999983999999280dc62cc8255c73471e0a61da0c89acdc0e035e260add7fc0c04ad9ebf3919644c91cb247affc82b69bd2ca235c71eab8e49737c937a2c396", 486 wantPacket: &findnode{ 487 Target: MustHexID("ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd31387574077f301b421bc84df7266c44e9e6d569fc56be00812904767bf5ccd1fc7f"), 488 Expiration: 1136239445, 489 Rest: []rlp.RawValue{{0x82, 0x99, 0x99}, {0x83, 0x99, 0x99, 0x99}}, 490 }, 491 }, 492 { 493 input: "c679fc8fe0b8b12f06577f2e802d34f6fa257e6137a995f6f4cbfc9ee50ed3710faf6e66f932c4c8d81d64343f429651328758b47d3dbc02c4042f0fff6946a50f4a49037a72bb550f3a7872363a83e1b9ee6469856c24eb4ef80b7535bcf99c0004f9015bf90150f84d846321163782115c82115db8403155e1427f85f10a5c9a7755877748041af1bcd8d474ec065eb33df57a97babf54bfd2103575fa829115d224c523596b401065a97f74010610fce76382c0bf32f84984010203040101b840312c55512422cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d20951933beea1e4dfa6f968212385e829f04c2d314fc2d4e255e0d3bc08792b069dbf8599020010db83c4d001500000000abcdef12820d05820d05b84038643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c765dd2d96126051913f44582e8c199ad7c6d6819e9a56483f637feaac9448aacf8599020010db885a308d313198a2e037073488203e78203e8b8408dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2d47295286fc00cc081bb542d760717d1bdd6bec2c37cd72eca367d6dd3b9df738443b9a355010203b525a138aa34383fec3d2719a0", 494 wantPacket: &neighbors{ 495 Nodes: []rpcNode{ 496 { 497 ID: MustHexID("3155e1427f85f10a5c9a7755877748041af1bcd8d474ec065eb33df57a97babf54bfd2103575fa829115d224c523596b401065a97f74010610fce76382c0bf32"), 498 IP: net.ParseIP("99.33.22.55").To4(), 499 UDP: 4444, 500 TCP: 4445, 501 }, 502 { 503 ID: MustHexID("312c55512422cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d20951933beea1e4dfa6f968212385e829f04c2d314fc2d4e255e0d3bc08792b069db"), 504 IP: net.ParseIP("1.2.3.4").To4(), 505 UDP: 1, 506 TCP: 1, 507 }, 508 { 509 ID: MustHexID("38643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c765dd2d96126051913f44582e8c199ad7c6d6819e9a56483f637feaac9448aac"), 510 IP: net.ParseIP("2001:db8:3c4d:15::abcd:ef12"), 511 UDP: 3333, 512 TCP: 3333, 513 }, 514 { 515 ID: MustHexID("8dcab8618c3253b558d459da53bd8fa68935a719aff8b811197101a4b2b47dd2d47295286fc00cc081bb542d760717d1bdd6bec2c37cd72eca367d6dd3b9df73"), 516 IP: net.ParseIP("2001:db8:85a3:8d3:1319:8a2e:370:7348"), 517 UDP: 999, 518 TCP: 1000, 519 }, 520 }, 521 Expiration: 1136239445, 522 Rest: []rlp.RawValue{{0x01}, {0x02}, {0x03}}, 523 }, 524 }, 525 } 526 527 func TestForwardCompatibility(t *testing.T) { 528 testkey, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 529 wantNodeID := PubkeyID(&testkey.PublicKey) 530 531 for _, test := range testPackets { 532 input, err := hex.DecodeString(test.input) 533 if err != nil { 534 t.Fatalf("invalid hex: %s", test.input) 535 } 536 packet, nodeid, _, err := decodePacket(input) 537 if err != nil { 538 t.Errorf("did not accept packet %s\n%v", test.input, err) 539 continue 540 } 541 if !reflect.DeepEqual(packet, test.wantPacket) { 542 t.Errorf("got %s\nwant %s", spew.Sdump(packet), spew.Sdump(test.wantPacket)) 543 } 544 if nodeid != wantNodeID { 545 t.Errorf("got id %v\nwant id %v", nodeid, wantNodeID) 546 } 547 } 548 } 549 550 func TestIPBetween(t *testing.T) { 551 HandleIpBetween(t, "0.0.0.0", "255.255.255.255", "128.128.128.128", true) 552 HandleIpBetween(t, "0.0.0.0", "128.128.128.128", "255.255.255.255", false) 553 HandleIpBetween(t, "74.50.153.0", "74.50.153.4", "74.50.153.0", true) 554 HandleIpBetween(t, "74.50.153.0", "74.50.153.4", "74.50.153.4", true) 555 HandleIpBetween(t, "74.50.153.0", "74.50.153.4", "74.50.153.5", false) 556 HandleIpBetween(t, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "74.50.153.4", "74.50.153.2", false) 557 HandleIpBetween(t, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "2001:0db8:85a3:0000:0000:8a2e:0370:8334", "2001:0db8:85a3:0000:0000:8a2e:0370:7334", true) 558 HandleIpBetween(t, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "2001:0db8:85a3:0000:0000:8a2e:0370:8334", "2001:0db8:85a3:0000:0000:8a2e:0370:7350", true) 559 HandleIpBetween(t, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "2001:0db8:85a3:0000:0000:8a2e:0370:8334", "2001:0db8:85a3:0000:0000:8a2e:0370:8334", true) 560 HandleIpBetween(t, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "2001:0db8:85a3:0000:0000:8a2e:0370:8334", "2001:0db8:85a3:0000:0000:8a2e:0370:8335", false) 561 HandleIpBetween(t, "::ffff:192.0.2.128", "::ffff:192.0.2.250", "::ffff:192.0.2.127", false) 562 HandleIpBetween(t, "::ffff:192.0.2.128", "::ffff:192.0.2.250", "::ffff:192.0.2.128", true) 563 HandleIpBetween(t, "::ffff:192.0.2.128", "::ffff:192.0.2.250", "::ffff:192.0.2.129", true) 564 HandleIpBetween(t, "::ffff:192.0.2.128", "::ffff:192.0.2.250", "::ffff:192.0.2.250", true) 565 HandleIpBetween(t, "::ffff:192.0.2.128", "::ffff:192.0.2.250", "::ffff:192.0.2.251", false) 566 HandleIpBetween(t, "::ffff:192.0.2.128", "::ffff:192.0.2.250", "192.0.2.130", true) 567 HandleIpBetween(t, "192.0.2.128", "192.0.2.250", "::ffff:192.0.2.130", true) 568 HandleIpBetween(t, "idonotparse", "192.0.2.250", "::ffff:192.0.2.130", false) 569 } 570 571 func HandleIpBetween(t *testing.T, from string, to string, test string, assert bool) { 572 res, e := IpBetween(net.ParseIP(from), net.ParseIP(to), net.ParseIP(test)) 573 // If there is an error and we expected truth. 574 if e != nil && assert { 575 t.Errorf("Assertion (have: %t should be: %t) failed on range %s-%s with test %s: error: %v", res, assert, from, to, test, e) 576 } 577 if res != assert { 578 t.Errorf("Assertion (have: %t should be: %t) failed on range %s-%s with test %s", res, assert, from, to, test) 579 } 580 } 581 582 func TestIsReserved(t *testing.T) { 583 table := []struct { 584 ip string 585 reserved bool 586 }{ 587 {"0.1.1.1", true}, 588 {"10.0.0.1", true}, 589 {"127.12.13.14", true}, 590 {"128.1.1.12", false}, 591 } 592 for _, tt := range table { 593 if got := isReserved(net.ParseIP(tt.ip)); got != tt.reserved { 594 t.Errorf("unexpected: ip: %v, notReserved? -> want: %v, got: %v", tt.ip, tt.reserved, got) 595 } 596 } 597 } 598 599 // dgramPipe is a fake UDP socket. It queues all sent datagrams. 600 type dgramPipe struct { 601 mu *sync.Mutex 602 cond *sync.Cond 603 closing chan struct{} 604 closed bool 605 queue [][]byte 606 } 607 608 func newpipe() *dgramPipe { 609 mu := new(sync.Mutex) 610 return &dgramPipe{ 611 closing: make(chan struct{}), 612 cond: &sync.Cond{L: mu}, 613 mu: mu, 614 } 615 } 616 617 // WriteToUDP queues a datagram. 618 func (c *dgramPipe) WriteToUDP(b []byte, to *net.UDPAddr) (n int, err error) { 619 msg := make([]byte, len(b)) 620 copy(msg, b) 621 c.mu.Lock() 622 defer c.mu.Unlock() 623 if c.closed { 624 return 0, errors.New("closed") 625 } 626 c.queue = append(c.queue, msg) 627 c.cond.Signal() 628 return len(b), nil 629 } 630 631 // ReadFromUDP just hangs until the pipe is closed. 632 func (c *dgramPipe) ReadFromUDP(b []byte) (n int, addr *net.UDPAddr, err error) { 633 <-c.closing 634 return 0, nil, io.EOF 635 } 636 637 func (c *dgramPipe) Close() error { 638 c.mu.Lock() 639 defer c.mu.Unlock() 640 if !c.closed { 641 close(c.closing) 642 c.closed = true 643 } 644 return nil 645 } 646 647 func (c *dgramPipe) LocalAddr() net.Addr { 648 return &net.UDPAddr{IP: testLocal.IP, Port: int(testLocal.UDP)} 649 } 650 651 func (c *dgramPipe) waitPacketOut() []byte { 652 c.mu.Lock() 653 defer c.mu.Unlock() 654 for len(c.queue) == 0 { 655 c.cond.Wait() 656 } 657 p := c.queue[0] 658 copy(c.queue, c.queue[1:]) 659 c.queue = c.queue[:len(c.queue)-1] 660 return p 661 }