// Copyright (c) 2012, 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.

#ifndef RUNTIME_BIN_EVENTHANDLER_WIN_H_
#define RUNTIME_BIN_EVENTHANDLER_WIN_H_

#if !defined(RUNTIME_BIN_EVENTHANDLER_H_)
#error Do not include eventhandler_win.h directly; use eventhandler.h instead.
#endif

#include <mswsock.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <memory>
#include <utility>

#include "bin/builtin.h"
#include "bin/reference_counting.h"
#include "bin/socket_base.h"
#include "bin/thread.h"

namespace dart {
namespace bin {

// Forward declarations.
class ClientSocket;
class EventHandlerImplementation;
class FileHandle;
class Handle;
class ListenSocket;
class MonitorLocker;
class SocketHandle;

// An OverlappedBuffer encapsulates the OVERLAPPED structure and the
// associated data buffer. For accept it also contains the pre-created
// socket for the client.
class OverlappedBuffer {
 public:
  enum Operation {
    kAccept,
    kRead,
    kRecvFrom,
    kWrite,
    kSendTo,
    kDisconnect,
    kConnect
  };

  static std::unique_ptr<OverlappedBuffer> AllocateAcceptBuffer(Handle* handle);
  static std::unique_ptr<OverlappedBuffer> AllocateReadBuffer(Handle* handle,
                                                              int buffer_size);
  static std::unique_ptr<OverlappedBuffer> AllocateRecvFromBuffer(
      Handle* handle,
      int buffer_size);
  static std::unique_ptr<OverlappedBuffer> AllocateWriteBuffer(Handle* handle,
                                                               int buffer_size);
  static std::unique_ptr<OverlappedBuffer> AllocateSendToBuffer(
      Handle* handle,
      int buffer_size);
  static std::unique_ptr<OverlappedBuffer> AllocateDisconnectBuffer(
      Handle* handle);
  static std::unique_ptr<OverlappedBuffer> AllocateConnectBuffer(
      Handle* handle);

  // Find the IO buffer from the OVERLAPPED address.
  static OverlappedBuffer* GetFromOverlapped(OVERLAPPED* overlapped);

  // Read data from a buffer which has been received. It will read up
  // to num_bytes bytes of data returning the actual number of bytes
  // read. This will update the index of the next byte in the buffer
  // so calling Read several times will keep returning new data from
  // the buffer until all data have been read.
  int Read(void* buffer, int num_bytes);

  // Write data to a buffer before sending it. Returns the number of bytes
  // actually written to the buffer. Calls to Write will always write to
  // the buffer from the beginning.
  int Write(const void* buffer, int num_bytes);

  // Check the amount of data in a read buffer which has not been read yet.
  int GetRemainingLength();
  bool IsEmpty() { return GetRemainingLength() == 0; }

  Operation operation() const { return operation_; }
  SOCKET client() const { return client_; }
  char* GetBufferStart() { return reinterpret_cast<char*>(&buffer_data_); }
  int GetBufferSize() const { return buflen_; }
  struct sockaddr* from() const { return from_; }
  socklen_t* from_len_addr() const { return from_len_addr_; }
  socklen_t from_len() const { return from_ == nullptr ? 0 : *from_len_addr_; }

  // Returns the address of the OVERLAPPED structure with all fields
  // initialized to zero.
  OVERLAPPED* GetCleanOverlapped() {
    memset(&overlapped_, 0, sizeof(overlapped_));
    return &overlapped_;
  }

  // Returns a WASBUF structure initialized with the data in this IO buffer.
  WSABUF* GetWASBUF() {
    wbuf_.buf = GetBufferStart();
    wbuf_.len = GetBufferSize();
    return &wbuf_;
  }

  void set_data_length(int data_length) { data_length_ = data_length; }

  void operator delete(void* buffer) { free(buffer); }

  Handle* StealHandle() {
    auto handle = handle_;
    handle_ = nullptr;
    return handle;
  }
  void DetachClient() { client_ = INVALID_SOCKET; }

  ~OverlappedBuffer();

 private:
  OverlappedBuffer(Handle* handle, int buffer_size, Operation operation);

