54 #include "magick/studio.h" 55 #include "magick/cache.h" 56 #include "magick/cache-private.h" 57 #include "magick/distribute-cache.h" 58 #include "magick/distribute-cache-private.h" 59 #include "magick/exception.h" 60 #include "magick/exception-private.h" 61 #include "magick/geometry.h" 62 #include "magick/image.h" 63 #include "magick/image-private.h" 64 #include "magick/list.h" 65 #include "magick/locale_.h" 66 #include "magick/memory_.h" 67 #include "magick/nt-base-private.h" 68 #include "magick/policy.h" 69 #include "magick/random_.h" 70 #include "magick/registry.h" 71 #include "magick/splay-tree.h" 72 #include "magick/string_.h" 73 #include "magick/string-private.h" 74 #include "magick/version.h" 75 #include "magick/version-private.h" 76 #undef MAGICKCORE_HAVE_DISTRIBUTE_CACHE 77 #if defined(MAGICKCORE_HAVE_SOCKET) && defined(MAGICKCORE_THREAD_SUPPORT) 78 #include <netinet/in.h> 80 #include <sys/socket.h> 81 #include <arpa/inet.h> 82 #define CLOSE_SOCKET(socket) (void) close(socket) 83 #define HANDLER_RETURN_TYPE void * 84 #define HANDLER_RETURN_VALUE (void *) NULL 85 #define SOCKET_TYPE int 86 #define LENGTH_TYPE size_t 87 #define MAGICKCORE_HAVE_DISTRIBUTE_CACHE 88 #elif defined(MAGICKCORE_WINDOWS_SUPPORT) && !defined(__MINGW32__) && !defined(__MINGW64__) 89 #define CLOSE_SOCKET(socket) (void) closesocket(socket) 90 #define HANDLER_RETURN_TYPE DWORD WINAPI 91 #define HANDLER_RETURN_VALUE 0 92 #define SOCKET_TYPE SOCKET 93 #define LENGTH_TYPE int 94 #define MAGICKCORE_HAVE_DISTRIBUTE_CACHE 97 #define CLOSE_SOCKET(socket) (void) close(socket) 99 #define CLOSE_SOCKET(socket) 101 #define HANDLER_RETURN_TYPE void * 102 #define HANDLER_RETURN_VALUE (void *) NULL 103 #define SOCKET_TYPE int 104 #define LENGTH_TYPE size_t 107 #define send(file,buffer,length,flags) 0 108 #define recv(file,buffer,length,flags) 0 114 #define DPCHostname "127.0.0.1" 115 #define DPCPendingConnections 10 117 #define DPCSessionKeyLength 8 119 # define MSG_NOSIGNAL 0 122 #ifdef MAGICKCORE_HAVE_WINSOCK2 127 *wsaData = (WSADATA*) NULL;
153 #if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) 154 static inline MagickOffsetType dpc_read(
int magick_unused(file),
155 const MagickSizeType magick_unused(length),
156 unsigned char *magick_restrict magick_unused(message))
158 magick_unreferenced(file);
159 magick_unreferenced(length);
160 magick_unreferenced(message);
164 static inline MagickOffsetType dpc_read(
int file,
const MagickSizeType length,
165 unsigned char *magick_restrict message)
174 for (i=0; i < (MagickOffsetType) length; i+=count)
176 count=recv(file,(
char *) message+i,(LENGTH_TYPE) MagickMin(length-i,
177 (MagickSizeType) MagickMaxBufferExtent),0);
189 #if defined(MAGICKCORE_HAVE_WINSOCK2) 190 static void InitializeWinsock2(MagickBooleanType use_lock)
192 if (use_lock != MagickFalse)
195 ActivateSemaphoreInfo(&winsock2_semaphore);
196 LockSemaphoreInfo(winsock2_semaphore);
198 if (wsaData == (WSADATA *) NULL)
200 wsaData=(WSADATA *) AcquireMagickMemory(
sizeof(WSADATA));
201 if (WSAStartup(MAKEWORD(2,2),wsaData) != 0)
202 ThrowFatalException(CacheFatalError,
"WSAStartup failed");
204 if (use_lock != MagickFalse)
205 UnlockSemaphoreInfo(winsock2_semaphore);
209 static inline uint64_t ROTL(uint64_t x,
int b)
211 return((x << b) | (x >> (64-b)));
214 static inline uint64_t U8TO64_LE(
const uint8_t *p)
216 return(((uint64_t) p[0] << 0) | ((uint64_t) p[1] << 8) |
217 ((uint64_t) p[2] << 16) | ((uint64_t) p[3] << 24) |
218 ((uint64_t) p[4] << 32) | ((uint64_t) p[5] << 40) |
219 ((uint64_t) p[6] << 48) | ((uint64_t) p[7] << 56));
222 static inline uint64_t SIPHash24(
const uint8_t key[16],
const uint8_t *message,
226 *end = message+length-(length % 8);
232 b = ((uint64_t) length) << 56,
234 k1 = U8TO64_LE(key+8),
236 v0 = 0x736f6d6570736575ULL^k0,
237 v1 = 0x646f72616e646f6dULL^k1,
238 v2 = 0x6c7967656e657261ULL^k0,
239 v3 = 0x7465646279746573ULL^k1;
241 for ( ; message != end; message+=8)
243 m=U8TO64_LE(message);
245 for (i=0; i < 2; i++)
247 v0+=v1; v1=ROTL(v1,13); v1^=v0; v0=ROTL(v0,32);
248 v2+=v3; v3=ROTL(v3,16); v3^=v2;
249 v0+=v3; v3=ROTL(v3,21); v3^=v0;
250 v2+=v1; v1=ROTL(v1,17); v1^=v2; v2=ROTL(v2,32);
254 switch (length & 0x07)
256 case 7: b|=((uint64_t) message[6]) << 48; magick_fallthrough;
257 case 6: b|=((uint64_t) message[5]) << 40; magick_fallthrough;
258 case 5: b|=((uint64_t) message[4]) << 32; magick_fallthrough;
259 case 4: b|=((uint64_t) message[3]) << 24; magick_fallthrough;
260 case 3: b|=((uint64_t) message[2]) << 16; magick_fallthrough;
261 case 2: b|=((uint64_t) message[1]) << 8; magick_fallthrough;
262 case 1: b|=((uint64_t) message[0]); magick_fallthrough;
266 for (i=0; i < 2; i++)
268 v0+=v1; v1=ROTL(v1,13); v1^=v0; v0=ROTL(v0,32);
269 v2+=v3; v3=ROTL(v3,16); v3^=v2;
270 v0+=v3; v3=ROTL(v3,21); v3^=v0;
271 v2+=v1; v1=ROTL(v1,17); v1^=v2; v2=ROTL(v2,32);
275 for (i=0; i < 4; i++)
277 v0+=v1; v1=ROTL(v1,13); v1^=v0; v0=ROTL(v0,32);
278 v2+=v3; v3=ROTL(v3,16); v3^=v2;
279 v0+=v3; v3=ROTL(v3,21); v3^=v0;
280 v2+=v1; v1=ROTL(v1,17); v1^=v2; v2=ROTL(v2,32);
285 static inline void DeriveSipKeyFromSecret(
const char *shared_secret,
293 k0 = 0x0706050403020100ULL,
294 k1 = 0x0f0e0d0c0b0a0908ULL;
296 length=strlen(shared_secret);
297 for (i=0; i < length; i++)
300 b = shared_secret[i];
303 k0*=0x100000001b3ULL;
304 k1^=(uint64_t) b << ((i & 7)*8);
305 k1=(k1 << 5) | (k1 >> (64-5));
307 (void) memcpy(key,&k0,8);
308 (void) memcpy(key+8,&k1,8);
311 static inline uint64_t GenerateSessionKey(
const char *shared_secret,
312 const unsigned char *nonce,
size_t length)
317 DeriveSipKeyFromSecret(shared_secret,key);
318 return(SIPHash24(key,nonce,length));
321 static int ConnectPixelCacheServer(
const char *hostname,
const int port,
324 #if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) 327 service[MagickPathExtent],
344 nonce[DPCSessionKeyLength];
350 #if defined(MAGICKCORE_HAVE_WINSOCK2) 351 InitializeWinsock2(MagickTrue);
353 (void) memset(&hints,0,
sizeof(hints));
354 hints.ai_family=AF_INET;
355 hints.ai_socktype=SOCK_STREAM;
356 hints.ai_flags=AI_PASSIVE;
357 (void) FormatLocaleString(service,MagickPathExtent,
"%d",port);
358 status=getaddrinfo(hostname,service,&hints,&result);
361 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
362 "DistributedPixelCache",
"'%s': %s",hostname,gai_strerror(status));
365 client_socket=socket(result->ai_family,result->ai_socktype,
366 result->ai_protocol);
367 if (client_socket == -1)
369 freeaddrinfo(result);
370 message=GetExceptionMessage(errno);
371 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
372 "DistributedPixelCache",
"'%s': %s",hostname,message);
373 message=DestroyString(message);
376 status=connect(client_socket,result->ai_addr,(socklen_t) result->ai_addrlen);
377 freeaddrinfo(result);
380 CLOSE_SOCKET(client_socket);
381 message=GetExceptionMessage(errno);
382 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
383 "DistributedPixelCache",
"'%s': %s",hostname,GetExceptionMessage(errno));
384 message=DestroyString(message);
390 count=recv(client_socket,(
char *) nonce,
sizeof(nonce),0);
391 if (count != (ssize_t)
sizeof(nonce))
393 CLOSE_SOCKET(client_socket);
394 message=GetExceptionMessage(errno);
395 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
396 "DistributedPixelCache",
"'%s': %s",hostname,message);
397 message=DestroyString(message);
403 shared_secret=GetPolicyValue(
"cache:shared-secret");
404 if (shared_secret == (
char*) NULL)
406 CLOSE_SOCKET(client_socket);
407 message=GetExceptionMessage(errno);
408 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
409 "DistributedPixelCache",
"'%s': shared secret required",hostname);
410 message=DestroyString(message);
413 *session_key=GenerateSessionKey(shared_secret,nonce,
sizeof(nonce));
414 shared_secret=DestroyString(shared_secret);
418 count=send(client_socket,(
char *) session_key,
sizeof(*session_key),
420 if (count != (ssize_t)
sizeof(*session_key))
422 CLOSE_SOCKET(client_socket);
423 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
424 "DistributedPixelCache",
"'%s': authentication failed",hostname);
427 return((
int) client_socket);
429 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
430 "DelegateLibrarySupportNotBuiltIn",
"distributed pixel cache");
454 hosts=(
char *) GetImageRegistry(StringRegistryType,
"cache:hosts",exception);
455 if (hosts == (
char *) NULL)
458 return(AcquireString(DPCHostname));
460 (void) SubstituteString(&hosts,
",",
" ");
461 hostlist=StringToArgv(hosts,&argc);
462 hosts=DestroyString(hosts);
463 if (hostlist == (
char **) NULL)
466 return(AcquireString(DPCHostname));
469 size_t host_count = (size_t) argc-1;
470 size_t index = (
id++ % host_count)+1;
471 hosts=AcquireString(hostlist[index]);
473 for (i=0; i < (ssize_t) argc; i++)
474 hostlist[i]=DestroyString(hostlist[i]);
475 hostlist=(
char **) RelinquishMagickMemory(hostlist);
476 (void) SubstituteString(&hosts,
":",
" ");
477 hostlist=StringToArgv(hosts,&argc);
478 if (hostlist == (
char **) NULL)
481 return(AcquireString(DPCHostname));
483 host=AcquireString(hostlist[1]);
484 if (hostlist[2] == (
char *) NULL)
487 *port=StringToLong(hostlist[2]);
488 for (i=0; i < (ssize_t) argc; i++)
489 hostlist[i]=DestroyString(hostlist[i]);
490 hostlist=(
char **) RelinquishMagickMemory(hostlist);
510 sizeof(*server_info));
511 (void) memset(server_info,0,
sizeof(*server_info));
512 server_info->signature=MagickCoreSignature;
514 hostname=GetHostname(&server_info->port,exception);
516 server_info->file=ConnectPixelCacheServer(hostname,server_info->port,
517 &session_key,exception);
518 if (server_info->file == -1)
519 server_info=DestroyDistributeCacheInfo(server_info);
522 server_info->session_key=session_key;
523 (void) CopyMagickString(server_info->hostname,hostname,MagickPathExtent);
524 server_info->debug=GetLogEventMask() & CacheEvent ? MagickTrue :
527 hostname=DestroyString(hostname);
559 assert(server_info->signature == MagickCoreSignature);
560 if (server_info->file >= 0)
561 CLOSE_SOCKET(server_info->file);
562 server_info->signature=(~MagickCoreSignature);
593 #if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) 594 static inline MagickOffsetType dpc_send(
int magick_unused(file),
595 const MagickSizeType magick_unused(length),
596 const void *magick_restrict magick_unused(message))
598 magick_unreferenced(file);
599 magick_unreferenced(length);
600 magick_unreferenced(message);
604 static inline MagickOffsetType dpc_send(
int file,
const MagickSizeType length,
605 const void *magick_restrict message)
617 for (i=0; i < (MagickOffsetType) length; i+=count)
619 count=(MagickOffsetType) send(file,(
char *) message+i,(LENGTH_TYPE)
620 MagickMin(length-i,(MagickSizeType) MagickMaxBufferExtent),MSG_NOSIGNAL);
632 #if defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) 633 static MagickBooleanType DestroyDistributeCache(
SplayTreeInfo *registry,
634 const uint64_t session_key)
637 key = (MagickAddressType) session_key;
642 return(DeleteNodeFromSplayTree(registry,(
const void *) key));
645 static MagickBooleanType OpenDistributeCache(
SplayTreeInfo *registry,
int file,
652 key = (MagickAddressType) session_key;
664 message[MagickPathExtent],
671 if (image == (
Image *) NULL)
673 length=
sizeof(image->storage_class)+
sizeof(image->colorspace)+
674 sizeof(image->channels)+
sizeof(image->columns)+
sizeof(image->rows);
675 count=dpc_read(file,length,message);
676 if (count != (MagickOffsetType) length)
678 image=DestroyImage(image);
685 (void) memcpy(&image->storage_class,p,
sizeof(image->storage_class));
686 p+=(ptrdiff_t)
sizeof(image->storage_class);
687 (void) memcpy(&image->colorspace,p,
sizeof(image->colorspace));
688 p+=(ptrdiff_t)
sizeof(image->colorspace);
689 (void) memcpy(&image->channels,p,
sizeof(image->channels));
690 p+=(ptrdiff_t)
sizeof(image->channels);
691 (void) memcpy(&image->columns,p,
sizeof(image->columns));
692 p+=(ptrdiff_t)
sizeof(image->columns);
693 (void) memcpy(&image->rows,p,
sizeof(image->rows));
694 p+=(ptrdiff_t)
sizeof(image->rows);
695 if (SyncImagePixelCache(image,exception) == MagickFalse)
697 image=DestroyImage(image);
700 status=AddValueToSplayTree(registry,(
const void *) key,image);
701 if (status == MagickFalse)
703 image=DestroyImage(image);
709 static inline MagickBooleanType ValidateDistributedPixelCache(
711 const MagickSizeType length)
717 if (HeapOverflowSanityCheckGetSize(region->width,region->height,&pixels) != MagickFalse)
719 if (HeapOverflowSanityCheckGetSize(pixels,per_pixel,&extent) != MagickFalse)
721 if (length > (MagickSizeType) extent)
726 static MagickBooleanType ReadDistributeCacheIndexes(
SplayTreeInfo *registry,
727 int file,
const uint64_t session_key,
ExceptionInfo *exception)
739 key = (MagickAddressType) session_key;
754 message[MagickPathExtent],
760 image=(
Image *) GetValueFromSplayTree(registry,(
const void *) key);
761 if (image == (
Image *) NULL)
763 length=
sizeof(region.width)+
sizeof(region.height)+
sizeof(region.x)+
764 sizeof(region.y)+
sizeof(length);
765 count=dpc_read(file,length,message);
766 if (count != (MagickOffsetType) length)
769 (void) memcpy(®ion.width,q,
sizeof(region.width));
770 q+=(ptrdiff_t)
sizeof(region.width);
771 (void) memcpy(®ion.height,q,
sizeof(region.height));
772 q+=(ptrdiff_t)
sizeof(region.height);
773 (void) memcpy(®ion.x,q,
sizeof(region.x));
774 q+=(ptrdiff_t)
sizeof(region.x);
775 (void) memcpy(®ion.y,q,
sizeof(region.y));
776 q+=(ptrdiff_t)
sizeof(region.y);
777 (void) memcpy(&length,q,
sizeof(length));
778 per_pixel=
sizeof(IndexPacket);
779 if (ValidateDistributedPixelCache(®ion,per_pixel,length) == MagickFalse)
781 q+=(ptrdiff_t)
sizeof(length);
782 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
786 indexes=GetVirtualIndexQueue(image);
787 count=dpc_send(file,length,indexes);
788 if (count != (MagickOffsetType) length)
793 static MagickBooleanType ReadDistributeCachePixels(
SplayTreeInfo *registry,
794 int file,
const uint64_t session_key,
ExceptionInfo *exception)
803 key = (MagickAddressType) session_key;
818 message[MagickPathExtent],
824 image=(
Image *) GetValueFromSplayTree(registry,(
const void *) key);
825 if (image == (
Image *) NULL)
827 length=
sizeof(region.width)+
sizeof(region.height)+
sizeof(region.x)+
828 sizeof(region.y)+
sizeof(length);
829 count=dpc_read(file,length,message);
830 if (count != (MagickOffsetType) length)
833 (void) memcpy(®ion.width,q,
sizeof(region.width));
834 q+=(ptrdiff_t)
sizeof(region.width);
835 (void) memcpy(®ion.height,q,
sizeof(region.height));
836 q+=(ptrdiff_t)
sizeof(region.height);
837 (void) memcpy(®ion.x,q,
sizeof(region.x));
838 q+=(ptrdiff_t)
sizeof(region.x);
839 (void) memcpy(®ion.y,q,
sizeof(region.y));
840 q+=(ptrdiff_t)
sizeof(region.y);
841 (void) memcpy(&length,q,
sizeof(length));
842 q+=(ptrdiff_t)
sizeof(length);
844 if (ValidateDistributedPixelCache(®ion,per_pixel,length) == MagickFalse)
846 p=GetVirtualPixels(image,region.x,region.y,region.width,region.height,
850 count=dpc_send(file,length,p);
851 if (count != (MagickOffsetType) length)
856 static void *RelinquishImageRegistry(
void *image)
858 return((
void *) DestroyImageList((
Image *) image));
861 static MagickBooleanType WriteDistributeCacheIndexes(
SplayTreeInfo *registry,
862 int file,
const uint64_t session_key,
ExceptionInfo *exception)
871 key = (MagickAddressType) session_key;
889 message[MagickPathExtent],
895 image=(
Image *) GetValueFromSplayTree(registry,(
const void *) key);
896 if (image == (
Image *) NULL)
898 length=
sizeof(region.width)+
sizeof(region.height)+
sizeof(region.x)+
899 sizeof(region.y)+
sizeof(length);
900 count=dpc_read(file,length,message);
901 if (count != (MagickOffsetType) length)
904 (void) memcpy(®ion.width,p,
sizeof(region.width));
905 p+=(ptrdiff_t)
sizeof(region.width);
906 (void) memcpy(®ion.height,p,
sizeof(region.height));
907 p+=(ptrdiff_t)
sizeof(region.height);
908 (void) memcpy(®ion.x,p,
sizeof(region.x));
909 p+=(ptrdiff_t)
sizeof(region.x);
910 (void) memcpy(®ion.y,p,
sizeof(region.y));
911 p+=(ptrdiff_t)
sizeof(region.y);
912 (void) memcpy(&length,p,
sizeof(length));
913 per_pixel=
sizeof(IndexPacket);
914 if (ValidateDistributedPixelCache(®ion,per_pixel,length) == MagickFalse)
916 p+=(ptrdiff_t)
sizeof(length);
917 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
921 indexes=GetAuthenticIndexQueue(image);
922 count=dpc_read(file,length,(
unsigned char *) indexes);
923 if (count != (MagickOffsetType) length)
925 return(SyncAuthenticPixels(image,exception));
928 static MagickBooleanType WriteDistributeCachePixels(
SplayTreeInfo *registry,
929 int file,
const uint64_t session_key,
ExceptionInfo *exception)
935 key = (MagickAddressType) session_key;
953 message[MagickPathExtent],
959 image=(
Image *) GetValueFromSplayTree(registry,(
const void *) key);
960 if (image == (
Image *) NULL)
962 length=
sizeof(region.width)+
sizeof(region.height)+
sizeof(region.x)+
963 sizeof(region.y)+
sizeof(length);
964 count=dpc_read(file,length,message);
965 if (count != (MagickOffsetType) length)
968 (void) memcpy(®ion.width,p,
sizeof(region.width));
969 p+=(ptrdiff_t)
sizeof(region.width);
970 (void) memcpy(®ion.height,p,
sizeof(region.height));
971 p+=(ptrdiff_t)
sizeof(region.height);
972 (void) memcpy(®ion.x,p,
sizeof(region.x));
973 p+=(ptrdiff_t)
sizeof(region.x);
974 (void) memcpy(®ion.y,p,
sizeof(region.y));
975 p+=(ptrdiff_t)
sizeof(region.y);
976 (void) memcpy(&length,p,
sizeof(length));
977 p+=(ptrdiff_t)
sizeof(length);
979 if (ValidateDistributedPixelCache(®ion,per_pixel,length) == MagickFalse)
981 q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
985 count=dpc_read(file,length,(
unsigned char *) q);
986 if (count != (MagickOffsetType) length)
988 return(SyncAuthenticPixels(image,exception));
991 static HANDLER_RETURN_TYPE DistributePixelCacheClient(
void *socket_arg)
1000 status = MagickFalse;
1010 *client_socket_ptr = (SOCKET_TYPE *) socket_arg;
1024 nonce[DPCSessionKeyLength];
1029 client_socket=(*client_socket_ptr);
1030 client_socket_ptr=(SOCKET_TYPE *) RelinquishMagickMemory(client_socket_ptr);
1031 shared_secret=GetPolicyValue(
"cache:shared-secret");
1032 if (shared_secret == NULL)
1033 ThrowFatalException(CacheFatalError,
"shared secret required");
1037 random_info=AcquireRandomInfo();
1038 entropy=GetRandomKey(random_info,
sizeof(nonce));
1039 (void) memcpy(nonce,GetStringInfoDatum(entropy),
sizeof(nonce));
1040 entropy=DestroyStringInfo(entropy);
1041 random_info=DestroyRandomInfo(random_info);
1045 session_key=GenerateSessionKey(shared_secret,nonce,
sizeof(nonce));
1046 shared_secret=DestroyString(shared_secret);
1050 count=dpc_send(client_socket,
sizeof(nonce),nonce);
1051 if (count != (MagickOffsetType)
sizeof(nonce))
1053 CLOSE_SOCKET(client_socket);
1054 return(HANDLER_RETURN_VALUE);
1059 count=dpc_read(client_socket,
sizeof(key),(
unsigned char *) &key);
1060 if ((count != (MagickOffsetType)
sizeof(key)) || (key != session_key))
1062 CLOSE_SOCKET(client_socket);
1063 return(HANDLER_RETURN_VALUE);
1065 exception=AcquireExceptionInfo();
1066 registry=NewSplayTree((
int (*)(
const void *,
const void *)) NULL,
1067 (
void *(*)(
void *)) NULL,RelinquishImageRegistry);
1071 for (status=MagickFalse; ; )
1076 count=dpc_read(client_socket,1,(
unsigned char *) &command);
1079 count=dpc_read(client_socket,
sizeof(key),(
unsigned char *) &key);
1080 if ((count != (MagickOffsetType)
sizeof(key)) || (key != session_key))
1086 status=OpenDistributeCache(registry,client_socket,session_key,
1088 dpc_send(client_socket,
sizeof(status),&status);
1093 status=ReadDistributeCachePixels(registry,client_socket,session_key,
1099 status=ReadDistributeCacheIndexes(registry,client_socket,session_key,
1105 status=WriteDistributeCachePixels(registry,client_socket,session_key,
1111 status=WriteDistributeCacheIndexes(registry,client_socket,session_key,
1117 status=DestroyDistributeCache(registry,session_key);
1123 if ((status == MagickFalse) || (command ==
'd'))
1126 count=dpc_send(client_socket,
sizeof(status),&status);
1127 CLOSE_SOCKET(client_socket);
1128 exception=DestroyExceptionInfo(exception);
1129 registry=DestroySplayTree(registry);
1130 return(HANDLER_RETURN_VALUE);
1134 #if !defined(MAGICKCORE_HAVE_DISTRIBUTE_CACHE) 1135 MagickExport
void DistributePixelCacheServer(
const int magick_unused(port),
1138 magick_unreferenced(port);
1139 magick_unreferenced(exception);
1140 ThrowFatalException(MissingDelegateError,
"DelegateLibrarySupportNotBuiltIn");
1143 MagickExport
void DistributePixelCacheServer(
const int port,
1147 service[MagickPathExtent];
1152 #if defined(MAGICKCORE_THREAD_SUPPORT) 1158 #elif defined(_MSC_VER) 1182 assert(exception->signature == MagickCoreSignature);
1183 magick_unreferenced(exception);
1184 #if defined(MAGICKCORE_HAVE_WINSOCK2) 1185 InitializeWinsock2(MagickFalse);
1187 memset(&hint,0,
sizeof(hint));
1188 hint.ai_family=AF_INET;
1189 hint.ai_socktype=SOCK_STREAM;
1190 hint.ai_flags=AI_PASSIVE;
1191 FormatLocaleString(service,MagickPathExtent,
"%d",port);
1192 status=getaddrinfo(NULL,service,&hint,&result);
1194 ThrowFatalException(CacheFatalError,
"UnableToListen");
1195 server_socket=(SOCKET_TYPE) 0;
1196 for (p=result; p != NULL; p=p->ai_next)
1201 server_socket=socket(p->ai_family,p->ai_socktype,p->ai_protocol);
1202 if (server_socket == -1)
1204 status=setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,(
char *) &one,
1205 (socklen_t)
sizeof(one));
1208 CLOSE_SOCKET(server_socket);
1211 status=bind(server_socket,p->ai_addr,(socklen_t) p->ai_addrlen);
1214 CLOSE_SOCKET(server_socket);
1219 if (p == (
struct addrinfo *) NULL)
1220 ThrowFatalException(CacheFatalError,
"UnableToBind");
1221 freeaddrinfo(result);
1222 status=listen(server_socket,DPCPendingConnections);
1224 ThrowFatalException(CacheFatalError,
"UnableToListen");
1225 #if defined(MAGICKCORE_THREAD_SUPPORT) 1226 pthread_attr_init(&attributes);
1227 pthread_attr_setdetachstate(&attributes,PTHREAD_CREATE_DETACHED);
1235 length = (socklen_t)
sizeof(address);
1237 client_socket_ptr=(SOCKET_TYPE *) AcquireMagickMemory(
sizeof(SOCKET_TYPE));
1238 if (client_socket_ptr == NULL)
1240 *client_socket_ptr=accept(server_socket,(
struct sockaddr *) &address,
1242 if (*client_socket_ptr == -1)
1244 client_socket_ptr=(SOCKET_TYPE *) RelinquishMagickMemory(
1248 #if defined(MAGICKCORE_THREAD_SUPPORT) 1249 status=pthread_create(&thread_id, &attributes,DistributePixelCacheClient,
1250 (
void *) client_socket_ptr);
1253 CLOSE_SOCKET(*client_socket_ptr);
1254 RelinquishMagickMemory(client_socket_ptr);
1255 ThrowFatalException(CacheFatalError,
"UnableToCreateClientThread");
1257 #elif defined(_MSC_VER) 1258 if (CreateThread(0,0,DistributePixelCacheClient,(
void*) client_socket_ptr,0,&threadID) == (HANDLE) NULL)
1260 CLOSE_SOCKET(*client_socket_ptr);
1261 RelinquishMagickMemory(client_socket_ptr);
1262 ThrowFatalException(CacheFatalError,
"UnableToCreateClientThread");
1297 assert(server_info->signature == MagickCoreSignature);
1298 return(server_info->file);
1325 MagickPrivate
const char *GetDistributeCacheHostname(
1329 assert(server_info->signature == MagickCoreSignature);
1330 return(server_info->hostname);
1359 assert(server_info->signature == MagickCoreSignature);
1360 return(server_info->port);
1388 MagickPrivate MagickBooleanType OpenDistributePixelCache(
1398 message[MagickPathExtent],
1405 assert(server_info->signature == MagickCoreSignature);
1406 assert(image != (
Image *) NULL);
1407 assert(image->signature == MagickCoreSignature);
1413 (void) memcpy(p,&server_info->session_key,
sizeof(server_info->session_key));
1414 p+=(ptrdiff_t)
sizeof(server_info->session_key);
1415 (void) memcpy(p,&image->storage_class,
sizeof(image->storage_class));
1416 p+=(ptrdiff_t)
sizeof(image->storage_class);
1417 (void) memcpy(p,&image->colorspace,
sizeof(image->colorspace));
1418 p+=(ptrdiff_t)
sizeof(image->colorspace);
1419 (void) memcpy(p,&image->channels,
sizeof(image->channels));
1420 p+=(ptrdiff_t)
sizeof(image->channels);
1421 (void) memcpy(p,&image->columns,
sizeof(image->columns));
1422 p+=(ptrdiff_t)
sizeof(image->columns);
1423 (void) memcpy(p,&image->rows,
sizeof(image->rows));
1424 p+=(ptrdiff_t)
sizeof(image->rows);
1425 count=dpc_send(server_info->file,p-message,message);
1426 if (count != (MagickOffsetType) (p-message))
1427 return(MagickFalse);
1429 count=dpc_read(server_info->file,
sizeof(status),(
unsigned char *) &status);
1430 if (count != (MagickOffsetType)
sizeof(status))
1431 return(MagickFalse);
1468 MagickPrivate MagickOffsetType ReadDistributePixelCacheIndexes(
1470 const MagickSizeType length,
unsigned char *indexes)
1476 message[MagickPathExtent],
1483 assert(server_info->signature == MagickCoreSignature);
1485 assert(indexes != (
unsigned char *) NULL);
1486 if (length > (MagickSizeType) MAGICK_SSIZE_MAX)
1490 (void) memcpy(p,&server_info->session_key,
sizeof(server_info->session_key));
1491 p+=(ptrdiff_t)
sizeof(server_info->session_key);
1492 (void) memcpy(p,®ion->width,
sizeof(region->width));
1493 p+=(ptrdiff_t)
sizeof(region->width);
1494 (void) memcpy(p,®ion->height,
sizeof(region->height));
1495 p+=(ptrdiff_t)
sizeof(region->height);
1496 (void) memcpy(p,®ion->x,
sizeof(region->x));
1497 p+=(ptrdiff_t)
sizeof(region->x);
1498 (void) memcpy(p,®ion->y,
sizeof(region->y));
1499 p+=(ptrdiff_t)
sizeof(region->y);
1500 (void) memcpy(p,&length,
sizeof(length));
1501 p+=(ptrdiff_t)
sizeof(length);
1502 count=dpc_send(server_info->file,p-message,message);
1503 if (count != (MagickOffsetType) (p-message))
1505 return(dpc_read(server_info->file,length,indexes));
1541 MagickPrivate MagickOffsetType ReadDistributePixelCachePixels(
1543 const MagickSizeType length,
unsigned char *magick_restrict pixels)
1549 message[MagickPathExtent],
1556 assert(server_info->signature == MagickCoreSignature);
1558 assert(pixels != (
unsigned char *) NULL);
1559 if (length > (MagickSizeType) MAGICK_SSIZE_MAX)
1563 (void) memcpy(p,&server_info->session_key,
sizeof(server_info->session_key));
1564 p+=(ptrdiff_t)
sizeof(server_info->session_key);
1565 (void) memcpy(p,®ion->width,
sizeof(region->width));
1566 p+=(ptrdiff_t)
sizeof(region->width);
1567 (void) memcpy(p,®ion->height,
sizeof(region->height));
1568 p+=(ptrdiff_t)
sizeof(region->height);
1569 (void) memcpy(p,®ion->x,
sizeof(region->x));
1570 p+=(ptrdiff_t)
sizeof(region->x);
1571 (void) memcpy(p,®ion->y,
sizeof(region->y));
1572 p+=(ptrdiff_t)
sizeof(region->y);
1573 (void) memcpy(p,&length,
sizeof(length));
1574 p+=(ptrdiff_t)
sizeof(length);
1575 count=dpc_send(server_info->file,p-message,message);
1576 if (count != (MagickOffsetType) (p-message))
1578 return(dpc_read(server_info->file,length,pixels));
1605 MagickPrivate MagickBooleanType RelinquishDistributePixelCache(
1615 message[MagickPathExtent],
1622 assert(server_info->signature == MagickCoreSignature);
1625 (void) memcpy(p,&server_info->session_key,
sizeof(server_info->session_key));
1626 p+=(ptrdiff_t)
sizeof(server_info->session_key);
1627 count=dpc_send(server_info->file,p-message,message);
1628 if (count != (MagickOffsetType) (p-message))
1629 return(MagickFalse);
1631 count=dpc_read(server_info->file,
sizeof(status),(
unsigned char *) &status);
1632 if (count != (MagickOffsetType)
sizeof(status))
1633 return(MagickFalse);
1670 MagickPrivate MagickOffsetType WriteDistributePixelCacheIndexes(
1672 const MagickSizeType length,
const unsigned char *indexes)
1678 message[MagickPathExtent],
1685 assert(server_info->signature == MagickCoreSignature);
1687 assert(indexes != (
unsigned char *) NULL);
1688 if (length > (MagickSizeType) MAGICK_SSIZE_MAX)
1692 (void) memcpy(p,&server_info->session_key,
sizeof(server_info->session_key));
1693 p+=(ptrdiff_t)
sizeof(server_info->session_key);
1694 (void) memcpy(p,®ion->width,
sizeof(region->width));
1695 p+=(ptrdiff_t)
sizeof(region->width);
1696 (void) memcpy(p,®ion->height,
sizeof(region->height));
1697 p+=(ptrdiff_t)
sizeof(region->height);
1698 (void) memcpy(p,®ion->x,
sizeof(region->x));
1699 p+=(ptrdiff_t)
sizeof(region->x);
1700 (void) memcpy(p,®ion->y,
sizeof(region->y));
1701 p+=(ptrdiff_t)
sizeof(region->y);
1702 (void) memcpy(p,&length,
sizeof(length));
1703 p+=(ptrdiff_t)
sizeof(length);
1704 count=dpc_send(server_info->file,p-message,message);
1705 if (count != (MagickOffsetType) (p-message))
1707 return(dpc_send(server_info->file,length,indexes));
1744 MagickPrivate MagickOffsetType WriteDistributePixelCachePixels(
1746 const MagickSizeType length,
const unsigned char *magick_restrict pixels)
1752 message[MagickPathExtent],
1759 assert(server_info->signature == MagickCoreSignature);
1761 assert(pixels != (
const unsigned char *) NULL);
1762 if (length > (MagickSizeType) MAGICK_SSIZE_MAX)
1766 (void) memcpy(p,&server_info->session_key,
sizeof(server_info->session_key));
1767 p+=(ptrdiff_t)
sizeof(server_info->session_key);
1768 (void) memcpy(p,®ion->width,
sizeof(region->width));
1769 p+=(ptrdiff_t)
sizeof(region->width);
1770 (void) memcpy(p,®ion->height,
sizeof(region->height));
1771 p+=(ptrdiff_t)
sizeof(region->height);
1772 (void) memcpy(p,®ion->x,
sizeof(region->x));
1773 p+=(ptrdiff_t)
sizeof(region->x);
1774 (void) memcpy(p,®ion->y,
sizeof(region->y));
1775 p+=(ptrdiff_t)
sizeof(region->y);
1776 (void) memcpy(p,&length,
sizeof(length));
1777 p+=(ptrdiff_t)
sizeof(length);
1778 count=dpc_send(server_info->file,p-message,message);
1779 if (count != (MagickOffsetType) (p-message))
1781 return(dpc_send(server_info->file,length,pixels));