Index: net/dns/dns_transaction.cc |
diff --git a/net/dns/dns_transaction.cc b/net/dns/dns_transaction.cc |
index 130922c6025620f821e6662d5ebfb318da00fb89..65c2f5e3771f8f4daf915050262d81b22e211453 100644 |
--- a/net/dns/dns_transaction.cc |
+++ b/net/dns/dns_transaction.cc |
@@ -338,7 +338,9 @@ class DnsTCPAttempt : public DnsAttempt { |
STATE_CONNECT_COMPLETE, |
STATE_SEND_LENGTH, |
STATE_SEND_QUERY, |
+ STATE_START_READING_LENGTH, |
STATE_READ_LENGTH, |
+ STATE_START_READING_RESPONSE, |
STATE_READ_RESPONSE, |
STATE_NONE, |
}; |
@@ -359,9 +361,15 @@ class DnsTCPAttempt : public DnsAttempt { |
case STATE_SEND_QUERY: |
rv = DoSendQuery(rv); |
break; |
+ case STATE_START_READING_LENGTH: |
+ rv = DoStartReadingLength(rv); |
+ break; |
case STATE_READ_LENGTH: |
rv = DoReadLength(rv); |
break; |
+ case STATE_START_READING_RESPONSE: |
+ rv = DoStartReadingResponse(rv); |
+ break; |
case STATE_READ_RESPONSE: |
rv = DoReadResponse(rv); |
break; |
@@ -430,23 +438,32 @@ class DnsTCPAttempt : public DnsAttempt { |
} |
buffer_ = |
new DrainableIOBuffer(length_buffer_.get(), length_buffer_->size()); |
- next_state_ = STATE_READ_LENGTH; |
+ next_state_ = STATE_START_READING_LENGTH; |
return OK; |
} |
+ int DoStartReadingLength(int rv) { |
+ DCHECK_NE(ERR_IO_PENDING, rv); |
+ if (rv < 0) |
+ return rv; |
+ |
+ next_state_ = STATE_READ_LENGTH; |
+ return ReadIntoBuffer(); |
+ } |
+ |
int DoReadLength(int rv) { |
DCHECK_NE(ERR_IO_PENDING, rv); |
if (rv < 0) |
return rv; |
+ if (rv == 0) |
+ return ERR_CONNECTION_CLOSED; |
buffer_->DidConsume(rv); |
if (buffer_->BytesRemaining() > 0) { |
next_state_ = STATE_READ_LENGTH; |
- return socket_->Read( |
- buffer_.get(), |
- buffer_->BytesRemaining(), |
- base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this))); |
+ return ReadIntoBuffer(); |
} |
+ |
base::ReadBigEndian<uint16>(length_buffer_->data(), &response_length_); |
// Check if advertised response is too short. (Optimization only.) |
if (response_length_ < query_->io_buffer()->size()) |
@@ -454,23 +471,32 @@ class DnsTCPAttempt : public DnsAttempt { |
// Allocate more space so that DnsResponse::InitParse sanity check passes. |
response_.reset(new DnsResponse(response_length_ + 1)); |
buffer_ = new DrainableIOBuffer(response_->io_buffer(), response_length_); |
- next_state_ = STATE_READ_RESPONSE; |
+ next_state_ = STATE_START_READING_RESPONSE; |
return OK; |
} |
+ int DoStartReadingResponse(int rv) { |
+ DCHECK_NE(ERR_IO_PENDING, rv); |
+ if (rv < 0) |
+ return rv; |
+ |
+ next_state_ = STATE_READ_RESPONSE; |
+ return ReadIntoBuffer(); |
+ } |
+ |
int DoReadResponse(int rv) { |
DCHECK_NE(ERR_IO_PENDING, rv); |
if (rv < 0) |
return rv; |
+ if (rv == 0) |
+ return ERR_CONNECTION_CLOSED; |
buffer_->DidConsume(rv); |
if (buffer_->BytesRemaining() > 0) { |
next_state_ = STATE_READ_RESPONSE; |
- return socket_->Read( |
- buffer_.get(), |
- buffer_->BytesRemaining(), |
- base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this))); |
+ return ReadIntoBuffer(); |
mmenke
2014/08/01 15:38:42
I think this would be much clearer with:
// Note
Deprecated (see juliatuttle)
2014/08/01 22:01:10
Done.
|
} |
+ |
if (!response_->InitParse(buffer_->BytesConsumed(), *query_)) |
return ERR_DNS_MALFORMED_RESPONSE; |
if (response_->flags() & dns_protocol::kFlagTC) |
@@ -490,6 +516,14 @@ class DnsTCPAttempt : public DnsAttempt { |
callback_.Run(rv); |
} |
+ int ReadIntoBuffer() { |
+ int rv = socket_->Read( |
+ buffer_.get(), |
+ buffer_->BytesRemaining(), |
+ base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this))); |
+ return (rv != 0) ? rv : ERR_CONNECTION_CLOSED; |
+ } |
+ |
State next_state_; |
base::TimeTicks start_time_; |