  void* operator new(size_t size, int buffer_size) {
    return malloc(size + buffer_size);
  }

  // Allocate an overlapped buffer for thse specified amount of data and
  // operation. Some operations need additional buffer space, which is
  // handled by this method.
  static std::unique_ptr<OverlappedBuffer> AllocateBuffer(Handle* handle,
                                                          int buffer_size,
                                                          Operation operation);

  OVERLAPPED overlapped_;           // OVERLAPPED structure for overlapped IO.
  SOCKET client_ = INVALID_SOCKET;  // Used for AcceptEx client socket.
  int buflen_;                      // Length of the buffer.
  Operation operation_;             // Type of operation issued.
  Handle* handle_ = nullptr;

  int index_;        // Index for next read from read buffer.
  int data_length_;  // Length of the actual data in the buffer.

  WSABUF wbuf_;  // Structure for passing buffer to WSA functions.

  // For the recvfrom operation additional storace is allocated for the
  // source sockaddr.
  socklen_t* from_len_addr_;  // Pointer to source sockaddr size storage.
  struct sockaddr* from_;     // Pointer to source sockaddr storage.

  // Buffer for recv/send/AcceptEx. This must be at the end of the
  // object as the object is allocated larger than it's definition
  // indicate to extend this array.
  uint8_t buffer_data_[1];

  DISALLOW_COPY_AND_ASSIGN(OverlappedBuffer);
};

// Abstract super class for holding information on listen and connected
// sockets.
class Handle : public ReferenceCounted<Handle>, public DescriptorInfoBase {
 public:
  enum Type {
    kFile,
    kStd,
    kDirectoryWatch,
    kClientSocket,
    kListenSocket,
    kDatagramSocket
  };

  enum class SupportsOverlappedIO { kYes, kNo };

  // Socket interface exposing normal socket operations.
  intptr_t Available();
  bool DataReady();
  intptr_t Read(void* buffer, intptr_t num_bytes);
  intptr_t RecvFrom(void* buffer,
                    intptr_t num_bytes,
                    struct sockaddr* sa,
                    socklen_t addr_len);
  virtual intptr_t Write(const void* buffer, intptr_t num_bytes);
  virtual intptr_t SendTo(const void* buffer,
                          intptr_t num_bytes,
                          struct sockaddr* sa,
                          socklen_t sa_len);

  // Internal interface used by the event handler.
  virtual bool IssueReadLocked(MonitorLocker* ml);
  virtual bool IssueRecvFromLocked(MonitorLocker* ml);
  bool HasPendingRead();
  bool HasPendingWrite();
  void ReadComplete(std::unique_ptr<OverlappedBuffer> buffer);
  void WriteComplete(std::unique_ptr<OverlappedBuffer> buffer);

  bool IsClosing() { return (flags_ & (1 << kClosing)) != 0; }
  bool IsClosedRead() { return (flags_ & (1 << kCloseRead)) != 0; }
  bool IsClosedWrite() { return (flags_ & (1 << kCloseWrite)) != 0; }
  bool IsError() { return (flags_ & (1 << kError)) != 0; }
  void MarkClosing() { flags_ |= (1 << kClosing); }
  void MarkClosedRead() { flags_ |= (1 << kCloseRead); }
  void MarkClosedWrite() { flags_ |= (1 << kCloseWrite); }
  void MarkError() { flags_ |= (1 << kError); }

  HANDLE handle() { return handle_; }

  void Close();
  void CloseLocked(MonitorLocker* ml);

  virtual void DoCloseLocked(MonitorLocker* ml);
  virtual bool IsClosed() = 0;

  bool IsHandleClosed() const { return handle_ == INVALID_HANDLE_VALUE; }

  Type type() { return type_; }
  bool is_file() { return type_ == kFile; }
  bool is_socket() {
    return type_ == kListenSocket || type_ == kClientSocket ||
           type_ == kDatagramSocket;
  }
  bool is_listen_socket() { return type_ == kListenSocket; }
  bool is_client_socket() { return type_ == kClientSocket; }
  bool is_datagram_socket() { return type_ == kDatagramSocket; }

  bool supports_overlapped_io() {
    return (flags_ & (1 << kDoesNotSupportOverlappedIO)) == 0;
  }

