text: // Copyright (c) 2015 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/tools/quic/synchronous_host_resolver.h"
  
  #include <memory>
  #include <utility>
  
  #include "base/at_exit.h"
  #include "base/bind.h"
  #include "base/location.h"
  #include "base/memory/weak_ptr.h"
  #include "base/message_loop/message_pump_type.h"
  #include "base/run_loop.h"
  #include "base/task/single_thread_task_executor.h"
  #include "base/task/single_thread_task_runner.h"
  #include "base/threading/simple_thread.h"
  #include "base/threading/thread_task_runner_handle.h"
  #include "net/base/host_port_pair.h"
  #include "net/base/net_errors.h"
  #include "net/base/network_isolation_key.h"
  #include "net/dns/host_resolver.h"
  #include "net/log/net_log.h"
  #include "net/log/net_log_with_source.h"
  #include "third_party/abseil-cpp/absl/types/optional.h"
  
  namespace net {
  
  
  namespace {
  
  class ResolverThread : public base::SimpleThread {
   public:
    ResolverThread();
  
    ResolverThread(const ResolverThread&) = delete;
    ResolverThread& operator=(const ResolverThread&) = delete;
  
    ~ResolverThread() override;
  
    // Called on the main thread.
    int Resolve(const std::string& host, AddressList* addresses);
  
    // SimpleThread methods:
    void Run() override;
  
   private:
    void OnResolutionComplete(base::OnceClosure on_done, int rv);
  
    AddressList* addresses_;
    std::string host_;
    int rv_;
  };
  
  ResolverThread::ResolverThread()
      : SimpleThread("resolver_thread"), rv_(ERR_UNEXPECTED) {}
  
  ResolverThread::~ResolverThread() = default;
  
  void ResolverThread::Run() {
    base::SingleThreadTaskExecutor io_task_executor(base::MessagePumpType::IO);
  
    net::HostResolver::ManagerOptions options;
    options.max_concurrent_resolves = 6;
    options.max_system_retry_attempts = 3u;
    std::unique_ptr<net::HostResolver> resolver =
        net::HostResolver::CreateStandaloneResolver(NetLog::Get(), options);
  
    HostPortPair host_port_pair(host_, 80);
    // No need to use a NetworkIsolationKey here, since this is an external tool
    // not used by net/ consumers.
    std::unique_ptr<net::HostResolver::ResolveHostRequest> request =
        resolver->CreateRequest(host_port_pair, NetworkIsolationKey(),
                                NetLogWithSource(), absl::nullopt);
  
    base::RunLoop run_loop;
    rv_ = request->Start(base::BindOnce(&ResolverThread::OnResolutionComplete,
                                        base::Unretained(this),
                                        run_loop.QuitClosure()));
  
    if (rv_ == ERR_IO_PENDING) {
      // Run the message loop until OnResolutionComplete quits it.
      run_loop.Run();
    }
  
    if (rv_ == OK) {
      *addresses_ = *request->GetAddressResults();
    }
  }
  
  int ResolverThread::Resolve(const std::string& host, AddressList* addresses) {
    host_ = host;
    addresses_ = addresses;
    this->Start();
    this->Join();
    return rv_;
  }
  
  void ResolverThread::OnResolutionComplete(base::OnceClosure on_done, int rv) {
    rv_ = rv;
    std::move(on_done).Run();
  }
  
  }  // namespace
  
  // static
  int SynchronousHostResolver::Resolve(const std::string& host,
                                       AddressList* addresses) {
    ResolverThread resolver;
    return resolver.Resolve(host, addresses);
  }
  
  }  // namespace net
  