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) Set(string, interface{}) {}
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 (
"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
}

View File

@ -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()

View File

@ -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,

View File

@ -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)
}
}