use crate::client::*; use hbb_common::{ config::PeerConfig, log, message_proto::*, protobuf::Message as _, tokio::{self, sync::mpsc}, Stream, }; use std::sync::{Arc, RwLock}; #[derive(Clone)] pub struct Session { id: String, lc: Arc>, sender: mpsc::UnboundedSender, password: String, } impl Session { pub fn new(id: &str, sender: mpsc::UnboundedSender) -> Self { let mut password = "".to_owned(); if PeerConfig::load(id).password.is_empty() { password = rpassword::read_password_from_tty(Some("Enter password: ")).unwrap(); } let session = Self { id: id.to_owned(), sender, password, lc: Default::default(), }; session .lc .write() .unwrap() .initialize(id.to_owned(), false, true); session } } #[async_trait] impl Interface for Session { fn msgbox(&self, msgtype: &str, title: &str, text: &str) { if msgtype == "input-password" { self.sender .send(Data::Login((self.password.clone(), true))) .ok(); } else if msgtype == "re-input-password" { log::error!("{}: {}", title, text); let pass = rpassword::read_password_from_tty(Some("Enter password: ")).unwrap(); self.sender.send(Data::Login((pass, true))).ok(); } else if msgtype.contains("error") { log::error!("{}: {}: {}", msgtype, title, text); } else { log::info!("{}: {}: {}", msgtype, title, text); } } fn handle_login_error(&mut self, err: &str) -> bool { self.lc.write().unwrap().handle_login_error(err, self) } fn handle_peer_info(&mut self, pi: PeerInfo) { let username = self.lc.read().unwrap().get_username(&pi); self.lc.write().unwrap().handle_peer_info(username, pi); } async fn handle_hash(&mut self, hash: Hash, peer: &mut Stream) { handle_hash(self.lc.clone(), hash, self, peer).await; } async fn handle_login_from_ui(&mut self, password: String, remember: bool, peer: &mut Stream) { handle_login_from_ui(self.lc.clone(), password, remember, peer).await; } async fn handle_test_delay(&mut self, t: TestDelay, peer: &mut Stream) { handle_test_delay(t, peer).await; } } #[tokio::main(flavor = "current_thread")] pub async fn start_one_port_forward( id: String, port: i32, remote_host: String, remote_port: i32, key: String, ) { crate::common::test_rendezvous_server(); crate::common::test_nat_type(); let (sender, mut receiver) = mpsc::unbounded_channel::(); let handler = Session::new(&id, sender); handler.lc.write().unwrap().port_forward = (remote_host, remote_port); if let Err(err) = crate::port_forward::listen(handler.id.clone(), port, handler.clone(), receiver, &key).await { log::error!("Failed to listen on {}: {}", port, err); } log::info!("port forward (:{}) exit", port); }