2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 Copyright 1999-2002, Apple, Inc. All rights reserved.
27 Responsibility: Doug Davidson
30 #include <CoreFoundation/CFSocket.h>
31 #include <sys/types.h>
34 #include <CoreFoundation/CFArray.h>
35 #include <CoreFoundation/CFData.h>
36 #include <CoreFoundation/CFDictionary.h>
37 #include <CoreFoundation/CFRunLoop.h>
38 #include <CoreFoundation/CFString.h>
39 #include <CoreFoundation/CFPropertyList.h>
40 #include "CFInternal.h"
41 #if defined(__WIN32__)
43 #define EINPROGRESS 36
45 #elif defined(__MACH__)
48 #include <sys/filio.h>
50 #include <sys/socket.h>
51 #include <netinet/in.h>
55 //#define LOG_CFSOCKET
57 #if !defined(__WIN32__)
58 #define INVALID_SOCKET (CFSocketNativeHandle)(-1)
59 #endif /* __WIN32__ */
61 #define MAX_SOCKADDR_LEN 256
62 #define MAX_DATA_SIZE 32768
64 static uint16_t __CFSocketDefaultNameRegistryPortNumber
= 2454;
66 CONST_STRING_DECL(kCFSocketCommandKey
, "Command")
67 CONST_STRING_DECL(kCFSocketNameKey
, "Name")
68 CONST_STRING_DECL(kCFSocketValueKey
, "Value")
69 CONST_STRING_DECL(kCFSocketResultKey
, "Result")
70 CONST_STRING_DECL(kCFSocketErrorKey
, "Error")
71 CONST_STRING_DECL(kCFSocketRegisterCommand
, "Register")
72 CONST_STRING_DECL(kCFSocketRetrieveCommand
, "Retrieve")
73 CONST_STRING_DECL(__kCFSocketRegistryRequestRunLoopMode
, "CFSocketRegistryRequest")
75 /* locks are to be acquired in the following order:
76 (1) __CFAllSocketsLock
77 (2) an individual CFSocket's lock
78 (3) __CFActiveSocketsLock
80 static CFSpinLock_t __CFAllSocketsLock
= 0; /* controls __CFAllSockets */
81 static CFMutableDictionaryRef __CFAllSockets
= NULL
;
82 static CFSpinLock_t __CFActiveSocketsLock
= 0; /* controls __CFRead/WriteSockets and __CFRead/WriteSocketsFds */
83 static CFMutableArrayRef __CFWriteSockets
= NULL
;
84 static CFMutableArrayRef __CFReadSockets
= NULL
;
85 static CFMutableDataRef __CFWriteSocketsFds
= NULL
;
86 static CFMutableDataRef __CFReadSocketsFds
= NULL
;
88 static CFSocketNativeHandle __CFWakeupSocketPair
[2] = {0, 0};
89 static void *__CFSocketManagerThread
= NULL
;
91 #if defined(__WIN32__)
92 static Boolean __CFSocketWinSockInitialized
= false;
94 #define CFSOCKET_USE_SOCKETPAIR
95 #define closesocket(a) close((a))
96 #define ioctlsocket(a,b,c) ioctl((a),(b),(c))
99 static CFTypeID __kCFSocketTypeID
= _kCFRuntimeNotATypeID
;
105 CFSpinLock_t _writeLock
;
106 CFSocketNativeHandle _socket
; /* immutable */
110 CFDataRef _peerAddress
;
111 SInt32 _socketSetCount
;
112 CFRunLoopSourceRef _source
;
113 CFMutableArrayRef _runLoops
;
114 CFSocketCallBack _callout
; /* immutable */
115 CFSocketContext _context
; /* immutable */
116 CFIndex _maxQueueLen
;
117 CFMutableArrayRef _dataQueue
;
118 CFMutableArrayRef _addressQueue
;
121 /* Bit 6 in the base reserved bits is used for write-signalled state (mutable) */
122 /* Bit 5 in the base reserved bits is used for read-signalled state (mutable) */
123 /* Bit 4 in the base reserved bits is used for invalid state (mutable) */
124 /* Bits 0-3 in the base reserved bits are used for callback types (immutable) */
125 /* Of this, bits 0-1 are used for the read callback type. */
127 CF_INLINE Boolean
__CFSocketIsWriteSignalled(CFSocketRef s
) {
128 return (Boolean
)__CFBitfieldGetValue(((const CFRuntimeBase
*)s
)->_info
, 6, 6);
131 CF_INLINE
void __CFSocketSetWriteSignalled(CFSocketRef s
) {
132 __CFBitfieldSetValue(((CFRuntimeBase
*)s
)->_info
, 6, 6, 1);
135 CF_INLINE
void __CFSocketUnsetWriteSignalled(CFSocketRef s
) {
136 __CFBitfieldSetValue(((CFRuntimeBase
*)s
)->_info
, 6, 6, 0);
139 CF_INLINE Boolean
__CFSocketIsReadSignalled(CFSocketRef s
) {
140 return (Boolean
)__CFBitfieldGetValue(((const CFRuntimeBase
*)s
)->_info
, 5, 5);
143 CF_INLINE
void __CFSocketSetReadSignalled(CFSocketRef s
) {
144 __CFBitfieldSetValue(((CFRuntimeBase
*)s
)->_info
, 5, 5, 1);
147 CF_INLINE
void __CFSocketUnsetReadSignalled(CFSocketRef s
) {
148 __CFBitfieldSetValue(((CFRuntimeBase
*)s
)->_info
, 5, 5, 0);
151 CF_INLINE Boolean
__CFSocketIsValid(CFSocketRef s
) {
152 return (Boolean
)__CFBitfieldGetValue(((const CFRuntimeBase
*)s
)->_info
, 4, 4);
155 CF_INLINE
void __CFSocketSetValid(CFSocketRef s
) {
156 __CFBitfieldSetValue(((CFRuntimeBase
*)s
)->_info
, 4, 4, 1);
159 CF_INLINE
void __CFSocketUnsetValid(CFSocketRef s
) {
160 __CFBitfieldSetValue(((CFRuntimeBase
*)s
)->_info
, 4, 4, 0);
163 CF_INLINE
uint8_t __CFSocketCallBackTypes(CFSocketRef s
) {
164 return (uint8_t)__CFBitfieldGetValue(((const CFRuntimeBase
*)s
)->_info
, 3, 0);
167 CF_INLINE
uint8_t __CFSocketReadCallBackType(CFSocketRef s
) {
168 return (uint8_t)__CFBitfieldGetValue(((const CFRuntimeBase
*)s
)->_info
, 1, 0);
171 CF_INLINE
void __CFSocketSetCallBackTypes(CFSocketRef s
, uint8_t types
) {
172 __CFBitfieldSetValue(((CFRuntimeBase
*)s
)->_info
, 3, 0, types
& 0xF);
175 CF_INLINE
void __CFSocketLock(CFSocketRef s
) {
176 __CFSpinLock(&(s
->_lock
));
179 CF_INLINE
void __CFSocketUnlock(CFSocketRef s
) {
180 __CFSpinUnlock(&(s
->_lock
));
183 CF_INLINE
void __CFSocketWriteLock(CFSocketRef s
) {
184 __CFSpinLock(&(s
->_writeLock
));
187 CF_INLINE
void __CFSocketWriteUnlock(CFSocketRef s
) {
188 __CFSpinUnlock(&(s
->_writeLock
));
191 CF_INLINE Boolean
__CFSocketIsConnectionOriented(CFSocketRef s
) {
192 return (SOCK_STREAM
== s
->_socketType
|| SOCK_SEQPACKET
== s
->_socketType
);
195 CF_INLINE
void __CFSocketEstablishAddress(CFSocketRef s
) {
196 /* socket should already be locked */
197 uint8_t name
[MAX_SOCKADDR_LEN
];
198 int namelen
= sizeof(name
);
199 if (__CFSocketIsValid(s
) && NULL
== s
->_address
&& INVALID_SOCKET
!= s
->_socket
&& 0 == getsockname(s
->_socket
, (struct sockaddr
*)name
, &namelen
) && NULL
!= name
&& 0 < namelen
) {
200 s
->_address
= CFDataCreate(CFGetAllocator(s
), name
, namelen
);
204 CF_INLINE
void __CFSocketEstablishPeerAddress(CFSocketRef s
) {
205 /* socket should already be locked */
206 uint8_t name
[MAX_SOCKADDR_LEN
];
207 int namelen
= sizeof(name
);
208 if (__CFSocketIsValid(s
) && NULL
== s
->_peerAddress
&& INVALID_SOCKET
!= s
->_socket
&& 0 == getpeername(s
->_socket
, (struct sockaddr
*)name
, &namelen
) && NULL
!= name
&& 0 < namelen
) {
209 s
->_peerAddress
= CFDataCreate(CFGetAllocator(s
), name
, namelen
);
213 CF_INLINE CFIndex
__CFSocketFdGetSize(CFDataRef fdSet
) {
214 #if defined(__WIN32__)
215 fd_set
* set
= CFDataGetBytePtr(fdSet
);
216 return set
? set
->fd_count
: 0;
218 return NBBY
* CFDataGetLength(fdSet
);
222 CF_INLINE Boolean
__CFSocketFdSet(CFSocketNativeHandle sock
, CFMutableDataRef fdSet
) {
223 /* returns true if a change occurred, false otherwise */
224 Boolean retval
= false;
225 if (INVALID_SOCKET
!= sock
&& 0 <= sock
) {
226 #if defined(__WIN32__)
227 fd_set
* set
= (fd_set
*)CFDataGetMutableBytePtr(fdSet
);
228 if ((set
->fd_count
* sizeof(SOCKET
) + sizeof(u_int
)) >= CFDataGetLength(fdSet
)) {
229 CFDataIncreaseLength(fdSet
, sizeof(SOCKET
));
230 set
= (fd_set
*)CFDataGetMutableBytePtr(fdSet
);
232 if (!FD_ISSET(sock
, set
)) {
237 CFIndex numFds
= NBBY
* CFDataGetLength(fdSet
);
239 if (sock
>= numFds
) {
240 CFIndex oldSize
= numFds
/ NFDBITS
, newSize
= (sock
+ NFDBITS
) / NFDBITS
, changeInBytes
= (newSize
- oldSize
) * sizeof(fd_mask
);
241 CFDataIncreaseLength(fdSet
, changeInBytes
);
242 fds_bits
= (fd_mask
*)CFDataGetMutableBytePtr(fdSet
);
243 memset(fds_bits
+ oldSize
, 0, changeInBytes
);
245 fds_bits
= (fd_mask
*)CFDataGetMutableBytePtr(fdSet
);
247 if (!FD_ISSET(sock
, (fd_set
*)fds_bits
)) {
249 FD_SET(sock
, (fd_set
*)fds_bits
);
256 CF_INLINE Boolean
__CFSocketFdClr(CFSocketNativeHandle sock
, CFMutableDataRef fdSet
) {
257 /* returns true if a change occurred, false otherwise */
258 Boolean retval
= false;
259 if (INVALID_SOCKET
!= sock
&& 0 <= sock
) {
260 #if defined(__WIN32__)
261 fd_set
* set
= (fd_set
*)CFDataGetMutableBytePtr(fdSet
);
262 if (FD_ISSET(sock
, set
)) {
267 CFIndex numFds
= NBBY
* CFDataGetLength(fdSet
);
270 fds_bits
= (fd_mask
*)CFDataGetMutableBytePtr(fdSet
);
271 if (FD_ISSET(sock
, (fd_set
*)fds_bits
)) {
273 FD_CLR(sock
, (fd_set
*)fds_bits
);
281 static SInt32
__CFSocketCreateWakeupSocketPair(void) {
282 #if defined(CFSOCKET_USE_SOCKETPAIR)
283 return socketpair(PF_LOCAL
, SOCK_DGRAM
, 0, __CFWakeupSocketPair
);
285 //??? should really use native Win32 facilities
288 struct sockaddr_in address
[2];
289 int namelen
= sizeof(struct sockaddr_in
);
290 for (i
= 0; i
< 2; i
++) {
291 __CFWakeupSocketPair
[i
] = socket(PF_INET
, SOCK_DGRAM
, 0);
292 memset(&(address
[i
]), 0, sizeof(struct sockaddr_in
));
293 address
[i
].sin_family
= AF_INET
;
294 address
[i
].sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
295 if (0 <= error
) error
= bind(__CFWakeupSocketPair
[i
], (struct sockaddr
*)&(address
[i
]), sizeof(struct sockaddr_in
));
296 if (0 <= error
) error
= getsockname(__CFWakeupSocketPair
[i
], (struct sockaddr
*)&(address
[i
]), &namelen
);
297 if (sizeof(struct sockaddr_in
) != namelen
) error
= -1;
299 if (0 <= error
) error
= connect(__CFWakeupSocketPair
[0], (struct sockaddr
*)&(address
[1]), sizeof(struct sockaddr_in
));
300 if (0 <= error
) error
= connect(__CFWakeupSocketPair
[1], (struct sockaddr
*)&(address
[0]), sizeof(struct sockaddr_in
));
302 closesocket(__CFWakeupSocketPair
[0]);
303 closesocket(__CFWakeupSocketPair
[1]);
309 static void __CFSocketInitializeSockets(void) {
311 #if defined(__WIN32__)
312 if (!__CFSocketWinSockInitialized
) {
313 WORD versionRequested
= MAKEWORD(1, 1);
315 int errorStatus
= WSAStartup(versionRequested
, &wsaData
);
316 if (errorStatus
!= 0 || LOBYTE(wsaData
.wVersion
) != LOBYTE(versionRequested
) || HIBYTE(wsaData
.wVersion
) != HIBYTE(versionRequested
)) {
318 CFLog(0, CFSTR("*** Could not initialize WinSock subsystem!!!"));
320 __CFSocketWinSockInitialized
= true;
323 __CFWriteSockets
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, NULL
);
324 __CFReadSockets
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, NULL
);
325 __CFWriteSocketsFds
= CFDataCreateMutable(kCFAllocatorSystemDefault
, 0);
326 __CFReadSocketsFds
= CFDataCreateMutable(kCFAllocatorSystemDefault
, 0);
327 #if defined(__WIN32__)
328 CFDataIncreaseLength(__CFWriteSocketsFds
, sizeof(u_int
) + sizeof(SOCKET
));
329 CFDataIncreaseLength(__CFReadSocketsFds
, sizeof(u_int
) + sizeof(SOCKET
));
331 if (0 > __CFSocketCreateWakeupSocketPair()) {
332 CFLog(0, CFSTR("*** Could not create wakeup socket pair for CFSocket!!!"));
334 /* wakeup sockets must be non-blocking */
335 ioctlsocket(__CFWakeupSocketPair
[0], FIONBIO
, &yes
);
336 ioctlsocket(__CFWakeupSocketPair
[1], FIONBIO
, &yes
);
337 __CFSocketFdSet(__CFWakeupSocketPair
[1], __CFReadSocketsFds
);
341 static CFRunLoopRef
__CFSocketCopyRunLoopToWakeUp(CFSocketRef s
) {
342 CFRunLoopRef rl
= NULL
;
343 SInt32 idx
, cnt
= CFArrayGetCount(s
->_runLoops
);
345 rl
= (CFRunLoopRef
)CFArrayGetValueAtIndex(s
->_runLoops
, 0);
346 for (idx
= 1; NULL
!= rl
&& idx
< cnt
; idx
++) {
347 CFRunLoopRef value
= (CFRunLoopRef
)CFArrayGetValueAtIndex(s
->_runLoops
, idx
);
348 if (value
!= rl
) rl
= NULL
;
350 if (NULL
== rl
) { /* more than one different rl, so we must pick one */
351 for (idx
= 0; idx
< cnt
; idx
++) {
352 CFRunLoopRef value
= (CFRunLoopRef
)CFArrayGetValueAtIndex(s
->_runLoops
, idx
);
353 CFStringRef currentMode
= CFRunLoopCopyCurrentMode(value
);
354 if (NULL
!= currentMode
&& CFRunLoopIsWaiting(value
) && CFRunLoopContainsSource(value
, s
->_source
, currentMode
)) {
355 CFRelease(currentMode
);
356 /* ideally, this would be a run loop which isn't also in a
357 * signaled state for this or another source, but that's tricky;
358 * we move this run loop to the end of the list to scramble them
359 * a bit, and always search from the front */
360 CFArrayRemoveValueAtIndex(s
->_runLoops
, idx
);
364 if (NULL
!= currentMode
) CFRelease(currentMode
);
366 if (NULL
== rl
) { /* didn't choose one above, so choose first */
367 rl
= (CFRunLoopRef
)CFArrayGetValueAtIndex(s
->_runLoops
, 0);
368 CFArrayRemoveValueAtIndex(s
->_runLoops
, 0);
370 CFArrayAppendValue(s
->_runLoops
, rl
);
373 if (NULL
!= rl
) CFRetain(rl
);
377 static void __CFSocketHandleWrite(CFSocketRef s
) {
378 SInt32 errorCode
= 0;
379 int errorSize
= sizeof(errorCode
);
380 CFRunLoopRef rl
= NULL
;
381 CFOptionFlags writeCallBacksAvailable
;
383 if (!CFSocketIsValid(s
)) return;
384 if (0 != getsockopt(s
->_socket
, SOL_SOCKET
, SO_ERROR
, &errorCode
, &errorSize
)) errorCode
= 0;
385 #if defined(LOG_CFSOCKET)
386 if (errorCode
) printf("error %d on socket %d\n", errorCode
, s
->_socket
);
389 writeCallBacksAvailable
= __CFSocketCallBackTypes(s
) & (kCFSocketWriteCallBack
| kCFSocketConnectCallBack
);
390 if ((s
->_flags
& kCFSocketConnectCallBack
) != 0) writeCallBacksAvailable
&= ~kCFSocketConnectCallBack
;
391 if (!__CFSocketIsValid(s
) || (((s
->_flags
>> 24) & writeCallBacksAvailable
) == writeCallBacksAvailable
)) {
395 s
->_errorCode
= errorCode
;
396 __CFSocketSetWriteSignalled(s
);
397 CFRunLoopSourceSignal(s
->_source
);
398 #if defined(LOG_CFSOCKET)
399 printf("write signaling source for socket %d\n", s
->_socket
);
401 rl
= __CFSocketCopyRunLoopToWakeUp(s
);
409 static void __CFSocketHandleRead(CFSocketRef s
) {
410 static CFDataRef zeroLengthData
= NULL
;
411 CFRunLoopRef rl
= NULL
;
412 if (NULL
== zeroLengthData
) zeroLengthData
= CFDataCreateMutable(kCFAllocatorSystemDefault
, 0);
413 if (!CFSocketIsValid(s
)) return;
414 if (__CFSocketReadCallBackType(s
) == kCFSocketDataCallBack
) {
415 uint8_t buffer
[MAX_DATA_SIZE
];
416 #if !defined(__WIN32__)
417 uint8_t name
[MAX_SOCKADDR_LEN
];
418 int namelen
= sizeof(name
);
420 struct sockaddr
* name
= NULL
;
423 SInt32 recvlen
= recvfrom(s
->_socket
, buffer
, sizeof(buffer
), 0, (struct sockaddr
*)name
, &namelen
);
424 CFDataRef data
, address
= NULL
;
425 #if defined(LOG_CFSOCKET)
426 printf("read %d bytes on socket %d\n", recvlen
, s
->_socket
);
429 //??? should return error if <0
430 /* zero-length data is the signal for perform to invalidate */
431 data
= CFRetain(zeroLengthData
);
433 data
= CFDataCreate(CFGetAllocator(s
), buffer
, recvlen
);
436 if (!__CFSocketIsValid(s
)) {
441 __CFSocketSetReadSignalled(s
);
442 if (NULL
!= name
&& 0 < namelen
) {
443 //??? possible optimizations: uniquing; storing last value
444 address
= CFDataCreate(CFGetAllocator(s
), name
, namelen
);
445 } else if (__CFSocketIsConnectionOriented(s
)) {
446 if (NULL
== s
->_peerAddress
) __CFSocketEstablishPeerAddress(s
);
447 if (NULL
!= s
->_peerAddress
) address
= CFRetain(s
->_peerAddress
);
449 if (NULL
== address
) {
450 address
= CFRetain(zeroLengthData
);
452 if (NULL
== s
->_dataQueue
) {
453 s
->_dataQueue
= CFArrayCreateMutable(CFGetAllocator(s
), 0, &kCFTypeArrayCallBacks
);
455 if (NULL
== s
->_addressQueue
) {
456 s
->_addressQueue
= CFArrayCreateMutable(CFGetAllocator(s
), 0, &kCFTypeArrayCallBacks
);
458 CFArrayAppendValue(s
->_dataQueue
, data
);
460 CFArrayAppendValue(s
->_addressQueue
, address
);
462 if (0 < recvlen
&& 0 < s
->_socketSetCount
&& (s
->_flags
& kCFSocketDataCallBack
) != 0 && ((s
->_flags
>> 24) & kCFSocketDataCallBack
) == 0 && (0 == s
->_maxQueueLen
|| CFArrayGetCount(s
->_dataQueue
) < s
->_maxQueueLen
)) {
463 __CFSpinLock(&__CFActiveSocketsLock
);
464 /* restore socket to fds */
465 __CFSocketFdSet(s
->_socket
, __CFReadSocketsFds
);
466 __CFSpinUnlock(&__CFActiveSocketsLock
);
468 } else if (__CFSocketReadCallBackType(s
) == kCFSocketAcceptCallBack
) {
469 uint8_t name
[MAX_SOCKADDR_LEN
];
470 int namelen
= sizeof(name
);
471 CFSocketNativeHandle sock
= accept(s
->_socket
, (struct sockaddr
*)name
, &namelen
);
473 if (INVALID_SOCKET
== sock
) {
474 //??? should return error
477 if (NULL
!= name
&& 0 < namelen
) {
478 address
= CFDataCreate(CFGetAllocator(s
), name
, namelen
);
480 address
= CFRetain(zeroLengthData
);
483 if (!__CFSocketIsValid(s
)) {
489 __CFSocketSetReadSignalled(s
);
490 if (NULL
== s
->_dataQueue
) {
491 s
->_dataQueue
= CFArrayCreateMutable(CFGetAllocator(s
), 0, NULL
);
493 if (NULL
== s
->_addressQueue
) {
494 s
->_addressQueue
= CFArrayCreateMutable(CFGetAllocator(s
), 0, &kCFTypeArrayCallBacks
);
496 CFArrayAppendValue(s
->_dataQueue
, (void *)sock
);
497 CFArrayAppendValue(s
->_addressQueue
, address
);
499 if (0 < s
->_socketSetCount
&& (s
->_flags
& kCFSocketAcceptCallBack
) != 0 && ((s
->_flags
>> 24) & kCFSocketAcceptCallBack
) == 0 && (0 == s
->_maxQueueLen
|| CFArrayGetCount(s
->_dataQueue
) < s
->_maxQueueLen
)) {
500 __CFSpinLock(&__CFActiveSocketsLock
);
501 /* restore socket to fds */
502 __CFSocketFdSet(s
->_socket
, __CFReadSocketsFds
);
503 __CFSpinUnlock(&__CFActiveSocketsLock
);
507 if (!__CFSocketIsValid(s
) || ((s
->_flags
>> 24) & kCFSocketReadCallBack
) != 0) {
511 __CFSocketSetReadSignalled(s
);
513 CFRunLoopSourceSignal(s
->_source
);
514 #if defined(LOG_CFSOCKET)
515 printf("read signaling source for socket %d\n", s
->_socket
);
517 rl
= __CFSocketCopyRunLoopToWakeUp(s
);
525 static void * __CFSocketManager(void * arg
) {
526 SInt32 nrfds
, maxnrfds
, fdentries
= 1;
527 #if defined(__WIN32__)
528 fd_set
*writefds
= (fd_set
*)CFAllocatorAllocate(kCFAllocatorSystemDefault
, fdentries
* sizeof(SOCKET
) + sizeof(u_int
), 0);
529 fd_set
*readfds
= (fd_set
*)CFAllocatorAllocate(kCFAllocatorSystemDefault
, fdentries
* sizeof(SOCKET
) + sizeof(u_int
), 0);
531 fd_set
*writefds
= (fd_set
*)CFAllocatorAllocate(kCFAllocatorSystemDefault
, fdentries
* sizeof(fd_mask
), 0);
532 fd_set
*readfds
= (fd_set
*)CFAllocatorAllocate(kCFAllocatorSystemDefault
, fdentries
* sizeof(fd_mask
), 0);
537 CFMutableArrayRef selectedWriteSockets
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
538 CFMutableArrayRef selectedReadSockets
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
541 __CFSpinLock(&__CFActiveSocketsLock
);
542 #if defined(LOG_CFSOCKET)
543 printf("socket manager looking at read sockets ");
544 tempfds
= (fd_set
*)CFDataGetBytePtr(__CFReadSocketsFds
);
545 for (idx
= 0, cnt
= CFArrayGetCount(__CFReadSockets
); idx
< cnt
; idx
++) {
546 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(__CFReadSockets
, idx
);
547 if (FD_ISSET(s
->_socket
, tempfds
)) {
548 printf("%d ", s
->_socket
);
550 printf("(%d) ", s
->_socket
);
553 if (0 < CFArrayGetCount(__CFWriteSockets
)) printf(" and write sockets ");
554 tempfds
= (fd_set
*)CFDataGetBytePtr(__CFWriteSocketsFds
);
555 for (idx
= 0, cnt
= CFArrayGetCount(__CFWriteSockets
); idx
< cnt
; idx
++) {
556 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(__CFWriteSockets
, idx
);
557 if (FD_ISSET(s
->_socket
, tempfds
)) {
558 printf("%d ", s
->_socket
);
560 printf("(%d) ", s
->_socket
);
565 maxnrfds
= MAX(__CFSocketFdGetSize(__CFWriteSocketsFds
), __CFSocketFdGetSize(__CFReadSocketsFds
));
566 #if defined(__WIN32__)
567 if (maxnrfds
> fdentries
) {
568 fdentries
= maxnrfds
;
569 writefds
= (fd_set
*)CFAllocatorReallocate(kCFAllocatorSystemDefault
, writefds
, fdentries
* sizeof(SOCKET
) + sizeof(u_int
), 0);
570 readfds
= (fd_set
*)CFAllocatorReallocate(kCFAllocatorSystemDefault
, readfds
, fdentries
* sizeof(SOCKET
) + sizeof(u_int
), 0);
572 memset(writefds
, 0, fdentries
* sizeof(SOCKET
) + sizeof(u_int
));
573 memset(readfds
, 0, fdentries
* sizeof(SOCKET
) + sizeof(u_int
));
575 if (maxnrfds
> fdentries
* (int)NFDBITS
) {
576 fdentries
= (maxnrfds
+ NFDBITS
- 1) / NFDBITS
;
577 writefds
= (fd_set
*)CFAllocatorReallocate(kCFAllocatorSystemDefault
, writefds
, fdentries
* sizeof(fd_mask
), 0);
578 readfds
= (fd_set
*)CFAllocatorReallocate(kCFAllocatorSystemDefault
, readfds
, fdentries
* sizeof(fd_mask
), 0);
580 memset(writefds
, 0, fdentries
* sizeof(fd_mask
));
581 memset(readfds
, 0, fdentries
* sizeof(fd_mask
));
583 CFDataGetBytes(__CFWriteSocketsFds
, CFRangeMake(0, CFDataGetLength(__CFWriteSocketsFds
)), (UInt8
*)writefds
);
584 CFDataGetBytes(__CFReadSocketsFds
, CFRangeMake(0, CFDataGetLength(__CFReadSocketsFds
)), (UInt8
*)readfds
);
585 __CFSpinUnlock(&__CFActiveSocketsLock
);
587 nrfds
= select(maxnrfds
, readfds
, writefds
, NULL
, NULL
);
588 if (0 == nrfds
) continue;
590 SInt32 selectError
= thread_errno();
591 #if defined(LOG_CFSOCKET)
592 printf("socket manager received error %d from select\n", selectError
);
594 if (EBADF
== selectError
) {
595 CFMutableArrayRef invalidSockets
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
596 __CFSpinLock(&__CFActiveSocketsLock
);
597 cnt
= CFArrayGetCount(__CFWriteSockets
);
598 for (idx
= 0; idx
< cnt
; idx
++) {
599 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(__CFWriteSockets
, idx
);
600 SInt32 flags
= fcntl(s
->_socket
, F_GETFL
, 0);
601 if (0 > flags
&& EBADF
== thread_errno()) {
602 #if defined(LOG_CFSOCKET)
603 printf("socket manager found write socket %d invalid\n", s
->_socket
);
605 CFArrayAppendValue(invalidSockets
, s
);
608 cnt
= CFArrayGetCount(__CFReadSockets
);
609 for (idx
= 0; idx
< cnt
; idx
++) {
610 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(__CFReadSockets
, idx
);
611 SInt32 flags
= fcntl(s
->_socket
, F_GETFL
, 0);
612 if (0 > flags
&& EBADF
== thread_errno()) {
613 #if defined(LOG_CFSOCKET)
614 printf("socket manager found read socket %d invalid\n", s
->_socket
);
616 CFArrayAppendValue(invalidSockets
, s
);
619 __CFSpinUnlock(&__CFActiveSocketsLock
);
621 cnt
= CFArrayGetCount(invalidSockets
);
622 for (idx
= 0; idx
< cnt
; idx
++) {
623 CFSocketInvalidate((CFSocketRef
)CFArrayGetValueAtIndex(invalidSockets
, idx
));
625 CFRelease(invalidSockets
);
629 if (FD_ISSET(__CFWakeupSocketPair
[1], readfds
)) {
630 recv(__CFWakeupSocketPair
[1], buffer
, sizeof(buffer
), 0);
631 #if defined(LOG_CFSOCKET)
632 printf("socket manager received %c on wakeup socket\n", buffer
[0]);
635 __CFSpinLock(&__CFActiveSocketsLock
);
637 cnt
= CFArrayGetCount(__CFWriteSockets
);
638 for (idx
= 0; idx
< cnt
; idx
++) {
639 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(__CFWriteSockets
, idx
);
640 CFSocketNativeHandle sock
= s
->_socket
;
641 if (INVALID_SOCKET
!= sock
&& 0 <= sock
&& sock
< maxnrfds
&& FD_ISSET(sock
, writefds
)) {
642 CFArrayAppendValue(selectedWriteSockets
, s
);
643 /* socket is removed from fds here, restored by CFSocketReschedule */
644 if (!tempfds
) tempfds
= (fd_set
*)CFDataGetMutableBytePtr(__CFWriteSocketsFds
);
645 FD_CLR(sock
, tempfds
);
649 cnt
= CFArrayGetCount(__CFReadSockets
);
650 for (idx
= 0; idx
< cnt
; idx
++) {
651 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(__CFReadSockets
, idx
);
652 CFSocketNativeHandle sock
= s
->_socket
;
653 if (INVALID_SOCKET
!= sock
&& 0 <= sock
&& sock
< maxnrfds
&& FD_ISSET(sock
, readfds
)) {
654 CFArrayAppendValue(selectedReadSockets
, s
);
655 /* socket is removed from fds here, will be restored in read handling or in perform function */
656 if (!tempfds
) tempfds
= (fd_set
*)CFDataGetMutableBytePtr(__CFReadSocketsFds
);
657 FD_CLR(sock
, tempfds
);
660 __CFSpinUnlock(&__CFActiveSocketsLock
);
662 cnt
= CFArrayGetCount(selectedWriteSockets
);
663 for (idx
= 0; idx
< cnt
; idx
++) {
664 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(selectedWriteSockets
, idx
);
665 #if defined(LOG_CFSOCKET)
666 printf("socket manager signaling socket %d for write\n", s
->_socket
);
668 __CFSocketHandleWrite(s
);
670 if (0 < cnt
) CFArrayRemoveAllValues(selectedWriteSockets
);
671 cnt
= CFArrayGetCount(selectedReadSockets
);
672 for (idx
= 0; idx
< cnt
; idx
++) {
673 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(selectedReadSockets
, idx
);
674 #if defined(LOG_CFSOCKET)
675 printf("socket manager signaling socket %d for read\n", s
->_socket
);
677 __CFSocketHandleRead(s
);
679 if (0 < cnt
) CFArrayRemoveAllValues(selectedReadSockets
);
684 static CFStringRef
__CFSocketCopyDescription(CFTypeRef cf
) {
685 CFSocketRef s
= (CFSocketRef
)cf
;
686 CFMutableStringRef result
;
687 CFStringRef contextDesc
= NULL
;
688 void *contextInfo
= NULL
;
689 CFStringRef (*contextCopyDescription
)(const void *info
) = NULL
;
690 result
= CFStringCreateMutable(CFGetAllocator(s
), 0);
692 CFStringAppendFormat(result
, NULL
, CFSTR("<CFSocket %p [%p]>{valid = %s, type = %d, socket = %d, socket set count = %d\n callback types = 0x%x, callout = %x, source = %p,\n run loops = %@,\n context = "), cf
, CFGetAllocator(s
), (__CFSocketIsValid(s
) ? "Yes" : "No"), s
->_socketType
, s
->_socket
, s
->_socketSetCount
, __CFSocketCallBackTypes(s
), s
->_callout
, s
->_source
, s
->_runLoops
);
693 contextInfo
= s
->_context
.info
;
694 contextCopyDescription
= s
->_context
.copyDescription
;
696 if (NULL
!= contextInfo
&& NULL
!= contextCopyDescription
) {
697 contextDesc
= (CFStringRef
)contextCopyDescription(contextInfo
);
699 if (NULL
== contextDesc
) {
700 contextDesc
= CFStringCreateWithFormat(CFGetAllocator(s
), NULL
, CFSTR("<CFSocket context %p>"), contextInfo
);
702 CFStringAppend(result
, contextDesc
);
703 CFRelease(contextDesc
);
707 static void __CFSocketDeallocate(CFTypeRef cf
) {
708 /* Since CFSockets are cached, we can only get here sometime after being invalidated */
709 CFSocketRef s
= (CFSocketRef
)cf
;
710 if (NULL
!= s
->_address
) {
711 CFRelease(s
->_address
);
716 static const CFRuntimeClass __CFSocketClass
= {
721 __CFSocketDeallocate
,
725 __CFSocketCopyDescription
728 __private_extern__
void __CFSocketInitialize(void) {
729 __kCFSocketTypeID
= _CFRuntimeRegisterClass(&__CFSocketClass
);
732 CFTypeID
CFSocketGetTypeID(void) {
733 return __kCFSocketTypeID
;
736 CFSocketError
CFSocketSetAddress(CFSocketRef s
, CFDataRef address
) {
738 SInt32 namelen
, result
= 0;
739 __CFGenericValidateType(s
, __kCFSocketTypeID
);
740 if (NULL
== address
) return -1;
741 name
= CFDataGetBytePtr(address
);
742 namelen
= CFDataGetLength(address
);
744 if (__CFSocketIsValid(s
) && INVALID_SOCKET
!= s
->_socket
&& NULL
!= name
&& 0 < namelen
) {
745 result
= bind(s
->_socket
, (struct sockaddr
*)name
, namelen
);
747 __CFSocketEstablishAddress(s
);
748 listen(s
->_socket
, 256);
751 if (NULL
== s
->_address
&& NULL
!= name
&& 0 < namelen
&& 0 == result
) {
752 s
->_address
= CFDataCreateCopy(CFGetAllocator(s
), address
);
755 //??? should return errno
759 __private_extern__
void CFSocketSetAcceptBacklog(CFSocketRef s
, CFIndex limit
) {
760 __CFGenericValidateType(s
, __kCFSocketTypeID
);
762 if (__CFSocketIsValid(s
) && INVALID_SOCKET
!= s
->_socket
) {
763 listen(s
->_socket
, limit
);
768 __private_extern__
void CFSocketSetMaximumQueueLength(CFSocketRef s
, CFIndex length
) {
769 __CFGenericValidateType(s
, __kCFSocketTypeID
);
771 if (__CFSocketIsValid(s
)) {
772 s
->_maxQueueLen
= length
;
777 CFSocketError
CFSocketConnectToAddress(CFSocketRef s
, CFDataRef address
, CFTimeInterval timeout
) {
778 //??? need error handling, retries
780 SInt32 namelen
, result
= 0, connect_err
= 0, flags
;
781 UInt32 yes
= 1, no
= 0;
782 Boolean wasBlocking
= true;
783 #if !defined(__WIN32__)
784 __CFGenericValidateType(s
, __kCFSocketTypeID
);
785 name
= CFDataGetBytePtr(address
);
786 namelen
= CFDataGetLength(address
);
788 if (__CFSocketIsValid(s
) && INVALID_SOCKET
!= s
->_socket
&& NULL
!= name
&& 0 < namelen
) {
789 #if !defined(__WIN32__)
790 flags
= fcntl(s
->_socket
, F_GETFL
, 0);
791 if (flags
>= 0) wasBlocking
= ((flags
& O_NONBLOCK
) == 0);
793 if (wasBlocking
&& (timeout
> 0.0 || timeout
< 0.0)) ioctlsocket(s
->_socket
, FIONBIO
, &yes
);
794 result
= connect(s
->_socket
, (struct sockaddr
*)name
, namelen
);
795 #if defined(__WIN32__)
796 if (result
!= 0 && WSAGetLastError() == WSAEWOULDBLOCK
) connect_err
= EINPROGRESS
;
798 if (result
!= 0) connect_err
= thread_errno();
800 #if defined(LOG_CFSOCKET)
801 printf("connection attempt returns %d error %d on socket %d (flags 0x%x blocking %d)\n", result
, connect_err
, s
->_socket
, flags
, wasBlocking
);
803 if (EINPROGRESS
== connect_err
&& timeout
>= 0.0) {
804 /* select on socket */
805 CFMutableDataRef fds
= CFDataCreateMutable(kCFAllocatorSystemDefault
, 0);
808 __CFSocketFdSet(s
->_socket
, fds
);
809 tv
.tv_sec
= (0 >= timeout
|| INT_MAX
<= timeout
) ? INT_MAX
: (int)(float)floor(timeout
);
810 tv
.tv_usec
= (int)((timeout
- floor(timeout
)) * 1.0E6
);
811 nrfds
= select(__CFSocketFdGetSize(fds
), NULL
, (fd_set
*)CFDataGetMutableBytePtr(fds
), NULL
, &tv
);
812 result
= (nrfds
> 0) ? 0 : -1;
814 #if defined(LOG_CFSOCKET)
815 printf("timed connection attempt %s on socket %d\n", (result
== 0) ? "succeeds" : "fails", s
->_socket
);
818 if (wasBlocking
&& (timeout
> 0.0 || timeout
< 0.0)) ioctlsocket(s
->_socket
, FIONBIO
, &no
);
820 __CFSocketEstablishPeerAddress(s
);
821 if (NULL
== s
->_peerAddress
&& NULL
!= name
&& 0 < namelen
&& __CFSocketIsConnectionOriented(s
)) {
822 s
->_peerAddress
= CFDataCreateCopy(CFGetAllocator(s
), address
);
825 if (EINPROGRESS
== connect_err
&& timeout
< 0.0) {
827 #if defined(LOG_CFSOCKET)
828 printf("connection attempt continues in background on socket %d\n", s
->_socket
);
833 //??? should return errno
838 CFSocketRef
CFSocketCreate(CFAllocatorRef allocator
, SInt32 protocolFamily
, SInt32 socketType
, SInt32 protocol
, CFOptionFlags callBackTypes
, CFSocketCallBack callout
, const CFSocketContext
*context
) {
839 CFSocketNativeHandle sock
= INVALID_SOCKET
;
840 CFSocketRef s
= NULL
;
841 if (0 >= protocolFamily
) protocolFamily
= PF_INET
;
842 if (PF_INET
== protocolFamily
) {
843 if (0 >= socketType
) socketType
= SOCK_STREAM
;
844 if (0 >= protocol
&& SOCK_STREAM
== socketType
) protocol
= IPPROTO_TCP
;
845 if (0 >= protocol
&& SOCK_DGRAM
== socketType
) protocol
= IPPROTO_UDP
;
847 #if !defined(__WIN32__)
848 if (PF_LOCAL
== protocolFamily
&& 0 >= socketType
) socketType
= SOCK_STREAM
;
850 /* Needs to be initialized at this point for Windows, before socket() */
851 if (NULL
== __CFReadSockets
) __CFSocketInitializeSockets();
852 sock
= socket(protocolFamily
, socketType
, protocol
);
853 if (INVALID_SOCKET
!= sock
) {
854 s
= CFSocketCreateWithNative(allocator
, sock
, callBackTypes
, callout
, context
);
859 CFSocketRef
CFSocketCreateWithNative(CFAllocatorRef allocator
, CFSocketNativeHandle sock
, CFOptionFlags callBackTypes
, CFSocketCallBack callout
, const CFSocketContext
*context
) {
861 int typeSize
= sizeof(memory
->_socketType
);
862 __CFSpinLock(&__CFActiveSocketsLock
);
863 if (NULL
== __CFReadSockets
) __CFSocketInitializeSockets();
864 __CFSpinUnlock(&__CFActiveSocketsLock
);
865 __CFSpinLock(&__CFAllSocketsLock
);
866 if (NULL
== __CFAllSockets
) {
867 __CFAllSockets
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, NULL
, &kCFTypeDictionaryValueCallBacks
);
869 if (INVALID_SOCKET
!= sock
&& CFDictionaryGetValueIfPresent(__CFAllSockets
, (void *)sock
, (const void **)&memory
)) {
870 __CFSpinUnlock(&__CFAllSocketsLock
);
874 memory
= (CFSocketRef
)_CFRuntimeCreateInstance(allocator
, __kCFSocketTypeID
, sizeof(struct __CFSocket
) - sizeof(CFRuntimeBase
), NULL
);
875 if (NULL
== memory
) {
876 __CFSpinUnlock(&__CFAllSocketsLock
);
879 __CFSocketSetCallBackTypes(memory
, callBackTypes
);
880 if (INVALID_SOCKET
!= sock
) __CFSocketSetValid(memory
);
881 __CFSocketUnsetWriteSignalled(memory
);
882 __CFSocketUnsetReadSignalled(memory
);
883 memory
->_flags
= ((callBackTypes
& (~kCFSocketConnectCallBack
)) & (~kCFSocketWriteCallBack
)) | kCFSocketCloseOnInvalidate
;
885 memory
->_writeLock
= 0;
886 memory
->_socket
= sock
;
887 if (INVALID_SOCKET
== sock
|| 0 != getsockopt(sock
, SOL_SOCKET
, SO_TYPE
, &(memory
->_socketType
), &typeSize
)) memory
->_socketType
= 0;
888 memory
->_errorCode
= 0;
889 memory
->_address
= NULL
;
890 memory
->_peerAddress
= NULL
;
891 memory
->_socketSetCount
= 0;
892 memory
->_source
= NULL
;
893 if (INVALID_SOCKET
!= sock
) {
894 memory
->_runLoops
= CFArrayCreateMutable(allocator
, 0, NULL
);
896 memory
->_runLoops
= NULL
;
898 memory
->_callout
= callout
;
899 memory
->_dataQueue
= NULL
;
900 memory
->_addressQueue
= NULL
;
901 memory
->_maxQueueLen
= 0;
902 memory
->_context
.info
= 0;
903 memory
->_context
.retain
= 0;
904 memory
->_context
.release
= 0;
905 memory
->_context
.copyDescription
= 0;
906 if (INVALID_SOCKET
!= sock
) CFDictionaryAddValue(__CFAllSockets
, (void *)sock
, memory
);
907 __CFSpinUnlock(&__CFAllSocketsLock
);
908 if (NULL
!= context
) {
909 void *contextInfo
= context
->retain
? (void *)context
->retain(context
->info
) : context
->info
;
910 __CFSocketLock(memory
);
911 memory
->_context
.retain
= context
->retain
;
912 memory
->_context
.release
= context
->release
;
913 memory
->_context
.copyDescription
= context
->copyDescription
;
914 memory
->_context
.info
= contextInfo
;
915 __CFSocketUnlock(memory
);
920 CFSocketRef
CFSocketCreateWithSocketSignature(CFAllocatorRef allocator
, const CFSocketSignature
*signature
, CFOptionFlags callBackTypes
, CFSocketCallBack callout
, const CFSocketContext
*context
) {
921 CFSocketRef s
= CFSocketCreate(allocator
, signature
->protocolFamily
, signature
->socketType
, signature
->protocol
, callBackTypes
, callout
, context
);
922 if (NULL
!= s
&& (!CFSocketIsValid(s
) || kCFSocketSuccess
!= CFSocketSetAddress(s
, signature
->address
))) {
923 CFSocketInvalidate(s
);
930 CFSocketRef
CFSocketCreateConnectedToSocketSignature(CFAllocatorRef allocator
, const CFSocketSignature
*signature
, CFOptionFlags callBackTypes
, CFSocketCallBack callout
, const CFSocketContext
*context
, CFTimeInterval timeout
) {
931 CFSocketRef s
= CFSocketCreate(allocator
, signature
->protocolFamily
, signature
->socketType
, signature
->protocol
, callBackTypes
, callout
, context
);
932 if (NULL
!= s
&& (!CFSocketIsValid(s
) || kCFSocketSuccess
!= CFSocketConnectToAddress(s
, signature
->address
, timeout
))) {
933 CFSocketInvalidate(s
);
940 void CFSocketInvalidate(CFSocketRef s
) {
941 __CFGenericValidateType(s
, __kCFSocketTypeID
);
943 __CFSpinLock(&__CFAllSocketsLock
);
945 if (__CFSocketIsValid(s
)) {
947 CFRunLoopSourceRef source
;
948 void *contextInfo
= NULL
;
949 void (*contextRelease
)(const void *info
) = NULL
;
950 __CFSocketUnsetValid(s
);
951 __CFSocketUnsetWriteSignalled(s
);
952 __CFSocketUnsetReadSignalled(s
);
953 __CFSpinLock(&__CFActiveSocketsLock
);
954 if (NULL
== __CFReadSockets
) __CFSocketInitializeSockets();
955 idx
= CFArrayGetFirstIndexOfValue(__CFWriteSockets
, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets
)), s
);
957 CFArrayRemoveValueAtIndex(__CFWriteSockets
, idx
);
958 __CFSocketFdClr(s
->_socket
, __CFWriteSocketsFds
);
960 idx
= CFArrayGetFirstIndexOfValue(__CFReadSockets
, CFRangeMake(0, CFArrayGetCount(__CFReadSockets
)), s
);
962 CFArrayRemoveValueAtIndex(__CFReadSockets
, idx
);
963 __CFSocketFdClr(s
->_socket
, __CFReadSocketsFds
);
965 __CFSpinUnlock(&__CFActiveSocketsLock
);
966 CFDictionaryRemoveValue(__CFAllSockets
, (void *)(s
->_socket
));
967 if ((s
->_flags
& kCFSocketCloseOnInvalidate
) != 0) closesocket(s
->_socket
);
968 s
->_socket
= INVALID_SOCKET
;
969 if (NULL
!= s
->_peerAddress
) {
970 CFRelease(s
->_peerAddress
);
971 s
->_peerAddress
= NULL
;
973 if (NULL
!= s
->_dataQueue
) {
974 CFRelease(s
->_dataQueue
);
975 s
->_dataQueue
= NULL
;
977 if (NULL
!= s
->_addressQueue
) {
978 CFRelease(s
->_addressQueue
);
979 s
->_addressQueue
= NULL
;
981 s
->_socketSetCount
= 0;
982 for (idx
= CFArrayGetCount(s
->_runLoops
); idx
--;) {
983 CFRunLoopWakeUp((CFRunLoopRef
)CFArrayGetValueAtIndex(s
->_runLoops
, idx
));
985 CFRelease(s
->_runLoops
);
989 contextInfo
= s
->_context
.info
;
990 contextRelease
= s
->_context
.release
;
991 s
->_context
.info
= 0;
992 s
->_context
.retain
= 0;
993 s
->_context
.release
= 0;
994 s
->_context
.copyDescription
= 0;
996 if (NULL
!= contextRelease
) {
997 contextRelease(contextInfo
);
999 if (NULL
!= source
) {
1000 CFRunLoopSourceInvalidate(source
);
1004 __CFSocketUnlock(s
);
1006 __CFSpinUnlock(&__CFAllSocketsLock
);
1010 Boolean
CFSocketIsValid(CFSocketRef s
) {
1011 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1012 return __CFSocketIsValid(s
);
1015 CFSocketNativeHandle
CFSocketGetNative(CFSocketRef s
) {
1016 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1020 CFDataRef
CFSocketCopyAddress(CFSocketRef s
) {
1021 CFDataRef result
= NULL
;
1022 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1024 __CFSocketEstablishAddress(s
);
1025 if (NULL
!= s
->_address
) {
1026 result
= CFRetain(s
->_address
);
1028 __CFSocketUnlock(s
);
1032 CFDataRef
CFSocketCopyPeerAddress(CFSocketRef s
) {
1033 CFDataRef result
= NULL
;
1034 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1036 __CFSocketEstablishPeerAddress(s
);
1037 if (NULL
!= s
->_peerAddress
) {
1038 result
= CFRetain(s
->_peerAddress
);
1040 __CFSocketUnlock(s
);
1044 void CFSocketGetContext(CFSocketRef s
, CFSocketContext
*context
) {
1045 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1046 CFAssert1(0 == context
->version
, __kCFLogAssertion
, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__
);
1047 *context
= s
->_context
;
1050 __private_extern__
void CFSocketReschedule(CFSocketRef s
) {
1051 CFSocketEnableCallBacks(s
, __CFSocketCallBackTypes(s
));
1054 CFOptionFlags
CFSocketGetSocketFlags(CFSocketRef s
) {
1055 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1056 return (s
->_flags
& (~(kCFSocketConnectCallBack
| (0xff << 24))));
1059 void CFSocketSetSocketFlags(CFSocketRef s
, CFOptionFlags flags
) {
1060 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1062 flags
&= ~(kCFSocketConnectCallBack
| (0xff << 24));
1063 #if defined(LOG_CFSOCKET)
1064 printf("setting flags for socket %d with %x, flags going from %x to %x\n", s
->_socket
, flags
, s
->_flags
, (s
->_flags
& (kCFSocketConnectCallBack
| (0xff << 24))) | flags
);
1066 s
->_flags
&= (kCFSocketConnectCallBack
| (0xff << 24));
1068 __CFSocketUnlock(s
);
1071 void CFSocketDisableCallBacks(CFSocketRef s
, CFOptionFlags callBackTypes
) {
1072 Boolean wakeup
= false;
1073 uint8_t c
= 'u', readCallBackType
;
1074 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1076 if (__CFSocketIsValid(s
) && 0 < s
->_socketSetCount
) {
1077 callBackTypes
&= __CFSocketCallBackTypes(s
);
1078 readCallBackType
= __CFSocketReadCallBackType(s
);
1079 s
->_flags
|= (callBackTypes
<< 24);
1080 #if defined(LOG_CFSOCKET)
1081 printf("unscheduling socket %d with flags 0x%x for types 0x%x\n", s
->_socket
, s
->_flags
, callBackTypes
);
1083 __CFSpinLock(&__CFActiveSocketsLock
);
1084 if (NULL
== __CFReadSockets
) __CFSocketInitializeSockets();
1085 if ((readCallBackType
== kCFSocketAcceptCallBack
) || !__CFSocketIsConnectionOriented(s
)) s
->_flags
|= kCFSocketConnectCallBack
;
1086 if (((callBackTypes
& kCFSocketWriteCallBack
) != 0) || (((callBackTypes
& kCFSocketConnectCallBack
) != 0) && ((s
->_flags
& kCFSocketConnectCallBack
) == 0))) {
1087 if (__CFSocketFdClr(s
->_socket
, __CFWriteSocketsFds
)) {
1088 // do not wake up the socket manager thread if all relevant write callbacks are disabled
1089 CFOptionFlags writeCallBacksAvailable
= __CFSocketCallBackTypes(s
) & (kCFSocketWriteCallBack
| kCFSocketConnectCallBack
);
1090 if ((s
->_flags
& kCFSocketConnectCallBack
) != 0) writeCallBacksAvailable
&= ~kCFSocketConnectCallBack
;
1091 if (((s
->_flags
>> 24) & writeCallBacksAvailable
) != writeCallBacksAvailable
) wakeup
= true;
1094 if (readCallBackType
!= kCFSocketNoCallBack
&& (callBackTypes
& readCallBackType
) != 0) {
1095 if (__CFSocketFdClr(s
->_socket
, __CFReadSocketsFds
)) {
1096 // do not wake up the socket manager thread if callback type is read
1097 if (readCallBackType
!= kCFSocketReadCallBack
) wakeup
= true;
1100 __CFSpinUnlock(&__CFActiveSocketsLock
);
1102 __CFSocketUnlock(s
);
1104 if (NULL
== __CFSocketManagerThread
) {
1105 __CFSocketManagerThread
= __CFStartSimpleThread(__CFSocketManager
, 0);
1107 send(__CFWakeupSocketPair
[0], &c
, sizeof(c
), 0);
1111 void CFSocketEnableCallBacks(CFSocketRef s
, CFOptionFlags callBackTypes
) {
1112 Boolean wakeup
= false;
1113 uint8_t c
= 'r', readCallBackType
;
1114 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1116 if (__CFSocketIsValid(s
) && 0 < s
->_socketSetCount
) {
1117 callBackTypes
&= __CFSocketCallBackTypes(s
);
1118 readCallBackType
= __CFSocketReadCallBackType(s
);
1119 s
->_flags
&= ~(callBackTypes
<< 24);
1120 #if defined(LOG_CFSOCKET)
1121 printf("rescheduling socket %d with flags 0x%x for types 0x%x\n", s
->_socket
, s
->_flags
, callBackTypes
);
1123 __CFSpinLock(&__CFActiveSocketsLock
);
1124 if (NULL
== __CFReadSockets
) __CFSocketInitializeSockets();
1125 /* we will wait for connection only for connection-oriented, non-rendezvous sockets that are not already connected */
1126 if ((readCallBackType
== kCFSocketAcceptCallBack
) || !__CFSocketIsConnectionOriented(s
)) s
->_flags
|= kCFSocketConnectCallBack
;
1127 if (((callBackTypes
& kCFSocketWriteCallBack
) != 0) || (((callBackTypes
& kCFSocketConnectCallBack
) != 0) && ((s
->_flags
& kCFSocketConnectCallBack
) == 0))) {
1128 SInt32 idx
= CFArrayGetFirstIndexOfValue(__CFWriteSockets
, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets
)), s
);
1129 if (kCFNotFound
== idx
) CFArrayAppendValue(__CFWriteSockets
, s
);
1130 if (__CFSocketFdSet(s
->_socket
, __CFWriteSocketsFds
)) wakeup
= true;
1132 if (readCallBackType
!= kCFSocketNoCallBack
&& (callBackTypes
& readCallBackType
) != 0) {
1133 SInt32 idx
= CFArrayGetFirstIndexOfValue(__CFReadSockets
, CFRangeMake(0, CFArrayGetCount(__CFReadSockets
)), s
);
1134 if (kCFNotFound
== idx
) CFArrayAppendValue(__CFReadSockets
, s
);
1135 if (__CFSocketFdSet(s
->_socket
, __CFReadSocketsFds
)) wakeup
= true;
1137 __CFSpinUnlock(&__CFActiveSocketsLock
);
1139 __CFSocketUnlock(s
);
1141 if (NULL
== __CFSocketManagerThread
) {
1142 __CFSocketManagerThread
= __CFStartSimpleThread(__CFSocketManager
, 0);
1144 send(__CFWakeupSocketPair
[0], &c
, sizeof(c
), 0);
1148 static void __CFSocketSchedule(void *info
, CFRunLoopRef rl
, CFStringRef mode
) {
1149 CFSocketRef s
= info
;
1150 Boolean wakeup
= false;
1151 uint8_t c
= 's', readCallBackType
, callBackTypes
;
1153 //??? also need to arrange delivery of all pending data
1154 if (__CFSocketIsValid(s
)) {
1155 CFArrayAppendValue(s
->_runLoops
, rl
);
1156 s
->_socketSetCount
++;
1157 if (1 == s
->_socketSetCount
) {
1158 #if defined(LOG_CFSOCKET)
1159 printf("scheduling socket %d\n", s
->_socket
);
1161 callBackTypes
= __CFSocketCallBackTypes(s
);
1162 readCallBackType
= __CFSocketReadCallBackType(s
);
1163 __CFSpinLock(&__CFActiveSocketsLock
);
1164 if (NULL
== __CFReadSockets
) __CFSocketInitializeSockets();
1165 /* we will wait for connection only for connection-oriented, non-rendezvous sockets that are not already connected */
1166 if ((readCallBackType
== kCFSocketAcceptCallBack
) || !__CFSocketIsConnectionOriented(s
)) s
->_flags
|= kCFSocketConnectCallBack
;
1167 if (((callBackTypes
& kCFSocketWriteCallBack
) != 0) || (((callBackTypes
& kCFSocketConnectCallBack
) != 0) && ((s
->_flags
& kCFSocketConnectCallBack
) == 0))) {
1168 SInt32 idx
= CFArrayGetFirstIndexOfValue(__CFWriteSockets
, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets
)), s
);
1169 if (kCFNotFound
== idx
) CFArrayAppendValue(__CFWriteSockets
, s
);
1170 if (__CFSocketFdSet(s
->_socket
, __CFWriteSocketsFds
)) wakeup
= true;
1172 if (readCallBackType
!= kCFSocketNoCallBack
) {
1173 SInt32 idx
= CFArrayGetFirstIndexOfValue(__CFReadSockets
, CFRangeMake(0, CFArrayGetCount(__CFReadSockets
)), s
);
1174 if (kCFNotFound
== idx
) CFArrayAppendValue(__CFReadSockets
, s
);
1175 if (__CFSocketFdSet(s
->_socket
, __CFReadSocketsFds
)) wakeup
= true;
1177 __CFSpinUnlock(&__CFActiveSocketsLock
);
1180 __CFSocketUnlock(s
);
1182 if (NULL
== __CFSocketManagerThread
) {
1183 __CFSocketManagerThread
= __CFStartSimpleThread(__CFSocketManager
, 0);
1185 send(__CFWakeupSocketPair
[0], &c
, sizeof(c
), 0);
1189 static void __CFSocketCancel(void *info
, CFRunLoopRef rl
, CFStringRef mode
) {
1190 CFSocketRef s
= info
;
1193 s
->_socketSetCount
--;
1194 if (0 == s
->_socketSetCount
) {
1195 __CFSpinLock(&__CFActiveSocketsLock
);
1196 if (NULL
== __CFReadSockets
) __CFSocketInitializeSockets();
1197 idx
= CFArrayGetFirstIndexOfValue(__CFWriteSockets
, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets
)), s
);
1199 CFArrayRemoveValueAtIndex(__CFWriteSockets
, idx
);
1200 __CFSocketFdClr(s
->_socket
, __CFWriteSocketsFds
);
1202 idx
= CFArrayGetFirstIndexOfValue(__CFReadSockets
, CFRangeMake(0, CFArrayGetCount(__CFReadSockets
)), s
);
1204 CFArrayRemoveValueAtIndex(__CFReadSockets
, idx
);
1205 __CFSocketFdClr(s
->_socket
, __CFReadSocketsFds
);
1207 __CFSpinUnlock(&__CFActiveSocketsLock
);
1209 if (NULL
!= s
->_runLoops
) {
1210 idx
= CFArrayGetFirstIndexOfValue(s
->_runLoops
, CFRangeMake(0, CFArrayGetCount(s
->_runLoops
)), rl
);
1211 if (0 <= idx
) CFArrayRemoveValueAtIndex(s
->_runLoops
, idx
);
1213 __CFSocketUnlock(s
);
1216 static void __CFSocketPerform(void *info
) {
1217 CFSocketRef s
= info
;
1218 CFDataRef data
= NULL
;
1219 CFDataRef address
= NULL
;
1220 CFSocketNativeHandle sock
= INVALID_SOCKET
;
1221 CFSocketCallBack callout
= NULL
;
1222 void *contextInfo
= NULL
;
1223 SInt32 errorCode
= 0;
1224 Boolean wakeup
= false, readSignalled
= false, writeSignalled
= false, connectSignalled
= false, calledOut
= false;
1225 uint8_t c
= 'p', readCallBackType
, callBackTypes
;
1226 CFRunLoopRef rl
= NULL
;
1229 if (!__CFSocketIsValid(s
)) {
1230 __CFSocketUnlock(s
);
1233 callBackTypes
= __CFSocketCallBackTypes(s
);
1234 readCallBackType
= __CFSocketReadCallBackType(s
);
1235 readSignalled
= __CFSocketIsReadSignalled(s
);
1236 writeSignalled
= __CFSocketIsWriteSignalled(s
);
1237 connectSignalled
= writeSignalled
&& ((s
->_flags
& kCFSocketConnectCallBack
) == 0);
1238 __CFSocketUnsetReadSignalled(s
);
1239 __CFSocketUnsetWriteSignalled(s
);
1240 callout
= s
->_callout
;
1241 contextInfo
= s
->_context
.info
;
1242 #if defined(LOG_CFSOCKET)
1243 printf("entering perform for socket %d with read signalled %d write signalled %d connect signalled %d callback types %d\n", s
->_socket
, readSignalled
, writeSignalled
, connectSignalled
, callBackTypes
);
1245 if (kCFSocketDataCallBack
== readCallBackType
) {
1246 if (NULL
!= s
->_dataQueue
&& 0 < CFArrayGetCount(s
->_dataQueue
)) {
1247 data
= CFArrayGetValueAtIndex(s
->_dataQueue
, 0);
1249 CFArrayRemoveValueAtIndex(s
->_dataQueue
, 0);
1250 address
= CFArrayGetValueAtIndex(s
->_addressQueue
, 0);
1252 CFArrayRemoveValueAtIndex(s
->_addressQueue
, 0);
1254 } else if (kCFSocketAcceptCallBack
== readCallBackType
) {
1255 if (NULL
!= s
->_dataQueue
&& 0 < CFArrayGetCount(s
->_dataQueue
)) {
1256 sock
= (CFSocketNativeHandle
)CFArrayGetValueAtIndex(s
->_dataQueue
, 0);
1257 CFArrayRemoveValueAtIndex(s
->_dataQueue
, 0);
1258 address
= CFArrayGetValueAtIndex(s
->_addressQueue
, 0);
1260 CFArrayRemoveValueAtIndex(s
->_addressQueue
, 0);
1263 if (writeSignalled
) {
1264 errorCode
= s
->_errorCode
;
1265 s
->_flags
|= kCFSocketConnectCallBack
;
1267 __CFSocketUnlock(s
);
1268 if ((callBackTypes
& kCFSocketConnectCallBack
) != 0) {
1269 if (connectSignalled
&& (!calledOut
|| CFSocketIsValid(s
))) {
1271 #if defined(LOG_CFSOCKET)
1272 printf("perform calling out error %d to socket %d\n", errorCode
, s
->_socket
);
1274 if (callout
) callout(s
, kCFSocketConnectCallBack
, NULL
, &errorCode
, contextInfo
);
1277 #if defined(LOG_CFSOCKET)
1278 printf("perform calling out connect to socket %d\n", s
->_socket
);
1280 if (callout
) callout(s
, kCFSocketConnectCallBack
, NULL
, NULL
, contextInfo
);
1285 if (kCFSocketDataCallBack
== readCallBackType
) {
1286 if (NULL
!= data
&& (!calledOut
|| CFSocketIsValid(s
))) {
1287 SInt32 datalen
= CFDataGetLength(data
);
1288 #if defined(LOG_CFSOCKET)
1289 printf("perform calling out data of length %d to socket %d\n", datalen
, s
->_socket
);
1291 if (callout
) callout(s
, kCFSocketDataCallBack
, address
, data
, contextInfo
);
1295 if (0 == datalen
) CFSocketInvalidate(s
);
1297 } else if (kCFSocketAcceptCallBack
== readCallBackType
) {
1298 if (INVALID_SOCKET
!= sock
&& (!calledOut
|| CFSocketIsValid(s
))) {
1299 #if defined(LOG_CFSOCKET)
1300 printf("perform calling out accept of socket %d to socket %d\n", sock
, s
->_socket
);
1302 if (callout
) callout(s
, kCFSocketAcceptCallBack
, address
, &sock
, contextInfo
);
1306 } else if (kCFSocketReadCallBack
== readCallBackType
) {
1307 if (readSignalled
&& (!calledOut
|| CFSocketIsValid(s
))) {
1308 #if defined(LOG_CFSOCKET)
1309 printf("perform calling out read to socket %d\n", s
->_socket
);
1311 if (callout
) callout(s
, kCFSocketReadCallBack
, NULL
, NULL
, contextInfo
);
1315 if ((callBackTypes
& kCFSocketWriteCallBack
) != 0) {
1316 if (writeSignalled
&& !errorCode
&& (!calledOut
|| CFSocketIsValid(s
))) {
1317 #if defined(LOG_CFSOCKET)
1318 printf("perform calling out write to socket %d\n", s
->_socket
);
1320 if (callout
) callout(s
, kCFSocketWriteCallBack
, NULL
, NULL
, contextInfo
);
1325 if (__CFSocketIsValid(s
) && kCFSocketNoCallBack
!= readCallBackType
) {
1326 if ((kCFSocketDataCallBack
== readCallBackType
|| kCFSocketAcceptCallBack
== readCallBackType
) && NULL
!= s
->_dataQueue
&& 0 < CFArrayGetCount(s
->_dataQueue
)) {
1327 CFRunLoopSourceSignal(s
->_source
);
1328 #if defined(LOG_CFSOCKET)
1329 printf("perform signaling source for socket %d with flags 0x%x\n", s
->_socket
, s
->_flags
);
1331 rl
= __CFSocketCopyRunLoopToWakeUp(s
);
1333 if (readSignalled
&& 0 < s
->_socketSetCount
&& (s
->_flags
& readCallBackType
) != 0 && ((s
->_flags
>> 24) & readCallBackType
) == 0) {
1334 __CFSpinLock(&__CFActiveSocketsLock
);
1335 /* restore socket to fds */
1336 if (__CFSocketFdSet(s
->_socket
, __CFReadSocketsFds
)) wakeup
= true;
1337 __CFSpinUnlock(&__CFActiveSocketsLock
);
1340 if (__CFSocketIsValid(s
) && (callBackTypes
& kCFSocketWriteCallBack
) != 0) {
1341 if (writeSignalled
&& 0 < s
->_socketSetCount
&& (s
->_flags
& kCFSocketWriteCallBack
) != 0 && ((s
->_flags
>> 24) & kCFSocketWriteCallBack
) == 0) {
1342 __CFSpinLock(&__CFActiveSocketsLock
);
1343 /* restore socket to fds */
1344 if (__CFSocketFdSet(s
->_socket
, __CFWriteSocketsFds
)) wakeup
= true;
1345 __CFSpinUnlock(&__CFActiveSocketsLock
);
1348 __CFSocketUnlock(s
);
1350 if (NULL
== __CFSocketManagerThread
) {
1351 __CFSocketManagerThread
= __CFStartSimpleThread(__CFSocketManager
, 0);
1353 send(__CFWakeupSocketPair
[0], &c
, sizeof(c
), 0);
1356 CFRunLoopWakeUp(rl
);
1361 CFRunLoopSourceRef
CFSocketCreateRunLoopSource(CFAllocatorRef allocator
, CFSocketRef s
, CFIndex order
) {
1362 CFRunLoopSourceRef result
= NULL
;
1363 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1365 if (__CFSocketIsValid(s
)) {
1366 if (NULL
== s
->_source
) {
1367 CFRunLoopSourceContext context
;
1368 context
.version
= 0;
1369 context
.info
= (void *)s
;
1370 context
.retain
= (const void *(*)(const void *))CFRetain
;
1371 context
.release
= (void (*)(const void *))CFRelease
;
1372 context
.copyDescription
= (CFStringRef (*)(const void *))CFCopyDescription
;
1373 context
.equal
= (Boolean (*)(const void *, const void *))CFEqual
;
1374 context
.hash
= (CFHashCode (*)(const void *))CFHash
;
1375 context
.schedule
= __CFSocketSchedule
;
1376 context
.cancel
= __CFSocketCancel
;
1377 context
.perform
= __CFSocketPerform
;
1378 s
->_source
= CFRunLoopSourceCreate(allocator
, order
, &context
);
1380 CFRetain(s
->_source
); /* This retain is for the receiver */
1381 result
= s
->_source
;
1383 __CFSocketUnlock(s
);
1387 //??? need timeout, error handling, retries
1388 CFSocketError
CFSocketSendData(CFSocketRef s
, CFDataRef address
, CFDataRef data
, CFTimeInterval timeout
) {
1389 const uint8_t *dataptr
, *addrptr
= NULL
;
1390 SInt32 datalen
, addrlen
= 0, size
= 0;
1391 CFSocketNativeHandle sock
= INVALID_SOCKET
;
1393 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1395 addrptr
= CFDataGetBytePtr(address
);
1396 addrlen
= CFDataGetLength(address
);
1398 dataptr
= CFDataGetBytePtr(data
);
1399 datalen
= CFDataGetLength(data
);
1401 if (__CFSocketIsValid(s
)) sock
= s
->_socket
;
1402 __CFSocketUnlock(s
);
1403 if (INVALID_SOCKET
!= sock
) {
1405 __CFSocketWriteLock(s
);
1406 tv
.tv_sec
= (0 >= timeout
|| INT_MAX
<= timeout
) ? INT_MAX
: (int)(float)floor(timeout
);
1407 tv
.tv_usec
= (int)((timeout
- floor(timeout
)) * 1.0E6
);
1408 setsockopt(sock
, SOL_SOCKET
, SO_SNDTIMEO
, &tv
, sizeof(tv
));
1409 if (NULL
!= addrptr
&& 0 < addrlen
) {
1410 size
= sendto(sock
, dataptr
, datalen
, 0, (struct sockaddr
*)addrptr
, addrlen
);
1412 size
= send(sock
, dataptr
, datalen
, 0);
1414 #if defined(LOG_CFSOCKET)
1415 printf("wrote %d bytes to socket %d\n", size
, s
->_socket
);
1417 __CFSocketWriteUnlock(s
);
1420 return (size
> 0) ? kCFSocketSuccess
: kCFSocketError
;
1424 CFSocketError
*error
;
1425 CFPropertyListRef
*value
;
1427 } __CFSocketNameRegistryResponse
;
1429 static void __CFSocketHandleNameRegistryReply(CFSocketRef s
, CFSocketCallBackType type
, CFDataRef address
, const void *data
, void *info
) {
1430 CFDataRef replyData
= (CFDataRef
)data
;
1431 __CFSocketNameRegistryResponse
*response
= (__CFSocketNameRegistryResponse
*)info
;
1432 CFDictionaryRef replyDictionary
= NULL
;
1433 CFPropertyListRef value
;
1434 replyDictionary
= CFPropertyListCreateFromXMLData(NULL
, replyData
, kCFPropertyListImmutable
, NULL
);
1435 if (NULL
!= response
->error
) *(response
->error
) = kCFSocketError
;
1436 if (NULL
!= replyDictionary
) {
1437 if (CFGetTypeID((CFTypeRef
)replyDictionary
) == CFDictionaryGetTypeID() && NULL
!= (value
= CFDictionaryGetValue(replyDictionary
, kCFSocketResultKey
))) {
1438 if (NULL
!= response
->error
) *(response
->error
) = kCFSocketSuccess
;
1439 if (NULL
!= response
->value
) *(response
->value
) = CFRetain(value
);
1440 if (NULL
!= response
->address
) *(response
->address
) = address
? CFDataCreateCopy(NULL
, address
) : NULL
;
1442 CFRelease(replyDictionary
);
1444 CFSocketInvalidate(s
);
1447 static void __CFSocketSendNameRegistryRequest(CFSocketSignature
*signature
, CFDictionaryRef requestDictionary
, __CFSocketNameRegistryResponse
*response
, CFTimeInterval timeout
) {
1448 CFDataRef requestData
= NULL
;
1449 CFSocketContext context
= {0, response
, NULL
, NULL
, NULL
};
1450 CFSocketRef s
= NULL
;
1451 CFRunLoopSourceRef source
= NULL
;
1452 if (NULL
!= response
->error
) *(response
->error
) = kCFSocketError
;
1453 requestData
= CFPropertyListCreateXMLData(NULL
, requestDictionary
);
1454 if (NULL
!= requestData
) {
1455 if (NULL
!= response
->error
) *(response
->error
) = kCFSocketTimeout
;
1456 s
= CFSocketCreateConnectedToSocketSignature(NULL
, signature
, kCFSocketDataCallBack
, __CFSocketHandleNameRegistryReply
, &context
, timeout
);
1458 if (kCFSocketSuccess
== CFSocketSendData(s
, NULL
, requestData
, timeout
)) {
1459 source
= CFSocketCreateRunLoopSource(NULL
, s
, 0);
1460 CFRunLoopAddSource(CFRunLoopGetCurrent(), source
, __kCFSocketRegistryRequestRunLoopMode
);
1461 CFRunLoopRunInMode(__kCFSocketRegistryRequestRunLoopMode
, timeout
, false);
1464 CFSocketInvalidate(s
);
1467 CFRelease(requestData
);
1471 static void __CFSocketValidateSignature(const CFSocketSignature
*providedSignature
, CFSocketSignature
*signature
, uint16_t defaultPortNumber
) {
1472 struct sockaddr_in sain
, *sainp
;
1473 memset(&sin
, 0, sizeof(sain
));
1474 #if !defined(__WIN32__)
1475 sain
.sin_len
= sizeof(sain
);
1477 sain
.sin_family
= AF_INET
;
1478 sain
.sin_port
= htons(__CFSocketDefaultNameRegistryPortNumber
);
1479 sain
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1480 if (NULL
== providedSignature
) {
1481 signature
->protocolFamily
= PF_INET
;
1482 signature
->socketType
= SOCK_STREAM
;
1483 signature
->protocol
= IPPROTO_TCP
;
1484 signature
->address
= CFDataCreate(NULL
, (uint8_t *)&sain
, sizeof(sain
));
1486 signature
->protocolFamily
= providedSignature
->protocolFamily
;
1487 signature
->socketType
= providedSignature
->socketType
;
1488 signature
->protocol
= providedSignature
->protocol
;
1489 if (0 >= signature
->protocolFamily
) signature
->protocolFamily
= PF_INET
;
1490 if (PF_INET
== signature
->protocolFamily
) {
1491 if (0 >= signature
->socketType
) signature
->socketType
= SOCK_STREAM
;
1492 if (0 >= signature
->protocol
&& SOCK_STREAM
== signature
->socketType
) signature
->protocol
= IPPROTO_TCP
;
1493 if (0 >= signature
->protocol
&& SOCK_DGRAM
== signature
->socketType
) signature
->protocol
= IPPROTO_UDP
;
1495 if (NULL
== providedSignature
->address
) {
1496 signature
->address
= CFDataCreate(NULL
, (uint8_t *)&sain
, sizeof(sain
));
1498 sainp
= (struct sockaddr_in
*)CFDataGetBytePtr(providedSignature
->address
);
1499 if ((int)sizeof(struct sockaddr_in
) <= CFDataGetLength(providedSignature
->address
) && (AF_INET
== sainp
->sin_family
|| 0 == sainp
->sin_family
)) {
1500 #if !defined(__WIN32__)
1501 sain
.sin_len
= sizeof(sain
);
1503 sain
.sin_family
= AF_INET
;
1504 sain
.sin_port
= sainp
->sin_port
;
1505 if (0 == sain
.sin_port
) sain
.sin_port
= htons(defaultPortNumber
);
1506 sain
.sin_addr
.s_addr
= sainp
->sin_addr
.s_addr
;
1507 if (htonl(INADDR_ANY
) == sain
.sin_addr
.s_addr
) sain
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1508 signature
->address
= CFDataCreate(NULL
, (uint8_t *)&sain
, sizeof(sain
));
1510 signature
->address
= CFRetain(providedSignature
->address
);
1516 CFSocketError
CFSocketRegisterValue(const CFSocketSignature
*nameServerSignature
, CFTimeInterval timeout
, CFStringRef name
, CFPropertyListRef value
) {
1517 CFSocketSignature signature
;
1518 CFMutableDictionaryRef dictionary
= CFDictionaryCreateMutable(NULL
, 3, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1519 CFSocketError retval
= kCFSocketError
;
1520 __CFSocketNameRegistryResponse response
= {&retval
, NULL
, NULL
};
1521 CFDictionaryAddValue(dictionary
, kCFSocketCommandKey
, kCFSocketRegisterCommand
);
1522 CFDictionaryAddValue(dictionary
, kCFSocketNameKey
, name
);
1523 if (NULL
!= value
) CFDictionaryAddValue(dictionary
, kCFSocketValueKey
, value
);
1524 __CFSocketValidateSignature(nameServerSignature
, &signature
, __CFSocketDefaultNameRegistryPortNumber
);
1525 __CFSocketSendNameRegistryRequest(&signature
, dictionary
, &response
, timeout
);
1526 CFRelease(dictionary
);
1527 CFRelease(signature
.address
);
1531 CFSocketError
CFSocketCopyRegisteredValue(const CFSocketSignature
*nameServerSignature
, CFTimeInterval timeout
, CFStringRef name
, CFPropertyListRef
*value
, CFDataRef
*serverAddress
) {
1532 CFSocketSignature signature
;
1533 CFMutableDictionaryRef dictionary
= CFDictionaryCreateMutable(NULL
, 2, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1534 CFSocketError retval
= kCFSocketError
;
1535 __CFSocketNameRegistryResponse response
= {&retval
, value
, serverAddress
};
1536 CFDictionaryAddValue(dictionary
, kCFSocketCommandKey
, kCFSocketRetrieveCommand
);
1537 CFDictionaryAddValue(dictionary
, kCFSocketNameKey
, name
);
1538 __CFSocketValidateSignature(nameServerSignature
, &signature
, __CFSocketDefaultNameRegistryPortNumber
);
1539 __CFSocketSendNameRegistryRequest(&signature
, dictionary
, &response
, timeout
);
1540 CFRelease(dictionary
);
1541 CFRelease(signature
.address
);
1545 CFSocketError
CFSocketRegisterSocketSignature(const CFSocketSignature
*nameServerSignature
, CFTimeInterval timeout
, CFStringRef name
, const CFSocketSignature
*signature
) {
1546 CFSocketSignature validatedSignature
;
1547 CFMutableDataRef data
= NULL
;
1548 CFSocketError retval
;
1551 if (NULL
== signature
) {
1552 retval
= CFSocketUnregister(nameServerSignature
, timeout
, name
);
1554 __CFSocketValidateSignature(signature
, &validatedSignature
, 0);
1555 if (NULL
== validatedSignature
.address
|| 0 > validatedSignature
.protocolFamily
|| 255 < validatedSignature
.protocolFamily
|| 0 > validatedSignature
.socketType
|| 255 < validatedSignature
.socketType
|| 0 > validatedSignature
.protocol
|| 255 < validatedSignature
.protocol
|| 0 >= (length
= CFDataGetLength(validatedSignature
.address
)) || 255 < length
) {
1556 retval
= kCFSocketError
;
1558 data
= CFDataCreateMutable(NULL
, sizeof(bytes
) + length
);
1559 bytes
[0] = validatedSignature
.protocolFamily
;
1560 bytes
[1] = validatedSignature
.socketType
;
1561 bytes
[2] = validatedSignature
.protocol
;
1563 CFDataAppendBytes(data
, bytes
, sizeof(bytes
));
1564 CFDataAppendBytes(data
, CFDataGetBytePtr(validatedSignature
.address
), length
);
1565 retval
= CFSocketRegisterValue(nameServerSignature
, timeout
, name
, data
);
1568 CFRelease(validatedSignature
.address
);
1573 CFSocketError
CFSocketCopyRegisteredSocketSignature(const CFSocketSignature
*nameServerSignature
, CFTimeInterval timeout
, CFStringRef name
, CFSocketSignature
*signature
, CFDataRef
*nameServerAddress
) {
1574 CFDataRef data
= NULL
;
1575 CFSocketSignature returnedSignature
;
1576 const uint8_t *ptr
= NULL
, *aptr
= NULL
;
1579 CFDataRef serverAddress
= NULL
;
1580 CFSocketError retval
= CFSocketCopyRegisteredValue(nameServerSignature
, timeout
, name
, (CFPropertyListRef
*)&data
, &serverAddress
);
1581 if (NULL
== data
|| CFGetTypeID(data
) != CFDataGetTypeID() || NULL
== (ptr
= CFDataGetBytePtr(data
)) || (length
= CFDataGetLength(data
)) < 4) retval
= kCFSocketError
;
1582 if (kCFSocketSuccess
== retval
&& NULL
!= signature
) {
1583 returnedSignature
.protocolFamily
= (SInt32
)*ptr
++;
1584 returnedSignature
.socketType
= (SInt32
)*ptr
++;
1585 returnedSignature
.protocol
= (SInt32
)*ptr
++;
1587 returnedSignature
.address
= CFDataCreate(NULL
, ptr
, length
- 4);
1588 __CFSocketValidateSignature(&returnedSignature
, signature
, 0);
1589 CFRelease(returnedSignature
.address
);
1590 ptr
= CFDataGetBytePtr(signature
->address
);
1591 if (CFDataGetLength(signature
->address
) >= (int)sizeof(struct sockaddr_in
) && AF_INET
== ((struct sockaddr
*)ptr
)->sa_family
&& NULL
!= serverAddress
&& CFDataGetLength(serverAddress
) >= (int)sizeof(struct sockaddr_in
) && NULL
!= (aptr
= CFDataGetBytePtr(serverAddress
)) && AF_INET
== ((struct sockaddr
*)aptr
)->sa_family
) {
1592 CFMutableDataRef address
= CFDataCreateMutableCopy(NULL
, CFDataGetLength(signature
->address
), signature
->address
);
1593 mptr
= CFDataGetMutableBytePtr(address
);
1594 ((struct sockaddr_in
*)mptr
)->sin_addr
= ((struct sockaddr_in
*)aptr
)->sin_addr
;
1595 CFRelease(signature
->address
);
1596 signature
->address
= address
;
1598 if (NULL
!= nameServerAddress
) *nameServerAddress
= serverAddress
? CFRetain(serverAddress
) : NULL
;
1600 if (NULL
!= data
) CFRelease(data
);
1601 if (NULL
!= serverAddress
) CFRelease(serverAddress
);
1605 CFSocketError
CFSocketUnregister(const CFSocketSignature
*nameServerSignature
, CFTimeInterval timeout
, CFStringRef name
) {
1606 return CFSocketRegisterValue(nameServerSignature
, timeout
, name
, NULL
);
1609 CF_EXPORT
void CFSocketSetDefaultNameRegistryPortNumber(uint16_t port
) {
1610 __CFSocketDefaultNameRegistryPortNumber
= port
;
1613 CF_EXPORT
uint16_t CFSocketGetDefaultNameRegistryPortNumber(void) {
1614 return __CFSocketDefaultNameRegistryPortNumber
;