Skip to content

Commit

Permalink
fix: DNS TTL not respected (#1442)
Browse files Browse the repository at this point in the history
## Description

Fixes #1425 

## Testing

Testing DNS change is not really possible in unit tests so @smuu agreed
to help me test manually
  • Loading branch information
ninabarbakadze committed Aug 23, 2024
1 parent b648b80 commit 0d2b638
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 13 deletions.
1 change: 1 addition & 0 deletions blockchain/v2/reactor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func (mp mockPeer) RemoteAddr() net.Addr { return &net.TCPAddr{IP: mp.RemoteIP()

func (mp mockPeer) IsOutbound() bool { return true }
func (mp mockPeer) IsPersistent() bool { return true }
func (mp mockPeer) HasIPChanged() bool { return false }
func (mp mockPeer) CloseConn() error { return nil }

func (mp mockPeer) NodeInfo() p2p.NodeInfo {
Expand Down
1 change: 1 addition & 0 deletions p2p/mock/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func (mp *Peer) Status() conn.ConnectionStatus { return conn.ConnectionStatus{}
func (mp *Peer) ID() p2p.ID { return mp.id }
func (mp *Peer) IsOutbound() bool { return mp.Outbound }
func (mp *Peer) IsPersistent() bool { return mp.Persistent }
func (mp *Peer) HasIPChanged() bool { return false }
func (mp *Peer) Get(key string) interface{} {
if value, ok := mp.kv[key]; ok {
return value
Expand Down
14 changes: 14 additions & 0 deletions p2p/mocks/peer.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions p2p/mocks/peer_envelope_sender.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions p2p/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ type Peer interface {
IsOutbound() bool // did we dial the peer
IsPersistent() bool // do we redial this peer when we disconnect

HasIPChanged() bool // has the peer's IP changed

CloseConn() error // close original connection

NodeInfo() NodeInfo // peer's info
Expand Down Expand Up @@ -300,6 +302,18 @@ func (p *peer) IsPersistent() bool {
return p.peerConn.persistent
}

// HasIPChanged returns true and the new IP if the peer's IP has changed.
func (p *peer) HasIPChanged() bool {
oldIP := p.ip
if oldIP == nil {
return false
}
// Reset the IP so we can get the new one
p.ip = nil
newIP := p.RemoteIP()
return !oldIP.Equal(newIP)
}

// NodeInfo returns a copy of the peer's NodeInfo.
func (p *peer) NodeInfo() NodeInfo {
return p.nodeInfo
Expand Down
1 change: 1 addition & 0 deletions p2p/peer_set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func (mp *mockPeer) NodeInfo() NodeInfo { return DefaultNodeInfo{}
func (mp *mockPeer) Status() ConnectionStatus { return ConnectionStatus{} }
func (mp *mockPeer) ID() ID { return mp.id }
func (mp *mockPeer) IsOutbound() bool { return false }
func (mp *mockPeer) HasIPChanged() bool { return false }
func (mp *mockPeer) IsPersistent() bool { return true }
func (mp *mockPeer) Get(s string) interface{} { return s }
func (mp *mockPeer) Set(string, interface{}) {}
Expand Down
39 changes: 28 additions & 11 deletions p2p/switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,20 +381,37 @@ func (sw *Switch) StopPeerForError(peer Peer, reason interface{}) {
sw.stopAndRemovePeer(peer, reason)

if peer.IsPersistent() {
var addr *NetAddress
if peer.IsOutbound() { // socket address for outbound peers
addr = peer.SocketAddr()
} else { // self-reported address for inbound peers
var err error
addr, err = peer.NodeInfo().NetAddress()
if err != nil {
sw.Logger.Error("Wanted to reconnect to inbound peer, but self-reported address is wrong",
"peer", peer, "err", err)
return
}
addr, err := sw.getPeerAddress(peer)
if err != nil {
sw.Logger.Error("Failed to get address for persistent peer", "peer", peer, "err", err)
return
}
go sw.reconnectToPeer(addr)
}

if peer.HasIPChanged() {
addr, err := sw.getPeerAddress(peer)
if err != nil {
sw.Logger.Error("Failed to get address for peer with changed IP", "peer", peer, "err", err)
}
go sw.reconnectToPeer(addr)
}
}

// getPeerAddress returns the appropriate NetAddress for a given peer,
// handling both outbound and inbound peers.
func (sw *Switch) getPeerAddress(peer Peer) (*NetAddress, error) {
if peer.IsOutbound() {
return peer.SocketAddr(), nil
}
// For inbound peers, get the self-reported address
addr, err := peer.NodeInfo().NetAddress()
if err != nil {
sw.Logger.Error("Failed to get address for inbound peer",
"peer", peer, "err", err)
return nil, err
}
return addr, nil
}

// StopPeerGracefully disconnects from a peer gracefully.
Expand Down
6 changes: 4 additions & 2 deletions test/fuzz/p2p/pex/reactor_receive.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,10 @@ func (fp *fuzzPeer) RemoteIP() net.IP { return net.IPv4(0, 0, 0, 0) }
func (fp *fuzzPeer) RemoteAddr() net.Addr {
return &net.TCPAddr{IP: fp.RemoteIP(), Port: 98991, Zone: ""}
}
func (fp *fuzzPeer) IsOutbound() bool { return false }
func (fp *fuzzPeer) IsPersistent() bool { return false }
func (fp *fuzzPeer) IsOutbound() bool { return false }
func (fp *fuzzPeer) IsPersistent() bool { return false }
func (fp *fuzzPeer) HasIPChanged() bool { return false }

func (fp *fuzzPeer) CloseConn() error { return nil }
func (fp *fuzzPeer) NodeInfo() p2p.NodeInfo { return defaultNodeInfo }
func (fp *fuzzPeer) Status() p2p.ConnectionStatus { var cs p2p.ConnectionStatus; return cs }
Expand Down

0 comments on commit 0d2b638

Please sign in to comment.