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  }