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 #[serde(skip)]
60 Invalid {
61 error: String,
62 },
63}
64
65#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, strum::Display, strum::EnumIs)]
66pub enum IpcResponse {
67 Ok,
68 ConnectOk {
70 version: String,
71 },
72 Yes,
73 No,
74 Error(String),
75 Notifications(Vec<(log::LevelFilter, String)>),
76 ActiveDaemons(Vec<Daemon>),
77 DisabledDaemons(Vec<DaemonId>),
78 DaemonAlreadyRunning,
79 DaemonStart {
80 daemon: Daemon,
81 },
82 DaemonFailed {
83 error: String,
84 },
85 PortConflict {
87 port: u16,
88 process: String,
89 pid: u32,
90 },
91 NoAvailablePort {
93 start_port: u16,
94 attempts: u32,
95 },
96 DaemonReady {
97 daemon: Daemon,
98 },
99 DaemonFailedWithCode {
100 exit_code: Option<i32>,
101 },
102 DaemonWasNotRunning,
104 MdnsSynced,
106 DaemonStopFailed {
108 error: String,
109 },
110 DaemonNotRunning,
112 DaemonNotFound,
113}
114fn fs_name(name: &str) -> Result<Name<'_>> {
115 let path = env::IPC_SOCK_DIR.join(name).with_extension("sock");
116 let fs_name = path.to_fs_name::<GenericFilePath>().into_diagnostic()?;
117 Ok(fs_name)
118}
119
120fn serialize<T: serde::Serialize>(msg: &T) -> Result<Vec<u8>> {
121 if *env::IPC_JSON {
122 serde_json::to_vec(msg)
123 .into_diagnostic()
124 .wrap_err("failed to serialize IPC message as JSON")
125 } else {
126 rmp_serde::to_vec(msg)
127 .into_diagnostic()
128 .wrap_err("failed to serialize IPC message as MessagePack")
129 }
130}
131
132fn deserialize<T: serde::de::DeserializeOwned>(bytes: &[u8]) -> Result<T> {
133 let mut bytes = bytes.to_vec();
134 bytes.pop();
135 let preview = std::str::from_utf8(&bytes).unwrap_or("<binary>");
136 trace!("msg: {preview:?}");
137 if *env::IPC_JSON {
138 serde_json::from_slice(&bytes)
139 .into_diagnostic()
140 .wrap_err("failed to deserialize IPC JSON response")
141 } else {
142 rmp_serde::from_slice(&bytes)
143 .into_diagnostic()
144 .wrap_err("failed to deserialize IPC MessagePack response")
145 }
146}