@@ -4,7 +4,7 @@ use anyhow::{Error, Result};
4
4
use futures:: stream:: StreamExt ;
5
5
use log:: * ;
6
6
use std:: time:: Duration ;
7
- use tokio:: time;
7
+ use tokio:: { io :: AsyncWriteExt , time} ;
8
8
use tokio_util:: compat:: * ;
9
9
10
10
mod fallback;
@@ -23,11 +23,17 @@ use pty::*;
23
23
24
24
type ShellStream = ShellServerStream < Compat < Box < dyn TunnelStream > > > ;
25
25
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
+ }
27
33
28
34
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 } )
31
37
}
32
38
33
39
pub ( crate ) async fn run ( self , stream : Box < dyn TunnelStream > , key : ShellKey ) -> Result < ( ) > {
@@ -108,6 +114,11 @@ impl ShellServer {
108
114
mut shell : Box < dyn Shell + Send + ' a > ,
109
115
) -> Result < ( ) > {
110
116
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
+ } ;
111
122
112
123
loop {
113
124
info ! ( "waiting for shell message" ) ;
@@ -122,6 +133,12 @@ impl ShellServer {
122
133
} ,
123
134
Ok ( read) => {
124
135
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
+
125
142
stream. write( & ShellServerMessage :: Stdout ( buff[ ..read] . to_vec( ) ) ) . await ?;
126
143
info!( "sent {} bytes to client shell" , read) ;
127
144
} ,
@@ -167,9 +184,13 @@ mod tests {
167
184
use tokio:: time:: timeout;
168
185
use tunshell_shared:: Message ;
169
186
187
+ fn new_shell_server ( ) -> ShellServer {
188
+ ShellServer :: new ( ShellServerConfig { echo_stdout : true } ) . unwrap ( )
189
+ }
190
+
170
191
#[ test]
171
192
fn test_new_shell_server ( ) {
172
- ShellServer :: new ( ) . unwrap ( ) ;
193
+ new_shell_server ( ) ;
173
194
}
174
195
175
196
#[ test]
@@ -186,8 +207,7 @@ mod tests {
186
207
) ;
187
208
188
209
let mock_stream = Cursor :: new ( mock_data) . compat ( ) ;
189
- ShellServer :: new ( )
190
- . unwrap ( )
210
+ new_shell_server ( )
191
211
. run ( Box :: new ( mock_stream) , ShellKey :: new ( "MyKey" ) )
192
212
. await
193
213
. expect_err ( "client key should be rejected" ) ;
@@ -203,9 +223,7 @@ mod tests {
203
223
204
224
timeout (
205
225
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" ) ) ,
209
227
)
210
228
. await
211
229
. unwrap ( )
@@ -230,9 +248,7 @@ mod tests {
230
248
231
249
timeout (
232
250
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" ) ) ,
236
252
)
237
253
. await
238
254
. unwrap ( )
@@ -289,7 +305,7 @@ mod tests {
289
305
) ;
290
306
291
307
let mock_stream = Cursor :: new ( mock_data) . compat ( ) ;
292
- let server = ShellServer :: new ( ) . unwrap ( ) ;
308
+ let server = new_shell_server ( ) ;
293
309
294
310
server
295
311
. run ( Box :: new ( mock_stream) , ShellKey :: new ( "CorrectKey" ) )
@@ -331,7 +347,7 @@ mod tests {
331
347
) ;
332
348
333
349
let mock_stream = Cursor :: new ( mock_data) . compat ( ) ;
334
- let server = ShellServer :: new ( ) . unwrap ( ) ;
350
+ let server = new_shell_server ( ) ;
335
351
336
352
server
337
353
. run ( Box :: new ( mock_stream) , ShellKey :: new ( "CorrectKey" ) )
0 commit comments