diff options
author | agayev@chromium.org <agayev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 15:58:20 +0000 |
---|---|---|
committer | agayev@chromium.org <agayev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 15:58:20 +0000 |
commit | 4b0112ab742b96585b897269dd27cc7818b3f129 (patch) | |
tree | 0ea379258252b88f5e323b9c6f547f8b3c2500fa /net/base | |
parent | 17bf5d37a85eff17c372db57ef37cc4b57f28b53 (diff) | |
download | chromium_src-4b0112ab742b96585b897269dd27cc7818b3f129.zip chromium_src-4b0112ab742b96585b897269dd27cc7818b3f129.tar.gz chromium_src-4b0112ab742b96585b897269dd27cc7818b3f129.tar.bz2 |
File reorganization: move AsyncHostResolver files to net/dns.
BUG=60149
TEST=net_unittest --gtest_filter="AsyncHostResolver*"
Review URL: http://codereview.chromium.org/7484012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93644 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base')
-rw-r--r-- | net/base/async_host_resolver.cc | 484 | ||||
-rw-r--r-- | net/base/async_host_resolver.h | 165 | ||||
-rw-r--r-- | net/base/async_host_resolver_unittest.cc | 590 | ||||
-rw-r--r-- | net/base/dns_query.cc | 97 | ||||
-rw-r--r-- | net/base/dns_query.h | 71 | ||||
-rw-r--r-- | net/base/dns_query_unittest.cc | 109 | ||||
-rw-r--r-- | net/base/dns_response.cc | 98 | ||||
-rw-r--r-- | net/base/dns_response.h | 47 | ||||
-rw-r--r-- | net/base/dns_response_unittest.cc | 141 | ||||
-rw-r--r-- | net/base/dns_test_util.h | 272 | ||||
-rw-r--r-- | net/base/dns_transaction.cc | 336 | ||||
-rw-r--r-- | net/base/dns_transaction.h | 148 | ||||
-rw-r--r-- | net/base/dns_transaction_unittest.cc | 342 | ||||
-rw-r--r-- | net/base/host_resolver_impl_unittest.cc | 2 | ||||
-rw-r--r-- | net/base/test_host_resolver_observer.cc (renamed from net/base/dns_test_util.cc) | 44 | ||||
-rw-r--r-- | net/base/test_host_resolver_observer.h | 73 |
16 files changed, 76 insertions, 2943 deletions
diff --git a/net/base/async_host_resolver.cc b/net/base/async_host_resolver.cc deleted file mode 100644 index 992767b..0000000 --- a/net/base/async_host_resolver.cc +++ /dev/null @@ -1,484 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/base/async_host_resolver.h" - -#include <algorithm> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/rand_util.h" -#include "base/stl_util.h" -#include "base/values.h" -#include "net/base/address_list.h" -#include "net/base/dns_util.h" -#include "net/base/net_errors.h" -#include "net/socket/client_socket_factory.h" - -namespace net { - -namespace { - -// TODO(agayev): fix this when IPv6 support is added. -uint16 QueryTypeFromAddressFamily(AddressFamily address_family) { - return kDNS_A; -} - -int ResolveAsIp(const HostResolver::RequestInfo& info, - const IPAddressNumber& ip_number, - AddressList* addresses) { - if (ip_number.size() != kIPv4AddressSize) - return ERR_NAME_NOT_RESOLVED; - - *addresses = AddressList::CreateFromIPAddressWithCname( - ip_number, - info.port(), - info.host_resolver_flags() & HOST_RESOLVER_CANONNAME); - return OK; -} - -class RequestParameters : public NetLog::EventParameters { - public: - RequestParameters(const HostResolver::RequestInfo& info, - const NetLog::Source& source) - : info_(info), source_(source) {} - - virtual Value* ToValue() const { - DictionaryValue* dict = new DictionaryValue(); - dict->SetString("hostname", info_.host_port_pair().ToString()); - dict->SetInteger("address_family", - static_cast<int>(info_.address_family())); - dict->SetBoolean("allow_cached_response", info_.allow_cached_response()); - dict->SetBoolean("only_use_cached_response", - info_.only_use_cached_response()); - dict->SetBoolean("is_speculative", info_.is_speculative()); - dict->SetInteger("priority", info_.priority()); - - if (source_.is_valid()) - dict->Set("source_dependency", source_.ToValue()); - - return dict; - } - - private: - const HostResolver::RequestInfo info_; - const NetLog::Source source_; -}; - -} // namespace - -HostResolver* CreateAsyncHostResolver(size_t max_concurrent_resolves, - const IPAddressNumber& dns_ip, - NetLog* net_log) { - size_t max_transactions = max_concurrent_resolves; - if (max_transactions == 0) - max_transactions = 20; - size_t max_pending_requests = max_transactions * 100; - HostResolver* resolver = new AsyncHostResolver( - IPEndPoint(dns_ip, 53), - max_transactions, - max_pending_requests, - base::Bind(&base::RandInt), - HostCache::CreateDefaultCache(), - NULL, - net_log); - return resolver; -} - -//----------------------------------------------------------------------------- -class AsyncHostResolver::Request { - public: - Request(const BoundNetLog& source_net_log, - const BoundNetLog& request_net_log, - int id, - const HostResolver::RequestInfo& info, - const Key& key, - CompletionCallback* callback, - AddressList* addresses) - : source_net_log_(source_net_log), - request_net_log_(request_net_log), - id_(id), - info_(info), - key_(key), - callback_(callback), - addresses_(addresses) { - DCHECK(addresses_); - } - - int id() const { return id_; } - const HostResolver::RequestInfo& info() const { return info_; } - const Key& key() const { return key_; } - RequestPriority priority() const { return info_.priority(); } - const BoundNetLog& source_net_log() const { return source_net_log_; } - const BoundNetLog& request_net_log() const { return request_net_log_; } - void set_addresses(const AddressList& addresses) { *addresses_ = addresses; } - - void OnComplete(int result, const IPAddressList& ip_addresses) { - DCHECK(callback_); - if (result == OK) - *addresses_ = - AddressList::CreateFromIPAddressList(ip_addresses, info_.port()); - callback_->Run(result); - } - - private: - BoundNetLog source_net_log_; - BoundNetLog request_net_log_; - const int id_; - const HostResolver::RequestInfo info_; - const Key key_; - CompletionCallback* callback_; - AddressList* addresses_; -}; - -//----------------------------------------------------------------------------- -AsyncHostResolver::AsyncHostResolver(const IPEndPoint& dns_server, - size_t max_transactions, - size_t max_pending_requests, - const RandIntCallback& rand_int_cb, - HostCache* cache, - ClientSocketFactory* factory, - NetLog* net_log) - : max_transactions_(max_transactions), - max_pending_requests_(max_pending_requests), - dns_server_(dns_server), - rand_int_cb_(rand_int_cb), - cache_(cache), - factory_(factory), - next_request_id_(0), - net_log_(net_log) { -} - -AsyncHostResolver::~AsyncHostResolver() { - // Destroy request lists. - for (KeyRequestListMap::iterator it = requestlist_map_.begin(); - it != requestlist_map_.end(); ++it) - STLDeleteElements(&it->second); - - // Destroy transactions. - STLDeleteElements(&transactions_); - - // Destroy pending requests. - for (size_t i = 0; i < arraysize(pending_requests_); ++i) - STLDeleteElements(&pending_requests_[i]); -} - -int AsyncHostResolver::Resolve(const RequestInfo& info, - AddressList* addresses, - CompletionCallback* callback, - RequestHandle* out_req, - const BoundNetLog& source_net_log) { - DCHECK(addresses); - IPAddressNumber ip_number; - std::string dns_name; - int rv = ERR_UNEXPECTED; - if (info.hostname().empty()) - rv = ERR_NAME_NOT_RESOLVED; - else if (ParseIPLiteralToNumber(info.hostname(), &ip_number)) - rv = ResolveAsIp(info, ip_number, addresses); - else if (!DNSDomainFromDot(info.hostname(), &dns_name)) - rv = ERR_NAME_NOT_RESOLVED; - - Request* request = CreateNewRequest( - info, dns_name, callback, addresses, source_net_log); - - OnStart(request); - if (rv == ERR_UNEXPECTED) { - if (ServeFromCache(request)) - rv = OK; - else if (info.only_use_cached_response()) - rv = ERR_NAME_NOT_RESOLVED; - } - - if (rv != ERR_UNEXPECTED) { - OnFinish(request, rv); - delete request; - return rv; // Synchronous resolution ends here. - } - - if (out_req) - *out_req = reinterpret_cast<RequestHandle>(request); - if (AttachToRequestList(request)) - return ERR_IO_PENDING; - if (transactions_.size() < max_transactions_) - return StartNewTransactionFor(request); - return Enqueue(request); -} - -void AsyncHostResolver::OnStart(Request* request) { - DCHECK(request); - - request->source_net_log().BeginEvent( - NetLog::TYPE_ASYNC_HOST_RESOLVER, - make_scoped_refptr(new NetLogSourceParameter( - "source_dependency", request->request_net_log().source()))); - - request->request_net_log().BeginEvent( - NetLog::TYPE_ASYNC_HOST_RESOLVER_REQUEST, - make_scoped_refptr(new RequestParameters( - request->info(), request->source_net_log().source()))); - - FOR_EACH_OBSERVER( - HostResolver::Observer, observers_, - OnStartResolution(request->id(), request->info())); -} - -void AsyncHostResolver::OnFinish(Request* request, int result) { - DCHECK(request); - bool was_resolved = result == OK; - - FOR_EACH_OBSERVER( - HostResolver::Observer, observers_, - OnFinishResolutionWithStatus( - request->id(), was_resolved, request->info())); - - request->request_net_log().EndEventWithNetErrorCode( - NetLog::TYPE_ASYNC_HOST_RESOLVER_REQUEST, result); - request->source_net_log().EndEvent( - NetLog::TYPE_ASYNC_HOST_RESOLVER, NULL); -} - -void AsyncHostResolver::OnCancel(Request* request) { - DCHECK(request); - - FOR_EACH_OBSERVER( - HostResolver::Observer, observers_, - OnCancelResolution(request->id(), request->info())); - - request->request_net_log().AddEvent( - NetLog::TYPE_CANCELLED, NULL); - request->request_net_log().EndEvent( - NetLog::TYPE_ASYNC_HOST_RESOLVER_REQUEST, NULL); - request->source_net_log().EndEvent( - NetLog::TYPE_ASYNC_HOST_RESOLVER, NULL); -} - -void AsyncHostResolver::CancelRequest(RequestHandle req_handle) { - scoped_ptr<Request> request(reinterpret_cast<Request*>(req_handle)); - DCHECK(request.get()); - - KeyRequestListMap::iterator it = requestlist_map_.find(request->key()); - if (it != requestlist_map_.end()) - it->second.remove(request.get()); - else - pending_requests_[request->priority()].remove(request.get()); - - OnCancel(request.get()); -} - -void AsyncHostResolver::AddObserver(HostResolver::Observer* observer) { - observers_.AddObserver(observer); -} - -void AsyncHostResolver::RemoveObserver(HostResolver::Observer* observer) { - observers_.RemoveObserver(observer); -} - -void AsyncHostResolver::SetDefaultAddressFamily( - AddressFamily address_family) { - NOTIMPLEMENTED(); -} - -AddressFamily AsyncHostResolver::GetDefaultAddressFamily() const { - return ADDRESS_FAMILY_IPV4; -} - -HostResolverImpl* AsyncHostResolver::GetAsHostResolverImpl() { - return NULL; -} - -void AsyncHostResolver::OnTransactionComplete( - int result, - const DnsTransaction* transaction, - const IPAddressList& ip_addresses) { - DCHECK(std::find(transactions_.begin(), transactions_.end(), transaction) - != transactions_.end()); - DCHECK(requestlist_map_.find(transaction->key()) != requestlist_map_.end()); - - // Run callback of every request that was depending on this transaction, - // also notify observers. - RequestList& requests = requestlist_map_[transaction->key()]; - for (RequestList::iterator it = requests.begin(); it != requests.end(); - ++it) { - Request* request = *it; - OnFinish(request, result); - request->OnComplete(result, ip_addresses); - } - - // It is possible that the requests that caused |transaction| to be - // created are cancelled by the time |transaction| completes. In that - // case |requests| would be empty. We are knowingly throwing away the - // result of a DNS resolution in that case, because (a) if there are no - // requests, we do not have info to obtain a key from, (b) DnsTransaction - // does not have info(), adding one into it just temporarily doesn't make - // sense, since HostCache will be replaced with RR cache soon, (c) - // recreating info from DnsTransaction::Key adds a lot of temporary - // code/functions (like converting back from qtype to AddressFamily.) - // Also, we only cache positive results. All of this will change when RR - // cache is added. - if (result == OK && cache_.get() && !requests.empty()) { - Request* request = requests.front(); - HostResolver::RequestInfo info = request->info(); - HostCache::Key key( - info.hostname(), info.address_family(), info.host_resolver_flags()); - AddressList addrlist = - AddressList::CreateFromIPAddressList(ip_addresses, info.port()); - cache_->Set(key, result, addrlist, base::TimeTicks::Now()); - } - - // Cleanup requests. - STLDeleteElements(&requests); - requestlist_map_.erase(transaction->key()); - - // Cleanup transaction and start a new one if there are pending requests. - delete transaction; - transactions_.remove(transaction); - ProcessPending(); -} - -bool AsyncHostResolver::ServeFromCache(Request* request) const { - // Sanity check -- it shouldn't be the case that allow_cached_response is - // false while only_use_cached_response is true. - DCHECK(request->info().allow_cached_response() || - !request->info().only_use_cached_response()); - - if (!cache_.get() || !request->info().allow_cached_response()) - return false; - - HostResolver::RequestInfo info = request->info(); - HostCache::Key key(info.hostname(), info.address_family(), - info.host_resolver_flags()); - const HostCache::Entry* cache_entry = cache_->Lookup( - key, base::TimeTicks::Now()); - if (cache_entry) { - request->request_net_log().AddEvent( - NetLog::TYPE_ASYNC_HOST_RESOLVER_CACHE_HIT, NULL); - DCHECK_EQ(OK, cache_entry->error); - request->set_addresses( - CreateAddressListUsingPort(cache_entry->addrlist, info.port())); - return true; - } - return false; -} - -AsyncHostResolver::Request* AsyncHostResolver::CreateNewRequest( - const RequestInfo& info, - const std::string& dns_name, - CompletionCallback* callback, - AddressList* addresses, - const BoundNetLog& source_net_log) { - - uint16 query_type = QueryTypeFromAddressFamily(info.address_family()); - Key key(dns_name, query_type); - - BoundNetLog request_net_log = BoundNetLog::Make(net_log_, - NetLog::SOURCE_ASYNC_HOST_RESOLVER_REQUEST); - - int id = next_request_id_++; - return new Request( - source_net_log, request_net_log, id, info, key, callback, addresses); -} - -bool AsyncHostResolver::AttachToRequestList(Request* request) { - KeyRequestListMap::iterator it = requestlist_map_.find(request->key()); - if (it == requestlist_map_.end()) - return false; - it->second.push_back(request); - return true; -} - -int AsyncHostResolver::StartNewTransactionFor(Request* request) { - DCHECK(requestlist_map_.find(request->key()) == requestlist_map_.end()); - DCHECK(transactions_.size() < max_transactions_); - - request->request_net_log().AddEvent( - NetLog::TYPE_ASYNC_HOST_RESOLVER_CREATE_DNS_TRANSACTION, NULL); - - requestlist_map_[request->key()].push_back(request); - DnsTransaction* transaction = new DnsTransaction( - dns_server_, - request->key().first, - request->key().second, - rand_int_cb_, - factory_, - request->request_net_log(), - net_log_); - transaction->SetDelegate(this); - transactions_.push_back(transaction); - return transaction->Start(); -} - -int AsyncHostResolver::Enqueue(Request* request) { - scoped_ptr<Request> evicted_request(Insert(request)); - if (evicted_request != NULL) { - int rv = ERR_HOST_RESOLVER_QUEUE_TOO_LARGE; - if (evicted_request.get() == request) - return rv; - evicted_request->OnComplete(rv, IPAddressList()); - } - return ERR_IO_PENDING; -} - -AsyncHostResolver::Request* AsyncHostResolver::Insert(Request* request) { - pending_requests_[request->priority()].push_back(request); - if (GetNumPending() > max_pending_requests_) { - Request* req = RemoveLowest(); - DCHECK(req); - return req; - } - return NULL; -} - -size_t AsyncHostResolver::GetNumPending() const { - size_t num_pending = 0; - for (size_t i = 0; i < arraysize(pending_requests_); ++i) - num_pending += pending_requests_[i].size(); - return num_pending; -} - -AsyncHostResolver::Request* AsyncHostResolver::RemoveLowest() { - for (int i = static_cast<int>(arraysize(pending_requests_)) - 1; - i >= 0; --i) { - RequestList& requests = pending_requests_[i]; - if (!requests.empty()) { - Request* request = requests.front(); - requests.pop_front(); - return request; - } - } - return NULL; -} - -AsyncHostResolver::Request* AsyncHostResolver::RemoveHighest() { - for (size_t i = 0; i < arraysize(pending_requests_) - 1; ++i) { - RequestList& requests = pending_requests_[i]; - if (!requests.empty()) { - Request* request = requests.front(); - requests.pop_front(); - return request; - } - } - return NULL; -} - -void AsyncHostResolver::ProcessPending() { - Request* request = RemoveHighest(); - if (!request) - return; - for (size_t i = 0; i < arraysize(pending_requests_); ++i) { - RequestList& requests = pending_requests_[i]; - RequestList::iterator it = requests.begin(); - while (it != requests.end()) { - if (request->key() == (*it)->key()) { - requestlist_map_[request->key()].push_back(*it); - it = requests.erase(it); - } else { - ++it; - } - } - } - StartNewTransactionFor(request); -} - -} // namespace net diff --git a/net/base/async_host_resolver.h b/net/base/async_host_resolver.h deleted file mode 100644 index c14e700..0000000 --- a/net/base/async_host_resolver.h +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_BASE_ASYNC_HOST_RESOLVER_H_ -#define NET_BASE_ASYNC_HOST_RESOLVER_H_ -#pragma once - -#include <list> -#include <map> -#include <vector> - -#include "base/observer_list.h" -#include "base/threading/non_thread_safe.h" -#include "net/base/address_family.h" -#include "net/base/dns_transaction.h" -#include "net/base/host_cache.h" -#include "net/base/host_resolver.h" -#include "net/base/ip_endpoint.h" -#include "net/base/net_log.h" -#include "net/base/rand_callback.h" - -namespace net { - -class AddressesList; -class ClientSocketFactory; - -class NET_API AsyncHostResolver - : public HostResolver, - public DnsTransaction::Delegate, - NON_EXPORTED_BASE(public base::NonThreadSafe) { - public: - AsyncHostResolver(const IPEndPoint& dns_server, - size_t max_transactions, - size_t max_pending_requests_, - const RandIntCallback& rand_int, - HostCache* cache, - ClientSocketFactory* factory, - NetLog* net_log); - virtual ~AsyncHostResolver(); - - // HostResolver interface - virtual int Resolve(const RequestInfo& info, - AddressList* addresses, - CompletionCallback* callback, - RequestHandle* out_req, - const BoundNetLog& source_net_log) OVERRIDE; - virtual void CancelRequest(RequestHandle req_handle) OVERRIDE; - virtual void AddObserver(HostResolver::Observer* observer) OVERRIDE; - virtual void RemoveObserver(HostResolver::Observer* observer) OVERRIDE; - virtual void SetDefaultAddressFamily(AddressFamily address_family) OVERRIDE; - virtual AddressFamily GetDefaultAddressFamily() const OVERRIDE; - virtual HostResolverImpl* GetAsHostResolverImpl() OVERRIDE; - - // DnsTransaction::Delegate interface - virtual void OnTransactionComplete( - int result, - const DnsTransaction* transaction, - const IPAddressList& ip_addresses) OVERRIDE; - - private: - FRIEND_TEST_ALL_PREFIXES(AsyncHostResolverTest, QueuedLookup); - FRIEND_TEST_ALL_PREFIXES(AsyncHostResolverTest, CancelPendingLookup); - FRIEND_TEST_ALL_PREFIXES(AsyncHostResolverTest, - ResolverDestructionCancelsLookups); - FRIEND_TEST_ALL_PREFIXES(AsyncHostResolverTest, - OverflowQueueWithLowPriorityLookup); - FRIEND_TEST_ALL_PREFIXES(AsyncHostResolverTest, - OverflowQueueWithHighPriorityLookup); - - class Request; - - typedef DnsTransaction::Key Key; - typedef std::list<Request*> RequestList; - typedef std::list<const DnsTransaction*> TransactionList; - typedef std::map<Key, RequestList> KeyRequestListMap; - - // Create a new request for the incoming Resolve() call. - Request* CreateNewRequest(const RequestInfo& info, - const std::string& dns_name, - CompletionCallback* callback, - AddressList* addresses, - const BoundNetLog& source_net_log); - - // Called when a request has just been started. - void OnStart(Request* request); - - // Called when a request has just completed (before its callback is run). - void OnFinish(Request* request, int result); - - // Called when a request has been cancelled. - void OnCancel(Request* request); - - // Tries to serve request from cache. - bool ServeFromCache(Request* request) const; - - // If there is an in-progress transaction for Request->key(), this will - // attach |request| to the respective list. - bool AttachToRequestList(Request* request); - - // Will start a new transaction for |request|, will insert a new key in - // |requestlist_map_| and append |request| to the respective list. - int StartNewTransactionFor(Request* request); - - // Will enqueue |request| in |pending_requests_|. - int Enqueue(Request* request); - - // A helper used by Enqueue to insert |request| into |pending_requests_|. - Request* Insert(Request* request); - - // Returns the number of pending requests. - size_t GetNumPending() const; - - // Removes and returns a pointer to the lowest/highest priority request - // from |pending_requests_|. - Request* RemoveLowest(); - Request* RemoveHighest(); - - // Once a transaction has completed, called to start a new transaction if - // there are pending requests. - void ProcessPending(); - - // Maximum number of concurrent transactions. - size_t max_transactions_; - - // List of current transactions. - TransactionList transactions_; - - // A map from Key to a list of requests waiting for the Key to resolve. - KeyRequestListMap requestlist_map_; - - // Maximum number of pending requests. - size_t max_pending_requests_; - - // Queues based on priority for putting pending requests. - RequestList pending_requests_[NUM_PRIORITIES]; - - // DNS server to which queries will be setn. - IPEndPoint dns_server_; - - // Callback to be passed to DnsTransaction for generating DNS query ids. - RandIntCallback rand_int_cb_; - - // Cache of host resolution results. - scoped_ptr<HostCache> cache_; - - // Also passed to DnsTransaction; it's a dependency injection to aid - // testing, outside of unit tests, its value is always NULL. - ClientSocketFactory* factory_; - - // The observers to notify when a request starts/ends. - ObserverList<HostResolver::Observer> observers_; - - // Monotonically increasing ID number to assign to the next request. - // Observers are the only consumers of this ID number. - int next_request_id_; - - NetLog* net_log_; - - DISALLOW_COPY_AND_ASSIGN(AsyncHostResolver); -}; - -} // namespace net - -#endif // NET_BASE_ASYNC_HOST_RESOLVER_H_ diff --git a/net/base/async_host_resolver_unittest.cc b/net/base/async_host_resolver_unittest.cc deleted file mode 100644 index 8f1a396..0000000 --- a/net/base/async_host_resolver_unittest.cc +++ /dev/null @@ -1,590 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/base/async_host_resolver.h" - -#include "base/bind.h" -#include "base/scoped_ptr.h" -#include "net/base/dns_test_util.h" -#include "net/base/host_cache.h" -#include "net/base/net_log.h" -#include "net/base/rand_callback.h" -#include "net/base/sys_addrinfo.h" -#include "net/socket/socket_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { - -namespace { - -void VerifyAddressList(const std::vector<const char*>& ip_addresses, - int port, - const AddressList& addrlist) { - ASSERT_LT(0u, ip_addresses.size()); - ASSERT_NE(static_cast<addrinfo*>(NULL), addrlist.head()); - - IPAddressNumber ip_number; - const struct addrinfo* ainfo = addrlist.head(); - for (std::vector<const char*>::const_iterator i = ip_addresses.begin(); - i != ip_addresses.end(); ++i, ainfo = ainfo->ai_next) { - ASSERT_NE(static_cast<addrinfo*>(NULL), ainfo); - EXPECT_EQ(sizeof(struct sockaddr_in), ainfo->ai_addrlen); - - const struct sockaddr* sa = ainfo->ai_addr; - const struct sockaddr_in* sa_in = (const struct sockaddr_in*) sa; - EXPECT_TRUE(htons(port) == sa_in->sin_port); - EXPECT_STREQ(*i, NetAddressToString(sa, ainfo->ai_addrlen).c_str()); - } - ASSERT_EQ(static_cast<addrinfo*>(NULL), ainfo); -} - -} // namespace - -static const int kPortNum = 80; -static const size_t kMaxTransactions = 2; -static const size_t kMaxPendingRequests = 1; -static int transaction_ids[] = {0, 1, 2, 3}; - -// The following fixture sets up an environment for four different lookups -// with their data defined in dns_test_util.h. All tests make use of these -// predefined variables instead of each defining their own, to avoid -// boilerplate code in every test. Assuming every coming query is for a -// distinct hostname, as |kMaxTransactions| is set to 2 and -// |kMaxPendingRequests| is set to 1, first two queries start immediately -// and the next one is sent to pending queue; as a result, the next query -// should either fail itself or cause the pending query to fail depending -// on its priority. -class AsyncHostResolverTest : public testing::Test { - public: - AsyncHostResolverTest() - : info0_(HostPortPair(kT0HostName, kPortNum)), - info1_(HostPortPair(kT1HostName, kPortNum)), - info2_(HostPortPair(kT2HostName, kPortNum)), - info3_(HostPortPair(kT3HostName, kPortNum)), - ip_addresses0_(kT0IpAddresses, - kT0IpAddresses + arraysize(kT0IpAddresses)), - ip_addresses1_(kT1IpAddresses, - kT1IpAddresses + arraysize(kT1IpAddresses)), - ip_addresses2_(kT2IpAddresses, - kT2IpAddresses + arraysize(kT2IpAddresses)), - ip_addresses3_(kT3IpAddresses, - kT3IpAddresses + arraysize(kT3IpAddresses)), - test_prng_(std::deque<int>( - transaction_ids, transaction_ids + arraysize(transaction_ids))) { - rand_int_cb_ = base::Bind(&TestPrng::GetNext, - base::Unretained(&test_prng_)); - // AF_INET only for now. - info0_.set_address_family(ADDRESS_FAMILY_IPV4); - info1_.set_address_family(ADDRESS_FAMILY_IPV4); - info2_.set_address_family(ADDRESS_FAMILY_IPV4); - info3_.set_address_family(ADDRESS_FAMILY_IPV4); - - // Setup socket read/writes for transaction 0. - writes0_.push_back( - MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), - arraysize(kT0QueryDatagram))); - reads0_.push_back( - MockRead(true, reinterpret_cast<const char*>(kT0ResponseDatagram), - arraysize(kT0ResponseDatagram))); - data0_.reset(new StaticSocketDataProvider(&reads0_[0], reads0_.size(), - &writes0_[0], writes0_.size())); - - // Setup socket read/writes for transaction 1. - writes1_.push_back( - MockWrite(true, reinterpret_cast<const char*>(kT1QueryDatagram), - arraysize(kT1QueryDatagram))); - reads1_.push_back( - MockRead(true, reinterpret_cast<const char*>(kT1ResponseDatagram), - arraysize(kT1ResponseDatagram))); - data1_.reset(new StaticSocketDataProvider(&reads1_[0], reads1_.size(), - &writes1_[0], writes1_.size())); - - // Setup socket read/writes for transaction 2. - writes2_.push_back( - MockWrite(true, reinterpret_cast<const char*>(kT2QueryDatagram), - arraysize(kT2QueryDatagram))); - reads2_.push_back( - MockRead(true, reinterpret_cast<const char*>(kT2ResponseDatagram), - arraysize(kT2ResponseDatagram))); - data2_.reset(new StaticSocketDataProvider(&reads2_[0], reads2_.size(), - &writes2_[0], writes2_.size())); - - // Setup socket read/writes for transaction 3. - writes3_.push_back( - MockWrite(true, reinterpret_cast<const char*>(kT3QueryDatagram), - arraysize(kT3QueryDatagram))); - reads3_.push_back( - MockRead(true, reinterpret_cast<const char*>(kT3ResponseDatagram), - arraysize(kT3ResponseDatagram))); - data3_.reset(new StaticSocketDataProvider(&reads3_[0], reads3_.size(), - &writes3_[0], writes3_.size())); - - factory_.AddSocketDataProvider(data0_.get()); - factory_.AddSocketDataProvider(data1_.get()); - factory_.AddSocketDataProvider(data2_.get()); - factory_.AddSocketDataProvider(data3_.get()); - - IPEndPoint dns_server; - bool rv0 = CreateDnsAddress(kDnsIp, kDnsPort, &dns_server); - DCHECK(rv0); - - resolver_.reset( - new AsyncHostResolver( - dns_server, kMaxTransactions, kMaxPendingRequests, rand_int_cb_, - HostCache::CreateDefaultCache(), &factory_, NULL)); - } - - protected: - AddressList addrlist0_, addrlist1_, addrlist2_, addrlist3_; - HostResolver::RequestInfo info0_, info1_, info2_, info3_; - std::vector<MockWrite> writes0_, writes1_, writes2_, writes3_; - std::vector<MockRead> reads0_, reads1_, reads2_, reads3_; - scoped_ptr<StaticSocketDataProvider> data0_, data1_, data2_, data3_; - std::vector<const char*> ip_addresses0_, ip_addresses1_, - ip_addresses2_, ip_addresses3_; - MockClientSocketFactory factory_; - TestPrng test_prng_; - RandIntCallback rand_int_cb_; - scoped_ptr<HostResolver> resolver_; - TestCompletionCallback callback0_, callback1_, callback2_, callback3_; -}; - -TEST_F(AsyncHostResolverTest, EmptyHostLookup) { - info0_.set_host_port_pair(HostPortPair("", kPortNum)); - int rv = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); -} - -TEST_F(AsyncHostResolverTest, IPv4LiteralLookup) { - const char* kIPLiteral = "192.168.1.2"; - info0_.set_host_port_pair(HostPortPair(kIPLiteral, kPortNum)); - info0_.set_host_resolver_flags(HOST_RESOLVER_CANONNAME); - int rv = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - EXPECT_EQ(OK, rv); - std::vector<const char*> ip_addresses(1, kIPLiteral); - VerifyAddressList(ip_addresses, kPortNum, addrlist0_); - EXPECT_STREQ(kIPLiteral, addrlist0_.head()->ai_canonname); -} - -TEST_F(AsyncHostResolverTest, IPv6LiteralLookup) { - info0_.set_host_port_pair(HostPortPair("2001:db8:0::42", kPortNum)); - int rv = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - // When support for IPv6 is added, this should succeed. - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); -} - -TEST_F(AsyncHostResolverTest, CachedLookup) { - info0_.set_only_use_cached_response(true); - int rv = resolver_->Resolve(info0_, &addrlist0_, NULL, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); - - // Cache the result of |info0_| lookup. - info0_.set_only_use_cached_response(false); - rv = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback0_.WaitForResult(); - EXPECT_EQ(OK, rv); - VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); - - // Now lookup |info0_| from cache only, store results in |addrlist1_|, - // should succeed synchronously. - info0_.set_only_use_cached_response(true); - rv = resolver_->Resolve(info0_, &addrlist1_, NULL, NULL, - BoundNetLog()); - EXPECT_EQ(OK, rv); - VerifyAddressList(ip_addresses0_, kPortNum, addrlist1_); -} - -TEST_F(AsyncHostResolverTest, InvalidHostNameLookup) { - const std::string kHostName1(64, 'a'); - info0_.set_host_port_pair(HostPortPair(kHostName1, kPortNum)); - int rv = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); - - const std::string kHostName2(4097, 'b'); - info0_.set_host_port_pair(HostPortPair(kHostName2, kPortNum)); - rv = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); -} - -TEST_F(AsyncHostResolverTest, Lookup) { - int rv = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback0_.WaitForResult(); - EXPECT_EQ(OK, rv); - VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); -} - -TEST_F(AsyncHostResolverTest, ConcurrentLookup) { - int rv0 = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - int rv1 = resolver_->Resolve(info1_, &addrlist1_, &callback1_, NULL, - BoundNetLog()); - int rv2 = resolver_->Resolve(info2_, &addrlist2_, &callback2_, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv0); - EXPECT_EQ(ERR_IO_PENDING, rv1); - EXPECT_EQ(ERR_IO_PENDING, rv2); - - rv0 = callback0_.WaitForResult(); - EXPECT_EQ(OK, rv0); - VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); - - rv1 = callback1_.WaitForResult(); - EXPECT_EQ(OK, rv1); - VerifyAddressList(ip_addresses1_, kPortNum, addrlist1_); - - rv2 = callback2_.WaitForResult(); - EXPECT_EQ(OK, rv2); - VerifyAddressList(ip_addresses2_, kPortNum, addrlist2_); - - EXPECT_EQ(3u, factory_.udp_client_sockets().size()); -} - -TEST_F(AsyncHostResolverTest, SameHostLookupsConsumeSingleTransaction) { - // We pass the info0_ to all requests. - int rv0 = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - int rv1 = resolver_->Resolve(info0_, &addrlist1_, &callback1_, NULL, - BoundNetLog()); - int rv2 = resolver_->Resolve(info0_, &addrlist2_, &callback2_, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv0); - EXPECT_EQ(ERR_IO_PENDING, rv1); - EXPECT_EQ(ERR_IO_PENDING, rv2); - - rv0 = callback0_.WaitForResult(); - EXPECT_EQ(OK, rv0); - VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); - - rv1 = callback1_.WaitForResult(); - EXPECT_EQ(OK, rv1); - VerifyAddressList(ip_addresses0_, kPortNum, addrlist1_); - - rv2 = callback2_.WaitForResult(); - EXPECT_EQ(OK, rv2); - VerifyAddressList(ip_addresses0_, kPortNum, addrlist2_); - - // Although we have three lookups, a single UDP socket was used. - EXPECT_EQ(1u, factory_.udp_client_sockets().size()); -} - -TEST_F(AsyncHostResolverTest, CancelLookup) { - HostResolver::RequestHandle req0 = NULL, req2 = NULL; - int rv0 = resolver_->Resolve(info0_, &addrlist0_, &callback0_, &req0, - BoundNetLog()); - int rv1 = resolver_->Resolve(info1_, &addrlist1_, &callback1_, NULL, - BoundNetLog()); - int rv2 = resolver_->Resolve(info2_, &addrlist2_, &callback2_, &req2, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv0); - EXPECT_EQ(ERR_IO_PENDING, rv1); - EXPECT_EQ(ERR_IO_PENDING, rv2); - - resolver_->CancelRequest(req0); - resolver_->CancelRequest(req2); - - MessageLoop::current()->RunAllPending(); - - EXPECT_FALSE(callback0_.have_result()); - EXPECT_FALSE(callback2_.have_result()); - - rv1 = callback1_.WaitForResult(); - EXPECT_EQ(OK, rv1); - VerifyAddressList(ip_addresses1_, kPortNum, addrlist1_); -} - -// Tests the following scenario: start two resolutions for the same host, -// cancel one of them, make sure that the other one completes. -TEST_F(AsyncHostResolverTest, CancelSameHostLookup) { - HostResolver::RequestHandle req0 = NULL; - - // Pass the info0_ to both requests. - int rv0 = resolver_->Resolve(info0_, &addrlist0_, &callback0_, &req0, - BoundNetLog()); - int rv1 = resolver_->Resolve(info0_, &addrlist1_, &callback1_, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv0); - EXPECT_EQ(ERR_IO_PENDING, rv1); - - resolver_->CancelRequest(req0); - MessageLoop::current()->RunAllPending(); - EXPECT_FALSE(callback0_.have_result()); - - rv1 = callback1_.WaitForResult(); - EXPECT_EQ(OK, rv1); - VerifyAddressList(ip_addresses0_, kPortNum, addrlist1_); - - EXPECT_EQ(1u, factory_.udp_client_sockets().size()); -} - -// Test that a queued lookup completes. -TEST_F(AsyncHostResolverTest, QueuedLookup) { - // kMaxTransactions is 2, thus the following requests consume all - // available transactions. - int rv0 = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - int rv1 = resolver_->Resolve(info1_, &addrlist1_, &callback1_, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv0); - EXPECT_EQ(ERR_IO_PENDING, rv1); - - // The following request will end up in queue. - int rv2 = resolver_->Resolve(info2_, &addrlist2_, &callback2_, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv2); - EXPECT_EQ(1u, - static_cast<AsyncHostResolver*>(resolver_.get())->GetNumPending()); - - // Make sure all requests complete. - rv0 = callback0_.WaitForResult(); - EXPECT_EQ(OK, rv0); - VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); - - rv1 = callback1_.WaitForResult(); - EXPECT_EQ(OK, rv1); - VerifyAddressList(ip_addresses1_, kPortNum, addrlist1_); - - rv2 = callback2_.WaitForResult(); - EXPECT_EQ(OK, rv2); - VerifyAddressList(ip_addresses2_, kPortNum, addrlist2_); -} - -// Test that cancelling a queued lookup works. -TEST_F(AsyncHostResolverTest, CancelPendingLookup) { - // kMaxTransactions is 2, thus the following requests consume all - // available transactions. - int rv0 = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - int rv1 = resolver_->Resolve(info1_, &addrlist1_, &callback1_, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv0); - EXPECT_EQ(ERR_IO_PENDING, rv1); - - // The following request will end up in queue. - HostResolver::RequestHandle req2 = NULL; - int rv2 = resolver_->Resolve(info2_, &addrlist2_, &callback2_, &req2, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv2); - EXPECT_EQ(1u, - static_cast<AsyncHostResolver*>(resolver_.get())->GetNumPending()); - - resolver_->CancelRequest(req2); - - // Make sure first two requests complete while the cancelled one doesn't. - MessageLoop::current()->RunAllPending(); - EXPECT_FALSE(callback2_.have_result()); - - rv0 = callback0_.WaitForResult(); - EXPECT_EQ(OK, rv0); - VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); - - rv1 = callback1_.WaitForResult(); - EXPECT_EQ(OK, rv1); - VerifyAddressList(ip_addresses1_, kPortNum, addrlist1_); -} - -TEST_F(AsyncHostResolverTest, ResolverDestructionCancelsLookups) { - int rv0 = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - int rv1 = resolver_->Resolve(info1_, &addrlist1_, &callback1_, NULL, - BoundNetLog()); - // This one is queued. - int rv2 = resolver_->Resolve(info2_, &addrlist2_, &callback2_, NULL, - BoundNetLog()); - EXPECT_EQ(1u, - static_cast<AsyncHostResolver*>(resolver_.get())->GetNumPending()); - - EXPECT_EQ(ERR_IO_PENDING, rv0); - EXPECT_EQ(ERR_IO_PENDING, rv1); - EXPECT_EQ(ERR_IO_PENDING, rv2); - - resolver_.reset(); - - MessageLoop::current()->RunAllPending(); - - EXPECT_FALSE(callback0_.have_result()); - EXPECT_FALSE(callback1_.have_result()); - EXPECT_FALSE(callback2_.have_result()); -} - -// Test that when the number of pending lookups is at max, a new lookup -// with a priority lower than all of those in the queue fails. -TEST_F(AsyncHostResolverTest, OverflowQueueWithLowPriorityLookup) { - int rv0 = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - int rv1 = resolver_->Resolve(info1_, &addrlist1_, &callback1_, NULL, - BoundNetLog()); - // This one is queued and fills up the queue since its size is 1. - int rv2 = resolver_->Resolve(info2_, &addrlist2_, &callback2_, NULL, - BoundNetLog()); - EXPECT_EQ(1u, - static_cast<AsyncHostResolver*>(resolver_.get())->GetNumPending()); - - EXPECT_EQ(ERR_IO_PENDING, rv0); - EXPECT_EQ(ERR_IO_PENDING, rv1); - EXPECT_EQ(ERR_IO_PENDING, rv2); - - // This one fails. - info3_.set_priority(LOWEST); - int rv3 = resolver_->Resolve(info3_, &addrlist3_, &callback3_, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, rv3); - - MessageLoop::current()->RunAllPending(); - EXPECT_FALSE(callback3_.have_result()); -} - -// Test that when the number of pending lookups is at max, a new lookup -// with a priority higher than any of those in the queue succeeds and -// causes the lowest priority lookup in the queue to fail. -TEST_F(AsyncHostResolverTest, OverflowQueueWithHighPriorityLookup) { - int rv0 = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - int rv1 = resolver_->Resolve(info1_, &addrlist1_, &callback1_, NULL, - BoundNetLog()); - - // Next lookup is queued. Since this will be ejected from the queue and - // will not consume a socket from our factory, we are not passing it - // predefined members. - HostResolver::RequestInfo info(HostPortPair("cnn.com", 80)); - info.set_address_family(ADDRESS_FAMILY_IPV4); - AddressList addrlist_fail; - TestCompletionCallback callback_fail; - int rv_fail = resolver_->Resolve(info, &addrlist_fail, &callback_fail, NULL, - BoundNetLog()); - EXPECT_EQ(1u, - static_cast<AsyncHostResolver*>(resolver_.get())->GetNumPending()); - - EXPECT_EQ(ERR_IO_PENDING, rv0); - EXPECT_EQ(ERR_IO_PENDING, rv1); - EXPECT_EQ(ERR_IO_PENDING, rv_fail); - - // Lookup 2 causes the above to fail, but itself should succeed. - info2_.set_priority(HIGHEST); - int rv2 = resolver_->Resolve(info2_, &addrlist2_, &callback2_, NULL, - BoundNetLog()); - - rv0 = callback0_.WaitForResult(); - EXPECT_EQ(OK, rv0); - VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); - - rv1 = callback1_.WaitForResult(); - EXPECT_EQ(OK, rv1); - VerifyAddressList(ip_addresses1_, kPortNum, addrlist1_); - - rv_fail = callback_fail.WaitForResult(); - EXPECT_EQ(ERR_HOST_RESOLVER_QUEUE_TOO_LARGE, rv_fail); - EXPECT_EQ(static_cast<addrinfo*>(NULL), addrlist_fail.head()); - - rv2 = callback2_.WaitForResult(); - EXPECT_EQ(OK, rv2); - VerifyAddressList(ip_addresses2_, kPortNum, addrlist2_); -} - -// Test that registering, unregistering, and notifying of observers of -// resolution start, completion and cancellation (both due to CancelRequest -// and resolver destruction) work. -TEST_F(AsyncHostResolverTest, Observers) { - TestHostResolverObserver observer; - resolver_->AddObserver(&observer); - - int rv0 = resolver_->Resolve(info0_, &addrlist0_, &callback0_, NULL, - BoundNetLog()); - int rv1 = resolver_->Resolve(info1_, &addrlist1_, &callback1_, NULL, - BoundNetLog()); - // We will cancel this one. - HostResolver::RequestHandle req2 = NULL; - int rv2 = resolver_->Resolve(info2_, &addrlist2_, &callback2_, &req2, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv0); - EXPECT_EQ(ERR_IO_PENDING, rv1); - EXPECT_EQ(ERR_IO_PENDING, rv2); - - // Cancel lookup 2. - resolver_->CancelRequest(req2); - - // Lookup 0 and 1 should succeed. - rv0 = callback0_.WaitForResult(); - EXPECT_EQ(OK, rv0); - VerifyAddressList(ip_addresses0_, kPortNum, addrlist0_); - - rv1 = callback1_.WaitForResult(); - EXPECT_EQ(OK, rv1); - VerifyAddressList(ip_addresses1_, kPortNum, addrlist1_); - - // Next lookup should not have finished. - MessageLoop::current()->RunAllPending(); - EXPECT_FALSE(callback2_.have_result()); - - // Verify observer calls. - EXPECT_EQ(3u, observer.start_log.size()); - EXPECT_EQ(2u, observer.finish_log.size()); - EXPECT_EQ(1u, observer.cancel_log.size()); - - // Lookup 0 started and finished. - EXPECT_TRUE(observer.start_log[0] == - TestHostResolverObserver::StartOrCancelEntry(0, info0_)); - EXPECT_TRUE(observer.finish_log[0] == - TestHostResolverObserver::FinishEntry(0, true, info0_)); - - // Ditto for lookup 1. - EXPECT_TRUE(observer.start_log[1] == - TestHostResolverObserver::StartOrCancelEntry(1, info1_)); - EXPECT_TRUE(observer.finish_log[1] == - TestHostResolverObserver::FinishEntry(1, true, info1_)); - - // Lookup 2 was cancelled, hence, failed to finish. - EXPECT_TRUE(observer.start_log[2] == - TestHostResolverObserver::StartOrCancelEntry(2, info2_)); - EXPECT_TRUE(observer.cancel_log[0] == - TestHostResolverObserver::StartOrCancelEntry(2, info2_)); - - // Unregister observer. - resolver_->RemoveObserver(&observer); - - // We will do lookup 2 again but will not be cancel it this time. - rv2 = resolver_->Resolve(info2_, &addrlist2_, &callback2_, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv2); - - // Run lookup 2 to completion. - rv2 = callback2_.WaitForResult(); - EXPECT_EQ(OK, rv2); - VerifyAddressList(ip_addresses2_, kPortNum, addrlist2_); - - // Observer log should stay the same. - EXPECT_EQ(3u, observer.start_log.size()); - EXPECT_EQ(2u, observer.finish_log.size()); - EXPECT_EQ(1u, observer.cancel_log.size()); - - // Re-register observer. - resolver_->AddObserver(&observer); - - // Start lookup 3. - int rv3 = resolver_->Resolve(info3_, &addrlist3_, &callback3_, NULL, - BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv3); - - // Destroy the resolver and make sure that observer was notified of just - // the resolution start. - resolver_.reset(); - - EXPECT_EQ(4u, observer.start_log.size()); // Was incremented by 1. - EXPECT_EQ(2u, observer.finish_log.size()); - EXPECT_EQ(1u, observer.cancel_log.size()); - - EXPECT_TRUE(observer.start_log[3] == - TestHostResolverObserver::StartOrCancelEntry(4, info3_)); -} - -} // namespace net diff --git a/net/base/dns_query.cc b/net/base/dns_query.cc deleted file mode 100644 index 3c92e1d..0000000 --- a/net/base/dns_query.cc +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/base/dns_query.h" - -#include <limits> -#include <string> - -#include "base/rand_util.h" -#include "net/base/dns_util.h" - -namespace net { - -namespace { - -void PackUint16BE(char buf[2], uint16 v) { - buf[0] = v >> 8; - buf[1] = v & 0xff; -} - -uint16 UnpackUint16BE(char buf[2]) { - return static_cast<uint8>(buf[0]) << 8 | static_cast<uint8>(buf[1]); -} - -} // namespace - -// DNS query consists of a 12-byte header followed by a question section. -// For details, see RFC 1035 section 4.1.1. This header template sets RD -// bit, which directs the name server to pursue query recursively, and sets -// the QDCOUNT to 1, meaning the question section has a single entry. The -// first two bytes of the header form a 16-bit random query ID to be copied -// in the corresponding reply by the name server -- randomized during -// DnsQuery construction. -static const char kHeader[] = {0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -static const size_t kHeaderSize = arraysize(kHeader); - -DnsQuery::DnsQuery(const std::string& qname, - uint16 qtype, - const RandIntCallback& rand_int_cb) - : qname_size_(qname.size()), - rand_int_cb_(rand_int_cb) { - DCHECK(DnsResponseBuffer(reinterpret_cast<const uint8*>(qname.c_str()), - qname.size()).DNSName(NULL)); - DCHECK(qtype == kDNS_A || qtype == kDNS_AAAA); - - io_buffer_ = new IOBufferWithSize(kHeaderSize + question_size()); - - int byte_offset = 0; - char* buffer_head = io_buffer_->data(); - memcpy(&buffer_head[byte_offset], kHeader, kHeaderSize); - byte_offset += kHeaderSize; - memcpy(&buffer_head[byte_offset], &qname[0], qname_size_); - byte_offset += qname_size_; - PackUint16BE(&buffer_head[byte_offset], qtype); - byte_offset += sizeof(qtype); - PackUint16BE(&buffer_head[byte_offset], kClassIN); - RandomizeId(); -} - -DnsQuery::~DnsQuery() { -} - -uint16 DnsQuery::id() const { - return UnpackUint16BE(&io_buffer_->data()[0]); -} - -uint16 DnsQuery::qtype() const { - return UnpackUint16BE(&io_buffer_->data()[kHeaderSize + qname_size_]); -} - -DnsQuery* DnsQuery::CloneWithNewId() const { - return new DnsQuery(qname(), qtype(), rand_int_cb_); -} - -size_t DnsQuery::question_size() const { - return qname_size_ // QNAME - + sizeof(uint16) // QTYPE - + sizeof(uint16); // QCLASS -} - -const char* DnsQuery::question_data() const { - return &io_buffer_->data()[kHeaderSize]; -} - -const std::string DnsQuery::qname() const { - return std::string(question_data(), qname_size_); -} - -void DnsQuery::RandomizeId() { - PackUint16BE(&io_buffer_->data()[0], rand_int_cb_.Run( - std::numeric_limits<uint16>::min(), - std::numeric_limits<uint16>::max())); -} - -} // namespace net diff --git a/net/base/dns_query.h b/net/base/dns_query.h deleted file mode 100644 index ef1dae5..0000000 --- a/net/base/dns_query.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_BASE_DNS_QUERY_H_ -#define NET_BASE_DNS_QUERY_H_ -#pragma once - -#include <string> - -#include "net/base/io_buffer.h" -#include "net/base/net_api.h" -#include "net/base/net_util.h" -#include "net/base/rand_callback.h" - -namespace net { - -// Represents on-the-wire DNS query message as an object. -class NET_TEST DnsQuery { - public: - // Constructs a query message from |qname| which *MUST* be in a valid - // DNS name format, and |qtype| which must be either kDNS_A or kDNS_AAAA. - - // Every generated object has a random ID, hence two objects generated - // with the same set of constructor arguments are generally not equal; - // there is a 1/2^16 chance of them being equal due to size of |id_|. - DnsQuery(const std::string& qname, - uint16 qtype, - const RandIntCallback& rand_int_cb); - ~DnsQuery(); - - // Clones |this| verbatim, with ID field of the header regenerated. - DnsQuery* CloneWithNewId() const; - - // DnsQuery field accessors. - uint16 id() const; - uint16 qtype() const; - - // Returns the size of the Question section of the query. Used when - // matching the response. - size_t question_size() const; - - // Returns pointer to the Question section of the query. Used when - // matching the response. - const char* question_data() const; - - // IOBuffer accessor to be used for writing out the query. - IOBufferWithSize* io_buffer() const { return io_buffer_; } - - private: - const std::string qname() const; - - // Randomizes ID field of the query message. - void RandomizeId(); - - // Size of the DNS name (*NOT* hostname) we are trying to resolve; used - // to calculate offsets. - size_t qname_size_; - - // Contains query bytes to be consumed by higher level Write() call. - scoped_refptr<IOBufferWithSize> io_buffer_; - - // PRNG function for generating IDs. - RandIntCallback rand_int_cb_; - - DISALLOW_COPY_AND_ASSIGN(DnsQuery); -}; - -} // namespace net - -#endif // NET_BASE_DNS_QUERY_H_ diff --git a/net/base/dns_query_unittest.cc b/net/base/dns_query_unittest.cc deleted file mode 100644 index 796dcff..0000000 --- a/net/base/dns_query_unittest.cc +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/base/dns_query.h" - -#include "base/bind.h" -#include "base/rand_util.h" -#include "net/base/dns_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { - -// DNS query consists of a header followed by a question. Header format -// and question format are described below. For the meaning of specific -// fields, please see RFC 1035. - -// Header format. -// 1 1 1 1 1 1 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | ID | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// |QR| Opcode |AA|TC|RD|RA| Z | RCODE | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | QDCOUNT | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | ANCOUNT | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | NSCOUNT | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | ARCOUNT | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - -// Question format. -// 1 1 1 1 1 1 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | | -// / QNAME / -// / / -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | QTYPE | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | QCLASS | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - -TEST(DnsQueryTest, ConstructorTest) { - std::string kQname("\003www\006google\003com", 16); - DnsQuery q1(kQname, kDNS_A, base::Bind(&base::RandInt)); - EXPECT_EQ(kDNS_A, q1.qtype()); - - uint8 id_hi = q1.id() >> 8, id_lo = q1.id() & 0xff; - - // See the top of the file for the description of a DNS query. - const uint8 query_data[] = { - // Header - id_hi, id_lo, - 0x01, 0x00, // Flags -- set RD (recursion desired) bit. - 0x00, 0x01, // Set QDCOUNT (question count) to 1, all the - // rest are 0 for a query. - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - - // Question - 0x03, 0x77, 0x77, 0x77, // QNAME: www.google.com in DNS format. - 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x03, 0x63, 0x6f, 0x6d, 0x00, - - 0x00, 0x01, // QTYPE: A query. - 0x00, 0x01, // QCLASS: IN class. - }; - - int expected_size = arraysize(query_data); - EXPECT_EQ(expected_size, q1.io_buffer()->size()); - EXPECT_EQ(0, memcmp(q1.io_buffer()->data(), query_data, expected_size)); -} - -TEST(DnsQueryTest, CloneTest) { - std::string kQname("\003www\006google\003com", 16); - DnsQuery q1(kQname, kDNS_A, base::Bind(&base::RandInt)); - - scoped_ptr<DnsQuery> q2(q1.CloneWithNewId()); - EXPECT_EQ(q1.io_buffer()->size(), q2->io_buffer()->size()); - EXPECT_EQ(q1.qtype(), q2->qtype()); - EXPECT_EQ(q1.question_size(), q2->question_size()); - EXPECT_EQ(0, memcmp(q1.question_data(), q2->question_data(), - q1.question_size())); -} - -TEST(DnsQueryTest, RandomIdTest) { - std::string kQname("\003www\006google\003com", 16); - - // Since id fields are 16-bit values, we iterate to reduce the - // probability of collision, to avoid a flaky test. - bool ids_are_random = false; - for (int i = 0; i < 1000; ++i) { - DnsQuery q1(kQname, kDNS_A, base::Bind(&base::RandInt)); - DnsQuery q2(kQname, kDNS_A, base::Bind(&base::RandInt)); - scoped_ptr<DnsQuery> q3(q1.CloneWithNewId()); - ids_are_random = q1.id () != q2.id() && q1.id() != q3->id(); - if (ids_are_random) - break; - } - EXPECT_TRUE(ids_are_random); -} - -} // namespace net diff --git a/net/base/dns_response.cc b/net/base/dns_response.cc deleted file mode 100644 index f7d88e1..0000000 --- a/net/base/dns_response.cc +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/base/dns_response.h" - -#include "net/base/dns_util.h" -#include "net/base/net_errors.h" - -namespace net { - -// RFC 1035, section 4.2.1: Messages carried by UDP are restricted to 512 -// bytes (not counting the IP nor UDP headers). -static const int kMaxResponseSize = 512; - -DnsResponse::DnsResponse(DnsQuery* query) - : query_(query), - io_buffer_(new IOBufferWithSize(kMaxResponseSize + 1)) { - DCHECK(query_); -} - -DnsResponse::~DnsResponse() { -} - -int DnsResponse::Parse(int nbytes, IPAddressList* ip_addresses) { - // Response includes query, it should be at least that size. - if (nbytes < query_->io_buffer()->size() || nbytes > kMaxResponseSize) - return ERR_DNS_MALFORMED_RESPONSE; - - DnsResponseBuffer response(reinterpret_cast<uint8*>(io_buffer_->data()), - io_buffer_->size()); - uint16 id; - if (!response.U16(&id) || id != query_->id()) // Make sure IDs match. - return ERR_DNS_MALFORMED_RESPONSE; - - uint8 flags, rcode; - if (!response.U8(&flags) || !response.U8(&rcode)) - return ERR_DNS_MALFORMED_RESPONSE; - - if (flags & 2) // TC is set -- server wants TCP, we don't support it (yet?). - return ERR_DNS_SERVER_REQUIRES_TCP; - - rcode &= 0x0f; // 3 means NXDOMAIN, the rest means server failed. - if (rcode && (rcode != 3)) - return ERR_DNS_SERVER_FAILED; - - uint16 query_count, answer_count, authority_count, additional_count; - if (!response.U16(&query_count) || - !response.U16(&answer_count) || - !response.U16(&authority_count) || - !response.U16(&additional_count)) { - return ERR_DNS_MALFORMED_RESPONSE; - } - - if (query_count != 1) // Sent a single question, shouldn't have changed. - return ERR_DNS_MALFORMED_RESPONSE; - - base::StringPiece question; // Make sure question section is echoed back. - if (!response.Block(&question, query_->question_size()) || - memcmp(question.data(), query_->question_data(), - query_->question_size())) { - return ERR_DNS_MALFORMED_RESPONSE; - } - - if (answer_count < 1) - return ERR_NAME_NOT_RESOLVED; - - IPAddressList rdatas; - while (answer_count--) { - uint32 ttl; - uint16 rdlength, qtype, qclass; - if (!response.DNSName(NULL) || - !response.U16(&qtype) || - !response.U16(&qclass) || - !response.U32(&ttl) || - !response.U16(&rdlength)) { - return ERR_DNS_MALFORMED_RESPONSE; - } - if (qtype == query_->qtype() && - qclass == kClassIN && - (rdlength == kIPv4AddressSize || rdlength == kIPv6AddressSize)) { - base::StringPiece rdata; - if (!response.Block(&rdata, rdlength)) - return ERR_DNS_MALFORMED_RESPONSE; - rdatas.push_back(IPAddressNumber(rdata.begin(), rdata.end())); - } else if (!response.Skip(rdlength)) - return ERR_DNS_MALFORMED_RESPONSE; - } - - if (rdatas.empty()) - return ERR_NAME_NOT_RESOLVED; - - if (ip_addresses) - ip_addresses->swap(rdatas); - return OK; -} - -} // namespace net diff --git a/net/base/dns_response.h b/net/base/dns_response.h deleted file mode 100644 index d62f350..0000000 --- a/net/base/dns_response.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_BASE_DNS_RESPONSE_H_ -#define NET_BASE_DNS_RESPONSE_H_ -#pragma once - -#include "net/base/dns_query.h" -#include "net/base/net_api.h" - -namespace net{ - -// Represents on-the-wire DNS response as an object; allows extracting -// records. -class NET_TEST DnsResponse { - public: - // Constructs an object with an IOBuffer large enough to read - // one byte more than largest possible response, to detect malformed - // responses; |query| is a pointer to the DnsQuery for which |this| - // is supposed to be a response. - explicit DnsResponse(DnsQuery* query); - ~DnsResponse(); - - // Internal buffer accessor into which actual bytes of response will be - // read. - IOBufferWithSize* io_buffer() { return io_buffer_.get(); } - - // Parses response of size nbytes and puts address into |ip_addresses|, - // returns net_error code in case of failure. - int Parse(int nbytes, IPAddressList* ip_addresses); - - private: - // The matching query; |this| is the response for |query_|. We do not - // own it, lifetime of |this| should be within the limits of lifetime of - // |query_|. - const DnsQuery* const query_; - - // Buffer into which response bytes are read. - scoped_refptr<IOBufferWithSize> io_buffer_; - - DISALLOW_COPY_AND_ASSIGN(DnsResponse); -}; - -} // namespace net - -#endif // NET_BASE_DNS_RESPONSE_H_ diff --git a/net/base/dns_response_unittest.cc b/net/base/dns_response_unittest.cc deleted file mode 100644 index e7701b0..0000000 --- a/net/base/dns_response_unittest.cc +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/base/dns_response.h" - -#include "base/bind.h" -#include "base/rand_util.h" -#include "net/base/dns_util.h" -#include "net/base/net_errors.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { - -// DNS response consists of a header followed by a question followed by -// answer. Header format, question format and response format are -// described below. For the meaning of specific fields, please see RFC -// 1035. - -// Header format. -// 1 1 1 1 1 1 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | ID | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// |QR| Opcode |AA|TC|RD|RA| Z | RCODE | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | QDCOUNT | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | ANCOUNT | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | NSCOUNT | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | ARCOUNT | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - -// Question format. -// 1 1 1 1 1 1 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | | -// / QNAME / -// / / -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | QTYPE | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | QCLASS | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - -// Answser format. -// 1 1 1 1 1 1 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | | -// / / -// / NAME / -// | | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | TYPE | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | CLASS | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | TTL | -// | | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -// | RDLENGTH | -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| -// / RDATA / -// / / -// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - -// TODO(agayev): add more thorough tests. -TEST(DnsResponseTest, ResponseWithCnameA) { - const std::string kQname("\012codereview\010chromium\003org", 25); - DnsQuery q1(kQname, kDNS_A, base::Bind(&base::RandInt)); - - uint8 id_hi = q1.id() >> 8, id_lo = q1.id() & 0xff; - - uint8 ip[] = { // codereview.chromium.org resolves to - 0x4a, 0x7d, 0x5f, 0x79 // 74.125.95.121 - }; - - IPAddressList expected_ips; - expected_ips.push_back(IPAddressNumber(ip, ip + arraysize(ip))); - - uint8 response_data[] = { - // Header - id_hi, id_lo, // ID - 0x81, 0x80, // Standard query response, no error - 0x00, 0x01, // 1 question - 0x00, 0x02, // 2 RRs (answers) - 0x00, 0x00, // 0 authority RRs - 0x00, 0x00, // 0 additional RRs - - // Question - 0x0a, 0x63, 0x6f, 0x64, // This part is echoed back from the - 0x65, 0x72, 0x65, 0x76, // respective query. - 0x69, 0x65, 0x77, 0x08, - 0x63, 0x68, 0x72, 0x6f, - 0x6d, 0x69, 0x75, 0x6d, - 0x03, 0x6f, 0x72, 0x67, - 0x00, - 0x00, 0x01, - 0x00, 0x01, - - // Answer 1 - 0xc0, 0x0c, // NAME is a pointer to name in Question section. - 0x00, 0x05, // TYPE is CNAME. - 0x00, 0x01, // CLASS is IN. - 0x00, 0x01, // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds. - 0x24, 0x74, - 0x00, 0x12, // RDLENGTH is 18 bytse. - 0x03, 0x67, 0x68, 0x73, // ghs.l.google.com in DNS format. - 0x01, 0x6c, 0x06, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x03, 0x63, 0x6f, - 0x6d, 0x00, - - // Answer 2 - 0xc0, 0x35, // NAME is a pointer to name in Question section. - 0x00, 0x01, // TYPE is A. - 0x00, 0x01, // CLASS is IN. - 0x00, 0x00, // TTL (4 bytes) is 53 seconds. - 0x00, 0x35, - 0x00, 0x04, // RDLENGTH is 4 bytes. - ip[0], ip[1], ip[2], ip[3], // RDATA is the IP. - }; - - // Create a response object and simulate reading into it. - DnsResponse r1(&q1); - memcpy(r1.io_buffer()->data(), &response_data[0], - r1.io_buffer()->size()); - - // Verify resolved IPs. - int response_size = arraysize(response_data); - IPAddressList actual_ips; - EXPECT_EQ(OK, r1.Parse(response_size, &actual_ips)); - EXPECT_EQ(expected_ips, actual_ips); -} - -} // namespace net diff --git a/net/base/dns_test_util.h b/net/base/dns_test_util.h deleted file mode 100644 index 04d8652..0000000 --- a/net/base/dns_test_util.h +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_BASE_DNS_TEST_UTIL_H_ -#define NET_BASE_DNS_TEST_UTIL_H_ -#pragma once - -#include <deque> -#include <vector> - -#include "base/logging.h" -#include "net/base/dns_transaction.h" -#include "net/base/dns_util.h" -#include "net/base/host_resolver.h" -#include "net/base/ip_endpoint.h" -#include "net/base/net_util.h" - -namespace net { - -// DNS related classes make use of PRNG for various tasks. This class is -// used as a PRNG for unit testing those tasks. It takes a deque of -// integers |numbers| which should be returned by calls to GetNext. -class TestPrng { - public: - explicit TestPrng(const std::deque<int>& numbers); - ~TestPrng(); - - // Pops and returns the next number from |numbers_| deque. - int GetNext(int min, int max); - - private: - std::deque<int> numbers_; - - DISALLOW_COPY_AND_ASSIGN(TestPrng); -}; - -bool operator==(const HostResolver::RequestInfo& a, - const HostResolver::RequestInfo& b); - -// Observer that just makes note of how it was called. The test code can then -// inspect to make sure it was called with the right parameters. Used by -// HostResolverImpl and AsyncHostResolver unit tests. -class TestHostResolverObserver : public HostResolver::Observer { - public: - TestHostResolverObserver(); - virtual ~TestHostResolverObserver(); - - // HostResolver::Observer methods: - virtual void OnStartResolution(int id, const HostResolver::RequestInfo& info); - virtual void OnFinishResolutionWithStatus( - int id, - bool was_resolved, - const HostResolver::RequestInfo& info); - virtual void OnCancelResolution( - int id, - const HostResolver::RequestInfo& info); - - // Tuple (id, info). - struct StartOrCancelEntry { - StartOrCancelEntry(int id, const HostResolver::RequestInfo& info) - : id(id), info(info) {} - - bool operator==(const StartOrCancelEntry& other) const { - return id == other.id && info == other.info; - } - - int id; - HostResolver::RequestInfo info; - }; - - // Tuple (id, was_resolved, info). - struct FinishEntry { - FinishEntry(int id, bool was_resolved, - const HostResolver::RequestInfo& info) - : id(id), was_resolved(was_resolved), info(info) {} - - bool operator==(const FinishEntry& other) const { - return id == other.id && - was_resolved == other.was_resolved && - info == other.info; - } - - int id; - bool was_resolved; - HostResolver::RequestInfo info; - }; - - std::vector<StartOrCancelEntry> start_log; - std::vector<FinishEntry> finish_log; - std::vector<StartOrCancelEntry> cancel_log; -}; - -// A utility function for tests that given an array of IP literals, -// converts it to an IPAddressList. -bool ConvertStringsToIPAddressList( - const char* const ip_strings[], size_t size, IPAddressList* address_list); - -// A utility function for tests that creates an IPEndPoint whose IP is -// |ip_string| and whose port is |port| and stores it in |endpoint|. -bool CreateDnsAddress(const char* ip_string, uint16 port, IPEndPoint* endpoint); - -static const char kDnsIp[] = "192.168.1.1"; -static const uint16 kDnsPort = 53; - -//----------------------------------------------------------------------------- -// Query/response set for www.google.com, ID is fixed to 0. -static const char kT0HostName[] = "www.google.com"; -static const uint16 kT0Qtype = kDNS_A; -static const char kT0DnsName[] = { - 0x03, 'w', 'w', 'w', - 0x06, 'g', 'o', 'o', 'g', 'l', 'e', - 0x03, 'c', 'o', 'm', - 0x00 -}; -static const uint8 kT0QueryDatagram[] = { - // query for www.google.com, type A. - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77, - 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, - 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 -}; -static const uint8 kT0ResponseDatagram[] = { - // response contains one CNAME for www.l.google.com and the following - // IP addresses: 74.125.226.{179,180,176,177,178} - 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77, - 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, - 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, - 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, - 0x4d, 0x13, 0x00, 0x08, 0x03, 0x77, 0x77, 0x77, - 0x01, 0x6c, 0xc0, 0x10, 0xc0, 0x2c, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x04, - 0x4a, 0x7d, 0xe2, 0xb3, 0xc0, 0x2c, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x04, - 0x4a, 0x7d, 0xe2, 0xb4, 0xc0, 0x2c, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x04, - 0x4a, 0x7d, 0xe2, 0xb0, 0xc0, 0x2c, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x04, - 0x4a, 0x7d, 0xe2, 0xb1, 0xc0, 0x2c, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x04, - 0x4a, 0x7d, 0xe2, 0xb2 -}; -static const char* const kT0IpAddresses[] = { - "74.125.226.179", "74.125.226.180", "74.125.226.176", - "74.125.226.177", "74.125.226.178" -}; - -//----------------------------------------------------------------------------- -// Query/response set for codereview.chromium.org, ID is fixed to 1. -static const char kT1HostName[] = "codereview.chromium.org"; -static const uint16 kT1Qtype = kDNS_A; -static const char kT1DnsName[] = { - 0x12, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w', - 0x10, 'c', 'h', 'r', 'o', 'm', 'i', 'u', 'm', - 0x03, 'o', 'r', 'g', - 0x00 -}; -static const uint8 kT1QueryDatagram[] = { - // query for codereview.chromium.org, type A. - 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, 0x64, - 0x65, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x08, - 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, - 0x03, 0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, - 0x01 -}; -static const uint8 kT1ResponseDatagram[] = { - // response contains one CNAME for ghs.l.google.com and the following - // IP address: 64.233.169.121 - 0x00, 0x01, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, 0x64, - 0x65, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x08, - 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, - 0x03, 0x6f, 0x72, 0x67, 0x00, 0x00, 0x01, 0x00, - 0x01, 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, - 0x01, 0x41, 0x75, 0x00, 0x12, 0x03, 0x67, 0x68, - 0x73, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0xc0, - 0x35, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x0b, 0x00, 0x04, 0x40, 0xe9, 0xa9, 0x79 -}; -static const char* const kT1IpAddresses[] = { - "64.233.169.121" -}; - -//----------------------------------------------------------------------------- -// Query/response set for www.ccs.neu.edu, ID is fixed to 2. -static const char kT2HostName[] = "www.ccs.neu.edu"; -static const uint16 kT2Qtype = kDNS_A; -static const char kT2DnsName[] = { - 0x03, 'w', 'w', 'w', - 0x03, 'c', 'c', 'c', - 0x03, 'n', 'e', 'u', - 0x03, 'e', 'd', 'u', - 0x00 -}; -static const uint8 kT2QueryDatagram[] = { - // query for www.ccs.neu.edu, type A. - 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77, - 0x03, 0x63, 0x63, 0x73, 0x03, 0x6e, 0x65, 0x75, - 0x03, 0x65, 0x64, 0x75, 0x00, 0x00, 0x01, 0x00, - 0x01 -}; -static const uint8 kT2ResponseDatagram[] = { - // response contains one CNAME for vulcan.ccs.neu.edu and the following - // IP address: 129.10.116.81 - 0x00, 0x02, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77, - 0x03, 0x63, 0x63, 0x73, 0x03, 0x6e, 0x65, 0x75, - 0x03, 0x65, 0x64, 0x75, 0x00, 0x00, 0x01, 0x00, - 0x01, 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x2c, 0x00, 0x09, 0x06, 0x76, 0x75, - 0x6c, 0x63, 0x61, 0x6e, 0xc0, 0x10, 0xc0, 0x2d, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x2c, - 0x00, 0x04, 0x81, 0x0a, 0x74, 0x51 -}; -static const char* const kT2IpAddresses[] = { - "129.10.116.81" -}; - -//----------------------------------------------------------------------------- -// Query/response set for www.google.az, ID is fixed to 3. -static const char kT3HostName[] = "www.google.az"; -static const uint16 kT3Qtype = kDNS_A; -static const char kT3DnsName[] = { - 0x03, 'w', 'w', 'w', - 0x06, 'g', 'o', 'o', 'g', 'l', 'e', - 0x02, 'a', 'z', - 0x00 -}; -static const uint8 kT3QueryDatagram[] = { - // query for www.google.az, type A. - 0x00, 0x03, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77, - 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x02, - 0x61, 0x7a, 0x00, 0x00, 0x01, 0x00, 0x01 -}; -static const uint8 kT3ResponseDatagram[] = { - // response contains www.google.com as CNAME for www.google.az and - // www.l.google.com as CNAME for www.google.com and the following - // IP addresses: 74.125.226.{178,179,180,176,177} - 0x00, 0x03, 0x81, 0x80, 0x00, 0x01, 0x00, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77, - 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x02, - 0x61, 0x7a, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, - 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x50, - 0x99, 0x00, 0x10, 0x03, 0x77, 0x77, 0x77, 0x06, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, - 0x6f, 0x6d, 0x00, 0xc0, 0x2b, 0x00, 0x05, 0x00, - 0x01, 0x00, 0x01, 0x50, 0x99, 0x00, 0x08, 0x03, - 0x77, 0x77, 0x77, 0x01, 0x6c, 0xc0, 0x2f, 0xc0, - 0x47, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x04, 0x4a, 0x7d, 0xe2, 0xb2, 0xc0, - 0x47, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x04, 0x4a, 0x7d, 0xe2, 0xb3, 0xc0, - 0x47, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x04, 0x4a, 0x7d, 0xe2, 0xb4, 0xc0, - 0x47, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x04, 0x4a, 0x7d, 0xe2, 0xb0, 0xc0, - 0x47, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x04, 0x4a, 0x7d, 0xe2, 0xb1 -}; -static const char* const kT3IpAddresses[] = { - "74.125.226.178", "74.125.226.179", "74.125.226.180", - "74.125.226.176", "74.125.226.177" -}; - -} // namespace net - -#endif // NET_BASE_DNS_TEST_UTIL_H_ diff --git a/net/base/dns_transaction.cc b/net/base/dns_transaction.cc deleted file mode 100644 index 84f123f..0000000 --- a/net/base/dns_transaction.cc +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/base/dns_transaction.h" - -#include "base/bind.h" -#include "base/rand_util.h" -#include "base/values.h" -#include "net/base/completion_callback.h" -#include "net/base/dns_query.h" -#include "net/base/dns_response.h" -#include "net/base/dns_util.h" -#include "net/base/rand_callback.h" -#include "net/socket/client_socket_factory.h" -#include "net/udp/datagram_client_socket.h" - -namespace net { - -namespace { - -// Retry timeouts. -const int kTimeoutsMs[] = {3000, 5000, 11000}; -const int kMaxAttempts = arraysize(kTimeoutsMs); - -// Returns the string representation of an IPAddressNumber. -std::string IPAddressToString(const IPAddressNumber& ip_address) { - IPEndPoint ip_endpoint(ip_address, 0); - struct sockaddr_storage addr; - size_t addr_len = sizeof(addr); - struct sockaddr* sockaddr = reinterpret_cast<struct sockaddr*>(&addr); - if (!ip_endpoint.ToSockAddr(sockaddr, &addr_len)) - return ""; - return NetAddressToString(sockaddr, addr_len); -} - -} - -DnsTransaction::Delegate::Delegate() { -} - -DnsTransaction::Delegate::~Delegate() { - while (!registered_transactions_.empty()) { - DnsTransaction* transaction = *registered_transactions_.begin(); - transaction->SetDelegate(NULL); - } - DCHECK(registered_transactions_.empty()); -} - -void DnsTransaction::Delegate::OnTransactionComplete( - int result, - const DnsTransaction* transaction, - const IPAddressList& ip_addresses) { -} - -void DnsTransaction::Delegate::Attach(DnsTransaction* transaction) { - DCHECK(registered_transactions_.find(transaction) == - registered_transactions_.end()); - registered_transactions_.insert(transaction); -} - -void DnsTransaction::Delegate::Detach(DnsTransaction* transaction) { - DCHECK(registered_transactions_.find(transaction) != - registered_transactions_.end()); - registered_transactions_.erase(transaction); -} - -namespace { - -class DnsTransactionStartParameters : public NetLog::EventParameters { - public: - DnsTransactionStartParameters(const IPEndPoint& dns_server, - const DnsTransaction::Key& key, - const NetLog::Source& source) - : dns_server_(dns_server), key_(key), source_(source) {} - - virtual Value* ToValue() const { - std::string hostname; - DnsResponseBuffer( - reinterpret_cast<const uint8*>(key_.first.c_str()), key_.first.size()). - DNSName(&hostname); - - DictionaryValue* dict = new DictionaryValue(); - dict->SetString("dns_server", dns_server_.ToString()); - dict->SetString("hostname", hostname); - dict->SetInteger("query_type", key_.second); - dict->Set("source_dependency", source_.ToValue()); - return dict; - } - - private: - const IPEndPoint dns_server_; - const DnsTransaction::Key key_; - const NetLog::Source source_; -}; - -class DnsTransactionFinishParameters : public NetLog::EventParameters { - public: - DnsTransactionFinishParameters(int net_error, - const IPAddressList& ip_address_list) - : net_error_(net_error), ip_address_list_(ip_address_list) {} - - virtual Value* ToValue() const { - ListValue* list = new ListValue(); - for (IPAddressList::const_iterator it = ip_address_list_.begin(); - it != ip_address_list_.end(); ++it) - list->Append(Value::CreateStringValue(IPAddressToString(*it))); - - DictionaryValue* dict = new DictionaryValue(); - dict->SetInteger("net_error", net_error_); - dict->Set("address_list", list); - return dict; - } - - private: - const int net_error_; - const IPAddressList ip_address_list_; -}; - -class DnsTransactionRetryParameters : public NetLog::EventParameters { - public: - DnsTransactionRetryParameters(int attempt_number, - const NetLog::Source& source) - : attempt_number_(attempt_number), source_(source) {} - - virtual Value* ToValue() const { - DictionaryValue* dict = new DictionaryValue(); - dict->SetInteger("attempt_number", attempt_number_); - dict->Set("source_dependency", source_.ToValue()); - return dict; - } - - private: - const int attempt_number_; - const NetLog::Source source_; -}; - -} // namespace - -DnsTransaction::DnsTransaction(const IPEndPoint& dns_server, - const std::string& dns_name, - uint16 query_type, - const RandIntCallback& rand_int, - ClientSocketFactory* socket_factory, - const BoundNetLog& source_net_log, - NetLog* net_log) - : dns_server_(dns_server), - key_(dns_name, query_type), - delegate_(NULL), - query_(new DnsQuery(dns_name, query_type, rand_int)), - attempts_(0), - next_state_(STATE_NONE), - socket_factory_(socket_factory ? socket_factory : - ClientSocketFactory::GetDefaultFactory()), - ALLOW_THIS_IN_INITIALIZER_LIST( - io_callback_(this, &DnsTransaction::OnIOComplete)), - net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_DNS_TRANSACTION)) { - DCHECK(!rand_int.is_null()); - for (size_t i = 0; i < arraysize(kTimeoutsMs); ++i) - timeouts_ms_.push_back(base::TimeDelta::FromMilliseconds(kTimeoutsMs[i])); - net_log_.BeginEvent( - NetLog::TYPE_DNS_TRANSACTION, - make_scoped_refptr( - new DnsTransactionStartParameters(dns_server_, key_, - source_net_log.source()))); -} - -DnsTransaction::~DnsTransaction() { - SetDelegate(NULL); -} - -void DnsTransaction::SetDelegate(Delegate* delegate) { - if (delegate == delegate_) - return; - if (delegate_) - delegate_->Detach(this); - delegate_ = delegate; - if (delegate_) - delegate_->Attach(this); -} - -int DnsTransaction::Start() { - DCHECK_EQ(STATE_NONE, next_state_); - next_state_ = STATE_CONNECT; - return DoLoop(OK); -} - -int DnsTransaction::DoLoop(int result) { - DCHECK_NE(STATE_NONE, next_state_); - int rv = result; - do { - State state = next_state_; - next_state_ = STATE_NONE; - switch (state) { - case STATE_CONNECT: - rv = DoConnect(); - break; - case STATE_CONNECT_COMPLETE: - rv = DoConnectComplete(rv); - break; - case STATE_SEND_QUERY: - rv = DoSendQuery(); - break; - case STATE_SEND_QUERY_COMPLETE: - rv = DoSendQueryComplete(rv); - break; - case STATE_READ_RESPONSE: - rv = DoReadResponse(); - break; - case STATE_READ_RESPONSE_COMPLETE: - rv = DoReadResponseComplete(rv); - break; - default: - NOTREACHED(); - break; - } - } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); - - return rv; -} - -void DnsTransaction::DoCallback(int result) { - DCHECK_NE(result, ERR_IO_PENDING); - net_log_.EndEvent( - NetLog::TYPE_DNS_TRANSACTION, - make_scoped_refptr( - new DnsTransactionFinishParameters(result, ip_addresses_))); - if (delegate_) - delegate_->OnTransactionComplete(result, this, ip_addresses_); -} - -void DnsTransaction::OnIOComplete(int result) { - int rv = DoLoop(result); - if (rv != ERR_IO_PENDING) - DoCallback(rv); -} - -int DnsTransaction::DoConnect() { - next_state_ = STATE_CONNECT_COMPLETE; - - DCHECK_LT(attempts_, timeouts_ms_.size()); - StartTimer(timeouts_ms_[attempts_]); - attempts_++; - - // TODO(agayev): keep all sockets around in case the server responds - // after its timeout; state machine will need to change to handle that. - socket_.reset(socket_factory_->CreateDatagramClientSocket( - DatagramSocket::RANDOM_BIND, - base::Bind(&base::RandInt), - NULL, - net_log_.source())); - - net_log_.AddEvent( - NetLog::TYPE_DNS_TRANSACTION_ATTEMPT_STARTED, - make_scoped_refptr( - new DnsTransactionRetryParameters(attempts_, - socket_->NetLog().source()))); - - return socket_->Connect(dns_server_); -} - -int DnsTransaction::DoConnectComplete(int rv) { - if (rv < 0) - return rv; - next_state_ = STATE_SEND_QUERY; - return OK; -} - -int DnsTransaction::DoSendQuery() { - next_state_ = STATE_SEND_QUERY_COMPLETE; - return socket_->Write(query_->io_buffer(), - query_->io_buffer()->size(), - &io_callback_); -} - -int DnsTransaction::DoSendQueryComplete(int rv) { - if (rv < 0) - return rv; - - // Writing to UDP should not result in a partial datagram. - if (rv != query_->io_buffer()->size()) - return ERR_NAME_NOT_RESOLVED; - - next_state_ = STATE_READ_RESPONSE; - return OK; -} - -int DnsTransaction::DoReadResponse() { - next_state_ = STATE_READ_RESPONSE_COMPLETE; - response_.reset(new DnsResponse(query_.get())); - return socket_->Read(response_->io_buffer(), - response_->io_buffer()->size(), - &io_callback_); -} - -int DnsTransaction::DoReadResponseComplete(int rv) { - DCHECK_NE(ERR_IO_PENDING, rv); - RevokeTimer(); - if (rv < 0) - return rv; - - DCHECK(rv); - // TODO(agayev): when supporting EDNS0 we may need to do multiple reads - // to read the whole response. - return response_->Parse(rv, &ip_addresses_); -} - -void DnsTransaction::StartTimer(base::TimeDelta delay) { - timer_.Start(delay, this, &DnsTransaction::OnTimeout); -} - -void DnsTransaction::RevokeTimer() { - timer_.Stop(); -} - -void DnsTransaction::OnTimeout() { - DCHECK(next_state_ == STATE_SEND_QUERY_COMPLETE || - next_state_ == STATE_READ_RESPONSE_COMPLETE); - if (attempts_ == timeouts_ms_.size()) { - DoCallback(ERR_DNS_TIMED_OUT); - return; - } - next_state_ = STATE_CONNECT; - query_.reset(query_->CloneWithNewId()); - int rv = DoLoop(OK); - if (rv != ERR_IO_PENDING) - DoCallback(rv); -} - -void DnsTransaction::set_timeouts_ms( - const std::vector<base::TimeDelta>& timeouts_ms) { - DCHECK_EQ(0u, attempts_); - timeouts_ms_ = timeouts_ms; -} - -} // namespace net diff --git a/net/base/dns_transaction.h b/net/base/dns_transaction.h deleted file mode 100644 index 433bd242..0000000 --- a/net/base/dns_transaction.h +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_BASE_DNS_TRANSACTION_H_ -#define NET_BASE_DNS_TRANSACTION_H_ -#pragma once - -#include <set> -#include <string> -#include <utility> -#include <vector> - -#include "base/basictypes.h" -#include "base/scoped_ptr.h" -#include "base/time.h" -#include "base/timer.h" -#include "base/threading/non_thread_safe.h" -#include "net/base/completion_callback.h" -#include "net/base/dns_query.h" -#include "net/base/dns_response.h" -#include "net/base/dns_transaction.h" -#include "net/base/ip_endpoint.h" -#include "net/base/net_api.h" -#include "net/base/net_errors.h" -#include "net/base/net_log.h" - -namespace net { - -class ClientSocketFactory; -class DatagramClientSocket; - -// Performs (with fixed retries) a single asynchronous DNS transaction, -// which consists of sending out a DNS query, waiting for response, and -// parsing and returning the IP addresses that it matches. -class NET_TEST DnsTransaction : NON_EXPORTED_BASE(public base::NonThreadSafe) { - public: - typedef std::pair<std::string, uint16> Key; - - // Interface that should implemented by DnsTransaction consumer and - // passed to |Start| method to be notified when the transaction has - // completed. - class NET_TEST Delegate { - public: - Delegate(); - virtual ~Delegate(); - - // A consumer of DnsTransaction should override |OnTransactionComplete| - // and call |set_delegate(this)|. The method will be called once the - // resolution has completed, results passed in as arguments. - virtual void OnTransactionComplete( - int result, - const DnsTransaction* transaction, - const IPAddressList& ip_addresses); - - private: - friend class DnsTransaction; - - void Attach(DnsTransaction* transaction); - void Detach(DnsTransaction* transaction); - - std::set<DnsTransaction*> registered_transactions_; - - DISALLOW_COPY_AND_ASSIGN(Delegate); - }; - - // |dns_server| is the address of the DNS server, |dns_name| is the - // hostname (in DNS format) to be resolved, |query_type| is the type of - // the query, either kDNS_A or kDNS_AAAA, |rand_int| is the PRNG used for - // generating DNS query. - DnsTransaction(const IPEndPoint& dns_server, - const std::string& dns_name, - uint16 query_type, - const RandIntCallback& rand_int, - ClientSocketFactory* socket_factory, - const BoundNetLog& source_net_log, - NetLog* net_log); - ~DnsTransaction(); - void SetDelegate(Delegate* delegate); - const Key& key() const { return key_; } - - // Starts the resolution process. Will return ERR_IO_PENDING and will - // notify the caller via |delegate|. Should only be called once. - int Start(); - - private: - FRIEND_TEST_ALL_PREFIXES(DnsTransactionTest, FirstTimeoutTest); - FRIEND_TEST_ALL_PREFIXES(DnsTransactionTest, SecondTimeoutTest); - FRIEND_TEST_ALL_PREFIXES(DnsTransactionTest, ThirdTimeoutTest); - - enum State { - STATE_CONNECT, - STATE_CONNECT_COMPLETE, - STATE_SEND_QUERY, - STATE_SEND_QUERY_COMPLETE, - STATE_READ_RESPONSE, - STATE_READ_RESPONSE_COMPLETE, - STATE_NONE, - }; - - int DoLoop(int result); - void DoCallback(int result); - void OnIOComplete(int result); - - int DoConnect(); - int DoConnectComplete(int result); - int DoSendQuery(); - int DoSendQueryComplete(int result); - int DoReadResponse(); - int DoReadResponseComplete(int result); - - // Fixed number of attempts are made to send a query and read a response, - // and at the start of each, a timer is started with increasing delays. - void StartTimer(base::TimeDelta delay); - void RevokeTimer(); - void OnTimeout(); - - // This is to be used by unit tests only. - void set_timeouts_ms(const std::vector<base::TimeDelta>& timeouts_ms); - - const IPEndPoint dns_server_; - Key key_; - IPAddressList ip_addresses_; - Delegate* delegate_; - - scoped_ptr<DnsQuery> query_; - scoped_ptr<DnsResponse> response_; - scoped_ptr<DatagramClientSocket> socket_; - - // Number of retry attempts so far. - size_t attempts_; - - // Timeouts in milliseconds. - std::vector<base::TimeDelta> timeouts_ms_; - - State next_state_; - ClientSocketFactory* socket_factory_; - base::OneShotTimer<DnsTransaction> timer_; - CompletionCallbackImpl<DnsTransaction> io_callback_; - - BoundNetLog net_log_; - - DISALLOW_COPY_AND_ASSIGN(DnsTransaction); -}; - -} // namespace net - -#endif // NET_BASE_DNS_TRANSACTION_H_ diff --git a/net/base/dns_transaction_unittest.cc b/net/base/dns_transaction_unittest.cc deleted file mode 100644 index 2e557e9..0000000 --- a/net/base/dns_transaction_unittest.cc +++ /dev/null @@ -1,342 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <vector> - -#include "base/bind.h" -#include "base/rand_util.h" -#include "net/base/dns_transaction.h" -#include "net/base/dns_query.h" -#include "net/base/dns_test_util.h" -#include "net/socket/socket_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { - -namespace { - -static const base::TimeDelta kTimeoutsMs[] = { - base::TimeDelta::FromMilliseconds(20), - base::TimeDelta::FromMilliseconds(20), - base::TimeDelta::FromMilliseconds(20), -}; - -} // namespace - -class TestDelegate : public DnsTransaction::Delegate { - public: - TestDelegate() : result_(ERR_UNEXPECTED), transaction_(NULL) {} - virtual ~TestDelegate() {} - virtual void OnTransactionComplete( - int result, - const DnsTransaction* transaction, - const IPAddressList& ip_addresses) { - result_ = result; - transaction_ = transaction; - ip_addresses_ = ip_addresses; - MessageLoop::current()->Quit(); - } - int result() const { return result_; } - const DnsTransaction* transaction() const { return transaction_; } - const IPAddressList& ip_addresses() const { - return ip_addresses_; - } - - private: - int result_; - const DnsTransaction* transaction_; - IPAddressList ip_addresses_; - - DISALLOW_COPY_AND_ASSIGN(TestDelegate); -}; - - -TEST(DnsTransactionTest, NormalQueryResponseTest) { - MockWrite writes0[] = { - MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), - arraysize(kT0QueryDatagram)) - }; - - MockRead reads0[] = { - MockRead(true, reinterpret_cast<const char*>(kT0ResponseDatagram), - arraysize(kT0ResponseDatagram)) - }; - - StaticSocketDataProvider data(reads0, arraysize(reads0), - writes0, arraysize(writes0)); - MockClientSocketFactory factory; - factory.AddSocketDataProvider(&data); - - TestPrng test_prng(std::deque<int>(1, 0)); - RandIntCallback rand_int_cb = - base::Bind(&TestPrng::GetNext, base::Unretained(&test_prng)); - std::string t0_dns_name(kT0DnsName, arraysize(kT0DnsName)); - - IPEndPoint dns_server; - bool rv = CreateDnsAddress(kDnsIp, kDnsPort, &dns_server); - ASSERT_TRUE(rv); - - DnsTransaction t(dns_server, t0_dns_name, kT1Qtype, rand_int_cb, &factory, - BoundNetLog(), NULL); - - TestDelegate delegate; - t.SetDelegate(&delegate); - - IPAddressList expected_ip_addresses; - rv = ConvertStringsToIPAddressList(kT0IpAddresses, - arraysize(kT0IpAddresses), - &expected_ip_addresses); - ASSERT_TRUE(rv); - - int rv0 = t.Start(); - EXPECT_EQ(ERR_IO_PENDING, rv0); - - MessageLoop::current()->Run(); - - EXPECT_TRUE(DnsTransaction::Key(t0_dns_name, kT0Qtype) == t.key()); - EXPECT_EQ(OK, delegate.result()); - EXPECT_EQ(&t, delegate.transaction()); - EXPECT_TRUE(expected_ip_addresses == delegate.ip_addresses()); - - EXPECT_TRUE(data.at_read_eof()); - EXPECT_TRUE(data.at_write_eof()); -} - -TEST(DnsTransactionTest, MismatchedQueryResponseTest) { - MockWrite writes0[] = { - MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), - arraysize(kT0QueryDatagram)) - }; - - MockRead reads1[] = { - MockRead(true, reinterpret_cast<const char*>(kT1ResponseDatagram), - arraysize(kT1ResponseDatagram)) - }; - - StaticSocketDataProvider data(reads1, arraysize(reads1), - writes0, arraysize(writes0)); - MockClientSocketFactory factory; - factory.AddSocketDataProvider(&data); - - TestPrng test_prng(std::deque<int>(1, 0)); - RandIntCallback rand_int_cb = - base::Bind(&TestPrng::GetNext, base::Unretained(&test_prng)); - std::string t0_dns_name(kT0DnsName, arraysize(kT0DnsName)); - - IPEndPoint dns_server; - bool rv = CreateDnsAddress(kDnsIp, kDnsPort, &dns_server); - ASSERT_TRUE(rv); - - DnsTransaction t(dns_server, t0_dns_name, kT1Qtype, rand_int_cb, &factory, - BoundNetLog(), NULL); - - TestDelegate delegate; - t.SetDelegate(&delegate); - - int rv0 = t.Start(); - EXPECT_EQ(ERR_IO_PENDING, rv0); - - MessageLoop::current()->Run(); - - EXPECT_TRUE(DnsTransaction::Key(t0_dns_name, kT0Qtype) == t.key()); - EXPECT_EQ(ERR_DNS_MALFORMED_RESPONSE, delegate.result()); - EXPECT_EQ(0u, delegate.ip_addresses().size()); - EXPECT_EQ(&t, delegate.transaction()); - EXPECT_TRUE(data.at_read_eof()); - EXPECT_TRUE(data.at_write_eof()); -} - -// Test that after the first timeout we do a fresh connection and if we get -// a response on the new connection, we return it. -TEST(DnsTransactionTest, FirstTimeoutTest) { - MockWrite writes0[] = { - MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), - arraysize(kT0QueryDatagram)) - }; - - MockRead reads0[] = { - MockRead(true, reinterpret_cast<const char*>(kT0ResponseDatagram), - arraysize(kT0ResponseDatagram)) - }; - - scoped_refptr<DelayedSocketData> socket0_data( - new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0))); - scoped_refptr<DelayedSocketData> socket1_data( - new DelayedSocketData(0, reads0, arraysize(reads0), - writes0, arraysize(writes0))); - MockClientSocketFactory factory; - factory.AddSocketDataProvider(socket0_data.get()); - factory.AddSocketDataProvider(socket1_data.get()); - - TestPrng test_prng(std::deque<int>(2, 0)); - RandIntCallback rand_int_cb = - base::Bind(&TestPrng::GetNext, base::Unretained(&test_prng)); - std::string t0_dns_name(kT0DnsName, arraysize(kT0DnsName)); - - IPEndPoint dns_server; - bool rv = CreateDnsAddress(kDnsIp, kDnsPort, &dns_server); - ASSERT_TRUE(rv); - - DnsTransaction t(dns_server, t0_dns_name, kT1Qtype, rand_int_cb, &factory, - BoundNetLog(), NULL); - - TestDelegate delegate; - t.SetDelegate(&delegate); - - t.set_timeouts_ms( - std::vector<base::TimeDelta>(kTimeoutsMs, - kTimeoutsMs + arraysize(kTimeoutsMs))); - - IPAddressList expected_ip_addresses; - rv = ConvertStringsToIPAddressList(kT0IpAddresses, - arraysize(kT0IpAddresses), - &expected_ip_addresses); - ASSERT_TRUE(rv); - - int rv0 = t.Start(); - EXPECT_EQ(ERR_IO_PENDING, rv0); - - - MessageLoop::current()->Run(); - - EXPECT_TRUE(DnsTransaction::Key(t0_dns_name, kT0Qtype) == t.key()); - EXPECT_EQ(OK, delegate.result()); - EXPECT_EQ(&t, delegate.transaction()); - EXPECT_TRUE(expected_ip_addresses == delegate.ip_addresses()); - - EXPECT_TRUE(socket0_data->at_read_eof()); - EXPECT_TRUE(socket0_data->at_write_eof()); - EXPECT_TRUE(socket1_data->at_read_eof()); - EXPECT_TRUE(socket1_data->at_write_eof()); - EXPECT_EQ(2u, factory.udp_client_sockets().size()); -} - -// Test that after the first timeout we do a fresh connection, and after -// the second timeout we do another fresh connection, and if we get a -// response on the second connection, we return it. -TEST(DnsTransactionTest, SecondTimeoutTest) { - MockWrite writes0[] = { - MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), - arraysize(kT0QueryDatagram)) - }; - - MockRead reads0[] = { - MockRead(true, reinterpret_cast<const char*>(kT0ResponseDatagram), - arraysize(kT0ResponseDatagram)) - }; - - scoped_refptr<DelayedSocketData> socket0_data( - new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0))); - scoped_refptr<DelayedSocketData> socket1_data( - new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0))); - scoped_refptr<DelayedSocketData> socket2_data( - new DelayedSocketData(0, reads0, arraysize(reads0), - writes0, arraysize(writes0))); - MockClientSocketFactory factory; - factory.AddSocketDataProvider(socket0_data.get()); - factory.AddSocketDataProvider(socket1_data.get()); - factory.AddSocketDataProvider(socket2_data.get()); - - TestPrng test_prng(std::deque<int>(3, 0)); - RandIntCallback rand_int_cb = - base::Bind(&TestPrng::GetNext, base::Unretained(&test_prng)); - std::string t0_dns_name(kT0DnsName, arraysize(kT0DnsName)); - - IPEndPoint dns_server; - bool rv = CreateDnsAddress(kDnsIp, kDnsPort, &dns_server); - ASSERT_TRUE(rv); - - DnsTransaction t(dns_server, t0_dns_name, kT1Qtype, rand_int_cb, &factory, - BoundNetLog(), NULL); - - TestDelegate delegate; - t.SetDelegate(&delegate); - - t.set_timeouts_ms( - std::vector<base::TimeDelta>(kTimeoutsMs, - kTimeoutsMs + arraysize(kTimeoutsMs))); - - IPAddressList expected_ip_addresses; - rv = ConvertStringsToIPAddressList(kT0IpAddresses, - arraysize(kT0IpAddresses), - &expected_ip_addresses); - ASSERT_TRUE(rv); - - int rv0 = t.Start(); - EXPECT_EQ(ERR_IO_PENDING, rv0); - - MessageLoop::current()->Run(); - - EXPECT_TRUE(DnsTransaction::Key(t0_dns_name, kT1Qtype) == t.key()); - EXPECT_EQ(OK, delegate.result()); - EXPECT_EQ(&t, delegate.transaction()); - EXPECT_TRUE(expected_ip_addresses == delegate.ip_addresses()); - - EXPECT_TRUE(socket0_data->at_read_eof()); - EXPECT_TRUE(socket0_data->at_write_eof()); - EXPECT_TRUE(socket1_data->at_read_eof()); - EXPECT_TRUE(socket1_data->at_write_eof()); - EXPECT_TRUE(socket2_data->at_read_eof()); - EXPECT_TRUE(socket2_data->at_write_eof()); - EXPECT_EQ(3u, factory.udp_client_sockets().size()); -} - -// Test that after the first timeout we do a fresh connection, and after -// the second timeout we do another fresh connection and after the third -// timeout we give up and return a timeout error. -TEST(DnsTransactionTest, ThirdTimeoutTest) { - MockWrite writes0[] = { - MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), - arraysize(kT0QueryDatagram)) - }; - - scoped_refptr<DelayedSocketData> socket0_data( - new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0))); - scoped_refptr<DelayedSocketData> socket1_data( - new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0))); - scoped_refptr<DelayedSocketData> socket2_data( - new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0))); - MockClientSocketFactory factory; - factory.AddSocketDataProvider(socket0_data.get()); - factory.AddSocketDataProvider(socket1_data.get()); - factory.AddSocketDataProvider(socket2_data.get()); - - TestPrng test_prng(std::deque<int>(3, 0)); - RandIntCallback rand_int_cb = - base::Bind(&TestPrng::GetNext, base::Unretained(&test_prng)); - std::string t0_dns_name(kT0DnsName, arraysize(kT0DnsName)); - - IPEndPoint dns_server; - bool rv = CreateDnsAddress(kDnsIp, kDnsPort, &dns_server); - ASSERT_TRUE(rv); - - DnsTransaction t(dns_server, t0_dns_name, kT1Qtype, rand_int_cb, &factory, - BoundNetLog(), NULL); - - TestDelegate delegate; - t.SetDelegate(&delegate); - - t.set_timeouts_ms( - std::vector<base::TimeDelta>(kTimeoutsMs, - kTimeoutsMs + arraysize(kTimeoutsMs))); - - int rv0 = t.Start(); - EXPECT_EQ(ERR_IO_PENDING, rv0); - - MessageLoop::current()->Run(); - - EXPECT_TRUE(DnsTransaction::Key(t0_dns_name, kT0Qtype) == t.key()); - EXPECT_EQ(ERR_DNS_TIMED_OUT, delegate.result()); - EXPECT_EQ(&t, delegate.transaction()); - - EXPECT_TRUE(socket0_data->at_read_eof()); - EXPECT_TRUE(socket0_data->at_write_eof()); - EXPECT_TRUE(socket1_data->at_read_eof()); - EXPECT_TRUE(socket1_data->at_write_eof()); - EXPECT_TRUE(socket2_data->at_read_eof()); - EXPECT_TRUE(socket2_data->at_write_eof()); - EXPECT_EQ(3u, factory.udp_client_sockets().size()); -} - -} // namespace net diff --git a/net/base/host_resolver_impl_unittest.cc b/net/base/host_resolver_impl_unittest.cc index 73567d3..f89c38b 100644 --- a/net/base/host_resolver_impl_unittest.cc +++ b/net/base/host_resolver_impl_unittest.cc @@ -16,7 +16,6 @@ #include "base/time.h" #include "net/base/address_list.h" #include "net/base/completion_callback.h" -#include "net/base/dns_test_util.h" #include "net/base/host_cache.h" #include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" @@ -24,6 +23,7 @@ #include "net/base/net_util.h" #include "net/base/sys_addrinfo.h" #include "net/base/test_completion_callback.h" +#include "net/base/test_host_resolver_observer.h" #include "testing/gtest/include/gtest/gtest.h" // TODO(eroman): diff --git a/net/base/dns_test_util.cc b/net/base/test_host_resolver_observer.cc index d7f6803..6bd04ba 100644 --- a/net/base/dns_test_util.cc +++ b/net/base/test_host_resolver_observer.cc @@ -2,26 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/base/dns_test_util.h" - -#include "base/message_loop.h" +#include "net/base/test_host_resolver_observer.h" namespace net { -TestPrng::TestPrng(const std::deque<int>& numbers) : numbers_(numbers) { -} - -TestPrng::~TestPrng() { -} - -int TestPrng::GetNext(int min, int max) { - DCHECK(!numbers_.empty()); - int rv = numbers_.front(); - numbers_.pop_front(); - DCHECK(rv >= min && rv <= max); - return rv; -} - bool operator==(const HostResolver::RequestInfo& a, const HostResolver::RequestInfo& b) { return a.hostname() == b.hostname() && @@ -57,28 +41,4 @@ void TestHostResolverObserver::OnCancelResolution( cancel_log.push_back(StartOrCancelEntry(id, info)); } -bool ConvertStringsToIPAddressList( - const char* const ip_strings[], size_t size, IPAddressList* address_list) { - DCHECK(address_list); - IPAddressList ip_addresses; - for (size_t i = 0; i < size; ++i) { - IPAddressNumber ip; - if (!ParseIPLiteralToNumber(ip_strings[i], &ip)) - return false; - ip_addresses.push_back(ip); - } - address_list->swap(ip_addresses); - return true; -} - -bool CreateDnsAddress( - const char* ip_string, uint16 port, IPEndPoint* endpoint) { - DCHECK(endpoint); - IPAddressNumber ip_address; - if (!ParseIPLiteralToNumber(ip_string, &ip_address)) - return false; - *endpoint = IPEndPoint(ip_address, port); - return true; -} - -} // namespace net +} // namespace diff --git a/net/base/test_host_resolver_observer.h b/net/base/test_host_resolver_observer.h new file mode 100644 index 0000000..e5ac70a --- /dev/null +++ b/net/base/test_host_resolver_observer.h @@ -0,0 +1,73 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_TEST_HOST_RESOLVER_OBSERVER_H_ +#define NET_BASE_TEST_HOST_RESOLVER_OBSERVER_H_ +#pragma once + +#include "net/base/host_resolver.h" + +#include <vector> + +namespace net { + +bool operator==(const HostResolver::RequestInfo& a, + const HostResolver::RequestInfo& b); + +// Observer that just makes note of how it was called. The test code can then +// inspect to make sure it was called with the right parameters. Used by +// HostResolverImpl and AsyncHostResolver unit tests. +class TestHostResolverObserver : public HostResolver::Observer { + public: + TestHostResolverObserver(); + virtual ~TestHostResolverObserver(); + + // HostResolver::Observer methods: + virtual void OnStartResolution(int id, const HostResolver::RequestInfo& info); + virtual void OnFinishResolutionWithStatus( + int id, + bool was_resolved, + const HostResolver::RequestInfo& info); + virtual void OnCancelResolution( + int id, + const HostResolver::RequestInfo& info); + + // Tuple (id, info). + struct StartOrCancelEntry { + StartOrCancelEntry(int id, const HostResolver::RequestInfo& info) + : id(id), info(info) {} + + bool operator==(const StartOrCancelEntry& other) const { + return id == other.id && info == other.info; + } + + int id; + HostResolver::RequestInfo info; + }; + + // Tuple (id, was_resolved, info). + struct FinishEntry { + FinishEntry(int id, bool was_resolved, + const HostResolver::RequestInfo& info) + : id(id), was_resolved(was_resolved), info(info) {} + + bool operator==(const FinishEntry& other) const { + return id == other.id && + was_resolved == other.was_resolved && + info == other.info; + } + + int id; + bool was_resolved; + HostResolver::RequestInfo info; + }; + + std::vector<StartOrCancelEntry> start_log; + std::vector<FinishEntry> finish_log; + std::vector<StartOrCancelEntry> cancel_log; +}; + +} // namespace net + +#endif // NET_BASE_TEST_HOST_RESOLVER_OBSERVER_H_ |