sentinelpass_protocol/transport/
mod.rs1#[cfg(unix)]
7pub mod unix;
8#[cfg(windows)]
9pub mod windows;
10
11use std::io;
12
13pub const MAX_MESSAGE_SIZE: usize = 65536;
15
16pub type TransportResult<T> = Result<T, TransportError>;
18
19#[derive(Debug)]
21pub enum TransportError {
22 ConnectionFailed(String),
23 Io(io::Error),
24 MessageTooLarge { size: usize, max: usize },
25 InvalidFormat(String),
26 Encryption(String),
27 Decryption(String),
28 Closed,
29 Timeout,
30 Other(String),
31}
32
33impl std::fmt::Display for TransportError {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 match self {
36 Self::ConnectionFailed(msg) => write!(f, "Connection failed: {}", msg),
37 Self::Io(e) => write!(f, "IO error: {}", e),
38 Self::MessageTooLarge { size, max } => {
39 write!(f, "Message too large: {} bytes (max: {} bytes)", size, max)
40 }
41 Self::InvalidFormat(msg) => write!(f, "Invalid format: {}", msg),
42 Self::Encryption(msg) => write!(f, "Encryption failed: {}", msg),
43 Self::Decryption(msg) => write!(f, "Decryption failed: {}", msg),
44 Self::Closed => write!(f, "Transport closed"),
45 Self::Timeout => write!(f, "Timeout"),
46 Self::Other(msg) => write!(f, "Other: {}", msg),
47 }
48 }
49}
50
51impl std::error::Error for TransportError {
52 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
53 match self {
54 Self::Io(e) => Some(e),
55 _ => None,
56 }
57 }
58}
59
60impl From<io::Error> for TransportError {
61 fn from(err: io::Error) -> Self {
62 Self::Io(err)
63 }
64}
65
66#[derive(Debug, Clone, Default)]
68pub struct TransportConfig {
69 pub unix_socket_path: Option<String>,
71
72 pub windows_pipe_path: Option<String>,
74
75 pub tcp_fallback_addr: Option<String>,
77
78 pub auth_token: Option<String>,
80}
81
82impl TransportConfig {
83 pub fn for_current_platform() -> Self {
85 #[cfg(unix)]
86 {
87 let runtime_dir =
88 std::env::var("XDG_RUNTIME_DIR").unwrap_or_else(|_| "/tmp".to_string());
89 Self {
90 unix_socket_path: Some(format!("{}/sentinelpass.sock", runtime_dir)),
91 ..Default::default()
92 }
93 }
94
95 #[cfg(windows)]
96 {
97 Self {
98 windows_pipe_path: Some(r"\\.\pipe\SentinelPass".to_string()),
99 tcp_fallback_addr: Some("127.0.0.1:35873".to_string()),
100 ..Default::default()
101 }
102 }
103
104 #[cfg(not(any(unix, windows)))]
105 {
106 Self::default()
107 }
108 }
109
110 pub fn with_auth_token(mut self, token: String) -> Self {
112 self.auth_token = Some(token);
113 self
114 }
115
116 pub fn with_unix_socket(mut self, path: String) -> Self {
118 self.unix_socket_path = Some(path);
119 self
120 }
121
122 pub fn with_windows_pipe(mut self, path: String) -> Self {
124 self.windows_pipe_path = Some(path);
125 self
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 #[test]
134 fn test_transport_config_defaults() {
135 let config = TransportConfig::default();
136 assert!(config.unix_socket_path.is_none());
137 assert!(config.windows_pipe_path.is_none());
138 assert!(config.auth_token.is_none());
139 }
140
141 #[test]
142 fn test_transport_config_builder() {
143 let config = TransportConfig::default()
144 .with_auth_token("test_token".to_string())
145 .with_unix_socket("/tmp/test.sock".to_string());
146
147 assert_eq!(config.auth_token, Some("test_token".to_string()));
148 assert_eq!(config.unix_socket_path, Some("/tmp/test.sock".to_string()));
149 }
150
151 #[test]
152 fn test_max_message_size() {
153 assert_eq!(MAX_MESSAGE_SIZE, 65536);
154 }
155
156 #[test]
157 fn test_transport_error_display() {
158 let err = TransportError::ConnectionFailed("test".to_string());
159 assert_eq!(err.to_string(), "Connection failed: test");
160
161 let err = TransportError::MessageTooLarge {
162 size: 100000,
163 max: 65536,
164 };
165 assert_eq!(
166 err.to_string(),
167 "Message too large: 100000 bytes (max: 65536 bytes)"
168 );
169 }
170
171 #[test]
172 fn test_transport_error_from_io() {
173 let io_err = io::Error::new(io::ErrorKind::ConnectionRefused, "test");
174 let transport_err: TransportError = io_err.into();
175 assert!(matches!(transport_err, TransportError::Io(_)));
176 }
177}