  void ReadSyncCompleteAsync();

  DWORD last_error() { return last_error_; }
  void set_last_error(DWORD last_error) { last_error_ = last_error; }

 protected:
  // For access to monitor_;
  friend class EventHandlerImplementation;

  enum Flags {
    kClosing = 0,
    kCloseRead = 1,
    kCloseWrite = 2,
    kDoesNotSupportOverlappedIO = 3,
    kError = 4
  };

  Handle(intptr_t handle,
         Type type_,
         SupportsOverlappedIO supports_overlapped_io);
  virtual ~Handle();

  virtual void HandleIssueError();

  Monitor monitor_;
  const Type type_;
  HANDLE handle_;

  std::unique_ptr<OverlappedBuffer>
      data_ready_;  // Buffer for data ready to be read.
  OverlappedBuffer* pending_read_ = nullptr;   // Buffer for pending read.
  OverlappedBuffer* pending_write_ = nullptr;  // Buffer for pending write

  DWORD last_error_ = NOERROR;

  HANDLE read_thread_ = INVALID_HANDLE_VALUE;
  bool read_thread_starting_ = false;
  bool read_thread_finished_ = false;

 private:
  void WaitForReadThreadStarted();
  void NotifyReadThreadStarted();
  void WaitForReadThreadFinished();
  void NotifyReadThreadFinished();

  virtual bool IssueWriteLocked(MonitorLocker* ml,
                                std::unique_ptr<OverlappedBuffer> buffer);
  virtual bool IssueSendToLocked(MonitorLocker* ml,
                                 std::unique_ptr<OverlappedBuffer> buffer,
                                 struct sockaddr* sa,
                                 socklen_t sa_len);

  int flags_ = 0;

  friend class ReferenceCounted<Handle>;
  DISALLOW_COPY_AND_ASSIGN(Handle);
};

class FileHandle : public DescriptorInfoSingleMixin<Handle> {
 public:
  explicit FileHandle(HANDLE handle)
      : DescriptorInfoSingleMixin(reinterpret_cast<intptr_t>(handle),
                                  kFile,
                                  SupportsOverlappedIO::kYes) {}

  virtual bool IsClosed();

 protected:
  FileHandle(HANDLE handle,
             Type type,
             SupportsOverlappedIO supports_overlapped_io)
      : DescriptorInfoSingleMixin(reinterpret_cast<intptr_t>(handle),
                                  type,
                                  supports_overlapped_io) {}

 private:
  DISALLOW_COPY_AND_ASSIGN(FileHandle);
};

class StdHandle : public FileHandle {
 public:
  static StdHandle* Stdin(HANDLE handle);

  virtual void DoCloseLocked(MonitorLocker* ml);
  virtual intptr_t Write(const void* buffer, intptr_t num_bytes);

  void WriteSyncCompleteAsync();
  void RunWriteLoop();

#if defined(DEBUG)
  static StdHandle* StdinPtr() { return stdin_; }
#endif

 private:
  static Mutex* stdin_mutex_;
  static StdHandle* stdin_;

  explicit StdHandle(HANDLE handle)
      : FileHandle(handle, kStd, SupportsOverlappedIO::kNo) {}

  HANDLE thread_handle_ = INVALID_HANDLE_VALUE;
  intptr_t thread_wrote_ = 0;
  bool write_thread_exists_ = false;
  bool write_thread_running_ = false;

  DISALLOW_COPY_AND_ASSIGN(StdHandle);
};

class DirectoryWatchHandle : public DescriptorInfoSingleMixin<Handle> {
 public:
  DirectoryWatchHandle(HANDLE handle, int events, bool recursive)
      : DescriptorInfoSingleMixin(reinterpret_cast<intptr_t>(handle),
                                  kDirectoryWatch,
                                  SupportsOverlappedIO::kYes),
        events_(events),
        recursive_(recursive) {}

  virtual bool IsClosed();

  virtual bool IssueReadLocked(MonitorLocker* ml);

  void Start();
  void Stop();

 private:
  int events_;
  bool recursive_;

