Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Side by Side Diff: net/dns/dns_transaction.cc

Issue 8835011: Revert 113282 - Isolates generic DnsClient from AsyncHostResolver. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/dns/dns_transaction.h ('k') | net/dns/dns_transaction_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/rand_util.h" 8 #include "base/rand_util.h"
9 #include "base/values.h" 9 #include "base/values.h"
10 #include "net/base/dns_util.h"
10 #include "net/base/io_buffer.h" 11 #include "net/base/io_buffer.h"
11 #include "net/base/net_errors.h" 12 #include "net/base/net_errors.h"
12 #include "net/dns/dns_protocol.h"
13 #include "net/dns/dns_query.h" 13 #include "net/dns/dns_query.h"
14 #include "net/dns/dns_response.h" 14 #include "net/dns/dns_response.h"
15 #include "net/dns/dns_session.h"
16 #include "net/socket/client_socket_factory.h" 15 #include "net/socket/client_socket_factory.h"
17 #include "net/udp/datagram_client_socket.h" 16 #include "net/udp/datagram_client_socket.h"
18 17
19 namespace net { 18 namespace net {
20 19
21 namespace { 20 namespace {
22 21
22 // Retry timeouts.
23 const int kTimeoutsMs[] = {3000, 5000, 11000};
24 const int kMaxAttempts = arraysize(kTimeoutsMs);
25
26 // Returns the string representation of an IPAddressNumber.
27 std::string IPAddressToString(const IPAddressNumber& ip_address) {
28 IPEndPoint ip_endpoint(ip_address, 0);
29 struct sockaddr_storage addr;
30 size_t addr_len = sizeof(addr);
31 struct sockaddr* sockaddr = reinterpret_cast<struct sockaddr*>(&addr);
32 if (!ip_endpoint.ToSockAddr(sockaddr, &addr_len))
33 return "";
34 return NetAddressToString(sockaddr, addr_len);
35 }
36
37 }
38
39 DnsTransaction::Delegate::Delegate() {
40 }
41
42 DnsTransaction::Delegate::~Delegate() {
43 while (!registered_transactions_.empty()) {
44 DnsTransaction* transaction = *registered_transactions_.begin();
45 transaction->SetDelegate(NULL);
46 }
47 DCHECK(registered_transactions_.empty());
48 }
49
50 void DnsTransaction::Delegate::OnTransactionComplete(
51 int result,
52 const DnsTransaction* transaction,
53 const IPAddressList& ip_addresses) {
54 }
55
56 void DnsTransaction::Delegate::Attach(DnsTransaction* transaction) {
57 DCHECK(registered_transactions_.find(transaction) ==
58 registered_transactions_.end());
59 registered_transactions_.insert(transaction);
60 }
61
62 void DnsTransaction::Delegate::Detach(DnsTransaction* transaction) {
63 DCHECK(registered_transactions_.find(transaction) !=
64 registered_transactions_.end());
65 registered_transactions_.erase(transaction);
66 }
67
68 namespace {
69
23 class DnsTransactionStartParameters : public NetLog::EventParameters { 70 class DnsTransactionStartParameters : public NetLog::EventParameters {
24 public: 71 public:
25 DnsTransactionStartParameters(const IPEndPoint& dns_server, 72 DnsTransactionStartParameters(const IPEndPoint& dns_server,
26 const base::StringPiece& qname, 73 const DnsTransaction::Key& key,
27 uint16 qtype,
28 const NetLog::Source& source) 74 const NetLog::Source& source)
29 : dns_server_(dns_server), 75 : dns_server_(dns_server), key_(key), source_(source) {}
30 qname_(qname.data(), qname.length()),
31 qtype_(qtype),
32 source_(source) {}
33 76
34 virtual Value* ToValue() const { 77 virtual Value* ToValue() const {
78 std::string hostname;
79 DnsResponseBuffer(
80 reinterpret_cast<const uint8*>(key_.first.c_str()), key_.first.size()).
81 DNSName(&hostname);
82
35 DictionaryValue* dict = new DictionaryValue(); 83 DictionaryValue* dict = new DictionaryValue();
36 dict->SetString("dns_server", dns_server_.ToString()); 84 dict->SetString("dns_server", dns_server_.ToString());
37 dict->SetString("hostname", qname_); 85 dict->SetString("hostname", hostname);
38 dict->SetInteger("query_type", qtype_); 86 dict->SetInteger("query_type", key_.second);
39 if (source_.is_valid()) 87 if (source_.is_valid())
40 dict->Set("source_dependency", source_.ToValue()); 88 dict->Set("source_dependency", source_.ToValue());
41 return dict; 89 return dict;
42 } 90 }
43 91
44 private: 92 private:
45 IPEndPoint dns_server_; 93 const IPEndPoint dns_server_;
46 std::string qname_; 94 const DnsTransaction::Key key_;
47 uint16 qtype_;
48 const NetLog::Source source_; 95 const NetLog::Source source_;
49 }; 96 };
50 97
51 class DnsTransactionFinishParameters : public NetLog::EventParameters { 98 class DnsTransactionFinishParameters : public NetLog::EventParameters {
52 public: 99 public:
53 // TODO(szym): add rcode ? 100 DnsTransactionFinishParameters(int net_error,
54 DnsTransactionFinishParameters(int net_error, int answer_count) 101 const IPAddressList& ip_address_list)
55 : net_error_(net_error), answer_count_(answer_count) {} 102 : net_error_(net_error), ip_address_list_(ip_address_list) {}
56 103
57 virtual Value* ToValue() const { 104 virtual Value* ToValue() const {
105 ListValue* list = new ListValue();
106 for (IPAddressList::const_iterator it = ip_address_list_.begin();
107 it != ip_address_list_.end(); ++it)
108 list->Append(Value::CreateStringValue(IPAddressToString(*it)));
109
58 DictionaryValue* dict = new DictionaryValue(); 110 DictionaryValue* dict = new DictionaryValue();
59 if (net_error_) 111 if (net_error_)
60 dict->SetInteger("net_error", net_error_); 112 dict->SetInteger("net_error", net_error_);
61 dict->SetInteger("answer_count", answer_count_); 113 dict->Set("address_list", list);
62 return dict; 114 return dict;
63 } 115 }
64 116
65 private: 117 private:
66 const int net_error_; 118 const int net_error_;
67 const int answer_count_; 119 const IPAddressList ip_address_list_;
68 }; 120 };
69 121
70 class DnsTransactionRetryParameters : public NetLog::EventParameters { 122 class DnsTransactionRetryParameters : public NetLog::EventParameters {
71 public: 123 public:
72 DnsTransactionRetryParameters(int attempt_number, 124 DnsTransactionRetryParameters(int attempt_number,
73 const NetLog::Source& source) 125 const NetLog::Source& source)
74 : attempt_number_(attempt_number), source_(source) {} 126 : attempt_number_(attempt_number), source_(source) {}
75 127
76 virtual Value* ToValue() const { 128 virtual Value* ToValue() const {
77 DictionaryValue* dict = new DictionaryValue(); 129 DictionaryValue* dict = new DictionaryValue();
78 dict->SetInteger("attempt_number", attempt_number_); 130 dict->SetInteger("attempt_number", attempt_number_);
79 dict->Set("source_dependency", source_.ToValue()); 131 dict->Set("source_dependency", source_.ToValue());
80 return dict; 132 return dict;
81 } 133 }
82 134
83 private: 135 private:
84 const int attempt_number_; 136 const int attempt_number_;
85 const NetLog::Source source_; 137 const NetLog::Source source_;
86 }; 138 };
87 139
88 } // namespace 140 } // namespace
89 141
90 142 DnsTransaction::DnsTransaction(const IPEndPoint& dns_server,
91 DnsTransaction::DnsTransaction(DnsSession* session, 143 const std::string& dns_name,
92 const base::StringPiece& qname, 144 uint16 query_type,
93 uint16 qtype, 145 const RandIntCallback& rand_int,
94 const ResultCallback& callback, 146 ClientSocketFactory* socket_factory,
95 const BoundNetLog& source_net_log) 147 const BoundNetLog& source_net_log,
96 : session_(session), 148 NetLog* net_log)
97 dns_server_(session->NextServer()), 149 : dns_server_(dns_server),
98 query_(new DnsQuery(session->NextId(), qname, qtype)), 150 key_(dns_name, query_type),
99 callback_(callback), 151 delegate_(NULL),
152 query_(new DnsQuery(dns_name, query_type, rand_int)),
100 attempts_(0), 153 attempts_(0),
101 next_state_(STATE_NONE), 154 next_state_(STATE_NONE),
155 socket_factory_(socket_factory ? socket_factory :
156 ClientSocketFactory::GetDefaultFactory()),
102 ALLOW_THIS_IN_INITIALIZER_LIST( 157 ALLOW_THIS_IN_INITIALIZER_LIST(
103 io_callback_(this, &DnsTransaction::OnIOComplete)), 158 io_callback_(this, &DnsTransaction::OnIOComplete)),
104 net_log_(BoundNetLog::Make(session->net_log(), 159 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_DNS_TRANSACTION)) {
105 NetLog::SOURCE_DNS_TRANSACTION)) { 160 DCHECK(!rand_int.is_null());
161 for (size_t i = 0; i < arraysize(kTimeoutsMs); ++i)
162 timeouts_ms_.push_back(base::TimeDelta::FromMilliseconds(kTimeoutsMs[i]));
106 net_log_.BeginEvent( 163 net_log_.BeginEvent(
107 NetLog::TYPE_DNS_TRANSACTION, 164 NetLog::TYPE_DNS_TRANSACTION,
108 make_scoped_refptr( 165 make_scoped_refptr(
109 new DnsTransactionStartParameters(dns_server_, 166 new DnsTransactionStartParameters(dns_server_, key_,
110 qname,
111 qtype,
112 source_net_log.source()))); 167 source_net_log.source())));
113 } 168 }
114 169
115 DnsTransaction::~DnsTransaction() {} 170 DnsTransaction::~DnsTransaction() {
171 SetDelegate(NULL);
172 }
173
174 void DnsTransaction::SetDelegate(Delegate* delegate) {
175 if (delegate == delegate_)
176 return;
177 if (delegate_)
178 delegate_->Detach(this);
179 delegate_ = delegate;
180 if (delegate_)
181 delegate_->Attach(this);
182 }
116 183
117 int DnsTransaction::Start() { 184 int DnsTransaction::Start() {
118 DCHECK_EQ(STATE_NONE, next_state_); 185 DCHECK_EQ(STATE_NONE, next_state_);
119 next_state_ = STATE_CONNECT; 186 next_state_ = STATE_CONNECT;
120 return DoLoop(OK); 187 return DoLoop(OK);
121 } 188 }
122 189
123 int DnsTransaction::DoLoop(int result) { 190 int DnsTransaction::DoLoop(int result) {
124 DCHECK_NE(STATE_NONE, next_state_); 191 DCHECK_NE(STATE_NONE, next_state_);
125 int rv = result; 192 int rv = result;
(...skipping 23 matching lines...) Expand all
149 NOTREACHED(); 216 NOTREACHED();
150 break; 217 break;
151 } 218 }
152 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 219 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
153 220
154 return rv; 221 return rv;
155 } 222 }
156 223
157 void DnsTransaction::DoCallback(int result) { 224 void DnsTransaction::DoCallback(int result) {
158 DCHECK_NE(result, ERR_IO_PENDING); 225 DCHECK_NE(result, ERR_IO_PENDING);
159 int answer_count = (result == OK) ? response()->answer_count() : 0;
160 net_log_.EndEvent( 226 net_log_.EndEvent(
161 NetLog::TYPE_DNS_TRANSACTION, 227 NetLog::TYPE_DNS_TRANSACTION,
162 make_scoped_refptr( 228 make_scoped_refptr(
163 new DnsTransactionFinishParameters(result, answer_count))); 229 new DnsTransactionFinishParameters(result, ip_addresses_)));
164 callback_.Run(this, result); 230 if (delegate_)
231 delegate_->OnTransactionComplete(result, this, ip_addresses_);
165 } 232 }
166 233
167 void DnsTransaction::OnIOComplete(int result) { 234 void DnsTransaction::OnIOComplete(int result) {
168 int rv = DoLoop(result); 235 int rv = DoLoop(result);
169 if (rv != ERR_IO_PENDING) 236 if (rv != ERR_IO_PENDING)
170 DoCallback(rv); 237 DoCallback(rv);
171 } 238 }
172 239
173 int DnsTransaction::DoConnect() { 240 int DnsTransaction::DoConnect() {
174 next_state_ = STATE_CONNECT_COMPLETE; 241 next_state_ = STATE_CONNECT_COMPLETE;
175 242
176 StartTimer(session_->NextTimeout(attempts_)); 243 DCHECK_LT(attempts_, timeouts_ms_.size());
177 ++attempts_; 244 StartTimer(timeouts_ms_[attempts_]);
245 attempts_++;
178 246
179 // TODO(szym): keep all sockets around in case the server responds 247 // TODO(agayev): keep all sockets around in case the server responds
180 // after its timeout; state machine will need to change to handle that. 248 // after its timeout; state machine will need to change to handle that.
181 // The current plan is to move socket management out to DnsSession. 249 socket_.reset(socket_factory_->CreateDatagramClientSocket(
182 // Hence also move retransmissions to DnsClient::Request.
183 socket_.reset(session_->socket_factory()->CreateDatagramClientSocket(
184 DatagramSocket::RANDOM_BIND, 250 DatagramSocket::RANDOM_BIND,
185 base::Bind(&base::RandInt), 251 base::Bind(&base::RandInt),
186 net_log_.net_log(), 252 net_log_.net_log(),
187 net_log_.source())); 253 net_log_.source()));
188 254
189 net_log_.AddEvent( 255 net_log_.AddEvent(
190 NetLog::TYPE_DNS_TRANSACTION_ATTEMPT_STARTED, 256 NetLog::TYPE_DNS_TRANSACTION_ATTEMPT_STARTED,
191 make_scoped_refptr( 257 make_scoped_refptr(
192 new DnsTransactionRetryParameters(attempts_, 258 new DnsTransactionRetryParameters(attempts_,
193 socket_->NetLog().source()))); 259 socket_->NetLog().source())));
(...skipping 14 matching lines...) Expand all
208 query_->io_buffer()->size(), 274 query_->io_buffer()->size(),
209 &io_callback_); 275 &io_callback_);
210 } 276 }
211 277
212 int DnsTransaction::DoSendQueryComplete(int rv) { 278 int DnsTransaction::DoSendQueryComplete(int rv) {
213 if (rv < 0) 279 if (rv < 0)
214 return rv; 280 return rv;
215 281
216 // Writing to UDP should not result in a partial datagram. 282 // Writing to UDP should not result in a partial datagram.
217 if (rv != query_->io_buffer()->size()) 283 if (rv != query_->io_buffer()->size())
218 return ERR_MSG_TOO_BIG; 284 return ERR_NAME_NOT_RESOLVED;
219 285
220 next_state_ = STATE_READ_RESPONSE; 286 next_state_ = STATE_READ_RESPONSE;
221 return OK; 287 return OK;
222 } 288 }
223 289
224 int DnsTransaction::DoReadResponse() { 290 int DnsTransaction::DoReadResponse() {
225 next_state_ = STATE_READ_RESPONSE_COMPLETE; 291 next_state_ = STATE_READ_RESPONSE_COMPLETE;
226 response_.reset(new DnsResponse()); 292 response_.reset(new DnsResponse(query_.get()));
227 return socket_->Read(response_->io_buffer(), 293 return socket_->Read(response_->io_buffer(),
228 response_->io_buffer()->size(), 294 response_->io_buffer()->size(),
229 &io_callback_); 295 &io_callback_);
230 } 296 }
231 297
232 int DnsTransaction::DoReadResponseComplete(int rv) { 298 int DnsTransaction::DoReadResponseComplete(int rv) {
233 DCHECK_NE(ERR_IO_PENDING, rv); 299 DCHECK_NE(ERR_IO_PENDING, rv);
234 RevokeTimer(); 300 RevokeTimer();
235 if (rv < 0) 301 if (rv < 0)
236 return rv; 302 return rv;
237 303
238 DCHECK(rv); 304 DCHECK(rv);
239 if (!response_->InitParse(rv, *query_)) 305 // TODO(agayev): when supporting EDNS0 we may need to do multiple reads
240 return ERR_DNS_MALFORMED_RESPONSE; 306 // to read the whole response.
241 // TODO(szym): define this flag value in dns_protocol 307 return response_->Parse(rv, &ip_addresses_);
242 if (response_->flags1() & 2)
243 return ERR_DNS_SERVER_REQUIRES_TCP;
244 // TODO(szym): move this handling out of DnsTransaction?
245 if (response_->rcode() != dns_protocol::kRcodeNOERROR &&
246 response_->rcode() != dns_protocol::kRcodeNXDOMAIN) {
247 return ERR_DNS_SERVER_FAILED;
248 }
249 // TODO(szym): add ERR_DNS_RR_NOT_FOUND?
250 if (response_->answer_count() == 0)
251 return ERR_NAME_NOT_RESOLVED;
252
253 return OK;
254 } 308 }
255 309
256 void DnsTransaction::StartTimer(base::TimeDelta delay) { 310 void DnsTransaction::StartTimer(base::TimeDelta delay) {
257 timer_.Start(FROM_HERE, delay, this, &DnsTransaction::OnTimeout); 311 timer_.Start(FROM_HERE, delay, this, &DnsTransaction::OnTimeout);
258 } 312 }
259 313
260 void DnsTransaction::RevokeTimer() { 314 void DnsTransaction::RevokeTimer() {
261 timer_.Stop(); 315 timer_.Stop();
262 } 316 }
263 317
264 void DnsTransaction::OnTimeout() { 318 void DnsTransaction::OnTimeout() {
265 DCHECK(next_state_ == STATE_SEND_QUERY_COMPLETE || 319 DCHECK(next_state_ == STATE_SEND_QUERY_COMPLETE ||
266 next_state_ == STATE_READ_RESPONSE_COMPLETE); 320 next_state_ == STATE_READ_RESPONSE_COMPLETE);
267 if (attempts_ == session_->config().attempts) { 321 if (attempts_ == timeouts_ms_.size()) {
268 DoCallback(ERR_DNS_TIMED_OUT); 322 DoCallback(ERR_DNS_TIMED_OUT);
269 return; 323 return;
270 } 324 }
271 next_state_ = STATE_CONNECT; 325 next_state_ = STATE_CONNECT;
272 query_.reset(query_->CloneWithNewId(session_->NextId())); 326 query_.reset(query_->CloneWithNewId());
273 int rv = DoLoop(OK); 327 int rv = DoLoop(OK);
274 if (rv != ERR_IO_PENDING) 328 if (rv != ERR_IO_PENDING)
275 DoCallback(rv); 329 DoCallback(rv);
276 } 330 }
277 331
332 void DnsTransaction::set_timeouts_ms(
333 const std::vector<base::TimeDelta>& timeouts_ms) {
334 DCHECK_EQ(0u, attempts_);
335 timeouts_ms_ = timeouts_ms;
336 }
337
278 } // namespace net 338 } // namespace net
OLDNEW
« no previous file with comments | « net/dns/dns_transaction.h ('k') | net/dns/dns_transaction_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698