// 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 <fcntl.h>
#include <fuchsia/posix/socket/llcpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/fd.h>
#include <lib/fidl-async/cpp/bind.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>

#include <array>
#include <cerrno>
#include <chrono>
#include <cstring>
#include <future>
#include <latch>

#include <fbl/array.h>
#include <fbl/unique_fd.h>
#include <zxtest/zxtest.h>

namespace {

class Server final : public llcpp::fuchsia::posix::socket::StreamSocket::Interface {
 public:
  explicit Server(zx::socket peer) : peer_(std::move(peer)) {
    // We need the FDIO to act like it's connected.
    // ZXSIO_SIGNAL_CONNECTED is private, but we know the value.
    ASSERT_OK(peer_.signal(0, ZX_USER_SIGNAL_3));
  }

  void Clone(uint32_t flags, ::zx::channel object, CloneCompleter::Sync& completer) override {
    return completer.Close(ZX_ERR_NOT_SUPPORTED);
  }

  void Close(CloseCompleter::Sync& completer) override {
    completer.Reply(ZX_OK);
    completer.Close(ZX_OK);
  }

  void Describe(DescribeCompleter::Sync& completer) override {
    llcpp::fuchsia::io::StreamSocket stream_socket;
    zx_status_t status =
        peer_.duplicate(ZX_RIGHTS_BASIC | ZX_RIGHT_READ | ZX_RIGHT_WRITE, &stream_socket.socket);
    if (status != ZX_OK) {
      return completer.Close(status);
    }
    llcpp::fuchsia::io::NodeInfo info;
    info.set_stream_socket(fidl::unowned_ptr(&stream_socket));
    completer.Reply(std::move(info));
  }

  void Sync(SyncCompleter::Sync& completer) override {
    return completer.Close(ZX_ERR_NOT_SUPPORTED);
  }

  void GetAttr(GetAttrCompleter::Sync& completer) override {
    return completer.Close(ZX_ERR_NOT_SUPPORTED);
  }

  void SetAttr(uint32_t flags, ::llcpp::fuchsia::io::NodeAttributes attributes,
               SetAttrCompleter::Sync& completer) override {
    return completer.Close(ZX_ERR_NOT_SUPPORTED);
  }

  void Bind(::llcpp::fuchsia::net::SocketAddress addr, BindCompleter::Sync& completer) override {
    return completer.Close(ZX_ERR_NOT_SUPPORTED);
  }

  void Connect(::llcpp::fuchsia::net::SocketAddress addr,
               ConnectCompleter::Sync& completer) override {
    return completer.Close(ZX_ERR_NOT_SUPPORTED);
  }

  void Listen(int16_t backlog, ListenCompleter::Sync& completer) override {
    return completer.Close(ZX_ERR_NOT_SUPPORTED);
  }

  void Accept(bool want_addr, AcceptCompleter::Sync& completer) override {
    return completer.Close(ZX_ERR_NOT_SUPPORTED);
  }

  void GetSockName(GetSockNameCompleter::Sync& completer) override {
    return completer.Close(ZX_ERR_NOT_SUPPORTED);
  }

  void GetPeerName(GetPeerNameCompleter::Sync& completer) override {
    return completer.Close(ZX_ERR_NOT_SUPPORTED);
  }

  void SetSockOpt(int16_t level, int16_t optname, fidl::VectorView<uint8_t> optval,
                  SetSockOptCompleter::Sync& completer) override {
    return completer.Close(ZX_ERR_NOT_SUPPORTED);
  }

  void GetSockOpt(int16_t level, int16_t optname, GetSockOptCompleter::Sync& completer) override {
    return completer.Close(ZX_ERR_NOT_SUPPORTED);
  }

  void Disconnect(DisconnectCompleter::Sync& completer) override {
    return completer.Close(ZX_ERR_NOT_CONNECTED);
  }

  void FillPeerSocket() const {
    zx_info_socket_t info;
    ASSERT_OK(peer_.get_info(ZX_INFO_SOCKET, &info, sizeof(info), nullptr, nullptr));
    size_t tx_buf_available = info.tx_buf_max - info.tx_buf_size;
    std::unique_ptr<uint8_t[]> buf(new uint8_t[tx_buf_available + 1]);
    size_t actual;
    ASSERT_OK(peer_.write(0, buf.get(), tx_buf_available, &actual));
    ASSERT_EQ(actual, tx_buf_available);
  }

