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

#define DART_CHECK_ERROR_AND_CLEANUP(handle, ptr)                              \
  do {                                                                         \
    if (Dart_IsError((handle))) {                                              \
      delete (ptr);                                                            \
      Dart_SetReturnValue(args, (handle));                                     \
      return;                                                                  \
    }                                                                          \
  } while (0)

#define DART_CHECK_ERROR(handle)                                               \
  do {                                                                         \
    if (Dart_IsError((handle))) {                                              \
      Dart_SetReturnValue(args, (handle));                                     \
      return;                                                                  \
    }                                                                          \
  } while (0)

namespace dart {
namespace bin {

static constexpr int kSocketIdNativeField = 0;

void FUNCTION_NAME(SynchronousSocket_LookupRequest)(Dart_NativeArguments args) {
  if (Dart_GetNativeArgumentCount(args) != 2) {
    Dart_SetReturnValue(
        args, DartUtils::NewDartArgumentError("Invalid argument count."));
    return;
  }

  char* peer = nullptr;
  Dart_Handle host_arg =
      Dart_GetNativeStringArgument(args, 0, reinterpret_cast<void**>(&peer));
  DART_CHECK_ERROR(host_arg);

  char* host = nullptr;
  host_arg = Dart_StringToCString(host_arg, const_cast<const char**>(&host));
  DART_CHECK_ERROR(host_arg);

  int64_t type = 0;
  Dart_Handle port_error = Dart_GetNativeIntegerArgument(args, 1, &type);
  DART_CHECK_ERROR(port_error);

  OSError* os_error = nullptr;
  AddressList<SocketAddress>* addresses =
      SocketBase::LookupAddress(host, type, &os_error);
  if (addresses == nullptr) {
    Dart_SetReturnValue(args, DartUtils::NewDartOSError(os_error));
    return;
  }

  Dart_Handle array = Dart_NewList(addresses->count());
  DART_CHECK_ERROR_AND_CLEANUP(array, addresses);

  for (intptr_t i = 0; i < addresses->count(); i++) {
    SocketAddress* addr = addresses->GetAt(i);
    Dart_Handle entry = Dart_NewList(3);
    DART_CHECK_ERROR_AND_CLEANUP(entry, addresses);

    Dart_Handle type = Dart_NewInteger(addr->GetType());
    DART_CHECK_ERROR_AND_CLEANUP(type, addresses);
    Dart_Handle error = Dart_ListSetAt(entry, 0, type);
    DART_CHECK_ERROR_AND_CLEANUP(error, addresses);

    Dart_Handle as_string = Dart_NewStringFromCString(addr->as_string());
    DART_CHECK_ERROR_AND_CLEANUP(as_string, addresses);
    error = Dart_ListSetAt(entry, 1, as_string);
    DART_CHECK_ERROR_AND_CLEANUP(error, addresses);

    RawAddr raw = addr->addr();
    Dart_Handle data = SocketAddress::ToTypedData(raw);
    DART_CHECK_ERROR_AND_CLEANUP(data, addresses);

    error = Dart_ListSetAt(entry, 2, data);
    DART_CHECK_ERROR_AND_CLEANUP(error, addresses);
    error = Dart_ListSetAt(array, i, entry);
    DART_CHECK_ERROR_AND_CLEANUP(error, addresses);
  }
  delete addresses;
  Dart_SetReturnValue(args, array);
  return;
}

void FUNCTION_NAME(SynchronousSocket_CreateConnectSync)(
    Dart_NativeArguments args) {
  RawAddr addr;
  SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
  Dart_Handle port_arg = Dart_GetNativeArgument(args, 2);
  DART_CHECK_ERROR(port_arg);
  int64_t port = DartUtils::GetInt64ValueCheckRange(port_arg, 0, 65535);
  SocketAddress::SetAddrPort(&addr, static_cast<intptr_t>(port));
  intptr_t socket = SynchronousSocket::CreateConnect(addr);
  if (socket >= 0) {
    Dart_Handle error = SynchronousSocket::SetSocketIdNativeField(
        Dart_GetNativeArgument(args, 0), new SynchronousSocket(socket));
    DART_CHECK_ERROR(error);
    Dart_SetBooleanReturnValue(args, true);
  } else {
    Dart_SetReturnValue(args, DartUtils::NewDartOSError());
  }
}

void FUNCTION_NAME(SynchronousSocket_WriteList)(Dart_NativeArguments args) {
  SynchronousSocket* socket = nullptr;
  Dart_Handle result = SynchronousSocket::GetSocketIdNativeField(
      Dart_GetNativeArgument(args, 0), &socket);
  DART_CHECK_ERROR(result);

  Dart_Handle buffer_obj = Dart_GetNativeArgument(args, 1);
  if (!Dart_IsList(buffer_obj)) {
    Dart_SetReturnValue(args, DartUtils::NewDartArgumentError(
                                  "First parameter must be a List<int>"));
    return;
  }
  intptr_t offset = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 2));
  intptr_t length = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 3));
  Dart_TypedData_Type type;
  uint8_t* buffer = nullptr;
  intptr_t len;
  result = Dart_TypedDataAcquireData(buffer_obj, &type,
                                     reinterpret_cast<void**>(&buffer), &len);
  DART_CHECK_ERROR(result);
  ASSERT((offset + length) <= len);
  buffer += offset;
  intptr_t bytes_written =
      SynchronousSocket::Write(socket->fd(), buffer, length);
  Dart_TypedDataReleaseData(buffer_obj);
  if (bytes_written >= 0) {
    Dart_SetIntegerReturnValue(args, bytes_written);
  } else {
    OSError os_error;
    Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
  }
}

