// 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/internal.h>
#include <lib/fidl/llcpp/coding.h>
#include <lib/fidl/llcpp/message.h>
#include <lib/fidl/trace.h>
#include <zircon/assert.h>
#include <zircon/errors.h>

#include <cstring>
#include <string>

#ifdef __Fuchsia__
#include <lib/fidl/llcpp/client_base.h>
#include <lib/fidl/llcpp/internal/transport_channel.h>
#include <lib/fidl/llcpp/server.h>
#include <zircon/syscalls.h>
#else
#include <lib/fidl/llcpp/internal/transport_channel_host.h>
#endif  // __Fuchsia__

namespace {

bool ContainsEnvelope(const fidl_type_t* type) {
  switch (type->type_tag()) {
    case kFidlTypeTable:
    case kFidlTypeXUnion:
      return true;
    case kFidlTypeStruct:
      return type->coded_struct().contains_envelope;
    default:
      ZX_PANIC("unexpected top-level type");
  }
}

}  // namespace

namespace fidl {

OutgoingMessage OutgoingMessage::FromEncodedCMessage(const fidl_outgoing_msg_t* c_msg) {
  return OutgoingMessage(c_msg, true);
}

OutgoingMessage OutgoingMessage::FromEncodedCValue(const fidl_outgoing_msg_t* c_msg) {
  return OutgoingMessage(c_msg, false);
}

OutgoingMessage::OutgoingMessage(const fidl_outgoing_msg_t* c_msg, bool is_transactional)
    : fidl::Status(fidl::Status::Ok()) {
  ZX_ASSERT(c_msg);
  transport_vtable_ = &internal::ChannelTransport::VTable;
  switch (c_msg->type) {
    case FIDL_OUTGOING_MSG_TYPE_IOVEC: {
      message_ = *c_msg;
      iovec_capacity_ = c_msg->iovec.num_iovecs;
      handle_capacity_ = c_msg->iovec.num_handles;
      break;
    }
    case FIDL_OUTGOING_MSG_TYPE_BYTE: {
      backing_buffer_ = reinterpret_cast<uint8_t*>(c_msg->byte.bytes);
      backing_buffer_capacity_ = c_msg->byte.num_bytes;
      converted_byte_message_iovec_ = {
          .buffer = backing_buffer_,
          .capacity = backing_buffer_capacity_,
          .reserved = 0,
      };
      message_ = {
          .type = FIDL_OUTGOING_MSG_TYPE_IOVEC,
          .iovec =
              {
                  .iovecs = &converted_byte_message_iovec_,
                  .num_iovecs = 1,
                  .handles = c_msg->byte.handles,
                  .handle_metadata = c_msg->byte.handle_metadata,
                  .num_handles = c_msg->byte.num_handles,
              },
      };
      iovec_capacity_ = 1;
      handle_capacity_ = c_msg->byte.num_handles;
      break;
    }
    default:
      ZX_PANIC("unhandled FIDL outgoing message type");
  }
  is_transactional_ = is_transactional;
}

OutgoingMessage::OutgoingMessage(const ::fidl::Status& failure)
    : fidl::Status(failure),
      message_({.type = FIDL_OUTGOING_MSG_TYPE_IOVEC,
                .iovec = {
                    .iovecs = nullptr,
                    .num_iovecs = 0,
                    .handles = nullptr,
                    .handle_metadata = nullptr,
                    .num_handles = 0,
                }}) {
  ZX_DEBUG_ASSERT(failure.status() != ZX_OK);
}

OutgoingMessage::OutgoingMessage(InternalIovecConstructorArgs args)
    : fidl::Status(fidl::Status::Ok()),
      transport_vtable_(args.transport_vtable),
      message_({
          .type = FIDL_OUTGOING_MSG_TYPE_IOVEC,
          .iovec = {.iovecs = args.iovecs,
                    .num_iovecs = 0,
                    .handles = args.handles,
                    .handle_metadata = args.handle_metadata,
                    .num_handles = 0},
      }),
      iovec_capacity_(args.iovec_capacity),
      handle_capacity_(args.handle_capacity),
      backing_buffer_capacity_(args.backing_buffer_capacity),
      backing_buffer_(args.backing_buffer),
      is_transactional_(args.is_transactional) {}

OutgoingMessage::OutgoingMessage(InternalByteBackedConstructorArgs args)
    : fidl::Status(fidl::Status::Ok()),
      transport_vtable_(args.transport_vtable),
      message_({
          .type = FIDL_OUTGOING_MSG_TYPE_IOVEC,
          .iovec =
              {
                  .iovecs = &converted_byte_message_iovec_,
                  .num_iovecs = 1,
                  .handles = args.handles,
                  .handle_metadata = args.handle_metadata,
                  .num_handles = args.num_handles,
              },
      }),
      iovec_capacity_(1),
      handle_capacity_(args.num_handles),
      backing_buffer_capacity_(args.num_bytes),
      backing_buffer_(args.bytes),
      converted_byte_message_iovec_(
          {.buffer = backing_buffer_, .capacity = backing_buffer_capacity_, .reserved = 0}),
      is_transactional_(args.is_transactional) {}

OutgoingMessage::~OutgoingMessage() {
  // We may not have a vtable when the |OutgoingMessage| represents an error.
  if (transport_vtable_) {
    transport_vtable_->encoding_configuration->close_many(handles(), handle_actual());
  }
}

fidl_outgoing_msg_t OutgoingMessage::ReleaseToEncodedCMessage() && {
  ZX_DEBUG_ASSERT(status() == ZX_OK);
  ZX_ASSERT(transport_type() == FIDL_TRANSPORT_TYPE_CHANNEL);
  fidl_outgoing_msg_t result = message_;
  ReleaseHandles();
  return result;
}

bool OutgoingMessage::BytesMatch(const OutgoingMessage& other) const {
  uint32_t iovec_index = 0, other_iovec_index = 0;
  uint32_t byte_index = 0, other_byte_index = 0;
  while (iovec_index < iovec_actual() && other_iovec_index < other.iovec_actual()) {
    zx_channel_iovec_t cur_iovec = iovecs()[iovec_index];
    zx_channel_iovec_t other_cur_iovec = other.iovecs()[other_iovec_index];
    const uint8_t* cur_bytes = reinterpret_cast<const uint8_t*>(cur_iovec.buffer);
    const uint8_t* other_cur_bytes = reinterpret_cast<const uint8_t*>(other_cur_iovec.buffer);

    uint32_t cmp_len =
        std::min(cur_iovec.capacity - byte_index, other_cur_iovec.capacity - other_byte_index);
    if (memcmp(&cur_bytes[byte_index], &other_cur_bytes[other_byte_index], cmp_len) != 0) {
      return false;
    }

    byte_index += cmp_len;
    if (byte_index == cur_iovec.capacity) {
      iovec_index++;
      byte_index = 0;
    }
    other_byte_index += cmp_len;
    if (other_byte_index == other_cur_iovec.capacity) {
      other_iovec_index++;
      other_byte_index = 0;
    }
  }
  return iovec_index == iovec_actual() && other_iovec_index == other.iovec_actual() &&
         byte_index == 0 && other_byte_index == 0;
}

void OutgoingMessage::EncodeImpl(fidl::internal::WireFormatVersion wire_format_version,
                                 const fidl_type_t* message_type, void* data) {
  if (!ok()) {
    return;
  }
  if (wire_format_version != fidl::internal::WireFormatVersion::kV2) {
    SetStatus(fidl::Status::EncodeError(ZX_ERR_INVALID_ARGS, "only v2 wire format supported"));
    return;
  }

  uint32_t num_iovecs_actual;
  uint32_t num_handles_actual;

  zx_status_t status = fidl::internal::EncodeIovecEtc<FIDL_WIRE_FORMAT_VERSION_V2>(
      *transport_vtable_->encoding_configuration, message_type, is_transactional(), data, iovecs(),
      iovec_capacity(), handles(), message_.iovec.handle_metadata, handle_capacity(),
      backing_buffer(), backing_buffer_capacity(), &num_iovecs_actual, &num_handles_actual,
      error_address());
  if (status != ZX_OK) {
    SetStatus(fidl::Status::EncodeError(status, *error_address()));
    return;
  }
  iovec_message().num_iovecs = num_iovecs_actual;
  iovec_message().num_handles = num_handles_actual;

  if (is_transactional()) {
    ZX_ASSERT(iovec_actual() >= 1 && iovecs()[0].capacity >= sizeof(fidl_message_header_t));
    static_cast<fidl_message_header_t*>(const_cast<void*>(iovecs()[0].buffer))->at_rest_flags[0] |=
        FIDL_MESSAGE_HEADER_AT_REST_FLAGS_0_USE_VERSION_V2;
  }
}

void OutgoingMessage::Write(internal::AnyUnownedTransport transport, WriteOptions options) {
  if (!ok()) {
    return;
  }
  ZX_ASSERT(transport_type() == transport.type());
  ZX_ASSERT(is_transactional());
  zx_status_t status = transport.write(std::move(options), iovecs(), iovec_actual(), handles(),
                                       message_.iovec.handle_metadata, handle_actual());
  ReleaseHandles();
  if (status != ZX_OK) {
    SetStatus(fidl::Status::TransportError(status));
  }
}

void OutgoingMessage::DecodeImplForCall(const internal::CodingConfig& coding_config,
                                        const fidl_type_t* response_type, uint8_t* bytes,
                                        uint32_t* in_out_num_bytes, fidl_handle_t* handles,
                                        fidl_handle_metadata_t* handle_metadata,
                                        uint32_t num_handles) {
  fidl_message_header_t& header = reinterpret_cast<fidl_message_header_t&>(*bytes);
  if (response_type == nullptr) {
    return;
  } else if (unlikely(*in_out_num_bytes <= sizeof(fidl_message_header_t))) {
    SetStatus(fidl::Status::DecodeError(ZX_ERR_BUFFER_TOO_SMALL,
                                        "non-nullptr response_type must be larger than 16 bytes"));
    return;
  }

  // Old versions of the C bindings will send wire format V1 payloads that are compatible
  // with wire format V2 (they don't contain envelopes). Confirm that V1 payloads don't
  // contain envelopes and are compatible with V2.
  if ((header.at_rest_flags[0] & FIDL_MESSAGE_HEADER_AT_REST_FLAGS_0_USE_VERSION_V2) == 0 &&
      ContainsEnvelope(response_type)) {
    SetStatus(fidl::Status::DecodeError(
        ZX_ERR_INVALID_ARGS, "wire format v1 header received with unsupported envelope"));
    return;
  }

  uint8_t* trimmed_result_bytes;
  uint32_t trimmed_num_bytes;
  zx_status_t trim_status = ::fidl::internal::fidl_exclude_header_bytes(
      bytes, *in_out_num_bytes, &trimmed_result_bytes, &trimmed_num_bytes, error_address());
  if (trim_status != ZX_OK) {
    SetStatus(fidl::Status::DecodeError(trim_status, *error_address()));
    return;
  }

  zx_status_t status = internal::DecodeEtc<FIDL_WIRE_FORMAT_VERSION_V2>(
      coding_config, response_type, trimmed_result_bytes, trimmed_num_bytes, handles,
      handle_metadata, num_handles, error_address());
  if (status != ZX_OK) {
    SetStatus(fidl::Status::DecodeError(status, *error_address()));
    return;
  }
}

void OutgoingMessage::CallImplForTransportProvidedBuffer(internal::AnyUnownedTransport transport,
                                                         const fidl_type_t* response_type,
                                                         uint8_t** out_bytes,
                                                         uint32_t* out_num_bytes,
                                                         CallOptions options) {
  if (status() != ZX_OK) {
    return;
  }
  ZX_ASSERT(transport_type() == transport.type());
  ZX_ASSERT(is_transactional());

  fidl_handle_t* result_handles;
  fidl_handle_metadata_t* result_handle_metadata;
  uint32_t result_num_handles;
  internal::CallMethodArgs args = {
      .wr_data = iovecs(),
      .wr_handles = handles(),
      .wr_handle_metadata = message_.iovec.handle_metadata,
      .wr_data_count = iovec_actual(),
      .wr_handles_count = handle_actual(),
      .out_rd_data = reinterpret_cast<void**>(out_bytes),
      .out_rd_handles = &result_handles,
      .out_rd_handle_metadata = &result_handle_metadata,
  };

  zx_status_t status = transport.call(std::move(options), args, out_num_bytes, &result_num_handles);
  ReleaseHandles();
  if (status != ZX_OK) {
    SetStatus(fidl::Status::TransportError(status));
    return;
  }

  DecodeImplForCall(*transport.vtable()->encoding_configuration, response_type, *out_bytes,
                    out_num_bytes, result_handles, result_handle_metadata, result_num_handles);
}

void OutgoingMessage::CallImplForCallerProvidedBuffer(
    internal::AnyUnownedTransport transport, const fidl_type_t* response_type,
    uint8_t* result_bytes, uint32_t result_byte_capacity, fidl_handle_t* result_handles,
    fidl_handle_metadata_t* result_handle_metadata, uint32_t result_handle_capacity,
    CallOptions options) {
  if (status() != ZX_OK) {
    return;
  }
  ZX_ASSERT(transport_type() == transport.type());
  ZX_ASSERT(is_transactional());

  uint32_t actual_num_bytes = 0u;
  uint32_t actual_num_handles = 0u;
  internal::CallMethodArgs args = {
      .wr_data = iovecs(),
      .wr_handles = handles(),
      .wr_handle_metadata = message_.iovec.handle_metadata,
      .wr_data_count = iovec_actual(),
      .wr_handles_count = handle_actual(),
      .rd_data = result_bytes,
      .rd_handles = result_handles,
      .rd_handle_metadata = result_handle_metadata,
      .rd_data_capacity = result_byte_capacity,
      .rd_handles_capacity = result_handle_capacity,
  };

  zx_status_t status =
      transport.call(std::move(options), args, &actual_num_bytes, &actual_num_handles);
  ReleaseHandles();
  if (status != ZX_OK) {
    SetStatus(fidl::Status::TransportError(status));
    return;
  }

  DecodeImplForCall(*transport.vtable()->encoding_configuration, response_type, result_bytes,
                    &actual_num_bytes, result_handles, result_handle_metadata, actual_num_handles);
}

IncomingMessage OutgoingMessage::CallImpl(internal::AnyUnownedTransport transport,
                                          internal::MessageStorageViewBase& storage,
                                          CallOptions options) {
  if (status() != ZX_OK) {
    return IncomingMessage::Create(Status(*this));
  }
  ZX_ASSERT(transport_type() == transport.type());
  ZX_ASSERT(is_transactional());

  uint8_t* result_bytes;
  fidl_handle_t* result_handles;
  fidl_handle_metadata_t* result_handle_metadata;
  uint32_t actual_num_bytes = 0u;
  uint32_t actual_num_handles = 0u;
  internal::CallMethodArgs args = {
      .wr_data = iovecs(),
      .wr_handles = handles(),
      .wr_handle_metadata = message_.iovec.handle_metadata,
      .wr_data_count = iovec_actual(),
      .wr_handles_count = handle_actual(),
      .out_rd_data = reinterpret_cast<void**>(&result_bytes),
      .out_rd_handles = &result_handles,
      .out_rd_handle_metadata = &result_handle_metadata,
      .rd_view = &storage,
  };

  zx_status_t status =
      transport.call(std::move(options), args, &actual_num_bytes, &actual_num_handles);
  ReleaseHandles();
  if (status != ZX_OK) {
    SetStatus(fidl::Status::TransportError(status));
    return IncomingMessage::Create(Status(*this));
  }

  return IncomingMessage(transport_vtable_, result_bytes, actual_num_bytes, result_handles,
                         result_handle_metadata, actual_num_handles);
}

OutgoingMessage::CopiedBytes::CopiedBytes(const OutgoingMessage& msg) {
  uint32_t byte_count = 0;
  for (uint32_t i = 0; i < msg.iovec_actual(); ++i) {
    byte_count += msg.iovecs()[i].capacity;
  }
  bytes_.reserve(byte_count);
  for (uint32_t i = 0; i < msg.iovec_actual(); ++i) {
    zx_channel_iovec_t iovec = msg.iovecs()[i];
    const uint8_t* buf_bytes = reinterpret_cast<const uint8_t*>(iovec.buffer);
    bytes_.insert(bytes_.end(), buf_bytes, buf_bytes + iovec.capacity);
  }
}

IncomingMessage::IncomingMessage(const internal::TransportVTable* transport_vtable, uint8_t* bytes,
                                 uint32_t byte_actual, zx_handle_t* handles,
                                 fidl_handle_metadata_t* handle_metadata, uint32_t handle_actual)
    : IncomingMessage(transport_vtable, bytes, byte_actual, handles, handle_metadata, handle_actual,
                      kSkipMessageHeaderValidation) {
  ValidateHeader();
  is_transactional_ = true;
}

IncomingMessage IncomingMessage::FromEncodedCMessage(const fidl_incoming_msg_t* c_msg) {
  return IncomingMessage(&internal::ChannelTransport::VTable,
                         reinterpret_cast<uint8_t*>(c_msg->bytes), c_msg->num_bytes, c_msg->handles,
                         c_msg->handle_metadata, c_msg->num_handles);
}

IncomingMessage::IncomingMessage(const internal::TransportVTable* transport_vtable, uint8_t* bytes,
                                 uint32_t byte_actual, zx_handle_t* handles,
                                 fidl_handle_metadata_t* handle_metadata, uint32_t handle_actual,
                                 SkipMessageHeaderValidationTag)
    : fidl::Status(fidl::Status::Ok()),
      transport_vtable_(transport_vtable),
      message_{
          .bytes = bytes,
          .handles = handles,
          .handle_metadata = handle_metadata,
          .num_bytes = byte_actual,
          .num_handles = handle_actual,
      } {}

IncomingMessage::IncomingMessage(const fidl::Status& failure) : fidl::Status(failure), message_{} {
  ZX_DEBUG_ASSERT(failure.status() != ZX_OK);
}

IncomingMessage::~IncomingMessage() { std::move(*this).CloseHandles(); }

fidl_incoming_msg_t IncomingMessage::ReleaseToEncodedCMessage() && {
  ZX_DEBUG_ASSERT(status() == ZX_OK);
  ZX_ASSERT(transport_vtable_->type == FIDL_TRANSPORT_TYPE_CHANNEL);
  fidl_incoming_msg_t result = message_;
  ReleaseHandles();
  return result;
}

void IncomingMessage::CloseHandles() && {
#ifdef __Fuchsia__
  if (handle_actual() > 0) {
    FidlHandleCloseMany(handles(), handle_actual());
  }
#else
  ZX_ASSERT(handle_actual() == 0);
#endif
  ReleaseHandles();
}

IncomingMessage IncomingMessage::SkipTransactionHeader() {
  ZX_ASSERT(is_transactional());
  fidl_handle_t* handles = message_.handles;
  fidl_handle_metadata_t* handle_metadata = message_.handle_metadata;
  uint32_t handle_actual = message_.num_handles;
  ReleaseHandles();
  return IncomingMessage(transport_vtable_, bytes() + sizeof(fidl_message_header_t),
                         byte_actual() - static_cast<uint32_t>(sizeof(fidl_message_header_t)),
                         handles, handle_metadata, handle_actual,
                         ::fidl::IncomingMessage::kSkipMessageHeaderValidation);
}

void IncomingMessage::Decode(const fidl_type_t* message_type) {
  ZX_ASSERT(is_transactional_);
  // Old versions of the C bindings will send wire format V1 payloads that are compatible
  // with wire format V2 (they don't contain envelopes). Confirm that V1 payloads don't
  // contain envelopes and are compatible with V2.
  // TODO(fxbug.dev/99738) Remove this logic.
  ZX_DEBUG_ASSERT(
      !ContainsEnvelope(message_type) ||
      (header()->at_rest_flags[0] & FIDL_MESSAGE_HEADER_AT_REST_FLAGS_0_USE_VERSION_V2) != 0);
  Decode(internal::WireFormatVersion::kV2, message_type, true);
}

void IncomingMessage::Decode(internal::WireFormatVersion wire_format_version,
                             const fidl_type_t* message_type, bool is_transactional) {
  ZX_DEBUG_ASSERT(status() == ZX_OK);
  if (wire_format_version != internal::WireFormatVersion::kV2) {
    SetStatus(fidl::Status::DecodeError(ZX_ERR_INVALID_ARGS, "only wire format v2 supported"));
    return;
  }

  uint8_t* trimmed_bytes = bytes();
  uint32_t trimmed_num_bytes = byte_actual();
  if (is_transactional) {
    zx_status_t status = ::fidl::internal::fidl_exclude_header_bytes(
        bytes(), byte_actual(), &trimmed_bytes, &trimmed_num_bytes, error_address());
    if (status != ZX_OK) {
      SetStatus(fidl::Status::DecodeError(status, *error_address()));
      return;
    }
  }

  fidl_trace(WillLLCPPDecode, message_type, trimmed_bytes, trimmed_num_bytes, handle_actual());
  zx_status_t status = fidl::internal::DecodeEtc<FIDL_WIRE_FORMAT_VERSION_V2>(
      *transport_vtable_->encoding_configuration, message_type, trimmed_bytes, trimmed_num_bytes,
      message_.handles, message_.handle_metadata, message_.num_handles, error_address());
  fidl_trace(DidLLCPPDecode);
  // Now the caller is responsible for the handles contained in `bytes()`.
  ReleaseHandles();
  if (status != ZX_OK) {
    SetStatus(fidl::Status::DecodeError(status, *error_address()));
  }
}

void IncomingMessage::ValidateHeader() {
  if (byte_actual() < sizeof(fidl_message_header_t)) {
    return SetStatus(fidl::Status::UnexpectedMessage(ZX_ERR_INVALID_ARGS,
                                                     ::fidl::internal::kErrorInvalidHeader));
  }

  auto* hdr = header();
  zx_status_t status = fidl_validate_txn_header(hdr);
  if (status != ZX_OK) {
    return SetStatus(
        fidl::Status::UnexpectedMessage(status, ::fidl::internal::kErrorInvalidHeader));
  }

  // See https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0053_epitaphs?hl=en#wire_format
  if (unlikely(maybe_epitaph())) {
    if (hdr->txid != 0) {
      return SetStatus(fidl::Status::UnexpectedMessage(ZX_ERR_INVALID_ARGS,
                                                       ::fidl::internal::kErrorInvalidHeader));
    }
  }
}

OutgoingToIncomingMessage::OutgoingToIncomingMessage(OutgoingMessage& input)
    : incoming_message_(ConversionImpl(input, buf_bytes_, buf_handles_, buf_handle_metadata_)) {}

[[nodiscard]] std::string OutgoingToIncomingMessage::FormatDescription() const {
  return incoming_message_.FormatDescription();
}

IncomingMessage OutgoingToIncomingMessage::ConversionImpl(
    OutgoingMessage& input, OutgoingMessage::CopiedBytes& buf_bytes,
    std::unique_ptr<zx_handle_t[]>& buf_handles,
    // TODO(fxbug.dev/85734) Remove channel-specific logic.
    std::unique_ptr<fidl_channel_handle_metadata_t[]>& buf_handle_metadata) {
  zx_handle_t* handles = input.handles();
  fidl_channel_handle_metadata_t* handle_metadata =
      input.handle_metadata<fidl::internal::ChannelTransport>();
  uint32_t num_handles = input.handle_actual();
  input.ReleaseHandles();

  if (num_handles > ZX_CHANNEL_MAX_MSG_HANDLES) {
    FidlHandleCloseMany(handles, num_handles);
    return fidl::IncomingMessage::Create(fidl::Status::EncodeError(ZX_ERR_OUT_OF_RANGE));
  }

  // Note: it may be possible to remove these allocations.
  buf_handles = std::make_unique<zx_handle_t[]>(ZX_CHANNEL_MAX_MSG_HANDLES);
  buf_handle_metadata =
      std::make_unique<fidl_channel_handle_metadata_t[]>(ZX_CHANNEL_MAX_MSG_HANDLES);
  for (uint32_t i = 0; i < num_handles; i++) {
    const char* error;
    zx_status_t status = FidlEnsureActualHandleRights(&handles[i], handle_metadata[i].obj_type,
                                                      handle_metadata[i].rights, &error);
    if (status != ZX_OK) {
      FidlHandleCloseMany(handles, num_handles);
      FidlHandleCloseMany(buf_handles.get(), num_handles);
      return fidl::IncomingMessage::Create(fidl::Status::EncodeError(status));
    }
    buf_handles[i] = handles[i];
    buf_handle_metadata[i] = handle_metadata[i];
  }

  buf_bytes = input.CopyBytes();
  if (buf_bytes.size() > ZX_CHANNEL_MAX_MSG_BYTES) {
    FidlHandleCloseMany(handles, num_handles);
    FidlHandleCloseMany(buf_handles.get(), num_handles);
    return fidl::IncomingMessage::Create(fidl::Status::EncodeError(ZX_ERR_INVALID_ARGS));
  }

  if (input.is_transactional()) {
    return fidl::IncomingMessage::Create(buf_bytes.data(), buf_bytes.size(), buf_handles.get(),
                                         buf_handle_metadata.get(), num_handles);
  }
  return fidl::IncomingMessage::Create(buf_bytes.data(), buf_bytes.size(), buf_handles.get(),
                                       buf_handle_metadata.get(), num_handles,
                                       fidl::IncomingMessage::kSkipMessageHeaderValidation);
}

}  // namespace fidl
