Commit e9c84d966 for imagemagick.org
commit e9c84d966ab6ca851d4c0772022585e83f828320
Author: Cristy <urban-warrior@imagemagick.org>
Date: Mon Jul 20 19:35:04 2026 -0400
configure distributed cache max clients and max unathenticated clients
diff --git a/MagickCore/distribute-cache.c b/MagickCore/distribute-cache.c
index 0f8ed729e..62c6158d8 100644
--- a/MagickCore/distribute-cache.c
+++ b/MagickCore/distribute-cache.c
@@ -103,6 +103,8 @@
Define declarations.
*/
#define DPCHostname "127.0.0.1"
+#define DPCMaxClientWorkers 128
+#define DPCMaxUnauthenticatedClientWorkers 16
#define DPCPendingConnections 10
#define DPCPort 6668
#define DPCSessionKeyLength 16
@@ -115,11 +117,20 @@
*/
#ifdef MAGICKCORE_HAVE_WINSOCK2
static SemaphoreInfo
- *winsock2_semaphore = (SemaphoreInfo *) NULL;
+ *winsock_semaphore = (SemaphoreInfo *) NULL;
static WSADATA
*wsaData = (WSADATA*) NULL;
#endif
+
+#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
+static SemaphoreInfo
+ *dpc_semaphore = (SemaphoreInfo *) NULL;
+
+static size_t
+ dpc_clients = 0,
+ dpc_unauthenticated_clients = 0;
+#endif
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -184,9 +195,9 @@ static void InitializeWinsock2(MagickBooleanType use_lock)
{
if (use_lock != MagickFalse)
{
- if (winsock2_semaphore == (SemaphoreInfo *) NULL)
- ActivateSemaphoreInfo(&winsock2_semaphore);
- LockSemaphoreInfo(winsock2_semaphore);
+ if (winsock_semaphore == (SemaphoreInfo *) NULL)
+ ActivateSemaphoreInfo(&winsock_semaphore);
+ LockSemaphoreInfo(winsock_semaphore);
}
if (wsaData == (WSADATA *) NULL)
{
@@ -195,7 +206,7 @@ static void InitializeWinsock2(MagickBooleanType use_lock)
ThrowFatalException(CacheFatalError,"WSAStartup failed");
}
if (use_lock != MagickFalse)
- UnlockSemaphoreInfo(winsock2_semaphore);
+ UnlockSemaphoreInfo(winsock_semaphore);
}
#endif
@@ -239,10 +250,10 @@ static inline uint64_t SIPHash24(const uint8_t key[16],const uint8_t *message,
k0 = U8TO64_LE(key),
k1 = U8TO64_LE(key+8),
m,
- v0 = 0x736f6d6570736575ULL^k0,
- v1 = 0x646f72616e646f6dULL^k1,
- v2 = 0x6c7967656e657261ULL^k0,
- v3 = 0x7465646279746573ULL^k1;
+ v0 = 0x736f6d6570736575ULL ^ k0,
+ v1 = 0x646f72616e646f6dULL ^ k1,
+ v2 = 0x6c7967656e657261ULL ^ k0,
+ v3 = 0x7465646279746573ULL ^ k1;
for ( ; message != end; message+=8)
{
@@ -288,7 +299,7 @@ static inline uint64_t SIPHash24(const uint8_t key[16],const uint8_t *message,
return(v0^v1^v2^v3);
}
-static inline void DeriveSipKeyFromSecret(const char *shared_secret,
+static inline void DeriveSIPKeyFromSecret(const char *shared_secret,
uint8_t key[16])
{
size_t
@@ -298,15 +309,15 @@ static inline void DeriveSipKeyFromSecret(const char *shared_secret,
uint64_t
k0 = 0x0706050403020100ULL,
k1 = 0x0f0e0d0c0b0a0908ULL;
-
+
length=strlen(shared_secret);
for (i=0; i < length; i++)
{
- uint8_t
+ uint8_t
b = shared_secret[i];
-
+
k0^=b;
- k0*=0x100000001b3ULL;
+ k0*=0x100000001b3ULL;
k1^=(uint64_t) b << ((i & 7)*8);
k1=(k1 << 5) | (k1 >> (64-5));
}
@@ -320,7 +331,7 @@ static inline uint64_t GenerateSessionKey(const char *shared_secret,
uint8_t
key[16];
- DeriveSipKeyFromSecret(shared_secret,key);
+ DeriveSIPKeyFromSecret(shared_secret,key);
return(SIPHash24(key,nonce,length));
}
@@ -465,7 +476,7 @@ static char *GetHostname(int *port,ExceptionInfo *exception)
(void) SubstituteString(&hosts,","," ");
hostlist=StringToArgv(hosts,&argc);
hosts=DestroyString(hosts);
- if (hostlist == (char **) NULL)
+ if ((hostlist == (char **) NULL) || ((argc-1) == 0))
{
*port=DPCPort;
return(AcquireString(DPCHostname));
@@ -1014,6 +1025,31 @@ static MagickBooleanType WriteDistributeCachePixels(SplayTreeInfo *registry,
return(SyncAuthenticPixels(image,exception));
}
+static void LockDPCSemaphore(void)
+{
+ if (dpc_semaphore == (SemaphoreInfo *) NULL)
+ ActivateSemaphoreInfo(&dpc_semaphore);
+ LockSemaphoreInfo(dpc_semaphore);
+}
+
+static void AuthenticateDPCClient(void)
+{
+ LockDPCSemaphore();
+ if (dpc_unauthenticated_clients != 0)
+ dpc_unauthenticated_clients--;
+ UnlockSemaphoreInfo(dpc_semaphore);
+}
+
+static void RelinquishDPCClient(const MagickBooleanType unauthenticated)
+{
+ LockDPCSemaphore();
+ if ((unauthenticated != MagickFalse) && (dpc_unauthenticated_clients != 0))
+ dpc_unauthenticated_clients--;
+ if (dpc_clients != 0)
+ dpc_clients--;
+ UnlockSemaphoreInfo(dpc_semaphore);
+}
+
static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket_arg)
{
char
@@ -1023,6 +1059,7 @@ static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket_arg)
*exception;
MagickBooleanType
+ authenticated = MagickFalse,
status = MagickFalse;
MagickOffsetType
@@ -1077,6 +1114,7 @@ static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket_arg)
if (count != (MagickOffsetType) sizeof(nonce))
{
CLOSE_SOCKET(client_socket);
+ RelinquishDPCClient(MagickTrue);
return(HANDLER_RETURN_VALUE);
}
/*
@@ -1086,8 +1124,11 @@ static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket_arg)
if ((count != (MagickOffsetType) sizeof(key)) || (key != session_key))
{
CLOSE_SOCKET(client_socket);
+ RelinquishDPCClient(MagickTrue);
return(HANDLER_RETURN_VALUE);
}
+ AuthenticateDPCClient();
+ authenticated=MagickTrue;
exception=AcquireExceptionInfo();
registry=NewSplayTree((int (*)(const void *,const void *)) NULL,
(void *(*)(void *)) NULL,RelinquishImageRegistry);
@@ -1153,9 +1194,81 @@ static HANDLER_RETURN_TYPE DistributePixelCacheClient(void *socket_arg)
CLOSE_SOCKET(client_socket);
exception=DestroyExceptionInfo(exception);
registry=DestroySplayTree(registry);
+ RelinquishDPCClient(authenticated == MagickFalse ? MagickTrue :
+ MagickFalse);
return(HANDLER_RETURN_VALUE);
}
+static size_t GetDPCPolicyLimit(const char *name,const size_t default_limit)
+{
+ char
+ policy_name[MagickPathExtent],
+ *policy_value;
+
+ size_t
+ limit;
+
+ limit=default_limit;
+ (void) FormatLocaleString(policy_name,MagickPathExtent,"cache:%s",name);
+ policy_value=GetPolicyValue(policy_name);
+ if (policy_value != (char *) NULL)
+ {
+ char
+ *q;
+
+ unsigned long
+ policy_limit;
+
+ errno=0;
+ policy_limit=strtoul(policy_value,&q,10);
+ if ((errno == 0) && (q != policy_value) && (policy_limit != 0))
+ limit=(size_t) policy_limit;
+ policy_value=DestroyString(policy_value);
+ }
+ return(limit);
+}
+
+static size_t GetMaxDPCClients(void)
+{
+ return(GetDPCPolicyLimit("max-dpc-clients",DPCMaxClientWorkers));
+}
+
+static size_t GetMaxDPCUnauthenticatedClients(void)
+{
+ size_t
+ client_workers,
+ unauthenticated_workers;
+
+ client_workers=GetMaxDPCClients();
+ unauthenticated_workers=GetDPCPolicyLimit("max-dpc-unauthenticated-clients",
+ DPCMaxUnauthenticatedClientWorkers);
+ return(MagickMin(unauthenticated_workers,client_workers));
+}
+
+static MagickBooleanType AcquireDPCClientWorker(void)
+{
+ MagickBooleanType
+ status;
+
+ size_t
+ max_dpc_clients,
+ unauthenticated_worker_limit;
+
+ status=MagickFalse;
+ max_dpc_clients=GetMaxDPCClients();
+ unauthenticated_worker_limit=GetMaxDPCUnauthenticatedClients();
+ LockDPCSemaphore();
+ if ((dpc_clients < max_dpc_clients) &&
+ (dpc_unauthenticated_clients < unauthenticated_worker_limit))
+ {
+ dpc_clients++;
+ dpc_unauthenticated_clients++;
+ status=MagickTrue;
+ }
+ UnlockSemaphoreInfo(dpc_semaphore);
+ return(status);
+}
+
MagickExport void DistributePixelCacheServer(const int port,
ExceptionInfo *exception)
{
@@ -1275,6 +1388,13 @@ MagickExport void DistributePixelCacheServer(const int port,
client_socket_ptr);
continue;
}
+ if (AcquireDPCClientWorker() == MagickFalse)
+ {
+ CLOSE_SOCKET(*client_socket_ptr);
+ client_socket_ptr=(SOCKET_TYPE *) RelinquishMagickMemory(
+ client_socket_ptr);
+ continue;
+ }
#if defined(MAGICKCORE_HAVE_WINSOCK2)
{
DWORD
@@ -1297,6 +1417,7 @@ MagickExport void DistributePixelCacheServer(const int port,
if (status == -1)
{
CLOSE_SOCKET(*client_socket_ptr);
+ RelinquishDPCClient(MagickTrue);
client_socket_ptr=(SOCKET_TYPE *) RelinquishMagickMemory(
client_socket_ptr);
continue;
@@ -1307,6 +1428,7 @@ MagickExport void DistributePixelCacheServer(const int port,
if (status != 0)
{
CLOSE_SOCKET(*client_socket_ptr);
+ RelinquishDPCClient(MagickTrue);
RelinquishMagickMemory(client_socket_ptr);
continue;
}
@@ -1314,6 +1436,7 @@ MagickExport void DistributePixelCacheServer(const int port,
if (CreateThread(0,0,DistributePixelCacheClient,(void*) client_socket_ptr,0,&threadID) == (HANDLE) NULL)
{
CLOSE_SOCKET(*client_socket_ptr);
+ RelinquishDPCClient(MagickTrue);
RelinquishMagickMemory(client_socket_ptr);
continue;
}
@@ -1341,16 +1464,20 @@ MagickExport void DistributePixelCacheServer(const int port,
MagickPrivate void DistributeCacheTerminus(void)
{
#ifdef MAGICKCORE_HAVE_WINSOCK2
- if (winsock2_semaphore == (SemaphoreInfo *) NULL)
- ActivateSemaphoreInfo(&winsock2_semaphore);
- LockSemaphoreInfo(winsock2_semaphore);
+ if (winsock_semaphore == (SemaphoreInfo *) NULL)
+ ActivateSemaphoreInfo(&winsock_semaphore);
+ LockSemaphoreInfo(winsock_semaphore);
if (wsaData != (WSADATA *) NULL)
{
WSACleanup();
wsaData=(WSADATA *) RelinquishMagickMemory((void *) wsaData);
}
- UnlockSemaphoreInfo(winsock2_semaphore);
- RelinquishSemaphoreInfo(&winsock2_semaphore);
+ UnlockSemaphoreInfo(winsock_semaphore);
+ RelinquishSemaphoreInfo(&winsock_semaphore);
+#endif
+#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
+ if (dpc_semaphore != (SemaphoreInfo *) NULL)
+ RelinquishSemaphoreInfo(&dpc_semaphore);
#endif
}
diff --git a/config/policy-open.xml b/config/policy-open.xml
index 033ec8a8f..016911738 100644
--- a/config/policy-open.xml
+++ b/config/policy-open.xml
@@ -157,4 +157,8 @@
<!-- <policy domain="system" name="symlink" rights="none" pattern="follow"/> -->
<!-- Blocks all SVG entity‑substitution attempts by denying the svg:substitute-entities define -->
<!-- <policy domain="system" name="svg" rights="none" pattern="substitute-entities"/> -->
+ <!-- Set the maximum distributed pixel cache clients -->
+ <!-- <policy domain="cache" name="max-dpc-clients" value="128"/> -->
+ <!-- Set the maximum distributed pixel cache unauthenticated clients -->
+ <!-- <policy domain="cache" name="max-dpc-unauthenticated-clients" value="16"/> -->
</policymap>