From b9ff4d929ccb51169ea03061b0292deab939dd5f Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Fri, 13 Sep 2019 20:38:34 +0300 Subject: [PATCH] network: add getaddr message handling Respond with known good addresses. --- pkg/network/payload/address.go | 8 ++++++++ pkg/network/payload/address_test.go | 2 +- pkg/network/server.go | 29 +++++++++++++++++++++++++---- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/pkg/network/payload/address.go b/pkg/network/payload/address.go index 23eb50408..a83498a7d 100644 --- a/pkg/network/payload/address.go +++ b/pkg/network/payload/address.go @@ -62,6 +62,14 @@ type AddressList struct { Addrs []*AddressAndTime } +// NewAddressList creates a list for n AddressAndTime elements. +func NewAddressList(n int) *AddressList { + alist := AddressList{ + Addrs: make([]*AddressAndTime, n), + } + return &alist +} + // DecodeBinary implements the Payload interface. func (p *AddressList) DecodeBinary(r io.Reader) error { br := util.BinReader{R: r} diff --git a/pkg/network/payload/address_test.go b/pkg/network/payload/address_test.go index 154bf017d..afece415a 100644 --- a/pkg/network/payload/address_test.go +++ b/pkg/network/payload/address_test.go @@ -35,7 +35,7 @@ func TestEncodeDecodeAddress(t *testing.T) { func TestEncodeDecodeAddressList(t *testing.T) { var lenList uint8 = 4 - addrList := &AddressList{make([]*AddressAndTime, lenList)} + addrList := NewAddressList(int(lenList)) for i := 0; i < int(lenList); i++ { e, _ := net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:200%d", i)) addrList.Addrs[i] = NewAddressAndTime(e, time.Now()) diff --git a/pkg/network/server.go b/pkg/network/server.go index fb3732505..1de1b060d 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "math/rand" + "net" "sync" "time" @@ -16,10 +17,11 @@ import ( const ( // peer numbers are arbitrary at the moment - minPeers = 5 - maxPeers = 20 - maxBlockBatch = 200 - minPoolCount = 30 + minPeers = 5 + maxPeers = 20 + maxBlockBatch = 200 + maxAddrsToSend = 200 + minPoolCount = 30 ) var ( @@ -294,6 +296,22 @@ func (s *Server) handleAddrCmd(p Peer, addrs *payload.AddressList) error { return nil } +// handleGetAddrCmd sends to the peer some good addresses that we know of. +func (s *Server) handleGetAddrCmd(p Peer) error { + addrs := s.discovery.GoodPeers() + if len(addrs) > maxAddrsToSend { + addrs = addrs[:maxAddrsToSend] + } + alist := payload.NewAddressList(len(addrs)) + ts := time.Now() + for i, addr := range addrs { + // we know it's a good address, so it can't fail + netaddr, _ := net.ResolveTCPAddr("tcp", addr) + alist.Addrs[i] = payload.NewAddressAndTime(netaddr, ts) + } + return p.WriteMsg(NewMessage(s.Net, CMDAddr, alist)) +} + // requestHeaders will send a getheaders message to the peer. // The peer will respond with headers op to a count of 2000. func (s *Server) requestHeaders(p Peer) error { @@ -338,6 +356,9 @@ func (s *Server) handleMessage(peer Peer, msg *Message) error { case CMDAddr: addrs := msg.Payload.(*payload.AddressList) return s.handleAddrCmd(peer, addrs) + case CMDGetAddr: + // it has no payload + return s.handleGetAddrCmd(peer) case CMDHeaders: headers := msg.Payload.(*payload.Headers) go s.handleHeadersCmd(peer, headers)