// Copyright (c) 2013, 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 "platform/globals.h"
#if defined(TARGET_OS_WINDOWS)

#include "bin/eventhandler.h"

#include <winsock2.h>  // NOLINT
#include <ws2tcpip.h>  // NOLINT
#include <mswsock.h>  // NOLINT
#include <io.h>  // NOLINT
#include <fcntl.h>  // NOLINT

#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/log.h"
#include "bin/socket.h"
#include "bin/utils.h"
#include "vm/thread.h"


namespace dart {
namespace bin {

static const int kBufferSize = 64 * 1024;
static const int kStdOverlappedBufferSize = 16 * 1024;

static const int kInfinityTimeout = -1;
static const int kTimeoutId = -1;
static const int kShutdownId = -2;

OverlappedBuffer* OverlappedBuffer::AllocateBuffer(int buffer_size,
                                                   Operation operation) {
  OverlappedBuffer* buffer =
      new(buffer_size) OverlappedBuffer(buffer_size, operation);
  return buffer;
}


OverlappedBuffer* OverlappedBuffer::AllocateAcceptBuffer(int buffer_size) {
  OverlappedBuffer* buffer = AllocateBuffer(buffer_size, kAccept);
  return buffer;
}


OverlappedBuffer* OverlappedBuffer::AllocateReadBuffer(int buffer_size) {
  return AllocateBuffer(buffer_size, kRead);
}


OverlappedBuffer* OverlappedBuffer::AllocateWriteBuffer(int buffer_size) {
  return AllocateBuffer(buffer_size, kWrite);
}


OverlappedBuffer* OverlappedBuffer::AllocateDisconnectBuffer() {
  return AllocateBuffer(0, kDisconnect);
}


void OverlappedBuffer::DisposeBuffer(OverlappedBuffer* buffer) {
  delete buffer;
}


OverlappedBuffer* OverlappedBuffer::GetFromOverlapped(OVERLAPPED* overlapped) {
  OverlappedBuffer* buffer =
      CONTAINING_RECORD(overlapped, OverlappedBuffer, overlapped_);
  return buffer;
}


int OverlappedBuffer::Read(void* buffer, int num_bytes) {
  if (num_bytes > GetRemainingLength()) {
    num_bytes = GetRemainingLength();
  }
  memmove(buffer, GetBufferStart() + index_, num_bytes);
  index_ += num_bytes;
  return num_bytes;
}


int OverlappedBuffer::Write(const void* buffer, int num_bytes) {
  ASSERT(num_bytes == buflen_);
  memmove(GetBufferStart(), buffer, num_bytes);
  data_length_ = num_bytes;
  return num_bytes;
}


int OverlappedBuffer::GetRemainingLength() {
  ASSERT(operation_ == kRead);
  return data_length_ - index_;
}


Handle::Handle(HANDLE handle)
    : handle_(reinterpret_cast<HANDLE>(handle)),
      port_(0),
      mask_(0),
      completion_port_(INVALID_HANDLE_VALUE),
      event_handler_(NULL),
      data_ready_(NULL),
      pending_read_(NULL),
      pending_write_(NULL),
      last_error_(NOERROR),
      flags_(0) {
  InitializeCriticalSection(&cs_);
}


Handle::Handle(HANDLE handle, Dart_Port port)
    : handle_(reinterpret_cast<HANDLE>(handle)),
      port_(port),
      mask_(0),
      completion_port_(INVALID_HANDLE_VALUE),
      event_handler_(NULL),
      data_ready_(NULL),
      pending_read_(NULL),
      pending_write_(NULL),
      last_error_(NOERROR),
      flags_(0) {
  InitializeCriticalSection(&cs_);
}


Handle::~Handle() {
  DeleteCriticalSection(&cs_);
}


void Handle::Lock() {
  EnterCriticalSection(&cs_);
}


void Handle::Unlock() {
  LeaveCriticalSection(&cs_);
}


bool Handle::CreateCompletionPort(HANDLE completion_port) {
  completion_port_ = CreateIoCompletionPort(handle_,
                                            completion_port,
                                            reinterpret_cast<ULONG_PTR>(this),
                                            0);
  if (completion_port_ == NULL) {
    Log::PrintErr("Error CreateIoCompletionPort: %d\n", GetLastError());
    return false;
  }
  return true;
}


void Handle::Close() {
  ScopedLock lock(this);
  if (!IsClosing()) {
    // Close the socket and set the closing state. This close method can be
    // called again if this socket has pending IO operations in flight.
    ASSERT(handle_ != INVALID_HANDLE_VALUE);
    MarkClosing();
    // Perform handle type specific closing.
    DoClose();
  }
}


void Handle::DoClose() {
  CloseHandle(handle_);
  handle_ = INVALID_HANDLE_VALUE;
}


bool Handle::HasPendingRead() {
  ScopedLock lock(this);
  return pending_read_ != NULL;
}


bool Handle::HasPendingWrite() {
  ScopedLock lock(this);
  return pending_write_ != NULL;
}


void Handle::ReadComplete(OverlappedBuffer* buffer) {
  ScopedLock lock(this);
  // Currently only one outstanding read at the time.
  ASSERT(pending_read_ == buffer);
  ASSERT(data_ready_ == NULL);
  if (!IsClosing() && !buffer->IsEmpty()) {
    data_ready_ = pending_read_;
  } else {
    OverlappedBuffer::DisposeBuffer(buffer);
  }
  pending_read_ = NULL;
}


void Handle::WriteComplete(OverlappedBuffer* buffer) {
  ScopedLock lock(this);
  // Currently only one outstanding write at the time.
  ASSERT(pending_write_ == buffer);
  OverlappedBuffer::DisposeBuffer(buffer);
  pending_write_ = NULL;
}


static void ReadFileThread(uword args) {
  Handle* handle = reinterpret_cast<Handle*>(args);
  handle->ReadSyncCompleteAsync();
}


void Handle::ReadSyncCompleteAsync() {
  ASSERT(pending_read_ != NULL);
  ASSERT(pending_read_->GetBufferSize() >= kStdOverlappedBufferSize);

  DWORD buffer_size = pending_read_->GetBufferSize();
  if (GetFileType(handle_) == FILE_TYPE_CHAR) {
    buffer_size = kStdOverlappedBufferSize;
  }
  DWORD bytes_read = 0;
  BOOL ok = ReadFile(handle_,
                     pending_read_->GetBufferStart(),
                     buffer_size,
                     &bytes_read,
                     NULL);
  if (!ok) {
    if (GetLastError() != ERROR_BROKEN_PIPE) {
      Log::PrintErr("ReadFile failed %d\n", GetLastError());
    }
    bytes_read = 0;
  }
  OVERLAPPED* overlapped = pending_read_->GetCleanOverlapped();
  ok = PostQueuedCompletionStatus(event_handler_->completion_port(),
                                  bytes_read,
                                  reinterpret_cast<ULONG_PTR>(this),
                                  overlapped);
  if (!ok) {
    FATAL("PostQueuedCompletionStatus failed");
  }
}


bool Handle::IssueRead() {
  ScopedLock lock(this);
  ASSERT(type_ != kListenSocket);
  ASSERT(pending_read_ == NULL);
  OverlappedBuffer* buffer = OverlappedBuffer::AllocateReadBuffer(kBufferSize);
  if (SupportsOverlappedIO()) {
    ASSERT(completion_port_ != INVALID_HANDLE_VALUE);

    BOOL ok = ReadFile(handle_,
                       buffer->GetBufferStart(),
                       buffer->GetBufferSize(),
                       NULL,
                       buffer->GetCleanOverlapped());
    if (ok || GetLastError() == ERROR_IO_PENDING) {
      // Completing asynchronously.
      pending_read_ = buffer;
      return true;
    }
    OverlappedBuffer::DisposeBuffer(buffer);
    HandleIssueError();
    return false;
  } else {
    // Completing asynchronously through thread.
    pending_read_ = buffer;
    int result = dart::Thread::Start(ReadFileThread,
                                     reinterpret_cast<uword>(this));
    if (result != 0) {
      FATAL1("Failed to start read file thread %d", result);
    }
    return true;
  }
}


bool Handle::IssueWrite() {
  ScopedLock lock(this);
  ASSERT(type_ != kListenSocket);
  ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
  ASSERT(pending_write_ != NULL);
  ASSERT(pending_write_->operation() == OverlappedBuffer::kWrite);

  OverlappedBuffer* buffer = pending_write_;
  BOOL ok = WriteFile(handle_,
                      buffer->GetBufferStart(),
                      buffer->GetBufferSize(),
                      NULL,
                      buffer->GetCleanOverlapped());
  if (ok || GetLastError() == ERROR_IO_PENDING) {
    // Completing asynchronously.
    pending_write_ = buffer;
    return true;
  }
  OverlappedBuffer::DisposeBuffer(buffer);
  HandleIssueError();
  return false;
}


void Handle::HandleIssueError() {
  DWORD error = GetLastError();
  if (error == ERROR_BROKEN_PIPE) {
    event_handler_->HandleClosed(this);
  } else {
    event_handler_->HandleError(this);
  }
  SetLastError(error);
}


void FileHandle::EnsureInitialized(EventHandlerImplementation* event_handler) {
  ScopedLock lock(this);
  event_handler_ = event_handler;
  if (SupportsOverlappedIO() && completion_port_ == INVALID_HANDLE_VALUE) {
    CreateCompletionPort(event_handler_->completion_port());
  }
}


bool FileHandle::IsClosed() {
  return IsClosing() && !HasPendingRead() && !HasPendingWrite();
}


void DirectoryWatchHandle::EnsureInitialized(
    EventHandlerImplementation* event_handler) {
  ScopedLock lock(this);
  event_handler_ = event_handler;
  if (completion_port_ == INVALID_HANDLE_VALUE) {
    CreateCompletionPort(event_handler_->completion_port());
  }
}


bool DirectoryWatchHandle::IsClosed() {
  return IsClosing() && pending_read_ == NULL;
}


bool DirectoryWatchHandle::IssueRead() {
  ScopedLock lock(this);
  OverlappedBuffer* buffer = OverlappedBuffer::AllocateReadBuffer(kBufferSize);

  ASSERT(completion_port_ != INVALID_HANDLE_VALUE);

  BOOL ok = ReadDirectoryChangesW(handle_,
                                  buffer->GetBufferStart(),
                                  buffer->GetBufferSize(),
                                  recursive_,
                                  events_,
                                  NULL,
                                  buffer->GetCleanOverlapped(),
                                  NULL);
  if (ok || GetLastError() == ERROR_IO_PENDING) {
    // Completing asynchronously.
    pending_read_ = buffer;
    return true;
  }
  OverlappedBuffer::DisposeBuffer(buffer);
  return false;
}


void SocketHandle::HandleIssueError() {
  int error = WSAGetLastError();
  if (error == WSAECONNRESET) {
    event_handler_->HandleClosed(this);
  } else {
    event_handler_->HandleError(this);
  }
  WSASetLastError(error);
}


bool ListenSocket::LoadAcceptEx() {
  // Load the AcceptEx function into memory using WSAIoctl.
  GUID guid_accept_ex = WSAID_ACCEPTEX;
  DWORD bytes;
  int status = WSAIoctl(socket(),
                        SIO_GET_EXTENSION_FUNCTION_POINTER,
                        &guid_accept_ex,
                        sizeof(guid_accept_ex),
                        &AcceptEx_,
                        sizeof(AcceptEx_),
                        &bytes,
                        NULL,
                        NULL);
  if (status == SOCKET_ERROR) {
    Log::PrintErr("Error WSAIoctl failed: %d\n", WSAGetLastError());
    return false;
  }
  return true;
}


bool ListenSocket::IssueAccept() {
  ScopedLock lock(this);

  // For AcceptEx there needs to be buffer storage for address
  // information for two addresses (local and remote address). The
  // AcceptEx documentation says: "This value must be at least 16
  // bytes more than the maximum address length for the transport
  // protocol in use."
  static const int kAcceptExAddressAdditionalBytes = 16;
  static const int kAcceptExAddressStorageSize =
      sizeof(SOCKADDR_STORAGE) + kAcceptExAddressAdditionalBytes;
  OverlappedBuffer* buffer =
      OverlappedBuffer::AllocateAcceptBuffer(2 * kAcceptExAddressStorageSize);
  DWORD received;
  BOOL ok;
  ok = AcceptEx_(socket(),
                 buffer->client(),
                 buffer->GetBufferStart(),
                 0,  // For now don't receive data with accept.
                 kAcceptExAddressStorageSize,
                 kAcceptExAddressStorageSize,
                 &received,
                 buffer->GetCleanOverlapped());
  if (!ok) {
    if (WSAGetLastError() != WSA_IO_PENDING) {
      Log::PrintErr("AcceptEx failed: %d\n", WSAGetLastError());
      closesocket(buffer->client());
      OverlappedBuffer::DisposeBuffer(buffer);
      return false;
    }
  }

  pending_accept_count_++;

  return true;
}


void ListenSocket::AcceptComplete(OverlappedBuffer* buffer,
                                  HANDLE completion_port) {
  ScopedLock lock(this);
  if (!IsClosing()) {
    // Update the accepted socket to support the full range of API calls.
    SOCKET s = socket();
    int rc = setsockopt(buffer->client(),
                        SOL_SOCKET,
                        SO_UPDATE_ACCEPT_CONTEXT,
                        reinterpret_cast<char*>(&s), sizeof(s));
    if (rc == NO_ERROR) {
      // Insert the accepted socket into the list.
      ClientSocket* client_socket = new ClientSocket(buffer->client(), 0);
      client_socket->CreateCompletionPort(completion_port);
      if (accepted_head_ == NULL) {
        accepted_head_ = client_socket;
        accepted_tail_ = client_socket;
      } else {
        ASSERT(accepted_tail_ != NULL);
        accepted_tail_->set_next(client_socket);
        accepted_tail_ = client_socket;
      }
    } else {
      Log::PrintErr("setsockopt failed: %d\n", WSAGetLastError());
      closesocket(buffer->client());
    }
  } else {
    // Close the socket, as it's already accepted.
    closesocket(buffer->client());
  }

  pending_accept_count_--;
  OverlappedBuffer::DisposeBuffer(buffer);
}


void ListenSocket::DoClose() {
  closesocket(socket());
  handle_ = INVALID_HANDLE_VALUE;
  while (CanAccept()) {
    // Get rid of connections already accepted.
    ClientSocket *client = Accept();
    if (client != NULL) {
      client->Close();
    } else {
      break;
    }
  }
}


bool ListenSocket::CanAccept() {
  ScopedLock lock(this);
  return accepted_head_ != NULL;
}


ClientSocket* ListenSocket::Accept() {
  ScopedLock lock(this);
  if (accepted_head_ == NULL) return NULL;
  ClientSocket* result = accepted_head_;
  accepted_head_ = accepted_head_->next();
  if (accepted_head_ == NULL) accepted_tail_ = NULL;
  result->set_next(NULL);
  return result;
}


void ListenSocket::EnsureInitialized(
    EventHandlerImplementation* event_handler) {
  ScopedLock lock(this);
  if (AcceptEx_ == NULL) {
    ASSERT(completion_port_ == INVALID_HANDLE_VALUE);
    ASSERT(event_handler_ == NULL);
    event_handler_ = event_handler;
    CreateCompletionPort(event_handler_->completion_port());
    LoadAcceptEx();
  }
}


bool ListenSocket::IsClosed() {
  return IsClosing() && !HasPendingAccept();
}


int Handle::Available() {
  ScopedLock lock(this);
  if (data_ready_ == NULL) return 0;
  ASSERT(!data_ready_->IsEmpty());
  return data_ready_->GetRemainingLength();
}


int Handle::Read(void* buffer, int num_bytes) {
  ScopedLock lock(this);
  if (data_ready_ == NULL) return 0;
  num_bytes = data_ready_->Read(buffer, num_bytes);
  if (data_ready_->IsEmpty()) {
    OverlappedBuffer::DisposeBuffer(data_ready_);
    data_ready_ = NULL;
  }
  return num_bytes;
}


int Handle::Write(const void* buffer, int num_bytes) {
  ScopedLock lock(this);
  if (pending_write_ != NULL) return 0;
  if (num_bytes > kBufferSize) num_bytes = kBufferSize;
  ASSERT(SupportsOverlappedIO());
  if (completion_port_ == INVALID_HANDLE_VALUE) return 0;
  pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes);
  pending_write_->Write(buffer, num_bytes);
  if (!IssueWrite()) return -1;
  return num_bytes;
}


static void WriteFileThread(uword args) {
  StdHandle* handle = reinterpret_cast<StdHandle*>(args);
  handle->RunWriteLoop();
}


void StdHandle::RunWriteLoop() {
  write_monitor_->Enter();
  write_thread_running_ = true;
  // Notify we have started.
  write_monitor_->Notify();

  while (write_thread_running_) {
    write_monitor_->Wait(Monitor::kNoTimeout);
    if (pending_write_ != NULL) {
      // We woke up and had a pending write. Execute it.
      WriteSyncCompleteAsync();
    }
  }

  write_thread_exists_ = false;
  write_monitor_->Notify();
  write_monitor_->Exit();
}


void StdHandle::WriteSyncCompleteAsync() {
  ASSERT(pending_write_ != NULL);

  DWORD bytes_written = -1;
  BOOL ok = WriteFile(handle_,
                      pending_write_->GetBufferStart(),
                      pending_write_->GetBufferSize(),
                      &bytes_written,
                      NULL);
  if (!ok) {
    if (GetLastError() != ERROR_BROKEN_PIPE) {
      Log::PrintErr("WriteFile failed %d\n", GetLastError());
    }
    bytes_written = 0;
  }
  thread_wrote_ += bytes_written;
  OVERLAPPED* overlapped = pending_write_->GetCleanOverlapped();
  ok = PostQueuedCompletionStatus(event_handler_->completion_port(),
                                  bytes_written,
                                  reinterpret_cast<ULONG_PTR>(this),
                                  overlapped);
  if (!ok) {
    FATAL("PostQueuedCompletionStatus failed");
  }
}

int StdHandle::Write(const void* buffer, int num_bytes) {
  ScopedLock lock(this);
  if (pending_write_ != NULL) return 0;
  if (num_bytes > kBufferSize) num_bytes = kBufferSize;
  // In the case of stdout and stderr, OverlappedIO is not supported.
  // Here we'll instead use a thread, to make it async.
  // This code is actually never exposed to the user, as stdout and stderr is
  // not available as a RawSocket, but only wrapped in a Socket.
  // Note that we return '0', unless a thread have already completed a write.
  MonitorLocker locker(write_monitor_);
  if (thread_wrote_ > 0) {
    if (num_bytes > thread_wrote_) num_bytes = thread_wrote_;
    thread_wrote_ -= num_bytes;
    return num_bytes;
  }
  if (!write_thread_exists_) {
    write_thread_exists_ = true;
    int result = dart::Thread::Start(WriteFileThread,
                                     reinterpret_cast<uword>(this));
    if (result != 0) {
      FATAL1("Failed to start write file thread %d", result);
    }
    while (!write_thread_running_) {
      // Wait until we the thread is running.
      locker.Wait(Monitor::kNoTimeout);
    }
  }
  // Create buffer and notify thread about the new handle.
  pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes);
  pending_write_->Write(buffer, num_bytes);
  locker.Notify();
  return 0;
}