  void ResetSocket() { peer_.reset(); }

 private:
  zx::socket peer_;
};

template <int sock_type>
class BaseTest : public ::zxtest::Test {
  static_assert(sock_type == ZX_SOCKET_STREAM || sock_type == ZX_SOCKET_DATAGRAM);

 public:
  BaseTest() : server(clientSocket()), loop(&kAsyncLoopConfigNoAttachToCurrentThread) {
    zx::channel client_channel, server_channel;
    ASSERT_OK(zx::channel::create(0, &client_channel, &server_channel));

    ASSERT_OK(fidl::BindSingleInFlightOnly(loop.dispatcher(), std::move(server_channel), &server));
    ASSERT_OK(loop.StartThread("fake-socket-server"));
    ASSERT_OK(fdio_fd_create(client_channel.release(), client_fd.reset_and_get_address()));
  }

 protected:
  zx::socket server_socket;
  fbl::unique_fd client_fd;
  Server server;
  async::Loop loop;

 private:
  zx::socket clientSocket() {
    zx::socket client_socket;
    // ASSERT_* macros return on failure; wrap it in a lambda to avoid returning void here.
    [&]() { ASSERT_OK(zx::socket::create(sock_type, &client_socket, &server_socket)); }();
    return client_socket;
  }
};

static void set_nonblocking_io(int fd) {
  int flags;
  EXPECT_GE(flags = fcntl(fd, F_GETFL), 0, "%s", strerror(errno));
  EXPECT_EQ(fcntl(fd, F_SETFL, flags | O_NONBLOCK), 0, "%s", strerror(errno));
}

using TcpSocketTest = BaseTest<ZX_SOCKET_STREAM>;
TEST_F(TcpSocketTest, CloseZXSocketOnTransfer) {
  // A socket's peer is not closed until all copies of that peer are closed. Since the server holds
  // one of those copies (and the file descriptor holds the other), we must destroy the server's
  // copy before asserting that fdio_fd_transfer closes the file descriptor's copy.
  server.ResetSocket();

  // The file descriptor still holds a copy of the peer; the peer is still open.
  ASSERT_OK(server_socket.wait_one(ZX_SOCKET_WRITABLE, zx::time::infinite_past(), nullptr));

  zx::handle handle;
  ASSERT_OK(fdio_fd_transfer(client_fd.get(), handle.reset_and_get_address()));

  // The file descriptor has been destroyed; the peer is closed.
  ASSERT_OK(server_socket.wait_one(ZX_SOCKET_PEER_CLOSED, zx::time::infinite_past(), nullptr));
}

// Verify scenario, where multi-segment recvmsg is requested, but the socket has
// just enough data to *completely* fill one segment.
// In this scenario, an attempt to read data for the next segment immediately
// fails with ZX_ERR_SHOULD_WAIT, and this may lead to bogus EAGAIN even if some
// data has actually been read.
TEST_F(TcpSocketTest, RecvmsgNonblockBoundary) {
  set_nonblocking_io(client_fd.get());

  // Write 4 bytes of data to socket.
  size_t actual;
  const uint32_t data_out = 0x12345678;
  EXPECT_OK(server_socket.write(0, &data_out, sizeof(data_out), &actual));
  EXPECT_EQ(actual, sizeof(data_out));

  uint32_t data_in1, data_in2;
  // Fail at compilation stage if anyone changes types.
  // This is mandatory here: we need the first chunk to be exactly the same
  // length as total size of data we just wrote.
  static_assert(sizeof(data_in1) == sizeof(data_out));

  struct iovec iov[2];
  iov[0].iov_base = &data_in1;
  iov[0].iov_len = sizeof(data_in1);
  iov[1].iov_base = &data_in2;
  iov[1].iov_len = sizeof(data_in2);

  struct msghdr msg = {};
  msg.msg_iov = iov;
  msg.msg_iovlen = sizeof(iov) / sizeof(*iov);

  EXPECT_EQ(recvmsg(client_fd.get(), &msg, 0), sizeof(data_out), "%s", strerror(errno));

  EXPECT_EQ(close(client_fd.release()), 0, "%s", strerror(errno));
}

// Make sure we can successfully read zero bytes if we pass a zero sized input buffer.
TEST_F(TcpSocketTest, RecvmsgEmptyBuffer) {
  set_nonblocking_io(client_fd.get());

  // Write 4 bytes of data to socket.
  size_t actual;
  const uint32_t data_out = 0x12345678;
  EXPECT_OK(server_socket.write(0, &data_out, sizeof(data_out), &actual));
  EXPECT_EQ(actual, sizeof(data_out));

  // Try to read into an empty set of io vectors.
  struct msghdr msg = {};
  msg.msg_iov = nullptr;
  msg.msg_iovlen = 0;

  // We should "successfully" read zero bytes.
  EXPECT_EQ(recvmsg(client_fd.get(), &msg, 0), 0, "%s", strerror(errno));
}

// Verify scenario, where multi-segment sendmsg is requested, but the socket has
// just enough spare buffer to *completely* read one segment.
// In this scenario, an attempt to send second segment should immediately fail
// with ZX_ERR_SHOULD_WAIT, but the sendmsg should report first segment length
// rather than failing with EAGAIN.
TEST_F(TcpSocketTest, SendmsgNonblockBoundary) {
  set_nonblocking_io(client_fd.get());

  const size_t memlength = 65536;
  std::unique_ptr<uint8_t[]> memchunk(new uint8_t[memlength]);

  struct iovec iov[2];
  iov[0].iov_base = memchunk.get();
  iov[0].iov_len = memlength;
  iov[1].iov_base = memchunk.get();
  iov[1].iov_len = memlength;

  struct msghdr msg = {};
  msg.msg_iov = iov;
  msg.msg_iovlen = sizeof(iov) / sizeof(*iov);

  // 1. Fill up the client socket.
  server.FillPeerSocket();

  // 2. Consume one segment of the data
  size_t actual;
  EXPECT_OK(server_socket.read(0, memchunk.get(), memlength, &actual));
  EXPECT_EQ(memlength, actual);

  // 3. Push again 2 packets of <memlength> bytes, observe only one sent.
  EXPECT_EQ(sendmsg(client_fd.get(), &msg, 0), (ssize_t)memlength, "%s", strerror(errno));

  EXPECT_EQ(close(client_fd.release()), 0, "%s", strerror(errno));
}

using UdpSocketTest = BaseTest<ZX_SOCKET_DATAGRAM>;
TEST_F(UdpSocketTest, DatagramSendMsg) {
  struct sockaddr_in addr = {};
  socklen_t addrlen = sizeof(addr);
  addr.sin_family = AF_INET;
  addr.sin_port = htons(0);
  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

  const char buf[] = "hello";
  char rcv_buf[4096] = {0};
  std::array<struct iovec, 1> iov = {{{
      .iov_base = (void*)buf,
      .iov_len = sizeof(buf),
  }}};

  struct msghdr msg = {};
  size_t actual = 0;
  // sendmsg should accept 0 length payload.
  EXPECT_EQ(sendmsg(client_fd.get(), &msg, 0), 0, "%s", strerror(errno));
  // no data will have arrived on the other end.
  EXPECT_EQ(server_socket.read(0, rcv_buf, sizeof(rcv_buf), &actual), ZX_ERR_SHOULD_WAIT);
  EXPECT_EQ(actual, 0);

  msg.msg_name = &addr;
  msg.msg_namelen = addrlen;
  msg.msg_iov = iov.data();
  msg.msg_iovlen = iov.size();

  EXPECT_EQ(sendmsg(client_fd.get(), &msg, 0), sizeof(buf), "%s", strerror(errno));

  // sendmsg doesn't fail when msg_namelen is greater than sizeof(struct sockaddr_storage) because
  // what's being tested here is a fuchsia.posix.socket.StreamSocket backed by a
  // zx::socket(ZX_SOCKET_DATAGRAM), a Frankenstein's monster which implements stream semantics on
  // the network and datagram semantics on the transport to the netstack.
  msg.msg_namelen = sizeof(sockaddr_storage) + 1;
  EXPECT_EQ(sendmsg(client_fd.get(), &msg, 0), sizeof(buf), "%s", strerror(errno));

  for (int i = 0; i < 2; i++) {
    EXPECT_OK(server_socket.read(0, rcv_buf, sizeof(rcv_buf), &actual));
    EXPECT_EQ(actual, sizeof(buf));
  }

  EXPECT_EQ(close(client_fd.release()), 0, "%s", strerror(errno));
}

template <int optname>
auto timeout = [](int client_fd, zx::socket server_socket) {
  static_assert(optname == SO_RCVTIMEO || optname == SO_SNDTIMEO);

  // We want this to be a small number so the test is fast, but at least 1
  // second so that we exercise `tv_sec`.
  const auto timeout = std::chrono::seconds(1) + std::chrono::milliseconds(50);
  {
    const auto sec = std::chrono::duration_cast<std::chrono::seconds>(timeout);
    const struct timeval tv = {
        .tv_sec = sec.count(),
        .tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(timeout - sec).count(),
    };
    ASSERT_EQ(setsockopt(client_fd, SOL_SOCKET, optname, &tv, sizeof(tv)), 0, "%s",
              strerror(errno));
    struct timeval actual_tv;
    socklen_t optlen = sizeof(actual_tv);
    ASSERT_EQ(getsockopt(client_fd, SOL_SOCKET, optname, &actual_tv, &optlen), 0, "%s",
              strerror(errno));
    ASSERT_EQ(optlen, sizeof(actual_tv));
    ASSERT_EQ(actual_tv.tv_sec, tv.tv_sec);
    ASSERT_EQ(actual_tv.tv_usec, tv.tv_usec);
  }

  const auto margin = std::chrono::milliseconds(50);

  uint8_t buf[16];

  // Perform the read/write. This is the core of the test - we expect the operation to time out
  // per our setting of the timeout above.

  const auto start = std::chrono::steady_clock::now();

  switch (optname) {
    case SO_RCVTIMEO:
      ASSERT_EQ(read(client_fd, buf, sizeof(buf)), -1);
      break;
    case SO_SNDTIMEO:
      ASSERT_EQ(write(client_fd, buf, sizeof(buf)), -1);
      break;
  }
  ASSERT_TRUE(errno == EAGAIN || errno == EWOULDBLOCK, "%s", strerror(errno));

  const auto elapsed = std::chrono::steady_clock::now() - start;

  // Check that the actual time waited was close to the expectation.
  const auto elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed);

