// Copyright 2016 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 "components/cronet/stale_host_resolver.h"

#include "base/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "net/base/net_errors.h"
#include "net/dns/dns_util.h"
#include "net/dns/host_resolver_impl.h"

namespace cronet {

namespace {

// Used in histograms; do not modify existing values.
enum RequestOutcome {
  // Served from (valid) cache, hosts file, IP literal, etc.
  SYNCHRONOUS = 0,

  // Network responded; there was no usable stale data.
  NETWORK_WITHOUT_STALE = 1,

  // Network responded before stale delay; there was usable stale data.
  NETWORK_WITH_STALE = 2,

  // Stale data returned; network didn't respond before the stale delay.
  STALE_BEFORE_NETWORK = 3,

  // Request canceled; there was no usable stale data.
  CANCELED_WITHOUT_STALE = 4,

  // Request canceled; there was usable stale data.
  CANCELED_WITH_STALE = 5,

  MAX_REQUEST_OUTCOME
};

void RecordRequestOutcome(RequestOutcome outcome) {
  UMA_HISTOGRAM_ENUMERATION("DNS.StaleHostResolver.RequestOutcome", outcome,
                            MAX_REQUEST_OUTCOME);
}

void RecordAddressListDelta(net::AddressListDeltaType delta) {
  UMA_HISTOGRAM_ENUMERATION("DNS.StaleHostResolver.StaleAddressListDelta",
                            delta, net::MAX_DELTA_TYPE);
}

void RecordTimeDelta(base::TimeTicks network_time, base::TimeTicks stale_time) {
  if (network_time <= stale_time) {
    UMA_HISTOGRAM_LONG_TIMES_100("DNS.StaleHostResolver.NetworkEarly",
                                 stale_time - network_time);
  } else {
    UMA_HISTOGRAM_LONG_TIMES_100("DNS.StaleHostResolver.NetworkLate",
                                 network_time - stale_time);
  }
}

bool StaleEntryIsUsable(const StaleHostResolver::StaleOptions& options,
                        const net::HostCache::EntryStaleness& entry) {
  if (options.max_expired_time != base::TimeDelta() &&
      entry.expired_by > options.max_expired_time) {
    return false;
  }
  if (options.max_stale_uses > 0 && entry.stale_hits > options.max_stale_uses)
    return false;
  if (!options.allow_other_network && entry.network_changes > 0)
    return false;
  return true;
}

}  // namespace

// A request made by the StaleHostResolver. May return fresh cached data,
// network data, or stale cached data.
class StaleHostResolver::RequestImpl {
 public:
  RequestImpl();
  ~RequestImpl();

  // A callback for the caller to decide whether a stale entry is usable or not.
  typedef base::Callback<bool(const net::HostCache::EntryStaleness&)>
      StaleEntryUsableCallback;

  // Starts the request. May call |usable_callback| inline if |resolver| returns
  // stale data to let the caller decide whether the data is usable.
  //
  // Returns the result if the request finishes synchronously. Returns
  // ERR_IO_PENDING and calls |result_callback| with the result if it finishes
  // asynchronously (unless destroyed first).
  //
  // |addresses| must remain valid until the Request completes (synchronously or
  // via |result_callback|) or is canceled by destroying the Request.
  int Start(net::HostResolverImpl* resolver,
            const RequestInfo& info,
            net::RequestPriority priority,
            net::AddressList* addresses,
            const net::CompletionCallback& result_callback,
            std::unique_ptr<net::HostResolver::Request>* out_req,
            const net::NetLogWithSource& net_log,
            const StaleEntryUsableCallback& usable_callback,
            base::TimeDelta stale_delay);

  void ChangeRequestPriority(net::RequestPriority priority);

 private:
  class Handle : public net::HostResolver::Request {
   public:
    Handle(RequestImpl* request) : request_(request) {}
    ~Handle() override { request_->OnHandleDestroyed(); }

    void ChangeRequestPriority(net::RequestPriority priority) override {
      request_->ChangeRequestPriority(priority);
    }

   private:
    RequestImpl* request_;
  };

  bool have_network_request() const {
    return network_request_.get() != nullptr;
  }
  bool have_stale_data() const {
    return stale_error_ != net::ERR_DNS_CACHE_MISS;
  }
  bool have_returned() const { return result_callback_.is_null(); }
  bool have_handle() const { return handle_ != nullptr; }

  // Callback for |stale_timer_| that returns stale results.
  void OnStaleDelayElapsed();
  // Callback for network request that returns fresh results if the request
  // hasn't already returned stale results, and completes the request.
  void OnNetworkRequestComplete(int error);
  void OnHandleDestroyed();

