| 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 23 matching lines...) Expand all Loading... |
| 34 #include "net/dns/dns_session.h" | 34 #include "net/dns/dns_session.h" |
| 35 #include "net/socket/stream_socket.h" | 35 #include "net/socket/stream_socket.h" |
| 36 #include "net/udp/datagram_client_socket.h" | 36 #include "net/udp/datagram_client_socket.h" |
| 37 | 37 |
| 38 namespace net { | 38 namespace net { |
| 39 | 39 |
| 40 namespace { | 40 namespace { |
| 41 | 41 |
| 42 // Provide a common macro to simplify code and readability. We must use a | 42 // Provide a common macro to simplify code and readability. We must use a |
| 43 // macro as the underlying HISTOGRAM macro creates static variables. | 43 // macro as the underlying HISTOGRAM macro creates static variables. |
| 44 #define DNS_HISTOGRAM(name, time) UMA_HISTOGRAM_CUSTOM_TIMES(name, time, \ | 44 #define DNS_HISTOGRAM(name, time) \ |
| 45 base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1), 100) | 45 UMA_HISTOGRAM_CUSTOM_TIMES(name, \ |
| 46 time, \ |
| 47 base::TimeDelta::FromMilliseconds(1), \ |
| 48 base::TimeDelta::FromHours(1), \ |
| 49 100) |
| 46 | 50 |
| 47 // Count labels in the fully-qualified name in DNS format. | 51 // Count labels in the fully-qualified name in DNS format. |
| 48 int CountLabels(const std::string& name) { | 52 int CountLabels(const std::string& name) { |
| 49 size_t count = 0; | 53 size_t count = 0; |
| 50 for (size_t i = 0; i < name.size() && name[i]; i += name[i] + 1) | 54 for (size_t i = 0; i < name.size() && name[i]; i += name[i] + 1) |
| 51 ++count; | 55 ++count; |
| 52 return count; | 56 return count; |
| 53 } | 57 } |
| 54 | 58 |
| 55 bool IsIPLiteral(const std::string& hostname) { | 59 bool IsIPLiteral(const std::string& hostname) { |
| 56 IPAddressNumber ip; | 60 IPAddressNumber ip; |
| 57 return ParseIPLiteralToNumber(hostname, &ip); | 61 return ParseIPLiteralToNumber(hostname, &ip); |
| 58 } | 62 } |
| 59 | 63 |
| 60 base::Value* NetLogStartCallback(const std::string* hostname, | 64 base::Value* NetLogStartCallback(const std::string* hostname, |
| 61 uint16 qtype, | 65 uint16 qtype, |
| 62 NetLog::LogLevel /* log_level */) { | 66 NetLog::LogLevel /* log_level */) { |
| 63 base::DictionaryValue* dict = new base::DictionaryValue(); | 67 base::DictionaryValue* dict = new base::DictionaryValue(); |
| 64 dict->SetString("hostname", *hostname); | 68 dict->SetString("hostname", *hostname); |
| 65 dict->SetInteger("query_type", qtype); | 69 dict->SetInteger("query_type", qtype); |
| 66 return dict; | 70 return dict; |
| 67 }; | 71 }; |
| 68 | 72 |
| 69 // ---------------------------------------------------------------------------- | 73 // ---------------------------------------------------------------------------- |
| 70 | 74 |
| 71 // A single asynchronous DNS exchange, which consists of sending out a | 75 // A single asynchronous DNS exchange, which consists of sending out a |
| 72 // DNS query, waiting for a response, and returning the response that it | 76 // DNS query, waiting for a response, and returning the response that it |
| (...skipping 27 matching lines...) Expand all Loading... |
| 100 base::Value* NetLogResponseCallback(NetLog::LogLevel log_level) const { | 104 base::Value* NetLogResponseCallback(NetLog::LogLevel log_level) const { |
| 101 DCHECK(GetResponse()->IsValid()); | 105 DCHECK(GetResponse()->IsValid()); |
| 102 | 106 |
| 103 base::DictionaryValue* dict = new base::DictionaryValue(); | 107 base::DictionaryValue* dict = new base::DictionaryValue(); |
| 104 dict->SetInteger("rcode", GetResponse()->rcode()); | 108 dict->SetInteger("rcode", GetResponse()->rcode()); |
| 105 dict->SetInteger("answer_count", GetResponse()->answer_count()); | 109 dict->SetInteger("answer_count", GetResponse()->answer_count()); |
| 106 GetSocketNetLog().source().AddToEventParameters(dict); | 110 GetSocketNetLog().source().AddToEventParameters(dict); |
| 107 return dict; | 111 return dict; |
| 108 } | 112 } |
| 109 | 113 |
| 110 void set_result(int result) { | 114 void set_result(int result) { result_ = result; } |
| 111 result_ = result; | |
| 112 } | |
| 113 | 115 |
| 114 // True if current attempt is pending (waiting for server response). | 116 // True if current attempt is pending (waiting for server response). |
| 115 bool is_pending() const { | 117 bool is_pending() const { return result_ == ERR_IO_PENDING; } |
| 116 return result_ == ERR_IO_PENDING; | |
| 117 } | |
| 118 | 118 |
| 119 // True if attempt is completed (received server response). | 119 // True if attempt is completed (received server response). |
| 120 bool is_completed() const { | 120 bool is_completed() const { |
| 121 return (result_ == OK) || (result_ == ERR_NAME_NOT_RESOLVED) || | 121 return (result_ == OK) || (result_ == ERR_NAME_NOT_RESOLVED) || |
| 122 (result_ == ERR_DNS_SERVER_REQUIRES_TCP); | 122 (result_ == ERR_DNS_SERVER_REQUIRES_TCP); |
| 123 } | 123 } |
| 124 | 124 |
| 125 private: | 125 private: |
| 126 // Result of last operation. | 126 // Result of last operation. |
| 127 int result_; | 127 int result_; |
| 128 | 128 |
| 129 const unsigned server_index_; | 129 const unsigned server_index_; |
| 130 }; | 130 }; |
| 131 | 131 |
| 132 class DnsUDPAttempt : public DnsAttempt { | 132 class DnsUDPAttempt : public DnsAttempt { |
| 133 public: | 133 public: |
| 134 DnsUDPAttempt(unsigned server_index, | 134 DnsUDPAttempt(unsigned server_index, |
| 135 scoped_ptr<DnsSession::SocketLease> socket_lease, | 135 scoped_ptr<DnsSession::SocketLease> socket_lease, |
| 136 scoped_ptr<DnsQuery> query) | 136 scoped_ptr<DnsQuery> query) |
| 137 : DnsAttempt(server_index), | 137 : DnsAttempt(server_index), |
| 138 next_state_(STATE_NONE), | 138 next_state_(STATE_NONE), |
| 139 received_malformed_response_(false), | 139 received_malformed_response_(false), |
| 140 socket_lease_(socket_lease.Pass()), | 140 socket_lease_(socket_lease.Pass()), |
| 141 query_(query.Pass()) {} | 141 query_(query.Pass()) {} |
| 142 | 142 |
| 143 // DnsAttempt: | 143 // DnsAttempt: |
| 144 virtual int Start(const CompletionCallback& callback) OVERRIDE { | 144 virtual int Start(const CompletionCallback& callback) OVERRIDE { |
| 145 DCHECK_EQ(STATE_NONE, next_state_); | 145 DCHECK_EQ(STATE_NONE, next_state_); |
| 146 callback_ = callback; | 146 callback_ = callback; |
| 147 start_time_ = base::TimeTicks::Now(); | 147 start_time_ = base::TimeTicks::Now(); |
| 148 next_state_ = STATE_SEND_QUERY; | 148 next_state_ = STATE_SEND_QUERY; |
| 149 return DoLoop(OK); | 149 return DoLoop(OK); |
| 150 } | 150 } |
| 151 | 151 |
| 152 virtual const DnsQuery* GetQuery() const OVERRIDE { | 152 virtual const DnsQuery* GetQuery() const OVERRIDE { return query_.get(); } |
| 153 return query_.get(); | |
| 154 } | |
| 155 | 153 |
| 156 virtual const DnsResponse* GetResponse() const OVERRIDE { | 154 virtual const DnsResponse* GetResponse() const OVERRIDE { |
| 157 const DnsResponse* resp = response_.get(); | 155 const DnsResponse* resp = response_.get(); |
| 158 return (resp != NULL && resp->IsValid()) ? resp : NULL; | 156 return (resp != NULL && resp->IsValid()) ? resp : NULL; |
| 159 } | 157 } |
| 160 | 158 |
| 161 virtual const BoundNetLog& GetSocketNetLog() const OVERRIDE { | 159 virtual const BoundNetLog& GetSocketNetLog() const OVERRIDE { |
| 162 return socket_lease_->socket()->NetLog(); | 160 return socket_lease_->socket()->NetLog(); |
| 163 } | 161 } |
| 164 | 162 |
| 165 private: | 163 private: |
| 166 enum State { | 164 enum State { |
| 167 STATE_SEND_QUERY, | 165 STATE_SEND_QUERY, |
| 168 STATE_SEND_QUERY_COMPLETE, | 166 STATE_SEND_QUERY_COMPLETE, |
| 169 STATE_READ_RESPONSE, | 167 STATE_READ_RESPONSE, |
| 170 STATE_READ_RESPONSE_COMPLETE, | 168 STATE_READ_RESPONSE_COMPLETE, |
| 171 STATE_NONE, | 169 STATE_NONE, |
| 172 }; | 170 }; |
| 173 | 171 |
| 174 DatagramClientSocket* socket() { | 172 DatagramClientSocket* socket() { return socket_lease_->socket(); } |
| 175 return socket_lease_->socket(); | |
| 176 } | |
| 177 | 173 |
| 178 int DoLoop(int result) { | 174 int DoLoop(int result) { |
| 179 CHECK_NE(STATE_NONE, next_state_); | 175 CHECK_NE(STATE_NONE, next_state_); |
| 180 int rv = result; | 176 int rv = result; |
| 181 do { | 177 do { |
| 182 State state = next_state_; | 178 State state = next_state_; |
| 183 next_state_ = STATE_NONE; | 179 next_state_ = STATE_NONE; |
| 184 switch (state) { | 180 switch (state) { |
| 185 case STATE_SEND_QUERY: | 181 case STATE_SEND_QUERY: |
| 186 rv = DoSendQuery(); | 182 rv = DoSendQuery(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 211 base::TimeTicks::Now() - start_time_); | 207 base::TimeTicks::Now() - start_time_); |
| 212 } else if (rv != ERR_IO_PENDING) { | 208 } else if (rv != ERR_IO_PENDING) { |
| 213 DNS_HISTOGRAM("AsyncDNS.UDPAttemptFail", | 209 DNS_HISTOGRAM("AsyncDNS.UDPAttemptFail", |
| 214 base::TimeTicks::Now() - start_time_); | 210 base::TimeTicks::Now() - start_time_); |
| 215 } | 211 } |
| 216 return rv; | 212 return rv; |
| 217 } | 213 } |
| 218 | 214 |
| 219 int DoSendQuery() { | 215 int DoSendQuery() { |
| 220 next_state_ = STATE_SEND_QUERY_COMPLETE; | 216 next_state_ = STATE_SEND_QUERY_COMPLETE; |
| 221 return socket()->Write(query_->io_buffer(), | 217 return socket()->Write( |
| 222 query_->io_buffer()->size(), | 218 query_->io_buffer(), |
| 223 base::Bind(&DnsUDPAttempt::OnIOComplete, | 219 query_->io_buffer()->size(), |
| 224 base::Unretained(this))); | 220 base::Bind(&DnsUDPAttempt::OnIOComplete, base::Unretained(this))); |
| 225 } | 221 } |
| 226 | 222 |
| 227 int DoSendQueryComplete(int rv) { | 223 int DoSendQueryComplete(int rv) { |
| 228 DCHECK_NE(ERR_IO_PENDING, rv); | 224 DCHECK_NE(ERR_IO_PENDING, rv); |
| 229 if (rv < 0) | 225 if (rv < 0) |
| 230 return rv; | 226 return rv; |
| 231 | 227 |
| 232 // Writing to UDP should not result in a partial datagram. | 228 // Writing to UDP should not result in a partial datagram. |
| 233 if (rv != query_->io_buffer()->size()) | 229 if (rv != query_->io_buffer()->size()) |
| 234 return ERR_MSG_TOO_BIG; | 230 return ERR_MSG_TOO_BIG; |
| 235 | 231 |
| 236 next_state_ = STATE_READ_RESPONSE; | 232 next_state_ = STATE_READ_RESPONSE; |
| 237 return OK; | 233 return OK; |
| 238 } | 234 } |
| 239 | 235 |
| 240 int DoReadResponse() { | 236 int DoReadResponse() { |
| 241 next_state_ = STATE_READ_RESPONSE_COMPLETE; | 237 next_state_ = STATE_READ_RESPONSE_COMPLETE; |
| 242 response_.reset(new DnsResponse()); | 238 response_.reset(new DnsResponse()); |
| 243 return socket()->Read(response_->io_buffer(), | 239 return socket()->Read( |
| 244 response_->io_buffer()->size(), | 240 response_->io_buffer(), |
| 245 base::Bind(&DnsUDPAttempt::OnIOComplete, | 241 response_->io_buffer()->size(), |
| 246 base::Unretained(this))); | 242 base::Bind(&DnsUDPAttempt::OnIOComplete, base::Unretained(this))); |
| 247 } | 243 } |
| 248 | 244 |
| 249 int DoReadResponseComplete(int rv) { | 245 int DoReadResponseComplete(int rv) { |
| 250 DCHECK_NE(ERR_IO_PENDING, rv); | 246 DCHECK_NE(ERR_IO_PENDING, rv); |
| 251 if (rv < 0) | 247 if (rv < 0) |
| 252 return rv; | 248 return rv; |
| 253 | 249 |
| 254 DCHECK(rv); | 250 DCHECK(rv); |
| 255 if (!response_->InitParse(rv, *query_)) { | 251 if (!response_->InitParse(rv, *query_)) { |
| 256 // Other implementations simply ignore mismatched responses. Since each | 252 // Other implementations simply ignore mismatched responses. Since each |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 query_(query.Pass()), | 300 query_(query.Pass()), |
| 305 length_buffer_(new IOBufferWithSize(sizeof(uint16))), | 301 length_buffer_(new IOBufferWithSize(sizeof(uint16))), |
| 306 response_length_(0) {} | 302 response_length_(0) {} |
| 307 | 303 |
| 308 // DnsAttempt: | 304 // DnsAttempt: |
| 309 virtual int Start(const CompletionCallback& callback) OVERRIDE { | 305 virtual int Start(const CompletionCallback& callback) OVERRIDE { |
| 310 DCHECK_EQ(STATE_NONE, next_state_); | 306 DCHECK_EQ(STATE_NONE, next_state_); |
| 311 callback_ = callback; | 307 callback_ = callback; |
| 312 start_time_ = base::TimeTicks::Now(); | 308 start_time_ = base::TimeTicks::Now(); |
| 313 next_state_ = STATE_CONNECT_COMPLETE; | 309 next_state_ = STATE_CONNECT_COMPLETE; |
| 314 int rv = socket_->Connect(base::Bind(&DnsTCPAttempt::OnIOComplete, | 310 int rv = socket_->Connect( |
| 315 base::Unretained(this))); | 311 base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this))); |
| 316 if (rv == ERR_IO_PENDING) { | 312 if (rv == ERR_IO_PENDING) { |
| 317 set_result(rv); | 313 set_result(rv); |
| 318 return rv; | 314 return rv; |
| 319 } | 315 } |
| 320 return DoLoop(rv); | 316 return DoLoop(rv); |
| 321 } | 317 } |
| 322 | 318 |
| 323 virtual const DnsQuery* GetQuery() const OVERRIDE { | 319 virtual const DnsQuery* GetQuery() const OVERRIDE { return query_.get(); } |
| 324 return query_.get(); | |
| 325 } | |
| 326 | 320 |
| 327 virtual const DnsResponse* GetResponse() const OVERRIDE { | 321 virtual const DnsResponse* GetResponse() const OVERRIDE { |
| 328 const DnsResponse* resp = response_.get(); | 322 const DnsResponse* resp = response_.get(); |
| 329 return (resp != NULL && resp->IsValid()) ? resp : NULL; | 323 return (resp != NULL && resp->IsValid()) ? resp : NULL; |
| 330 } | 324 } |
| 331 | 325 |
| 332 virtual const BoundNetLog& GetSocketNetLog() const OVERRIDE { | 326 virtual const BoundNetLog& GetSocketNetLog() const OVERRIDE { |
| 333 return socket_->NetLog(); | 327 return socket_->NetLog(); |
| 334 } | 328 } |
| 335 | 329 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 return rv; | 396 return rv; |
| 403 | 397 |
| 404 buffer_->DidConsume(rv); | 398 buffer_->DidConsume(rv); |
| 405 if (buffer_->BytesRemaining() > 0) { | 399 if (buffer_->BytesRemaining() > 0) { |
| 406 next_state_ = STATE_SEND_LENGTH; | 400 next_state_ = STATE_SEND_LENGTH; |
| 407 return socket_->Write( | 401 return socket_->Write( |
| 408 buffer_.get(), | 402 buffer_.get(), |
| 409 buffer_->BytesRemaining(), | 403 buffer_->BytesRemaining(), |
| 410 base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this))); | 404 base::Bind(&DnsTCPAttempt::OnIOComplete, base::Unretained(this))); |
| 411 } | 405 } |
| 412 buffer_ = new DrainableIOBuffer(query_->io_buffer(), | 406 buffer_ = |
| 413 query_->io_buffer()->size()); | 407 new DrainableIOBuffer(query_->io_buffer(), query_->io_buffer()->size()); |
| 414 next_state_ = STATE_SEND_QUERY; | 408 next_state_ = STATE_SEND_QUERY; |
| 415 return OK; | 409 return OK; |
| 416 } | 410 } |
| 417 | 411 |
| 418 int DoSendQuery(int rv) { | 412 int DoSendQuery(int rv) { |
| 419 DCHECK_NE(ERR_IO_PENDING, rv); | 413 DCHECK_NE(ERR_IO_PENDING, rv); |
| 420 if (rv < 0) | 414 if (rv < 0) |
| 421 return rv; | 415 return rv; |
| 422 | 416 |
| 423 buffer_->DidConsume(rv); | 417 buffer_->DidConsume(rv); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 // Each server is attempted DnsConfig::attempts times. | 510 // Each server is attempted DnsConfig::attempts times. |
| 517 class DnsTransactionImpl : public DnsTransaction, | 511 class DnsTransactionImpl : public DnsTransaction, |
| 518 public base::NonThreadSafe, | 512 public base::NonThreadSafe, |
| 519 public base::SupportsWeakPtr<DnsTransactionImpl> { | 513 public base::SupportsWeakPtr<DnsTransactionImpl> { |
| 520 public: | 514 public: |
| 521 DnsTransactionImpl(DnsSession* session, | 515 DnsTransactionImpl(DnsSession* session, |
| 522 const std::string& hostname, | 516 const std::string& hostname, |
| 523 uint16 qtype, | 517 uint16 qtype, |
| 524 const DnsTransactionFactory::CallbackType& callback, | 518 const DnsTransactionFactory::CallbackType& callback, |
| 525 const BoundNetLog& net_log) | 519 const BoundNetLog& net_log) |
| 526 : session_(session), | 520 : session_(session), |
| 527 hostname_(hostname), | 521 hostname_(hostname), |
| 528 qtype_(qtype), | 522 qtype_(qtype), |
| 529 callback_(callback), | 523 callback_(callback), |
| 530 net_log_(net_log), | 524 net_log_(net_log), |
| 531 qnames_initial_size_(0), | 525 qnames_initial_size_(0), |
| 532 attempts_count_(0), | 526 attempts_count_(0), |
| 533 had_tcp_attempt_(false), | 527 had_tcp_attempt_(false), |
| 534 first_server_index_(0) { | 528 first_server_index_(0) { |
| 535 DCHECK(session_.get()); | 529 DCHECK(session_.get()); |
| 536 DCHECK(!hostname_.empty()); | 530 DCHECK(!hostname_.empty()); |
| 537 DCHECK(!callback_.is_null()); | 531 DCHECK(!callback_.is_null()); |
| 538 DCHECK(!IsIPLiteral(hostname_)); | 532 DCHECK(!IsIPLiteral(hostname_)); |
| 539 } | 533 } |
| 540 | 534 |
| 541 virtual ~DnsTransactionImpl() { | 535 virtual ~DnsTransactionImpl() { |
| 542 if (!callback_.is_null()) { | 536 if (!callback_.is_null()) { |
| 543 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION, | 537 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION, |
| 544 ERR_ABORTED); | 538 ERR_ABORTED); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 | 624 |
| 631 if (ndots > 0 && !had_hostname) | 625 if (ndots > 0 && !had_hostname) |
| 632 qnames_.push_back(labeled_hostname); | 626 qnames_.push_back(labeled_hostname); |
| 633 | 627 |
| 634 return qnames_.empty() ? ERR_DNS_SEARCH_EMPTY : OK; | 628 return qnames_.empty() ? ERR_DNS_SEARCH_EMPTY : OK; |
| 635 } | 629 } |
| 636 | 630 |
| 637 void DoCallback(AttemptResult result) { | 631 void DoCallback(AttemptResult result) { |
| 638 DCHECK(!callback_.is_null()); | 632 DCHECK(!callback_.is_null()); |
| 639 DCHECK_NE(ERR_IO_PENDING, result.rv); | 633 DCHECK_NE(ERR_IO_PENDING, result.rv); |
| 640 const DnsResponse* response = result.attempt ? | 634 const DnsResponse* response = |
| 641 result.attempt->GetResponse() : NULL; | 635 result.attempt ? result.attempt->GetResponse() : NULL; |
| 642 CHECK(result.rv != OK || response != NULL); | 636 CHECK(result.rv != OK || response != NULL); |
| 643 | 637 |
| 644 timer_.Stop(); | 638 timer_.Stop(); |
| 645 RecordLostPacketsIfAny(); | 639 RecordLostPacketsIfAny(); |
| 646 if (result.rv == OK) | 640 if (result.rv == OK) |
| 647 UMA_HISTOGRAM_COUNTS("AsyncDNS.AttemptCountSuccess", attempts_count_); | 641 UMA_HISTOGRAM_COUNTS("AsyncDNS.AttemptCountSuccess", attempts_count_); |
| 648 else | 642 else |
| 649 UMA_HISTOGRAM_COUNTS("AsyncDNS.AttemptCountFail", attempts_count_); | 643 UMA_HISTOGRAM_COUNTS("AsyncDNS.AttemptCountFail", attempts_count_); |
| 650 | 644 |
| 651 if (response && qtype_ == dns_protocol::kTypeA) { | 645 if (response && qtype_ == dns_protocol::kTypeA) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 attempts_.push_back(attempt); | 686 attempts_.push_back(attempt); |
| 693 ++attempts_count_; | 687 ++attempts_count_; |
| 694 | 688 |
| 695 if (!got_socket) | 689 if (!got_socket) |
| 696 return AttemptResult(ERR_CONNECTION_REFUSED, NULL); | 690 return AttemptResult(ERR_CONNECTION_REFUSED, NULL); |
| 697 | 691 |
| 698 net_log_.AddEvent( | 692 net_log_.AddEvent( |
| 699 NetLog::TYPE_DNS_TRANSACTION_ATTEMPT, | 693 NetLog::TYPE_DNS_TRANSACTION_ATTEMPT, |
| 700 attempt->GetSocketNetLog().source().ToEventParametersCallback()); | 694 attempt->GetSocketNetLog().source().ToEventParametersCallback()); |
| 701 | 695 |
| 702 int rv = attempt->Start( | 696 int rv = |
| 703 base::Bind(&DnsTransactionImpl::OnUdpAttemptComplete, | 697 attempt->Start(base::Bind(&DnsTransactionImpl::OnUdpAttemptComplete, |
| 704 base::Unretained(this), attempt_number, | 698 base::Unretained(this), |
| 705 base::TimeTicks::Now())); | 699 attempt_number, |
| 700 base::TimeTicks::Now())); |
| 706 if (rv == ERR_IO_PENDING) { | 701 if (rv == ERR_IO_PENDING) { |
| 707 base::TimeDelta timeout = session_->NextTimeout(server_index, | 702 base::TimeDelta timeout = |
| 708 attempt_number); | 703 session_->NextTimeout(server_index, attempt_number); |
| 709 timer_.Start(FROM_HERE, timeout, this, &DnsTransactionImpl::OnTimeout); | 704 timer_.Start(FROM_HERE, timeout, this, &DnsTransactionImpl::OnTimeout); |
| 710 } | 705 } |
| 711 return AttemptResult(rv, attempt); | 706 return AttemptResult(rv, attempt); |
| 712 } | 707 } |
| 713 | 708 |
| 714 AttemptResult MakeTCPAttempt(const DnsAttempt* previous_attempt) { | 709 AttemptResult MakeTCPAttempt(const DnsAttempt* previous_attempt) { |
| 715 DCHECK(previous_attempt); | 710 DCHECK(previous_attempt); |
| 716 DCHECK(!had_tcp_attempt_); | 711 DCHECK(!had_tcp_attempt_); |
| 717 | 712 |
| 718 unsigned server_index = previous_attempt->server_index(); | 713 unsigned server_index = previous_attempt->server_index(); |
| 719 | 714 |
| 720 scoped_ptr<StreamSocket> socket( | 715 scoped_ptr<StreamSocket> socket( |
| 721 session_->CreateTCPSocket(server_index, net_log_.source())); | 716 session_->CreateTCPSocket(server_index, net_log_.source())); |
| 722 | 717 |
| 723 // TODO(szym): Reuse the same id to help the server? | 718 // TODO(szym): Reuse the same id to help the server? |
| 724 uint16 id = session_->NextQueryId(); | 719 uint16 id = session_->NextQueryId(); |
| 725 scoped_ptr<DnsQuery> query( | 720 scoped_ptr<DnsQuery> query( |
| 726 previous_attempt->GetQuery()->CloneWithNewId(id)); | 721 previous_attempt->GetQuery()->CloneWithNewId(id)); |
| 727 | 722 |
| 728 RecordLostPacketsIfAny(); | 723 RecordLostPacketsIfAny(); |
| 729 // Cancel all other attempts, no point waiting on them. | 724 // Cancel all other attempts, no point waiting on them. |
| 730 attempts_.clear(); | 725 attempts_.clear(); |
| 731 | 726 |
| 732 unsigned attempt_number = attempts_.size(); | 727 unsigned attempt_number = attempts_.size(); |
| 733 | 728 |
| 734 DnsTCPAttempt* attempt = new DnsTCPAttempt(server_index, socket.Pass(), | 729 DnsTCPAttempt* attempt = |
| 735 query.Pass()); | 730 new DnsTCPAttempt(server_index, socket.Pass(), query.Pass()); |
| 736 | 731 |
| 737 attempts_.push_back(attempt); | 732 attempts_.push_back(attempt); |
| 738 ++attempts_count_; | 733 ++attempts_count_; |
| 739 had_tcp_attempt_ = true; | 734 had_tcp_attempt_ = true; |
| 740 | 735 |
| 741 net_log_.AddEvent( | 736 net_log_.AddEvent( |
| 742 NetLog::TYPE_DNS_TRANSACTION_TCP_ATTEMPT, | 737 NetLog::TYPE_DNS_TRANSACTION_TCP_ATTEMPT, |
| 743 attempt->GetSocketNetLog().source().ToEventParametersCallback()); | 738 attempt->GetSocketNetLog().source().ToEventParametersCallback()); |
| 744 | 739 |
| 745 int rv = attempt->Start(base::Bind(&DnsTransactionImpl::OnAttemptComplete, | 740 int rv = attempt->Start(base::Bind(&DnsTransactionImpl::OnAttemptComplete, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 786 AttemptResult result = ProcessAttemptResult(AttemptResult(rv, attempt)); | 781 AttemptResult result = ProcessAttemptResult(AttemptResult(rv, attempt)); |
| 787 if (result.rv != ERR_IO_PENDING) | 782 if (result.rv != ERR_IO_PENDING) |
| 788 DoCallback(result); | 783 DoCallback(result); |
| 789 } | 784 } |
| 790 | 785 |
| 791 // Record packet loss for any incomplete attempts. | 786 // Record packet loss for any incomplete attempts. |
| 792 void RecordLostPacketsIfAny() { | 787 void RecordLostPacketsIfAny() { |
| 793 // Loop through attempts until we find first that is completed | 788 // Loop through attempts until we find first that is completed |
| 794 size_t first_completed = 0; | 789 size_t first_completed = 0; |
| 795 for (first_completed = 0; first_completed < attempts_.size(); | 790 for (first_completed = 0; first_completed < attempts_.size(); |
| 796 ++first_completed) { | 791 ++first_completed) { |
| 797 if (attempts_[first_completed]->is_completed()) | 792 if (attempts_[first_completed]->is_completed()) |
| 798 break; | 793 break; |
| 799 } | 794 } |
| 800 // If there were no completed attempts, then we must be offline, so don't | 795 // If there were no completed attempts, then we must be offline, so don't |
| 801 // record any attempts as lost packets. | 796 // record any attempts as lost packets. |
| 802 if (first_completed == attempts_.size()) | 797 if (first_completed == attempts_.size()) |
| 803 return; | 798 return; |
| 804 | 799 |
| 805 size_t num_servers = session_->config().nameservers.size(); | 800 size_t num_servers = session_->config().nameservers.size(); |
| 806 std::vector<int> server_attempts(num_servers); | 801 std::vector<int> server_attempts(num_servers); |
| 807 for (size_t i = 0; i < first_completed; ++i) { | 802 for (size_t i = 0; i < first_completed; ++i) { |
| 808 unsigned server_index = attempts_[i]->server_index(); | 803 unsigned server_index = attempts_[i]->server_index(); |
| 809 int server_attempt = server_attempts[server_index]++; | 804 int server_attempt = server_attempts[server_index]++; |
| 810 // Don't record lost packet unless attempt is in pending state. | 805 // Don't record lost packet unless attempt is in pending state. |
| 811 if (!attempts_[i]->is_pending()) | 806 if (!attempts_[i]->is_pending()) |
| 812 continue; | 807 continue; |
| 813 session_->RecordLostPacket(server_index, server_attempt); | 808 session_->RecordLostPacket(server_index, server_attempt); |
| 814 } | 809 } |
| 815 } | 810 } |
| 816 | 811 |
| 817 void LogResponse(const DnsAttempt* attempt) { | 812 void LogResponse(const DnsAttempt* attempt) { |
| 818 if (attempt && attempt->GetResponse()) { | 813 if (attempt && attempt->GetResponse()) { |
| 819 net_log_.AddEvent( | 814 net_log_.AddEvent(NetLog::TYPE_DNS_TRANSACTION_RESPONSE, |
| 820 NetLog::TYPE_DNS_TRANSACTION_RESPONSE, | 815 base::Bind(&DnsAttempt::NetLogResponseCallback, |
| 821 base::Bind(&DnsAttempt::NetLogResponseCallback, | 816 base::Unretained(attempt))); |
| 822 base::Unretained(attempt))); | |
| 823 } | 817 } |
| 824 } | 818 } |
| 825 | 819 |
| 826 bool MoreAttemptsAllowed() const { | 820 bool MoreAttemptsAllowed() const { |
| 827 if (had_tcp_attempt_) | 821 if (had_tcp_attempt_) |
| 828 return false; | 822 return false; |
| 829 const DnsConfig& config = session_->config(); | 823 const DnsConfig& config = session_->config(); |
| 830 return attempts_.size() < config.attempts * config.nameservers.size(); | 824 return attempts_.size() < config.attempts * config.nameservers.size(); |
| 831 } | 825 } |
| 832 | 826 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 911 | 905 |
| 912 BoundNetLog net_log_; | 906 BoundNetLog net_log_; |
| 913 | 907 |
| 914 // Search list of fully-qualified DNS names to query next (in DNS format). | 908 // Search list of fully-qualified DNS names to query next (in DNS format). |
| 915 std::deque<std::string> qnames_; | 909 std::deque<std::string> qnames_; |
| 916 size_t qnames_initial_size_; | 910 size_t qnames_initial_size_; |
| 917 | 911 |
| 918 // List of attempts for the current name. | 912 // List of attempts for the current name. |
| 919 ScopedVector<DnsAttempt> attempts_; | 913 ScopedVector<DnsAttempt> attempts_; |
| 920 // Count of attempts, not reset when |attempts_| vector is cleared. | 914 // Count of attempts, not reset when |attempts_| vector is cleared. |
| 921 int attempts_count_; | 915 int attempts_count_; |
| 922 bool had_tcp_attempt_; | 916 bool had_tcp_attempt_; |
| 923 | 917 |
| 924 // Index of the first server to try on each search query. | 918 // Index of the first server to try on each search query. |
| 925 int first_server_index_; | 919 int first_server_index_; |
| 926 | 920 |
| 927 base::OneShotTimer<DnsTransactionImpl> timer_; | 921 base::OneShotTimer<DnsTransactionImpl> timer_; |
| 928 | 922 |
| 929 DISALLOW_COPY_AND_ASSIGN(DnsTransactionImpl); | 923 DISALLOW_COPY_AND_ASSIGN(DnsTransactionImpl); |
| 930 }; | 924 }; |
| 931 | 925 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 955 } // namespace | 949 } // namespace |
| 956 | 950 |
| 957 // static | 951 // static |
| 958 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory( | 952 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory( |
| 959 DnsSession* session) { | 953 DnsSession* session) { |
| 960 return scoped_ptr<DnsTransactionFactory>( | 954 return scoped_ptr<DnsTransactionFactory>( |
| 961 new DnsTransactionFactoryImpl(session)); | 955 new DnsTransactionFactoryImpl(session)); |
| 962 } | 956 } |
| 963 | 957 |
| 964 } // namespace net | 958 } // namespace net |
| OLD | NEW |