github.com/phillinzzz/newBsc@v1.1.6/eth/protocols/diff/peer.go (about)

     1  package diff
     2  
     3  import (
     4  	"math/rand"
     5  
     6  	"github.com/phillinzzz/newBsc/common"
     7  	"github.com/phillinzzz/newBsc/log"
     8  	"github.com/phillinzzz/newBsc/p2p"
     9  	"github.com/phillinzzz/newBsc/rlp"
    10  )
    11  
    12  const maxQueuedDiffLayers = 12
    13  
    14  // Peer is a collection of relevant information we have about a `diff` peer.
    15  type Peer struct {
    16  	id               string              // Unique ID for the peer, cached
    17  	diffSync         bool                // whether the peer can diff sync
    18  	queuedDiffLayers chan []rlp.RawValue // Queue of diff layers to broadcast to the peer
    19  
    20  	*p2p.Peer                   // The embedded P2P package peer
    21  	rw        p2p.MsgReadWriter // Input/output streams for diff
    22  	version   uint              // Protocol version negotiated
    23  	logger    log.Logger        // Contextual logger with the peer id injected
    24  	term      chan struct{}     // Termination channel to stop the broadcasters
    25  }
    26  
    27  // NewPeer create a wrapper for a network connection and negotiated  protocol
    28  // version.
    29  func NewPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
    30  	id := p.ID().String()
    31  	peer := &Peer{
    32  		id:               id,
    33  		Peer:             p,
    34  		rw:               rw,
    35  		diffSync:         false,
    36  		version:          version,
    37  		logger:           log.New("peer", id[:8]),
    38  		queuedDiffLayers: make(chan []rlp.RawValue, maxQueuedDiffLayers),
    39  		term:             make(chan struct{}),
    40  	}
    41  	go peer.broadcastDiffLayers()
    42  	return peer
    43  }
    44  
    45  func (p *Peer) broadcastDiffLayers() {
    46  	for {
    47  		select {
    48  		case prop := <-p.queuedDiffLayers:
    49  			if err := p.SendDiffLayers(prop); err != nil {
    50  				p.Log().Error("Failed to propagated diff layer", "err", err)
    51  				return
    52  			}
    53  		case <-p.term:
    54  			return
    55  		}
    56  	}
    57  }
    58  
    59  // ID retrieves the peer's unique identifier.
    60  func (p *Peer) ID() string {
    61  	return p.id
    62  }
    63  
    64  // Version retrieves the peer's negoatiated `diff` protocol version.
    65  func (p *Peer) Version() uint {
    66  	return p.version
    67  }
    68  
    69  func (p *Peer) DiffSync() bool {
    70  	return p.diffSync
    71  }
    72  
    73  // Log overrides the P2P logget with the higher level one containing only the id.
    74  func (p *Peer) Log() log.Logger {
    75  	return p.logger
    76  }
    77  
    78  // Close signals the broadcast goroutine to terminate. Only ever call this if
    79  // you created the peer yourself via NewPeer. Otherwise let whoever created it
    80  // clean it up!
    81  func (p *Peer) Close() {
    82  	close(p.term)
    83  }
    84  
    85  // RequestDiffLayers fetches a batch of diff layers corresponding to the hashes
    86  // specified.
    87  func (p *Peer) RequestDiffLayers(hashes []common.Hash) error {
    88  	id := rand.Uint64()
    89  
    90  	requestTracker.Track(p.id, p.version, GetDiffLayerMsg, FullDiffLayerMsg, id)
    91  	return p2p.Send(p.rw, GetDiffLayerMsg, GetDiffLayersPacket{
    92  		RequestId:   id,
    93  		BlockHashes: hashes,
    94  	})
    95  }
    96  
    97  func (p *Peer) SendDiffLayers(diffs []rlp.RawValue) error {
    98  	return p2p.Send(p.rw, DiffLayerMsg, diffs)
    99  }
   100  
   101  func (p *Peer) AsyncSendDiffLayer(diffLayers []rlp.RawValue) {
   102  	select {
   103  	case p.queuedDiffLayers <- diffLayers:
   104  	default:
   105  		p.Log().Debug("Dropping diff layers propagation")
   106  	}
   107  }