1use std::path::PathBuf;
4use tokio::net::UnixStream;
5
6#[derive(Debug, Clone)]
8pub struct PeerCredentials {
9 pub pid: u32,
11 pub uid: u32,
13}
14
15impl PeerCredentials {
16 #[must_use]
21 pub fn in_process() -> Self {
22 Self {
23 pid: std::process::id(),
24 uid: u32::MAX,
25 }
26 }
27}
28
29#[must_use]
34pub fn local_credentials() -> PeerCredentials {
35 PeerCredentials {
36 pid: std::process::id(),
37 uid: current_uid(),
38 }
39}
40
41pub fn extract_ucred(stream: &UnixStream) -> core_types::Result<PeerCredentials> {
51 let cred = stream
52 .peer_cred()
53 .map_err(|e| core_types::Error::Ipc(format!("UCred extraction failed: {e}")))?;
54 let pid = cred
55 .pid()
56 .and_then(|p| u32::try_from(p).ok())
57 .ok_or_else(|| core_types::Error::Ipc("UCred: PID unavailable".into()))?;
58 Ok(PeerCredentials {
59 pid,
60 uid: cred.uid(),
61 })
62}
63
64#[cfg(unix)]
68fn current_uid() -> u32 {
69 rustix::process::getuid().as_raw()
70}
71
72#[cfg(not(unix))]
73fn current_uid() -> u32 {
74 0
75}
76
77pub fn socket_path() -> core_types::Result<PathBuf> {
84 #[cfg(target_os = "linux")]
85 {
86 let runtime = std::env::var("XDG_RUNTIME_DIR").map_err(|_| {
87 core_types::Error::Platform(
88 "XDG_RUNTIME_DIR is not set; cannot determine IPC socket path".into(),
89 )
90 })?;
91 Ok(PathBuf::from(runtime).join("pds/bus.sock"))
92 }
93
94 #[cfg(target_os = "macos")]
95 {
96 let home = dirs::home_dir()
97 .ok_or_else(|| core_types::Error::Platform("cannot determine home directory".into()))?;
98 Ok(home.join("Library/Application Support/pds/bus.sock"))
99 }
100
101 #[cfg(target_os = "windows")]
102 {
103 Ok(PathBuf::from(r"\\.\pipe\pds\bus"))
104 }
105
106 #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
107 {
108 Err(core_types::Error::Platform(
109 "unsupported platform: cannot determine IPC socket path".into(),
110 ))
111 }
112}