diff --git a/peer/example_test.go b/peer/example_test.go index a549fe21..cb67683b 100644 --- a/peer/example_test.go +++ b/peer/example_test.go @@ -1,4 +1,5 @@ -// Copyright (c) 2015-2016 The btcsuite developers +// Copyright (c) 2015-2018 The btcsuite developers +// Copyright (c) 2016-2018 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -72,8 +73,9 @@ func Example_newOutboundPeer() { Services: 0, TrickleInterval: time.Second * 10, Listeners: peer.MessageListeners{ - OnVersion: func(p *peer.Peer, msg *wire.MsgVersion) { + OnVersion: func(p *peer.Peer, msg *wire.MsgVersion) *wire.MsgReject { fmt.Println("outbound: received version") + return nil }, OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { verack <- struct{}{} diff --git a/peer/peer.go b/peer/peer.go index a4ea1fd4..afb14173 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -187,7 +187,9 @@ type MessageListeners struct { OnMerkleBlock func(p *Peer, msg *wire.MsgMerkleBlock) // OnVersion is invoked when a peer receives a version bitcoin message. - OnVersion func(p *Peer, msg *wire.MsgVersion) + // The caller may return a reject message in which case the message will + // be sent to the peer and the peer will be disconnected. + OnVersion func(p *Peer, msg *wire.MsgVersion) *wire.MsgReject // OnVerAck is invoked when a peer receives a verack bitcoin message. OnVerAck func(p *Peer, msg *wire.MsgVerAck) @@ -1944,7 +1946,11 @@ func (p *Peer) readRemoteVersionMsg() error { // Invoke the callback if specified. if p.cfg.Listeners.OnVersion != nil { - p.cfg.Listeners.OnVersion(p, msg) + rejectMsg := p.cfg.Listeners.OnVersion(p, msg) + if rejectMsg != nil { + _ = p.writeMessage(rejectMsg, wire.LatestEncoding) + return errors.New(rejectMsg.Reason) + } } // Notify and disconnect clients that have a protocol version that is diff --git a/peer/peer_test.go b/peer/peer_test.go index 4c49040b..fff0ce3f 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -432,8 +432,9 @@ func TestPeerListeners(t *testing.T) { OnMerkleBlock: func(p *peer.Peer, msg *wire.MsgMerkleBlock) { ok <- msg }, - OnVersion: func(p *peer.Peer, msg *wire.MsgVersion) { + OnVersion: func(p *peer.Peer, msg *wire.MsgVersion) *wire.MsgReject { ok <- msg + return nil }, OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { verack <- struct{}{} diff --git a/server.go b/server.go index 9c82ffa7..320238ad 100644 --- a/server.go +++ b/server.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2017 The btcsuite developers -// Copyright (c) 2015-2017 The Decred developers +// Copyright (c) 2015-2018 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -388,11 +388,11 @@ func (sp *serverPeer) addBanScore(persistent, transient uint32, reason string) { // OnVersion is invoked when a peer receives a version bitcoin message // and is used to negotiate the protocol version details as well as kick start // the communications. -func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) { +func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgReject { // Ignore peers that have a protcol version that is too old. The peer // negotiation logic will disconnect it after this callback returns. if msg.ProtocolVersion < int32(peer.MinAcceptableProtocolVersion) { - return + return nil } // Add the remote peer time as a sample for creating an offset against @@ -424,7 +424,7 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) { if err != nil { peerLog.Errorf("Unable to query for segwit "+ "soft-fork state: %v", err) - return + return nil } if segwitActive && !sp.IsWitnessEnabled() { @@ -432,7 +432,7 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) { "peer %v, isn't segwit enabled and "+ "we need more segwit enabled peers", sp) sp.Disconnect() - return + return nil } // TODO(davec): Only do this if not doing the initial block @@ -463,6 +463,7 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) { // Add valid peer to the server. sp.server.AddPeer(sp) + return nil } // OnMemPool is invoked when a peer receives a mempool bitcoin message.