// Copyright 2022 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 "udp_serde.h"

#include <fidl/fuchsia.net/cpp/wire.h>
#include <fidl/fuchsia.posix.socket/cpp/wire.h>
#include <netinet/in.h>

#include <span>

namespace fnet = fuchsia_net;

namespace {

constexpr uint8_t kVersioningSegmentSize = 8;
constexpr uint8_t kVersioningSegment[kVersioningSegmentSize] = {0};
constexpr cpp20::span<const uint8_t> kVersioningSegmentSpan(kVersioningSegment,
                                                            kVersioningSegmentSize);

constexpr uint8_t kMetadataSizeSegmentSize = 8;
constexpr uint8_t kMetadataSizeSize = sizeof(uint16_t);
constexpr uint8_t kMetadataSizeSegmentPaddingSize = kMetadataSizeSegmentSize - kMetadataSizeSize;
constexpr uint8_t kMetadataSizeSegmentPadding[kMetadataSizeSegmentPaddingSize] = {0};
constexpr cpp20::span<const uint8_t> kMetaSizeSegmentPaddingSpan(kMetadataSizeSegmentPadding,
                                                                 kMetadataSizeSegmentPaddingSize);

constexpr uint8_t kSumOfSegmentSizes = kVersioningSegmentSize + kMetadataSizeSegmentSize;

template <class T, class U, std::size_t N, std::size_t M>
constexpr bool starts_with(const cpp20::span<T, N>& data, const cpp20::span<U, M>& prefix) {
  return data.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin());
}

template <class T, class U, std::size_t N, std::size_t M>
void copy_into(cpp20::span<U, M>& to, const cpp20::span<T, N>& from) {
  ZX_ASSERT_MSG(from.size() <= to.size(), "from size (%zu) < to size (%zu)", from.size(),
                to.size());
  std::copy(from.begin(), from.end(), to.begin());
}

template <class T>
void advance_by(cpp20::span<T>& buf, size_t len) {
  ZX_ASSERT_MSG(buf.size() >= len, "buf size (%zu) < len (%zu)", buf.size(), len);
  buf = buf.subspan(len);
}

template <class T, class U, std::size_t N, std::size_t M>
void copy_into_and_advance_by(cpp20::span<U, M>& to, const cpp20::span<T, N>& from) {
  copy_into(to, from);
  advance_by(to, from.size());
}

bool consume_versioning_segment_unchecked(cpp20::span<uint8_t>& buf) {
  if (!starts_with(buf, kVersioningSegmentSpan)) {
    return false;
  }
  advance_by(buf, kVersioningSegmentSpan.size());
  return true;
}

uint16_t consume_meta_size_segment_unchecked(cpp20::span<uint8_t>& buf) {
  uint8_t meta_size[kMetadataSizeSize];
  cpp20::span<uint8_t, sizeof(meta_size)> meta_size_span(meta_size);
  copy_into(meta_size_span, buf.subspan(0, sizeof(meta_size)));
  advance_by(buf, kMetadataSizeSegmentSize);
  return *reinterpret_cast<uint16_t*>(meta_size);
}

void serialize_unchecked(cpp20::span<uint8_t>& buf, uint16_t meta_size,
                         const fidl::OutgoingMessage& msg) {
  copy_into_and_advance_by(
      buf, cpp20::span<uint8_t>(reinterpret_cast<uint8_t*>(&meta_size), sizeof(meta_size)));
  copy_into_and_advance_by(buf, kMetaSizeSegmentPaddingSpan);

  // This prelude is zeroed in preparation for the transition to use FIDL-at-rest as an encoding
  // scheme. Since FIDL-at-rest serializes a non-zero magic number within the first eight bytes
  // (see
  // https://fuchsia.dev/fuchsia-src/contribute/governance/rfcs/0120_standalone_use_of_fidl_wire_format?hl=en#fidl_wire_format)
  // zero-ing them will let us signal the encoding scheme during the period of transition.
  copy_into_and_advance_by(buf, kVersioningSegmentSpan);

  for (uint32_t i = 0; i < msg.iovec_actual(); ++i) {
    copy_into_and_advance_by(
        buf, cpp20::span<const uint8_t>(static_cast<const uint8_t*>(msg.iovecs()[i].buffer),
                                        msg.iovecs()[i].capacity));
  }
}

