示例#1
0
        // files must be a list to make the function predictable. (As we modify the FileSendInfo objects by calling their InitSlicingAsync() funciton)
        public async Task <FileTransferResult> Send(List <FileSendInfo> files, CancellationToken cancellationToken = default(CancellationToken))
        {
            IWebServer server = null;

            var transferProgress = new FileSendProgressCalculator(Constants.FileSliceMaxLength);

            transferProgress.FileTransferProgress += TransferProgress_FileTransferProgress;

            try
            {
                transferTcs = new TaskCompletionSource <FileTransferResult>();
                timeoutTcs  = new TaskCompletionSource <FileTransferResult>();
                var sessionKey = Guid.NewGuid().ToString();

                var myIp = await handshaker.Handshake(cancellationToken);

                if (myIp.Length == 0)
                {
                    return(FileTransferResult.FailedOnHandshake);
                }
                if (cancellationToken.IsCancellationRequested)
                {
                    return(FileTransferResult.Cancelled);
                }

                server = InitServer(myIp, Constants.CommunicationPort);
                await InitFileReceiveEndpoints(server, files, transferProgress, cancellationToken);
                await InitGenericEndpoints(server, sessionKey, myIp, files, cancellationToken);

                if (cancellationToken.IsCancellationRequested)
                {
                    return(FileTransferResult.Cancelled);
                }

                return(await SendFiles(sessionKey, myIp, transferProgress, cancellationToken));
            }
            finally
            {
                transferProgress.FileTransferProgress -= TransferProgress_FileTransferProgress;
                server?.Dispose();
            }
        }
示例#2
0
        private async Task InitFileReceiveEndpoints(IWebServer server, FileSendInfo fileInfo, FileSendProgressCalculator transferProgress)
        {
            await fileInfo.InitSlicingAsync();

            var fileSliceSender = new FileSliceSender(fileInfo);

            transferProgress.AddFileSliceSender(fileSliceSender);
            fileSliceSender.SliceRequested += transferProgress.SliceRequestReceived;

            for (int i = 0; i < fileInfo.SlicesCount; i++)
            {
                server.AddResponseUrl($"/{fileInfo.UniqueKey}/{i}/", (Func <IWebServer, RequestDetails, Task <byte[]> >)fileSliceSender.GetFileSlice);
            }
        }
示例#3
0
        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();
            }
        }
示例#4
0
        private async Task InitFileReceiveEndpoints(IWebServer server, IEnumerable <FileSendInfo> files, FileSendProgressCalculator transferProgress, CancellationToken cancellationToken = default(CancellationToken))
        {
            foreach (var item in files)
            {
                await InitFileReceiveEndpoints(server, item, transferProgress);

                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }
            }

            var list = files.ToList();
        }