mirror of
https://github.com/PeernetOfficial/core.git
synced 2026-07-17 02:47:51 +01:00
131 lines
3.5 KiB
Go
131 lines
3.5 KiB
Go
/*
|
|
File Name: Download.go
|
|
Copyright: 2021 Peernet Foundation s.r.o.
|
|
Author: Peter Kleissner
|
|
*/
|
|
|
|
package webapi
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"github.com/PeernetOfficial/core/blockchain"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type hostInfo struct {
|
|
api *WebapiInstance
|
|
info *downloadInfo
|
|
filepath string
|
|
}
|
|
|
|
/*
|
|
apiCloneFile starts the download of a file, adds it the current warehouse and adds it
|
|
to your blockchain. The path is the full path on disk to store the file.
|
|
The hash parameter identifies the file to download. The node ID identifies the blockchain (i.e., the "owner" of the file).
|
|
|
|
The following is a prototype implementation
|
|
|
|
Request: GET /follow/file?path=[target path on disk]&hash=[file hash to download]&node=[node ID]
|
|
Result: 200 with JSON structure apiResponseDownloadStatus
|
|
*/
|
|
func (api *WebapiInstance) apiHostFile(w http.ResponseWriter, r *http.Request) {
|
|
r.ParseForm()
|
|
|
|
// validate hashes, must be blake3
|
|
hash, valid1 := DecodeBlake3Hash(r.Form.Get("hash"))
|
|
nodeID, valid2 := DecodeBlake3Hash(r.Form.Get("node"))
|
|
if !valid1 || !valid2 {
|
|
http.Error(w, "node ID or hash not valid", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
filePath := r.Form.Get("path")
|
|
if filePath == "" {
|
|
http.Error(w, "file path provided is blank", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
info := &downloadInfo{backend: api.backend, api: api, id: uuid.New(), created: time.Now(), hash: hash, nodeID: nodeID}
|
|
|
|
// create the file immediately
|
|
if info.initDiskFile(filePath) != nil {
|
|
EncodeJSON(api.backend, w, r, apiResponseDownloadStatus{APIStatus: DownloadResponseFileInvalid})
|
|
return
|
|
}
|
|
|
|
// add the download to the list
|
|
api.downloadAdd(info)
|
|
|
|
// Setting host information
|
|
var HostInfo hostInfo
|
|
HostInfo.api = api
|
|
HostInfo.info = info
|
|
HostInfo.filepath = filePath
|
|
|
|
// start the download!
|
|
go HostInfo.StartHostDownload()
|
|
|
|
EncodeJSON(api.backend, w, r, apiResponseDownloadStatus{APIStatus: DownloadResponseSuccess, ID: info.id, DownloadStatus: DownloadWaitMetadata})
|
|
}
|
|
|
|
// StartHostDownload Starts the download, adds the downloaded file to the warehouse and then the following file is added to the user blockchain
|
|
func (info *hostInfo) StartHostDownload() error {
|
|
// current user?
|
|
if bytes.Equal(info.info.nodeID, info.info.backend.SelfNodeID()) {
|
|
info.info.DownloadSelf()
|
|
return nil
|
|
}
|
|
|
|
for n := 0; n < 3 && info.info.peer == nil; n++ {
|
|
_, info.info.peer, _ = info.info.backend.FindNode(info.info.nodeID, time.Second*5)
|
|
|
|
if info.info.status == DownloadCanceled {
|
|
return errors.New("DownloadCanceled")
|
|
}
|
|
}
|
|
|
|
if info.info.peer != nil {
|
|
info.info.Download()
|
|
|
|
// Adding the following file the warehouse
|
|
if info.filepath == "" {
|
|
return errors.New("File Path empty. ")
|
|
}
|
|
|
|
hash, status, err := info.api.backend.UserWarehouse.CreateFileFromPath(info.filepath)
|
|
|
|
if err != nil {
|
|
info.api.backend.LogError("warehouse.CreateFile", "status %d error: %v", status, err)
|
|
}
|
|
|
|
// Adding file to the blockchain
|
|
var fileMetaData blockchain.BlockRecordFile
|
|
|
|
// Add the following file to the blockchain
|
|
fileMetaData.ID = uuid.New()
|
|
fileMetaData.Hash = hash
|
|
|
|
_, fileSize, _, _ := info.api.backend.UserWarehouse.FileExists(fileMetaData.Hash)
|
|
// setting file size
|
|
fileMetaData.Size = fileSize
|
|
|
|
// create block based on file information provided
|
|
block := blockRecordFileFromAPI(info.info.file)
|
|
|
|
var filesAdd []blockchain.BlockRecordFile
|
|
// appending the block to the file added
|
|
filesAdd = append(filesAdd, block)
|
|
|
|
info.api.backend.UserBlockchain.AddFiles(filesAdd)
|
|
|
|
} else {
|
|
info.info.status = DownloadCanceled
|
|
}
|
|
|
|
return nil
|
|
}
|