| // Copyright 2019 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/lib/vsh/client.h" | |
| #include <lib/syslog/cpp/macros.h> | |
| #include <lib/zx/socket.h> | |
| #include <zircon/status.h> | |
| #include "src/virtualization/lib/vsh/util.h" | |
| namespace vsh { | |
| // static | |
| fit::result<BlockingClient, zx_status_t> BlockingClient::Connect( | |
| const fuchsia::virtualization::HostVsockEndpointSyncPtr& socket_endpoint, uint32_t cid, | |
| uint32_t port) { | |
| // Open a socket to the guest's vsock port where vshd should be listening | |
| zx::socket socket, remote_socket; | |
| zx_status_t status = zx::socket::create(ZX_SOCKET_STREAM, &socket, &remote_socket); | |
| if (status != ZX_OK) { | |
| FX_LOGS(ERROR) << "Failed to create socket: " << zx_status_get_string(status); | |
| return fit::error(status); | |
| } | |
| zx_status_t fidl_status = socket_endpoint->Connect(cid, port, std::move(remote_socket), &status); | |
| if (status != ZX_OK) { | |
| FX_LOGS(ERROR) << "Failed to connect to vshd: " << zx_status_get_string(status); | |
| return fit::error(status); | |
| } | |
| if (fidl_status != ZX_OK) { | |
| FX_LOGS(ERROR) << "FIDL error connecting to vshd: " << zx_status_get_string(fidl_status); | |
| return fit::error(fidl_status); | |
| } | |
| return fit::ok(BlockingClient(std::move(socket))); | |
| } | |
| BlockingClient::BlockingClient(zx::socket socket) : vsock_(std::move(socket)) {} | |
| zx_status_t BlockingClient::Setup(vm_tools::vsh::SetupConnectionRequest conn_req) { | |
| vm_tools::vsh::SetupConnectionResponse conn_resp; | |
| if (!SendMessage(vsock_, conn_req)) { | |
| FX_LOGS(ERROR) << "Failed to send connection request"; | |
| return ZX_ERR_INTERNAL; | |
| } | |
| if (!RecvMessage(vsock_, &conn_resp)) { | |
| FX_LOGS(ERROR) << "Failed to receive response from vshd, giving up after one try"; | |
| return ZX_ERR_INTERNAL; | |
| } | |
| if (conn_resp.status() != vm_tools::vsh::READY) { | |
| FX_LOGS(ERROR) << "Server was unable to set up connection properly: " | |
| << conn_resp.description(); | |
| return ZX_ERR_INTERNAL; | |
| } | |
| status_ = conn_resp.status(); | |
| return ZX_OK; | |
| } | |
| fit::result<vm_tools::vsh::HostMessage, zx_status_t> BlockingClient::NextMessage() { | |
| FX_CHECK(status_ == vm_tools::vsh::ConnectionStatus::READY); | |
| vm_tools::vsh::HostMessage msg; | |
| if (!RecvMessage(vsock_, &msg)) { | |
| FX_LOGS(ERROR) << "Failed to receive response from vshd, giving up after one try"; | |
| return fit::error(ZX_ERR_INTERNAL); | |
| } | |
| if (msg.msg_case() == vm_tools::vsh::HostMessage::MsgCase::kStatusMessage) { | |
| auto new_status = msg.status_message().status(); | |
| status_ = new_status; | |
| } | |
| return fit::ok(std::move(msg)); | |
| } | |
| } // namespace vsh |