-
Notifications
You must be signed in to change notification settings - Fork 28
/
main.rs
137 lines (119 loc) · 3.65 KB
/
main.rs
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#[cfg(unix)]
use mio::unix::SourceFd;
use std::fs::File;
#[cfg(unix)]
use std::os::unix::io::FromRawFd;
use std::time::Duration;
use std::{cell::RefCell, rc::Rc};
use tracing::Level;
use tracing_subscriber::FmtSubscriber;
use mio::net::TcpStream;
use mio::{event::Source, Events, Interest, Poll, Token};
const SERVER: Token = Token(0);
const SHELL: Token = Token(1);
#[cfg(not(unix))]
fn main() {
panic!("This example can run on unix only")
}
#[cfg(unix)]
fn main() {
use std::{io::Read, os::unix::prelude::AsRawFd};
// a builder for `FmtSubscriber`.
let subscriber = FmtSubscriber::builder()
// all spans/events with a level higher than INFO (e.g, info, warn, etc.)
// will be written to stdout.
.with_max_level(Level::INFO)
// completes the builder.
.finish();
tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");
let tcp = TcpStream::connect("127.0.0.1:22".parse().unwrap()).unwrap();
let mut session = ssh::create_session()
.username("ubuntu")
.password("password")
.timeout(Some(Duration::from_millis(1000)))
.private_key_path("./id_rsa")
.connect_bio(tcp)
.unwrap()
.run_local();
let mut shell = session.open_shell().unwrap();
let mut tcp_wrap = TcpWrap::new(session.get_raw_io());
let mut std_in = unsafe { File::from_raw_fd(0) };
let mut poll = Poll::new().unwrap();
let mut events = Events::with_capacity(1024);
poll.registry()
.register(&mut tcp_wrap, SERVER, Interest::READABLE)
.unwrap();
poll.registry()
.register(
&mut SourceFd(&std_in.as_raw_fd()),
SHELL,
Interest::READABLE,
)
.unwrap();
let mut buf = [0; 2048];
'main_loop: loop {
poll.poll(&mut events, None).unwrap();
for event in &events {
match event.token() {
SERVER => match shell.read() {
Ok(buf) => print!("{}", String::from_utf8_lossy(&buf)),
_ => break 'main_loop,
},
SHELL => {
let len = std_in.read(&mut buf).unwrap();
shell.write(&buf[..len]).unwrap();
}
_ => break 'main_loop,
}
}
}
session.close();
}
struct TcpWrap {
server: Rc<RefCell<TcpStream>>,
}
impl TcpWrap {
fn new(tcp: Rc<RefCell<TcpStream>>) -> Self {
Self { server: tcp }
}
}
impl std::io::Read for TcpWrap {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
println!("bio log: read {} bytes", buf.len());
self.server.borrow_mut().read(buf)
}
}
impl std::io::Write for TcpWrap {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
println!("bio log: write {} bytes", buf.len());
self.server.borrow_mut().write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.server.borrow_mut().flush()
}
}
impl Source for TcpWrap {
fn deregister(&mut self, registry: &mio::Registry) -> std::io::Result<()> {
self.server.borrow_mut().deregister(registry)
}
fn register(
&mut self,
registry: &mio::Registry,
token: Token,
interests: Interest,
) -> std::io::Result<()> {
self.server
.borrow_mut()
.register(registry, token, interests)
}
fn reregister(
&mut self,
registry: &mio::Registry,
token: Token,
interests: Interest,
) -> std::io::Result<()> {
self.server
.borrow_mut()
.reregister(registry, token, interests)
}
}