diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index ad9474564..4702f8332 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -171,6 +171,8 @@ extern "C" char* PrivateKeyFile; CRITICAL_SECTION lock; freerdp_listener* listener; + + size_t maxClientsConnected; }; struct rdp_shadow_surface diff --git a/server/shadow/shadow.c b/server/shadow/shadow.c index 2575bc30f..730e5fe1f 100644 --- a/server/shadow/shadow.c +++ b/server/shadow/shadow.c @@ -50,6 +50,8 @@ int main(int argc, char** argv) "localhost" }, { "monitors", COMMAND_LINE_VALUE_OPTIONAL, "<0,1,2...>", NULL, NULL, -1, NULL, "Select or list monitors" }, + { "max-connections", COMMAND_LINE_VALUE_REQUIRED, "", 0, NULL, -1, NULL, + "maximum connections allowed to server, 0 to deactivate" }, { "rect", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Select rectangle within monitor to share" }, { "auth", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c index 59533c181..aa2a0bff5 100644 --- a/server/shadow/shadow_server.c +++ b/server/shadow/shadow_server.c @@ -214,6 +214,15 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a { server->mayInteract = arg->Value ? TRUE : FALSE; } + CommandLineSwitchCase(arg, "max-connections") + { + errno = 0; + unsigned long val = strtoul(arg->Value, NULL, 0); + + if ((errno != 0) || (val > UINT32_MAX)) + return -1; + server->maxClientsConnected = val; + } CommandLineSwitchCase(arg, "rect") { char* p; @@ -859,6 +868,26 @@ out_fail: return ret; } +static BOOL shadow_server_check_peer_restrictions(freerdp_listener* listener) +{ + WINPR_ASSERT(listener); + + rdpShadowServer* server = (rdpShadowServer*)listener->info; + WINPR_ASSERT(server); + + if (server->maxClientsConnected > 0) + { + const size_t count = ArrayList_Count(server->clients); + if (count >= server->maxClientsConnected) + { + WLog_WARN(TAG, "connection limit [%" PRIuz "] reached, discarding client", + server->maxClientsConnected); + return FALSE; + } + } + return TRUE; +} + int shadow_server_init(rdpShadowServer* server) { int status; @@ -888,6 +917,7 @@ int shadow_server_init(rdpShadowServer* server) goto fail; server->listener->info = (void*)server; + server->listener->CheckPeerAcceptRestrictions = shadow_server_check_peer_restrictions; server->listener->PeerAccepted = shadow_client_accepted; server->subsystem = shadow_subsystem_new();