// Copyright 2018 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 "shill/dbus/chromeos_dhcpcd_listener.h"

#include <string.h>

#include <memory>

#include <base/bind.h>
#include <base/callback.h>
#include <base/strings/stringprintf.h>
#include <brillo/dbus/dbus_method_invoker.h>
#include <dbus/util.h>

#include "shill/dhcp/dhcp_config.h"
#include "shill/dhcp/dhcp_provider.h"
#include "shill/event_dispatcher.h"
#include "shill/logging.h"

using std::string;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kDHCP;
static string ObjectID(ChromeosDHCPCDListener* d) {
  return "(dhcpcd_listener)";
}
}

const char ChromeosDHCPCDListener::kDBusInterfaceName[] = "org.chromium.dhcpcd";
const char ChromeosDHCPCDListener::kSignalEvent[] = "Event";
const char ChromeosDHCPCDListener::kSignalStatusChanged[] = "StatusChanged";

ChromeosDHCPCDListener::ChromeosDHCPCDListener(
    const scoped_refptr<dbus::Bus>& bus,
    EventDispatcher* dispatcher,
    DHCPProvider* provider)
    : bus_(bus),
      dispatcher_(dispatcher),
      provider_(provider),
      match_rule_(base::StringPrintf("type='signal', interface='%s'",
                                     kDBusInterfaceName)) {
  bus_->AssertOnDBusThread();
  CHECK(bus_->SetUpAsyncOperations());
  if (!bus_->IsConnected()) {
    LOG(FATAL) << "DBus isn't connected.";
  }

  // Register filter function to the bus.  It will be called when incoming
  // messages are received.
  bus_->AddFilterFunction(&ChromeosDHCPCDListener::HandleMessageThunk, this);

  // Add match rule to the bus.
  dbus::ScopedDBusError error;
  bus_->AddMatch(match_rule_, error.get());
  if (error.is_set()) {
    LOG(FATAL) << "Failed to add match rule: " << error.name() << " "
               << error.message();
  }
}

ChromeosDHCPCDListener::~ChromeosDHCPCDListener() {
  bus_->RemoveFilterFunction(&ChromeosDHCPCDListener::HandleMessageThunk, this);
  dbus::ScopedDBusError error;
  bus_->RemoveMatch(match_rule_, error.get());
  if (error.is_set()) {
    LOG(FATAL) << "Failed to remove match rule: " << error.name() << " "
               << error.message();
  }
}

// static.
DBusHandlerResult ChromeosDHCPCDListener::HandleMessageThunk(
    DBusConnection* connection, DBusMessage* raw_message, void* user_data) {
  ChromeosDHCPCDListener* self =
      static_cast<ChromeosDHCPCDListener*>(user_data);
  return self->HandleMessage(connection, raw_message);
}

DBusHandlerResult ChromeosDHCPCDListener::HandleMessage(
    DBusConnection* connection, DBusMessage* raw_message) {
  bus_->AssertOnDBusThread();

  // Only interested in signal message.
  if (dbus_message_get_type(raw_message) != DBUS_MESSAGE_TYPE_SIGNAL) {
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  }

  // raw_message will be unrefed in Signal's parent class's (dbus::Message)
  // destructor. Increment the reference so we can use it in Signal.
  dbus_message_ref(raw_message);
  std::unique_ptr<dbus::Signal> signal(
      dbus::Signal::FromRawMessage(raw_message));

  // Verify the signal comes from the interface that we interested in.
  if (signal->GetInterface() != kDBusInterfaceName) {
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  }

  string sender = signal->GetSender();
  string member_name = signal->GetMember();
  dbus::MessageReader reader(signal.get());
  if (member_name == kSignalEvent) {
    uint32_t pid;
    string reason;
    brillo::VariantDictionary configurations;
    // ExtracMessageParameters will log the error if it failed.
    if (brillo::dbus_utils::ExtractMessageParameters(&reader,
                                                     nullptr,
                                                     &pid,
                                                     &reason,
                                                     &configurations)) {
      dispatcher_->PostTask(FROM_HERE,
          base::Bind(&ChromeosDHCPCDListener::EventSignal,
                     weak_factory_.GetWeakPtr(),
                     sender, pid, reason, configurations));
    }
  } else if (member_name == kSignalStatusChanged) {
    uint32_t pid;
    string status;
    // ExtracMessageParameters will log the error if it failed.
    if (brillo::dbus_utils::ExtractMessageParameters(&reader,
                                                     nullptr,
                                                     &pid,
                                                     &status)) {
      dispatcher_->PostTask(FROM_HERE,
          base::Bind(&ChromeosDHCPCDListener::StatusChangedSignal,
                     weak_factory_.GetWeakPtr(),
                     sender, pid, status));
    }
  } else {
    LOG(INFO) << "Ignore signal: " << member_name;
  }

  return DBUS_HANDLER_RESULT_HANDLED;
}

void ChromeosDHCPCDListener::EventSignal(
    const string& sender,
    uint32_t pid,
    const string& reason,
    const brillo::VariantDictionary& configuration) {
  DHCPConfigRefPtr config = provider_->GetConfig(pid);
  if (!config) {
    if (provider_->IsRecentlyUnbound(pid)) {
      SLOG(nullptr, 3)
          << __func__ << ": ignoring message from recently unbound PID " << pid;
    } else {
      LOG(ERROR) << "Unknown DHCP client PID " << pid;
    }
    return;
  }
  config->InitProxy(sender);
  KeyValueStore configuration_store;
  KeyValueStore::ConvertFromVariantDictionary(configuration,
                                              &configuration_store);
  config->ProcessEventSignal(reason, configuration_store);
}

void ChromeosDHCPCDListener::StatusChangedSignal(const string& sender,
                                                 uint32_t pid,
                                                 const string& status) {
  DHCPConfigRefPtr config = provider_->GetConfig(pid);
  if (!config) {
    if (provider_->IsRecentlyUnbound(pid)) {
      SLOG(nullptr, 3)
          << __func__ << ": ignoring message from recently unbound PID " << pid;
    } else {
      LOG(ERROR) << "Unknown DHCP client PID " << pid;
    }
    return;
  }
  config->InitProxy(sender);
  config->ProcessStatusChangeSignal(status);
}

}  // namespace shill