  DISALLOW_COPY_AND_ASSIGN(DirectoryWatchHandle);
};

class SocketHandle : public Handle {
 public:
  SOCKET socket() const { return socket_; }

 protected:
  explicit SocketHandle(intptr_t s, Type type)
      : Handle(s, type, SupportsOverlappedIO::kYes), socket_(s) {}

  virtual void HandleIssueError();

 private:
  const SOCKET socket_;

  DISALLOW_COPY_AND_ASSIGN(SocketHandle);
};

// Information on listen sockets.
class ListenSocket : public DescriptorInfoMultipleMixin<SocketHandle> {
 public:
  explicit ListenSocket(intptr_t s)
      : DescriptorInfoMultipleMixin(s, kListenSocket),
        pending_accept_count_(0),
        accepted_head_(nullptr),
        accepted_tail_(nullptr),
        accepted_count_(0) {}
  virtual ~ListenSocket() {
    ASSERT(!HasPendingAccept());
    ASSERT(accepted_head_ == nullptr);
    ASSERT(accepted_tail_ == nullptr);
  }

  // Socket interface exposing normal socket operations.
  ClientSocket* Accept();
  bool StartAccept();

  // Internal interface used by the event handler.
  bool HasPendingAccept() { return pending_accept_count_ > 0; }
  void AcceptComplete(std::unique_ptr<OverlappedBuffer> buffer);

  virtual void DoCloseLocked(MonitorLocker* ml);
  virtual bool IsClosed();

  int pending_accept_count() { return pending_accept_count_; }

  int accepted_count() { return accepted_count_; }

  void DispatchCompletedAcceptsLocked(MonitorLocker* ml);

 private:
  static constexpr intptr_t kMinIssuedAccepts = 5;

  bool IssueAcceptLocked(MonitorLocker* ml);

  // The number of asynchronous `IssueAccept` operations which haven't completed
  // yet.
  int pending_accept_count_;

  // Linked list of accepted connections provided by completion code. Ready to
  // be handed over through accept.
  ClientSocket* accepted_head_;
  ClientSocket* accepted_tail_;

  // The number of accepted connections which are waiting to be removed from
  // this queue and processed by dart isolates.
  int accepted_count_;

  DISALLOW_COPY_AND_ASSIGN(ListenSocket);
};

// Information on connected sockets.
class ClientSocket : public DescriptorInfoSingleMixin<SocketHandle> {
 public:
  explicit ClientSocket(intptr_t s,
                        std::unique_ptr<RawAddr> remote_addr = nullptr)
      : DescriptorInfoSingleMixin(s, kClientSocket),
        next_(nullptr),
        connected_(false),
        closed_(false),
        remote_addr_(std::move(remote_addr)) {}

  virtual ~ClientSocket() {
    // Don't delete this object until all pending requests have been handled.
    ASSERT(!HasPendingRead());
    ASSERT(!HasPendingWrite());
    ASSERT(next_ == nullptr);
    ASSERT(closed_ == true);
  }

  void Shutdown(int how);

  // Internal interface used by the event handler.
  virtual bool IssueReadLocked(MonitorLocker* ml);
  void IssueDisconnectLocked(MonitorLocker* ml);
  void DisconnectComplete();
  void ConnectComplete();

  virtual void DoCloseLocked(MonitorLocker* ml);
  virtual bool IsClosed();

  // If `ClientSocket` was constructed with a `remote_addr`, populate `addr`
  // with that value and return `true`. Otherwise leave `addr` untouched and
  // return `false`.
  bool PopulateRemoteAddr(RawAddr& addr);

  ClientSocket* next() { return next_; }
  void set_next(ClientSocket* next) { next_ = next; }

  void mark_connected() { connected_ = true; }
  bool is_connected() const { return connected_; }

  void mark_closed() { closed_ = true; }

#if defined(DEBUG)
  static intptr_t disconnecting() { return disconnecting_; }
#endif

 private:
  virtual bool IssueWriteLocked(MonitorLocker* ml,
                                std::unique_ptr<OverlappedBuffer> buffer);

  ClientSocket* next_;
  bool connected_;
  bool closed_;
  std::unique_ptr<RawAddr> remote_addr_;

#if defined(DEBUG)
  static intptr_t disconnecting_;
#endif

