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

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

Issue 149043: Make new FtpNetworkTransaction handle short reads correctly.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: updated Created 11 years, 5 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 | 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) 2008 The Chromium Authors. All rights reserved. Use of this 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the 2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file. 3 // 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/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/string_util.h" 8 #include "base/string_util.h"
9 #include "net/base/connection_type_histograms.h" 9 #include "net/base/connection_type_histograms.h"
10 #include "net/base/net_errors.h" 10 #include "net/base/net_errors.h"
(...skipping 16 matching lines...) Expand all
27 FtpNetworkTransaction::FtpNetworkTransaction( 27 FtpNetworkTransaction::FtpNetworkTransaction(
28 FtpNetworkSession* session, 28 FtpNetworkSession* session,
29 ClientSocketFactory* socket_factory) 29 ClientSocketFactory* socket_factory)
30 : command_sent_(COMMAND_NONE), 30 : command_sent_(COMMAND_NONE),
31 ALLOW_THIS_IN_INITIALIZER_LIST( 31 ALLOW_THIS_IN_INITIALIZER_LIST(
32 io_callback_(this, &FtpNetworkTransaction::OnIOComplete)), 32 io_callback_(this, &FtpNetworkTransaction::OnIOComplete)),
33 user_callback_(NULL), 33 user_callback_(NULL),
34 session_(session), 34 session_(session),
35 request_(NULL), 35 request_(NULL),
36 resolver_(session->host_resolver()), 36 resolver_(session->host_resolver()),
37 read_ctrl_buf_size_(kCtrlBufLen), 37 response_message_buf_(new IOBufferWithSize(kCtrlBufLen)),
38 response_message_buf_len_(0), 38 response_message_buf_len_(0),
39 read_ctrl_buf_(new ReusedIOBuffer(response_message_buf_,
40 response_message_buf_->size())),
39 read_data_buf_len_(0), 41 read_data_buf_len_(0),
40 file_data_len_(0), 42 file_data_len_(0),
41 last_error_(OK), 43 last_error_(OK),
42 is_anonymous_(false), 44 is_anonymous_(false),
43 retr_failed_(false), 45 retr_failed_(false),
44 data_connection_port_(0), 46 data_connection_port_(0),
45 socket_factory_(socket_factory), 47 socket_factory_(socket_factory),
46 next_state_(STATE_NONE) { 48 next_state_(STATE_NONE) {
47 read_ctrl_buf_ = new IOBuffer(kCtrlBufLen);
48 response_message_buf_ = new IOBuffer(kCtrlBufLen);
49 } 49 }
50 50
51 FtpNetworkTransaction::~FtpNetworkTransaction() { 51 FtpNetworkTransaction::~FtpNetworkTransaction() {
52 } 52 }
53 53
54 int FtpNetworkTransaction::Start(const FtpRequestInfo* request_info, 54 int FtpNetworkTransaction::Start(const FtpRequestInfo* request_info,
55 CompletionCallback* callback) { 55 CompletionCallback* callback) {
56 request_ = request_info; 56 request_ = request_info;
57 57
58 next_state_ = STATE_CTRL_INIT; 58 next_state_ = STATE_CTRL_INIT;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 } 112 }
113 113
114 LoadState FtpNetworkTransaction::GetLoadState() const { 114 LoadState FtpNetworkTransaction::GetLoadState() const {
115 return LOAD_STATE_IDLE; 115 return LOAD_STATE_IDLE;
116 } 116 }
117 117
118 uint64 FtpNetworkTransaction::GetUploadProgress() const { 118 uint64 FtpNetworkTransaction::GetUploadProgress() const {
119 return 0; 119 return 0;
120 } 120 }
121 121
122 int FtpNetworkTransaction::ParseCtrlResponse(int* cut_pos) {
123 enum {
124 CODE, // Three-digit status code.
125 TEXT, // The text after code, not including the space after code.
126 ENDLINE, // We expect a CRLF at end of each line.
127 } scan_state = CODE;
128
129 *cut_pos = 0; // Index of first unparsed character.
130
131 // Store parsed code and text for current line.
132 int status_code = 0;
133 std::string status_text;
134
135 const char* data = response_message_buf_->data();
136 for (int i = 0; i < response_message_buf_len_; i++) {
137 switch (scan_state) {
138 case CODE:
139 if (data[i] == ' ' || data[i] == '\t') {
140 if (status_code < 100 || status_code > 599)
141 return ERR_INVALID_RESPONSE;
142 scan_state = TEXT;
143 break;
144 }
145 if (data[i] < '0' || data[i] > '9')
146 return ERR_INVALID_RESPONSE;
147 status_code = 10 * status_code + (data[i] - '0');
148 break;
149 case TEXT:
150 if (data[i] == '\r') {
151 scan_state = ENDLINE;
152 break;
153 }
154 status_text.push_back(data[i]);
155 break;
156 case ENDLINE:
157 if (data[i] != '\n')
158 return ERR_INVALID_RESPONSE;
159 ctrl_responses_.push(ResponseLine(status_code, status_text));
160 *cut_pos = i + 1;
161 scan_state = CODE;
162 break;
163 default:
164 NOTREACHED();
165 return ERR_UNEXPECTED;
166 }
167 }
168
169 return OK;
170 }
171
122 // Used to prepare and send FTP commad. 172 // Used to prepare and send FTP commad.
123 int FtpNetworkTransaction::SendFtpCommand(const std::string& command, 173 int FtpNetworkTransaction::SendFtpCommand(const std::string& command,
124 Command cmd) { 174 Command cmd) {
125 response_message_buf_len_ = 0; 175 response_message_buf_len_ = 0;
126 command_sent_ = cmd; 176 command_sent_ = cmd;
127 DLOG(INFO) << " >> " << command; 177 DLOG(INFO) << " >> " << command;
128 const char* buf = command.c_str(); 178 const char* buf = command.c_str();
129 int buf_len = command.size(); 179 int buf_len = command.size();
130 DCHECK(!write_buf_); 180 DCHECK(!write_buf_);
131 write_buf_ = new IOBuffer(buf_len + 2); 181 write_buf_ = new IOBuffer(buf_len + 2);
132 memcpy(write_buf_->data(), buf, buf_len); 182 memcpy(write_buf_->data(), buf, buf_len);
133 memcpy(write_buf_->data() + buf_len, kCRLF, 2); 183 memcpy(write_buf_->data() + buf_len, kCRLF, 2);
134 buf_len += 2; 184 buf_len += 2;
135 185
136 return ctrl_socket_->Write(write_buf_, buf_len, &io_callback_); 186 return ctrl_socket_->Write(write_buf_, buf_len, &io_callback_);
137 } 187 }
138 188
139 int FtpNetworkTransaction::GetRespnseCode() { 189 int FtpNetworkTransaction::ProcessCtrlResponses() {
140 std::string str(response_message_buf_->data(), 3); 190 int rv = OK;
141 return StringToInt(str); 191 if (command_sent_ == COMMAND_NONE) {
142 } 192 while (!ctrl_responses_.empty()) {
193 ResponseLine line = ctrl_responses_.front();
194 ctrl_responses_.pop();
195 if (GetErrorClass(line.code) != ERROR_CLASS_OK)
196 return Stop(ERR_FAILED);
197 }
198 next_state_ = STATE_CTRL_WRITE_USER;
199 return rv;
200 }
143 201
144 int FtpNetworkTransaction::ProcessResponse(int response_code) { 202 // TODO(phajdan.jr): Correctly handle multiple code 230 response lines after
145 int rv = OK; 203 // PASS command.
204 if (ctrl_responses_.size() != 1)
205 return Stop(ERR_INVALID_RESPONSE);
206
207 ResponseLine response_line = ctrl_responses_.front();
208 ctrl_responses_.pop();
209
146 switch (command_sent_) { 210 switch (command_sent_) {
147 case COMMAND_NONE:
148 next_state_ = STATE_CTRL_WRITE_USER;
149 break;
150 case COMMAND_USER: 211 case COMMAND_USER:
151 rv = ProcessResponseUSER(response_code); 212 rv = ProcessResponseUSER(response_line);
152 break; 213 break;
153 case COMMAND_PASS: 214 case COMMAND_PASS:
154 rv = ProcessResponsePASS(response_code); 215 rv = ProcessResponsePASS(response_line);
155 break; 216 break;
156 case COMMAND_ACCT: 217 case COMMAND_ACCT:
157 rv = ProcessResponseACCT(response_code); 218 rv = ProcessResponseACCT(response_line);
158 break; 219 break;
159 case COMMAND_SYST: 220 case COMMAND_SYST:
160 rv = ProcessResponseSYST(response_code); 221 rv = ProcessResponseSYST(response_line);
161 break; 222 break;
162 case COMMAND_PWD: 223 case COMMAND_PWD:
163 rv = ProcessResponsePWD(response_code); 224 rv = ProcessResponsePWD(response_line);
164 break; 225 break;
165 case COMMAND_TYPE: 226 case COMMAND_TYPE:
166 rv = ProcessResponseTYPE(response_code); 227 rv = ProcessResponseTYPE(response_line);
167 break; 228 break;
168 case COMMAND_PASV: 229 case COMMAND_PASV:
169 rv = ProcessResponsePASV(response_code); 230 rv = ProcessResponsePASV(response_line);
170 break; 231 break;
171 case COMMAND_SIZE: 232 case COMMAND_SIZE:
172 rv = ProcessResponseSIZE(response_code); 233 rv = ProcessResponseSIZE(response_line);
173 break; 234 break;
174 case COMMAND_RETR: 235 case COMMAND_RETR:
175 rv = ProcessResponseRETR(response_code); 236 rv = ProcessResponseRETR(response_line);
176 break; 237 break;
177 case COMMAND_CWD: 238 case COMMAND_CWD:
178 rv = ProcessResponseCWD(response_code); 239 rv = ProcessResponseCWD(response_line);
179 break; 240 break;
180 case COMMAND_LIST: 241 case COMMAND_LIST:
181 rv = ProcessResponseLIST(response_code); 242 rv = ProcessResponseLIST(response_line);
182 break; 243 break;
183 case COMMAND_MDTM: 244 case COMMAND_MDTM:
184 rv = ProcessResponseMDTM(response_code); 245 rv = ProcessResponseMDTM(response_line);
185 break; 246 break;
186 case COMMAND_QUIT: 247 case COMMAND_QUIT:
187 rv = ProcessResponseQUIT(response_code); 248 rv = ProcessResponseQUIT(response_line);
188 break; 249 break;
189 default: 250 default:
190 DLOG(INFO) << "Missing Command response handling!"; 251 DLOG(INFO) << "Missing Command response handling!";
191 return ERR_FAILED; 252 return ERR_FAILED;
192 } 253 }
254 DCHECK(ctrl_responses_.empty());
193 return rv; 255 return rv;
194 } 256 }
195 257
196 void FtpNetworkTransaction::DoCallback(int rv) { 258 void FtpNetworkTransaction::DoCallback(int rv) {
197 DCHECK(rv != ERR_IO_PENDING); 259 DCHECK(rv != ERR_IO_PENDING);
198 DCHECK(user_callback_); 260 DCHECK(user_callback_);
199 261
200 // Since Run may result in Read being called, clear callback_ up front. 262 // Since Run may result in Read being called, clear callback_ up front.
201 CompletionCallback* c = user_callback_; 263 CompletionCallback* c = user_callback_;
202 user_callback_ = NULL; 264 user_callback_ = NULL;
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 next_state_ = STATE_CTRL_READ; 435 next_state_ = STATE_CTRL_READ;
374 return result; 436 return result;
375 } 437 }
376 438
377 int FtpNetworkTransaction::DoCtrlRead() { 439 int FtpNetworkTransaction::DoCtrlRead() {
378 if (write_buf_) // Clear the write buffer 440 if (write_buf_) // Clear the write buffer
379 write_buf_ = NULL; 441 write_buf_ = NULL;
380 442
381 next_state_ = STATE_CTRL_READ_COMPLETE; 443 next_state_ = STATE_CTRL_READ_COMPLETE;
382 read_ctrl_buf_->data()[0] = 0; 444 read_ctrl_buf_->data()[0] = 0;
383 return ctrl_socket_->Read(read_ctrl_buf_, read_ctrl_buf_size_ - 1, 445 return ctrl_socket_->Read(
384 &io_callback_); 446 read_ctrl_buf_,
447 response_message_buf_->size() - response_message_buf_len_,
448 &io_callback_);
385 } 449 }
386 450
387 int FtpNetworkTransaction::DoCtrlReadComplete(int result) { 451 int FtpNetworkTransaction::DoCtrlReadComplete(int result) {
388 if (result < 0) 452 if (result < 0)
389 return Stop(ERR_FAILED); 453 return Stop(ERR_FAILED);
390 int response_code;
391 // Null termination added, now we can treat this as string.
392 read_ctrl_buf_->data()[result] = 0;
393 memcpy(response_message_buf_->data() + response_message_buf_len_,
394 read_ctrl_buf_->data(), result);
395 454
396 response_message_buf_len_ = response_message_buf_len_ + result; 455 response_message_buf_len_ += result;
397 for (int i = 0; i < response_message_buf_len_; i++) { 456
398 if (response_message_buf_->data()[i] == '\r' && 457 int cut_pos;
399 response_message_buf_->data()[i + 1] == '\n') { 458 int rv = ParseCtrlResponse(&cut_pos);
400 if (response_message_buf_len_ > 3 && 459
401 response_message_buf_->data()[3] == ' ') { 460 if (rv != OK)
402 response_message_buf_->data()[response_message_buf_len_ - 2] = 0; 461 return Stop(rv);
eroman 2009/07/02 22:56:48 I am not excited about the use of Stop() in this f
403 response_code = GetRespnseCode(); 462
404 return ProcessResponse(response_code); 463 if (cut_pos > 0) {
405 } 464 // Parsed at least one response line.
406 response_message_buf_len_ -= (i + 2); 465 memmove(response_message_buf_->data(),
407 memcpy(response_message_buf_->data(), 466 response_message_buf_->data() + cut_pos,
408 response_message_buf_->data() + i + 2, 467 response_message_buf_len_ - cut_pos);
eroman 2009/07/02 22:56:48 Can you add: DCHECK_GE(response_message_buf_len_,
409 response_message_buf_len_); 468 response_message_buf_len_ -= cut_pos;
410 i = 0; 469
411 } 470 rv = ProcessCtrlResponses();
471 } else {
472 // Incomplete response line. Read more.
473 next_state_ = STATE_CTRL_READ;
412 } 474 }
413 next_state_ = STATE_CTRL_READ; 475
414 return OK; 476 read_ctrl_buf_->SetOffset(response_message_buf_len_);
477
478 return rv;
415 } 479 }
416 480
417 // FTP Commands and responses 481 // FTP Commands and responses
418 482
419 // USER Command. 483 // USER Command.
420 int FtpNetworkTransaction::DoCtrlWriteUSER() { 484 int FtpNetworkTransaction::DoCtrlWriteUSER() {
421 std::string command = "USER"; 485 std::string command = "USER";
422 if (request_->url.has_username()) { 486 if (request_->url.has_username()) {
423 command.append(" "); 487 command.append(" ");
424 command.append(request_->url.username()); 488 command.append(request_->url.username());
425 } else { 489 } else {
426 is_anonymous_ = true; 490 is_anonymous_ = true;
427 command.append(" anonymous"); 491 command.append(" anonymous");
428 } 492 }
429 next_state_ = STATE_CTRL_READ; 493 next_state_ = STATE_CTRL_READ;
430 return SendFtpCommand(command, COMMAND_USER); 494 return SendFtpCommand(command, COMMAND_USER);
431 } 495 }
432 496
433 int FtpNetworkTransaction::ProcessResponseUSER(int response_code) { 497 int FtpNetworkTransaction::ProcessResponseUSER(const ResponseLine& response) {
434 switch (GetErrorClass(response_code)) { 498 switch (GetErrorClass(response.code)) {
435 case ERROR_CLASS_OK: 499 case ERROR_CLASS_OK:
436 next_state_ = STATE_CTRL_WRITE_SYST; 500 next_state_ = STATE_CTRL_WRITE_SYST;
437 break; 501 break;
438 case ERROR_CLASS_PENDING: 502 case ERROR_CLASS_PENDING:
439 next_state_ = STATE_CTRL_WRITE_PASS; 503 next_state_ = STATE_CTRL_WRITE_PASS;
440 break; 504 break;
441 case ERROR_CLASS_ERROR_RETRY: 505 case ERROR_CLASS_ERROR_RETRY:
442 if (response_code == 421) 506 if (response.code == 421)
443 return Stop(ERR_FAILED); 507 return Stop(ERR_FAILED);
444 break; 508 break;
445 case ERROR_CLASS_ERROR: 509 case ERROR_CLASS_ERROR:
446 return Stop(ERR_FAILED); 510 return Stop(ERR_FAILED);
447 default: 511 default:
448 return Stop(ERR_FAILED); 512 return Stop(ERR_FAILED);
449 } 513 }
450 return OK; 514 return OK;
451 } 515 }
452 516
453 // PASS command. 517 // PASS command.
454 int FtpNetworkTransaction::DoCtrlWritePASS() { 518 int FtpNetworkTransaction::DoCtrlWritePASS() {
455 std::string command = "PASS"; 519 std::string command = "PASS";
456 if (request_->url.has_password()) { 520 if (request_->url.has_password()) {
457 command.append(" "); 521 command.append(" ");
458 command.append(request_->url.password()); 522 command.append(request_->url.password());
459 } else { 523 } else {
460 command.append(" "); 524 command.append(" ");
461 command.append("chrome@example.com"); 525 command.append("chrome@example.com");
462 } 526 }
463 next_state_ = STATE_CTRL_READ; 527 next_state_ = STATE_CTRL_READ;
464 return SendFtpCommand(command, COMMAND_PASS); 528 return SendFtpCommand(command, COMMAND_PASS);
465 } 529 }
466 530
467 int FtpNetworkTransaction::ProcessResponsePASS(int response_code) { 531 int FtpNetworkTransaction::ProcessResponsePASS(const ResponseLine& response) {
468 switch (GetErrorClass(response_code)) { 532 switch (GetErrorClass(response.code)) {
469 case ERROR_CLASS_OK: 533 case ERROR_CLASS_OK:
470 next_state_ = STATE_CTRL_WRITE_SYST; 534 next_state_ = STATE_CTRL_WRITE_SYST;
471 break; 535 break;
472 case ERROR_CLASS_PENDING: 536 case ERROR_CLASS_PENDING:
473 next_state_ = STATE_CTRL_WRITE_ACCT; 537 next_state_ = STATE_CTRL_WRITE_ACCT;
474 break; 538 break;
475 case ERROR_CLASS_ERROR_RETRY: 539 case ERROR_CLASS_ERROR_RETRY:
476 if (response_code == 421) { 540 if (response.code == 421) {
477 // TODO(ibrar): Retry here. 541 // TODO(ibrar): Retry here.
478 } 542 }
479 return Stop(ERR_FAILED); 543 return Stop(ERR_FAILED);
480 case ERROR_CLASS_ERROR: 544 case ERROR_CLASS_ERROR:
481 if (response_code == 503) { 545 if (response.code == 503) {
482 next_state_ = STATE_CTRL_WRITE_USER; 546 next_state_ = STATE_CTRL_WRITE_USER;
483 } else { 547 } else {
484 // TODO(ibrar): Retry here. 548 // TODO(ibrar): Retry here.
485 return Stop(ERR_FAILED); 549 return Stop(ERR_FAILED);
486 } 550 }
487 break; 551 break;
488 default: 552 default:
489 return Stop(ERR_FAILED); 553 return Stop(ERR_FAILED);
490 } 554 }
491 return OK; 555 return OK;
492 } 556 }
493 557
494 // SYST command. 558 // SYST command.
495 int FtpNetworkTransaction::DoCtrlWriteSYST() { 559 int FtpNetworkTransaction::DoCtrlWriteSYST() {
496 std::string command = "SYST"; 560 std::string command = "SYST";
497 next_state_ = STATE_CTRL_READ; 561 next_state_ = STATE_CTRL_READ;
498 return SendFtpCommand(command, COMMAND_SYST); 562 return SendFtpCommand(command, COMMAND_SYST);
499 } 563 }
500 564
501 int FtpNetworkTransaction::ProcessResponseSYST(int response_code) { 565 int FtpNetworkTransaction::ProcessResponseSYST(const ResponseLine& response) {
502 switch (GetErrorClass(response_code)) { 566 switch (GetErrorClass(response.code)) {
503 case ERROR_CLASS_INITIATED: 567 case ERROR_CLASS_INITIATED:
504 return Stop(ERR_FAILED); 568 return Stop(ERR_FAILED);
505 case ERROR_CLASS_OK: 569 case ERROR_CLASS_OK:
506 // TODO(ibrar): Process SYST response properly. 570 // TODO(ibrar): Process SYST response properly.
507 next_state_ = STATE_CTRL_WRITE_PWD; 571 next_state_ = STATE_CTRL_WRITE_PWD;
508 break; 572 break;
509 case ERROR_CLASS_PENDING: 573 case ERROR_CLASS_PENDING:
510 return Stop(ERR_FAILED); 574 return Stop(ERR_FAILED);
511 case ERROR_CLASS_ERROR_RETRY: 575 case ERROR_CLASS_ERROR_RETRY:
512 return Stop(ERR_FAILED); 576 return Stop(ERR_FAILED);
513 case ERROR_CLASS_ERROR: 577 case ERROR_CLASS_ERROR:
514 // Server does not recognize the SYST command so proceed. 578 // Server does not recognize the SYST command so proceed.
515 next_state_ = STATE_CTRL_WRITE_PWD; 579 next_state_ = STATE_CTRL_WRITE_PWD;
516 break; 580 break;
517 default: 581 default:
518 return Stop(ERR_FAILED); 582 return Stop(ERR_FAILED);
519 } 583 }
520 return OK; 584 return OK;
521 } 585 }
522 586
523 // PWD command. 587 // PWD command.
524 int FtpNetworkTransaction::DoCtrlWritePWD() { 588 int FtpNetworkTransaction::DoCtrlWritePWD() {
525 std::string command = "PWD"; 589 std::string command = "PWD";
526 next_state_ = STATE_CTRL_READ; 590 next_state_ = STATE_CTRL_READ;
527 return SendFtpCommand(command, COMMAND_PWD); 591 return SendFtpCommand(command, COMMAND_PWD);
528 } 592 }
529 593
530 int FtpNetworkTransaction::ProcessResponsePWD(int response_code) { 594 int FtpNetworkTransaction::ProcessResponsePWD(const ResponseLine& response) {
531 switch (GetErrorClass(response_code)) { 595 switch (GetErrorClass(response.code)) {
532 case ERROR_CLASS_INITIATED: 596 case ERROR_CLASS_INITIATED:
533 return Stop(ERR_FAILED); 597 return Stop(ERR_FAILED);
534 case ERROR_CLASS_OK: 598 case ERROR_CLASS_OK:
535 next_state_ = STATE_CTRL_WRITE_TYPE; 599 next_state_ = STATE_CTRL_WRITE_TYPE;
536 break; 600 break;
537 case ERROR_CLASS_PENDING: 601 case ERROR_CLASS_PENDING:
538 return Stop(ERR_FAILED); 602 return Stop(ERR_FAILED);
539 case ERROR_CLASS_ERROR_RETRY: 603 case ERROR_CLASS_ERROR_RETRY:
540 return Stop(ERR_FAILED); 604 return Stop(ERR_FAILED);
541 case ERROR_CLASS_ERROR: 605 case ERROR_CLASS_ERROR:
542 return Stop(ERR_FAILED); 606 return Stop(ERR_FAILED);
543 default: 607 default:
544 return Stop(ERR_FAILED); 608 return Stop(ERR_FAILED);
545 } 609 }
546 return OK; 610 return OK;
547 } 611 }
548 612
549 // TYPE command. 613 // TYPE command.
550 int FtpNetworkTransaction::DoCtrlWriteTYPE() { 614 int FtpNetworkTransaction::DoCtrlWriteTYPE() {
551 std::string command = "TYPE I"; 615 std::string command = "TYPE I";
552 next_state_ = STATE_CTRL_READ; 616 next_state_ = STATE_CTRL_READ;
553 return SendFtpCommand(command, COMMAND_TYPE); 617 return SendFtpCommand(command, COMMAND_TYPE);
554 } 618 }
555 619
556 int FtpNetworkTransaction::ProcessResponseTYPE(int response_code) { 620 int FtpNetworkTransaction::ProcessResponseTYPE(const ResponseLine& response) {
557 switch (GetErrorClass(response_code)) { 621 switch (GetErrorClass(response.code)) {
558 case ERROR_CLASS_INITIATED: 622 case ERROR_CLASS_INITIATED:
559 return Stop(ERR_FAILED); 623 return Stop(ERR_FAILED);
560 case ERROR_CLASS_OK: 624 case ERROR_CLASS_OK:
561 next_state_ = STATE_CTRL_WRITE_PASV; 625 next_state_ = STATE_CTRL_WRITE_PASV;
562 break; 626 break;
563 case ERROR_CLASS_PENDING: 627 case ERROR_CLASS_PENDING:
564 return Stop(ERR_FAILED); 628 return Stop(ERR_FAILED);
565 case ERROR_CLASS_ERROR_RETRY: 629 case ERROR_CLASS_ERROR_RETRY:
566 return Stop(ERR_FAILED); 630 return Stop(ERR_FAILED);
567 case ERROR_CLASS_ERROR: 631 case ERROR_CLASS_ERROR:
568 return Stop(ERR_FAILED); 632 return Stop(ERR_FAILED);
569 default: 633 default:
570 return Stop(ERR_FAILED); 634 return Stop(ERR_FAILED);
571 } 635 }
572 return OK; 636 return OK;
573 } 637 }
574 638
575 // ACCT command. 639 // ACCT command.
576 int FtpNetworkTransaction::DoCtrlWriteACCT() { 640 int FtpNetworkTransaction::DoCtrlWriteACCT() {
577 std::string command = "ACCT noaccount"; 641 std::string command = "ACCT noaccount";
578 next_state_ = STATE_CTRL_READ; 642 next_state_ = STATE_CTRL_READ;
579 return SendFtpCommand(command, COMMAND_ACCT); 643 return SendFtpCommand(command, COMMAND_ACCT);
580 } 644 }
581 645
582 int FtpNetworkTransaction::ProcessResponseACCT(int response_code) { 646 int FtpNetworkTransaction::ProcessResponseACCT(const ResponseLine& response) {
583 switch (GetErrorClass(response_code)) { 647 switch (GetErrorClass(response.code)) {
584 case ERROR_CLASS_INITIATED: 648 case ERROR_CLASS_INITIATED:
585 return Stop(ERR_FAILED); 649 return Stop(ERR_FAILED);
586 case ERROR_CLASS_OK: 650 case ERROR_CLASS_OK:
587 next_state_ = STATE_CTRL_WRITE_SYST; 651 next_state_ = STATE_CTRL_WRITE_SYST;
588 break; 652 break;
589 case ERROR_CLASS_PENDING: 653 case ERROR_CLASS_PENDING:
590 return Stop(ERR_FAILED); 654 return Stop(ERR_FAILED);
591 case ERROR_CLASS_ERROR_RETRY: 655 case ERROR_CLASS_ERROR_RETRY:
592 return Stop(ERR_FAILED); 656 return Stop(ERR_FAILED);
593 case ERROR_CLASS_ERROR: 657 case ERROR_CLASS_ERROR:
594 return Stop(ERR_FAILED); 658 return Stop(ERR_FAILED);
595 default: 659 default:
596 return Stop(ERR_FAILED); 660 return Stop(ERR_FAILED);
597 } 661 }
598 return OK; 662 return OK;
599 } 663 }
600 664
601 // PASV command 665 // PASV command
602 int FtpNetworkTransaction::DoCtrlWritePASV() { 666 int FtpNetworkTransaction::DoCtrlWritePASV() {
603 std::string command = "PASV"; 667 std::string command = "PASV";
604 next_state_ = STATE_CTRL_READ; 668 next_state_ = STATE_CTRL_READ;
605 return SendFtpCommand(command, COMMAND_PASV); 669 return SendFtpCommand(command, COMMAND_PASV);
606 } 670 }
607 671
608 // There are two way we can receive IP address and port. 672 // There are two way we can receive IP address and port.
609 // (127,0,0,1,23,21) IP address and port encapsulate in (). 673 // (127,0,0,1,23,21) IP address and port encapsulate in ().
610 // 127,0,0,1,23,21 IP address and port without (). 674 // 127,0,0,1,23,21 IP address and port without ().
611 int FtpNetworkTransaction::ProcessResponsePASV(int response_code) { 675 int FtpNetworkTransaction::ProcessResponsePASV(const ResponseLine& response) {
612 switch (GetErrorClass(response_code)) { 676 switch (GetErrorClass(response.code)) {
613 case ERROR_CLASS_INITIATED: 677 case ERROR_CLASS_INITIATED:
614 return Stop(ERR_FAILED); 678 return Stop(ERR_FAILED);
615 case ERROR_CLASS_OK: 679 case ERROR_CLASS_OK:
616 char* ptr; 680 const char* ptr;
617 int i0, i1, i2, i3, p0, p1; 681 int i0, i1, i2, i3, p0, p1;
618 ptr = read_ctrl_buf_->data(); // Try with bracket. 682 ptr = response.text.c_str(); // Try with bracket.
619 while (*ptr && *ptr != '(') 683 while (*ptr && *ptr != '(')
620 ++ptr; 684 ++ptr;
621 if (*ptr) { 685 if (*ptr) {
622 ++ptr; 686 ++ptr;
623 } else { 687 } else {
624 ptr = read_ctrl_buf_->data(); // Try without bracket. 688 ptr = response.text.c_str(); // Try without bracket.
625 while (*ptr && *ptr != ',') 689 while (*ptr && *ptr != ',')
626 ++ptr; 690 ++ptr;
627 while (*ptr && *ptr != ' ') 691 while (*ptr && *ptr != ' ')
628 --ptr; 692 --ptr;
629 } 693 }
630 if (sscanf_s(ptr, "%d,%d,%d,%d,%d,%d", 694 if (sscanf_s(ptr, "%d,%d,%d,%d,%d,%d",
631 &i0, &i1, &i2, &i3, &p0, &p1) == 6) { 695 &i0, &i1, &i2, &i3, &p0, &p1) == 6) {
632 data_connection_ip_ = StringPrintf("%d.%d.%d.%d", i0, i1, i2, i3); 696 data_connection_ip_ = StringPrintf("%d.%d.%d.%d", i0, i1, i2, i3);
633 data_connection_port_ = (p0 << 8) + p1; 697 data_connection_port_ = (p0 << 8) + p1;
634 next_state_ = STATE_DATA_RESOLVE_HOST; 698 next_state_ = STATE_DATA_RESOLVE_HOST;
(...skipping 17 matching lines...) Expand all
652 int FtpNetworkTransaction::DoCtrlWriteSIZE() { 716 int FtpNetworkTransaction::DoCtrlWriteSIZE() {
653 std::string command = "SIZE"; 717 std::string command = "SIZE";
654 if (request_->url.has_path()) { 718 if (request_->url.has_path()) {
655 command.append(" "); 719 command.append(" ");
656 command.append(request_->url.path()); 720 command.append(request_->url.path());
657 } 721 }
658 next_state_ = STATE_CTRL_READ; 722 next_state_ = STATE_CTRL_READ;
659 return SendFtpCommand(command, COMMAND_SIZE); 723 return SendFtpCommand(command, COMMAND_SIZE);
660 } 724 }
661 725
662 int FtpNetworkTransaction::ProcessResponseSIZE(int response_code) { 726 int FtpNetworkTransaction::ProcessResponseSIZE(const ResponseLine& response) {
663 switch (GetErrorClass(response_code)) { 727 switch (GetErrorClass(response.code)) {
664 case ERROR_CLASS_INITIATED: 728 case ERROR_CLASS_INITIATED:
665 break; 729 break;
666 case ERROR_CLASS_OK: 730 case ERROR_CLASS_OK:
667 // Remove CR, CRLF from read_ctrl_buf_. 731 if (!StringToInt(response.text, &file_data_len_))
668 for (char* ptr = read_ctrl_buf_->data(); *ptr != '\0'; ptr++) { 732 return Stop(ERR_INVALID_RESPONSE);
669 if ((*ptr == '\r') || (*ptr == '\n')) { 733 if (file_data_len_ < 0)
670 // Stop if '\n' or '\r' detected. 734 return Stop(ERR_INVALID_RESPONSE);
671 *ptr = '\0';
672 break;
673 }
674 }
675 if (!StringToInt(read_ctrl_buf_->data() + 4, &file_data_len_))
676 return Stop(ERR_FAILED);
677 break; 735 break;
678 case ERROR_CLASS_PENDING: 736 case ERROR_CLASS_PENDING:
679 break; 737 break;
680 case ERROR_CLASS_ERROR_RETRY: 738 case ERROR_CLASS_ERROR_RETRY:
681 break; 739 break;
682 case ERROR_CLASS_ERROR: 740 case ERROR_CLASS_ERROR:
683 break; 741 break;
684 default: 742 default:
685 return Stop(ERR_FAILED); 743 return Stop(ERR_FAILED);
686 } 744 }
687 next_state_ = STATE_CTRL_WRITE_MDTM; 745 next_state_ = STATE_CTRL_WRITE_MDTM;
688 return OK; 746 return OK;
689 } 747 }
690 748
691 // RETR command 749 // RETR command
692 int FtpNetworkTransaction::DoCtrlWriteRETR() { 750 int FtpNetworkTransaction::DoCtrlWriteRETR() {
693 std::string command = "RETR"; 751 std::string command = "RETR";
694 if (request_->url.has_path()) { 752 if (request_->url.has_path()) {
695 command.append(" "); 753 command.append(" ");
696 command.append(request_->url.path()); 754 command.append(request_->url.path());
697 } else { 755 } else {
698 command.append(" /"); 756 command.append(" /");
699 } 757 }
700 next_state_ = STATE_CTRL_READ; 758 next_state_ = STATE_CTRL_READ;
701 return SendFtpCommand(command, COMMAND_RETR); 759 return SendFtpCommand(command, COMMAND_RETR);
702 } 760 }
703 761
704 int FtpNetworkTransaction::ProcessResponseRETR(int response_code) { 762 int FtpNetworkTransaction::ProcessResponseRETR(const ResponseLine& response) {
705 switch (GetErrorClass(response_code)) { 763 switch (GetErrorClass(response.code)) {
706 case ERROR_CLASS_INITIATED: 764 case ERROR_CLASS_INITIATED:
707 break; 765 break;
708 case ERROR_CLASS_OK: 766 case ERROR_CLASS_OK:
709 next_state_ = STATE_CTRL_WRITE_QUIT; 767 next_state_ = STATE_CTRL_WRITE_QUIT;
710 break; 768 break;
711 case ERROR_CLASS_PENDING: 769 case ERROR_CLASS_PENDING:
712 next_state_ = STATE_CTRL_WRITE_PASV; 770 next_state_ = STATE_CTRL_WRITE_PASV;
713 break; 771 break;
714 case ERROR_CLASS_ERROR_RETRY: 772 case ERROR_CLASS_ERROR_RETRY:
715 if (response_code == 421 || response_code == 425 || response_code == 426) 773 if (response.code == 421 || response.code == 425 || response.code == 426)
716 return Stop(ERR_FAILED); 774 return Stop(ERR_FAILED);
717 return ERR_FAILED; // TODO(ibrar): Retry here. 775 return ERR_FAILED; // TODO(ibrar): Retry here.
718 case ERROR_CLASS_ERROR: 776 case ERROR_CLASS_ERROR:
719 if (retr_failed_) 777 if (retr_failed_)
720 return Stop(ERR_FAILED); 778 return Stop(ERR_FAILED);
721 retr_failed_ = true; 779 retr_failed_ = true;
722 next_state_ = STATE_CTRL_WRITE_PASV; 780 next_state_ = STATE_CTRL_WRITE_PASV;
723 break; 781 break;
724 default: 782 default:
725 return Stop(ERR_FAILED); 783 return Stop(ERR_FAILED);
726 } 784 }
727 return OK; 785 return OK;
728 } 786 }
729 787
730 // MDMT command 788 // MDMT command
731 int FtpNetworkTransaction::DoCtrlWriteMDTM() { 789 int FtpNetworkTransaction::DoCtrlWriteMDTM() {
732 std::string command = "MDTM"; 790 std::string command = "MDTM";
733 if (request_->url.has_path()) { 791 if (request_->url.has_path()) {
734 command.append(" "); 792 command.append(" ");
735 command.append(request_->url.path()); 793 command.append(request_->url.path());
736 } else { 794 } else {
737 command.append(" /"); 795 command.append(" /");
738 } 796 }
739 next_state_ = STATE_CTRL_READ; 797 next_state_ = STATE_CTRL_READ;
740 return SendFtpCommand(command, COMMAND_MDTM); 798 return SendFtpCommand(command, COMMAND_MDTM);
741 } 799 }
742 800
743 int FtpNetworkTransaction::ProcessResponseMDTM(int response_code) { 801 int FtpNetworkTransaction::ProcessResponseMDTM(const ResponseLine& response) {
744 switch (GetErrorClass(response_code)) { 802 switch (GetErrorClass(response.code)) {
745 case ERROR_CLASS_INITIATED: 803 case ERROR_CLASS_INITIATED:
746 return Stop(ERR_FAILED); 804 return Stop(ERR_FAILED);
747 case ERROR_CLASS_OK: 805 case ERROR_CLASS_OK:
748 next_state_ = STATE_CTRL_WRITE_RETR; 806 next_state_ = STATE_CTRL_WRITE_RETR;
749 break; 807 break;
750 case ERROR_CLASS_PENDING: 808 case ERROR_CLASS_PENDING:
751 return Stop(ERR_FAILED); 809 return Stop(ERR_FAILED);
752 case ERROR_CLASS_ERROR_RETRY: 810 case ERROR_CLASS_ERROR_RETRY:
753 return Stop(ERR_FAILED); 811 return Stop(ERR_FAILED);
754 case ERROR_CLASS_ERROR: 812 case ERROR_CLASS_ERROR:
(...skipping 12 matching lines...) Expand all
767 if (request_->url.has_path()) { 825 if (request_->url.has_path()) {
768 command.append(" "); 826 command.append(" ");
769 command.append(request_->url.path()); 827 command.append(request_->url.path());
770 } else { 828 } else {
771 command.append(" /"); 829 command.append(" /");
772 } 830 }
773 next_state_ = STATE_CTRL_READ; 831 next_state_ = STATE_CTRL_READ;
774 return SendFtpCommand(command, COMMAND_CWD); 832 return SendFtpCommand(command, COMMAND_CWD);
775 } 833 }
776 834
777 int FtpNetworkTransaction::ProcessResponseCWD(int response_code) { 835 int FtpNetworkTransaction::ProcessResponseCWD(const ResponseLine& response) {
778 switch (GetErrorClass(response_code)) { 836 switch (GetErrorClass(response.code)) {
779 case ERROR_CLASS_INITIATED: 837 case ERROR_CLASS_INITIATED:
780 return Stop(ERR_FAILED); 838 return Stop(ERR_FAILED);
781 case ERROR_CLASS_OK: 839 case ERROR_CLASS_OK:
782 next_state_ = STATE_CTRL_WRITE_LIST; 840 next_state_ = STATE_CTRL_WRITE_LIST;
783 break; 841 break;
784 case ERROR_CLASS_PENDING: 842 case ERROR_CLASS_PENDING:
785 return Stop(ERR_FAILED); 843 return Stop(ERR_FAILED);
786 case ERROR_CLASS_ERROR_RETRY: 844 case ERROR_CLASS_ERROR_RETRY:
787 return Stop(ERR_FAILED); 845 return Stop(ERR_FAILED);
788 case ERROR_CLASS_ERROR: 846 case ERROR_CLASS_ERROR:
789 return Stop(ERR_FAILED); 847 return Stop(ERR_FAILED);
790 default: 848 default:
791 return Stop(ERR_FAILED); 849 return Stop(ERR_FAILED);
792 } 850 }
793 return OK; 851 return OK;
794 } 852 }
795 853
796 // LIST command 854 // LIST command
797 int FtpNetworkTransaction::DoCtrlWriteLIST() { 855 int FtpNetworkTransaction::DoCtrlWriteLIST() {
798 std::string command = "LIST"; 856 std::string command = "LIST";
799 next_state_ = STATE_CTRL_READ; 857 next_state_ = STATE_CTRL_READ;
800 return SendFtpCommand(command, COMMAND_LIST); 858 return SendFtpCommand(command, COMMAND_LIST);
801 } 859 }
802 860
803 int FtpNetworkTransaction::ProcessResponseLIST(int response_code) { 861 int FtpNetworkTransaction::ProcessResponseLIST(const ResponseLine& response) {
804 switch (GetErrorClass(response_code)) { 862 switch (GetErrorClass(response.code)) {
805 case ERROR_CLASS_INITIATED: 863 case ERROR_CLASS_INITIATED:
806 response_message_buf_len_ = 0; // Clear the responce buffer. 864 response_message_buf_len_ = 0; // Clear the response buffer.
807 next_state_ = STATE_CTRL_READ; 865 next_state_ = STATE_CTRL_READ;
808 break; 866 break;
809 case ERROR_CLASS_OK: 867 case ERROR_CLASS_OK:
810 response_.is_directory_listing = true; 868 response_.is_directory_listing = true;
811 next_state_ = STATE_CTRL_WRITE_QUIT; 869 next_state_ = STATE_CTRL_WRITE_QUIT;
812 break; 870 break;
813 case ERROR_CLASS_PENDING: 871 case ERROR_CLASS_PENDING:
814 return Stop(ERR_FAILED); 872 return Stop(ERR_FAILED);
815 case ERROR_CLASS_ERROR_RETRY: 873 case ERROR_CLASS_ERROR_RETRY:
816 return Stop(ERR_FAILED); 874 return Stop(ERR_FAILED);
817 case ERROR_CLASS_ERROR: 875 case ERROR_CLASS_ERROR:
818 return Stop(ERR_FAILED); 876 return Stop(ERR_FAILED);
819 default: 877 default:
820 return Stop(ERR_FAILED); 878 return Stop(ERR_FAILED);
821 } 879 }
822 return OK; 880 return OK;
823 } 881 }
824 882
825 // Quit command 883 // Quit command
826 int FtpNetworkTransaction::DoCtrlWriteQUIT() { 884 int FtpNetworkTransaction::DoCtrlWriteQUIT() {
827 std::string command = "QUIT"; 885 std::string command = "QUIT";
828 next_state_ = STATE_CTRL_READ; 886 next_state_ = STATE_CTRL_READ;
829 return SendFtpCommand(command, COMMAND_QUIT); 887 return SendFtpCommand(command, COMMAND_QUIT);
830 } 888 }
831 889
832 int FtpNetworkTransaction::ProcessResponseQUIT(int response_code) { 890 int FtpNetworkTransaction::ProcessResponseQUIT(const ResponseLine& response) {
833 ctrl_socket_->Disconnect(); 891 ctrl_socket_->Disconnect();
834 return last_error_; 892 return last_error_;
835 } 893 }
836 894
837 // Data Connection 895 // Data Connection
838 896
839 int FtpNetworkTransaction::DoDataResolveHost() { 897 int FtpNetworkTransaction::DoDataResolveHost() {
840 if (data_socket_ != NULL && data_socket_->IsConnected()) 898 if (data_socket_ != NULL && data_socket_->IsConnected())
841 data_socket_->Disconnect(); 899 data_socket_->Disconnect();
842 900
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
882 &io_callback_); 940 &io_callback_);
883 } 941 }
884 942
885 int FtpNetworkTransaction::DoDataReadComplete(int result) { 943 int FtpNetworkTransaction::DoDataReadComplete(int result) {
886 DLOG(INFO) << read_data_buf_->data(); // The read_data_buf_ is NULL 944 DLOG(INFO) << read_data_buf_->data(); // The read_data_buf_ is NULL
887 // terminated string. 945 // terminated string.
888 return result; 946 return result;
889 } 947 }
890 948
891 } // namespace net 949 } // 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