blob: 75aa335a6f5f8a60872fd714368f6ae1893862b5 [file] [log] [blame]
// 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 "garnet/bin/guest/cli/socat.h"
#include <iostream>
#include <fuchsia/guest/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include "garnet/bin/guest/cli/serial.h"
#include "lib/fidl/cpp/binding.h"
#include "lib/fsl/handles/object_info.h"
#include "lib/fxl/logging.h"
class GuestVsockAcceptor : public fuchsia::guest::HostVsockAcceptor {
public:
GuestVsockAcceptor(uint32_t port, async::Loop* loop)
: port_(port), console_(loop) {}
// |fuchsia::guest::GuestVsockAcceptor|
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,
component::StartupContext* context) {
fuchsia::guest::EnvironmentManagerSyncPtr environment_manager;
context->ConnectToEnvironmentService(environment_manager.NewRequest());
fuchsia::guest::EnvironmentControllerSyncPtr environment_controller;
environment_manager->Connect(env_id, environment_controller.NewRequest());
fuchsia::guest::HostVsockEndpointSyncPtr vsock_endpoint;
environment_controller->GetHostVsockEndpoint(vsock_endpoint.NewRequest());
GuestVsockAcceptor acceptor(port, loop);
fidl::Binding<fuchsia::guest::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,
component::StartupContext* context) {
fuchsia::guest::EnvironmentManagerSyncPtr environment_manager;
context->ConnectToEnvironmentService(environment_manager.NewRequest());
fuchsia::guest::EnvironmentControllerSyncPtr environment_controller;
environment_manager->Connect(env_id, environment_controller.NewRequest());
fuchsia::guest::HostVsockEndpointSyncPtr vsock_endpoint;
environment_controller->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();
}