//===-- SocketTestUtilities.cpp -------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "SocketTestUtilities.h"
#include "lldb/Host/Config.h"
#include "lldb/Utility/StreamString.h"

#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <arpa/inet.h>
#endif

using namespace lldb_private;

static void AcceptThread(Socket *listen_socket, bool child_processes_inherit,
                         Socket **accept_socket, Status *error) {
  *error = listen_socket->Accept(*accept_socket);
}

template <typename SocketType>
void lldb_private::CreateConnectedSockets(
    llvm::StringRef listen_remote_address,
    const std::function<std::string(const SocketType &)> &get_connect_addr,
    std::unique_ptr<SocketType> *a_up, std::unique_ptr<SocketType> *b_up) {
  bool child_processes_inherit = false;
  Status error;
  std::unique_ptr<SocketType> listen_socket_up(
      new SocketType(true, child_processes_inherit));
  ASSERT_THAT_ERROR(error.ToError(), llvm::Succeeded());
  error = listen_socket_up->Listen(listen_remote_address, 5);
  ASSERT_THAT_ERROR(error.ToError(), llvm::Succeeded());
  ASSERT_TRUE(listen_socket_up->IsValid());

  Status accept_error;
  Socket *accept_socket;
  std::thread accept_thread(AcceptThread, listen_socket_up.get(),
                            child_processes_inherit, &accept_socket,
                            &accept_error);

  std::string connect_remote_address = get_connect_addr(*listen_socket_up);
  std::unique_ptr<SocketType> connect_socket_up(
      new SocketType(true, child_processes_inherit));
  ASSERT_THAT_ERROR(error.ToError(), llvm::Succeeded());
  error = connect_socket_up->Connect(connect_remote_address);
  ASSERT_THAT_ERROR(error.ToError(), llvm::Succeeded());
  ASSERT_TRUE(connect_socket_up->IsValid());

  a_up->swap(connect_socket_up);
  ASSERT_TRUE((*a_up)->IsValid());

  accept_thread.join();
  b_up->reset(static_cast<SocketType *>(accept_socket));
  ASSERT_THAT_ERROR(accept_error.ToError(), llvm::Succeeded());
  ASSERT_NE(nullptr, b_up->get());
  ASSERT_TRUE((*b_up)->IsValid());

  listen_socket_up.reset();
}

bool lldb_private::CreateTCPConnectedSockets(
    std::string listen_remote_ip, std::unique_ptr<TCPSocket> *socket_a_up,
    std::unique_ptr<TCPSocket> *socket_b_up) {
  StreamString strm;
  strm.Printf("[%s]:0", listen_remote_ip.c_str());
  CreateConnectedSockets<TCPSocket>(
      strm.GetString(),
      [=](const TCPSocket &s) {
        char connect_remote_address[64];
        snprintf(connect_remote_address, sizeof(connect_remote_address),
                 "[%s]:%u", listen_remote_ip.c_str(), s.GetLocalPortNumber());
        return std::string(connect_remote_address);
      },
      socket_a_up, socket_b_up);
  return true;
}

#if LLDB_ENABLE_POSIX
void lldb_private::CreateDomainConnectedSockets(
    llvm::StringRef path, std::unique_ptr<DomainSocket> *socket_a_up,
    std::unique_ptr<DomainSocket> *socket_b_up) {
  return CreateConnectedSockets<DomainSocket>(
      path, [=](const DomainSocket &) { return path.str(); }, socket_a_up,
      socket_b_up);
}
#endif

static bool CheckIPSupport(llvm::StringRef Proto, llvm::StringRef Addr) {
  llvm::Expected<std::unique_ptr<TCPSocket>> Sock = Socket::TcpListen(
      Addr, /*child_processes_inherit=*/false);
  if (Sock)
    return true;
  llvm::Error Err = Sock.takeError();
  GTEST_LOG_(WARNING) << llvm::formatv(
                             "Creating a canary {0} TCP socket failed: {1}.",
                             Proto, Err)
                             .str();
  bool HasProtocolError = false;
  handleAllErrors(std::move(Err), [&](std::unique_ptr<llvm::ECError> ECErr) {
    std::error_code ec = ECErr->convertToErrorCode();
    if (ec == std::make_error_code(std::errc::address_family_not_supported) ||
        ec == std::make_error_code(std::errc::address_not_available))
      HasProtocolError = true;
  });
  if (HasProtocolError) {
    GTEST_LOG_(WARNING)
        << llvm::formatv(
               "Assuming the host does not support {0}. Skipping test.", Proto)
               .str();
    return false;
  }
  GTEST_LOG_(WARNING) << "Continuing anyway. The test will probably fail.";
  return true;
}

bool lldb_private::HostSupportsIPv4() {
  return CheckIPSupport("IPv4", "127.0.0.1:0");
}

bool lldb_private::HostSupportsIPv6() {
  return CheckIPSupport("IPv6", "[::1]:0");
}
