1use std::path::PathBuf;
2
3use serde::Serialize;
4use serde::de::DeserializeOwned;
5use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
6use tokio::net::{UnixListener, UnixStream};
7
8use crate::session::scoping::session_dir;
9
10pub fn socket_path(session_key: &str) -> PathBuf {
13 let short_key = &session_key[..session_key.len().min(12)];
14 session_dir().join(format!("{short_key}.sock"))
15}
16
17pub async fn start_ipc_server(session_key: &str) -> std::io::Result<UnixListener> {
22 let path = socket_path(session_key);
23 if let Some(parent) = path.parent() {
25 std::fs::create_dir_all(parent)?;
26 }
27 let _ = std::fs::remove_file(&path);
29 UnixListener::bind(&path)
30}
31
32pub async fn connect_ipc(session_key: &str) -> std::io::Result<UnixStream> {
34 let path = socket_path(session_key);
35 UnixStream::connect(&path).await
36}
37
38pub async fn send_message<T: Serialize>(stream: &mut UnixStream, msg: &T) -> std::io::Result<()> {
40 let json = serde_json::to_string(msg)
41 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
42 stream.write_all(json.as_bytes()).await?;
43 stream.write_all(b"\n").await?;
44 stream.flush().await
45}
46
47pub async fn recv_message<T: DeserializeOwned>(
51 reader: &mut BufReader<UnixStream>,
52) -> std::io::Result<Option<T>> {
53 let mut line = String::new();
54 let n = reader.read_line(&mut line).await?;
55 if n == 0 {
56 return Ok(None);
57 }
58 let msg = serde_json::from_str(&line)
59 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
60 Ok(Some(msg))
61}
62
63pub fn cleanup_socket(session_key: &str) {
65 let _ = std::fs::remove_file(socket_path(session_key));
66}