#[cfg(feature = "builtin-ssh")]
pub mod builtin;
mod openssh;
use tokio::io::{AsyncRead, AsyncWrite};
#[cfg(feature = "builtin-ssh")]
pub use self::builtin::BuiltinTransport;
pub use self::openssh::OpenSshTransport;
use super::SshError;
#[derive(Debug)]
pub enum Transport {
OpenSsh(OpenSshTransport),
#[cfg(feature = "builtin-ssh")]
Builtin(BuiltinTransport),
}
impl Transport {
pub async fn exec(&self, command: &str, pipes: Pipes) -> Result<RemoteProcess, SshError> {
match self {
Self::OpenSsh(transport) => Box::pin(transport.exec(command, pipes)).await,
#[cfg(feature = "builtin-ssh")]
Self::Builtin(transport) => transport.exec(command, pipes).await,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Pipes {
pub stdin: bool,
pub stdout: bool,
pub stderr: bool,
}
pub struct RemoteProcess {
pub stdin: Option<Box<dyn AsyncWrite + Send + Unpin>>,
pub stdout: Option<Box<dyn AsyncRead + Send + Unpin>>,
pub stderr: Option<Box<dyn AsyncRead + Send + Unpin>>,
pub(crate) waiter: Waiter,
}
pub(crate) enum Waiter {
OpenSsh(Box<self::openssh::OpenSshWaiter>),
#[cfg(feature = "builtin-ssh")]
Builtin(self::builtin::BuiltinWaiter),
}
impl RemoteProcess {
pub async fn wait(mut self) -> Result<i32, SshError> {
drop(self.stdin.take());
drop(self.stdout.take());
drop(self.stderr.take());
match self.waiter {
Waiter::OpenSsh(waiter) => Box::pin((*waiter).wait()).await,
#[cfg(feature = "builtin-ssh")]
Waiter::Builtin(waiter) => waiter.wait().await,
}
}
}