Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: net/ftp/ftp_network_transaction.cc

Issue 11364224: FTP: Open a fresh data connection after a command error. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: nit Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/ftp/ftp_network_transaction.h ('k') | net/ftp/ftp_network_transaction_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/ftp/ftp_network_transaction.h" 5 #include "net/ftp/ftp_network_transaction.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 read_data_buf_len_(0), 217 read_data_buf_len_(0),
218 last_error_(OK), 218 last_error_(OK),
219 system_type_(SYSTEM_TYPE_UNKNOWN), 219 system_type_(SYSTEM_TYPE_UNKNOWN),
220 // Use image (binary) transfer by default. It should always work, 220 // Use image (binary) transfer by default. It should always work,
221 // whereas the ascii transfer may damage binary data. 221 // whereas the ascii transfer may damage binary data.
222 data_type_(DATA_TYPE_IMAGE), 222 data_type_(DATA_TYPE_IMAGE),
223 resource_type_(RESOURCE_TYPE_UNKNOWN), 223 resource_type_(RESOURCE_TYPE_UNKNOWN),
224 use_epsv_(true), 224 use_epsv_(true),
225 data_connection_port_(0), 225 data_connection_port_(0),
226 socket_factory_(socket_factory), 226 socket_factory_(socket_factory),
227 next_state_(STATE_NONE) { 227 next_state_(STATE_NONE),
228 state_after_data_connect_complete_(STATE_CTRL_WRITE_SIZE) {
228 } 229 }
229 230
230 FtpNetworkTransaction::~FtpNetworkTransaction() { 231 FtpNetworkTransaction::~FtpNetworkTransaction() {
231 } 232 }
232 233
233 int FtpNetworkTransaction::Stop(int error) { 234 int FtpNetworkTransaction::Stop(int error) {
234 if (command_sent_ == COMMAND_QUIT) 235 if (command_sent_ == COMMAND_QUIT)
235 return error; 236 return error;
236 237
237 next_state_ = STATE_CTRL_WRITE_QUIT; 238 next_state_ = STATE_CTRL_WRITE_QUIT;
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 ctrl_response_buffer_.reset(new FtpCtrlResponseBuffer(net_log_)); 340 ctrl_response_buffer_.reset(new FtpCtrlResponseBuffer(net_log_));
340 read_data_buf_ = NULL; 341 read_data_buf_ = NULL;
341 read_data_buf_len_ = 0; 342 read_data_buf_len_ = 0;
342 if (write_buf_) 343 if (write_buf_)
343 write_buf_->SetOffset(0); 344 write_buf_->SetOffset(0);
344 last_error_ = OK; 345 last_error_ = OK;
345 data_connection_port_ = 0; 346 data_connection_port_ = 0;
346 ctrl_socket_.reset(); 347 ctrl_socket_.reset();
347 data_socket_.reset(); 348 data_socket_.reset();
348 next_state_ = STATE_NONE; 349 next_state_ = STATE_NONE;
350 state_after_data_connect_complete_ = STATE_CTRL_WRITE_SIZE;
351 }
352
353 void FtpNetworkTransaction::ResetDataConnectionAfterError(State next_state) {
354 // The server _might_ have reset the data connection
355 // (see RFC 959 3.2. ESTABLISHING DATA CONNECTIONS:
356 // "The server MUST close the data connection under the following
357 // conditions:
358 // ...
359 // 5. An irrecoverable error condition occurs.")
360 //
361 // It is ambiguous what an irrecoverable error condition is,
362 // so we take no chances.
363 state_after_data_connect_complete_ = next_state;
364 next_state_ = use_epsv_ ? STATE_CTRL_WRITE_EPSV : STATE_CTRL_WRITE_PASV;
349 } 365 }
350 366
351 void FtpNetworkTransaction::DoCallback(int rv) { 367 void FtpNetworkTransaction::DoCallback(int rv) {
352 DCHECK(rv != ERR_IO_PENDING); 368 DCHECK(rv != ERR_IO_PENDING);
353 DCHECK(!user_callback_.is_null()); 369 DCHECK(!user_callback_.is_null());
354 370
355 // Since Run may result in Read being called, clear callback_ up front. 371 // Since Run may result in Read being called, clear callback_ up front.
356 CompletionCallback c = user_callback_; 372 CompletionCallback c = user_callback_;
357 user_callback_.Reset(); 373 user_callback_.Reset();
358 c.Run(rv); 374 c.Run(rv);
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 1059
1044 // SIZE command 1060 // SIZE command
1045 int FtpNetworkTransaction::DoCtrlWriteSIZE() { 1061 int FtpNetworkTransaction::DoCtrlWriteSIZE() {
1046 std::string command = "SIZE " + GetRequestPathForFtpCommand(false); 1062 std::string command = "SIZE " + GetRequestPathForFtpCommand(false);
1047 next_state_ = STATE_CTRL_READ; 1063 next_state_ = STATE_CTRL_READ;
1048 return SendFtpCommand(command, command, COMMAND_SIZE); 1064 return SendFtpCommand(command, command, COMMAND_SIZE);
1049 } 1065 }
1050 1066
1051 int FtpNetworkTransaction::ProcessResponseSIZE( 1067 int FtpNetworkTransaction::ProcessResponseSIZE(
1052 const FtpCtrlResponse& response) { 1068 const FtpCtrlResponse& response) {
1069 State state_after_size;
1070 if (resource_type_ == RESOURCE_TYPE_FILE)
1071 state_after_size = STATE_CTRL_WRITE_RETR;
1072 else
1073 state_after_size = STATE_CTRL_WRITE_CWD;
1074
1053 switch (GetErrorClass(response.status_code)) { 1075 switch (GetErrorClass(response.status_code)) {
1054 case ERROR_CLASS_INITIATED: 1076 case ERROR_CLASS_INITIATED:
1077 next_state_ = state_after_size;
1055 break; 1078 break;
1056 case ERROR_CLASS_OK: 1079 case ERROR_CLASS_OK:
1057 if (response.lines.size() != 1) 1080 if (response.lines.size() != 1)
1058 return Stop(ERR_INVALID_RESPONSE); 1081 return Stop(ERR_INVALID_RESPONSE);
1059 int64 size; 1082 int64 size;
1060 if (!base::StringToInt64(response.lines[0], &size)) 1083 if (!base::StringToInt64(response.lines[0], &size))
1061 return Stop(ERR_INVALID_RESPONSE); 1084 return Stop(ERR_INVALID_RESPONSE);
1062 if (size < 0) 1085 if (size < 0)
1063 return Stop(ERR_INVALID_RESPONSE); 1086 return Stop(ERR_INVALID_RESPONSE);
1064 1087
1065 // A successful response to SIZE does not mean the resource is a file. 1088 // A successful response to SIZE does not mean the resource is a file.
1066 // Some FTP servers (for example, the qnx one) send a SIZE even for 1089 // Some FTP servers (for example, the qnx one) send a SIZE even for
1067 // directories. 1090 // directories.
1068 response_.expected_content_size = size; 1091 response_.expected_content_size = size;
1092
1093 next_state_ = state_after_size;
1069 break; 1094 break;
1070 case ERROR_CLASS_INFO_NEEDED: 1095 case ERROR_CLASS_INFO_NEEDED:
1096 next_state_ = state_after_size;
1071 break; 1097 break;
1072 case ERROR_CLASS_TRANSIENT_ERROR: 1098 case ERROR_CLASS_TRANSIENT_ERROR:
1099 ResetDataConnectionAfterError(state_after_size);
1073 break; 1100 break;
1074 case ERROR_CLASS_PERMANENT_ERROR: 1101 case ERROR_CLASS_PERMANENT_ERROR:
1075 // It's possible that SIZE failed because the path is a directory. 1102 // It's possible that SIZE failed because the path is a directory.
1076 if (resource_type_ == RESOURCE_TYPE_UNKNOWN && 1103 if (resource_type_ == RESOURCE_TYPE_UNKNOWN &&
1077 response.status_code != 550) { 1104 response.status_code != 550) {
1078 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); 1105 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
1079 } 1106 }
1107
1108 ResetDataConnectionAfterError(state_after_size);
1080 break; 1109 break;
1081 default: 1110 default:
1082 NOTREACHED(); 1111 NOTREACHED();
1083 return Stop(ERR_UNEXPECTED); 1112 return Stop(ERR_UNEXPECTED);
1084 } 1113 }
1085 1114
1086 if (resource_type_ == RESOURCE_TYPE_FILE)
1087 next_state_ = STATE_CTRL_WRITE_RETR;
1088 else
1089 next_state_ = STATE_CTRL_WRITE_CWD;
1090
1091 return OK; 1115 return OK;
1092 } 1116 }
1093 1117
1094 // CWD command 1118 // CWD command
1095 int FtpNetworkTransaction::DoCtrlWriteCWD() { 1119 int FtpNetworkTransaction::DoCtrlWriteCWD() {
1096 std::string command = "CWD " + GetRequestPathForFtpCommand(true); 1120 std::string command = "CWD " + GetRequestPathForFtpCommand(true);
1097 next_state_ = STATE_CTRL_READ; 1121 next_state_ = STATE_CTRL_READ;
1098 return SendFtpCommand(command, command, COMMAND_CWD); 1122 return SendFtpCommand(command, command, COMMAND_CWD);
1099 } 1123 }
1100 1124
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1135 // We're assuming that the resource is a directory, but the server 1159 // We're assuming that the resource is a directory, but the server
1136 // says it's not true. The most probable interpretation is that it 1160 // says it's not true. The most probable interpretation is that it
1137 // doesn't exist (with FTP we can't be sure). 1161 // doesn't exist (with FTP we can't be sure).
1138 return Stop(ERR_FILE_NOT_FOUND); 1162 return Stop(ERR_FILE_NOT_FOUND);
1139 } 1163 }
1140 1164
1141 // We are here because SIZE failed and we are not sure what the resource 1165 // We are here because SIZE failed and we are not sure what the resource
1142 // type is. It could still be file, and SIZE could fail because of 1166 // type is. It could still be file, and SIZE could fail because of
1143 // an access error (http://crbug.com/56734). Try RETR just to be sure. 1167 // an access error (http://crbug.com/56734). Try RETR just to be sure.
1144 resource_type_ = RESOURCE_TYPE_FILE; 1168 resource_type_ = RESOURCE_TYPE_FILE;
1145 next_state_ = STATE_CTRL_WRITE_RETR;
1146 1169
1170 ResetDataConnectionAfterError(STATE_CTRL_WRITE_RETR);
1147 return OK; 1171 return OK;
1148 } 1172 }
1149 1173
1150 // LIST command 1174 // LIST command
1151 int FtpNetworkTransaction::DoCtrlWriteLIST() { 1175 int FtpNetworkTransaction::DoCtrlWriteLIST() {
1152 // Use the -l option for mod_ftp configured in LISTIsNLST mode: the option 1176 // Use the -l option for mod_ftp configured in LISTIsNLST mode: the option
1153 // forces LIST output instead of NLST (which would be ambiguous for us 1177 // forces LIST output instead of NLST (which would be ambiguous for us
1154 // to parse). 1178 // to parse).
1155 std::string command("LIST -l"); 1179 std::string command("LIST -l");
1156 if (system_type_ == SYSTEM_TYPE_VMS) 1180 if (system_type_ == SYSTEM_TYPE_VMS)
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1232 return OK; 1256 return OK;
1233 } 1257 }
1234 1258
1235 // Only record the connection error after we've applied all our fallbacks. 1259 // Only record the connection error after we've applied all our fallbacks.
1236 // We want to capture the final error, one we're not going to recover from. 1260 // We want to capture the final error, one we're not going to recover from.
1237 RecordDataConnectionError(result); 1261 RecordDataConnectionError(result);
1238 1262
1239 if (result != OK) 1263 if (result != OK)
1240 return Stop(result); 1264 return Stop(result);
1241 1265
1242 next_state_ = STATE_CTRL_WRITE_SIZE; 1266 next_state_ = state_after_data_connect_complete_;
1243 return OK; 1267 return OK;
1244 } 1268 }
1245 1269
1246 int FtpNetworkTransaction::DoDataRead() { 1270 int FtpNetworkTransaction::DoDataRead() {
1247 DCHECK(read_data_buf_); 1271 DCHECK(read_data_buf_);
1248 DCHECK_GT(read_data_buf_len_, 0); 1272 DCHECK_GT(read_data_buf_len_, 0);
1249 1273
1250 if (data_socket_ == NULL || !data_socket_->IsConnected()) { 1274 if (data_socket_ == NULL || !data_socket_->IsConnected()) {
1251 // If we don't destroy the data socket completely, some servers will wait 1275 // If we don't destroy the data socket completely, some servers will wait
1252 // for us (http://crbug.com/21127). The half-closed TCP connection needs 1276 // for us (http://crbug.com/21127). The half-closed TCP connection needs
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1354 if (!had_error_type[type]) { 1378 if (!had_error_type[type]) {
1355 had_error_type[type] = true; 1379 had_error_type[type] = true;
1356 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorHappened", 1380 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorHappened",
1357 type, NUM_OF_NET_ERROR_TYPES); 1381 type, NUM_OF_NET_ERROR_TYPES);
1358 } 1382 }
1359 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorCount", 1383 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorCount",
1360 type, NUM_OF_NET_ERROR_TYPES); 1384 type, NUM_OF_NET_ERROR_TYPES);
1361 } 1385 }
1362 1386
1363 } // namespace net 1387 } // namespace net
OLDNEW
« no previous file with comments | « net/ftp/ftp_network_transaction.h ('k') | net/ftp/ftp_network_transaction_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698