// Copyright (c) 2012 The Chromium OS 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 "wimax_manager/gdm_device.h"

#include <set>
#include <vector>

#include <base/logging.h>
#include <base/memory/scoped_vector.h>
#include <base/stl_util.h>
#include <base/string_util.h>
#include <chromeos/dbus/service_constants.h>

#include "wimax_manager/device_dbus_adaptor.h"
#include "wimax_manager/gdm_driver.h"
#include "wimax_manager/manager.h"
#include "wimax_manager/network.h"
#include "wimax_manager/network_dbus_adaptor.h"
#include "wimax_manager/proto_bindings/eap_parameters.pb.h"
#include "wimax_manager/proto_bindings/network_operator.pb.h"
#include "wimax_manager/utility.h"

using base::DictionaryValue;
using std::set;
using std::string;
using std::vector;

namespace wimax_manager {

namespace {

// Timeout for connecting to a network.
const int kConnectTimeoutInSeconds = 60;
// Initial network scan interval, in seconds, after the device is enabled.
const int kInitialNetworkScanIntervalInSeconds = 1;
// Default time interval, in seconds, between status updates when the device
// is connecting to a network.
const int kStatusUpdateIntervalDuringConnectInSeconds = 1;

const char kRealmTag[] = "@${realm}";

bool ExtractStringParameter(const DictionaryValue &parameters,
                            const string &key,
                            const string &default_value,
                            string *value) {
  if (!parameters.HasKey(key)) {
    *value = default_value;
    return true;
  }

  if (parameters.GetString(key, value))
    return true;

  return false;
}

template <size_t N>
bool CopyStringToUInt8Array(const string &value, UINT8 (&uint8_array)[N]) {
  size_t value_length = value.length();
  if (value_length >= N)
    return false;

  char *char_array = reinterpret_cast<char *>(uint8_array);
  value.copy(char_array, value_length);
  char_array[value_length] = '\0';
  return true;
}

const char *GetEAPTypeString(GCT_API_EAP_TYPE eap_type) {
  switch (eap_type) {
    case GCT_WIMAX_NO_EAP:
      return "No EAP";
    case GCT_WIMAX_EAP_TLS:
      return "TLS";
    case GCT_WIMAX_EAP_TTLS_MD5:
      return "TTLS/MD5";
    case GCT_WIMAX_EAP_TTLS_MSCHAPV2:
      return "TTLS/MS-CHAP v2";
    case GCT_WIMAX_EAP_TTLS_CHAP:
      return "TTLS/CHAP";
    case GCT_WIMAX_EAP_AKA:
      return "AKA";
    default:
      return "Unknown";
  }
}

const char *MaskString(const char *value) {
  return (value && value[0]) ? "<***>" : "";
}

gboolean OnInitialNetworkScan(gpointer data) {
  CHECK(data);

  reinterpret_cast<GdmDevice *>(data)->InitialScanNetworks();

  // Return FALSE as this is a one-shot update.
  return FALSE;
}

gboolean OnNetworkScan(gpointer data) {
  CHECK(data);

  reinterpret_cast<GdmDevice *>(data)->ScanNetworks();

  // Return TRUE to keep calling this function repeatedly.
  return TRUE;
}

gboolean OnStatusUpdate(gpointer data) {
  CHECK(data);

  reinterpret_cast<GdmDevice *>(data)->UpdateStatus();

  // Return TRUE to keep calling this function repeatedly.
  return TRUE;
}

gboolean OnDeferredStatusUpdate(gpointer data) {
  CHECK(data);

  reinterpret_cast<GdmDevice *>(data)->dbus_adaptor()->UpdateStatus();

  // Return FALSE as this is a one-shot update.
  return FALSE;
}

gboolean OnConnectTimeout(gpointer data) {
  CHECK(data);

  reinterpret_cast<GdmDevice *>(data)->CancelConnectOnTimeout();

  // Return FALSE as this is a one-shot update.
  return FALSE;
}

gboolean OnDeferredRestoreStatusUpdateInterval(gpointer data) {
  CHECK(data);

  reinterpret_cast<GdmDevice *>(data)->RestoreStatusUpdateInterval();

  // Return FALSE as this is a one-shot update.
  return FALSE;
}

}  // namespace

GdmDevice::GdmDevice(Manager *manager, uint8 index, const string &name,
                     const base::WeakPtr<GdmDriver> &driver)
    : Device(manager, index, name),
      driver_(driver),
      open_(false),
      connection_progress_(WIMAX_API_DEVICE_CONNECTION_PROGRESS_Ranging),
      connect_timeout_id_(0),
      initial_network_scan_timeout_id_(0),
      network_scan_timeout_id_(0),
      status_update_timeout_id_(0),
      restore_status_update_interval_timeout_id_(0),
      restore_status_update_interval_(false),
      current_network_identifier_(Network::kInvalidIdentifier) {
}

GdmDevice::~GdmDevice() {
  Disable();
  Close();
}

bool GdmDevice::Open() {
  if (!driver_)
    return false;

  if (open_)
    return true;

  if (!driver_->OpenDevice(this)) {
    LOG(ERROR) << "Failed to open device '" << name() << "'";
    return false;
  }

  open_ = true;
  return true;
}

bool GdmDevice::Close() {
  if (!driver_)
    return false;

  if (!open_)
    return true;

  if (!driver_->CloseDevice(this)) {
    LOG(ERROR) << "Failed to close device '" << name() << "'";
    return false;
  }

  ClearCurrentConnectionProfile();

  open_ = false;
  return true;
}

bool GdmDevice::Enable() {
  if (!Open())
    return false;

  if (!driver_->GetDeviceStatus(this)) {
    LOG(ERROR) << "Failed to get status of device '" << name() << "'";
    return false;
  }

  if (!driver_->AutoSelectProfileForDevice(this)) {
    LOG(ERROR) << "Failed to auto select profile for device '" << name() << "'";
    return false;
  }

  if (!driver_->PowerOnDeviceRF(this)) {
    LOG(ERROR) << "Failed to power on RF of device '" << name() << "'";
    return false;
  }

  if (!driver_->SetScanInterval(this, network_scan_interval())) {
    LOG(WARNING) << "Failed to set internal network scan by SDK.";
  }

  // Schedule an initial network scan shortly after the device is enabled.
  if (initial_network_scan_timeout_id_ != 0) {
    g_source_remove(initial_network_scan_timeout_id_);
  }
  initial_network_scan_timeout_id_ = g_timeout_add_seconds(
      kInitialNetworkScanIntervalInSeconds, OnInitialNetworkScan, this);

  // Set OnNetworkScan() to be called repeatedly at |network_scan_interval_|
  // intervals to scan and update the list of networks via ScanNetworks().
  //
  // TODO(benchan): Refactor common functionalities like periodic network scan
  // to the Device base class.
  if (network_scan_timeout_id_ != 0) {
    g_source_remove(network_scan_timeout_id_);
  }
  network_scan_timeout_id_ =
      g_timeout_add_seconds(network_scan_interval(), OnNetworkScan, this);

  if (status_update_timeout_id_ != 0) {
    g_source_remove(status_update_timeout_id_);
  }
  status_update_timeout_id_ =
      g_timeout_add_seconds(status_update_interval(), OnStatusUpdate, this);

  if (!driver_->GetDeviceStatus(this)) {
    LOG(ERROR) << "Failed to get status of device '" << name() << "'";
    return false;
  }
  return true;
}

bool GdmDevice::Disable() {
  if (!driver_ || !open_)
    return false;

  ClearCurrentConnectionProfile();

  CancelRestoreStatusUpdateIntervalTimeout();
  RestoreStatusUpdateInterval();

  // Cancel any pending connect timeout.
  if (connect_timeout_id_ != 0) {
    g_source_remove(connect_timeout_id_);
    connect_timeout_id_ = 0;
  }

  // Cancel the periodic calls to OnNetworkScan().
  if (initial_network_scan_timeout_id_ != 0) {
    g_source_remove(initial_network_scan_timeout_id_);
    initial_network_scan_timeout_id_ = 0;
  }
  if (network_scan_timeout_id_ != 0) {
    g_source_remove(network_scan_timeout_id_);
    network_scan_timeout_id_ = 0;
  }

  // Cancel the periodic calls to OnStatusUpdate().
  if (status_update_timeout_id_ != 0) {
    g_source_remove(status_update_timeout_id_);
    status_update_timeout_id_ = 0;
  }

  NetworkMap *networks = mutable_networks();
  if (!networks->empty()) {
    networks->clear();
    UpdateNetworks();
  }

  if (!driver_->PowerOffDeviceRF(this)) {
    LOG(ERROR) << "Failed to power off RF of device '" << name() << "'";
    return false;
  }

  if (!driver_->GetDeviceStatus(this)) {
    LOG(ERROR) << "Failed to get status of device '" << name() << "'";
    return false;
  }
  return true;
}

bool GdmDevice::InitialScanNetworks() {
  initial_network_scan_timeout_id_ = 0;
  return ScanNetworks();
}

bool GdmDevice::ScanNetworks() {
  if (!Open())
    return false;

  vector<NetworkRefPtr> scanned_networks;
  if (!driver_->GetNetworksForDevice(this, &scanned_networks)) {
    LOG(WARNING) << "Failed to get list of networks for device '"
                 << name() << "'";
    // Ignore error and wait for next scan.
    return true;
  }

  bool networks_added = false;
  NetworkMap *networks = mutable_networks();
  set<Network::Identifier> networks_to_remove = GetKeysOfMap(*networks);

  for (size_t i = 0; i < scanned_networks.size(); ++i) {
    Network::Identifier identifier = scanned_networks[i]->identifier();
    NetworkMap::iterator network_iterator = networks->find(identifier);
    if (network_iterator == networks->end()) {
      // Add a newly found network.
      scanned_networks[i]->CreateDBusAdaptor();
      (*networks)[identifier] = scanned_networks[i];
      networks_added = true;
    } else {
      // Update an existing network.
      network_iterator->second->UpdateFrom(*scanned_networks[i]);
    }
    networks_to_remove.erase(identifier);
  }

  // Remove networks that disappeared.
  RemoveKeysFromMap(networks, networks_to_remove);

  // Only call UpdateNetworks(), which emits NetworksChanged signal, when
  // a network is added or removed.
  if (networks_added || !networks_to_remove.empty())
    UpdateNetworks();

  return true;
}

bool GdmDevice::UpdateStatus() {
  if (!driver_->GetDeviceStatus(this)) {
    LOG(ERROR) << "Failed to get status of device '" << name() << "'";
    return false;
  }

  // Cancel the timeout for connect and restore status update interval
  // if the device is no longer in the 'connecting' state.
  if (connect_timeout_id_ != 0 && status() != kDeviceStatusConnecting) {
    LOG(INFO) << "Disable connect timeout.";
    g_source_remove(connect_timeout_id_);
    connect_timeout_id_ = 0;

    CancelRestoreStatusUpdateIntervalTimeout();
    if (restore_status_update_interval_) {
      restore_status_update_interval_timeout_id_ =
          g_timeout_add_seconds(1, OnDeferredRestoreStatusUpdateInterval, this);
    }
  }

  if (!driver_->GetDeviceRFInfo(this)) {
    LOG(ERROR) << "Failed to get RF information of device '" << name() << "'";
    return false;
  }
  return true;
}

void GdmDevice::UpdateNetworkScanInterval(uint32 network_scan_interval) {
  if (network_scan_timeout_id_ != 0) {
    LOG(INFO) << "Update network scan interval to " << network_scan_interval
              << "s.";
    g_source_remove(network_scan_timeout_id_);
    network_scan_timeout_id_ =
        g_timeout_add_seconds(network_scan_interval, OnNetworkScan, this);

    if (!driver_->SetScanInterval(this, network_scan_interval)) {
      LOG(WARNING) << "Failed to set internal network scan by SDK.";
    }
  }
}

void GdmDevice::UpdateStatusUpdateInterval(uint32 status_update_interval) {
  if (status_update_timeout_id_ != 0) {
    LOG(INFO) << "Update status update interval to " << status_update_interval
              << "s.";
    g_source_remove(status_update_timeout_id_);
    status_update_timeout_id_ =
        g_timeout_add_seconds(status_update_interval, OnStatusUpdate, this);
  }
}

void GdmDevice::RestoreStatusUpdateInterval() {
  if (!restore_status_update_interval_)
    return;

  UpdateStatusUpdateInterval(status_update_interval());
  restore_status_update_interval_ = false;
  restore_status_update_interval_timeout_id_ = 0;

  // Restarts the network scan timeout source to be aligned with the status
  // update timeout source, which helps increase the idle time of the device
  // when both sources are fired and served by the device around the same time.
  UpdateNetworkScanInterval(network_scan_interval());
}

bool GdmDevice::Connect(const Network &network,
                        const DictionaryValue &parameters) {
  if (!Open())
    return false;

  if (networks().empty())
    return false;

  if (!driver_->GetDeviceStatus(this)) {
    LOG(ERROR) << "Failed to get status of device '" << name() << "'";
    return false;
  }

  EAPParameters operator_eap_parameters =
      GetNetworkOperatorEAPParameters(network);

  // TODO(benchan): Refactor this code into Device base class.
  string user_identity;
  ExtractStringParameter(parameters,
                         kEAPUserIdentity,
                         operator_eap_parameters.user_identity(),
                         &user_identity);
  if (status() == kDeviceStatusConnecting ||
      status() == kDeviceStatusConnected) {
    if (current_network_identifier_ == network.identifier() &&
        current_user_identity_ == user_identity) {
      // The device status may remain unchanged, schedule a deferred call to
      // DeviceDBusAdaptor::UpdateStatus() to explicitly notify the connection
      // manager about the current device status.
      g_timeout_add_seconds(1, OnDeferredStatusUpdate, this);
      return true;
    }

    if (!driver_->DisconnectDeviceFromNetwork(this)) {
      LOG(ERROR) << "Failed to disconnect device '" << name()
                 << "' from network";
      return false;
    }
  }

  GCT_API_EAP_PARAM eap_parameters;
  if (!ConstructEAPParameters(parameters, operator_eap_parameters,
                              &eap_parameters))
    return false;

  VLOG(1) << "Connect to " << network.GetNameWithIdentifier()
          << " via EAP (Type: " << GetEAPTypeString(eap_parameters.type)
          << ", Anonymous identity: '"
          << MaskString(reinterpret_cast<const char *>(
              eap_parameters.anonymousId))
          << "', User identity: '"
          << MaskString(reinterpret_cast<const char *>(eap_parameters.userId))
          << "', User password: '"
          << MaskString(reinterpret_cast<const char *>(
              eap_parameters.userIdPwd))
          << "', Bypass device certificate: "
          << (eap_parameters.devCertNULL == 0 ? false : true)
          << ", Bypass CA certificate: "
          << (eap_parameters.caCertNULL == 0 ? false : true)
          << ")";

  if (!driver_->SetDeviceEAPParameters(this, &eap_parameters)) {
    LOG(ERROR) << "Failed to set EAP parameters on device '" << name() << "'";
    return false;
  }

  if (!driver_->ConnectDeviceToNetwork(this, network)) {
    LOG(ERROR) << "Failed to connect device '" << name()
               << "' to " << network.GetNameWithIdentifier();
    return false;
  }

  CancelRestoreStatusUpdateIntervalTimeout();
  UpdateStatusUpdateInterval(kStatusUpdateIntervalDuringConnectInSeconds);
  restore_status_update_interval_ = true;

  current_network_identifier_ = network.identifier();
  current_user_identity_ = user_identity;

  // Schedule a timeout to abort the connection attempt in case the device
  // is stuck at the 'connecting' state.
  connect_timeout_id_ =
      g_timeout_add_seconds(kConnectTimeoutInSeconds, OnConnectTimeout, this);

  if (!driver_->GetDeviceStatus(this)) {
    LOG(ERROR) << "Failed to get status of device '" << name() << "'";
    return false;
  }
  return true;
}

bool GdmDevice::Disconnect() {
  if (!driver_ || !open_)
    return false;

  if (!driver_->DisconnectDeviceFromNetwork(this)) {
    LOG(ERROR) << "Failed to disconnect device '" << name() << "' from network";
    return false;
  }

  ClearCurrentConnectionProfile();

  CancelRestoreStatusUpdateIntervalTimeout();
  RestoreStatusUpdateInterval();

  if (!driver_->GetDeviceStatus(this)) {
    LOG(ERROR) << "Failed to get status of device '" << name() << "'";
    return false;
  }
  return true;
}

void GdmDevice::CancelConnectOnTimeout() {
  LOG(WARNING) << "Timed out connecting to the network.";
  connect_timeout_id_ = 0;
  Disconnect();
}

void GdmDevice::CancelRestoreStatusUpdateIntervalTimeout() {
  if (restore_status_update_interval_timeout_id_ != 0) {
    g_source_remove(restore_status_update_interval_timeout_id_);
    restore_status_update_interval_timeout_id_ = 0;
  }
}

void GdmDevice::ClearCurrentConnectionProfile() {
  current_network_identifier_ = Network::kInvalidIdentifier;
  current_user_identity_.clear();
}

// static
bool GdmDevice::ConstructEAPParameters(
    const DictionaryValue &connect_parameters,
    const EAPParameters &operator_eap_parameters,
    GCT_API_EAP_PARAM *eap_parameters) {
  CHECK(eap_parameters);

  memset(eap_parameters, 0, sizeof(GCT_API_EAP_PARAM));
  eap_parameters->fragSize = 1300;
  eap_parameters->logEnable = 1;

  switch (operator_eap_parameters.type()) {
    case EAP_TYPE_TLS:
      eap_parameters->type = GCT_WIMAX_EAP_TLS;
      break;
    case EAP_TYPE_TTLS_MD5:
      eap_parameters->type = GCT_WIMAX_EAP_TTLS_MD5;
      break;
    case EAP_TYPE_TTLS_MSCHAPV2:
      eap_parameters->type = GCT_WIMAX_EAP_TTLS_MSCHAPV2;
      break;
    case EAP_TYPE_TTLS_CHAP:
      eap_parameters->type = GCT_WIMAX_EAP_TTLS_CHAP;
      break;
    case EAP_TYPE_AKA:
      eap_parameters->type = GCT_WIMAX_EAP_AKA;
      break;
    default:
      eap_parameters->type = GCT_WIMAX_NO_EAP;
      break;
  }

  if (operator_eap_parameters.bypass_device_certificate())
    eap_parameters->devCertNULL = 1;

  if (operator_eap_parameters.bypass_ca_certificate())
    eap_parameters->caCertNULL = 1;

  string user_identity;
  if (!ExtractStringParameter(connect_parameters,
                              kEAPUserIdentity,
                              operator_eap_parameters.user_identity(),
                              &user_identity) ||
      !CopyStringToUInt8Array(user_identity, eap_parameters->userId)) {
    LOG(ERROR) << "Invalid EAP user identity";
    return false;
  }

  string user_password;
  if (!ExtractStringParameter(connect_parameters,
                              kEAPUserPassword,
                              operator_eap_parameters.user_password(),
                              &user_password) ||
      !CopyStringToUInt8Array(user_password, eap_parameters->userIdPwd)) {
    LOG(ERROR) << "Invalid EAP user password";
    return false;
  }

  string anonymous_identity;
  if (!ExtractStringParameter(connect_parameters,
                              kEAPAnonymousIdentity,
                              operator_eap_parameters.anonymous_identity(),
                              &anonymous_identity)) {
    LOG(ERROR) << "Invalid EAP anonymous identity";
    return false;
  }

  // If the anonymous identity contains a realm tag ('@${realm}'),
  // replace it with the realm extracted from the user identity.
  string realm;
  size_t realm_pos = user_identity.find('@');
  if (realm_pos != string::npos)
    realm = user_identity.substr(realm_pos);

  ReplaceSubstringsAfterOffset(&anonymous_identity, 0, kRealmTag, realm);

  if (!CopyStringToUInt8Array(anonymous_identity,
                              eap_parameters->anonymousId)) {
    LOG(ERROR) << "Invalid EAP anonymous identity";
    return false;
  }

  return true;
}

EAPParameters GdmDevice::GetNetworkOperatorEAPParameters(
    const Network &network) const {
  const NetworkOperator *network_operator =
      manager()->GetNetworkOperator(network.identifier());
  if (network_operator)
    return network_operator->eap_parameters();

  LOG(INFO) << "No network operator information specified for "
            << network.GetNameWithIdentifier();
  return EAPParameters();
}

}  // namespace wimax_manager
