dotfiles/agent/src/services/terminal.rs

67 lines
1.6 KiB
Rust
Raw Normal View History

2024-01-30 21:34:19 +00:00
use std::convert::Infallible;
2024-01-29 18:18:29 +00:00
use bytes::Bytes;
use serde::Deserialize;
use tokio::io::AsyncWriteExt;
use tokio_stream::StreamExt;
use tokio_util::codec::{BytesCodec, FramedRead};
2024-01-30 21:34:19 +00:00
use crate::pty::open_shell;
2024-01-29 18:18:29 +00:00
use super::Ctx;
#[derive(Debug, Deserialize)]
2024-01-30 21:34:19 +00:00
pub struct OpenTerminalMessage(Bytes);
2024-01-29 18:18:29 +00:00
impl TryFrom<Bytes> for OpenTerminalMessage {
2024-01-30 21:34:19 +00:00
type Error = Infallible;
2024-01-29 18:18:29 +00:00
fn try_from(value: Bytes) -> Result<Self, Self::Error> {
2024-01-30 21:34:19 +00:00
Ok(Self(value))
2024-01-29 18:18:29 +00:00
}
}
2024-01-30 21:34:19 +00:00
#[derive(Debug, Deserialize)]
pub struct TerminalInput(Bytes);
impl TryFrom<Bytes> for TerminalInput {
type Error = Infallible;
fn try_from(value: Bytes) -> Result<Self, Self::Error> {
Ok(Self(value))
}
}
pub async fn open_terminal(
mut ctx: Ctx<OpenTerminalMessage>,
) -> anyhow::Result<Ctx<OpenTerminalMessage>> {
2024-01-29 18:18:29 +00:00
let pty = crate::pty::Pty::open()?;
2024-01-30 21:34:19 +00:00
let shell = open_shell(pty.child()?, "/bin/bash")?;
2024-01-29 18:18:29 +00:00
2024-01-30 21:34:19 +00:00
let _out_stream = FramedRead::new(pty.try_clone()?, BytesCodec::new()).filter_map(|inner| {
2024-01-29 18:18:29 +00:00
inner
.map(|bytes| bytes.freeze())
.map_err(|err| {
tracing::warn!(%err, "pseudoterminal read error");
})
.ok()
});
2024-01-30 21:34:19 +00:00
ctx.terminals.insert(String::from("test"), (pty, shell));
Ok(ctx)
}
pub async fn terminal_input(
terminal_id: &str,
mut ctx: Ctx<TerminalInput>,
) -> anyhow::Result<Ctx<TerminalInput>> {
let (pty, _) = ctx.terminals.get_mut(terminal_id).unwrap();
if let Err(err) = pty.write_all(&ctx.body.0[..]).await {
tracing::warn!(%err, "pseudoterminal write error");
}
Ok(ctx)
2024-01-29 18:18:29 +00:00
}