diff --git a/p2p/discv5/node.go b/p2p/discv5/node.go index 44d3025b70..c9904d96c2 100644 --- a/p2p/discv5/node.go +++ b/p2p/discv5/node.go @@ -106,7 +106,10 @@ func (n *Node) String() string { return u.String() } -var incompleteNodeURL = regexp.MustCompile("(?i)^(?:enode://)?([0-9a-f]+)$") +var ( + incompleteNodeURL = regexp.MustCompile("(?i)^(?:enode://)?([0-9a-f]+)$") + lookupIPFunc = net.LookupIP +) // ParseNode parses a node designator. // @@ -168,7 +171,11 @@ func parseComplete(rawurl string) (*Node, error) { return nil, fmt.Errorf("invalid host: %v", err) } if ip = net.ParseIP(host); ip == nil { - return nil, errors.New("invalid IP address") + ips, err := lookupIPFunc(u.Hostname()) + if err != nil { + return nil, errors.New("no such host") + } + ip = ips[0] } // Ensure the IP is 4 bytes long for IPv4 addresses. if ipv4 := ip.To4(); ipv4 != nil { diff --git a/p2p/discv5/node_test.go b/p2p/discv5/node_test.go index 4e0fdbe3db..e20b3af1e6 100644 --- a/p2p/discv5/node_test.go +++ b/p2p/discv5/node_test.go @@ -17,6 +17,7 @@ package discv5 import ( + "errors" "fmt" "math/big" "math/rand" @@ -31,6 +32,15 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) +func init() { + lookupIPFunc = func(name string) ([]net.IP, error) { + if name == "node.example.org" { + return []net.IP{{33, 44, 55, 66}}, nil + } + return nil, errors.New("no such host") + } +} + func ExampleNewNode() { id := MustHexID("1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439") @@ -68,7 +78,7 @@ var parseNodeTests = []struct { // Complete nodes with IP address. { rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@hostname:3", - wantError: `invalid IP address`, + wantError: `no such host`, }, { rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:foo", @@ -123,10 +133,12 @@ var parseNodeTests = []struct { ), }, { - rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439", + rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@node.example.org:52150?discport=22334", wantResult: NewNode( MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), - nil, 0, 0, + net.IP{0x21, 0x2C, 0x37, 0x42}, + 22334, + 52150, ), }, // Invalid URLs @@ -143,6 +155,15 @@ var parseNodeTests = []struct { rawurl: "://foo", wantError: `missing protocol scheme`, }, + { + rawurl: "enode://1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439@127.0.0.1:52150?discport=22334", + wantResult: NewNode( + MustHexID("0x1dd9d65c4552b5eb43d5ad55a2ee3f56c6cbc1c64a5c8d659f51fcd51bace24351232b8d7821617d2b29b54b81cdefb9b3e9c37d7fd5f63270bcc9e1a6f6a439"), + net.IP{0x7f, 0x0, 0x0, 0x1}, + 22334, + 52150, + ), + }, } func TestParseNode(t *testing.T) { @@ -173,7 +194,14 @@ func TestNodeString(t *testing.T) { if test.wantError == "" && strings.HasPrefix(test.rawurl, "enode://") { str := test.wantResult.String() if str != test.rawurl { - t.Errorf("test %d: Node.String() mismatch:\ngot: %s\nwant: %s", i, str, test.rawurl) + if strings.Contains(test.rawurl, "node.example.org") { + resolvedurl := strings.Replace(test.rawurl, "node.example.org", "33.44.55.66", 1) + if str != resolvedurl { + t.Errorf("test %d: Node.String() mismatch:\ngot: %s\nwant: %s", i, str, resolvedurl) + } + } else { + t.Errorf("test %d: Node.String() mismatch:\ngot: %s\nwant: %s", i, str, test.rawurl) + } } } }