use std::path::PathBuf;
#[cfg(feature = "transport")]
#[derive(Debug, thiserror::Error)]
pub enum TransportError {
#[error("failed to bind transport endpoint")]
EndpointBind {
#[source]
source: iroh::endpoint::BindError,
},
#[error("transport connection lost: {source}")]
ConnectionLost {
#[source]
source: iroh::endpoint::ConnectionError,
},
#[error(transparent)]
Metadata(#[from] crate::transport::metadata::MetadataError),
#[error(transparent)]
Transfer(#[from] crate::transport::transfer::TransferError),
#[error("invalid connection ticket format")]
TicketFormatInvalid,
#[error("invalid relay URL: {url}")]
InvalidRelayUrl { url: String },
#[error("protocol violation: {details}")]
ProtocolError { details: String },
}
#[cfg(feature = "storage")]
#[derive(Debug, thiserror::Error)]
pub enum StorageError {
#[error("failed to create directory at {path}")]
DirectoryCreate {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("failed to read directory at {path}")]
DirectoryRead {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("failed to read entry in directory {path}")]
DirectoryEntryRead {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("failed to read file at {path}")]
FileRead {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("failed to write file at {path}")]
FileWrite {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("failed to delete file at {path}")]
FileDelete {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("peer '{alias}' not found in storage")]
PeerNotFound { alias: String },
#[error("failed to parse connection ticket")]
TicketParse {
#[source]
source: crate::transport::ticket::TicketError,
},
#[error("failed to load or generate local identity")]
IdentityLoad {
#[source]
source: iroh::endpoint::TransportError,
},
#[error("failed to parse SSH public key")]
PublicKeyParse {
#[source]
source: russh::keys::ssh_key::Error,
},
#[error("failed to read SSH public key file at {path}")]
PublicKeyRead {
path: PathBuf,
#[source]
source: russh::keys::ssh_key::Error,
},
#[error("failed to write SSH public key")]
PublicKeyWrite {
path: PathBuf,
#[source]
source: russh::keys::ssh_key::Error,
},
#[error("failed to format public key")]
PublicKeyFormat {
#[source]
source: russh::keys::ssh_key::Error,
},
#[error("blocking storage task failed during {operation}")]
BlockingTaskFailed {
operation: &'static str,
#[source]
source: tokio::task::JoinError,
},
#[error("invalid node secret at {path}: {details}")]
NodeSecretInvalid {
path: PathBuf,
details: String,
#[source]
source: Box<dyn std::error::Error + Send + Sync>,
},
#[error("invalid peer name: {name}")]
PeerNameInvalid { name: String },
#[error("failed to serialize peer profile")]
PeerProfileSerialize {
#[source]
source: serde_json::Error,
},
#[error("failed to parse peer profile")]
PeerProfileParse {
#[source]
source: serde_json::Error,
},
#[error("failed to hash password: {reason}")]
PasswordHash {
reason: argon2::password_hash::Error,
},
}
#[derive(Debug, thiserror::Error)]
pub enum AuthError {
#[error("invalid password provided")]
InvalidPassword,
#[error("password verification failed: {reason}")]
VerificationFailed {
reason: argon2::password_hash::Error,
},
#[error("unsupported authentication method: {0}")]
UnsupportedMethod(String),
#[error("missing required credential: {0}")]
MissingCredential(String),
}
#[derive(Debug, thiserror::Error)]
pub enum ClientError {
#[error("failed to connect to P2P endpoint")]
ConnectFailed {
#[source]
source: iroh::endpoint::ConnectError,
},
#[error("failed to open SSH transport stream")]
StreamOpenFailed {
#[source]
source: iroh::endpoint::ConnectionError,
},
#[error("metadata request failed: {detail}")]
MetadataFailed { detail: String },
#[error("failed to negotiate SSH protocol")]
SshNegotiationFailed {
#[source]
source: russh::Error,
},
#[error("failed to open SSH session channel")]
ChannelOpenFailed {
#[source]
source: russh::Error,
},
#[error("failed to request PTY")]
PtyRequestFailed {
#[source]
source: russh::Error,
},
#[error("failed to request shell")]
ShellRequestFailed {
#[source]
source: russh::Error,
},
#[error("remote command execution failed")]
ExecFailed {
#[source]
source: russh::Error,
},
#[error("failed to send data to remote channel")]
DataSendFailed {
#[source]
source: russh::Error,
},
#[error("failed to send EOF")]
EofSendFailed {
#[source]
source: russh::Error,
},
#[error("failed to resize PTY window")]
WindowChangeFailed {
#[source]
source: russh::Error,
},
#[error("failed to disconnect SSH session")]
DisconnectFailed {
#[source]
source: russh::Error,
},
#[error("terminal I/O error")]
TerminalIo {
#[source]
source: std::io::Error,
},
#[error("SSH peer disconnected during handshake")]
SshHandshakeDisconnected { detail: Option<String> },
#[error("upload failed: {details}")]
UploadFailed { details: String },
#[error("download failed: {details}")]
DownloadFailed { details: String },
#[error("failed to {operation} at {path}")]
FileIo {
operation: &'static str,
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("invalid transfer target: {reason}")]
TransferTargetInvalid { reason: &'static str },
#[error("transfer rejected by remote: {details}")]
TransferRejected { details: String },
#[error("transfer control operation failed: {details}")]
TransferFailed { details: String },
#[error("transport unavailable: {details}")]
TransportUnavailable { details: &'static str },
#[error("tunnel failed: {details}")]
TunnelFailed { details: String },
}
#[derive(Debug, thiserror::Error)]
pub enum ServerError {
#[error("failed to bind server endpoint")]
EndpointBind {
#[source]
source: iroh::endpoint::BindError,
},
#[error("failed to load server identity")]
IdentityLoad {
#[source]
source: iroh::endpoint::TransportError,
},
#[error("failed to configure SSH server")]
SshConfig {
#[source]
source: russh::keys::ssh_key::Error,
},
#[error("remote shell error: {details}")]
ShellError { details: String },
#[error("channel error during {operation}: {details}")]
ChannelError {
operation: &'static str,
details: String,
},
#[error("server transfer error: {details}")]
TransferFailed { details: String },
#[error("invalid transfer path: {details}")]
InvalidPath { details: String },
#[error("failed to format host key")]
FormatHostKey {
#[source]
source: russh::keys::ssh_key::Error,
},
#[error("blocking storage task failed during {operation}")]
BlockingTaskFailed {
operation: &'static str,
#[source]
source: tokio::task::JoinError,
},
#[error("failed to query process information for PID {pid}: {details}")]
ProcessQueryFailed {
pid: u32,
details: String,
#[source]
source: std::io::Error,
},
#[error("Service management failure: {details}")]
ServiceManagement { details: String },
}
#[derive(Debug, thiserror::Error)]
pub enum IroshError {
#[error("platform not supported: {0}")]
PlatformNotSupported(String),
#[cfg(feature = "transport")]
#[error("transport error: {0}")]
Transport(#[from] TransportError),
#[cfg(feature = "storage")]
#[error("storage error: {0}")]
Storage(#[from] StorageError),
#[error("client error: {0}")]
Client(#[from] ClientError),
#[error("server error: {0}")]
Server(#[from] ServerError),
#[error("ssh protocol error: {0}")]
Russh(#[from] russh::Error),
#[error("ticket error: {0}")]
Ticket(#[from] crate::transport::ticket::TicketError),
#[error("authentication error: {0}")]
Auth(#[from] AuthError),
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("authentication failed")]
AuthenticationFailed,
#[error("server host key mismatch (expected {expected}, got {actual})")]
ServerKeyMismatch { expected: String, actual: String },
#[error("invalid connection target: {raw}")]
InvalidTarget { raw: String },
}
pub type Result<T> = std::result::Result<T, IroshError>;