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