// Copyright (c) 2006-2008 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_HOST_RESOLVER_H_
#define NET_BASE_HOST_RESOLVER_H_
#include <string>
#include "base/ref_counted.h"
#include "googleurl/src/gurl.h"
#include "net/base/address_family.h"
#include "net/base/completion_callback.h"
#include "net/base/request_priority.h"
class MessageLoop;
namespace net {
class AddressList;
class HostCache;
class LoadLog;
class NetworkChangeNotifier;
// This class represents the task of resolving hostnames (or IP address
// literal) to an AddressList object.
//
// HostResolver can handle multiple requests at a time, so when cancelling a
// request the RequestHandle that was returned by Resolve() needs to be
// given. A simpler alternative for consumers that only have 1 outstanding
// request at a time is to create a SingleRequestHostResolver wrapper around
// HostResolver (which will automatically cancel the single request when it
// goes out of scope).
class HostResolver : public base::RefCountedThreadSafe<HostResolver> {
public:
// The parameters for doing a Resolve(). |hostname| and |port| are required,
// the rest are optional (and have reasonable defaults).
class RequestInfo {
public:
RequestInfo(const std::string& hostname, int port)
: hostname_(hostname),
address_family_(ADDRESS_FAMILY_UNSPECIFIED),
port_(port),
allow_cached_response_(true),
is_speculative_(false),
priority_(MEDIUM) {}
const int port() const { return port_; }
const std::string& hostname() const { return hostname_; }
AddressFamily address_family() const { return address_family_; }
void set_address_family(AddressFamily address_family) {
address_family_ = address_family;
}
bool allow_cached_response() const { return allow_cached_response_; }
void set_allow_cached_response(bool b) { allow_cached_response_ = b; }
bool is_speculative() const { return is_speculative_; }
void set_is_speculative(bool b) { is_speculative_ = b; }
RequestPriority priority() const { return priority_; }
void set_priority(RequestPriority priority) { priority_ = priority; }
const GURL& referrer() const { return referrer_; }
void set_referrer(const GURL& referrer) { referrer_ = referrer; }
private:
// The hostname to resolve.
std::string hostname_;
// The address family to restrict results to.
AddressFamily address_family_;
// The port number to set in the result's sockaddrs.
int port_;
// Whether it is ok to return a result from the host cache.
bool allow_cached_response_;
// Whether this request was started by the DNS prefetcher.
bool is_speculative_;
// The priority for the request.
RequestPriority priority_;
// Optional data for consumption by observers. This is the URL of the
// page that lead us to the navigation, for DNS prefetcher's benefit.
GURL referrer_;
};
// Interface for observing the requests that flow through a HostResolver.
class Observer {
public:
virtual ~Observer() {}
// Called at the start of HostResolver::Resolve(). |id| is a unique number
// given to the request, so it can be matched up with a corresponding call
// to OnFinishResolutionWithStatus() or OnCancelResolution().
virtual void OnStartResolution(int id, const RequestInfo& info) = 0;
// Called on completion of request |id|. Note that if the request was
// cancelled, OnCancelResolution() will be called instead.
virtual void OnFinishResolutionWithStatus(int id, bool was_resolved,
const RequestInfo& info) = 0;
// Called when request |id| has been cancelled. A request is "cancelled"
// if either the HostResolver is destroyed while a resolution is in
// progress, or HostResolver::CancelRequest() is called.
virtual void OnCancelResolution(int id, const RequestInfo& info) = 0;
};
// Opaque type used to cancel a request.
typedef void* RequestHandle;
// Resolves the given hostname (or IP address literal), filling out the
// |addresses| object upon success. The |info.port| parameter will be set as
// the sin(6)_port field of the sockaddr_in{6} struct. Returns OK if
// successful or an error code upon failure.
//
// When callback is null, the operation completes synchronously.
//
// When callback is non-null, the operation may be performed asynchronously.
// If the operation cannnot be completed synchronously, ERR_IO_PENDING will
// be returned and the real result code will be passed to the completion
// callback. Otherwise the result code is returned immediately from this
// call.
// If |out_req| is non-NULL, then |*out_req| will be filled with a handle to
// the async request. This handle is not valid after the request has
// completed.
//
// Profiling information for the request is saved to |load_log| if non-NULL.
virtual int Resolve(const RequestInfo& info,
AddressList* addresses,
CompletionCallback* callback,
RequestHandle* out_req,
LoadLog* load_log) = 0;
// Cancels the specified request. |req| is the handle returned by Resolve().
// After a request is cancelled, its completion callback will not be called.
virtual void CancelRequest(RequestHandle req) = 0;
// Adds an observer to this resolver. The observer will be notified of the
// start and completion of all requests (excluding cancellation). |observer|
// must remain valid for the duration of this HostResolver's lifetime.
virtual void AddObserver(Observer* observer) = 0;
// Unregisters an observer previously added by AddObserver().
virtual void RemoveObserver(Observer* observer) = 0;
// TODO(eroman): temp hack for http://crbug.com/18373
virtual void Shutdown() = 0;
// Sets the default AddressFamily to use when requests have left it
// unspecified. For example, this could be used to restrict resolution
// results to AF_INET by passing in ADDRESS_FAMILY_IPV4, or to
// AF_INET6 by passing in ADDRESS_FAMILY_IPV6.
virtual void SetDefaultAddressFamily(AddressFamily address_family) {}
// Returns true if this HostResolver is an instance of HostResolverImpl.
// Used primarily to expose additional functionality on the
// about:net-internals page.
virtual bool IsHostResolverImpl() { return false; }
protected:
friend class base::RefCountedThreadSafe<HostResolver>;
HostResolver() { }
// If any completion callbacks are pending when the resolver is destroyed,
// the host resolutions are cancelled, and the completion callbacks will not
// be called.
virtual ~HostResolver() {}
private:
DISALLOW_COPY_AND_ASSIGN(HostResolver);
};
// This class represents the task of resolving a hostname (or IP address
// literal) to an AddressList object. It wraps HostResolver to resolve only a
// single hostname at a time and cancels this request when going out of scope.
class SingleRequestHostResolver {
public:
explicit SingleRequestHostResolver(HostResolver* resolver);
// If a completion callback is pending when the resolver is destroyed, the
// host resolution is cancelled, and the completion callback will not be
// called.
~SingleRequestHostResolver();
// Resolves the given hostname (or IP address literal), filling out the
// |addresses| object upon success. See HostResolver::Resolve() for details.
int Resolve(const HostResolver::RequestInfo& info,
AddressList* addresses,
CompletionCallback* callback,
LoadLog* load_log);
// Cancels the in-progress request, if any. This prevents the callback
// from being invoked. Resolve() can be called again after cancelling.
void Cancel();
private:
// Callback for when the request to |resolver_| completes, so we dispatch
// to the user's callback.
void OnResolveCompletion(int result);
// The actual host resolver that will handle the request.
scoped_refptr<HostResolver> resolver_;
// The current request (if any).
HostResolver::RequestHandle cur_request_;
CompletionCallback* cur_request_callback_;
// Completion callback for when request to |resolver_| completes.
net::CompletionCallbackImpl<SingleRequestHostResolver> callback_;
DISALLOW_COPY_AND_ASSIGN(SingleRequestHostResolver);
};
// Creates a HostResolver implementation that queries the underlying system.
// (Except if a unit-test has changed the global HostResolverProc using
// ScopedHostResolverProc to intercept requests to the system).
// |network_change_notifier| must outlive HostResolver. It can optionally be
// NULL, in which case HostResolver will not respond to network changes.
HostResolver* CreateSystemHostResolver(
NetworkChangeNotifier* network_change_notifier);
} // namespace net
#endif // NET_BASE_HOST_RESOLVER_H_