atagen

headroom

public
Star0
Watch0
b4f9722db37afb8ec0881327edf1a085c821d6a9
1
ssh://brewery@pls.lobotomise.me:33/atagen/headroom.git

Blame: crates/headroom-ipc/src/lib.rs

dd6b8e786e1fatagen2026-05-27 15:49 UTC1
//! headroom control-protocol types and framing. spec: `IPC.md` (repo root); this is its rust binding.
dd6b8e786e1fatagen2026-05-27 15:49 UTC2
dd6b8e786e1fatagen2026-05-27 15:49 UTC3
#![forbid(unsafe_code)]
dd6b8e786e1fatagen2026-05-27 15:49 UTC4
#![warn(missing_docs)]
dd6b8e786e1fatagen2026-05-27 15:49 UTC5
dd6b8e786e1fatagen2026-05-27 15:49 UTC6
mod codec;
dd6b8e786e1fatagen2026-05-27 15:49 UTC7
mod error;
dd6b8e786e1fatagen2026-05-27 15:49 UTC8
mod proto;
dd6b8e786e1fatagen2026-05-27 15:49 UTC9
dd6b8e786e1fatagen2026-05-27 15:49 UTC10
pub use codec::{Codec, DEFAULT_MAX_FRAME_BYTES, MIN_MAX_FRAME_BYTES};
dd6b8e786e1fatagen2026-05-27 15:49 UTC11
pub use error::{Error, ErrorCode, ProtoError};
dd6b8e786e1fatagen2026-05-27 15:49 UTC12
pub use proto::{
dd6b8e786e1fatagen2026-05-27 15:49 UTC13
    DaemonEvent, Event, HelloData, LayerALevel, LayerASnapshot, MeterTick, Op, ProfileEvent,
dd6b8e786e1fatagen2026-05-27 15:49 UTC14
    ProfileInfo, Request, Response, ResponsePayload, Route, RouteList, RouteRule, RouteRuleMatch,
dd6b8e786e1fatagen2026-05-27 15:49 UTC15
    RoutingEvent, ServerFrame, SinkInfo, Sinks, Status, StreamRoute, Topic,
dd6b8e786e1fatagen2026-05-27 15:49 UTC16
};
dd6b8e786e1fatagen2026-05-27 15:49 UTC17
dd6b8e786e1fatagen2026-05-27 15:49 UTC18
/// wire version; bumped only on incompatible changes.
dd6b8e786e1fatagen2026-05-27 15:49 UTC19
pub const PROTOCOL_VERSION: u32 = 1;
dd6b8e786e1fatagen2026-05-27 15:49 UTC20
dd6b8e786e1fatagen2026-05-27 15:49 UTC21
/// socket dir stem; full path `${XDG_RUNTIME_DIR}/headroom/control.sock`, falling back to `/run/user/$UID/...`.
dd6b8e786e1fatagen2026-05-27 15:49 UTC22
pub const DEFAULT_SOCKET_DIR: &str = "headroom";
dd6b8e786e1fatagen2026-05-27 15:49 UTC23
dd6b8e786e1fatagen2026-05-27 15:49 UTC24
pub const DEFAULT_SOCKET_NAME: &str = "control.sock";
dd6b8e786e1fatagen2026-05-27 15:49 UTC25
dd6b8e786e1fatagen2026-05-27 15:49 UTC26
/// honours `XDG_RUNTIME_DIR`, else falls back to `/run/user/$UID/...`. `None` when neither is determinable.
dd6b8e786e1fatagen2026-05-27 15:49 UTC27
#[must_use]
dd6b8e786e1fatagen2026-05-27 15:49 UTC28
pub fn default_socket_path() -> Option<std::path::PathBuf> {
dd6b8e786e1fatagen2026-05-27 15:49 UTC29
    use std::path::PathBuf;
dd6b8e786e1fatagen2026-05-27 15:49 UTC30
    if let Ok(dir) = std::env::var("XDG_RUNTIME_DIR") {
dd6b8e786e1fatagen2026-05-27 15:49 UTC31
        if !dir.is_empty() {
dd6b8e786e1fatagen2026-05-27 15:49 UTC32
            return Some(
dd6b8e786e1fatagen2026-05-27 15:49 UTC33
                PathBuf::from(dir)
dd6b8e786e1fatagen2026-05-27 15:49 UTC34
                    .join(DEFAULT_SOCKET_DIR)
dd6b8e786e1fatagen2026-05-27 15:49 UTC35
                    .join(DEFAULT_SOCKET_NAME),
dd6b8e786e1fatagen2026-05-27 15:49 UTC36
            );
dd6b8e786e1fatagen2026-05-27 15:49 UTC37
        }
dd6b8e786e1fatagen2026-05-27 15:49 UTC38
    }
dd6b8e786e1fatagen2026-05-27 15:49 UTC39
    // uid from /proc/self/status: nix-free, dependency-light
dd6b8e786e1fatagen2026-05-27 15:49 UTC40
    let uid = read_self_uid()?;
dd6b8e786e1fatagen2026-05-27 15:49 UTC41
    Some(
dd6b8e786e1fatagen2026-05-27 15:49 UTC42
        PathBuf::from(format!("/run/user/{uid}"))
dd6b8e786e1fatagen2026-05-27 15:49 UTC43
            .join(DEFAULT_SOCKET_DIR)
dd6b8e786e1fatagen2026-05-27 15:49 UTC44
            .join(DEFAULT_SOCKET_NAME),
dd6b8e786e1fatagen2026-05-27 15:49 UTC45
    )
dd6b8e786e1fatagen2026-05-27 15:49 UTC46
}
dd6b8e786e1fatagen2026-05-27 15:49 UTC47
dd6b8e786e1fatagen2026-05-27 15:49 UTC48
fn read_self_uid() -> Option<u32> {
dd6b8e786e1fatagen2026-05-27 15:49 UTC49
    let s = std::fs::read_to_string("/proc/self/status").ok()?;
dd6b8e786e1fatagen2026-05-27 15:49 UTC50
    for line in s.lines() {
dd6b8e786e1fatagen2026-05-27 15:49 UTC51
        if let Some(rest) = line.strip_prefix("Uid:") {
dd6b8e786e1fatagen2026-05-27 15:49 UTC52
            let first = rest.split_whitespace().next()?;
dd6b8e786e1fatagen2026-05-27 15:49 UTC53
            return first.parse().ok();
dd6b8e786e1fatagen2026-05-27 15:49 UTC54
        }
dd6b8e786e1fatagen2026-05-27 15:49 UTC55
    }
dd6b8e786e1fatagen2026-05-27 15:49 UTC56
    None
dd6b8e786e1fatagen2026-05-27 15:49 UTC57
}