private void OnUploadProgressAsync(UploadProgressEventArgs e)
 {
     var handler = this.UploadProgress;
     if (handler != null)
     {
         handler.BeginInvoke(this,
                             e,
                             handler.EndInvoke,
                             null);
     }
 }
        public async Task<bool> UploadAsync(Stream stream,
                                            FtpFile ftpFile,
                                            CancellationToken cancellationToken,
                                            bool createDirectoryIfNotExists = true)
        {
            using (await this._mutex.LockAsync(cancellationToken))
            {
                var controlComplexSocket = await this.EnsureConnectionAndAuthenticationAsync(cancellationToken);
                if (controlComplexSocket == null)
                {
                    return false;
                }

                {
                    var success = await this.GotoParentDirectoryAsync(controlComplexSocket,
                                                                      ftpFile,
                                                                      cancellationToken,
                                                                      createDirectoryIfNotExists);
                    if (!success)
                    {
                        return false;
                    }
                }

                // sending PASV
                // reading PASV
                var transferComplexSocket = await this.GetPassiveComplexSocketAsync(controlComplexSocket,
                                                                                    cancellationToken);
                if (transferComplexSocket == null)
                {
                    return false;
                }

                FtpReply ftpReply;
                using (transferComplexSocket)
                {
                    // sending STOR
                    // open transfer socket
                    // reading STOR (150 ...)
                    var success = await this.SendAndLogAsync(controlComplexSocket,
                                                             cancellationToken,
                                                             "STOR {0}",
                                                             ftpFile.FileName);
                    if (!success)
                    {
                        return false;
                    }

                    success = await transferComplexSocket.ConnectAsync(cancellationToken);
                    if (!success)
                    {
                        return false;
                    }

                    ftpReply = await this.ReceiveAndLogAsync(controlComplexSocket,
                                                             cancellationToken);
                    if (!ftpReply.Success)
                    {
                        return false;
                    }

                    {
                        // sending transfer socket
                        success = await transferComplexSocket.Socket.SendAsync(this.ChunkSendBufferSize,
                                                                               controlComplexSocket.GetSocketAsyncEventArgs,
                                                                               stream,
                                                                               cancellationToken,
                                                                               (bytesSent,
                                                                                bytesTotal) =>
                                                                               {
                                                                                   var uploadProgressEventArgs = new UploadProgressEventArgs(bytesSent,
                                                                                                                                             bytesTotal);
                                                                                   this.OnUploadProgressAsync(uploadProgressEventArgs);
                                                                               });
                        if (!success)
                        {
                            return false;
                        }
                    }
                }

                if (!ftpReply.Completed)
                {
                    // reading STOR (226 ...)
                    ftpReply = await this.ReceiveAndLogAsync(controlComplexSocket,
                                                             cancellationToken);
                    if (!ftpReply.Success)
                    {
                        return false;
                    }
                }
            }

            return true;
        }