OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |