2024-02-23 03:25:06 +00:00
|
|
|
use std::{
|
|
|
|
io::{stdin, stdout},
|
|
|
|
os::fd::{AsRawFd, FromRawFd},
|
|
|
|
};
|
|
|
|
|
|
|
|
use anyhow::Result;
|
2024-03-05 11:35:25 +00:00
|
|
|
use krata::{
|
|
|
|
control::{ConsoleStreamUpdate, StreamUpdate},
|
|
|
|
stream::StreamContext,
|
|
|
|
};
|
2024-02-23 05:26:32 +00:00
|
|
|
use log::debug;
|
2024-02-23 03:25:06 +00:00
|
|
|
use std::process::exit;
|
|
|
|
use termion::raw::IntoRawMode;
|
|
|
|
use tokio::{
|
|
|
|
fs::File,
|
|
|
|
io::{AsyncReadExt, AsyncWriteExt},
|
2024-03-05 11:35:25 +00:00
|
|
|
select,
|
2024-02-23 03:25:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
pub struct XenConsole {
|
2024-03-05 11:35:25 +00:00
|
|
|
stream: StreamContext,
|
2024-02-23 03:25:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl XenConsole {
|
2024-03-05 11:35:25 +00:00
|
|
|
pub async fn new(stream: StreamContext) -> Result<XenConsole> {
|
|
|
|
Ok(XenConsole { stream })
|
2024-02-23 03:25:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn attach(self) -> Result<()> {
|
2024-03-05 11:35:25 +00:00
|
|
|
let stdin = unsafe { File::from_raw_fd(stdin().as_raw_fd()) };
|
2024-02-23 03:25:06 +00:00
|
|
|
let terminal = stdout().into_raw_mode()?;
|
|
|
|
let stdout = unsafe { File::from_raw_fd(terminal.as_raw_fd()) };
|
|
|
|
|
2024-03-05 11:35:25 +00:00
|
|
|
if let Err(error) = XenConsole::process(stdin, stdout, self.stream).await {
|
|
|
|
debug!("failed to process console stream: {}", error);
|
2024-02-23 03:25:06 +00:00
|
|
|
}
|
2024-03-05 11:35:25 +00:00
|
|
|
|
|
|
|
Ok(())
|
2024-02-23 03:25:06 +00:00
|
|
|
}
|
|
|
|
|
2024-03-05 11:35:25 +00:00
|
|
|
async fn process(mut stdin: File, mut stdout: File, mut stream: StreamContext) -> Result<()> {
|
2024-02-23 03:25:06 +00:00
|
|
|
let mut buffer = vec![0u8; 60];
|
|
|
|
loop {
|
2024-03-05 11:35:25 +00:00
|
|
|
select! {
|
|
|
|
x = stream.receiver.recv() => match x {
|
|
|
|
Some(StreamUpdate::ConsoleStream(update)) => {
|
|
|
|
stdout.write_all(&update.data).await?;
|
|
|
|
stdout.flush().await?;
|
|
|
|
},
|
|
|
|
|
|
|
|
None => {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
x = stdin.read(&mut buffer) => match x {
|
|
|
|
Ok(size) => {
|
|
|
|
if size == 1 && buffer[0] == 0x1d {
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
let data = buffer[0..size].to_vec();
|
|
|
|
stream.send(StreamUpdate::ConsoleStream(ConsoleStreamUpdate {
|
|
|
|
data,
|
|
|
|
})).await?;
|
|
|
|
},
|
|
|
|
|
|
|
|
Err(error) => {
|
|
|
|
return Err(error.into());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2024-02-23 03:25:06 +00:00
|
|
|
}
|
2024-03-05 11:35:25 +00:00
|
|
|
Ok(())
|
2024-02-23 03:25:06 +00:00
|
|
|
}
|
|
|
|
}
|