// Copyright 2018 The Fuchsia 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 <lib/fidl/coding.h>
#include <lib/fidl/cpp/message.h>
#include <lib/fidl/internal.h>
#include <string.h>

#include "zircon/fidl.h"

#ifdef __Fuchsia__
#include <zircon/errors.h>
#include <zircon/syscalls.h>
#endif

#include <utility>

namespace {

zx_status_t CheckWireFormatVersion(fidl::internal::WireFormatVersion wire_format,
                                   const fidl_type_t* type, const char** out_error_msg) {
  switch (wire_format) {
    case fidl::internal::WireFormatVersion::kV1:
      *out_error_msg = "wire format v1 message received, but it is unsupported";
      return ZX_ERR_INVALID_ARGS;
    case fidl::internal::WireFormatVersion::kV2:
      return ZX_OK;
    default:
      *out_error_msg = "unknown wire format version";
      return ZX_ERR_INVALID_ARGS;
  }
}

}  // namespace

namespace fidl {

HLCPPIncomingBody::HLCPPIncomingBody() = default;

HLCPPIncomingBody::HLCPPIncomingBody(BytePart bytes, HandleInfoPart handles)
    : bytes_(std::move(bytes)), handles_(std::move(handles)) {}

HLCPPIncomingBody::~HLCPPIncomingBody() {
#ifdef __Fuchsia__
  FidlHandleInfoCloseMany(handles_.data(), handles_.actual());
#endif
  ClearHandlesUnsafe();
}

HLCPPIncomingBody::HLCPPIncomingBody(HLCPPIncomingBody&& other)
    : bytes_(std::move(other.bytes_)), handles_(std::move(other.handles_)) {}

HLCPPIncomingBody& HLCPPIncomingBody::operator=(HLCPPIncomingBody&& other) {
  bytes_ = std::move(other.bytes_);
  handles_ = std::move(other.handles_);
  return *this;
}

zx_status_t HLCPPIncomingBody::Decode(const WireFormatMetadata& metadata, const fidl_type_t* type,
                                      const char** error_msg_out) {
  if (!metadata.is_valid()) {
    *error_msg_out = "invalid wire format metadata";
    return ZX_ERR_INVALID_ARGS;
  }
  zx_status_t status = CheckWireFormatVersion(metadata.wire_format_version(), type, error_msg_out);
  if (status != ZX_OK) {
    return status;
  }
  status = internal__fidl_decode_etc_hlcpp__v2__may_break(
      type, bytes_.data(), bytes_.actual(), handles_.data(), handles_.actual(), error_msg_out);

  ClearHandlesUnsafe();
  return status;
}

void HLCPPIncomingBody::ClearHandlesUnsafe() { handles_.set_actual(0u); }

HLCPPIncomingMessage::HLCPPIncomingMessage() = default;

HLCPPIncomingMessage::HLCPPIncomingMessage(BytePart bytes, HandleInfoPart handles)
    : bytes_(std::move(bytes)),
      body_view_(
          HLCPPIncomingBody(BytePart(bytes_, sizeof(fidl_message_header_t)), std::move(handles))) {}

HLCPPIncomingMessage::HLCPPIncomingMessage(HLCPPIncomingMessage&& other)
    : bytes_(std::move(other.bytes_)), body_view_(std::move(other.body_view_)) {}

HLCPPIncomingMessage& HLCPPIncomingMessage::operator=(HLCPPIncomingMessage&& other) {
  bytes_ = std::move(other.bytes_);
  body_view_ = std::move(other.body_view_);
  return *this;
}

zx_status_t HLCPPIncomingMessage::Decode(const fidl_type_t* type, const char** error_msg_out) {
  zx_status_t status =
      body_view_.Decode(WireFormatMetadata::FromTransactionalHeader(header()), type, error_msg_out);
  return status;
}

#ifdef __Fuchsia__
zx_status_t HLCPPIncomingMessage::Read(zx_handle_t channel, uint32_t flags) {
  uint32_t actual_bytes = 0u;
  uint32_t actual_handles = 0u;
  zx_status_t status =
      zx_channel_read_etc(channel, flags, bytes_.data(), handles().data(), bytes_.capacity(),
                          handles().capacity(), &actual_bytes, &actual_handles);
  if (status != ZX_OK) {
    return status;
  }

  // Ensure we received enough bytes for the FIDL header.
  if (actual_bytes < sizeof(fidl_message_header_t)) {
    return ZX_ERR_INVALID_ARGS;
  }

  resize_bytes(actual_bytes);
  handles().set_actual(actual_handles);
  return ZX_OK;
}
#endif

void HLCPPIncomingMessage::ClearHandlesUnsafe() { body_view_.ClearHandlesUnsafe(); }

HLCPPOutgoingBody::HLCPPOutgoingBody() = default;

HLCPPOutgoingBody::HLCPPOutgoingBody(BytePart bytes, HandleDispositionPart handles)
    : bytes_(std::move(bytes)), handles_(std::move(handles)) {}

HLCPPOutgoingBody::~HLCPPOutgoingBody() {
#ifdef __Fuchsia__
  if (handles_.actual() > 0) {
    FidlHandleDispositionCloseMany(handles_.data(), handles_.actual());
  }
#endif
  ClearHandlesUnsafe();
}

HLCPPOutgoingBody::HLCPPOutgoingBody(HLCPPOutgoingBody&& other)
    : bytes_(std::move(other.bytes_)), handles_(std::move(other.handles_)) {}

HLCPPOutgoingBody& HLCPPOutgoingBody::operator=(HLCPPOutgoingBody&& other) {
  bytes_ = std::move(other.bytes_);
  handles_ = std::move(other.handles_);
  return *this;
}

zx_status_t HLCPPOutgoingBody::Validate(const internal::WireFormatVersion& wire_format_version,
                                        const fidl_type_t* type, const char** error_msg_out) const {
  zx_status_t status = CheckWireFormatVersion(wire_format_version, type, error_msg_out);
  if (status != ZX_OK) {
    return status;
  }
  status = internal__fidl_validate__v2__may_break(type, bytes_.data(), bytes_.actual(),
                                                  handles().actual(), error_msg_out);
  return status;
}

void HLCPPOutgoingBody::ClearHandlesUnsafe() { handles_.set_actual(0u); }

HLCPPOutgoingMessage::HLCPPOutgoingMessage() = default;

HLCPPOutgoingMessage::HLCPPOutgoingMessage(BytePart bytes, HandleDispositionPart handles)
    : bytes_(std::move(bytes)),
      body_view_(
          HLCPPOutgoingBody(BytePart(bytes_, sizeof(fidl_message_header_t)), std::move(handles))) {}

HLCPPOutgoingMessage::HLCPPOutgoingMessage(HLCPPOutgoingMessage&& other)
    : bytes_(std::move(other.bytes_)), body_view_(std::move(other.body_view_)) {}

HLCPPOutgoingMessage& HLCPPOutgoingMessage::operator=(HLCPPOutgoingMessage&& other) {
  bytes_ = std::move(other.bytes_);
  body_view_ = std::move(other.body_view_);
  return *this;
}

zx_status_t HLCPPOutgoingMessage::Validate(const fidl_type_t* type,
                                           const char** error_msg_out) const {
  WireFormatMetadata wire_format_metadata = WireFormatMetadata::FromTransactionalHeader(header());
  if (!wire_format_metadata.is_valid()) {
    *error_msg_out = "invalid wire format metadata";
    return ZX_ERR_INVALID_ARGS;
  }
  return body_view_.Validate(wire_format_metadata.wire_format_version(), type, error_msg_out);
}

#ifdef __Fuchsia__
zx_status_t HLCPPOutgoingMessage::Write(zx_handle_t channel, uint32_t flags) {
  zx_status_t status = zx_channel_write_etc(channel, flags, bytes_.data(), bytes_.actual(),
                                            handles().data(), handles().actual());

  // Handles are cleared by the kernel on either success or failure.
  ClearHandlesUnsafe();

  return status;
}

zx_status_t HLCPPOutgoingMessage::Call(zx_handle_t channel, uint32_t flags, zx_time_t deadline,
                                       HLCPPIncomingMessage* response) {
  zx_channel_call_etc_args_t args;
  args.wr_bytes = bytes_.data();
  args.wr_handles = handles().data();
  args.rd_bytes = response->bytes().data();
  args.rd_handles = response->handles().data();
  args.wr_num_bytes = bytes_.actual();
  args.wr_num_handles = handles().actual();
  args.rd_num_bytes = response->bytes().capacity();
  args.rd_num_handles = response->handles().capacity();
  uint32_t actual_bytes = 0u;
  uint32_t actual_handles = 0u;
  zx_status_t status =
      zx_channel_call_etc(channel, flags, deadline, &args, &actual_bytes, &actual_handles);
  ClearHandlesUnsafe();
  if (status == ZX_OK) {
    response->resize_bytes(actual_bytes);
    response->handles().set_actual(actual_handles);
  }
  return status;
}
#endif

void HLCPPOutgoingMessage::ClearHandlesUnsafe() { body_view_.ClearHandlesUnsafe(); }

}  // namespace fidl
