use std::io::{Read, Write};
use std::sync::Arc;
use foundation_netio::netcap::connection::{
ConnWaker, Connection, Connector, OverlayReadWrite,
};
use foundation_sshkit::{ChannelStream, Dialer, Host};
const DIAL_STDIO: &str = "docker system dial-stdio";
struct SshOverlay(ChannelStream);
impl std::fmt::Debug for SshOverlay {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("SshOverlay(docker system dial-stdio)")
}
}
impl Read for SshOverlay {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.0.read(buf)
}
}
impl Write for SshOverlay {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.0.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.0.flush()
}
}
impl OverlayReadWrite for SshOverlay {
fn clone_box(&self) -> Box<dyn OverlayReadWrite> {
Box::new(SshOverlay(self.0.clone()))
}
fn local_addr(&self) -> std::net::SocketAddr {
std::net::SocketAddr::from(([127, 0, 0, 1], 0))
}
fn peer_addr(&self) -> std::net::SocketAddr {
std::net::SocketAddr::from(([127, 0, 0, 1], 0))
}
fn set_read_waker(&self, _waker: ConnWaker) {}
fn set_write_waker(&self, _waker: ConnWaker) {}
fn should_pool(&self) -> bool {
false
}
}
pub struct SshConnector {
dialer: Arc<Dialer>,
}
impl SshConnector {
#[must_use]
pub fn new(host: Host) -> Self {
Self {
dialer: Arc::new(Dialer::new(host)),
}
}
}
impl Connector for SshConnector {
fn connect(
&self,
_host: &str,
_port: u16,
_timeout: Option<std::time::Duration>,
) -> std::io::Result<Connection> {
let channel = self.dialer.dial(DIAL_STDIO).map_err(|e| {
std::io::Error::new(std::io::ErrorKind::ConnectionRefused, format!("ssh dial: {e}"))
})?;
Ok(Connection::Overlay(Box::new(SshOverlay(channel))))
}
}