Skip to content

Commit a07d513

Browse files
committed
Implement --echo argument to enable the echoing of shell io on the target session
1 parent de93b62 commit a07d513

File tree

7 files changed

+62
-20
lines changed

7 files changed

+62
-20
lines changed

tunshell-client/src/client.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#[cfg(not(target_arch = "wasm32"))]
2-
use crate::p2p;
2+
use crate::{p2p, ShellServerConfig};
33
use crate::{
44
AesStream, ClientMode, Config, HostShell, RelayStream, ServerStream, ShellKey, TunnelStream,
55
};
@@ -312,10 +312,12 @@ impl Client {
312312

313313
#[cfg(not(target_arch = "wasm32"))]
314314
async fn start_shell_server(&self, peer_socket: Box<dyn TunnelStream>) -> Result<u8> {
315-
crate::ShellServer::new()?
316-
.run(peer_socket, ShellKey::new(self.config.encryption_key()))
317-
.await
318-
.and_then(|_| Ok(0))
315+
crate::ShellServer::new(ShellServerConfig {
316+
echo_stdout: self.config.echo_stdout(),
317+
})?
318+
.run(peer_socket, ShellKey::new(self.config.encryption_key()))
319+
.await
320+
.and_then(|_| Ok(0))
319321
}
320322

321323
#[cfg(target_arch = "wasm32")]
@@ -362,6 +364,7 @@ mod tests {
362364
443,
363365
"test",
364366
true,
367+
false,
365368
);
366369
let mut client = Client::new(config, HostShell::new().unwrap());
367370

tunshell-client/src/config.rs

+17
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub struct Config {
1313
relay_ws_port: u16,
1414
server_connection_timeout: Duration,
1515
direct_connection_timeout: Duration,
16+
echo_stdout: bool,
1617
enable_direct_connection: bool,
1718
dangerous_disable_relay_server_verification: bool,
1819
}
@@ -44,6 +45,15 @@ impl Config {
4445
.unwrap_or("443".to_owned())
4546
.parse::<u16>()
4647
.expect("could not parse arg (7) as WebSocket port");
48+
let mut echo_stdout = false;
49+
50+
// Parse optional args
51+
while let Some(arg) = args.next() {
52+
match arg.as_str() {
53+
"--echo" => echo_stdout = true,
54+
arg @ _ => panic!(format!("Unknown argument: {}", arg)),
55+
}
56+
}
4757

4858
if session_key.len() < 10 {
4959
panic!("session key is too short")
@@ -62,6 +72,7 @@ impl Config {
6272
encryption_key,
6373
server_connection_timeout: Duration::from_millis(DEFAULT_SERVER_CONNECT_TIMEOUT),
6474
direct_connection_timeout: Duration::from_millis(DEFAULT_DIRECT_CONNECT_TIMEOUT),
75+
echo_stdout,
6576
enable_direct_connection: true,
6677
dangerous_disable_relay_server_verification: false,
6778
}
@@ -75,6 +86,7 @@ impl Config {
7586
relay_ws_port: u16,
7687
encryption_key: &str,
7788
enable_direct_connection: bool,
89+
echo_stdout: bool,
7890
) -> Self {
7991
Self {
8092
mode,
@@ -86,6 +98,7 @@ impl Config {
8698
server_connection_timeout: Duration::from_millis(DEFAULT_SERVER_CONNECT_TIMEOUT),
8799
direct_connection_timeout: Duration::from_millis(DEFAULT_DIRECT_CONNECT_TIMEOUT),
88100
enable_direct_connection,
101+
echo_stdout,
89102
dangerous_disable_relay_server_verification: false,
90103
}
91104
}
@@ -126,6 +139,10 @@ impl Config {
126139
self.direct_connection_timeout
127140
}
128141

142+
pub fn echo_stdout(&self) -> bool {
143+
self.echo_stdout
144+
}
145+
129146
pub fn enable_direct_connection(&self) -> bool {
130147
self.enable_direct_connection
131148
}

tunshell-client/src/server/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ mod tests {
3030
443,
3131
"test",
3232
true,
33+
false
3334
);
3435

3536
let result = Runtime::new()

tunshell-client/src/shell/server/mod.rs

+31-15
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use anyhow::{Error, Result};
44
use futures::stream::StreamExt;
55
use log::*;
66
use std::time::Duration;
7-
use tokio::time;
7+
use tokio::{io::AsyncWriteExt, time};
88
use tokio_util::compat::*;
99

1010
mod fallback;
@@ -23,11 +23,17 @@ use pty::*;
2323

2424
type ShellStream = ShellServerStream<Compat<Box<dyn TunnelStream>>>;
2525

26-
pub(crate) struct ShellServer {}
26+
pub(crate) struct ShellServer {
27+
conf: ShellServerConfig,
28+
}
29+
30+
pub(crate) struct ShellServerConfig {
31+
pub(crate) echo_stdout: bool,
32+
}
2733

2834
impl ShellServer {
29-
pub(crate) fn new() -> Result<ShellServer> {
30-
Ok(ShellServer {})
35+
pub(crate) fn new(conf: ShellServerConfig) -> Result<ShellServer> {
36+
Ok(ShellServer { conf })
3137
}
3238

3339
pub(crate) async fn run(self, stream: Box<dyn TunnelStream>, key: ShellKey) -> Result<()> {
@@ -108,6 +114,11 @@ impl ShellServer {
108114
mut shell: Box<dyn Shell + Send + 'a>,
109115
) -> Result<()> {
110116
let mut buff = [0u8; 1024];
117+
let mut host_stdout = if self.conf.echo_stdout {
118+
Some(tokio::io::stdout())
119+
} else {
120+
None
121+
};
111122

112123
loop {
113124
info!("waiting for shell message");
@@ -122,6 +133,12 @@ impl ShellServer {
122133
},
123134
Ok(read) => {
124135
info!("read {} bytes from stdout", read);
136+
137+
if let Some(host_stdout) = host_stdout.as_mut() {
138+
host_stdout.write_all(&buff[..read]).await?;
139+
host_stdout.flush().await?;
140+
}
141+
125142
stream.write(&ShellServerMessage::Stdout(buff[..read].to_vec())).await?;
126143
info!("sent {} bytes to client shell", read);
127144
},
@@ -167,9 +184,13 @@ mod tests {
167184
use tokio::time::timeout;
168185
use tunshell_shared::Message;
169186

187+
fn new_shell_server() -> ShellServer {
188+
ShellServer::new(ShellServerConfig { echo_stdout: true }).unwrap()
189+
}
190+
170191
#[test]
171192
fn test_new_shell_server() {
172-
ShellServer::new().unwrap();
193+
new_shell_server();
173194
}
174195

175196
#[test]
@@ -186,8 +207,7 @@ mod tests {
186207
);
187208

188209
let mock_stream = Cursor::new(mock_data).compat();
189-
ShellServer::new()
190-
.unwrap()
210+
new_shell_server()
191211
.run(Box::new(mock_stream), ShellKey::new("MyKey"))
192212
.await
193213
.expect_err("client key should be rejected");
@@ -203,9 +223,7 @@ mod tests {
203223

204224
timeout(
205225
Duration::from_millis(5000),
206-
ShellServer::new()
207-
.unwrap()
208-
.run(Box::new(mock_stream), ShellKey::new("CorrectKey")),
226+
new_shell_server().run(Box::new(mock_stream), ShellKey::new("CorrectKey")),
209227
)
210228
.await
211229
.unwrap()
@@ -230,9 +248,7 @@ mod tests {
230248

231249
timeout(
232250
Duration::from_millis(5000),
233-
ShellServer::new()
234-
.unwrap()
235-
.run(Box::new(mock_stream), ShellKey::new("CorrectKey")),
251+
new_shell_server().run(Box::new(mock_stream), ShellKey::new("CorrectKey")),
236252
)
237253
.await
238254
.unwrap()
@@ -289,7 +305,7 @@ mod tests {
289305
);
290306

291307
let mock_stream = Cursor::new(mock_data).compat();
292-
let server = ShellServer::new().unwrap();
308+
let server = new_shell_server();
293309

294310
server
295311
.run(Box::new(mock_stream), ShellKey::new("CorrectKey"))
@@ -331,7 +347,7 @@ mod tests {
331347
);
332348

333349
let mock_stream = Cursor::new(mock_data).compat();
334-
let server = ShellServer::new().unwrap();
350+
let server = new_shell_server();
335351

336352
server
337353
.run(Box::new(mock_stream), ShellKey::new("CorrectKey"))

tunshell-client/src/wasm.rs

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ pub async fn tunshell_init_client(config: BrowserConfig) {
9393
5000,
9494
443,
9595
&config.encryption_key,
96+
false,
9697
false
9798
);
9899

tunshell-tests/tests/valid_direct_connection.rs

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ fn test() {
4444
config.api_port,
4545
"mock_encryption_key",
4646
true,
47+
false,
4748
);
4849
target_config.set_dangerous_disable_relay_server_verification(true);
4950
let mut target = client::Client::new(target_config, target_shell.clone());
@@ -58,6 +59,7 @@ fn test() {
5859
config.api_port,
5960
"mock_encryption_key",
6061
true,
62+
false,
6163
);
6264
local_config.set_dangerous_disable_relay_server_verification(true);
6365
let mut local = client::Client::new(local_config, local_shell.clone());

tunshell-tests/tests/valid_relay_connection.rs

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ fn test() {
4444
config.api_port,
4545
"mock_encryption_key",
4646
false,
47+
false,
4748
);
4849
target_config.set_dangerous_disable_relay_server_verification(true);
4950
let mut target = client::Client::new(target_config, target_shell.clone());
@@ -58,6 +59,7 @@ fn test() {
5859
config.api_port,
5960
"mock_encryption_key",
6061
false,
62+
false,
6163
);
6264
local_config.set_dangerous_disable_relay_server_verification(true);
6365
let mut local = client::Client::new(local_config, local_shell.clone());

0 commit comments

Comments
 (0)