  // Fills |*result_addresses_| if rv is OK and returns rv.
  int HandleResult(int rv, const net::AddressList& addresses);
  // Fills |*result_addresses_| if rv is OK and calls |result_callback_| with
  // rv.
  void ReturnResult(int rv, const net::AddressList& addresses);

  void MaybeDeleteThis();

  void RecordSynchronousRequest();
  void RecordNetworkRequest(int error, bool returned_stale_data);
  void RecordCanceledRequest();

  // The address list passed into |Start()| to be filled in when the request
  // returns.
  net::AddressList* result_addresses_;
  // The callback passed into |Start()| to be called when the request returns.
  net::CompletionCallback result_callback_;
  // Set when |result_callback_| is being called so |OnHandleDestroyed()|
  // doesn't delete the request.
  bool returning_result_;

  // The error from the stale cache entry, if there was one.
  // If not, net::ERR_DNS_CACHE_MISS.
  int stale_error_;
  // The address list from the stale cache entry, if there was one.
  net::AddressList stale_addresses_;
  // A timer that fires when the |Request| should return stale results, if the
  // underlying network request has not finished yet.
  base::OneShotTimer stale_timer_;

  // The address list the underlying network request will fill in. (Can't be the
  // one passed to |Start()|, or else the network request would overwrite stale
  // results after they are returned.)
  net::AddressList network_addresses_;
  // The underlying network request, so the priority can be changed.
  std::unique_ptr<net::HostResolver::Request> network_request_;

