github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/whisper/whisperv5/peer.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:46</date>
    10  //</624450124763893760>
    11  
    12  
    13  package whisperv5
    14  
    15  import (
    16  	"fmt"
    17  	"time"
    18  
    19  	mapset "github.com/deckarep/golang-set"
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/log"
    22  	"github.com/ethereum/go-ethereum/p2p"
    23  	"github.com/ethereum/go-ethereum/rlp"
    24  )
    25  
    26  //Peer表示一个耳语协议对等连接。
    27  type Peer struct {
    28  	host    *Whisper
    29  	peer    *p2p.Peer
    30  	ws      p2p.MsgReadWriter
    31  	trusted bool
    32  
    33  known mapset.Set //对等方已经知道的消息,以避免浪费带宽
    34  
    35  	quit chan struct{}
    36  }
    37  
    38  //new peer创建一个新的whisper peer对象,但不运行握手本身。
    39  func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
    40  	return &Peer{
    41  		host:    host,
    42  		peer:    remote,
    43  		ws:      rw,
    44  		trusted: false,
    45  		known:   mapset.NewSet(),
    46  		quit:    make(chan struct{}),
    47  	}
    48  }
    49  
    50  //启动启动对等更新程序,定期广播低语数据包
    51  //进入网络。
    52  func (peer *Peer) start() {
    53  	go peer.update()
    54  	log.Trace("start", "peer", peer.ID())
    55  }
    56  
    57  //stop终止对等更新程序,停止向其转发消息。
    58  func (peer *Peer) stop() {
    59  	close(peer.quit)
    60  	log.Trace("stop", "peer", peer.ID())
    61  }
    62  
    63  //握手向远程对等端发送协议启动状态消息,并且
    64  //也验证远程状态。
    65  func (peer *Peer) handshake() error {
    66  //异步发送握手状态消息
    67  	errc := make(chan error, 1)
    68  	go func() {
    69  		errc <- p2p.Send(peer.ws, statusCode, ProtocolVersion)
    70  	}()
    71  //获取远程状态包并验证协议匹配
    72  	packet, err := peer.ws.ReadMsg()
    73  	if err != nil {
    74  		return err
    75  	}
    76  	if packet.Code != statusCode {
    77  		return fmt.Errorf("peer [%x] sent packet %x before status packet", peer.ID(), packet.Code)
    78  	}
    79  	s := rlp.NewStream(packet.Payload, uint64(packet.Size))
    80  	peerVersion, err := s.Uint()
    81  	if err != nil {
    82  		return fmt.Errorf("peer [%x] sent bad status message: %v", peer.ID(), err)
    83  	}
    84  	if peerVersion != ProtocolVersion {
    85  		return fmt.Errorf("peer [%x]: protocol version mismatch %d != %d", peer.ID(), peerVersion, ProtocolVersion)
    86  	}
    87  //等待直到消耗掉自己的状态
    88  	if err := <-errc; err != nil {
    89  		return fmt.Errorf("peer [%x] failed to send status packet: %v", peer.ID(), err)
    90  	}
    91  	return nil
    92  }
    93  
    94  //更新在对等机上执行定期操作,包括消息传输
    95  //和呼气。
    96  func (peer *Peer) update() {
    97  //启动更新的滚动条
    98  	expire := time.NewTicker(expirationCycle)
    99  	transmit := time.NewTicker(transmissionCycle)
   100  
   101  //循环并发送直到请求终止
   102  	for {
   103  		select {
   104  		case <-expire.C:
   105  			peer.expire()
   106  
   107  		case <-transmit.C:
   108  			if err := peer.broadcast(); err != nil {
   109  				log.Trace("broadcast failed", "reason", err, "peer", peer.ID())
   110  				return
   111  			}
   112  
   113  		case <-peer.quit:
   114  			return
   115  		}
   116  	}
   117  }
   118  
   119  //马克标记了一个同伴知道的信封,这样它就不会被送回。
   120  func (peer *Peer) mark(envelope *Envelope) {
   121  	peer.known.Add(envelope.Hash())
   122  }
   123  
   124  //标记检查远程对等机是否已经知道信封。
   125  func (peer *Peer) marked(envelope *Envelope) bool {
   126  	return peer.known.Contains(envelope.Hash())
   127  }
   128  
   129  //Expire迭代主机中的所有已知信封,并删除所有
   130  //已知列表中过期(未知)的。
   131  func (peer *Peer) expire() {
   132  	unmark := make(map[common.Hash]struct{})
   133  	peer.known.Each(func(v interface{}) bool {
   134  		if !peer.host.isEnvelopeCached(v.(common.Hash)) {
   135  			unmark[v.(common.Hash)] = struct{}{}
   136  		}
   137  		return true
   138  	})
   139  //转储所有已知但不再缓存的内容
   140  	for hash := range unmark {
   141  		peer.known.Remove(hash)
   142  	}
   143  }
   144  
   145  //广播在信封集合上迭代,传输未知信息
   146  //在网络上。
   147  func (peer *Peer) broadcast() error {
   148  	var cnt int
   149  	envelopes := peer.host.Envelopes()
   150  	for _, envelope := range envelopes {
   151  		if !peer.marked(envelope) {
   152  			err := p2p.Send(peer.ws, messagesCode, envelope)
   153  			if err != nil {
   154  				return err
   155  			} else {
   156  				peer.mark(envelope)
   157  				cnt++
   158  			}
   159  		}
   160  	}
   161  	if cnt > 0 {
   162  		log.Trace("broadcast", "num. messages", cnt)
   163  	}
   164  	return nil
   165  }
   166  
   167  func (peer *Peer) ID() []byte {
   168  	id := peer.peer.ID()
   169  	return id[:]
   170  }
   171