ssh_ui/
lib.rs

1pub(crate) mod ssh;
2
3#[macro_use]
4extern crate lazy_static;
5
6use std::{
7    error::Error,
8    sync::{mpsc::Sender, Arc},
9};
10
11use cursive::View;
12
13pub use cursive;
14pub use russh_keys;
15
16use russh_keys::key::{KeyPair, PublicKey};
17use ssh::{plugin::set_plugin, server::Server, session_manager::SessionManager};
18use tokio::sync::{mpsc, watch};
19
20#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
21pub struct SessionHandle(u64);
22
23pub trait AppSession {
24    /// Called when the session starts. Returns a cursive view that will be displayed to the user.
25    fn on_start(
26        &mut self,
27        siv: &mut cursive::Cursive,
28        session_handle: SessionHandle,
29        pub_key: Option<PublicKey>,
30        force_refresh_sender: Sender<()>,
31    ) -> Result<Box<dyn View>, Box<dyn Error>>;
32
33    /// Called when the session ticks.
34    fn on_tick(&mut self, _siv: &mut cursive::Cursive) -> Result<(), Box<dyn Error>> {
35        Ok(())
36    }
37}
38
39/// A plugin that lets you integrate with the ssh_ui system.
40pub trait App: Send + Sync {
41    /// Called when the plugin is loaded.
42    fn on_load(&mut self) -> Result<(), Box<dyn Error>>;
43    /// Called to request a new session.
44    fn new_session(&self) -> Box<dyn AppSession>;
45}
46
47/// Server that handles incoming ssh connections.
48pub struct AppServer {
49    port: u16,
50}
51
52impl AppServer {
53    /// Creates a new server with the specified port.
54    pub fn new_with_port(port: u16) -> Self {
55        Self { port }
56    }
57
58    /// Listens on the specified port for new ssh connections indefinitely.
59    pub async fn run(
60        &mut self,
61        key_pairs: &[KeyPair],
62        plugin: Arc<dyn App>,
63    ) -> Result<(), Box<dyn Error>> {
64        set_plugin(plugin);
65        let (sender, receiver) = mpsc::channel(100);
66        let (_tx, rx) = watch::channel(false);
67        let repo = SessionManager::new(sender.clone(), receiver);
68        let sh = Server::new(key_pairs, rx, sender, self.port).await;
69        sh.listen(repo).await.unwrap();
70
71        Ok(())
72    }
73}