File 0010-throttler-Introduce-limits-struct.patch of Package gnome-remote-desktop

From 44a9c90d99e13d495d0a3480a655490d8aede854 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Fri, 30 May 2025 16:54:00 +0200
Subject: [PATCH 10/13] throttler: Introduce limits struct

This will be used by the server implementation to customize throttling
limits. This will be used by the VNC server to limit to one global
session at a time, replacing it's own existing condition.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-remote-desktop/-/merge_requests/321>
---
 src/grd-rdp-server.c |  3 ++-
 src/grd-throttler.c  | 64 ++++++++++++++++++++++++++++++++++++--------
 src/grd-throttler.h  | 14 ++++++++--
 3 files changed, 67 insertions(+), 14 deletions(-)

diff --git a/src/grd-rdp-server.c b/src/grd-rdp-server.c
index 2132e42..d823063 100644
--- a/src/grd-rdp-server.c
+++ b/src/grd-rdp-server.c
@@ -541,7 +541,8 @@ grd_rdp_server_constructed (GObject *object)
 
   if (allow_callback)
     {
-      rdp_server->throttler = grd_throttler_new (allow_callback,
+      rdp_server->throttler = grd_throttler_new (grd_throttler_limits_new (),
+                                                 allow_callback,
                                                  rdp_server);
     }
 
diff --git a/src/grd-throttler.c b/src/grd-throttler.c
index a21563a..5c404ed 100644
--- a/src/grd-throttler.c
+++ b/src/grd-throttler.c
@@ -23,10 +23,18 @@
 
 #include "grd-utils.h"
 
-#define MAX_GLOBAL_CONNECTIONS 10
-#define MAX_CONNECTIONS_PER_PEER 5
-#define MAX_PENDING_CONNECTIONS 5
-#define MAX_ATTEMPTS_PER_SECOND 5
+#define DEFAULT_MAX_GLOBAL_CONNECTIONS 10
+#define DEFAULT_MAX_CONNECTIONS_PER_PEER 5
+#define DEFAULT_MAX_PENDING_CONNECTIONS 5
+#define DEFAULT_MAX_ATTEMPTS_PER_SECOND 10
+
+struct _GrdThrottlerLimits
+{
+  int max_global_connections;
+  int max_connections_per_peer;
+  int max_pending_connections;
+  int max_attempts_per_second;
+};
 
 #define PRUNE_TIME_CUTOFF_US (s2us (1))
 
@@ -44,6 +52,8 @@ struct _GrdThrottler
 {
   GObject parent;
 
+  GrdThrottlerLimits *limits;
+
   int active_connections;
 
   GrdThrottlerAllowCallback allow_callback;
@@ -219,10 +229,12 @@ static gboolean
 is_connection_limit_reached (GrdThrottler *throttler,
                              GrdPeer      *peer)
 {
-  if (peer->active_connections >= MAX_CONNECTIONS_PER_PEER)
+  GrdThrottlerLimits *limits = throttler->limits;
+
+  if (peer->active_connections >= limits->max_connections_per_peer)
     return TRUE;
 
-  if (throttler->active_connections >= MAX_GLOBAL_CONNECTIONS)
+  if (throttler->active_connections >= limits->max_global_connections)
     return TRUE;
 
   return FALSE;
@@ -232,11 +244,13 @@ static gboolean
 is_new_connection_allowed (GrdThrottler *throttler,
                            GrdPeer      *peer)
 {
+  GrdThrottlerLimits *limits = throttler->limits;
+
   if (is_connection_limit_reached (throttler, peer))
     return FALSE;
 
   if (peer->connect_timestamps &&
-      peer->connect_timestamps->len >= MAX_ATTEMPTS_PER_SECOND)
+      peer->connect_timestamps->len >= limits->max_attempts_per_second)
     return FALSE;
 
   return TRUE;
@@ -295,6 +309,7 @@ ensure_delayed_connections_source (GrdThrottler *throttler)
 static void
 maybe_queue_timeout (GrdThrottler *throttler)
 {
+  GrdThrottlerLimits *limits = throttler->limits;
   GHashTableIter iter;
   gpointer key, value;
   int64_t next_timeout_us = INT64_MAX;
@@ -312,7 +327,7 @@ maybe_queue_timeout (GrdThrottler *throttler)
 
       next_timeout_us = MIN (next_timeout_us,
                              peer->last_accept_us +
-                             G_USEC_PER_SEC / MAX_ATTEMPTS_PER_SECOND);
+                             G_USEC_PER_SEC / limits->max_attempts_per_second);
     }
 
 
@@ -333,6 +348,7 @@ maybe_delay_connection (GrdThrottler      *throttler,
                         GrdPeer           *peer,
                         int64_t            now_us)
 {
+  GrdThrottlerLimits *limits = throttler->limits;
   GQueue *delayed_connections;
 
   delayed_connections = peer->delayed_connections;
@@ -342,7 +358,7 @@ maybe_delay_connection (GrdThrottler      *throttler,
       peer->delayed_connections = delayed_connections;
     }
 
-  if (g_queue_get_length (delayed_connections) > MAX_PENDING_CONNECTIONS)
+  if (g_queue_get_length (delayed_connections) > limits->max_pending_connections)
     {
       grd_throttler_deny_connection (throttler, peer->name, connection);
       return;
@@ -416,15 +432,40 @@ grd_throttler_handle_connection (GrdThrottler      *throttler,
   maybe_delay_connection (throttler, connection, peer, now_us);
 }
 
+void
+grd_throttler_limits_set_max_global_connections (GrdThrottlerLimits *limits,
+                                                 int                 limit)
+{
+  limits->max_global_connections = limit;
+}
+
+GrdThrottlerLimits *
+grd_throttler_limits_new (void)
+{
+  GrdThrottlerLimits *limits;
+
+  limits = g_new0 (GrdThrottlerLimits, 1);
+  limits->max_global_connections = DEFAULT_MAX_GLOBAL_CONNECTIONS;
+  limits->max_connections_per_peer = DEFAULT_MAX_CONNECTIONS_PER_PEER;
+  limits->max_pending_connections = DEFAULT_MAX_PENDING_CONNECTIONS;
+  limits->max_attempts_per_second = DEFAULT_MAX_ATTEMPTS_PER_SECOND;
+
+  return limits;
+}
+
 GrdThrottler *
-grd_throttler_new (GrdThrottlerAllowCallback allow_callback,
-                   gpointer                  user_data)
+grd_throttler_new (GrdThrottlerLimits        *limits,
+                   GrdThrottlerAllowCallback  allow_callback,
+                   gpointer                   user_data)
 {
   GrdThrottler *throttler;
 
+  g_assert (limits);
+
   throttler = g_object_new (GRD_TYPE_THROTTLER, NULL);
   throttler->allow_callback = allow_callback;
   throttler->user_data = user_data;
+  throttler->limits = limits;
 
   return throttler;
 }
@@ -446,6 +487,7 @@ grd_throttler_finalize (GObject *object)
 
   g_clear_pointer (&throttler->delayed_connections_source, g_source_destroy);
   g_clear_pointer (&throttler->peers, g_hash_table_unref);
+  g_clear_pointer (&throttler->limits, g_free);
 
   G_OBJECT_CLASS (grd_throttler_parent_class)->finalize (object);
 }
diff --git a/src/grd-throttler.h b/src/grd-throttler.h
index d57d653..9e72b8f 100644
--- a/src/grd-throttler.h
+++ b/src/grd-throttler.h
@@ -23,6 +23,8 @@
 #include <gio/gio.h>
 #include <glib-object.h>
 
+typedef struct _GrdThrottlerLimits GrdThrottlerLimits;
+
 #define GRD_TYPE_THROTTLER (grd_throttler_get_type())
 G_DECLARE_FINAL_TYPE (GrdThrottler, grd_throttler, GRD, THROTTLER, GObject)
 
@@ -34,8 +36,16 @@ void
 grd_throttler_handle_connection (GrdThrottler      *throttler,
                                  GSocketConnection *connection);
 
+void
+grd_throttler_limits_set_max_global_connections (GrdThrottlerLimits *limits,
+                                                 int                 limit);
+
+GrdThrottlerLimits *
+grd_throttler_limits_new (void);
+
 GrdThrottler *
-grd_throttler_new (GrdThrottlerAllowCallback allow_callback,
-                   gpointer                  user_data);
+grd_throttler_new (GrdThrottlerLimits        *limits,
+                   GrdThrottlerAllowCallback  allow_callback,
+                   gpointer                   user_data);
 
 #endif /* GRD_THROTTLER_H */
-- 
2.53.0

openSUSE Build Service is sponsored by