/*
 * 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;
}

}  // 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) {
    // TODO(b/170075468): Retrieve the token generated by CameraHalDispatcher.
    auto token = base::UnguessableToken::Create();
    auto mojo_token = mojo_base::mojom::UnguessableToken::New();
    mojo_token->high = token.GetHighForSerialization();
    mojo_token->low = token.GetLowForSerialization();
    dispatcher_->RegisterServerWithToken(
        std::move(camera_hal_server_request_.requestOrPtr),
        std::move(mojo_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
