Copy stdin/stdout while waiting for sync

This should allow password authentication on ssh connect
This commit is contained in:
John Doty 2022-10-09 08:43:18 -07:00
parent 7f8e14384e
commit d4a8b041dd

View file

@ -161,22 +161,38 @@ async fn server_main<Reader: AsyncRead + Unpin, Writer: AsyncWrite + Unpin>(
} }
} }
async fn client_sync<T: AsyncRead + Unpin>(reader: &mut T) -> Result<()> { async fn client_sync<Read: AsyncRead + Unpin, Write: AsyncWrite + Unpin>(
// TODO: While we're waiting here we should be echoing everything we read. reader: &mut Read,
// We should also be proxying *our* stdin to the processes stdin, writer: &mut Write,
// and turn that off when we've synchronized. That way we can ) -> Result<(), tokio::io::Error> {
// handle passwords and the like for authentication.
eprintln!("> Waiting for synchronization marker..."); eprintln!("> Waiting for synchronization marker...");
// Run these two loops in parallel; the copy of stdin should stop when
// we've seen the marker from the client. If the pipe closes for whatever
// reason then obviously we quit.
let mut stdout = tokio::io::stdout();
tokio::select! {
result = async {
let mut stdin = tokio::io::stdin();
tokio::io::copy(&mut stdin, writer).await
} => match result {
Ok(_) => Ok(()),
Err(e) => Err(e),
},
result = async {
let mut seen = 0; let mut seen = 0;
while seen < 8 { while seen < 8 {
let byte = reader.read_u8().await?; let byte = reader.read_u8().await?;
if byte == 0 { if byte == 0 {
seen += 1; seen += 1;
} else { } else {
tokio::io::stdout().write_u8(byte).await?; stdout.write_u8(byte).await?;
} }
} }
Ok(())
Ok::<_, tokio::io::Error>(())
} => result,
}
} }
async fn client_handle_connection( async fn client_handle_connection(
@ -388,12 +404,10 @@ pub async fn run_client(remote: &str) {
// TODO: Drive a reconnect loop // TODO: Drive a reconnect loop
let mut child = spawn_ssh(remote).await.expect("failed to spawn"); let mut child = spawn_ssh(remote).await.expect("failed to spawn");
let mut writer = MessageWriter::new(BufWriter::new( let mut writer = child
child
.stdin .stdin
.take() .take()
.expect("child did not have a handle to stdout"), .expect("child did not have a handle to stdin");
));
let mut reader = BufReader::new( let mut reader = BufReader::new(
child child
@ -402,11 +416,12 @@ pub async fn run_client(remote: &str) {
.expect("child did not have a handle to stdout"), .expect("child did not have a handle to stdout"),
); );
if let Err(e) = client_sync(&mut reader).await { if let Err(e) = client_sync(&mut reader, &mut writer).await {
eprintln!("Error synchronizing: {:?}", e); eprintln!("Error synchronizing: {:?}", e);
return; return;
} }
let mut writer = MessageWriter::new(BufWriter::new(writer));
let mut reader = MessageReader::new(reader); let mut reader = MessageReader::new(reader);
if let Err(e) = client_main(&mut reader, &mut writer).await { if let Err(e) = client_main(&mut reader, &mut writer).await {
eprintln!("Error: {:?}", e); eprintln!("Error: {:?}", e);