// Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this // source code is governed by a BSD-style license that can be found in the // LICENSE file. #ifndef NET_FTP_FTP_NETWORK_TRANSACTION_H_ #define NET_FTP_FTP_NETWORK_TRANSACTION_H_ #include #include #include #include #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "net/base/address_list.h" #include "net/base/host_resolver.h" #include "net/ftp/ftp_ctrl_response_buffer.h" #include "net/ftp/ftp_response_info.h" #include "net/ftp/ftp_transaction.h" namespace net { class ClientSocket; class ClientSocketFactory; class FtpNetworkSession; class FtpNetworkTransaction : public FtpTransaction { public: FtpNetworkTransaction(FtpNetworkSession* session, ClientSocketFactory* socket_factory); virtual ~FtpNetworkTransaction(); // FtpTransaction methods: virtual int Start(const FtpRequestInfo* request_info, CompletionCallback* callback, LoadLog* load_log); virtual int Stop(int error); virtual int RestartWithAuth(const std::wstring& username, const std::wstring& password, CompletionCallback* callback); virtual int RestartIgnoringLastError(CompletionCallback* callback); virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback); virtual const FtpResponseInfo* GetResponseInfo() const; virtual LoadState GetLoadState() const; virtual uint64 GetUploadProgress() const; private: enum Command { COMMAND_NONE, COMMAND_USER, COMMAND_PASS, COMMAND_ACCT, COMMAND_SYST, COMMAND_TYPE, COMMAND_PASV, COMMAND_PWD, COMMAND_SIZE, COMMAND_RETR, COMMAND_CWD, COMMAND_MLSD, COMMAND_LIST, COMMAND_MDTM, COMMAND_QUIT }; enum ErrorClass { // The requested action was initiated. The client should expect another // reply before issuing the next command. ERROR_CLASS_INITIATED, // The requested action has been successfully completed. ERROR_CLASS_OK, // The command has been accepted, but to complete the operation, more // information must be sent by the client. ERROR_CLASS_INFO_NEEDED, // The command was not accepted and the requested action did not take place. // This condition is temporary, and the client is encouraged to restart the // command sequence. ERROR_CLASS_TRANSIENT_ERROR, // The command was not accepted and the requested action did not take place. // This condition is rather permanent, and the client is discouraged from // repeating the exact request. ERROR_CLASS_PERMANENT_ERROR, }; // Major categories of remote system types, as returned by SYST command. enum SystemType { SYSTEM_TYPE_UNKNOWN, SYSTEM_TYPE_UNIX, SYSTEM_TYPE_WINDOWS, SYSTEM_TYPE_OS2, SYSTEM_TYPE_VMS, }; // Resets the members of the transaction so it can be restarted. void ResetStateForRestart(); void DoCallback(int result); void OnIOComplete(int result); // Executes correct ProcessResponse + command_name function based on last // issued command. Returns error code. int ProcessCtrlResponse(); int SendFtpCommand(const std::string& command, Command cmd); // Return the error class for given response code. You should validate the // code to be in range 100-599. static ErrorClass GetErrorClass(int response_code); // Returns request path suitable to be included in an FTP command. If the path // will be used as a directory, |is_directory| should be true. std::string GetRequestPathForFtpCommand(bool is_directory) const; // Runs the state transition loop. int DoLoop(int result); // Each of these methods corresponds to a State value. Those with an input // argument receive the result from the previous state. If a method returns // ERR_IO_PENDING, then the result from OnIOComplete will be passed to the // next state method as the result arg. int DoCtrlInit(); int DoCtrlInitComplete(int result); int DoCtrlResolveHost(); int DoCtrlResolveHostComplete(int result); int DoCtrlConnect(); int DoCtrlConnectComplete(int result); int DoCtrlRead(); int DoCtrlReadComplete(int result); int DoCtrlWrite(); int DoCtrlWriteComplete(int result); int DoCtrlWriteUSER(); int ProcessResponseUSER(const FtpCtrlResponse& response); int DoCtrlWritePASS(); int ProcessResponsePASS(const FtpCtrlResponse& response); int DoCtrlWriteACCT(); int ProcessResponseACCT(const FtpCtrlResponse& response); int DoCtrlWriteSYST(); int ProcessResponseSYST(const FtpCtrlResponse& response); int DoCtrlWritePWD(); int ProcessResponsePWD(const FtpCtrlResponse& response); int DoCtrlWriteTYPE(); int ProcessResponseTYPE(const FtpCtrlResponse& response); int DoCtrlWritePASV(); int ProcessResponsePASV(const FtpCtrlResponse& response); int DoCtrlWriteRETR(); int ProcessResponseRETR(const FtpCtrlResponse& response); int DoCtrlWriteSIZE(); int ProcessResponseSIZE(const FtpCtrlResponse& response); int DoCtrlWriteCWD(); int ProcessResponseCWD(const FtpCtrlResponse& response); int DoCtrlWriteMLSD(); int ProcessResponseMLSD(const FtpCtrlResponse& response); int DoCtrlWriteLIST(); int ProcessResponseLIST(const FtpCtrlResponse& response); int DoCtrlWriteMDTM(); int ProcessResponseMDTM(const FtpCtrlResponse& response); int DoCtrlWriteQUIT(); int ProcessResponseQUIT(const FtpCtrlResponse& response); int DoDataConnect(); int DoDataConnectComplete(int result); int DoDataRead(); int DoDataReadComplete(int result); void RecordDataConnectionError(int result); Command command_sent_; CompletionCallbackImpl io_callback_; CompletionCallback* user_callback_; scoped_refptr session_; scoped_refptr load_log_; const FtpRequestInfo* request_; FtpResponseInfo response_; // Cancels the outstanding request on destruction. SingleRequestHostResolver resolver_; AddressList addresses_; // User buffer passed to the Read method for control socket. scoped_refptr read_ctrl_buf_; scoped_ptr ctrl_response_buffer_; scoped_refptr read_data_buf_; int read_data_buf_len_; int file_data_len_; // Buffer holding the command line to be written to the control socket. scoped_refptr write_command_buf_; // Buffer passed to the Write method of control socket. It actually writes // to the write_command_buf_ at correct offset. scoped_refptr write_buf_; int last_error_; SystemType system_type_; // We get username and password as wstrings in RestartWithAuth, so they are // also kept as wstrings here. std::wstring username_; std::wstring password_; // Current directory on the remote server, as returned by last PWD command, // with any trailing slash removed. std::string current_remote_directory_; bool retr_failed_; int data_connection_port_; ClientSocketFactory* socket_factory_; scoped_ptr ctrl_socket_; scoped_ptr data_socket_; enum State { // Control connection states: STATE_CTRL_INIT, STATE_CTRL_INIT_COMPLETE, STATE_CTRL_RESOLVE_HOST, STATE_CTRL_RESOLVE_HOST_COMPLETE, STATE_CTRL_CONNECT, STATE_CTRL_CONNECT_COMPLETE, STATE_CTRL_READ, STATE_CTRL_READ_COMPLETE, STATE_CTRL_WRITE, STATE_CTRL_WRITE_COMPLETE, STATE_CTRL_WRITE_USER, STATE_CTRL_WRITE_PASS, STATE_CTRL_WRITE_ACCT, STATE_CTRL_WRITE_SYST, STATE_CTRL_WRITE_TYPE, STATE_CTRL_WRITE_PASV, STATE_CTRL_WRITE_PWD, STATE_CTRL_WRITE_RETR, STATE_CTRL_WRITE_SIZE, STATE_CTRL_WRITE_CWD, STATE_CTRL_WRITE_MLSD, STATE_CTRL_WRITE_LIST, STATE_CTRL_WRITE_MDTM, STATE_CTRL_WRITE_QUIT, // Data connection states: STATE_DATA_CONNECT, STATE_DATA_CONNECT_COMPLETE, STATE_DATA_READ, STATE_DATA_READ_COMPLETE, STATE_NONE }; State next_state_; }; } // namespace net #endif // NET_FTP_FTP_NETWORK_TRANSACTION_H_