1use openssh::{Session, SessionBuilder};
2use std::net::IpAddr;
3use uuid::Uuid;
4
5#[derive(Debug)]
6pub struct Peer {
7 pub id: Uuid,
8 pub ip_addr: IpAddr,
9 pub session: Option<Session>,
11 pub user: String,
12 pub keyfile: Option<String>,
13}
14
15impl Peer {
16 pub fn new(addr: IpAddr, user: Option<&str>, keyfile: Option<&str>) -> Self {
17 Self {
18 id: Uuid::new_v4(),
19 ip_addr: addr,
20 session: None,
22 user: user.unwrap_or("root").to_string(),
23 keyfile: keyfile.map(|s| s.to_string()),
24 }
25 }
26
27 pub async fn connect(&mut self) -> crate::Result<()> {
28 if self.session.is_some() {
29 return Ok(());
30 }
31 let mut session_builder = SessionBuilder::default();
32 session_builder
33 .known_hosts_check(openssh::KnownHosts::Accept)
34 .user_known_hosts_file("/dev/null")
35 .user(self.user.clone());
36
37 if let Some(keyfile) = &self.keyfile {
38 session_builder.keyfile(std::path::PathBuf::from(keyfile.to_owned()));
39 }
40 let session = session_builder.connect(self.ip_addr.to_string()).await?;
41 self.session = Some(session);
42
43 Ok(())
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 use std::env;
52
53 #[tokio::test]
54 async fn test_peer_new() {
55 let mut peer = Peer::new(
56 "192.168.1.137".parse().unwrap(),
57 Some("pi"),
58 Some(env::var("SSH_KEYFILE").unwrap().as_str()),
59 );
60 peer.connect().await.unwrap();
61 println!("{:?}", peer);
62 }
63}