void StdHandle::DoClose() {
  MonitorLocker locker(write_monitor_);
  if (write_thread_exists_) {
    write_thread_running_ = false;
    locker.Notify();
    while (write_thread_exists_) {
      locker.Wait(Monitor::kNoTimeout);
    }
  }
  if (handle_ == GetStdHandle(STD_OUTPUT_HANDLE)) {
    int fd = _open("NUL", _O_WRONLY);
    ASSERT(fd >= 0);
    _dup2(fd, _fileno(stdout));
    close(fd);
  } else {
    Handle::DoClose();
  }
}


bool ClientSocket::LoadDisconnectEx() {
  // Load the DisconnectEx function into memory using WSAIoctl.
  GUID guid_disconnect_ex = WSAID_DISCONNECTEX;
  DWORD bytes;
  int status = WSAIoctl(socket(),
                        SIO_GET_EXTENSION_FUNCTION_POINTER,
                        &guid_disconnect_ex,
                        sizeof(guid_disconnect_ex),
                        &DisconnectEx_,
                        sizeof(DisconnectEx_),
                        &bytes,
                        NULL,
                        NULL);
  if (status == SOCKET_ERROR) {
    Log::PrintErr("Error WSAIoctl failed: %d\n", WSAGetLastError());
    return false;
  }
  return true;
}


