// 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 "net/proxy/sync_host_resolver_bridge.h"

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"

namespace net {

// SyncHostResolverBridge::Core ----------------------------------------------

class SyncHostResolverBridge::Core
    : public base::RefCountedThreadSafe<SyncHostResolverBridge::Core> {
 public:
  Core(HostResolver* resolver, MessageLoop* host_resolver_loop);

  int ResolveSynchronously(const HostResolver::RequestInfo& info,
                           AddressList* addresses,
                           const BoundNetLog& net_log);

  // Returns true if Shutdown() has been called.
  bool HasShutdown() const {
    base::AutoLock l(lock_);
    return HasShutdownLocked();
  }

  // Called on |host_resolver_loop_|.
  void Shutdown();

 private:
  friend class base::RefCountedThreadSafe<SyncHostResolverBridge::Core>;
  ~Core() {}

  bool HasShutdownLocked() const {
    return has_shutdown_;
  }

  // Called on |host_resolver_loop_|.
  void StartResolve(const HostResolver::RequestInfo& info,
                    AddressList* addresses,
                    const BoundNetLog& net_log);

  // Called on |host_resolver_loop_|.
  void OnResolveCompletion(int result);

  // Not called on |host_resolver_loop_|.
  int WaitForResolveCompletion();

  HostResolver* const host_resolver_;
  MessageLoop* const host_resolver_loop_;
  // The result from the current request (set on |host_resolver_loop_|).
  int err_;
  // The currently outstanding request to |host_resolver_|, or NULL.
  HostResolver::RequestHandle outstanding_request_;

  // Event to notify completion of resolve request.  We always Signal() on
  // |host_resolver_loop_| and Wait() on a different thread.
  base::WaitableEvent event_;

  // True if Shutdown() has been called. Must hold |lock_| to access it.
  bool has_shutdown_;

  // Mutex to guard accesses to |has_shutdown_|.
      mutable base::Lock lock_;

  DISALLOW_COPY_AND_ASSIGN(Core);
};

SyncHostResolverBridge::Core::Core(HostResolver* host_resolver,
                                   MessageLoop* host_resolver_loop)
    : host_resolver_(host_resolver),
      host_resolver_loop_(host_resolver_loop),
      err_(0),
      outstanding_request_(NULL),
      event_(true, false),
      has_shutdown_(false) {}

int SyncHostResolverBridge::Core::ResolveSynchronously(
    const HostResolver::RequestInfo& info,
    net::AddressList* addresses,
    const BoundNetLog& net_log) {
  // Otherwise start an async resolve on the resolver's thread.
  host_resolver_loop_->PostTask(
      FROM_HERE,
      base::Bind(&Core::StartResolve, this, info, addresses, net_log));

  return WaitForResolveCompletion();
}

void SyncHostResolverBridge::Core::StartResolve(
    const HostResolver::RequestInfo& info,
    net::AddressList* addresses,
    const BoundNetLog& net_log) {
  DCHECK_EQ(MessageLoop::current(), host_resolver_loop_);
  DCHECK(!outstanding_request_);

  if (HasShutdown())
    return;

  int error = host_resolver_->Resolve(
      info, addresses, base::Bind(&Core::OnResolveCompletion, this),
      &outstanding_request_, net_log);
  if (error != ERR_IO_PENDING)
    OnResolveCompletion(error);  // Completed synchronously.
}

void SyncHostResolverBridge::Core::OnResolveCompletion(int result) {
  DCHECK_EQ(MessageLoop::current(), host_resolver_loop_);
  err_ = result;
  outstanding_request_ = NULL;
  event_.Signal();
}

int SyncHostResolverBridge::Core::WaitForResolveCompletion() {
  DCHECK_NE(MessageLoop::current(), host_resolver_loop_);
  event_.Wait();

  {
    base::AutoLock l(lock_);
    if (HasShutdownLocked())
      return ERR_ABORTED;
    event_.Reset();
  }

  return err_;
}

void SyncHostResolverBridge::Core::Shutdown() {
  DCHECK_EQ(MessageLoop::current(), host_resolver_loop_);

  if (outstanding_request_) {
    host_resolver_->CancelRequest(outstanding_request_);
    outstanding_request_ = NULL;
  }

  {
    base::AutoLock l(lock_);
    has_shutdown_ = true;
  }

  // Wake up the PAC thread in case it was waiting for resolve completion.
  event_.Signal();
}

// SyncHostResolverBridge -----------------------------------------------------

SyncHostResolverBridge::SyncHostResolverBridge(HostResolver* host_resolver,
                                               MessageLoop* host_resolver_loop)
    : host_resolver_loop_(host_resolver_loop),
      core_(new Core(host_resolver, host_resolver_loop)) {
  DCHECK(host_resolver_loop_);
}

SyncHostResolverBridge::~SyncHostResolverBridge() {
  DCHECK(core_->HasShutdown());
}

int SyncHostResolverBridge::Resolve(const HostResolver::RequestInfo& info,
                                    AddressList* addresses,
                                    const BoundNetLog& net_log) {
  return core_->ResolveSynchronously(info, addresses, net_log);
}

void SyncHostResolverBridge::Shutdown() {
  DCHECK_EQ(MessageLoop::current(), host_resolver_loop_);
  core_->Shutdown();
}

}  // namespace net
