From d815690a234fcb92342543ed0b3ebb67d8a9a7a2 Mon Sep 17 00:00:00 2001
From: Doralitze <doralitze@chaotikum.org>
Date: Mon, 19 Jul 2021 17:34:37 +0200
Subject: [PATCH] add: max number of connected clients boundry for tcp server
 socket

---
 src/net/tcp_server_socket.cpp | 24 ++++++++++++++++++++----
 src/net/tcp_server_socket.hpp | 22 +++++++++++++++++++++-
 2 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/src/net/tcp_server_socket.cpp b/src/net/tcp_server_socket.cpp
index 1979e7e..d98d2ce 100644
--- a/src/net/tcp_server_socket.cpp
+++ b/src/net/tcp_server_socket.cpp
@@ -33,7 +33,9 @@ tcp_server_socket::tcp_server_socket(
 ) :
     ss{nullptr},
     client_listener(client_listener_),
-    number_of_connected_clients(0)
+    overflow_client_listener(nullptr),
+    number_of_connected_clients(0),
+    max_number_of_simulataneusly_allowed_clients(0)
 {
     auto_fd socket_fd{socket(socket_identifier.family(), SOCK_STREAM, 0)};
 
@@ -108,12 +110,18 @@ void tcp_server_socket::await_raw_socket_incomming(
 
     // Generate client object from fd and announce it
     this->number_of_connected_clients++;
-
     using namespace std::placeholders;
-    this->client_listener(tcp_client(std::bind(&tcp_server_socket::client_destructed_cb, this, _1), auto_fd(client_fd_raw), address, port));
+
+    if (this->max_number_of_simulataneusly_allowed_clients == 0 || this->get_number_of_connected_clients() <= this->max_number_of_simulataneusly_allowed_clients) {
+        this->client_listener(tcp_client(std::bind(&tcp_server_socket::client_destructed_cb, this, _1), auto_fd(client_fd_raw), address, port));
+    } else {
+        if (this->overflow_client_listener != nullptr) {
+            this->overflow_client_listener(tcp_client(std::bind(&tcp_server_socket::client_destructed_cb, this, _1), auto_fd(client_fd_raw), address, port));
+        }
+    }
 }
 
-int tcp_server_socket::get_number_of_connected_clients() const {
+unsigned int tcp_server_socket::get_number_of_connected_clients() const {
     return this->number_of_connected_clients;
 }
 
@@ -123,4 +131,12 @@ void tcp_server_socket::client_destructed_cb(exit_status_t exit_status) {
     this->number_of_connected_clients--;
 }
 
+void tcp_server_socket::set_client_overflow_handler(incoming_client_listener_type overflow_client_listener_) {
+    this->overflow_client_listener = overflow_client_listener_;
+}
+
+void tcp_server_socket::set_maximum_concurrent_connections(unsigned int max_connections) {
+    this->max_number_of_simulataneusly_allowed_clients = max_connections;
+}
+
 }
diff --git a/src/net/tcp_server_socket.hpp b/src/net/tcp_server_socket.hpp
index a56ee7f..ffc2757 100644
--- a/src/net/tcp_server_socket.hpp
+++ b/src/net/tcp_server_socket.hpp
@@ -32,7 +32,9 @@ public:
 private:
     async_server_socket::self_ptr_type ss;
     incoming_client_listener_type client_listener;
+    incoming_client_listener_type overflow_client_listener;
     std::atomic_uint32_t number_of_connected_clients;
+    unsigned int max_number_of_simulataneusly_allowed_clients;
 
 public:
     /**
@@ -59,7 +61,25 @@ public:
      * @brief Get the current number of connected clients.
      * @return  The number of connected clients
      */
-    int get_number_of_connected_clients() const;
+    unsigned int get_number_of_connected_clients() const;
+
+    /**
+     * This method sets the overflow handler to use if the maximum number of allowed clients was reached.
+     * The purpose of said handler is to inform the connected client that the connection cant be established
+     * due to isufficient resources. It should transmit the appropriate error message and drop the client.
+     * @brief Set the client overflow handler
+     * @param overflow_client_listener The listener that handles clients that couldn't be accepted
+     */
+    void set_client_overflow_handler(incoming_client_listener_type overflow_client_listener);
+
+    /**
+     * Use this method in order to set the maximum number of allowed connections. Set it to
+     * 0 in order to disable the limit. If anything other than 0 is set it is highly recommended
+     * to also set an overflow handler.
+     * @brief Set the maximum allowed simultaneus connections.
+     * @param max_connections The maximum number of allowed connections.
+     */
+    void set_maximum_concurrent_connections(unsigned int max_connections);
 
 private:
     void await_raw_socket_incomming(async_server_socket::self_ptr_type ass, const auto_fd& socket);
-- 
GitLab