Skip to content

Commit d746cef

Browse files
committed
feat!: Add a hook-trigger to the handler.
This is useful if you need to update the handler without relying on a mutex (or similar synchronization).
1 parent d3ae702 commit d746cef

16 files changed

Lines changed: 83 additions & 0 deletions

russh/examples/echoserver.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ impl server::Server for Server {
7676

7777
impl server::Handler for Server {
7878
type Error = russh::Error;
79+
type Data = ();
7980

8081
async fn channel_open_session(
8182
&mut self,

russh/examples/ratatui_app.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ impl Server for AppServer {
143143

144144
impl Handler for AppServer {
145145
type Error = anyhow::Error;
146+
type Data = ();
146147

147148
async fn channel_open_session(
148149
&mut self,

russh/examples/ratatui_shared_app.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ impl Server for AppServer {
145145

146146
impl Handler for AppServer {
147147
type Error = anyhow::Error;
148+
type Data = ();
148149

149150
async fn channel_open_session(
150151
&mut self,

russh/examples/sftp_server.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ impl SshSession {
4141

4242
impl russh::server::Handler for SshSession {
4343
type Error = anyhow::Error;
44+
type Data = ();
4445

4546
async fn auth_password(&mut self, user: &str, password: &str) -> Result<Auth, Self::Error> {
4647
info!("credentials: {user}, {password}");

russh/examples/test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ impl server::Server for Server {
4747

4848
impl server::Handler for Server {
4949
type Error = anyhow::Error;
50+
type Data = ();
5051

5152
async fn channel_open_session(
5253
&mut self,

russh/src/client/test.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ mod tests {
3434

3535
impl ServerHandler for TestServer {
3636
type Error = Error;
37+
type Data = ();
3738

3839
async fn channel_open_session(
3940
&mut self,

russh/src/server/mod.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ impl Auth {
214214
#[cfg_attr(feature = "async-trait", async_trait::async_trait)]
215215
pub trait Handler: Sized {
216216
type Error: From<crate::Error> + Send;
217+
type Data: Send;
217218

218219
/// Check authentication using the "none" method.
219220
///
@@ -849,6 +850,58 @@ pub trait Handler: Sized {
849850
Ok(Some(best_group.clone()))
850851
}
851852
}
853+
854+
/// Called when the handler needs to be updated.
855+
/// ['trigger'] should be used with ['process']
856+
///
857+
/// # Cancel safety
858+
///
859+
/// The safety of this method depends entirely on how you implement it;
860+
/// it provides no inherent security guarantees.
861+
///
862+
/// # Example
863+
///
864+
/// ```
865+
/// use tokio::sync::mpsc::Receiver;
866+
/// use russh::server::{Handler, Session};
867+
///
868+
/// struct App{
869+
/// foo: String,
870+
/// recv: Receiver<String>,
871+
/// trigger: Receiver<String>,
872+
/// }
873+
///
874+
/// impl Handler for App {
875+
/// type Error = russh::Error;
876+
/// type Data = String;
877+
/// async fn trigger(&mut self) -> Result<Self::Data, Self::Error> {
878+
/// match self.trigger.recv().await {
879+
/// Some(d) => Ok(d),
880+
/// None => std::future::pending().await,
881+
/// }
882+
/// }
883+
///
884+
/// async fn process(&mut self, s: Self::Data, session: &mut Session) -> Result<(), Self::Error> {
885+
/// let s = self.recv.recv().await.unwrap();
886+
/// self.foo = s;
887+
/// Ok(())
888+
/// }
889+
/// }
890+
/// ```
891+
///
892+
fn trigger(&mut self) -> impl Future<Output = Result<Self::Data, Self::Error>> + Send {
893+
std::future::pending()
894+
}
895+
896+
/// Called after [`trigger`], See [`trigger`] for more.
897+
#[allow(unused_variables)]
898+
fn process(
899+
&mut self,
900+
data: Self::Data,
901+
session: &mut Session,
902+
) -> impl Future<Output = Result<(), Self::Error>> + Send {
903+
async { Ok(()) }
904+
}
852905
}
853906

854907
pub struct RunningServerHandle {

russh/src/server/session.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,13 @@ impl Session {
746746
}
747747
reading.set(start_reading(stream_read, buffer, opening_cipher));
748748
}
749+
t = handler.trigger() => {
750+
debug!("handler trigger is invoked");
751+
match t {
752+
Ok(d) => handler.process(d,&mut self).await?,
753+
Err(e) => return Err(e)
754+
}
755+
}
749756
() = &mut keepalive_timer => {
750757
self.common.alive_timeouts = self.common.alive_timeouts.saturating_add(1);
751758
if self.common.config.keepalive_max != 0 && self.common.alive_timeouts > self.common.config.keepalive_max {
@@ -1515,6 +1522,7 @@ mod tests {
15151522

15161523
impl crate::server::Handler for TestHandler {
15171524
type Error = crate::Error;
1525+
type Data = ();
15181526
}
15191527

15201528
fn authenticated_session() -> Session {

russh/src/tests.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ mod compress {
110110

111111
impl server::Handler for Server {
112112
type Error = super::Error;
113+
type Data = ();
113114

114115
async fn channel_open_session(
115116
&mut self,
@@ -289,6 +290,7 @@ mod channels {
289290

290291
impl server::Handler for ServerHandle {
291292
type Error = crate::Error;
293+
type Data = ();
292294

293295
async fn auth_publickey(
294296
&mut self,
@@ -360,6 +362,7 @@ mod channels {
360362

361363
impl server::Handler for ServerHandle {
362364
type Error = crate::Error;
365+
type Data = ();
363366

364367
async fn auth_publickey(
365368
&mut self,
@@ -446,6 +449,7 @@ mod channels {
446449

447450
impl server::Handler for ServerHandle {
448451
type Error = crate::Error;
452+
type Data = ();
449453

450454
async fn auth_publickey(
451455
&mut self,
@@ -532,6 +536,7 @@ mod channels {
532536

533537
impl server::Handler for ServerHandle {
534538
type Error = crate::Error;
539+
type Data = ();
535540

536541
async fn auth_publickey(
537542
&mut self,
@@ -614,6 +619,7 @@ mod channels {
614619

615620
impl server::Handler for ServerHandle {
616621
type Error = crate::Error;
622+
type Data = ();
617623

618624
async fn auth_publickey(
619625
&mut self,
@@ -755,6 +761,7 @@ mod server_kex_junk {
755761

756762
impl server::Handler for Server {
757763
type Error = super::Error;
764+
type Data = ();
758765
}
759766
}
760767

@@ -1206,6 +1213,7 @@ pub(crate) mod raw_no_crypto {
12061213

12071214
impl server::Handler for MalformedInputServer {
12081215
type Error = Error;
1216+
type Data = ();
12091217

12101218
async fn auth_none(&mut self, _user: &str) -> Result<server::Auth, Self::Error> {
12111219
self.record("auth_none");
@@ -1409,6 +1417,7 @@ mod future_certificate {
14091417

14101418
impl server::Handler for CertHandler {
14111419
type Error = crate::Error;
1420+
type Data = ();
14121421

14131422
async fn auth_publickey_offered(
14141423
&mut self,

russh/tests/auth_state_reset.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct RemainingMethodsUserSwitchServer;
2121

2222
impl server::Handler for RemainingMethodsUserSwitchServer {
2323
type Error = russh::Error;
24+
type Data = ();
2425

2526
async fn auth_none(&mut self, user: &str) -> Result<server::Auth, Self::Error> {
2627
if user == "alice" {

0 commit comments

Comments
 (0)