diff options
-rw-r--r-- | eth/backend.go | 4 | ||||
-rw-r--r-- | p2p/discover/database_test.go | 10 | ||||
-rw-r--r-- | p2p/discover/node.go | 61 | ||||
-rw-r--r-- | p2p/discover/node_test.go | 26 | ||||
-rw-r--r-- | p2p/discover/table.go | 9 | ||||
-rw-r--r-- | p2p/discover/table_test.go | 4 | ||||
-rw-r--r-- | p2p/discover/udp.go | 78 | ||||
-rw-r--r-- | p2p/discover/udp_test.go | 81 | ||||
-rw-r--r-- | p2p/handshake_test.go | 12 | ||||
-rw-r--r-- | p2p/server.go | 2 | ||||
-rw-r--r-- | p2p/server_test.go | 2 |
11 files changed, 160 insertions, 129 deletions
diff --git a/eth/backend.go b/eth/backend.go index c5fa328b0..6a5792c46 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -277,8 +277,8 @@ func (s *Ethereum) NodeInfo() *NodeInfo { NodeUrl: node.String(), NodeID: node.ID.String(), IP: node.IP.String(), - DiscPort: node.DiscPort, - TCPPort: node.TCPPort, + DiscPort: int(node.UDP), + TCPPort: int(node.TCP), ListenAddr: s.net.ListenAddr, Td: s.ChainManager().Td().String(), } diff --git a/p2p/discover/database_test.go b/p2p/discover/database_test.go index f327cf73b..0cc0dec32 100644 --- a/p2p/discover/database_test.go +++ b/p2p/discover/database_test.go @@ -6,6 +6,7 @@ import ( "net" "os" "path/filepath" + "reflect" "testing" "time" ) @@ -86,9 +87,10 @@ func TestNodeDBInt64(t *testing.T) { func TestNodeDBFetchStore(t *testing.T) { node := &Node{ - ID: MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), - IP: net.IP([]byte{192, 168, 0, 1}), - TCPPort: 30303, + ID: MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), + IP: net.IP([]byte{192, 168, 0, 1}), + UDP: 30303, + TCP: 30303, } inst := time.Now() @@ -124,7 +126,7 @@ func TestNodeDBFetchStore(t *testing.T) { } if stored := db.node(node.ID); stored == nil { t.Errorf("node: not found") - } else if !bytes.Equal(stored.ID[:], node.ID[:]) || !stored.IP.Equal(node.IP) || stored.TCPPort != node.TCPPort { + } else if !reflect.DeepEqual(stored, node) { t.Errorf("node: data mismatch: have %v, want %v", stored, node) } } diff --git a/p2p/discover/node.go b/p2p/discover/node.go index e66ca37a4..cfb6ff552 100644 --- a/p2p/discover/node.go +++ b/p2p/discover/node.go @@ -6,7 +6,6 @@ import ( "encoding/hex" "errors" "fmt" - "io" "math/big" "math/rand" "net" @@ -16,49 +15,45 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/secp256k1" - "github.com/ethereum/go-ethereum/rlp" ) const nodeIDBits = 512 // Node represents a host on the network. type Node struct { - ID NodeID - IP net.IP - - DiscPort int // UDP listening port for discovery protocol - TCPPort int // TCP listening port for RLPx + IP net.IP // len 4 for IPv4 or 16 for IPv6 + UDP, TCP uint16 // port numbers + ID NodeID } func newNode(id NodeID, addr *net.UDPAddr) *Node { + ip := addr.IP.To4() + if ip == nil { + ip = addr.IP.To16() + } return &Node{ - ID: id, - IP: addr.IP, - DiscPort: addr.Port, - TCPPort: addr.Port, + IP: ip, + UDP: uint16(addr.Port), + TCP: uint16(addr.Port), + ID: id, } } -func (n *Node) isValid() bool { - // TODO: don't accept localhost, LAN addresses from internet hosts - return !n.IP.IsMulticast() && !n.IP.IsUnspecified() && n.TCPPort != 0 && n.DiscPort != 0 -} - func (n *Node) addr() *net.UDPAddr { - return &net.UDPAddr{IP: n.IP, Port: n.DiscPort} + return &net.UDPAddr{IP: n.IP, Port: int(n.UDP)} } // The string representation of a Node is a URL. // Please see ParseNode for a description of the format. func (n *Node) String() string { - addr := net.TCPAddr{IP: n.IP, Port: n.TCPPort} + addr := net.TCPAddr{IP: n.IP, Port: int(n.TCP)} u := url.URL{ Scheme: "enode", User: url.User(fmt.Sprintf("%x", n.ID[:])), Host: addr.String(), } - if n.DiscPort != n.TCPPort { - u.RawQuery = "discport=" + strconv.Itoa(n.DiscPort) + if n.UDP != n.TCP { + u.RawQuery = "discport=" + strconv.Itoa(int(n.UDP)) } return u.String() } @@ -98,16 +93,20 @@ func ParseNode(rawurl string) (*Node, error) { if n.IP = net.ParseIP(ip); n.IP == nil { return nil, errors.New("invalid IP address") } - if n.TCPPort, err = strconv.Atoi(port); err != nil { + tcp, err := strconv.ParseUint(port, 10, 16) + if err != nil { return nil, errors.New("invalid port") } + n.TCP = uint16(tcp) qv := u.Query() if qv.Get("discport") == "" { - n.DiscPort = n.TCPPort + n.UDP = n.TCP } else { - if n.DiscPort, err = strconv.Atoi(qv.Get("discport")); err != nil { + udp, err := strconv.ParseUint(qv.Get("discport"), 10, 16) + if err != nil { return nil, errors.New("invalid discport in query") } + n.UDP = uint16(udp) } return &n, nil } @@ -121,22 +120,6 @@ func MustParseNode(rawurl string) *Node { return n } -func (n Node) EncodeRLP(w io.Writer) error { - return rlp.Encode(w, rpcNode{IP: n.IP.String(), Port: uint16(n.TCPPort), ID: n.ID}) -} -func (n *Node) DecodeRLP(s *rlp.Stream) (err error) { - var ext rpcNode - if err = s.Decode(&ext); err == nil { - n.TCPPort = int(ext.Port) - n.DiscPort = int(ext.Port) - n.ID = ext.ID - if n.IP = net.ParseIP(ext.IP); n.IP == nil { - return errors.New("invalid IP string") - } - } - return err -} - // NodeID is a unique identifier for each node. // The node identifier is a marshaled elliptic curve public key. type NodeID [nodeIDBits / 8]byte diff --git a/p2p/discover/node_test.go b/p2p/discover/node_test.go index 60b01b6ca..8ea9018c5 100644 --- a/p2p/discover/node_test.go +++ b/p2p/discover/node_test.go @@ -49,28 +49,28 @@ var parseNodeTests = []struct { { rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150", wantResult: &Node{ - ID: MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), - IP: net.ParseIP("127.0.0.1"), - DiscPort: 52150, - TCPPort: 52150, + ID: MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), + IP: net.ParseIP("127.0.0.1"), + UDP: 52150, + TCP: 52150, }, }, { rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@[::]:52150", wantResult: &Node{ - ID: MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), - IP: net.ParseIP("::"), - DiscPort: 52150, - TCPPort: 52150, + ID: MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), + IP: net.ParseIP("::"), + UDP: 52150, + TCP: 52150, }, }, { - rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=223344", + rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=22334", wantResult: &Node{ - ID: MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), - IP: net.ParseIP("127.0.0.1"), - DiscPort: 223344, - TCPPort: 52150, + ID: MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), + IP: net.ParseIP("127.0.0.1"), + UDP: 22334, + TCP: 52150, }, }, } diff --git a/p2p/discover/table.go b/p2p/discover/table.go index d3fe373f4..bbd40fde9 100644 --- a/p2p/discover/table.go +++ b/p2p/discover/table.go @@ -220,7 +220,7 @@ func (tab *Table) bondall(nodes []*Node) (result []*Node) { rc := make(chan *Node, len(nodes)) for i := range nodes { go func(n *Node) { - nn, _ := tab.bond(false, n.ID, n.addr(), uint16(n.TCPPort)) + nn, _ := tab.bond(false, n.ID, n.addr(), uint16(n.TCP)) rc <- nn }(nodes[i]) } @@ -299,12 +299,7 @@ func (tab *Table) pingpong(w *bondproc, pinged bool, id NodeID, addr *net.UDPAdd tab.net.waitping(id) } // Bonding succeeded, update the node database - w.n = &Node{ - ID: id, - IP: addr.IP, - DiscPort: addr.Port, - TCPPort: int(tcpPort), - } + w.n = &Node{ID: id, IP: addr.IP, UDP: uint16(addr.Port), TCP: tcpPort} tab.db.updateNode(w.n) close(w.done) } diff --git a/p2p/discover/table_test.go b/p2p/discover/table_test.go index e2bd3c8ad..e7394756d 100644 --- a/p2p/discover/table_test.go +++ b/p2p/discover/table_test.go @@ -261,9 +261,9 @@ func (t findnodeOracle) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID panic("query to node at distance 0") default: // TODO: add more randomness to distances - next := toaddr.Port - 1 + next := uint16(toaddr.Port) - 1 for i := 0; i < bucketSize; i++ { - result = append(result, &Node{ID: randomID(t.target, next), DiscPort: next}) + result = append(result, &Node{ID: randomID(t.target, int(next)), UDP: next}) } } return result, nil diff --git a/p2p/discover/udp.go b/p2p/discover/udp.go index 65741b5f5..baff75a63 100644 --- a/p2p/discover/udp.go +++ b/p2p/discover/udp.go @@ -49,16 +49,20 @@ const ( // RPC request structures type ( ping struct { - Version uint // must match Version - IP string // our IP - Port uint16 // our port + Version uint + From, To rpcEndpoint Expiration uint64 } - // reply to Ping + // pong is the reply to ping. pong struct { - ReplyTok []byte - Expiration uint64 + // This field should mirror the UDP envelope address + // of the ping packet, which provides a way to discover the + // the external address (after NAT). + To rpcEndpoint + + ReplyTok []byte // This contains the hash of the ping packet. + Expiration uint64 // Absolute timestamp at which the packet becomes invalid. } findnode struct { @@ -73,12 +77,25 @@ type ( Nodes []*Node Expiration uint64 } + + rpcEndpoint struct { + IP net.IP // len 4 for IPv4 or 16 for IPv6 + UDP uint16 // for discovery protocol + TCP uint16 // for RLPx protocol + } ) -type rpcNode struct { - IP string - Port uint16 - ID NodeID +func makeEndpoint(addr *net.UDPAddr, tcpPort uint16) rpcEndpoint { + ip := addr.IP.To4() + if ip == nil { + ip = addr.IP.To16() + } + return rpcEndpoint{IP: ip, UDP: uint16(addr.Port), TCP: tcpPort} +} + +func validNode(n *Node) bool { + // TODO: don't accept localhost, LAN addresses from internet hosts + return !n.IP.IsMulticast() && !n.IP.IsUnspecified() && n.UDP != 0 } type packet interface { @@ -94,8 +111,9 @@ type conn interface { // udp implements the RPC protocol. type udp struct { - conn conn - priv *ecdsa.PrivateKey + conn conn + priv *ecdsa.PrivateKey + ourEndpoint rpcEndpoint addpending chan *pending gotreply chan reply @@ -176,6 +194,8 @@ func newUDP(priv *ecdsa.PrivateKey, c conn, natm nat.Interface, nodeDBPath strin realaddr = &net.UDPAddr{IP: ext, Port: realaddr.Port} } } + // TODO: separate TCP port + udp.ourEndpoint = makeEndpoint(realaddr, uint16(realaddr.Port)) udp.Table = newTable(udp, PubkeyID(&priv.PublicKey), realaddr, nodeDBPath) go udp.loop() go udp.readLoop() @@ -194,8 +214,8 @@ func (t *udp) ping(toid NodeID, toaddr *net.UDPAddr) error { errc := t.pending(toid, pongPacket, func(interface{}) bool { return true }) t.send(toaddr, pingPacket, ping{ Version: Version, - IP: t.self.IP.String(), - Port: uint16(t.self.TCPPort), + From: t.ourEndpoint, + To: makeEndpoint(toaddr, 0), // TODO: maybe use known TCP port from DB Expiration: uint64(time.Now().Add(expiration).Unix()), }) return <-errc @@ -214,7 +234,7 @@ func (t *udp) findnode(toid NodeID, toaddr *net.UDPAddr, target NodeID) ([]*Node reply := r.(*neighbors) for _, n := range reply.Nodes { nreceived++ - if n.isValid() { + if validNode(n) { nodes = append(nodes, n) } } @@ -374,17 +394,22 @@ func (t *udp) readLoop() { if err != nil { return } - packet, fromID, hash, err := decodePacket(buf[:nbytes]) - if err != nil { - glog.V(logger.Debug).Infof("Bad packet from %v: %v\n", from, err) - continue - } - status := "ok" - if err := packet.handle(t, from, fromID, hash); err != nil { - status = err.Error() - } - glog.V(logger.Detail).Infof("<<< %v %T: %s\n", from, packet, status) + t.handlePacket(from, buf[:nbytes]) + } +} + +func (t *udp) handlePacket(from *net.UDPAddr, buf []byte) error { + packet, fromID, hash, err := decodePacket(buf) + if err != nil { + glog.V(logger.Debug).Infof("Bad packet from %v: %v\n", from, err) + return err } + status := "ok" + if err = packet.handle(t, from, fromID, hash); err != nil { + status = err.Error() + } + glog.V(logger.Detail).Infof("<<< %v %T: %s\n", from, packet, status) + return err } func decodePacket(buf []byte) (packet, NodeID, []byte, error) { @@ -425,12 +450,13 @@ func (req *ping) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) er return errBadVersion } t.send(from, pongPacket, pong{ + To: makeEndpoint(from, req.From.TCP), ReplyTok: mac, Expiration: uint64(time.Now().Add(expiration).Unix()), }) if !t.handleReply(fromID, pingPacket, req) { // Note: we're ignoring the provided IP address right now - go t.bond(true, fromID, from, req.Port) + go t.bond(true, fromID, from, req.From.TCP) } return nil } diff --git a/p2p/discover/udp_test.go b/p2p/discover/udp_test.go index 47e04b85a..378edaaa7 100644 --- a/p2p/discover/udp_test.go +++ b/p2p/discover/udp_test.go @@ -23,6 +23,15 @@ func init() { logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, logpkg.LstdFlags, logger.ErrorLevel)) } +// shared test variables +var ( + futureExp = uint64(time.Now().Add(10 * time.Hour).Unix()) + testTarget = MustHexID("01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101") + testRemote = rpcEndpoint{IP: net.ParseIP("1.1.1.1").To4(), UDP: 1, TCP: 2} + testLocalAnnounced = rpcEndpoint{IP: net.ParseIP("2.2.2.2").To4(), UDP: 3, TCP: 4} + testLocal = rpcEndpoint{IP: net.ParseIP("3.3.3.3").To4(), UDP: 5, TCP: 6} +) + type udpTest struct { t *testing.T pipe *dgramPipe @@ -52,8 +61,7 @@ func (test *udpTest) packetIn(wantError error, ptype byte, data packet) error { return test.errorf("packet (%d) encode error: %v", err) } test.sent = append(test.sent, enc) - err = data.handle(test.udp, test.remoteaddr, PubkeyID(&test.remotekey.PublicKey), enc[:macSize]) - if err != wantError { + if err = test.udp.handlePacket(test.remoteaddr, enc); err != wantError { return test.errorf("error mismatch: got %q, want %q", err, wantError) } return nil @@ -90,18 +98,12 @@ func (test *udpTest) errorf(format string, args ...interface{}) error { return err } -// shared test variables -var ( - futureExp = uint64(time.Now().Add(10 * time.Hour).Unix()) - testTarget = MustHexID("01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101") -) - func TestUDP_packetErrors(t *testing.T) { test := newUDPTest(t) defer test.table.Close() - test.packetIn(errExpired, pingPacket, &ping{IP: "foo", Port: 99, Version: Version}) - test.packetIn(errBadVersion, pingPacket, &ping{IP: "foo", Port: 99, Version: 99, Expiration: futureExp}) + test.packetIn(errExpired, pingPacket, &ping{From: testRemote, To: testLocalAnnounced, Version: Version}) + test.packetIn(errBadVersion, pingPacket, &ping{From: testRemote, To: testLocalAnnounced, Version: 99, Expiration: futureExp}) test.packetIn(errUnsolicitedReply, pongPacket, &pong{ReplyTok: []byte{}, Expiration: futureExp}) test.packetIn(errUnknownNode, findnodePacket, &findnode{Expiration: futureExp}) test.packetIn(errUnsolicitedReply, neighborsPacket, &neighbors{Expiration: futureExp}) @@ -147,10 +149,10 @@ func TestUDP_findnode(t *testing.T) { nodes := &nodesByDistance{target: target} for i := 0; i < bucketSize; i++ { nodes.push(&Node{ - IP: net.IP{1, 2, 3, byte(i)}, - DiscPort: i + 2, - TCPPort: i + 2, - ID: randomID(test.table.self.ID, i+2), + IP: net.IP{1, 2, 3, byte(i)}, + UDP: uint16(i + 2), + TCP: uint16(i + 3), + ID: randomID(test.table.self.ID, i+2), }, bucketSize) } test.table.add(nodes.entries) @@ -158,10 +160,10 @@ func TestUDP_findnode(t *testing.T) { // ensure there's a bond with the test node, // findnode won't be accepted otherwise. test.table.db.updateNode(&Node{ - ID: PubkeyID(&test.remotekey.PublicKey), - IP: test.remoteaddr.IP, - DiscPort: test.remoteaddr.Port, - TCPPort: 99, + ID: PubkeyID(&test.remotekey.PublicKey), + IP: test.remoteaddr.IP, + UDP: uint16(test.remoteaddr.Port), + TCP: 99, }) // check that closest neighbors are returned. test.packetIn(nil, findnodePacket, &findnode{Target: testTarget, Expiration: futureExp}) @@ -204,9 +206,9 @@ func TestUDP_findnodeMultiReply(t *testing.T) { // send the reply as two packets. list := []*Node{ - MustParseNode("enode://ba85011c70bcc5c04d8607d3a0ed29aa6179c092cbdda10d5d32684fb33ed01bd94f588ca8f91ac48318087dcb02eaf36773a7a453f0eedd6742af668097b29c@10.0.1.16:30303"), + MustParseNode("enode://ba85011c70bcc5c04d8607d3a0ed29aa6179c092cbdda10d5d32684fb33ed01bd94f588ca8f91ac48318087dcb02eaf36773a7a453f0eedd6742af668097b29c@10.0.1.16:30303?discport=30304"), MustParseNode("enode://81fa361d25f157cd421c60dcc28d8dac5ef6a89476633339c5df30287474520caca09627da18543d9079b5b288698b542d56167aa5c09111e55acdbbdf2ef799@10.0.1.16:30303"), - MustParseNode("enode://9bffefd833d53fac8e652415f4973bee289e8b1a5c6c4cbe70abf817ce8a64cee11b823b66a987f51aaa9fba0d6a91b3e6bf0d5a5d1042de8e9eeea057b217f8@10.0.1.36:30301"), + MustParseNode("enode://9bffefd833d53fac8e652415f4973bee289e8b1a5c6c4cbe70abf817ce8a64cee11b823b66a987f51aaa9fba0d6a91b3e6bf0d5a5d1042de8e9eeea057b217f8@10.0.1.36:30301?discport=17"), MustParseNode("enode://1b5b4aa662d7cb44a7221bfba67302590b643028197a7d5214790f3bac7aaa4a3241be9e83c09cf1f6c69d007c634faae3dc1b1221793e8446c0b3a09de65960@10.0.1.16:30303"), } test.packetIn(nil, neighborsPacket, &neighbors{Expiration: futureExp, Nodes: list[:2]}) @@ -231,7 +233,8 @@ func TestUDP_successfulPing(t *testing.T) { done := make(chan struct{}) go func() { - test.packetIn(nil, pingPacket, &ping{IP: "foo", Port: 99, Version: Version, Expiration: futureExp}) + // The remote side sends a ping packet to initiate the exchange. + test.packetIn(nil, pingPacket, &ping{From: testRemote, To: testLocalAnnounced, Version: Version, Expiration: futureExp}) close(done) }() @@ -239,12 +242,34 @@ func TestUDP_successfulPing(t *testing.T) { test.waitPacketOut(func(p *pong) { pinghash := test.sent[0][:macSize] if !bytes.Equal(p.ReplyTok, pinghash) { - t.Errorf("got ReplyTok %x, want %x", p.ReplyTok, pinghash) + t.Errorf("got pong.ReplyTok %x, want %x", p.ReplyTok, pinghash) + } + wantTo := rpcEndpoint{ + // The mirrored UDP address is the UDP packet sender + IP: test.remoteaddr.IP, UDP: uint16(test.remoteaddr.Port), + // The mirrored TCP port is the one from the ping packet + TCP: testRemote.TCP, + } + if !reflect.DeepEqual(p.To, wantTo) { + t.Errorf("got pong.To %v, want %v", p.To, wantTo) } }) // remote is unknown, the table pings back. - test.waitPacketOut(func(p *ping) error { return nil }) + test.waitPacketOut(func(p *ping) error { + if !reflect.DeepEqual(p.From, test.udp.ourEndpoint) { + t.Errorf("got ping.From %v, want %v", p.From, test.udp.ourEndpoint) + } + wantTo := rpcEndpoint{ + // The mirrored UDP address is the UDP packet sender. + IP: test.remoteaddr.IP, UDP: uint16(test.remoteaddr.Port), + TCP: 0, + } + if !reflect.DeepEqual(p.To, wantTo) { + t.Errorf("got ping.To %v, want %v", p.To, wantTo) + } + return nil + }) test.packetIn(nil, pongPacket, &pong{Expiration: futureExp}) // ping should return shortly after getting the pong packet. @@ -259,11 +284,11 @@ func TestUDP_successfulPing(t *testing.T) { if !bytes.Equal(rnode.IP, test.remoteaddr.IP) { t.Errorf("node has wrong IP: got %v, want: %v", rnode.IP, test.remoteaddr.IP) } - if rnode.DiscPort != test.remoteaddr.Port { - t.Errorf("node has wrong Port: got %v, want: %v", rnode.DiscPort, test.remoteaddr.Port) + if int(rnode.UDP) != test.remoteaddr.Port { + t.Errorf("node has wrong UDP port: got %v, want: %v", rnode.UDP, test.remoteaddr.Port) } - if rnode.TCPPort != 99 { - t.Errorf("node has wrong Port: got %v, want: %v", rnode.TCPPort, 99) + if rnode.TCP != testRemote.TCP { + t.Errorf("node has wrong TCP port: got %v, want: %v", rnode.TCP, testRemote.TCP) } } @@ -327,7 +352,7 @@ func (c *dgramPipe) Close() error { } func (c *dgramPipe) LocalAddr() net.Addr { - return &net.UDPAddr{} + return &net.UDPAddr{IP: testLocal.IP, Port: int(testLocal.UDP)} } func (c *dgramPipe) waitPacketOut() []byte { diff --git a/p2p/handshake_test.go b/p2p/handshake_test.go index c22af7a9c..f618ef20d 100644 --- a/p2p/handshake_test.go +++ b/p2p/handshake_test.go @@ -119,14 +119,14 @@ func TestSetupConn(t *testing.T) { prv0, _ := crypto.GenerateKey() prv1, _ := crypto.GenerateKey() node0 := &discover.Node{ - ID: discover.PubkeyID(&prv0.PublicKey), - IP: net.IP{1, 2, 3, 4}, - TCPPort: 33, + ID: discover.PubkeyID(&prv0.PublicKey), + IP: net.IP{1, 2, 3, 4}, + TCP: 33, } node1 := &discover.Node{ - ID: discover.PubkeyID(&prv1.PublicKey), - IP: net.IP{5, 6, 7, 8}, - TCPPort: 44, + ID: discover.PubkeyID(&prv1.PublicKey), + IP: net.IP{5, 6, 7, 8}, + TCP: 44, } hs0 := &protoHandshake{ Version: baseProtocolVersion, diff --git a/p2p/server.go b/p2p/server.go index 5c5883ae8..e648c72c9 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -394,7 +394,7 @@ func (srv *Server) dialLoop() { } func (srv *Server) dialNode(dest *discover.Node) { - addr := &net.TCPAddr{IP: dest.IP, Port: dest.TCPPort} + addr := &net.TCPAddr{IP: dest.IP, Port: int(dest.TCP)} glog.V(logger.Debug).Infof("Dialing %v\n", dest) conn, err := srv.Dialer.Dial("tcp", addr.String()) if err != nil { diff --git a/p2p/server_test.go b/p2p/server_test.go index 53cc3c258..86514b650 100644 --- a/p2p/server_test.go +++ b/p2p/server_test.go @@ -102,7 +102,7 @@ func TestServerDial(t *testing.T) { // tell the server to connect tcpAddr := listener.Addr().(*net.TCPAddr) - srv.SuggestPeer(&discover.Node{IP: tcpAddr.IP, TCPPort: tcpAddr.Port}) + srv.SuggestPeer(&discover.Node{IP: tcpAddr.IP, TCP: uint16(tcpAddr.Port)}) select { case conn := <-accepted: |