Browse Source

p2p: explicit netaddress errors

pull/1519/head
Ethan Buchman 6 years ago
parent
commit
3ee1d7909e
3 changed files with 64 additions and 15 deletions
  1. +28
    -0
      p2p/errors.go
  2. +17
    -13
      p2p/netaddress.go
  3. +19
    -2
      p2p/node_info.go

+ 28
- 0
p2p/errors.go View File

@ -18,3 +18,31 @@ type ErrSwitchAuthenticationFailure struct {
func (e ErrSwitchAuthenticationFailure) Error() string {
return fmt.Sprintf("Failed to authenticate peer. Dialed %v, but got peer with ID %s", e.Dialed, e.Got)
}
//-------------------------------------------------------------------
type ErrNetAddressNoID struct {
Addr string
}
func (e ErrNetAddressNoID) Error() string {
return fmt.Errorf("Address (%s) does not contain ID", e.Addr)
}
type ErrNetAddressInvalid struct {
Addr string
Err error
}
func (e ErrNetAddressInvalid) Error() string {
return fmt.Errorf("Invalid address (%s): %v", e.Addr, e.Err)
}
type ErrNetAddressLookup struct {
Addr string
Err error
}
func (e ErrNetAddressLookup) Error() string {
return fmt.Errorf("Error looking up host (%s): %v", e.Addr, e.Err)
}

+ 17
- 13
p2p/netaddress.go View File

@ -19,11 +19,13 @@ import (
// NetAddress defines information about a peer on the network
// including its ID, IP address, and port.
type NetAddress struct {
ID ID
IP net.IP
Port uint16
Name string // optional DNS name
str string
ID ID `json:"id"`
IP net.IP `json:"ip"`
Port uint16 `json:"port"`
Name string `json:"name"` // optional DNS name
// memoize .String()
str string
}
// IDAddressString returns id@hostPort.
@ -57,10 +59,11 @@ func NewNetAddress(id ID, addr net.Addr) *NetAddress {
// NewNetAddressString returns a new NetAddress using the provided address in
// the form of "ID@IP:Port".
// Also resolves the host if host is not an IP.
// Errors are of type ErrNetAddressXxx where Xxx is in (NoID, Invalid, Lookup)
func NewNetAddressString(addr string) (*NetAddress, error) {
spl := strings.Split(addr, "@")
if len(spl) < 2 {
return nil, fmt.Errorf("Address (%s) does not contain ID", addr)
return nil, ErrNetAddressNoID{addr}
}
return NewNetAddressStringWithOptionalID(addr)
}
@ -77,11 +80,12 @@ func NewNetAddressStringWithOptionalID(addr string) (*NetAddress, error) {
idStr := spl[0]
idBytes, err := hex.DecodeString(idStr)
if err != nil {
return nil, cmn.ErrorWrap(err, fmt.Sprintf("Address (%s) contains invalid ID", addrWithoutProtocol))
return nil, ErrNetAddressInvalid{addrWithoutProtocol, err}
}
if len(idBytes) != IDByteLength {
return nil, fmt.Errorf("Address (%s) contains ID of invalid length (%d). Should be %d hex-encoded bytes",
addrWithoutProtocol, len(idBytes), IDByteLength)
return nil, ErrNetAddressInvalid{
addrWithoutProtocol,
fmt.Errorf("invalid hex length - got %d, expected %d", len(idBytes), IDByteLength)}
}
id, addrWithoutProtocol = ID(idStr), spl[1]
@ -89,7 +93,7 @@ func NewNetAddressStringWithOptionalID(addr string) (*NetAddress, error) {
host, portStr, err := net.SplitHostPort(addrWithoutProtocol)
if err != nil {
return nil, err
return nil, ErrNetAddressInvalid{addrWithoutProtocol, err}
}
ip := net.ParseIP(host)
@ -97,7 +101,7 @@ func NewNetAddressStringWithOptionalID(addr string) (*NetAddress, error) {
if len(host) > 0 {
ips, err := net.LookupIP(host)
if err != nil {
return nil, err
return nil, ErrNetAddressLookup{host, err}
}
ip = ips[0]
}
@ -105,7 +109,7 @@ func NewNetAddressStringWithOptionalID(addr string) (*NetAddress, error) {
port, err := strconv.ParseUint(portStr, 10, 16)
if err != nil {
return nil, err
return nil, ErrNetAddressInvalid{portStr, err}
}
na := NewNetAddressIPPort(ip, uint16(port))
@ -121,7 +125,7 @@ func NewNetAddressStrings(addrs []string) ([]*NetAddress, []error) {
for _, addr := range addrs {
netAddr, err := NewNetAddressString(addr)
if err != nil {
errs = append(errs, fmt.Errorf("Error in address %s: %v", addr, err))
errs = append(errs, err)
} else {
netAddrs = append(netAddrs, netAddr)
}


+ 19
- 2
p2p/node_info.go View File

@ -21,6 +21,7 @@ func MaxNodeInfoSize() int {
// between two peers during the Tendermint P2P handshake.
type NodeInfo struct {
// Authenticate
// TODO: replace with NetAddress
ID ID `json:"id"` // authenticated identifier
ListenAddr string `json:"listen_addr"` // accepting incoming
@ -37,7 +38,9 @@ type NodeInfo struct {
// Validate checks the self-reported NodeInfo is safe.
// It returns an error if there
// are too many Channels or any duplicate Channels.
// are too many Channels, if there are any duplicate Channels,
// if the ListenAddr is malformed, or if the ListenAddr is a host name
// that can not be resolved to some IP.
// TODO: constraints for Moniker/Other? Or is that for the UI ?
func (info NodeInfo) Validate() error {
if len(info.Channels) > maxNumChannels {
@ -52,6 +55,13 @@ func (info NodeInfo) Validate() error {
}
channels[ch] = struct{}{}
}
// ensure ListenAddr is good
netAddr, err := NewNetAddressString(IDAddressString(info.ID, info.ListenAddr))
if err != nil {
return err
}
return nil
}
@ -116,7 +126,14 @@ OUTER_LOOP:
func (info NodeInfo) NetAddress() *NetAddress {
netAddr, err := NewNetAddressString(IDAddressString(info.ID, info.ListenAddr))
if err != nil {
panic(err) // everything should be well formed by now
switch err.(type) {
case ErrNetAddressLookup:
// XXX If the peer provided a host name and the lookup fails here
// we're out of luck.
// TODO: use a NetAddress in NodeInfo
default:
panic(err) // everything should be well formed by now
}
}
return netAddr
}


Loading…
Cancel
Save