preserve original address and dial it instead of self-reported address (#1994)

Refs #1720
This commit is contained in:
Anton Kaliaev 2018-07-18 13:23:29 +04:00 committed by GitHub
parent 6c4ca140ed
commit b31ee798bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 21 deletions

View File

@ -206,3 +206,4 @@ func (tp *bcrTestPeer) IsPersistent() bool { return true }
func (tp *bcrTestPeer) Get(s string) interface{} { return s } func (tp *bcrTestPeer) Get(s string) interface{} { return s }
func (tp *bcrTestPeer) Set(string, interface{}) {} func (tp *bcrTestPeer) Set(string, interface{}) {}
func (tp *bcrTestPeer) RemoteIP() net.IP { return []byte{127, 0, 0, 1} } func (tp *bcrTestPeer) RemoteIP() net.IP { return []byte{127, 0, 0, 1} }
func (tp *bcrTestPeer) OriginalAddr() *p2p.NetAddress { return nil }

View File

@ -3,9 +3,9 @@ package dummy
import ( import (
"net" "net"
cmn "github.com/tendermint/tendermint/libs/common"
p2p "github.com/tendermint/tendermint/p2p" p2p "github.com/tendermint/tendermint/p2p"
tmconn "github.com/tendermint/tendermint/p2p/conn" tmconn "github.com/tendermint/tendermint/p2p/conn"
cmn "github.com/tendermint/tendermint/libs/common"
) )
type peer struct { type peer struct {
@ -78,3 +78,8 @@ func (p *peer) Get(key string) interface{} {
} }
return nil return nil
} }
// OriginalAddr always returns nil.
func (p *peer) OriginalAddr() *p2p.NetAddress {
return nil
}

View File

@ -26,6 +26,7 @@ type Peer interface {
IsPersistent() bool // do we redial this peer when we disconnect IsPersistent() bool // do we redial this peer when we disconnect
NodeInfo() NodeInfo // peer's info NodeInfo() NodeInfo // peer's info
Status() tmconn.ConnectionStatus Status() tmconn.ConnectionStatus
OriginalAddr() *NetAddress
Send(byte, []byte) bool Send(byte, []byte) bool
TrySend(byte, []byte) bool TrySend(byte, []byte) bool
@ -38,11 +39,12 @@ type Peer interface {
// peerConn contains the raw connection and its config. // peerConn contains the raw connection and its config.
type peerConn struct { type peerConn struct {
outbound bool outbound bool
persistent bool persistent bool
config *config.P2PConfig config *config.P2PConfig
conn net.Conn // source connection conn net.Conn // source connection
ip net.IP ip net.IP
originalAddr *NetAddress // nil for inbound connections
} }
// ID only exists for SecretConnection. // ID only exists for SecretConnection.
@ -139,7 +141,7 @@ func newOutboundPeerConn(
return peerConn{}, cmn.ErrorWrap(err, "Error creating peer") return peerConn{}, cmn.ErrorWrap(err, "Error creating peer")
} }
pc, err := newPeerConn(conn, config, true, persistent, ourNodePrivKey) pc, err := newPeerConn(conn, config, true, persistent, ourNodePrivKey, addr)
if err != nil { if err != nil {
if cerr := conn.Close(); cerr != nil { if cerr := conn.Close(); cerr != nil {
return peerConn{}, cmn.ErrorWrap(err, cerr.Error()) return peerConn{}, cmn.ErrorWrap(err, cerr.Error())
@ -166,7 +168,7 @@ func newInboundPeerConn(
// TODO: issue PoW challenge // TODO: issue PoW challenge
return newPeerConn(conn, config, false, false, ourNodePrivKey) return newPeerConn(conn, config, false, false, ourNodePrivKey, nil)
} }
func newPeerConn( func newPeerConn(
@ -174,6 +176,7 @@ func newPeerConn(
cfg *config.P2PConfig, cfg *config.P2PConfig,
outbound, persistent bool, outbound, persistent bool,
ourNodePrivKey crypto.PrivKey, ourNodePrivKey crypto.PrivKey,
originalAddr *NetAddress,
) (pc peerConn, err error) { ) (pc peerConn, err error) {
conn := rawConn conn := rawConn
@ -200,10 +203,11 @@ func newPeerConn(
// Only the information we already have // Only the information we already have
return peerConn{ return peerConn{
config: cfg, config: cfg,
outbound: outbound, outbound: outbound,
persistent: persistent, persistent: persistent,
conn: conn, conn: conn,
originalAddr: originalAddr,
}, nil }, nil
} }
@ -254,6 +258,15 @@ func (p *peer) NodeInfo() NodeInfo {
return p.nodeInfo return p.nodeInfo
} }
// OriginalAddr returns the original address, which was used to connect with
// the peer. Returns nil for inbound peers.
func (p *peer) OriginalAddr() *NetAddress {
if p.peerConn.outbound {
return p.peerConn.originalAddr
}
return nil
}
// Status returns the peer's ConnectionStatus. // Status returns the peer's ConnectionStatus.
func (p *peer) Status() tmconn.ConnectionStatus { func (p *peer) Status() tmconn.ConnectionStatus {
return p.mconn.Status() return p.mconn.Status()

View File

@ -372,12 +372,13 @@ func (mp mockPeer) NodeInfo() p2p.NodeInfo {
ListenAddr: mp.addr.DialString(), ListenAddr: mp.addr.DialString(),
} }
} }
func (mp mockPeer) RemoteIP() net.IP { return net.ParseIP("127.0.0.1") } func (mockPeer) RemoteIP() net.IP { return net.ParseIP("127.0.0.1") }
func (mp mockPeer) Status() conn.ConnectionStatus { return conn.ConnectionStatus{} } func (mockPeer) Status() conn.ConnectionStatus { return conn.ConnectionStatus{} }
func (mp mockPeer) Send(byte, []byte) bool { return false } func (mockPeer) Send(byte, []byte) bool { return false }
func (mp mockPeer) TrySend(byte, []byte) bool { return false } func (mockPeer) TrySend(byte, []byte) bool { return false }
func (mp mockPeer) Set(string, interface{}) {} func (mockPeer) Set(string, interface{}) {}
func (mp mockPeer) Get(string) interface{} { return nil } func (mockPeer) Get(string) interface{} { return nil }
func (mockPeer) OriginalAddr() *p2p.NetAddress { return nil }
func assertPeersWithTimeout( func assertPeersWithTimeout(
t *testing.T, t *testing.T,

View File

@ -8,8 +8,8 @@ import (
"time" "time"
"github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/p2p/conn"
cmn "github.com/tendermint/tendermint/libs/common" cmn "github.com/tendermint/tendermint/libs/common"
"github.com/tendermint/tendermint/p2p/conn"
) )
const ( const (
@ -281,8 +281,11 @@ func (sw *Switch) StopPeerForError(peer Peer, reason interface{}) {
sw.stopAndRemovePeer(peer, reason) sw.stopAndRemovePeer(peer, reason)
if peer.IsPersistent() { if peer.IsPersistent() {
// NOTE: this is the self-reported addr, not the original we dialed addr := peer.OriginalAddr()
go sw.reconnectToPeer(peer.NodeInfo().NetAddress()) if addr == nil {
panic(fmt.Sprintf("persistent peer %v with no original address", peer))
}
go sw.reconnectToPeer(addr)
} }
} }