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

#include "src/bringup/bin/virtcon/session-manager.h"

#include <fuchsia/hardware/pty/llcpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/io.h>
#include <lib/fdio/spawn.h>
#include <lib/fdio/unsafe.h>
#include <lib/fdio/watcher.h>
#include <lib/service/llcpp/service.h>
#include <lib/zircon-internal/paths.h>
#include <sys/ioctl.h>

#include <fbl/unique_fd.h>

namespace virtcon {

namespace fpty = fuchsia_hardware_pty;

namespace {

void SessionDestroy(vc_t* vc) {
  if (vc->io != nullptr) {
    fdio_unsafe_release(vc->io);
  }
  if (vc->proc != ZX_HANDLE_INVALID) {
    zx_task_kill(vc->proc);
  }
  if (vc->pty_wait) {
    vc->pty_wait.reset();
  }
  // vc_destroy() closes the vc->fd.
  vc_destroy(vc);
}

}  // namespace

void SessionManager::SessionIoCallback(vc_t* vc, async_dispatcher_t* dispatcher, async::Wait* wait,
                                       zx_status_t status, const zx_packet_signal_t* signal) {
  if (status == ZX_OK) {
    uint32_t pollevt = 0;
    fdio_unsafe_wait_end(vc->io, signal->observed, &pollevt);

    if (pollevt & POLLIN) {
      char data[1024] = {};
      ssize_t r = read(vc->fd, data, sizeof(data));
      if (r >= 0) {
        if (r > 0) {
          vc_write(vc, data, r, 0);
        }
        wait->Begin(dispatcher);
        return;
      }
    }
  }

  num_vcs_--;
  SessionDestroy(vc);
}

zx::status<vc_t*> SessionManager::CreateSession(fidl::ServerEnd<fpty::Device> session,
                                                bool make_active,
                                                const color_scheme_t* color_scheme) {
  auto client_end = service::Connect<fpty::Device>();
  if (client_end.is_error()) {
    return client_end.take_error();
  }

  auto result = fidl::WireCall(client_end->borrow()).OpenClient(0, std::move(session));
  if (result.status() != ZX_OK) {
    return zx::error(result.status());
  }
  if (result->s != ZX_OK) {
    return zx::error(result->s);
  }

  // We have to do this dance because the plumbing of the PTY service through svchost causes the
  // DESCRIBE flag to get consumed by the wrong code, resulting in the wrong NodeInfo being
  // provided. This manifests as a loss of fd signals. Setting the O_NONBLOCK flag manually fixes
  // the connection's state.
  fbl::unique_fd fd;
  zx_status_t status =
      fdio_fd_create(client_end.value().channel().release(), fd.reset_and_get_address());
  if (status != ZX_OK) {
    return zx::error(status);
  }
  int flags = fcntl(fd.get(), F_GETFL);
  if (flags < 0) {
    return zx::error(ZX_ERR_IO);
  }
  if (fcntl(fd.get(), F_SETFL, flags | O_NONBLOCK) < 0) {
    return zx::error(ZX_ERR_IO);
  }

  vc_t* vc;
  if (vc_create(&vc, color_scheme)) {
    return zx::error(ZX_ERR_INTERNAL);
  }

  struct winsize wsz = {
      .ws_row = static_cast<unsigned short>(vc->rows),
      .ws_col = static_cast<unsigned short>(vc->columns),
  };
  ioctl(fd.get(), TIOCSWINSZ, &wsz);

  vc->io = fdio_unsafe_fd_to_io(fd.get());
  if (vc->io == nullptr) {
    return zx::error(ZX_ERR_INTERNAL);
  }
  vc->fd = fd.release();

  zx_handle_t handle;
  zx_signals_t signals;
  fdio_unsafe_wait_begin(vc->io, POLLIN | POLLRDHUP | POLLHUP, &handle, &signals);

  vc->pty_wait = std::make_unique<async::Wait>(
      handle, signals, 0,
      [this, vc](async_dispatcher_t* dispatcher, async::Wait* wait, zx_status_t status,
                 const zx_packet_signal_t* signal) {
        SessionIoCallback(vc, dispatcher, wait, status, signal);
      });

  if (make_active) {
    vc_set_active(-1, vc);
  }
  vc->pty_wait->Begin(dispatcher_);

  num_vcs_++;
  return zx::ok(vc);
}

void SessionManager::Bind(fidl::ServerEnd<fuchsia_virtualconsole::SessionManager> request) {
  fidl::BindServer(dispatcher_, std::move(request), this);
}

void SessionManager::CreateSession(fidl::ServerEnd<fpty::Device> session,
                                   CreateSessionCompleter::Sync& completer) {
  completer.Reply(CreateSession(std::move(session)).status_value());
}

zx::status<vc_t*> SessionManager::CreateSession(fidl::ServerEnd<fpty::Device> session) {
  return CreateSession(std::move(session), !keep_log_visible_ && (num_vcs_ == 0), color_scheme_);
}

void SessionManager::HasPrimaryConnected(HasPrimaryConnectedCompleter::Sync& completer) {
  completer.Reply(is_primary_bound());
}

}  // namespace virtcon
