1- use std:: sync:: Arc ;
1+ use std:: { ops :: DerefMut , sync:: Arc , task :: ready } ;
22
33use russh:: {
44 client:: Handle ,
@@ -9,6 +9,7 @@ pub enum AuthMode {
99 UsernamePassword { username : String , password : String } ,
1010}
1111
12+ #[ derive( Clone ) ]
1213pub struct Client {
1314 handle : Arc < Handle < ClientHandler > > ,
1415}
@@ -37,10 +38,90 @@ impl Client {
3738 }
3839 }
3940 }
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+ }
40113}
41114
42115struct ClientHandler ;
43116
44117impl Handler for ClientHandler {
45118 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+ }
46127}
0 commit comments