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 }