// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "bin/socket_base.h"

#include <errno.h>  // NOLINT

#include "bin/dartutils.h"
#include "bin/io_buffer.h"
#include "bin/isolate_data.h"
#include "bin/lockers.h"
#include "bin/thread.h"
#include "bin/typed_data_utils.h"
#include "bin/utils.h"

#include "include/dart_api.h"

#include "platform/globals.h"
#include "platform/utils.h"

namespace dart {
namespace bin {

int SocketAddress::GetType() const {
  switch (addr_.ss.ss_family) {
    case AF_INET6:
      return TYPE_IPV6;
    case AF_INET:
      return TYPE_IPV4;
    case AF_UNIX:
      return TYPE_UNIX;
    default:
      UNREACHABLE();
      return TYPE_ANY;
  }
}

intptr_t SocketAddress::GetInAddrLength(const RawAddr& addr) {
  ASSERT((addr.ss.ss_family == AF_INET) || (addr.ss.ss_family == AF_INET6));
  return (addr.ss.ss_family == AF_INET6) ? sizeof(struct in6_addr)
                                         : sizeof(struct in_addr);
}

bool SocketAddress::AreAddressesEqual(const RawAddr& a, const RawAddr& b) {
  if (a.ss.ss_family != b.ss.ss_family) {
    return false;
  }
  if (a.ss.ss_family == AF_INET) {
    return memcmp(&a.in.sin_addr, &b.in.sin_addr, sizeof(a.in.sin_addr)) == 0;
  } else if (a.ss.ss_family == AF_INET6) {
    return memcmp(&a.in6.sin6_addr, &b.in6.sin6_addr,
                  sizeof(a.in6.sin6_addr)) == 0 &&
           a.in6.sin6_scope_id == b.in6.sin6_scope_id;
  } else if (a.ss.ss_family == AF_UNIX) {
    if (a.size != b.size) {
      return false;
    }

    // Cast below is avoid signed vs unsigned comparison warning on some OSes.
    return (a.size <=
            static_cast<socklen_t>(offsetof(decltype(a.un), sun_path))) ||
           (memcmp(a.un.sun_path, b.un.sun_path,
                   a.size - offsetof(decltype(a.un), sun_path)) == 0);
  } else {
    UNREACHABLE();
    return false;
  }
}

void SocketAddress::GetSockAddr(Dart_Handle obj, RawAddr* addr) {
  Dart_TypedData_Type data_type;
  uint8_t* data = nullptr;
  intptr_t len;
  Dart_Handle result = Dart_TypedDataAcquireData(
      obj, &data_type, reinterpret_cast<void**>(&data), &len);
  if (Dart_IsError(result)) {
    Dart_PropagateError(result);
  }
  if ((data_type != Dart_TypedData_kUint8) ||
      ((len != sizeof(in_addr)) && (len != sizeof(in6_addr)))) {
    Dart_TypedDataReleaseData(obj);
    Dart_PropagateError(Dart_NewApiError("Unexpected type for socket address"));
  }
  memset(reinterpret_cast<void*>(addr), 0, sizeof(RawAddr));
  if (len == sizeof(in_addr)) {
    addr->in.sin_family = AF_INET;
    addr->size = sizeof(sockaddr_in);
    memmove(reinterpret_cast<void*>(&addr->in.sin_addr), data, len);
  } else {
    ASSERT(len == sizeof(in6_addr));
    addr->in6.sin6_family = AF_INET6;
    addr->size = sizeof(sockaddr_in6);
    memmove(reinterpret_cast<void*>(&addr->in6.sin6_addr), data, len);
  }
  Dart_TypedDataReleaseData(obj);
}

Dart_Handle SocketAddress::GetUnixDomainSockAddr(const char* path,
                                                 Namespace* namespc,
                                                 RawAddr* addr) {
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
  NamespaceScope ns(namespc, path);
  path = ns.path();
  const bool is_abstract = (path[0] == '@');
  if (is_abstract) {
    // The following 107 bytes after the leading null byte represents the name
    // of unix domain socket. Without reseting, even users provide the same path
    // for bind and connect, they actually represent two different address and
    // connection will be rejected.
    bzero(addr->un.sun_path, sizeof(addr->un.sun_path));
  }
#else
  const bool is_abstract = false;
#endif  // defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
  const auto path_len = strlen(path);
  if (path_len >= sizeof(addr->un.sun_path)) {
    OSError os_error(-1,
                     "The length of path exceeds the limit. "
                     "Check out man 7 unix page",
                     OSError::kUnknown);
    return DartUtils::NewDartOSError(&os_error);
  }
  addr->un.sun_family = AF_UNIX;
  // Trailing '\0' is not meaningful for abstract namespace sockets.
  const auto path_total_bytes = path_len + (is_abstract ? 0 : 1);
  memmove(addr->un.sun_path, path, path_total_bytes);
  addr->size = offsetof(decltype(addr->un), sun_path) + path_total_bytes;
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
  // In case of abstract namespace, transfer the leading '@' into a null byte.
  if (is_abstract) {
    addr->un.sun_path[0] = '\0';
  }
#endif  // defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
  return Dart_Null();
}

int16_t SocketAddress::FromType(int type) {
  if (type == TYPE_ANY) {
    return AF_UNSPEC;
  }
  if (type == TYPE_IPV4) {
    return AF_INET;
  }
  if (type == TYPE_UNIX) {
    return AF_UNIX;
  }
  ASSERT((type == TYPE_IPV6) && "Invalid type");
  return AF_INET6;
}

void SocketAddress::SetAddrPort(RawAddr* addr, intptr_t port) {
  if (addr->ss.ss_family == AF_INET) {
    addr->in.sin_port = htons(port);
  } else if (addr->ss.ss_family == AF_INET6) {
    addr->in6.sin6_port = htons(port);
  } else {
    UNREACHABLE();
  }
}

intptr_t SocketAddress::GetAddrPort(const RawAddr& addr) {
  if (addr.ss.ss_family == AF_INET) {
    return ntohs(addr.in.sin_port);
  } else if (addr.ss.ss_family == AF_INET6) {
    return ntohs(addr.in6.sin6_port);
  } else if (addr.ss.ss_family == AF_UNIX) {
    return 0;
  } else {
    UNREACHABLE();
    return -1;
  }
}

Dart_Handle SocketAddress::ToTypedData(const RawAddr& addr) {
  int len = GetInAddrLength(addr);
  Dart_Handle result = Dart_NewTypedData(Dart_TypedData_kUint8, len);
  if (Dart_IsError(result)) {
    Dart_PropagateError(result);
  }
  Dart_Handle err;
  if (addr.addr.sa_family == AF_INET6) {
    err = Dart_ListSetAsBytes(
        result, 0, reinterpret_cast<const uint8_t*>(&addr.in6.sin6_addr), len);
  } else {
    err = Dart_ListSetAsBytes(
        result, 0, reinterpret_cast<const uint8_t*>(&addr.in.sin_addr), len);
  }
  if (Dart_IsError(err)) {
    Dart_PropagateError(err);
  }
  return result;
}

CObjectUint8Array* SocketAddress::ToCObject(const RawAddr& addr) {
  int in_addr_len = SocketAddress::GetInAddrLength(addr);
  const void* in_addr;
  if (addr.addr.sa_family == AF_INET6) {
    in_addr = reinterpret_cast<const void*>(&addr.in6.sin6_addr);
  } else {
    in_addr = reinterpret_cast<const void*>(&addr.in.sin_addr);
  }
  CObjectUint8Array* data =
      new CObjectUint8Array(CObject::NewUint8Array(in_addr, in_addr_len));
  return data;
}
void SocketAddress::SetAddrScope(RawAddr* addr, intptr_t scope_id) {
  if (addr->addr.sa_family != AF_INET6) return;
  addr->in6.sin6_scope_id = scope_id;
}

intptr_t SocketAddress::GetAddrScope(const RawAddr& addr) {
  if (addr.addr.sa_family == AF_INET6) {
    return addr.in6.sin6_scope_id;
  } else {
    return 0;
  }
}

void FUNCTION_NAME(InternetAddress_Parse)(Dart_NativeArguments args) {
  const char* address =
      DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
  ASSERT(address != nullptr);
  RawAddr raw;
  memset(&raw.addr, 0, sizeof(raw.addr));
  int type = strchr(address, ':') == nullptr ? SocketAddress::TYPE_IPV4
                                             : SocketAddress::TYPE_IPV6;
  if (type == SocketAddress::TYPE_IPV4) {
    raw.addr.sa_family = AF_INET;
    raw.size = sizeof(sockaddr_in);
  } else {
    raw.addr.sa_family = AF_INET6;
    raw.size = sizeof(sockaddr_in6);
  }
  bool ok = SocketBase::ParseAddress(type, address, &raw);
  if (!ok) {
    Dart_SetReturnValue(args, Dart_Null());
  } else {
    Dart_SetReturnValue(args, SocketAddress::ToTypedData(raw));
  }
}

void FUNCTION_NAME(InternetAddress_ParseScopedLinkLocalAddress)(
    Dart_NativeArguments args) {
  const char* address =
      DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
  // This must be an IPv6 address.
  intptr_t type = 1;
  ASSERT(address != nullptr);
  OSError* os_error = nullptr;
  AddressList<SocketAddress>* addresses =
      SocketBase::LookupAddress(address, type, &os_error);
  if (addresses != nullptr) {
    SocketAddress* addr = addresses->GetAt(0);
    Dart_SetReturnValue(
        args, Dart_NewInteger(SocketAddress::GetAddrScope(addr->addr())));
    delete addresses;
  } else {
    Dart_SetReturnValue(args, DartUtils::NewDartOSError(os_error));
    delete os_error;
  }
}

void FUNCTION_NAME(InternetAddress_RawAddrToString)(Dart_NativeArguments args) {
  RawAddr addr;
  SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 0), &addr);
  char str[SocketAddress::kMaxAddressStringLength];
  bool ok = SocketBase::RawAddrToString(&addr, str);
  if (!ok) {
    str[0] = '\0';
  }
  Dart_SetReturnValue(args, ThrowIfError(DartUtils::NewString(str)));
}

