// 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.

#if !defined(DART_IO_DISABLED)

#include "bin/socket_base.h"

#include "bin/dartutils.h"
#include "bin/io_buffer.h"
#include "bin/isolate_data.h"
#include "bin/lockers.h"
#include "bin/thread.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() {
  if (addr_.ss.ss_family == AF_INET6) {
    return TYPE_IPV6;
  }
  return TYPE_IPV4;
}


intptr_t SocketAddress::GetAddrLength(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 sockaddr_in6)
                                         : sizeof(struct sockaddr_in);
}


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 == AF_INET) {
    if (b.ss.ss_family != AF_INET) {
      return false;
    }
    return memcmp(&a.in.sin_addr, &b.in.sin_addr, sizeof(a.in.sin_addr)) == 0;
  } else if (a.ss.ss_family == AF_INET6) {
    if (b.ss.ss_family != AF_INET6) {
      return false;
    }
    return memcmp(&a.in6.sin6_addr, &b.in6.sin6_addr,
                  sizeof(a.in6.sin6_addr)) == 0;
  } else {
    UNREACHABLE();
    return false;
  }
}


void SocketAddress::GetSockAddr(Dart_Handle obj, RawAddr* addr) {
  Dart_TypedData_Type data_type;
  uint8_t* data = NULL;
  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_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;
    memmove(reinterpret_cast<void*>(&addr->in.sin_addr), data, len);
  } else {
    ASSERT(len == sizeof(in6_addr));
    addr->in6.sin6_family = AF_INET6;
    memmove(reinterpret_cast<void*>(&addr->in6.sin6_addr), data, len);
  }
  Dart_TypedDataReleaseData(obj);
}


int16_t SocketAddress::FromType(int type) {
  if (type == TYPE_ANY) {
    return AF_UNSPEC;
  }
  if (type == TYPE_IPV4) {
    return AF_INET;
  }
  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 {
    addr->in6.sin6_port = htons(port);
  }
}


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


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;
  CObjectUint8Array* data =
      new CObjectUint8Array(CObject::NewUint8Array(in_addr_len));
  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);
  }
  memmove(data->Buffer(), in_addr, in_addr_len);
  return data;
}


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


void FUNCTION_NAME(NetworkInterface_ListSupported)(Dart_NativeArguments args) {
  Dart_SetReturnValue(args,
                      Dart_NewBoolean(SocketBase::ListInterfacesSupported()));
}


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_SetReturnValue(args, is_bind_error ? Dart_True() : Dart_False());
}

}  // namespace bin
}  // namespace dart

#endif  // !defined(DART_IO_DISABLED)
