gardesk/garnotify / 170dbaf

Browse files

garnotifyctl: add IPC client

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
170dbafa454e8e819a7210442023088ad544fa98
Parents
e51733b
Tree
39880bf

1 changed file

StatusFile+-
A garnotifyctl/src/ipc.rs 78 0
garnotifyctl/src/ipc.rsadded
@@ -0,0 +1,78 @@
1
+//! IPC client for garnotifyctl
2
+
3
+use anyhow::{Context, Result};
4
+use serde::{Deserialize, Serialize};
5
+use std::io::{BufRead, BufReader, Write};
6
+use std::os::unix::net::UnixStream;
7
+use std::path::PathBuf;
8
+
9
+/// Get the path to the IPC socket
10
+fn socket_path() -> PathBuf {
11
+    dirs::runtime_dir()
12
+        .unwrap_or_else(|| PathBuf::from("/tmp"))
13
+        .join("garnotify.sock")
14
+}
15
+
16
+/// IPC commands (must match daemon's Command enum)
17
+#[derive(Debug, Clone, Serialize, Deserialize)]
18
+#[serde(tag = "command", rename_all = "snake_case")]
19
+pub enum Command {
20
+    Close {
21
+        #[serde(default)]
22
+        id: Option<u32>,
23
+    },
24
+    CloseAll,
25
+    HistoryPop,
26
+    HistoryClear,
27
+    SetPaused {
28
+        paused: bool,
29
+        #[serde(default)]
30
+        level: u8,
31
+    },
32
+    IsPaused,
33
+    Count,
34
+    List,
35
+    RuleEnable {
36
+        name: String,
37
+    },
38
+    RuleDisable {
39
+        name: String,
40
+    },
41
+    Reload,
42
+    Status,
43
+    Quit,
44
+}
45
+
46
+/// IPC response
47
+#[derive(Debug, Clone, Serialize, Deserialize)]
48
+pub struct Response {
49
+    pub success: bool,
50
+    pub message: Option<String>,
51
+    pub data: Option<serde_json::Value>,
52
+}
53
+
54
+/// Send a command to the running daemon
55
+pub fn send_command(cmd: &Command) -> Result<Response> {
56
+    let path = socket_path();
57
+
58
+    if !path.exists() {
59
+        anyhow::bail!("garnotify daemon not running (socket not found at {})", path.display());
60
+    }
61
+
62
+    let mut stream =
63
+        UnixStream::connect(&path).with_context(|| "Failed to connect to garnotify daemon")?;
64
+
65
+    let cmd_json = serde_json::to_string(cmd)?;
66
+    writeln!(stream, "{}", cmd_json)?;
67
+    stream.flush()?;
68
+
69
+    // Read response
70
+    let mut reader = BufReader::new(stream);
71
+    let mut response_line = String::new();
72
+    reader.read_line(&mut response_line)?;
73
+
74
+    let response: Response = serde_json::from_str(&response_line)
75
+        .with_context(|| "Failed to parse response from daemon")?;
76
+
77
+    Ok(response)
78
+}