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

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>

#include "bin/dbg_connection.h"
#include "bin/fdutils.h"
#include "bin/socket.h"

int DebuggerConnectionImpl::epoll_fd_ = -1;
int DebuggerConnectionImpl::wakeup_fds_[2] = {-1, -1};


void DebuggerConnectionImpl::HandleEvent(struct epoll_event* event) {
  if (event->data.fd == DebuggerConnectionHandler::listener_fd_) {
    if (DebuggerConnectionHandler::IsConnected()) {
      FATAL("Cannot connect to more than one debugger.\n");
    }
    int fd = ServerSocket::Accept(event->data.fd);
    if (fd < 0) {
      FATAL("Accepting new debugger connection failed.\n");
    }
    FDUtils::SetBlocking(fd);
    DebuggerConnectionHandler::AcceptDbgConnection(fd);
    // TODO(hausner): add the debugger wire socket fd to the event poll queue
    // once we poll the debugger connection.
  } else if (event->data.fd == wakeup_fds_[0]) {
    // Sync message. Not yet implemented.
    UNIMPLEMENTED();
  } else {
    printf("unexpected: receiving debugger connection event.\n");
    UNIMPLEMENTED();
  }
}


void DebuggerConnectionImpl::Handler(uword args) {
  static const intptr_t kMaxEvents = 4;
  struct epoll_event events[kMaxEvents];
  while (1) {
    const int no_timeout = -1;
    intptr_t result = TEMP_FAILURE_RETRY(
        epoll_wait(epoll_fd_, events, kMaxEvents, no_timeout));
    ASSERT(EAGAIN == EWOULDBLOCK);
    if (result == -1) {
      if (errno != EWOULDBLOCK) {
        perror("epoll_wait failed");
      }
    } else {
      ASSERT(result <= kMaxEvents);
      for (int i = 0; i < result; i++) {
        HandleEvent(&events[i]);
      }
    }
  }
}


void DebuggerConnectionImpl::SetupPollQueue() {
  int result = TEMP_FAILURE_RETRY(pipe(wakeup_fds_));
  if (result != 0) {
    FATAL1("Pipe creation failed with error %d\n", result);
  }
  FDUtils::SetNonBlocking(wakeup_fds_[0]);

  static const int kEpollInitialSize = 16;
  epoll_fd_ = TEMP_FAILURE_RETRY(epoll_create(kEpollInitialSize));
  if (epoll_fd_ == -1) {
    FATAL("Failed creating epoll file descriptor");
  }

  // Register the wakeup _fd with the epoll instance.
  struct epoll_event event;
  event.events = EPOLLIN;
  event.data.fd = wakeup_fds_[0];
  int status = TEMP_FAILURE_RETRY(epoll_ctl(
                   epoll_fd_, EPOLL_CTL_ADD, wakeup_fds_[0], &event));
  if (status == -1) {
    FATAL("Failed adding wakeup fd to epoll instance");
  }

  // Register the listener_fd with the epoll instance.
  event.events = EPOLLIN;
  event.data.fd = DebuggerConnectionHandler::listener_fd_;
  status = TEMP_FAILURE_RETRY(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD,
               DebuggerConnectionHandler::listener_fd_, &event));
  if (status == -1) {
    FATAL("Failed adding listener fd to epoll instance");
  }
}


void DebuggerConnectionImpl::StartHandler(int port_number) {
  ASSERT(DebuggerConnectionHandler::listener_fd_ != -1);
  SetupPollQueue();
  int result = dart::Thread::Start(&DebuggerConnectionImpl::Handler, 0);
  if (result != 0) {
    FATAL1("Failed to start debugger connection handler thread: %d\n", result);
  }
}
