public override void Execute() { _dataConnection = _connectionFactory.CreateDataConnection(DataConnectionType.Active); _dataConnection.Connection = _commandExecutorHelper.GetActiveDataConnection(FtpMessage); _dataConnectionListener = new TcpListener(ServerConnection.LocalEndPoint.Address, 0); _dataConnectionListener.Start(); IPEndPoint passiveListenerEndpoint = (IPEndPoint)_dataConnectionListener.LocalEndpoint; byte[] address = passiveListenerEndpoint.Address.GetAddressBytes(); short clientPort = (short)passiveListenerEndpoint.Port; byte[] clientPortArray = BitConverter.GetBytes(clientPort); if (BitConverter.IsLittleEndian) { Array.Reverse(clientPortArray); } int ipver; switch (passiveListenerEndpoint.AddressFamily) { case AddressFamily.InterNetwork: ipver = 1; break; case AddressFamily.InterNetworkV6: ipver = 2; break; default: throw new InvalidOperationException("The IP protocol being used is not supported."); } // созданы команды для двух типов подключения чтобы в случае когда сервер не поддерживает одну из них - использовать вторую FtpMessage portCommand = new FtpMessage( String.Format("PORT {0},{1},{2},{3},{4},{5}", address[0], address[1], address[2], address[3], clientPortArray[0], clientPortArray[1]), ServerConnection.Encoding); FtpMessage eprtCommand = new FtpMessage( String.Format("EPRT |{0}|{1}|{2}|", ipver, passiveListenerEndpoint.Address, passiveListenerEndpoint.Port), ServerConnection.Encoding); FtpMessage successfulResponce = new FtpMessage( String.Format("200 {0} command successful", FtpMessage.CommandName), ClientConnection.Encoding); List <IFtpMessage> messagesQueue = new List <IFtpMessage>(); if (FtpMessage.CommandName == ProcessingClientCommand.Port) { messagesQueue.Add(portCommand); messagesQueue.Add(eprtCommand); } else { messagesQueue.Add(eprtCommand); messagesQueue.Add(portCommand); } foreach (IFtpMessage message in messagesQueue) { IFtpMessage serverResponse = SendWithResponceServer(message); if (serverResponse.CommandType != ServerCommandType.Error) { SendToClient(successfulResponce); return; } } _dataConnectionListener.Stop(); _dataConnectionListener = null; SendToClient(new FtpMessage("451 can't open data connection", ClientConnection.Encoding)); }
public override void Execute() { _dataConnection = _connectionFactory.CreateDataConnection(DataConnectionType.Passive); List <FtpMessage> commandQueue = new List <FtpMessage>(); if (FtpMessage.CommandName == ProcessingClientCommand.Pasv) { commandQueue.Add(new FtpMessage(ProcessingClientCommand.Pasv, ServerConnection.Encoding)); commandQueue.Add(new FtpMessage(ProcessingClientCommand.Epsv, ServerConnection.Encoding)); } else { commandQueue.Add(new FtpMessage(ProcessingClientCommand.Epsv, ServerConnection.Encoding)); commandQueue.Add(new FtpMessage(ProcessingClientCommand.Pasv, ServerConnection.Encoding)); } string dataConnectionVersion = String.Empty; IFtpMessage serverResponce = null; foreach (FtpMessage message in commandQueue) { serverResponce = SendWithResponceServer(message); if (serverResponce.CommandType == ServerCommandType.Success) { dataConnectionVersion = message.CommandName; break; } } // Если не удалось установить соединение с сервером ни по одному из возможных типов соединения // обычному или расширенному - говорим клиенту, что соединение открыть с этим режимом нельзя if (String.IsNullOrEmpty(dataConnectionVersion)) { SendToClient(new FtpMessage("451 can't open data connection", ClientConnection.Encoding)); return; } _dataConnection.Connection = dataConnectionVersion == ProcessingClientCommand.Pasv ? _commandExecutorHelper.GetPasvDataConnection(serverResponce) : _commandExecutorHelper.GetEpsvDataConnection(serverResponce, ServerConnection.RemoteIpAddress); if (_dataConnection.Connection == null) { Logger.Log.Error(String.Format("Malformed PASV response: {0}:{1}", serverResponce, ClientConnection.IpAddress)); // Останавливаем на сервере ожидание подключения, т.к. не удалось получить адрес ServerConnection.SendCommand("ABOR can't parse pasv address"); ServerConnection.GetMessage(); SendToClient(new FtpMessage("451 can't open passive mode", ClientConnection.Encoding)); return; } // Открываем соединение данных с сервером _dataConnection.Connection.Connect(); //if (ServerConnection.DataEncryptionEnabled) //{ // _dataConnection.Connection.SetUpSecureConnectionAsClient(); //} _dataConnectionListener = new TcpListener(ClientConnection.IpAddress, 0); _dataConnectionListener.Start(); IPEndPoint passiveListenerEndpoint = (IPEndPoint)_dataConnectionListener.LocalEndpoint; // Для расширенного пассивного режима соедиенние и данные подготовлены, можно вернуть команду // Клиенту отдаем команду по тому типу режима, который он запросил, независимо // от того, какой установлен с сервером, иначе соединение будет оборвано клиентом if (FtpMessage.CommandName == ProcessingClientCommand.Epsv) { SendToClient(new FtpMessage( String.Format("229 Entering Extended Passive Mode (|||{0}|)", passiveListenerEndpoint.Port), ClientConnection.Encoding)); return; } // далее подготавливаются данные для ответа по обычному пассивному режиму. byte[] address = passiveListenerEndpoint.Address.GetAddressBytes(); short clientPort = (short)passiveListenerEndpoint.Port; byte[] clientPortArray = BitConverter.GetBytes(clientPort); if (BitConverter.IsLittleEndian) { Array.Reverse(clientPortArray); } SendToClient(new FtpMessage( String.Format("227 Entering Passive Mode ({0},{1},{2},{3},{4},{5})", address[0], address[1], address[2], address[3], clientPortArray[0], clientPortArray[1]), ClientConnection.Encoding)); }