internal FtpAuthenticationFailedEventArgs(ComplexSocket complexSocket,
                                                  string message)
        {
            Contract.Requires(complexSocket != null);

            this._complexSocket = complexSocket;
            this._message       = message;
        }
        protected BaseFtpCommandWithSocketEventArgsFailedEventArgs(SocketAsyncEventArgs socketAsyncEventArgs)
        {
            Contract.Requires(socketAsyncEventArgs != null);

            // TODO clear things out: is it a good idea to keep socketAsyncEventArgs in here, because we are firing off the using eventHandler asynchronously

            var userToken = socketAsyncEventArgs.UserToken;
            var socketAsyncEventArgsUserToken = (SocketAsyncEventArgsUserToken)userToken;

            this._complexSocket = socketAsyncEventArgsUserToken.ComplexSocket;
            this._timeout       = socketAsyncEventArgsUserToken.Timeout;
            this._exception     = socketAsyncEventArgs.ConnectByNameError;
            this._socketError   = socketAsyncEventArgs.SocketError;
            this._lastOperation = socketAsyncEventArgs.LastOperation;
        }
        internal static ComplexSocket CreateControlComplexSocket(this FtpClient ftpClient)
        {
            Contract.Requires(ftpClient != null);
            Contract.Requires(!String.IsNullOrEmpty(ftpClient.Server));

            // TODO add check for ftpClient.Port 0 - 0xffff

            var endPoint = new DnsEndPoint(ftpClient.Server,
                                           ftpClient.Port);

            var complexSocket = new ComplexSocket(ftpClient,
                                                  endPoint,
                                                  true);

            return(complexSocket);
        }
        internal static ComplexSocket CreateTransferComplexSocket(this FtpClient ftpClient,
                                                                  IPAddress ipAddress,
                                                                  int port)
        {
            Contract.Requires(ftpClient != null);
            Contract.Requires(ipAddress != null);

            // TODO add check for ftpClient.Port 0 - 0xffff

            var endPoint = new IPEndPoint(ipAddress,
                                          port);

            var complexSocket = new ComplexSocket(ftpClient,
                                                  endPoint,
                                                  false);

            return(complexSocket);
        }
        internal static bool Send(this ComplexSocket complexSocket,
                                  string command,
                                  Encoding encoding,
                                  TimeSpan timeout)
        {
            Contract.Requires(complexSocket != null);
            Contract.Requires(!string.IsNullOrEmpty(command));
            Contract.Requires(encoding != null);

            if (!command.EndsWith(Environment.NewLine))
            {
                command = string.Concat(command,
                                        Environment.NewLine);
            }

            var buffer = encoding.GetBytes(command);

            using (var memoryStream = new MemoryStream(buffer))
            {
                var success = complexSocket.Send(memoryStream,
                                                 timeout);
                return(success);
            }
        }
        internal static bool Authenticate(this ComplexSocket complexSocket,
                                          string username,
                                          string password,
                                          Encoding encoding,
                                          TimeSpan sendTimeout,
                                          TimeSpan receiveTimeout)
        {
            Contract.Requires(complexSocket != null);
            Contract.Requires(complexSocket.IsControlSocket);
            Contract.Requires(!string.IsNullOrEmpty(username));
            Contract.Requires(encoding != null);

            {
                var success = complexSocket.Send(string.Format("USER {0}",
                                                               username),
                                                 encoding,
                                                 sendTimeout);
                if (!success)
                {
                    return(false);
                }
            }
            {
                var complexResult = complexSocket.Receive(encoding,
                                                          receiveTimeout);
                if (complexResult.FtpResponseType == FtpResponseType.PositiveIntermediate)
                {
                    {
                        var success = complexSocket.Send(string.Format("PASS {0}",
                                                                       password),
                                                         encoding,
                                                         sendTimeout);
                        if (!success)
                        {
                            return(false);
                        }
                    }
                    {
                        complexResult = complexSocket.Receive(encoding,
                                                              receiveTimeout);
                        if (!complexResult.Success)
                        {
                            var message = string.Format("Could not authenticate with USER '{0}' and PASS '{1}'",
                                                        username,
                                                        password);
                            var ftpCommandFailedEventArgs = new FtpAuthenticationFailedEventArgs(complexSocket,
                                                                                                 message);
                            complexSocket.RaiseFtpCommandFailedAsync(ftpCommandFailedEventArgs);
                            return(false);
                        }
                    }
                }
                else if (!complexResult.Success)
                {
                    var message = string.Format("Could not authenticate with USER '{0}'",
                                                username);
                    var ftpCommandFailedEventArgs = new FtpAuthenticationFailedEventArgs(complexSocket,
                                                                                         message);
                    complexSocket.RaiseFtpCommandFailedAsync(ftpCommandFailedEventArgs);
                    return(false);
                }
            }

            return(true);
        }