void FUNCTION_NAME(SynchronousSocket_ReadList)(Dart_NativeArguments args) {
  SynchronousSocket* socket = nullptr;
  Dart_Handle result = SynchronousSocket::GetSocketIdNativeField(
      Dart_GetNativeArgument(args, 0), &socket);
  DART_CHECK_ERROR(result);

  Dart_Handle buffer_obj = Dart_GetNativeArgument(args, 1);
  if (!Dart_IsList(buffer_obj)) {
    Dart_SetReturnValue(args, DartUtils::NewDartArgumentError(
                                  "First parameter must be a List<int>"));
    return;
  }
  intptr_t offset = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 2));
  intptr_t bytes = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 3));
  intptr_t array_len = 0;

  result = Dart_ListLength(buffer_obj, &array_len);
  DART_CHECK_ERROR(result);

  uint8_t* buffer = Dart_ScopeAllocate(bytes);
  intptr_t bytes_read = SynchronousSocket::Read(socket->fd(), buffer, bytes);
  if (bytes_read < 0) {
    Dart_SetReturnValue(args, DartUtils::NewDartOSError());
    return;
  }
  if (bytes_read > 0) {
    result = Dart_ListSetAsBytes(buffer_obj, offset, buffer, bytes_read);
    DART_CHECK_ERROR(result);
  }
  Dart_SetIntegerReturnValue(args, bytes_read);
}

void FUNCTION_NAME(SynchronousSocket_Available)(Dart_NativeArguments args) {
  SynchronousSocket* socket = nullptr;
  Dart_Handle result = SynchronousSocket::GetSocketIdNativeField(
      Dart_GetNativeArgument(args, 0), &socket);
  DART_CHECK_ERROR(result);

  intptr_t available = SynchronousSocket::Available(socket->fd());
  if (available >= 0) {
    Dart_SetIntegerReturnValue(args, available);
  } else {
    Dart_SetReturnValue(args, DartUtils::NewDartOSError());
  }
}

void FUNCTION_NAME(SynchronousSocket_CloseSync)(Dart_NativeArguments args) {
  SynchronousSocket* socket = nullptr;
  Dart_Handle result = SynchronousSocket::GetSocketIdNativeField(
      Dart_GetNativeArgument(args, 0), &socket);
  DART_CHECK_ERROR(result);

  SynchronousSocket::Close(socket->fd());
  socket->SetClosedFd();
}

void FUNCTION_NAME(SynchronousSocket_Read)(Dart_NativeArguments args) {
  SynchronousSocket* socket = nullptr;
  Dart_Handle result = SynchronousSocket::GetSocketIdNativeField(
      Dart_GetNativeArgument(args, 0), &socket);
  DART_CHECK_ERROR(result);

  int64_t length = 0;
  if (!DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 1), &length) ||
      (length < 0)) {
    Dart_SetReturnValue(args, DartUtils::NewDartArgumentError(
                                  "First parameter must be an integer."));
    return;
  }
  uint8_t* buffer = nullptr;
  result = IOBuffer::Allocate(length, &buffer);
  if (Dart_IsNull(result)) {
    Dart_SetReturnValue(args, DartUtils::NewDartOSError());
    return;
  }
  ASSERT(buffer != nullptr);
  intptr_t bytes_read = SynchronousSocket::Read(socket->fd(), buffer, length);
  if (bytes_read == length) {
    Dart_SetReturnValue(args, result);
  } else if (bytes_read > 0) {
    uint8_t* new_buffer = nullptr;
    Dart_Handle new_result = IOBuffer::Allocate(bytes_read, &new_buffer);
    if (Dart_IsNull(new_result)) {
      Dart_SetReturnValue(args, DartUtils::NewDartOSError());
      return;
    }
    ASSERT(new_buffer != nullptr);
    memmove(new_buffer, buffer, bytes_read);
    Dart_SetReturnValue(args, new_result);
  } else if (bytes_read == -1) {
    Dart_SetReturnValue(args, DartUtils::NewDartOSError());
  }
}

