github.com/aergoio/aergo@v1.3.1/p2p/ancestorreceiver.go (about)

     1  /*
     2   * @file
     3   * @copyright defined in aergo/LICENSE.txt
     4   */
     5  
     6  package p2p
     7  
     8  import (
     9  	"github.com/aergoio/aergo/message"
    10  	"github.com/aergoio/aergo/p2p/p2pcommon"
    11  	"github.com/aergoio/aergo/types"
    12  	"time"
    13  )
    14  
    15  // BlocksChunkReceiver is send p2p getBlocksRequest to target peer and receive p2p responses till all requests blocks are received
    16  // It will send response actor message if all blocks are received or failed to receive, but not send response if timeout expired.
    17  type AncestorReceiver struct {
    18  	syncerSeq uint64
    19  	requestID p2pcommon.MsgID
    20  
    21  	peer  p2pcommon.RemotePeer
    22  	actor p2pcommon.ActorService
    23  
    24  	hashes  [][]byte
    25  	timeout  time.Time
    26  	finished bool
    27  }
    28  
    29  func NewAncestorReceiver(actor p2pcommon.ActorService, peer p2pcommon.RemotePeer, seq uint64, hashes [][]byte, ttl time.Duration) *AncestorReceiver {
    30  	timeout := time.Now().Add(ttl)
    31  	return &AncestorReceiver{syncerSeq: seq, actor: actor, peer: peer, hashes: hashes, timeout: timeout}
    32  }
    33  
    34  func (br *AncestorReceiver) StartGet() {
    35  	// create message data
    36  	req := &types.GetAncestorRequest{Hashes: br.hashes}
    37  	mo := br.peer.MF().NewMsgBlockRequestOrder(br.ReceiveResp, p2pcommon.GetAncestorRequest, req)
    38  	br.requestID = mo.GetMsgID()
    39  	br.peer.SendMessage(mo)
    40  }
    41  
    42  // ReceiveResp must be called just in read go routine
    43  func (br *AncestorReceiver) ReceiveResp(msg p2pcommon.Message, msgBody p2pcommon.MessageBody) (ret bool) {
    44  	ret = true
    45  	// timeout
    46  	if br.finished || br.timeout.Before(time.Now()) {
    47  		br.finished = true
    48  		br.peer.ConsumeRequest(br.requestID)
    49  		return
    50  	}
    51  	// remote peer response failure
    52  	data := msgBody.(*types.GetAncestorResponse)
    53  	if data.Status != types.ResultStatus_OK {
    54  		br.actor.TellRequest(message.SyncerSvc, &message.GetSyncAncestorRsp{Seq:br.syncerSeq, Ancestor: nil})
    55  		br.finished = true
    56  		br.peer.ConsumeRequest(br.requestID)
    57  		return
    58  	}
    59  	ancestor := &types.BlockInfo{Hash: data.AncestorHash, No: data.AncestorNo}
    60  
    61  	br.actor.TellRequest(message.SyncerSvc, &message.GetSyncAncestorRsp{Seq:br.syncerSeq, Ancestor: ancestor})
    62  	br.finished = true
    63  	br.peer.ConsumeRequest(br.requestID)
    64  	return
    65  }