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

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

Issue 895853003: Update from https://crrev.com/314320 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 10 months 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
« 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 last_error_(OK), 217 last_error_(OK),
218 system_type_(SYSTEM_TYPE_UNKNOWN), 218 system_type_(SYSTEM_TYPE_UNKNOWN),
219 // Use image (binary) transfer by default. It should always work, 219 // Use image (binary) transfer by default. It should always work,
220 // whereas the ascii transfer may damage binary data. 220 // whereas the ascii transfer may damage binary data.
221 data_type_(DATA_TYPE_IMAGE), 221 data_type_(DATA_TYPE_IMAGE),
222 resource_type_(RESOURCE_TYPE_UNKNOWN), 222 resource_type_(RESOURCE_TYPE_UNKNOWN),
223 use_epsv_(true), 223 use_epsv_(true),
224 data_connection_port_(0), 224 data_connection_port_(0),
225 socket_factory_(socket_factory), 225 socket_factory_(socket_factory),
226 next_state_(STATE_NONE), 226 next_state_(STATE_NONE),
227 state_after_data_connect_complete_(STATE_CTRL_WRITE_SIZE) {} 227 state_after_data_connect_complete_(STATE_NONE) {
228 }
228 229
229 FtpNetworkTransaction::~FtpNetworkTransaction() { 230 FtpNetworkTransaction::~FtpNetworkTransaction() {
230 } 231 }
231 232
232 int FtpNetworkTransaction::Stop(int error) { 233 int FtpNetworkTransaction::Stop(int error) {
233 if (command_sent_ == COMMAND_QUIT) 234 if (command_sent_ == COMMAND_QUIT)
234 return error; 235 return error;
235 236
236 next_state_ = STATE_CTRL_WRITE_QUIT; 237 next_state_ = STATE_CTRL_WRITE_QUIT;
237 last_error_ = error; 238 last_error_ = error;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 ctrl_response_buffer_.reset(new FtpCtrlResponseBuffer(net_log_)); 339 ctrl_response_buffer_.reset(new FtpCtrlResponseBuffer(net_log_));
339 read_data_buf_ = NULL; 340 read_data_buf_ = NULL;
340 read_data_buf_len_ = 0; 341 read_data_buf_len_ = 0;
341 if (write_buf_.get()) 342 if (write_buf_.get())
342 write_buf_->SetOffset(0); 343 write_buf_->SetOffset(0);
343 last_error_ = OK; 344 last_error_ = OK;
344 data_connection_port_ = 0; 345 data_connection_port_ = 0;
345 ctrl_socket_.reset(); 346 ctrl_socket_.reset();
346 data_socket_.reset(); 347 data_socket_.reset();
347 next_state_ = STATE_NONE; 348 next_state_ = STATE_NONE;
348 state_after_data_connect_complete_ = STATE_CTRL_WRITE_SIZE; 349 state_after_data_connect_complete_ = STATE_NONE;
349 } 350 }
350 351
351 void FtpNetworkTransaction::ResetDataConnectionAfterError(State next_state) { 352 void FtpNetworkTransaction::EstablishDataConnection(State state_after_connect) {
352 // The server _might_ have reset the data connection 353 DCHECK(state_after_connect == STATE_CTRL_WRITE_RETR ||
353 // (see RFC 959 3.2. ESTABLISHING DATA CONNECTIONS: 354 state_after_connect == STATE_CTRL_WRITE_LIST);
354 // "The server MUST close the data connection under the following 355 state_after_data_connect_complete_ = state_after_connect;
355 // conditions:
356 // ...
357 // 5. An irrecoverable error condition occurs.")
358 //
359 // It is ambiguous what an irrecoverable error condition is,
360 // so we take no chances.
361 state_after_data_connect_complete_ = next_state;
362 next_state_ = use_epsv_ ? STATE_CTRL_WRITE_EPSV : STATE_CTRL_WRITE_PASV; 356 next_state_ = use_epsv_ ? STATE_CTRL_WRITE_EPSV : STATE_CTRL_WRITE_PASV;
363 } 357 }
364 358
365 void FtpNetworkTransaction::DoCallback(int rv) { 359 void FtpNetworkTransaction::DoCallback(int rv) {
366 DCHECK(rv != ERR_IO_PENDING); 360 DCHECK(rv != ERR_IO_PENDING);
367 DCHECK(!user_callback_.is_null()); 361 DCHECK(!user_callback_.is_null());
368 362
369 // Since Run may result in Read being called, clear callback_ up front. 363 // Since Run may result in Read being called, clear callback_ up front.
370 CompletionCallback c = user_callback_; 364 CompletionCallback c = user_callback_;
371 user_callback_.Reset(); 365 user_callback_.Reset();
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after
937 next_state_ = STATE_CTRL_READ; 931 next_state_ = STATE_CTRL_READ;
938 return SendFtpCommand(command, command, COMMAND_TYPE); 932 return SendFtpCommand(command, command, COMMAND_TYPE);
939 } 933 }
940 934
941 int FtpNetworkTransaction::ProcessResponseTYPE( 935 int FtpNetworkTransaction::ProcessResponseTYPE(
942 const FtpCtrlResponse& response) { 936 const FtpCtrlResponse& response) {
943 switch (GetErrorClass(response.status_code)) { 937 switch (GetErrorClass(response.status_code)) {
944 case ERROR_CLASS_INITIATED: 938 case ERROR_CLASS_INITIATED:
945 return Stop(ERR_INVALID_RESPONSE); 939 return Stop(ERR_INVALID_RESPONSE);
946 case ERROR_CLASS_OK: 940 case ERROR_CLASS_OK:
947 next_state_ = use_epsv_ ? STATE_CTRL_WRITE_EPSV : STATE_CTRL_WRITE_PASV; 941 next_state_ = STATE_CTRL_WRITE_SIZE;
948 break; 942 break;
949 case ERROR_CLASS_INFO_NEEDED: 943 case ERROR_CLASS_INFO_NEEDED:
950 return Stop(ERR_INVALID_RESPONSE); 944 return Stop(ERR_INVALID_RESPONSE);
951 case ERROR_CLASS_TRANSIENT_ERROR: 945 case ERROR_CLASS_TRANSIENT_ERROR:
952 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); 946 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
953 case ERROR_CLASS_PERMANENT_ERROR: 947 case ERROR_CLASS_PERMANENT_ERROR:
954 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); 948 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
955 default: 949 default:
956 NOTREACHED(); 950 NOTREACHED();
957 return Stop(ERR_UNEXPECTED); 951 return Stop(ERR_UNEXPECTED);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1049 break; 1043 break;
1050 case ERROR_CLASS_OK: 1044 case ERROR_CLASS_OK:
1051 resource_type_ = RESOURCE_TYPE_FILE; 1045 resource_type_ = RESOURCE_TYPE_FILE;
1052 next_state_ = STATE_CTRL_WRITE_QUIT; 1046 next_state_ = STATE_CTRL_WRITE_QUIT;
1053 break; 1047 break;
1054 case ERROR_CLASS_INFO_NEEDED: 1048 case ERROR_CLASS_INFO_NEEDED:
1055 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); 1049 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
1056 case ERROR_CLASS_TRANSIENT_ERROR: 1050 case ERROR_CLASS_TRANSIENT_ERROR:
1057 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); 1051 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
1058 case ERROR_CLASS_PERMANENT_ERROR: 1052 case ERROR_CLASS_PERMANENT_ERROR:
1059 // Code 550 means "Failed to open file". Other codes are unrelated, 1053 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
1060 // like "Not logged in" etc.
1061 if (response.status_code != 550 || resource_type_ == RESOURCE_TYPE_FILE)
1062 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
1063
1064 // It's possible that RETR failed because the path is a directory.
1065 resource_type_ = RESOURCE_TYPE_DIRECTORY;
1066
1067 // We're going to try CWD next, but first send a PASV one more time,
1068 // because some FTP servers, including FileZilla, require that.
1069 // See http://crbug.com/25316.
1070 next_state_ = use_epsv_ ? STATE_CTRL_WRITE_EPSV : STATE_CTRL_WRITE_PASV;
1071 break;
1072 default: 1054 default:
1073 NOTREACHED(); 1055 NOTREACHED();
1074 return Stop(ERR_UNEXPECTED); 1056 return Stop(ERR_UNEXPECTED);
1075 } 1057 }
1076 1058
1077 // We should be sure about our resource type now. Otherwise we risk 1059 // We should be sure about our resource type now. Otherwise we risk
1078 // an infinite loop (RETR can later send CWD, and CWD can later send RETR). 1060 // an infinite loop (RETR can later send CWD, and CWD can later send RETR).
1079 DCHECK_NE(RESOURCE_TYPE_UNKNOWN, resource_type_); 1061 DCHECK_NE(RESOURCE_TYPE_UNKNOWN, resource_type_);
1080 1062
1081 return OK; 1063 return OK;
1082 } 1064 }
1083 1065
1084 // SIZE command 1066 // SIZE command
1085 int FtpNetworkTransaction::DoCtrlWriteSIZE() { 1067 int FtpNetworkTransaction::DoCtrlWriteSIZE() {
1086 std::string command = "SIZE " + GetRequestPathForFtpCommand(false); 1068 std::string command = "SIZE " + GetRequestPathForFtpCommand(false);
1087 next_state_ = STATE_CTRL_READ; 1069 next_state_ = STATE_CTRL_READ;
1088 return SendFtpCommand(command, command, COMMAND_SIZE); 1070 return SendFtpCommand(command, command, COMMAND_SIZE);
1089 } 1071 }
1090 1072
1091 int FtpNetworkTransaction::ProcessResponseSIZE( 1073 int FtpNetworkTransaction::ProcessResponseSIZE(
1092 const FtpCtrlResponse& response) { 1074 const FtpCtrlResponse& response) {
1093 State state_after_size;
1094 if (resource_type_ == RESOURCE_TYPE_FILE)
1095 state_after_size = STATE_CTRL_WRITE_RETR;
1096 else
1097 state_after_size = STATE_CTRL_WRITE_CWD;
1098
1099 switch (GetErrorClass(response.status_code)) { 1075 switch (GetErrorClass(response.status_code)) {
1100 case ERROR_CLASS_INITIATED: 1076 case ERROR_CLASS_INITIATED:
1101 next_state_ = state_after_size;
1102 break; 1077 break;
1103 case ERROR_CLASS_OK: 1078 case ERROR_CLASS_OK:
1104 if (response.lines.size() != 1) 1079 if (response.lines.size() != 1)
1105 return Stop(ERR_INVALID_RESPONSE); 1080 return Stop(ERR_INVALID_RESPONSE);
1106 int64 size; 1081 int64 size;
1107 if (!base::StringToInt64(response.lines[0], &size)) 1082 if (!base::StringToInt64(response.lines[0], &size))
1108 return Stop(ERR_INVALID_RESPONSE); 1083 return Stop(ERR_INVALID_RESPONSE);
1109 if (size < 0) 1084 if (size < 0)
1110 return Stop(ERR_INVALID_RESPONSE); 1085 return Stop(ERR_INVALID_RESPONSE);
1111 1086
1112 // A successful response to SIZE does not mean the resource is a file. 1087 // A successful response to SIZE does not mean the resource is a file.
1113 // Some FTP servers (for example, the qnx one) send a SIZE even for 1088 // Some FTP servers (for example, the qnx one) send a SIZE even for
1114 // directories. 1089 // directories.
1115 response_.expected_content_size = size; 1090 response_.expected_content_size = size;
1116
1117 next_state_ = state_after_size;
1118 break; 1091 break;
1119 case ERROR_CLASS_INFO_NEEDED: 1092 case ERROR_CLASS_INFO_NEEDED:
1120 next_state_ = state_after_size;
1121 break; 1093 break;
1122 case ERROR_CLASS_TRANSIENT_ERROR: 1094 case ERROR_CLASS_TRANSIENT_ERROR:
1123 ResetDataConnectionAfterError(state_after_size);
1124 break; 1095 break;
1125 case ERROR_CLASS_PERMANENT_ERROR: 1096 case ERROR_CLASS_PERMANENT_ERROR:
1126 // It's possible that SIZE failed because the path is a directory. 1097 // It's possible that SIZE failed because the path is a directory.
1127 if (resource_type_ == RESOURCE_TYPE_UNKNOWN && 1098 if (resource_type_ == RESOURCE_TYPE_UNKNOWN &&
1128 response.status_code != 550) { 1099 response.status_code != 550) {
1129 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); 1100 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
1130 } 1101 }
1131
1132 ResetDataConnectionAfterError(state_after_size);
1133 break; 1102 break;
1134 default: 1103 default:
1135 NOTREACHED(); 1104 NOTREACHED();
1136 return Stop(ERR_UNEXPECTED); 1105 return Stop(ERR_UNEXPECTED);
1137 } 1106 }
1138 1107 if (resource_type_ == RESOURCE_TYPE_FILE)
1108 EstablishDataConnection(STATE_CTRL_WRITE_RETR);
1109 else
1110 next_state_ = STATE_CTRL_WRITE_CWD;
1139 return OK; 1111 return OK;
1140 } 1112 }
1141 1113
1142 // CWD command 1114 // CWD command
1143 int FtpNetworkTransaction::DoCtrlWriteCWD() { 1115 int FtpNetworkTransaction::DoCtrlWriteCWD() {
1144 std::string command = "CWD " + GetRequestPathForFtpCommand(true); 1116 std::string command = "CWD " + GetRequestPathForFtpCommand(true);
1145 next_state_ = STATE_CTRL_READ; 1117 next_state_ = STATE_CTRL_READ;
1146 return SendFtpCommand(command, command, COMMAND_CWD); 1118 return SendFtpCommand(command, command, COMMAND_CWD);
1147 } 1119 }
1148 1120
1149 int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) { 1121 int FtpNetworkTransaction::ProcessResponseCWD(const FtpCtrlResponse& response) {
1150 // We should never issue CWD if we know the target resource is a file. 1122 // We should never issue CWD if we know the target resource is a file.
1151 DCHECK_NE(RESOURCE_TYPE_FILE, resource_type_); 1123 DCHECK_NE(RESOURCE_TYPE_FILE, resource_type_);
1152 1124
1153 switch (GetErrorClass(response.status_code)) { 1125 switch (GetErrorClass(response.status_code)) {
1154 case ERROR_CLASS_INITIATED: 1126 case ERROR_CLASS_INITIATED:
1155 return Stop(ERR_INVALID_RESPONSE); 1127 return Stop(ERR_INVALID_RESPONSE);
1156 case ERROR_CLASS_OK: 1128 case ERROR_CLASS_OK:
1157 next_state_ = STATE_CTRL_WRITE_LIST; 1129 EstablishDataConnection(STATE_CTRL_WRITE_LIST);
1158 break; 1130 break;
1159 case ERROR_CLASS_INFO_NEEDED: 1131 case ERROR_CLASS_INFO_NEEDED:
1160 return Stop(ERR_INVALID_RESPONSE); 1132 return Stop(ERR_INVALID_RESPONSE);
1161 case ERROR_CLASS_TRANSIENT_ERROR: 1133 case ERROR_CLASS_TRANSIENT_ERROR:
1162 // Some FTP servers send response 451 (not a valid CWD response according 1134 // Some FTP servers send response 451 (not a valid CWD response according
1163 // to RFC 959) instead of 550. 1135 // to RFC 959) instead of 550.
1164 if (response.status_code == 451) 1136 if (response.status_code == 451)
1165 return ProcessResponseCWDNotADirectory(); 1137 return ProcessResponseCWDNotADirectory();
1166 1138
1167 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code)); 1139 return Stop(GetNetErrorCodeForFtpResponseCode(response.status_code));
(...skipping 16 matching lines...) Expand all
1184 // says it's not true. The most probable interpretation is that it 1156 // says it's not true. The most probable interpretation is that it
1185 // doesn't exist (with FTP we can't be sure). 1157 // doesn't exist (with FTP we can't be sure).
1186 return Stop(ERR_FILE_NOT_FOUND); 1158 return Stop(ERR_FILE_NOT_FOUND);
1187 } 1159 }
1188 1160
1189 // We are here because SIZE failed and we are not sure what the resource 1161 // We are here because SIZE failed and we are not sure what the resource
1190 // type is. It could still be file, and SIZE could fail because of 1162 // type is. It could still be file, and SIZE could fail because of
1191 // an access error (http://crbug.com/56734). Try RETR just to be sure. 1163 // an access error (http://crbug.com/56734). Try RETR just to be sure.
1192 resource_type_ = RESOURCE_TYPE_FILE; 1164 resource_type_ = RESOURCE_TYPE_FILE;
1193 1165
1194 ResetDataConnectionAfterError(STATE_CTRL_WRITE_RETR); 1166 EstablishDataConnection(STATE_CTRL_WRITE_RETR);
1195 return OK; 1167 return OK;
1196 } 1168 }
1197 1169
1198 // LIST command 1170 // LIST command
1199 int FtpNetworkTransaction::DoCtrlWriteLIST() { 1171 int FtpNetworkTransaction::DoCtrlWriteLIST() {
1200 // Use the -l option for mod_ftp configured in LISTIsNLST mode: the option 1172 // Use the -l option for mod_ftp configured in LISTIsNLST mode: the option
1201 // forces LIST output instead of NLST (which would be ambiguous for us 1173 // forces LIST output instead of NLST (which would be ambiguous for us
1202 // to parse). 1174 // to parse).
1203 std::string command("LIST -l"); 1175 std::string command("LIST -l");
1204 if (system_type_ == SYSTEM_TYPE_VMS) 1176 if (system_type_ == SYSTEM_TYPE_VMS)
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
1403 if (!had_error_type[type]) { 1375 if (!had_error_type[type]) {
1404 had_error_type[type] = true; 1376 had_error_type[type] = true;
1405 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorHappened", 1377 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorHappened",
1406 type, NUM_OF_NET_ERROR_TYPES); 1378 type, NUM_OF_NET_ERROR_TYPES);
1407 } 1379 }
1408 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorCount", 1380 UMA_HISTOGRAM_ENUMERATION("Net.FtpDataConnectionErrorCount",
1409 type, NUM_OF_NET_ERROR_TYPES); 1381 type, NUM_OF_NET_ERROR_TYPES);
1410 } 1382 }
1411 1383
1412 } // namespace net 1384 } // 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