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

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

Issue 115137: FTP Transaction code for new Portable FTP code.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Upload before checkin Created 11 years, 7 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_request_info.h » ('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/logging.h" 8 #include "base/string_util.h"
9 #include "net/base/client_socket.h" 9 #include "net/base/client_socket.h"
10 #include "net/base/client_socket_factory.h"
11 #include "net/base/connection_type_histograms.h"
12 #include "net/base/dns_resolution_observer.h"
10 #include "net/base/net_errors.h" 13 #include "net/base/net_errors.h"
11 #include "net/ftp/ftp_network_session.h" 14 #include "net/ftp/ftp_network_session.h"
15 #include "net/ftp/ftp_request_info.h"
16
17 // TODO(ibrar): Try to avoid sscanf.
18 #if !defined(COMPILER_MSVC)
19 #define sscanf_s sscanf
20 #endif
21
22 const char kCRLF[] = "\r\n";
23
24 const int kCtrlBufLen = 1024;
12 25
13 namespace net { 26 namespace net {
14 27
15 FtpNetworkTransaction::FtpNetworkTransaction( 28 FtpNetworkTransaction::FtpNetworkTransaction(
16 FtpNetworkSession* session, ClientSocketFactory* socket_factory) 29 FtpNetworkSession* session,
17 : ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(this, 30 ClientSocketFactory* socket_factory)
18 &FtpNetworkTransaction::OnIOComplete)), 31 : command_sent_(COMMAND_NONE),
32 ALLOW_THIS_IN_INITIALIZER_LIST(
33 io_callback_(this, &FtpNetworkTransaction::OnIOComplete)),
19 user_callback_(NULL), 34 user_callback_(NULL),
20 session_(session), 35 session_(session),
36 request_(NULL),
37 read_ctrl_buf_size_(kCtrlBufLen),
38 response_message_buf_len_(0),
39 read_data_buf_len_(0),
40 file_data_len_(0),
41 last_error_(OK),
42 data_connection_port_(0),
21 socket_factory_(socket_factory), 43 socket_factory_(socket_factory),
22 next_state_(STATE_NONE) { 44 next_state_(STATE_NONE) {
45 read_ctrl_buf_ = new IOBuffer(kCtrlBufLen);
46 response_message_buf_ = new IOBuffer(kCtrlBufLen);
23 } 47 }
24 48
25 FtpNetworkTransaction::~FtpNetworkTransaction() { 49 FtpNetworkTransaction::~FtpNetworkTransaction() {
26 } 50 }
27 51
28 void FtpNetworkTransaction::Destroy() { 52 int FtpNetworkTransaction::Start(const FtpRequestInfo* request_info,
29 delete this; 53 CompletionCallback* callback) {
30 }
31
32 int FtpNetworkTransaction::Start(
33 const FtpRequestInfo* request_info, CompletionCallback* callback) {
34 request_ = request_info; 54 request_ = request_info;
35 55
36 next_state_ = STATE_CTRL_INIT; 56 next_state_ = STATE_CTRL_INIT;
37 int rv = DoLoop(OK); 57 int rv = DoLoop(OK);
38 if (rv == ERR_IO_PENDING) 58 if (rv == ERR_IO_PENDING)
39 user_callback_ = callback; 59 user_callback_ = callback;
40 return rv; 60 return rv;
41 } 61 }
42 62
43 int FtpNetworkTransaction::RestartWithAuth( 63 int FtpNetworkTransaction::Stop(int error) {
44 const std::wstring& username, const std::wstring& password, 64 next_state_ = STATE_CTRL_WRITE_QUIT;
65 last_error_ = error;
66 return OK;
67 }
68
69 int FtpNetworkTransaction::RestartWithAuth(const std::wstring& username,
70 const std::wstring& password,
71 CompletionCallback* callback) {
72 return ERR_FAILED;
73 }
74
75 int FtpNetworkTransaction::RestartIgnoringLastError(
45 CompletionCallback* callback) { 76 CompletionCallback* callback) {
46 return ERR_FAILED; 77 return ERR_FAILED;
47 } 78 }
48 79
49 int FtpNetworkTransaction::Read( 80 int FtpNetworkTransaction::Read(IOBuffer* buf,
50 char* buf, int buf_len, CompletionCallback* callback) { 81 int buf_len,
51 return ERR_FAILED; 82 CompletionCallback* callback) {
83 DCHECK(buf);
84 DCHECK(buf_len > 0);
85
86 if (data_socket_ == NULL)
87 return 0; // Data socket closed, no more data left.
88
89 if (!data_socket_->IsConnected())
90 return 0; // Data socket disconnected, no more data left.
91
92 read_data_buf_ = buf;
93 read_data_buf_len_ = buf_len;
94
95 next_state_ = STATE_DATA_READ;
96
97 int rv = DoLoop(OK);
98 if (rv == ERR_IO_PENDING)
99 user_callback_ = callback;
100 else if (rv == 0)
101 data_socket_->Disconnect();
102 return rv;
52 } 103 }
53 104
54 const FtpResponseInfo* FtpNetworkTransaction::GetResponseInfo() const { 105 const FtpResponseInfo* FtpNetworkTransaction::GetResponseInfo() const {
55 return NULL; 106 return &response_;
56 } 107 }
57 108
58 LoadState FtpNetworkTransaction::GetLoadState() const { 109 LoadState FtpNetworkTransaction::GetLoadState() const {
59 return LOAD_STATE_IDLE; 110 return LOAD_STATE_IDLE;
60 } 111 }
61 112
62 uint64 FtpNetworkTransaction::GetUploadProgress() const { 113 uint64 FtpNetworkTransaction::GetUploadProgress() const {
63 return 0; 114 return 0;
64 } 115 }
65 116
117 // Used to prepare and send FTP commad.
118 int FtpNetworkTransaction::SendFtpCommand(const std::string& command,
119 Command cmd) {
120 response_message_buf_len_ = 0;
121 command_sent_ = cmd;
122 DLOG(INFO) << " >> " << command;
123 const char* buf = command.c_str();
124 int buf_len = command.size();
125 DCHECK(!write_buf_);
126 write_buf_ = new IOBuffer(buf_len + 2);
127 memcpy(write_buf_->data(), buf, buf_len);
128 memcpy(write_buf_->data() + buf_len, kCRLF, 2);
129
130 // TODO(ibrar): Handle the completion of Write and release write_buf_.
131 return ctrl_socket_->Write(write_buf_, buf_len, &io_callback_);
132 }
133
134 int FtpNetworkTransaction::GetRespnseCode() {
135 std::string str(response_message_buf_->data(), 3);
136 return StringToInt(str);
137 }
138
139 int FtpNetworkTransaction::ProcessResponse(int response_code) {
140 int rv = OK;
141 switch (command_sent_) {
142 case COMMAND_NONE:
143 next_state_ = STATE_CTRL_WRITE_USER;
144 break;
145 case COMMAND_USER:
146 rv = ProcessResponseUSER(response_code);
147 break;
148 case COMMAND_PASS:
149 rv = ProcessResponsePASS(response_code);
150 break;
151 case COMMAND_ACCT:
152 rv = ProcessResponseACCT(response_code);
153 break;
154 case COMMAND_SYST:
155 rv = ProcessResponseSYST(response_code);
156 break;
157 case COMMAND_PWD:
158 rv = ProcessResponsePWD(response_code);
159 break;
160 case COMMAND_TYPE:
161 rv = ProcessResponseTYPE(response_code);
162 break;
163 case COMMAND_PASV:
164 rv = ProcessResponsePASV(response_code);
165 break;
166 case COMMAND_SIZE:
167 rv = ProcessResponseSIZE(response_code);
168 break;
169 case COMMAND_RETR:
170 rv = ProcessResponseRETR(response_code);
171 break;
172 case COMMAND_CWD:
173 rv = ProcessResponseCWD(response_code);
174 break;
175 case COMMAND_LIST:
176 rv = ProcessResponseLIST(response_code);
177 break;
178 case COMMAND_QUIT:
179 rv = ProcessResponseQUIT(response_code);
180 break;
181 default:
182 DLOG(INFO) << "Missing Command response handling!";
183 return ERR_FAILED;
184 }
185 return rv;
186 }
187
66 void FtpNetworkTransaction::DoCallback(int rv) { 188 void FtpNetworkTransaction::DoCallback(int rv) {
67 DCHECK(rv != ERR_IO_PENDING); 189 DCHECK(rv != ERR_IO_PENDING);
68 DCHECK(user_callback_); 190 DCHECK(user_callback_);
69 191
70 // Since Run may result in Read being called, clear callback_ up front. 192 // Since Run may result in Read being called, clear callback_ up front.
71 CompletionCallback* c = user_callback_; 193 CompletionCallback* c = user_callback_;
72 user_callback_ = NULL; 194 user_callback_ = NULL;
73 c->Run(rv); 195 c->Run(rv);
74 } 196 }
75 197
(...skipping 25 matching lines...) Expand all
101 case STATE_CTRL_RESOLVE_HOST_COMPLETE: 223 case STATE_CTRL_RESOLVE_HOST_COMPLETE:
102 rv = DoCtrlResolveHostComplete(rv); 224 rv = DoCtrlResolveHostComplete(rv);
103 break; 225 break;
104 case STATE_CTRL_CONNECT: 226 case STATE_CTRL_CONNECT:
105 DCHECK(rv == OK); 227 DCHECK(rv == OK);
106 rv = DoCtrlConnect(); 228 rv = DoCtrlConnect();
107 break; 229 break;
108 case STATE_CTRL_CONNECT_COMPLETE: 230 case STATE_CTRL_CONNECT_COMPLETE:
109 rv = DoCtrlConnectComplete(rv); 231 rv = DoCtrlConnectComplete(rv);
110 break; 232 break;
111 case STATE_CTRL_WRITE:
112 DCHECK(rv == OK);
113 rv = DoCtrlWrite();
114 break;
115 case STATE_CTRL_WRITE_COMPLETE:
116 rv = DoCtrlWriteComplete(rv);
117 break;
118 case STATE_CTRL_READ: 233 case STATE_CTRL_READ:
119 DCHECK(rv == OK);
120 rv = DoCtrlRead(); 234 rv = DoCtrlRead();
121 break; 235 break;
122 case STATE_CTRL_READ_COMPLETE: 236 case STATE_CTRL_READ_COMPLETE:
123 rv = DoCtrlReadComplete(rv); 237 rv = DoCtrlReadComplete(rv);
124 break; 238 break;
239 case STATE_CTRL_WRITE_USER:
240 DCHECK(rv == OK);
241 rv = DoCtrlWriteUSER();
242 break;
243 case STATE_CTRL_WRITE_PASS:
244 DCHECK(rv == OK);
245 rv = DoCtrlWritePASS();
246 break;
247 case STATE_CTRL_WRITE_SYST:
248 DCHECK(rv == OK);
249 rv = DoCtrlWriteSYST();
250 break;
251 case STATE_CTRL_WRITE_ACCT:
252 DCHECK(rv == OK);
253 rv = DoCtrlWriteACCT();
254 break;
255 case STATE_CTRL_WRITE_PWD:
256 DCHECK(rv == OK);
257 rv = DoCtrlWritePWD();
258 break;
259 case STATE_CTRL_WRITE_TYPE:
260 DCHECK(rv == OK);
261 rv = DoCtrlWriteTYPE();
262 break;
263 case STATE_CTRL_WRITE_PASV:
264 DCHECK(rv == OK);
265 rv = DoCtrlWritePASV();
266 break;
267 case STATE_CTRL_WRITE_RETR:
268 DCHECK(rv == OK);
269 rv = DoCtrlWriteRETR();
270 break;
271 case STATE_CTRL_WRITE_SIZE:
272 DCHECK(rv == OK);
273 rv = DoCtrlWriteSIZE();
274 break;
275 case STATE_CTRL_WRITE_CWD:
276 rv = DoCtrlWriteCWD();
277 break;
278 case STATE_CTRL_WRITE_LIST:
279 rv = DoCtrlWriteLIST();
280 break;
281 case STATE_CTRL_WRITE_QUIT:
282 rv = DoCtrlWriteQUIT();
283 break;
284
125 case STATE_DATA_CONNECT: 285 case STATE_DATA_CONNECT:
126 DCHECK(rv == OK); 286 DCHECK(rv == OK);
127 rv = DoDataConnect(); 287 rv = DoDataConnect();
128 break; 288 break;
129 case STATE_DATA_CONNECT_COMPLETE: 289 case STATE_DATA_CONNECT_COMPLETE:
130 rv = DoDataConnectComplete(rv); 290 rv = DoDataConnectComplete(rv);
131 break; 291 break;
132 case STATE_DATA_READ: 292 case STATE_DATA_READ:
133 DCHECK(rv == OK);
134 rv = DoDataRead(); 293 rv = DoDataRead();
135 break; 294 break;
136 case STATE_DATA_READ_COMPLETE: 295 case STATE_DATA_READ_COMPLETE:
137 rv = DoDataReadComplete(rv); 296 rv = DoDataReadComplete(rv);
138 break; 297 break;
139 default: 298 default:
140 NOTREACHED() << "bad state"; 299 NOTREACHED() << "bad state";
141 rv = ERR_FAILED; 300 rv = ERR_FAILED;
142 break; 301 break;
143 } 302 }
144 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 303 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
145
146 return rv; 304 return rv;
147 } 305 }
148 306
307 // TODO(ibrar): Yet to see if we need any intialization
149 int FtpNetworkTransaction::DoCtrlInit() { 308 int FtpNetworkTransaction::DoCtrlInit() {
150 return ERR_FAILED; // TODO(darin): implement me 309 next_state_ = STATE_CTRL_INIT_COMPLETE;
310 return OK;
151 } 311 }
152 312
153 int FtpNetworkTransaction::DoCtrlInitComplete(int result) { 313 int FtpNetworkTransaction::DoCtrlInitComplete(int result) {
154 return ERR_FAILED; // TODO(darin): implement me 314 next_state_ = STATE_CTRL_RESOLVE_HOST;
315 return OK;
155 } 316 }
156 317
157 int FtpNetworkTransaction::DoCtrlResolveHost() { 318 int FtpNetworkTransaction::DoCtrlResolveHost() {
158 return ERR_FAILED; // TODO(darin): implement me 319 next_state_ = STATE_CTRL_RESOLVE_HOST_COMPLETE;
320
321 std::string host;
322 int port;
323
324 host = request_->url.host();
325 port = request_->url.EffectiveIntPort();
326
327 DidStartDnsResolution(host, this);
328 return resolver_.Resolve(host, port, &addresses_, &io_callback_);
159 } 329 }
160 330
161 int FtpNetworkTransaction::DoCtrlResolveHostComplete(int result) { 331 int FtpNetworkTransaction::DoCtrlResolveHostComplete(int result) {
162 return ERR_FAILED; // TODO(darin): implement me 332 bool ok = (result == OK);
333 DidFinishDnsResolutionWithStatus(ok, GURL(), this);
334 if (ok) {
335 next_state_ = STATE_CTRL_CONNECT;
336 return result;
337 }
338 return ERR_FAILED;
163 } 339 }
164 340
165 int FtpNetworkTransaction::DoCtrlConnect() { 341 int FtpNetworkTransaction::DoCtrlConnect() {
166 return ERR_FAILED; // TODO(darin): implement me 342 next_state_ = STATE_CTRL_CONNECT_COMPLETE;
343 ctrl_socket_.reset(socket_factory_->CreateTCPClientSocket(addresses_));
344 return ctrl_socket_->Connect(&io_callback_);
167 } 345 }
168 346
169 int FtpNetworkTransaction::DoCtrlConnectComplete(int result) { 347 int FtpNetworkTransaction::DoCtrlConnectComplete(int result) {
170 return ERR_FAILED; // TODO(darin): implement me 348 next_state_ = STATE_CTRL_READ;
171 } 349 return result;
172
173 int FtpNetworkTransaction::DoCtrlWrite() {
174 return ERR_FAILED; // TODO(darin): implement me
175 }
176
177 int FtpNetworkTransaction::DoCtrlWriteComplete(int result) {
178 return ERR_FAILED; // TODO(darin): implement me
179 } 350 }
180 351
181 int FtpNetworkTransaction::DoCtrlRead() { 352 int FtpNetworkTransaction::DoCtrlRead() {
182 return ERR_FAILED; // TODO(darin): implement me 353 next_state_ = STATE_CTRL_READ_COMPLETE;
354 read_ctrl_buf_->data()[0] = 0;
355 return ctrl_socket_->Read(read_ctrl_buf_, read_ctrl_buf_size_ - 1,
356 &io_callback_);
183 } 357 }
184 358
185 int FtpNetworkTransaction::DoCtrlReadComplete(int result) { 359 int FtpNetworkTransaction::DoCtrlReadComplete(int result) {
186 return ERR_FAILED; // TODO(darin): implement me 360 if (result < 0)
187 } 361 return Stop(ERR_FAILED);
188 362 int response_code;
363 // Null termination added, now we can treat this as string.
364 read_ctrl_buf_->data()[result] = 0;
365 memcpy(response_message_buf_->data() + response_message_buf_len_,
366 read_ctrl_buf_->data(), result);
367
368 response_message_buf_len_ = response_message_buf_len_ + result;
369 for (int i = 0; i < response_message_buf_len_; i++) {
370 if (response_message_buf_->data()[i] == '\r' &&
371 response_message_buf_->data()[i + 1] == '\n') {
372 if (response_message_buf_len_ > 3 &&
373 response_message_buf_->data()[3] == ' ') {
374 response_message_buf_->data()[response_message_buf_len_ - 2] = 0;
375 response_code = GetRespnseCode();
376 return ProcessResponse(response_code);
377 }
378 response_message_buf_len_ -= (i + 2);
379 memcpy(response_message_buf_->data(),
380 response_message_buf_->data() + i + 2,
381 response_message_buf_len_);
382 i = 0;
383 }
384 }
385 next_state_ = STATE_CTRL_READ;
386 return OK;
387 }
388
389 // FTP Commands and responses
390
391 // USER Command.
392 int FtpNetworkTransaction::DoCtrlWriteUSER() {
393 std::string command = "USER ";
394 if (request_->url.has_username()) {
395 command.append(request_->url.username());
396 } else {
397 command.append("anonymous");
398 }
399 next_state_ = STATE_CTRL_READ;
400 return SendFtpCommand(command, COMMAND_USER);
401 }
402
403 int FtpNetworkTransaction::ProcessResponseUSER(int response_code) {
404 switch (GetErrorClass(response_code)) {
405 case ERROR_CLASS_INITIATED:
406 case ERROR_CLASS_OK:
407 next_state_ = STATE_CTRL_WRITE_USER;
408 break;
409 case ERROR_CLASS_PENDING:
410 next_state_ = STATE_CTRL_WRITE_PASS;
411 break;
412 case ERROR_CLASS_ERROR_RETRY:
413 if (response_code == 421)
414 return Stop(ERR_FAILED);
415 break;
416 case ERROR_CLASS_ERROR:
417 return Stop(ERR_FAILED);
418 default:
419 return Stop(ERR_FAILED);
420 }
421 return OK;
422 }
423
424 // PASS command.
425 int FtpNetworkTransaction::DoCtrlWritePASS() {
426 std::string command = "PASS ";
427 if (request_->url.has_password()) {
428 command.append(request_->url.password());
429 } else {
430 command.append("IEUser@");
431 }
432 next_state_ = STATE_CTRL_READ;
433 return SendFtpCommand(command, COMMAND_PASS);
434 }
435
436 int FtpNetworkTransaction::ProcessResponsePASS(int response_code) {
437 switch (GetErrorClass(response_code)) {
438 case ERROR_CLASS_INITIATED:
439 case ERROR_CLASS_OK:
440 next_state_ = STATE_CTRL_WRITE_SYST;
441 break;
442 case ERROR_CLASS_PENDING:
443 next_state_ = STATE_CTRL_WRITE_ACCT;
444 break;
445 case ERROR_CLASS_ERROR_RETRY:
446 return Stop(ERR_FAILED);
447 case ERROR_CLASS_ERROR:
448 if (response_code == 503) {
449 next_state_ = STATE_CTRL_WRITE_PASS;
450 } else {
451 return Stop(ERR_FAILED);
452 }
453 break;
454 default:
455 return Stop(ERR_FAILED);
456 }
457 return OK;
458 }
459
460 // ACCT command.
461 int FtpNetworkTransaction::DoCtrlWriteACCT() {
462 std::string command = "ACCT noaccount";
463 next_state_ = STATE_CTRL_READ;
464 return SendFtpCommand(command, COMMAND_ACCT);
465 }
466
467 int FtpNetworkTransaction::ProcessResponseACCT(int response_code) {
468 switch (GetErrorClass(response_code)) {
469 case ERROR_CLASS_INITIATED:
470 return Stop(ERR_FAILED);
471 case ERROR_CLASS_OK:
472 next_state_ = STATE_CTRL_WRITE_SYST;
473 break;
474 case ERROR_CLASS_PENDING:
475 return Stop(ERR_FAILED);
476 case ERROR_CLASS_ERROR_RETRY:
477 return Stop(ERR_FAILED);
478 case ERROR_CLASS_ERROR:
479 return Stop(ERR_FAILED);
480 default:
481 return Stop(ERR_FAILED);
482 }
483 return OK;
484 }
485
486 // SYST command.
487 int FtpNetworkTransaction::DoCtrlWriteSYST() {
488 std::string command = "SYST";
489 next_state_ = STATE_CTRL_READ;
490 return SendFtpCommand(command, COMMAND_SYST);
491 }
492
493 int FtpNetworkTransaction::ProcessResponseSYST(int response_code) {
494 next_state_ = STATE_CTRL_WRITE_PWD;
495 return OK;
496 }
497
498 // PWD command.
499 int FtpNetworkTransaction::DoCtrlWritePWD() {
500 std::string command = "PWD";
501 next_state_ = STATE_CTRL_READ;
502 return SendFtpCommand(command, COMMAND_PWD);
503 }
504
505 int FtpNetworkTransaction::ProcessResponsePWD(int response_code) {
506 switch (GetErrorClass(response_code)) {
507 case ERROR_CLASS_INITIATED:
508 return Stop(ERR_FAILED);
509 case ERROR_CLASS_OK:
510 next_state_ = STATE_CTRL_WRITE_TYPE;
511 break;
512 case ERROR_CLASS_PENDING:
513 return Stop(ERR_FAILED);
514 case ERROR_CLASS_ERROR_RETRY:
515 return Stop(ERR_FAILED);
516 case ERROR_CLASS_ERROR:
517 return Stop(ERR_FAILED);
518 default:
519 return Stop(ERR_FAILED);
520 }
521 return OK;
522 }
523
524 // TYPE command.
525 int FtpNetworkTransaction::DoCtrlWriteTYPE() {
526 std::string command = "TYPE I";
527 next_state_ = STATE_CTRL_READ;
528 return SendFtpCommand(command, COMMAND_TYPE);
529 }
530
531 int FtpNetworkTransaction::ProcessResponseTYPE(int response_code) {
532 switch (GetErrorClass(response_code)) {
533 case ERROR_CLASS_INITIATED:
534 return Stop(ERR_FAILED);
535 case ERROR_CLASS_OK:
536 next_state_ = STATE_CTRL_WRITE_PASV;
537 break;
538 case ERROR_CLASS_PENDING:
539 return Stop(ERR_FAILED);
540 case ERROR_CLASS_ERROR_RETRY:
541 return Stop(ERR_FAILED);
542 case ERROR_CLASS_ERROR:
543 return Stop(ERR_FAILED);
544 default:
545 return Stop(ERR_FAILED);
546 }
547 return OK;
548 }
549
550 // PASV command
551 int FtpNetworkTransaction::DoCtrlWritePASV() {
552 std::string command = "PASV ";
553 next_state_ = STATE_CTRL_READ;
554 return SendFtpCommand(command, COMMAND_PASV);
555 }
556
557 // There are two way we can receive IP address and port.
558 // (127,0,0,1,23,21) IP address and port encapsulate in ().
559 // 127,0,0,1,23,21 IP address and port without ().
560 int FtpNetworkTransaction::ProcessResponsePASV(int response_code) {
561 switch (GetErrorClass(response_code)) {
562 case ERROR_CLASS_INITIATED:
563 return Stop(ERR_FAILED);
564 case ERROR_CLASS_OK:
565 char* ptr;
566 int i0, i1, i2, i3, p0, p1;
567 ptr = read_ctrl_buf_->data(); // Try with bracket.
568 while (*ptr && *ptr != '(')
569 ++ptr;
570 if (*ptr) {
571 ++ptr;
572 } else {
573 ptr = read_ctrl_buf_->data(); // Try without bracket.
574 while (*ptr && *ptr != ',')
575 ++ptr;
576 while (*ptr && *ptr != ' ')
577 --ptr;
578 }
579 if (sscanf_s(ptr, "%d,%d,%d,%d,%d,%d",
580 &i0, &i1, &i2, &i3, &p0, &p1) == 6) {
581 data_connection_ip_ = StringPrintf("%d.%d.%d.%d", i0, i1, i2, i3);
582 data_connection_port_ = (p0 << 8) + p1;
583 next_state_ = STATE_DATA_CONNECT;
584 } else {
585 return Stop(ERR_FAILED);
586 }
587 break;
588 case ERROR_CLASS_PENDING:
589 return Stop(ERR_FAILED);
590 case ERROR_CLASS_ERROR_RETRY:
591 return Stop(ERR_FAILED);
592 case ERROR_CLASS_ERROR:
593 return Stop(ERR_FAILED);
594 default:
595 return Stop(ERR_FAILED);
596 }
597 return OK;
598 }
599
600 // SIZE command
601 int FtpNetworkTransaction::DoCtrlWriteSIZE() {
602 std::string command = "SIZE ";
603 if (request_->url.has_path())
604 command.append(request_->url.path());
605 next_state_ = STATE_CTRL_READ;
606 return SendFtpCommand(command, COMMAND_SIZE);
607 }
608
609 int FtpNetworkTransaction::ProcessResponseSIZE(int response_code) {
610 switch (GetErrorClass(response_code)) {
611 case ERROR_CLASS_INITIATED:
612 next_state_ = STATE_CTRL_WRITE_LIST;
613 break;
614 case ERROR_CLASS_OK:
615 next_state_ = STATE_CTRL_WRITE_RETR;
616 if (!StringToInt(read_ctrl_buf_->data() + 4, &file_data_len_))
617 return Stop(ERR_FAILED);
618 break;
619 case ERROR_CLASS_PENDING:
620 next_state_ = STATE_CTRL_WRITE_LIST;
621 break;
622 case ERROR_CLASS_ERROR_RETRY:
623 next_state_ = STATE_CTRL_WRITE_LIST;
624 break;
625 case ERROR_CLASS_ERROR:
626 next_state_ = STATE_CTRL_WRITE_LIST;
627 break;
628 default:
629 return Stop(ERR_FAILED);
630 }
631 return OK;
632 }
633
634 // RETR command
635 int FtpNetworkTransaction::DoCtrlWriteRETR() {
636 std::string command = "RETR ";
637 if (request_->url.has_path())
638 command.append(request_->url.path());
639 next_state_ = STATE_CTRL_READ;
640 return SendFtpCommand(command, COMMAND_RETR);
641 }
642
643 int FtpNetworkTransaction::ProcessResponseRETR(int response_code) {
644 switch (GetErrorClass(response_code)) {
645 case ERROR_CLASS_INITIATED:
646 next_state_ = STATE_CTRL_WRITE_QUIT;
647 ctrl_socket_->Disconnect();
648 break;
649 case ERROR_CLASS_OK:
650 break; // FTP Done
651 case ERROR_CLASS_PENDING:
652 next_state_ = STATE_CTRL_WRITE_PASV;
653 break;
654 case ERROR_CLASS_ERROR_RETRY:
655 if (response_code == 421 || response_code == 425 || response_code == 426)
656 return Stop(ERR_FAILED);
657 return ERR_FAILED; // TODO(ibrar): Retry here.
658 case ERROR_CLASS_ERROR:
659 next_state_ = STATE_CTRL_WRITE_CWD;
660 break;
661 default:
662 return Stop(ERR_FAILED);
663 }
664 return OK;
665 }
666
667 // CWD command
668 int FtpNetworkTransaction::DoCtrlWriteCWD() {
669 std::string command = "CWD";
670 next_state_ = STATE_CTRL_READ;
671 return SendFtpCommand(command, COMMAND_CWD);
672 }
673
674 int FtpNetworkTransaction::ProcessResponseCWD(int response_code) {
675 switch (GetErrorClass(response_code)) {
676 case ERROR_CLASS_INITIATED:
677 return Stop(ERR_FAILED);
678 case ERROR_CLASS_OK:
679 next_state_ = STATE_CTRL_WRITE_LIST;
680 case ERROR_CLASS_PENDING:
681 return Stop(ERR_FAILED);
682 case ERROR_CLASS_ERROR_RETRY:
683 return Stop(ERR_FAILED);
684 case ERROR_CLASS_ERROR:
685 return Stop(ERR_FAILED);
686 default:
687 return Stop(ERR_FAILED);
688 }
689 return OK;
690 }
691
692 // LIST command
693 int FtpNetworkTransaction::DoCtrlWriteLIST() {
694 std::string command = "LIST ";
695 if (request_->url.has_path())
696 command.append(request_->url.path());
697 next_state_ = STATE_CTRL_READ;
698 return SendFtpCommand(command, COMMAND_LIST);
699 }
700
701 int FtpNetworkTransaction::ProcessResponseLIST(int response_code) {
702 switch (GetErrorClass(response_code)) {
703 case ERROR_CLASS_INITIATED:
704 next_state_ = STATE_CTRL_WRITE_QUIT;
705 response_.is_directory_listing = true;
706 break;
707 case ERROR_CLASS_OK:
708 next_state_ = STATE_CTRL_WRITE_QUIT;
709 response_.is_directory_listing = true;
710 break;
711 case ERROR_CLASS_PENDING:
712 return Stop(ERR_FAILED);
713 case ERROR_CLASS_ERROR_RETRY:
714 return Stop(ERR_FAILED);
715 case ERROR_CLASS_ERROR:
716 return Stop(ERR_FAILED);
717 default:
718 return Stop(ERR_FAILED);
719 }
720 return OK;
721 }
722
723 // Quit command
724 int FtpNetworkTransaction::DoCtrlWriteQUIT() {
725 std::string command = "QUIT";
726 next_state_ = STATE_CTRL_READ;
727 return SendFtpCommand(command, COMMAND_QUIT);
728 }
729
730 int FtpNetworkTransaction::ProcessResponseQUIT(int response_code) {
731 ctrl_socket_->Disconnect();
732 return last_error_;
733 }
734
735 // Data Connection
189 int FtpNetworkTransaction::DoDataConnect() { 736 int FtpNetworkTransaction::DoDataConnect() {
190 return ERR_FAILED; // TODO(darin): implement me 737 next_state_ = STATE_DATA_CONNECT_COMPLETE;
738 AddressList adr;
739 // TODO(ibrar): Call resolver_.Resolve in asynchronous mode, with a non-null
740 // callback.
741 int err = resolver_.Resolve(data_connection_ip_,
742 data_connection_port_, &adr, NULL);
743 if (err != OK)
744 return err;
745 data_socket_.reset(socket_factory_->CreateTCPClientSocket(adr));
746 return data_socket_->Connect(&io_callback_);
191 } 747 }
192 748
193 int FtpNetworkTransaction::DoDataConnectComplete(int result) { 749 int FtpNetworkTransaction::DoDataConnectComplete(int result) {
194 return ERR_FAILED; // TODO(darin): implement me 750 next_state_ = STATE_CTRL_WRITE_SIZE;
751 return result;
195 } 752 }
196 753
197 int FtpNetworkTransaction::DoDataRead() { 754 int FtpNetworkTransaction::DoDataRead() {
198 return ERR_FAILED; // TODO(darin): implement me 755 DCHECK(read_data_buf_);
756 DCHECK(read_data_buf_len_ > 0);
757
758 next_state_ = STATE_DATA_READ_COMPLETE;
759 read_data_buf_->data()[0] = 0;
760 return data_socket_->Read(read_data_buf_, read_data_buf_len_,
761 &io_callback_);
199 } 762 }
200 763
201 int FtpNetworkTransaction::DoDataReadComplete(int result) { 764 int FtpNetworkTransaction::DoDataReadComplete(int result) {
202 return ERR_FAILED; // TODO(darin): implement me 765 DLOG(INFO) << read_data_buf_->data(); // The read_data_buf_ is NULL
766 // terminated string.
767 return result;
203 } 768 }
204 769
205 } // namespace net 770 } // namespace net
OLDNEW
« no previous file with comments | « net/ftp/ftp_network_transaction.h ('k') | net/ftp/ftp_request_info.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698