github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/netsync/protocol_reactor.go (about)

     1  package netsync
     2  
     3  import (
     4  	"time"
     5  
     6  	log "github.com/sirupsen/logrus"
     7  
     8  	"github.com/bytom/bytom/errors"
     9  	"github.com/bytom/bytom/p2p"
    10  	"github.com/bytom/bytom/p2p/connection"
    11  )
    12  
    13  const (
    14  	handshakeTimeout    = 10 * time.Second
    15  	handshakeCheckPerid = 500 * time.Millisecond
    16  )
    17  
    18  var (
    19  	errProtocolHandshakeTimeout = errors.New("Protocol handshake timeout")
    20  	errStatusRequest            = errors.New("Status request error")
    21  )
    22  
    23  //ProtocolReactor handles new coming protocol message.
    24  type ProtocolReactor struct {
    25  	p2p.BaseReactor
    26  
    27  	sm    *SyncManager
    28  	peers *peerSet
    29  }
    30  
    31  // NewProtocolReactor returns the reactor of whole blockchain.
    32  func NewProtocolReactor(sm *SyncManager, peers *peerSet) *ProtocolReactor {
    33  	pr := &ProtocolReactor{
    34  		sm:    sm,
    35  		peers: peers,
    36  	}
    37  	pr.BaseReactor = *p2p.NewBaseReactor("ProtocolReactor", pr)
    38  	return pr
    39  }
    40  
    41  // GetChannels implements Reactor
    42  func (pr *ProtocolReactor) GetChannels() []*connection.ChannelDescriptor {
    43  	return []*connection.ChannelDescriptor{
    44  		{
    45  			ID:                BlockchainChannel,
    46  			Priority:          5,
    47  			SendQueueCapacity: 100,
    48  		},
    49  	}
    50  }
    51  
    52  // OnStart implements BaseService
    53  func (pr *ProtocolReactor) OnStart() error {
    54  	pr.BaseReactor.OnStart()
    55  	return nil
    56  }
    57  
    58  // OnStop implements BaseService
    59  func (pr *ProtocolReactor) OnStop() {
    60  	pr.BaseReactor.OnStop()
    61  }
    62  
    63  // AddPeer implements Reactor by sending our state to peer.
    64  func (pr *ProtocolReactor) AddPeer(peer *p2p.Peer) error {
    65  	if ok := peer.TrySend(BlockchainChannel, struct{ BlockchainMessage }{&StatusRequestMessage{}}); !ok {
    66  		return errStatusRequest
    67  	}
    68  
    69  	checkTicker := time.NewTicker(handshakeCheckPerid)
    70  	defer checkTicker.Stop()
    71  	timeout := time.NewTimer(handshakeTimeout)
    72  	defer timeout.Stop()
    73  	for {
    74  		select {
    75  		case <-checkTicker.C:
    76  			if exist := pr.peers.getPeer(peer.Key); exist != nil {
    77  				pr.sm.syncTransactions(peer.Key)
    78  				return nil
    79  			}
    80  
    81  		case <-timeout.C:
    82  			return errProtocolHandshakeTimeout
    83  		}
    84  	}
    85  }
    86  
    87  // RemovePeer implements Reactor by removing peer from the pool.
    88  func (pr *ProtocolReactor) RemovePeer(peer *p2p.Peer, reason interface{}) {
    89  	pr.peers.removePeer(peer.Key)
    90  }
    91  
    92  // Receive implements Reactor by handling 4 types of messages (look below).
    93  func (pr *ProtocolReactor) Receive(chID byte, src *p2p.Peer, msgBytes []byte) {
    94  	msgType, msg, err := DecodeMessage(msgBytes)
    95  	if err != nil {
    96  		log.WithFields(log.Fields{"module": logModule, "err": err}).Error("fail on reactor decoding message")
    97  		return
    98  	}
    99  
   100  	pr.sm.processMsg(src, msgType, msg)
   101  }