taiga_plugin_api/daemon/
socket.rs1use interprocess::local_socket::traits::tokio::Stream as _;
6use interprocess::local_socket::{
7 GenericFilePath, GenericNamespaced, ListenerOptions, ToFsName, ToNsName,
8 tokio::Listener, tokio::Stream,
9};
10use crate::PluginError;
11
12pub fn create_listener(path: &str) -> Result<Listener, PluginError> {
17 let listener = if cfg!(windows) {
18 let name = path
19 .to_ns_name::<GenericNamespaced>()
20 .map_err(|e| PluginError::ipc_connection(format!("Invalid socket name: {}", e)))?;
21 ListenerOptions::new()
22 .name(name)
23 .create_tokio()
24 .map_err(|e| PluginError::ipc_connection(format!("Failed to create listener: {}", e)))?
25 } else {
26 let name = path
27 .to_fs_name::<GenericFilePath>()
28 .map_err(|e| PluginError::ipc_connection(format!("Invalid socket name: {}", e)))?;
29 ListenerOptions::new()
30 .name(name)
31 .create_tokio()
32 .map_err(|e| PluginError::ipc_connection(format!("Failed to create listener: {}", e)))?
33 };
34 Ok(listener)
35}
36
37pub async fn connect(path: &str) -> Result<Stream, PluginError> {
42 let stream = if cfg!(windows) {
43 let name = path
44 .to_ns_name::<GenericNamespaced>()
45 .map_err(|e| PluginError::ipc_connection(format!("Invalid socket name: {}", e)))?;
46 Stream::connect(name)
47 .await
48 .map_err(|e| PluginError::ipc_connection(format!("Connection failed: {}", e)))?
49 } else {
50 let name = path
51 .to_fs_name::<GenericFilePath>()
52 .map_err(|e| PluginError::ipc_connection(format!("Invalid socket name: {}", e)))?;
53 Stream::connect(name)
54 .await
55 .map_err(|e| PluginError::ipc_connection(format!("Connection failed: {}", e)))?
56 };
57 Ok(stream)
58}
59
60pub fn cleanup_socket(path: &str) {
64 if !cfg!(windows) && std::fs::metadata(path).is_ok() {
65 std::fs::remove_file(path).ok();
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn test_cleanup_nonexistent_socket() {
75 cleanup_socket("/nonexistent/socket/path");
77 }
78}