| 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 |