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 |