From: Ian Jackson Date: Sun, 28 Mar 2021 18:43:29 +0000 (+0100) Subject: packetframe: Initial wip, buggy and not used, but but compiles X-Git-Tag: otter-0.6.0~586 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=0a06822be8087e920820e6d59cb2e0cb80ede9f5;p=otter.git packetframe: Initial wip, buggy and not used, but but compiles Signed-off-by: Ian Jackson --- diff --git a/src/lib.rs b/src/lib.rs index c9f5ecad..f4cd9207 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,6 +25,7 @@ pub mod mgmtchannel; pub mod nwtemplates; pub mod occultilks; pub mod organise; +pub mod packetframe; pub mod pcaliases; pub mod pcrender; pub mod pieces; diff --git a/src/packetframe.rs b/src/packetframe.rs new file mode 100644 index 00000000..5403c24e --- /dev/null +++ b/src/packetframe.rs @@ -0,0 +1,130 @@ +// Copyright 2020-2021 Ian Jackson and contributors to Otter +// SPDX-License-Identifier: AGPL-3.0-or-later +// There is NO WARRANTY. + +//! Frame format: +//! zero or more chunks +//! end marker +//! +//! Chunk format: +//! u16 chunk length, nonzero +//! chunk data +//! Packet end marker: +//! 0u16 marker +//! 0xffffu16 marker, error! + +use crate::prelude::*; + +const CHUNK_MAX: u16 = 65534; +const CHUNK_ERR: u16 = 65535; + +type BO = BigEndian; + +#[derive(Debug)] +struct Fuse(Result); + +#[derive(Debug)] +pub struct FrameReader { + inner: Fuse, + in_frame: Option, +} + +#[derive(Debug)] +pub struct ReadFrame<'r,R:BufRead> { + fr: Result<&'r mut FrameReader, Option>, +} + +#[derive(Debug,Copy,Clone,Error)] +#[error("error occurred at peer, during construction of frame data")] +struct SenderError; + +#[derive(Clone,Error,Debug)] +pub struct Broken { + msg: String, + kind: io::ErrorKind, +} + +impl Read for Fuse { + #[throws(io::Error)] + fn read(&mut self, buf: &mut [u8]) -> usize { + match &mut self.0 { + Err(broken) => throw!(broken.clone()), + Ok(inner) => { + let r = inner.read(buf); + if let Err(e) = &r { + self.0 = Err(Broken { + msg: e.to_string(), + kind: e.kind(), + }); + } + r? + } + } + } +} + +impl From for io::Error { + fn from(broken: Broken) -> io::Error { + io::Error::new(broken.kind, broken) + } +} +impl From for io::Error { + fn from(se: SenderError) -> io::Error { + io::Error::new(io::ErrorKind::Other, se) + } +} + +impl Display for Broken { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(&self.msg) + } +} + +impl FrameReader { + fn frame<'r>(&'r mut self) -> ReadFrame<'r,R> { ReadFrame { + fr: Ok(self), + } } + + #[throws(MgmtChannelReadError)] + pub fn read_rmp(&mut self) -> T { + let mut frame = self.frame(); + rmp_serde::decode::from_read(&mut frame) + .map_err(|e| MgmtChannelReadError::Parse(format!("{}", &e)))? + } +} + +impl<'r, R:BufRead> Read for ReadFrame<'r, R> { + #[throws(io::Error)] + fn read(&mut self, buf: &mut [u8]) -> usize { + if buf.len() == 0 { return 0 } + loop { match self.fr { + Err(None) => return 0, + Err(Some(e)) => throw!(e), + Ok(ref mut fr) => { + if fr.in_frame.is_none() || fr.in_frame == Some(0) { + match match fr.inner.read_u16::()? { + 0 => Err(None), + CHUNK_ERR => Err(Some(SenderError)), + x => Ok(x as usize), + } { + Err(done) => { + fr.in_frame = None; + self.fr = Err(done); + continue; + }, + Ok(in_chunk) => { + fr.in_frame = Some(in_chunk); + } + }; + } + let remaining = fr.in_frame.as_mut().unwrap(); + + let n = min(buf.len(), *remaining); + let r = fr.inner.read(&mut buf[0..n])?; + assert!(r <= n); + *remaining -= n; + break r; + } + } } + } +} diff --git a/src/prelude.rs b/src/prelude.rs index 829aad36..cdde169d 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -53,6 +53,7 @@ pub use std::time::{self, Duration, Instant}; pub use anyhow::{anyhow, ensure, Context}; pub use arrayvec::ArrayVec; pub use boolinator::Boolinator as _; +pub use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt}; pub use cast_trait_object::{dyn_upcast, DynCastExt}; pub use delegate::delegate; pub use derive_more::*;