// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

#include "src/developer/debug/zxdb/debug_adapter/server.h"

#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <unistd.h>

#include "src/developer/debug/shared/logging/logging.h"

namespace zxdb {

DebugAdapterServer::DebugAdapterServer(Session* session, uint16_t port)
    : session_(session), port_(port) {
  int fd[2] = {};
  pipe(fd);
  exit_pipe_[0] = fbl::unique_fd(fd[0]);
  exit_pipe_[1] = fbl::unique_fd(fd[1]);
}

Err DebugAdapterServer::Init() {
  main_loop_ = debug::MessageLoop::Current();
  server_socket_.reset(socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP));
  if (!server_socket_.is_valid()) {
    return Err("Could not create socket.");
  }

  {
    // Set SO_REUSEPORT so that subsequent binds succeeds.
    int opt = 1;
    setsockopt(server_socket_.get(), SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
  }

  {
    // Bind to local address.
    struct sockaddr_in6 addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin6_family = AF_INET6;
    addr.sin6_addr = in6addr_any;
    addr.sin6_port = htons(port_);
    if (bind(server_socket_.get(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
      return Err("Could not bind socket to port: %d", port_);
    }
  }

  if (listen(server_socket_.get(), 1) < 0) {
    return Err("Failed to listen on server socket");
  }
  ListenConnection();
  return Err();
}

void DebugAdapterServer::ListenConnection() {
  FX_DCHECK(!background_thread_.get());  // Duplicate ListenConnection() call.

  // Create the background thread to listen to incoming connections.
  background_thread_ = std::make_unique<std::thread>([this]() { ListenBackgroundThread(); });
}

void DebugAdapterServer::ListenBackgroundThread() {
  // Wait for one connection.
  // TODO(puneetha) : Replace FX_LOGS with call to console output.
  FX_LOGS(INFO) << "Waiting on port " << port_ << " for debug adapter connection.\r\n";
  fbl::unique_fd client;
  while (!Accept(client)) {
    if (background_thread_exit_) {
      return;
    }
  }
  FX_LOGS(INFO) << "Debug Adapter connection established.\r\n";

  main_loop_->PostTask(FROM_HERE, [this, client = std::move(client)]() mutable {
    ConnectionResolvedMainThread(std::move(client));
  });
}

bool DebugAdapterServer::Accept(fbl::unique_fd& client) {
  // Wait on server_socket fd and exit_event fd until new connection is received or thread exit is
  // requested.
  fd_set read_set;
  FD_ZERO(&read_set);
  FD_SET(server_socket_.get(), &read_set);
  FD_SET(exit_pipe_[0].get(), &read_set);
  int nfds =
      server_socket_.get() > exit_pipe_[0].get() ? server_socket_.get() : exit_pipe_[0].get();
  auto status = select(nfds + 1, &read_set, NULL, NULL, NULL);
  if (status <= 0) {
    // An error or timeout occured.
    return false;
  }

  if (FD_ISSET(exit_pipe_[0].get(), &read_set)) {
    // Thread exit requested.
    return false;
  }

  // Accept the new connection.
  sockaddr_in6 addr;
  memset(&addr, 0, sizeof(addr));

  socklen_t addrlen = sizeof(addr);
  client =
      fbl::unique_fd(accept(server_socket_.get(), reinterpret_cast<sockaddr*>(&addr), &addrlen));
  if (!client.is_valid()) {
    FX_LOGS(ERROR) << "Accept failed.";
    return false;
  }

  if (fcntl(client.get(), F_SETFL, O_NONBLOCK) < 0) {
    FX_LOGS(ERROR) << "Couldn't make port nonblocking.";
    return false;
  }
  return true;
}

void DebugAdapterServer::ConnectionResolvedMainThread(fbl::unique_fd client) {
  background_thread_->join();
  background_thread_.reset();

  for (auto& observer : observers_) {
    observer.ClientConnected();
  }

  buffer_ = std::make_unique<debug::BufferedFD>(std::move(client));
  if (!buffer_->Start()) {
    FX_LOGS(ERROR) << "Failed to initialize debug adapter buffer";
    return;
  }

  context_ = std::make_unique<DebugAdapterContext>(session_, &buffer_->stream());
  buffer_->set_data_available_callback(
      [context = context_.get()]() { context->OnStreamReadable(); });
  context_->set_destroy_connection_callback([this]() { OnDisconnect(); });

  // Reset the client connection on error.
  buffer_->set_error_callback([this]() {
    FX_LOGS(INFO) << "Connection lost.";
    OnDisconnect();
  });
}

void DebugAdapterServer::OnDisconnect() {
  ResetClientConnection();
  for (auto& observer : observers_) {
    observer.ClientDisconnected();
  }
  ListenConnection();
}

void DebugAdapterServer::ResetClientConnection() {
  context_.reset();
  buffer_.reset();
}

DebugAdapterServer::~DebugAdapterServer() {
  ResetClientConnection();

  if (background_thread_) {
    background_thread_exit_ = true;
    // Write to exit_event to unblock select().
    int ret;
    do {
      int val = 1;
      ret = write(exit_pipe_[1].get(), &val, sizeof(val));
    } while (ret < 0 && errno == EINTR);
    // Wait for background thread to exit.
    background_thread_->join();
    background_thread_.reset();
  }
}

}  // namespace zxdb
