//! Terminal adapter around the shared client transport. //! //! All protocol work (TLS, TOFU, HELLO, auto-login) lives in //! `zagan_bet::client::transport`; this file only decides how to ask a //! terminal player about a new certificate and how to print the result. use parking_lot::Mutex; use std::error::Error; use zagan_bet::client::transport::{self, TrustPrompt}; use zagan_bet::client::ui::first_contact_lines; use zagan_bet::version::{VERSION, is_newer}; pub use zagan_bet::client::transport::TlsStream; static UNSAFE_MODE: Mutex = Mutex::new(false); pub fn set_unsafe_mode(unsafe_mode: bool) { *UNSAFE_MODE.lock() = unsafe_mode; } pub fn connect( addr: &str, conn: &rusqlite::Connection, ) -> Result<(TlsStream, Option, u64), Box> { let unsafe_mode = *UNSAFE_MODE.lock(); // The terminal has no dialog: print the first-contact notice and trust. let mut trust = |prompt: &TrustPrompt| { for line in first_contact_lines(&prompt.addr, &prompt.fingerprint) { println!("{line}"); } true }; let connected = transport::connect(addr, conn, unsafe_mode, &mut trust) .map_err(|error| Box::new(error) as Box)?; println!( "\n\rConnected to {} with ping delay: {:.1}ms (TLS)", addr, connected.elapsed.as_secs_f64() * 1000.0 ); if is_newer(&connected.latest, VERSION) { println!( "A newer version is available: {} ({})", connected.latest, connected.url ); } if let Some(user) = &connected.user { println!("Authenticated as {user}"); } if let Some(error) = &connected.auth_error { println!("Authentication failed: {error}"); } Ok((connected.stream, connected.user, connected.server_time)) }