// Copyright 2014 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 "chromeos/dbus/shill_third_party_vpn_driver_client.h"

#include <stddef.h>
#include <stdint.h>

#include <map>
#include <set>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/stl_util.h"
#include "chromeos/dbus/shill_third_party_vpn_observer.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_proxy.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace chromeos {

namespace {

const char* kSetParametersKeyList[] = {
    shill::kAddressParameterThirdPartyVpn,
    shill::kBroadcastAddressParameterThirdPartyVpn,
    shill::kExclusionListParameterThirdPartyVpn,
    shill::kInclusionListParameterThirdPartyVpn,
    shill::kSubnetPrefixParameterThirdPartyVpn,
    shill::kMtuParameterThirdPartyVpn,
    shill::kDomainSearchParameterThirdPartyVpn,
    shill::kDnsServersParameterThirdPartyVpn,
    shill::kReconnectParameterThirdPartyVpn};

// The ShillThirdPartyVpnDriverClient implementation.
class ShillThirdPartyVpnDriverClientImpl
    : public ShillThirdPartyVpnDriverClient {
 public:
  ShillThirdPartyVpnDriverClientImpl();
  ~ShillThirdPartyVpnDriverClientImpl() override;

  // ShillThirdPartyVpnDriverClient overrides
  void AddShillThirdPartyVpnObserver(
      const std::string& object_path_value,
      ShillThirdPartyVpnObserver* observer) override;

  void RemoveShillThirdPartyVpnObserver(
      const std::string& object_path_value) override;

  void SetParameters(
      const std::string& object_path_value,
      const base::DictionaryValue& parameters,
      const ShillClientHelper::StringCallback& callback,
      const ShillClientHelper::ErrorCallback& error_callback) override;

  void UpdateConnectionState(
      const std::string& object_path_value,
      const uint32_t connection_state,
      const base::Closure& callback,
      const ShillClientHelper::ErrorCallback& error_callback) override;

  void SendPacket(
      const std::string& object_path_value,
      const std::vector<char>& ip_packet,
      const base::Closure& callback,
      const ShillClientHelper::ErrorCallback& error_callback) override;

 protected:
  void Init(dbus::Bus* bus) override { bus_ = bus; }

  ShillThirdPartyVpnDriverClient::TestInterface* GetTestInterface() override {
    return nullptr;
  }

 private:
  class HelperInfo {
   public:
    explicit HelperInfo(dbus::ObjectProxy* object_proxy);

    ShillClientHelper* helper() { return &helper_; }
    ShillThirdPartyVpnObserver* observer() { return observer_; }

    void set_observer(ShillThirdPartyVpnObserver* observer) {
      observer_ = observer;
    }

    base::WeakPtr<HelperInfo> GetWeakPtr() {
      return weak_ptr_factory_.GetWeakPtr();
    }

   private:
    ShillClientHelper helper_;
    ShillThirdPartyVpnObserver* observer_;

    base::WeakPtrFactory<HelperInfo> weak_ptr_factory_;
  };
  using HelperMap = std::map<std::string, HelperInfo*>;

  static void OnPacketReceived(base::WeakPtr<HelperInfo> helper_info,
                               dbus::Signal* signal);
  static void OnPlatformMessage(base::WeakPtr<HelperInfo> helper_info,
                                dbus::Signal* signal);
  static void OnSignalConnected(const std::string& interface,
                                const std::string& signal,
                                bool success);

  // Returns or creates the corresponding ShillClientHelper for the
  // |object_path_value|.
  ShillClientHelper* GetHelper(const std::string& object_path_value);

  // Returns or creates the corresponding HelperInfo for the
  // |object_path_value|.
  HelperInfo* GetHelperInfo(const std::string& object_path_value);

  // Returns the corresponding HelperInfo for the |object_path| if exists,
  // nullptr if not.
  HelperInfo* FindHelperInfo(const dbus::ObjectPath& object_path);

  // Deletes the helper object corresponding to |object_path|.
  void DeleteHelper(const dbus::ObjectPath& object_path);

  dbus::Bus* bus_;
  HelperMap helpers_;
  std::set<std::string> valid_keys_;

  DISALLOW_COPY_AND_ASSIGN(ShillThirdPartyVpnDriverClientImpl);
};

ShillThirdPartyVpnDriverClientImpl::HelperInfo::HelperInfo(
    dbus::ObjectProxy* object_proxy)
    : helper_(object_proxy), observer_(nullptr), weak_ptr_factory_(this) {
}

ShillThirdPartyVpnDriverClientImpl::ShillThirdPartyVpnDriverClientImpl()
    : bus_(nullptr) {
  for (uint32_t i = 0; i < base::size(kSetParametersKeyList); ++i) {
    valid_keys_.insert(kSetParametersKeyList[i]);
  }
}

ShillThirdPartyVpnDriverClientImpl::~ShillThirdPartyVpnDriverClientImpl() {
  for (auto& iter : helpers_) {
    HelperInfo* helper_info = iter.second;
    bus_->RemoveObjectProxy(
        shill::kFlimflamServiceName,
        helper_info->helper()->object_proxy()->object_path(),
        base::DoNothing());
    delete helper_info;
  }
}

void ShillThirdPartyVpnDriverClientImpl::AddShillThirdPartyVpnObserver(
    const std::string& object_path_value,
    ShillThirdPartyVpnObserver* observer) {
  HelperInfo* helper_info = GetHelperInfo(object_path_value);
  if (helper_info->observer()) {
    LOG(ERROR) << "Observer exists for " << object_path_value;
    return;
  }

  // TODO(kaliamoorthi): Remove the const_cast.
  helper_info->set_observer(observer);
  dbus::ObjectProxy* proxy =
      const_cast<dbus::ObjectProxy*>(helper_info->helper()->object_proxy());

  proxy->ConnectToSignal(
      shill::kFlimflamThirdPartyVpnInterface, shill::kOnPlatformMessageFunction,
      base::Bind(&ShillThirdPartyVpnDriverClientImpl::OnPlatformMessage,
                 helper_info->GetWeakPtr()),
      base::BindOnce(&ShillThirdPartyVpnDriverClientImpl::OnSignalConnected));

  proxy->ConnectToSignal(
      shill::kFlimflamThirdPartyVpnInterface, shill::kOnPacketReceivedFunction,
      base::Bind(&ShillThirdPartyVpnDriverClientImpl::OnPacketReceived,
                 helper_info->GetWeakPtr()),
      base::BindOnce(&ShillThirdPartyVpnDriverClientImpl::OnSignalConnected));
}

void ShillThirdPartyVpnDriverClientImpl::RemoveShillThirdPartyVpnObserver(
    const std::string& object_path_value) {
  HelperInfo* helper_info = FindHelperInfo(dbus::ObjectPath(object_path_value));
  if (!helper_info) {
    LOG(ERROR) << "Unknown object_path_value " << object_path_value;
    return;
  }

  CHECK(helper_info->observer());
  helper_info->set_observer(nullptr);
  DeleteHelper(dbus::ObjectPath(object_path_value));
}

void ShillThirdPartyVpnDriverClientImpl::DeleteHelper(
    const dbus::ObjectPath& object_path) {
  HelperInfo* helper_info = FindHelperInfo(dbus::ObjectPath(object_path));
  if (!helper_info) {
    LOG(ERROR) << "Unknown object_path " << object_path.value();
    return;
  }

  bus_->RemoveObjectProxy(shill::kFlimflamServiceName, object_path,
                          base::DoNothing());
  helpers_.erase(helpers_.find(object_path.value()));
  delete helper_info;
}

void ShillThirdPartyVpnDriverClientImpl::SetParameters(
    const std::string& object_path_value,
    const base::DictionaryValue& parameters,
    const ShillClientHelper::StringCallback& callback,
    const ShillClientHelper::ErrorCallback& error_callback) {
  dbus::MethodCall method_call(shill::kFlimflamThirdPartyVpnInterface,
                               shill::kSetParametersFunction);
  dbus::MessageWriter writer(&method_call);
  dbus::MessageWriter array_writer(nullptr);
  writer.OpenArray("{ss}", &array_writer);
  for (base::DictionaryValue::Iterator it(parameters); !it.IsAtEnd();
       it.Advance()) {
    if (valid_keys_.find(it.key()) == valid_keys_.end()) {
      LOG(WARNING) << "Unknown key " << it.key();
      continue;
    }
    std::string value;
    if (!it.value().GetAsString(&value)) {
      LOG(WARNING) << "Non string value " << it.value();
      continue;
    }
    dbus::MessageWriter entry_writer(nullptr);
    array_writer.OpenDictEntry(&entry_writer);
    entry_writer.AppendString(it.key());
    entry_writer.AppendString(value);
    array_writer.CloseContainer(&entry_writer);
  }
  writer.CloseContainer(&array_writer);
  GetHelper(object_path_value)
      ->CallStringMethodWithErrorCallback(&method_call, callback,
                                          error_callback);
}

void ShillThirdPartyVpnDriverClientImpl::UpdateConnectionState(
    const std::string& object_path_value,
    const uint32_t connection_state,
    const base::Closure& callback,
    const ShillClientHelper::ErrorCallback& error_callback) {
  dbus::MethodCall method_call(shill::kFlimflamThirdPartyVpnInterface,
                               shill::kUpdateConnectionStateFunction);
  dbus::MessageWriter writer(&method_call);
  writer.AppendUint32(connection_state);
  GetHelper(object_path_value)
      ->CallVoidMethodWithErrorCallback(&method_call, callback, error_callback);
}

void ShillThirdPartyVpnDriverClientImpl::SendPacket(
    const std::string& object_path_value,
    const std::vector<char>& ip_packet,
    const base::Closure& callback,
    const ShillClientHelper::ErrorCallback& error_callback) {
  dbus::MethodCall method_call(shill::kFlimflamThirdPartyVpnInterface,
                               shill::kSendPacketFunction);
  dbus::MessageWriter writer(&method_call);
  static_assert(sizeof(uint8_t) == sizeof(char),
                "Can't reinterpret ip_packet if char is not 8 bit large.");
  writer.AppendArrayOfBytes(reinterpret_cast<const uint8_t*>(ip_packet.data()),
                            ip_packet.size());
  GetHelper(object_path_value)
      ->CallVoidMethodWithErrorCallback(&method_call, callback, error_callback);
}

// static
void ShillThirdPartyVpnDriverClientImpl::OnPacketReceived(
    base::WeakPtr<HelperInfo> helper_info,
    dbus::Signal* signal) {
  if (!helper_info || !helper_info->observer())
    return;

  dbus::MessageReader reader(signal);
  const uint8_t* data = nullptr;
  size_t length = 0;
  if (reader.PopArrayOfBytes(&data, &length)) {
    helper_info->observer()->OnPacketReceived(
        std::vector<char>(data, data + length));
  }
}

// static
void ShillThirdPartyVpnDriverClientImpl::OnPlatformMessage(
    base::WeakPtr<HelperInfo> helper_info,
    dbus::Signal* signal) {
  if (!helper_info || !helper_info->observer())
    return;

  dbus::MessageReader reader(signal);
  uint32_t platform_message = 0;
  if (reader.PopUint32(&platform_message))
    helper_info->observer()->OnPlatformMessage(platform_message);
}

// static
void ShillThirdPartyVpnDriverClientImpl::OnSignalConnected(
    const std::string& interface,
    const std::string& signal,
    bool success) {
  LOG_IF(ERROR, !success) << "Connect to " << interface << " " << signal
                          << " failed.";
}

ShillClientHelper* ShillThirdPartyVpnDriverClientImpl::GetHelper(
    const std::string& object_path_value) {
  return GetHelperInfo(object_path_value)->helper();
}

ShillThirdPartyVpnDriverClientImpl::HelperInfo*
ShillThirdPartyVpnDriverClientImpl::FindHelperInfo(
    const dbus::ObjectPath& object_path) {
  HelperMap::iterator it = helpers_.find(object_path.value());
  return (it != helpers_.end()) ? it->second : nullptr;
}

ShillThirdPartyVpnDriverClientImpl::HelperInfo*
ShillThirdPartyVpnDriverClientImpl::GetHelperInfo(
    const std::string& object_path_value) {
  dbus::ObjectPath object_path(object_path_value);
  HelperInfo* helper_info = FindHelperInfo(object_path);
  if (helper_info)
    return helper_info;

  // There is no helper for the profile, create it.
  dbus::ObjectProxy* object_proxy =
      bus_->GetObjectProxy(shill::kFlimflamServiceName, object_path);
  helper_info = new HelperInfo(object_proxy);
  helpers_[object_path_value] = helper_info;
  return helper_info;
}

}  // namespace

ShillThirdPartyVpnDriverClient::ShillThirdPartyVpnDriverClient() = default;

ShillThirdPartyVpnDriverClient::~ShillThirdPartyVpnDriverClient() = default;

// static
ShillThirdPartyVpnDriverClient* ShillThirdPartyVpnDriverClient::Create() {
  return new ShillThirdPartyVpnDriverClientImpl();
}

}  // namespace chromeos
