#include "pdx/service.h"

#include <fcntl.h>
#include <log/log.h>
#include <utils/misc.h>

#include <algorithm>
#include <cstdint>

#include <pdx/trace.h>

namespace android {
namespace pdx {

std::shared_ptr<Channel> Channel::GetFromMessageInfo(const MessageInfo& info) {
  return info.channel ? info.channel->shared_from_this()
                      : std::shared_ptr<Channel>();
}

Message::Message() : replied_(true) {}

Message::Message(const MessageInfo& info)
    : service_{Service::GetFromMessageInfo(info)},
      channel_{Channel::GetFromMessageInfo(info)},
      info_{info},
      replied_{IsImpulse()} {
  auto svc = service_.lock();
  if (svc)
    state_ = svc->endpoint()->AllocateMessageState();
}

// C++11 specifies the move semantics for shared_ptr but not weak_ptr. This
// means we have to manually implement the desired move semantics for Message.
Message::Message(Message&& other) { *this = std::move(other); }

Message& Message::operator=(Message&& other) {
  Destroy();
  auto base = reinterpret_cast<std::uint8_t*>(&info_);
  std::fill(&base[0], &base[sizeof(info_)], 0);
  replied_ = true;
  std::swap(service_, other.service_);
  std::swap(channel_, other.channel_);
  std::swap(info_, other.info_);
  std::swap(state_, other.state_);
  std::swap(replied_, other.replied_);
  return *this;
}

Message::~Message() { Destroy(); }

void Message::Destroy() {
  auto svc = service_.lock();
  if (svc) {
    if (!replied_) {
      ALOGE(
          "ERROR: Service \"%s\" failed to reply to message: op=%d pid=%d "
          "cid=%d\n",
          svc->name_.c_str(), info_.op, info_.pid, info_.cid);
      svc->DefaultHandleMessage(*this);
    }
    svc->endpoint()->FreeMessageState(state_);
  }
  state_ = nullptr;
  service_.reset();
  channel_.reset();
}

const std::uint8_t* Message::ImpulseBegin() const {
  return reinterpret_cast<const std::uint8_t*>(info_.impulse);
}

const std::uint8_t* Message::ImpulseEnd() const {
  return ImpulseBegin() + (IsImpulse() ? GetSendLength() : 0);
}

Status<size_t> Message::ReadVector(const struct iovec* vector,
                                   size_t vector_length) {
  PDX_TRACE_NAME("Message::ReadVector");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->ReadMessageData(this, vector, vector_length);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<void> Message::ReadVectorAll(const struct iovec* vector,
                                    size_t vector_length) {
  PDX_TRACE_NAME("Message::ReadVectorAll");
  if (auto svc = service_.lock()) {
    const auto status =
        svc->endpoint()->ReadMessageData(this, vector, vector_length);
    if (!status)
      return status.error_status();
    size_t size_to_read = 0;
    for (size_t i = 0; i < vector_length; i++)
      size_to_read += vector[i].iov_len;
    if (status.get() < size_to_read)
      return ErrorStatus{EIO};
    return {};
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<size_t> Message::Read(void* buffer, size_t length) {
  PDX_TRACE_NAME("Message::Read");
  if (auto svc = service_.lock()) {
    const struct iovec vector = {buffer, length};
    return svc->endpoint()->ReadMessageData(this, &vector, 1);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<size_t> Message::WriteVector(const struct iovec* vector,
                                    size_t vector_length) {
  PDX_TRACE_NAME("Message::WriteVector");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->WriteMessageData(this, vector, vector_length);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<void> Message::WriteVectorAll(const struct iovec* vector,
                                     size_t vector_length) {
  PDX_TRACE_NAME("Message::WriteVector");
  if (auto svc = service_.lock()) {
    const auto status =
        svc->endpoint()->WriteMessageData(this, vector, vector_length);
    if (!status)
      return status.error_status();
    size_t size_to_write = 0;
    for (size_t i = 0; i < vector_length; i++)
      size_to_write += vector[i].iov_len;
    if (status.get() < size_to_write)
      return ErrorStatus{EIO};
    return {};
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<size_t> Message::Write(const void* buffer, size_t length) {
  PDX_TRACE_NAME("Message::Write");
  if (auto svc = service_.lock()) {
    const struct iovec vector = {const_cast<void*>(buffer), length};
    return svc->endpoint()->WriteMessageData(this, &vector, 1);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<FileReference> Message::PushFileHandle(const LocalHandle& handle) {
  PDX_TRACE_NAME("Message::PushFileHandle");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->PushFileHandle(this, handle);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<FileReference> Message::PushFileHandle(const BorrowedHandle& handle) {
  PDX_TRACE_NAME("Message::PushFileHandle");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->PushFileHandle(this, handle);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<FileReference> Message::PushFileHandle(const RemoteHandle& handle) {
  PDX_TRACE_NAME("Message::PushFileHandle");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->PushFileHandle(this, handle);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<ChannelReference> Message::PushChannelHandle(
    const LocalChannelHandle& handle) {
  PDX_TRACE_NAME("Message::PushChannelHandle");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->PushChannelHandle(this, handle);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<ChannelReference> Message::PushChannelHandle(
    const BorrowedChannelHandle& handle) {
  PDX_TRACE_NAME("Message::PushChannelHandle");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->PushChannelHandle(this, handle);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<ChannelReference> Message::PushChannelHandle(
    const RemoteChannelHandle& handle) {
  PDX_TRACE_NAME("Message::PushChannelHandle");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->PushChannelHandle(this, handle);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

bool Message::GetFileHandle(FileReference ref, LocalHandle* handle) {
  PDX_TRACE_NAME("Message::GetFileHandle");
  auto svc = service_.lock();
  if (!svc)
    return false;

  if (ref >= 0) {
    *handle = svc->endpoint()->GetFileHandle(this, ref);
    if (!handle->IsValid())
      return false;
  } else {
    *handle = LocalHandle{ref};
  }
  return true;
}

bool Message::GetChannelHandle(ChannelReference ref,
                               LocalChannelHandle* handle) {
  PDX_TRACE_NAME("Message::GetChannelHandle");
  auto svc = service_.lock();
  if (!svc)
    return false;

  if (ref >= 0) {
    *handle = svc->endpoint()->GetChannelHandle(this, ref);
    if (!handle->valid())
      return false;
  } else {
    *handle = LocalChannelHandle{nullptr, ref};
  }
  return true;
}

Status<void> Message::Reply(int return_code) {
  PDX_TRACE_NAME("Message::Reply");
  auto svc = service_.lock();
  if (!replied_ && svc) {
    const auto ret = svc->endpoint()->MessageReply(this, return_code);
    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::ReplyFileDescriptor(unsigned int fd) {
  PDX_TRACE_NAME("Message::ReplyFileDescriptor");
  auto svc = service_.lock();
  if (!replied_ && svc) {
    const auto ret = svc->endpoint()->MessageReplyFd(this, fd);
    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::ReplyError(unsigned int error) {
  PDX_TRACE_NAME("Message::ReplyError");
  auto svc = service_.lock();
  if (!replied_ && svc) {
    const auto ret =
        svc->endpoint()->MessageReply(this, -static_cast<int>(error));
    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::Reply(const LocalHandle& handle) {
  PDX_TRACE_NAME("Message::ReplyFileHandle");
  auto svc = service_.lock();
  if (!replied_ && svc) {
    Status<void> ret;

    if (handle)
      ret = svc->endpoint()->MessageReplyFd(this, handle.Get());
    else
      ret = svc->endpoint()->MessageReply(this, handle.Get());

    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::Reply(const BorrowedHandle& handle) {
  PDX_TRACE_NAME("Message::ReplyFileHandle");
  auto svc = service_.lock();
  if (!replied_ && svc) {
    Status<void> ret;

    if (handle)
      ret = svc->endpoint()->MessageReplyFd(this, handle.Get());
    else
      ret = svc->endpoint()->MessageReply(this, handle.Get());

    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::Reply(const RemoteHandle& handle) {
  PDX_TRACE_NAME("Message::ReplyFileHandle");
  auto svc = service_.lock();
  if (!replied_ && svc) {
    Status<void> ret;

    if (handle)
      ret = svc->endpoint()->MessageReply(this, handle.Get());
    else
      ret = svc->endpoint()->MessageReply(this, handle.Get());

    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::Reply(const LocalChannelHandle& handle) {
  auto svc = service_.lock();
  if (!replied_ && svc) {
    const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::Reply(const BorrowedChannelHandle& handle) {
  auto svc = service_.lock();
  if (!replied_ && svc) {
    const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::Reply(const RemoteChannelHandle& handle) {
  auto svc = service_.lock();
  if (!replied_ && svc) {
    const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
    replied_ = ret.ok();
    return ret;
  } else {
    return ErrorStatus{EINVAL};
  }
}

Status<void> Message::ModifyChannelEvents(int clear_mask, int set_mask) {
  PDX_TRACE_NAME("Message::ModifyChannelEvents");
  if (auto svc = service_.lock()) {
    return svc->endpoint()->ModifyChannelEvents(info_.cid, clear_mask,
                                                set_mask);
  } else {
    return ErrorStatus{ESHUTDOWN};
  }
}

Status<RemoteChannelHandle> Message::PushChannel(
    int flags, const std::shared_ptr<Channel>& channel, int* channel_id) {
  PDX_TRACE_NAME("Message::PushChannel");
  if (auto svc = service_.lock()) {
    return svc->PushChannel(this, flags, channel, channel_id);
  } else {
    return ErrorStatus(ESHUTDOWN);
  }
}

Status<RemoteChannelHandle> Message::PushChannel(
    Service* service, int flags, const std::shared_ptr<Channel>& channel,
    int* channel_id) {
  PDX_TRACE_NAME("Message::PushChannel");
  return service->PushChannel(this, flags, channel, channel_id);
}

Status<int> Message::CheckChannel(ChannelReference ref,
                                  std::shared_ptr<Channel>* channel) const {
  PDX_TRACE_NAME("Message::CheckChannel");
  if (auto svc = service_.lock()) {
    return svc->CheckChannel(this, ref, channel);
  } else {
    return ErrorStatus(ESHUTDOWN);
  }
}

Status<int> Message::CheckChannel(const Service* service, ChannelReference ref,
                                  std::shared_ptr<Channel>* channel) const {
  PDX_TRACE_NAME("Message::CheckChannel");
  return service->CheckChannel(this, ref, channel);
}

pid_t Message::GetProcessId() const { return info_.pid; }

pid_t Message::GetThreadId() const { return info_.tid; }

uid_t Message::GetEffectiveUserId() const { return info_.euid; }

gid_t Message::GetEffectiveGroupId() const { return info_.egid; }

int Message::GetChannelId() const { return info_.cid; }

int Message::GetMessageId() const { return info_.mid; }

int Message::GetOp() const { return info_.op; }

int Message::GetFlags() const { return info_.flags; }

size_t Message::GetSendLength() const { return info_.send_len; }

size_t Message::GetReceiveLength() const { return info_.recv_len; }

size_t Message::GetFileDescriptorCount() const { return info_.fd_count; }

std::shared_ptr<Channel> Message::GetChannel() const { return channel_.lock(); }

Status<void> Message::SetChannel(const std::shared_ptr<Channel>& chan) {
  channel_ = chan;
  Status<void> status;
  if (auto svc = service_.lock())
    status = svc->SetChannel(info_.cid, chan);
  return status;
}

std::shared_ptr<Service> Message::GetService() const { return service_.lock(); }

const MessageInfo& Message::GetInfo() const { return info_; }

Service::Service(const std::string& name, std::unique_ptr<Endpoint> endpoint)
    : name_(name), endpoint_{std::move(endpoint)} {
  if (!endpoint_)
    return;

  const auto status = endpoint_->SetService(this);
  ALOGE_IF(!status, "Failed to set service context because: %s",
           status.GetErrorMessage().c_str());
}

Service::~Service() {
  if (endpoint_) {
    const auto status = endpoint_->SetService(nullptr);
    ALOGE_IF(!status, "Failed to clear service context because: %s",
             status.GetErrorMessage().c_str());
  }
}

std::shared_ptr<Service> Service::GetFromMessageInfo(const MessageInfo& info) {
  return info.service ? info.service->shared_from_this()
                      : std::shared_ptr<Service>();
}

bool Service::IsInitialized() const { return endpoint_.get() != nullptr; }

std::shared_ptr<Channel> Service::OnChannelOpen(Message& /*message*/) {
  return nullptr;
}

void Service::OnChannelClose(Message& /*message*/,
                             const std::shared_ptr<Channel>& /*channel*/) {}

Status<void> Service::SetChannel(int channel_id,
                                 const std::shared_ptr<Channel>& channel) {
  PDX_TRACE_NAME("Service::SetChannel");
  std::lock_guard<std::mutex> autolock(channels_mutex_);

  const auto status = endpoint_->SetChannel(channel_id, channel.get());
  if (!status) {
    ALOGE("%s::SetChannel: Failed to set channel context: %s\n", name_.c_str(),
          status.GetErrorMessage().c_str());

    // It's possible someone mucked with things behind our back by calling the C
    // API directly. Since we know the channel id isn't valid, make sure we
    // don't have it in the channels map.
    if (status.error() == ENOENT)
      channels_.erase(channel_id);
  } else {
    if (channel != nullptr)
      channels_[channel_id] = channel;
    else
      channels_.erase(channel_id);
  }
  return status;
}

std::shared_ptr<Channel> Service::GetChannel(int channel_id) const {
  PDX_TRACE_NAME("Service::GetChannel");
  std::lock_guard<std::mutex> autolock(channels_mutex_);

  auto search = channels_.find(channel_id);
  if (search != channels_.end())
    return search->second;
  else
    return nullptr;
}

Status<void> Service::CloseChannel(int channel_id) {
  PDX_TRACE_NAME("Service::CloseChannel");
  std::lock_guard<std::mutex> autolock(channels_mutex_);

  const auto status = endpoint_->CloseChannel(channel_id);

  // Always erase the map entry, in case someone mucked with things behind our
  // back using the C API directly.
  channels_.erase(channel_id);

  return status;
}

Status<void> Service::ModifyChannelEvents(int channel_id, int clear_mask,
                                          int set_mask) {
  PDX_TRACE_NAME("Service::ModifyChannelEvents");
  return endpoint_->ModifyChannelEvents(channel_id, clear_mask, set_mask);
}

Status<RemoteChannelHandle> Service::PushChannel(
    Message* message, int flags, const std::shared_ptr<Channel>& channel,
    int* channel_id) {
  PDX_TRACE_NAME("Service::PushChannel");

  std::lock_guard<std::mutex> autolock(channels_mutex_);

  int channel_id_temp = -1;
  Status<RemoteChannelHandle> ret =
      endpoint_->PushChannel(message, flags, channel.get(), &channel_id_temp);
  ALOGE_IF(!ret.ok(), "%s::PushChannel: Failed to push channel: %s",
           name_.c_str(), strerror(ret.error()));

  if (channel && channel_id_temp != -1)
    channels_[channel_id_temp] = channel;
  if (channel_id)
    *channel_id = channel_id_temp;

  return ret;
}

Status<int> Service::CheckChannel(const Message* message, ChannelReference ref,
                                  std::shared_ptr<Channel>* channel) const {
  PDX_TRACE_NAME("Service::CheckChannel");

  // Synchronization to maintain consistency between the kernel's channel
  // context pointer and the userspace channels_ map. Other threads may attempt
  // to modify the map at the same time, which could cause the channel context
  // pointer returned by the kernel to be invalid.
  std::lock_guard<std::mutex> autolock(channels_mutex_);

  Channel* channel_context = nullptr;
  Status<int> ret = endpoint_->CheckChannel(
      message, ref, channel ? &channel_context : nullptr);
  if (ret && channel) {
    if (channel_context)
      *channel = channel_context->shared_from_this();
    else
      *channel = nullptr;
  }

  return ret;
}

std::string Service::DumpState(size_t /*max_length*/) { return ""; }

Status<void> Service::HandleMessage(Message& message) {
  return DefaultHandleMessage(message);
}

void Service::HandleImpulse(Message& /*impulse*/) {}

Status<void> Service::HandleSystemMessage(Message& message) {
  const MessageInfo& info = message.GetInfo();

  switch (info.op) {
    case opcodes::CHANNEL_OPEN: {
      ALOGD("%s::OnChannelOpen: pid=%d cid=%d\n", name_.c_str(), info.pid,
            info.cid);
      message.SetChannel(OnChannelOpen(message));
      return message.Reply(0);
    }

    case opcodes::CHANNEL_CLOSE: {
      ALOGD("%s::OnChannelClose: pid=%d cid=%d\n", name_.c_str(), info.pid,
            info.cid);
      OnChannelClose(message, Channel::GetFromMessageInfo(info));
      message.SetChannel(nullptr);
      return message.Reply(0);
    }

    case opcodes::REPORT_SYSPROP_CHANGE:
      ALOGD("%s:REPORT_SYSPROP_CHANGE: pid=%d cid=%d\n", name_.c_str(),
            info.pid, info.cid);
      OnSysPropChange();
      android::report_sysprop_change();
      return message.Reply(0);

    case opcodes::DUMP_STATE: {
      ALOGD("%s:DUMP_STATE: pid=%d cid=%d\n", name_.c_str(), info.pid,
            info.cid);
      auto response = DumpState(message.GetReceiveLength());
      const size_t response_size = response.size() < message.GetReceiveLength()
                                       ? response.size()
                                       : message.GetReceiveLength();
      const Status<size_t> status =
          message.Write(response.data(), response_size);
      if (status && status.get() < response_size)
        return message.ReplyError(EIO);
      else
        return message.Reply(status);
    }

    default:
      return ErrorStatus{EOPNOTSUPP};
  }
}

Status<void> Service::DefaultHandleMessage(Message& message) {
  const MessageInfo& info = message.GetInfo();

  ALOGD_IF(TRACE, "Service::DefaultHandleMessage: pid=%d cid=%d op=%d\n",
           info.pid, info.cid, info.op);

  switch (info.op) {
    case opcodes::CHANNEL_OPEN:
    case opcodes::CHANNEL_CLOSE:
    case opcodes::REPORT_SYSPROP_CHANGE:
    case opcodes::DUMP_STATE:
      return HandleSystemMessage(message);

    default:
      return message.ReplyError(EOPNOTSUPP);
  }
}

void Service::OnSysPropChange() {}

Status<void> Service::ReceiveAndDispatch() {
  Message message;
  const auto status = endpoint_->MessageReceive(&message);
  if (!status) {
    ALOGE("Failed to receive message: %s\n", status.GetErrorMessage().c_str());
    return status;
  }

  std::shared_ptr<Service> service = message.GetService();

  if (!service) {
    ALOGE("Service::ReceiveAndDispatch: service context is NULL!!!\n");
    // Don't block the sender indefinitely in this error case.
    endpoint_->MessageReply(&message, -EINVAL);
    return ErrorStatus{EINVAL};
  }

  if (message.IsImpulse()) {
    service->HandleImpulse(message);
    return {};
  } else if (service->HandleSystemMessage(message)) {
    return {};
  } else {
    return service->HandleMessage(message);
  }
}

Status<void> Service::Cancel() { return endpoint_->Cancel(); }

}  // namespace pdx
}  // namespace android
