OLD | NEW |
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/async_host_resolver.h" | 5 #include "net/dns/async_host_resolver.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/message_loop.h" |
11 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
12 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
13 #include "base/values.h" | 14 #include "base/values.h" |
14 #include "net/base/address_list.h" | 15 #include "net/base/address_list.h" |
15 #include "net/base/dns_util.h" | 16 #include "net/base/dns_util.h" |
16 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
| 18 #include "net/dns/dns_protocol.h" |
| 19 #include "net/dns/dns_response.h" |
| 20 #include "net/dns/dns_session.h" |
17 #include "net/socket/client_socket_factory.h" | 21 #include "net/socket/client_socket_factory.h" |
18 | 22 |
19 namespace net { | 23 namespace net { |
20 | 24 |
21 namespace { | 25 namespace { |
22 | 26 |
23 // TODO(agayev): fix this when IPv6 support is added. | 27 // TODO(agayev): fix this when IPv6 support is added. |
24 uint16 QueryTypeFromAddressFamily(AddressFamily address_family) { | 28 uint16 QueryTypeFromAddressFamily(AddressFamily address_family) { |
25 return kDNS_A; | 29 return dns_protocol::kTypeA; |
26 } | 30 } |
27 | 31 |
28 class RequestParameters : public NetLog::EventParameters { | 32 class RequestParameters : public NetLog::EventParameters { |
29 public: | 33 public: |
30 RequestParameters(const HostResolver::RequestInfo& info, | 34 RequestParameters(const HostResolver::RequestInfo& info, |
31 const NetLog::Source& source) | 35 const NetLog::Source& source) |
32 : info_(info), source_(source) {} | 36 : info_(info), source_(source) {} |
33 | 37 |
34 virtual Value* ToValue() const { | 38 virtual Value* ToValue() const { |
35 DictionaryValue* dict = new DictionaryValue(); | 39 DictionaryValue* dict = new DictionaryValue(); |
(...skipping 13 matching lines...) Expand all Loading... |
49 private: | 53 private: |
50 const HostResolver::RequestInfo info_; | 54 const HostResolver::RequestInfo info_; |
51 const NetLog::Source source_; | 55 const NetLog::Source source_; |
52 }; | 56 }; |
53 | 57 |
54 } // namespace | 58 } // namespace |
55 | 59 |
56 HostResolver* CreateAsyncHostResolver(size_t max_concurrent_resolves, | 60 HostResolver* CreateAsyncHostResolver(size_t max_concurrent_resolves, |
57 const IPAddressNumber& dns_ip, | 61 const IPAddressNumber& dns_ip, |
58 NetLog* net_log) { | 62 NetLog* net_log) { |
59 size_t max_transactions = max_concurrent_resolves; | 63 size_t max_dns_requests = max_concurrent_resolves; |
60 if (max_transactions == 0) | 64 if (max_dns_requests == 0) |
61 max_transactions = 20; | 65 max_dns_requests = 20; |
62 size_t max_pending_requests = max_transactions * 100; | 66 size_t max_pending_requests = max_dns_requests * 100; |
| 67 DnsConfig config; |
| 68 config.nameservers.push_back(IPEndPoint(dns_ip, 53)); |
| 69 DnsSession* session = new DnsSession( |
| 70 config, |
| 71 ClientSocketFactory::GetDefaultFactory(), |
| 72 base::Bind(&base::RandInt), |
| 73 net_log); |
63 HostResolver* resolver = new AsyncHostResolver( | 74 HostResolver* resolver = new AsyncHostResolver( |
64 IPEndPoint(dns_ip, 53), | 75 max_dns_requests, |
65 max_transactions, | |
66 max_pending_requests, | 76 max_pending_requests, |
67 base::Bind(&base::RandInt), | |
68 HostCache::CreateDefaultCache(), | 77 HostCache::CreateDefaultCache(), |
69 NULL, | 78 DnsClient::CreateClient(session), |
70 net_log); | 79 net_log); |
71 return resolver; | 80 return resolver; |
72 } | 81 } |
73 | 82 |
74 //----------------------------------------------------------------------------- | 83 //----------------------------------------------------------------------------- |
75 // Every call to Resolve() results in Request object being created. Such a | 84 // Every call to Resolve() results in Request object being created. Such a |
76 // call may complete either synchronously or asynchronously or it may get | 85 // call may complete either synchronously or asynchronously or it may get |
77 // cancelled, which can be either through specific CancelRequest call or by | 86 // cancelled, which can be either through specific CancelRequest call or by |
78 // the destruction of AsyncHostResolver, which would destruct pending or | 87 // the destruction of AsyncHostResolver, which would destruct pending or |
79 // in-progress requests, causing them to be cancelled. Synchronous | 88 // in-progress requests, causing them to be cancelled. Synchronous |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 BoundNetLog source_net_log_; | 195 BoundNetLog source_net_log_; |
187 BoundNetLog request_net_log_; | 196 BoundNetLog request_net_log_; |
188 const HostResolver::RequestInfo info_; | 197 const HostResolver::RequestInfo info_; |
189 Key key_; | 198 Key key_; |
190 CompletionCallback callback_; | 199 CompletionCallback callback_; |
191 AddressList* addresses_; | 200 AddressList* addresses_; |
192 int result_; | 201 int result_; |
193 }; | 202 }; |
194 | 203 |
195 //----------------------------------------------------------------------------- | 204 //----------------------------------------------------------------------------- |
196 AsyncHostResolver::AsyncHostResolver(const IPEndPoint& dns_server, | 205 AsyncHostResolver::AsyncHostResolver(size_t max_dns_requests, |
197 size_t max_transactions, | |
198 size_t max_pending_requests, | 206 size_t max_pending_requests, |
199 const RandIntCallback& rand_int_cb, | |
200 HostCache* cache, | 207 HostCache* cache, |
201 ClientSocketFactory* factory, | 208 DnsClient* client, |
202 NetLog* net_log) | 209 NetLog* net_log) |
203 : max_transactions_(max_transactions), | 210 : max_dns_requests_(max_dns_requests), |
204 max_pending_requests_(max_pending_requests), | 211 max_pending_requests_(max_pending_requests), |
205 dns_server_(dns_server), | |
206 rand_int_cb_(rand_int_cb), | |
207 cache_(cache), | 212 cache_(cache), |
208 factory_(factory), | 213 client_(client), |
209 net_log_(net_log) { | 214 net_log_(net_log) { |
210 } | 215 } |
211 | 216 |
212 AsyncHostResolver::~AsyncHostResolver() { | 217 AsyncHostResolver::~AsyncHostResolver() { |
213 // Destroy request lists. | 218 // Destroy request lists. |
214 for (KeyRequestListMap::iterator it = requestlist_map_.begin(); | 219 for (KeyRequestListMap::iterator it = requestlist_map_.begin(); |
215 it != requestlist_map_.end(); ++it) | 220 it != requestlist_map_.end(); ++it) |
216 STLDeleteElements(&it->second); | 221 STLDeleteElements(&it->second); |
217 | 222 |
218 // Destroy transactions. | 223 // Destroy DNS requests. |
219 STLDeleteElements(&transactions_); | 224 STLDeleteElements(&dns_requests_); |
220 | 225 |
221 // Destroy pending requests. | 226 // Destroy pending requests. |
222 for (size_t i = 0; i < arraysize(pending_requests_); ++i) | 227 for (size_t i = 0; i < arraysize(pending_requests_); ++i) |
223 STLDeleteElements(&pending_requests_[i]); | 228 STLDeleteElements(&pending_requests_[i]); |
224 } | 229 } |
225 | 230 |
226 int AsyncHostResolver::Resolve(const RequestInfo& info, | 231 int AsyncHostResolver::Resolve(const RequestInfo& info, |
227 AddressList* addresses, | 232 AddressList* addresses, |
228 const CompletionCallback& callback, | 233 const CompletionCallback& callback, |
229 RequestHandle* out_req, | 234 RequestHandle* out_req, |
230 const BoundNetLog& source_net_log) { | 235 const BoundNetLog& source_net_log) { |
231 DCHECK(addresses); | 236 DCHECK(addresses); |
232 DCHECK_EQ(false, callback.is_null()); | 237 DCHECK_EQ(false, callback.is_null()); |
233 scoped_ptr<Request> request( | 238 scoped_ptr<Request> request( |
234 CreateNewRequest(info, callback, addresses, source_net_log)); | 239 CreateNewRequest(info, callback, addresses, source_net_log)); |
235 | 240 |
236 int rv = ERR_UNEXPECTED; | 241 int rv = ERR_UNEXPECTED; |
237 if (!request->IsValid()) | 242 if (!request->IsValid()) |
238 rv = ERR_NAME_NOT_RESOLVED; | 243 rv = ERR_NAME_NOT_RESOLVED; |
239 else if (request->ResolveAsIp() || request->ServeFromCache()) | 244 else if (request->ResolveAsIp() || request->ServeFromCache()) |
240 rv = request->result(); | 245 rv = request->result(); |
241 else if (AttachToRequestList(request.get())) | 246 else if (AttachToRequestList(request.get())) |
242 rv = ERR_IO_PENDING; | 247 rv = ERR_IO_PENDING; |
243 else if (transactions_.size() < max_transactions_) | 248 else if (dns_requests_.size() < max_dns_requests_) |
244 rv = StartNewTransactionFor(request.get()); | 249 rv = StartNewDnsRequestFor(request.get()); |
245 else | 250 else |
246 rv = Enqueue(request.get()); | 251 rv = Enqueue(request.get()); |
247 | 252 |
248 if (rv != ERR_IO_PENDING) { | 253 if (rv != ERR_IO_PENDING) { |
249 request->OnSyncComplete(rv); | 254 request->OnSyncComplete(rv); |
250 } else { | 255 } else { |
251 Request* req = request.release(); | 256 Request* req = request.release(); |
252 if (out_req) | 257 if (out_req) |
253 *out_req = reinterpret_cast<RequestHandle>(req); | 258 *out_req = reinterpret_cast<RequestHandle>(req); |
254 } | 259 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 } | 325 } |
321 | 326 |
322 AddressFamily AsyncHostResolver::GetDefaultAddressFamily() const { | 327 AddressFamily AsyncHostResolver::GetDefaultAddressFamily() const { |
323 return ADDRESS_FAMILY_IPV4; | 328 return ADDRESS_FAMILY_IPV4; |
324 } | 329 } |
325 | 330 |
326 HostCache* AsyncHostResolver::GetHostCache() { | 331 HostCache* AsyncHostResolver::GetHostCache() { |
327 return cache_.get(); | 332 return cache_.get(); |
328 } | 333 } |
329 | 334 |
330 void AsyncHostResolver::OnTransactionComplete( | 335 void AsyncHostResolver::OnDnsRequestComplete( |
| 336 DnsClient::Request* dns_req, |
331 int result, | 337 int result, |
332 const DnsTransaction* transaction, | 338 const DnsResponse* response) { |
333 const IPAddressList& ip_addresses) { | 339 DCHECK(std::find(dns_requests_.begin(), dns_requests_.end(), dns_req) |
334 DCHECK(std::find(transactions_.begin(), transactions_.end(), transaction) | 340 != dns_requests_.end()); |
335 != transactions_.end()); | |
336 DCHECK(requestlist_map_.find(transaction->key()) != requestlist_map_.end()); | |
337 | 341 |
338 // If by the time requests that caused |transaction| are cancelled, we do | 342 // If by the time requests that caused |dns_req| are cancelled, we do |
339 // not have a port number to associate with the result, therefore, we | 343 // not have a port number to associate with the result, therefore, we |
340 // assume the most common port, otherwise we use the port number of the | 344 // assume the most common port, otherwise we use the port number of the |
341 // first request. | 345 // first request. |
342 RequestList& requests = requestlist_map_[transaction->key()]; | 346 KeyRequestListMap::iterator rit = requestlist_map_.find( |
| 347 std::make_pair(dns_req->qname(), dns_req->qtype())); |
| 348 DCHECK(rit != requestlist_map_.end()); |
| 349 RequestList& requests = rit->second; |
343 int port = requests.empty() ? 80 : requests.front()->info().port(); | 350 int port = requests.empty() ? 80 : requests.front()->info().port(); |
344 | 351 |
345 // Run callback of every request that was depending on this transaction, | 352 // Extract AddressList out of DnsResponse. |
| 353 AddressList addr_list; |
| 354 if (result == OK) { |
| 355 IPAddressList ip_addresses; |
| 356 DnsRecordParser parser = response->Parser(); |
| 357 DnsResourceRecord record; |
| 358 // TODO(szym): Add stricter checking of names, aliases and address lengths. |
| 359 while (parser.ParseRecord(&record)) { |
| 360 if (record.type == dns_req->qtype() && |
| 361 (record.rdata.size() == kIPv4AddressSize || |
| 362 record.rdata.size() == kIPv6AddressSize)) { |
| 363 ip_addresses.push_back(IPAddressNumber(record.rdata.begin(), |
| 364 record.rdata.end())); |
| 365 } |
| 366 } |
| 367 if (!ip_addresses.empty()) |
| 368 addr_list = AddressList::CreateFromIPAddressList(ip_addresses, port); |
| 369 else |
| 370 result = ERR_NAME_NOT_RESOLVED; |
| 371 } |
| 372 |
| 373 // Run callback of every request that was depending on this DNS request, |
346 // also notify observers. | 374 // also notify observers. |
347 AddressList addrlist; | 375 for (RequestList::iterator it = requests.begin(); it != requests.end(); ++it) |
348 if (result == OK) | 376 (*it)->OnAsyncComplete(result, addr_list); |
349 addrlist = AddressList::CreateFromIPAddressList(ip_addresses, port); | |
350 for (RequestList::iterator it = requests.begin(); it != requests.end(); | |
351 ++it) | |
352 (*it)->OnAsyncComplete(result, addrlist); | |
353 | 377 |
354 // It is possible that the requests that caused |transaction| to be | 378 // It is possible that the requests that caused |dns_req| to be |
355 // created are cancelled by the time |transaction| completes. In that | 379 // created are cancelled by the time |dns_req| completes. In that |
356 // case |requests| would be empty. We are knowingly throwing away the | 380 // case |requests| would be empty. We are knowingly throwing away the |
357 // result of a DNS resolution in that case, because (a) if there are no | 381 // result of a DNS resolution in that case, because (a) if there are no |
358 // requests, we do not have info to obtain a key from, (b) DnsTransaction | 382 // requests, we do not have info to obtain a key from, (b) DnsTransaction |
359 // does not have info(), adding one into it just temporarily doesn't make | 383 // does not have info(), adding one into it just temporarily doesn't make |
360 // sense, since HostCache will be replaced with RR cache soon, (c) | 384 // sense, since HostCache will be replaced with RR cache soon. |
361 // recreating info from DnsTransaction::Key adds a lot of temporary | |
362 // code/functions (like converting back from qtype to AddressFamily.) | |
363 // Also, we only cache positive results. All of this will change when RR | 385 // Also, we only cache positive results. All of this will change when RR |
364 // cache is added. | 386 // cache is added. |
365 if (result == OK && cache_.get() && !requests.empty()) { | 387 if (result == OK && cache_.get() && !requests.empty()) { |
366 Request* request = requests.front(); | 388 Request* request = requests.front(); |
367 HostResolver::RequestInfo info = request->info(); | 389 HostResolver::RequestInfo info = request->info(); |
368 HostCache::Key key( | 390 HostCache::Key key( |
369 info.hostname(), info.address_family(), info.host_resolver_flags()); | 391 info.hostname(), info.address_family(), info.host_resolver_flags()); |
370 cache_->Set(key, result, addrlist, base::TimeTicks::Now()); | 392 cache_->Set(key, result, addr_list, base::TimeTicks::Now()); |
371 } | 393 } |
372 | 394 |
373 // Cleanup requests. | 395 // Cleanup requests. |
374 STLDeleteElements(&requests); | 396 STLDeleteElements(&requests); |
375 requestlist_map_.erase(transaction->key()); | 397 requestlist_map_.erase(rit); |
376 | 398 |
377 // Cleanup transaction and start a new one if there are pending requests. | 399 // Cleanup |dns_req| and start a new one if there are pending requests. |
378 delete transaction; | 400 delete dns_req; |
379 transactions_.remove(transaction); | 401 dns_requests_.remove(dns_req); |
380 ProcessPending(); | 402 ProcessPending(); |
381 } | 403 } |
382 | 404 |
383 AsyncHostResolver::Request* AsyncHostResolver::CreateNewRequest( | 405 AsyncHostResolver::Request* AsyncHostResolver::CreateNewRequest( |
384 const RequestInfo& info, | 406 const RequestInfo& info, |
385 const CompletionCallback& callback, | 407 const CompletionCallback& callback, |
386 AddressList* addresses, | 408 AddressList* addresses, |
387 const BoundNetLog& source_net_log) { | 409 const BoundNetLog& source_net_log) { |
388 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, | 410 BoundNetLog request_net_log = BoundNetLog::Make(net_log_, |
389 NetLog::SOURCE_ASYNC_HOST_RESOLVER_REQUEST); | 411 NetLog::SOURCE_ASYNC_HOST_RESOLVER_REQUEST); |
390 return new Request( | 412 return new Request( |
391 this, source_net_log, request_net_log, info, callback, addresses); | 413 this, source_net_log, request_net_log, info, callback, addresses); |
392 } | 414 } |
393 | 415 |
394 bool AsyncHostResolver::AttachToRequestList(Request* request) { | 416 bool AsyncHostResolver::AttachToRequestList(Request* request) { |
395 KeyRequestListMap::iterator it = requestlist_map_.find(request->key()); | 417 KeyRequestListMap::iterator it = requestlist_map_.find(request->key()); |
396 if (it == requestlist_map_.end()) | 418 if (it == requestlist_map_.end()) |
397 return false; | 419 return false; |
398 it->second.push_back(request); | 420 it->second.push_back(request); |
399 return true; | 421 return true; |
400 } | 422 } |
401 | 423 |
402 int AsyncHostResolver::StartNewTransactionFor(Request* request) { | 424 int AsyncHostResolver::StartNewDnsRequestFor(Request* request) { |
403 DCHECK(requestlist_map_.find(request->key()) == requestlist_map_.end()); | 425 DCHECK(requestlist_map_.find(request->key()) == requestlist_map_.end()); |
404 DCHECK(transactions_.size() < max_transactions_); | 426 DCHECK(dns_requests_.size() < max_dns_requests_); |
405 | 427 |
406 request->request_net_log().AddEvent( | 428 request->request_net_log().AddEvent( |
407 NetLog::TYPE_ASYNC_HOST_RESOLVER_CREATE_DNS_TRANSACTION, NULL); | 429 NetLog::TYPE_ASYNC_HOST_RESOLVER_CREATE_DNS_TRANSACTION, NULL); |
408 | 430 |
409 requestlist_map_[request->key()].push_back(request); | 431 requestlist_map_[request->key()].push_back(request); |
410 DnsTransaction* transaction = new DnsTransaction( | 432 DnsClient::Request* dns_req = client_->CreateRequest( |
411 dns_server_, | |
412 request->key().first, | 433 request->key().first, |
413 request->key().second, | 434 request->key().second, |
414 rand_int_cb_, | 435 base::Bind(&AsyncHostResolver::OnDnsRequestComplete, |
415 factory_, | 436 base::Unretained(this)), |
416 request->request_net_log(), | 437 request->request_net_log()); |
417 net_log_); | 438 dns_requests_.push_back(dns_req); |
418 transaction->SetDelegate(this); | 439 return dns_req->Start(); |
419 transactions_.push_back(transaction); | |
420 return transaction->Start(); | |
421 } | 440 } |
422 | 441 |
423 int AsyncHostResolver::Enqueue(Request* request) { | 442 int AsyncHostResolver::Enqueue(Request* request) { |
424 Request* evicted_request = Insert(request); | 443 Request* evicted_request = Insert(request); |
425 int rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; | 444 int rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; |
426 if (evicted_request == request) | 445 if (evicted_request == request) |
427 return rv; | 446 return rv; |
428 if (evicted_request != NULL) { | 447 if (evicted_request != NULL) { |
429 evicted_request->OnAsyncComplete(rv, AddressList()); | 448 evicted_request->OnAsyncComplete(rv, AddressList()); |
430 delete evicted_request; | 449 delete evicted_request; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 RequestList::iterator it = requests.begin(); | 502 RequestList::iterator it = requests.begin(); |
484 while (it != requests.end()) { | 503 while (it != requests.end()) { |
485 if (request->key() == (*it)->key()) { | 504 if (request->key() == (*it)->key()) { |
486 requestlist_map_[request->key()].push_back(*it); | 505 requestlist_map_[request->key()].push_back(*it); |
487 it = requests.erase(it); | 506 it = requests.erase(it); |
488 } else { | 507 } else { |
489 ++it; | 508 ++it; |
490 } | 509 } |
491 } | 510 } |
492 } | 511 } |
493 StartNewTransactionFor(request); | 512 StartNewDnsRequestFor(request); |
494 } | 513 } |
495 | 514 |
496 } // namespace net | 515 } // namespace net |
OLD | NEW |