github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/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 12:09:51</date> 10 //</624342689218826240> 11 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 // 25 // 26 // 27 28 package whisperv5 29 30 import ( 31 "fmt" 32 "time" 33 34 mapset "github.com/deckarep/golang-set" 35 "github.com/ethereum/go-ethereum/common" 36 "github.com/ethereum/go-ethereum/log" 37 "github.com/ethereum/go-ethereum/p2p" 38 "github.com/ethereum/go-ethereum/rlp" 39 ) 40 41 // 42 type Peer struct { 43 host *Whisper 44 peer *p2p.Peer 45 ws p2p.MsgReadWriter 46 trusted bool 47 48 known mapset.Set // 49 50 quit chan struct{} 51 } 52 53 // 54 func newPeer(host *Whisper, remote *p2p.Peer, rw p2p.MsgReadWriter) *Peer { 55 return &Peer{ 56 host: host, 57 peer: remote, 58 ws: rw, 59 trusted: false, 60 known: mapset.NewSet(), 61 quit: make(chan struct{}), 62 } 63 } 64 65 // 66 // 67 func (peer *Peer) start() { 68 go peer.update() 69 log.Trace("start", "peer", peer.ID()) 70 } 71 72 // 73 func (peer *Peer) stop() { 74 close(peer.quit) 75 log.Trace("stop", "peer", peer.ID()) 76 } 77 78 // 79 // 80 func (peer *Peer) handshake() error { 81 // 82 errc := make(chan error, 1) 83 go func() { 84 errc <- p2p.Send(peer.ws, statusCode, ProtocolVersion) 85 }() 86 // 87 packet, err := peer.ws.ReadMsg() 88 if err != nil { 89 return err 90 } 91 if packet.Code != statusCode { 92 return fmt.Errorf("peer [%x] sent packet %x before status packet", peer.ID(), packet.Code) 93 } 94 s := rlp.NewStream(packet.Payload, uint64(packet.Size)) 95 peerVersion, err := s.Uint() 96 if err != nil { 97 return fmt.Errorf("peer [%x] sent bad status message: %v", peer.ID(), err) 98 } 99 if peerVersion != ProtocolVersion { 100 return fmt.Errorf("peer [%x]: protocol version mismatch %d != %d", peer.ID(), peerVersion, ProtocolVersion) 101 } 102 // 103 if err := <-errc; err != nil { 104 return fmt.Errorf("peer [%x] failed to send status packet: %v", peer.ID(), err) 105 } 106 return nil 107 } 108 109 // 110 // 111 func (peer *Peer) update() { 112 // 113 expire := time.NewTicker(expirationCycle) 114 transmit := time.NewTicker(transmissionCycle) 115 116 // 117 for { 118 select { 119 case <-expire.C: 120 peer.expire() 121 122 case <-transmit.C: 123 if err := peer.broadcast(); err != nil { 124 log.Trace("broadcast failed", "reason", err, "peer", peer.ID()) 125 return 126 } 127 128 case <-peer.quit: 129 return 130 } 131 } 132 } 133 134 // 135 func (peer *Peer) mark(envelope *Envelope) { 136 peer.known.Add(envelope.Hash()) 137 } 138 139 // 140 func (peer *Peer) marked(envelope *Envelope) bool { 141 return peer.known.Contains(envelope.Hash()) 142 } 143 144 // 145 // 146 func (peer *Peer) expire() { 147 unmark := make(map[common.Hash]struct{}) 148 peer.known.Each(func(v interface{}) bool { 149 if !peer.host.isEnvelopeCached(v.(common.Hash)) { 150 unmark[v.(common.Hash)] = struct{}{} 151 } 152 return true 153 }) 154 // 155 for hash := range unmark { 156 peer.known.Remove(hash) 157 } 158 } 159 160 // 161 // 162 func (peer *Peer) broadcast() error { 163 var cnt int 164 envelopes := peer.host.Envelopes() 165 for _, envelope := range envelopes { 166 if !peer.marked(envelope) { 167 err := p2p.Send(peer.ws, messagesCode, envelope) 168 if err != nil { 169 return err 170 } else { 171 peer.mark(envelope) 172 cnt++ 173 } 174 } 175 } 176 if cnt > 0 { 177 log.Trace("broadcast", "num. messages", cnt) 178 } 179 return nil 180 } 181 182 func (peer *Peer) ID() []byte { 183 id := peer.peer.ID() 184 return id[:] 185 } 186