diff --git a/sample/sample.config.ron b/sample/sample.config.ron index bd76407..576fa4d 100644 --- a/sample/sample.config.ron +++ b/sample/sample.config.ron @@ -18,4 +18,5 @@ FriendlyConfig( // This is a bad idea in production, but useful for testing or for dumping // your entire relay allow_scraping: true, + max_subscriptions: 32, ) \ No newline at end of file diff --git a/src/config.rs b/src/config.rs index 4f9501e..6db98c5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,6 +19,7 @@ pub struct FriendlyConfig { pub user_hex_keys: Vec, pub verify_events: bool, pub allow_scraping: bool, + pub max_subscriptions: usize, } impl Default for FriendlyConfig { @@ -38,6 +39,7 @@ impl Default for FriendlyConfig { user_hex_keys: vec![], verify_events: true, allow_scraping: false, + max_subscriptions: 32, } } } @@ -59,6 +61,7 @@ impl FriendlyConfig { user_hex_keys, verify_events, allow_scraping, + max_subscriptions, } = self; let mut public_key: Option = None; @@ -89,6 +92,7 @@ impl FriendlyConfig { user_hex_keys, verify_events, allow_scraping, + max_subscriptions, }) } } @@ -110,4 +114,5 @@ pub struct Config { pub user_hex_keys: Vec, pub verify_events: bool, pub allow_scraping: bool, + pub max_subscriptions: usize, } diff --git a/src/main.rs b/src/main.rs index e1a4a77..df0f51c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -267,7 +267,7 @@ async fn handle_http_request( } } - // DecrementIncrement count of active websockets + // Decrement count of active websockets let old_num_websockets = GLOBALS.num_clients.fetch_sub(1, Ordering::SeqCst); log::info!( diff --git a/src/nostr.rs b/src/nostr.rs index 6cbeb0e..cefcd18 100644 --- a/src/nostr.rs +++ b/src/nostr.rs @@ -62,6 +62,19 @@ impl WebSocketService { log::info!("SUBID={}", subid); + let max_subscriptions = GLOBALS.config.read().await.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 {