1
- use std:: sync:: Arc ;
1
+ use std:: { ops :: DerefMut , sync:: Arc , task :: ready } ;
2
2
3
3
use russh:: {
4
4
client:: Handle ,
@@ -9,6 +9,7 @@ pub enum AuthMode {
9
9
UsernamePassword { username : String , password : String } ,
10
10
}
11
11
12
+ #[ derive( Clone ) ]
12
13
pub struct Client {
13
14
handle : Arc < Handle < ClientHandler > > ,
14
15
}
@@ -37,10 +38,90 @@ impl Client {
37
38
}
38
39
}
39
40
}
41
+
42
+ pub async fn open_session ( & mut self ) -> Result < Session , super :: Error > {
43
+ let channel = self . handle . channel_open_session ( ) . await ?;
44
+ let stream = channel. into_stream ( ) ;
45
+ Ok ( Session {
46
+ stream : Arc :: new ( std:: sync:: Mutex :: new ( stream) ) ,
47
+ } )
48
+ }
49
+ }
50
+
51
+ #[ derive( Clone ) ]
52
+ pub struct Session {
53
+ stream : Arc < std:: sync:: Mutex < russh:: ChannelStream < russh:: client:: Msg > > > ,
54
+ }
55
+
56
+ impl Session {
57
+ fn poll_fn < F , R > ( self : std:: pin:: Pin < & mut Self > , cx : & mut std:: task:: Context < ' _ > , poll_fn : F ) -> std:: task:: Poll < R >
58
+ where
59
+ F : FnOnce (
60
+ std:: pin:: Pin < & mut russh:: ChannelStream < russh:: client:: Msg > > ,
61
+ & mut std:: task:: Context < ' _ > ,
62
+ ) -> std:: task:: Poll < R > ,
63
+ {
64
+ match self . stream . try_lock ( ) {
65
+ Ok ( mut inner) => {
66
+ let pinned = std:: pin:: Pin :: new ( inner. deref_mut ( ) ) ;
67
+ ( poll_fn) ( pinned, cx)
68
+ }
69
+ Err ( _) => {
70
+ cx. waker ( ) . wake_by_ref ( ) ;
71
+ std:: task:: Poll :: Pending
72
+ }
73
+ }
74
+ }
75
+ }
76
+
77
+ impl futures_io:: AsyncRead for Session {
78
+ fn poll_read (
79
+ self : std:: pin:: Pin < & mut Self > ,
80
+ cx : & mut std:: task:: Context < ' _ > ,
81
+ slice : & mut [ u8 ] ,
82
+ ) -> std:: task:: Poll < std:: io:: Result < usize > > {
83
+ self . poll_fn ( cx, |pinned, cx| {
84
+ let mut buf = tokio:: io:: ReadBuf :: new ( slice) ;
85
+ ready ! ( tokio:: io:: AsyncRead :: poll_read( pinned, cx, & mut buf) ) ?;
86
+ std:: task:: Poll :: Ready ( Ok ( buf. filled ( ) . len ( ) ) )
87
+ } )
88
+ }
89
+ }
90
+
91
+ impl futures_io:: AsyncWrite for Session {
92
+ fn poll_write (
93
+ self : std:: pin:: Pin < & mut Self > ,
94
+ cx : & mut std:: task:: Context < ' _ > ,
95
+ buf : & [ u8 ] ,
96
+ ) -> std:: task:: Poll < std:: io:: Result < usize > > {
97
+ self . poll_fn ( cx, |pinned, cx| tokio:: io:: AsyncWrite :: poll_write ( pinned, cx, buf) )
98
+ }
99
+
100
+ fn poll_flush (
101
+ self : std:: pin:: Pin < & mut Self > ,
102
+ cx : & mut std:: task:: Context < ' _ > ,
103
+ ) -> std:: task:: Poll < std:: io:: Result < ( ) > > {
104
+ self . poll_fn ( cx, tokio:: io:: AsyncWrite :: poll_flush)
105
+ }
106
+
107
+ fn poll_close (
108
+ self : std:: pin:: Pin < & mut Self > ,
109
+ cx : & mut std:: task:: Context < ' _ > ,
110
+ ) -> std:: task:: Poll < std:: io:: Result < ( ) > > {
111
+ self . poll_fn ( cx, tokio:: io:: AsyncWrite :: poll_shutdown)
112
+ }
40
113
}
41
114
42
115
struct ClientHandler ;
43
116
44
117
impl Handler for ClientHandler {
45
118
type Error = super :: Error ;
119
+
120
+ async fn check_server_key (
121
+ & mut self ,
122
+ _server_public_key : & russh:: keys:: ssh_key:: PublicKey ,
123
+ ) -> Result < bool , Self :: Error > {
124
+ // TODO: configurable
125
+ Ok ( true )
126
+ }
46
127
}
0 commit comments