void ClientSocket::Shutdown(int how) {
  int rc = shutdown(socket(), how);
  if (how == SD_RECEIVE) MarkClosedRead();
  if (how == SD_SEND) MarkClosedWrite();
  if (how == SD_BOTH) {
    MarkClosedRead();
    MarkClosedWrite();
  }
}


void ClientSocket::DoClose() {
  // Always do a shutdown before initiating a disconnect.
  shutdown(socket(), SD_BOTH);
  IssueDisconnect();
}


bool ClientSocket::IssueRead() {
  ScopedLock lock(this);
  ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
  ASSERT(pending_read_ == NULL);

  OverlappedBuffer* buffer = OverlappedBuffer::AllocateReadBuffer(1024);

  DWORD flags;
  flags = 0;
  int rc = WSARecv(socket(),
                   buffer->GetWASBUF(),
                   1,
                   NULL,
                   &flags,
                   buffer->GetCleanOverlapped(),
                   NULL);
  if (rc == NO_ERROR || WSAGetLastError() == WSA_IO_PENDING) {
    pending_read_ = buffer;
    return true;
  }
  OverlappedBuffer::DisposeBuffer(buffer);
  pending_read_ = NULL;
  HandleIssueError();
  return false;
}


bool ClientSocket::IssueWrite() {
  ScopedLock lock(this);
  ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
  ASSERT(pending_write_ != NULL);
  ASSERT(pending_write_->operation() == OverlappedBuffer::kWrite);

  int rc = WSASend(socket(),
                   pending_write_->GetWASBUF(),
                   1,
                   NULL,
                   0,
                   pending_write_->GetCleanOverlapped(),
                   NULL);
  if (rc == NO_ERROR || WSAGetLastError() == WSA_IO_PENDING) {
    return true;
  }
  OverlappedBuffer::DisposeBuffer(pending_write_);
  pending_write_ = NULL;
  HandleIssueError();
  return false;
}


