1use embedded_io_async::{Read, Write};
2
3use sunset::*;
4
5use crate::*;
6use async_channel::{ChanIn, ChanInOut};
7use async_sunset::{AsyncSunset, ProgressHolder};
8
9pub struct SSHClient<'a> {
19 sunset: AsyncSunset<'a, sunset::Client>,
20}
21
22impl<'a> SSHClient<'a> {
23 pub fn new(inbuf: &'a mut [u8], outbuf: &'a mut [u8]) -> Self {
24 let runner = Runner::new_client(inbuf, outbuf);
25 let sunset = AsyncSunset::new(runner);
26 Self { sunset }
27 }
28
29 pub async fn run(
33 &self,
34 rsock: &mut impl Read,
35 wsock: &mut impl Write,
36 ) -> Result<()> {
37 self.sunset.run(rsock, wsock).await
38 }
39
40 pub async fn progress<'g, 'f>(
46 &'g self,
47 ph: &'f mut ProgressHolder<'g, 'a, sunset::Client>,
48 ) -> Result<CliEvent<'f, 'a>> {
49 match self.sunset.progress(ph).await? {
50 Event::Cli(x) => Ok(x),
51 Event::None => Ok(CliEvent::PollAgain),
52 Event::Progressed => Ok(CliEvent::PollAgain),
53 _ => Error::bug(),
54 }
55 }
56
57 pub async fn open_session_nopty(&self) -> Result<(ChanInOut<'_>, ChanIn<'_>)> {
58 let ch =
59 self.sunset.with_runner(|runner| runner.open_client_session()).await?;
60
61 let io_normal = self.sunset.add_channel(ch).await?;
62 let e = ChanIn::new(io_normal.clone_stderr());
63 let i = ChanInOut::new(io_normal);
64 Ok((i, e))
65 }
66
67 pub async fn open_session_pty(&self) -> Result<ChanInOut<'_>> {
68 let ch =
69 self.sunset.with_runner(|runner| runner.open_client_session()).await?;
70
71 Ok(ChanInOut::new(self.sunset.add_channel(ch).await?))
72 }
73}
74
75#[cfg(feature = "alloc")]
76impl SSHClient<'static> {
77 pub fn new_owned() -> Self {
78 let runner = Runner::<'static, _>::new_client_owned();
79 let sunset = AsyncSunset::new(runner);
80 Self { sunset }
81 }
82}
83
84#[cfg(feature = "futures-io")]
85impl SSHClient<'_> {
86 pub async fn run_futures_io(
87 &self,
88 rsock: &mut (impl futures_io::AsyncRead + Unpin),
89 wsock: &mut (impl futures_io::AsyncWrite + Unpin),
90 ) -> Result<()> {
91 let mut rsock = embedded_io_adapters::futures_03::FromFutures::new(rsock);
92 let mut wsock = embedded_io_adapters::futures_03::FromFutures::new(wsock);
93 self.sunset.run(&mut rsock, &mut wsock).await
94 }
95}
96
97#[cfg(feature = "tokio")]
98impl SSHClient<'_> {
99 pub async fn run_tokio(
100 &self,
101 rsock: &mut (impl tokio::io::AsyncRead + Unpin),
102 wsock: &mut (impl tokio::io::AsyncWrite + Unpin),
103 ) -> Result<()> {
104 let mut rsock = embedded_io_adapters::tokio_1::FromTokio::new(rsock);
105 let mut wsock = embedded_io_adapters::tokio_1::FromTokio::new(wsock);
106 self.sunset.run(&mut rsock, &mut wsock).await
107 }
108}