fix: deletable self-sent mail, honest refused-handshake reporting, registration remedy

This commit is contained in:
randogoth 2026-09-29 09:35:46 +03:00
parent 4a780ed648
commit 39c4c4d6a5
3 changed files with 211 additions and 55 deletions

View file

@ -55,6 +55,16 @@ pub enum Error {
port: u16,
source: std::io::Error,
},
/// The server dropped the connection mid-handshake after bounded
/// retries. A rate limiter drops connections without a reply, so this
/// is indistinguishable from a dying server; the decision it supports
/// is "retry later", not "treat the server as dead".
HandshakeRefused {
host: String,
port: u16,
source: std::io::Error,
attempts: usize,
},
#[cfg(feature = "store")]
Storage(rusqlite::Error),
Noise(snow::Error),
@ -100,7 +110,10 @@ impl fmt::Display for Error {
b32(known),
b32(offered)
),
Self::NotRegistered => write!(f, "not registered"),
Self::NotRegistered => write!(
f,
"not registered; this store has no account (registering or restoring creates one)"
),
Self::ChainLimit { index } => write!(
f,
"rotation index {index} exceeds the chain limit of {MAX_CHAIN}"
@ -112,6 +125,16 @@ impl fmt::Display for Error {
Self::Unreachable { host, port, source } => {
write!(f, "cannot reach {host}:{port}: {source}")
}
Self::HandshakeRefused {
host,
port,
source,
attempts,
} => write!(
f,
"{host}:{port} refused the connection mid-handshake after {attempts} attempt(s) ({source})\n \
possibly rate limited; a limiter drops connections without a reply, so a dying server looks the same"
),
#[cfg(feature = "store")]
Self::Storage(e) => write!(f, "storage error: {e}"),
Self::Noise(e) => write!(f, "noise error: {e}"),
@ -124,7 +147,9 @@ impl fmt::Display for Error {
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Unreachable { source, .. } => Some(source),
Self::Unreachable { source, .. } | Self::HandshakeRefused { source, .. } => {
Some(source)
}
#[cfg(feature = "store")]
Self::Storage(e) => Some(e),
Self::Noise(e) => Some(e),