void ClientSocket::IssueDisconnect() {
  Dart_Port p = port();
  OverlappedBuffer* buffer = OverlappedBuffer::AllocateDisconnectBuffer();
  BOOL ok = DisconnectEx_(
    socket(), buffer->GetCleanOverlapped(), TF_REUSE_SOCKET, 0);
  if (!ok && WSAGetLastError() != WSA_IO_PENDING) {
    DisconnectComplete(buffer);
  }
  if (p != ILLEGAL_PORT) DartUtils::PostInt32(p, 1 << kDestroyedEvent);
}


void ClientSocket::DisconnectComplete(OverlappedBuffer* buffer) {
  OverlappedBuffer::DisposeBuffer(buffer);
  closesocket(socket());
  if (data_ready_ != NULL) {
    OverlappedBuffer::DisposeBuffer(data_ready_);
  }
  // When disconnect is complete get rid of the object.
  delete this;
}


void ClientSocket::EnsureInitialized(
    EventHandlerImplementation* event_handler) {
  ScopedLock lock(this);
  if (completion_port_ == INVALID_HANDLE_VALUE) {
    ASSERT(event_handler_ == NULL);
    event_handler_ = event_handler;
    CreateCompletionPort(event_handler_->completion_port());
  }
}


bool ClientSocket::IsClosed() {
  return false;
}


