use crate::configuration::Configuration;
use crate::error::Result;
use crate::known_host::KnownHost;
use crate::known_hosts::KnownHosts;
use crate::sftp::{SftpEntry, SftpReader, SftpWriter, list};
use ssh2::{HostKeyType, Session};
use std::net::TcpStream;
pub struct Connection {
pub config: Configuration,
pub session: Session,
pub known_hosts: KnownHosts,
}
unsafe impl Send for Connection {}
impl Connection {
pub fn new(config: &Configuration) -> Result<Self> {
let session = Self::open_session(config)?;
let known_hosts = KnownHosts::new(&session)?;
Ok(Connection {
config: config.clone(),
session,
known_hosts,
})
}
fn open_session(config: &Configuration) -> Result<Session> {
let tcp_stream = TcpStream::connect((config.hostname.as_str(), config.port))?;
let mut session = Session::new()?;
session.set_timeout(config.timeout);
session.set_compress(config.compress);
session.set_tcp_stream(tcp_stream);
session.handshake()?;
Ok(session)
}
pub fn add_known_host(&mut self, known_host: &KnownHost) -> Result<()> {
self.known_hosts.add_known_host(known_host)
}
pub fn get_remote_host_key(&self) -> Option<(String, HostKeyType)> {
self
.session
.host_key()
.map(|(key, key_type)| (base64::encode(key), key_type))
}
pub fn start(&mut self) -> Result<()> {
self.known_hosts.check_remote(
&self.session,
&self.config.hostname,
self.config.port,
self.config.trust_host,
)?;
self.authenticate()
}
fn authenticate(&self) -> Result<()> {
self
.config
.authentication
.authenticate(&self.session, &self.config.username)
}
pub fn read_over_sftp(&self, path: &str) -> Result<SftpReader> {
SftpReader::new(&self.session, path)
}
pub fn write_over_sftp(&self, path: &str) -> Result<SftpWriter> {
SftpWriter::new(&self.session, path)
}
pub fn list_over_sftp(&self, path: &str) -> Result<Vec<SftpEntry>> {
list(&self.session, path)
}
}