std::optional<uint16_t> compute_and_validate_message_size(const fidl::OutgoingMessage& msg) {
  size_t total = 0;
  for (uint32_t i = 0; i < msg.iovec_actual(); ++i) {
    total += msg.iovecs()[i].capacity;
  }
  // Message must fit within 2 bytes.
  if (total > std::numeric_limits<uint16_t>::max()) {
    return std::nullopt;
  }

  return static_cast<uint16_t>(total);
}

bool can_serialize_into(const cpp20::span<uint8_t>& buf, uint16_t meta_size) {
  return static_cast<uint64_t>(meta_size) + static_cast<uint64_t>(kSumOfSegmentSizes) < buf.size();
}

}  // namespace

// Size occupied by the prelude bytes in a Tx message.
const uint32_t kTxUdpPreludeSize =
    fidl::MaxSizeInChannel<fsocket::wire::SendMsgMeta, fidl::MessageDirection::kSending>() +
    kSumOfSegmentSizes;

// Size occupied by the prelude bytes in an Rx message.
const uint32_t kRxUdpPreludeSize =
    fidl::MaxSizeInChannel<fsocket::wire::RecvMsgMeta, fidl::MessageDirection::kSending>() +
    kSumOfSegmentSizes;

DeserializeSendMsgMetaResult deserialize_send_msg_meta(Buffer buf) {
  DeserializeSendMsgMetaResult res;
  if (buf.buf == nullptr) {
    res.err = DeserializeSendMsgMetaErrorInputBufferNull;
    return res;
  }
  if (buf.buf_size < kSumOfSegmentSizes) {
    res.err = DeserializeSendMsgMetaErrorInputBufferTooSmall;
    return res;
  }
  cpp20::span<uint8_t> span{buf.buf, buf.buf_size};
  uint16_t meta_size = consume_meta_size_segment_unchecked(span);
  if (!consume_versioning_segment_unchecked(span)) {
    res.err = DeserializeSendMsgMetaErrorNonZeroPrelude;
    return res;
  }
  if (span.size() < meta_size) {
    res.err = DeserializeSendMsgMetaErrorInputBufferTooSmall;
    return res;
  }
  fidl::unstable::DecodedMessage<fsocket::wire::SendMsgMeta> decoded(
      fidl::internal::WireFormatVersion::kV2, span.begin(), static_cast<uint32_t>(meta_size));

  if (!decoded.ok()) {
    res.err = DeserializeSendMsgMetaErrorFailedToDecode;
    return res;
  }

  fsocket::wire::SendMsgMeta& meta = *decoded.PrimaryObject();

  if (meta.has_to()) {
    res.has_addr = true;
    fnet::wire::SocketAddress& sockaddr = meta.to();
    switch (sockaddr.Which()) {
      case fnet::wire::SocketAddress::Tag::kIpv4: {
        const fnet::wire::Ipv4SocketAddress& ipv4 = sockaddr.ipv4();
        res.port = ipv4.port;
        res.to_addr.addr_type = IpAddrType::Ipv4;
        res.to_addr.addr_size = decltype(ipv4.address.addr)::size();
        std::copy(ipv4.address.addr.begin(), ipv4.address.addr.end(), res.to_addr.addr);
        break;
      }
      case fnet::wire::SocketAddress::Tag::kIpv6: {
        const fnet::wire::Ipv6SocketAddress& ipv6 = sockaddr.ipv6();
        res.port = ipv6.port;
        res.to_addr.addr_type = IpAddrType::Ipv6;
        res.to_addr.addr_size = decltype(ipv6.address.addr)::size();
        std::copy(ipv6.address.addr.begin(), ipv6.address.addr.end(), res.to_addr.addr);
        break;
      }
    }
  } else {
    res.has_addr = false;
  }

  res.err = DeserializeSendMsgMetaErrorNone;
  return res;
}

