// 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 "remoting/host/chromoting_host.h"

#include <algorithm>

#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/message_loop/message_loop_proxy.h"
#include "build/build_config.h"
#include "jingle/glue/thread_wrapper.h"
#include "remoting/base/constants.h"
#include "remoting/base/logging.h"
#include "remoting/host/chromoting_host_context.h"
#include "remoting/host/desktop_environment.h"
#include "remoting/host/host_config.h"
#include "remoting/host/input_injector.h"
#include "remoting/protocol/connection_to_client.h"
#include "remoting/protocol/client_stub.h"
#include "remoting/protocol/host_stub.h"
#include "remoting/protocol/input_stub.h"
#include "remoting/protocol/session_config.h"

using remoting::protocol::ConnectionToClient;
using remoting::protocol::InputStub;

namespace remoting {

namespace {

const net::BackoffEntry::Policy kDefaultBackoffPolicy = {
  // Number of initial errors (in sequence) to ignore before applying
  // exponential back-off rules.
  0,

  // Initial delay for exponential back-off in ms.
  2000,

  // Factor by which the waiting time will be multiplied.
  2,

  // Fuzzing percentage. ex: 10% will spread requests randomly
  // between 90%-100% of the calculated time.
  0,

  // Maximum amount of time we are willing to delay our request in ms.
  -1,

  // Time to keep an entry from being discarded even when it
  // has no significant state, -1 to never discard.
  -1,

  // Don't use initial delay unless the last request was an error.
  false,
};

}  // namespace

ChromotingHost::ChromotingHost(
    SignalStrategy* signal_strategy,
    DesktopEnvironmentFactory* desktop_environment_factory,
    scoped_ptr<protocol::SessionManager> session_manager,
    scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
    : desktop_environment_factory_(desktop_environment_factory),
      session_manager_(session_manager.Pass()),
      audio_task_runner_(audio_task_runner),
      input_task_runner_(input_task_runner),
      video_capture_task_runner_(video_capture_task_runner),
      video_encode_task_runner_(video_encode_task_runner),
      network_task_runner_(network_task_runner),
      ui_task_runner_(ui_task_runner),
      signal_strategy_(signal_strategy),
      started_(false),
      protocol_config_(protocol::CandidateSessionConfig::CreateDefault()),
      login_backoff_(&kDefaultBackoffPolicy),
      authenticating_client_(false),
      reject_authenticating_client_(false),
      enable_curtaining_(false),
      weak_factory_(this) {
  DCHECK(network_task_runner_->BelongsToCurrentThread());
  DCHECK(signal_strategy);

  jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();

  if (!desktop_environment_factory_->SupportsAudioCapture()) {
    protocol_config_->DisableAudioChannel();
  }
}

ChromotingHost::~ChromotingHost() {
  DCHECK(CalledOnValidThread());

  // Disconnect all of the clients.
  while (!clients_.empty()) {
    clients_.front()->DisconnectSession();
  }

  // Destroy the session manager to make sure that |signal_strategy_| does not
  // have any listeners registered.
  session_manager_.reset();

  // Notify observers.
  if (started_)
    FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, OnShutdown());
}

void ChromotingHost::Start(const std::string& host_owner) {
  DCHECK(CalledOnValidThread());
  DCHECK(!started_);

  HOST_LOG << "Starting host";
  started_ = true;
  FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, OnStart(host_owner));

  // Start the SessionManager, supplying this ChromotingHost as the listener.
  session_manager_->Init(signal_strategy_, this);
}

void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) {
  DCHECK(CalledOnValidThread());
  status_observers_.AddObserver(observer);
}

void ChromotingHost::RemoveStatusObserver(HostStatusObserver* observer) {
  DCHECK(CalledOnValidThread());
  status_observers_.RemoveObserver(observer);
}

void ChromotingHost::AddExtension(scoped_ptr<HostExtension> extension) {
  extensions_.push_back(extension.release());
}

void ChromotingHost::RejectAuthenticatingClient() {
  DCHECK(authenticating_client_);
  reject_authenticating_client_ = true;
}

void ChromotingHost::SetAuthenticatorFactory(
    scoped_ptr<protocol::AuthenticatorFactory> authenticator_factory) {
  DCHECK(CalledOnValidThread());
  session_manager_->set_authenticator_factory(authenticator_factory.Pass());
}

void ChromotingHost::SetEnableCurtaining(bool enable) {
  DCHECK(network_task_runner_->BelongsToCurrentThread());

  if (enable_curtaining_ == enable)
    return;

  enable_curtaining_ = enable;
  desktop_environment_factory_->SetEnableCurtaining(enable_curtaining_);

  // Disconnect all existing clients because they might be running not
  // curtained.
  // TODO(alexeypa): fix this such that the curtain is applied to the not
  // curtained sessions or disconnect only the client connected to not
  // curtained sessions.
  if (enable_curtaining_)
    DisconnectAllClients();
}

void ChromotingHost::SetMaximumSessionDuration(
    const base::TimeDelta& max_session_duration) {
  max_session_duration_ = max_session_duration;
}

////////////////////////////////////////////////////////////////////////////
// protocol::ClientSession::EventHandler implementation.
void ChromotingHost::OnSessionAuthenticating(ClientSession* client) {
  // We treat each incoming connection as a failure to authenticate,
  // and clear the backoff when a connection successfully
  // authenticates. This allows the backoff to protect from parallel
  // connection attempts as well as sequential ones.
  if (login_backoff_.ShouldRejectRequest()) {
    LOG(WARNING) << "Disconnecting client " << client->client_jid() << " due to"
                    " an overload of failed login attempts.";
    client->DisconnectSession();
    return;
  }
  login_backoff_.InformOfRequest(false);
}

