atagen

headroom

public
Star0
Watch0
ssh://brewery@pls.lobotomise.me:33/atagen/headroom.git
crates/headroom-ipc/src/lib.rsRust57 lines1.9 KB
1
//! headroom control-protocol types and framing. spec: `IPC.md` (repo root); this is its rust binding.
2
3
#![forbid(unsafe_code)]
4
#![warn(missing_docs)]
5
6
mod codec;
7
mod error;
8
mod proto;
9
10
pub use codec::{Codec, DEFAULT_MAX_FRAME_BYTES, MIN_MAX_FRAME_BYTES};
11
pub use error::{Error, ErrorCode, ProtoError};
12
pub use proto::{
13
    DaemonEvent, Event, HelloData, LayerALevel, LayerASnapshot, MeterTick, Op, ProfileEvent,
14
    ProfileInfo, Request, Response, ResponsePayload, Route, RouteList, RouteRule, RouteRuleMatch,
15
    RoutingEvent, ServerFrame, SinkInfo, Sinks, Status, StreamRoute, Topic,
16
};
17
18
/// wire version; bumped only on incompatible changes.
19
pub const PROTOCOL_VERSION: u32 = 1;
20
21
/// socket dir stem; full path `${XDG_RUNTIME_DIR}/headroom/control.sock`, falling back to `/run/user/$UID/...`.
22
pub const DEFAULT_SOCKET_DIR: &str = "headroom";
23
24
pub const DEFAULT_SOCKET_NAME: &str = "control.sock";
25
26
/// honours `XDG_RUNTIME_DIR`, else falls back to `/run/user/$UID/...`. `None` when neither is determinable.
27
#[must_use]
28
pub fn default_socket_path() -> Option<std::path::PathBuf> {
29
    use std::path::PathBuf;
30
    if let Ok(dir) = std::env::var("XDG_RUNTIME_DIR") {
31
        if !dir.is_empty() {
32
            return Some(
33
                PathBuf::from(dir)
34
                    .join(DEFAULT_SOCKET_DIR)
35
                    .join(DEFAULT_SOCKET_NAME),
36
            );
37
        }
38
    }
39
    // uid from /proc/self/status: nix-free, dependency-light
40
    let uid = read_self_uid()?;
41
    Some(
42
        PathBuf::from(format!("/run/user/{uid}"))
43
            .join(DEFAULT_SOCKET_DIR)
44
            .join(DEFAULT_SOCKET_NAME),
45
    )
46
}
47
48
fn read_self_uid() -> Option<u32> {
49
    let s = std::fs::read_to_string("/proc/self/status").ok()?;
50
    for line in s.lines() {
51
        if let Some(rest) = line.strip_prefix("Uid:") {
52
            let first = rest.split_whitespace().next()?;
53
            return first.parse().ok();
54
        }
55
    }
56
    None
57
}