Skip to content

Commit

Permalink
network: treat unsolicited addr commands as errors
Browse files Browse the repository at this point in the history
  • Loading branch information
roman-khimov committed Nov 25, 2020
1 parent 619b6d4 commit 2ce3c8b
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 0 deletions.
9 changes: 9 additions & 0 deletions pkg/network/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ type localPeer struct {
t *testing.T
messageHandler func(t *testing.T, msg *Message)
pingSent int
getAddrSent int
}

func newLocalPeer(t *testing.T, s *Server) *localPeer {
Expand Down Expand Up @@ -323,6 +324,14 @@ func (p *localPeer) IsFullNode() bool {
return p.isFullNode
}

func (p *localPeer) AddGetAddrSent() {
p.getAddrSent++
}
func (p *localPeer) CanProcessAddr() bool {
p.getAddrSent--
return p.getAddrSent >= 0
}

func newTestServer(t *testing.T, serverConfig ServerConfig) *Server {
s := &Server{
ServerConfig: serverConfig,
Expand Down
9 changes: 9 additions & 0 deletions pkg/network/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,13 @@ type Peer interface {

// HandlePong checks pong contents against Peer's state and updates it.
HandlePong(pong *payload.Ping) error

// AddGetAddrSent is to inform local peer context that a getaddr command
// is sent. The decision to send getaddr is server-wide, but it needs to be
// accounted for in peer's context, thus this method.
AddGetAddrSent()

// CanProcessAddr checks whether an addr command is expected to come from
// this peer and can be processed.
CanProcessAddr() bool
}
6 changes: 6 additions & 0 deletions pkg/network/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,9 @@ func (s *Server) handleTxCmd(tx *transaction.Transaction) error {

// handleAddrCmd will process received addresses.
func (s *Server) handleAddrCmd(p Peer, addrs *payload.AddressList) error {
if !p.CanProcessAddr() {
return errors.New("unexpected addr received")
}
for _, a := range addrs.Addrs {
addr, err := a.GetTCPAddress()
if err == nil {
Expand Down Expand Up @@ -830,6 +833,9 @@ func (s *Server) iteratePeersWithSendMsg(msg *Message, send func(Peer, []byte) e
if peerOK != nil && !peerOK(peer) {
continue
}
if msg.Command == CMDGetAddr {
peer.AddGetAddrSent()
}
// Who cares about these messages anyway?
_ = send(peer, pkt)
}
Expand Down
17 changes: 17 additions & 0 deletions pkg/network/tcp_peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/network/capability"
"github.com/nspcc-dev/neo-go/pkg/network/payload"
"go.uber.org/atomic"
"go.uber.org/zap"
)

Expand Down Expand Up @@ -58,6 +59,9 @@ type TCPPeer struct {

wg sync.WaitGroup

// track outstanding getaddr requests.
getAddrSent atomic.Int32

// number of sent pings.
pingSent int
pingTimer *time.Timer
Expand Down Expand Up @@ -455,3 +459,16 @@ func (p *TCPPeer) HandlePong(pong *payload.Ping) error {
p.lastBlockIndex = pong.LastBlockIndex
return nil
}

// AddGetAddrSent increments internal outstanding getaddr requests counter. The
// peer can only send then one addr reply per getaddr request.
func (p *TCPPeer) AddGetAddrSent() {
p.getAddrSent.Inc()
}

// CanProcessAddr decrements internal outstanding getaddr requests counter and
// answers whether the addr command from the peer can be safely processed.
func (p *TCPPeer) CanProcessAddr() bool {
v := p.getAddrSent.Dec()
return v >= 0
}

0 comments on commit 2ce3c8b

Please sign in to comment.