static void DeleteIfClosed(Handle* handle) {
  if (handle->IsClosed()) {
    Dart_Port port = handle->port();
    delete handle;
    DartUtils::PostInt32(port, 1 << kDestroyedEvent);
  }
}


void EventHandlerImplementation::HandleInterrupt(InterruptMessage* msg) {
  if (msg->id == kTimeoutId) {
    // Change of timeout request. Just set the new timeout and port as the
    // completion thread will use the new timeout value for its next wait.
    timeout_queue_.UpdateTimeout(msg->dart_port, msg->data);
  } else if (msg->id == kShutdownId) {
    shutdown_ = true;
  } else {
    Handle* handle = reinterpret_cast<Handle*>(msg->id);
    ASSERT(handle != NULL);
    if (handle->is_listen_socket()) {
      ListenSocket* listen_socket =
          reinterpret_cast<ListenSocket*>(handle);
      listen_socket->EnsureInitialized(this);
      listen_socket->SetPortAndMask(msg->dart_port, msg->data);

      Handle::ScopedLock lock(listen_socket);

      // If incomming connections are requested make sure to post already
      // accepted connections.
      if ((msg->data & (1 << kInEvent)) != 0) {
        if (listen_socket->CanAccept()) {
          int event_mask = (1 << kInEvent);
          handle->set_mask(handle->mask() & ~event_mask);
          DartUtils::PostInt32(handle->port(), event_mask);
        }
        // Always keep 5 outstanding accepts going, to enhance performance.
        while (listen_socket->pending_accept_count() < 5) {
          listen_socket->IssueAccept();
        }
      }

      if ((msg->data & (1 << kCloseCommand)) != 0) {
        listen_socket->Close();
      }
    } else {
      handle->EnsureInitialized(this);

      Handle::ScopedLock lock(handle);

      if (!handle->IsError()) {
        if ((msg->data & ((1 << kInEvent) | (1 << kOutEvent))) != 0) {
          // Only set mask if we turned on kInEvent or kOutEvent.
          handle->SetPortAndMask(msg->dart_port, msg->data);

          // If in events (data available events) have been requested, and data
          // is available, post an in event immediately. Otherwise make sure
          // that a pending read is issued, unless the socket is already closed
          // for read.
          if ((msg->data & (1 << kInEvent)) != 0) {
            if (handle->Available() > 0) {
              int event_mask = (1 << kInEvent);
              handle->set_mask(handle->mask() & ~event_mask);
              DartUtils::PostInt32(handle->port(), event_mask);
            } else if (handle->IsClosedRead()) {
              int event_mask = (1 << kCloseEvent);
              DartUtils::PostInt32(handle->port(), event_mask);
            } else if (!handle->HasPendingRead()) {
              handle->IssueRead();
            }
          }

          // If out events (can write events) have been requested, and there
          // are no pending writes, post an out event immediately.
          if ((msg->data & (1 << kOutEvent)) != 0) {
            if (!handle->HasPendingWrite()) {
              int event_mask = (1 << kOutEvent);
              handle->set_mask(handle->mask() & ~event_mask);
              DartUtils::PostInt32(handle->port(), event_mask);
            }
          }
        }

        if (handle->is_client_socket()) {
          ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(handle);
          if ((msg->data & (1 << kShutdownReadCommand)) != 0) {
            client_socket->Shutdown(SD_RECEIVE);
          }

          if ((msg->data & (1 << kShutdownWriteCommand)) != 0) {
            client_socket->Shutdown(SD_SEND);
          }
        }
      }

      if ((msg->data & (1 << kCloseCommand)) != 0) {
        handle->SetPortAndMask(msg->dart_port, msg->data);
        handle->Close();
      }
    }
    DeleteIfClosed(handle);
  }
}


