More reliable stderr piping when disconnected
This commit is contained in:
parent
1308f8828a
commit
c6acf52b32
2 changed files with 38 additions and 21 deletions
37
src/lib.rs
37
src/lib.rs
|
|
@ -1,4 +1,5 @@
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
|
use bytes::BytesMut;
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
use message::{Message, MessageReader, MessageWriter};
|
use message::{Message, MessageReader, MessageWriter};
|
||||||
|
|
@ -84,12 +85,17 @@ async fn client_sync<S: AsyncRead + Unpin, T: AsyncRead + Unpin>(
|
||||||
|
|
||||||
let mut stderr = tokio::io::stderr();
|
let mut stderr = tokio::io::stderr();
|
||||||
let mut stdout = tokio::io::stdout();
|
let mut stdout = tokio::io::stdout();
|
||||||
|
let mut buf = BytesMut::with_capacity(1024);
|
||||||
|
|
||||||
let mut seen = 0;
|
let mut seen = 0;
|
||||||
tokio::select! {
|
let result = tokio::select! {
|
||||||
result = tokio::io::copy(client_stderr, &mut stderr) => match result {
|
result = async {
|
||||||
Ok(_) => Ok(()), // ?
|
loop {
|
||||||
Err(e) => Err(e),
|
buf.clear();
|
||||||
},
|
client_stderr.read_buf(&mut buf).await?;
|
||||||
|
stderr.write_all(&buf[..]).await?;
|
||||||
|
}
|
||||||
|
} => result,
|
||||||
result = async {
|
result = async {
|
||||||
while seen < 8 {
|
while seen < 8 {
|
||||||
let byte = reader.read_u8().await?;
|
let byte = reader.read_u8().await?;
|
||||||
|
|
@ -103,7 +109,17 @@ async fn client_sync<S: AsyncRead + Unpin, T: AsyncRead + Unpin>(
|
||||||
|
|
||||||
Ok::<_, tokio::io::Error>(())
|
Ok::<_, tokio::io::Error>(())
|
||||||
} => result,
|
} => result,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(_) = result {
|
||||||
|
// Something went wrong, let's just make sure we flush the client's
|
||||||
|
// stderr before we return.
|
||||||
|
_ = stderr.write_all(&buf[..]).await;
|
||||||
|
_ = tokio::io::copy(client_stderr, &mut stderr).await;
|
||||||
|
_ = stderr.flush().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle an incoming client connection, by forwarding it to the SOCKS5
|
/// Handle an incoming client connection, by forwarding it to the SOCKS5
|
||||||
|
|
@ -356,12 +372,10 @@ async fn client_connect_loop(remote: &str, events: mpsc::Sender<ui::UIEvent>) {
|
||||||
let (mut child, socks_port) =
|
let (mut child, socks_port) =
|
||||||
spawn_ssh(remote).await.expect("failed to spawn");
|
spawn_ssh(remote).await.expect("failed to spawn");
|
||||||
|
|
||||||
let mut stderr = BufReader::new(
|
let mut stderr = child
|
||||||
child
|
.stderr
|
||||||
.stderr
|
.take()
|
||||||
.take()
|
.expect("child did not have a handle to stderr");
|
||||||
.expect("child did not have a handle to stderr"),
|
|
||||||
);
|
|
||||||
|
|
||||||
let writer = child
|
let writer = child
|
||||||
.stdin
|
.stdin
|
||||||
|
|
@ -395,6 +409,7 @@ async fn client_connect_loop(remote: &str, events: mpsc::Sender<ui::UIEvent>) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut stderr = BufReader::new(stderr);
|
||||||
let mut writer = MessageWriter::new(BufWriter::new(writer));
|
let mut writer = MessageWriter::new(BufWriter::new(writer));
|
||||||
let mut reader = MessageReader::new(reader);
|
let mut reader = MessageReader::new(reader);
|
||||||
|
|
||||||
|
|
|
||||||
22
src/ui.rs
22
src/ui.rs
|
|
@ -2,7 +2,7 @@ use crate::client_listen;
|
||||||
use crate::message::PortDesc;
|
use crate::message::PortDesc;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
cursor::MoveTo,
|
cursor::{MoveTo, RestorePosition, SavePosition},
|
||||||
event::{Event, EventStream, KeyCode, KeyEvent, KeyModifiers},
|
event::{Event, EventStream, KeyCode, KeyEvent, KeyModifiers},
|
||||||
execute, queue,
|
execute, queue,
|
||||||
style::{Color, PrintStyledContent, Stylize},
|
style::{Color, PrintStyledContent, Stylize},
|
||||||
|
|
@ -88,14 +88,6 @@ impl UI {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run(&mut self) -> Result<()> {
|
pub async fn run(&mut self) -> Result<()> {
|
||||||
self.enter_alternate_screen()?;
|
|
||||||
let result = self.run_core().await;
|
|
||||||
_ = self.disable_raw_mode();
|
|
||||||
_ = self.leave_alternate_screen();
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn run_core(&mut self) -> Result<()> {
|
|
||||||
let mut console_events = EventStream::new();
|
let mut console_events = EventStream::new();
|
||||||
|
|
||||||
self.running = true;
|
self.running = true;
|
||||||
|
|
@ -113,6 +105,7 @@ impl UI {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_disconnected(&mut self) -> Result<()> {
|
fn render_disconnected(&mut self) -> Result<()> {
|
||||||
|
self.enter_alternate_screen()?;
|
||||||
self.disable_raw_mode()?;
|
self.disable_raw_mode()?;
|
||||||
let mut stdout = stdout();
|
let mut stdout = stdout();
|
||||||
|
|
||||||
|
|
@ -121,18 +114,20 @@ impl UI {
|
||||||
|
|
||||||
execute!(
|
execute!(
|
||||||
stdout,
|
stdout,
|
||||||
Clear(ClearType::All),
|
SavePosition,
|
||||||
MoveTo(0, 0),
|
MoveTo(0, 0),
|
||||||
PrintStyledContent(
|
PrintStyledContent(
|
||||||
format!("{:^columns$}\r\n", "Not Connected")
|
format!("{:^columns$}\r\n", "Not Connected")
|
||||||
.with(Color::Black)
|
.with(Color::Black)
|
||||||
.on(Color::Red)
|
.on(Color::Red)
|
||||||
),
|
),
|
||||||
|
RestorePosition,
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_connected(&mut self) -> Result<()> {
|
fn render_connected(&mut self) -> Result<()> {
|
||||||
|
self.enter_alternate_screen()?;
|
||||||
self.enable_raw_mode()?;
|
self.enable_raw_mode()?;
|
||||||
let mut stdout = stdout();
|
let mut stdout = stdout();
|
||||||
|
|
||||||
|
|
@ -404,3 +399,10 @@ impl UI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for UI {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
_ = self.disable_raw_mode();
|
||||||
|
_ = self.leave_alternate_screen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue