|
@ -5,6 +5,7 @@ |
|
|
package p2p |
|
|
package p2p |
|
|
|
|
|
|
|
|
import ( |
|
|
import ( |
|
|
|
|
|
"encoding/hex" |
|
|
"flag" |
|
|
"flag" |
|
|
"fmt" |
|
|
"fmt" |
|
|
"net" |
|
|
"net" |
|
@ -12,6 +13,7 @@ import ( |
|
|
"strings" |
|
|
"strings" |
|
|
"time" |
|
|
"time" |
|
|
|
|
|
|
|
|
|
|
|
"github.com/pkg/errors" |
|
|
cmn "github.com/tendermint/tmlibs/common" |
|
|
cmn "github.com/tendermint/tmlibs/common" |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
@ -29,25 +31,45 @@ type NetAddress struct { |
|
|
// using 0.0.0.0:0. When normal run, other net.Addr (except TCP) will
|
|
|
// using 0.0.0.0:0. When normal run, other net.Addr (except TCP) will
|
|
|
// panic.
|
|
|
// panic.
|
|
|
// TODO: socks proxies?
|
|
|
// TODO: socks proxies?
|
|
|
func NewNetAddress(addr net.Addr) *NetAddress { |
|
|
|
|
|
|
|
|
func NewNetAddress(id ID, addr net.Addr) *NetAddress { |
|
|
tcpAddr, ok := addr.(*net.TCPAddr) |
|
|
tcpAddr, ok := addr.(*net.TCPAddr) |
|
|
if !ok { |
|
|
if !ok { |
|
|
if flag.Lookup("test.v") == nil { // normal run
|
|
|
if flag.Lookup("test.v") == nil { // normal run
|
|
|
cmn.PanicSanity(cmn.Fmt("Only TCPAddrs are supported. Got: %v", addr)) |
|
|
cmn.PanicSanity(cmn.Fmt("Only TCPAddrs are supported. Got: %v", addr)) |
|
|
} else { // in testing
|
|
|
} else { // in testing
|
|
|
return NewNetAddressIPPort(net.IP("0.0.0.0"), 0) |
|
|
|
|
|
|
|
|
netAddr := NewNetAddressIPPort(net.IP("0.0.0.0"), 0) |
|
|
|
|
|
netAddr.ID = id |
|
|
|
|
|
return netAddr |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
ip := tcpAddr.IP |
|
|
ip := tcpAddr.IP |
|
|
port := uint16(tcpAddr.Port) |
|
|
port := uint16(tcpAddr.Port) |
|
|
return NewNetAddressIPPort(ip, port) |
|
|
|
|
|
|
|
|
netAddr := NewNetAddressIPPort(ip, port) |
|
|
|
|
|
netAddr.ID = id |
|
|
|
|
|
return netAddr |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// NewNetAddressString returns a new NetAddress using the provided
|
|
|
// NewNetAddressString returns a new NetAddress using the provided
|
|
|
// address in the form of "IP:Port". Also resolves the host if host
|
|
|
// address in the form of "IP:Port". Also resolves the host if host
|
|
|
// is not an IP.
|
|
|
// is not an IP.
|
|
|
func NewNetAddressString(addr string) (*NetAddress, error) { |
|
|
func NewNetAddressString(addr string) (*NetAddress, error) { |
|
|
host, portStr, err := net.SplitHostPort(removeProtocolIfDefined(addr)) |
|
|
|
|
|
|
|
|
addr = removeProtocolIfDefined(addr) |
|
|
|
|
|
|
|
|
|
|
|
var id ID |
|
|
|
|
|
spl := strings.Split(addr, "@") |
|
|
|
|
|
if len(spl) == 2 { |
|
|
|
|
|
idStr := spl[0] |
|
|
|
|
|
idBytes, err := hex.DecodeString(idStr) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return nil, errors.Wrap(err, fmt.Sprintf("Address (%s) contains invalid ID", addr)) |
|
|
|
|
|
} |
|
|
|
|
|
if len(idBytes) != 20 { |
|
|
|
|
|
return nil, fmt.Errorf("Address (%s) contains ID of invalid length (%d). Should be 20 hex-encoded bytes", len(idBytes)) |
|
|
|
|
|
} |
|
|
|
|
|
id, addr = ID(idStr), spl[1] |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
host, portStr, err := net.SplitHostPort(addr) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
return nil, err |
|
|
return nil, err |
|
|
} |
|
|
} |
|
@ -69,6 +91,7 @@ func NewNetAddressString(addr string) (*NetAddress, error) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
na := NewNetAddressIPPort(ip, uint16(port)) |
|
|
na := NewNetAddressIPPort(ip, uint16(port)) |
|
|
|
|
|
na.ID = id |
|
|
return na, nil |
|
|
return na, nil |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -94,10 +117,6 @@ func NewNetAddressIPPort(ip net.IP, port uint16) *NetAddress { |
|
|
na := &NetAddress{ |
|
|
na := &NetAddress{ |
|
|
IP: ip, |
|
|
IP: ip, |
|
|
Port: port, |
|
|
Port: port, |
|
|
str: net.JoinHostPort( |
|
|
|
|
|
ip.String(), |
|
|
|
|
|
strconv.FormatUint(uint64(port), 10), |
|
|
|
|
|
), |
|
|
|
|
|
} |
|
|
} |
|
|
return na |
|
|
return na |
|
|
} |
|
|
} |
|
@ -111,23 +130,10 @@ func (na *NetAddress) Equals(other interface{}) bool { |
|
|
return false |
|
|
return false |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (na *NetAddress) Less(other interface{}) bool { |
|
|
|
|
|
if o, ok := other.(*NetAddress); ok { |
|
|
|
|
|
return na.String() < o.String() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
cmn.PanicSanity("Cannot compare unequal types") |
|
|
|
|
|
return false |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// String representation.
|
|
|
|
|
|
|
|
|
// String representation: <ID>@<IP>:<PORT>
|
|
|
func (na *NetAddress) String() string { |
|
|
func (na *NetAddress) String() string { |
|
|
if na.str == "" { |
|
|
if na.str == "" { |
|
|
|
|
|
|
|
|
addrStr := net.JoinHostPort( |
|
|
|
|
|
na.IP.String(), |
|
|
|
|
|
strconv.FormatUint(uint64(na.Port), 10), |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
addrStr := na.DialString() |
|
|
if na.ID != "" { |
|
|
if na.ID != "" { |
|
|
addrStr = fmt.Sprintf("%s@%s", na.ID, addrStr) |
|
|
addrStr = fmt.Sprintf("%s@%s", na.ID, addrStr) |
|
|
} |
|
|
} |
|
@ -136,9 +142,16 @@ func (na *NetAddress) String() string { |
|
|
return na.str |
|
|
return na.str |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (na *NetAddress) DialString() string { |
|
|
|
|
|
return net.JoinHostPort( |
|
|
|
|
|
na.IP.String(), |
|
|
|
|
|
strconv.FormatUint(uint64(na.Port), 10), |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Dial calls net.Dial on the address.
|
|
|
// Dial calls net.Dial on the address.
|
|
|
func (na *NetAddress) Dial() (net.Conn, error) { |
|
|
func (na *NetAddress) Dial() (net.Conn, error) { |
|
|
conn, err := net.Dial("tcp", na.String()) |
|
|
|
|
|
|
|
|
conn, err := net.Dial("tcp", na.DialString()) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
return nil, err |
|
|
return nil, err |
|
|
} |
|
|
} |
|
@ -147,7 +160,7 @@ func (na *NetAddress) Dial() (net.Conn, error) { |
|
|
|
|
|
|
|
|
// DialTimeout calls net.DialTimeout on the address.
|
|
|
// DialTimeout calls net.DialTimeout on the address.
|
|
|
func (na *NetAddress) DialTimeout(timeout time.Duration) (net.Conn, error) { |
|
|
func (na *NetAddress) DialTimeout(timeout time.Duration) (net.Conn, error) { |
|
|
conn, err := net.DialTimeout("tcp", na.String(), timeout) |
|
|
|
|
|
|
|
|
conn, err := net.DialTimeout("tcp", na.DialString(), timeout) |
|
|
if err != nil { |
|
|
if err != nil { |
|
|
return nil, err |
|
|
return nil, err |
|
|
} |
|
|
} |
|
|