void EventHandlerImplementation::HandleAccept(ListenSocket* listen_socket,
                                              OverlappedBuffer* buffer) {
  listen_socket->AcceptComplete(buffer, completion_port_);

  if (!listen_socket->IsClosing()) {
    int event_mask = 1 << kInEvent;
    if ((listen_socket->mask() & event_mask) != 0) {
      DartUtils::PostInt32(listen_socket->port(), event_mask);
    }
  }

  DeleteIfClosed(listen_socket);
}


void EventHandlerImplementation::HandleClosed(Handle* handle) {
  if (!handle->IsClosing()) {
    int event_mask = 1 << kCloseEvent;
    DartUtils::PostInt32(handle->port(), event_mask);
  }
}


void EventHandlerImplementation::HandleError(Handle* handle) {
  handle->set_last_error(WSAGetLastError());
  handle->MarkError();
  if (!handle->IsClosing()) {
    int event_mask = 1 << kErrorEvent;
    DartUtils::PostInt32(handle->port(), event_mask);
  }
}


void EventHandlerImplementation::HandleRead(Handle* handle,
                                            int bytes,
                                            OverlappedBuffer* buffer) {
  buffer->set_data_length(bytes);
  handle->ReadComplete(buffer);
  if (bytes > 0) {
    if (!handle->IsClosing()) {
      int event_mask = 1 << kInEvent;
      if ((handle->mask() & event_mask) != 0) {
        DartUtils::PostInt32(handle->port(), event_mask);
      }
    }
  } else {
    handle->MarkClosedRead();
    if (bytes == 0) {
      HandleClosed(handle);
    } else {
      HandleError(handle);
    }
  }

  DeleteIfClosed(handle);
}


