Skip to main content

agent_graph_mcp/
proxy.rs

1//! Framing and stdio/Unix transport helpers for the thin proxy.
2use std::io::{self, Read, Write};
3use std::os::unix::net::UnixStream;
4
5pub const MAX_FRAME: usize = 1024 * 1024;
6
7#[derive(Debug)]
8#[allow(dead_code)]
9pub enum ProxyError {
10    DaemonUnavailable,
11    FrameTooLarge,
12    Io(io::Error),
13}
14
15impl From<io::Error> for ProxyError {
16    fn from(e: io::Error) -> Self {
17        Self::Io(e)
18    }
19}
20
21pub fn connect(path: &std::path::Path) -> Result<UnixStream, ProxyError> {
22    connect_timeout(path, 2000)
23}
24
25pub fn connect_timeout(path: &std::path::Path, timeout_ms: u64) -> Result<UnixStream, ProxyError> {
26    let stream = UnixStream::connect(path).map_err(|_| ProxyError::DaemonUnavailable)?;
27    stream.set_read_timeout(Some(std::time::Duration::from_millis(timeout_ms)))?;
28    Ok(stream)
29}
30
31pub fn read_frame<R: Read>(r: &mut R) -> Result<Vec<u8>, ProxyError> {
32    let mut n = [0u8; 4];
33    r.read_exact(&mut n)?;
34    let len = u32::from_be_bytes(n) as usize;
35    if len > MAX_FRAME {
36        return Err(ProxyError::FrameTooLarge);
37    }
38    let mut b = vec![0; len];
39    r.read_exact(&mut b)?;
40    Ok(b)
41}
42
43pub fn write_frame<W: Write>(w: &mut W, payload: &[u8]) -> Result<(), ProxyError> {
44    if payload.len() > MAX_FRAME {
45        return Err(ProxyError::FrameTooLarge);
46    }
47    w.write_all(&(payload.len() as u32).to_be_bytes())?;
48    w.write_all(payload)?;
49    w.flush()?;
50    Ok(())
51}