use std::path::PathBuf;
use serde::Serialize;
use serde::de::DeserializeOwned;
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
use tokio::net::{UnixListener, UnixStream};
use crate::session::scoping::session_dir;
pub fn socket_path(session_key: &str) -> PathBuf {
let short_key = &session_key[..session_key.len().min(12)];
session_dir().join(format!("{short_key}.sock"))
}
pub async fn start_ipc_server(session_key: &str) -> std::io::Result<UnixListener> {
let path = socket_path(session_key);
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)?;
}
let _ = std::fs::remove_file(&path);
UnixListener::bind(&path)
}
pub async fn connect_ipc(session_key: &str) -> std::io::Result<UnixStream> {
let path = socket_path(session_key);
UnixStream::connect(&path).await
}
pub async fn send_message<T: Serialize>(stream: &mut UnixStream, msg: &T) -> std::io::Result<()> {
let json = serde_json::to_string(msg)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
stream.write_all(json.as_bytes()).await?;
stream.write_all(b"\n").await?;
stream.flush().await
}
pub async fn recv_message<T: DeserializeOwned>(
reader: &mut BufReader<UnixStream>,
) -> std::io::Result<Option<T>> {
let mut line = String::new();
let n = reader.read_line(&mut line).await?;
if n == 0 {
return Ok(None);
}
let msg = serde_json::from_str(&line)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
Ok(Some(msg))
}
pub fn cleanup_socket(session_key: &str) {
let _ = std::fs::remove_file(socket_path(session_key));
}