// Copyright (c) 2012 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 <stdio.h>
#include <string>

#include "base/at_exit.h"
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/cancelable_callback.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "net/base/address_list.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
#include "net/base/net_util.h"
#include "net/dns/dns_client.h"
#include "net/dns/dns_config_service.h"
#include "net/dns/dns_protocol.h"
#include "net/dns/host_cache.h"
#include "net/dns/host_resolver_impl.h"
#include "net/tools/gdig/file_net_log.h"

#if defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
#endif

namespace net {

namespace {

bool StringToIPEndPoint(const std::string& ip_address_and_port,
                        IPEndPoint* ip_end_point) {
  DCHECK(ip_end_point);

  std::string ip;
  int port;
  if (!ParseHostAndPort(ip_address_and_port, &ip, &port))
    return false;
  if (port == -1)
    port = dns_protocol::kDefaultPort;

  net::IPAddressNumber ip_number;
  if (!net::ParseIPLiteralToNumber(ip, &ip_number))
    return false;

  *ip_end_point = net::IPEndPoint(ip_number, static_cast<uint16>(port));
  return true;
}

// Convert DnsConfig to human readable text omitting the hosts member.
std::string DnsConfigToString(const DnsConfig& dns_config) {
  std::string output;
  output.append("search ");
  for (size_t i = 0; i < dns_config.search.size(); ++i) {
    output.append(dns_config.search[i] + " ");
  }
  output.append("\n");

  for (size_t i = 0; i < dns_config.nameservers.size(); ++i) {
    output.append("nameserver ");
    output.append(dns_config.nameservers[i].ToString()).append("\n");
  }

  base::StringAppendF(&output, "options ndots:%d\n", dns_config.ndots);
  base::StringAppendF(&output, "options timeout:%d\n",
                      static_cast<int>(dns_config.timeout.InMilliseconds()));
  base::StringAppendF(&output, "options attempts:%d\n", dns_config.attempts);
  if (dns_config.rotate)
    output.append("options rotate\n");
  if (dns_config.edns0)
    output.append("options edns0\n");
  return output;
}

// Convert DnsConfig hosts member to a human readable text.
std::string DnsHostsToString(const DnsHosts& dns_hosts) {
  std::string output;
  for (DnsHosts::const_iterator i = dns_hosts.begin();
       i != dns_hosts.end();
       ++i) {
    const DnsHostsKey& key = i->first;
    std::string host_name = key.first;
    output.append(IPEndPoint(i->second, 0).ToStringWithoutPort());
    output.append(" ").append(host_name).append("\n");
  }
  return output;
}

struct ReplayLogEntry {
  base::TimeDelta start_time;
  std::string domain_name;
};

typedef std::vector<ReplayLogEntry> ReplayLog;

// Loads and parses a replay log file and fills |replay_log| with a structured
// representation. Returns whether the operation was successful. If not, the
// contents of |replay_log| are undefined.
//
// The replay log is a text file where each line contains
//
//   timestamp_in_milliseconds domain_name
//
// The timestamp_in_milliseconds needs to be an integral delta from start of
// resolution and is in milliseconds. domain_name is the name to be resolved.
//
// The file should be sorted by timestamp in ascending time.
bool LoadReplayLog(const base::FilePath& file_path, ReplayLog* replay_log) {
  std::string original_replay_log_contents;
  if (!base::ReadFileToString(file_path, &original_replay_log_contents)) {
    fprintf(stderr, "Unable to open replay file %s\n",
            file_path.MaybeAsASCII().c_str());
    return false;
  }

  // Strip out \r characters for Windows files. This isn't as efficient as a
  // smarter line splitter, but this particular use does not need to target
  // efficiency.
  std::string replay_log_contents;
  base::RemoveChars(original_replay_log_contents, "\r", &replay_log_contents);

  std::vector<std::string> lines;
  base::SplitString(replay_log_contents, '\n', &lines);
  base::TimeDelta previous_delta;
  bool bad_parse = false;
  for (unsigned i = 0; i < lines.size(); ++i) {
    if (lines[i].empty())
      continue;
    std::vector<std::string> time_and_name;
    base::SplitString(lines[i], ' ', &time_and_name);
    if (time_and_name.size() != 2) {
      fprintf(
          stderr,
          "[%s %u] replay log should have format 'timestamp domain_name\\n'\n",
          file_path.MaybeAsASCII().c_str(),
          i + 1);
      bad_parse = true;
      continue;
    }

    int64 delta_in_milliseconds;
    if (!base::StringToInt64(time_and_name[0], &delta_in_milliseconds)) {
      fprintf(
          stderr,
          "[%s %u] replay log should have format 'timestamp domain_name\\n'\n",
          file_path.MaybeAsASCII().c_str(),
          i + 1);
      bad_parse = true;
      continue;
    }

    base::TimeDelta delta =
        base::TimeDelta::FromMilliseconds(delta_in_milliseconds);
    if (delta < previous_delta) {
      fprintf(
          stderr,
          "[%s %u] replay log should be sorted by time\n",
          file_path.MaybeAsASCII().c_str(),
          i + 1);
      bad_parse = true;
      continue;
    }

    previous_delta = delta;
    ReplayLogEntry entry;
    entry.start_time = delta;
    entry.domain_name = time_and_name[1];
    replay_log->push_back(entry);
  }
  return !bad_parse;
}

class GDig {
 public:
  GDig();
  ~GDig();

