Chromium Code Reviews| Index: net/dns/dns_transaction.cc |
| diff --git a/net/dns/dns_transaction.cc b/net/dns/dns_transaction.cc |
| index 00d8064f6e8d6f263423659519e9691a99e406aa..98fc9742da419d11a869bc289e03d9c4a1f9ba14 100644 |
| --- a/net/dns/dns_transaction.cc |
| +++ b/net/dns/dns_transaction.cc |
| @@ -71,6 +71,7 @@ class DnsUDPAttempt { |
| scoped_ptr<DnsQuery> query, |
| const CompletionCallback& callback) |
| : next_state_(STATE_NONE), |
| + received_malformed_response_(false), |
| socket_(socket.Pass()), |
| server_(server), |
| query_(query.Pass()), |
| @@ -150,7 +151,11 @@ class DnsUDPAttempt { |
| break; |
| } |
| } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
| - |
| + // Indicate to the transaction that the server might be misbehaving. |
| + if (rv == ERR_IO_PENDING && received_malformed_response_) |
| + return ERR_DNS_MALFORMED_RESPONSE; |
|
mmenke
2012/08/29 16:23:57
When does this happen? Won't we just end up with
szym
2012/08/29 21:37:26
As long as we have packets on the socket, we will
mmenke
2012/08/29 21:43:53
I'm not following. It seems to me like this if st
mmenke
2012/08/29 21:46:42
Err...That should be "that if statement will never
szym
2012/08/29 21:55:05
The goal is not to just ignore malformed packets b
mmenke
2012/08/29 22:01:22
But DoReadResponse sets next_state_ to STATE_READ_
szym
2012/08/29 22:19:11
If DoReadResponse returns ERR_IO_PENDING, then we
mmenke
2012/08/29 22:29:44
Gah, for some reason, I was thinking the next_stat
szym
2012/08/29 22:33:41
Note that the attempt will be kept alive and that
|
| + // If we received any other result, it takes precedence. |
| + received_malformed_response_ = false; |
|
szym
2012/08/29 21:37:26
On second thought, this is not necessary. At that
|
| return rv; |
| } |
| @@ -196,12 +201,14 @@ class DnsUDPAttempt { |
| DCHECK(rv); |
| if (!response_->InitParse(rv, *query_)) { |
| - // TODO(szym): Consider making this reaction less aggressive. |
| // Other implementations simply ignore mismatched responses. Since each |
| // DnsUDPAttempt binds to a different port, we might find that responses |
| // to previously timed out queries lead to failures in the future. |
| - // http://crbug.com/107413 |
| - return ERR_DNS_MALFORMED_RESPONSE; |
| + // Our solution is to make another attempt, in case the query truly |
| + // failed, but keep this attempt alive, in case it was a false alarm. |
| + received_malformed_response_ = true; |
| + next_state_ = STATE_READ_RESPONSE; |
| + return OK; |
| } |
| if (response_->flags() & dns_protocol::kFlagTC) |
| return ERR_DNS_SERVER_REQUIRES_TCP; |
| @@ -222,6 +229,7 @@ class DnsUDPAttempt { |
| } |
| State next_state_; |
| + bool received_malformed_response_; |
| scoped_ptr<DatagramClientSocket> socket_; |
| IPEndPoint server_; |
| @@ -510,9 +518,9 @@ class DnsTransactionImpl : public DnsTransaction, |
| } |
| if (MoreAttemptsAllowed()) { |
| result = MakeAttempt(); |
| - } else { |
| + } else if (result.rv != ERR_DNS_MALFORMED_RESPONSE) { |
| return AttemptResult(result.rv, NULL); |
| - } |
| + } // else wait until attempt times out. |
| break; |
| } |
| } |