From 9b2d6365f03e60690539134e209b9372451beb7b Mon Sep 17 00:00:00 2001 From: Mike Dilger Date: Wed, 21 Feb 2024 09:30:10 +1300 Subject: [PATCH] Respond to REQ errors properly with CLOSED --- sample/sample.config.ron | 2 +- src/error.rs | 4 ++++ src/nostr.rs | 47 +++++++++++++++++++++++++++------------- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/sample/sample.config.ron b/sample/sample.config.ron index 229e5e3..b4777ac 100644 --- a/sample/sample.config.ron +++ b/sample/sample.config.ron @@ -17,7 +17,7 @@ FriendlyConfig( // This is a bad idea in production, but useful for testing or for dumping // your entire relay - allow_scraping: true, + allow_scraping: false, max_subscriptions: 32, serve_ephemeral: true, serve_relay_lists: true, diff --git a/src/error.rs b/src/error.rs index 46e4166..4ba7304 100644 --- a/src/error.rs +++ b/src/error.rs @@ -115,6 +115,9 @@ pub enum ChorusError { // Too many errors TooManyErrors, + // Too many subscriptions + TooManySubscriptions, + // URL Parse UrlParse(url::ParseError), @@ -174,6 +177,7 @@ impl std::fmt::Display for ChorusError { ChorusError::Tungstenite(e) => write!(f, "{e}"), ChorusError::Scraper => write!(f, "Filter is underspecified. Scrapers are not allowed"), ChorusError::TooManyErrors => write!(f, "Too many errors"), + ChorusError::TooManySubscriptions => write!(f, "Too many subscriptions"), ChorusError::UrlParse(e) => write!(f, "{e}"), ChorusError::Utf8(e) => write!(f, "{e}"), ChorusError::Utf8Error => write!(f, "UTF-8 error"), diff --git a/src/nostr.rs b/src/nostr.rs index 00c57f3..306d71d 100644 --- a/src/nostr.rs +++ b/src/nostr.rs @@ -60,19 +60,6 @@ impl WebSocketService { outpos += outlen; verify_char(input, b'"', &mut inpos)?; // FIXME: json_unescape should eat the closing quote - let max_subscriptions = GLOBALS.config.get().unwrap().max_subscriptions; - if self.subscriptions.len() >= max_subscriptions { - let reply = NostrReply::Closed( - &subid, - NostrReplyPrefix::RateLimited, - format!( - "No more than {max_subscriptions} subscriptions are allowed at any one time" - ), - ); - self.websocket.send(Message::text(reply.as_json())).await?; - return Ok(()); - } - // Read the filter into the session buffer let mut filters: Vec = Vec::new(); loop { @@ -91,6 +78,36 @@ impl WebSocketService { filters.push(OwnedFilter(filterbytes)); } + if let Err(e) = self.req_inner(&subid, filters).await { + let reply = match e.inner { + ChorusError::TooManySubscriptions => { + let max_subscriptions = GLOBALS.config.get().unwrap().max_subscriptions; + NostrReply::Closed( + &subid, + NostrReplyPrefix::Blocked, + format!( + "No more than {max_subscriptions} subscriptions are allowed at any one time" + ), + ) + } + ChorusError::Scraper => { + NostrReply::Closed(&subid, NostrReplyPrefix::Invalid, format!("{e}")) + } + _ => NostrReply::Closed(&subid, NostrReplyPrefix::Error, format!("{e}")), + }; + + self.websocket.send(Message::text(reply.as_json())).await?; + } + + Ok(()) + } + + async fn req_inner(&mut self, subid: &String, filters: Vec) -> Result<(), Error> { + let max_subscriptions = GLOBALS.config.get().unwrap().max_subscriptions; + if self.subscriptions.len() >= max_subscriptions { + return Err(ChorusError::TooManySubscriptions.into()); + } + let user = self.user; let authorized_user = authorized_user(&user).await; @@ -126,12 +143,12 @@ impl WebSocketService { events.dedup(); for event in events.drain(..) { - let reply = NostrReply::Event(&subid, event); + let reply = NostrReply::Event(subid, event); self.websocket.send(Message::text(reply.as_json())).await?; } // eose - let reply = NostrReply::Eose(&subid); + let reply = NostrReply::Eose(subid); self.websocket.send(Message::text(reply.as_json())).await?; }