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 }