void FUNCTION_NAME(SynchronousSocket_ShutdownRead)(Dart_NativeArguments args) {
  SynchronousSocket* socket = nullptr;
  Dart_Handle result = SynchronousSocket::GetSocketIdNativeField(
      Dart_GetNativeArgument(args, 0), &socket);
  DART_CHECK_ERROR(result);

  SynchronousSocket::ShutdownRead(socket->fd());
}

void FUNCTION_NAME(SynchronousSocket_ShutdownWrite)(Dart_NativeArguments args) {
  SynchronousSocket* socket = nullptr;
  Dart_Handle result = SynchronousSocket::GetSocketIdNativeField(
      Dart_GetNativeArgument(args, 0), &socket);
  DART_CHECK_ERROR(result);

  SynchronousSocket::ShutdownWrite(socket->fd());
}

void FUNCTION_NAME(SynchronousSocket_GetPort)(Dart_NativeArguments args) {
  SynchronousSocket* socket = nullptr;
  Dart_Handle result = SynchronousSocket::GetSocketIdNativeField(
      Dart_GetNativeArgument(args, 0), &socket);
  DART_CHECK_ERROR(result);

  intptr_t port = SynchronousSocket::GetPort(socket->fd());
  if (port > 0) {
    Dart_SetReturnValue(args, Dart_NewInteger(port));
  } else {
    Dart_SetReturnValue(args, DartUtils::NewDartOSError());
  }
}

void FUNCTION_NAME(SynchronousSocket_GetRemotePeer)(Dart_NativeArguments args) {
  SynchronousSocket* socket = nullptr;
  Dart_Handle result = SynchronousSocket::GetSocketIdNativeField(
      Dart_GetNativeArgument(args, 0), &socket);
  DART_CHECK_ERROR(result);

  intptr_t port = 0;
  SocketAddress* addr = SynchronousSocket::GetRemotePeer(socket->fd(), &port);
  if (addr == nullptr) {
    Dart_SetReturnValue(args, DartUtils::NewDartOSError());
    return;
  }
  Dart_Handle list = Dart_NewList(2);
  DART_CHECK_ERROR_AND_CLEANUP(list, addr);

  Dart_Handle entry = Dart_NewList(3);
  DART_CHECK_ERROR_AND_CLEANUP(entry, addr);

  Dart_Handle error =
      Dart_ListSetAt(entry, 0, Dart_NewInteger(addr->GetType()));
  DART_CHECK_ERROR_AND_CLEANUP(error, addr);
  error =
      Dart_ListSetAt(entry, 1, Dart_NewStringFromCString(addr->as_string()));
  DART_CHECK_ERROR_AND_CLEANUP(error, addr);

  RawAddr raw = addr->addr();
  error = Dart_ListSetAt(entry, 2, SocketAddress::ToTypedData(raw));
  DART_CHECK_ERROR_AND_CLEANUP(error, addr);

  error = Dart_ListSetAt(list, 0, entry);
  DART_CHECK_ERROR_AND_CLEANUP(error, addr);
  error = Dart_ListSetAt(list, 1, Dart_NewInteger(port));
  DART_CHECK_ERROR_AND_CLEANUP(error, addr);
  Dart_SetReturnValue(args, list);
  delete addr;
}

static void SynchronousSocketFinalizer(void* isolate_data, void* data) {
  SynchronousSocket* socket = reinterpret_cast<SynchronousSocket*>(data);
  if (socket->fd() >= 0) {
    SynchronousSocket::Close(socket->fd());
    socket->SetClosedFd();
  }
  delete socket;
}

Dart_Handle SynchronousSocket::SetSocketIdNativeField(
    Dart_Handle handle,
    SynchronousSocket* socket) {
  Dart_Handle error = Dart_SetNativeInstanceField(
      handle, kSocketIdNativeField, reinterpret_cast<intptr_t>(socket));
  if (Dart_IsError(error)) {
    delete socket;
    return error;
  }

  Dart_NewFinalizableHandle(handle, reinterpret_cast<void*>(socket),
                            sizeof(SynchronousSocket),
                            SynchronousSocketFinalizer);
  return error;
}

Dart_Handle SynchronousSocket::GetSocketIdNativeField(
    Dart_Handle socket_obj,
    SynchronousSocket** socket) {
  ASSERT(socket != nullptr);
  intptr_t id;
  Dart_Handle result =
      Dart_GetNativeInstanceField(socket_obj, kSocketIdNativeField, &id);
  if (Dart_IsError(result)) {
    return result;
  }
  *socket = reinterpret_cast<SynchronousSocket*>(id);
  if (*socket == nullptr) {
    Dart_PropagateError(Dart_NewUnhandledExceptionError(
        DartUtils::NewInternalError("No native peer")));
  }
  return result;
}

}  // namespace bin
}  // namespace dart
