github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/whisper/whisperv5/peer.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //
    10  //
    11  //
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  
    25  package whisperv5
    26  
    27  import (
    28  	"fmt"
    29  	"time"
    30  
    31  	mapset "github.com/deckarep/golang-set"
    32  	"github.com/ethereum/go-ethereum/common"
    33  	"github.com/ethereum/go-ethereum/log"
    34  	"github.com/ethereum/go-ethereum/p2p"
    35  	"github.com/ethereum/go-ethereum/rlp"
    36  )
    37  
    38  //
    39  type Peer struct {
    40  	host    *Whisper
    41  	peer    *p2p.Peer
    42  	ws      p2p.MsgReadWriter
    43  	trusted bool
    44  
    45  known mapset.Set //
    46  
    47  	quit chan struct{}
    48  }
    49  
    50  //
    51  func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
    52  	return &Peer{
    53  		host:    host,
    54  		peer:    remote,
    55  		ws:      rw,
    56  		trusted: false,
    57  		known:   mapset.NewSet(),
    58  		quit:    make(chan struct{}),
    59  	}
    60  }
    61  
    62  //
    63  //
    64  func (peer *Peer) start() {
    65  	go peer.update()
    66  	log.Trace("start", "peer", peer.ID())
    67  }
    68  
    69  //
    70  func (peer *Peer) stop() {
    71  	close(peer.quit)
    72  	log.Trace("stop", "peer", peer.ID())
    73  }
    74  
    75  //
    76  //
    77  func (peer *Peer) handshake() error {
    78  //
    79  	errc := make(chan error, 1)
    80  	go func() {
    81  		errc <- p2p.Send(peer.ws, statusCode, ProtocolVersion)
    82  	}()
    83  //
    84  	packet, err := peer.ws.ReadMsg()
    85  	if err != nil {
    86  		return err
    87  	}
    88  	if packet.Code != statusCode {
    89  		return fmt.Errorf("peer [%x] sent packet %x before status packet", peer.ID(), packet.Code)
    90  	}
    91  	s := rlp.NewStream(packet.Payload, uint64(packet.Size))
    92  	peerVersion, err := s.Uint()
    93  	if err != nil {
    94  		return fmt.Errorf("peer [%x] sent bad status message: %v", peer.ID(), err)
    95  	}
    96  	if peerVersion != ProtocolVersion {
    97  		return fmt.Errorf("peer [%x]: protocol version mismatch %d != %d", peer.ID(), peerVersion, ProtocolVersion)
    98  	}
    99  //
   100  	if err := <-errc; err != nil {
   101  		return fmt.Errorf("peer [%x] failed to send status packet: %v", peer.ID(), err)
   102  	}
   103  	return nil
   104  }
   105  
   106  //
   107  //
   108  func (peer *Peer) update() {
   109  //
   110  	expire := time.NewTicker(expirationCycle)
   111  	transmit := time.NewTicker(transmissionCycle)
   112  
   113  //
   114  	for {
   115  		select {
   116  		case <-expire.C:
   117  			peer.expire()
   118  
   119  		case <-transmit.C:
   120  			if err := peer.broadcast(); err != nil {
   121  				log.Trace("broadcast failed", "reason", err, "peer", peer.ID())
   122  				return
   123  			}
   124  
   125  		case <-peer.quit:
   126  			return
   127  		}
   128  	}
   129  }
   130  
   131  //
   132  func (peer *Peer) mark(envelope *Envelope) {
   133  	peer.known.Add(envelope.Hash())
   134  }
   135  
   136  //
   137  func (peer *Peer) marked(envelope *Envelope) bool {
   138  	return peer.known.Contains(envelope.Hash())
   139  }
   140  
   141  //
   142  //
   143  func (peer *Peer) expire() {
   144  	unmark := make(map[common.Hash]struct{})
   145  	peer.known.Each(func(v interface{}) bool {
   146  		if !peer.host.isEnvelopeCached(v.(common.Hash)) {
   147  			unmark[v.(common.Hash)] = struct{}{}
   148  		}
   149  		return true
   150  	})
   151  //
   152  	for hash := range unmark {
   153  		peer.known.Remove(hash)
   154  	}
   155  }
   156  
   157  //
   158  //
   159  func (peer *Peer) broadcast() error {
   160  	var cnt int
   161  	envelopes := peer.host.Envelopes()
   162  	for _, envelope := range envelopes {
   163  		if !peer.marked(envelope) {
   164  			err := p2p.Send(peer.ws, messagesCode, envelope)
   165  			if err != nil {
   166  				return err
   167  			} else {
   168  				peer.mark(envelope)
   169  				cnt++
   170  			}
   171  		}
   172  	}
   173  	if cnt > 0 {
   174  		log.Trace("broadcast", "num. messages", cnt)
   175  	}
   176  	return nil
   177  }
   178  
   179  func (peer *Peer) ID() []byte {
   180  	id := peer.peer.ID()
   181  	return id[:]
   182  }