1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef NET_FTP_FTP_NETWORK_TRANSACTION_H_
6#define NET_FTP_FTP_NETWORK_TRANSACTION_H_
7
8#include <string>
9#include <utility>
10
11#include "base/compiler_specific.h"
12#include "base/memory/ref_counted.h"
13#include "base/memory/scoped_ptr.h"
14#include "net/base/address_list.h"
15#include "net/base/auth.h"
16#include "net/base/net_log.h"
17#include "net/dns/host_resolver.h"
18#include "net/dns/single_request_host_resolver.h"
19#include "net/ftp/ftp_ctrl_response_buffer.h"
20#include "net/ftp/ftp_response_info.h"
21#include "net/ftp/ftp_transaction.h"
22
23namespace net {
24
25class ClientSocketFactory;
26class FtpNetworkSession;
27class StreamSocket;
28
29class NET_EXPORT_PRIVATE FtpNetworkTransaction : public FtpTransaction {
30 public:
31  FtpNetworkTransaction(FtpNetworkSession* session,
32                        ClientSocketFactory* socket_factory);
33  virtual ~FtpNetworkTransaction();
34
35  virtual int Stop(int error);
36  virtual int RestartIgnoringLastError(const CompletionCallback& callback);
37
38  // FtpTransaction methods:
39  virtual int Start(const FtpRequestInfo* request_info,
40                    const CompletionCallback& callback,
41                    const BoundNetLog& net_log) OVERRIDE;
42  virtual int RestartWithAuth(const AuthCredentials& credentials,
43                              const CompletionCallback& callback) OVERRIDE;
44  virtual int Read(IOBuffer* buf, int buf_len,
45                   const CompletionCallback& callback) OVERRIDE;
46  virtual const FtpResponseInfo* GetResponseInfo() const OVERRIDE;
47  virtual LoadState GetLoadState() const OVERRIDE;
48  virtual uint64 GetUploadProgress() const OVERRIDE;
49
50 private:
51  FRIEND_TEST_ALL_PREFIXES(FtpNetworkTransactionTest,
52                           DownloadTransactionEvilPasvUnsafeHost);
53
54  enum Command {
55    COMMAND_NONE,
56    COMMAND_USER,
57    COMMAND_PASS,
58    COMMAND_SYST,
59    COMMAND_TYPE,
60    COMMAND_EPSV,
61    COMMAND_PASV,
62    COMMAND_PWD,
63    COMMAND_SIZE,
64    COMMAND_RETR,
65    COMMAND_CWD,
66    COMMAND_LIST,
67    COMMAND_QUIT,
68  };
69
70  // Major categories of remote system types, as returned by SYST command.
71  enum SystemType {
72    SYSTEM_TYPE_UNKNOWN,
73    SYSTEM_TYPE_UNIX,
74    SYSTEM_TYPE_WINDOWS,
75    SYSTEM_TYPE_OS2,
76    SYSTEM_TYPE_VMS,
77  };
78
79  // Data representation type, see RFC 959 section 3.1.1. Data Types.
80  // We only support the two most popular data types.
81  enum DataType {
82    DATA_TYPE_ASCII,
83    DATA_TYPE_IMAGE,
84  };
85
86  // In FTP we need to issue different commands depending on whether a resource
87  // is a file or directory. If we don't know that, we're going to autodetect
88  // it.
89  enum ResourceType {
90    RESOURCE_TYPE_UNKNOWN,
91    RESOURCE_TYPE_FILE,
92    RESOURCE_TYPE_DIRECTORY,
93  };
94
95  enum State {
96    // Control connection states:
97    STATE_CTRL_RESOLVE_HOST,
98    STATE_CTRL_RESOLVE_HOST_COMPLETE,
99    STATE_CTRL_CONNECT,
100    STATE_CTRL_CONNECT_COMPLETE,
101    STATE_CTRL_READ,
102    STATE_CTRL_READ_COMPLETE,
103    STATE_CTRL_WRITE,
104    STATE_CTRL_WRITE_COMPLETE,
105    STATE_CTRL_WRITE_USER,
106    STATE_CTRL_WRITE_PASS,
107    STATE_CTRL_WRITE_SYST,
108    STATE_CTRL_WRITE_TYPE,
109    STATE_CTRL_WRITE_EPSV,
110    STATE_CTRL_WRITE_PASV,
111    STATE_CTRL_WRITE_PWD,
112    STATE_CTRL_WRITE_RETR,
113    STATE_CTRL_WRITE_SIZE,
114    STATE_CTRL_WRITE_CWD,
115    STATE_CTRL_WRITE_LIST,
116    STATE_CTRL_WRITE_QUIT,
117    // Data connection states:
118    STATE_DATA_CONNECT,
119    STATE_DATA_CONNECT_COMPLETE,
120    STATE_DATA_READ,
121    STATE_DATA_READ_COMPLETE,
122    STATE_NONE
123  };
124
125  // Resets the members of the transaction so it can be restarted.
126  void ResetStateForRestart();
127
128  // Resets the data connection after an error and switches to |next_state|.
129  void ResetDataConnectionAfterError(State next_state);
130
131  void DoCallback(int result);
132  void OnIOComplete(int result);
133
134  // Executes correct ProcessResponse + command_name function based on last
135  // issued command. Returns error code.
136  int ProcessCtrlResponse();
137
138  int SendFtpCommand(const std::string& command,
139                     const std::string& command_for_log,
140                     Command cmd);
141
142  // Returns request path suitable to be included in an FTP command. If the path
143  // will be used as a directory, |is_directory| should be true.
144  std::string GetRequestPathForFtpCommand(bool is_directory) const;
145
146  // See if the request URL contains a typecode and make us respect it.
147  void DetectTypecode();
148
149  // Runs the state transition loop.
150  int DoLoop(int result);
151
152  // Each of these methods corresponds to a State value.  Those with an input
153  // argument receive the result from the previous state.  If a method returns
154  // ERR_IO_PENDING, then the result from OnIOComplete will be passed to the
155  // next state method as the result arg.
156  int DoCtrlResolveHost();
157  int DoCtrlResolveHostComplete(int result);
158  int DoCtrlConnect();
159  int DoCtrlConnectComplete(int result);
160  int DoCtrlRead();
161  int DoCtrlReadComplete(int result);
162  int DoCtrlWrite();
163  int DoCtrlWriteComplete(int result);
164  int DoCtrlWriteUSER();
165  int ProcessResponseUSER(const FtpCtrlResponse& response);
166  int DoCtrlWritePASS();
167  int ProcessResponsePASS(const FtpCtrlResponse& response);
168  int DoCtrlWriteSYST();
169  int ProcessResponseSYST(const FtpCtrlResponse& response);
170  int DoCtrlWritePWD();
171  int ProcessResponsePWD(const FtpCtrlResponse& response);
172  int DoCtrlWriteTYPE();
173  int ProcessResponseTYPE(const FtpCtrlResponse& response);
174  int DoCtrlWriteEPSV();
175  int ProcessResponseEPSV(const FtpCtrlResponse& response);
176  int DoCtrlWritePASV();
177  int ProcessResponsePASV(const FtpCtrlResponse& response);
178  int DoCtrlWriteRETR();
179  int ProcessResponseRETR(const FtpCtrlResponse& response);
180  int DoCtrlWriteSIZE();
181  int ProcessResponseSIZE(const FtpCtrlResponse& response);
182  int DoCtrlWriteCWD();
183  int ProcessResponseCWD(const FtpCtrlResponse& response);
184  int ProcessResponseCWDNotADirectory();
185  int DoCtrlWriteLIST();
186  int ProcessResponseLIST(const FtpCtrlResponse& response);
187  int DoCtrlWriteQUIT();
188  int ProcessResponseQUIT(const FtpCtrlResponse& response);
189
190  int DoDataConnect();
191  int DoDataConnectComplete(int result);
192  int DoDataRead();
193  int DoDataReadComplete(int result);
194
195  void RecordDataConnectionError(int result);
196
197  Command command_sent_;
198
199  CompletionCallback io_callback_;
200  CompletionCallback user_callback_;
201
202  scoped_refptr<FtpNetworkSession> session_;
203
204  BoundNetLog net_log_;
205  const FtpRequestInfo* request_;
206  FtpResponseInfo response_;
207
208  // Cancels the outstanding request on destruction.
209  SingleRequestHostResolver resolver_;
210  AddressList addresses_;
211
212  // User buffer passed to the Read method for control socket.
213  scoped_refptr<IOBuffer> read_ctrl_buf_;
214
215  scoped_ptr<FtpCtrlResponseBuffer> ctrl_response_buffer_;
216
217  scoped_refptr<IOBuffer> read_data_buf_;
218  int read_data_buf_len_;
219
220  // Buffer holding the command line to be written to the control socket.
221  scoped_refptr<IOBufferWithSize> write_command_buf_;
222
223  // Buffer passed to the Write method of control socket. It actually writes
224  // to the write_command_buf_ at correct offset.
225  scoped_refptr<DrainableIOBuffer> write_buf_;
226
227  int last_error_;
228
229  SystemType system_type_;
230
231  // Data type to be used for the TYPE command.
232  DataType data_type_;
233
234  // Detected resource type (file or directory).
235  ResourceType resource_type_;
236
237  // Initially we favour EPSV over PASV for transfers but should any
238  // EPSV fail, we fall back to PASV for the duration of connection.
239  bool use_epsv_;
240
241  AuthCredentials credentials_;
242
243  // Current directory on the remote server, as returned by last PWD command,
244  // with any trailing slash removed.
245  std::string current_remote_directory_;
246
247  int data_connection_port_;
248
249  ClientSocketFactory* socket_factory_;
250
251  scoped_ptr<StreamSocket> ctrl_socket_;
252  scoped_ptr<StreamSocket> data_socket_;
253
254  State next_state_;
255
256  // State to switch to after data connection is complete.
257  State state_after_data_connect_complete_;
258};
259
260}  // namespace net
261
262#endif  // NET_FTP_FTP_NETWORK_TRANSACTION_H_
263