// Copyright 2017 The Chromium 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 "ipc/ipc_perftest_util.h"

#include "base/ignore_result.h"
#include "base/logging.h"
#include "base/run_loop.h"
#include "ipc/ipc_channel_proxy.h"
#include "ipc/ipc_perftest_messages.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/test/multiprocess_test_helper.h"

namespace IPC {

scoped_refptr<base::SingleThreadTaskRunner> GetIOThreadTaskRunner() {
  scoped_refptr<base::TaskRunner> runner = mojo::core::GetIOTaskRunner();
  return scoped_refptr<base::SingleThreadTaskRunner>(
      static_cast<base::SingleThreadTaskRunner*>(runner.get()));
}

ChannelReflectorListener::ChannelReflectorListener() : channel_(nullptr) {
  VLOG(1) << "Client listener up";
}

ChannelReflectorListener::~ChannelReflectorListener() {
  VLOG(1) << "Client listener down";
}

void ChannelReflectorListener::Init(Sender* channel,
                                    base::OnceClosure quit_closure) {
  DCHECK(!channel_);
  channel_ = channel;
  quit_closure_ = std::move(quit_closure);
}

bool ChannelReflectorListener::OnMessageReceived(const Message& message) {
  CHECK(channel_);
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(ChannelReflectorListener, message)
    IPC_MESSAGE_HANDLER(TestMsg_Hello, OnHello)
    IPC_MESSAGE_HANDLER(TestMsg_Ping, OnPing)
    IPC_MESSAGE_HANDLER(TestMsg_SyncPing, OnSyncPing)
    IPC_MESSAGE_HANDLER(TestMsg_Quit, OnQuit)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void ChannelReflectorListener::OnHello() {
  channel_->Send(new TestMsg_Hello);
}

void ChannelReflectorListener::OnPing(const std::string& payload) {
  channel_->Send(new TestMsg_Ping(payload));
}

void ChannelReflectorListener::OnSyncPing(const std::string& payload,
                                          std::string* response) {
  *response = payload;
}

void ChannelReflectorListener::OnQuit() {
  std::move(quit_closure_).Run();
}

void ChannelReflectorListener::Send(IPC::Message* message) {
  channel_->Send(message);
}

LockThreadAffinity::LockThreadAffinity(int cpu_number)
    : affinity_set_ok_(false) {
#if defined(OS_WIN)
  const DWORD_PTR thread_mask = static_cast<DWORD_PTR>(1) << cpu_number;
  old_affinity_ = SetThreadAffinityMask(GetCurrentThread(), thread_mask);
  affinity_set_ok_ = old_affinity_ != 0;
#elif defined(OS_LINUX) || defined(OS_CHROMEOS)
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
  CPU_SET(cpu_number, &cpuset);
  auto get_result = sched_getaffinity(0, sizeof(old_cpuset_), &old_cpuset_);
  DCHECK_EQ(0, get_result);
  auto set_result = sched_setaffinity(0, sizeof(cpuset), &cpuset);
  // Check for get_result failure, even though it should always succeed.
  affinity_set_ok_ = (set_result == 0) && (get_result == 0);
#endif
  if (!affinity_set_ok_)
    LOG(WARNING) << "Failed to set thread affinity to CPU " << cpu_number;
}

LockThreadAffinity::~LockThreadAffinity() {
  if (!affinity_set_ok_)
    return;
#if defined(OS_WIN)
  auto set_result = SetThreadAffinityMask(GetCurrentThread(), old_affinity_);
  DCHECK_NE(0u, set_result);
#elif defined(OS_LINUX) || defined(OS_CHROMEOS)
  auto set_result = sched_setaffinity(0, sizeof(old_cpuset_), &old_cpuset_);
  DCHECK_EQ(0, set_result);
#endif
}

MojoPerfTestClient::MojoPerfTestClient()
    : listener_(new ChannelReflectorListener()) {
  mojo::core::test::MultiprocessTestHelper::ChildSetup();
}

MojoPerfTestClient::~MojoPerfTestClient() = default;

int MojoPerfTestClient::Run(MojoHandle handle) {
  handle_ = mojo::MakeScopedHandle(mojo::MessagePipeHandle(handle));
  LockThreadAffinity thread_locker(kSharedCore);

  base::RunLoop run_loop;
  std::unique_ptr<ChannelProxy> channel = IPC::ChannelProxy::Create(
      handle_.release(), Channel::MODE_CLIENT, listener_.get(),
      GetIOThreadTaskRunner(), base::ThreadTaskRunnerHandle::Get());
  listener_->Init(channel.get(), run_loop.QuitWhenIdleClosure());
  run_loop.Run();
  return 0;
}

ReflectorImpl::ReflectorImpl(mojo::ScopedMessagePipeHandle handle,
                             base::OnceClosure quit_closure)
    : quit_closure_(std::move(quit_closure)),
      receiver_(
          this,
          mojo::PendingReceiver<IPC::mojom::Reflector>(std::move(handle))) {}

ReflectorImpl::~ReflectorImpl() {
  ignore_result(receiver_.Unbind().PassPipe().release());
}

void ReflectorImpl::Ping(const std::string& value, PingCallback callback) {
  std::move(callback).Run(value);
}

void ReflectorImpl::SyncPing(const std::string& value, PingCallback callback) {
  std::move(callback).Run(value);
}

void ReflectorImpl::Quit() {
  if (quit_closure_)
    std::move(quit_closure_).Run();
}

}  // namespace IPC