  enum Result {
    RESULT_NO_RESOLVE = -3,
    RESULT_NO_CONFIG = -2,
    RESULT_WRONG_USAGE = -1,
    RESULT_OK = 0,
    RESULT_PENDING = 1,
  };

  Result Main(int argc, const char* argv[]);

 private:
  bool ParseCommandLine(int argc, const char* argv[]);

  void Start();
  void Finish(Result);

  void OnDnsConfig(const DnsConfig& dns_config_const);
  void OnResolveComplete(unsigned index, AddressList* address_list,
                         base::TimeDelta time_since_start, int val);
  void OnTimeout();
  void ReplayNextEntry();

  base::TimeDelta config_timeout_;
  bool print_config_;
  bool print_hosts_;
  net::IPEndPoint nameserver_;
  base::TimeDelta timeout_;
  int parallellism_;
  ReplayLog replay_log_;
  unsigned replay_log_index_;
  base::Time start_time_;
  int active_resolves_;
  Result result_;

  base::CancelableClosure timeout_closure_;
  scoped_ptr<DnsConfigService> dns_config_service_;
  scoped_ptr<FileNetLogObserver> log_observer_;
  scoped_ptr<NetLog> log_;
  scoped_ptr<HostResolver> resolver_;

#if defined(OS_MACOSX)
  // Without this there will be a mem leak on osx.
  base::mac::ScopedNSAutoreleasePool scoped_pool_;
#endif