  DISALLOW_COPY_AND_ASSIGN(ClientSocket);
};

class DatagramSocket : public DescriptorInfoSingleMixin<SocketHandle> {
 public:
  explicit DatagramSocket(intptr_t s)
      : DescriptorInfoSingleMixin(s, kDatagramSocket) {}

  virtual ~DatagramSocket() {
    // Don't delete this object until all pending requests have been handled.
    ASSERT(!HasPendingRead());
    ASSERT(!HasPendingWrite());
  }

  // Internal interface used by the event handler.
  virtual bool IssueRecvFromLocked(MonitorLocker* ml);

  virtual void DoCloseLocked(MonitorLocker* ml);
  virtual bool IsClosed();

 private:
  virtual bool IssueSendToLocked(MonitorLocker* ml,
                                 std::unique_ptr<OverlappedBuffer> buffer,
                                 sockaddr* sa,
                                 socklen_t sa_len);

  DISALLOW_COPY_AND_ASSIGN(DatagramSocket);
};

// Event handler.
class EventHandlerImplementation {
 public:
  EventHandlerImplementation();
  virtual ~EventHandlerImplementation();

  void AssociateWithCompletionPort(Handle* handle);

  void SendData(intptr_t id, Dart_Port dart_port, int64_t data);
  void Start(EventHandler* handler);
  void Shutdown();

  static void EventHandlerEntry(uword args);

  int64_t GetTimeout();
  void HandleInterrupt(InterruptMessage* msg);
  void HandleTimeout();

  void HandleIOCompletion(int32_t bytes, ULONG_PTR key, OVERLAPPED* overlapped);

  void HandleCompletionOrInterrupt(BOOL ok,
                                   DWORD bytes,
                                   ULONG_PTR key,
                                   OVERLAPPED* overlapped);

  HANDLE completion_port() { return completion_port_; }

  LPFN_ACCEPTEX accept_ex() {
    InitializeSocketExtensions();
    return accept_ex_;
  }

  LPFN_CONNECTEX connect_ex() {
    InitializeSocketExtensions();
    return connect_ex_;
  }

  LPFN_DISCONNECTEX disconnect_ex() {
    InitializeSocketExtensions();
    return disconnect_ex_;
  }

  LPFN_GETACCEPTEXSOCKADDRS get_accept_ex_sockaddrs() {
    InitializeSocketExtensions();
    return get_accept_ex_sockaddrs_;
  }

 private:
  void InitializeSocketExtensions();

  void HandleAccept(ListenSocket* listen_socket,
                    std::unique_ptr<OverlappedBuffer> buffer);
  void HandleRead(Handle* handle,
                  int bytes,
                  std::unique_ptr<OverlappedBuffer> buffer);
  void HandleRecvFrom(Handle* handle,
                      int bytes,
                      std::unique_ptr<OverlappedBuffer> buffer);
  void HandleWrite(Handle* handle,
                   int bytes,
                   std::unique_ptr<OverlappedBuffer> buffer);
  void HandleDisconnect(ClientSocket* client_socket,
                        int bytes,
                        std::unique_ptr<OverlappedBuffer> buffer);
  void HandleConnect(ClientSocket* client_socket,
                     int bytes,
                     std::unique_ptr<OverlappedBuffer> buffer);

  Monitor monitor_;
  HANDLE handler_thread_ = INVALID_HANDLE_VALUE;

  TimeoutQueue timeout_queue_;  // Time for next timeout.
  bool shutdown_ = false;
  HANDLE completion_port_ = INVALID_HANDLE_VALUE;

  std::atomic<bool> socket_extensions_initialized_{false};
  LPFN_ACCEPTEX accept_ex_ = nullptr;
  LPFN_CONNECTEX connect_ex_ = nullptr;
  LPFN_DISCONNECTEX disconnect_ex_ = nullptr;
  LPFN_GETACCEPTEXSOCKADDRS get_accept_ex_sockaddrs_ = nullptr;

  DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
};

}  // namespace bin
}  // namespace dart

#endif  // RUNTIME_BIN_EVENTHANDLER_WIN_H_
