1use crate::Result;
2use crate::daemon::{Daemon, RunOptions};
3use crate::daemon_id::DaemonId;
4use crate::env;
5use interprocess::local_socket::{GenericFilePath, Name, ToFsName};
6use miette::{Context, IntoDiagnostic};
7use std::path::PathBuf;
8
9pub(crate) mod batch;
10pub(crate) mod client;
11pub(crate) mod server;
12
13#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, strum::Display, strum::EnumIs)]
28#[allow(clippy::large_enum_variant)]
29pub enum IpcRequest {
30 Connect,
31 ConnectV2 {
35 version: String,
36 },
37 Clean,
38 Stop {
39 id: DaemonId,
40 },
41 GetActiveDaemons,
42 GetDisabledDaemons,
43 Run(RunOptions),
44 Enable {
45 id: DaemonId,
46 },
47 Disable {
48 id: DaemonId,
49 },
50 UpdateShellDir {
51 shell_pid: u32,
52 dir: PathBuf,
53 },
54 GetNotifications,
55 SyncMdns,
58 ReloadConfig,
61 #[serde(skip)]
63 Invalid {
64 error: String,
65 },
66}
67
68#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, strum::Display, strum::EnumIs)]
69pub enum IpcResponse {
70 Ok,
71 ConnectOk {
73 version: String,
74 },
75 Yes,
76 No,
77 Error(String),
78 Notifications(Vec<(log::LevelFilter, String)>),
79 ActiveDaemons(Vec<Daemon>),
80 DisabledDaemons(Vec<DaemonId>),
81 DaemonAlreadyRunning,
82 DaemonStart {
83 daemon: Daemon,
84 },
85 DaemonFailed {
86 error: String,
87 },
88 PortConflict {
90 port: u16,
91 process: String,
92 pid: u32,
93 },
94 NoAvailablePort {
96 start_port: u16,
97 attempts: u32,
98 },
99 DaemonReady {
100 daemon: Daemon,
101 },
102 DaemonFailedWithCode {
103 exit_code: Option<i32>,
104 },
105 DaemonWasNotRunning,
107 MdnsSynced,
109 ConfigReloaded,
111 DaemonStopFailed {
113 error: String,
114 },
115 DaemonNotRunning,
117 DaemonNotFound,
118}
119fn fs_name(name: &str) -> Result<Name<'_>> {
120 let path = env::IPC_SOCK_DIR.join(name).with_extension("sock");
121 let fs_name = path.to_fs_name::<GenericFilePath>().into_diagnostic()?;
122 Ok(fs_name)
123}
124
125fn serialize<T: serde::Serialize>(msg: &T) -> Result<Vec<u8>> {
126 if *env::IPC_JSON {
127 serde_json::to_vec(msg)
128 .into_diagnostic()
129 .wrap_err("failed to serialize IPC message as JSON")
130 } else {
131 rmp_serde::to_vec(msg)
132 .into_diagnostic()
133 .wrap_err("failed to serialize IPC message as MessagePack")
134 }
135}
136
137fn deserialize<T: serde::de::DeserializeOwned>(bytes: &[u8]) -> Result<T> {
138 let mut bytes = bytes.to_vec();
139 bytes.pop();
140 let preview = std::str::from_utf8(&bytes).unwrap_or("<binary>");
141 trace!("msg: {preview:?}");
142 if *env::IPC_JSON {
143 serde_json::from_slice(&bytes)
144 .into_diagnostic()
145 .wrap_err("failed to deserialize IPC JSON response")
146 } else {
147 rmp_serde::from_slice(&bytes)
148 .into_diagnostic()
149 .wrap_err("failed to deserialize IPC MessagePack response")
150 }
151}