blob: b8ed20e7bda7bb6334002d819e6d025520c59bef [file] [log] [blame]
// 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.
use {
anyhow::Error,
anyhow::Result,
futures_util::future::FutureExt,
futures_util::io::{AsyncReadExt, AsyncWriteExt},
};
#[ffx_core::ffx_plugin(
"zxdb_enabled",
fidl_fuchsia_debugger::DebugAgentProxy = "core/appmgr:out:fuchsia.debugger.DebugAgent"
)]
pub async fn debug(
debugger_proxy: fidl_fuchsia_debugger::DebugAgentProxy,
cmd: ffx_zxdb_plugin_args::DebugCommand,
) -> Result<(), Error> {
let sdk = ffx_config::get_sdk().await?;
let zxdb_path = sdk.get_host_tool("zxdb")?;
// Connect to the debug_agent on the device.
let (sock_server, sock_client) =
fidl::Socket::create(fidl::SocketOpts::STREAM).expect("Failed while creating socket");
debugger_proxy.connect(sock_client).await?;
let (rx, tx) = fidl::AsyncSocket::from_socket(sock_server)?.split();
let rx = std::cell::RefCell::new(rx);
let tx = std::cell::RefCell::new(tx);
// Create our Unix socket.
let listener = async_std::os::unix::net::UnixListener::bind(&cmd.socket_location).await?;
// Start the local debugger.
std::process::Command::new(zxdb_path)
.args(&[
"--unix-connect",
&cmd.socket_location,
"--symbol-server",
"gs://fuchsia-artifacts-release/debug",
])
.spawn()
.expect("zxdb failed to start");
loop {
// Wait for a connection on the unix socket.
let (socket, _) = listener.accept().await?;
let (mut host_rx, mut host_tx) = socket.split();
let mut fuchsia_rx = rx.borrow_mut();
let mut fuchsia_tx = tx.borrow_mut();
// Reading from the ZXDB socket and writing to the Fuchsia channel.
let host_socket_read = async move {
let mut buffer = [0; 4096];
loop {
let n = host_rx.read(&mut buffer[..]).await?;
if n == 0 {
return Ok(()) as Result<(), Error>;
}
let mut ofs = 0;
while ofs != n {
let wrote = fuchsia_tx.write(&buffer[ofs..n]).await?;
ofs += wrote;
if wrote == 0 {
return Ok(()) as Result<(), Error>;
}
}
}
};
let mut host_socket_read = Box::pin(host_socket_read.fuse());
// Reading from the Fuchsia socket and writing to the ZXDB channel.
let host_socket_write = async move {
let mut buffer = [0; 4096];
loop {
let n = fuchsia_rx.read(&mut buffer).await?;
let mut ofs = 0;
while ofs != n {
let wrote = host_tx.write(&buffer[ofs..n]).await?;
ofs += wrote;
if wrote == 0 {
return Ok(()) as Result<(), Error>;
}
}
}
};
let mut host_socket_write = Box::pin(host_socket_write.fuse());
futures::select! {
read_res = host_socket_read => read_res?,
write_res = host_socket_write => write_res?,
};
}
}