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
use tokio_io::{AsyncRead, AsyncWrite};
use std::sync::Arc;
use std::rc::Rc;
use std::cell::RefCell;
use futures::Future;
use tokio_core::reactor::Handle;
use channel;
use {Connection, SharableConnection};
use thrussh;
use thrussh_keys;
pub(crate) mod state;
pub struct NewSession<S: AsyncRead + AsyncWrite> {
c: Connection<S>,
handle: Handle,
}
impl<S: AsyncRead + AsyncWrite + 'static> NewSession<S> {
pub fn authenticate_key(
self,
user: &str,
key: thrussh_keys::key::KeyPair,
) -> Box<Future<Item = Session<S>, Error = thrussh::HandlerError<()>>>
where
S: thrussh::Tcp,
{
let NewSession { c, handle } = self;
Box::new(
c.c
.authenticate_key(user, key)
.map(move |c| Session::make(Connection { c, task: None }, handle)),
)
}
}
pub struct Session<S: AsyncRead + AsyncWrite>(SharableConnection<S>);
impl<S: AsyncRead + AsyncWrite + thrussh::Tcp + 'static> Session<S> {
pub fn new(stream: S, handle: &Handle) -> Result<NewSession<S>, thrussh::HandlerError<()>> {
thrussh::client::Connection::new(Arc::default(), stream, state::Ref::default(), None)
.map(|c| NewSession {
c: Connection { c, task: None },
handle: handle.clone(),
})
.map_err(thrussh::HandlerError::Error)
}
fn make(c: Connection<S>, handle: Handle) -> Self {
let c = SharableConnection(Rc::new(RefCell::new(c)));
handle.spawn(c.clone());
Session(c)
}
pub fn last_error(&mut self) -> Option<thrussh::HandlerError<()>> {
let connection = (self.0).0.borrow();
let handler = connection.c.handler();
let mut state = handler.borrow_mut();
state.errored_with.take()
}
pub fn open_exec<'a>(&mut self, cmd: &'a str) -> channel::ChannelOpenFuture<'a, S> {
let mut session = (self.0).0.borrow_mut();
let state = session.c.handler().clone();
let channel_id = (&mut *session.c)
.channel_open_session()
.expect("sessions are always authenticated");
state
.borrow_mut()
.state_for
.insert(channel_id, channel::State::default());
channel::ChannelOpenFuture::new(cmd, self.0.clone(), state, channel_id)
}
}