From 332165248165d4afec300ee2d647a2564b1649b1 Mon Sep 17 00:00:00 2001 From: Mike Dilger Date: Wed, 21 Feb 2024 11:08:49 +1300 Subject: [PATCH] Rank errors, require punishment of 1.0 before closing connection --- src/error.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 12 +++++------- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/error.rs b/src/error.rs index 4dd667f..26ee33c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -211,6 +211,50 @@ impl StdError for ChorusError { } } +impl ChorusError { + pub fn punishment(&self) -> f32 { + match self { + ChorusError::AuthFailure(_) => 0.25, + ChorusError::AuthRequired => 0.0, + ChorusError::BadEventId => 0.1, + ChorusError::BadHexInput => 0.25, + ChorusError::BufferTooSmall => 0.0, + ChorusError::ChannelRecv(_) => 0.0, + ChorusError::ChannelSend(_) => 0.0, + ChorusError::Config(_) => 0.0, + ChorusError::Crypto(_) => 0.1, + ChorusError::Deleted => 0.1, + ChorusError::Duplicate => 0.01, + ChorusError::EndOfInput => 0.2, + ChorusError::EventIsInvalid(_) => 0.2, + ChorusError::Http(_) => 0.0, + ChorusError::Hyper(_) => 0.0, + ChorusError::Io(_) => 0.0, + ChorusError::JsonBad(_, _) => 0.2, + ChorusError::JsonBadCharacter(_, _, _) => 0.2, + ChorusError::JsonBadEvent(_, _) => 0.2, + ChorusError::JsonBadFilter(_, _) => 0.2, + ChorusError::JsonBadStringChar(_) => 0.2, + ChorusError::JsonEscape => 0.2, + ChorusError::JsonEscapeSurrogate => 0.05, + ChorusError::Lmdb(_) => 0.0, + ChorusError::NoPrivateKey => 0.0, + ChorusError::NoSuchSubscription => 0.05, + ChorusError::Restricted => 0.1, + ChorusError::Rustls(_) => 0.0, + ChorusError::TimedOut => 0.1, + ChorusError::Tungstenite(_) => 0.0, + ChorusError::Scraper => 0.5, + ChorusError::TooManyErrors => 1.0, + ChorusError::TooManySubscriptions => 0.1, + ChorusError::UrlParse(_) => 0.1, + ChorusError::Utf8(_) => 0.1, + ChorusError::Utf8Error => 0.1, + ChorusError::WebsocketProtocol(_) => 0.1, + } + } +} + // Note: we impl Into because our typical pattern is ChorusError::Variant.into() // when we tried implementing From, the location was deep in rust code's // blanket into implementation, which wasn't the line number we wanted. diff --git a/src/main.rs b/src/main.rs index 111a9ec..3767fbc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -278,7 +278,7 @@ async fn handle_http_request( websocket, challenge: TextNonce::new().into_string(), user: None, - errcount: 0, + error_punishment: 0.0, replied: false, }; @@ -364,7 +364,7 @@ struct WebSocketService { pub websocket: WebSocketStream, pub challenge: String, pub user: Option, - pub errcount: usize, + pub error_punishment: f32, pub replied: bool, } @@ -468,7 +468,7 @@ impl WebSocketService { self.replied = false; // This is defined in nostr.rs if let Err(e) = self.handle_nostr_message(&msg).await { - self.errcount += 1; + self.error_punishment += e.inner.punishment(); log::error!("{}: {e}", self.peer); if msg.len() < 2048 { log::error!("{}: msg was {}", self.peer, msg); @@ -479,10 +479,8 @@ impl WebSocketService { let reply = NostrReply::Notice(format!("error: {}", e)); self.websocket.send(Message::text(reply.as_json())).await?; } - if self.errcount >= 3 { - let reply = NostrReply::Notice( - "Too many errors (3). Banned for 60 seconds.".into(), - ); + if self.error_punishment > 1.0 { + let reply = NostrReply::Notice("Too many errors".into()); self.websocket.send(Message::text(reply.as_json())).await?; return Err(ChorusError::TooManyErrors.into()); }