Skip to content

Commit

Permalink
Implement Session Exit for client
Browse files Browse the repository at this point in the history
  • Loading branch information
mkj committed Jun 2, 2024
1 parent 8c02faf commit fab8cca
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 14 deletions.
4 changes: 4 additions & 0 deletions async/src/cmdline_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,11 @@ impl CmdlineClient {
// TODO is there a better way
launch_chan.send((io.clone().unwrap(), extin.clone(), self.pty_guard.take())).await;
}
CliEvent::SessionExit(ex) => {
debug!("TODO handle session exit {ex:?}")
}
CliEvent::Defunct => {
trace!("break defunct");
break Ok::<_, Error>(())
}
}
Expand Down
37 changes: 28 additions & 9 deletions src/channel.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use self::{event::ChanRequest, packets::ExitSignal};

#[allow(unused_imports)]
use {
crate::error::{Error, Result, TrapBug},
Expand Down Expand Up @@ -722,23 +724,18 @@ impl Channel {
fn dispatch_client_request(
&mut self,
p: &packets::ChannelRequest,
s: &mut TrafSend,
_s: &mut TrafSend,
) -> Result<DispatchEvent> {
if !matches!(self.ty, ChanType::Session) {
return Err(Error::SSHProtoUnsupported)
}

match &p.req {
ChannelReqType::ExitStatus(_st) => {
// TODO
self.handle_close(s)?;
// Ok(DispatchEvent::CliEvent(Exit(st)
Err(Error::SSHProtoUnsupported)
ChannelReqType::ExitStatus(_) => {
Ok(DispatchEvent::CliEvent(CliEventId::SessionExit))
}
ChannelReqType::ExitSignal(_sig) => {
// TODO
self.handle_close(s)?;
Err(Error::SSHProtoUnsupported)
Ok(DispatchEvent::CliEvent(CliEventId::SessionExit))
}
_ => {
if let ChannelReqType::Unknown(u) = &p.req {
Expand Down Expand Up @@ -954,3 +951,25 @@ impl core::fmt::Debug for CliSessionOpener<'_, '_> {
f.debug_struct("CliSessionOpener").finish()
}
}

#[derive(Debug)]
pub enum CliSessionExit<'g> {
/// Remote process exited with an exit status code
Status(u32),
/// Remote process exited by signal
Signal(ExitSignal<'g>)
}

impl<'g> CliSessionExit<'g> {
pub fn new(p: &Packet<'g>) -> Result<Self> {
match p {
Packet::ChannelRequest(ChannelRequest { req: ChannelReqType::ExitStatus(e), .. }) => {
Ok(Self::Status(e.status))
}
Packet::ChannelRequest(ChannelRequest { req: ChannelReqType::ExitSignal(e), .. }) => {
Ok(Self::Signal(e.clone()))
}
_ => Err(Error::bug())
}
}
}
8 changes: 7 additions & 1 deletion src/conn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use client::Client;
use packets::{Packet,ParseContext};
use server::Server;
use traffic::TrafSend;
use channel::Channels;
use channel::{Channels, CliSessionExit};
use config::MAX_CHANNELS;
use kex::{Kex, SessId, AlgoConfig};
use event::{CliEvent, ServEvent};
Expand Down Expand Up @@ -532,6 +532,12 @@ impl Conn {
}
}

pub(crate) fn fetch_cli_session_exit<'p>(&mut self, payload: &'p [u8]) -> Result<CliSessionExit<'p>> {
self.client()?;
let packet = self.packet(payload)?;
CliSessionExit::new(&packet)
}

pub(crate) fn resume_servhostkeys(&mut self,
payload: &[u8], s: &mut TrafSend, keys: &[&SignKey]) -> Result<()> {
self.server()?;
Expand Down
17 changes: 15 additions & 2 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use core::fmt::Debug;
use crate::*;
use sshwire::TextString;
use packets::Packet;
use channel::CliSessionOpener;
use channel::{CliSessionOpener, CliSessionExit};

#[derive(Debug)]
pub enum Event<'g, 'a> {
Expand Down Expand Up @@ -55,8 +55,10 @@ pub enum CliEvent<'g, 'a>
Password(RequestPassword<'g, 'a>),
Authenticated,
SessionOpened(CliSessionOpener<'g, 'a>),
/// Remote process exited
SessionExit(CliSessionExit<'g>),

/// The SSH session is no longer running
/// The SSH connection is no longer running
Defunct,

// ChanRequest(ChanRequest<'g, 'a>),
Expand All @@ -71,6 +73,7 @@ impl Debug for CliEvent<'_, '_> {
Self::Password(_) => "Password",
Self::Authenticated => "Authenticated",
Self::SessionOpened(_) => "SessionOpened",
Self::SessionExit(_) => "SessionExit",
Self::Defunct => "Defunct",
};
write!(f, "CliEvent({e})")
Expand Down Expand Up @@ -115,13 +118,19 @@ impl CheckHostkey<'_, '_> {
}
}

// impl CliExit<''_, '_> {
// pub fn

// }

#[derive(Debug, Clone, Copy)]
pub(crate) enum CliEventId {
Hostkey,
Username,
Password,
Authenticated,
SessionOpened(ChanNum),
SessionExit,
Defunct

// TODO:
Expand Down Expand Up @@ -155,6 +164,9 @@ impl CliEventId {
// (Self::Banner, Packet::UserauthBanner(p)) => {
// CliEvent::Banner { banner: p.message, language: p.lang }
// }
Self::SessionExit => {
Ok(CliEvent::SessionExit(runner.fetch_cli_session_exit()?))
}
Self::Defunct => error::BadUsage.fail()
}
}
Expand All @@ -165,6 +177,7 @@ impl CliEventId {
match self {
| Self::Authenticated
| Self::SessionOpened(_)
| Self::SessionExit
| Self::Defunct
=> false,
| Self::Hostkey
Expand Down
2 changes: 1 addition & 1 deletion src/packets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ pub struct ExitStatus {
pub status: u32,
}

#[derive(Debug, SSHEncode, SSHDecode)]
#[derive(Debug, SSHEncode, SSHDecode, Clone)]
pub struct ExitSignal<'a> {
pub signal: &'a str,
pub core: bool,
Expand Down
7 changes: 6 additions & 1 deletion src/runner.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use self::{channel::CliSessionOpener, event::Event};
use self::{channel::{CliSessionExit, CliSessionOpener}, event::Event};

#[allow(unused_imports)]
use {
Expand Down Expand Up @@ -440,6 +440,11 @@ impl<'a> Runner<'a> {
})
}

pub(crate) fn fetch_cli_session_exit(&mut self) -> Result<CliSessionExit> {
let (payload, _seq) = self.traf_in.payload().trap()?;
self.conn.fetch_cli_session_exit(payload)
}

fn wake(&mut self) {
if self.is_input_ready() {
trace!("wake ready_input, waker {:?}", self.input_waker);
Expand Down

0 comments on commit fab8cca

Please sign in to comment.