diff --git a/core/version/version.go b/core/version/version.go index fa0af25cc..344e36610 100644 --- a/core/version/version.go +++ b/core/version/version.go @@ -2,4 +2,5 @@ package version -const VERSIONSTR = "v1.17.11-269-g7fd90660" +const VERSIONSTR = "v1.19.10-10-g116daead +const VERSIONSTR = "v1.19.10-10-g116daead" diff --git a/winsdk/sdk.go b/winsdk/sdk.go index d26afb7fa..98c4c1ac9 100644 --- a/winsdk/sdk.go +++ b/winsdk/sdk.go @@ -108,12 +108,14 @@ func InitSDKs(configJson *C.char) *C.char { } err = client.Init(context.Background(), *configObj) - if err != nil { l.Logger.Error(err, configJs) return WithJSON(false, err) } + client.SetSdkInitialized(true) + client.SetSignatureScheme(configObj.SignatureScheme) + l.Logger.Info("InitZCNSDK success") l.Logger.Info(configObj.BlockWorker) l.Logger.Info(configObj.ChainID) diff --git a/winsdk/status2.go b/winsdk/status2.go new file mode 100644 index 000000000..3d4e5f10a --- /dev/null +++ b/winsdk/status2.go @@ -0,0 +1,51 @@ +package main + +import ( + "sync" +) + +type StatusCallback2 struct { + wg *sync.WaitGroup + isRepair bool + success bool + err error +} + +func (cb *StatusCallback2) Started(allocationId, filePath string, op, totalBytes int) { + +} + +func (cb *StatusCallback2) InProgress(allocationId, filePath string, op, completedBytes int, data []byte) { +} + +func (cb *StatusCallback2) RepairCompleted(filesRepaired int) { + if cb.err == nil { + cb.success = true + } + cb.wg.Done() +} + +func (cb *StatusCallback2) Completed(allocationId, filePath, filename, mimetype string, size, op int) { + if !cb.isRepair { + cb.success = true + cb.wg.Done() + } +} + +func (cb *StatusCallback2) Error(allocationID, filePath string, op int, err error) { + cb.success = false + cb.err = err + if !cb.isRepair { + cb.wg.Done() + } +} + +func (cb *StatusCallback2) StatusError() error { + return cb.err +} + +func NewStatusCallback2(wg *sync.WaitGroup) *StatusCallback2 { + return &StatusCallback2{ + wg: wg, + } +} diff --git a/winsdk/storage.go b/winsdk/storage.go index d8463c0f0..fe5ac9cda 100644 --- a/winsdk/storage.go +++ b/winsdk/storage.go @@ -11,7 +11,11 @@ import ( "encoding/json" "errors" "fmt" + l "github.com/0chain/gosdk/zboxcore/logger" "os" + "path/filepath" + "strconv" + "sync" "time" "github.com/0chain/gosdk/core/common" @@ -616,6 +620,144 @@ func DownloadSharedFileBlocks(localPath, authTicket *C.char, startBlock int64, e return WithJSON(info, nil) } +func DownloadFromAuthTicket(authTicket, fileName, lookupHash, downloadPath, taskID string) (string, string, error) { + var err error + authTicketObj := sdk.InitAuthTicket(authTicket) + if fileName == "" { + fileName, err = authTicketObj.GetFileName() + if err != nil { + return "", "", err + } + } + + fileName = lookupHash + "_" + taskID + filepath.Ext(fileName) + + // Check if directory exists, create only if it doesn't + if _, err = os.Stat(downloadPath); os.IsNotExist(err) { + if err = os.MkdirAll(downloadPath, os.ModePerm); err != nil { + return "", "", err + } + } + + alloc, err := sdk.GetAllocationFromAuthTicket(authTicket) + if err != nil { + return "", "", err + } + + localPath := filepath.Join(downloadPath, fileName) + f, err := os.Create(localPath) + if err != nil { + return "", "", err + } + defer f.Close() + + wg := &sync.WaitGroup{} + wg.Add(1) + cb := NewStatusCallback2(wg) + // Download file from allocation + err = alloc.DownloadFileToFileHandlerFromAuthTicket(f, authTicket, lookupHash, "", false, cb, true) + if err != nil { + return "", "", err + } + wg.Wait() + + return localPath, fileName, nil +} + +func downloadFilesRecursively(alloc *sdk.Allocation, authTicket, downloadPath string, listRes *sdk.ListResult, taskID string) (int64, error) { + l.Logger.Debug("download total size: ", downloadPath) + + totalSize := int64(0) + for _, file := range listRes.Children { + if file.Type == "f" { + if totalSize+file.Size >= 100*1024*1024 { + return 0, errors.New("download size exceeds 100MB") + } else { + totalSize += file.Size + } + + _, _, err := DownloadFromAuthTicket(authTicket, file.Name, file.LookupHash, downloadPath, taskID) + if err != nil { + return 0, err + } + + } else if file.Type == "d" { + listSubDirRes, err := alloc.ListDirFromAuthTicket(authTicket, file.LookupHash) + if err != nil || listSubDirRes == nil { + return 0, fmt.Errorf("failed to list directory: %w", err) + } + + // Recursively download files from subdirectories + subDirPath := filepath.Join(downloadPath, file.Name) + if _, err := os.Stat(subDirPath); os.IsNotExist(err) { + if err = os.MkdirAll(subDirPath, os.ModePerm); err != nil { + return 0, err + } + } + + subDirSize, err := downloadFilesRecursively(alloc, authTicket, subDirPath, listSubDirRes, taskID) + if err != nil { + return 0, err + } + totalSize += subDirSize + } + } + + l.Logger.Debug("download total size: ", totalSize) + return totalSize, nil +} + +// DownloadDirFromAuthTicket - download directory using auth ticket +// ## Inputs +// - authTicket +// - remotePath +// - downloadPath +// +// ## Outputs +// +// { +// "error":"", +// "result":"path where files were downloaded", +// } +// +//export DownloadDirFromAuthTicket +func DownloadDirFromAuthTicket(authTicket, lookupHash, downloadPath *C.char) *C.char { + defer func() { + if r := recover(); r != nil { + log.Error("win: crash ", r) + } + }() + + allocTicket := C.GoString(authTicket) + lHash := C.GoString(lookupHash) + dPath := C.GoString(downloadPath) + + alloc, err := sdk.GetAllocationFromAuthTicket(allocTicket) + if err != nil { + return WithJSON(nil, err) + } + + listRes, err := alloc.ListDirFromAuthTicket(allocTicket, lHash) + if err != nil || listRes == nil { + return WithJSON(nil, fmt.Errorf("failed to list directory: %w", err)) + } + + fullPath := filepath.Join(dPath, lHash) + + totalSize, err := downloadFilesRecursively(alloc, allocTicket, fullPath, listRes, strconv.FormatInt(time.Now().Unix(), 10)) + if err != nil { + return WithJSON(nil, err) + } + + l.Logger.Debug("Finished downloading total size: ", totalSize) + + if totalSize >= 100*1024*1024 { + return WithJSON(nil, errors.New("download size exceeds 100MB")) + } + + return WithJSON(map[string]string{"path": fullPath}, nil) +} + // GetDownloadStatus - get download status // ## Inputs // - key: lookuphash/lookuphash:thumbnail/lookuphash:startBlock-endBlock-numBlocks/lookuphash:startBlock-endBlock-numBlocks:thumbnail