OLD | NEW |
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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 } | 44 } |
45 | 45 |
46 bool IsIPLiteral(const std::string& hostname) { | 46 bool IsIPLiteral(const std::string& hostname) { |
47 IPAddressNumber ip; | 47 IPAddressNumber ip; |
48 return ParseIPLiteralToNumber(hostname, &ip); | 48 return ParseIPLiteralToNumber(hostname, &ip); |
49 } | 49 } |
50 | 50 |
51 class StartParameters : public NetLog::EventParameters { | 51 class StartParameters : public NetLog::EventParameters { |
52 public: | 52 public: |
53 StartParameters(const std::string& hostname, | 53 StartParameters(const std::string& hostname, |
54 uint16 qtype, | 54 uint16 qtype) |
55 const NetLog::Source& source) | 55 : hostname_(hostname), qtype_(qtype) {} |
56 : hostname_(hostname), qtype_(qtype), source_(source) {} | |
57 | 56 |
58 virtual Value* ToValue() const OVERRIDE { | 57 virtual Value* ToValue() const OVERRIDE { |
59 DictionaryValue* dict = new DictionaryValue(); | 58 DictionaryValue* dict = new DictionaryValue(); |
60 dict->SetString("hostname", hostname_); | 59 dict->SetString("hostname", hostname_); |
61 dict->SetInteger("query_type", qtype_); | 60 dict->SetInteger("query_type", qtype_); |
62 dict->Set("source_dependency", source_.ToValue()); | |
63 return dict; | 61 return dict; |
64 } | 62 } |
65 | 63 |
66 private: | 64 private: |
67 const std::string hostname_; | 65 const std::string hostname_; |
68 const uint16 qtype_; | 66 const uint16 qtype_; |
69 const NetLog::Source source_; | |
70 }; | 67 }; |
71 | 68 |
72 class ResponseParameters : public NetLog::EventParameters { | 69 class ResponseParameters : public NetLog::EventParameters { |
73 public: | 70 public: |
74 ResponseParameters(int rcode, int answer_count, const NetLog::Source& source) | 71 ResponseParameters(int rcode, int answer_count, const NetLog::Source& source) |
75 : rcode_(rcode), answer_count_(answer_count), source_(source) {} | 72 : rcode_(rcode), answer_count_(answer_count), source_(source) {} |
76 | 73 |
77 virtual Value* ToValue() const OVERRIDE { | 74 virtual Value* ToValue() const OVERRIDE { |
78 DictionaryValue* dict = new DictionaryValue(); | 75 DictionaryValue* dict = new DictionaryValue(); |
79 dict->SetInteger("rcode", rcode_); | 76 dict->SetInteger("rcode", rcode_); |
80 dict->SetInteger("answer_count", answer_count_); | 77 dict->SetInteger("answer_count", answer_count_); |
81 dict->Set("socket_source", source_.ToValue()); | 78 dict->Set("source_dependency", source_.ToValue()); |
82 return dict; | 79 return dict; |
83 } | 80 } |
84 | 81 |
85 private: | 82 private: |
86 const int rcode_; | 83 const int rcode_; |
87 const int answer_count_; | 84 const int answer_count_; |
88 const NetLog::Source source_; | 85 const NetLog::Source source_; |
89 }; | 86 }; |
90 | 87 |
91 // ---------------------------------------------------------------------------- | 88 // ---------------------------------------------------------------------------- |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 base::Bind(&DnsUDPAttempt::OnIOComplete, | 201 base::Bind(&DnsUDPAttempt::OnIOComplete, |
205 base::Unretained(this))); | 202 base::Unretained(this))); |
206 } | 203 } |
207 | 204 |
208 int DoReadResponseComplete(int rv) { | 205 int DoReadResponseComplete(int rv) { |
209 DCHECK_NE(ERR_IO_PENDING, rv); | 206 DCHECK_NE(ERR_IO_PENDING, rv); |
210 if (rv < 0) | 207 if (rv < 0) |
211 return rv; | 208 return rv; |
212 | 209 |
213 DCHECK(rv); | 210 DCHECK(rv); |
214 if (!response_->InitParse(rv, *query_)) | 211 if (!response_->InitParse(rv, *query_)) { |
| 212 // TODO(szym): Consider making this reaction less aggressive. |
| 213 // Other implementations simply ignore mismatched responses. Since each |
| 214 // DnsUDPAttempt binds to a different port, we might find that responses |
| 215 // to previously timed out queries lead to failures in the future. |
| 216 // http://crbug.com/107413 |
215 return ERR_DNS_MALFORMED_RESPONSE; | 217 return ERR_DNS_MALFORMED_RESPONSE; |
| 218 } |
216 if (response_->flags() & dns_protocol::kFlagTC) | 219 if (response_->flags() & dns_protocol::kFlagTC) |
217 return ERR_DNS_SERVER_REQUIRES_TCP; | 220 return ERR_DNS_SERVER_REQUIRES_TCP; |
218 if (response_->rcode() != dns_protocol::kRcodeNOERROR && | 221 if (response_->rcode() != dns_protocol::kRcodeNOERROR && |
219 response_->rcode() != dns_protocol::kRcodeNXDOMAIN) { | 222 response_->rcode() != dns_protocol::kRcodeNXDOMAIN) { |
220 return ERR_DNS_SERVER_FAILED; | 223 return ERR_DNS_SERVER_FAILED; |
221 } | 224 } |
222 if (response_->answer_count() == 0) | 225 if (response_->answer_count() == 0) |
223 return ERR_NAME_NOT_RESOLVED; | 226 return ERR_NAME_NOT_RESOLVED; |
224 | 227 |
225 return OK; | 228 return OK; |
(...skipping 25 matching lines...) Expand all Loading... |
251 // The timeout for each DnsUDPAttempt is given by DnsSession::NextTimeout. | 254 // The timeout for each DnsUDPAttempt is given by DnsSession::NextTimeout. |
252 // The first server to attempt on each query is given by | 255 // The first server to attempt on each query is given by |
253 // DnsSession::NextFirstServerIndex, and the order is round-robin afterwards. | 256 // DnsSession::NextFirstServerIndex, and the order is round-robin afterwards. |
254 // Each server is attempted DnsConfig::attempts times. | 257 // Each server is attempted DnsConfig::attempts times. |
255 class DnsTransactionImpl : public DnsTransaction, public base::NonThreadSafe { | 258 class DnsTransactionImpl : public DnsTransaction, public base::NonThreadSafe { |
256 public: | 259 public: |
257 DnsTransactionImpl(DnsSession* session, | 260 DnsTransactionImpl(DnsSession* session, |
258 const std::string& hostname, | 261 const std::string& hostname, |
259 uint16 qtype, | 262 uint16 qtype, |
260 const DnsTransactionFactory::CallbackType& callback, | 263 const DnsTransactionFactory::CallbackType& callback, |
261 const BoundNetLog& source_net_log) | 264 const BoundNetLog& net_log) |
262 : session_(session), | 265 : session_(session), |
263 hostname_(hostname), | 266 hostname_(hostname), |
264 qtype_(qtype), | 267 qtype_(qtype), |
265 callback_(callback), | 268 callback_(callback), |
266 net_log_(BoundNetLog::Make(session->net_log(), | 269 net_log_(net_log), |
267 NetLog::SOURCE_DNS_TRANSACTION)), | |
268 first_server_index_(0) { | 270 first_server_index_(0) { |
269 DCHECK(session_); | 271 DCHECK(session_); |
270 DCHECK(!hostname_.empty()); | 272 DCHECK(!hostname_.empty()); |
271 DCHECK(!callback_.is_null()); | 273 DCHECK(!callback_.is_null()); |
272 | 274 |
273 DCHECK(!IsIPLiteral(hostname_)); | 275 DCHECK(!IsIPLiteral(hostname_)); |
274 | 276 |
275 net_log_.BeginEvent(NetLog::TYPE_DNS_TRANSACTION, make_scoped_refptr( | 277 net_log_.BeginEvent(NetLog::TYPE_DNS_TRANSACTION, make_scoped_refptr( |
276 new StartParameters(hostname_, qtype_, source_net_log.source()))); | 278 new StartParameters(hostname_, qtype_))); |
277 } | 279 } |
278 | 280 |
279 virtual ~DnsTransactionImpl() { | 281 virtual ~DnsTransactionImpl() { |
280 STLDeleteElements(&attempts_); | 282 STLDeleteElements(&attempts_); |
281 if (!callback_.is_null()) { | 283 if (!callback_.is_null()) { |
282 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); | 284 net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); |
283 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION, | 285 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION, |
284 ERR_ABORTED); | 286 ERR_ABORTED); |
285 } | 287 } |
286 } | 288 } |
287 | 289 |
288 virtual const std::string& GetHostname() const OVERRIDE { | 290 virtual const std::string& GetHostname() const OVERRIDE { |
289 DCHECK(CalledOnValidThread()); | 291 DCHECK(CalledOnValidThread()); |
290 return hostname_; | 292 return hostname_; |
291 } | 293 } |
292 | 294 |
293 virtual uint16 GetType() const OVERRIDE { | 295 virtual uint16 GetType() const OVERRIDE { |
294 DCHECK(CalledOnValidThread()); | 296 DCHECK(CalledOnValidThread()); |
295 return qtype_; | 297 return qtype_; |
296 } | 298 } |
297 | 299 |
298 virtual int Start() OVERRIDE { | 300 virtual int Start() OVERRIDE { |
299 int rv = PrepareSearch(); | 301 int rv = PrepareSearch(); |
300 if (rv == OK) | 302 if (rv == OK) |
301 rv = StartQuery(); | 303 rv = StartQuery(); |
302 DCHECK_NE(OK, rv); | 304 if (rv == OK) { |
| 305 // In the very unlikely case that we immediately received the response, we |
| 306 // cannot simply return OK nor run the callback, but instead complete |
| 307 // asynchronously. |
| 308 // TODO(szym): replace Unretained with WeakPtr factory. |
| 309 MessageLoop::current()->PostTask( |
| 310 FROM_HERE, |
| 311 base::Bind(&DnsTransactionImpl::DoCallback, |
| 312 base::Unretained(this), |
| 313 OK, |
| 314 attempts_.back())); |
| 315 return ERR_IO_PENDING; |
| 316 } |
303 return rv; | 317 return rv; |
304 } | 318 } |
305 | 319 |
306 private: | 320 private: |
307 // Prepares |qnames_| according to the DnsConfig. | 321 // Prepares |qnames_| according to the DnsConfig. |
308 int PrepareSearch() { | 322 int PrepareSearch() { |
309 const DnsConfig& config = session_->config(); | 323 const DnsConfig& config = session_->config(); |
310 | 324 |
311 std::string labeled_hostname; | 325 std::string labeled_hostname; |
312 if (!DNSDomainFromDot(hostname_, &labeled_hostname)) | 326 if (!DNSDomainFromDot(hostname_, &labeled_hostname)) |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 | 394 |
381 uint16 id = session_->NextQueryId(); | 395 uint16 id = session_->NextQueryId(); |
382 scoped_ptr<DnsQuery> query; | 396 scoped_ptr<DnsQuery> query; |
383 if (attempts_.empty()) { | 397 if (attempts_.empty()) { |
384 query.reset(new DnsQuery(id, qnames_.front(), qtype_)); | 398 query.reset(new DnsQuery(id, qnames_.front(), qtype_)); |
385 } else { | 399 } else { |
386 query.reset(attempts_[0]->query()->CloneWithNewId(id)); | 400 query.reset(attempts_[0]->query()->CloneWithNewId(id)); |
387 } | 401 } |
388 | 402 |
389 net_log_.AddEvent(NetLog::TYPE_DNS_TRANSACTION_ATTEMPT, make_scoped_refptr( | 403 net_log_.AddEvent(NetLog::TYPE_DNS_TRANSACTION_ATTEMPT, make_scoped_refptr( |
390 new NetLogSourceParameter("socket_source", socket->NetLog().source()))); | 404 new NetLogSourceParameter("source_dependency", |
| 405 socket->NetLog().source()))); |
391 | 406 |
392 const DnsConfig& config = session_->config(); | 407 const DnsConfig& config = session_->config(); |
393 | 408 |
394 unsigned server_index = first_server_index_ + | 409 unsigned server_index = first_server_index_ + |
395 (attempt_number % config.nameservers.size()); | 410 (attempt_number % config.nameservers.size()); |
396 | 411 |
397 DnsUDPAttempt* attempt = new DnsUDPAttempt( | 412 DnsUDPAttempt* attempt = new DnsUDPAttempt( |
398 socket.Pass(), | 413 socket.Pass(), |
399 config.nameservers[server_index], | 414 config.nameservers[server_index], |
400 query.Pass(), | 415 query.Pass(), |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 qnames_.pop_front(); | 459 qnames_.pop_front(); |
445 if (qnames_.empty()) | 460 if (qnames_.empty()) |
446 rv = ERR_NAME_NOT_RESOLVED; | 461 rv = ERR_NAME_NOT_RESOLVED; |
447 else | 462 else |
448 rv = StartQuery(); | 463 rv = StartQuery(); |
449 break; | 464 break; |
450 case OK: | 465 case OK: |
451 DoCallback(rv, attempt); | 466 DoCallback(rv, attempt); |
452 return; | 467 return; |
453 default: | 468 default: |
454 // TODO(szym): Some nameservers could fail so try the next one. | 469 // Some nameservers could fail so try the next one. |
455 const DnsConfig& config = session_->config(); | 470 const DnsConfig& config = session_->config(); |
456 if (attempts_.size() < config.attempts * config.nameservers.size()) { | 471 if (attempts_.size() < config.attempts * config.nameservers.size()) { |
457 rv = MakeAttempt(); | 472 rv = MakeAttempt(); |
458 } else { | 473 } else { |
459 // TODO(szym): Should this be different than the timeout case? | 474 // TODO(szym): Should this be different than the timeout case? |
460 rv = ERR_DNS_SERVER_FAILED; | 475 rv = ERR_DNS_SERVER_FAILED; |
461 } | 476 } |
462 break; | 477 break; |
463 } | 478 } |
464 if (rv != ERR_IO_PENDING) | 479 if (rv != ERR_IO_PENDING) |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
505 class DnsTransactionFactoryImpl : public DnsTransactionFactory { | 520 class DnsTransactionFactoryImpl : public DnsTransactionFactory { |
506 public: | 521 public: |
507 explicit DnsTransactionFactoryImpl(DnsSession* session) { | 522 explicit DnsTransactionFactoryImpl(DnsSession* session) { |
508 session_ = session; | 523 session_ = session; |
509 } | 524 } |
510 | 525 |
511 virtual scoped_ptr<DnsTransaction> CreateTransaction( | 526 virtual scoped_ptr<DnsTransaction> CreateTransaction( |
512 const std::string& hostname, | 527 const std::string& hostname, |
513 uint16 qtype, | 528 uint16 qtype, |
514 const CallbackType& callback, | 529 const CallbackType& callback, |
515 const BoundNetLog& source_net_log) OVERRIDE { | 530 const BoundNetLog& net_log) OVERRIDE { |
516 return scoped_ptr<DnsTransaction>(new DnsTransactionImpl(session_, | 531 return scoped_ptr<DnsTransaction>(new DnsTransactionImpl(session_, |
517 hostname, | 532 hostname, |
518 qtype, | 533 qtype, |
519 callback, | 534 callback, |
520 source_net_log)); | 535 net_log)); |
521 } | 536 } |
522 | 537 |
523 private: | 538 private: |
524 scoped_refptr<DnsSession> session_; | 539 scoped_refptr<DnsSession> session_; |
525 }; | 540 }; |
526 | 541 |
527 } // namespace | 542 } // namespace |
528 | 543 |
529 // static | 544 // static |
530 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory( | 545 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory( |
531 DnsSession* session) { | 546 DnsSession* session) { |
532 return scoped_ptr<DnsTransactionFactory>( | 547 return scoped_ptr<DnsTransactionFactory>( |
533 new DnsTransactionFactoryImpl(session)); | 548 new DnsTransactionFactoryImpl(session)); |
534 } | 549 } |
535 | 550 |
536 } // namespace net | 551 } // namespace net |
537 | 552 |
OLD | NEW |