github.com/turingchain2020/turingchain@v1.1.21/system/p2p/dht/protocol/download/download.go (about) 1 package download 2 3 import ( 4 "context" 5 "errors" 6 "time" 7 8 "github.com/turingchain2020/turingchain/common/log/log15" 9 "github.com/turingchain2020/turingchain/system/p2p/dht/protocol" 10 "github.com/turingchain2020/turingchain/types" 11 "github.com/libp2p/go-libp2p-core/peer" 12 ) 13 14 var ( 15 log = log15.New("module", "p2p.download") 16 ) 17 18 func init() { 19 protocol.RegisterProtocolInitializer(InitProtocol) 20 } 21 22 const ( 23 // Deprecated: old version, use downloadBlock instead 24 downloadBlockOld = "/turingchain/downloadBlockReq/1.0.0" 25 downloadBlock = "/turingchain/download-block/1.0.0" 26 ) 27 28 // Protocol ... 29 type Protocol struct { 30 *protocol.P2PEnv 31 } 32 33 // InitProtocol initials protocol 34 func InitProtocol(env *protocol.P2PEnv) { 35 p := &Protocol{ 36 P2PEnv: env, 37 } 38 //注册p2p通信协议,用于处理节点之间请求 39 protocol.RegisterStreamHandler(p.Host, downloadBlockOld, p.handleStreamDownloadBlockOld) 40 protocol.RegisterStreamHandler(p.Host, downloadBlock, p.handleStreamDownloadBlock) 41 //注册事件处理函数 42 protocol.RegisterEventHandler(types.EventFetchBlocks, p.handleEventDownloadBlock) 43 44 } 45 46 func (p *Protocol) downloadBlock(height int64, tasks tasks) error { 47 48 var retryCount uint 49 tasks.Sort() //对任务节点时延进行排序,优先选择时延低的节点进行下载 50 ReDownload: 51 select { 52 case <-p.Ctx.Done(): 53 log.Warn("downloadBlock", "process", "done") 54 return p.Ctx.Err() 55 default: 56 break 57 } 58 59 if tasks.Size() == 0 { 60 return errors.New("no peer for download") 61 } 62 63 retryCount++ 64 if retryCount > 50 { 65 return errors.New("beyound max try count 50") 66 } 67 68 task := p.availbTask(tasks, height) 69 if task == nil { 70 time.Sleep(time.Millisecond * 400) 71 goto ReDownload 72 } 73 74 var downloadStart = time.Now().UnixNano() 75 block, err := p.downloadBlockFromPeerOld(height, task.Pid) 76 if err != nil { 77 log.Error("handleEventDownloadBlock", "SendRecvPeer", err, "pid", task.Pid) 78 p.releaseJob(task) 79 tasks = tasks.Remove(task) 80 goto ReDownload 81 } 82 remotePid := task.Pid.Pretty() 83 costTime := (time.Now().UnixNano() - downloadStart) / 1e6 84 85 log.Debug("download+++++", "from", remotePid, "height", block.GetHeight(), 86 "blockSize (bytes)", block.Size(), "costTime ms", costTime) 87 88 msg := p.QueueClient.NewMessage("blockchain", types.EventSyncBlock, &types.BlockPid{Pid: remotePid, Block: block}) //加入到输出通道) 89 _ = p.QueueClient.Send(msg, false) 90 p.releaseJob(task) 91 92 return nil 93 } 94 95 func (p *Protocol) downloadBlockFromPeer(height int64, pid peer.ID) (*types.Block, error) { 96 ctx, cancel := context.WithTimeout(p.Ctx, time.Second*10) 97 defer cancel() 98 stream, err := p.Host.NewStream(ctx, pid, downloadBlock) 99 if err != nil { 100 return nil, err 101 } 102 defer protocol.CloseStream(stream) 103 blockReq := &types.ReqBlocks{Start: height, End: height} 104 err = protocol.WriteStream(blockReq, stream) 105 if err != nil { 106 return nil, err 107 } 108 var block types.Block 109 err = protocol.ReadStream(&block, stream) 110 if err != nil { 111 return nil, err 112 } 113 return &block, nil 114 } 115 116 func (p *Protocol) downloadBlockFromPeerOld(height int64, pid peer.ID) (*types.Block, error) { 117 ctx, cancel := context.WithTimeout(p.Ctx, time.Second*10) 118 defer cancel() 119 stream, err := p.Host.NewStream(ctx, pid, downloadBlockOld) 120 if err != nil { 121 return nil, err 122 } 123 defer protocol.CloseStream(stream) 124 blockReq := types.MessageGetBlocksReq{ 125 Message: &types.P2PGetBlocks{ 126 StartHeight: height, 127 EndHeight: height, 128 }, 129 } 130 err = protocol.WriteStream(&blockReq, stream) 131 if err != nil { 132 return nil, err 133 } 134 var resp types.MessageGetBlocksResp 135 err = protocol.ReadStream(&resp, stream) 136 if err != nil { 137 return nil, err 138 } 139 block := resp.Message.Items[0].Value.(*types.InvData_Block).Block 140 return block, nil 141 }