  // Handle that caller can use to cancel the request before it returns.
  // Owned by the caller; cleared via |OnHandleDestroyed()| when destroyed.
  Handle* handle_;
};

StaleHostResolver::RequestImpl::RequestImpl()
    : result_addresses_(nullptr),
      returning_result_(false),
      stale_error_(net::ERR_DNS_CACHE_MISS),
      handle_(nullptr) {}

StaleHostResolver::RequestImpl::~RequestImpl() {}

int StaleHostResolver::RequestImpl::Start(
    net::HostResolverImpl* resolver,
    const RequestInfo& info,
    net::RequestPriority priority,
    net::AddressList* addresses,
    const net::CompletionCallback& result_callback,
    std::unique_ptr<net::HostResolver::Request>* out_req,
    const net::NetLogWithSource& net_log,
    const StaleEntryUsableCallback& usable_callback,
    base::TimeDelta stale_delay) {
  DCHECK(resolver);
  DCHECK(addresses);
  DCHECK(!result_callback.is_null());
  DCHECK(out_req);
  DCHECK(!usable_callback.is_null());

  result_addresses_ = addresses;

  net::AddressList cache_addresses;
  net::HostCache::EntryStaleness stale_info;
  int cache_rv = resolver->ResolveStaleFromCache(info, &cache_addresses,
                                                 &stale_info, net_log);
  // If it's a fresh cache hit (or literal), return it synchronously.
  if (cache_rv != net::ERR_DNS_CACHE_MISS && !stale_info.is_stale()) {
    RecordSynchronousRequest();
    return HandleResult(cache_rv, cache_addresses);
  }

  result_callback_ = result_callback;
  handle_ = new Handle(this);
  *out_req = std::unique_ptr<net::HostResolver::Request>(handle_);

  if (cache_rv != net::ERR_DNS_CACHE_MISS && usable_callback.Run(stale_info)) {
    stale_error_ = cache_rv;
    stale_addresses_ = cache_addresses;
    // |stale_timer_| is deleted when the Request is deleted, so it's safe to
    // use Unretained here.
    base::Callback<void()> stale_callback =
        base::Bind(&StaleHostResolver::RequestImpl::OnStaleDelayElapsed,
                   base::Unretained(this));
    stale_timer_.Start(FROM_HERE, stale_delay, stale_callback);
  }

  // Don't check the cache again.
  net::HostResolver::RequestInfo no_cache_info(info);
  no_cache_info.set_allow_cached_response(false);
  int network_rv = resolver->Resolve(
      no_cache_info, priority, &network_addresses_,
      base::Bind(&StaleHostResolver::RequestImpl::OnNetworkRequestComplete,
                 base::Unretained(this)),
      &network_request_, net_log);
  DCHECK_EQ(net::ERR_IO_PENDING, network_rv);
  return net::ERR_IO_PENDING;
}

void StaleHostResolver::RequestImpl::ChangeRequestPriority(
    net::RequestPriority priority) {
  DCHECK(have_network_request());

  network_request_->ChangeRequestPriority(priority);
}

void StaleHostResolver::RequestImpl::OnStaleDelayElapsed() {
  DCHECK(!have_returned());
  DCHECK(have_stale_data());

  ReturnResult(stale_error_, stale_addresses_);

  // The request needs to wait for both the network request to complete (to
  // backfill the cache) and the caller to delete the handle before deleting
  // itself.
  DCHECK(have_network_request());
}

void StaleHostResolver::RequestImpl::OnNetworkRequestComplete(int error) {
  DCHECK(have_network_request());
  network_request_.reset();

  RecordNetworkRequest(error, /* returned_stale_data = */ have_returned());

  if (!have_returned()) {
    if (have_stale_data())
      stale_timer_.Stop();
    ReturnResult(error, network_addresses_);
  }

  if (!have_handle())
    delete this;
}

void StaleHostResolver::RequestImpl::OnHandleDestroyed() {
  DCHECK(have_handle());
  handle_ = nullptr;

  // If the caller deletes the handle *before* the request has returned, treat
  // it as a cancel.
  if (!have_returned()) {
    network_request_.reset();
    result_callback_ = net::CompletionCallback();
    RecordCanceledRequest();
  }

  if (!returning_result_ && !have_handle() && !have_network_request())
    delete this;
}

int StaleHostResolver::RequestImpl::HandleResult(
    int rv,
    const net::AddressList& addresses) {
  DCHECK(result_addresses_);

  if (rv == net::OK)
    *result_addresses_ = addresses;
  result_addresses_ = nullptr;
  return rv;
}

void StaleHostResolver::RequestImpl::ReturnResult(
    int rv,
    const net::AddressList& addresses) {
  DCHECK(result_callback_);
  returning_result_ = true;
  base::ResetAndReturn(&result_callback_).Run(HandleResult(rv, addresses));
  returning_result_ = false;
}

void StaleHostResolver::RequestImpl::RecordSynchronousRequest() {
  RecordRequestOutcome(SYNCHRONOUS);
}

void StaleHostResolver::RequestImpl::RecordNetworkRequest(
    int error,
    bool returned_stale_data) {
  if (have_stale_data())
    RecordTimeDelta(base::TimeTicks::Now(), stale_timer_.desired_run_time());

  if (returned_stale_data && stale_error_ == net::OK && error == net::OK) {
    RecordAddressListDelta(
        FindAddressListDeltaType(stale_addresses_, network_addresses_));
  }

  if (returned_stale_data)
    RecordRequestOutcome(STALE_BEFORE_NETWORK);
  else if (have_stale_data())
    RecordRequestOutcome(NETWORK_WITH_STALE);
  else
    RecordRequestOutcome(NETWORK_WITHOUT_STALE);
}

void StaleHostResolver::RequestImpl::RecordCanceledRequest() {
  if (have_stale_data())
    RecordRequestOutcome(CANCELED_WITH_STALE);
  else
    RecordRequestOutcome(CANCELED_WITHOUT_STALE);
}

StaleHostResolver::StaleOptions::StaleOptions()
    : delay(),
      max_expired_time(),
      allow_other_network(false),
      max_stale_uses(0) {}

StaleHostResolver::StaleHostResolver(
    std::unique_ptr<net::HostResolverImpl> inner_resolver,
    const StaleOptions& stale_options)
    : inner_resolver_(std::move(inner_resolver)), options_(stale_options) {
  DCHECK_LE(0, stale_options.max_expired_time.InMicroseconds());
  DCHECK_LE(0, stale_options.max_stale_uses);
}

StaleHostResolver::~StaleHostResolver() {}

int StaleHostResolver::Resolve(const RequestInfo& info,
                               net::RequestPriority priority,
                               net::AddressList* addresses,
                               const net::CompletionCallback& callback,
                               std::unique_ptr<Request>* out_req,
                               const net::NetLogWithSource& net_log) {
  StaleHostResolver::RequestImpl::StaleEntryUsableCallback usable_callback =
      base::Bind(&StaleEntryIsUsable, options_);

  RequestImpl* request = new RequestImpl();
  int rv =
      request->Start(inner_resolver_.get(), info, priority, addresses, callback,
                     out_req, net_log, usable_callback, options_.delay);
  if (rv != net::ERR_IO_PENDING)
    delete request;

  return rv;
}

int StaleHostResolver::ResolveFromCache(const RequestInfo& info,
                                        net::AddressList* addresses,
                                        const net::NetLogWithSource& net_log) {
  return inner_resolver_->ResolveFromCache(info, addresses, net_log);
}

void StaleHostResolver::SetDnsClientEnabled(bool enabled) {
  inner_resolver_->SetDnsClientEnabled(enabled);
}

net::HostCache* StaleHostResolver::GetHostCache() {
  return inner_resolver_->GetHostCache();
}

std::unique_ptr<base::Value> StaleHostResolver::GetDnsConfigAsValue() const {
  return inner_resolver_->GetDnsConfigAsValue();
}

}  // namespace net
