openssh/native_mux_impl/
session.rs
1use super::{Command, Error};
2
3use std::ffi::OsStr;
4use std::os::unix::ffi::OsStrExt;
5use std::path::Path;
6
7use openssh_mux_client::{shutdown_mux_master, Connection};
8use tempfile::TempDir;
9
10#[derive(Debug)]
11pub(crate) struct Session {
12 tempdir: Option<TempDir>,
14 ctl: Box<Path>,
15}
16
17impl Session {
18 pub(crate) fn new(dir: TempDir) -> Self {
19 let ctl = dir.path().join("master").into_boxed_path();
20
21 Self {
22 tempdir: Some(dir),
23 ctl,
24 }
25 }
26
27 pub(crate) fn resume(ctl: Box<Path>, _master_log: Option<Box<Path>>) -> Self {
28 Self { tempdir: None, ctl }
29 }
30
31 pub(crate) async fn check(&self) -> Result<(), Error> {
32 Connection::connect(&self.ctl)
33 .await?
34 .send_alive_check()
35 .await?;
36
37 Ok(())
38 }
39
40 pub(crate) fn ctl(&self) -> &Path {
41 &self.ctl
42 }
43
44 pub(crate) fn raw_command<S: AsRef<OsStr>>(&self, program: S) -> Command {
45 Command::new(self.ctl.clone(), program.as_ref().as_bytes().into(), false)
46 }
47
48 pub(crate) fn subsystem<S: AsRef<OsStr>>(&self, program: S) -> Command {
49 Command::new(self.ctl.clone(), program.as_ref().as_bytes().into(), true)
50 }
51
52 pub(crate) async fn request_port_forward(
53 &self,
54 forward_type: crate::ForwardType,
55 listen_socket: crate::Socket<'_>,
56 connect_socket: crate::Socket<'_>,
57 ) -> Result<(), Error> {
58 Connection::connect(&self.ctl)
59 .await?
60 .request_port_forward(
61 forward_type.into(),
62 &listen_socket.into(),
63 &connect_socket.into(),
64 )
65 .await?;
66
67 Ok(())
68 }
69
70 pub(crate) async fn close_port_forward(
71 &self,
72 forward_type: crate::ForwardType,
73 listen_socket: crate::Socket<'_>,
74 connect_socket: crate::Socket<'_>,
75 ) -> Result<(), Error> {
76 Connection::connect(&self.ctl)
77 .await?
78 .close_port_forward(
79 forward_type.into(),
80 &listen_socket.into(),
81 &connect_socket.into(),
82 )
83 .await?;
84
85 Ok(())
86 }
87
88 async fn close_impl(&self) -> Result<(), Error> {
89 Connection::connect(&self.ctl)
90 .await?
91 .request_stop_listening()
92 .await?;
93
94 Ok(())
95 }
96
97 pub(crate) async fn close(mut self) -> Result<Option<TempDir>, Error> {
98 let tempdir = self.tempdir.take();
100
101 self.close_impl().await?;
102
103 Ok(tempdir)
104 }
105
106 pub(crate) fn detach(mut self) -> (Box<Path>, Option<Box<Path>>) {
107 (
108 self.ctl.clone(),
109 self.tempdir.take().map(TempDir::into_path).map(|mut path| {
110 path.push("log");
111 path.into_boxed_path()
112 }),
113 )
114 }
115}
116
117impl Drop for Session {
118 fn drop(&mut self) {
119 let _tempdir = match self.tempdir.take() {
121 Some(tempdir) => tempdir,
122 None => return,
124 };
125
126 let _res = shutdown_mux_master(&self.ctl);
127 #[cfg(feature = "tracing")]
128 if let Err(err) = _res {
129 tracing::error!("Closing ssh session failed: {}", err);
130 }
131 }
132}