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

Side by Side Diff: net/dns/dns_transaction.cc

Issue 422323004: DNS: Don't spin on unexpected EOF reading TCP response (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Refactor state machine. Created 6 years, 4 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 | « no previous file | net/dns/dns_transaction_unittest.cc » ('j') | net/dns/dns_transaction_unittest.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/dns/dns_transaction.h" 5 #include "net/dns/dns_transaction.h"
6 6
7 #include <deque> 7 #include <deque>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 virtual const BoundNetLog& GetSocketNetLog() const OVERRIDE { 332 virtual const BoundNetLog& GetSocketNetLog() const OVERRIDE {
333 return socket_->NetLog(); 333 return socket_->NetLog();
334 } 334 }
335 335
336 private: 336 private:
337 enum State { 337 enum State {
338 STATE_CONNECT_COMPLETE, 338 STATE_CONNECT_COMPLETE,
339 STATE_SEND_LENGTH, 339 STATE_SEND_LENGTH,
340 STATE_SEND_QUERY, 340 STATE_SEND_QUERY,
341 STATE_READ_LENGTH, 341 STATE_READ_LENGTH,
342 STATE_READ_LENGTH_COMPLETE,
342 STATE_READ_RESPONSE, 343 STATE_READ_RESPONSE,
344 STATE_READ_RESPONSE_COMPLETE,
343 STATE_NONE, 345 STATE_NONE,
344 }; 346 };
345 347
346 int DoLoop(int result) { 348 int DoLoop(int result) {
347 CHECK_NE(STATE_NONE, next_state_); 349 CHECK_NE(STATE_NONE, next_state_);
348 int rv = result; 350 int rv = result;
349 do { 351 do {
350 State state = next_state_; 352 State state = next_state_;
351 next_state_ = STATE_NONE; 353 next_state_ = STATE_NONE;
352 switch (state) { 354 switch (state) {
353 case STATE_CONNECT_COMPLETE: 355 case STATE_CONNECT_COMPLETE:
354 rv = DoConnectComplete(rv); 356 rv = DoConnectComplete(rv);
355 break; 357 break;
356 case STATE_SEND_LENGTH: 358 case STATE_SEND_LENGTH:
357 rv = DoSendLength(rv); 359 rv = DoSendLength(rv);
358 break; 360 break;
359 case STATE_SEND_QUERY: 361 case STATE_SEND_QUERY:
360 rv = DoSendQuery(rv); 362 rv = DoSendQuery(rv);
361 break; 363 break;
362 case STATE_READ_LENGTH: 364 case STATE_READ_LENGTH:
363 rv = DoReadLength(rv); 365 rv = DoReadLength(rv);
364 break; 366 break;
367 case STATE_READ_LENGTH_COMPLETE:
368 rv = DoReadLengthComplete(rv);
369 break;
365 case STATE_READ_RESPONSE: 370 case STATE_READ_RESPONSE:
366 rv = DoReadResponse(rv); 371 rv = DoReadResponse(rv);
367 break; 372 break;
373 case STATE_READ_RESPONSE_COMPLETE:
374 rv = DoReadResponseComplete(rv);
375 break;
368 default: 376 default:
369 NOTREACHED(); 377 NOTREACHED();
370 break; 378 break;
371 } 379 }
372 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 380 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
373 381
374 set_result(rv); 382 set_result(rv);
375 if (rv == OK) { 383 if (rv == OK) {
376 DCHECK_EQ(STATE_NONE, next_state_); 384 DCHECK_EQ(STATE_NONE, next_state_);
377 DNS_HISTOGRAM("AsyncDNS.TCPAttemptSuccess", 385 DNS_HISTOGRAM("AsyncDNS.TCPAttemptSuccess",
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 buffer_->BytesRemaining(), 436 buffer_->BytesRemaining(),
429 base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this))); 437 base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this)));
430 } 438 }
431 buffer_ = 439 buffer_ =
432 new DrainableIOBuffer(length_buffer_.get(), length_buffer_->size()); 440 new DrainableIOBuffer(length_buffer_.get(), length_buffer_->size());
433 next_state_ = STATE_READ_LENGTH; 441 next_state_ = STATE_READ_LENGTH;
434 return OK; 442 return OK;
435 } 443 }
436 444
437 int DoReadLength(int rv) { 445 int DoReadLength(int rv) {
446 DCHECK_EQ(OK, rv);
447
448 next_state_ = STATE_READ_LENGTH_COMPLETE;
449 return ReadIntoBuffer();
450 }
451
452 int DoReadLengthComplete(int rv) {
438 DCHECK_NE(ERR_IO_PENDING, rv); 453 DCHECK_NE(ERR_IO_PENDING, rv);
439 if (rv < 0) 454 if (rv < 0)
440 return rv; 455 return rv;
456 if (rv == 0)
457 return ERR_CONNECTION_CLOSED;
441 458
442 buffer_->DidConsume(rv); 459 buffer_->DidConsume(rv);
443 if (buffer_->BytesRemaining() > 0) { 460 if (buffer_->BytesRemaining() > 0) {
444 next_state_ = STATE_READ_LENGTH; 461 next_state_ = STATE_READ_LENGTH;
445 return socket_->Read( 462 return OK;
446 buffer_.get(),
447 buffer_->BytesRemaining(),
448 base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this)));
449 } 463 }
464
450 base::ReadBigEndian<uint16>(length_buffer_->data(), &response_length_); 465 base::ReadBigEndian<uint16>(length_buffer_->data(), &response_length_);
451 // Check if advertised response is too short. (Optimization only.) 466 // Check if advertised response is too short. (Optimization only.)
452 if (response_length_ < query_->io_buffer()->size()) 467 if (response_length_ < query_->io_buffer()->size())
453 return ERR_DNS_MALFORMED_RESPONSE; 468 return ERR_DNS_MALFORMED_RESPONSE;
454 // Allocate more space so that DnsResponse::InitParse sanity check passes. 469 // Allocate more space so that DnsResponse::InitParse sanity check passes.
455 response_.reset(new DnsResponse(response_length_ + 1)); 470 response_.reset(new DnsResponse(response_length_ + 1));
456 buffer_ = new DrainableIOBuffer(response_->io_buffer(), response_length_); 471 buffer_ = new DrainableIOBuffer(response_->io_buffer(), response_length_);
457 next_state_ = STATE_READ_RESPONSE; 472 next_state_ = STATE_READ_RESPONSE;
458 return OK; 473 return OK;
459 } 474 }
460 475
461 int DoReadResponse(int rv) { 476 int DoReadResponse(int rv) {
477 DCHECK_EQ(OK, rv);
478
479 next_state_ = STATE_READ_RESPONSE_COMPLETE;
480 return ReadIntoBuffer();
481 }
482
483 int DoReadResponseComplete(int rv) {
462 DCHECK_NE(ERR_IO_PENDING, rv); 484 DCHECK_NE(ERR_IO_PENDING, rv);
463 if (rv < 0) 485 if (rv < 0)
464 return rv; 486 return rv;
487 if (rv == 0)
488 return ERR_CONNECTION_CLOSED;
465 489
466 buffer_->DidConsume(rv); 490 buffer_->DidConsume(rv);
467 if (buffer_->BytesRemaining() > 0) { 491 if (buffer_->BytesRemaining() > 0) {
468 next_state_ = STATE_READ_RESPONSE; 492 next_state_ = STATE_READ_RESPONSE;
469 return socket_->Read( 493 return OK;
470 buffer_.get(),
471 buffer_->BytesRemaining(),
472 base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this)));
473 } 494 }
495
474 if (!response_->InitParse(buffer_->BytesConsumed(), *query_)) 496 if (!response_->InitParse(buffer_->BytesConsumed(), *query_))
475 return ERR_DNS_MALFORMED_RESPONSE; 497 return ERR_DNS_MALFORMED_RESPONSE;
476 if (response_->flags() & dns_protocol::kFlagTC) 498 if (response_->flags() & dns_protocol::kFlagTC)
477 return ERR_UNEXPECTED; 499 return ERR_UNEXPECTED;
478 // TODO(szym): Frankly, none of these are expected. 500 // TODO(szym): Frankly, none of these are expected.
479 if (response_->rcode() == dns_protocol::kRcodeNXDOMAIN) 501 if (response_->rcode() == dns_protocol::kRcodeNXDOMAIN)
480 return ERR_NAME_NOT_RESOLVED; 502 return ERR_NAME_NOT_RESOLVED;
481 if (response_->rcode() != dns_protocol::kRcodeNOERROR) 503 if (response_->rcode() != dns_protocol::kRcodeNOERROR)
482 return ERR_DNS_SERVER_FAILED; 504 return ERR_DNS_SERVER_FAILED;
483 505
484 return OK; 506 return OK;
485 } 507 }
486 508
487 void OnIOComplete(int rv) { 509 void OnIOComplete(int rv) {
488 rv = DoLoop(rv); 510 rv = DoLoop(rv);
489 if (rv != ERR_IO_PENDING) 511 if (rv != ERR_IO_PENDING)
490 callback_.Run(rv); 512 callback_.Run(rv);
491 } 513 }
492 514
515 int ReadIntoBuffer() {
516 return socket_->Read(
517 buffer_.get(),
518 buffer_->BytesRemaining(),
519 base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this)));
520 }
521
493 State next_state_; 522 State next_state_;
494 base::TimeTicks start_time_; 523 base::TimeTicks start_time_;
495 524
496 scoped_ptr<StreamSocket> socket_; 525 scoped_ptr<StreamSocket> socket_;
497 scoped_ptr<DnsQuery> query_; 526 scoped_ptr<DnsQuery> query_;
498 scoped_refptr<IOBufferWithSize> length_buffer_; 527 scoped_refptr<IOBufferWithSize> length_buffer_;
499 scoped_refptr<DrainableIOBuffer> buffer_; 528 scoped_refptr<DrainableIOBuffer> buffer_;
500 529
501 uint16 response_length_; 530 uint16 response_length_;
502 scoped_ptr<DnsResponse> response_; 531 scoped_ptr<DnsResponse> response_;
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 } // namespace 984 } // namespace
956 985
957 // static 986 // static
958 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory( 987 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory(
959 DnsSession* session) { 988 DnsSession* session) {
960 return scoped_ptr<DnsTransactionFactory>( 989 return scoped_ptr<DnsTransactionFactory>(
961 new DnsTransactionFactoryImpl(session)); 990 new DnsTransactionFactoryImpl(session));
962 } 991 }
963 992
964 } // namespace net 993 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/dns/dns_transaction_unittest.cc » ('j') | net/dns/dns_transaction_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698