-
-
Notifications
You must be signed in to change notification settings - Fork 182
Add a hook-trigger to the handler. #557
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
New feather:
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).
|
IMO this is a bit of a crutch that doesn't belong in the library. Is there any reason for this except running inside the russh event loop? Mutable access to the handler? TBH I'm rather inclined to hand off resources to the task that is supposed to call |
|
Yes, Mutable access to the handler. I don’t know if there’s another way to update the handler’s status without locking it. |
|
I think |
|
No, I meant the event loop messages that are going through |
|
Below is some pseudo-code whose purpose is to switch apps at runtime. pub struct MyHandler {
app: Application,
send_app_msg: Sender<Application>,
recv_app_msg: Receiver<Application>,
}
pub enum Application {
Foo(Box<Foo>),
Bar(Box<Bar>),
}
impl ru_server::Handler for MyHandler {
async fn data(
&mut self,
channel: ChannelId,
data: &[u8],
session: &mut ru_server::Session,
) -> Result<(), Self::Error> {
match self.app {
Application::Foo(ref mut app) => app.data(channel, data, session).await,
Application::Bar(ref mut app) => app.data(channel, data, session).await,
}
}
async fn trigger(&mut self) -> Result<Self::Data, Self::Error> {
match self.recv_app_msg.recv().await {
Some(d) => Ok(d),
None => std::future::pending().await,
}
}
async fn process(&mut self, app: Self::Data) -> Result<(), Self::Error> {
app.init().await?;
self.app = app;
}
} |
|
I think this could work? enum CustomEvent {
AppSwap(App)
}
impl ru_server::Handler for MyHandler {
type CustomEvent = CustomEvent;
async fn custom_event(&mut self, e: Self::CustomEvent) {
match e {
CustomEvent::AppSwap(app) => {
app.init().await?;
self.app = app
}
}
}
}
..
// from another task
session_handle.emit_custom_event(CustomEvent::AppSwap(...)) // places Msg::Custom(CustomEvent::AppSwap(...)) on the event queue |
|
Got it, I will try it |
|
Do you mean something like this? impl Handle {
...
/// Emit custom event.
pub async fn emit_custom_event<H>(&self, event: H::CustomEvent) -> Result<(), ()>
where
H: Handler,
{
self.sender
.send(Msg::CustomEvent(event))
.await
.map_err(|_| ())
}
}
#[derive(Debug)]
pub enum Msg<H:Handler> {
......
Channel(ChannelId, ChannelMsg),
CustomEvent(H::CustomEvent),
}
pub(crate) async fn run<H, R>(
mut self,
mut stream: SshRead<R>,
mut handler: H,
) -> Result<(), H::Error>
where
H: Handler + Send + 'static,
R: AsyncRead + AsyncWrite + Unpin + Send + 'static,
{
.......
msg = self.receiver.recv(), if !self.kex.active() => {
match msg {
Some(Msg::Disconnect {reason, description, language_tag}) => {
self.common.disconnect(reason, &description, &language_tag)?;
}
Some(Msg::CustomEvent(event)) => {
handler.custom_event(event).await?;
}
}
}
.....
}
pub trait Handler: Sized {
type Error: From<crate::Error> + Send;
type CustomEvent: Send;
...
///
#[allow(unused_variables)]
fn custom_event(
&mut self,
event: Self::CustomEvent,
) -> impl Future<Output = Result<(), Self::Error>> + Send {
async { Ok(()) }
}
}Here is compile error error[E0107]: missing generics for enum `server::session::Msg`
--> russh/src/server/session.rs:358:25
|
358 | ) -> Result<Channel<Msg>, Error> {
| ^^^ expected 1 generic argument
|
note: enum defined here, with 1 generic parameter: `H`
--> russh/src/server/session.rs:34:10
|
34 | pub enum Msg<H: Handler> {
| ^^^ -
help: add missing generic argument
|
358 | ) -> Result<Channel<Msg<H>>, Error> {
| +++ |
Note: this is a breaking API change.
New feather:
This is useful if you need to update the handler
without relying on a mutex (or similar synchronization).
here is demo