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