54#include "MagickCore/studio.h"
55#include "MagickCore/cache.h"
56#include "MagickCore/cache-private.h"
57#include "MagickCore/distribute-cache.h"
58#include "MagickCore/distribute-cache-private.h"
59#include "MagickCore/exception.h"
60#include "MagickCore/exception-private.h"
61#include "MagickCore/geometry.h"
62#include "MagickCore/image.h"
63#include "MagickCore/image-private.h"
64#include "MagickCore/list.h"
65#include "MagickCore/locale_.h"
66#include "MagickCore/memory_.h"
67#include "MagickCore/nt-base-private.h"
68#include "MagickCore/pixel.h"
69#include "MagickCore/policy.h"
70#include "MagickCore/random_.h"
71#include "MagickCore/registry.h"
72#include "MagickCore/splay-tree.h"
73#include "MagickCore/string_.h"
74#include "MagickCore/string-private.h"
75#include "MagickCore/utility-private.h"
76#include "MagickCore/version.h"
77#include "MagickCore/version-private.h"
78#define SOCKET_TYPE int
79#undef MAGICKCORE_HAVE_DISTRIBUTE_CACHE
80#if defined(MAGICKCORE_DPC_SUPPORT)
81#if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT)
82#include <netinet/in.h>
83#include <netinet/tcp.h>
85#include <sys/socket.h>
87#define CLOSE_SOCKET(socket) (void) close_utf8(socket)
88#define HANDLER_RETURN_TYPE void *
89#define HANDLER_RETURN_VALUE (void *) NULL
90#define SOCKET_TYPE int
91#define LENGTH_TYPE size_t
92#define MAGICKCORE_HAVE_DISTRIBUTE_CACHE 1
93#elif defined(_MSC_VER)
94#define CLOSE_SOCKET(socket) (void) closesocket(socket)
95#define HANDLER_RETURN_TYPE DWORD WINAPI
96#define HANDLER_RETURN_VALUE 0
97#define LENGTH_TYPE int
98#define MAGICKCORE_HAVE_DISTRIBUTE_CACHE 1
99#define MAGICKCORE_HAVE_WINSOCK2 1
106#define DPCHostname "127.0.0.1"
107#define DPCMacLength 32
108#define DPCMaxClientWorkers 128
109#define DPCMaxUnauthenticatedClientWorkers 16
110#define DPCPendingConnections 10
112#define DPCScratchExtent 16384
113#define DPCSessionKeyLength 16
115# define MSG_NOSIGNAL 0
136#ifdef MAGICKCORE_HAVE_WINSOCK2
141 *wsaData = (WSADATA*) NULL;
144#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
149 *dpc_shared_secret = (
char *) NULL;
153 dpc_unauthenticated_clients = 0;
179#if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
180static inline MagickOffsetType dpc_receive(SOCKET_TYPE magick_unused(file),
181 const MagickSizeType magick_unused(length),
182 unsigned char *magick_restrict magick_unused(message))
184 magick_unreferenced(file);
185 magick_unreferenced(length);
186 magick_unreferenced(message);
190static void SetSocketNoDelay(SOCKET_TYPE file)
198 (void) setsockopt(file,IPPROTO_TCP,TCP_NODELAY,(
const char *) &one,
199 (socklen_t)
sizeof(one));
202static void SetSocketReceiveTimeout(SOCKET_TYPE file,
double seconds)
207#if defined(MAGICKCORE_HAVE_WINSOCK2)
209 DWORD timeout = (DWORD) (seconds*1000.0);
210 (void) setsockopt(file,SOL_SOCKET,SO_RCVTIMEO,
211 (
const char *) &timeout,
sizeof(timeout));
216 tv.tv_sec=(int) seconds;
217 tv.tv_usec=(int) ((seconds-(
double) tv.tv_sec)*1000000.0);
218 (void) setsockopt(file,SOL_SOCKET,SO_RCVTIMEO,&tv,
sizeof(tv));
223static inline MagickOffsetType dpc_receive(SOCKET_TYPE file,
224 const MagickSizeType length,
unsigned char *magick_restrict message)
226 MagickOffsetType offset = 0;
227 while (offset < (MagickOffsetType) length)
229 MagickSizeType chunk = MagickMin(length-offset,(MagickSizeType)
230 MagickMaxBufferExtent);
231 ssize_t count = recv(file,(
char *) message+offset,(LENGTH_TYPE) chunk,0);
233 offset+=(MagickOffsetType) count;
239#ifdef MAGICKCORE_HAVE_WINSOCK2
240 int wsa_err = WSAGetLastError();
241 if ((wsa_err == WSAEINTR) || (wsa_err == WSAEWOULDBLOCK))
243 if (wsa_err == WSAECONNRESET)
246 if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
248 if (errno == ECONNRESET)
257static inline MagickOffsetType dpc_receive_deadline(SOCKET_TYPE file,
258 MagickSizeType length,
unsigned char *message,
double deadline)
263 MagickOffsetType offset = 0;
264 while (offset < (MagickOffsetType) length)
267 now = (double) time((time_t *) NULL),
268 remaining = deadline-now;
278 if (remaining < 0.001)
280 SetSocketReceiveTimeout(file,remaining);
281 chunk=MagickMin(length-offset,(MagickSizeType) MagickMaxBufferExtent);
282 count=recv(file,(
char *) message+offset,(LENGTH_TYPE) chunk,0);
284 offset+=(MagickOffsetType) count;
290#ifdef MAGICKCORE_HAVE_WINSOCK2
291 int wsa_err = WSAGetLastError();
292 if ((wsa_err == WSAEINTR) || (wsa_err == WSAEWOULDBLOCK))
294 if (wsa_err == WSAECONNRESET)
298 if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK))
300 if (errno == ECONNRESET)
310#if defined(MAGICKCORE_HAVE_WINSOCK2)
311static void InitializeWinsock2(MagickBooleanType use_lock)
313 if (use_lock != MagickFalse)
316 ActivateSemaphoreInfo(&winsock_semaphore);
317 LockSemaphoreInfo(winsock_semaphore);
319 if (wsaData == (WSADATA *) NULL)
321 wsaData=(WSADATA *) AcquireMagickMemory(
sizeof(WSADATA));
322 if (WSAStartup(MAKEWORD(2,2),wsaData) != 0)
323 ThrowFatalException(CacheFatalError,
"WSAStartup failed");
325 if (use_lock != MagickFalse)
326 UnlockSemaphoreInfo(winsock_semaphore);
330#if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
331static int ConnectPixelCacheServer(
const char *magick_unused(hostname),
332 const int magick_unused(port),uint64_t *magick_unused(session_key),
335 magick_unreferenced(hostname);
336 magick_unreferenced(port);
337 magick_unreferenced(session_key);
338 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
339 "DelegateLibrarySupportNotBuiltIn",
"distributed pixel cache");
343static inline uint64_t ROTL(uint64_t x,
int b)
345 return((x << b) | (x >> (64-b)));
348static inline uint64_t U8TO64_LE(
const uint8_t *p)
350 return(((uint64_t) p[0] << 0) | ((uint64_t) p[1] << 8) |
351 ((uint64_t) p[2] << 16) | ((uint64_t) p[3] << 24) |
352 ((uint64_t) p[4] << 32) | ((uint64_t) p[5] << 40) |
353 ((uint64_t) p[6] << 48) | ((uint64_t) p[7] << 56));
356static inline uint64_t SIPHash24(
const uint8_t key[16],
const uint8_t *message,
360 *end = message+length-(length % 8);
366 b = ((uint64_t) length) << 56,
368 k1 = U8TO64_LE(key+8),
370 v0 = 0x736f6d6570736575ULL ^ k0,
371 v1 = 0x646f72616e646f6dULL ^ k1,
372 v2 = 0x6c7967656e657261ULL ^ k0,
373 v3 = 0x7465646279746573ULL ^ k1;
375 for ( ; message != end; message+=8)
377 m=U8TO64_LE(message);
379 for (i=0; i < 2; i++)
381 v0+=v1; v1=ROTL(v1,13); v1^=v0; v0=ROTL(v0,32);
382 v2+=v3; v3=ROTL(v3,16); v3^=v2;
383 v0+=v3; v3=ROTL(v3,21); v3^=v0;
384 v2+=v1; v1=ROTL(v1,17); v1^=v2; v2=ROTL(v2,32);
388 switch (length & 0x07)
390 case 7: b|=((uint64_t) message[6]) << 48; magick_fallthrough;
391 case 6: b|=((uint64_t) message[5]) << 40; magick_fallthrough;
392 case 5: b|=((uint64_t) message[4]) << 32; magick_fallthrough;
393 case 4: b|=((uint64_t) message[3]) << 24; magick_fallthrough;
394 case 3: b|=((uint64_t) message[2]) << 16; magick_fallthrough;
395 case 2: b|=((uint64_t) message[1]) << 8; magick_fallthrough;
396 case 1: b|=((uint64_t) message[0]); magick_fallthrough;
400 for (i=0; i < 2; i++)
402 v0+=v1; v1=ROTL(v1,13); v1^=v0; v0=ROTL(v0,32);
403 v2+=v3; v3=ROTL(v3,16); v3^=v2;
404 v0+=v3; v3=ROTL(v3,21); v3^=v0;
405 v2+=v1; v1=ROTL(v1,17); v1^=v2; v2=ROTL(v2,32);
409 for (i=0; i < 4; i++)
411 v0+=v1; v1=ROTL(v1,13); v1^=v0; v0=ROTL(v0,32);
412 v2+=v3; v3=ROTL(v3,16); v3^=v2;
413 v0+=v3; v3=ROTL(v3,21); v3^=v0;
414 v2+=v1; v1=ROTL(v1,17); v1^=v2; v2=ROTL(v2,32);
419static inline void DeriveSIPKeyFromSecret(
const char *shared_secret,
427 k0 = 0x0706050403020100ULL,
428 k1 = 0x0f0e0d0c0b0a0908ULL;
430 length=strlen(shared_secret);
431 for (i=0; i < length; i++)
434 b = (uint8_t) shared_secret[i];
437 k0*=0x100000001b3ULL;
438 k1^=(uint64_t) b << ((i & 7)*8);
439 k1=(k1 << 5) | (k1 >> (64-5));
441 (void) memcpy(key,&k0,8);
442 (void) memcpy(key+8,&k1,8);
445static inline uint64_t GenerateSessionKey(
const char *shared_secret,
446 const unsigned char *nonce,
size_t length)
451 DeriveSIPKeyFromSecret(shared_secret,key);
452 return(SIPHash24(key,nonce,length));
455static int ConnectPixelCacheServer(
const char *hostname,
const int port,
458#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
461 service[MagickPathExtent],
478 nonce[DPCSessionKeyLength];
484#if defined(MAGICKCORE_HAVE_WINSOCK2)
485 InitializeWinsock2(MagickTrue);
487 (void) memset(&hints,0,
sizeof(hints));
488 hints.ai_family=AF_INET;
489 hints.ai_socktype=SOCK_STREAM;
490 hints.ai_flags=AI_PASSIVE;
491 (void) FormatLocaleString(service,MagickPathExtent,
"%d",port);
492 status=getaddrinfo(hostname,service,&hints,&result);
495 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
496 "DistributedPixelCache",
"'%s': %s",hostname,gai_strerror(status));
499 client_socket=(SOCKET_TYPE) socket(result->ai_family,result->ai_socktype,
500 result->ai_protocol);
501 if (client_socket == -1)
503 freeaddrinfo(result);
504 message=GetExceptionMessage(errno);
505 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
506 "DistributedPixelCache",
"'%s': %s",hostname,message);
507 message=DestroyString(message);
510 status=connect(client_socket,result->ai_addr,(socklen_t) result->ai_addrlen);
511 freeaddrinfo(result);
514 CLOSE_SOCKET(client_socket);
515 message=GetExceptionMessage(errno);
516 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
517 "DistributedPixelCache",
"'%s': %s",hostname,message);
518 message=DestroyString(message);
521 SetSocketNoDelay(client_socket);
525 count=recv(client_socket,(
char *) nonce,
sizeof(nonce),0);
526 if (count != (ssize_t)
sizeof(nonce))
528 CLOSE_SOCKET(client_socket);
529 message=GetExceptionMessage(errno);
530 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
531 "DistributedPixelCache",
"'%s': %s",hostname,message);
532 message=DestroyString(message);
538 shared_secret=GetPolicyValue(
"cache:shared-secret");
539 if (shared_secret == (
const char *) NULL)
541 CLOSE_SOCKET(client_socket);
542 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
543 "DistributedPixelCache",
"'%s': shared secret required",hostname);
546 *session_key=GenerateSessionKey(shared_secret,nonce,
sizeof(nonce));
547 shared_secret=DestroyString(shared_secret);
551 count=send(client_socket,(
char *) session_key,
sizeof(*session_key),
553 if (count != (ssize_t)
sizeof(*session_key))
555 CLOSE_SOCKET(client_socket);
556 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
557 "DistributedPixelCache",
"'%s': authentication failed",hostname);
560 return((
int) client_socket);
562 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
563 "DelegateLibrarySupportNotBuiltIn",
"distributed pixel cache");
588 hosts=(
char *) GetImageRegistry(StringRegistryType,
"cache:hosts",exception);
589 if (hosts == (
char *) NULL)
592 return(AcquireString(DPCHostname));
594 (void) SubstituteString(&hosts,
",",
" ");
595 hostlist=StringToArgv(hosts,&argc);
596 hosts=DestroyString(hosts);
597 if ((hostlist == (
char **) NULL) || ((argc-1) == 0))
600 return(AcquireString(DPCHostname));
603 size_t host_count = (size_t) argc-1;
604 size_t index = (
id++ % host_count)+1;
605 hosts=AcquireString(hostlist[index]);
607 for (i=0; i < (ssize_t) argc; i++)
608 hostlist[i]=DestroyString(hostlist[i]);
609 hostlist=(
char **) RelinquishMagickMemory(hostlist);
610 (void) SubstituteString(&hosts,
":",
" ");
611 hostlist=StringToArgv(hosts,&argc);
612 if (hostlist == (
char **) NULL)
615 return(AcquireString(DPCHostname));
617 host=AcquireString(hostlist[1]);
618 if (hostlist[2] == (
char *) NULL)
621 *port=(int) StringToLong(hostlist[2]);
622 for (i=0; i < (ssize_t) argc; i++)
623 hostlist[i]=DestroyString(hostlist[i]);
624 hostlist=(
char **) RelinquishMagickMemory(hostlist);
644 sizeof(*server_info));
645 (void) memset(server_info,0,
sizeof(*server_info));
646 server_info->signature=MagickCoreSignature;
648 hostname=GetHostname(&server_info->port,exception);
650 server_info->file=ConnectPixelCacheServer(hostname,server_info->port,
651 &session_key,exception);
652 if (server_info->file == -1)
653 server_info=DestroyDistributeCacheInfo(server_info);
656 server_info->session_key=session_key;
657 (void) CopyMagickString(server_info->hostname,hostname,MagickPathExtent);
658 server_info->debug=(GetLogEventMask() & CacheEvent) != 0 ? MagickTrue :
661 hostname=DestroyString(hostname);
700static void InitializeSHA256Hash(
SHA256Hash *sha256_hash)
702 sha256_hash->count=0;
703 sha256_hash->state[0]=0x6a09e667;
704 sha256_hash->state[1]=0xbb67ae85;
705 sha256_hash->state[2]=0x3c6ef372;
706 sha256_hash->state[3]=0xa54ff53a;
707 sha256_hash->state[4]=0x510e527f;
708 sha256_hash->state[5]=0x9b05688c;
709 sha256_hash->state[6]=0x1f83d9ab;
710 sha256_hash->state[7]=0x5be0cd19;
713static void TransformSHA256Hash(
SHA256Hash *sha256_hash,
714 const unsigned char data[])
716#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
717#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
718#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
719#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
720#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
721#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
722#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
724 static const uint32_t K[64] =
726 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
727 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
728 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
729 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
730 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
731 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
732 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
733 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
734 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
735 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
736 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
753 for (i=0; i < 16; i++, j+=4)
754 m[i]=((uint32_t) data[j] << 24) | ((uint32_t) data[j+1] << 16) |
755 ((uint32_t) data[j+2] << 8) | ((uint32_t) data[j+3]);
757 m[i]=SIG1(m[i-2])+m[i-7]+SIG0(m[i-15])+m[i-16];
758 a=sha256_hash->state[0];
759 b=sha256_hash->state[1];
760 c=sha256_hash->state[2];
761 d=sha256_hash->state[3];
762 e=sha256_hash->state[4];
763 f=sha256_hash->state[5];
764 g=sha256_hash->state[6];
765 h=sha256_hash->state[7];
766 for (i=0; i < 64; i++)
769 alpha = h+EP1(e)+CH(e,f,g)+K[i]+m[i],
770 beta = EP0(a)+MAJ(a,b,c);
781 sha256_hash->state[0]+=a;
782 sha256_hash->state[1]+=b;
783 sha256_hash->state[2]+=c;
784 sha256_hash->state[3]+=d;
785 sha256_hash->state[4]+=e;
786 sha256_hash->state[5]+=f;
787 sha256_hash->state[6]+=g;
788 sha256_hash->state[7]+=h;
791static void UpdateSHA256Hash(
SHA256Hash *sha256_hash,
const unsigned char *data,
792 const size_t data_length)
796 index = (size_t) ((sha256_hash->count/8) % 64);
798 sha256_hash->count+=(uint64_t) data_length*8;
799 for (i=0; i < data_length; i++)
801 sha256_hash->buffer[index++]=data[i];
804 TransformSHA256Hash(sha256_hash,sha256_hash->buffer);
810static void FinalizeSHA256Hash(
SHA256Hash *sha256_hash,
unsigned char hash[32])
814 index = (size_t) ((sha256_hash->count/8) % 64),
815 pad_length = (index < 56) ? (56-index) : (120-index);
818 bit_count = sha256_hash->count;
824 (void) memset(pad+1,0,pad_length-1);
825 UpdateSHA256Hash(sha256_hash,pad,pad_length);
826 for (i=0; i < 8; i++)
827 pad[i]=(
unsigned char) (bit_count >> ((7-i)*8));
828 UpdateSHA256Hash(sha256_hash, pad, 8);
829 for (i=0; i < 32; i++)
830 hash[i]=(
unsigned char) (sha256_hash->state[i/4] >> ((3-(i % 4))*8));
833static void ComputeSHA256Hash(
const unsigned char *data,
size_t length,
834 unsigned char hash[32])
842 InitializeSHA256Hash(&sha256_hash);
843 UpdateSHA256Hash(&sha256_hash,data,length);
844 FinalizeSHA256Hash(&sha256_hash,hash);
847static int ComputeHMACSHA256Mac(
const void *key,
size_t key_length,
848 const void *message,
size_t message_length,
unsigned char *mac,
867 if ((mac == (
unsigned char *) NULL) || (mac_length == 0))
869 if (((key == (
const void *) NULL) && (key_length != 0)) ||
870 ((message == (
const void *) NULL) && (message_length != 0)))
873 ComputeSHA256Hash((
unsigned char *) key,key_length,k_prime);
875 (
void) memcpy(k_prime,key,key_length);
879 for (i=0; i < 64; i++)
881 inner_pad[i]=k_prime[i] ^ 0x36;
882 outer_pad[i]=k_prime[i] ^ 0x5c;
887 InitializeSHA256Hash(&sha256_hash);
888 UpdateSHA256Hash(&sha256_hash,inner_pad,64);
889 UpdateSHA256Hash(&sha256_hash,(
unsigned char *) message,message_length);
890 FinalizeSHA256Hash(&sha256_hash,inner_hash);
894 InitializeSHA256Hash(&sha256_hash);
895 UpdateSHA256Hash(&sha256_hash,outer_pad,64);
896 UpdateSHA256Hash(&sha256_hash,inner_hash,32);
897 FinalizeSHA256Hash(&sha256_hash,full_hash);
901 (void) memcpy(mac,full_hash,(mac_length < 32) ? mac_length : 32);
933 assert(server_info->signature == MagickCoreSignature);
934#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
935 if (server_info->file >= 0)
936 CLOSE_SOCKET(server_info->file);
938 server_info->signature=(~MagickCoreSignature);
969#if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
970static inline MagickOffsetType dpc_send(SOCKET_TYPE magick_unused(file),
971 const MagickSizeType magick_unused(length),
972 const void *magick_restrict magick_unused(message))
974 magick_unreferenced(file);
975 magick_unreferenced(length);
976 magick_unreferenced(message);
980static inline MagickOffsetType dpc_send(SOCKET_TYPE file,
981 const MagickSizeType length,
const void *magick_restrict message)
993 for (i=0; i < (MagickOffsetType) length; i+=count)
995 count=(ssize_t) send(file,(
const char *) message+i,(LENGTH_TYPE) MagickMin(
996 length-(MagickSizeType) i,(MagickSizeType) MagickMaxBufferExtent),
1009static const char *GetDPCSharedSecret(
void)
1011#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
1015 if (dpc_shared_secret == (
char *) NULL)
1018 ActivateSemaphoreInfo(&dpc_semaphore);
1019 LockSemaphoreInfo(dpc_semaphore);
1020 if (dpc_shared_secret == (
char *) NULL)
1021 dpc_shared_secret=GetPolicyValue(
"cache:shared-secret");
1022 UnlockSemaphoreInfo(dpc_semaphore);
1024 return(dpc_shared_secret);
1026 return((
const char *) NULL);
1030static int DeriveDPCKey(
const uint64_t session_key,
const char label,
1031 unsigned char key[DPCMacLength])
1037 info[
sizeof(session_key)+1];
1043 shared_secret=GetDPCSharedSecret();
1044 if (shared_secret == (
const char *) NULL)
1046 (void) memcpy(info,&session_key,
sizeof(session_key));
1047 info[
sizeof(session_key)]=(
unsigned char) label;
1048 return(ComputeHMACSHA256Mac(shared_secret,strlen(shared_secret),info,
1049 sizeof(info),key,DPCMacLength));
1052static inline uint64_t LoadDPCWord(
const unsigned char *p)
1054 return(((uint64_t) p[0]) | ((uint64_t) p[1] << 8) |
1055 ((uint64_t) p[2] << 16) | ((uint64_t) p[3] << 24) |
1056 ((uint64_t) p[4] << 32) | ((uint64_t) p[5] << 40) |
1057 ((uint64_t) p[6] << 48) | ((uint64_t) p[7] << 56));
1060static void SplitMix64Keystream(
const unsigned char *stream_key,
1061 const unsigned char *mac,
const MagickSizeType offset,
unsigned char *data,
1062 const size_t length)
1075 seed=LoadDPCWord(stream_key) ^ LoadDPCWord(mac);
1076 block=(uint64_t) (offset >> 3);
1078 for (i=0; i < length; i++)
1081 j = (size_t) ((offset+i) & 7);
1083 if ((i == 0) || (j == 0))
1085 block=(uint64_t) ((offset+i) >> 3);
1086 z=seed+(block+1)*0x9e3779b97f4a7c15ULL;
1087 z=(z ^ (z >> 30))*0xbf58476d1ce4e5b9ULL;
1088 z=(z ^ (z >> 27))*0x94d049bb133111ebULL;
1091 data[i]^=(
unsigned char) (z >> (j*8));
1095static inline void WipeDPCKey(
unsigned char *key,
const size_t length)
1097 volatile unsigned char
1103 for (i=0; i < length; i++)
1107static inline int mac_compare(
const unsigned char *a,
const unsigned char *b,
1108 const size_t length)
1113 volatile unsigned char
1119 for (i=0; i < length; i++)
1120 difference|=(
unsigned char) (a[i] ^ b[i]);
1121 return(difference == 0 ? 0 : -1);
1124static inline MagickOffsetType dpc_send_mac(SOCKET_TYPE file,
1125 const MagickSizeType length,
const void *magick_restrict message,
1126 uint64_t session_key)
1129 *p = (
const unsigned char *) message;
1139 mac_key[DPCMacLength],
1140 scratch[DPCScratchExtent],
1141 stream_key[DPCMacLength];
1146 if (length > (MagickSizeType) MAGICK_SSIZE_MAX)
1148 if ((DeriveDPCKey(session_key,
'm',mac_key) != 0) ||
1149 (DeriveDPCKey(session_key,
'e',stream_key) != 0) ||
1150 (ComputeHMACSHA256Mac(mac_key,
sizeof(mac_key),message,(
size_t) length, mac,
sizeof(mac)) != 0))
1152 WipeDPCKey(mac_key,
sizeof(mac_key));
1153 WipeDPCKey(stream_key,
sizeof(stream_key));
1156 WipeDPCKey(mac_key,
sizeof(mac_key));
1157 status=dpc_send(file,
sizeof(mac),mac);
1158 if (status != (MagickOffsetType)
sizeof(mac))
1160 WipeDPCKey(stream_key,
sizeof(stream_key));
1166 for (offset=0; offset < length; )
1169 chunk = (size_t) MagickMin(length-offset,(MagickSizeType)
1172 (void) memcpy(scratch,p+offset,chunk);
1173 SplitMix64Keystream(stream_key,mac,offset,scratch,chunk);
1174 status=dpc_send(file,(MagickSizeType) chunk,scratch);
1175 if (status != (MagickOffsetType) chunk)
1177 offset+=(MagickSizeType) chunk;
1179 WipeDPCKey(stream_key,
sizeof(stream_key));
1180 WipeDPCKey(scratch,
sizeof(scratch));
1181 if (offset != length)
1183 return((MagickOffsetType) length);
1186static inline MagickOffsetType dpc_receive_mac(SOCKET_TYPE file,
1187 const MagickSizeType length,
unsigned char *magick_restrict message,
1188 uint64_t session_key)
1194 expected_mac[DPCMacLength],
1195 mac_key[DPCMacLength],
1196 received_mac[DPCMacLength],
1197 stream_key[DPCMacLength];
1205 if (length > (MagickSizeType) MAGICK_SSIZE_MAX)
1207 count=dpc_receive(file,
sizeof(received_mac),received_mac);
1208 if (count != (MagickOffsetType)
sizeof(received_mac))
1210 count=dpc_receive(file,length,message);
1211 if (count != (MagickOffsetType) length)
1213 status=DeriveDPCKey(session_key,
'e',stream_key);
1216 SplitMix64Keystream(stream_key,received_mac,0,message,(
size_t) length);
1217 status=DeriveDPCKey(session_key,
'm',mac_key);
1220 status=ComputeHMACSHA256Mac(mac_key,
sizeof(mac_key),message,
1221 (
size_t) length,expected_mac,
sizeof(expected_mac));
1222 WipeDPCKey(mac_key,
sizeof(mac_key));
1223 WipeDPCKey(stream_key,
sizeof(stream_key));
1226 if (mac_compare(received_mac,expected_mac,
sizeof(expected_mac)) != 0)
1231#if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
1232MagickExport
void DistributePixelCacheServer(
const int magick_unused(port),
1235 magick_unreferenced(port);
1236 magick_unreferenced(exception);
1237 ThrowFatalException(MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn");
1240static MagickBooleanType DestroyDistributeCache(
SplayTreeInfo *registry,
1241 const uint64_t session_key)
1244 key = (MagickAddressType) session_key;
1249 return(DeleteNodeFromSplayTree(registry,(
const void *) key));
1252static MagickBooleanType OpenDistributeCache(
SplayTreeInfo *registry,
1253 SOCKET_TYPE file,
const uint64_t session_key,
ExceptionInfo *exception)
1259 key = (MagickAddressType) session_key;
1271 message[MagickPathExtent],
1277 image=AcquireImage((
ImageInfo *) NULL,exception);
1278 if (image == (
Image *) NULL)
1279 return(MagickFalse);
1280 length=
sizeof(image->storage_class)+
sizeof(image->colorspace)+
1281 sizeof(image->alpha_trait)+
sizeof(image->channels)+
sizeof(image->columns)+
1282 sizeof(image->rows)+
sizeof(image->number_channels)+MaxPixelChannels*
1283 sizeof(*image->channel_map)+
sizeof(image->metacontent_extent);
1284 count=dpc_receive(file,length,message);
1285 if (count != (MagickOffsetType) length)
1287 image=DestroyImage(image);
1288 return(MagickFalse);
1294 (void) memcpy(&image->storage_class,p,
sizeof(image->storage_class));
1295 p+=(ptrdiff_t)
sizeof(image->storage_class);
1296 (void) memcpy(&image->colorspace,p,
sizeof(image->colorspace));
1297 p+=(ptrdiff_t)
sizeof(image->colorspace);
1298 (void) memcpy(&image->alpha_trait,p,
sizeof(image->alpha_trait));
1299 p+=(ptrdiff_t)
sizeof(image->alpha_trait);
1300 (void) memcpy(&image->channels,p,
sizeof(image->channels));
1301 p+=(ptrdiff_t)
sizeof(image->channels);
1302 (void) memcpy(&image->columns,p,
sizeof(image->columns));
1303 p+=(ptrdiff_t)
sizeof(image->columns);
1304 (void) memcpy(&image->rows,p,
sizeof(image->rows));
1305 p+=(ptrdiff_t)
sizeof(image->rows);
1306 (void) memcpy(&image->number_channels,p,
sizeof(image->number_channels));
1307 p+=(ptrdiff_t)
sizeof(image->number_channels);
1308 (void) memcpy(image->channel_map,p,MaxPixelChannels*
1309 sizeof(*image->channel_map));
1310 p+=(ptrdiff_t) MaxPixelChannels*
sizeof(*image->channel_map);
1311 (void) memcpy(&image->metacontent_extent,p,
sizeof(image->metacontent_extent));
1312 p+=(ptrdiff_t)
sizeof(image->metacontent_extent);
1313 if (SyncImagePixelCache(image,exception) == MagickFalse)
1315 image=DestroyImage(image);
1316 return(MagickFalse);
1318 status=AddValueToSplayTree(registry,(
const void *) key,image);
1319 if (status == MagickFalse)
1321 image=DestroyImage(image);
1322 return(MagickFalse);
1327static inline MagickBooleanType ValidateDistributedPixelCache(
1329 const MagickSizeType length)
1335 if (HeapOverflowSanityCheckGetSize(region->width,region->height,&pixels) != MagickFalse)
1336 return(MagickFalse);
1337 if (HeapOverflowSanityCheckGetSize(pixels,per_pixel,&extent) != MagickFalse)
1338 return(MagickFalse);
1339 if (length > (MagickSizeType) extent)
1340 return(MagickFalse);
1344static MagickBooleanType ReadDistributeCacheMetacontent(
SplayTreeInfo *registry,
1345 SOCKET_TYPE file,
const uint64_t session_key,
ExceptionInfo *exception)
1357 key = (MagickAddressType) session_key;
1372 message[MagickPathExtent],
1378 image=(
Image *) GetValueFromSplayTree(registry,(
const void *) key);
1379 if (image == (
Image *) NULL)
1380 return(MagickFalse);
1381 length=
sizeof(region.width)+
sizeof(region.height)+
sizeof(region.x)+
1382 sizeof(region.y)+
sizeof(length);
1383 count=dpc_receive(file,length,message);
1384 if (count != (MagickOffsetType) length)
1385 return(MagickFalse);
1387 (void) memcpy(®ion.width,q,
sizeof(region.width));
1388 q+=(ptrdiff_t)
sizeof(region.width);
1389 (void) memcpy(®ion.height,q,
sizeof(region.height));
1390 q+=(ptrdiff_t)
sizeof(region.height);
1391 (void) memcpy(®ion.x,q,
sizeof(region.x));
1392 q+=(ptrdiff_t)
sizeof(region.x);
1393 (void) memcpy(®ion.y,q,
sizeof(region.y));
1394 q+=(ptrdiff_t)
sizeof(region.y);
1395 (void) memcpy(&length,q,
sizeof(length));
1396 q+=(ptrdiff_t)
sizeof(length);
1397 per_pixel=image->number_meta_channels*
sizeof(Quantum);
1398 if (ValidateDistributedPixelCache(®ion,per_pixel,length) == MagickFalse)
1399 return(MagickFalse);
1400 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
1402 if (p == (
const Quantum *) NULL)
1403 return(MagickFalse);
1404 metacontent=(
const unsigned char *) GetVirtualMetacontent(image);
1405 count=dpc_send_mac(file,length,metacontent,session_key);
1406 if (count != (MagickOffsetType) length)
1407 return(MagickFalse);
1411static MagickBooleanType ReadDistributeCachePixels(
SplayTreeInfo *registry,
1412 SOCKET_TYPE file,
const uint64_t session_key,
ExceptionInfo *exception)
1421 key = (MagickAddressType) session_key;
1436 message[MagickPathExtent],
1442 image=(
Image *) GetValueFromSplayTree(registry,(
const void *) key);
1443 if (image == (
Image *) NULL)
1444 return(MagickFalse);
1445 length=
sizeof(region.width)+
sizeof(region.height)+
sizeof(region.x)+
1446 sizeof(region.y)+
sizeof(length);
1447 count=dpc_receive(file,length,message);
1448 if (count != (MagickOffsetType) length)
1449 return(MagickFalse);
1451 (void) memcpy(®ion.width,q,
sizeof(region.width));
1452 q+=(ptrdiff_t)
sizeof(region.width);
1453 (void) memcpy(®ion.height,q,
sizeof(region.height));
1454 q+=(ptrdiff_t)
sizeof(region.height);
1455 (void) memcpy(®ion.x,q,
sizeof(region.x));
1456 q+=(ptrdiff_t)
sizeof(region.x);
1457 (void) memcpy(®ion.y,q,
sizeof(region.y));
1458 q+=(ptrdiff_t)
sizeof(region.y);
1459 (void) memcpy(&length,q,
sizeof(length));
1460 per_pixel=image->number_channels*
sizeof(Quantum);
1461 if (ValidateDistributedPixelCache(®ion,per_pixel,length) == MagickFalse)
1462 return(MagickFalse);
1463 q+=(ptrdiff_t)
sizeof(length);
1464 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
1466 if (p == (
const Quantum *) NULL)
1467 return(MagickFalse);
1468 count=dpc_send_mac(file,length,p,session_key);
1469 if (count != (MagickOffsetType) length)
1470 return(MagickFalse);
1474static void *RelinquishImageRegistry(
void *image)
1476 return((
void *) DestroyImageList((
Image *) image));
1479static MagickBooleanType WriteDistributeCacheMetacontent(
1480 SplayTreeInfo *registry,SOCKET_TYPE file,
const uint64_t session_key,
1487 key = (MagickAddressType) session_key;
1505 message[MagickPathExtent],
1512 image=(
Image *) GetValueFromSplayTree(registry,(
const void *) key);
1513 if (image == (
Image *) NULL)
1514 return(MagickFalse);
1515 length=
sizeof(region.width)+
sizeof(region.height)+
sizeof(region.x)+
1516 sizeof(region.y)+
sizeof(length);
1517 count=dpc_receive(file,length,message);
1518 if (count != (MagickOffsetType) length)
1519 return(MagickFalse);
1521 (void) memcpy(®ion.width,p,
sizeof(region.width));
1522 p+=(ptrdiff_t)
sizeof(region.width);
1523 (void) memcpy(®ion.height,p,
sizeof(region.height));
1524 p+=(ptrdiff_t)
sizeof(region.height);
1525 (void) memcpy(®ion.x,p,
sizeof(region.x));
1526 p+=(ptrdiff_t)
sizeof(region.x);
1527 (void) memcpy(®ion.y,p,
sizeof(region.y));
1528 p+=(ptrdiff_t)
sizeof(region.y);
1529 (void) memcpy(&length,p,
sizeof(length));
1530 per_pixel=image->number_meta_channels*
sizeof(Quantum);
1531 if (ValidateDistributedPixelCache(®ion,per_pixel,length) == MagickFalse)
1532 return(MagickFalse);
1533 p+=(ptrdiff_t)
sizeof(length);
1534 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
1536 if (q == (Quantum *) NULL)
1537 return(MagickFalse);
1538 metacontent=(
unsigned char *) GetAuthenticMetacontent(image);
1539 count=dpc_receive_mac(file,length,metacontent,session_key);
1540 if (count != (MagickOffsetType) length)
1541 return(MagickFalse);
1542 return(SyncAuthenticPixels(image,exception));
1545static MagickBooleanType WriteDistributeCachePixels(
SplayTreeInfo *registry,
1546 SOCKET_TYPE file,
const uint64_t session_key,
ExceptionInfo *exception)
1552 key = (MagickAddressType) session_key;
1570 message[MagickPathExtent],
1576 image=(
Image *) GetValueFromSplayTree(registry,(
const void *) key);
1577 if (image == (
Image *) NULL)
1578 return(MagickFalse);
1579 length=
sizeof(region.width)+
sizeof(region.height)+
sizeof(region.x)+
1580 sizeof(region.y)+
sizeof(length);
1581 count=dpc_receive(file,length,message);
1582 if (count != (MagickOffsetType) length)
1583 return(MagickFalse);
1585 (void) memcpy(®ion.width,p,
sizeof(region.width));
1586 p+=(ptrdiff_t)
sizeof(region.width);
1587 (void) memcpy(®ion.height,p,
sizeof(region.height));
1588 p+=(ptrdiff_t)
sizeof(region.height);
1589 (void) memcpy(®ion.x,p,
sizeof(region.x));
1590 p+=(ptrdiff_t)
sizeof(region.x);
1591 (void) memcpy(®ion.y,p,
sizeof(region.y));
1592 p+=(ptrdiff_t)
sizeof(region.y);
1593 (void) memcpy(&length,p,
sizeof(length));
1594 per_pixel=image->number_channels*
sizeof(Quantum);
1595 if (ValidateDistributedPixelCache(®ion,per_pixel,length) == MagickFalse)
1596 return(MagickFalse);
1597 p+=(ptrdiff_t)
sizeof(length);
1598 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
1600 if (q == (Quantum *) NULL)
1601 return(MagickFalse);
1602 count=dpc_receive_mac(file,length,(
unsigned char *) q,session_key);
1603 if (count != (MagickOffsetType) length)
1604 return(MagickFalse);
1605 return(SyncAuthenticPixels(image,exception));
1608static void LockDPCSemaphore(
void)
1611 ActivateSemaphoreInfo(&dpc_semaphore);
1612 LockSemaphoreInfo(dpc_semaphore);
1615static void AuthenticateDPCClient(
void)
1618 if (dpc_unauthenticated_clients != 0)
1619 dpc_unauthenticated_clients--;
1620 UnlockSemaphoreInfo(dpc_semaphore);
1623static void RelinquishDPCClient(
const MagickBooleanType unauthenticated)
1626 if ((unauthenticated != MagickFalse) && (dpc_unauthenticated_clients != 0))
1627 dpc_unauthenticated_clients--;
1628 if (dpc_clients != 0)
1630 UnlockSemaphoreInfo(dpc_semaphore);
1633static HANDLER_RETURN_TYPE DistributePixelCacheConnectionHandler(
1640 authenticated = MagickFalse,
1641 status = MagickFalse;
1651 *client_socket_ptr = (SOCKET_TYPE *) socket_arg;
1665 nonce[DPCSessionKeyLength];
1667 client_socket=(*client_socket_ptr);
1668 client_socket_ptr=(SOCKET_TYPE *) RelinquishMagickMemory(client_socket_ptr);
1672 random_info=AcquireRandomInfo();
1673 entropy=GetRandomKey(random_info,
sizeof(nonce));
1674 (void) memcpy(nonce,GetStringInfoDatum(entropy),
sizeof(nonce));
1675 entropy=DestroyStringInfo(entropy);
1676 random_info=DestroyRandomInfo(random_info);
1680 session_key=GenerateSessionKey(dpc_shared_secret,nonce,
sizeof(nonce));
1684 count=dpc_send(client_socket,
sizeof(nonce),nonce);
1685 if (count != (MagickOffsetType)
sizeof(nonce))
1687 CLOSE_SOCKET(client_socket);
1688 RelinquishDPCClient(MagickTrue);
1689 return(HANDLER_RETURN_VALUE);
1694 count=dpc_receive_deadline(client_socket,
sizeof(key),(
unsigned char *) &key,
1695 (
double) time((time_t *) NULL)+5.0);
1696 if ((count != (MagickOffsetType)
sizeof(key)) || (key != session_key))
1698 CLOSE_SOCKET(client_socket);
1699 RelinquishDPCClient(MagickTrue);
1700 return(HANDLER_RETURN_VALUE);
1702 AuthenticateDPCClient();
1703 authenticated=MagickTrue;
1704 exception=AcquireExceptionInfo();
1705 registry=NewSplayTree((
int (*)(
const void *,
const void *)) NULL,
1706 (
void *(*)(
void *)) NULL,RelinquishImageRegistry);
1710 for (status=MagickFalse; ; )
1715 count=dpc_receive_deadline(client_socket,1,(
unsigned char *) &command,
1716 (
double) time((time_t *) NULL)+5.0);
1719 count=dpc_receive_deadline(client_socket,
sizeof(key),(
unsigned char *) &key,
1720 (
double) time((time_t *) NULL)+5.0);
1721 if ((count != (MagickOffsetType)
sizeof(key)) || (key != session_key))
1727 status=OpenDistributeCache(registry,client_socket,session_key,
1729 dpc_send(client_socket,
sizeof(status),&status);
1734 status=ReadDistributeCachePixels(registry,client_socket,session_key,
1740 status=ReadDistributeCacheMetacontent(registry,client_socket,
1741 session_key,exception);
1746 status=WriteDistributeCachePixels(registry,client_socket,session_key,
1752 status=WriteDistributeCacheMetacontent(registry,client_socket,
1753 session_key,exception);
1758 status=DestroyDistributeCache(registry,session_key);
1764 if ((status == MagickFalse) || (command ==
'd'))
1767 count=dpc_send(client_socket,
sizeof(status),&status);
1768 CLOSE_SOCKET(client_socket);
1769 exception=DestroyExceptionInfo(exception);
1770 registry=DestroySplayTree(registry);
1771 RelinquishDPCClient(authenticated == MagickFalse ? MagickTrue :
1773 return(HANDLER_RETURN_VALUE);
1776static size_t GetDPCPolicyLimit(
const char *name,
const size_t default_limit)
1779 policy_name[MagickPathExtent],
1785 limit=default_limit;
1786 (void) FormatLocaleString(policy_name,MagickPathExtent,
"cache:%s",name);
1787 policy_value=GetPolicyValue(policy_name);
1788 if (policy_value != (
char *) NULL)
1797 policy_limit=strtoul(policy_value,&q,10);
1798 if ((errno == 0) && (q != policy_value) && (policy_limit != 0))
1799 limit=(size_t) policy_limit;
1800 policy_value=DestroyString(policy_value);
1805static size_t GetMaxDPCClients(
void)
1807 return(GetDPCPolicyLimit(
"max-dpc-clients",DPCMaxClientWorkers));
1810static size_t GetMaxDPCUnauthenticatedClients(
void)
1814 unauthenticated_workers;
1816 client_workers=GetMaxDPCClients();
1817 unauthenticated_workers=GetDPCPolicyLimit(
"max-dpc-unauthenticated-clients",
1818 DPCMaxUnauthenticatedClientWorkers);
1819 return(MagickMin(unauthenticated_workers,client_workers));
1822static MagickBooleanType AcquireDPCClientWorker(
void)
1829 unauthenticated_worker_limit;
1832 max_dpc_clients=GetMaxDPCClients();
1833 unauthenticated_worker_limit=GetMaxDPCUnauthenticatedClients();
1835 if ((dpc_clients < max_dpc_clients) &&
1836 (dpc_unauthenticated_clients < unauthenticated_worker_limit))
1839 dpc_unauthenticated_clients++;
1842 UnlockSemaphoreInfo(dpc_semaphore);
1846MagickExport
void DistributePixelCacheServer(
const int port,
1850 service[MagickPathExtent];
1855#if defined(MAGICKCORE_THREAD_SUPPORT)
1861#elif defined(_MSC_VER)
1885 assert(exception->signature == MagickCoreSignature);
1886 magick_unreferenced(exception);
1887 dpc_shared_secret=GetPolicyValue(
"cache:shared-secret");
1888 if (dpc_shared_secret == (
char *) NULL)
1889 ThrowFatalException(CacheFatalError,
"no shared secret");
1890#if defined(MAGICKCORE_HAVE_WINSOCK2)
1891 InitializeWinsock2(MagickFalse);
1893 (void) memset(&hint,0,
sizeof(hint));
1894 hint.ai_family=AF_INET;
1895 hint.ai_socktype=SOCK_STREAM;
1896 hint.ai_flags=AI_PASSIVE;
1897 FormatLocaleString(service,MagickPathExtent,
"%d",port);
1898 status=getaddrinfo(NULL,service,&hint,&result);
1900 ThrowFatalException(CacheFatalError,
"UnableToListen");
1901 server_socket=(SOCKET_TYPE) 0;
1902 for (p=result; p != NULL; p=p->ai_next)
1907 server_socket=(SOCKET_TYPE) socket(p->ai_family,p->ai_socktype,
1909 if (server_socket == -1)
1911 status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,(
char *) &one,
1912 (socklen_t)
sizeof(one));
1915 CLOSE_SOCKET(server_socket);
1918 SetSocketReceiveTimeout(server_socket,5.0);
1919 status=bind(server_socket,p->ai_addr,(socklen_t) p->ai_addrlen);
1922 CLOSE_SOCKET(server_socket);
1927 if (p == (
struct addrinfo *) NULL)
1928 ThrowFatalException(CacheFatalError,
"UnableToBind");
1929 freeaddrinfo(result);
1930 status=listen(server_socket,DPCPendingConnections);
1932 ThrowFatalException(CacheFatalError,
"UnableToListen");
1933#if defined(MAGICKCORE_THREAD_SUPPORT)
1934 pthread_attr_init(&attributes);
1935 pthread_attr_setdetachstate(&attributes,PTHREAD_CREATE_DETACHED);
1943 length = (socklen_t)
sizeof(address);
1945 client_socket_ptr=(SOCKET_TYPE *) AcquireMagickMemory(
sizeof(SOCKET_TYPE));
1946 if (client_socket_ptr == NULL)
1948 *client_socket_ptr=(SOCKET_TYPE) accept(server_socket,(
struct sockaddr *)
1950 if (*client_socket_ptr == -1)
1952 client_socket_ptr=(SOCKET_TYPE *) RelinquishMagickMemory(
1956 if (AcquireDPCClientWorker() == MagickFalse)
1958 CLOSE_SOCKET(*client_socket_ptr);
1959 client_socket_ptr=(SOCKET_TYPE *) RelinquishMagickMemory(
1963 SetSocketReceiveTimeout(*client_socket_ptr,5.0);
1964 SetSocketNoDelay(*client_socket_ptr);
1967 CLOSE_SOCKET(*client_socket_ptr);
1968 RelinquishDPCClient(MagickTrue);
1969 client_socket_ptr=(SOCKET_TYPE *) RelinquishMagickMemory(
1973#if defined(MAGICKCORE_THREAD_SUPPORT)
1974 status=pthread_create(&thread_id,&attributes,
1975 DistributePixelCacheConnectionHandler,(
void *) client_socket_ptr);
1978 CLOSE_SOCKET(*client_socket_ptr);
1979 RelinquishDPCClient(MagickTrue);
1980 RelinquishMagickMemory(client_socket_ptr);
1983#elif defined(_MSC_VER)
1984 if (CreateThread(0,0,DistributePixelCacheConnectionHandler,(
void*) client_socket_ptr,0,&threadID) == (HANDLE) NULL)
1986 CLOSE_SOCKET(*client_socket_ptr);
1987 RelinquishDPCClient(MagickTrue);
1988 RelinquishMagickMemory(client_socket_ptr);
2012MagickPrivate
void DistributeCacheTerminus(
void)
2014#ifdef MAGICKCORE_HAVE_WINSOCK2
2016 ActivateSemaphoreInfo(&winsock_semaphore);
2017 LockSemaphoreInfo(winsock_semaphore);
2018 if (wsaData != (WSADATA *) NULL)
2021 wsaData=(WSADATA *) RelinquishMagickMemory((
void *) wsaData);
2023 UnlockSemaphoreInfo(winsock_semaphore);
2024 RelinquishSemaphoreInfo(&winsock_semaphore);
2026#if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE)
2027 if (dpc_shared_secret != (
char *) NULL)
2028 dpc_shared_secret=DestroyString(dpc_shared_secret);
2030 RelinquishSemaphoreInfo(&dpc_semaphore);
2060 assert(server_info->signature == MagickCoreSignature);
2061 return(server_info->file);
2088MagickPrivate
const char *GetDistributeCacheHostname(
2092 assert(server_info->signature == MagickCoreSignature);
2093 return(server_info->hostname);
2122 assert(server_info->signature == MagickCoreSignature);
2123 return(server_info->port);
2151MagickPrivate MagickBooleanType OpenDistributePixelCache(
2161 message[MagickPathExtent],
2168 assert(server_info->signature == MagickCoreSignature);
2169 assert(image != (
Image *) NULL);
2170 assert(image->signature == MagickCoreSignature);
2176 (void) memcpy(p,&server_info->session_key,
sizeof(server_info->session_key));
2177 p+=(ptrdiff_t)
sizeof(server_info->session_key);
2178 (void) memcpy(p,&image->storage_class,
sizeof(image->storage_class));
2179 p+=(ptrdiff_t)
sizeof(image->storage_class);
2180 (void) memcpy(p,&image->colorspace,
sizeof(image->colorspace));
2181 p+=(ptrdiff_t)
sizeof(image->colorspace);
2182 (void) memcpy(p,&image->alpha_trait,
sizeof(image->alpha_trait));
2183 p+=(ptrdiff_t)
sizeof(image->alpha_trait);
2184 (void) memcpy(p,&image->channels,
sizeof(image->channels));
2185 p+=(ptrdiff_t)
sizeof(image->channels);
2186 (void) memcpy(p,&image->columns,
sizeof(image->columns));
2187 p+=(ptrdiff_t)
sizeof(image->columns);
2188 (void) memcpy(p,&image->rows,
sizeof(image->rows));
2189 p+=(ptrdiff_t)
sizeof(image->rows);
2190 (void) memcpy(p,&image->number_channels,
sizeof(image->number_channels));
2191 p+=(ptrdiff_t)
sizeof(image->number_channels);
2192 (void) memcpy(p,image->channel_map,MaxPixelChannels*
2193 sizeof(*image->channel_map));
2194 p+=(ptrdiff_t) MaxPixelChannels*
sizeof(*image->channel_map);
2195 (void) memcpy(p,&image->metacontent_extent,
sizeof(image->metacontent_extent));
2196 p+=(ptrdiff_t)
sizeof(image->metacontent_extent);
2197 count=dpc_send(server_info->file,(MagickSizeType) (p-message),message);
2198 if (count != (MagickOffsetType) (p-message))
2199 return(MagickFalse);
2201 count=dpc_receive(server_info->file,
sizeof(status),(
unsigned char *) &status);
2202 if (count != (MagickOffsetType)
sizeof(status))
2203 return(MagickFalse);
2240MagickPrivate MagickOffsetType ReadDistributePixelCacheMetacontent(
2242 const MagickSizeType length,
unsigned char *metacontent)
2248 message[MagickPathExtent],
2255 assert(server_info->signature == MagickCoreSignature);
2257 assert(metacontent != (
unsigned char *) NULL);
2258 if (length > (MagickSizeType) MAGICK_SSIZE_MAX)
2262 (void) memcpy(p,&server_info->session_key,
sizeof(server_info->session_key));
2263 p+=(ptrdiff_t)
sizeof(server_info->session_key);
2264 (void) memcpy(p,®ion->width,
sizeof(region->width));
2265 p+=(ptrdiff_t)
sizeof(region->width);
2266 (void) memcpy(p,®ion->height,
sizeof(region->height));
2267 p+=(ptrdiff_t)
sizeof(region->height);
2268 (void) memcpy(p,®ion->x,
sizeof(region->x));
2269 p+=(ptrdiff_t)
sizeof(region->x);
2270 (void) memcpy(p,®ion->y,
sizeof(region->y));
2271 p+=(ptrdiff_t)
sizeof(region->y);
2272 (void) memcpy(p,&length,
sizeof(length));
2273 p+=(ptrdiff_t)
sizeof(length);
2274 count=dpc_send(server_info->file,(MagickSizeType) (p-message),message);
2275 if (count != (MagickOffsetType) (p-message))
2277 return(dpc_receive_mac(server_info->file,length,metacontent,
2278 server_info->session_key));
2314MagickPrivate MagickOffsetType ReadDistributePixelCachePixels(
2316 const MagickSizeType length,
unsigned char *magick_restrict pixels)
2322 message[MagickPathExtent],
2329 assert(server_info->signature == MagickCoreSignature);
2331 assert(pixels != (
unsigned char *) NULL);
2332 if (length > (MagickSizeType) MAGICK_SSIZE_MAX)
2336 (void) memcpy(p,&server_info->session_key,
sizeof(server_info->session_key));
2337 p+=(ptrdiff_t)
sizeof(server_info->session_key);
2338 (void) memcpy(p,®ion->width,
sizeof(region->width));
2339 p+=(ptrdiff_t)
sizeof(region->width);
2340 (void) memcpy(p,®ion->height,
sizeof(region->height));
2341 p+=(ptrdiff_t)
sizeof(region->height);
2342 (void) memcpy(p,®ion->x,
sizeof(region->x));
2343 p+=(ptrdiff_t)
sizeof(region->x);
2344 (void) memcpy(p,®ion->y,
sizeof(region->y));
2345 p+=(ptrdiff_t)
sizeof(region->y);
2346 (void) memcpy(p,&length,
sizeof(length));
2347 p+=(ptrdiff_t)
sizeof(length);
2348 count=dpc_send(server_info->file,(MagickSizeType) (p-message),message);
2349 if (count != (MagickOffsetType) (p-message))
2351 return(dpc_receive_mac(server_info->file,length,pixels,
2352 server_info->session_key));
2379MagickPrivate MagickBooleanType RelinquishDistributePixelCache(
2389 message[MagickPathExtent],
2396 assert(server_info->signature == MagickCoreSignature);
2399 (void) memcpy(p,&server_info->session_key,
sizeof(server_info->session_key));
2400 p+=(ptrdiff_t)
sizeof(server_info->session_key);
2401 count=dpc_send(server_info->file,(MagickSizeType) (p-message),message);
2402 if (count != (MagickOffsetType) (p-message))
2403 return(MagickFalse);
2405 count=dpc_receive(server_info->file,
sizeof(status),(
unsigned char *) &status);
2406 if (count != (MagickOffsetType)
sizeof(status))
2407 return(MagickFalse);
2444MagickPrivate MagickOffsetType WriteDistributePixelCacheMetacontent(
2446 const MagickSizeType length,
const unsigned char *metacontent)
2452 message[MagickPathExtent],
2459 assert(server_info->signature == MagickCoreSignature);
2461 assert(metacontent != (
unsigned char *) NULL);
2462 if (length > (MagickSizeType) MAGICK_SSIZE_MAX)
2466 (void) memcpy(p,&server_info->session_key,
sizeof(server_info->session_key));
2467 p+=(ptrdiff_t)
sizeof(server_info->session_key);
2468 (void) memcpy(p,®ion->width,
sizeof(region->width));
2469 p+=(ptrdiff_t)
sizeof(region->width);
2470 (void) memcpy(p,®ion->height,
sizeof(region->height));
2471 p+=(ptrdiff_t)
sizeof(region->height);
2472 (void) memcpy(p,®ion->x,
sizeof(region->x));
2473 p+=(ptrdiff_t)
sizeof(region->x);
2474 (void) memcpy(p,®ion->y,
sizeof(region->y));
2475 p+=(ptrdiff_t)
sizeof(region->y);
2476 (void) memcpy(p,&length,
sizeof(length));
2477 p+=(ptrdiff_t)
sizeof(length);
2478 count=dpc_send(server_info->file,(MagickSizeType) (p-message),message);
2479 if (count != (MagickOffsetType) (p-message))
2481 return(dpc_send_mac(server_info->file,length,metacontent,
2482 server_info->session_key));
2519MagickPrivate MagickOffsetType WriteDistributePixelCachePixels(
2521 const MagickSizeType length,
const unsigned char *magick_restrict pixels)
2527 message[MagickPathExtent],
2534 assert(server_info->signature == MagickCoreSignature);
2536 assert(pixels != (
const unsigned char *) NULL);
2537 if (length > (MagickSizeType) MAGICK_SSIZE_MAX)
2541 (void) memcpy(p,&server_info->session_key,
sizeof(server_info->session_key));
2542 p+=(ptrdiff_t)
sizeof(server_info->session_key);
2543 (void) memcpy(p,®ion->width,
sizeof(region->width));
2544 p+=(ptrdiff_t)
sizeof(region->width);
2545 (void) memcpy(p,®ion->height,
sizeof(region->height));
2546 p+=(ptrdiff_t)
sizeof(region->height);
2547 (void) memcpy(p,®ion->x,
sizeof(region->x));
2548 p+=(ptrdiff_t)
sizeof(region->x);
2549 (void) memcpy(p,®ion->y,
sizeof(region->y));
2550 p+=(ptrdiff_t)
sizeof(region->y);
2551 (void) memcpy(p,&length,
sizeof(length));
2552 p+=(ptrdiff_t)
sizeof(length);
2553 count=dpc_send(server_info->file,(MagickSizeType) (p-message),message);
2554 if (count != (MagickOffsetType) (p-message))
2556 return(dpc_send_mac(server_info->file,length,pixels,
2557 server_info->session_key));