/// <summary>
        /// Transfers a file from the source FTP Server to the destination FTP Server via the FXP protocol asynchronously.
        /// </summary>
        private async Task <bool> TransferFileFXPInternalAsync(string sourcePath, FtpClient remoteClient, string remotePath, bool createRemoteDir, FtpRemoteExists existsMode,
                                                               IProgress <FtpProgress> progress, CancellationToken token, FtpProgress metaProgress)
        {
            FtpReply reply;
            long     offset     = 0;
            bool     fileExists = false;
            long     fileSize   = 0;

            var ftpFxpSession = await OpenPassiveFXPConnectionAsync(remoteClient, progress != null, token);

            if (ftpFxpSession != null)
            {
                try {
                    ftpFxpSession.SourceServer.ReadTimeout = (int)TimeSpan.FromMinutes(30.0).TotalMilliseconds;
                    ftpFxpSession.TargetServer.ReadTimeout = (int)TimeSpan.FromMinutes(30.0).TotalMilliseconds;


                    // check if the file exists, and skip, overwrite or append
                    if (existsMode == FtpRemoteExists.AppendNoCheck)
                    {
                        offset = await remoteClient.GetFileSizeAsync(remotePath, token);

                        if (offset == -1)
                        {
                            offset = 0;                             // start from the beginning
                        }
                    }
                    else
                    {
                        fileExists = await remoteClient.FileExistsAsync(remotePath, token);

                        switch (existsMode)
                        {
                        case FtpRemoteExists.Skip:

                            if (fileExists)
                            {
                                LogStatus(FtpTraceLevel.Info, "Skip is selected => Destination file exists => skipping");

                                //Fix #413 - progress callback isn't called if the file has already been uploaded to the server
                                //send progress reports
                                if (progress != null)
                                {
                                    progress.Report(new FtpProgress(100.0, 0, 0, TimeSpan.FromSeconds(0), sourcePath, remotePath, metaProgress));
                                }

                                return(true);
                            }

                            break;

                        case FtpRemoteExists.Overwrite:

                            if (fileExists)
                            {
                                await remoteClient.DeleteFileAsync(remotePath, token);
                            }

                            break;

                        case FtpRemoteExists.Append:

                            if (fileExists)
                            {
                                offset = await remoteClient.GetFileSizeAsync(remotePath, token);

                                if (offset == -1)
                                {
                                    offset = 0;                                             // start from the beginning
                                }
                            }

                            break;
                        }
                    }

                    fileSize = await GetFileSizeAsync(sourcePath, token);

                    // ensure the remote dir exists .. only if the file does not already exist!
                    if (createRemoteDir && !fileExists)
                    {
                        var dirname = remotePath.GetFtpDirectoryName();
                        if (!await remoteClient.DirectoryExistsAsync(dirname, token))
                        {
                            await remoteClient.CreateDirectoryAsync(dirname, token);
                        }
                    }

                    if (offset == 0 && existsMode != FtpRemoteExists.AppendNoCheck)
                    {
                        // send command to tell the source server to 'send' the file to the destination server
                        if (!(reply = await ftpFxpSession.SourceServer.ExecuteAsync($"RETR {sourcePath}", token)).Success)
                        {
                            throw new FtpCommandException(reply);
                        }

                        //Instruct destination server to store the file
                        if (!(reply = await ftpFxpSession.TargetServer.ExecuteAsync($"STOR {remotePath}", token)).Success)
                        {
                            throw new FtpCommandException(reply);
                        }
                    }
                    else
                    {
                        //tell source server to restart / resume
                        if (!(reply = await ftpFxpSession.SourceServer.ExecuteAsync($"REST {offset}", token)).Success)
                        {
                            throw new FtpCommandException(reply);
                        }

                        // send command to tell the source server to 'send' the file to the destination server
                        if (!(reply = await ftpFxpSession.SourceServer.ExecuteAsync($"RETR {sourcePath}", token)).Success)
                        {
                            throw new FtpCommandException(reply);
                        }

                        //Instruct destination server to append the file
                        if (!(reply = await ftpFxpSession.TargetServer.ExecuteAsync($"APPE {remotePath}", token)).Success)
                        {
                            throw new FtpCommandException(reply);
                        }
                    }

                    var  transferStarted = DateTime.Now;
                    long lastSize        = 0;


                    var sourceFXPTransferReply      = ftpFxpSession.SourceServer.GetReplyAsync(token);
                    var destinationFXPTransferReply = ftpFxpSession.TargetServer.GetReplyAsync(token);

                    // while the transfer is not complete
                    while (!sourceFXPTransferReply.IsCompleted || !destinationFXPTransferReply.IsCompleted)
                    {
                        // send progress reports every 1 second
                        if (ftpFxpSession.ProgressServer != null)
                        {
                            // send progress reports
                            if (progress != null && fileSize != -1)
                            {
                                offset = await ftpFxpSession.ProgressServer.GetFileSizeAsync(remotePath, token);

                                if (offset != -1 && lastSize <= offset)
                                {
                                    long bytesProcessed = offset - lastSize;
                                    lastSize = offset;
                                    ReportProgress(progress, fileSize, offset, bytesProcessed, DateTime.Now - transferStarted, sourcePath, remotePath, metaProgress);
                                }
                            }
                        }

                        await Task.Delay(FXPProgressInterval);
                    }

                    FtpTrace.WriteLine(FtpTraceLevel.Info, $"FXP transfer of file {sourcePath} has completed");

                    await NoopAsync(token);

                    await remoteClient.NoopAsync(token);

                    ftpFxpSession.Dispose();

                    return(true);
                }

                // Fix: catch all exceptions and dispose off the FTP clients if one occurs
                catch (Exception ex) {
                    ftpFxpSession.Dispose();
                    throw ex;
                }
            }
            else
            {
                FtpTrace.WriteLine(FtpTraceLevel.Error, "Failed to open FXP passive Connection");
                return(false);
            }
        }