bool serialize_send_msg_meta(fsocket::wire::SendMsgMeta& meta, cpp20::span<uint8_t> out_buf) {
  fidl::unstable::OwnedEncodedMessage<fsocket::wire::SendMsgMeta> encoded(
      fidl::internal::WireFormatVersion::kV2, &meta);
  if (!encoded.ok()) {
    return false;
  }

  fidl::OutgoingMessage& outgoing_meta = encoded.GetOutgoingMessage();
  std::optional meta_size_validated = compute_and_validate_message_size(outgoing_meta);
  if (!meta_size_validated.has_value() ||
      !can_serialize_into(out_buf, meta_size_validated.value())) {
    return false;
  }
  serialize_unchecked(out_buf, meta_size_validated.value(), outgoing_meta);
  return true;
}

fidl::unstable::DecodedMessage<fsocket::wire::RecvMsgMeta> deserialize_recv_msg_meta(
    cpp20::span<uint8_t> buf) {
  if (buf.size() < kSumOfSegmentSizes) {
    return fidl::unstable::DecodedMessage<fsocket::wire::RecvMsgMeta>(nullptr, 0);
  }
  uint16_t meta_size = consume_meta_size_segment_unchecked(buf);
  if (!consume_versioning_segment_unchecked(buf)) {
    return fidl::unstable::DecodedMessage<fsocket::wire::RecvMsgMeta>(nullptr, 0);
  }

  if (meta_size > buf.size()) {
    return fidl::unstable::DecodedMessage<fsocket::wire::RecvMsgMeta>(nullptr, 0);
  }

  return fidl::unstable::DecodedMessage<fsocket::wire::RecvMsgMeta>(
      fidl::internal::WireFormatVersion::kV2, buf.data(), static_cast<uint32_t>(meta_size));
}

