// 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 <limits.h>
#include <sys/socket.h>
#include <syslog.h>
#include <unistd.h>

#include <linux/vm_sockets.h>  // Needs to come after sys/socket.h

#include <memory>
#include <string>

// syslog.h and base/logging.h both try to #define LOG_INFO and LOG_WARNING.
// We need to #undef at least these two before including base/logging.h.  The
// others are included to be consistent.
namespace {
const int kSyslogDebug = LOG_DEBUG;
const int kSyslogInfo = LOG_INFO;
const int kSyslogWarning = LOG_WARNING;
const int kSyslogError = LOG_ERR;
const int kSyslogCritical = LOG_CRIT;

#undef LOG_INFO
#undef LOG_WARNING
#undef LOG_ERR
#undef LOG_CRIT
}  // namespace

#include <base/at_exit.h>
#include <base/bind.h>
#include <base/command_line.h>
#include <base/files/file_descriptor_watcher_posix.h>
#include <base/logging.h>
#include <base/message_loop/message_pump_type.h>
#include <base/run_loop.h>
#include <base/strings/stringprintf.h>
#include <base/synchronization/waitable_event.h>
#include <base/task/single_thread_task_executor.h>
#include <base/task_runner.h>
#include <base/threading/thread.h>
#include <vm_protos/proto_bindings/container_guest.grpc.pb.h>
#include <chromeos/constants/vm_tools.h>

#include "vm_tools/garcon/host_notifier.h"
#include "vm_tools/garcon/package_kit_proxy.h"
#include "vm_tools/garcon/service_impl.h"

constexpr char kLogPrefix[] = "garcon: ";
constexpr char kAllowAnyUserSwitch[] = "allow_any_user";
constexpr char kServerSwitch[] = "server";
constexpr char kClientSwitch[] = "client";
constexpr char kUrlSwitch[] = "url";
constexpr char kTerminalSwitch[] = "terminal";
constexpr uint32_t kVsockPortStart = 10000;
constexpr uint32_t kVsockPortEnd = 20000;

constexpr uid_t kCrostiniDefaultUid = 1000;

bool LogToSyslog(logging::LogSeverity severity,
                 const char* /* file */,
                 int /* line */,
                 size_t message_start,
                 const std::string& message) {
  switch (severity) {
    case logging::LOGGING_INFO:
      severity = kSyslogInfo;
      break;
    case logging::LOGGING_WARNING:
      severity = kSyslogWarning;
      break;
    case logging::LOGGING_ERROR:
      severity = kSyslogError;
      break;
    case logging::LOGGING_FATAL:
      severity = kSyslogCritical;
      break;
    default:
      severity = kSyslogDebug;
      break;
  }
  syslog(severity, "%s", message.c_str() + message_start);

  return true;
}

void RunGarconService(vm_tools::garcon::PackageKitProxy* pk_proxy,
                      base::WaitableEvent* event,
                      std::shared_ptr<grpc::Server>* server_copy,
                      int* vsock_listen_port,
                      scoped_refptr<base::TaskRunner> task_runner,
                      vm_tools::garcon::HostNotifier* host_notifier) {
  // We don't want to receive SIGTERM on this thread.
  sigset_t mask;
  sigemptyset(&mask);
  sigaddset(&mask, SIGTERM);
  sigprocmask(SIG_BLOCK, &mask, nullptr);

  // See crbug.com/922694 for more reference.
  // There's a bug in our patched version of gRPC where it uses signed integers
  // for ports. VSOCK uses unsigned integers for ports. So if we let the kernel
  // choose the port for us, then it can end up choosing one that has the high
  // bit set and cause gRPC to assert on the negative port number. This was a
  // much easier solution than patching gRPC or updating the kernel to keep the
  // VSOCK ports in the signed integer range.
  // The end on this for loop only exists to prevent running forever in case
  // something else goes wrong.
  for (*vsock_listen_port = kVsockPortStart; *vsock_listen_port < kVsockPortEnd;
       ++(*vsock_listen_port)) {
    // Build the server.
    grpc::ServerBuilder builder;
    builder.AddListeningPort(
        base::StringPrintf("vsock:%u:%d", VMADDR_CID_ANY, *vsock_listen_port),
        grpc::InsecureServerCredentials(), nullptr);

    vm_tools::garcon::ServiceImpl garcon_service(pk_proxy, task_runner.get(),
                                                 host_notifier);
    builder.RegisterService(&garcon_service);

    std::shared_ptr<grpc::Server> server(builder.BuildAndStart().release());
    if (!server) {
      LOG(WARNING) << "garcon failed binding requested vsock port "
                   << *vsock_listen_port << ", trying again with a new port";
      continue;
    }

    *server_copy = server;
    event->Signal();

    LOG(INFO) << "Server listening on vsock port " << *vsock_listen_port;
    // The following call will return once we invoke Shutdown on the gRPC
    // server when the main RunLoop exits.
    server->Wait();
    break;
  }
}

