peer: Simplify PushAddrMsg method loop.

This implementation ensures that all addresses have an equal chance of
being included in the addr message. It also moves the pseudorandom number
generator seeding to package level so that it can be overridden for
testing if required.
This commit is contained in:
Jonathan Gillham 2016-01-23 22:47:12 +00:00
parent 407fcc2aaf
commit e03fa30e89

View file

@ -1,4 +1,4 @@
// Copyright (c) 2013-2015 The btcsuite developers // Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC // Use of this source code is governed by an ISC
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -10,7 +10,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
prand "math/rand" "math/rand"
"net" "net"
"strconv" "strconv"
"sync" "sync"
@ -814,36 +814,34 @@ func (p *Peer) pushVersionMsg() error {
// addresses. This function is useful over manually sending the message via // addresses. This function is useful over manually sending the message via
// QueueMessage since it automatically limits the addresses to the maximum // QueueMessage since it automatically limits the addresses to the maximum
// number allowed by the message and randomizes the chosen addresses when there // number allowed by the message and randomizes the chosen addresses when there
// are too many. No message will be sent if there are no entries in the // are too many. It returns the addresses that were actually sent and no
// provided addresses slice. // message will be sent if there are no entries in the provided addresses slice.
// It is safe for concurrent access. //
// This function is safe for concurrent access.
func (p *Peer) PushAddrMsg(addresses []*wire.NetAddress) ([]*wire.NetAddress, error) { func (p *Peer) PushAddrMsg(addresses []*wire.NetAddress) ([]*wire.NetAddress, error) {
// Nothing to send. // Nothing to send.
if len(addresses) == 0 { if len(addresses) == 0 {
return nil, nil return nil, nil
} }
r := prand.New(prand.NewSource(time.Now().UnixNano()))
numAdded := 0
msg := wire.NewMsgAddr() msg := wire.NewMsgAddr()
for _, na := range addresses { msg.AddrList = make([]*wire.NetAddress, len(addresses))
// Randomize the list with the remaining addresses when the copy(msg.AddrList, addresses)
// max addresses limit has been reached.
if numAdded == wire.MaxAddrPerMsg { // Randomize the addresses sent if there are more than the maximum allowed.
msg.AddrList[r.Intn(wire.MaxAddrPerMsg)] = na if len(msg.AddrList) > wire.MaxAddrPerMsg {
continue // Shuffle the address list.
for i := range msg.AddrList {
j := rand.Intn(i + 1)
msg.AddrList[i], msg.AddrList[j] = msg.AddrList[j], msg.AddrList[i]
} }
// Add the address to the message. // Truncate it to the maximum size.
err := msg.AddAddress(na) msg.AddrList = msg.AddrList[:wire.MaxAddrPerMsg]
if err != nil {
return nil, err
}
numAdded++
}
if numAdded > 0 {
p.QueueMessage(msg, nil)
} }
p.QueueMessage(msg, nil)
return msg.AddrList, nil return msg.AddrList, nil
} }
@ -2099,3 +2097,7 @@ func NewOutboundPeer(cfg *Config, addr string) (*Peer, error) {
return p, nil return p, nil
} }
func init() {
rand.Seed(time.Now().UnixNano())
}