  // TODO(fxbug.dev/40135): Only the lower bound of the elapsed time is checked. The upper bound
  // check is ignored as the syscall could far miss the defined deadline to return.
  EXPECT_GT(elapsed, timeout - margin, "elapsed=%lld ms (which is not within %lld ms of %lld ms)",
            elapsed_ms.count(), margin.count(), std::chrono::milliseconds(timeout).count());

  // Remove the timeout.
  const struct timeval tv = {};
  ASSERT_EQ(setsockopt(client_fd, SOL_SOCKET, optname, &tv, sizeof(tv)), 0, "%s", strerror(errno));
  // Wrap the read/write in a future to enable a timeout. We expect the future
  // to time out.
  std::latch fut_started(1);
  auto fut = std::async(std::launch::async, [&]() -> std::pair<ssize_t, int> {
    fut_started.count_down();

    switch (optname) {
      case SO_RCVTIMEO:
        return std::make_pair(read(client_fd, buf, sizeof(buf)), errno);
      case SO_SNDTIMEO:
        return std::make_pair(write(client_fd, buf, sizeof(buf)), errno);
    }
  });
  fut_started.wait();
  EXPECT_EQ(fut.wait_for(margin), std::future_status::timeout);
  // Resetting the remote end socket should cause the read/write to complete.
  server_socket.reset();
  auto return_code_and_errno = fut.get();
  EXPECT_EQ(return_code_and_errno.first, -1);
  ASSERT_EQ(return_code_and_errno.second, ECONNRESET, "%s", strerror(return_code_and_errno.second));

  ASSERT_EQ(close(client_fd), 0, "%s", strerror(errno));
};

TEST_F(TcpSocketTest, RcvTimeout) {
  timeout<SO_RCVTIMEO>(client_fd.release(), std::move(server_socket));
}

TEST_F(TcpSocketTest, SndTimeout) {
  server.FillPeerSocket();
  timeout<SO_SNDTIMEO>(client_fd.release(), std::move(server_socket));
}

}  // namespace
