// 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/virtualization/bin/guest/socat.h"

#include <fuchsia/virtualization/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/syslog/cpp/macros.h>

#include <iostream>

#include "lib/fidl/cpp/binding.h"
#include "src/lib/fsl/handles/object_info.h"
#include "src/virtualization/bin/guest/serial.h"

class HostVsockAcceptor : public fuchsia::virtualization::HostVsockAcceptor {
 public:
  HostVsockAcceptor(uint32_t port, async::Loop* loop) : port_(port), console_(loop) {}

  // |fuchsia::virtualization::HostVsockAcceptor|
  void Accept(uint32_t src_cid, uint32_t src_port, uint32_t port,
              AcceptCallback callback) override {
    if (port != port_) {
      std::cerr << "Unexpected port " << port << "\n";
      callback(ZX_ERR_CONNECTION_REFUSED, zx::handle());
      return;
    }
    zx::socket socket, remote_socket;
    zx_status_t status = zx::socket::create(ZX_SOCKET_STREAM, &socket, &remote_socket);
    if (status != ZX_OK) {
      std::cerr << "Failed to create socket " << status << "\n";
      callback(ZX_ERR_CONNECTION_REFUSED, zx::handle());
      return;
    }
    callback(ZX_OK, std::move(remote_socket));
    console_.Start(zx::socket(std::move(socket)));
  }

 private:
  uint32_t port_;
  SerialConsole console_;
};

void handle_socat_listen(uint32_t env_id, uint32_t port, async::Loop* loop,
                         sys::ComponentContext* context) {
  fuchsia::virtualization::ManagerSyncPtr manager;
  context->svc()->Connect(manager.NewRequest());
  fuchsia::virtualization::RealmSyncPtr realm;
  manager->Connect(env_id, realm.NewRequest());
  fuchsia::virtualization::HostVsockEndpointSyncPtr vsock_endpoint;
  realm->GetHostVsockEndpoint(vsock_endpoint.NewRequest());

  HostVsockAcceptor acceptor(port, loop);
  fidl::Binding<fuchsia::virtualization::HostVsockAcceptor> binding(&acceptor);
  zx_status_t status;
  vsock_endpoint->Listen(port, binding.NewBinding(), &status);
  if (status != ZX_OK) {
    std::cerr << "Failed to listen on port " << port << "\n";
    return;
  }

  loop->Run();
}

void handle_socat_connect(uint32_t env_id, uint32_t cid, uint32_t port, async::Loop* loop,
                          sys::ComponentContext* context) {
  fuchsia::virtualization::ManagerSyncPtr manager;
  context->svc()->Connect(manager.NewRequest());
  fuchsia::virtualization::RealmSyncPtr realm;
  manager->Connect(env_id, realm.NewRequest());
  fuchsia::virtualization::HostVsockEndpointSyncPtr vsock_endpoint;
  realm->GetHostVsockEndpoint(vsock_endpoint.NewRequest());

  zx::socket socket, remote_socket;
  zx_status_t status = zx::socket::create(ZX_SOCKET_STREAM, &socket, &remote_socket);
  if (status != ZX_OK) {
    std::cerr << "Failed to create socket " << status << "\n";
    return;
  }
  vsock_endpoint->Connect(cid, port, std::move(remote_socket), &status);
  if (status != ZX_OK) {
    std::cerr << "Failed to connect " << status << "\n";
    return;
  }

  SerialConsole console(loop);
  console.Start(std::move(socket));
  loop->Run();
}
