// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "secagentd/message_sender.h"

#include <memory>
#include <string>
#include <utility>

#include "absl/status/status.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/json/string_escape.h"
#include "base/logging.h"
#include "base/synchronization/lock.h"
#include "base/task/sequenced_task_runner.h"
#include "google/protobuf/message_lite.h"
#include "missive/client/report_queue.h"
#include "missive/client/report_queue_configuration.h"
#include "missive/client/report_queue_factory.h"
#include "missive/proto/record_constants.pb.h"
#include "missive/util/status.h"
#include "re2/re2.h"
#include "secagentd/metrics_sender.h"
#include "secagentd/proto/security_xdr_events.pb.h"

namespace secagentd {

namespace pb = cros_xdr::reporting;

namespace {

void SendMessageStatusCallback(
    reporting::Destination destination,
    std::optional<reporting::ReportQueue::EnqueueCallback> cb,
    reporting::Status status) {
  metrics::SendMessage send_message_metric = metrics::SendMessage::kSuccess;
  if (!status.ok()) {
    LOG(ERROR) << destination << ", status=" << status;
    send_message_metric =
        static_cast<metrics::SendMessage>(status.error_code());
  }
  MetricsSender::GetInstance().IncrementBatchedMetric(metrics::kSendMessage,
                                                      send_message_metric);

  if (cb.has_value()) {
    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE, base::BindOnce(std::move(cb.value()), status));
  }
}

void VlogEventForDebug(reporting::Destination destination,
                       google::protobuf::MessageLite* message) {
  switch (destination) {
    case reporting::CROS_SECURITY_AGENT: {
      auto agent_event =
          google::protobuf::internal::DownCast<pb::XdrAgentEvent*>(message);
      VLOG(1) << "XdrAgentEvent:";
      VLOG(1) << agent_event->DebugString();
      break;
    }
    case reporting::CROS_SECURITY_PROCESS: {
      auto process_event =
          google::protobuf::internal::DownCast<pb::XdrProcessEvent*>(message);
      VLOG(1) << "XdrProcessEvent:";
      VLOG(1) << process_event->DebugString();
      break;
    }
    case reporting::CROS_SECURITY_NETWORK: {
      auto network_event =
          google::protobuf::internal::DownCast<pb::XdrNetworkEvent*>(message);
      VLOG(1) << "XdrNetworkEvent:";
      VLOG(1) << network_event->DebugString();
      break;
    }
    case reporting::CROS_SECURITY_USER: {
      auto authenticate_event =
          google::protobuf::internal::DownCast<pb::XdrUserEvent*>(message);
      VLOG(1) << "XdrUserEvent:";
      VLOG(1) << authenticate_event->DebugString();
      break;
    }
    default:
      LOG(ERROR) << "Unknown destination: " << destination;
  }
  VLOG(1) << "Raw serialized message:";
  // GetQuotedJSONString just escapes the given string for cleaner output.
  // There's no actual JSON conversion happening here.
  VLOG(1) << base::GetQuotedJSONString(message->SerializeAsString());
}

}  // namespace

MessageSender::MessageSender(const base::FilePath& root_path)
    : root_path_(root_path) {}

MessageSender::MessageSender() : MessageSender(base::FilePath("/")) {}

void MessageSender::UpdateDeviceTz(const base::FilePath& timezone_symlink,
                                   bool error) {
  static constexpr char kTimezoneFilesDir[] = "usr/share/zoneinfo/";
  if (error) {
    LOG(ERROR) << "TZ symlink watch was aborted due to a system error.";
    return;
  }
  const base::FilePath zoneinfo_dir = root_path_.Append(kTimezoneFilesDir);
  base::FilePath timezone_file;
  if (!base::ReadSymbolicLink(timezone_symlink, &timezone_file)) {
    LOG(ERROR) << "Failed to resolve symlink at " << timezone_symlink.value();
    return;
  }
  base::FilePath relpath;
  if (!zoneinfo_dir.AppendRelativePath(timezone_file, &relpath)) {
    LOG(ERROR) << "Failed to find relative zoneinfo path of "
               << timezone_file.value();
    return;
  }
  base::AutoLock lock(common_lock_);
  common_.set_local_timezone(relpath.value());
  LOG(INFO) << "Device timezone set to " << relpath.value();
}

