github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/p2pserver/p2pserver.go (about)

     1  package p2pserver
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	//"fmt"
     6  
     7  	// "encoding/json"
     8  	"errors"
     9  	// "io/ioutil"
    10  	"math/rand"
    11  	"net"
    12  
    13  	// "os"
    14  	"reflect"
    15  	"strconv"
    16  
    17  	// "strings"
    18  	"sync"
    19  	"time"
    20  
    21  	evtActor "github.com/ontio/ontology-eventbus/actor"
    22  	comm "github.com/sixexorg/magnetic-ring/common"
    23  	"github.com/sixexorg/magnetic-ring/config"
    24  	"github.com/sixexorg/magnetic-ring/core/mainchain/types"
    25  	"github.com/sixexorg/magnetic-ring/log"
    26  	ledger "github.com/sixexorg/magnetic-ring/store/mainchain/storages"
    27  
    28  	// orgtypes "github.com/sixexorg/magnetic-ring/core/orgchain/types"
    29  	"github.com/ethereum/go-ethereum/crypto"
    30  	"github.com/sixexorg/magnetic-ring/p2pserver/common"
    31  	msgpack "github.com/sixexorg/magnetic-ring/p2pserver/message"
    32  	"github.com/sixexorg/magnetic-ring/p2pserver/net/netserver"
    33  	p2pnet "github.com/sixexorg/magnetic-ring/p2pserver/net/protocol"
    34  	"github.com/sixexorg/magnetic-ring/p2pserver/peer"
    35  	utils "github.com/sixexorg/magnetic-ring/p2pserver/sync"
    36  
    37  	// table
    38  	"github.com/sixexorg/magnetic-ring/p2pserver/discover"
    39  	"github.com/sixexorg/magnetic-ring/p2pserver/spcnode"
    40  
    41  	// org
    42  
    43  	"fmt"
    44  
    45  	mainsync "github.com/sixexorg/magnetic-ring/p2pserver/sync/main"
    46  	"github.com/sixexorg/magnetic-ring/p2pserver/temp"
    47  )
    48  
    49  type recentData struct {
    50  	addr    string
    51  	nodestr string
    52  }
    53  
    54  //P2PServer control all network activities
    55  type P2PServer struct {
    56  	network   p2pnet.P2P
    57  	msgRouter *utils.MessageRouter
    58  	pid       *evtActor.PID
    59  	blockSync *mainsync.BlockSyncMgr
    60  	ledger    *ledger.LedgerStoreImp
    61  	ReconnectAddrs
    62  	quitSyncRecent chan bool
    63  	quitOnline     chan bool
    64  	quitHeartBeat  chan bool
    65  	quitCheckConn  chan bool
    66  	// table
    67  	ntab      *discover.Table
    68  	bootnodes []*discover.Node
    69  	nodeKey   *ecdsa.PrivateKey
    70  	// org
    71  	orgman   *OrgMan
    72  	nodeA    *spcnode.NodeA
    73  	nodeStar *spcnode.NodeStar
    74  }
    75  
    76  type retryPeerInfo struct {
    77  	num     int
    78  	nodestr string
    79  }
    80  
    81  //ReconnectAddrs contain addr need to reconnect
    82  type ReconnectAddrs struct {
    83  	sync.RWMutex
    84  	RetryAddrs map[string]*retryPeerInfo
    85  }
    86  
    87  //NewServer return a new p2pserver according to the pubkey
    88  func NewServer() *P2PServer {
    89  	common.InitP2PVariable()
    90  
    91  	p := &P2PServer{}
    92  	n := netserver.NewNetServer(p)
    93  
    94  	p.network = n
    95  	p.ledger = ledger.GetLedgerStore()
    96  
    97  	p.msgRouter = utils.NewMsgRouter(p.network)
    98  	p.blockSync = mainsync.NewBlockSyncMgr(p)
    99  	p.quitSyncRecent = make(chan bool)
   100  	p.quitOnline = make(chan bool)
   101  	p.quitHeartBeat = make(chan bool)
   102  	p.quitCheckConn = make(chan bool)
   103  	p.orgman = NewAddOrg()
   104  	p.nodeA = spcnode.NewNodeA(p)
   105  	p.nodeStar = spcnode.NewNodeStar(p)
   106  	return p
   107  }
   108  
   109  //GetConnectionCnt return the established connect count
   110  func (this *P2PServer) GetLedger() *ledger.LedgerStoreImp {
   111  	return this.ledger
   112  }
   113  
   114  //GetConnectionCnt return the established connect count
   115  func (this *P2PServer) GetConnectionCnt() uint32 {
   116  	return this.network.GetConnectionCnt()
   117  }
   118  
   119  func (this *P2PServer) genPrikey() error {
   120  	var (
   121  		nodeKey *ecdsa.PrivateKey
   122  		err     error
   123  	)
   124  	nodeKey, err = crypto.GenerateKey()
   125  	if err != nil {
   126  		return err
   127  	}
   128  	this.nodeKey = nodeKey
   129  
   130  	portstr := strconv.Itoa(int(config.GlobalConfig.P2PCfg.NodePort))
   131  	ntab, err := discover.ListenUDP(this.nodeKey, "0.0.0.0:"+portstr, nil, "", nil,
   132  		this.TabCallPeerConnectInfo, this.TabCallPeerOrgInfo, this.TabCallSendConnectOrg, false, comm.Address{})
   133  	if err != nil {
   134  		return err
   135  	}
   136  
   137  	this.ntab = ntab
   138  	this.bootnodes = make([]*discover.Node, 0)
   139  	// gen bootnode
   140  	for _, nodestr := range common.BootNodes {
   141  		node, err := discover.ParseNode(nodestr)
   142  		if err != nil {
   143  			return err
   144  		}
   145  		this.bootnodes = append(this.bootnodes, node)
   146  	}
   147  
   148  	if err := ntab.SetFallbackNodes(this.bootnodes); err != nil {
   149  		return err
   150  	}
   151  	// deliver prvikey to network
   152  	this.network.SetPrivateKey(this.nodeKey, this.ntab)
   153  	this.network.SetBootNodes(this.bootnodes)
   154  
   155  	return nil
   156  }
   157  
   158  //Start create all services
   159  func (this *P2PServer) Start() error {
   160  	if this.genPrikey() != nil {
   161  		return errors.New("[p2p]genPrikey invalid")
   162  	}
   163  
   164  	if this.network == nil {
   165  		return errors.New("[p2p]network invalid")
   166  	}
   167  
   168  	this.network.Start()
   169  
   170  	if this.msgRouter == nil {
   171  		return errors.New("[p2p]msg router invalid")
   172  	}
   173  
   174  	this.msgRouter.Start()
   175  
   176  	go this.connectSeedService()
   177  	go this.keepOnlineService()
   178  	go this.heartBeatService()
   179  	go this.blockSync.Start()
   180  	// NodeA
   181  	this.nodeA.Start()
   182  	// NodeStar
   183  	this.nodeStar.Start()
   184  	// for test
   185  	// go this.testOrg()
   186  	return nil
   187  }
   188  
   189  //Stop halt all service by send signal to channels
   190  func (this *P2PServer) Stop() {
   191  	this.network.Halt()
   192  	this.quitSyncRecent <- true
   193  	this.quitOnline <- true
   194  	this.quitHeartBeat <- true
   195  	this.quitCheckConn <- true
   196  	this.msgRouter.Stop()
   197  	this.blockSync.Close()
   198  	this.nodeA.Close()
   199  	this.nodeStar.Close()
   200  
   201  	this.orgman.RLock()
   202  	for _, orgsync := range this.orgman.OrgSync {
   203  		orgsync.Close()
   204  	}
   205  	this.orgman.Reset()
   206  	this.orgman.RUnlock()
   207  }
   208  
   209  // GetNetWork returns the low level netserver
   210  func (this *P2PServer) GetNetWork() p2pnet.P2P {
   211  	return this.network
   212  }
   213  
   214  //GetPort return two network port
   215  func (this *P2PServer) GetPort() (uint16, uint16) {
   216  	return this.network.GetSyncPort(), this.network.GetConsPort()
   217  }
   218  
   219  //GetVersion return self version
   220  func (this *P2PServer) GetVersion() uint32 {
   221  	return this.network.GetVersion()
   222  }
   223  
   224  //GetNeighborAddrs return all nbr`s address
   225  func (this *P2PServer) GetNeighborAddrs() []common.PeerAddr {
   226  	return this.network.GetNeighborAddrs()
   227  }
   228  
   229  //Xmit called by other module to broadcast msg
   230  func (this *P2PServer) Xmit(message interface{}) error {
   231  	log.Debug("[p2p] Xmit Start...")
   232  	var msg common.Message
   233  	isConsensus := false
   234  	switch message.(type) {
   235  	case *types.Transaction: //
   236  		log.Debug("[p2p]TX transaction message ••••••••••••••••")
   237  		txn := message.(*types.Transaction)
   238  		msg = msgpack.NewTxn(txn, nil, comm.Address{}, common.SYNC_DATA_MAIN)
   239  
   240  
   241  	case *common.OrgTx: //
   242  		log.Debug("[p2p]TX transaction message")
   243  		orgtx := message.(*common.OrgTx)
   244  		txn := orgtx.Tx
   245  		msg = msgpack.NewTxn(nil, txn, comm.Address{}, common.SYNC_DATA_ORG)
   246  
   247  	case *types.Block: // sync bblock //
   248  		log.Debug("[p2p]TX block message")
   249  		block := message.(*types.Block)
   250  		msg = msgpack.NewBlock(block, nil, comm.Address{}, common.SYNC_DATA_MAIN)
   251  	case *common.ConsensusPayload:
   252  		log.Debug("[p2p]TX consensus message")
   253  		consensusPayload := message.(*common.ConsensusPayload)
   254  		msg = msgpack.NewConsensus(consensusPayload)
   255  		isConsensus = true
   256  
   257  	case *common.NotifyBlk:
   258  		//return nil
   259  		blkntf := message.(*common.NotifyBlk)
   260  		//time.Sleep(time.Millisecond*500)
   261  
   262  		log.Info("[p2p]TX block hash message unique", "hash", blkntf)
   263  
   264  		// construct inv message
   265  		invPayload := msgpack.NewInvPayload(comm.BLOCK, []comm.Hash{blkntf.BlkHash}, []uint64{blkntf.BlkHeight})
   266  
   267  		msg = msgpack.NewInv(invPayload)
   268  	case *common.EarthNotifyBlk:
   269  		ntf := message.(*common.EarthNotifyBlk)
   270  
   271  		msg = msgpack.NewEarthNotifyHash(ntf)
   272  	case *comm.NodeLH:
   273  		fmt.Println("🌐 📩  p2p receive nodeLH")
   274  		nodeLH := message.(*comm.NodeLH)
   275  		msg = msgpack.NewNodeLHMsg(nodeLH)
   276  	case *common.ExtDataRequest:
   277  		fmt.Println("🌐 📩  p2p extData requtst")
   278  		extData := message.(*common.ExtDataRequest)
   279  		msg  = msgpack.NewExtDataRequestMsg(extData)
   280  	default:
   281  		log.Info("[p2p]Unknown Xmit ", "message", message, "type", reflect.TypeOf(message))
   282  		return errors.New("[p2p]Unknown Xmit message type")
   283  	}
   284  	this.network.Xmit(msg, isConsensus)
   285  	return nil
   286  }
   287  
   288  //Send tranfer buffer to peer
   289  func (this *P2PServer) Send(p *peer.Peer, msg common.Message,
   290  	isConsensus bool) error {
   291  	if this.network.IsPeerEstablished(p) {
   292  		return this.network.Send(p, msg, isConsensus)
   293  	}
   294  	log.Warn("[p2p]send to a not ESTABLISH ", "peerid", p.GetID())
   295  	return errors.New("[p2p]send to a not ESTABLISH peer")
   296  }
   297  
   298  // GetID returns local node id
   299  func (this *P2PServer) GetID() uint64 {
   300  	return this.network.GetID()
   301  }
   302  
   303  // OnAddNode adds the peer id to the block sync mgr
   304  func (this *P2PServer) SetSyncStatus(status bool,lockHeight uint64) {
   305  	this.blockSync.SetSyncStatus(status,lockHeight)
   306  }
   307  
   308  // OnAddNode adds the peer id to the block sync mgr
   309  func (this *P2PServer) OnAddNode(id uint64) {
   310  	this.blockSync.OnAddNode(id)
   311  }
   312  
   313  // OnDelNode removes the peer id from the block sync mgr
   314  func (this *P2PServer) OnDelNode(id uint64) {
   315  	this.blockSync.OnDelNode(id)
   316  }
   317  
   318  // OnHeaderReceive adds the header list from network
   319  func (this *P2PServer) OnHeaderReceive(fromID uint64, headers []*types.Header) {
   320  	this.blockSync.OnHeaderReceive(fromID, headers)
   321  }
   322  
   323  // OnBlockReceive adds the block from network
   324  func (this *P2PServer) OnBlockReceive(fromID uint64, blockSize uint32, block *types.Block) {
   325  	this.blockSync.OnBlockReceive(fromID, blockSize, block)
   326  }
   327  
   328  // Todo: remove it if no use
   329  func (this *P2PServer) GetConnectionState() uint32 {
   330  	return common.INIT
   331  }
   332  
   333  //GetTime return lastet contact time
   334  func (this *P2PServer) GetTime() int64 {
   335  	return this.network.GetTime()
   336  }
   337  
   338  // SetPID sets p2p actor
   339  func (this *P2PServer) SetPID(pid *evtActor.PID) {
   340  	this.pid = pid
   341  	this.msgRouter.SetPID(pid)
   342  }
   343  
   344  // GetPID returns p2p actor
   345  func (this *P2PServer) GetPID() *evtActor.PID {
   346  	return this.pid
   347  }
   348  
   349  //blockSyncFinished compare all nbr peers and self height at beginning
   350  func (this *P2PServer) blockSyncFinished() bool {
   351  	peers := this.network.GetNeighbors()
   352  	if len(peers) == 0 {
   353  		return false
   354  	}
   355  
   356  	blockHeight := this.ledger.GetCurrentBlockHeight()
   357  
   358  	for _, v := range peers {
   359  		if blockHeight < v.GetHeight() {
   360  			return false
   361  		}
   362  	}
   363  	return true
   364  }
   365  
   366  //WaitForSyncBlkFinish compare the height of self and remote peer in loop
   367  func (this *P2PServer) WaitForSyncBlkFinish() {
   368  	for {
   369  		headerHeight := this.ledger.GetCurrentHeaderHeight()
   370  		currentBlkHeight := this.ledger.GetCurrentBlockHeight()
   371  		log.Info("[p2p]WaitForSyncBlkFinish... current block height is ", "currentBlkHeight",
   372  			currentBlkHeight, " ,current header height is ", headerHeight)
   373  
   374  		if this.blockSyncFinished() {
   375  			break
   376  		}
   377  
   378  		<-time.After(time.Second * (time.Duration(common.SYNC_BLK_WAIT)))
   379  	}
   380  }
   381  
   382  //WaitForPeersStart check whether enough peer linked in loop
   383  func (this *P2PServer) WaitForPeersStart() {
   384  	periodTime := common.DEFAULT_GEN_BLOCK_TIME / common.UPDATE_RATE_PER_BLOCK
   385  	for {
   386  		log.Info("[p2p]Wait for minimum connection...")
   387  		if this.ReachMinConnection() {
   388  			break
   389  		}
   390  
   391  		<-time.After(time.Second * (time.Duration(periodTime)))
   392  	}
   393  }
   394  
   395  func (this *P2PServer) getRandList() map[string]*discover.Node {
   396  	nodes := make([]*discover.Node, 5)
   397  	num := this.ntab.ReadRandomNodes(nodes)
   398  	lennode := len(nodes)
   399  	seedNodes := make(map[string]*discover.Node)
   400  
   401  	bootmap := make(map[discover.NodeID]bool)
   402  	for _, node := range this.bootnodes {
   403  		bootmap[node.ID] = true
   404  	}
   405  
   406  	for i := 0; i < num && i < lennode; i++ {
   407  		if nodes[i] == nil {
   408  			continue
   409  		}
   410  		if ok := bootmap[nodes[i].ID]; !ok {
   411  			addr := &net.TCPAddr{IP: nodes[i].IP, Port: int(nodes[i].TCP)}
   412  			seedNodes[addr.String()] = nodes[i]
   413  		}
   414  	}
   415  	return seedNodes
   416  }
   417  
   418  //connectSeeds connect the seeds in seedlist and call for nbr list
   419  func (this *P2PServer) connectSeeds() {
   420  	seedNodes := make(map[string]*discover.Node)
   421  	pList := make([]*peer.Peer, 0)
   422  
   423  	seedNodes = this.getRandList()
   424  
   425  	for nodeAddr, _ := range seedNodes {
   426  		var ip net.IP
   427  		np := this.network.GetNp()
   428  		np.Lock()
   429  		for _, tn := range np.List {
   430  			ipAddr, _ := tn.GetAddr16()
   431  			ip = ipAddr[:]
   432  			addrString := ip.To16().String() + ":" +
   433  				strconv.Itoa(int(tn.GetSyncPort()))
   434  			if nodeAddr == addrString && tn.GetSyncState() == common.ESTABLISH {
   435  				pList = append(pList, tn)
   436  			}
   437  		}
   438  		np.Unlock()
   439  	}
   440  	if len(pList) > 0 {
   441  		rand.Seed(time.Now().UnixNano())
   442  		index := rand.Intn(len(pList))
   443  		this.reqNbrList(pList[index])
   444  	} else { //not found
   445  		for nodeAddr, node := range seedNodes {
   446  			go this.network.Connect(nodeAddr, false, node, false)
   447  		}
   448  	}
   449  }
   450  
   451  //reachMinConnection return whether net layer have enough link under different config
   452  func (this *P2PServer) ReachMinConnection() bool {
   453  	// consensusType := strings.ToLower(config.DefConfig.Genesis.ConsensusType)
   454  	// if consensusType == "" {
   455  	// 	consensusType = "dbft"
   456  	// }
   457  	// minCount := config.DBFT_MIN_NODE_NUM
   458  	// switch consensusType {
   459  	// case "dbft":
   460  	// case "solo":
   461  	// 	minCount = config.SOLO_MIN_NODE_NUM
   462  	// case "vbft":
   463  	// 	minCount = config.VBFT_MIN_NODE_NUM
   464  
   465  	// }
   466  	// for test
   467  	minCount := 2
   468  	return int(this.GetConnectionCnt())+1 >= minCount
   469  }
   470  
   471  //getNode returns the peer with the id
   472  func (this *P2PServer) GetNode(id uint64) *peer.Peer {
   473  	return this.network.GetPeer(id)
   474  }
   475  
   476  //getNode returns the peer with the id
   477  func (this *P2PServer) GetNodeFromDiscoverID(discoverNodeID string) *peer.Peer {
   478  	return this.network.GetNp().GetPeerFromDiscoverNodeId(discoverNodeID)
   479  }
   480  
   481  //retryInactivePeer try to connect peer in INACTIVITY state
   482  func (this *P2PServer) retryInactivePeer() {
   483  	np := this.network.GetNp()
   484  	np.Lock()
   485  	var ip net.IP
   486  	neighborPeers := make(map[uint64]*peer.Peer)
   487  	for _, p := range np.List {
   488  		addr, _ := p.GetAddr16()
   489  		ip = addr[:]
   490  		nodeAddr := ip.To16().String() + ":" +
   491  			strconv.Itoa(int(p.GetSyncPort()))
   492  		if p.GetSyncState() == common.INACTIVITY {
   493  			log.Debug("[p2p] try reconnect", "nodeAddr", nodeAddr)
   494  			//add addr to retry list
   495  			this.addToRetryList(nodeAddr, p.GetNode())
   496  			p.CloseSync()
   497  			p.CloseCons()
   498  		} else {
   499  			//add others to tmp node map
   500  			this.removeFromRetryList(nodeAddr)
   501  			neighborPeers[p.GetID()] = p
   502  		}
   503  	}
   504  
   505  	np.List = neighborPeers
   506  	np.Unlock()
   507  
   508  	connCount := uint(this.network.GetOutConnRecordLen())
   509  	if connCount >= config.GlobalConfig.P2PCfg.MaxConnOutBound {
   510  		log.Warn("[p2p]Connect: out connections", "connCount", connCount,
   511  			"reach the max limit", config.GlobalConfig.P2PCfg.MaxConnOutBound)
   512  		return
   513  	}
   514  
   515  	//try connect
   516  	if len(this.RetryAddrs) > 0 {
   517  		this.ReconnectAddrs.Lock()
   518  
   519  		list := make(map[string]*retryPeerInfo)
   520  		addrs := make([]string, 0, len(this.RetryAddrs))
   521  		nodestr := make([]string, 0, len(this.RetryAddrs))
   522  		for addr, v := range this.RetryAddrs {
   523  			v.num += 1
   524  			addrs = append(addrs, addr)
   525  			nodestr = append(nodestr, v.nodestr)
   526  			if v.num < common.MAX_RETRY_COUNT {
   527  				list[addr] = v
   528  			}
   529  			if v.num >= common.MAX_RETRY_COUNT {
   530  				this.network.RemoveFromConnectingList(addr)
   531  				remotePeer := this.network.GetPeerFromAddr(addr)
   532  				if remotePeer != nil {
   533  					if remotePeer.SyncLink.GetAddr() == addr {
   534  						this.network.RemovePeerSyncAddress(addr)
   535  						this.network.RemovePeerConsAddress(addr)
   536  					}
   537  					if remotePeer.ConsLink.GetAddr() == addr {
   538  						this.network.RemovePeerConsAddress(addr)
   539  					}
   540  					this.network.DelNbrNode(remotePeer.GetID())
   541  				}
   542  			}
   543  		}
   544  
   545  		this.RetryAddrs = list
   546  		this.ReconnectAddrs.Unlock()
   547  		for index, addr := range addrs {
   548  			rand.Seed(time.Now().UnixNano())
   549  			log.Debug("[p2p]Try to reconnect peer, peer addr is ", "addr", addr)
   550  			<-time.After(time.Duration(rand.Intn(common.CONN_MAX_BACK)) * time.Millisecond)
   551  			log.Debug("[p2p]Back off time`s up, start connect node")
   552  			if index < len(nodestr) && index >= 0 {
   553  				temnode, err := discover.ParseNode(nodestr[index])
   554  				if err != nil {
   555  					continue
   556  				}
   557  				this.network.Connect(addr, false, temnode, false)
   558  			}
   559  		}
   560  
   561  	}
   562  }
   563  
   564  //connectSeedService make sure seed peer be connected
   565  func (this *P2PServer) connectSeedService() {
   566  	t := time.NewTimer(time.Second * common.CONN_MONITOR)
   567  	for {
   568  		select {
   569  		case <-t.C:
   570  			this.connectSeeds()
   571  			t.Stop()
   572  			if this.ReachMinConnection() {
   573  				t.Reset(time.Second * time.Duration(10*common.CONN_MONITOR))
   574  			} else {
   575  				t.Reset(time.Second * common.CONN_MONITOR)
   576  			}
   577  		case <-this.quitOnline:
   578  			t.Stop()
   579  			break
   580  		}
   581  	}
   582  }
   583  
   584  //keepOnline try connect lost peer
   585  func (this *P2PServer) keepOnlineService() {
   586  	t := time.NewTimer(time.Second * common.CONN_MONITOR)
   587  	for {
   588  		select {
   589  		case <-t.C:
   590  			this.retryInactivePeer()
   591  			t.Stop()
   592  			t.Reset(time.Second * common.CONN_MONITOR)
   593  		case <-this.quitOnline:
   594  			t.Stop()
   595  			break
   596  		}
   597  	}
   598  }
   599  
   600  //reqNbrList ask the peer for its neighbor list
   601  func (this *P2PServer) reqNbrList(p *peer.Peer) {
   602  	msg := msgpack.NewAddrReq()
   603  	go this.Send(p, msg, false)
   604  }
   605  
   606  //heartBeat send ping to nbr peers and check the timeout
   607  func (this *P2PServer) heartBeatService() {
   608  	var periodTime uint
   609  	periodTime = common.DEFAULT_GEN_BLOCK_TIME / common.UPDATE_RATE_PER_BLOCK
   610  	t := time.NewTicker(time.Second * (time.Duration(periodTime)))
   611  
   612  	for {
   613  		select {
   614  		case <-t.C:
   615  			this.ping()
   616  			this.timeout()
   617  		case <-this.quitHeartBeat:
   618  			t.Stop()
   619  			break
   620  		}
   621  	}
   622  }
   623  
   624  //ping send pkg to get pong msg from others
   625  func (this *P2PServer) ping() {
   626  
   627  	peers := this.network.GetNeighbors()
   628  	fmt.Println("==========>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", time.Now().String(), "len(peers):",len(peers))
   629  	this.PingTo(peers, true)
   630  }
   631  
   632  // pings send pkgs to get pong msg from others
   633  // add org and StellarNode need call this func
   634  func (this *P2PServer) PingTo(peers []*peer.Peer, bTimer bool, orgID ...comm.Address) {
   635  	for _, p := range peers {
   636  		fmt.Println("P2PServerPingTo out",  "time", time.Now().String(), "GetSyncState", p.GetSyncState())
   637  		log.Info("P2PServerPingTo out",  "time", time.Now().String(), "GetSyncState", p.GetSyncState())
   638  		if p.GetSyncState() == common.ESTABLISH {
   639  			if bTimer {
   640  				height := this.ledger.GetCurrentBlockHeight()
   641  				//
   642  				orgs := this.network.PeerGetOrg()
   643  				orgpings := this.getOrgInfo(orgs)
   644  				ping := msgpack.NewPingMsg(uint64(height), orgpings, common.PING_INFO_ALL)
   645  				log.Info("P2PServerPingTo", "height", height, "time", time.Now().String())
   646  				go this.Send(p, ping, false)
   647  			} else {
   648  				if len(orgID) <= 0 { // main
   649  					height := this.ledger.GetCurrentBlockHeight()
   650  					ping := msgpack.NewPingMsg(uint64(height), nil, common.PING_INFO_MAIN)
   651  					go this.Send(p, ping, false)
   652  				} else {
   653  					orgs := []comm.Address{orgID[0]}
   654  					orgpings := this.getOrgInfo(orgs)
   655  					ping := msgpack.NewPingMsg(uint64(0), orgpings, common.PING_INFO_ORG)
   656  					go this.Send(p, ping, false)
   657  				}
   658  			}
   659  		}
   660  	}
   661  }
   662  
   663  func (this *P2PServer) getOrgInfo(orgIDArr []comm.Address) []*common.OrgPIPOInfo {
   664  	result := make([]*common.OrgPIPOInfo, 0)
   665  	for _, id := range orgIDArr {
   666  		if id == common.StellarNodeID { //
   667  			result = append(result, msgpack.NewOrgPIPOMsg(id, uint64(0)))
   668  		} else {
   669  			// SFC,
   670  			//height := this.ledger.GetCurrentBlockHeight(/*id*/)
   671  			orgLedger := temp.GetLedger(id)
   672  			if orgLedger == nil {
   673  				continue
   674  			}
   675  			height := orgLedger.GetCurrentBlockHeight( /*id*/ )
   676  			result = append(result, msgpack.NewOrgPIPOMsg(id, uint64(height)))
   677  		}
   678  	}
   679  	return result
   680  }
   681  
   682  //timeout trace whether some peer be long time no response
   683  func (this *P2PServer) timeout() {
   684  	peers := this.network.GetNeighbors()
   685  	var periodTime uint
   686  	periodTime = common.DEFAULT_GEN_BLOCK_TIME / common.UPDATE_RATE_PER_BLOCK
   687  	for _, p := range peers {
   688  		if p.GetSyncState() == common.ESTABLISH {
   689  			t := p.GetContactTime()
   690  			if t.Before(time.Now().Add(-1 * time.Second *
   691  				time.Duration(periodTime) * common.KEEPALIVE_TIMEOUT)) {
   692  				log.Warn("[p2p]keep alive timeout!!!lost remote", "peer", p.GetID(), "Addr", p.SyncLink.GetAddr(), "Addr", t.String())
   693  				p.CloseSync()
   694  				p.CloseCons()
   695  			}
   696  		}
   697  	}
   698  }
   699  
   700  //addToRetryList add retry address to ReconnectAddrs
   701  func (this *P2PServer) addToRetryList(addr string, node *discover.Node) {
   702  	this.ReconnectAddrs.Lock()
   703  	defer this.ReconnectAddrs.Unlock()
   704  	if this.RetryAddrs == nil {
   705  		this.RetryAddrs = make(map[string]*retryPeerInfo)
   706  	}
   707  	if _, ok := this.RetryAddrs[addr]; ok {
   708  		delete(this.RetryAddrs, addr)
   709  	}
   710  	//alway set retry to 0
   711  	this.RetryAddrs[addr] = &retryPeerInfo{
   712  		num:     0,
   713  		nodestr: node.String(),
   714  	}
   715  }
   716  
   717  //removeFromRetryList remove connected address from ReconnectAddrs
   718  func (this *P2PServer) removeFromRetryList(addr string) {
   719  	this.ReconnectAddrs.Lock()
   720  	defer this.ReconnectAddrs.Unlock()
   721  	if len(this.RetryAddrs) > 0 {
   722  		if _, ok := this.RetryAddrs[addr]; ok {
   723  			delete(this.RetryAddrs, addr)
   724  		}
   725  	}
   726  }