private static void InvokeProgressEvent(uint currentFileSlicesCount, uint currentFileSlice, FileTransferState state) { if (state == FileTransferState.Finished) { throw new InvalidOperationException(); } FileTransferProgressEventArgs ea = null; if (!isQueue) { ea = new FileTransferProgressEventArgs { CurrentPart = currentFileSlice + 1, Total = currentFileSlicesCount, State = FileTransferState.DataTransfer, Guid = requestGuid, SenderName = senderName, TotalFiles = filesCount }; System.Diagnostics.Debug.WriteLine(ea.CurrentPart + " / " + ea.Total); } else if (state == FileTransferState.QueueList) { ea = new FileTransferProgressEventArgs { CurrentPart = 0, Total = 0, State = FileTransferState.QueueList, Guid = requestGuid, SenderName = senderName, TotalFiles = filesCount }; System.Diagnostics.Debug.WriteLine("Downloading queue data..."); } else { ea = new FileTransferProgressEventArgs { CurrentPart = (ulong)(queueSlicesFinished + currentFileSlice + 1), Total = (ulong)queueTotalSlices, State = FileTransferState.QueueList, Guid = requestGuid, SenderName = senderName, TotalFiles = filesCount }; System.Diagnostics.Debug.WriteLine(ea.CurrentPart + " / " + ea.Total); } FileTransferProgress?.Invoke(ea); }
private static async Task ProcessRequest(Dictionary <string, object> request, int fileSenderVersion, IDownloadFolderDecider downloadFolderDecider, Func <string, Task <IFolder> > folderResolver, bool isResume) { var sessionKey = Guid.Parse(request["Guid"] as string); var ip = request["ServerIP"].ToString(); var isCompatible = CompatibilityHelper.IsCompatible(fileSenderVersion, fileReceiverVersion); var senderName = request["SenderName"].ToString(); if ((!isResume) && (fileSenderVersion >= 2)) { await SendVersionCheckGetRequestAsync(ip, sessionKey, isCompatible); } if (!isCompatible) { // TODO return; } currentReceiveSessionAgent = new ReceiveSessionAgent(ip, sessionKey, senderName, downloadFolderDecider, folderResolver); currentReceiveSessionAgent.FileTransferProgress += (e) => { FileTransferProgress?.Invoke(e); }; currentReceiveSessionAgent.StartReceive(isResume); await currentReceiveSessionAgent.ReceiveFinishTcs.Task; }
public static async Task <Dictionary <string, object> > ReceiveRequest(Dictionary <string, object> request, IDownloadFolderDecider downloadFolderDecider) { Dictionary <string, object> returnVal = new Dictionary <string, object>(); try { if ((request.ContainsKey("Type")) && (request["Type"] as string == "QueueInit")) { await InitQueue(request, downloadFolderDecider, returnVal); } else if ((request.ContainsKey("IsQueueItemGroup")) && (request["IsQueueItemGroup"] as string == "true")) { await ProcessQueueItemGroup(request, downloadFolderDecider); } else if ((request.ContainsKey("IsQueueItem")) && (request["IsQueueItem"] as string == "true")) { await ProcessQueueItem(request, downloadFolderDecider); } else { await ProcessSingularFile(request, downloadFolderDecider); } } catch (FailedToDownloadException) { FileTransferProgress?.Invoke(new FileTransferProgressEventArgs { Guid = requestGuid, State = FileTransferState.Error, }); } return(returnVal); }
private static async Task BeginProcessingQueue(Func <string[], Task <IFolder> > downloadFolderDecider) { var downloadFolder = await downloadFolderDecider(queueItems.Select(x => Path.GetExtension((string)x["FileName"])).ToArray()); string queueParentDirectory2 = await GetUniqueQueueParentDirectory(downloadFolder); foreach (var item in queueItems) { if ((((string)item["Directory"]).Length >= queueParentDirectory.Length) && (((string)item["Directory"]).Substring(0, queueParentDirectory.Length) == queueParentDirectory)) { if (queueParentDirectory2 != queueParentDirectory) { item["Directory"] = queueParentDirectory2 + ((string)item["Directory"]).Substring(queueParentDirectory.Length); } } else if (queueParentDirectory.Length > 0) { item["Directory"] = Path.Combine(queueParentDirectory2, (string)item["Directory"]); } } var logItems = from x in queueItems select new ReceivedFile { Name = (string)x["FileName"], Size = (long)x["FileSize"], StorePath = System.IO.Path.Combine(downloadFolder.Path, (string)x["Directory"]), }; await DataStorageProviders.HistoryManager.OpenAsync(); DataStorageProviders.HistoryManager.Add(requestGuid, DateTime.Now, senderName, new ReceivedFileCollection { Files = logItems.ToList(), StoreRootPath = System.IO.Path.Combine(downloadFolder.Path, queueParentDirectory2), }, false); DataStorageProviders.HistoryManager.Close(); foreach (var item in queueItems) { await DownloadFile(item, downloadFolder); } FileTransferProgress?.Invoke(new FileTransferProgressEventArgs { CurrentPart = (ulong)queueTotalSlices, Total = (ulong)queueTotalSlices, State = FileTransferState.Finished, Guid = requestGuid, SenderName = senderName, TotalFiles = filesCount }); await DataStorageProviders.HistoryManager.OpenAsync(); DataStorageProviders.HistoryManager.ChangeCompletedStatus(requestGuid, true); DataStorageProviders.HistoryManager.Close(); await QueueProcessFinishedNotifySender(); }
private static void ServerIPFinder_IPDetectionFailed() { FileTransferProgress?.Invoke(new FileTransfer2ProgressEventArgs { State = FileTransferState.Error, Exception = new HandshakeFailedException(), Guid = Guid.NewGuid(), }); }
private async Task <FileTransferResult> SendFiles(string sessionKey, string ip, FileSendProgressCalculator transferProgress, CancellationToken cancellationToken = default(CancellationToken)) { #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed SendInitReceiverMessage(transferProgress.TotalSlices, sessionKey, ip, isResume: false); #pragma warning restore CS4014 transferProgress.InitTimeout(timeoutTcs); var cancellationTcs = new TaskCompletionSource <FileTransferResult>(); var cancellationRegistration = cancellationToken.Register(s => ((TaskCompletionSource <FileTransferResult>)s).SetResult(FileTransferResult.Cancelled), cancellationTcs); try { while (true) { var result = (await Task.WhenAny(transferTcs.Task, timeoutTcs.Task, cancellationTcs.Task)).Result; if (result == FileTransferResult.Timeout && fileReceiverVersion >= 2) { if (transferProgress.TransferStarted) { // Resume Request FileTransferProgress?.Invoke(this, new FileTransfer2ProgressEventArgs { State = FileTransferState.Reconnecting, }); await packageManager.Connect(); await Task.Delay(1000); // This is needed otherwise the message won't reach destination (Windows). Why? Idk, ask Project Rome SDK. #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed SendInitReceiverMessage(transferProgress.TotalSlices, sessionKey, ip, isResume: true); #pragma warning restore CS4014 FileTransferProgress?.Invoke(this, new FileTransfer2ProgressEventArgs { State = FileTransferState.Reconnected, }); timeoutTcs = new TaskCompletionSource <FileTransferResult>(); transferProgress.InitTimeout(timeoutTcs); } else { return(FileTransferResult.FailedOnPrepare); } } else { return(result); } } } finally { cancellationRegistration.Dispose(); } }
private void OnProgressChanged(object sender, FileTransferProgress e) { Task fileCompressProgressTask = Task.Factory.StartNew(() => { ShowTotalProcess = true; ValueProgress = CalcUploadPresignedURClientProgress((int)e.Offset, e.FileSize, ProgressOrigineType.UploadFile); }); fileCompressProgressTask.Wait(); }
private static void LegacyFileReceiver_FileTransferProgress(FileTransferProgressEventArgs e) { FileTransferProgress?.Invoke(new FileTransfer2ProgressEventArgs { Guid = e.Guid, SenderName = e.SenderName, State = e.State, TotalBytes = e.Total * Constants.FileSliceMaxLength, TotalTransferredBytes = e.CurrentPart * Constants.FileSliceMaxLength, TotalFiles = e.TotalFiles, }); }
/// <summary> /// Callback method invoked whenever bytes have been transferred. /// </summary> /// <param name="sender">The sender of the event.</param> /// <param name="e">The event arguments containing the SISession instance for /// which bytes have been transferred.</param> void OnBytesTransferred(object sender, BytesTransferredEventArgs e) { // Get the Metadata of the file. FileMetaData meta; if (metaData.TryGetValue(e.Session.Sid, out meta)) { // Raise the 'FileTransferProgress' event. FileTransferProgress.Raise(this, new FileTransferProgressEventArgs( new FileTransfer(e.Session, meta.Name, meta.Description))); } }
private static void InvokeFinishedEvent(uint currentFileSlicesCount) { if (!isQueue) { FileTransferProgress?.Invoke(new FileTransferProgressEventArgs { CurrentPart = currentFileSlicesCount, Total = currentFileSlicesCount, State = FileTransferState.Finished, Guid = requestGuid, SenderName = senderName, TotalFiles = filesCount }); } else { queueSlicesFinished += (int)currentFileSlicesCount; } }
private void DispatchFileTransferProgress(long bytesLoaded, long bytesTotal, string callbackId, bool keepCallback = true) { Debug.WriteLine("DispatchFileTransferProgress : " + callbackId); // send a progress change event FileTransferProgress progEvent = new FileTransferProgress(bytesTotal); progEvent.BytesLoaded = bytesLoaded; PluginResult plugRes = new PluginResult(PluginResult.Status.OK, progEvent); plugRes.KeepCallback = keepCallback; plugRes.CallbackId = callbackId; DispatchCommandResult(plugRes, callbackId); }
public static async Task <Dictionary <string, object> > ReceiveRequest(Dictionary <string, object> request, IDownloadFolderDecider downloadFolderDecider, Func <string, Task <IFolder> > folderResolver) { try { int fileSenderVersion = 2; // FileSender v1 if (!request.ContainsKey("FileSenderVersion") || (int.Parse(request["FileSenderVersion"].ToString()) < 2)) { fileSenderVersion = 1; return(await ProcessRequestLegacy(request, fileSenderVersion, downloadFolderDecider)); } if (!request.ContainsKey("Type")) { throw new InvalidOperationException("Field 'Type' is missing from request."); } switch (request["Type"] as string) { case "QueueInit": await ProcessRequest(request, fileSenderVersion, downloadFolderDecider, folderResolver, isResume : false); return(new Dictionary <string, object>()); case "ResumeReceive": Debug.WriteLine("Received ResumeReceive request. TODO."); if (currentReceiveSessionAgent != null) { currentReceiveSessionAgent.Stop(); await Task.Delay(500); } await ProcessRequest(request, fileSenderVersion, downloadFolderDecider, folderResolver, isResume : true); return(new Dictionary <string, object>()); default: throw new InvalidOperationException($"Type '{request["Type"]}' is invalid."); } } catch (Exception ex) { FileTransferProgress?.Invoke(new FileTransfer2ProgressEventArgs { State = FileTransferState.Error, Exception = ex, }); throw ex; } }
private async Task StartDownload(QueueInfo queueInfo, string senderName, string ip, Guid sessionKey, bool isResume, CancellationToken cancellationToken) { IFolder downloadRootFolder; if (isResume) { await DataStorageProviders.HistoryManager.OpenAsync(); downloadRootFolder = await folderResolver((DataStorageProviders.HistoryManager.GetItem(sessionKey).Data as ReceivedFileCollection).StoreRootPath); DataStorageProviders.HistoryManager.Close(); } else { downloadRootFolder = await downloadFolderDecider.DecideAsync(queueInfo.Files.Select(x => Path.GetExtension(x.FileName)).ToArray()); await AddToHistory(queueInfo, sessionKey, senderName, downloadRootFolder); } progressCalculator = new FileReceiveProgressCalculator(queueInfo, queueInfo.Files.First().SliceMaxLength, senderName, sessionKey); progressCalculator.FileTransferProgress += ProgressCalculator_FileTransferProgress; await queueInfo.Files.ParallelForEachAsync(numberOfParallelDownloads, async item => { await DownloadFile(item, downloadRootFolder, ip, sessionKey, cancellationToken); }); await DataStorageProviders.HistoryManager.OpenAsync(); DataStorageProviders.HistoryManager.ChangeCompletedStatus(sessionKey, true); DataStorageProviders.HistoryManager.Close(); await SendFinishGetRequestAsync(ip, sessionKey); FileTransferProgress?.Invoke(new FileTransfer2ProgressEventArgs { State = FileTransferState.Finished, Guid = sessionKey, TotalFiles = queueInfo.Files.Count, SenderName = senderName, }); ReceiveFinishTcs.SetResult(true); }
private void TransferProgress_FileTransferProgress(object sender, FileTransfer2ProgressEventArgs e) { FileTransferProgress?.Invoke(this, e); }
public virtual async Task <Result> ReceiveFileAsync( FileTransfer fileTransfer, Socket socket, byte[] unreadBytes, CancellationToken token) { var bufferSize = Settings.SocketSettings.BufferSize; var timeoutMs = Settings.SocketSettings.SocketTimeoutInMilliseconds; var updateInterval = Settings.TransferUpdateInterval; var buffer = new byte[bufferSize]; fileTransfer.Status = FileTransferStatus.InProgress; fileTransfer.TransferStartTime = DateTime.Now; EventOccurred?.Invoke(this, new ServerEvent { EventType = EventType.ReceiveFileBytesStarted, FileTransferId = fileTransfer.Id, RemoteServerIpAddress = fileTransfer.RemoteServerInfo.SessionIpAddress, RemoteServerPortNumber = fileTransfer.RemoteServerInfo.PortNumber, FileTransferStartTime = fileTransfer.TransferStartTime, FileName = fileTransfer.FileName, FileSizeInBytes = fileTransfer.FileSizeInBytes, LocalFolder = fileTransfer.LocalFolderPath, RetryCounter = fileTransfer.RetryCounter, RemoteServerRetryLimit = fileTransfer.RemoteServerRetryLimit }); var receiveCount = 0; fileTransfer.TotalBytesReceived = 0; fileTransfer.BytesRemaining = fileTransfer.FileSizeInBytes; fileTransfer.PercentComplete = 0; fileTransfer.InboundFileTransferStalled = false; if (unreadBytes.Length > 0) { fileTransfer.TotalBytesReceived += unreadBytes.Length; fileTransfer.BytesRemaining -= unreadBytes.Length; lock (FileLock) { var writeBytesToFile = FileHelper.WriteBytesToFile( fileTransfer.LocalFilePath, unreadBytes, unreadBytes.Length, 10); if (writeBytesToFile.Failure) { return(writeBytesToFile); } } EventOccurred?.Invoke(this, new ServerEvent { EventType = EventType.CopySavedBytesToIncomingFile, CurrentFileBytesReceived = unreadBytes.Length, TotalFileBytesReceived = fileTransfer.TotalBytesReceived, FileSizeInBytes = fileTransfer.FileSizeInBytes, FileBytesRemaining = fileTransfer.BytesRemaining, FileTransferId = fileTransfer.Id, }); } // Read file bytes from transfer socket until // 1. the entire file has been received OR // 2. Data is no longer being received OR // 3, Transfer is canceled var receivedZeroBytesFromSocket = false; while (!receivedZeroBytesFromSocket) { if (token.IsCancellationRequested) { fileTransfer.Status = FileTransferStatus.Cancelled; fileTransfer.TransferCompleteTime = DateTime.Now; fileTransfer.ErrorMessage = "Cancellation requested"; return(Result.Ok()); } var readFromSocket = await socket.ReceiveWithTimeoutAsync( buffer, 0, bufferSize, SocketFlags.None, timeoutMs) .ConfigureAwait(false); if (readFromSocket.Failure) { return(readFromSocket); } fileTransfer.CurrentBytesReceived = readFromSocket.Value; if (fileTransfer.CurrentBytesReceived == 0) { receivedZeroBytesFromSocket = true; continue; } var receivedBytes = new byte[fileTransfer.CurrentBytesReceived]; buffer.ToList().CopyTo(0, receivedBytes, 0, fileTransfer.CurrentBytesReceived); int fileWriteAttempts; lock (FileLock) { var writeBytesToFile = FileHelper.WriteBytesToFile( fileTransfer.LocalFilePath, receivedBytes, fileTransfer.CurrentBytesReceived, 999); if (writeBytesToFile.Failure) { return(writeBytesToFile); } fileWriteAttempts = writeBytesToFile.Value + 1; } receiveCount++; fileTransfer.TotalBytesReceived += fileTransfer.CurrentBytesReceived; fileTransfer.BytesRemaining -= fileTransfer.CurrentBytesReceived; var checkPercentComplete = fileTransfer.TotalBytesReceived / (float)fileTransfer.FileSizeInBytes; var changeSinceLastUpdate = checkPercentComplete - fileTransfer.PercentComplete; if (fileWriteAttempts > 1) { EventOccurred?.Invoke(this, new ServerEvent { EventType = EventType.MultipleFileWriteAttemptsNeeded, FileWriteAttempts = fileWriteAttempts, PercentComplete = fileTransfer.PercentComplete, FileTransferId = fileTransfer.Id, }); } // this event fires on every socket read event, which could be hurdreds of thousands // of times depending on the file size and buffer size. Since this event is only used // by myself when debugging small test files, I limited this event to only fire when // the size of the file will result in 10 socket read events at most. if (fileTransfer.FileSizeInBytes <= 10 * bufferSize) { SocketEventOccurred?.Invoke(this, new ServerEvent { EventType = EventType.ReceivedFileBytesFromSocket, SocketReadCount = receiveCount, BytesReceivedCount = fileTransfer.CurrentBytesReceived, CurrentFileBytesReceived = fileTransfer.CurrentBytesReceived, TotalFileBytesReceived = fileTransfer.TotalBytesReceived, FileSizeInBytes = fileTransfer.FileSizeInBytes, FileBytesRemaining = fileTransfer.BytesRemaining, PercentComplete = fileTransfer.PercentComplete, FileTransferId = fileTransfer.Id }); } // Report progress in intervals which are set by the user in the settings file if (changeSinceLastUpdate < updateInterval) { continue; } fileTransfer.PercentComplete = checkPercentComplete; FileTransferProgress?.Invoke(this, new ServerEvent { EventType = EventType.UpdateFileTransferProgress, TotalFileBytesReceived = fileTransfer.TotalBytesReceived, PercentComplete = fileTransfer.PercentComplete, FileTransferId = fileTransfer.Id }); } var fileTransferIsIncomplete = (fileTransfer.TotalBytesReceived / (float)fileTransfer.FileSizeInBytes) < 1; if (fileTransfer.InboundFileTransferStalled || fileTransferIsIncomplete) { const string fileTransferStalledErrorMessage = "Data is no longer bring received from remote client, file transfer has been canceled (ReceiveFileAsync)"; fileTransfer.Status = FileTransferStatus.Stalled; fileTransfer.ErrorMessage = fileTransferStalledErrorMessage; return(Result.Ok()); } fileTransfer.Status = FileTransferStatus.ConfirmedComplete; fileTransfer.TransferCompleteTime = DateTime.Now; fileTransfer.PercentComplete = 1; fileTransfer.CurrentBytesReceived = 0; fileTransfer.BytesRemaining = 0; EventOccurred?.Invoke(this, new ServerEvent { EventType = EventType.ReceiveFileBytesComplete, FileTransferStartTime = fileTransfer.TransferStartTime, FileTransferCompleteTime = DateTime.Now, FileSizeInBytes = fileTransfer.FileSizeInBytes, FileTransferRate = fileTransfer.TransferRate, RemoteServerIpAddress = fileTransfer.RemoteServerInfo.SessionIpAddress, RemoteServerPortNumber = fileTransfer.RemoteServerInfo.PortNumber, FileTransferId = fileTransfer.Id }); return(Result.Ok()); }
private void ProgressCalculator_FileTransferProgress(object sender, FileTransfer2ProgressEventArgs e) { FileTransferProgress?.Invoke(e); }
void HandleFileTransferProgress(object sender, ServerEvent serverEvent) { _eventLog.Add(serverEvent); FileTransferProgress?.Invoke(sender, serverEvent); }
public virtual async Task <Result> SendFileAsync(FileTransfer fileTransfer, Socket socket, CancellationToken token) { var bufferSize = Settings.SocketSettings.BufferSize; var timeoutMs = Settings.SocketSettings.SocketTimeoutInMilliseconds; var updateInterval = Settings.TransferUpdateInterval; fileTransfer.Status = FileTransferStatus.InProgress; fileTransfer.TransferStartTime = DateTime.Now; EventOccurred?.Invoke(this, new ServerEvent { EventType = EventType.SendFileBytesStarted, RemoteServerIpAddress = fileTransfer.RemoteServerInfo.SessionIpAddress, RemoteServerPortNumber = fileTransfer.RemoteServerInfo.PortNumber, FileTransferId = fileTransfer.Id }); fileTransfer.BytesRemaining = fileTransfer.FileSizeInBytes; fileTransfer.FileChunkSentCount = 0; fileTransfer.OutboundFileTransferStalled = false; using (var file = File.OpenRead(fileTransfer.LocalFilePath)) { while (fileTransfer.BytesRemaining > 0) { if (token.IsCancellationRequested) { fileTransfer.Status = FileTransferStatus.Cancelled; fileTransfer.TransferCompleteTime = DateTime.Now; fileTransfer.ErrorMessage = "Cancellation requested"; return(Result.Ok()); } var fileChunkSize = (int)Math.Min(bufferSize, fileTransfer.BytesRemaining); var buffer = new byte[fileChunkSize]; var numberOfBytesToSend = file.Read(buffer, 0, fileChunkSize); fileTransfer.BytesRemaining -= numberOfBytesToSend; var offset = 0; var socketSendCount = 0; while (numberOfBytesToSend > 0) { var sendFileChunkResult = await socket.SendWithTimeoutAsync( buffer, offset, fileChunkSize, SocketFlags.None, timeoutMs).ConfigureAwait(false); if (fileTransfer.OutboundFileTransferStalled) { const string fileTransferStalledErrorMessage = "Aborting file transfer, client says that data is no longer being received (SendFileBytesAsync)"; fileTransfer.Status = FileTransferStatus.Cancelled; fileTransfer.TransferCompleteTime = DateTime.Now; fileTransfer.ErrorMessage = fileTransferStalledErrorMessage; return(Result.Ok()); } if (sendFileChunkResult.Failure) { return(sendFileChunkResult); } fileTransfer.CurrentBytesSent = sendFileChunkResult.Value; numberOfBytesToSend -= fileTransfer.CurrentBytesSent; offset += fileTransfer.CurrentBytesSent; socketSendCount++; } fileTransfer.CurrentBytesSent = fileChunkSize; fileTransfer.FileChunkSentCount++; var checkPercentRemaining = fileTransfer.BytesRemaining / (float)fileTransfer.FileSizeInBytes; var checkPercentComplete = 1 - checkPercentRemaining; var changeSinceLastUpdate = checkPercentComplete - fileTransfer.PercentComplete; // this event fires on every file chunk sent event, which could be hurdreds of thousands // of times depending on the file size and buffer size. Since this event is only used // by myself when debugging small test files, I limited this event to only fire when // the size of the file will result in 10 file chunk sent events at most. if (fileTransfer.FileSizeInBytes <= 10 * bufferSize) { SocketEventOccurred?.Invoke(this, new ServerEvent { EventType = EventType.SentFileChunkToRemoteServer, FileSizeInBytes = fileTransfer.FileSizeInBytes, CurrentFileBytesSent = fileChunkSize, FileBytesRemaining = fileTransfer.BytesRemaining, FileChunkSentCount = fileTransfer.FileChunkSentCount, SocketSendCount = socketSendCount, FileTransferId = fileTransfer.Id }); } // Report progress in intervals which are set by the user in the settings file if (changeSinceLastUpdate < updateInterval) { continue; } fileTransfer.PercentComplete = checkPercentComplete; FileTransferProgress?.Invoke(this, new ServerEvent { EventType = EventType.UpdateFileTransferProgress, TotalFileBytesReceived = fileTransfer.TotalBytesReceived, PercentComplete = fileTransfer.PercentComplete, FileTransferId = fileTransfer.Id }); } fileTransfer.Status = FileTransferStatus.TransferComplete; fileTransfer.TransferCompleteTime = DateTime.Now; fileTransfer.PercentComplete = 1; fileTransfer.CurrentBytesSent = 0; fileTransfer.BytesRemaining = 0; EventOccurred?.Invoke(this, new ServerEvent { EventType = EventType.SendFileBytesComplete, RemoteServerIpAddress = fileTransfer.RemoteServerInfo.SessionIpAddress, RemoteServerPortNumber = fileTransfer.RemoteServerInfo.PortNumber, FileTransferId = fileTransfer.Id, }); return(Result.Ok()); } }
/// <param name="files">A list of Tuple(Relative directory path, StorageFile) objects.</param> public async Task <FileTransferResult> SendQueue(CancellationToken cancellationToken, List <Tuple <string, IFile> > files, string parentDirectoryName) { if ((ipFinderResult == null) || (ipFinderResult.Success == false)) { await Handshake(); if (ipFinderResult == null) { ipFinderResult = new IPDetectionCompletedEventArgs { Success = false, } } ; } if (ipFinderResult.Success == false) { return(FileTransferResult.FailedOnHandshake); } InitServer(); Dictionary <IFile, string> sFileKeyPairs = new Dictionary <IFile, string>(); IFileStats[] fs = new IFileStats[files.Count]; ulong totalSlices = 0; for (int i = 0; i < files.Count; i++) { var item = files[i]; var key = GenerateUniqueRandomKey(); fs[i] = await item.Item2.GetFileStats(); var slicesCount = (uint)Math.Ceiling(((double)fs[i].Length) / ((double)Constants.FileSliceMaxLength)); totalSlices += slicesCount; keyTable.Add(key, new FileDetails { storageFile = item.Item2, lastPieceAccessed = 0, lastSliceSize = (uint)((ulong)fs[i].Length % Constants.FileSliceMaxLength), lastSliceId = slicesCount - 1 }); sFileKeyPairs.Add(item.Item2, key); InitUrls(key, slicesCount); } var queueFinishKey = RandomFunctions.RandomString(15); server.AddResponseUrl("/" + queueFinishKey + "/finishQueue/", (Func <IWebServer, RequestDetails, string>)QueueFinished); System.Diagnostics.Debug.WriteLine("/" + queueFinishKey + "/finishQueue/"); queueFinishTcs = new TaskCompletionSource <string>(); fileSendTcs = null; ulong finishedSlices = 0; ClearInternalEventSubscribers(); FileTransferProgressInternal += (s, ee) => { FileTransferProgress?.Invoke(s, new FileTransferProgressEventArgs { State = ee.State, CurrentPart = finishedSlices + ee.CurrentPart, Total = totalSlices }); if (ee.State == FileTransferState.Finished) { finishedSlices += ee.Total; } }; cancellationToken.Register(() => { queueFinishTcs?.TrySetResult(TRANSFER_CANCELLED_MESSAGE); server?.Dispose(); }); if (await SendQueueInit(totalSlices, queueFinishKey, parentDirectoryName) == false) { return(FileTransferResult.FailedOnQueueInit); } bool infoSendResult = await SendQueueInfo(files, sFileKeyPairs, fs); return(await WaitQueueToFinish(cancellationToken)); }
public async Task <FileTransferResult> SendFile(CancellationToken cancellationToken, IFile file, string directory = "", bool isQueue = false) { if ((ipFinderResult == null) || (ipFinderResult.Success == false)) { await Handshake(); if (ipFinderResult == null) { ipFinderResult = new IPDetectionCompletedEventArgs { Success = false, } } ; } if (ipFinderResult.Success == false) { return(FileTransferResult.FailedOnHandshake); } InitServer(); var key = GenerateUniqueRandomKey(); var properties = await file.GetFileStats(); var slicesCount = (uint)Math.Ceiling(((double)properties.Length) / ((double)Constants.FileSliceMaxLength)); keyTable.Add(key, new FileDetails { storageFile = file, lastPieceAccessed = 0, lastSliceSize = (uint)((ulong)properties.Length % Constants.FileSliceMaxLength), lastSliceId = slicesCount - 1 }); InitUrls(key, slicesCount); queueFinishTcs = null; fileSendTcs = new TaskCompletionSource <string>(); ClearInternalEventSubscribers(); FileTransferProgressInternal += (s, ee) => { FileTransferProgress?.Invoke(s, ee); }; cancellationToken.Register(() => { fileSendTcs?.TrySetResult(TRANSFER_CANCELLED_MESSAGE); server?.Dispose(); }); if (!(await BeginSending(key, slicesCount, file.Name, properties, directory, false))) { return(FileTransferResult.FailedOnPrepare); } return(await WaitForFinish(cancellationToken)); }