// Copyright 2019 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 "src/developer/debug/zxdb/client/socket_connect.h"

#include <fcntl.h>
#include <sys/socket.h>

#include "src/developer/debug/shared/logging/logging.h"
#include "src/developer/debug/zxdb/common/err.h"

#if defined(__APPLE__)

// NOTE): In the MacOS case, getaddrinfo (the approach used for Linux) would result almost always in
// an "Address family not supported by protocol family" error when trying to connect. A lot of
// debugging got nowhere and finally decided to go the inet_pton way.
//
// Ironically, we cannot (easily) use this approach for linux too because turns out that MacOS's
// inet_pton has extended functionality that enables it to support link-local IPv6 addresses that
// specify the interface (which is needed to correctly connect to link-local addresses). In linux is
// a more contrived dance that requires to iterate over all the interfaces, so it's simpler to go
// the normal getaddrinfo route.
//
// Some background info that lead me to discard getaddrinfo altogether:
//
// https://blog.powerdns.com/2014/05/21/a-surprising-discovery-on-converting-ipv6-addresses-we-no-longer-prefer-getaddrinfo/

#include <arpa/inet.h>

#include <variant>

namespace zxdb {

namespace {

using SockAddrVariant = std::variant<sockaddr_in, sockaddr_in6>;

Err ResolveTargetAddress(const std::string& host, uint16_t port, SockAddrVariant* out) {
  int res;
  // First try IPv6. Result of 0 means that the string is not IPv6.
  struct sockaddr_in6 addr6 = {};  // zero-out.
  res = inet_pton(AF_INET6, host.c_str(), &addr6.sin6_addr);
  if (res == 1) {
    // Successfully found IPv6 address.
    addr6.sin6_family = AF_INET6;
    addr6.sin6_port = htons(port);
    *out = std::move(addr6);
    return Err();
  }

  DEBUG_LOG(RemoteAPI) << "Could not resolve IPv6: " << strerror(errno) << " (res: " << res << ").";

  // We now try IPv4.
  struct sockaddr_in addr4 = {};  // zero-out.
  res = inet_pton(AF_INET, host.c_str(), &addr4.sin_addr);
  if (res == 1) {
    // Successfully found IPv4 address.
    addr4.sin_family = AF_INET;
    addr4.sin_port = htons(port);
    *out = std::move(addr4);
    return Err();
  }

  return Err("Address %s is not a valid IPv4 or IPv6 address.", host.c_str());
}

}  // namespace

Err ConnectToHost(const std::string& host, uint16_t port, fbl::unique_fd* socket_out) {
  SockAddrVariant addr_variant;
  Err err = ResolveTargetAddress(host, port, &addr_variant);
  if (err.has_error())
    return err;

  fbl::unique_fd res_socket;

  // Is it IPv6?
  if (std::holds_alternative<sockaddr_in6>(addr_variant)) {
    res_socket.reset(socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP));
    if (!res_socket.is_valid())
      return Err("Could not create socket: %s.", strerror(errno));

    sockaddr_in6& addr6 = std::get<sockaddr_in6>(addr_variant);
    if (connect(res_socket.get(), reinterpret_cast<sockaddr*>(&addr6), sizeof(sockaddr_in6))) {
      return Err("Could not connect to socket: %s.", strerror(errno));
    }
  }

  // Fallback to IPv4.
  if (std::holds_alternative<sockaddr_in>(addr_variant)) {
    res_socket.reset(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
    if (!res_socket.is_valid())
      return Err("Could not create socket: %s.", strerror(errno));

    sockaddr_in& addr4 = std::get<sockaddr_in>(addr_variant);
    if (connect(res_socket.get(), reinterpret_cast<sockaddr*>(&addr4), sizeof(sockaddr_in))) {
      return Err("Could not connect to socket: %s.", strerror(errno));
    }
  }

  // By default sockets are blocking which we don't want.
  if (fcntl(res_socket.get(), F_SETFL, O_NONBLOCK) < 0)
    return Err("Could not make nonblocking socket.");

  *socket_out = std::move(res_socket);
  return Err();
}

}  // namespace zxdb

#elif defined(__linux__)

#include <netdb.h>

#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

namespace {

// Tries to resolve the host/port. On success populates *addr and returns Err().
Err ResolveAddress(const std::string& host, uint16_t port, addrinfo* addr) {
  std::string port_str = fxl::StringPrintf("%u", port);

  struct addrinfo hints;
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP;

  struct addrinfo* addrs = nullptr;
  int addr_err = getaddrinfo(host.c_str(), port_str.c_str(), &hints, &addrs);
  if (addr_err != 0) {
    return Err("Failed to resolve %s: %s.", host.c_str(), gai_strerror(addr_err));
  }

  struct addrinfo* p;
  for (p = addrs; p != nullptr; p = p->ai_next) {
    char buf[1024];
    getnameinfo(p->ai_addr, p->ai_addrlen, buf, sizeof(buf), nullptr, 0, NI_NUMERICHOST);
  }

  *addr = *addrs;
  freeaddrinfo(addrs);
  return Err();
}

}  // namespace

Err ConnectToHost(const std::string& host, uint16_t port, fbl::unique_fd* socket_out) {
  addrinfo addr;
  Err err = ResolveAddress(host, port, &addr);
  if (err.has_error())
    return err;

  fbl::unique_fd res_socket;

  res_socket.reset(socket(addr.ai_family, SOCK_STREAM, IPPROTO_TCP));
  if (!res_socket.is_valid())
    return Err("Could not create socket: %s.", strerror(errno));

  if (connect(res_socket.get(), addr.ai_addr, addr.ai_addrlen))
    return Err("Failed to connect socket: %s.", strerror(errno));

  // By default sockets are blocking which we don't want.
  if (fcntl(res_socket.get(), F_SETFL, O_NONBLOCK) < 0)
    return Err("Could not make nonblocking socket: %s.", strerror(errno));

  *socket_out = std::move(res_socket);
  return Err();
}

}  // namespace zxdb

#else
#error Unsupported OS
#endif

namespace zxdb {

Err ConnectToUnixSocket(const std::string& path, fbl::unique_fd* socket_out) {
  int fd;
  if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
    return Err("Socket error");
  }
  fcntl(fd, F_SETFL, O_NONBLOCK);

  std::vector<uint8_t> sockaddr_data(path.size() + sizeof(sockaddr));
  auto addr = reinterpret_cast<struct sockaddr*>(sockaddr_data.data());
  addr->sa_family = AF_UNIX;
  strcpy(addr->sa_data, path.c_str());

  if (connect(fd, addr, sockaddr_data.size()) == -1) {
    return Err("Connect error");
  }

  *socket_out = fbl::unique_fd(fd);
  return Err();
}

}  // namespace zxdb
