use std::fmt::{Display, Formatter}; use std::convert::From; use std::str::Utf8Error; use sqlx::{ error::Error as SqlxError, migrate::MigrateError, }; // error during initial setup (primarily loading state from db) pub enum SetupError { InvalidRecord, // e.g. wrong size blob for nonce or salt DbError(SqlxError), } impl From for SetupError { fn from(e: SqlxError) -> SetupError { SetupError::DbError(e) } } impl From for SetupError { fn from (e: MigrateError) -> SetupError { SetupError::DbError(SqlxError::from(e)) } } impl Display for SetupError { fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { match self { SetupError::InvalidRecord => write!(f, "Malformed database record"), SetupError::DbError(e) => write!(f, "Error from database: {e}"), } } } // error when attempting to tell a request handler whether to release or deny crednetials pub enum SendResponseError { NotFound, // no request with the given id Abandoned, // request has already been closed by client } impl Display for SendResponseError { fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { use SendResponseError::*; match self { NotFound => write!(f, "The specified command was not found."), Abandoned => write!(f, "The specified request was closed by the client."), } } } // errors encountered while handling an HTTP request pub enum RequestError { StreamIOError(std::io::Error), InvalidUtf8, MalformedHttpRequest, RequestTooLarge, NoCredentials(GetCredentialsError), ClientInfo(ClientInfoError), } impl From for RequestError { fn from(e: std::io::Error) -> RequestError { RequestError::StreamIOError(e) } } impl From for RequestError { fn from(_e: Utf8Error) -> RequestError { RequestError::InvalidUtf8 } } impl From for RequestError { fn from (e: GetCredentialsError) -> RequestError { RequestError::NoCredentials(e) } } impl From for RequestError { fn from(e: ClientInfoError) -> RequestError { RequestError::ClientInfo(e) } } impl Display for RequestError { fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { use RequestError::*; match self { StreamIOError(e) => write!(f, "Stream IO error: {e}"), InvalidUtf8 => write!(f, "Could not decode UTF-8 from bytestream"), MalformedHttpRequest => write!(f, "Maformed HTTP request"), RequestTooLarge => write!(f, "HTTP request too large"), NoCredentials(GetCredentialsError::Locked) => write!(f, "Recieved go-ahead but app is locked"), NoCredentials(GetCredentialsError::Empty) => write!(f, "Received go-ahead but no credentials are known"), ClientInfo(ClientInfoError::PidNotFound) => write!(f, "Could not resolve PID of client process."), ClientInfo(ClientInfoError::NetstatError(e)) => write!(f, "Error getting client socket details: {e}"), } } } pub enum GetCredentialsError { Locked, Empty, } pub enum UnlockError { NotLocked, NoCredentials, BadPassphrase, InvalidUtf8, // Somehow we got invalid utf-8 even though decryption succeeded DbError(SqlxError), } impl From for UnlockError { fn from (e: SqlxError) -> UnlockError { match e { SqlxError::RowNotFound => UnlockError::NoCredentials, _ => UnlockError::DbError(e), } } } impl Display for UnlockError { fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { use UnlockError::*; match self { NotLocked => write!(f, "App is not locked"), NoCredentials => write!(f, "No saved credentials were found"), BadPassphrase => write!(f, "Invalid passphrase"), InvalidUtf8 => write!(f, "Decrypted data was corrupted"), DbError(e) => write!(f, "Database error: {e}"), } } } // Errors encountered while trying to figure out who's on the other end of a request pub enum ClientInfoError { PidNotFound, NetstatError(netstat2::error::Error), } impl From for ClientInfoError { fn from(e: netstat2::error::Error) -> ClientInfoError { ClientInfoError::NetstatError(e) } }