| 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 for (size_t i = 0; i < name.size() && name[i]; i += name[i] + 1) | 43 for (size_t i = 0; i < name.size() && name[i]; i += name[i] + 1) |
| 44 ++count; | 44 ++count; |
| 45 return count; | 45 return count; |
| 46 } | 46 } |
| 47 | 47 |
| 48 bool IsIPLiteral(const std::string& hostname) { | 48 bool IsIPLiteral(const std::string& hostname) { |
| 49 IPAddressNumber ip; | 49 IPAddressNumber ip; |
| 50 return ParseIPLiteralToNumber(hostname, &ip); | 50 return ParseIPLiteralToNumber(hostname, &ip); |
| 51 } | 51 } |
| 52 | 52 |
| 53 class StartParameters : public NetLog::EventParameters { | 53 Value* NetLogStartCallback(const std::string* hostname, |
| 54 public: | 54 uint16 qtype, |
| 55 StartParameters(const std::string& hostname, | 55 NetLog::LogLevel /* log_level */) { |
| 56 uint16 qtype) | 56 DictionaryValue* dict = new DictionaryValue(); |
| 57 : hostname_(hostname), qtype_(qtype) {} | 57 dict->SetString("hostname", *hostname); |
| 58 | 58 dict->SetInteger("query_type", qtype); |
| 59 virtual Value* ToValue() const OVERRIDE { | 59 return dict; |
| 60 DictionaryValue* dict = new DictionaryValue(); | |
| 61 dict->SetString("hostname", hostname_); | |
| 62 dict->SetInteger("query_type", qtype_); | |
| 63 return dict; | |
| 64 } | |
| 65 | |
| 66 protected: | |
| 67 virtual ~StartParameters() {} | |
| 68 | |
| 69 private: | |
| 70 const std::string hostname_; | |
| 71 const uint16 qtype_; | |
| 72 }; | |
| 73 | |
| 74 class ResponseParameters : public NetLog::EventParameters { | |
| 75 public: | |
| 76 ResponseParameters(int rcode, int answer_count, const NetLog::Source& source) | |
| 77 : rcode_(rcode), answer_count_(answer_count), source_(source) {} | |
| 78 | |
| 79 virtual Value* ToValue() const OVERRIDE { | |
| 80 DictionaryValue* dict = new DictionaryValue(); | |
| 81 dict->SetInteger("rcode", rcode_); | |
| 82 dict->SetInteger("answer_count", answer_count_); | |
| 83 dict->Set("source_dependency", source_.ToValue()); | |
| 84 return dict; | |
| 85 } | |
| 86 | |
| 87 protected: | |
| 88 virtual ~ResponseParameters() {} | |
| 89 | |
| 90 private: | |
| 91 const int rcode_; | |
| 92 const int answer_count_; | |
| 93 const NetLog::Source source_; | |
| 94 }; | 60 }; |
| 95 | 61 |
| 96 // ---------------------------------------------------------------------------- | 62 // ---------------------------------------------------------------------------- |
| 97 | 63 |
| 98 // 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 |
| 99 // 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 |
| 100 // 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. |
| 101 class DnsUDPAttempt { | 67 class DnsUDPAttempt { |
| 102 public: | 68 public: |
| 103 DnsUDPAttempt(scoped_ptr<DatagramClientSocket> socket, | 69 DnsUDPAttempt(scoped_ptr<DatagramClientSocket> socket, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 127 return socket_.get(); | 93 return socket_.get(); |
| 128 } | 94 } |
| 129 | 95 |
| 130 // Returns the response or NULL if has not received a matching response from | 96 // Returns the response or NULL if has not received a matching response from |
| 131 // the server. | 97 // the server. |
| 132 const DnsResponse* response() const { | 98 const DnsResponse* response() const { |
| 133 const DnsResponse* resp = response_.get(); | 99 const DnsResponse* resp = response_.get(); |
| 134 return (resp != NULL && resp->IsValid()) ? resp : NULL; | 100 return (resp != NULL && resp->IsValid()) ? resp : NULL; |
| 135 } | 101 } |
| 136 | 102 |
| 103 // Returns a Value representing the received response, along with a reference |
| 104 // to the NetLog source source of the UDP socket used. The request must have |
| 105 // completed before this is called. |
| 106 Value* NetLogResponseCallback(NetLog::LogLevel /* log_level */) const { |
| 107 DCHECK(response_->IsValid()); |
| 108 |
| 109 DictionaryValue* dict = new DictionaryValue(); |
| 110 dict->SetInteger("rcode", response_->rcode()); |
| 111 dict->SetInteger("answer_count", response_->answer_count()); |
| 112 socket_->NetLog().source().AddToEventParameters(dict); |
| 113 return dict; |
| 114 } |
| 115 |
| 137 private: | 116 private: |
| 138 enum State { | 117 enum State { |
| 139 STATE_CONNECT, | 118 STATE_CONNECT, |
| 140 STATE_SEND_QUERY, | 119 STATE_SEND_QUERY, |
| 141 STATE_SEND_QUERY_COMPLETE, | 120 STATE_SEND_QUERY_COMPLETE, |
| 142 STATE_READ_RESPONSE, | 121 STATE_READ_RESPONSE, |
| 143 STATE_READ_RESPONSE_COMPLETE, | 122 STATE_READ_RESPONSE_COMPLETE, |
| 144 STATE_NONE, | 123 STATE_NONE, |
| 145 }; | 124 }; |
| 146 | 125 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 } | 276 } |
| 298 | 277 |
| 299 virtual uint16 GetType() const OVERRIDE { | 278 virtual uint16 GetType() const OVERRIDE { |
| 300 DCHECK(CalledOnValidThread()); | 279 DCHECK(CalledOnValidThread()); |
| 301 return qtype_; | 280 return qtype_; |
| 302 } | 281 } |
| 303 | 282 |
| 304 virtual int Start() OVERRIDE { | 283 virtual int Start() OVERRIDE { |
| 305 DCHECK(!callback_.is_null()); | 284 DCHECK(!callback_.is_null()); |
| 306 DCHECK(attempts_.empty()); | 285 DCHECK(attempts_.empty()); |
| 307 net_log_.BeginEvent(NetLog::TYPE_DNS_TRANSACTION, make_scoped_refptr( | 286 net_log_.BeginEvent(NetLog::TYPE_DNS_TRANSACTION, |
| 308 new StartParameters(hostname_, qtype_))); | 287 base::Bind(&NetLogStartCallback, &hostname_, qtype_)); |
| 309 int rv = PrepareSearch(); | 288 int rv = PrepareSearch(); |
| 310 if (rv == OK) { | 289 if (rv == OK) { |
| 311 AttemptResult result = FinishAttempt(StartQuery()); | 290 AttemptResult result = FinishAttempt(StartQuery()); |
| 312 if (result.rv == OK) { | 291 if (result.rv == OK) { |
| 313 // DnsTransaction must never succeed synchronously. | 292 // DnsTransaction must never succeed synchronously. |
| 314 MessageLoop::current()->PostTask( | 293 MessageLoop::current()->PostTask( |
| 315 FROM_HERE, | 294 FROM_HERE, |
| 316 base::Bind(&DnsTransactionImpl::DoCallback, AsWeakPtr(), result)); | 295 base::Bind(&DnsTransactionImpl::DoCallback, AsWeakPtr(), result)); |
| 317 return ERR_IO_PENDING; | 296 return ERR_IO_PENDING; |
| 318 } | 297 } |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 net_log_.source())); | 400 net_log_.source())); |
| 422 | 401 |
| 423 uint16 id = session_->NextQueryId(); | 402 uint16 id = session_->NextQueryId(); |
| 424 scoped_ptr<DnsQuery> query; | 403 scoped_ptr<DnsQuery> query; |
| 425 if (attempts_.empty()) { | 404 if (attempts_.empty()) { |
| 426 query.reset(new DnsQuery(id, qnames_.front(), qtype_)); | 405 query.reset(new DnsQuery(id, qnames_.front(), qtype_)); |
| 427 } else { | 406 } else { |
| 428 query.reset(attempts_[0]->query()->CloneWithNewId(id)); | 407 query.reset(attempts_[0]->query()->CloneWithNewId(id)); |
| 429 } | 408 } |
| 430 | 409 |
| 431 net_log_.AddEvent(NetLog::TYPE_DNS_TRANSACTION_ATTEMPT, make_scoped_refptr( | 410 net_log_.AddEvent(NetLog::TYPE_DNS_TRANSACTION_ATTEMPT, |
| 432 new NetLogSourceParameter("source_dependency", | 411 socket->NetLog().source().ToEventParametersCallback()); |
| 433 socket->NetLog().source()))); | |
| 434 | 412 |
| 435 const DnsConfig& config = session_->config(); | 413 const DnsConfig& config = session_->config(); |
| 436 | 414 |
| 437 unsigned server_index = first_server_index_ + | 415 unsigned server_index = first_server_index_ + |
| 438 (attempt_number % config.nameservers.size()); | 416 (attempt_number % config.nameservers.size()); |
| 439 | 417 |
| 440 DnsUDPAttempt* attempt = new DnsUDPAttempt( | 418 DnsUDPAttempt* attempt = new DnsUDPAttempt( |
| 441 socket.Pass(), | 419 socket.Pass(), |
| 442 config.nameservers[server_index], | 420 config.nameservers[server_index], |
| 443 query.Pass(), | 421 query.Pass(), |
| 444 base::Bind(&DnsTransactionImpl::OnAttemptComplete, | 422 base::Bind(&DnsTransactionImpl::OnAttemptComplete, |
| 445 base::Unretained(this), | 423 base::Unretained(this), |
| 446 attempt_number)); | 424 attempt_number)); |
| 447 | 425 |
| 448 attempts_.push_back(attempt); | 426 attempts_.push_back(attempt); |
| 449 | 427 |
| 450 int rv = attempt->Start(); | 428 int rv = attempt->Start(); |
| 451 if (rv == ERR_IO_PENDING) { | 429 if (rv == ERR_IO_PENDING) { |
| 452 timer_.Stop(); | 430 timer_.Stop(); |
| 453 base::TimeDelta timeout = session_->NextTimeout(attempt_number); | 431 base::TimeDelta timeout = session_->NextTimeout(attempt_number); |
| 454 timer_.Start(FROM_HERE, timeout, this, &DnsTransactionImpl::OnTimeout); | 432 timer_.Start(FROM_HERE, timeout, this, &DnsTransactionImpl::OnTimeout); |
| 455 } | 433 } |
| 456 return AttemptResult(rv, attempt); | 434 return AttemptResult(rv, attempt); |
| 457 } | 435 } |
| 458 | 436 |
| 459 // Begins query for the current name. Makes the first attempt. | 437 // Begins query for the current name. Makes the first attempt. |
| 460 AttemptResult StartQuery() { | 438 AttemptResult StartQuery() { |
| 461 std::string dotted_qname = DNSDomainToString(qnames_.front()); | 439 std::string dotted_qname = DNSDomainToString(qnames_.front()); |
| 462 net_log_.BeginEvent( | 440 net_log_.BeginEvent(NetLog::TYPE_DNS_TRANSACTION_QUERY, |
| 463 NetLog::TYPE_DNS_TRANSACTION_QUERY, | 441 NetLog::StringCallback("qname", &dotted_qname)); |
| 464 make_scoped_refptr(new NetLogStringParameter("qname", dotted_qname))); | |
| 465 | 442 |
| 466 first_server_index_ = session_->NextFirstServerIndex(); | 443 first_server_index_ = session_->NextFirstServerIndex(); |
| 467 | 444 |
| 468 attempts_.reset(); | 445 attempts_.reset(); |
| 469 return MakeAttempt(); | 446 return MakeAttempt(); |
| 470 } | 447 } |
| 471 | 448 |
| 472 void OnAttemptComplete(unsigned attempt_number, int rv) { | 449 void OnAttemptComplete(unsigned attempt_number, int rv) { |
| 473 if (callback_.is_null()) | 450 if (callback_.is_null()) |
| 474 return; | 451 return; |
| 475 DCHECK_LT(attempt_number, attempts_.size()); | 452 DCHECK_LT(attempt_number, attempts_.size()); |
| 476 const DnsUDPAttempt* attempt = attempts_[attempt_number]; | 453 const DnsUDPAttempt* attempt = attempts_[attempt_number]; |
| 477 AttemptResult result = FinishAttempt(AttemptResult(rv, attempt)); | 454 AttemptResult result = FinishAttempt(AttemptResult(rv, attempt)); |
| 478 if (result.rv != ERR_IO_PENDING) | 455 if (result.rv != ERR_IO_PENDING) |
| 479 DoCallback(result); | 456 DoCallback(result); |
| 480 } | 457 } |
| 481 | 458 |
| 482 void LogResponse(const DnsUDPAttempt* attempt) { | 459 void LogResponse(const DnsUDPAttempt* attempt) { |
| 483 if (attempt && attempt->response()) { | 460 if (attempt && attempt->response()) { |
| 484 net_log_.AddEvent( | 461 net_log_.AddEvent( |
| 485 NetLog::TYPE_DNS_TRANSACTION_RESPONSE, | 462 NetLog::TYPE_DNS_TRANSACTION_RESPONSE, |
| 486 make_scoped_refptr( | 463 base::Bind(&DnsUDPAttempt::NetLogResponseCallback, |
| 487 new ResponseParameters(attempt->response()->rcode(), | 464 base::Unretained(attempt))); |
| 488 attempt->response()->answer_count(), | |
| 489 attempt->socket()->NetLog().source()))); | |
| 490 } | 465 } |
| 491 } | 466 } |
| 492 | 467 |
| 493 bool MoreAttemptsAllowed() const { | 468 bool MoreAttemptsAllowed() const { |
| 494 const DnsConfig& config = session_->config(); | 469 const DnsConfig& config = session_->config(); |
| 495 return attempts_.size() < config.attempts * config.nameservers.size(); | 470 return attempts_.size() < config.attempts * config.nameservers.size(); |
| 496 } | 471 } |
| 497 | 472 |
| 498 // Resolves the result of a DnsUDPAttempt until a terminal result is reached | 473 // Resolves the result of a DnsUDPAttempt until a terminal result is reached |
| 499 // or it will complete asynchronously (ERR_IO_PENDING). | 474 // or it will complete asynchronously (ERR_IO_PENDING). |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 | 580 |
| 606 // static | 581 // static |
| 607 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory( | 582 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory( |
| 608 DnsSession* session) { | 583 DnsSession* session) { |
| 609 return scoped_ptr<DnsTransactionFactory>( | 584 return scoped_ptr<DnsTransactionFactory>( |
| 610 new DnsTransactionFactoryImpl(session)); | 585 new DnsTransactionFactoryImpl(session)); |
| 611 } | 586 } |
| 612 | 587 |
| 613 } // namespace net | 588 } // namespace net |
| 614 | 589 |
| OLD | NEW |