// 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 "arc/vm/mojo_proxy/mojo_proxy.h"

#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <tuple>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/check.h>
#include <base/files/file_path.h>
#include <base/logging.h>

#include "arc/vm/mojo_proxy/file_descriptor_util.h"
#include "arc/vm/mojo_proxy/local_file.h"

namespace arc {
namespace {

// Path to the ARC bridge socket path.
constexpr char kArcBridgeSocketPath[] = "/run/chrome/arc_bridge.sock";

std::unique_ptr<LocalFile> CreateFile(
    base::ScopedFD fd,
    arc_proxy::FileDescriptor::Type fd_type,
    base::OnceClosure error_handler,
    scoped_refptr<base::TaskRunner> blocking_task_runner) {
  switch (fd_type) {
    case arc_proxy::FileDescriptor::SOCKET_STREAM:
    case arc_proxy::FileDescriptor::SOCKET_DGRAM:
    case arc_proxy::FileDescriptor::SOCKET_SEQPACKET: {
      // Set non-blocking.
      int flags = fcntl(fd.get(), F_GETFL);
      PCHECK(flags != -1);
      flags = fcntl(fd.get(), F_SETFL, flags | O_NONBLOCK);
      PCHECK(flags != -1);
      return std::make_unique<LocalFile>(std::move(fd), true,
                                         std::move(error_handler), nullptr);
    }
    case arc_proxy::FileDescriptor::FIFO_READ:
    case arc_proxy::FileDescriptor::FIFO_WRITE: {
      // Set non-blocking.
      int flags = fcntl(fd.get(), F_GETFL);
      PCHECK(flags != -1);
      flags = fcntl(fd.get(), F_SETFL, flags | O_NONBLOCK);
      PCHECK(flags != -1);
      return std::make_unique<LocalFile>(std::move(fd), false,
                                         std::move(error_handler), nullptr);
    }
    case arc_proxy::FileDescriptor::REGULAR_FILE:
      return std::make_unique<LocalFile>(
          std::move(fd), false, std::move(error_handler), blocking_task_runner);
    case arc_proxy::FileDescriptor::TRANSPORTABLE:
      return nullptr;
    default:
      LOG(ERROR) << "Unknown FileDescriptor::Type: " << fd_type;
      return nullptr;
  }
}

}  // namespace

MojoProxy::MojoProxy(Delegate* delegate)
    : delegate_(delegate),
      expected_socket_paths_{base::FilePath(kArcBridgeSocketPath)},
      next_handle_(delegate_->GetType() == Type::SERVER ? 1 : -1),
      next_cookie_(delegate_->GetType() == Type::SERVER ? 1 : -1) {
  // Note: this needs to be initialized after weak_factory_, which is
  // declared after message_watcher_ in order to destroy it first.
  message_watcher_ = base::FileDescriptorWatcher::WatchReadable(
      delegate_->GetPollFd(),
      base::BindRepeating(&MojoProxy::OnMojoMessageAvailable,
                          weak_factory_.GetWeakPtr()));

  CHECK(blocking_task_thread_.Start());
}

MojoProxy::~MojoProxy() {
  Stop();
}

int64_t MojoProxy::RegisterFileDescriptor(
    base::ScopedFD fd,
    arc_proxy::FileDescriptor::Type fd_type,
    int64_t handle) {
  if (!fd.is_valid()) {
    LOG(ERROR) << "Registering invalid fd.";
    return 0;
  }

  const int raw_fd = fd.get();
  if (handle == 0) {
    // TODO(hidehiko): Ensure handle is unique in case of overflow.
    if (delegate_->GetType() == Type::SERVER)
      handle = next_handle_++;
    else
      handle = next_handle_--;
  }

  auto file = CreateFile(std::move(fd), fd_type,
                         base::BindOnce(&MojoProxy::HandleLocalFileError,
                                        weak_factory_.GetWeakPtr(), handle),
                         blocking_task_thread_.task_runner());
  std::unique_ptr<base::FileDescriptorWatcher::Controller> controller;
  if (fd_type != arc_proxy::FileDescriptor::REGULAR_FILE &&
      fd_type != arc_proxy::FileDescriptor::TRANSPORTABLE) {
    controller = base::FileDescriptorWatcher::WatchReadable(
        raw_fd, base::BindRepeating(&MojoProxy::OnLocalFileDesciptorReadReady,
                                    weak_factory_.GetWeakPtr(), handle));
  }
  fd_map_.emplace(handle,
                  FileDescriptorInfo{std::move(file), std::move(controller)});
  return handle;
}

void MojoProxy::Connect(const base::FilePath& path, ConnectCallback callback) {
  const int64_t cookie = GenerateCookie();

  arc_proxy::MojoMessage message;
  auto* request = message.mutable_connect_request();
  request->set_cookie(cookie);
  request->set_path(path.value());
  pending_connect_.emplace(cookie, std::move(callback));
  if (!delegate_->SendMessage(message, {}))
    Stop();
}

void MojoProxy::Pread(int64_t handle,
                      uint64_t count,
                      uint64_t offset,
                      PreadCallback callback) {
  const int64_t cookie = GenerateCookie();

  arc_proxy::MojoMessage message;
  auto* request = message.mutable_pread_request();
  request->set_cookie(cookie);
  request->set_handle(handle);
  request->set_count(count);
  request->set_offset(offset);
  pending_pread_.emplace(cookie, std::move(callback));
  if (!delegate_->SendMessage(message, {}))
    Stop();
}

void MojoProxy::Pwrite(int64_t handle,
                       std::string blob,
                       uint64_t offset,
                       PwriteCallback callback) {
  const int64_t cookie = GenerateCookie();

  arc_proxy::MojoMessage message;
  auto* request = message.mutable_pwrite_request();
  request->set_cookie(cookie);
  request->set_handle(handle);
  request->set_blob(std::move(blob));
  request->set_offset(offset);
  pending_pwrite_.emplace(cookie, std::move(callback));
  if (!delegate_->SendMessage(message, {}))
    Stop();
}

void MojoProxy::Fstat(int64_t handle, FstatCallback callback) {
  const int64_t cookie = GenerateCookie();

  arc_proxy::MojoMessage message;
  auto* request = message.mutable_fstat_request();
  request->set_cookie(cookie);
  request->set_handle(handle);
  pending_fstat_.emplace(cookie, std::move(callback));
  if (!delegate_->SendMessage(message, {}))
    Stop();
}

void MojoProxy::Close(int64_t handle) {
  arc_proxy::MojoMessage message;
  message.mutable_close()->set_handle(handle);
  if (!delegate_->SendMessage(message, {}))
    Stop();
}

void MojoProxy::OnMojoMessageAvailable() {
  arc_proxy::MojoMessage message;
  std::vector<base::ScopedFD> fds;
  if (!delegate_->ReceiveMessage(&message, &fds) ||
      !HandleMessage(&message, std::move(fds)))
    Stop();
}

bool MojoProxy::HandleMessage(arc_proxy::MojoMessage* message,
                              std::vector<base::ScopedFD> fds) {
  for (auto& fd : fds)
    received_fds_.push_back(std::move(fd));

  switch (message->command_case()) {
    case arc_proxy::MojoMessage::kClose:
      return OnClose(message->mutable_close());
    case arc_proxy::MojoMessage::kData:
      return OnData(message->mutable_data());
    case arc_proxy::MojoMessage::kConnectRequest:
      return OnConnectRequest(message->mutable_connect_request());
    case arc_proxy::MojoMessage::kConnectResponse:
      return OnConnectResponse(message->mutable_connect_response());
    case arc_proxy::MojoMessage::kPreadRequest:
      OnPreadRequest(message->mutable_pread_request());
      return true;
    case arc_proxy::MojoMessage::kPreadResponse:
      return OnPreadResponse(message->mutable_pread_response());
    case arc_proxy::MojoMessage::kPwriteRequest:
      OnPwriteRequest(message->mutable_pwrite_request());
      return true;
    case arc_proxy::MojoMessage::kPwriteResponse:
      return OnPwriteResponse(message->mutable_pwrite_response());
    case arc_proxy::MojoMessage::kFstatRequest:
      OnFstatRequest(message->mutable_fstat_request());
      return true;
    case arc_proxy::MojoMessage::kFstatResponse:
      return OnFstatResponse(message->mutable_fstat_response());
    default:
      LOG(ERROR) << "Unknown message type: " << message->command_case();
      return false;
  }
}

void MojoProxy::Stop() {
  if (!message_watcher_)  // Do nothing if already stopped.
    return;

  // Run all pending callbacks.
  for (auto& x : pending_fstat_) {
    FstatCallback& callback = x.second;
    std::move(callback).Run(ECONNREFUSED, 0);
  }
  for (auto& x : pending_pread_) {
    PreadCallback& callback = x.second;
    std::move(callback).Run(ECONNREFUSED, std::string());
  }
  for (auto& x : pending_pwrite_) {
    PwriteCallback& callback = x.second;
    std::move(callback).Run(ECONNREFUSED, 0);
  }
  for (auto& x : pending_connect_) {
    ConnectCallback& callback = x.second;
    std::move(callback).Run(ECONNREFUSED, 0);
  }
  // Clear registered file descriptors.
  fd_map_.clear();
  // Stop watching the message stream.
  message_watcher_.reset();

  delegate_->OnStopped();
}

bool MojoProxy::OnClose(arc_proxy::Close* close) {
  auto it = fd_map_.find(close->handle());
  if (it == fd_map_.end()) {
    // The file was already closed.
    return true;
  }
  fd_map_.erase(it);
  return true;
}

bool MojoProxy::OnData(arc_proxy::Data* data) {
  auto it = fd_map_.find(data->handle());
  if (it == fd_map_.end()) {
    // The file was already closed.
    return true;
  }

  // First, create file descriptors for the received message.
  std::vector<base::ScopedFD> transferred_fds;
  transferred_fds.reserve(data->transferred_fd().size());
  for (const auto& transferred_fd : data->transferred_fd()) {
    base::ScopedFD local_fd;
    base::ScopedFD remote_fd;
    switch (transferred_fd.type()) {
      case arc_proxy::FileDescriptor::FIFO_READ: {
        auto created = CreatePipe();
        if (!created)
          return false;
        std::tie(remote_fd, local_fd) = std::move(*created);
        break;
      }
      case arc_proxy::FileDescriptor::FIFO_WRITE: {
        auto created = CreatePipe();
        if (!created)
          return false;
        std::tie(local_fd, remote_fd) = std::move(*created);
        break;
      }
      case arc_proxy::FileDescriptor::REGULAR_FILE: {
        remote_fd = delegate_->CreateProxiedRegularFile(transferred_fd.handle(),
                                                        transferred_fd.flags());
        if (!remote_fd.is_valid())
          return false;
        break;
      }
      case arc_proxy::FileDescriptor::TRANSPORTABLE: {
        if (received_fds_.empty()) {
          LOG(ERROR) << "Type in proto is TRANSPORTABLE but no FD remaining.";
          return false;
        }
        remote_fd = std::move(received_fds_.front());
        received_fds_.pop_front();
        break;
      }
      case arc_proxy::FileDescriptor::SOCKET_STREAM: {
        auto created = CreateSocketPair(SOCK_STREAM | SOCK_NONBLOCK);
        if (!created)
          return false;
        std::tie(local_fd, remote_fd) = std::move(*created);
        break;
      }
      case arc_proxy::FileDescriptor::SOCKET_DGRAM: {
        auto created = CreateSocketPair(SOCK_DGRAM | SOCK_NONBLOCK);
        if (!created)
          return false;
        std::tie(local_fd, remote_fd) = std::move(*created);
        break;
      }
      case arc_proxy::FileDescriptor::SOCKET_SEQPACKET: {
        auto created = CreateSocketPair(SOCK_SEQPACKET | SOCK_NONBLOCK);
        if (!created)
          return false;
        std::tie(local_fd, remote_fd) = std::move(*created);
        break;
      }
      default:
        LOG(ERROR) << "Invalid type value: " << transferred_fd.type();
        return false;
    }

    // |local_fd| is set iff the descriptor's read readiness needs to be
    // watched, so register it.
    if (local_fd.is_valid()) {
      RegisterFileDescriptor(std::move(local_fd), transferred_fd.type(),
                             transferred_fd.handle());
    }
    transferred_fds.emplace_back(std::move(remote_fd));
  }

  if (!it->second.file->Write(std::move(*data->mutable_blob()),
                              std::move(transferred_fds)))
    HandleLocalFileError(data->handle());
  return true;
}

bool MojoProxy::OnConnectRequest(arc_proxy::ConnectRequest* request) {
  base::FilePath path(request->path());
  if (expected_socket_paths_.count(path) == 0) {
    LOG(ERROR) << "Unexpected socket path: " << path;
    return false;
  }
  arc_proxy::MojoMessage reply;
  auto* response = reply.mutable_connect_response();
  response->set_cookie(request->cookie());
  // Currently, this actually uses only on ArcBridgeService's initial
  // connection establishment, and the request comes from the guest to the host
  // including the |path|.
  auto result = ConnectUnixDomainSocket(path);
  response->set_error_code(result.first);
  if (result.first == 0) {
    response->set_handle(RegisterFileDescriptor(
        std::move(result.second), arc_proxy::FileDescriptor::SOCKET_STREAM,
        0 /* generate handle */));
  }
  return delegate_->SendMessage(reply, {});
}

bool MojoProxy::OnConnectResponse(arc_proxy::ConnectResponse* response) {
  auto it = pending_connect_.find(response->cookie());
  if (it == pending_connect_.end()) {
    LOG(ERROR) << "Unexpected connect response: cookie=" << response->cookie();
    return false;
  }

  auto callback = std::move(it->second);
  pending_connect_.erase(it);
  std::move(callback).Run(response->error_code(), response->handle());
  return true;
}

void MojoProxy::OnPreadRequest(arc_proxy::PreadRequest* request) {
  auto it = fd_map_.find(request->handle());
  if (it == fd_map_.end()) {
    LOG(ERROR) << "Couldn't find handle: handle=" << request->handle();
    arc_proxy::PreadResponse response;
    response.set_error_code(EBADF);
    SendPreadResponse(request->cookie(), response);
    return;
  }
  it->second.file->Pread(
      request->count(), request->offset(),
      base::BindOnce(&MojoProxy::SendPreadResponse, weak_factory_.GetWeakPtr(),
                     request->cookie()));
}

void MojoProxy::SendPreadResponse(int64_t cookie,
                                  arc_proxy::PreadResponse response) {
  response.set_cookie(cookie);
  arc_proxy::MojoMessage reply;
  *reply.mutable_pread_response() = std::move(response);

  if (!delegate_->SendMessage(reply, {}))
    Stop();
}

bool MojoProxy::OnPreadResponse(arc_proxy::PreadResponse* response) {
  auto it = pending_pread_.find(response->cookie());
  if (it == pending_pread_.end()) {
    LOG(ERROR) << "Unexpected pread response: cookie=" << response->cookie();
    return false;
  }

  auto callback = std::move(it->second);
  pending_pread_.erase(it);
  std::move(callback).Run(response->error_code(),
                          std::move(*response->mutable_blob()));
  return true;
}

void MojoProxy::OnPwriteRequest(arc_proxy::PwriteRequest* request) {
  auto it = fd_map_.find(request->handle());
  if (it == fd_map_.end()) {
    LOG(ERROR) << "Couldn't find handle: handle=" << request->handle();
    arc_proxy::PwriteResponse response;
    response.set_error_code(EBADF);
    SendPwriteResponse(request->cookie(), response);
    return;
  }
  it->second.file->Pwrite(
      std::move(request->blob()), request->offset(),
      base::BindOnce(&MojoProxy::SendPwriteResponse, weak_factory_.GetWeakPtr(),
                     request->cookie()));
}

void MojoProxy::SendPwriteResponse(int64_t cookie,
                                   arc_proxy::PwriteResponse response) {
  response.set_cookie(cookie);
  arc_proxy::MojoMessage reply;
  *reply.mutable_pwrite_response() = std::move(response);

  if (!delegate_->SendMessage(reply, {}))
    Stop();
}

bool MojoProxy::OnPwriteResponse(arc_proxy::PwriteResponse* response) {
  auto it = pending_pwrite_.find(response->cookie());
  if (it == pending_pwrite_.end()) {
    LOG(ERROR) << "Unexpected pwrite response: cookie=" << response->cookie();
    return false;
  }

  auto callback = std::move(it->second);
  pending_pwrite_.erase(it);
  std::move(callback).Run(response->error_code(), response->bytes_written());
  return true;
}

void MojoProxy::OnFstatRequest(arc_proxy::FstatRequest* request) {
  auto it = fd_map_.find(request->handle());
  if (it == fd_map_.end()) {
    LOG(ERROR) << "Couldn't find handle: handle=" << request->handle();
    arc_proxy::FstatResponse response;
    response.set_error_code(EBADF);
    SendFstatResponse(request->cookie(), std::move(response));
    return;
  }
  it->second.file->Fstat(base::BindOnce(&MojoProxy::SendFstatResponse,
                                        weak_factory_.GetWeakPtr(),
                                        request->cookie()));
}

void MojoProxy::SendFstatResponse(int64_t cookie,
                                  arc_proxy::FstatResponse response) {
  response.set_cookie(cookie);
  arc_proxy::MojoMessage reply;
  *reply.mutable_fstat_response() = std::move(response);

  if (!delegate_->SendMessage(reply, {}))
    Stop();
}

bool MojoProxy::OnFstatResponse(arc_proxy::FstatResponse* response) {
  auto it = pending_fstat_.find(response->cookie());
  if (it == pending_fstat_.end()) {
    LOG(ERROR) << "Unexpected pread response: cookie=" << response->cookie();
    return false;
  }

  auto callback = std::move(it->second);
  pending_fstat_.erase(it);
  std::move(callback).Run(response->error_code(), response->size());
  return true;
}

void MojoProxy::OnLocalFileDesciptorReadReady(int64_t handle) {
  auto it = fd_map_.find(handle);
  if (it == fd_map_.end()) {
    LOG(ERROR) << "Unknown FD gets read ready: handle=" << handle;
    return;
  }

  auto read_result = it->second.file->Read();
  arc_proxy::MojoMessage message;
  std::vector<base::ScopedFD> fds_to_send;
  if (read_result.error_code != 0) {
    LOG(ERROR) << "Failed to read from file descriptor. handle=" << handle;
    // Notify the other side to close.
    message.mutable_close();
  } else if (read_result.blob.empty() && read_result.fds.empty()) {
    // Read empty message, i.e. reached EOF.
    message.mutable_close();
  } else if (!ConvertDataToMojoMessage(std::move(read_result.blob),
                                       std::move(read_result.fds), &message,
                                       &fds_to_send)) {
    // Failed to convert read result into proto.
    message.Clear();
    message.mutable_close();
  }

  if (message.has_close()) {
    // In case of EOF on the other side of the |fd|, |fd| needs to be closed.
    // Otherwise it will be kept read-ready and this callback will be
    // repeatedly called.
    message.mutable_close()->set_handle(handle);
    // Close the corresponding fd, too.
    fd_map_.erase(it);
  } else {
    DCHECK(message.has_data());
    message.mutable_data()->set_handle(handle);
  }
  if (!delegate_->SendMessage(message, fds_to_send))
    Stop();
}

bool MojoProxy::ConvertDataToMojoMessage(
    std::string blob,
    std::vector<base::ScopedFD> fds,
    arc_proxy::MojoMessage* message,
    std::vector<base::ScopedFD>* fds_to_send) {
  DCHECK(!blob.empty() || !fds.empty());

  // Build returning message.
  auto* data = message->mutable_data();
  *data->mutable_blob() = std::move(blob);
  for (auto& fd : fds) {
    auto* transferred_fd = data->add_transferred_fd();

    struct stat st;
    if (fstat(fd.get(), &st) == -1) {
      PLOG(ERROR) << "Failed to fstat";
      return false;
    }
    int flags = fcntl(fd.get(), F_GETFL, 0);
    if (flags < 0) {
      PLOG(ERROR) << "Failed to find file status flags";
      return false;
    }
    transferred_fd->set_flags(flags);

    if (S_ISFIFO(st.st_mode)) {
      switch (flags & O_ACCMODE) {
        case O_RDONLY:
          transferred_fd->set_type(arc_proxy::FileDescriptor::FIFO_READ);
          break;
        case O_WRONLY:
          transferred_fd->set_type(arc_proxy::FileDescriptor::FIFO_WRITE);
          break;
        default:
          LOG(ERROR) << "Unsupported access mode: " << (flags & O_ACCMODE);
          return false;
      }
    } else if (S_ISSOCK(st.st_mode)) {
      const int type = GetSocketType(fd.get());
      switch (type) {
        case SOCK_STREAM:
          transferred_fd->set_type(arc_proxy::FileDescriptor::SOCKET_STREAM);
          break;
        case SOCK_DGRAM:
          transferred_fd->set_type(arc_proxy::FileDescriptor::SOCKET_DGRAM);
          break;
        case SOCK_SEQPACKET:
          transferred_fd->set_type(arc_proxy::FileDescriptor::SOCKET_SEQPACKET);
          break;
        default:
          LOG(ERROR) << "Unexpected socket type: " << type;
          return false;
      }
    } else if (S_ISREG(st.st_mode)) {
      transferred_fd->set_type(arc_proxy::FileDescriptor::REGULAR_FILE);
    } else {
      // Just send it over virtio-wl.
      transferred_fd->set_type(arc_proxy::FileDescriptor::TRANSPORTABLE);
      fds_to_send->push_back(std::move(fd));
    }
    if (transferred_fd->type() != arc_proxy::FileDescriptor::TRANSPORTABLE) {
      transferred_fd->set_handle(RegisterFileDescriptor(
          std::move(fd), transferred_fd->type(), 0 /* generate handle */));
    }
  }
  return true;
}

void MojoProxy::HandleLocalFileError(int64_t handle) {
  fd_map_.erase(handle);
  Close(handle);
}

int64_t MojoProxy::GenerateCookie() {
  // TODO(hidehiko): Ensure cookie is unique in case of overflow.
  return delegate_->GetType() == Type::SERVER ? next_cookie_++ : next_cookie_--;
}

}  // namespace arc
