1use std::path::PathBuf;
4
5#[cfg(feature = "transport")]
7#[derive(Debug, thiserror::Error)]
8pub enum TransportError {
9 #[error("failed to bind transport endpoint")]
11 EndpointBind {
12 #[source]
13 source: iroh::endpoint::BindError,
14 },
15
16 #[error("transport connection lost: {source}")]
18 ConnectionLost {
19 #[source]
20 source: iroh::endpoint::ConnectionError,
21 },
22
23 #[error(transparent)]
25 Metadata(#[from] crate::transport::metadata::MetadataError),
26
27 #[error(transparent)]
29 Transfer(#[from] crate::transport::transfer::TransferError),
30
31 #[error("invalid connection ticket format")]
33 TicketFormatInvalid,
34
35 #[error("invalid relay URL: {url}")]
37 InvalidRelayUrl { url: String },
38
39 #[error("protocol violation: {details}")]
41 ProtocolError { details: String },
42}
43
44#[cfg(feature = "storage")]
46#[derive(Debug, thiserror::Error)]
47pub enum StorageError {
48 #[error("failed to create directory at {path}")]
49 DirectoryCreate {
50 path: PathBuf,
51 #[source]
52 source: std::io::Error,
53 },
54
55 #[error("failed to read directory at {path}")]
56 DirectoryRead {
57 path: PathBuf,
58 #[source]
59 source: std::io::Error,
60 },
61
62 #[error("failed to read entry in directory {path}")]
63 DirectoryEntryRead {
64 path: PathBuf,
65 #[source]
66 source: std::io::Error,
67 },
68
69 #[error("failed to read file at {path}")]
70 FileRead {
71 path: PathBuf,
72 #[source]
73 source: std::io::Error,
74 },
75
76 #[error("failed to write file at {path}")]
77 FileWrite {
78 path: PathBuf,
79 #[source]
80 source: std::io::Error,
81 },
82
83 #[error("failed to delete file at {path}")]
84 FileDelete {
85 path: PathBuf,
86 #[source]
87 source: std::io::Error,
88 },
89
90 #[error("peer '{alias}' not found in storage")]
91 PeerNotFound { alias: String },
92
93 #[error("failed to parse connection ticket")]
94 TicketParse {
95 #[source]
96 source: crate::transport::ticket::TicketError,
97 },
98
99 #[error("failed to load or generate local identity")]
100 IdentityLoad {
101 #[source]
102 source: iroh::endpoint::TransportError,
103 },
104
105 #[error("failed to parse SSH public key")]
106 PublicKeyParse {
107 #[source]
108 source: russh::keys::ssh_key::Error,
109 },
110
111 #[error("failed to read SSH public key file at {path}")]
112 PublicKeyRead {
113 path: PathBuf,
114 #[source]
115 source: russh::keys::ssh_key::Error,
116 },
117
118 #[error("failed to write SSH public key")]
119 PublicKeyWrite {
120 path: PathBuf,
121 #[source]
122 source: russh::keys::ssh_key::Error,
123 },
124
125 #[error("failed to format public key")]
126 PublicKeyFormat {
127 #[source]
128 source: russh::keys::ssh_key::Error,
129 },
130
131 #[error("blocking storage task failed during {operation}")]
132 BlockingTaskFailed {
133 operation: &'static str,
134 #[source]
135 source: tokio::task::JoinError,
136 },
137
138 #[error("invalid node secret at {path}: {details}")]
139 NodeSecretInvalid {
140 path: PathBuf,
141 details: String,
142 #[source]
143 source: Box<dyn std::error::Error + Send + Sync>,
144 },
145
146 #[error("invalid peer name: {name}")]
147 PeerNameInvalid { name: String },
148
149 #[error("failed to serialize peer profile")]
150 PeerProfileSerialize {
151 #[source]
152 source: serde_json::Error,
153 },
154
155 #[error("failed to parse peer profile")]
156 PeerProfileParse {
157 #[source]
158 source: serde_json::Error,
159 },
160
161 #[error("failed to hash password: {reason}")]
162 PasswordHash {
163 reason: argon2::password_hash::Error,
168 },
169}
170
171#[derive(Debug, thiserror::Error)]
173pub enum AuthError {
174 #[error("invalid password provided")]
176 InvalidPassword,
177
178 #[error("password verification failed: {reason}")]
180 VerificationFailed {
181 reason: argon2::password_hash::Error,
186 },
187
188 #[error("unsupported authentication method: {0}")]
190 UnsupportedMethod(String),
191
192 #[error("missing required credential: {0}")]
194 MissingCredential(String),
195}
196
197#[derive(Debug, thiserror::Error)]
199pub enum ClientError {
200 #[error("failed to connect to P2P endpoint")]
202 ConnectFailed {
203 #[source]
204 source: iroh::endpoint::ConnectError,
205 },
206
207 #[error("failed to open SSH transport stream")]
209 StreamOpenFailed {
210 #[source]
211 source: iroh::endpoint::ConnectionError,
212 },
213
214 #[error("metadata request failed: {detail}")]
216 MetadataFailed { detail: String },
217
218 #[error("failed to negotiate SSH protocol")]
220 SshNegotiationFailed {
221 #[source]
222 source: russh::Error,
223 },
224
225 #[error("failed to open SSH session channel")]
227 ChannelOpenFailed {
228 #[source]
229 source: russh::Error,
230 },
231
232 #[error("failed to request PTY")]
234 PtyRequestFailed {
235 #[source]
236 source: russh::Error,
237 },
238
239 #[error("failed to request shell")]
241 ShellRequestFailed {
242 #[source]
243 source: russh::Error,
244 },
245
246 #[error("remote command execution failed")]
248 ExecFailed {
249 #[source]
250 source: russh::Error,
251 },
252
253 #[error("failed to send data to remote channel")]
255 DataSendFailed {
256 #[source]
257 source: russh::Error,
258 },
259
260 #[error("failed to send EOF")]
262 EofSendFailed {
263 #[source]
264 source: russh::Error,
265 },
266
267 #[error("failed to resize PTY window")]
269 WindowChangeFailed {
270 #[source]
271 source: russh::Error,
272 },
273
274 #[error("failed to disconnect SSH session")]
276 DisconnectFailed {
277 #[source]
278 source: russh::Error,
279 },
280
281 #[error("terminal I/O error")]
283 TerminalIo {
284 #[source]
285 source: std::io::Error,
286 },
287
288 #[error("SSH peer disconnected during handshake")]
290 SshHandshakeDisconnected { detail: Option<String> },
291
292 #[error("upload failed: {details}")]
294 UploadFailed { details: String },
295
296 #[error("download failed: {details}")]
298 DownloadFailed { details: String },
299
300 #[error("failed to {operation} at {path}")]
302 FileIo {
303 operation: &'static str,
304 path: PathBuf,
305 #[source]
306 source: std::io::Error,
307 },
308
309 #[error("invalid transfer target: {reason}")]
311 TransferTargetInvalid { reason: &'static str },
312
313 #[error("transfer rejected by remote: {details}")]
315 TransferRejected { details: String },
316
317 #[error("transfer control operation failed: {details}")]
319 TransferFailed { details: String },
320
321 #[error("transport unavailable: {details}")]
323 TransportUnavailable { details: &'static str },
324
325 #[error("tunnel failed: {details}")]
327 TunnelFailed { details: String },
328}
329
330#[derive(Debug, thiserror::Error)]
332pub enum ServerError {
333 #[error("failed to bind server endpoint")]
335 EndpointBind {
336 #[source]
337 source: iroh::endpoint::BindError,
338 },
339
340 #[error("failed to load server identity")]
342 IdentityLoad {
343 #[source]
344 source: iroh::endpoint::TransportError,
345 },
346
347 #[error("failed to configure SSH server")]
349 SshConfig {
350 #[source]
351 source: russh::keys::ssh_key::Error,
352 },
353
354 #[error("remote shell error: {details}")]
356 ShellError { details: String },
357
358 #[error("channel error during {operation}: {details}")]
360 ChannelError {
361 operation: &'static str,
362 details: String,
363 },
364
365 #[error("server transfer error: {details}")]
367 TransferFailed { details: String },
368
369 #[error("invalid transfer path: {details}")]
371 InvalidPath { details: String },
372
373 #[error("failed to format host key")]
374 FormatHostKey {
375 #[source]
376 source: russh::keys::ssh_key::Error,
377 },
378
379 #[error("blocking storage task failed during {operation}")]
380 BlockingTaskFailed {
381 operation: &'static str,
382 #[source]
383 source: tokio::task::JoinError,
384 },
385
386 #[error("failed to query process information for PID {pid}: {details}")]
387 ProcessQueryFailed {
388 pid: u32,
389 details: String,
390 #[source]
391 source: std::io::Error,
392 },
393
394 #[error("Service management failure: {details}")]
396 ServiceManagement { details: String },
397}
398
399#[derive(Debug, thiserror::Error)]
401pub enum IroshError {
402 #[error("platform not supported: {0}")]
403 PlatformNotSupported(String),
404
405 #[cfg(feature = "transport")]
407 #[error("transport error: {0}")]
408 Transport(#[from] TransportError),
409
410 #[cfg(feature = "storage")]
412 #[error("storage error: {0}")]
413 Storage(#[from] StorageError),
414
415 #[error("client error: {0}")]
417 Client(#[from] ClientError),
418
419 #[error("server error: {0}")]
421 Server(#[from] ServerError),
422
423 #[error("ssh protocol error: {0}")]
425 Russh(#[from] russh::Error),
426
427 #[error("ticket error: {0}")]
429 Ticket(#[from] crate::transport::ticket::TicketError),
430
431 #[error("authentication error: {0}")]
433 Auth(#[from] AuthError),
434
435 #[error("I/O error: {0}")]
437 Io(#[from] std::io::Error),
438
439 #[error("authentication failed")]
441 AuthenticationFailed,
442
443 #[error("server host key mismatch (expected {expected}, got {actual})")]
445 ServerKeyMismatch { expected: String, actual: String },
446
447 #[error("invalid connection target: {raw}")]
449 InvalidTarget { raw: String },
450}
451
452pub type Result<T> = std::result::Result<T, IroshError>;