async_ssh2/
listener.rs

1use crate::{channel::Channel, Error};
2use smol::{Async, Timer};
3use ssh2::{self};
4use std::{net::TcpStream, sync::Arc, time::Duration};
5
6/// See [`Listener`](ssh2::Listener).
7pub struct Listener {
8    inner: ssh2::Listener,
9    stream: Arc<Async<TcpStream>>,
10}
11
12impl Listener {
13    pub(crate) fn new(listener: ssh2::Listener, stream: Arc<Async<TcpStream>>) -> Self {
14        Self {
15            inner: listener,
16            stream,
17        }
18    }
19
20    /// See [`accept`](ssh2::Listener::accept).
21    pub async fn accept(&mut self) -> Result<Channel, Error> {
22        // The I/O object for Listener::accept is on the remote SSH server. There is no way to poll
23        // its state so the best we can do is loop and check whether we have a new connection every
24        // 10ms.
25        let channel = loop {
26            match self.inner.accept() {
27                Ok(channel) => break channel,
28                Err(e)
29                    if std::io::Error::from(ssh2::Error::from_errno(e.code())).kind()
30                        == std::io::ErrorKind::WouldBlock => {}
31                Err(e) => return Err(Error::SSH2(e)),
32            };
33
34            Timer::after(Duration::from_millis(10)).await;
35        };
36
37        Ok(Channel::new(channel, self.stream.clone()))
38    }
39}