diff --git a/async/src/cmdline_client.rs b/async/src/cmdline_client.rs index f7d67effa6d9cb30456bd41ed5f9172d30abb857..2f1c062fcfb3271d53b2afe45273e0b7de907164 100644 --- a/async/src/cmdline_client.rs +++ b/async/src/cmdline_client.rs @@ -35,11 +35,11 @@ enum CmdlineState<'a> { PreAuth, Authed, Opening { - io: ChanInOut<'a, CmdlineHooks<'a>, UnusedServ>, - extin: Option<ChanIn<'a, CmdlineHooks<'a>, UnusedServ>>, + io: ChanInOut<'a>, + extin: Option<ChanIn<'a>>, }, Ready { - io: ChanInOut<'a, CmdlineHooks<'a>, UnusedServ>, + io: ChanInOut<'a>, }, } @@ -184,8 +184,8 @@ impl<'a> CmdlineRunner<'a> { } } - async fn chan_run(io: ChanInOut<'a, CmdlineHooks<'a>, UnusedServ>, - io_err: Option<ChanIn<'a, CmdlineHooks<'a>, UnusedServ>>, + async fn chan_run(io: ChanInOut<'a>, + io_err: Option<ChanIn<'a>>, pty_guard: Option<RawPtyGuard>) -> Result<()> { // out let fo = async { @@ -318,7 +318,7 @@ impl<'a> CmdlineRunner<'a> { /// /// Performs authentication, requests a shell or command, performs channel IO. /// Will return `Ok` after the session ends normally, or an error. - pub async fn run(&mut self, cli: &'a SSHClient<'a, CmdlineHooks<'a>>) -> Result<()> { + pub async fn run(&mut self, cli: &'a SSHClient<'a>) -> Result<()> { // chanio is only set once a channel is opened below let chanio = Fuse::terminated(); pin_mut!(chanio); @@ -385,7 +385,7 @@ impl<'a> CmdlineRunner<'a> { Ok(()) } - async fn open_session(&mut self, cli: &'a SSHClient<'a, CmdlineHooks<'a>>) -> Result<()> { + async fn open_session(&mut self, cli: &'a SSHClient<'a>) -> Result<()> { debug_assert!(matches!(self.state, CmdlineState::Authed)); let (io, extin) = if self.want_pty { diff --git a/embassy/demos/common/src/server.rs b/embassy/demos/common/src/server.rs index 3cd858f443fe411691875c60379da9c9117373a0..f6160bbabda1816755369bf5daff40b4d8e07d76 100644 --- a/embassy/demos/common/src/server.rs +++ b/embassy/demos/common/src/server.rs @@ -228,7 +228,7 @@ pub trait DemoServer { /// A task to run for each incoming connection. // TODO: eventually the compiler should add must_use automatically? #[must_use] - async fn run<'f, S: ServBehaviour>(&self, serv: &'f SSHServer<'f, S>) -> Result<()>; + async fn run<'f>(&self, serv: &'f SSHServer<'f>) -> Result<()>; } diff --git a/embassy/demos/picow/src/main.rs b/embassy/demos/picow/src/main.rs index 7ce795becd799e2161776de1d7116c8cc2db2377..e83ba6af575bc9e55636dd8fe8ff63225b94e70d 100644 --- a/embassy/demos/picow/src/main.rs +++ b/embassy/demos/picow/src/main.rs @@ -323,9 +323,9 @@ impl DemoServer for PicoServer { *u = username.try_into().unwrap_or(String::new()); } - async fn run<'f, S: ServBehaviour>( + async fn run<'f>( &self, - serv: &'f SSHServer<'f, S>, + serv: &'f SSHServer<'f>, ) -> Result<()> { let session = async { // wait for a shell to start diff --git a/embassy/demos/std/src/main.rs b/embassy/demos/std/src/main.rs index 8188b1a499bc2ede460f65972c327b08aefc5fe3..e0c62cc288816d5a835f23961f22eea5da862d01 100644 --- a/embassy/demos/std/src/main.rs +++ b/embassy/demos/std/src/main.rs @@ -88,7 +88,7 @@ impl DemoServer for StdDemo { self.notify.signal(handle); } - async fn run<'f, S: ServBehaviour>(&self, serv: &'f SSHServer<'f, S>) -> Result<()> + async fn run<'f>(&self, serv: &'f SSHServer<'f>) -> Result<()> { let session = async { // wait for a shell to start diff --git a/embassy/src/client.rs b/embassy/src/client.rs index ca7c77ae2f9a3aa0d06bfe5027c7a66ce1f09e7a..91e85d15efe30adebc8ad3a82dceb87b306ff934 100644 --- a/embassy/src/client.rs +++ b/embassy/src/client.rs @@ -10,13 +10,21 @@ use sunset::ChanData; use embassy_sunset::EmbassySunset; use embassy_channel::{ChanInOut, ChanIn}; -pub struct SSHClient<'a, C: CliBehaviour> { - sunset: EmbassySunset<'a, C, UnusedServ>, +/// An async SSH client instance +/// +/// The [`run()`][Self::run] method runs the session to completion, with application behaviour +/// defined by the [`CliBehaviour`] instance. +/// +/// Once authentication has completed ([`authenticated()`][CliBehaviour] is called), the application +/// may open remote channels with [`open_session_pty()`][Self::open_session_pty] etc. +/// +/// This is async executor agnostic, though requires the `CliBehaviour` instance +/// to be wrapped in an Embassy [`Mutex`]. +pub struct SSHClient<'a> { + sunset: EmbassySunset<'a>, } -type S = UnusedServ; - -impl<'a, C: CliBehaviour> SSHClient<'a, C> { +impl<'a> SSHClient<'a> { pub fn new(inbuf: &'a mut [u8], outbuf: &'a mut [u8], ) -> Result<Self> { let runner = Runner::new_client(inbuf, outbuf)?; @@ -24,12 +32,12 @@ impl<'a, C: CliBehaviour> SSHClient<'a, C> { Ok(Self { sunset }) } - pub async fn run<B: ?Sized, M: RawMutex>(&self, + pub async fn run<B: ?Sized, M: RawMutex, C: CliBehaviour>(&self, rsock: &mut impl Read, wsock: &mut impl Write, b: &Mutex<M, B>) -> Result<()> where - for<'f> Behaviour<'f, C, S>: From<&'f mut B> + for<'f> Behaviour<'f, C, UnusedServ>: From<&'f mut B> { self.sunset.run(rsock, wsock, b).await } @@ -39,7 +47,7 @@ impl<'a, C: CliBehaviour> SSHClient<'a, C> { } pub async fn open_session_nopty(&'a self) - -> Result<(ChanInOut<'a, C, S>, ChanIn<'a, C, S>)> { + -> Result<(ChanInOut<'a>, ChanIn<'a>)> { let chan = self.sunset.with_runner(|runner| { runner.open_client_session() }).await?; @@ -52,7 +60,7 @@ impl<'a, C: CliBehaviour> SSHClient<'a, C> { Ok((cstd, cerr)) } - pub async fn open_session_pty(&'a self) -> Result<ChanInOut<'a, C, S>> { + pub async fn open_session_pty(&'a self) -> Result<ChanInOut<'a>> { let chan = self.sunset.with_runner(|runner| { runner.open_client_session() }).await?; diff --git a/embassy/src/embassy_channel.rs b/embassy/src/embassy_channel.rs index a9e3b83e242cbea85e9d1ffd5c91da48625005f4..33b0cce060f5c1dd2b698540af8d3a887ff98e08 100644 --- a/embassy/src/embassy_channel.rs +++ b/embassy/src/embassy_channel.rs @@ -9,16 +9,16 @@ use embedded_io_async::{Read, Write, ErrorType}; use crate::*; use embassy_sunset::EmbassySunset; -use sunset::{Result, ChanData, ChanNum, CliBehaviour, ServBehaviour}; +use sunset::{Result, ChanData, ChanNum}; /// Common implementation -struct ChanIO<'a, C: CliBehaviour, S: ServBehaviour> { +struct ChanIO<'a> { num: ChanNum, dt: ChanData, - sunset: &'a EmbassySunset<'a, C, S>, + sunset: &'a EmbassySunset<'a>, } -impl<C: CliBehaviour, S: ServBehaviour> core::fmt::Debug for ChanIO<'_, C, S> { +impl core::fmt::Debug for ChanIO<'_> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("ChanIO") .field("num", &self.num) @@ -27,19 +27,19 @@ impl<C: CliBehaviour, S: ServBehaviour> core::fmt::Debug for ChanIO<'_, C, S> { } } -impl<C: CliBehaviour, S: ServBehaviour> ChanIO<'_, C, S> { +impl ChanIO<'_> { pub async fn until_closed(&self) -> Result<()> { self.sunset.until_channel_closed(self.num).await } } -impl<C: CliBehaviour, S: ServBehaviour> Drop for ChanIO<'_, C, S> { +impl Drop for ChanIO<'_> { fn drop(&mut self) { self.sunset.dec_chan(self.num) } } -impl<C: CliBehaviour, S: ServBehaviour> Clone for ChanIO<'_, C, S> { +impl Clone for ChanIO<'_> { fn clone(&self) -> Self { self.sunset.inc_chan(self.num); Self { @@ -50,17 +50,17 @@ impl<C: CliBehaviour, S: ServBehaviour> Clone for ChanIO<'_, C, S> { } } -impl<C: CliBehaviour, S: ServBehaviour> ErrorType for ChanIO<'_, C, S> { +impl ErrorType for ChanIO<'_> { type Error = sunset::Error; } -impl<'a, C: CliBehaviour, S: ServBehaviour> Read for ChanIO<'a, C, S> { +impl<'a> Read for ChanIO<'a> { async fn read(&mut self, buf: &mut [u8]) -> Result<usize, sunset::Error> { self.sunset.read_channel(self.num, self.dt, buf).await } } -impl<'a, C: CliBehaviour, S: ServBehaviour> Write for ChanIO<'a, C, S> { +impl<'a> Write for ChanIO<'a> { async fn write(&mut self, buf: &[u8]) -> Result<usize, sunset::Error> { self.sunset.write_channel(self.num, self.dt, buf).await } @@ -74,37 +74,37 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> Write for ChanIO<'a, C, S> { /// A standard bidirectional SSH channel #[derive(Debug)] -pub struct ChanInOut<'a, C: CliBehaviour, S: ServBehaviour>(ChanIO<'a, C, S>); +pub struct ChanInOut<'a>(ChanIO<'a>); /// An input-only SSH channel, such as stderr for a client #[derive(Debug)] -pub struct ChanIn<'a, C: CliBehaviour, S: ServBehaviour>(ChanIO<'a, C, S>); +pub struct ChanIn<'a>(ChanIO<'a>); #[derive(Debug)] /// An output-only SSH channel, such as stderr for a server -pub struct ChanOut<'a, C: CliBehaviour, S: ServBehaviour>(ChanIO<'a, C, S>); +pub struct ChanOut<'a>(ChanIO<'a>); // derive(Clone) adds unwanted `: Clone` bounds on C and S, so we implement manually // https://github.com/rust-lang/rust/issues/26925 -impl<'a, C: CliBehaviour, S: ServBehaviour> Clone for ChanInOut<'a, C, S> { +impl<'a> Clone for ChanInOut<'a> { fn clone(&self) -> Self { Self(self.0.clone()) } } -impl<'a, C: CliBehaviour, S: ServBehaviour> Clone for ChanIn<'a, C, S> { +impl<'a> Clone for ChanIn<'a> { fn clone(&self) -> Self { Self(self.0.clone()) } } -impl<'a, C: CliBehaviour, S: ServBehaviour> Clone for ChanOut<'a, C, S> { +impl<'a> Clone for ChanOut<'a> { fn clone(&self) -> Self { Self(self.0.clone()) } } -impl<'a, C: CliBehaviour, S: ServBehaviour> ChanInOut<'a, C, S> { +impl<'a> ChanInOut<'a> { // caller must have already incremented the refcount - pub(crate) fn new(num: ChanNum, dt: ChanData, sunset: &'a EmbassySunset<'a, C, S>) -> Self { + pub(crate) fn new(num: ChanNum, dt: ChanData, sunset: &'a EmbassySunset<'a>) -> Self { Self(ChanIO { num, dt, sunset, }) @@ -123,18 +123,18 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> ChanInOut<'a, C, S> { } } -impl<'a, C: CliBehaviour, S: ServBehaviour> ChanIn<'a, C, S> { +impl<'a> ChanIn<'a> { // caller must have already incremented the refcount - pub(crate) fn new(num: ChanNum, dt: ChanData, sunset: &'a EmbassySunset<'a, C, S>) -> Self { + pub(crate) fn new(num: ChanNum, dt: ChanData, sunset: &'a EmbassySunset<'a>) -> Self { Self(ChanIO { num, dt, sunset, }) } } -impl<'a, C: CliBehaviour, S: ServBehaviour> ChanOut<'a, C, S> { +impl<'a> ChanOut<'a> { // caller must have already incremented the refcount - pub(crate) fn new(num: ChanNum, dt: ChanData, sunset: &'a EmbassySunset<'a, C, S>) -> Self { + pub(crate) fn new(num: ChanNum, dt: ChanData, sunset: &'a EmbassySunset<'a>) -> Self { Self(ChanIO { num, dt, sunset, }) @@ -146,37 +146,37 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> ChanOut<'a, C, S> { } } -impl<C: CliBehaviour, S: ServBehaviour> ErrorType for ChanInOut<'_, C, S> { +impl ErrorType for ChanInOut<'_> { type Error = sunset::Error; } -impl<C: CliBehaviour, S: ServBehaviour> ErrorType for ChanIn<'_, C, S> { +impl ErrorType for ChanIn<'_> { type Error = sunset::Error; } -impl<C: CliBehaviour, S: ServBehaviour> ErrorType for ChanOut<'_, C, S> { +impl ErrorType for ChanOut<'_> { type Error = sunset::Error; } -impl<'a, C: CliBehaviour, S: ServBehaviour> Read for ChanInOut<'a, C, S> { +impl<'a> Read for ChanInOut<'a> { async fn read(&mut self, buf: &mut [u8]) -> Result<usize, sunset::Error> { self.0.read(buf).await } } -impl<'a, C: CliBehaviour, S: ServBehaviour> Write for ChanInOut<'a, C, S> { +impl<'a> Write for ChanInOut<'a> { async fn write(&mut self, buf: &[u8]) -> Result<usize, sunset::Error> { self.0.write(buf).await } } -impl<'a, C: CliBehaviour, S: ServBehaviour> Read for ChanIn<'a, C, S> { +impl<'a> Read for ChanIn<'a> { async fn read(&mut self, buf: &mut [u8]) -> Result<usize, sunset::Error> { self.0.read(buf).await } } -impl<'a, C: CliBehaviour, S: ServBehaviour> Write for ChanOut<'a, C, S> { +impl<'a> Write for ChanOut<'a> { async fn write(&mut self, buf: &[u8]) -> Result<usize, sunset::Error> { self.0.write(buf).await } diff --git a/embassy/src/embassy_sunset.rs b/embassy/src/embassy_sunset.rs index f06dce788001e845f8971691ad53ba82655d604b..51e55cf055b58ed7b9a6f2c012033fac45d9bcc2 100644 --- a/embassy/src/embassy_sunset.rs +++ b/embassy/src/embassy_sunset.rs @@ -49,8 +49,8 @@ struct Wakers { chan_close: [WakerRegistration; MAX_CHANNELS], } -struct Inner<'a, C: CliBehaviour, S: ServBehaviour> { - runner: Runner<'a, C, S>, +struct Inner<'a> { + runner: Runner<'a>, wakers: Wakers, @@ -59,11 +59,11 @@ struct Inner<'a, C: CliBehaviour, S: ServBehaviour> { chan_handles: [Option<ChanHandle>; MAX_CHANNELS], } -impl<'a, C: CliBehaviour, S: ServBehaviour> Inner<'a, C, S> { +impl<'a> Inner<'a> { /// Helper to lookup the corresponding ChanHandle /// /// Returns split references that will be required by many callers - fn fetch(&mut self, num: ChanNum) -> Result<(&mut Runner<'a, C, S>, &ChanHandle, &mut Wakers)> { + fn fetch(&mut self, num: ChanNum) -> Result<(&mut Runner<'a>, &ChanHandle, &mut Wakers)> { self.chan_handles[num.0 as usize].as_ref().map(|ch| { (&mut self.runner, ch, &mut self.wakers) }) @@ -71,14 +71,14 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> Inner<'a, C, S> { } } -/// Provides an async wrapper for sunset core +/// Provides an async wrapper for Sunset core /// -/// A `ChanHandle` provided by sunset core must be added with `add_channel()` before +/// A [`ChanHandle`] provided by sunset core must be added with [`add_channel()`] before /// a method can be called with the equivalent ChanNum. /// /// Applications use `embassy_sunset::{Client,Server}`. -pub(crate) struct EmbassySunset<'a, C: CliBehaviour, S: ServBehaviour> { - inner: Mutex<SunsetRawMutex, Inner<'a, C, S>>, +pub(crate) struct EmbassySunset<'a> { + inner: Mutex<SunsetRawMutex, Inner<'a>>, progress_notify: Signal<SunsetRawMutex, ()>, @@ -94,8 +94,8 @@ pub(crate) struct EmbassySunset<'a, C: CliBehaviour, S: ServBehaviour> { chan_refcounts: [AtomicUsize; MAX_CHANNELS], } -impl<'a, C: CliBehaviour, S: ServBehaviour> EmbassySunset<'a, C, S> { - pub fn new(runner: Runner<'a, C, S>) -> Self { +impl<'a> EmbassySunset<'a> { + pub fn new(runner: Runner<'a>) -> Self { let wakers = Wakers { chan_read: Default::default(), chan_write: Default::default(), @@ -120,7 +120,7 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> EmbassySunset<'a, C, S> { } } - pub async fn run<B: ?Sized, M: RawMutex>(&self, + pub async fn run<B: ?Sized, M: RawMutex, C: CliBehaviour, S: ServBehaviour>(&self, rsock: &mut impl Read, wsock: &mut impl Write, b: &Mutex<M, B>) -> Result<()> @@ -224,7 +224,7 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> EmbassySunset<'a, C, S> { self.wake_progress() } - fn wake_channels(&self, inner: &mut Inner<C, S>) -> Result<()> { + fn wake_channels(&self, inner: &mut Inner) -> Result<()> { // Read wakers let w = &mut inner.wakers; if let Some((num, dt, _len)) = inner.runner.ready_channel_input() { @@ -278,7 +278,7 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> EmbassySunset<'a, C, S> { /// without "async Drop" it isn't possible to take the `inner` lock during /// `drop()`. /// Instead this runs periodically from an async context to release channels. - fn clear_refcounts(&self, inner: &mut Inner<C, S>) -> Result<()> { + fn clear_refcounts(&self, inner: &mut Inner) -> Result<()> { for (ch, count) in inner.chan_handles.iter_mut().zip(self.chan_refcounts.iter()) { let count = count.load(Relaxed); if count > 0 { @@ -294,7 +294,7 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> EmbassySunset<'a, C, S> { } /// Returns ControlFlow::Break on session exit. - async fn progress<B: ?Sized, M: RawMutex>(&self, + async fn progress<B: ?Sized, M: RawMutex, C: CliBehaviour, S: ServBehaviour>(&self, b: &Mutex<M, B>) -> Result<ControlFlow<()>> where @@ -342,14 +342,14 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> EmbassySunset<'a, C, S> { } pub(crate) async fn with_runner<F, R>(&self, f: F) -> R - where F: FnOnce(&mut Runner<C, S>) -> R { + where F: FnOnce(&mut Runner) -> R { let mut inner = self.inner.lock().await; f(&mut inner.runner) } /// helper to perform a function on the `inner`, returning a `Poll` value async fn poll_inner<F, T>(&self, mut f: F) -> T - where F: FnMut(&mut Inner<C, S>, &mut Context) -> Poll<T> { + where F: FnMut(&mut Inner, &mut Context) -> Poll<T> { poll_fn(|cx| { // Attempt to lock .inner let i = self.inner.lock(); diff --git a/embassy/src/server.rs b/embassy/src/server.rs index 5d0e1ae9a82172cfd5aa4594502a3fff0c0f886f..88b1dc32658313bc71970278f963325d2b69bbd7 100644 --- a/embassy/src/server.rs +++ b/embassy/src/server.rs @@ -8,13 +8,21 @@ use sunset::behaviour::UnusedCli; use crate::*; use embassy_sunset::EmbassySunset; -pub struct SSHServer<'a, S: ServBehaviour> { - sunset: EmbassySunset<'a, UnusedCli, S>, +/// An async SSH server instance +/// +/// The [`run()`][Self::run] method runs the session to completion, with application behaviour +/// defined by the [`ServBehaviour`] instance. +/// +/// Once the client has opened sessions, those can be retrieved with [`stdio()`][Self::stdio] +/// and [`stdio_stderr()`][Self::stdio_stderr] methods. +/// +/// This is async executor agnostic, though requires the `ServBehaviour` instance +/// to be wrapped in an Embassy [`Mutex`]. +pub struct SSHServer<'a> { + sunset: EmbassySunset<'a>, } -type C = UnusedCli; - -impl<'a, S: ServBehaviour> SSHServer<'a, S> { +impl<'a> SSHServer<'a> { // May return an error if RNG fails pub fn new(inbuf: &'a mut [u8], outbuf: &'a mut [u8], ) -> Result<Self> { @@ -23,7 +31,7 @@ impl<'a, S: ServBehaviour> SSHServer<'a, S> { Ok(Self { sunset }) } - pub async fn run<B: ?Sized, M: RawMutex>(&self, + pub async fn run<B: ?Sized, M: RawMutex, S: ServBehaviour>(&self, rsock: &mut impl Read, wsock: &mut impl Write, b: &Mutex<M, B>) -> Result<()> @@ -39,14 +47,20 @@ impl<'a, S: ServBehaviour> SSHServer<'a, S> { /// data type. /// `ch` is the [`ChanHandle`] passed to the application's `Behaviour` /// methods. - pub async fn stdio(&'a self, ch: ChanHandle) -> Result<ChanInOut<'a, C, S>> { + pub async fn stdio(&'a self, ch: ChanHandle) -> Result<ChanInOut<'a>> { let num = ch.num(); self.sunset.add_channel(ch, 1).await?; Ok(ChanInOut::new(num, ChanData::Normal, &self.sunset)) } + /// Retrieve the stdin/stdout/stderr streams. + /// + /// If stderr is not required, use [`stdio()`][Self::stdio] instead to avoid needing to poll + /// the returned stderr. + /// The session will block until the streams are drained (they use the session buffer), + /// so they must be drained if used. pub async fn stdio_stderr(&'a self, ch: ChanHandle) - -> Result<(ChanInOut<'a, C, S>, ChanOut<'a, C, S>)> { + -> Result<(ChanInOut<'a>, ChanOut<'a>)> { let num = ch.num(); self.sunset.add_channel(ch, 2).await?; let i = ChanInOut::new(num, ChanData::Normal, &self.sunset); diff --git a/src/channel.rs b/src/channel.rs index fd6e5f38f90f6157be09a593d62ef992b80b1e42..2dff752c799f8b8f953e61ac4e5fe1d9d439b4d2 100644 --- a/src/channel.rs +++ b/src/channel.rs @@ -22,16 +22,14 @@ use runner::ChanHandle; use snafu::ErrorCompat; -pub(crate) struct Channels<C: CliBehaviour, S: ServBehaviour> { +pub(crate) struct Channels { ch: [Option<Channel>; config::MAX_CHANNELS], - _ph: (PhantomData<C>, PhantomData<S>), } -impl<C: CliBehaviour, S: ServBehaviour> Channels<C, S> { +impl Channels { pub fn new() -> Self { Channels { ch: Default::default(), - _ph: Default::default() } } @@ -219,7 +217,7 @@ impl<C: CliBehaviour, S: ServBehaviour> Channels<C, S> { } } - fn dispatch_open( + fn dispatch_open<C: CliBehaviour, S: ServBehaviour>( &mut self, p: &ChannelOpen<'_>, s: &mut TrafSend, @@ -241,7 +239,7 @@ impl<C: CliBehaviour, S: ServBehaviour> Channels<C, S> { } // the caller will send failure messages if required - fn dispatch_open_inner( + fn dispatch_open_inner<C: CliBehaviour, S: ServBehaviour>( &mut self, p: &ChannelOpen<'_>, s: &mut TrafSend, @@ -304,7 +302,7 @@ impl<C: CliBehaviour, S: ServBehaviour> Channels<C, S> { } // Some returned errors will be caught by caller and returned as SSH messages - async fn dispatch_inner( + async fn dispatch_inner<C: CliBehaviour, S: ServBehaviour>( &mut self, packet: Packet<'_>, is_client: bool, @@ -417,7 +415,7 @@ impl<C: CliBehaviour, S: ServBehaviour> Channels<C, S> { /// Incoming packet handling // TODO: protocol errors etc should perhaps be less fatal, // ssh implementations are usually imperfect. - pub async fn dispatch( + pub async fn dispatch<C: CliBehaviour, S: ServBehaviour>( &mut self, packet: Packet<'_>, is_client: bool, diff --git a/src/conn.rs b/src/conn.rs index 2e193f70a3053bc90d49be561291c4b19e0ce4cb..16bd39c672dbdf1a048416eaf30886fbe88fcc5e 100644 --- a/src/conn.rs +++ b/src/conn.rs @@ -23,7 +23,7 @@ use config::MAX_CHANNELS; use kex::{Kex, SessId, AlgoConfig}; /// The core state of a SSH instance. -pub(crate) struct Conn<C: CliBehaviour, S: ServBehaviour> { +pub(crate) struct Conn { state: ConnState, // State of any current Key Exchange @@ -42,7 +42,7 @@ pub(crate) struct Conn<C: CliBehaviour, S: ServBehaviour> { // 256 bytes -> 112 bytes pub(crate) remote_version: ident::RemoteVersion, - pub(crate) channels: Channels<C, S>, + pub(crate) channels: Channels, } // TODO: what tricks can we do to optimise away client or server code if we only @@ -84,7 +84,7 @@ pub(crate) struct Dispatched { pub disconnect: bool, } -impl<C: CliBehaviour, S: ServBehaviour> Conn<C, S> { +impl Conn { pub fn new_client() -> Result<Self> { let algo_conf = AlgoConfig::new(true); Self::new(ClientServer::Client(client::Client::new()), algo_conf) @@ -114,7 +114,7 @@ impl<C: CliBehaviour, S: ServBehaviour> Conn<C, S> { /// Updates `ConnState` and sends any packets required to progress the connection state. // TODO can this just move to the bottom of handle_payload(), and make module-private? - pub(crate) async fn progress( + pub(crate) async fn progress<C: CliBehaviour, S: ServBehaviour>( &mut self, s: &mut TrafSend<'_, '_>, b: &mut Behaviour<'_, C, S>, @@ -166,7 +166,7 @@ impl<C: CliBehaviour, S: ServBehaviour> Conn<C, S> { /// Consumes an input payload which is a view into [`traffic::Traffic::rxbuf`]. /// We queue response packets that can be sent (written into the same buffer) /// after `handle_payload()` runs. - pub(crate) async fn handle_payload( + pub(crate) async fn handle_payload<C: CliBehaviour, S: ServBehaviour>( &mut self, payload: &[u8], seq: u32, s: &mut TrafSend<'_, '_>, b: &mut Behaviour<'_, C, S>, @@ -255,7 +255,7 @@ impl<C: CliBehaviour, S: ServBehaviour> Conn<C, S> { self.sess_id.is_none() } - async fn dispatch_packet( + async fn dispatch_packet<C: CliBehaviour, S: ServBehaviour>( &mut self, packet: Packet<'_>, s: &mut TrafSend<'_, '_>, b: &mut Behaviour<'_, C, S>, ) -> Result<Dispatched, Error> { // TODO: perhaps could consolidate packet client vs server checks diff --git a/src/runner.rs b/src/runner.rs index b74031c5a635d29138ae278246fb1a3ae849ec61..1bcde5bc7521fa78ec68b384c35548ef7ba7646e 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -26,8 +26,8 @@ use conn::{Conn, Dispatched}; /// /// An application provides network or channel data to `Runner` method calls, /// and provides customisation callbacks via `CliBehaviour` or `ServBehaviour`. -pub struct Runner<'a, C: CliBehaviour, S: ServBehaviour> { - conn: Conn<C, S>, +pub struct Runner<'a> { + conn: Conn, /// Binary packet handling from the network buffer traf_in: TrafIn<'a>, @@ -45,7 +45,7 @@ pub struct Runner<'a, C: CliBehaviour, S: ServBehaviour> { closed: bool, } -impl<C: CliBehaviour, S: ServBehaviour> core::fmt::Debug for Runner<'_, C, S> { +impl core::fmt::Debug for Runner<'_> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("Runner") .field("keys", &self.keys) @@ -61,12 +61,12 @@ pub struct Progress { pub disconnected: bool, } -impl<'a, C: CliBehaviour> Runner<'a, C, UnusedServ> { - /// `inbuf` must be sized to fit the largest SSH packet allowed. +impl<'a> Runner<'a> { + /// `inbuf` and `outbuf` must be sized to fit the largest SSH packet allowed. pub fn new_client( inbuf: &'a mut [u8], outbuf: &'a mut [u8], - ) -> Result<Runner<'a, C, UnusedServ>, Error> { + ) -> Result<Runner<'a>, Error> { let conn = Conn::new_client()?; let runner = Runner { conn, @@ -80,14 +80,12 @@ impl<'a, C: CliBehaviour> Runner<'a, C, UnusedServ> { Ok(runner) } -} - -impl<'a, S: ServBehaviour> Runner<'a, UnusedCli, S> { + /// `inbuf` and `outbuf` must be sized to fit the largest SSH packet allowed. pub fn new_server( inbuf: &'a mut [u8], outbuf: &'a mut [u8], - ) -> Result<Runner<'a, UnusedCli, S>, Error> { + ) -> Result<Runner<'a>, Error> { let conn = Conn::new_server()?; let runner = Runner { conn, @@ -101,9 +99,6 @@ impl<'a, S: ServBehaviour> Runner<'a, UnusedCli, S> { Ok(runner) } -} - -impl<'a, C: CliBehaviour, S: ServBehaviour> Runner<'a, C, S> { pub fn is_client(&self) -> bool { self.conn.is_client() } @@ -121,7 +116,7 @@ impl<'a, C: CliBehaviour, S: ServBehaviour> Runner<'a, C, S> { /// /// Returns `Ok(true)` if an input packet was handled, `Ok(false)` if no packet was ready /// (Can also return various errors) - pub async fn progress(&mut self, behaviour: &mut Behaviour<'_, C, S>) + pub async fn progress<C: CliBehaviour, S: ServBehaviour>(&mut self, behaviour: &mut Behaviour<'_, C, S>) -> Result<Progress> { let mut prog = Progress::default();