bool ChromotingHost::OnSessionAuthenticated(ClientSession* client) {
  DCHECK(CalledOnValidThread());

  login_backoff_.Reset();

  // Disconnect all other clients. |it| should be advanced before Disconnect()
  // is called to avoid it becoming invalid when the client is removed from
  // the list.
  ClientList::iterator it = clients_.begin();
  while (it != clients_.end()) {
    ClientSession* other_client = *it++;
    if (other_client != client)
      other_client->DisconnectSession();
  }

  // Disconnects above must have destroyed all other clients.
  DCHECK_EQ(clients_.size(), 1U);

  // Notify observers that there is at least one authenticated client.
  const std::string& jid = client->client_jid();

  reject_authenticating_client_ = false;

  authenticating_client_ = true;
  FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
                    OnClientAuthenticated(jid));
  authenticating_client_ = false;

  return !reject_authenticating_client_;
}

void ChromotingHost::OnSessionChannelsConnected(ClientSession* client) {
  DCHECK(CalledOnValidThread());

  // Notify observers.
  FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
                    OnClientConnected(client->client_jid()));
}

void ChromotingHost::OnSessionClientCapabilities(ClientSession* client) {
  DCHECK(CalledOnValidThread());

  // Create extension sessions from each registered extension for this client.
  for (HostExtensionList::iterator extension = extensions_.begin();
       extension != extensions_.end(); ++extension) {
    scoped_ptr<HostExtensionSession> extension_session =
        (*extension)->CreateExtensionSession(client);
    if (extension_session)
      client->AddExtensionSession(extension_session.Pass());
  }
}

void ChromotingHost::OnSessionAuthenticationFailed(ClientSession* client) {
  DCHECK(CalledOnValidThread());

  // Notify observers.
  FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
                    OnAccessDenied(client->client_jid()));
}

void ChromotingHost::OnSessionClosed(ClientSession* client) {
  DCHECK(CalledOnValidThread());

  ClientList::iterator it = std::find(clients_.begin(), clients_.end(), client);
  CHECK(it != clients_.end());

  if (client->is_authenticated()) {
    FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
                      OnClientDisconnected(client->client_jid()));
  }

  clients_.erase(it);
  delete client;
}

void ChromotingHost::OnSessionSequenceNumber(ClientSession* session,
                                             int64 sequence_number) {
  DCHECK(CalledOnValidThread());
}

void ChromotingHost::OnSessionRouteChange(
    ClientSession* session,
    const std::string& channel_name,
    const protocol::TransportRoute& route) {
  DCHECK(CalledOnValidThread());
  FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
                    OnClientRouteChange(session->client_jid(), channel_name,
                                        route));
}

void ChromotingHost::OnSessionManagerReady() {
  DCHECK(CalledOnValidThread());
  // Don't need to do anything here, just wait for incoming
  // connections.
}

void ChromotingHost::OnIncomingSession(
      protocol::Session* session,
      protocol::SessionManager::IncomingSessionResponse* response) {
  DCHECK(CalledOnValidThread());

  if (!started_) {
    *response = protocol::SessionManager::DECLINE;
    return;
  }

  if (login_backoff_.ShouldRejectRequest()) {
    LOG(WARNING) << "Rejecting connection due to"
                    " an overload of failed login attempts.";
    *response = protocol::SessionManager::OVERLOAD;
    return;
  }

  protocol::SessionConfig config;
  if (!protocol_config_->Select(session->candidate_config(), &config)) {
    LOG(WARNING) << "Rejecting connection from " << session->jid()
                 << " because no compatible configuration has been found.";
    *response = protocol::SessionManager::INCOMPATIBLE;
    return;
  }

  session->set_config(config);

  *response = protocol::SessionManager::ACCEPT;

  HOST_LOG << "Client connected: " << session->jid();

  // Create a client object.
  scoped_ptr<protocol::ConnectionToClient> connection(
      new protocol::ConnectionToClient(session));
  ClientSession* client = new ClientSession(
      this,
      audio_task_runner_,
      input_task_runner_,
      video_capture_task_runner_,
      video_encode_task_runner_,
      network_task_runner_,
      ui_task_runner_,
      connection.Pass(),
      desktop_environment_factory_,
      max_session_duration_,
      pairing_registry_);

  // Registers capabilities provided by host extensions.
  for (HostExtensionList::iterator extension = extensions_.begin();
       extension != extensions_.end(); ++extension) {
    client->AddHostCapabilities((*extension)->GetCapabilities());
  }

  clients_.push_back(client);
}

void ChromotingHost::set_protocol_config(
    scoped_ptr<protocol::CandidateSessionConfig> config) {
  DCHECK(CalledOnValidThread());
  DCHECK(config.get());
  DCHECK(!started_);
  protocol_config_ = config.Pass();
}

void ChromotingHost::DisconnectAllClients() {
  DCHECK(CalledOnValidThread());

  while (!clients_.empty()) {
    size_t size = clients_.size();
    clients_.front()->DisconnectSession();
    CHECK_EQ(clients_.size(), size - 1);
  }
}

}  // namespace remoting
