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

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: Handle sync and async cases. Add test. 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') | 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) 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 return received_malformed_response_ ? ERR_DNS_MALFORMED_RESPONSE : rv;
mmenke 2012/08/28 14:15:54 Err...How does this work? It looks like if we eve
szym 2012/08/28 14:59:44 You're right. This isn't finished yet, and the tes
154 return rv;
155 } 155 }
156 156
157 int DoConnect() { 157 int DoConnect() {
158 next_state_ = STATE_SEND_QUERY; 158 next_state_ = STATE_SEND_QUERY;
159 return socket_->Connect(server_); 159 return socket_->Connect(server_);
160 } 160 }
161 161
162 int DoSendQuery() { 162 int DoSendQuery() {
163 next_state_ = STATE_SEND_QUERY_COMPLETE; 163 next_state_ = STATE_SEND_QUERY_COMPLETE;
164 return socket_->Write(query_->io_buffer(), 164 return socket_->Write(query_->io_buffer(),
(...skipping 24 matching lines...) Expand all
189 base::Unretained(this))); 189 base::Unretained(this)));
190 } 190 }
191 191
192 int DoReadResponseComplete(int rv) { 192 int DoReadResponseComplete(int rv) {
193 DCHECK_NE(ERR_IO_PENDING, rv); 193 DCHECK_NE(ERR_IO_PENDING, rv);
194 if (rv < 0) 194 if (rv < 0)
195 return rv; 195 return rv;
196 196
197 DCHECK(rv); 197 DCHECK(rv);
198 if (!response_->InitParse(rv, *query_)) { 198 if (!response_->InitParse(rv, *query_)) {
199 // TODO(szym): Consider making this reaction less aggressive.
200 // Other implementations simply ignore mismatched responses. Since each 199 // Other implementations simply ignore mismatched responses. Since each
201 // DnsUDPAttempt binds to a different port, we might find that responses 200 // DnsUDPAttempt binds to a different port, we might find that responses
202 // to previously timed out queries lead to failures in the future. 201 // to previously timed out queries lead to failures in the future.
203 // http://crbug.com/107413 202 // Our solution is to make another attempt, in case the query truly
204 return ERR_DNS_MALFORMED_RESPONSE; 203 // failed, but keep this attempt alive, in case it was a false alarm.
204 received_malformed_response_ = true;
205 next_state_ = STATE_READ_RESPONSE;
206 return ERR_IO_PENDING;
205 } 207 }
206 if (response_->flags() & dns_protocol::kFlagTC) 208 if (response_->flags() & dns_protocol::kFlagTC)
207 return ERR_DNS_SERVER_REQUIRES_TCP; 209 return ERR_DNS_SERVER_REQUIRES_TCP;
208 // TODO(szym): Extract TTL for NXDOMAIN results. http://crbug.com/115051 210 // TODO(szym): Extract TTL for NXDOMAIN results. http://crbug.com/115051
209 if (response_->rcode() == dns_protocol::kRcodeNXDOMAIN) 211 if (response_->rcode() == dns_protocol::kRcodeNXDOMAIN)
210 return ERR_NAME_NOT_RESOLVED; 212 return ERR_NAME_NOT_RESOLVED;
211 if (response_->rcode() != dns_protocol::kRcodeNOERROR) 213 if (response_->rcode() != dns_protocol::kRcodeNOERROR)
212 return ERR_DNS_SERVER_FAILED; 214 return ERR_DNS_SERVER_FAILED;
213 215
214 CHECK(response()); 216 CHECK(response());
215 return OK; 217 return OK;
216 } 218 }
217 219
218 void OnIOComplete(int rv) { 220 void OnIOComplete(int rv) {
219 rv = DoLoop(rv); 221 rv = DoLoop(rv);
220 if (rv != ERR_IO_PENDING) 222 if (rv != ERR_IO_PENDING)
221 callback_.Run(rv); 223 callback_.Run(rv);
222 } 224 }
223 225
224 State next_state_; 226 State next_state_;
227 bool received_malformed_response_;
225 228
226 scoped_ptr<DatagramClientSocket> socket_; 229 scoped_ptr<DatagramClientSocket> socket_;
227 IPEndPoint server_; 230 IPEndPoint server_;
228 scoped_ptr<DnsQuery> query_; 231 scoped_ptr<DnsQuery> query_;
229 232
230 scoped_ptr<DnsResponse> response_; 233 scoped_ptr<DnsResponse> response_;
231 234
232 CompletionCallback callback_; 235 CompletionCallback callback_;
233 236
234 DISALLOW_COPY_AND_ASSIGN(DnsUDPAttempt); 237 DISALLOW_COPY_AND_ASSIGN(DnsUDPAttempt);
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 } // namespace 582 } // namespace
580 583
581 // static 584 // static
582 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory( 585 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory(
583 DnsSession* session) { 586 DnsSession* session) {
584 return scoped_ptr<DnsTransactionFactory>( 587 return scoped_ptr<DnsTransactionFactory>(
585 new DnsTransactionFactoryImpl(session)); 588 new DnsTransactionFactoryImpl(session));
586 } 589 }
587 590
588 } // namespace net 591 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/dns/dns_transaction_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698