github.com/0chain/gosdk@v1.17.11/winsdk/storage.go (about)

     1  package main
     2  
     3  /*
     4  #include <stdlib.h>
     5  */
     6  import (
     7  	"C"
     8  )
     9  
    10  import (
    11  	"encoding/json"
    12  	"errors"
    13  	"fmt"
    14  	"os"
    15  	"time"
    16  
    17  	"github.com/0chain/gosdk/core/common"
    18  	"github.com/0chain/gosdk/zboxcore/marker"
    19  	"github.com/0chain/gosdk/zboxcore/sdk"
    20  )
    21  
    22  // GetFileStats get file stats of blobbers
    23  //
    24  //	return
    25  //		{
    26  //			"error":"",
    27  //			"result":"xxx",
    28  //		}
    29  //
    30  //export GetFileStats
    31  func GetFileStats(allocationID, remotePath *C.char) *C.char {
    32  	defer func() {
    33  		if r := recover(); r != nil {
    34  			log.Error("win: crash ", r)
    35  		}
    36  	}()
    37  
    38  	allocID := C.GoString(allocationID)
    39  	path := C.GoString(remotePath)
    40  
    41  	if len(allocID) == 0 {
    42  		return WithJSON(nil, errors.New("allocationID is required"))
    43  	}
    44  
    45  	if len(path) == 0 {
    46  		return WithJSON(nil, errors.New("remotePath is required"))
    47  	}
    48  
    49  	allocationObj, err := getAllocation(allocID)
    50  	if err != nil {
    51  		return WithJSON(nil, err)
    52  	}
    53  
    54  	stats, err := allocationObj.GetFileStats(path)
    55  	if err != nil {
    56  		return WithJSON(nil, err)
    57  	}
    58  
    59  	result := make([]*sdk.FileStats, 0, len(stats))
    60  
    61  	//convert map[string]*sdk.FileStats to []*sdk.FileStats
    62  	for _, v := range stats {
    63  		result = append(result, v)
    64  	}
    65  
    66  	return WithJSON(result, nil)
    67  }
    68  
    69  // Delete delete path
    70  //
    71  //	return
    72  //		{
    73  //			"error":"",
    74  //			"result":"true",
    75  //		}
    76  //
    77  //export Delete
    78  func Delete(allocationID, path *C.char) *C.char {
    79  	defer func() {
    80  		if r := recover(); r != nil {
    81  			log.Error("win: crash ", r)
    82  		}
    83  	}()
    84  
    85  	allocID := C.GoString(allocationID)
    86  
    87  	alloc, err := getAllocation(allocID)
    88  	if err != nil {
    89  		return WithJSON(false, err)
    90  	}
    91  
    92  	s := C.GoString(path)
    93  
    94  	err = alloc.DoMultiOperation([]sdk.OperationRequest{
    95  		{
    96  			OperationType: "delete",
    97  			RemotePath:    s,
    98  		},
    99  	})
   100  
   101  	if err != nil {
   102  		return WithJSON(false, err)
   103  	}
   104  
   105  	log.Info("winsdk: deleted ", s)
   106  
   107  	return WithJSON(true, nil)
   108  }
   109  
   110  type MultiOperationOption struct {
   111  	OperationType string `json:"OperationType,omitempty"`
   112  	RemotePath    string `json:"RemotePath,omitempty"`
   113  	DestName      string `json:"DestName,omitempty"` // Required only for rename operation
   114  	DestPath      string `json:"DestPath,omitempty"` // Required for copy and move operation`
   115  }
   116  
   117  // MultiOperation - do copy, move, delete and createdir operation together
   118  // ## Inputs
   119  //   - allocationID
   120  //   - jsonMultiOperationOptions: Json Array of MultiOperationOption. eg: "[{"operationType":"move","remotePath":"/README.md","destPath":"/folder1/"},{"operationType":"delete","remotePath":"/t3.txt"}]"
   121  //     return
   122  //     {
   123  //     "error":"",
   124  //     "result":"true",
   125  //     }
   126  //
   127  //export MultiOperation
   128  func MultiOperation(_allocationID, _jsonMultiOperationOptions *C.char) *C.char {
   129  	defer func() {
   130  		if r := recover(); r != nil {
   131  			log.Error("win: crash ", r)
   132  		}
   133  	}()
   134  	allocationID := C.GoString(_allocationID)
   135  	jsonMultiOperationOptions := C.GoString(_jsonMultiOperationOptions)
   136  	if allocationID == "" {
   137  		return WithJSON(false, errors.New("AllocationID is required"))
   138  	}
   139  
   140  	var options []MultiOperationOption
   141  	err := json.Unmarshal([]byte(jsonMultiOperationOptions), &options)
   142  	if err != nil {
   143  		return WithJSON(false, err)
   144  	}
   145  	totalOp := len(options)
   146  	operations := make([]sdk.OperationRequest, totalOp)
   147  	for idx, op := range options {
   148  		operations[idx] = sdk.OperationRequest{
   149  			OperationType: op.OperationType,
   150  			RemotePath:    op.RemotePath,
   151  			DestName:      op.DestName,
   152  			DestPath:      op.DestPath,
   153  		}
   154  
   155  		log.Info("multi-operation: index=", idx, " op=", op.OperationType, " remotePath=", op.RemotePath, " destName=", op.DestName, " destPath=", op.DestPath)
   156  	}
   157  	allocationObj, err := getAllocation(allocationID)
   158  	if err != nil {
   159  		return WithJSON(false, err)
   160  	}
   161  	err = allocationObj.DoMultiOperation(operations)
   162  	if err != nil {
   163  		return WithJSON(false, err)
   164  	}
   165  	return WithJSON(true, nil)
   166  
   167  }
   168  
   169  // GetFileMeta get metadata by path
   170  // ## Inputs
   171  //   - allocationID
   172  //   - path
   173  //   - authTicket
   174  //
   175  // ## Outputs
   176  //
   177  //	return
   178  //		{
   179  //			"error":"",
   180  //			"result":"true",
   181  //		}
   182  //
   183  //export GetFileMeta
   184  func GetFileMeta(allocationID, path, authTicket *C.char) *C.char {
   185  	defer func() {
   186  		if r := recover(); r != nil {
   187  			log.Error("win: crash ", r)
   188  		}
   189  	}()
   190  	allocID := C.GoString(allocationID)
   191  
   192  	t := C.GoString(authTicket)
   193  
   194  	var ticket *marker.AuthTicket
   195  
   196  	var alloc *sdk.Allocation
   197  	var err error
   198  	isShared := len(t) > 0
   199  	if isShared {
   200  		alloc, ticket, err = getAllocationWith(t)
   201  	} else {
   202  		alloc, err = getAllocation(allocID)
   203  	}
   204  
   205  	if err != nil {
   206  		log.Error("win: ", err)
   207  		return WithJSON(nil, err)
   208  	}
   209  
   210  	s := C.GoString(path)
   211  
   212  	var f *sdk.ConsolidatedFileMeta
   213  	if isShared {
   214  		f, err = alloc.GetFileMetaFromAuthTicket(t, ticket.FilePathHash)
   215  	} else {
   216  		f, err = alloc.GetFileMeta(s)
   217  	}
   218  
   219  	if err != nil {
   220  		log.Error("win: ", err, " authTicket=", t, " path=", s)
   221  		return WithJSON(nil, err)
   222  	}
   223  
   224  	return WithJSON(f, nil)
   225  }
   226  
   227  // BulkUpload - upload files from local path to remote path
   228  // ## Inputs
   229  //   - allocationID
   230  //   - files: Json Array of UploadFile
   231  //     return
   232  //     {
   233  //     "error":"",
   234  //     "result":"true",
   235  //     }
   236  //
   237  //export BulkUpload
   238  func BulkUpload(allocationID, files *C.char) *C.char {
   239  	defer func() {
   240  		if r := recover(); r != nil {
   241  			log.Error("win: crash ", r)
   242  		}
   243  	}()
   244  	allocID := C.GoString(allocationID)
   245  	workdir, _ := os.UserHomeDir()
   246  	jsFiles := C.GoString(files)
   247  	var options []UploadFile
   248  	err := json.Unmarshal([]byte(jsFiles), &options)
   249  	if err != nil {
   250  		return WithJSON(nil, err)
   251  	}
   252  	totalUploads := len(options)
   253  	filePaths := make([]string, totalUploads)
   254  	fileNames := make([]string, totalUploads)
   255  	remotePaths := make([]string, totalUploads)
   256  	thumbnailPaths := make([]string, totalUploads)
   257  	chunkNumbers := make([]int, totalUploads)
   258  	encrypts := make([]bool, totalUploads)
   259  	isUpdates := make([]bool, totalUploads)
   260  	isWebstreaming := make([]bool, totalUploads)
   261  
   262  	statusBar := NewStatusBar(statusUpload, "")
   263  
   264  	for idx, option := range options {
   265  		filePaths[idx] = option.Path
   266  		fileNames[idx] = option.Name
   267  		thumbnailPaths[idx] = option.ThumbnailPath
   268  		remotePaths[idx] = option.RemotePath
   269  		chunkNumbers[idx] = option.ChunkNumber
   270  		isUpdates[idx] = option.IsUpdate
   271  		isWebstreaming[idx] = option.IsWebstreaming
   272  		encrypts[idx] = option.Encrypt
   273  		if option.IsWebstreaming {
   274  			originalLookupHash := getLookupHash(allocID, option.RemotePath+option.Name)
   275  			_, transcodeRemotePath := sdk.GetTranscodeFile(option.RemotePath + option.Name)
   276  			transcodeLookupHash := getLookupHash(allocID, transcodeRemotePath)
   277  			transcodeFiles.Add(originalLookupHash, transcodeLookupHash)
   278  			statusUpload.Add(transcodeLookupHash, &Status{})
   279  
   280  		} else {
   281  			statusUpload.Add(getLookupHash(allocID, option.RemotePath+option.Name), &Status{})
   282  		}
   283  
   284  	}
   285  
   286  	a, err := getAllocation(allocID)
   287  	if err != nil {
   288  		return WithJSON(nil, err)
   289  	}
   290  
   291  	err = a.StartMultiUpload(workdir, filePaths, fileNames, thumbnailPaths, encrypts, chunkNumbers, remotePaths, isUpdates, isWebstreaming, statusBar)
   292  	if err != nil {
   293  		return WithJSON(nil, err)
   294  	}
   295  	return WithJSON(nil, nil)
   296  }
   297  
   298  // GetUploadStatus - get upload status
   299  // ## Inputs
   300  //   - lookupHash
   301  //
   302  // ## Outputs
   303  //
   304  //	{
   305  //	"error":"",
   306  //	"result":"{'Started':false,'CompletedBytes': 0,Error:”,'Completed':false}",
   307  //	}
   308  //
   309  //export GetUploadStatus
   310  func GetUploadStatus(lookupHash *C.char) *C.char {
   311  	defer func() {
   312  		if r := recover(); r != nil {
   313  			log.Error("win: crash ", r)
   314  		}
   315  	}()
   316  	h := C.GoString(lookupHash)
   317  
   318  	h2, ok := transcodeFiles.Get(h)
   319  
   320  	if ok {
   321  		h = h2
   322  	}
   323  
   324  	s, ok := statusUpload.Get(h)
   325  
   326  	if !ok {
   327  		s = &Status{}
   328  	}
   329  
   330  	return WithJSON(s, nil)
   331  }
   332  
   333  // SetNumBlockDownloads - set global the number of blocks on downloading
   334  // ## Inputs
   335  //   - num
   336  //
   337  // ## Outputs
   338  //
   339  //	{
   340  //	"error":"",
   341  //	"result":"",
   342  //	}
   343  //
   344  //export SetNumBlockDownloads
   345  func SetNumBlockDownloads(num int) {
   346  	sdk.SetNumBlockDownloads(num)
   347  }
   348  
   349  // DownloadFile - downalod file
   350  // ## Inputs
   351  //   - allocationID
   352  //   - localPath
   353  //   - remotePath
   354  //   - verifyDownload
   355  //   - isFinal
   356  //
   357  // ## Outputs
   358  //
   359  //	{
   360  //	"error":"",
   361  //	"result":"true",
   362  //	}
   363  //
   364  //export DownloadFile
   365  func DownloadFile(allocationID, localPath, remotePath *C.char, verifyDownload, isFinal bool) *C.char {
   366  	defer func() {
   367  		if r := recover(); r != nil {
   368  			log.Error("win: crash ", r)
   369  		}
   370  	}()
   371  	allocID := C.GoString(allocationID)
   372  
   373  	alloc, err := getAllocation(allocID)
   374  	if err != nil {
   375  		return WithJSON(false, err)
   376  	}
   377  
   378  	statusBar := NewStatusBar(statusDownload, "")
   379  
   380  	err = alloc.DownloadFile(C.GoString(localPath), C.GoString(remotePath), verifyDownload, statusBar, isFinal)
   381  	if err != nil {
   382  		return WithJSON(false, err)
   383  	}
   384  
   385  	return WithJSON(true, nil)
   386  }
   387  
   388  // DownloadThumbnail - downalod thumbnial
   389  // ## Inputs
   390  //   - allocationID
   391  //   - localPath
   392  //   - remotePath
   393  //   - verifyDownload
   394  //   - isFinal
   395  //
   396  // ## Outputs
   397  //
   398  //	{
   399  //	"error":"",
   400  //	"result":"true",
   401  //	}
   402  //
   403  //export DownloadThumbnail
   404  func DownloadThumbnail(allocationID, localPath, remotePath *C.char, verifyDownload bool, isFinal bool) *C.char {
   405  	defer func() {
   406  		if r := recover(); r != nil {
   407  			log.Error("win: crash ", r)
   408  		}
   409  	}()
   410  	allocID := C.GoString(allocationID)
   411  
   412  	alloc, err := getAllocation(allocID)
   413  	if err != nil {
   414  		return WithJSON(false, err)
   415  	}
   416  
   417  	r := C.GoString(remotePath)
   418  
   419  	lookupHash := getLookupHash(allocID, r)
   420  	statusBar := NewStatusBar(statusDownload, lookupHash+":thumbnail")
   421  
   422  	err = alloc.DownloadThumbnail(C.GoString(localPath), r, verifyDownload, statusBar, isFinal)
   423  	if err != nil {
   424  		return WithJSON(false, err)
   425  	}
   426  
   427  	return WithJSON(true, nil)
   428  }
   429  
   430  // DownloadSharedFile - downalod shared file by authTicket
   431  // ## Inputs
   432  //   - localPath
   433  //   - authTicket
   434  //   - verifyDownload
   435  //   - isFinal
   436  //
   437  // ## Outputs
   438  //
   439  //	{
   440  //	"error":"",
   441  //	"result":"{"AllocationID":"xxx","LookupHash":"xxxxxx" }",
   442  //	}
   443  //
   444  //export DownloadSharedFile
   445  func DownloadSharedFile(localPath, authTicket *C.char, verifyDownload bool, isFinal bool) *C.char {
   446  	defer func() {
   447  		if r := recover(); r != nil {
   448  			log.Error("win: crash ", r)
   449  		}
   450  	}()
   451  	info := &SharedInfo{}
   452  	t, at, err := decodeAuthTicket(authTicket)
   453  	if err != nil {
   454  		return WithJSON(info, err)
   455  	}
   456  
   457  	info.AllocationID = t.AllocationID
   458  	info.LookupHash = t.FilePathHash
   459  
   460  	alloc, err := getAllocation(t.AllocationID)
   461  	if err != nil {
   462  		return WithJSON(info, err)
   463  	}
   464  
   465  	statusBar := NewStatusBar(statusDownload, t.FilePathHash)
   466  
   467  	err = alloc.DownloadFromAuthTicket(C.GoString(localPath), at, t.FilePathHash, t.FileName, verifyDownload, statusBar, isFinal)
   468  	if err != nil {
   469  		return WithJSON(info, err)
   470  	}
   471  
   472  	return WithJSON(info, nil)
   473  }
   474  
   475  // DownloadSharedThumbnail - downalod shared thumbnial by authTicket
   476  // ## Inputs
   477  //   - localPath
   478  //   - authTicket
   479  //   - verifyDownload
   480  //   - isFinal
   481  //
   482  // ## Outputs
   483  //
   484  //	{
   485  //	"error":"",
   486  //	"result":"{"AllocationID":"xxx","LookupHash":"xxx" }",
   487  //	}
   488  //
   489  //export DownloadSharedThumbnail
   490  func DownloadSharedThumbnail(localPath, authTicket *C.char, verifyDownload bool, isFinal bool) *C.char {
   491  	defer func() {
   492  		if r := recover(); r != nil {
   493  			log.Error("win: crash ", r)
   494  		}
   495  	}()
   496  	info := &SharedInfo{}
   497  	t, at, err := decodeAuthTicket(authTicket)
   498  	if err != nil {
   499  		log.Error("win: ", err, " authTicket=", at)
   500  		return WithJSON(info, err)
   501  	}
   502  	info.AllocationID = t.AllocationID
   503  	info.LookupHash = t.FilePathHash
   504  
   505  	alloc, err := getAllocation(t.AllocationID)
   506  	if err != nil {
   507  		log.Error("win: ", err, " authTicket=", at)
   508  		return WithJSON(info, err)
   509  	}
   510  
   511  	statusBar := NewStatusBar(statusDownload, t.FilePathHash)
   512  
   513  	err = alloc.DownloadThumbnailFromAuthTicket(C.GoString(localPath), at, t.FilePathHash, t.FileName, verifyDownload, statusBar, isFinal)
   514  	if err != nil {
   515  		log.Error("win: ", err, " authTicket=", at, " lookuphash=", t.FilePathHash)
   516  		return WithJSON(info, err)
   517  	}
   518  
   519  	return WithJSON(info, nil)
   520  }
   521  
   522  // DownloadFileBlocks - downalod file blocks
   523  // ## Inputs
   524  //   - allocationID
   525  //   - localPath
   526  //   - remotePath
   527  //   - startBlock
   528  //   - endBlock
   529  //   - numBlocks
   530  //   - verifyDownload
   531  //   - isFinal
   532  //
   533  // ## Outputs
   534  //
   535  //	{
   536  //	"error":"",
   537  //	"result":"true",
   538  //	}
   539  //
   540  //export DownloadFileBlocks
   541  func DownloadFileBlocks(allocationID,
   542  	localPath, remotePath *C.char, startBlock int64, endBlock int64,
   543  	numBlocks int, verifyDownload bool, isFinal bool) *C.char {
   544  	defer func() {
   545  		if r := recover(); r != nil {
   546  			log.Error("win: crash ", r)
   547  		}
   548  	}()
   549  
   550  	allocID := C.GoString(allocationID)
   551  
   552  	alloc, err := getAllocation(allocID)
   553  	if err != nil {
   554  		return WithJSON(false, err)
   555  	}
   556  
   557  	r := C.GoString(remotePath)
   558  
   559  	lookupHash := getLookupHash(allocID, r)
   560  	statusBar := NewStatusBar(statusDownload, lookupHash+fmt.Sprintf(":%v-%v-%v", startBlock, endBlock, numBlocks))
   561  
   562  	err = alloc.DownloadFileByBlock(C.GoString(localPath), r, startBlock, endBlock, numBlocks, verifyDownload, statusBar, isFinal)
   563  	if err != nil {
   564  		return WithJSON(false, err)
   565  	}
   566  
   567  	return WithJSON(true, nil)
   568  }
   569  
   570  // DownloadSharedFileBlocks - downalod shared file blocks
   571  // ## Inputs
   572  //   - localPath
   573  //   - remotePath
   574  //   - startBlock
   575  //   - endBlock
   576  //   - numBlocks
   577  //   - verifyDownload
   578  //   - isFinal
   579  //
   580  // ## Outputs
   581  //
   582  //	{
   583  //	"error":"",
   584  //	"result":"true",
   585  //	}
   586  //
   587  //export DownloadSharedFileBlocks
   588  func DownloadSharedFileBlocks(localPath, authTicket *C.char, startBlock int64, endBlock int64,
   589  	numBlocks int, verifyDownload bool, isFinal bool) *C.char {
   590  	defer func() {
   591  		if r := recover(); r != nil {
   592  			log.Error("win: crash ", r)
   593  		}
   594  	}()
   595  
   596  	info := &SharedInfo{}
   597  	t, at, err := decodeAuthTicket(authTicket)
   598  	if err != nil {
   599  		return WithJSON(info, err)
   600  	}
   601  	info.AllocationID = t.AllocationID
   602  	info.LookupHash = t.FilePathHash
   603  
   604  	alloc, err := getAllocation(t.AllocationID)
   605  	if err != nil {
   606  		return WithJSON(info, err)
   607  	}
   608  
   609  	statusBar := NewStatusBar(statusDownload, t.FilePathHash+fmt.Sprintf(":%v-%v-%v", startBlock, endBlock, numBlocks))
   610  
   611  	err = alloc.DownloadFromAuthTicketByBlocks(C.GoString(localPath), at, startBlock, endBlock, numBlocks, t.FilePathHash, t.FileName, verifyDownload, statusBar, isFinal)
   612  	if err != nil {
   613  		return WithJSON(info, err)
   614  	}
   615  
   616  	return WithJSON(info, nil)
   617  }
   618  
   619  // GetDownloadStatus - get download status
   620  // ## Inputs
   621  //   - key: lookuphash/lookuphash:thumbnail/lookuphash:startBlock-endBlock-numBlocks/lookuphash:startBlock-endBlock-numBlocks:thumbnail
   622  //
   623  // ## Outputs
   624  //
   625  //	{
   626  //	"error":"",
   627  //	"result":"{'Started':false,'CompletedBytes': 0,Error:”,'Completed':false}",
   628  //	}
   629  //
   630  //export GetDownloadStatus
   631  func GetDownloadStatus(key *C.char, isThumbnail bool) *C.char {
   632  	defer func() {
   633  		if r := recover(); r != nil {
   634  			log.Error("win: crash ", r)
   635  		}
   636  	}()
   637  	k := C.GoString(key)
   638  	if isThumbnail {
   639  		k += ":thumbnail"
   640  	}
   641  
   642  	s, ok := statusDownload.Get(k)
   643  
   644  	if !ok {
   645  		s = &Status{}
   646  	}
   647  
   648  	return WithJSON(s, nil)
   649  }
   650  
   651  // CreateAuthTicket - create AuthTicket for sharing
   652  // ## Inputs
   653  //   - allocationID
   654  //   - remotePath
   655  //   - refereeClientID
   656  //   - refereePublicEncryptionKey
   657  //   - availableAfter
   658  //   - expirationSeconds
   659  //
   660  // ## Outputs
   661  //
   662  //	{
   663  //	"error":"",
   664  //	"result":"{}",
   665  //	}
   666  //
   667  //export CreateAuthTicket
   668  func CreateAuthTicket(allocationID, remotePath, refereeClientID, refereePublicEncryptionKey, availableAfter *C.char, expirationSeconds int64) *C.char {
   669  	defer func() {
   670  		if r := recover(); r != nil {
   671  			log.Error("win: crash ", r)
   672  		}
   673  	}()
   674  	alloc, err := getAllocation(C.GoString(allocationID))
   675  
   676  	if err != nil {
   677  		log.Error("win: ", err)
   678  		return WithJSON(nil, err)
   679  	}
   680  
   681  	rPath := C.GoString(remotePath)
   682  
   683  	fileMeta, err := alloc.GetFileMeta(rPath)
   684  	if err != nil {
   685  		log.Error("win: ", err)
   686  		return WithJSON(nil, err)
   687  	}
   688  
   689  	af := time.Now()
   690  	availableAfterString := C.GoString(availableAfter)
   691  
   692  	if len(availableAfterString) > 0 {
   693  		aa, err := common.ParseTime(af, availableAfterString)
   694  		if err != nil {
   695  			log.Error("win: ", err)
   696  			return WithJSON(nil, err)
   697  		}
   698  		af = *aa
   699  	}
   700  
   701  	at, err := alloc.GetAuthTicket(rPath, fileMeta.Name, fileMeta.Type, C.GoString(refereeClientID), C.GoString(refereePublicEncryptionKey), expirationSeconds, &af)
   702  	if err != nil {
   703  		log.Error("win: ", err)
   704  		return WithJSON(nil, err)
   705  	}
   706  
   707  	return WithJSON(at, nil)
   708  
   709  }
   710  
   711  // DeleteAuthTicket - delete AuthTicket
   712  // ## Inputs
   713  //   - allocationID
   714  //   - remotePath
   715  //   - refereeClientID
   716  //
   717  // ## Outputs
   718  //
   719  //	{
   720  //	"error":"",
   721  //	"result":"true",
   722  //	}
   723  //
   724  //export DeleteAuthTicket
   725  func DeleteAuthTicket(allocationID, remotePath, refereeClientID *C.char) *C.char {
   726  	defer func() {
   727  		if r := recover(); r != nil {
   728  			log.Error("win: crash ", r)
   729  		}
   730  	}()
   731  	alloc, err := getAllocation(C.GoString(allocationID))
   732  	if err != nil {
   733  		log.Error("win: ", err)
   734  		return WithJSON(false, err)
   735  	}
   736  
   737  	rPath := C.GoString(remotePath)
   738  
   739  	err = alloc.RevokeShare(rPath, C.GoString(refereeClientID))
   740  	if err != nil {
   741  		log.Error("win: ", err)
   742  		return WithJSON(false, err)
   743  	}
   744  
   745  	return WithJSON(true, nil)
   746  
   747  }
   748  
   749  func CancelUpload(allocationID, remotePath *C.char) *C.char {
   750  	defer func() {
   751  		if r := recover(); r != nil {
   752  			log.Error("win: crash ", r)
   753  		}
   754  	}()
   755  	alloc, err := getAllocation(C.GoString(allocationID))
   756  	if err != nil {
   757  		log.Error("win: ", err)
   758  		return WithJSON(false, err)
   759  	}
   760  
   761  	rPath := C.GoString(remotePath)
   762  	err = alloc.CancelUpload(rPath)
   763  	if err != nil {
   764  		log.Error("win: ", err)
   765  		return WithJSON(false, err)
   766  	}
   767  	return WithJSON(true, nil)
   768  }
   769  
   770  func PauseUpload(allocationID, remotePath *C.char) *C.char {
   771  	defer func() {
   772  		if r := recover(); r != nil {
   773  			log.Error("win: crash ", r)
   774  		}
   775  	}()
   776  	alloc, err := getAllocation(C.GoString(allocationID))
   777  	if err != nil {
   778  		log.Error("win: ", err)
   779  		return WithJSON(false, err)
   780  	}
   781  
   782  	rPath := C.GoString(remotePath)
   783  	err = alloc.PauseUpload(rPath)
   784  	if err != nil {
   785  		log.Error("win: ", err)
   786  		return WithJSON(false, err)
   787  	}
   788  	return WithJSON(true, nil)
   789  }
   790  
   791  // SetUploadMode sets upload mode
   792  //
   793  //	## Inputs
   794  //	- mode: 0 for low, 1 for medium, 2 for high
   795  func SetUploadMode(mode int) {
   796  	switch mode {
   797  	case 0:
   798  		sdk.SetUploadMode(sdk.UploadModeLow)
   799  	case 1:
   800  		sdk.SetUploadMode(sdk.UploadModeMedium)
   801  	case 2:
   802  		sdk.SetUploadMode(sdk.UploadModeHigh)
   803  	}
   804  }