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

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

Issue 10824238: [net/dns] Don't abandon a DnsUDPAttempt when the response does not match the query. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: delinted; comments Created 8 years, 3 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 // A single asynchronous DNS exchange over UDP, which consists of sending out a 64 // A single asynchronous DNS exchange over UDP, which consists of sending out a
65 // DNS query, waiting for a response, and returning the response that it 65 // DNS query, waiting for a response, and returning the response that it
66 // matches. Logging is done in the socket and in the outer DnsTransaction. 66 // matches. Logging is done in the socket and in the outer DnsTransaction.
67 class DnsUDPAttempt { 67 class DnsUDPAttempt {
68 public: 68 public:
69 DnsUDPAttempt(scoped_ptr<DatagramClientSocket> socket, 69 DnsUDPAttempt(scoped_ptr<DatagramClientSocket> socket,
70 const IPEndPoint& server, 70 const IPEndPoint& server,
71 scoped_ptr<DnsQuery> query, 71 scoped_ptr<DnsQuery> query,
72 const CompletionCallback& callback) 72 const CompletionCallback& callback)
73 : next_state_(STATE_NONE), 73 : next_state_(STATE_NONE),
74 received_malformed_response_(false),
74 socket_(socket.Pass()), 75 socket_(socket.Pass()),
75 server_(server), 76 server_(server),
76 query_(query.Pass()), 77 query_(query.Pass()),
77 callback_(callback) { 78 callback_(callback) {
78 } 79 }
79 80
80 // Starts the attempt. Returns ERR_IO_PENDING if cannot complete synchronously 81 // Starts the attempt. Returns ERR_IO_PENDING if cannot complete synchronously
81 // and calls |callback| upon completion. 82 // and calls |callback| upon completion.
82 int Start() { 83 int Start() {
83 DCHECK_EQ(STATE_NONE, next_state_); 84 DCHECK_EQ(STATE_NONE, next_state_);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 rv = DoReadResponse(); 144 rv = DoReadResponse();
144 break; 145 break;
145 case STATE_READ_RESPONSE_COMPLETE: 146 case STATE_READ_RESPONSE_COMPLETE:
146 rv = DoReadResponseComplete(rv); 147 rv = DoReadResponseComplete(rv);
147 break; 148 break;
148 default: 149 default:
149 NOTREACHED(); 150 NOTREACHED();
150 break; 151 break;
151 } 152 }
152 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 153 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
153 154 // Indicate to the transaction that the server might be misbehaving.
155 if (rv == ERR_IO_PENDING && received_malformed_response_)
156 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
157 // If we received any other result, it takes precedence.
158 received_malformed_response_ = false;
szym 2012/08/29 21:37:26 On second thought, this is not necessary. At that
154 return rv; 159 return rv;
155 } 160 }
156 161
157 int DoConnect() { 162 int DoConnect() {
158 next_state_ = STATE_SEND_QUERY; 163 next_state_ = STATE_SEND_QUERY;
159 return socket_->Connect(server_); 164 return socket_->Connect(server_);
160 } 165 }
161 166
162 int DoSendQuery() { 167 int DoSendQuery() {
163 next_state_ = STATE_SEND_QUERY_COMPLETE; 168 next_state_ = STATE_SEND_QUERY_COMPLETE;
(...skipping 25 matching lines...) Expand all
189 base::Unretained(this))); 194 base::Unretained(this)));
190 } 195 }
191 196
192 int DoReadResponseComplete(int rv) { 197 int DoReadResponseComplete(int rv) {
193 DCHECK_NE(ERR_IO_PENDING, rv); 198 DCHECK_NE(ERR_IO_PENDING, rv);
194 if (rv < 0) 199 if (rv < 0)
195 return rv; 200 return rv;
196 201
197 DCHECK(rv); 202 DCHECK(rv);
198 if (!response_->InitParse(rv, *query_)) { 203 if (!response_->InitParse(rv, *query_)) {
199 // TODO(szym): Consider making this reaction less aggressive.
200 // Other implementations simply ignore mismatched responses. Since each 204 // Other implementations simply ignore mismatched responses. Since each
201 // DnsUDPAttempt binds to a different port, we might find that responses 205 // DnsUDPAttempt binds to a different port, we might find that responses
202 // to previously timed out queries lead to failures in the future. 206 // to previously timed out queries lead to failures in the future.
203 // http://crbug.com/107413 207 // Our solution is to make another attempt, in case the query truly
204 return ERR_DNS_MALFORMED_RESPONSE; 208 // failed, but keep this attempt alive, in case it was a false alarm.
209 received_malformed_response_ = true;
210 next_state_ = STATE_READ_RESPONSE;
211 return OK;
205 } 212 }
206 if (response_->flags() & dns_protocol::kFlagTC) 213 if (response_->flags() & dns_protocol::kFlagTC)
207 return ERR_DNS_SERVER_REQUIRES_TCP; 214 return ERR_DNS_SERVER_REQUIRES_TCP;
208 // TODO(szym): Extract TTL for NXDOMAIN results. http://crbug.com/115051 215 // TODO(szym): Extract TTL for NXDOMAIN results. http://crbug.com/115051
209 if (response_->rcode() == dns_protocol::kRcodeNXDOMAIN) 216 if (response_->rcode() == dns_protocol::kRcodeNXDOMAIN)
210 return ERR_NAME_NOT_RESOLVED; 217 return ERR_NAME_NOT_RESOLVED;
211 if (response_->rcode() != dns_protocol::kRcodeNOERROR) 218 if (response_->rcode() != dns_protocol::kRcodeNOERROR)
212 return ERR_DNS_SERVER_FAILED; 219 return ERR_DNS_SERVER_FAILED;
213 220
214 CHECK(response()); 221 CHECK(response());
215 return OK; 222 return OK;
216 } 223 }
217 224
218 void OnIOComplete(int rv) { 225 void OnIOComplete(int rv) {
219 rv = DoLoop(rv); 226 rv = DoLoop(rv);
220 if (rv != ERR_IO_PENDING) 227 if (rv != ERR_IO_PENDING)
221 callback_.Run(rv); 228 callback_.Run(rv);
222 } 229 }
223 230
224 State next_state_; 231 State next_state_;
232 bool received_malformed_response_;
225 233
226 scoped_ptr<DatagramClientSocket> socket_; 234 scoped_ptr<DatagramClientSocket> socket_;
227 IPEndPoint server_; 235 IPEndPoint server_;
228 scoped_ptr<DnsQuery> query_; 236 scoped_ptr<DnsQuery> query_;
229 237
230 scoped_ptr<DnsResponse> response_; 238 scoped_ptr<DnsResponse> response_;
231 239
232 CompletionCallback callback_; 240 CompletionCallback callback_;
233 241
234 DISALLOW_COPY_AND_ASSIGN(DnsUDPAttempt); 242 DISALLOW_COPY_AND_ASSIGN(DnsUDPAttempt);
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 break; 511 break;
504 default: 512 default:
505 // Server failure. 513 // Server failure.
506 DCHECK(result.attempt); 514 DCHECK(result.attempt);
507 if (result.attempt != attempts_.back()) { 515 if (result.attempt != attempts_.back()) {
508 // This attempt already timed out. Ignore it. 516 // This attempt already timed out. Ignore it.
509 return AttemptResult(ERR_IO_PENDING, NULL); 517 return AttemptResult(ERR_IO_PENDING, NULL);
510 } 518 }
511 if (MoreAttemptsAllowed()) { 519 if (MoreAttemptsAllowed()) {
512 result = MakeAttempt(); 520 result = MakeAttempt();
513 } else { 521 } else if (result.rv != ERR_DNS_MALFORMED_RESPONSE) {
514 return AttemptResult(result.rv, NULL); 522 return AttemptResult(result.rv, NULL);
515 } 523 } // else wait until attempt times out.
516 break; 524 break;
517 } 525 }
518 } 526 }
519 return result; 527 return result;
520 } 528 }
521 529
522 void OnTimeout() { 530 void OnTimeout() {
523 if (callback_.is_null()) 531 if (callback_.is_null())
524 return; 532 return;
525 AttemptResult result = FinishAttempt( 533 AttemptResult result = FinishAttempt(
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 } // namespace 587 } // namespace
580 588
581 // static 589 // static
582 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory( 590 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory(
583 DnsSession* session) { 591 DnsSession* session) {
584 return scoped_ptr<DnsTransactionFactory>( 592 return scoped_ptr<DnsTransactionFactory>(
585 new DnsTransactionFactoryImpl(session)); 593 new DnsTransactionFactoryImpl(session));
586 } 594 }
587 595
588 } // namespace net 596 } // 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