void EventHandlerImplementation::HandleWrite(Handle* handle,
                                             int bytes,
                                             OverlappedBuffer* buffer) {
  handle->WriteComplete(buffer);

  if (bytes > 0) {
    if (!handle->IsError() && !handle->IsClosing()) {
      int event_mask = 1 << kOutEvent;
      if ((handle->mask() & event_mask) != 0) {
        DartUtils::PostInt32(handle->port(), event_mask);
      }
    }
  } else if (bytes == 0) {
    HandleClosed(handle);
  } else {
    HandleError(handle);
  }

  DeleteIfClosed(handle);
}


void EventHandlerImplementation::HandleDisconnect(
    ClientSocket* client_socket,
    int bytes,
    OverlappedBuffer* buffer) {
  client_socket->DisconnectComplete(buffer);
}

void EventHandlerImplementation::HandleTimeout() {
  if (!timeout_queue_.HasTimeout()) return;
  DartUtils::PostNull(timeout_queue_.CurrentPort());
  timeout_queue_.RemoveCurrent();
}


void EventHandlerImplementation::HandleIOCompletion(DWORD bytes,
                                                    ULONG_PTR key,
                                                    OVERLAPPED* overlapped) {
  OverlappedBuffer* buffer = OverlappedBuffer::GetFromOverlapped(overlapped);
  switch (buffer->operation()) {
    case OverlappedBuffer::kAccept: {
      ListenSocket* listen_socket = reinterpret_cast<ListenSocket*>(key);
      HandleAccept(listen_socket, buffer);
      break;
    }
    case OverlappedBuffer::kRead: {
      Handle* handle = reinterpret_cast<Handle*>(key);
      HandleRead(handle, bytes, buffer);
      break;
    }
    case OverlappedBuffer::kWrite: {
      Handle* handle = reinterpret_cast<Handle*>(key);
      HandleWrite(handle, bytes, buffer);
      break;
    }
    case OverlappedBuffer::kDisconnect: {
      ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(key);
      HandleDisconnect(client_socket, bytes, buffer);
      break;
    }
    default:
      UNREACHABLE();
  }
}


