From b31ee798bdead06a6e4b9b34c279722b0713df24 Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 18 Jul 2018 13:23:29 +0400 Subject: [PATCH] preserve original address and dial it instead of self-reported address (#1994) Refs #1720 --- blockchain/reactor_test.go | 1 + p2p/dummy/peer.go | 7 ++++++- p2p/peer.go | 35 ++++++++++++++++++++++++----------- p2p/pex/pex_reactor_test.go | 13 +++++++------ p2p/switch.go | 9 ++++++--- 5 files changed, 44 insertions(+), 21 deletions(-) diff --git a/blockchain/reactor_test.go b/blockchain/reactor_test.go index 2bb6e976..21eaae4b 100644 --- a/blockchain/reactor_test.go +++ b/blockchain/reactor_test.go @@ -206,3 +206,4 @@ func (tp *bcrTestPeer) IsPersistent() bool { return true } func (tp *bcrTestPeer) Get(s string) interface{} { return s } func (tp *bcrTestPeer) Set(string, interface{}) {} func (tp *bcrTestPeer) RemoteIP() net.IP { return []byte{127, 0, 0, 1} } +func (tp *bcrTestPeer) OriginalAddr() *p2p.NetAddress { return nil } diff --git a/p2p/dummy/peer.go b/p2p/dummy/peer.go index d18a9f99..bb6e822f 100644 --- a/p2p/dummy/peer.go +++ b/p2p/dummy/peer.go @@ -3,9 +3,9 @@ package dummy import ( "net" + cmn "github.com/tendermint/tendermint/libs/common" p2p "github.com/tendermint/tendermint/p2p" tmconn "github.com/tendermint/tendermint/p2p/conn" - cmn "github.com/tendermint/tendermint/libs/common" ) type peer struct { @@ -78,3 +78,8 @@ func (p *peer) Get(key string) interface{} { } return nil } + +// OriginalAddr always returns nil. +func (p *peer) OriginalAddr() *p2p.NetAddress { + return nil +} diff --git a/p2p/peer.go b/p2p/peer.go index 5c615275..4f59fef7 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -26,6 +26,7 @@ type Peer interface { IsPersistent() bool // do we redial this peer when we disconnect NodeInfo() NodeInfo // peer's info Status() tmconn.ConnectionStatus + OriginalAddr() *NetAddress Send(byte, []byte) bool TrySend(byte, []byte) bool @@ -38,11 +39,12 @@ type Peer interface { // peerConn contains the raw connection and its config. type peerConn struct { - outbound bool - persistent bool - config *config.P2PConfig - conn net.Conn // source connection - ip net.IP + outbound bool + persistent bool + config *config.P2PConfig + conn net.Conn // source connection + ip net.IP + originalAddr *NetAddress // nil for inbound connections } // ID only exists for SecretConnection. @@ -139,7 +141,7 @@ func newOutboundPeerConn( 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 cerr := conn.Close(); cerr != nil { return peerConn{}, cmn.ErrorWrap(err, cerr.Error()) @@ -166,7 +168,7 @@ func newInboundPeerConn( // TODO: issue PoW challenge - return newPeerConn(conn, config, false, false, ourNodePrivKey) + return newPeerConn(conn, config, false, false, ourNodePrivKey, nil) } func newPeerConn( @@ -174,6 +176,7 @@ func newPeerConn( cfg *config.P2PConfig, outbound, persistent bool, ourNodePrivKey crypto.PrivKey, + originalAddr *NetAddress, ) (pc peerConn, err error) { conn := rawConn @@ -200,10 +203,11 @@ func newPeerConn( // Only the information we already have return peerConn{ - config: cfg, - outbound: outbound, - persistent: persistent, - conn: conn, + config: cfg, + outbound: outbound, + persistent: persistent, + conn: conn, + originalAddr: originalAddr, }, nil } @@ -254,6 +258,15 @@ func (p *peer) NodeInfo() 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. func (p *peer) Status() tmconn.ConnectionStatus { return p.mconn.Status() diff --git a/p2p/pex/pex_reactor_test.go b/p2p/pex/pex_reactor_test.go index 60b0821f..25da4f89 100644 --- a/p2p/pex/pex_reactor_test.go +++ b/p2p/pex/pex_reactor_test.go @@ -372,12 +372,13 @@ func (mp mockPeer) NodeInfo() p2p.NodeInfo { ListenAddr: mp.addr.DialString(), } } -func (mp mockPeer) RemoteIP() net.IP { return net.ParseIP("127.0.0.1") } -func (mp mockPeer) Status() conn.ConnectionStatus { return conn.ConnectionStatus{} } -func (mp mockPeer) Send(byte, []byte) bool { return false } -func (mp mockPeer) TrySend(byte, []byte) bool { return false } -func (mp mockPeer) Set(string, interface{}) {} -func (mp mockPeer) Get(string) interface{} { return nil } +func (mockPeer) RemoteIP() net.IP { return net.ParseIP("127.0.0.1") } +func (mockPeer) Status() conn.ConnectionStatus { return conn.ConnectionStatus{} } +func (mockPeer) Send(byte, []byte) bool { return false } +func (mockPeer) TrySend(byte, []byte) bool { return false } +func (mockPeer) Set(string, interface{}) {} +func (mockPeer) Get(string) interface{} { return nil } +func (mockPeer) OriginalAddr() *p2p.NetAddress { return nil } func assertPeersWithTimeout( t *testing.T, diff --git a/p2p/switch.go b/p2p/switch.go index d1e2ef23..77c64fca 100644 --- a/p2p/switch.go +++ b/p2p/switch.go @@ -8,8 +8,8 @@ import ( "time" "github.com/tendermint/tendermint/config" - "github.com/tendermint/tendermint/p2p/conn" cmn "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/p2p/conn" ) const ( @@ -281,8 +281,11 @@ func (sw *Switch) StopPeerForError(peer Peer, reason interface{}) { sw.stopAndRemovePeer(peer, reason) if peer.IsPersistent() { - // NOTE: this is the self-reported addr, not the original we dialed - go sw.reconnectToPeer(peer.NodeInfo().NetAddress()) + addr := peer.OriginalAddr() + if addr == nil { + panic(fmt.Sprintf("persistent peer %v with no original address", peer)) + } + go sw.reconnectToPeer(addr) } }