use crate::ssh::ReceiveSyncService; use crate::ssh::SshTokenService; use crate::ssh::handle::SSHandle; use db::cache::AppCache; use db::database::AppDatabase; use deadpool_redis::cluster::Pool as RedisPool; use russh::server::Handler; use slog::{Logger, info, warn}; use std::io; use std::net::SocketAddr; pub struct SSHServer { pub db: AppDatabase, pub cache: AppCache, pub redis_pool: RedisPool, pub logger: Logger, pub token_service: SshTokenService, } impl SSHServer { pub fn new( db: AppDatabase, cache: AppCache, redis_pool: RedisPool, logger: Logger, token_service: SshTokenService, ) -> Self { SSHServer { db, cache, redis_pool, logger, token_service, } } } impl russh::server::Server for SSHServer { type Handler = SSHandle; fn new_client(&mut self, addr: Option) -> Self::Handler { if let Some(addr) = addr { info!( self.logger, "New SSH connection from {}:{}", addr.ip(), addr.port() ); } else { info!(self.logger, "New SSH connection from unknown address"); } let sync_service = ReceiveSyncService::new(self.redis_pool.clone(), self.logger.clone()); SSHandle::new( self.db.clone(), self.cache.clone(), sync_service, self.logger.clone(), self.token_service.clone(), addr, ) } fn handle_session_error(&mut self, error: ::Error) { match error { russh::Error::Disconnect => { info!(self.logger, "Connection disconnected by peer"); } russh::Error::Inconsistent => { warn!(self.logger, "Protocol inconsistency detected"); } russh::Error::NotAuthenticated => { warn!(self.logger, "Authentication failed"); } russh::Error::IO(ref io_err) => { let error_msg = format!( "IO error: kind={:?}, message={}, raw_os_error={:?}", io_err.kind(), io_err, io_err.raw_os_error() ); warn!(self.logger, "{}", error_msg); if io_err.kind() == io::ErrorKind::UnexpectedEof { warn!( self.logger, "Client disconnected during handshake or before authentication" ); } } _ => { let error_msg = format!("SSH session error: {}", error); warn!(self.logger, "{}", error_msg); } } } }