void CreatePackageKitProxy(
    base::WaitableEvent* event,
    vm_tools::garcon::HostNotifier* host_notifier,
    std::unique_ptr<vm_tools::garcon::PackageKitProxy>* proxy_ptr) {
  // We don't want to receive SIGTERM on this thread.
  sigset_t mask;
  sigemptyset(&mask);
  sigaddset(&mask, SIGTERM);
  sigprocmask(SIG_BLOCK, &mask, nullptr);

  *proxy_ptr = vm_tools::garcon::PackageKitProxy::Create(host_notifier);
  event->Signal();
}

void PrintUsage() {
  LOG(INFO) << "Garcon: VM container bridge for Chrome OS\n\n"
            << "Mode Switches (must use one):\n"
            << "Mode Switch:\n"
            << "  --server: run in background as daemon\n"
            << "  --client: run as client and send message to host\n"
            << "Client Switches (only with --client):\n"
            << "  --url: opens all arguments as URLs in host browser\n"
            << "Server Switches (only with --server):\n"
            << "  --allow_any_user: allow running as non-default uid\n";
}

int main(int argc, char** argv) {
  base::AtExitManager at_exit;
  base::SingleThreadTaskExecutor task_executor(base::MessagePumpType::IO);
  base::FileDescriptorWatcher watcher(task_executor.task_runner());
  base::CommandLine::Init(argc, argv);
  base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
  logging::InitLogging(logging::LoggingSettings());

  bool serverMode = cl->HasSwitch(kServerSwitch);
  bool clientMode = cl->HasSwitch(kClientSwitch);
  // The standard says that bool to int conversion is implicit and that
  // false => 0 and true => 1.
  // clang-format off
  if (serverMode + clientMode != 1) {
    // clang-format on
    LOG(ERROR) << "Exactly one of --server or --client must be used.";
    PrintUsage();
    return -1;
  }

  if (clientMode) {
    if (cl->HasSwitch(kUrlSwitch)) {
      std::vector<std::string> args = cl->GetArgs();
      if (args.empty()) {
        LOG(ERROR) << "Missing URL arguments in --url mode";
        PrintUsage();
        return -1;
      }
      // All arguments are URLs, send them to the host to be opened. The host
      // will do its own verification for validity of the URLs.
      for (const auto& arg : args) {
        if (!vm_tools::garcon::HostNotifier::OpenUrlInHost(arg)) {
          return -1;
        }
      }
      return 0;
    } else if (cl->HasSwitch(kTerminalSwitch)) {
      std::vector<std::string> args = cl->GetArgs();
      if (vm_tools::garcon::HostNotifier::OpenTerminal(std::move(args)))
        return 0;
      else
        return -1;
    }
    LOG(ERROR) << "Missing client switch for client mode.";
    PrintUsage();
    return -1;
  }

  // Set up logging to syslog for server mode.
  openlog(kLogPrefix, LOG_PID, LOG_DAEMON);
  logging::SetLogMessageHandler(LogToSyslog);

  // Exit if not running as the container default user.
  if (getuid() != kCrostiniDefaultUid && !cl->HasSwitch(kAllowAnyUserSwitch)) {
    LOG(ERROR) << "garcon normally runs only as uid(" << kCrostiniDefaultUid
               << "). Use --allow_any_user to override";
    return -1;
  }

  // Note on threading model. There are 4 threads used in garcon. One is for the
  // incoming gRPC requests. One is for the D-Bus communication with the
  // PackageKit daemon. The third is the main thread which is for gRPC requests
  // to the host as well as for monitoring filesystem changes (which result in a
  // gRPC call to the host under certain conditions). The main thing to be
  // careful of is that the gRPC thread for incoming requests is never blocking
  // on the gRPC thread for outgoing requests (since they are both talking to
  // cicerone, and both of those operations in cicerone are likely going to use
  // the same D-Bus thread for communication within cicerone). The fourth thread
  // is for running tasks initiated by garcon service.

  // Thread that the gRPC server is running on.
  base::Thread grpc_thread{"gRPC Server Thread"};
  if (!grpc_thread.Start()) {
    LOG(ERROR) << "Failed starting the gRPC thread";
    return -1;
  }

  // Thread that D-Bus communication runs on.
  base::Thread dbus_thread{"D-Bus Thread"};
  if (!dbus_thread.StartWithOptions(
          base::Thread::Options(base::MessagePumpType::IO, 0))) {
    LOG(ERROR) << "Failed starting the D-Bus thread";
    return -1;
  }

  // Thread that tasks started from garcon service run on.
  // Specifically, Ansible playbook application runs on
  // |garcon_service_tasks_thread|.
  base::Thread garcon_service_tasks_thread{"Garcon Service Tasks Thread"};
  if (!garcon_service_tasks_thread.StartWithOptions(
          base::Thread::Options(base::MessagePumpType::IO, 0))) {
    LOG(ERROR) << "Failed starting the garcon service tasks thread";
    return -1;
  }

  // Setup the HostNotifier on the run loop for the main thread. It needs to
  // have its own run loop separate from the gRPC server & D-Bus server since it
  // will be using base::FilePathWatcher to identify installed application and
  // mime type changes.
  base::RunLoop run_loop;

  std::unique_ptr<vm_tools::garcon::HostNotifier> host_notifier =
      vm_tools::garcon::HostNotifier::Create(run_loop.QuitClosure());
  if (!host_notifier) {
    LOG(ERROR) << "Failure setting up the HostNotifier";
    return -1;
  }

  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                            base::WaitableEvent::InitialState::NOT_SIGNALED);

  // This needs to be created on the D-Bus thread.
  std::unique_ptr<vm_tools::garcon::PackageKitProxy> pk_proxy;
  bool ret = dbus_thread.task_runner()->PostTask(
      FROM_HERE, base::Bind(&CreatePackageKitProxy, &event, host_notifier.get(),
                            &pk_proxy));
  if (!ret) {
    LOG(ERROR) << "Failed to post PackageKit proxy creation to D-Bus thread";
    return -1;
  }
  // Wait for the creation to complete.
  event.Wait();
  if (!pk_proxy) {
    LOG(ERROR) << "Failed in creating the PackageKit proxy";
    return -1;
  }
  event.Reset();

  // Launch the gRPC server on the gRPC thread.
  std::shared_ptr<grpc::Server> server_copy;
  int vsock_listen_port = 0;
  ret = grpc_thread.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&RunGarconService, pk_proxy.get(), &event, &server_copy,
                 &vsock_listen_port, garcon_service_tasks_thread.task_runner(),
                 host_notifier.get()));
  if (!ret) {
    LOG(ERROR) << "Failed to post server startup task to grpc thread";
    return -1;
  }

  // Wait for the gRPC server to start.
  event.Wait();

  if (!server_copy) {
    LOG(ERROR) << "gRPC server failed to start";
    return -1;
  }

  if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
    PLOG(ERROR) << "Unable to explicitly ignore SIGCHILD";
    return -1;
  }

  if (!host_notifier->Init(static_cast<uint32_t>(vsock_listen_port),
                           pk_proxy.get())) {
    LOG(ERROR) << "Failed to set up host notifier";
    return -1;
  }

  // Start the main run loop now for the HostNotifier.
  run_loop.Run();

  // We get here after a SIGTERM gets posted and the main run loop has exited.
  // We then shutdown the gRPC server (which will terminate that thread) and
  // then stop the D-Bus thread. We will be the only remaining thread at that
  // point so everything can be safely destructed and we remove the need for
  // any weak pointers.
  server_copy->Shutdown();
  dbus_thread.Stop();
  garcon_service_tasks_thread.Stop();
  return 0;
}