  // Need AtExitManager to support AsWeakPtr (in NetLog).
  base::AtExitManager exit_manager_;
};

GDig::GDig()
    : config_timeout_(base::TimeDelta::FromSeconds(5)),
      print_config_(false),
      print_hosts_(false),
      parallellism_(6),
      replay_log_index_(0u),
      active_resolves_(0) {
}

GDig::~GDig() {
  if (log_)
    log_->RemoveThreadSafeObserver(log_observer_.get());
}

GDig::Result GDig::Main(int argc, const char* argv[]) {
  if (!ParseCommandLine(argc, argv)) {
      fprintf(stderr,
              "usage: %s [--net_log[=<basic|no_bytes|all>]]"
              " [--print_config] [--print_hosts]"
              " [--nameserver=<ip_address[:port]>]"
              " [--timeout=<milliseconds>]"
              " [--config_timeout=<seconds>]"
              " [--j=<parallel resolves>]"
              " [--replay_file=<path>]"
              " [domain_name]\n",
              argv[0]);
      return RESULT_WRONG_USAGE;
  }

  base::MessageLoopForIO loop;

  result_ = RESULT_PENDING;
  Start();
  if (result_ == RESULT_PENDING)
    base::MessageLoop::current()->Run();

  // Destroy it while MessageLoopForIO is alive.
  dns_config_service_.reset();
  return result_;
}

bool GDig::ParseCommandLine(int argc, const char* argv[]) {
  base::CommandLine::Init(argc, argv);
  const base::CommandLine& parsed_command_line =
      *base::CommandLine::ForCurrentProcess();

  if (parsed_command_line.HasSwitch("config_timeout")) {
    int timeout_seconds = 0;
    bool parsed = base::StringToInt(
        parsed_command_line.GetSwitchValueASCII("config_timeout"),
        &timeout_seconds);
    if (parsed && timeout_seconds > 0) {
      config_timeout_ = base::TimeDelta::FromSeconds(timeout_seconds);
    } else {
      fprintf(stderr, "Invalid config_timeout parameter\n");
      return false;
    }
  }

  if (parsed_command_line.HasSwitch("net_log")) {
    std::string log_param = parsed_command_line.GetSwitchValueASCII("net_log");
    NetLog::LogLevel level = NetLog::LOG_ALL_BUT_BYTES;

    if (log_param.length() > 0) {
      std::map<std::string, NetLog::LogLevel> log_levels;
      log_levels["all"] = NetLog::LOG_ALL;
      log_levels["no_bytes"] = NetLog::LOG_ALL_BUT_BYTES;

      if (log_levels.find(log_param) != log_levels.end()) {
        level = log_levels[log_param];
      } else {
        fprintf(stderr, "Invalid net_log parameter\n");
        return false;
      }
    }
    log_.reset(new NetLog);
    log_observer_.reset(new FileNetLogObserver(stderr));
    log_->AddThreadSafeObserver(log_observer_.get(), level);
  }

  print_config_ = parsed_command_line.HasSwitch("print_config");
  print_hosts_ = parsed_command_line.HasSwitch("print_hosts");

  if (parsed_command_line.HasSwitch("nameserver")) {
    std::string nameserver =
      parsed_command_line.GetSwitchValueASCII("nameserver");
    if (!StringToIPEndPoint(nameserver, &nameserver_)) {
      fprintf(stderr,
              "Cannot parse the namerserver string into an IPEndPoint\n");
      return false;
    }
  }

  if (parsed_command_line.HasSwitch("timeout")) {
    int timeout_millis = 0;
    bool parsed = base::StringToInt(
        parsed_command_line.GetSwitchValueASCII("timeout"),
        &timeout_millis);
    if (parsed && timeout_millis > 0) {
      timeout_ = base::TimeDelta::FromMilliseconds(timeout_millis);
    } else {
      fprintf(stderr, "Invalid timeout parameter\n");
      return false;
    }
  }

  if (parsed_command_line.HasSwitch("replay_file")) {
    base::FilePath replay_path =
        parsed_command_line.GetSwitchValuePath("replay_file");
    if (!LoadReplayLog(replay_path, &replay_log_))
      return false;
  }

  if (parsed_command_line.HasSwitch("j")) {
    int parallellism = 0;
    bool parsed = base::StringToInt(
        parsed_command_line.GetSwitchValueASCII("j"),
        &parallellism);
    if (parsed && parallellism > 0) {
      parallellism_ = parallellism;
    } else {
      fprintf(stderr, "Invalid parallellism parameter\n");
    }
  }

  if (parsed_command_line.GetArgs().size() == 1) {
    ReplayLogEntry entry;
    entry.start_time = base::TimeDelta();
#if defined(OS_WIN)
    entry.domain_name = base::UTF16ToASCII(parsed_command_line.GetArgs()[0]);
#else
    entry.domain_name = parsed_command_line.GetArgs()[0];
#endif
    replay_log_.push_back(entry);
  } else if (parsed_command_line.GetArgs().size() != 0) {
    return false;
  }
  return print_config_ || print_hosts_ || !replay_log_.empty();
}

void GDig::Start() {
  if (nameserver_.address().size() > 0) {
    DnsConfig dns_config;
    dns_config.attempts = 1;
    dns_config.nameservers.push_back(nameserver_);
    OnDnsConfig(dns_config);
  } else {
    dns_config_service_ = DnsConfigService::CreateSystemService();
    dns_config_service_->ReadConfig(base::Bind(&GDig::OnDnsConfig,
                                               base::Unretained(this)));
    timeout_closure_.Reset(base::Bind(&GDig::OnTimeout,
                                      base::Unretained(this)));
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE, timeout_closure_.callback(), config_timeout_);
  }
}

void GDig::Finish(Result result) {
  DCHECK_NE(RESULT_PENDING, result);
  result_ = result;
  if (base::MessageLoop::current())
    base::MessageLoop::current()->Quit();
}

void GDig::OnDnsConfig(const DnsConfig& dns_config_const) {
  timeout_closure_.Cancel();
  DCHECK(dns_config_const.IsValid());
  DnsConfig dns_config = dns_config_const;

  if (timeout_.InMilliseconds() > 0)
    dns_config.timeout = timeout_;
  if (print_config_) {
    printf("# Dns Configuration\n"
           "%s", DnsConfigToString(dns_config).c_str());
  }
  if (print_hosts_) {
    printf("# Host Database\n"
           "%s", DnsHostsToString(dns_config.hosts).c_str());
  }

  if (replay_log_.empty()) {
    Finish(RESULT_OK);
    return;
  }

  scoped_ptr<DnsClient> dns_client(DnsClient::CreateClient(NULL));
  dns_client->SetConfig(dns_config);
  HostResolver::Options options;
  options.max_concurrent_resolves = parallellism_;
  options.max_retry_attempts = 1u;
  scoped_ptr<HostResolverImpl> resolver(
      new HostResolverImpl(options, log_.get()));
  resolver->SetDnsClient(dns_client.Pass());
  resolver_ = resolver.Pass();

  start_time_ = base::Time::Now();

  ReplayNextEntry();
}

void GDig::ReplayNextEntry() {
  DCHECK_LT(replay_log_index_, replay_log_.size());

  base::TimeDelta time_since_start = base::Time::Now() - start_time_;
  while (replay_log_index_ < replay_log_.size()) {
    const ReplayLogEntry& entry = replay_log_[replay_log_index_];
    if (time_since_start < entry.start_time) {
      // Delay call to next time and return.
      base::MessageLoop::current()->PostDelayedTask(
          FROM_HERE,
          base::Bind(&GDig::ReplayNextEntry, base::Unretained(this)),
          entry.start_time - time_since_start);
      return;
    }

    HostResolver::RequestInfo info(HostPortPair(entry.domain_name.c_str(), 80));
    AddressList* addrlist = new AddressList();
    unsigned current_index = replay_log_index_;
    CompletionCallback callback = base::Bind(&GDig::OnResolveComplete,
                                             base::Unretained(this),
                                             current_index,
                                             base::Owned(addrlist),
                                             time_since_start);
    ++active_resolves_;
    ++replay_log_index_;
    int ret = resolver_->Resolve(
        info,
        DEFAULT_PRIORITY,
        addrlist,
        callback,
        NULL,
        BoundNetLog::Make(log_.get(), net::NetLog::SOURCE_NONE));
    if (ret != ERR_IO_PENDING)
      callback.Run(ret);
  }
}

void GDig::OnResolveComplete(unsigned entry_index,
                             AddressList* address_list,
                             base::TimeDelta resolve_start_time,
                             int val) {
  DCHECK_GT(active_resolves_, 0);
  DCHECK(address_list);
  DCHECK_LT(entry_index, replay_log_.size());
  --active_resolves_;
  base::TimeDelta resolve_end_time = base::Time::Now() - start_time_;
  base::TimeDelta resolve_time = resolve_end_time - resolve_start_time;
  printf("%u %d %d %s %d ",
         entry_index,
         static_cast<int>(resolve_end_time.InMilliseconds()),
         static_cast<int>(resolve_time.InMilliseconds()),
         replay_log_[entry_index].domain_name.c_str(), val);
  if (val != OK) {
    std::string error_string = ErrorToString(val);
    printf("%s", error_string.c_str());
  } else {
    for (size_t i = 0; i < address_list->size(); ++i) {
      if (i != 0)
        printf(" ");
      printf("%s", (*address_list)[i].ToStringWithoutPort().c_str());
    }
  }
  printf("\n");
  if (active_resolves_ == 0 && replay_log_index_ >= replay_log_.size())
    Finish(RESULT_OK);
}

void GDig::OnTimeout() {
  fprintf(stderr, "Timed out waiting to load the dns config\n");
  Finish(RESULT_NO_CONFIG);
}

}  // empty namespace

}  // namespace net

int main(int argc, const char* argv[]) {
  net::GDig dig;
  return dig.Main(argc, argv);
}