SerializeRecvMsgMetaError serialize_recv_msg_meta(const RecvMsgMeta* meta_, ConstBuffer from_addr,
                                                  Buffer out_buf) {
  fidl::Arena<
      fidl::MaxSizeInChannel<fsocket::wire::RecvMsgMeta, fidl::MessageDirection::kSending>()>
      alloc;
  fidl::WireTableBuilder<fsocket::wire::RecvMsgMeta> meta_builder =
      fsocket::wire::RecvMsgMeta::Builder(alloc);

  fnet::wire::SocketAddress socket_addr;
  fnet::wire::Ipv4SocketAddress ipv4_socket_addr;
  fnet::wire::Ipv6SocketAddress ipv6_socket_addr;
  const RecvMsgMeta& meta = *meta_;
  switch (meta.from_addr_type) {
    case IpAddrType::Ipv4: {
      if (from_addr.buf == nullptr) {
        return SerializeRecvMsgMetaErrorFromAddrBufferNull;
      }
      cpp20::span<const uint8_t> from_addr_span(from_addr.buf, from_addr.buf_size);
      cpp20::span<uint8_t> to_addr(ipv4_socket_addr.address.addr.data(),
                                   sizeof(ipv4_socket_addr.address.addr));
      if (from_addr_span.size() != to_addr.size()) {
        return SerializeRecvMsgMetaErrorFromAddrBufferTooSmall;
      }
      copy_into(to_addr, from_addr_span);
      ipv4_socket_addr.port = meta.port;
      socket_addr = fnet::wire::SocketAddress::WithIpv4(alloc, ipv4_socket_addr);
    } break;
    case IpAddrType::Ipv6: {
      if (from_addr.buf == nullptr) {
        return SerializeRecvMsgMetaErrorFromAddrBufferNull;
      }
      cpp20::span<const uint8_t> from_addr_span(from_addr.buf, from_addr.buf_size);
      cpp20::span<uint8_t> to_addr(ipv6_socket_addr.address.addr.data(),
                                   sizeof(ipv6_socket_addr.address.addr));
      if (from_addr_span.size() != to_addr.size()) {
        return SerializeRecvMsgMetaErrorFromAddrBufferTooSmall;
      }
      copy_into(to_addr, from_addr_span);
      ipv6_socket_addr.port = meta.port;
      socket_addr = fnet::wire::SocketAddress::WithIpv6(alloc, ipv6_socket_addr);
    } break;
  }
  meta_builder.from(socket_addr);

  fidl::WireTableBuilder<fsocket::wire::NetworkSocketRecvControlData> net_control_builder =
      fsocket::wire::NetworkSocketRecvControlData::Builder(alloc);
  bool net_control_set = false;

  {
    fidl::WireTableBuilder<fsocket::wire::IpRecvControlData> ip_control_builder =
        fsocket::wire::IpRecvControlData::Builder(alloc);
    bool ip_control_set = false;
    if (meta.cmsg_set.has_ip_tos) {
      ip_control_set = true;
      ip_control_builder.tos(meta.cmsg_set.ip_tos);
    }
    if (meta.cmsg_set.has_ip_ttl) {
      ip_control_set = true;
      ip_control_builder.ttl(meta.cmsg_set.ip_ttl);
    }
    if (ip_control_set) {
      net_control_set = true;
      net_control_builder.ip(ip_control_builder.Build());
    }
  }

  {
    fidl::WireTableBuilder<fsocket::wire::Ipv6RecvControlData> ipv6_control_builder =
        fsocket::wire::Ipv6RecvControlData::Builder(alloc);
    bool ipv6_control_set = false;
    if (meta.cmsg_set.has_ipv6_pktinfo) {
      const Ipv6PktInfo& pktinfo = meta.cmsg_set.ipv6_pktinfo;
      fuchsia_posix_socket::wire::Ipv6PktInfoRecvControlData fidl_pktinfo = {
          .iface = pktinfo.if_index,
      };
      const cpp20::span<const uint8_t> from_addr(pktinfo.addr);
      cpp20::span<uint8_t> to_addr(fidl_pktinfo.header_destination_addr.addr.data(),
                                   decltype(fidl_pktinfo.header_destination_addr.addr)::size());
      copy_into(to_addr, from_addr);
      ipv6_control_set = true;
      ipv6_control_builder.pktinfo(fidl_pktinfo);
    }
    if (meta.cmsg_set.has_ipv6_hoplimit) {
      ipv6_control_set = true;
      ipv6_control_builder.hoplimit(meta.cmsg_set.ipv6_hoplimit);
    }
    if (meta.cmsg_set.has_ipv6_tclass) {
      ipv6_control_set = true;
      ipv6_control_builder.tclass(meta.cmsg_set.ipv6_tclass);
    }
    if (ipv6_control_set) {
      net_control_set = true;
      net_control_builder.ipv6(ipv6_control_builder.Build());
    }
  }

  {
    fidl::WireTableBuilder<fsocket::wire::SocketRecvControlData> sock_control_builder =
        fsocket::wire::SocketRecvControlData::Builder(alloc);
    bool sock_control_set = false;
    if (meta.cmsg_set.has_timestamp_nanos) {
      sock_control_set = true;
      sock_control_builder.timestamp(fsocket::wire::Timestamp{
          .nanoseconds = meta.cmsg_set.timestamp_nanos,
      });
    }
    if (sock_control_set) {
      net_control_set = true;
      net_control_builder.socket(sock_control_builder.Build());
    }
  }

  if (net_control_set) {
    fidl::WireTableBuilder<fsocket::wire::DatagramSocketRecvControlData> datagram_control_builder =
        fsocket::wire::DatagramSocketRecvControlData::Builder(alloc);
    datagram_control_builder.network(net_control_builder.Build());
    meta_builder.control(datagram_control_builder.Build());
  }

  meta_builder.payload_len(meta.payload_size);

  fsocket::wire::RecvMsgMeta fsocket_meta = meta_builder.Build();

  fidl::unstable::OwnedEncodedMessage<fsocket::wire::RecvMsgMeta> encoded(
      fidl::internal::WireFormatVersion::kV2, &fsocket_meta);
  if (!encoded.ok()) {
    return SerializeRecvMsgMetaErrorFailedToEncode;
  }

  if (out_buf.buf == nullptr) {
    return SerializeRecvMsgMetaErrorOutputBufferNull;
  }

  cpp20::span<uint8_t> outbuf{out_buf.buf, out_buf.buf_size};

  fidl::OutgoingMessage& outgoing_meta = encoded.GetOutgoingMessage();
  std::optional meta_size_validated = compute_and_validate_message_size(outgoing_meta);
  if (!meta_size_validated.has_value() ||
      !can_serialize_into(outbuf, meta_size_validated.value())) {
    return SerializeRecvMsgMetaErrorOutputBufferTooSmall;
  }
  serialize_unchecked(outbuf, meta_size_validated.value(), outgoing_meta);
  return SerializeRecvMsgMetaErrorNone;
}
