66 lines
1.6 KiB
Rust
66 lines
1.6 KiB
Rust
use std::convert::Infallible;
|
|
|
|
use bytes::Bytes;
|
|
use serde::Deserialize;
|
|
use tokio::io::AsyncWriteExt;
|
|
use tokio_stream::StreamExt;
|
|
use tokio_util::codec::{BytesCodec, FramedRead};
|
|
|
|
use crate::pty::open_shell;
|
|
|
|
use super::Ctx;
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct OpenTerminalMessage(Bytes);
|
|
|
|
impl TryFrom<Bytes> for OpenTerminalMessage {
|
|
type Error = Infallible;
|
|
|
|
fn try_from(value: Bytes) -> Result<Self, Self::Error> {
|
|
Ok(Self(value))
|
|
}
|
|
}
|
|
|
|
#[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>> {
|
|
let pty = crate::pty::Pty::open()?;
|
|
let shell = open_shell(pty.child()?, "/bin/bash")?;
|
|
|
|
let _out_stream = FramedRead::new(pty.try_clone()?, BytesCodec::new()).filter_map(|inner| {
|
|
inner
|
|
.map(|bytes| bytes.freeze())
|
|
.map_err(|err| {
|
|
tracing::warn!(%err, "pseudoterminal read error");
|
|
})
|
|
.ok()
|
|
});
|
|
|
|
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)
|
|
}
|