// Copyright 2018 The Fuchsia 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 "src/developer/debug/debug_agent/debugged_job.h"

#include <lib/syslog/cpp/macros.h>

#include "src/developer/debug/debug_agent/zircon_process_handle.h"
#include "src/developer/debug/shared/component_utils.h"
#include "src/developer/debug/shared/logging/logging.h"
#include "src/developer/debug/shared/platform_message_loop.h"
#include "src/developer/debug/shared/regex.h"
#include "src/developer/debug/shared/zx_status.h"

namespace debug_agent {

DebuggedJob::DebuggedJob(ProcessStartHandler* handler, std::unique_ptr<JobHandle> job_handle)
    : handler_(handler), job_handle_(std::move(job_handle)) {}

DebuggedJob::~DebuggedJob() = default;

zx_status_t DebuggedJob::Init() {
  debug_ipc::MessageLoopTarget* loop = debug_ipc::MessageLoopTarget::Current();
  FX_DCHECK(loop);  // Loop must be created on this thread first.

  // Register for debug exceptions.
  debug_ipc::MessageLoopTarget::WatchJobConfig config;
  config.job_name = job_handle_->GetName();
  config.job_handle = job_handle_->GetNativeHandle().get();
  config.job_koid = koid();
  config.watcher = this;
  return loop->WatchJobExceptions(std::move(config), &job_watch_handle_);
}

bool DebuggedJob::FilterInfo::Matches(const std::string& proc_name) {
  if (regex.valid()) {
    return regex.Match(proc_name);
  }

  // TODO(DX-953): Job filters should always be valid.
  return proc_name.find(filter) != std::string::npos;
}

void DebuggedJob::OnProcessStarting(zx::exception exception_token,
                                    zx_exception_info_t exception_info) {
  // TODO(brettw) convert this to ExceptionHandle.
  zx_handle_t zircon_handle = ZX_HANDLE_INVALID;
  zx_status_t status = zx_exception_get_process(exception_token.get(), &zircon_handle);
  FX_DCHECK(status == ZX_OK) << "Got: " << debug_ipc::ZxStatusToString(status);

  std::unique_ptr<ProcessHandle> process =
      std::make_unique<ZirconProcessHandle>(zx::process(zircon_handle));
  auto proc_name = process->GetName();

  // Tools like fx serve will connect every second or so to the target, spamming logging for this
  // with a lot of "/boot/bin/sh" starting. We filter this out as it makes debugging much harder.
  if (proc_name != "/boot/bin/sh") {
    DEBUG_LOG(Job) << "Debugged job " << koid() << ": Process " << proc_name << " starting.";
  }

  // Search through the available filters. If the regex is not valid, fallback to checking if
  // |proc_name| contains the filter.
  FilterInfo* matching_filter = nullptr;
  for (auto& filter : filters_) {
    if (filter.Matches(proc_name)) {
      matching_filter = &filter;
      break;
    }
  }

  if (matching_filter) {
    DEBUG_LOG(Job) << "Filter " << matching_filter->filter << " matches process " << proc_name
                   << ". Attaching.";
    handler_->OnProcessStart(matching_filter->filter, std::move(process));
  }

  // Attached to the process. At that point it will get a new thread notification for the initial
  // thread which it can stop or continue as it desires. Therefore, we can always resume the thread
  // in the "new process" exception.
  //
  // Technically it's not necessary to reset the handle, but being explicit here helps readability.
  exception_token.reset();
}

void DebuggedJob::ApplyToJob(FilterInfo& filter, JobHandle& job, ProcessHandleSetByKoid& matches) {
  for (std::unique_ptr<ProcessHandle>& proc : job.GetChildProcesses()) {
    if (filter.Matches(proc->GetName())) {
      DEBUG_LOG(Job) << "Filter " << filter.filter << " matches process " << proc->GetName();
      matches.insert(std::move(proc));
    }
  }

  for (std::unique_ptr<JobHandle>& child_job : job.GetChildJobs())
    ApplyToJob(filter, *child_job, matches);
}

DebuggedJob::ProcessHandleSetByKoid DebuggedJob::SetFilters(std::vector<std::string> filters) {
  filters_.clear();
  filters_.reserve(filters.size());

  ProcessHandleSetByKoid matches;

  for (auto& filter : filters) {
    // We check if this is a package url. If that is the case, me only need the component as a
    // filter, as the whole URL won't match.
    debug_ipc::ComponentDescription desc;
    if (debug_ipc::ExtractComponentFromPackageUrl(filter, &desc))
      filter = desc.component_name;

    debug_ipc::Regex regex;
    if (!regex.Init(filter))
      FX_LOGS(WARNING) << "Could not initialize regex for filter " << filter;

    DEBUG_LOG(Job) << "Debug job " << koid() << ": Adding filter " << filter;

    FilterInfo filter_info = {};
    filter_info.filter = std::move(filter);
    filter_info.regex = std::move(regex);
    ApplyToJob(filters_.emplace_back(std::move(filter_info)), *job_handle_, matches);
  }

  return matches;
}

void DebuggedJob::AppendFilter(std::string filter) {
  // We check whether this filter already exists.
  for (auto& existent_filter : filters_) {
    if (existent_filter.filter == filter)
      return;
  }

  debug_ipc::Regex regex;
  if (!regex.Init(filter)) {
    FX_LOGS(WARNING) << "Could not initialize regex for filter " << filter;
  }

  DEBUG_LOG(Job) << "Debugged job " << koid() << ": Appending filter " << filter;

  FilterInfo filter_info = {};
  filter_info.filter = std::move(filter);
  filter_info.regex = std::move(regex);
  filters_.push_back(std::move(filter_info));
}

}  // namespace debug_agent