void MessageSender::InitializeDeviceBtime() {
  static constexpr char kProcStatFile[] = "proc/stat";
  static constexpr char kProcStatBtimePattern[] = R"(\nbtime (\d+)\n)";
  static const re2::LazyRE2 kStatBtimeRe = {kProcStatBtimePattern};

  const base::FilePath proc_stat_file(kProcStatFile);
  // Base doesn't have a ReadLine-ey helper. /proc/stat does scale with the
  // number of CPU threads but shouldn't be too bad on a mobile/desktop.
  // Around 1.5K on a 8-thread CPU. This is a one-time parse at startup.
  std::string proc_stat_contents;
  int64_t btime;
  if ((!base::ReadFileToString(root_path_.Append(kProcStatFile),
                               &proc_stat_contents)) ||
      (!RE2::PartialMatch(proc_stat_contents, *kStatBtimeRe, &btime))) {
    LOG(ERROR) << "Failed to parse boot time from " << kProcStatFile;
    return;
  }
  base::AutoLock lock(common_lock_);
  common_.set_device_boot_time(btime);
  LOG(INFO) << "Set device boot time to " << btime;
}

void MessageSender::InitializeAndWatchDeviceTz() {
  static constexpr char kTimezoneSymlink[] = "var/lib/timezone/localtime";
  const base::FilePath timezone_symlink = root_path_.Append(kTimezoneSymlink);
  UpdateDeviceTz(base::FilePath(timezone_symlink), false);
  if (!common_file_watcher_.Watch(
          timezone_symlink, base::FilePathWatcher::Type::kNonRecursive,
          base::BindRepeating(&MessageSender::UpdateDeviceTz,
                              base::Unretained(this)))) {
    LOG(ERROR) << "Failed to add a file watch on " << timezone_symlink.value();
  }
}

absl::Status MessageSender::InitializeQueues() {
  // Array of possible destinations.
  const reporting::Destination kDestinations[] = {
      reporting::CROS_SECURITY_NETWORK, reporting::CROS_SECURITY_PROCESS,
      reporting::CROS_SECURITY_AGENT, reporting::CROS_SECURITY_USER};

  for (auto destination : kDestinations) {
    auto report_queue_result =
        reporting::ReportQueueFactory::CreateSpeculativeReportQueue(
            reporting::EventType::kDevice, destination);

    if (report_queue_result == nullptr) {
      return absl::InternalError(
          "InitializeQueues: Report queue failed to create");
    }
    queue_map_.insert(
        std::make_pair(destination, std::move(report_queue_result)));
  }
  return absl::OkStatus();
}

absl::Status MessageSender::Initialize() {
  // We don't care as much about common fields as we do about errors in creating
  // the message queues.
  InitializeDeviceBtime();
  InitializeAndWatchDeviceTz();
  return InitializeQueues();
}

void MessageSender::SendMessage(
    reporting::Destination destination,
    pb::CommonEventDataFields* mutable_common,
    std::unique_ptr<google::protobuf::MessageLite> message,
    std::optional<reporting::ReportQueue::EnqueueCallback> cb) {
  auto it = queue_map_.find(destination);
  CHECK(it != queue_map_.end());

  if (mutable_common) {
    base::AutoLock lock(common_lock_);
    mutable_common->CopyFrom(common_);
  }

  if (logging::GetVlogVerbosity() > 0) {
    VlogEventForDebug(destination, message.get());
  }
  it->second.get()->Enqueue(
      std::move(message), reporting::SLOW_BATCH,
      base::BindOnce(&SendMessageStatusCallback, destination, std::move(cb)));
}

}  // namespace secagentd
