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