| Index: net/ftp/ftp_network_transaction.cc
|
| diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc
|
| index 1b5bd92f61465ce67121b137bb3bbd04c0f64450..272f49fbee8ed9316ffc916dd40b0318d2906f0a 100644
|
| --- a/net/ftp/ftp_network_transaction.cc
|
| +++ b/net/ftp/ftp_network_transaction.cc
|
| @@ -224,7 +224,8 @@ FtpNetworkTransaction::FtpNetworkTransaction(
|
| use_epsv_(true),
|
| data_connection_port_(0),
|
| socket_factory_(socket_factory),
|
| - next_state_(STATE_NONE) {
|
| + next_state_(STATE_NONE),
|
| + state_after_data_connect_complete_(STATE_CTRL_WRITE_SIZE) {
|
| }
|
|
|
| FtpNetworkTransaction::~FtpNetworkTransaction() {
|
| @@ -346,6 +347,21 @@ void FtpNetworkTransaction::ResetStateForRestart() {
|
| ctrl_socket_.reset();
|
| data_socket_.reset();
|
| next_state_ = STATE_NONE;
|
| + state_after_data_connect_complete_ = STATE_CTRL_WRITE_SIZE;
|
| +}
|
| +
|
| +void FtpNetworkTransaction::ResetDataConnectionAfterError(State next_state) {
|
| + // The server _might_ have reset the data connection
|
| + // (see RFC 959 3.2. ESTABLISHING DATA CONNECTIONS:
|
| + // "The server MUST close the data connection under the following
|
| + // conditions:
|
| + // ...
|
| + // 5. An irrecoverable error condition occurs.")
|
| + //
|
| + // It is ambiguous what an irrecoverable error condition is,
|
| + // so we take no chances.
|
| + state_after_data_connect_complete_ = next_state;
|
| + next_state_ = use_epsv_ ? STATE_CTRL_WRITE_EPSV : STATE_CTRL_WRITE_PASV;
|
| }
|
|
|
| void FtpNetworkTransaction::DoCallback(int rv) {
|
| @@ -1050,8 +1066,15 @@ int FtpNetworkTransaction::DoCtrlWriteSIZE() {
|
|
|
| int FtpNetworkTransaction::ProcessResponseSIZE(
|
| const FtpCtrlResponse& response) {
|
| + State state_after_size;
|
| + if (resource_type_ == RESOURCE_TYPE_FILE)
|
| + state_after_size = STATE_CTRL_WRITE_RETR;
|
| + else
|
| + state_after_size = STATE_CTRL_WRITE_CWD;
|
| +
|
| switch (GetErrorClass(response.status_code)) {
|
| case ERROR_CLASS_INITIATED:
|
| + next_state_ = state_after_size;
|
| break;
|
| case ERROR_CLASS_OK:
|
| if (response.lines.size() != 1)
|
| @@ -1066,10 +1089,14 @@ int FtpNetworkTransaction::ProcessResponseSIZE(
|
| // Some FTP servers (for example, the qnx one) send a SIZE even for
|
| // directories.
|
| response_.expected_content_size = size;
|
| +
|
| + next_state_ = state_after_size;
|
| break;
|
| case ERROR_CLASS_INFO_NEEDED:
|
| + next_state_ = state_after_size;
|
| break;
|
| case ERROR_CLASS_TRANSIENT_ERROR:
|
| + ResetDataConnectionAfterError(state_after_size);
|
| break;
|
| case ERROR_CLASS_PERMANENT_ERROR:
|
| // It's possible that SIZE failed because the path is a directory.
|
| @@ -1077,17 +1104,14 @@ int FtpNetworkTransaction::ProcessResponseSIZE(
|
| response.status_code != 550) {
|
| return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
|
| }
|
| +
|
| + ResetDataConnectionAfterError(state_after_size);
|
| break;
|
| default:
|
| NOTREACHED();
|
| return Stop(ERR_UNEXPECTED);
|
| }
|
|
|
| - if (resource_type_ == RESOURCE_TYPE_FILE)
|
| - next_state_ = STATE_CTRL_WRITE_RETR;
|
| - else
|
| - next_state_ = STATE_CTRL_WRITE_CWD;
|
| -
|
| return OK;
|
| }
|
|
|
| @@ -1142,8 +1166,8 @@ int FtpNetworkTransaction::ProcessResponseCWDNotADirectory() {
|
| // type is. It could still be file, and SIZE could fail because of
|
| // an access error (http://crbug.com/56734). Try RETR just to be sure.
|
| resource_type_ = RESOURCE_TYPE_FILE;
|
| - next_state_ = STATE_CTRL_WRITE_RETR;
|
|
|
| + ResetDataConnectionAfterError(STATE_CTRL_WRITE_RETR);
|
| return OK;
|
| }
|
|
|
| @@ -1239,7 +1263,7 @@ int FtpNetworkTransaction::DoDataConnectComplete(int result) {
|
| if (result != OK)
|
| return Stop(result);
|
|
|
| - next_state_ = STATE_CTRL_WRITE_SIZE;
|
| + next_state_ = state_after_data_connect_complete_;
|
| return OK;
|
| }
|
|
|
|
|