/*
 * 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 "common/camera_mojo_channel_manager_impl.h"

#include <grp.h>

#include <string>
#include <utility>

#include <base/bind.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/no_destructor.h>
#include <mojo/core/embedder/embedder.h>

#include "cros-camera/common.h"
#include "cros-camera/constants.h"
#include "cros-camera/ipc_util.h"

namespace cros {

namespace {

constexpr ino_t kInvalidInodeNum = 0;

// Gets the socket file by |socket_path| and checks if it is in correct group
// and has correct permission. Returns |kInvalidInodeNum| if it is invalid.
// Otherwise, returns its inode number.
ino_t GetSocketInodeNumber(const base::FilePath& socket_path) {
  // Ensure that socket file is ready before trying to connect the dispatcher.
  struct group arc_camera_group;
  struct group* result = nullptr;
  char buf[1024];

  getgrnam_r(constants::kArcCameraGroup, &arc_camera_group, buf, sizeof(buf),
             &result);
  if (!result) {
    return kInvalidInodeNum;
  }

  int mode;
  if (!base::GetPosixFilePermissions(socket_path, &mode) || mode != 0660) {
    return kInvalidInodeNum;
  }

  struct stat st;
  if (stat(socket_path.value().c_str(), &st) ||
      st.st_gid != arc_camera_group.gr_gid) {
    return kInvalidInodeNum;
  }
  return st.st_ino;
}

base::UnguessableToken ReadServerToken() {
  static constexpr char kServerTokenPath[] = "/run/camera_tokens/server/token";

  base::FilePath token_path(kServerTokenPath);
  std::string token_string;
  if (!base::ReadFileToString(token_path, &token_string)) {
    LOGF(ERROR) << "Failed to read server token";
    return {};
  }
  return cros::TokenFromString(token_string);
}

}  // namespace

// static
CameraMojoChannelManagerImpl* CameraMojoChannelManagerImpl::instance_ = nullptr;

CameraMojoChannelManagerImpl::CameraMojoChannelManagerImpl()
    : ipc_thread_("MojoIpcThread"), bound_socket_inode_num_(kInvalidInodeNum) {
  instance_ = this;
  if (!ipc_thread_.StartWithOptions(
          base::Thread::Options(base::MessagePumpType::IO, 0))) {
    LOGF(ERROR) << "Failed to start IPC Thread";
    return;
  }
  mojo::core::Init();
  ipc_support_ = std::make_unique<mojo::core::ScopedIPCSupport>(
      ipc_thread_.task_runner(),
      mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST);

  base::FilePath socket_path(constants::kCrosCameraSocketPathString);
  if (!watcher_.Watch(
          socket_path, false,
          base::Bind(&CameraMojoChannelManagerImpl::OnSocketFileStatusChange,
                     base::Unretained(this)))) {
    LOGF(ERROR) << "Failed to watch socket path";
    return;
  }
}

CameraMojoChannelManagerImpl::~CameraMojoChannelManagerImpl() {
  if (ipc_thread_.IsRunning()) {
    ipc_thread_.task_runner()->PostTask(
        FROM_HERE,
        base::Bind(&CameraMojoChannelManagerImpl::TearDownMojoEnvOnIpcThread,
                   base::Unretained(this)));
    ipc_thread_.Stop();
  }
}

// static
std::unique_ptr<CameraMojoChannelManager>
CameraMojoChannelManager::CreateInstance() {
  return base::WrapUnique<CameraMojoChannelManager>(
      new CameraMojoChannelManagerImpl());
}

// static
CameraMojoChannelManager* CameraMojoChannelManager::GetInstance() {
  DCHECK(CameraMojoChannelManagerImpl::instance_ != nullptr);
  return CameraMojoChannelManagerImpl::instance_;
}

scoped_refptr<base::SingleThreadTaskRunner>
CameraMojoChannelManagerImpl::GetIpcTaskRunner() {
  CHECK(ipc_thread_.task_runner());
  return ipc_thread_.task_runner();
}

void CameraMojoChannelManagerImpl::RegisterServer(
    mojom::CameraHalServerPtr hal_ptr,
    mojom::CameraHalDispatcher::RegisterServerWithTokenCallback
        on_construct_callback,
    Callback on_error_callback) {
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());
  VLOGF_ENTER();

  camera_hal_server_request_ = {
      .requestOrPtr = std::move(hal_ptr),
      .on_construct_callback = std::move(on_construct_callback),
      .on_error_callback = std::move(on_error_callback)};
  ipc_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&CameraMojoChannelManagerImpl::TryConnectToDispatcher,
                 base::Unretained(this)));
}

void CameraMojoChannelManagerImpl::CreateMjpegDecodeAccelerator(
    mojom::MjpegDecodeAcceleratorRequest request,
    Callback on_construct_callback,
    Callback on_error_callback) {
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());
  VLOGF_ENTER();

  JpegPendingMojoRequest<mojom::MjpegDecodeAcceleratorRequest> pending_request =
      {.requestOrPtr = std::move(request),
       .on_construct_callback = std::move(on_construct_callback),
       .on_error_callback = std::move(on_error_callback)};
  jda_requests_.push_back(std::move(pending_request));
  ipc_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&CameraMojoChannelManagerImpl::TryConnectToDispatcher,
                 base::Unretained(this)));
}

void CameraMojoChannelManagerImpl::CreateJpegEncodeAccelerator(
    mojom::JpegEncodeAcceleratorRequest request,
    Callback on_construct_callback,
    Callback on_error_callback) {
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());
  VLOGF_ENTER();

  JpegPendingMojoRequest<mojom::JpegEncodeAcceleratorRequest> pending_request =
      {.requestOrPtr = std::move(request),
       .on_construct_callback = std::move(on_construct_callback),
       .on_error_callback = std::move(on_error_callback)};
  jea_requests_.push_back(std::move(pending_request));
  ipc_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&CameraMojoChannelManagerImpl::TryConnectToDispatcher,
                 base::Unretained(this)));
}

mojom::CameraAlgorithmOpsPtr
CameraMojoChannelManagerImpl::CreateCameraAlgorithmOpsPtr(
    const std::string& socket_path, const std::string& pipe_name) {
  VLOGF_ENTER();

  mojo::ScopedMessagePipeHandle parent_pipe;
  mojom::CameraAlgorithmOpsPtr algorithm_ops;

  base::FilePath socket_file_path(socket_path);
  MojoResult result = cros::CreateMojoChannelToChildByUnixDomainSocket(
      socket_file_path, &parent_pipe, pipe_name);
  if (result != MOJO_RESULT_OK) {
    LOGF(WARNING) << "Failed to create Mojo Channel to "
                  << socket_file_path.value();
    return nullptr;
  }

  algorithm_ops.Bind(
      mojom::CameraAlgorithmOpsPtrInfo(std::move(parent_pipe), 0u));

  LOGF(INFO) << "Connected to CameraAlgorithmOps";

  VLOGF_EXIT();
  return algorithm_ops;
}

void CameraMojoChannelManagerImpl::OnSocketFileStatusChange(
    const base::FilePath& socket_path, bool error) {
  if (error) {
    LOGF(ERROR) << "Error occurs in socket file watcher.";
    return;
  }

  ipc_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(
          &CameraMojoChannelManagerImpl::OnSocketFileStatusChangeOnIpcThread,
          base::Unretained(this)));
}

void CameraMojoChannelManagerImpl::OnSocketFileStatusChangeOnIpcThread() {
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());
  VLOGF_ENTER();

  base::FilePath socket_path(constants::kCrosCameraSocketPathString);
  if (dispatcher_.is_bound()) {
    // If the dispatcher is already bound but the inode number of the socket is
    // unreadable or has been changed, we assume the other side of the
    // dispatcher (Chrome) might be destroyed. As a result, we fire the on error
    // event here in case it is not fired correctly.
    if (bound_socket_inode_num_ != GetSocketInodeNumber(socket_path)) {
      ipc_thread_.task_runner()->PostTask(
          FROM_HERE,
          base::Bind(&CameraMojoChannelManagerImpl::ResetDispatcherPtr,
                     base::Unretained(this)));
    }
    return;
  }

  ipc_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&CameraMojoChannelManagerImpl::TryConnectToDispatcher,
                 base::Unretained(this)));
}

void CameraMojoChannelManagerImpl::TryConnectToDispatcher() {
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());
  VLOGF_ENTER();

  if (dispatcher_.is_bound()) {
    TryConsumePendingMojoRequests();
    return;
  }

  base::FilePath socket_path(constants::kCrosCameraSocketPathString);
  ino_t socket_inode_num = GetSocketInodeNumber(socket_path);
  if (socket_inode_num == kInvalidInodeNum) {
    return;
  }

  mojo::ScopedMessagePipeHandle child_pipe;
  MojoResult result = cros::CreateMojoChannelToParentByUnixDomainSocket(
      socket_path, &child_pipe);
  if (result != MOJO_RESULT_OK) {
    LOGF(WARNING) << "Failed to create Mojo Channel to " << socket_path.value();
    return;
  }

  dispatcher_ = mojo::MakeProxy(
      mojom::CameraHalDispatcherPtrInfo(std::move(child_pipe), 0u),
      ipc_thread_.task_runner());
  dispatcher_.set_connection_error_handler(
      base::Bind(&CameraMojoChannelManagerImpl::ResetDispatcherPtr,
                 base::Unretained(this)));
  bound_socket_inode_num_ = socket_inode_num;

  TryConsumePendingMojoRequests();
}

void CameraMojoChannelManagerImpl::TryConsumePendingMojoRequests() {
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());
  VLOGF_ENTER();

  if (camera_hal_server_request_.requestOrPtr) {
    auto server_token = ReadServerToken();
    if (server_token.is_empty()) {
      LOGF(ERROR) << "Failed to read server token";
      std::move(camera_hal_server_request_.on_construct_callback)
          .Run(-EPERM, nullptr);
    } else {
      auto token = mojo_base::mojom::UnguessableToken::New();
      token->high = server_token.GetHighForSerialization();
      token->low = server_token.GetLowForSerialization();
      dispatcher_->RegisterServerWithToken(
          std::move(camera_hal_server_request_.requestOrPtr), std::move(token),
          std::move(camera_hal_server_request_.on_construct_callback));
    }
  }

  for (auto& request : jda_requests_) {
    if (request.requestOrPtr) {
      dispatcher_->GetMjpegDecodeAccelerator(std::move(request.requestOrPtr));
      std::move(request.on_construct_callback).Run();
    }
  }

  for (auto& request : jea_requests_) {
    if (request.requestOrPtr) {
      dispatcher_->GetJpegEncodeAccelerator(std::move(request.requestOrPtr));
      std::move(request.on_construct_callback).Run();
    }
  }
}

void CameraMojoChannelManagerImpl::TearDownMojoEnvOnIpcThread() {
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());
  VLOGF_ENTER();

  ResetDispatcherPtr();
  ipc_support_.reset();
}

void CameraMojoChannelManagerImpl::ResetDispatcherPtr() {
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());
  VLOGF_ENTER();

  if (camera_hal_server_request_.on_error_callback) {
    std::move(camera_hal_server_request_.on_error_callback).Run();
    camera_hal_server_request_ = {};
  }

  for (auto& request : jda_requests_) {
    if (request.on_error_callback) {
      std::move(request.on_error_callback).Run();
    }
  }
  jda_requests_.clear();

  for (auto& request : jea_requests_) {
    if (request.on_error_callback) {
      std::move(request.on_error_callback).Run();
    }
  }
  jea_requests_.clear();

  dispatcher_.reset();
  bound_socket_inode_num_ = kInvalidInodeNum;
}

}  // namespace cros