void FUNCTION_NAME(SocketBase_IsBindError)(Dart_NativeArguments args) {
  intptr_t error_number =
      DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 1));
  bool is_bind_error = SocketBase::IsBindError(error_number);
  Dart_SetBooleanReturnValue(args, is_bind_error ? true : false);
}

bool SocketBase::IsValidAddress(const char* address) {
  ASSERT(address != nullptr);
  RawAddr raw;
  memset(&raw.addr, 0, sizeof(raw.addr));
  int type = strchr(address, ':') == nullptr ? SocketAddress::TYPE_IPV4
                                             : SocketAddress::TYPE_IPV6;
  if (type == SocketAddress::TYPE_IPV4) {
    raw.addr.sa_family = AF_INET;
    raw.size = sizeof(sockaddr_in);
  } else {
    raw.addr.sa_family = AF_INET6;
    raw.size = sizeof(sockaddr_in6);
  }
  return SocketBase::ParseAddress(type, address, &raw);
}

#if !defined(DART_HOST_OS_WINDOWS)
intptr_t SocketBase::Write(intptr_t fd,
                           const void* buffer,
                           intptr_t num_bytes,
                           SocketOpKind sync) {
  // For non-blocking sockets we must write as many bytes as possible into
  // the output to trigger EAGAIN otherwise we are not guaranteed to
  // receive an event from epoll which we are using in edge-triggering
  // (EPOLLET) mode. See man epoll for more information and guidelines.
  ssize_t num_bytes_left = num_bytes;
  while (num_bytes_left > 0) {
    ssize_t written_bytes = WriteImpl(fd, buffer, num_bytes_left, sync);
    static_assert(EAGAIN == EWOULDBLOCK);
    if (written_bytes == -1) {
      if ((sync == kAsync) && (errno == EWOULDBLOCK)) {
        break;
      }

      return -1;  // Error occurred.
    }

    num_bytes_left -= written_bytes;
    buffer = static_cast<const char*>(buffer) + written_bytes;
  }

  return num_bytes - num_bytes_left;
}
#endif

}  // namespace bin
}  // namespace dart
