1use crate::{util::run_ssh2_fn, Error};
2use futures::prelude::*;
3use smol::Async;
4use ssh2::{self, ExitSignal, ExtendedData, PtyModes, ReadWindow, Stream, WriteWindow};
5use std::{
6 convert::From,
7 io,
8 io::{Read, Write},
9 net::TcpStream,
10 pin::Pin,
11 sync::Arc,
12 task::{Context, Poll},
13};
14
15pub struct Channel {
17 inner: ssh2::Channel,
18 stream: Arc<Async<TcpStream>>,
19}
20
21impl Channel {
22 pub(crate) fn new(channel: ssh2::Channel, stream: Arc<Async<TcpStream>>) -> Self {
23 Self {
24 inner: channel,
25 stream,
26 }
27 }
28
29 pub async fn setenv(&mut self, var: &str, val: &str) -> Result<(), Error> {
31 run_ssh2_fn(&self.stream.clone(), || self.inner.setenv(var, val)).await
32 }
33
34 pub async fn request_pty(
36 &mut self,
37 term: &str,
38 mode: Option<PtyModes>,
39 dim: Option<(u32, u32, u32, u32)>,
40 ) -> Result<(), Error> {
41 run_ssh2_fn(&self.stream.clone(), || {
42 self.inner.request_pty(term, mode.clone(), dim)
43 })
44 .await
45 }
46
47 pub async fn request_pty_size(
49 &mut self,
50 width: u32,
51 height: u32,
52 width_px: Option<u32>,
53 height_px: Option<u32>,
54 ) -> Result<(), Error> {
55 run_ssh2_fn(&self.stream.clone(), || {
56 self.inner
57 .request_pty_size(width, height, width_px, height_px)
58 })
59 .await
60 }
61
62 pub async fn exec(&mut self, command: &str) -> Result<(), Error> {
64 run_ssh2_fn(&self.stream.clone(), || self.inner.exec(command)).await
65 }
66
67 pub async fn shell(&mut self) -> Result<(), Error> {
69 run_ssh2_fn(&self.stream.clone(), || self.inner.shell()).await
70 }
71
72 pub async fn subsystem(&mut self, system: &str) -> Result<(), Error> {
74 run_ssh2_fn(&self.stream.clone(), || self.inner.subsystem(system)).await
75 }
76
77 pub async fn process_startup(
79 &mut self,
80 request: &str,
81 message: Option<&str>,
82 ) -> Result<(), Error> {
83 run_ssh2_fn(&self.stream.clone(), || {
84 self.inner.process_startup(request, message)
85 })
86 .await
87 }
88
89 pub fn stderr(&mut self) -> Stream {
91 self.inner.stderr()
92 }
93
94 pub fn stream(&mut self, stream_id: i32) -> Stream {
96 self.inner.stream(stream_id)
97 }
98
99 pub async fn handle_extended_data(&mut self, mode: ExtendedData) -> Result<(), Error> {
101 run_ssh2_fn(&self.stream.clone(), || {
102 self.inner.handle_extended_data(mode)
103 })
104 .await
105 }
106
107 pub fn exit_status(&self) -> Result<i32, Error> {
109 self.inner.exit_status().map_err(From::from)
110 }
111
112 pub fn exit_signal(&self) -> Result<ExitSignal, Error> {
114 self.inner.exit_signal().map_err(From::from)
115 }
116
117 pub fn read_window(&self) -> ReadWindow {
119 self.inner.read_window()
120 }
121
122 pub fn write_window(&self) -> WriteWindow {
124 self.inner.write_window()
125 }
126
127 pub async fn adjust_receive_window(&mut self, adjust: u64, force: bool) -> Result<u64, Error> {
129 run_ssh2_fn(&self.stream.clone(), || {
130 self.inner.adjust_receive_window(adjust, force)
131 })
132 .await
133 }
134
135 pub fn eof(&self) -> bool {
137 self.inner.eof()
138 }
139
140 pub async fn send_eof(&mut self) -> Result<(), Error> {
142 run_ssh2_fn(&self.stream.clone(), || self.inner.send_eof()).await
143 }
144
145 pub async fn wait_eof(&mut self) -> Result<(), Error> {
147 run_ssh2_fn(&self.stream.clone(), || self.inner.wait_eof()).await
148 }
149
150 pub async fn close(&mut self) -> Result<(), Error> {
152 run_ssh2_fn(&self.stream.clone(), || self.inner.close()).await
153 }
154
155 pub async fn wait_close(&mut self) -> Result<(), Error> {
157 run_ssh2_fn(&self.stream.clone(), || self.inner.wait_close()).await
158 }
159}
160
161impl AsyncRead for Channel {
162 fn poll_read(
163 mut self: Pin<&mut Self>,
164 cx: &mut Context<'_>,
165 buf: &mut [u8],
166 ) -> Poll<io::Result<usize>> {
167 self.stream
168 .clone()
169 .read_with(|_s| self.inner.read(buf))
170 .boxed()
171 .poll_unpin(cx)
172 }
173}
174
175impl AsyncWrite for Channel {
176 fn poll_write(
177 mut self: Pin<&mut Self>,
178 cx: &mut Context<'_>,
179 buf: &[u8],
180 ) -> Poll<Result<usize, io::Error>> {
181 self.stream
182 .clone()
183 .write_with(|_s| self.inner.write(buf))
184 .boxed()
185 .poll_unpin(cx)
186 }
187
188 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
189 self.stream
190 .clone()
191 .write_with(|_s| self.inner.flush())
192 .boxed()
193 .poll_unpin(cx)
194 }
195
196 fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
197 self.stream
198 .clone()
199 .write_with(|_s| self.inner.close().map_err(|e| io::Error::from(ssh2::Error::from_errno(e.code()))))
200 .boxed()
201 .poll_unpin(cx)
202 }
203}
204
205