use std::time::Duration;
use portable_pty::CommandBuilder;
use tokio::net::TcpStream;
pub fn build_attach_command(
ssh_target: Option<&str>,
tmux_bin: &str,
session_name: &str,
) -> CommandBuilder {
let tmux_setup = format!(
"{tmux} set-option -g mouse on 2>/dev/null; \
{tmux} set-option -g allow-passthrough on 2>/dev/null; \
{tmux} set-window-option -g aggressive-resize on 2>/dev/null; \
{tmux} attach-session -t {session}",
tmux = tmux_bin,
session = session_name,
);
match ssh_target {
None => {
let mut cmd = CommandBuilder::new("bash");
cmd.env("TERM", "xterm-256color");
cmd.args(["-c", &tmux_setup]);
cmd
}
Some(target) => {
let mut cmd = CommandBuilder::new("ssh");
cmd.args(["-tt", target, &format!("TERM=xterm-256color {tmux_setup}")]);
cmd
}
}
}
fn resolve_addr(ssh_target: &str) -> String {
let host_port = ssh_target.rsplit_once('@').map_or(ssh_target, |(_, h)| h);
if host_port.contains(':') {
host_port.to_string()
} else {
format!("{host_port}:22")
}
}
pub async fn probe_reachable(ssh_target: &str, timeout: Duration) -> bool {
let addr = resolve_addr(ssh_target);
tokio::time::timeout(timeout, TcpStream::connect(&addr))
.await
.map(|r| r.is_ok())
.unwrap_or(false)
}
#[cfg(test)]
mod tests {
use super::*;
use tokio::net::TcpListener;
#[test]
fn resolve_addr_defaults_port_22() {
assert_eq!(resolve_addr("gpu-box.local"), "gpu-box.local:22");
assert_eq!(resolve_addr("mvhenten@gpu-box.local"), "gpu-box.local:22");
}
#[test]
fn resolve_addr_keeps_explicit_port() {
assert_eq!(resolve_addr("gpu-box.local:2222"), "gpu-box.local:2222");
assert_eq!(
resolve_addr("mvhenten@gpu-box.local:2222"),
"gpu-box.local:2222"
);
}
#[test]
fn resolve_addr_handles_bare_ip() {
assert_eq!(resolve_addr("10.0.0.5"), "10.0.0.5:22");
assert_eq!(resolve_addr("root@10.0.0.5:22"), "10.0.0.5:22");
}
#[tokio::test]
async fn probe_reachable_true_for_listening_port() {
let listener = TcpListener::bind("127.0.0.1:0").await.expect("bind");
let addr = listener.local_addr().expect("addr");
let _accept = tokio::spawn(async move {
let _ = listener.accept().await;
});
assert!(probe_reachable(&addr.to_string(), Duration::from_secs(2)).await);
}
#[tokio::test]
async fn probe_reachable_false_for_closed_port() {
let listener = TcpListener::bind("127.0.0.1:0").await.expect("bind");
let addr = listener.local_addr().expect("addr");
drop(listener);
assert!(!probe_reachable(&addr.to_string(), Duration::from_millis(500)).await);
}
fn argv(cmd: &CommandBuilder) -> Vec<String> {
cmd.get_argv()
.iter()
.map(|s| s.to_string_lossy().into_owned())
.collect()
}
#[test]
fn build_attach_command_local_uses_bash() {
let cmd = build_attach_command(None, "tmux", "demo");
let argv = argv(&cmd);
assert_eq!(argv[0], "bash");
assert_eq!(argv[1], "-c");
assert!(argv[2].contains("tmux attach-session -t demo"));
}
#[test]
fn build_attach_command_remote_uses_ssh_tt() {
let cmd = build_attach_command(Some("mvhenten@gpu-box"), "tmux", "demo");
let argv = argv(&cmd);
assert_eq!(argv[0], "ssh");
assert_eq!(argv[1], "-tt");
assert_eq!(argv[2], "mvhenten@gpu-box");
assert!(argv[3].starts_with("TERM=xterm-256color "));
assert!(argv[3].contains("tmux attach-session -t demo"));
}
}