X-Git-Url: https://code.octet-stream.net/m17rt/blobdiff_plain/e67ea96c8a3d7c23ba29c6ed91ddb451927176a1..bd5155840661f90aab8c06413fb1e9f256824b55:/m17app/src/tnc.rs?ds=sidebyside diff --git a/m17app/src/tnc.rs b/m17app/src/tnc.rs index 56cb661..e7799b4 100644 --- a/m17app/src/tnc.rs +++ b/m17app/src/tnc.rs @@ -1,60 +1,46 @@ -use std::io::{self, ErrorKind, Read, Write}; - -use m17core::tnc::SoftTnc; +use std::io::{Read, Write}; +/// A TNC that supports reading and writing M17 KISS messages. /// -pub trait Tnc: Read + Write + Sized { +/// TNCs must be cloneable to support reading and writing from different threads, +/// via a working implementation of try_clone(). We do not require `Clone` directly +/// as this could not be fulfilled by `TcpStream`. +pub trait Tnc: Read + Write + Sized + Send + 'static { + /// Return a copy of this TNC. + /// + /// `M17App` will use this to create a second instance of the supplied TNC then use + /// one of them for reading and one of them for writing, concurrently across two threads. + /// + /// Implementations do not need to worry about trying to make two simultaneous reads or + /// two simultaneous writes do something sensible. `M17App` will not do this and it would + /// probably produce garbled KISS messages anyway. fn try_clone(&mut self) -> Result; + + /// Start I/O. fn start(&mut self) -> Result<(), TncError>; + + /// Shut down I/O - it is assumed we cannot restart. fn close(&mut self) -> Result<(), TncError>; } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq, Clone)] pub enum TncError { - General(String), -} - -// TODO: move the following to its own module - -pub struct Soundmodem { - tnc: SoftTnc, - config: SoundmodemConfig, -} - -pub struct SoundmodemConfig { - // sound cards, PTT, etc. -} - -impl Read for Soundmodem { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.tnc - .read_kiss(buf) - .map_err(|s| io::Error::new(ErrorKind::Other, format!("{:?}", s))) - } + // TODO: Good error cases + Unknown, } -impl Write for Soundmodem { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - self.tnc - .write_kiss(buf) - .map_err(|s| io::Error::new(ErrorKind::Other, format!("{:?}", s))) - } - - fn flush(&mut self) -> std::io::Result<()> { - Ok(()) - } -} - -impl Tnc for Soundmodem { +impl Tnc for std::net::TcpStream { fn try_clone(&mut self) -> Result { - unimplemented!(); + std::net::TcpStream::try_clone(self).map_err(|_| TncError::Unknown) } fn start(&mut self) -> Result<(), TncError> { - unimplemented!(); + // already started, hopefully we get onto reading the socket quickly + Ok(()) } fn close(&mut self) -> Result<(), TncError> { - unimplemented!(); + self.shutdown(std::net::Shutdown::Both) + .map_err(|_| TncError::Unknown) } }