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