github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/consense/dpoa/peerpool.go (about) 1 package dpoa 2 3 import ( 4 "fmt" 5 "sync" 6 "time" 7 8 "github.com/sixexorg/magnetic-ring/log" 9 //"github.com/ontio/ontology-crypto/vrf" 10 //"github.com/ontio/ontology-crypto/keypair" 11 "github.com/sixexorg/magnetic-ring/consense/dpoa/comm" 12 //"github.com/sixexorg/magnetic-ring/consensus/vbft/config" 13 "github.com/sixexorg/magnetic-ring/common" 14 "github.com/sixexorg/magnetic-ring/crypto" 15 ) 16 17 18 19 type Peer struct { 20 Index string 21 PubKey crypto.PublicKey 22 handShake *comm.PeerHandshakeMsg 23 LatestInfo *comm.PeerHeartbeatMsg // latest heartbeat msg 24 LastUpdateTime time.Time // time received heartbeat from peer 25 connected bool 26 } 27 28 type PeerPool struct { 29 lock sync.RWMutex 30 IDMap map[string]uint32 31 P2pMap map[string]uint64 //value: p2p random id 32 peers map[string]*Peer 33 peerConnectionWaitings map[string]chan struct{} 34 } 35 36 func NewPeerPool() *PeerPool { 37 return &PeerPool{ 38 IDMap: make(map[string]uint32), 39 P2pMap: make(map[string]uint64), 40 peers: make(map[string]*Peer), 41 peerConnectionWaitings: make(map[string]chan struct{}), 42 } 43 } 44 func (pool *PeerPool) Init(peers []string) error { 45 for _, p := range peers { 46 //pk, _ := vconfig.Pubkey(p) 47 //if !vrf.ValidatePublicKey(pk) { 48 // return fmt.Errorf("peer %d: invalid peer pubkey for VRF", p) 49 //} 50 if err := pool.addPeer(p); err != nil { 51 return fmt.Errorf("failed to add peer %d: %s", p, err) 52 } 53 log.Info("added peer: %s", p) 54 } 55 return nil 56 } 57 58 func (pool *PeerPool) clean() { 59 pool.lock.Lock() 60 defer pool.lock.Unlock() 61 62 //pool.configs = make(map[uint32]*vconfig.PeerConfig) 63 pool.IDMap = make(map[string]uint32) 64 pool.P2pMap = make(map[string]uint64) 65 pool.peers = make(map[string]*Peer) 66 } 67 68 // FIXME: should rename to isPeerConnected 69 func (pool *PeerPool) isNewPeer(peerIdx string) bool { 70 pool.lock.RLock() 71 defer pool.lock.RUnlock() 72 73 if _, present := pool.peers[peerIdx]; present { 74 return !pool.peers[peerIdx].connected 75 } 76 77 return true 78 } 79 80 func (pool *PeerPool) addPeer(p string) error { 81 pool.lock.Lock() 82 defer pool.lock.Unlock() 83 84 buf, err := common.Hex2Bytes(p) 85 if err != nil { 86 return err 87 } 88 89 peerPK, err := crypto.UnmarshalPubkey(buf) 90 //peerPK, err := vconfig.Pubkey(p) 91 if err != nil { 92 return fmt.Errorf("failed to unmarshal peer pubkey: %s", err) 93 } 94 95 pool.peers[p] = &Peer{ 96 Index: p, 97 PubKey: peerPK, 98 LastUpdateTime: time.Unix(0, 0), 99 connected: false, 100 } 101 return nil 102 } 103 104 func (pool *PeerPool) getActivePeerCount() int { 105 pool.lock.RLock() 106 defer pool.lock.RUnlock() 107 108 n := 0 109 for _, p := range pool.peers { 110 if p.connected { 111 n++ 112 } 113 } 114 return n 115 } 116 117 func (pool *PeerPool) waitPeerConnected(peerIdx string) error { 118 if !pool.isNewPeer(peerIdx) { 119 // peer already connected 120 return nil 121 } 122 123 var C chan struct{} 124 pool.lock.Lock() 125 if _, present := pool.peerConnectionWaitings[peerIdx]; !present { 126 C = make(chan struct{}) 127 pool.peerConnectionWaitings[peerIdx] = C 128 } else { 129 C = pool.peerConnectionWaitings[peerIdx] 130 } 131 pool.lock.Unlock() 132 133 <-C 134 135 return nil 136 } 137 138 func (pool *PeerPool) peerConnected(peerIdx string) error { 139 pool.lock.Lock() 140 defer pool.lock.Unlock() 141 // new peer, rather than modify 142 143 buf, err := common.Hex2Bytes(peerIdx) 144 if err != nil { 145 return err 146 } 147 148 peerPK, err := crypto.UnmarshalPubkey(buf) 149 if err != nil { 150 log.Error("PeerPool peerConnected", "peerIdx", peerIdx, "err", err) 151 return err 152 } 153 pool.peers[peerIdx] = &Peer{ 154 Index: peerIdx, 155 PubKey: peerPK, 156 LastUpdateTime: time.Now(), 157 connected: true, 158 } 159 if C, present := pool.peerConnectionWaitings[peerIdx]; present { 160 delete(pool.peerConnectionWaitings, peerIdx) 161 close(C) 162 } 163 return nil 164 } 165 166 func (pool *PeerPool) peerDisconnected(peerIdx string) error { 167 pool.lock.Lock() 168 defer pool.lock.Unlock() 169 170 var lastUpdateTime time.Time 171 if p, present := pool.peers[peerIdx]; present { 172 lastUpdateTime = p.LastUpdateTime 173 } 174 175 pool.peers[peerIdx] = &Peer{ 176 Index: peerIdx, 177 PubKey: pool.peers[peerIdx].PubKey, 178 LastUpdateTime: lastUpdateTime, 179 connected: false, 180 } 181 return nil 182 } 183 184 func (pool *PeerPool) peerHandshake(peerIdx string, msg *comm.PeerHandshakeMsg) error { 185 pool.lock.Lock() 186 defer pool.lock.Unlock() 187 188 pool.peers[peerIdx] = &Peer{ 189 Index: peerIdx, 190 PubKey: pool.peers[peerIdx].PubKey, 191 handShake: msg, 192 LatestInfo: pool.peers[peerIdx].LatestInfo, 193 LastUpdateTime: time.Now(), 194 connected: true, 195 } 196 197 return nil 198 } 199 200 func (pool *PeerPool) peerHeartbeat(peerIdx string, msg *comm.PeerHeartbeatMsg) error { 201 pool.lock.Lock() 202 defer pool.lock.Unlock() 203 204 if C, present := pool.peerConnectionWaitings[peerIdx]; present { 205 // wake up peer connection waitings 206 delete(pool.peerConnectionWaitings, peerIdx) 207 close(C) 208 } 209 210 pool.peers[peerIdx] = &Peer{ 211 Index: peerIdx, 212 PubKey: pool.peers[peerIdx].PubKey, 213 handShake: pool.peers[peerIdx].handShake, 214 LatestInfo: msg, 215 LastUpdateTime: time.Now(), 216 connected: true, 217 } 218 219 return nil 220 } 221 222 func (pool *PeerPool) getNeighbours() []*Peer { 223 pool.lock.RLock() 224 defer pool.lock.RUnlock() 225 226 peers := make([]*Peer, 0) 227 for _, p := range pool.peers { 228 if p.connected { 229 peers = append(peers, p) 230 } 231 } 232 return peers 233 } 234 235 func (pool *PeerPool) GetPeerIndex(nodeId string) (uint32, bool) { 236 pool.lock.RLock() 237 defer pool.lock.RUnlock() 238 239 idx, present := pool.IDMap[nodeId] 240 return idx, present 241 } 242 243 func (pool *PeerPool) GetPeerPubKey(peerIdx string) crypto.PublicKey { 244 pool.lock.RLock() 245 defer pool.lock.RUnlock() 246 247 if p, present := pool.peers[peerIdx]; present && p != nil { 248 return p.PubKey 249 } 250 251 return nil 252 } 253 254 func (pool *PeerPool) isPeerAlive(peerIdx string) bool { 255 pool.lock.RLock() 256 defer pool.lock.RUnlock() 257 258 p := pool.peers[peerIdx] 259 if p == nil || !p.connected { 260 return false 261 } 262 263 // p2pserver keeps peer alive 264 265 return true 266 } 267 268 func (pool *PeerPool) getPeer(idx string) *Peer { 269 pool.lock.RLock() 270 defer pool.lock.RUnlock() 271 272 peer := pool.peers[idx] 273 if peer != nil { 274 if peer.PubKey == nil { 275 276 buf, err := common.Hex2Bytes(idx) 277 if err != nil { 278 return nil 279 } 280 281 peer.PubKey, _ = crypto.UnmarshalPubkey(buf) 282 //peer.PubKey, _ = vconfig.Pubkey(idx) 283 } 284 return peer 285 } 286 287 return nil 288 } 289 290 func (pool *PeerPool) addP2pId(peerIdx string, p2pId uint64) { 291 pool.lock.Lock() 292 defer pool.lock.Unlock() 293 294 pool.P2pMap[peerIdx] = p2pId 295 } 296 297 func (pool *PeerPool) getP2pId(peerIdx string) (uint64, bool) { 298 pool.lock.RLock() 299 defer pool.lock.RUnlock() 300 301 p2pid, present := pool.P2pMap[peerIdx] 302 return p2pid, present 303 } 304 305 func (pool *PeerPool) RemovePeerIndex(nodeId string) { 306 pool.lock.Lock() 307 defer pool.lock.Unlock() 308 309 delete(pool.IDMap, nodeId) 310 }