use crate::{SocketRequest, SocketResponse};
use std::io::{self, BufRead, BufReader, ErrorKind, Read, Write};
use std::net::Shutdown;
use std::os::unix::net::UnixStream;
use std::path::Path;
use std::time::Duration;
const RESPONSE_LIMIT: u64 = 64 * 1024;
pub fn send_socket_request(socket_path: &Path, request: &SocketRequest) -> io::Result<String> {
let mut stream = UnixStream::connect(socket_path).map_err(|error| {
io::Error::new(
error.kind(),
format!(
"cannot connect to {}: {error}; is `hxr --listen` running?",
socket_path.display()
),
)
})?;
stream.set_read_timeout(Some(Duration::from_secs(10)))?;
stream.set_write_timeout(Some(Duration::from_secs(10)))?;
serde_json::to_writer(&mut stream, request)
.map_err(|error| io::Error::new(ErrorKind::InvalidData, error))?;
stream.write_all(b"\n")?;
stream.flush()?;
stream.shutdown(Shutdown::Write)?;
let mut response_bytes = Vec::new();
BufReader::new(stream)
.take(RESPONSE_LIMIT + 1)
.read_until(b'\n', &mut response_bytes)?;
if response_bytes.len() as u64 > RESPONSE_LIMIT {
return Err(io::Error::new(
ErrorKind::InvalidData,
"bridge response was unexpectedly large",
));
}
if response_bytes.is_empty() {
return Err(io::Error::new(
ErrorKind::UnexpectedEof,
"bridge closed the connection without a response",
));
}
let response: SocketResponse = serde_json::from_slice(&response_bytes)
.map_err(|error| io::Error::new(ErrorKind::InvalidData, error))?;
if response.ok {
Ok(response.message)
} else {
Err(io::Error::other(response.message))
}
}