use std::io::{BufRead, BufReader, Write, stdin, stdout}; use std::net::TcpStream; use std::time::Instant; #[cfg(windows)] mod win { use std::io; use std::os::windows::io::AsRawHandle; use winapi::um::consoleapi::GetConsoleMode; use winapi::um::consoleapi::SetConsoleMode; use winapi::um::wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING; use winapi::um::winbase::STD_OUTPUT_HANDLE; use winapi::um::processenv::GetStdHandle; use winapi::shared::minwindef::DWORD; pub fn enable_vt() -> io::Result<()> { unsafe { let h = GetStdHandle(STD_OUTPUT_HANDLE); if h.is_null() { return Err(io::Error::last_os_error()); } let mut mode: DWORD = 0; if GetConsoleMode(h, &mut mode) == 0 { return Err(io::Error::last_os_error()); } let new = mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING; if SetConsoleMode(h, new) == 0 { return Err(io::Error::last_os_error()); } Ok(()) } } } fn main() { #[cfg(windows)] win::enable_vt().unwrap(); let mut addr: Option; let mut stream: Option = None; loop { print!("Command: "); stdout().flush().unwrap(); let mut line = String::new(); stdin().read_line(&mut line).unwrap(); let line = line.trim(); if line.is_empty() { continue; } let parts: Vec<&str> = line.splitn(2, ' ').collect(); match parts[0] { "connect" => { if parts.len() < 2 { println!("Usage: connect "); continue; } addr = Some(parts[1].to_string()); match TcpStream::connect(addr.as_ref().unwrap()) { Ok(s) => { let mut ping_writer = s.try_clone().unwrap(); let mut ping_reader = BufReader::new(s.try_clone().unwrap()); let start = Instant::now(); writeln!(ping_writer, "PING").unwrap(); let mut response = String::new(); ping_reader.read_line(&mut response).unwrap(); let elapsed = start.elapsed(); println!("Connected to {} with ping delay: {:?}", addr.as_ref().unwrap(), elapsed); stream = Some(s); } Err(e) => { println!("Failed to connect: {}", e); } } } "send" => { if stream.is_none() { println!("Not connected. Use 'connect ' first."); continue; } if parts.len() < 2 { println!("Usage: send "); continue; } let msg = parts[1]; let s = stream.as_mut().unwrap(); let writer_stream = s.try_clone().unwrap(); let mut writer = writer_stream; let response_reader_stream = s.try_clone().unwrap(); let mut response_reader = BufReader::new(response_reader_stream); writeln!(writer, "{}", msg).unwrap(); let mut response = String::new(); response_reader.read_line(&mut response).unwrap(); println!("Echo: {}", response.trim()); } "quit" => break, _ => println!("Unknown command. Available: connect, send, quit"), } } }