diff --git a/README.md b/README.md index e1e3613..19b21cb 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,9 @@ This tool bypasses port restrictions of your router using some not-very-powerful server (a cheap 1€ vserver will suffice.) +NEW: Modem support! RevPFW3 can now interact with modems using AT commands. A demo +is included for the SIM800L GSM modem. + --- ### How to download it diff --git a/src/client.rs b/src/client.rs index f237fe5..dd8ab90 100644 --- a/src/client.rs +++ b/src/client.rs @@ -67,9 +67,12 @@ fn connect(params: &ClientParams) -> Connection { } } serial.set_timeout(Duration::from_millis(600000)).unwrap(); - return Connection::new_serial(serial); + return Connection::new_serial(serial, true); } - Connection::new_tcp(TcpStream::connect((params.server_ip, params.server_port)).unwrap()) + Connection::new_tcp( + TcpStream::connect((params.server_ip, params.server_port)).unwrap(), + true, + ) } pub fn client(params: ClientParams) { @@ -94,6 +97,7 @@ pub fn client(params: ClientParams) { tcp.write_all(&[PacketType::KeepAlive.ordinal() as u8]) .unwrap(); + println!(); println!("READY!"); let mut tcp = SocketAdapter::new(tcp); @@ -163,6 +167,7 @@ pub fn client(params: ClientParams) { PacketType::NewClient => { let mut tcp = SocketAdapter::new(Connection::new_tcp( TcpStream::connect((params.dest_ip, params.dest_port)).unwrap(), + false, )); tcp.set_nonblocking(true); sockets.insert((id, id += 1).0, tcp); diff --git a/src/server.rs b/src/server.rs index a6d3d07..f1de154 100644 --- a/src/server.rs +++ b/src/server.rs @@ -42,7 +42,7 @@ pub fn server(port: u16, key: &str, sleep_delay_ms: u64) { tcpl.set_nonblocking(true).unwrap(); - let mut tcp = SocketAdapter::new(Connection::new_tcp(tcp)); + let mut tcp = SocketAdapter::new(Connection::new_tcp(tcp, false)); tcp.set_nonblocking(true); let mut sockets: HashMap = HashMap::new(); let mut id = 0; @@ -60,7 +60,7 @@ pub fn server(port: u16, key: &str, sleep_delay_ms: u64) { } if let Ok(new) = tcpl.accept() { - let mut new = SocketAdapter::new(Connection::new_tcp(new.0)); + let mut new = SocketAdapter::new(Connection::new_tcp(new.0, false)); new.set_nonblocking(true); sockets.insert((id, id += 1).0, new); tcp.write(&[PacketType::NewClient.ordinal() as u8]).unwrap(); diff --git a/src/server_connection.rs b/src/server_connection.rs index 559cdd2..f8662b0 100644 --- a/src/server_connection.rs +++ b/src/server_connection.rs @@ -1,8 +1,8 @@ use std::{ - io::{self, ErrorKind, Read, Write}, + io::{self, stdout, ErrorKind, Read, Write}, net::{Shutdown, TcpStream}, ptr::NonNull, - time::Duration, + time::{Duration, SystemTime}, }; use serial::SerialPort; @@ -10,6 +10,15 @@ use serial::SerialPort; trait ReadWrite: Write + Read + 'static {} impl ReadWrite for T where T: Write + Read + 'static {} +enum PrintStatus { + No, + Yes { + last_print: SystemTime, + bytes: u128, + last_bytes: u128, + }, +} + pub struct Connection { readwrite: Box, data: NonNull<()>, @@ -17,30 +26,13 @@ pub struct Connection { close_thunk: fn(NonNull<()>) -> io::Result<()>, is_nb: bool, is_serial: bool, + print_status: PrintStatus, } impl Write for Connection { - fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result { - self.as_write().write_vectored(bufs) - } - - fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - self.as_write().write_all(buf) - } - - fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> io::Result<()> { - self.as_write().write_fmt(fmt) - } - - fn by_ref(&mut self) -> &mut Self - where - Self: Sized, - { - self - } - fn write(&mut self, buf: &[u8]) -> io::Result { - self.as_write().write(buf) + let result = self.as_write().write(buf); + self.print_status_result(result) } fn flush(&mut self) -> io::Result<()> { @@ -50,19 +42,8 @@ impl Write for Connection { impl Read for Connection { fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.as_read().read(buf) - } - - fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { - self.as_read().read_vectored(bufs) - } - - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - self.as_read().read_to_end(buf) - } - - fn read_to_string(&mut self, buf: &mut String) -> io::Result { - self.as_read().read_to_string(buf) + let result = self.as_read().read(buf); + self.print_status_result(result) } fn read_exact(&mut self, mut buf: &mut [u8]) -> io::Result<()> { @@ -92,7 +73,7 @@ impl Read for Connection { } impl Connection { - pub fn new_tcp(stream: TcpStream) -> Self { + pub fn new_tcp(stream: TcpStream, print: bool) -> Self { let mut stream = Box::new(stream); Connection { data: NonNull::from(stream.as_mut()).cast(), @@ -105,9 +86,18 @@ impl Connection { }, is_nb: false, is_serial: false, + print_status: if print { + PrintStatus::Yes { + last_print: SystemTime::now(), + bytes: 0, + last_bytes: 0, + } + } else { + PrintStatus::No + }, } } - pub fn new_serial(serial: T) -> Self { + pub fn new_serial(serial: T, print: bool) -> Self { let mut serial = Box::new(serial); Connection { data: NonNull::from(serial.as_mut()).cast(), @@ -124,6 +114,15 @@ impl Connection { close_thunk: |_data| Ok(()), is_nb: false, is_serial: true, + print_status: if print { + PrintStatus::Yes { + last_print: SystemTime::now(), + bytes: 0, + last_bytes: 0, + } + } else { + PrintStatus::No + }, } } fn as_read(&mut self) -> &mut (dyn Read) { @@ -132,6 +131,7 @@ impl Connection { fn as_write(&mut self) -> &mut (dyn Write) { &mut self.readwrite } + #[allow(dead_code)] pub fn is_nonblocking(&self) -> bool { self.is_nb } @@ -146,4 +146,41 @@ impl Connection { pub fn is_serial(&self) -> bool { self.is_serial } + + fn print_status(&mut self, add: usize) { + if let &mut PrintStatus::Yes { + ref mut last_print, + ref mut bytes, + ref mut last_bytes, + } = &mut self.print_status + { + *bytes += add as u128; + if last_print.elapsed().unwrap().as_secs() > 0 { + let diff = *bytes - *last_bytes; + let bps = to_units(diff); + let total = to_units(*bytes); + print!("\r\x1b[KCurrent transfer speed: {bps}B/s, transferred {total}B so far."); + stdout().flush().unwrap(); + *last_bytes = *bytes; + *last_print = SystemTime::now(); + } + } + } + + fn print_status_result(&mut self, result: io::Result) -> io::Result { + if let Ok(b) = result { + self.print_status(b) + } + result + } +} + +fn to_units(diff: u128) -> String { + match diff { + x @ 1_000_000_000_000.. => ((x / 1_000_000_000) as f64 / 1000.0).to_string() + "G", + x @ 1_000_000_000.. => ((x / 1_000_000) as f64 / 1000.0).to_string() + "G", + x @ 1_000_000.. => ((x / 1_000) as f64 / 1000.0).to_string() + "M", + x @ 10_000.. => (x as f64 / 1000.0).to_string() + "K", + x => x.to_string(), + } }