EventHandlerImplementation::EventHandlerImplementation() {
  intptr_t result;
  completion_port_ =
      CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1);
  if (completion_port_ == NULL) {
    FATAL("Completion port creation failed");
  }
  shutdown_ = false;
}


EventHandlerImplementation::~EventHandlerImplementation() {
  CloseHandle(completion_port_);
}


int64_t EventHandlerImplementation::GetTimeout() {
  if (!timeout_queue_.HasTimeout()) {
    return kInfinityTimeout;
  }
  int64_t millis = timeout_queue_.CurrentTimeout() -
      TimerUtils::GetCurrentTimeMilliseconds();
  return (millis < 0) ? 0 : millis;
}


void EventHandlerImplementation::SendData(intptr_t id,
                                          Dart_Port dart_port,
                                          int64_t data) {
  InterruptMessage* msg = new InterruptMessage;
  msg->id = id;
  msg->dart_port = dart_port;
  msg->data = data;
  BOOL ok = PostQueuedCompletionStatus(
      completion_port_, 0, NULL, reinterpret_cast<OVERLAPPED*>(msg));
  if (!ok) {
    FATAL("PostQueuedCompletionStatus failed");
  }
}


void EventHandlerImplementation::EventHandlerEntry(uword args) {
  EventHandler* handler = reinterpret_cast<EventHandler*>(args);
  EventHandlerImplementation* handler_impl = &handler->delegate_;
  ASSERT(handler_impl != NULL);
  while (!handler_impl->shutdown_) {
    DWORD bytes;
    ULONG_PTR key;
    OVERLAPPED* overlapped;
    int64_t millis = handler_impl->GetTimeout();
    ASSERT(millis == kInfinityTimeout || millis >= 0);
    if (millis > kMaxInt32) millis = kMaxInt32;
    ASSERT(sizeof(int32_t) == sizeof(DWORD));
    BOOL ok = GetQueuedCompletionStatus(handler_impl->completion_port(),
                                        &bytes,
                                        &key,
                                        &overlapped,
                                        static_cast<DWORD>(millis));
    if (!ok && overlapped == NULL) {
      if (GetLastError() == ERROR_ABANDONED_WAIT_0) {
        // The completion port should never be closed.
        Log::Print("Completion port closed\n");
        UNREACHABLE();
      } else {
        // Timeout is signalled by false result and NULL in overlapped.
        handler_impl->HandleTimeout();
      }
    } else if (!ok) {
      // Treat ERROR_CONNECTION_ABORTED as connection closed.
      // The error ERROR_OPERATION_ABORTED is set for pending
      // accept requests for a listen socket which is closed.
      // ERROR_NETNAME_DELETED occurs when the client closes
      // the socket it is reading from.
      DWORD last_error = GetLastError();
      if (last_error == ERROR_CONNECTION_ABORTED ||
          last_error == ERROR_OPERATION_ABORTED ||
          last_error == ERROR_NETNAME_DELETED ||
          last_error == ERROR_BROKEN_PIPE) {
        ASSERT(bytes == 0);
        handler_impl->HandleIOCompletion(bytes, key, overlapped);
      } else {
        ASSERT(bytes == 0);
        handler_impl->HandleIOCompletion(-1, key, overlapped);
      }
    } else if (key == NULL) {
      // A key of NULL signals an interrupt message.
      InterruptMessage* msg = reinterpret_cast<InterruptMessage*>(overlapped);
      handler_impl->HandleInterrupt(msg);
      delete msg;
    } else {
      handler_impl->HandleIOCompletion(bytes, key, overlapped);
    }
  }
  delete handler;
}


void EventHandlerImplementation::Start(EventHandler* handler) {
  int result = dart::Thread::Start(EventHandlerEntry,
                                   reinterpret_cast<uword>(handler));
  if (result != 0) {
    FATAL1("Failed to start event handler thread %d", result);
  }

  // Initialize Winsock32
  if (!Socket::Initialize()) {
    FATAL("Failed to initialized Windows sockets");
  }
}


void EventHandlerImplementation::Shutdown() {
  SendData(kShutdownId, 0, 0);
}

}  // namespace bin
}  // namespace dart

#endif  // defined(TARGET_OS_WINDOWS)
