// 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/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 const 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 = NULL;
  Dart_Handle host_arg =
      Dart_GetNativeStringArgument(args, 0, reinterpret_cast<void**>(&peer));
  DART_CHECK_ERROR(host_arg);

  char* host = NULL;
  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 = NULL;
  AddressList<SocketAddress>* addresses =
      SocketBase::LookupAddress(host, type, &os_error);
  if (addresses == NULL) {
    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 = NULL;
  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 = NULL;
  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);
  if (bytes_written >= 0) {
    Dart_SetIntegerReturnValue(args, bytes_written);
  } else {
    OSError os_error;
    Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
  }
  Dart_TypedDataReleaseData(buffer_obj);
}

void FUNCTION_NAME(SynchronousSocket_ReadList)(Dart_NativeArguments args) {
  SynchronousSocket* socket = NULL;
  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 = NULL;
  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 = NULL;
  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 = NULL;
  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)) {
    Dart_SetReturnValue(args, DartUtils::NewDartArgumentError(
                                  "First parameter must be an integer."));
    return;
  }
  uint8_t* buffer = NULL;
  result = IOBuffer::Allocate(length, &buffer);
  ASSERT(buffer != NULL);
  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 = NULL;
    Dart_Handle new_result = IOBuffer::Allocate(bytes_read, &new_buffer);
    ASSERT(new_buffer != NULL);
    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 = NULL;
  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 = NULL;
  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 = NULL;
  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 = NULL;
  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 == NULL) {
    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,
                                       Dart_WeakPersistentHandle handle,
                                       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_NewWeakPersistentHandle(handle, reinterpret_cast<void*>(socket),
                               sizeof(SynchronousSocket),
                               SynchronousSocketFinalizer);
  return error;
}

Dart_Handle SynchronousSocket::GetSocketIdNativeField(
    Dart_Handle socket_obj,
    SynchronousSocket** socket) {
  ASSERT(socket != NULL);
  intptr_t id;
  Dart_Handle result =
      Dart_GetNativeInstanceField(socket_obj, kSocketIdNativeField, &id);
  if (Dart_IsError(result)) {
    return result;
  }
  *socket = reinterpret_cast<SynchronousSocket*>(id);
  return result;
}

}  // namespace bin
}  // namespace dart

#endif  // !defined(DART_IO_DISABLED)
