// 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 "platform/globals.h"
#if defined(HOST_OS_WINDOWS)

#include "bin/socket_base.h"
#include "bin/sync_socket.h"

namespace dart {
namespace bin {

bool SynchronousSocket::Initialize() {
  return SocketBase::Initialize();
}


static intptr_t Create(const RawAddr& addr) {
  const intptr_t type = SOCK_STREAM;
  SOCKET s = WSASocket(addr.ss.ss_family, type, 0, NULL, 0, 0);
  return (s == INVALID_SOCKET) ? -1 : s;
}


static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
  SOCKET socket = static_cast<SOCKET>(fd);
  intptr_t result =
      connect(socket, &addr.addr, SocketAddress::GetAddrLength(addr));
  return (result == SOCKET_ERROR) ? -1 : socket;
}


intptr_t SynchronousSocket::CreateConnect(const RawAddr& addr) {
  intptr_t fd = Create(addr);
  return (fd < 0) ? fd : Connect(fd, addr);
}


intptr_t SynchronousSocket::Available(intptr_t fd) {
  SOCKET socket = static_cast<SOCKET>(fd);
  DWORD available;
  intptr_t result = ioctlsocket(socket, FIONREAD, &available);
  return (result == SOCKET_ERROR) ? -1 : static_cast<intptr_t>(available);
}


intptr_t SynchronousSocket::GetPort(intptr_t fd) {
  SOCKET socket = static_cast<SOCKET>(fd);
  RawAddr raw;
  socklen_t size = sizeof(raw);
  if (getsockname(socket, &raw.addr, &size) == SOCKET_ERROR) {
    return 0;
  }
  return SocketAddress::GetAddrPort(raw);
}


SocketAddress* SynchronousSocket::GetRemotePeer(intptr_t fd, intptr_t* port) {
  SOCKET socket = static_cast<SOCKET>(fd);
  RawAddr raw;
  socklen_t size = sizeof(raw);
  if (getpeername(socket, &raw.addr, &size)) {
    return NULL;
  }
  *port = SocketAddress::GetAddrPort(raw);
  // Clear the port before calling WSAAddressToString as WSAAddressToString
  // includes the port in the formatted string.
  SocketAddress::SetAddrPort(&raw, 0);
  return new SocketAddress(&raw.addr);
}


intptr_t SynchronousSocket::Read(intptr_t fd,
                                 void* buffer,
                                 intptr_t num_bytes) {
  SOCKET socket = static_cast<SOCKET>(fd);
  return recv(socket, reinterpret_cast<char*>(buffer), num_bytes, 0);
}


intptr_t SynchronousSocket::Write(intptr_t fd,
                                  const void* buffer,
                                  intptr_t num_bytes) {
  SOCKET socket = static_cast<SOCKET>(fd);
  return send(socket, reinterpret_cast<const char*>(buffer), num_bytes, 0);
}


void SynchronousSocket::ShutdownRead(intptr_t fd) {
  SOCKET socket = static_cast<SOCKET>(fd);
  shutdown(socket, SD_RECEIVE);
}


void SynchronousSocket::ShutdownWrite(intptr_t fd) {
  SOCKET socket = static_cast<SOCKET>(fd);
  shutdown(socket, SD_SEND);
}


void SynchronousSocket::Close(intptr_t fd) {
  SOCKET socket = static_cast<SOCKET>(fd);
  closesocket(socket);
}

}  // namespace bin
}  // namespace dart

#endif  // defined(HOST_OS_WINDOWS)

#endif  // !defined(DART_IO_DISABLED)
