2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 Copyright (c) 1999-2007 Apple Inc. All rights reserved.
25 Responsibility: Christopher Kane
28 #define _DARWIN_UNLIMITED_SELECT 1
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"
43 #include "auto_stubs.h"
45 // On Mach we use a v0 RunLoopSource to make client callbacks. That source is signalled by a
46 // separate SocketManager thread who uses select() to watch the sockets' fds.
48 //#define LOG_CFSOCKET
50 #define INVALID_SOCKET (CFSocketNativeHandle)(-1)
53 kCFSocketLeaveErrors
= 64 // candidate for publicization in future
56 static uint16_t __CFSocketDefaultNameRegistryPortNumber
= 2454;
58 CONST_STRING_DECL(kCFSocketCommandKey
, "Command")
59 CONST_STRING_DECL(kCFSocketNameKey
, "Name")
60 CONST_STRING_DECL(kCFSocketValueKey
, "Value")
61 CONST_STRING_DECL(kCFSocketResultKey
, "Result")
62 CONST_STRING_DECL(kCFSocketErrorKey
, "Error")
63 CONST_STRING_DECL(kCFSocketRegisterCommand
, "Register")
64 CONST_STRING_DECL(kCFSocketRetrieveCommand
, "Retrieve")
65 CONST_STRING_DECL(__kCFSocketRegistryRequestRunLoopMode
, "CFSocketRegistryRequest")
67 #define closesocket(a) close((a))
68 #define ioctlsocket(a,b,c) ioctl((a),(b),(c))
70 CF_INLINE
int __CFSocketLastError(void) {
71 return thread_errno();
74 CF_INLINE CFIndex
__CFSocketFdGetSize(CFDataRef fdSet
) {
75 return NBBY
* CFDataGetLength(fdSet
);
78 CF_INLINE Boolean
__CFSocketFdSet(CFSocketNativeHandle sock
, CFMutableDataRef fdSet
) {
79 /* returns true if a change occurred, false otherwise */
80 Boolean retval
= false;
81 if (INVALID_SOCKET
!= sock
&& 0 <= sock
) {
82 CFIndex numFds
= NBBY
* CFDataGetLength(fdSet
);
85 CFIndex oldSize
= numFds
/ NFDBITS
, newSize
= (sock
+ NFDBITS
) / NFDBITS
, changeInBytes
= (newSize
- oldSize
) * sizeof(fd_mask
);
86 CFDataIncreaseLength(fdSet
, changeInBytes
);
87 fds_bits
= (fd_mask
*)CFDataGetMutableBytePtr(fdSet
);
88 memset(fds_bits
+ oldSize
, 0, changeInBytes
);
90 fds_bits
= (fd_mask
*)CFDataGetMutableBytePtr(fdSet
);
92 if (!FD_ISSET(sock
, (fd_set
*)fds_bits
)) {
94 FD_SET(sock
, (fd_set
*)fds_bits
);
104 __private_extern__
void __CFSocketInitialize(void) {}
108 #define MAX_SOCKADDR_LEN 256
109 #define MAX_DATA_SIZE 65535
110 #define MAX_CONNECTION_ORIENTED_DATA_SIZE 32768
112 /* locks are to be acquired in the following order:
113 (1) __CFAllSocketsLock
114 (2) an individual CFSocket's lock
115 (3) __CFActiveSocketsLock
117 static CFSpinLock_t __CFAllSocketsLock
= CFSpinLockInit
; /* controls __CFAllSockets */
118 static CFMutableDictionaryRef __CFAllSockets
= NULL
;
119 static CFSpinLock_t __CFActiveSocketsLock
= CFSpinLockInit
; /* controls __CFRead/WriteSockets, __CFRead/WriteSocketsFds, __CFSocketManagerThread, and __CFSocketManagerIteration */
120 static volatile UInt32 __CFSocketManagerIteration
= 0;
121 static CFMutableArrayRef __CFWriteSockets
= NULL
;
122 static CFMutableArrayRef __CFReadSockets
= NULL
;
123 static CFMutableDataRef __CFWriteSocketsFds
= NULL
;
124 static CFMutableDataRef __CFReadSocketsFds
= NULL
;
125 static CFDataRef zeroLengthData
= NULL
;
126 static Boolean __CFReadSocketsTimeoutInvalid
= true; /* rebuild the timeout value before calling select */
128 static CFSocketNativeHandle __CFWakeupSocketPair
[2] = {INVALID_SOCKET
, INVALID_SOCKET
};
129 static void *__CFSocketManagerThread
= NULL
;
131 static CFTypeID __kCFSocketTypeID
= _kCFRuntimeNotATypeID
;
132 static void __CFSocketDoCallback(CFSocketRef s
, CFDataRef data
, CFDataRef address
, CFSocketNativeHandle sock
);
137 unsigned client
:8; // flags set by client (reenable, CloseOnInvalidate)
138 unsigned disabled
:8; // flags marking disabled callbacks
139 unsigned connected
:1; // Are we connected yet? (also true for connectionless sockets)
140 unsigned writableHint
:1; // Did the polling the socket show it to be writable?
141 unsigned closeSignaled
:1; // Have we seen FD_CLOSE? (only used on Win32)
145 CFSpinLock_t _writeLock
;
146 CFSocketNativeHandle _socket
; /* immutable */
150 CFDataRef _peerAddress
;
151 SInt32 _socketSetCount
;
152 CFRunLoopSourceRef _source0
; // v0 RLS, messaged from SocketMgr
153 CFMutableArrayRef _runLoops
;
154 CFSocketCallBack _callout
; /* immutable */
155 CFSocketContext _context
; /* immutable */
156 CFMutableArrayRef _dataQueue
; // queues to pass data from SocketMgr thread
157 CFMutableArrayRef _addressQueue
;
159 struct timeval _readBufferTimeout
;
160 CFMutableDataRef _readBuffer
;
161 CFIndex _bytesToBuffer
; /* is length of _readBuffer */
162 CFIndex _bytesToBufferPos
; /* where the next _CFSocketRead starts from */
163 CFIndex _bytesToBufferReadPos
; /* Where the buffer will next be read into (always after _bytesToBufferPos, but less than _bytesToBuffer) */
165 int _bufferedReadError
;
167 CFMutableDataRef _leftoverBytes
;
170 /* Bit 6 in the base reserved bits is used for write-signalled state (mutable) */
171 /* Bit 5 in the base reserved bits is used for read-signalled state (mutable) */
172 /* Bit 4 in the base reserved bits is used for invalid state (mutable) */
173 /* Bits 0-3 in the base reserved bits are used for callback types (immutable) */
174 /* Of this, bits 0-1 are used for the read callback type. */
176 CF_INLINE Boolean
__CFSocketIsWriteSignalled(CFSocketRef s
) {
177 return (Boolean
)__CFBitfieldGetValue(((const CFRuntimeBase
*)s
)->_cfinfo
[CF_INFO_BITS
], 6, 6);
180 CF_INLINE
void __CFSocketSetWriteSignalled(CFSocketRef s
) {
181 __CFBitfieldSetValue(((CFRuntimeBase
*)s
)->_cfinfo
[CF_INFO_BITS
], 6, 6, 1);
184 CF_INLINE
void __CFSocketUnsetWriteSignalled(CFSocketRef s
) {
185 __CFBitfieldSetValue(((CFRuntimeBase
*)s
)->_cfinfo
[CF_INFO_BITS
], 6, 6, 0);
188 CF_INLINE Boolean
__CFSocketIsReadSignalled(CFSocketRef s
) {
189 return (Boolean
)__CFBitfieldGetValue(((const CFRuntimeBase
*)s
)->_cfinfo
[CF_INFO_BITS
], 5, 5);
192 CF_INLINE
void __CFSocketSetReadSignalled(CFSocketRef s
) {
193 __CFBitfieldSetValue(((CFRuntimeBase
*)s
)->_cfinfo
[CF_INFO_BITS
], 5, 5, 1);
196 CF_INLINE
void __CFSocketUnsetReadSignalled(CFSocketRef s
) {
197 __CFBitfieldSetValue(((CFRuntimeBase
*)s
)->_cfinfo
[CF_INFO_BITS
], 5, 5, 0);
200 CF_INLINE Boolean
__CFSocketIsValid(CFSocketRef s
) {
201 return (Boolean
)__CFBitfieldGetValue(((const CFRuntimeBase
*)s
)->_cfinfo
[CF_INFO_BITS
], 4, 4);
204 CF_INLINE
void __CFSocketSetValid(CFSocketRef s
) {
205 __CFBitfieldSetValue(((CFRuntimeBase
*)s
)->_cfinfo
[CF_INFO_BITS
], 4, 4, 1);
208 CF_INLINE
void __CFSocketUnsetValid(CFSocketRef s
) {
209 __CFBitfieldSetValue(((CFRuntimeBase
*)s
)->_cfinfo
[CF_INFO_BITS
], 4, 4, 0);
212 CF_INLINE
uint8_t __CFSocketCallBackTypes(CFSocketRef s
) {
213 return (uint8_t)__CFBitfieldGetValue(((const CFRuntimeBase
*)s
)->_cfinfo
[CF_INFO_BITS
], 3, 0);
216 CF_INLINE
uint8_t __CFSocketReadCallBackType(CFSocketRef s
) {
217 return (uint8_t)__CFBitfieldGetValue(((const CFRuntimeBase
*)s
)->_cfinfo
[CF_INFO_BITS
], 1, 0);
220 CF_INLINE
void __CFSocketSetCallBackTypes(CFSocketRef s
, uint8_t types
) {
221 __CFBitfieldSetValue(((CFRuntimeBase
*)s
)->_cfinfo
[CF_INFO_BITS
], 3, 0, types
& 0xF);
224 CF_INLINE
void __CFSocketLock(CFSocketRef s
) {
225 __CFSpinLock(&(s
->_lock
));
228 CF_INLINE
void __CFSocketUnlock(CFSocketRef s
) {
229 __CFSpinUnlock(&(s
->_lock
));
232 CF_INLINE Boolean
__CFSocketIsConnectionOriented(CFSocketRef s
) {
233 return (SOCK_STREAM
== s
->_socketType
|| SOCK_SEQPACKET
== s
->_socketType
);
236 CF_INLINE Boolean
__CFSocketIsScheduled(CFSocketRef s
) {
237 return (s
->_socketSetCount
> 0);
240 CF_INLINE
void __CFSocketEstablishAddress(CFSocketRef s
) {
241 /* socket should already be locked */
242 uint8_t name
[MAX_SOCKADDR_LEN
];
243 int namelen
= sizeof(name
);
244 if (__CFSocketIsValid(s
) && NULL
== s
->_address
&& INVALID_SOCKET
!= s
->_socket
&& 0 == getsockname(s
->_socket
, (struct sockaddr
*)name
, (socklen_t
*)&namelen
) && NULL
!= name
&& 0 < namelen
) {
245 s
->_address
= CFDataCreate(CFGetAllocator(s
), name
, namelen
);
249 CF_INLINE
void __CFSocketEstablishPeerAddress(CFSocketRef s
) {
250 /* socket should already be locked */
251 uint8_t name
[MAX_SOCKADDR_LEN
];
252 int namelen
= sizeof(name
);
253 if (__CFSocketIsValid(s
) && NULL
== s
->_peerAddress
&& INVALID_SOCKET
!= s
->_socket
&& 0 == getpeername(s
->_socket
, (struct sockaddr
*)name
, (socklen_t
*)&namelen
) && NULL
!= name
&& 0 < namelen
) {
254 s
->_peerAddress
= CFDataCreate(CFGetAllocator(s
), name
, namelen
);
258 static Boolean
__CFNativeSocketIsValid(CFSocketNativeHandle sock
) {
259 SInt32 flags
= fcntl(sock
, F_GETFL
, 0);
260 return !(0 > flags
&& EBADF
== thread_errno());
263 CF_INLINE Boolean
__CFSocketFdClr(CFSocketNativeHandle sock
, CFMutableDataRef fdSet
) {
264 /* returns true if a change occurred, false otherwise */
265 Boolean retval
= false;
266 if (INVALID_SOCKET
!= sock
&& 0 <= sock
) {
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
);
280 static SInt32
__CFSocketCreateWakeupSocketPair(void) {
281 return socketpair(PF_LOCAL
, SOCK_DGRAM
, 0, __CFWakeupSocketPair
);
285 // Version 0 RunLoopSources set a mask in an FD set to control what socket activity we hear about.
286 CF_INLINE Boolean
__CFSocketSetFDForRead(CFSocketRef s
) {
287 __CFReadSocketsTimeoutInvalid
= true;
288 return __CFSocketFdSet(s
->_socket
, __CFReadSocketsFds
);
291 CF_INLINE Boolean
__CFSocketClearFDForRead(CFSocketRef s
) {
292 __CFReadSocketsTimeoutInvalid
= true;
293 return __CFSocketFdClr(s
->_socket
, __CFReadSocketsFds
);
296 CF_INLINE Boolean
__CFSocketSetFDForWrite(CFSocketRef s
) {
297 return __CFSocketFdSet(s
->_socket
, __CFWriteSocketsFds
);
300 CF_INLINE Boolean
__CFSocketClearFDForWrite(CFSocketRef s
) {
301 return __CFSocketFdClr(s
->_socket
, __CFWriteSocketsFds
);
305 // CFNetwork needs to call this, especially for Win32 to get WSAStartup
306 static void __CFSocketInitializeSockets(void) {
307 __CFWriteSockets
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, NULL
);
308 __CFReadSockets
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, NULL
);
309 __CFWriteSocketsFds
= CFDataCreateMutable(kCFAllocatorSystemDefault
, 0);
310 __CFReadSocketsFds
= CFDataCreateMutable(kCFAllocatorSystemDefault
, 0);
311 zeroLengthData
= CFDataCreateMutable(kCFAllocatorSystemDefault
, 0);
312 if (0 > __CFSocketCreateWakeupSocketPair()) {
313 CFLog(kCFLogLevelWarning
, CFSTR("*** Could not create wakeup socket pair for CFSocket!!!"));
316 /* wakeup sockets must be non-blocking */
317 ioctlsocket(__CFWakeupSocketPair
[0], FIONBIO
, &yes
);
318 ioctlsocket(__CFWakeupSocketPair
[1], FIONBIO
, &yes
);
319 __CFSocketFdSet(__CFWakeupSocketPair
[1], __CFReadSocketsFds
);
323 static CFRunLoopRef
__CFSocketCopyRunLoopToWakeUp(CFSocketRef s
) {
324 CFRunLoopRef rl
= NULL
;
325 SInt32 idx
, cnt
= CFArrayGetCount(s
->_runLoops
);
327 rl
= (CFRunLoopRef
)CFArrayGetValueAtIndex(s
->_runLoops
, 0);
328 for (idx
= 1; NULL
!= rl
&& idx
< cnt
; idx
++) {
329 CFRunLoopRef value
= (CFRunLoopRef
)CFArrayGetValueAtIndex(s
->_runLoops
, idx
);
330 if (value
!= rl
) rl
= NULL
;
332 if (NULL
== rl
) { /* more than one different rl, so we must pick one */
333 /* ideally, this would be a run loop which isn't also in a
334 * signaled state for this or another source, but that's tricky;
335 * we pick one that is running in an appropriate mode for this
336 * source, and from those if possible one that is waiting; then
337 * we move this run loop to the end of the list to scramble them
338 * a bit, and always search from the front */
339 Boolean foundIt
= false, foundBackup
= false;
341 for (idx
= 0; !foundIt
&& idx
< cnt
; idx
++) {
342 CFRunLoopRef value
= (CFRunLoopRef
)CFArrayGetValueAtIndex(s
->_runLoops
, idx
);
343 CFStringRef currentMode
= CFRunLoopCopyCurrentMode(value
);
344 if (NULL
!= currentMode
) {
345 if (CFRunLoopContainsSource(value
, s
->_source0
, currentMode
)) {
346 if (CFRunLoopIsWaiting(value
)) {
349 } else if (!foundBackup
) {
354 CFRelease(currentMode
);
357 rl
= (CFRunLoopRef
)CFArrayGetValueAtIndex(s
->_runLoops
, foundIdx
);
359 CFArrayRemoveValueAtIndex(s
->_runLoops
, foundIdx
);
360 CFArrayAppendValue(s
->_runLoops
, rl
);
368 // If callBackNow, we immediately do client callbacks, else we have to signal a v0 RunLoopSource so the
369 // callbacks can happen in another thread.
370 static void __CFSocketHandleWrite(CFSocketRef s
, Boolean callBackNow
) {
371 SInt32 errorCode
= 0;
372 int errorSize
= sizeof(errorCode
);
373 CFOptionFlags writeCallBacksAvailable
;
375 if (!CFSocketIsValid(s
)) return;
376 if (0 != (s
->_f
.client
& kCFSocketLeaveErrors
) || 0 != getsockopt(s
->_socket
, SOL_SOCKET
, SO_ERROR
, (void *)&errorCode
, (socklen_t
*)&errorSize
)) errorCode
= 0; // cast for WinSock bad API
377 #if defined(LOG_CFSOCKET)
378 if (errorCode
) fprintf(stdout
, "error %ld on socket %d\n", errorCode
, s
->_socket
);
381 writeCallBacksAvailable
= __CFSocketCallBackTypes(s
) & (kCFSocketWriteCallBack
| kCFSocketConnectCallBack
);
382 if ((s
->_f
.client
& kCFSocketConnectCallBack
) != 0) writeCallBacksAvailable
&= ~kCFSocketConnectCallBack
;
383 if (!__CFSocketIsValid(s
) || ((s
->_f
.disabled
& writeCallBacksAvailable
) == writeCallBacksAvailable
)) {
387 s
->_errorCode
= errorCode
;
388 __CFSocketSetWriteSignalled(s
);
389 #if defined(LOG_CFSOCKET)
390 fprintf(stdout
, "write signaling source for socket %d\n", s
->_socket
);
393 __CFSocketDoCallback(s
, NULL
, NULL
, 0);
396 CFRunLoopSourceSignal(s
->_source0
);
397 rl
= __CFSocketCopyRunLoopToWakeUp(s
);
406 static void __CFSocketHandleRead(CFSocketRef s
, Boolean causedByTimeout
)
408 CFDataRef data
= NULL
, address
= NULL
;
409 CFSocketNativeHandle sock
= INVALID_SOCKET
;
410 if (!CFSocketIsValid(s
)) return;
411 if (__CFSocketReadCallBackType(s
) == kCFSocketDataCallBack
) {
412 uint8_t bufferArray
[MAX_CONNECTION_ORIENTED_DATA_SIZE
], *buffer
;
413 uint8_t name
[MAX_SOCKADDR_LEN
];
414 int namelen
= sizeof(name
);
416 if (__CFSocketIsConnectionOriented(s
)) {
417 buffer
= bufferArray
;
418 recvlen
= recvfrom(s
->_socket
, buffer
, MAX_CONNECTION_ORIENTED_DATA_SIZE
, 0, (struct sockaddr
*)name
, (socklen_t
*)&namelen
);
420 buffer
= malloc(MAX_DATA_SIZE
);
421 if (buffer
) recvlen
= recvfrom(s
->_socket
, buffer
, MAX_DATA_SIZE
, 0, (struct sockaddr
*)name
, (socklen_t
*)&namelen
);
423 #if defined(LOG_CFSOCKET)
424 fprintf(stdout
, "read %ld bytes on socket %d\n", recvlen
, s
->_socket
);
427 //??? should return error if <0
428 /* zero-length data is the signal for perform to invalidate */
429 data
= CFRetain(zeroLengthData
);
431 data
= CFDataCreate(CFGetAllocator(s
), buffer
, recvlen
);
433 if (buffer
&& buffer
!= bufferArray
) free(buffer
);
435 if (!__CFSocketIsValid(s
)) {
440 __CFSocketSetReadSignalled(s
);
441 if (NULL
!= name
&& 0 < namelen
) {
442 //??? possible optimizations: uniquing; storing last value
443 address
= CFDataCreate(CFGetAllocator(s
), name
, namelen
);
444 } else if (__CFSocketIsConnectionOriented(s
)) {
445 if (NULL
== s
->_peerAddress
) __CFSocketEstablishPeerAddress(s
);
446 if (NULL
!= s
->_peerAddress
) address
= CFRetain(s
->_peerAddress
);
448 if (NULL
== address
) {
449 address
= CFRetain(zeroLengthData
);
451 if (NULL
== s
->_dataQueue
) {
452 s
->_dataQueue
= CFArrayCreateMutable(CFGetAllocator(s
), 0, &kCFTypeArrayCallBacks
);
454 if (NULL
== s
->_addressQueue
) {
455 s
->_addressQueue
= CFArrayCreateMutable(CFGetAllocator(s
), 0, &kCFTypeArrayCallBacks
);
457 CFArrayAppendValue(s
->_dataQueue
, data
);
459 CFArrayAppendValue(s
->_addressQueue
, address
);
462 && (s
->_f
.client
& kCFSocketDataCallBack
) != 0 && (s
->_f
.disabled
& kCFSocketDataCallBack
) == 0
463 && __CFSocketIsScheduled(s
)
465 __CFSpinLock(&__CFActiveSocketsLock
);
466 /* restore socket to fds */
467 __CFSocketSetFDForRead(s
);
468 __CFSpinUnlock(&__CFActiveSocketsLock
);
470 } else if (__CFSocketReadCallBackType(s
) == kCFSocketAcceptCallBack
) {
471 uint8_t name
[MAX_SOCKADDR_LEN
];
472 int namelen
= sizeof(name
);
473 sock
= accept(s
->_socket
, (struct sockaddr
*)name
, (socklen_t
*)&namelen
);
474 if (INVALID_SOCKET
== sock
) {
475 //??? should return error
478 if (NULL
!= name
&& 0 < namelen
) {
479 address
= CFDataCreate(CFGetAllocator(s
), name
, namelen
);
481 address
= CFRetain(zeroLengthData
);
484 if (!__CFSocketIsValid(s
)) {
490 __CFSocketSetReadSignalled(s
);
491 if (NULL
== s
->_dataQueue
) {
492 s
->_dataQueue
= CFArrayCreateMutable(CFGetAllocator(s
), 0, NULL
);
494 if (NULL
== s
->_addressQueue
) {
495 s
->_addressQueue
= CFArrayCreateMutable(CFGetAllocator(s
), 0, &kCFTypeArrayCallBacks
);
497 CFArrayAppendValue(s
->_dataQueue
, (void *)(uintptr_t)sock
);
498 CFArrayAppendValue(s
->_addressQueue
, address
);
500 if ((s
->_f
.client
& kCFSocketAcceptCallBack
) != 0 && (s
->_f
.disabled
& kCFSocketAcceptCallBack
) == 0
501 && __CFSocketIsScheduled(s
)
503 __CFSpinLock(&__CFActiveSocketsLock
);
504 /* restore socket to fds */
505 __CFSocketSetFDForRead(s
);
506 __CFSpinUnlock(&__CFActiveSocketsLock
);
510 if (!__CFSocketIsValid(s
) || (s
->_f
.disabled
& kCFSocketReadCallBack
) != 0) {
515 if (causedByTimeout
) {
516 #if defined(LOG_CFSOCKET)
517 fprintf(stdout
, "TIMEOUT RECEIVED - WILL SIGNAL IMMEDIATELY TO FLUSH (%d buffered)\n", s
->_bytesToBufferPos
);
519 /* we've got a timeout, but no bytes read. Ignore the timeout. */
520 if (s
->_bytesToBufferPos
== 0) {
521 #if defined(LOG_CFSOCKET)
522 fprintf(stdout
, "TIMEOUT - but no bytes, restoring to active set\n");
526 __CFSpinLock(&__CFActiveSocketsLock
);
527 /* restore socket to fds */
528 __CFSocketSetFDForRead(s
);
529 __CFSpinUnlock(&__CFActiveSocketsLock
);
533 } else if (s
->_bytesToBuffer
!= 0 && ! s
->_atEOF
) {
536 CFIndex ctRemaining
= s
->_bytesToBuffer
- s
->_bytesToBufferPos
;
538 /* if our buffer has room, we go ahead and buffer */
539 if (ctRemaining
> 0) {
540 base
= CFDataGetMutableBytePtr(s
->_readBuffer
);
543 ctRead
= read(CFSocketGetNative(s
), &base
[s
->_bytesToBufferPos
], ctRemaining
);
544 } while (ctRead
== -1 && errno
== EAGAIN
);
548 s
->_bufferedReadError
= errno
;
550 #if defined(LOG_CFSOCKET)
551 fprintf(stderr
, "BUFFERED READ GOT ERROR %d\n", errno
);
556 #if defined(LOG_CFSOCKET)
557 fprintf(stdout
, "DONE READING (EOF) - GOING TO SIGNAL\n");
563 s
->_bytesToBufferPos
+= ctRead
;
564 if (s
->_bytesToBuffer
!= s
->_bytesToBufferPos
) {
565 #if defined(LOG_CFSOCKET)
566 fprintf(stdout
, "READ %d - need %d MORE - GOING BACK FOR MORE\n", ctRead
, s
->_bytesToBuffer
- s
->_bytesToBufferPos
);
568 __CFSpinLock(&__CFActiveSocketsLock
);
569 /* restore socket to fds */
570 __CFSocketSetFDForRead(s
);
571 __CFSpinUnlock(&__CFActiveSocketsLock
);
575 #if defined(LOG_CFSOCKET)
576 fprintf(stdout
, "DONE READING (read %d bytes) - GOING TO SIGNAL\n", ctRead
);
583 __CFSocketSetReadSignalled(s
);
585 #if defined(LOG_CFSOCKET)
586 fprintf(stdout
, "read signaling source for socket %d\n", s
->_socket
);
588 CFRunLoopSourceSignal(s
->_source0
);
589 CFRunLoopRef rl
= __CFSocketCopyRunLoopToWakeUp(s
);
597 static struct timeval
* intervalToTimeval(CFTimeInterval timeout
, struct timeval
* tv
)
602 tv
->tv_sec
= (0 >= timeout
|| INT_MAX
<= timeout
) ? INT_MAX
: (int)(float)floor(timeout
);
603 tv
->tv_usec
= (int)((timeout
- floor(timeout
)) * 1.0E6
);
608 /* note that this returns a pointer to the min value, which won't have changed during
609 the dictionary apply, since we've got the active sockets lock held */
610 static void _calcMinTimeout_locked(const void* val
, void* ctxt
)
612 CFSocketRef s
= (CFSocketRef
) val
;
613 struct timeval
** minTime
= (struct timeval
**) ctxt
;
614 if (timerisset(&s
->_readBufferTimeout
) && (*minTime
== NULL
|| timercmp(&s
->_readBufferTimeout
, *minTime
, <)))
615 *minTime
= &s
->_readBufferTimeout
;
616 else if (s
->_leftoverBytes
) {
617 /* If there's anyone with leftover bytes, they'll need to be awoken immediately */
618 static struct timeval sKickerTime
= { 0, 0 };
619 *minTime
= &sKickerTime
;
623 void __CFSocketSetSocketReadBufferAttrs(CFSocketRef s
, CFTimeInterval timeout
, CFIndex length
)
625 struct timeval timeoutVal
;
627 intervalToTimeval(timeout
, &timeoutVal
);
629 /* lock ordering is socket lock, activesocketslock */
630 /* activesocketslock protects our timeout calculation */
632 __CFSpinLock(&__CFActiveSocketsLock
);
634 #if defined(LOG_CFSOCKET)
635 s
->didLogSomething
= false;
638 if (s
->_bytesToBuffer
!= length
) {
639 CFIndex ctBuffer
= s
->_bytesToBufferPos
- s
->_bytesToBufferReadPos
;
642 /* As originally envisaged, you were supposed to be sure to drain the buffer before
643 * issuing another request on the socket. In practice, there seem to be times when we want to re-use
644 * the stream (or perhaps, are on our way to closing it out) and this policy doesn't work so well.
645 * So, if someone changes the buffer size while we have bytes already buffered, we put them
646 * aside and use them to satisfy any subsequent reads.
648 #if defined(LOG_CFSOCKET)
649 __socketLog("%s(%d): WARNING: shouldn't set read buffer length while data (%d bytes) is still in the read buffer (leftover total %d)", __FUNCTION__
, __LINE__
, ctBuffer
, s
->_leftoverBytes
? CFDataGetLength(s
->_leftoverBytes
) : 0);
652 if (s
->_leftoverBytes
== NULL
)
653 s
->_leftoverBytes
= CFDataCreateMutable(CFGetAllocator(s
), 0);
655 /* append the current buffered bytes over. We'll keep draining _leftoverBytes while we have them... */
656 CFDataAppendBytes(s
->_leftoverBytes
, CFDataGetBytePtr(s
->_readBuffer
) + s
->_bytesToBufferReadPos
, ctBuffer
);
657 CFRelease(s
->_readBuffer
);
658 s
->_readBuffer
= NULL
;
660 s
->_bytesToBuffer
= 0;
661 s
->_bytesToBufferPos
= 0;
662 s
->_bytesToBufferReadPos
= 0;
665 s
->_bytesToBuffer
= 0;
666 s
->_bytesToBufferPos
= 0;
667 s
->_bytesToBufferReadPos
= 0;
668 if (s
->_readBuffer
) {
669 CFRelease(s
->_readBuffer
);
670 s
->_readBuffer
= NULL
;
672 // Zero length buffer, smash the timeout
673 timeoutVal
= (struct timeval
) { 0, 0 };
675 /* if the buffer shrank, we can re-use the old one */
676 if (length
> s
->_bytesToBuffer
) {
677 if (s
->_readBuffer
) {
678 CFRelease(s
->_readBuffer
);
679 s
->_readBuffer
= NULL
;
683 s
->_bytesToBuffer
= length
;
684 s
->_bytesToBufferPos
= 0;
685 s
->_bytesToBufferReadPos
= 0;
686 if (s
->_readBuffer
== NULL
) {
687 s
->_readBuffer
= CFDataCreateMutable(kCFAllocatorSystemDefault
, length
);
688 CFDataSetLength(s
->_readBuffer
, length
);
693 if (timercmp(&s
->_readBufferTimeout
, &timeoutVal
, !=)) {
694 s
->_readBufferTimeout
= timeoutVal
;
695 __CFReadSocketsTimeoutInvalid
= true;
698 __CFSpinUnlock(&__CFActiveSocketsLock
);
702 void __CFSocketSetReadBufferTimeout(CFSocketRef s
, CFTimeInterval timeout
)
704 #if defined(LOG_CFSOCKET)
705 __socketLog("### (%s DEPRECATED) SET READ BUFFER TIMEOUT for %p (bufferSize %d, timeout %d.%d)\n", __FUNCTION__
, s
, s
->_bytesToBuffer
, s
->_readBufferTimeout
.tv_sec
, s
->_readBufferTimeout
.tv_usec
);
708 __CFSocketSetSocketReadBufferAttrs(s
, timeout
, s
->_bytesToBuffer
);
711 void __CFSocketSetReadBufferLength(CFSocketRef s
, CFIndex length
)
713 #if defined(LOG_CFSOCKET)
714 __socketLog("### (%s DEPRECATED) SET READ BUFFER LENGTH for %p (bufferSize %d, timeout %d.%d)\n", __FUNCTION__
, s
, s
->_bytesToBuffer
, s
->_readBufferTimeout
.tv_sec
, s
->_readBufferTimeout
.tv_usec
);
717 CFTimeInterval timeout
;
719 if (! timerisset(&s
->_readBufferTimeout
))
724 __CFSocketSetSocketReadBufferAttrs(s
, timeout
, length
);
728 CFIndex
__CFSocketRead(CFSocketRef s
, UInt8
* buffer
, CFIndex length
, int* error
)
730 #if defined(LOG_CFSOCKET)
731 fprintf(stdout
, "READING BYTES FOR SOCKET %d (%d buffered, out of %d desired, eof = %d, err = %d)\n", s
->_socket
, s
->_bytesToBufferPos
, s
->_bytesToBuffer
, s
->_atEOF
, s
->_bufferedReadError
);
740 /* Any leftover buffered bytes? */
741 if (s
->_leftoverBytes
) {
742 CFIndex ctBuffer
= CFDataGetLength(s
->_leftoverBytes
);
744 fprintf(stderr
, "%s(%ld): WARNING: Draining %d leftover bytes first\n\n", __FUNCTION__
, __LINE__
, (long)ctBuffer
);
746 if (ctBuffer
> length
)
748 memcpy(buffer
, CFDataGetBytePtr(s
->_leftoverBytes
), ctBuffer
);
749 if (ctBuffer
< CFDataGetLength(s
->_leftoverBytes
))
750 CFDataReplaceBytes(s
->_leftoverBytes
, CFRangeMake(0, ctBuffer
), NULL
, 0);
752 CFRelease(s
->_leftoverBytes
);
753 s
->_leftoverBytes
= NULL
;
759 /* return whatever we've buffered */
760 if (s
->_bytesToBuffer
!= 0) {
761 CFIndex ctBuffer
= s
->_bytesToBufferPos
- s
->_bytesToBufferReadPos
;
763 /* drain our buffer first */
764 if (ctBuffer
> length
)
766 memcpy(buffer
, CFDataGetBytePtr(s
->_readBuffer
) + s
->_bytesToBufferReadPos
, ctBuffer
);
767 s
->_bytesToBufferReadPos
+= ctBuffer
;
768 if (s
->_bytesToBufferReadPos
== s
->_bytesToBufferPos
) {
769 #if defined(LOG_CFSOCKET)
770 fprintf(stdout
, "DRAINED BUFFER - SHOULD START BUFFERING AGAIN!\n");
772 s
->_bytesToBufferPos
= 0;
773 s
->_bytesToBufferReadPos
= 0;
776 #if defined(LOG_CFSOCKET)
777 fprintf(stdout
, "SLURPED %d BYTES FROM BUFFER %d LEFT TO READ!\n", ctBuffer
, length
);
784 /* nothing buffered, or no buffer selected */
786 /* Did we get an error on a previous read (or buffered read)? */
787 if (s
->_bufferedReadError
!= 0) {
788 #if defined(LOG_CFSOCKET)
789 fprintf(stdout
, "RETURNING ERROR %d\n", s
->_bufferedReadError
);
791 *error
= s
->_bufferedReadError
;
796 /* nothing buffered, if we've hit eof, don't bother reading any more */
798 #if defined(LOG_CFSOCKET)
799 fprintf(stdout
, "RETURNING EOF\n");
806 result
= read(CFSocketGetNative(s
), buffer
, length
);
807 #if defined(LOG_CFSOCKET)
808 fprintf(stdout
, "READ %d bytes", result
);
812 /* note that we hit EOF */
814 } else if (result
< 0) {
817 /* if it wasn't EAGAIN, record it (although we shouldn't get called again) */
818 if (*error
!= EAGAIN
) {
819 s
->_bufferedReadError
= *error
;
829 Boolean
__CFSocketGetBytesAvailable(CFSocketRef s
, CFIndex
* ctBytesAvailable
)
831 CFIndex ctBuffer
= s
->_bytesToBufferPos
- s
->_bytesToBufferReadPos
;
833 *ctBytesAvailable
= ctBuffer
;
837 #if DEPLOYMENT_TARGET_WINDOWS
838 int bytesAvailable
, intLen
= sizeof(bytesAvailable
);
839 result
= getsockopt(CFSocketGetNative(s
), SOL_SOCKET
, SO_NREAD
, &bytesAvailable
, (void *)&intLen
);
841 unsigned long bytesAvailable
;
842 result
= ioctlsocket(CFSocketGetNative(s
), FIONREAD
, &bytesAvailable
);
846 *ctBytesAvailable
= (CFIndex
) bytesAvailable
;
851 #if defined(LOG_CFSOCKET)
852 static void __CFSocketWriteSocketList(CFArrayRef sockets
, CFDataRef fdSet
, Boolean onlyIfSet
) {
853 fd_set
*tempfds
= (fd_set
*)CFDataGetBytePtr(fdSet
);
855 for (idx
= 0, cnt
= CFArrayGetCount(sockets
); idx
< cnt
; idx
++) {
856 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(sockets
, idx
);
857 if (FD_ISSET(s
->_socket
, tempfds
)) {
858 fprintf(stdout
, "%d ", s
->_socket
);
859 } else if (!onlyIfSet
) {
860 fprintf(stdout
, "(%d) ", s
->_socket
);
867 __attribute__ ((noreturn
)) // mostly interesting for shutting up a warning
868 #endif /* __GNUC__ */
869 static void __CFSocketManager(void * arg
)
871 if (objc_collecting_enabled()) auto_zone_register_thread(auto_zone());
872 SInt32 nrfds
, maxnrfds
, fdentries
= 1;
874 fd_set
*exceptfds
= NULL
;
875 fd_set
*writefds
= (fd_set
*)CFAllocatorAllocate(kCFAllocatorSystemDefault
, fdentries
* sizeof(fd_mask
), 0);
876 fd_set
*readfds
= (fd_set
*)CFAllocatorAllocate(kCFAllocatorSystemDefault
, fdentries
* sizeof(fd_mask
), 0);
880 CFMutableArrayRef selectedWriteSockets
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
881 CFMutableArrayRef selectedReadSockets
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
882 CFIndex selectedWriteSocketsIndex
= 0, selectedReadSocketsIndex
= 0;
885 struct timeval
* pTimeout
= NULL
;
886 struct timeval timeBeforeSelect
;
889 __CFSpinLock(&__CFActiveSocketsLock
);
890 __CFSocketManagerIteration
++;
891 #if defined(LOG_CFSOCKET)
892 fprintf(stdout
, "socket manager iteration %lu looking at read sockets ", __CFSocketManagerIteration
);
893 __CFSocketWriteSocketList(__CFReadSockets
, __CFReadSocketsFds
, FALSE
);
894 if (0 < CFArrayGetCount(__CFWriteSockets
)) {
895 fprintf(stdout
, " and write sockets ");
896 __CFSocketWriteSocketList(__CFWriteSockets
, __CFWriteSocketsFds
, FALSE
);
898 fprintf(stdout
, "\n");
900 rfds
= __CFSocketFdGetSize(__CFReadSocketsFds
);
901 wfds
= __CFSocketFdGetSize(__CFWriteSocketsFds
);
902 maxnrfds
= __CFMax(rfds
, wfds
);
903 if (maxnrfds
> fdentries
* (int)NFDBITS
) {
904 fdentries
= (maxnrfds
+ NFDBITS
- 1) / NFDBITS
;
905 writefds
= (fd_set
*)CFAllocatorReallocate(kCFAllocatorSystemDefault
, writefds
, fdentries
* sizeof(fd_mask
), 0);
906 readfds
= (fd_set
*)CFAllocatorReallocate(kCFAllocatorSystemDefault
, readfds
, fdentries
* sizeof(fd_mask
), 0);
908 memset(writefds
, 0, fdentries
* sizeof(fd_mask
));
909 memset(readfds
, 0, fdentries
* sizeof(fd_mask
));
910 CFDataGetBytes(__CFWriteSocketsFds
, CFRangeMake(0, CFDataGetLength(__CFWriteSocketsFds
)), (UInt8
*)writefds
);
911 CFDataGetBytes(__CFReadSocketsFds
, CFRangeMake(0, CFDataGetLength(__CFReadSocketsFds
)), (UInt8
*)readfds
);
913 if (__CFReadSocketsTimeoutInvalid
) {
914 struct timeval
* minTimeout
= NULL
;
915 __CFReadSocketsTimeoutInvalid
= false;
916 #if defined(LOG_CFSOCKET)
917 fprintf(stdout
, "Figuring out which sockets have timeouts...\n");
919 CFArrayApplyFunction(__CFReadSockets
, CFRangeMake(0, CFArrayGetCount(__CFReadSockets
)), _calcMinTimeout_locked
, (void*) &minTimeout
);
921 if (minTimeout
== NULL
) {
922 #if defined(LOG_CFSOCKET)
923 fprintf(stdout
, "No one wants a timeout!\n");
927 #if defined(LOG_CFSOCKET)
928 fprintf(stdout
, "timeout will be %d, %d!\n", minTimeout
->tv_sec
, minTimeout
->tv_usec
);
936 #if defined(LOG_CFSOCKET)
937 fprintf(stdout
, "select will have a %d, %d timeout\n", pTimeout
->tv_sec
, pTimeout
->tv_usec
);
939 gettimeofday(&timeBeforeSelect
, NULL
);
942 __CFSpinUnlock(&__CFActiveSocketsLock
);
944 nrfds
= select(maxnrfds
, readfds
, writefds
, exceptfds
, pTimeout
);
946 #if defined(LOG_CFSOCKET)
947 fprintf(stdout
, "socket manager woke from select, ret=%ld\n", nrfds
);
951 * select returned a timeout
954 struct timeval timeAfterSelect
;
955 struct timeval deltaTime
;
956 gettimeofday(&timeAfterSelect
, NULL
);
957 /* timeBeforeSelect becomes the delta */
958 timersub(&timeAfterSelect
, &timeBeforeSelect
, &deltaTime
);
960 #if defined(LOG_CFSOCKET)
961 fprintf(stdout
, "Socket manager received timeout - kicking off expired reads (expired delta %d, %d)\n", deltaTime
.tv_sec
, deltaTime
.tv_usec
);
964 __CFSpinLock(&__CFActiveSocketsLock
);
967 cnt
= CFArrayGetCount(__CFReadSockets
);
968 for (idx
= 0; idx
< cnt
; idx
++) {
969 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(__CFReadSockets
, idx
);
970 if (timerisset(&s
->_readBufferTimeout
) || s
->_leftoverBytes
) {
971 CFSocketNativeHandle sock
= s
->_socket
;
972 // We might have an new element in __CFReadSockets that we weren't listening to,
973 // in which case we must be sure not to test a bit in the fdset that is
974 // outside our mask size.
975 Boolean sockInBounds
= (0 <= sock
&& sock
< maxnrfds
);
976 /* if this sockets timeout is less than or equal elapsed time, then signal it */
977 if (INVALID_SOCKET
!= sock
&& sockInBounds
) {
978 #if defined(LOG_CFSOCKET)
979 fprintf(stdout
, "Expiring socket %d (delta %d, %d)\n", sock
, s
->_readBufferTimeout
.tv_sec
, s
->_readBufferTimeout
.tv_usec
);
981 CFArraySetValueAtIndex(selectedReadSockets
, selectedReadSocketsIndex
, s
);
982 selectedReadSocketsIndex
++;
983 /* socket is removed from fds here, will be restored in read handling or in perform function */
984 if (!tempfds
) tempfds
= (fd_set
*)CFDataGetMutableBytePtr(__CFReadSocketsFds
);
985 FD_CLR(sock
, tempfds
);
990 __CFSpinUnlock(&__CFActiveSocketsLock
);
992 /* and below, we dispatch through the normal read dispatch mechanism */
996 SInt32 selectError
= __CFSocketLastError();
997 #if defined(LOG_CFSOCKET)
998 fprintf(stdout
, "socket manager received error %ld from select\n", selectError
);
1000 if (EBADF
== selectError
) {
1001 CFMutableArrayRef invalidSockets
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
1002 __CFSpinLock(&__CFActiveSocketsLock
);
1003 cnt
= CFArrayGetCount(__CFWriteSockets
);
1004 for (idx
= 0; idx
< cnt
; idx
++) {
1005 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(__CFWriteSockets
, idx
);
1006 if (!__CFNativeSocketIsValid(s
->_socket
)) {
1007 #if defined(LOG_CFSOCKET)
1008 fprintf(stdout
, "socket manager found write socket %d invalid\n", s
->_socket
);
1010 CFArrayAppendValue(invalidSockets
, s
);
1013 cnt
= CFArrayGetCount(__CFReadSockets
);
1014 for (idx
= 0; idx
< cnt
; idx
++) {
1015 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(__CFReadSockets
, idx
);
1016 if (!__CFNativeSocketIsValid(s
->_socket
)) {
1017 #if defined(LOG_CFSOCKET)
1018 fprintf(stdout
, "socket manager found read socket %d invalid\n", s
->_socket
);
1020 CFArrayAppendValue(invalidSockets
, s
);
1023 __CFSpinUnlock(&__CFActiveSocketsLock
);
1025 cnt
= CFArrayGetCount(invalidSockets
);
1026 for (idx
= 0; idx
< cnt
; idx
++) {
1027 CFSocketInvalidate(((CFSocketRef
)CFArrayGetValueAtIndex(invalidSockets
, idx
)));
1029 CFRelease(invalidSockets
);
1033 if (FD_ISSET(__CFWakeupSocketPair
[1], readfds
)) {
1034 recv(__CFWakeupSocketPair
[1], buffer
, sizeof(buffer
), 0);
1035 #if defined(LOG_CFSOCKET)
1036 fprintf(stdout
, "socket manager received %c on wakeup socket\n", buffer
[0]);
1039 __CFSpinLock(&__CFActiveSocketsLock
);
1041 cnt
= CFArrayGetCount(__CFWriteSockets
);
1042 for (idx
= 0; idx
< cnt
; idx
++) {
1043 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(__CFWriteSockets
, idx
);
1044 CFSocketNativeHandle sock
= s
->_socket
;
1045 // We might have an new element in __CFWriteSockets that we weren't listening to,
1046 // in which case we must be sure not to test a bit in the fdset that is
1047 // outside our mask size.
1048 Boolean sockInBounds
= (0 <= sock
&& sock
< maxnrfds
);
1049 if (INVALID_SOCKET
!= sock
&& sockInBounds
) {
1050 if (FD_ISSET(sock
, writefds
)) {
1051 CFArraySetValueAtIndex(selectedWriteSockets
, selectedWriteSocketsIndex
, s
);
1052 selectedWriteSocketsIndex
++;
1053 /* socket is removed from fds here, restored by CFSocketReschedule */
1054 if (!tempfds
) tempfds
= (fd_set
*)CFDataGetMutableBytePtr(__CFWriteSocketsFds
);
1055 FD_CLR(sock
, tempfds
);
1060 cnt
= CFArrayGetCount(__CFReadSockets
);
1061 for (idx
= 0; idx
< cnt
; idx
++) {
1062 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(__CFReadSockets
, idx
);
1063 CFSocketNativeHandle sock
= s
->_socket
;
1064 // We might have an new element in __CFReadSockets that we weren't listening to,
1065 // in which case we must be sure not to test a bit in the fdset that is
1066 // outside our mask size.
1067 Boolean sockInBounds
= (0 <= sock
&& sock
< maxnrfds
);
1068 if (INVALID_SOCKET
!= sock
&& sockInBounds
&& FD_ISSET(sock
, readfds
)) {
1069 CFArraySetValueAtIndex(selectedReadSockets
, selectedReadSocketsIndex
, s
);
1070 selectedReadSocketsIndex
++;
1071 /* socket is removed from fds here, will be restored in read handling or in perform function */
1072 if (!tempfds
) tempfds
= (fd_set
*)CFDataGetMutableBytePtr(__CFReadSocketsFds
);
1073 FD_CLR(sock
, tempfds
);
1076 __CFSpinUnlock(&__CFActiveSocketsLock
);
1078 for (idx
= 0; idx
< selectedWriteSocketsIndex
; idx
++) {
1079 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(selectedWriteSockets
, idx
);
1080 if (kCFNull
== (CFNullRef
)s
) continue;
1081 #if defined(LOG_CFSOCKET)
1082 fprintf(stdout
, "socket manager signaling socket %d for write\n", s
->_socket
);
1084 __CFSocketHandleWrite(s
, FALSE
);
1085 CFArraySetValueAtIndex(selectedWriteSockets
, idx
, kCFNull
);
1087 selectedWriteSocketsIndex
= 0;
1089 for (idx
= 0; idx
< selectedReadSocketsIndex
; idx
++) {
1090 CFSocketRef s
= (CFSocketRef
)CFArrayGetValueAtIndex(selectedReadSockets
, idx
);
1091 if (kCFNull
== (CFNullRef
)s
) continue;
1092 #if defined(LOG_CFSOCKET)
1093 fprintf(stdout
, "socket manager signaling socket %d for read\n", s
->_socket
);
1095 __CFSocketHandleRead(s
, nrfds
== 0);
1096 CFArraySetValueAtIndex(selectedReadSockets
, idx
, kCFNull
);
1098 selectedReadSocketsIndex
= 0;
1100 if (objc_collecting_enabled()) auto_zone_unregister_thread(auto_zone());
1103 static CFStringRef
__CFSocketCopyDescription(CFTypeRef cf
) {
1104 CFSocketRef s
= (CFSocketRef
)cf
;
1105 CFMutableStringRef result
;
1106 CFStringRef contextDesc
= NULL
;
1107 void *contextInfo
= NULL
;
1108 CFStringRef (*contextCopyDescription
)(const void *info
) = NULL
;
1109 result
= CFStringCreateMutable(CFGetAllocator(s
), 0);
1111 void *addr
= s
->_callout
;
1113 const char *name
= (dladdr(addr
, &info
) && info
.dli_saddr
== addr
&& info
.dli_sname
) ? info
.dli_sname
: "???";
1114 CFStringAppendFormat(result
, NULL
, CFSTR("<CFSocket %p [%p]>{valid = %s, type = %d, socket = %d, socket set count = %ld,\n callback types = 0x%x, callout = %s (%p), source = %p,\n run loops = %@,\n context = "), cf
, CFGetAllocator(s
), (__CFSocketIsValid(s
) ? "Yes" : "No"), s
->_socketType
, s
->_socket
, s
->_socketSetCount
, __CFSocketCallBackTypes(s
), name
, addr
, s
->_source0
, s
->_runLoops
);
1115 contextInfo
= s
->_context
.info
;
1116 contextCopyDescription
= s
->_context
.copyDescription
;
1117 __CFSocketUnlock(s
);
1118 if (NULL
!= contextInfo
&& NULL
!= contextCopyDescription
) {
1119 contextDesc
= (CFStringRef
)contextCopyDescription(contextInfo
);
1121 if (NULL
== contextDesc
) {
1122 contextDesc
= CFStringCreateWithFormat(CFGetAllocator(s
), NULL
, CFSTR("<CFSocket context %p>"), contextInfo
);
1124 CFStringAppend(result
, contextDesc
);
1125 CFStringAppend(result
, CFSTR("}"));
1126 CFRelease(contextDesc
);
1130 static void __CFSocketDeallocate(CFTypeRef cf
) {
1131 /* Since CFSockets are cached, we can only get here sometime after being invalidated */
1132 CFSocketRef s
= (CFSocketRef
)cf
;
1133 if (NULL
!= s
->_address
) {
1134 CFRelease(s
->_address
);
1137 if (NULL
!= s
->_readBuffer
) {
1138 CFRelease(s
->_readBuffer
);
1139 s
->_readBuffer
= NULL
;
1141 if (NULL
!= s
->_leftoverBytes
) {
1142 CFRelease(s
->_leftoverBytes
);
1143 s
->_leftoverBytes
= NULL
;
1145 timerclear(&s
->_readBufferTimeout
);
1146 s
->_bytesToBuffer
= 0;
1147 s
->_bytesToBufferPos
= 0;
1148 s
->_bytesToBufferReadPos
= 0;
1150 s
->_bufferedReadError
= 0;
1153 static const CFRuntimeClass __CFSocketClass
= {
1158 __CFSocketDeallocate
,
1162 __CFSocketCopyDescription
1165 __private_extern__
void __CFSocketInitialize(void) {
1166 __kCFSocketTypeID
= _CFRuntimeRegisterClass(&__CFSocketClass
);
1169 CFTypeID
CFSocketGetTypeID(void) {
1170 return __kCFSocketTypeID
;
1173 static CFSocketRef
_CFSocketCreateWithNative(CFAllocatorRef allocator
, CFSocketNativeHandle sock
, CFOptionFlags callBackTypes
, CFSocketCallBack callout
, const CFSocketContext
*context
, Boolean useExistingInstance
) {
1176 int typeSize
= sizeof(memory
->_socketType
);
1177 __CFSpinLock(&__CFActiveSocketsLock
);
1178 if (NULL
== __CFReadSockets
) __CFSocketInitializeSockets();
1179 __CFSpinUnlock(&__CFActiveSocketsLock
);
1180 __CFSpinLock(&__CFAllSocketsLock
);
1181 if (NULL
== __CFAllSockets
) {
1182 __CFAllSockets
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, NULL
, &kCFTypeDictionaryValueCallBacks
);
1184 if (INVALID_SOCKET
!= sock
&& CFDictionaryGetValueIfPresent(__CFAllSockets
, (void *)(uintptr_t)sock
, (const void **)&memory
)) {
1185 if (useExistingInstance
) {
1186 __CFSpinUnlock(&__CFAllSocketsLock
);
1190 #if defined(LOG_CFSOCKET)
1191 fprintf(stdout
, "useExistingInstance is FALSE, removing existing instance %d from __CFAllSockets\n", (int)memory
);
1193 __CFSpinUnlock(&__CFAllSocketsLock
);
1194 CFSocketInvalidate(memory
);
1195 __CFSpinLock(&__CFAllSocketsLock
);
1198 memory
= (CFSocketRef
)_CFRuntimeCreateInstance(allocator
, __kCFSocketTypeID
, sizeof(struct __CFSocket
) - sizeof(CFRuntimeBase
), NULL
);
1199 if (NULL
== memory
) {
1200 __CFSpinUnlock(&__CFAllSocketsLock
);
1203 __CFSocketSetCallBackTypes(memory
, callBackTypes
);
1204 if (INVALID_SOCKET
!= sock
) __CFSocketSetValid(memory
);
1205 __CFSocketUnsetWriteSignalled(memory
);
1206 __CFSocketUnsetReadSignalled(memory
);
1207 memory
->_f
.client
= ((callBackTypes
& (~kCFSocketConnectCallBack
)) & (~kCFSocketWriteCallBack
)) | kCFSocketCloseOnInvalidate
;
1208 memory
->_f
.disabled
= 0;
1209 memory
->_f
.connected
= FALSE
;
1210 memory
->_f
.writableHint
= FALSE
;
1211 memory
->_f
.closeSignaled
= FALSE
;
1212 memory
->_lock
= CFSpinLockInit
;
1213 memory
->_writeLock
= CFSpinLockInit
;
1214 memory
->_socket
= sock
;
1215 if (INVALID_SOCKET
== sock
|| 0 != getsockopt(sock
, SOL_SOCKET
, SO_TYPE
, (void *)&(memory
->_socketType
), (socklen_t
*)&typeSize
)) memory
->_socketType
= 0; // cast for WinSock bad API
1216 memory
->_errorCode
= 0;
1217 memory
->_address
= NULL
;
1218 memory
->_peerAddress
= NULL
;
1219 memory
->_socketSetCount
= 0;
1220 memory
->_source0
= NULL
;
1221 if (INVALID_SOCKET
!= sock
) {
1222 memory
->_runLoops
= CFArrayCreateMutable(allocator
, 0, NULL
);
1224 memory
->_runLoops
= NULL
;
1226 memory
->_callout
= callout
;
1227 memory
->_dataQueue
= NULL
;
1228 memory
->_addressQueue
= NULL
;
1229 memory
->_context
.info
= 0;
1230 memory
->_context
.retain
= 0;
1231 memory
->_context
.release
= 0;
1232 memory
->_context
.copyDescription
= 0;
1233 timerclear(&memory
->_readBufferTimeout
);
1234 memory
->_readBuffer
= NULL
;
1235 memory
->_bytesToBuffer
= 0;
1236 memory
->_bytesToBufferPos
= 0;
1237 memory
->_bytesToBufferReadPos
= 0;
1238 memory
->_atEOF
= false;
1239 memory
->_bufferedReadError
= 0;
1240 memory
->_leftoverBytes
= NULL
;
1242 if (INVALID_SOCKET
!= sock
) CFDictionaryAddValue(__CFAllSockets
, (void *)(uintptr_t)sock
, memory
);
1243 __CFSpinUnlock(&__CFAllSocketsLock
);
1244 if (NULL
!= context
) {
1245 void *contextInfo
= context
->retain
? (void *)context
->retain(context
->info
) : context
->info
;
1246 __CFSocketLock(memory
);
1247 memory
->_context
.retain
= context
->retain
;
1248 memory
->_context
.release
= context
->release
;
1249 memory
->_context
.copyDescription
= context
->copyDescription
;
1250 memory
->_context
.info
= contextInfo
;
1251 __CFSocketUnlock(memory
);
1256 CFSocketRef
CFSocketCreateWithNative(CFAllocatorRef allocator
, CFSocketNativeHandle sock
, CFOptionFlags callBackTypes
, CFSocketCallBack callout
, const CFSocketContext
*context
) {
1257 return _CFSocketCreateWithNative(allocator
, sock
, callBackTypes
, callout
, context
, TRUE
);
1260 void CFSocketInvalidate(CFSocketRef s
) {
1262 UInt32 previousSocketManagerIteration
;
1263 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1264 #if defined(LOG_CFSOCKET)
1265 fprintf(stdout
, "invalidating socket %d with flags 0x%x disabled 0x%x connected 0x%x\n", s
->_socket
, s
->_f
.client
, s
->_f
.disabled
, s
->_f
.connected
);
1268 __CFSpinLock(&__CFAllSocketsLock
);
1270 if (__CFSocketIsValid(s
)) {
1272 CFRunLoopSourceRef source0
;
1273 void *contextInfo
= NULL
;
1274 void (*contextRelease
)(const void *info
) = NULL
;
1275 __CFSocketUnsetValid(s
);
1276 __CFSocketUnsetWriteSignalled(s
);
1277 __CFSocketUnsetReadSignalled(s
);
1278 __CFSpinLock(&__CFActiveSocketsLock
);
1279 idx
= CFArrayGetFirstIndexOfValue(__CFWriteSockets
, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets
)), s
);
1281 CFArrayRemoveValueAtIndex(__CFWriteSockets
, idx
);
1282 __CFSocketClearFDForWrite(s
);
1284 // No need to clear FD's for V1 sources, since we'll just throw the whole event away
1285 idx
= CFArrayGetFirstIndexOfValue(__CFReadSockets
, CFRangeMake(0, CFArrayGetCount(__CFReadSockets
)), s
);
1287 CFArrayRemoveValueAtIndex(__CFReadSockets
, idx
);
1288 __CFSocketClearFDForRead(s
);
1290 previousSocketManagerIteration
= __CFSocketManagerIteration
;
1291 __CFSpinUnlock(&__CFActiveSocketsLock
);
1292 CFDictionaryRemoveValue(__CFAllSockets
, (void *)(uintptr_t)(s
->_socket
));
1293 if ((s
->_f
.client
& kCFSocketCloseOnInvalidate
) != 0) closesocket(s
->_socket
);
1294 s
->_socket
= INVALID_SOCKET
;
1295 if (NULL
!= s
->_peerAddress
) {
1296 CFRelease(s
->_peerAddress
);
1297 s
->_peerAddress
= NULL
;
1299 if (NULL
!= s
->_dataQueue
) {
1300 CFRelease(s
->_dataQueue
);
1301 s
->_dataQueue
= NULL
;
1303 if (NULL
!= s
->_addressQueue
) {
1304 CFRelease(s
->_addressQueue
);
1305 s
->_addressQueue
= NULL
;
1307 s
->_socketSetCount
= 0;
1308 for (idx
= CFArrayGetCount(s
->_runLoops
); idx
--;) {
1309 CFRunLoopWakeUp((CFRunLoopRef
)CFArrayGetValueAtIndex(s
->_runLoops
, idx
));
1311 CFRelease(s
->_runLoops
);
1312 s
->_runLoops
= NULL
;
1313 source0
= s
->_source0
;
1315 contextInfo
= s
->_context
.info
;
1316 contextRelease
= s
->_context
.release
;
1317 s
->_context
.info
= 0;
1318 s
->_context
.retain
= 0;
1319 s
->_context
.release
= 0;
1320 s
->_context
.copyDescription
= 0;
1321 __CFSocketUnlock(s
);
1322 if (NULL
!= contextRelease
) {
1323 contextRelease(contextInfo
);
1325 if (NULL
!= source0
) {
1326 CFRunLoopSourceInvalidate(source0
);
1330 __CFSocketUnlock(s
);
1332 __CFSpinUnlock(&__CFAllSocketsLock
);
1336 Boolean
CFSocketIsValid(CFSocketRef s
) {
1338 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1339 return __CFSocketIsValid(s
);
1342 CFSocketNativeHandle
CFSocketGetNative(CFSocketRef s
) {
1344 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1348 CFDataRef
CFSocketCopyAddress(CFSocketRef s
) {
1350 CFDataRef result
= NULL
;
1351 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1353 __CFSocketEstablishAddress(s
);
1354 if (NULL
!= s
->_address
) {
1355 result
= CFRetain(s
->_address
);
1357 __CFSocketUnlock(s
);
1361 CFDataRef
CFSocketCopyPeerAddress(CFSocketRef s
) {
1363 CFDataRef result
= NULL
;
1364 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1366 __CFSocketEstablishPeerAddress(s
);
1367 if (NULL
!= s
->_peerAddress
) {
1368 result
= CFRetain(s
->_peerAddress
);
1370 __CFSocketUnlock(s
);
1374 void CFSocketGetContext(CFSocketRef s
, CFSocketContext
*context
) {
1376 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1377 CFAssert1(0 == context
->version
, __kCFLogAssertion
, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__
);
1378 *context
= s
->_context
;
1381 CFOptionFlags
CFSocketGetSocketFlags(CFSocketRef s
) {
1383 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1384 return s
->_f
.client
;
1387 void CFSocketSetSocketFlags(CFSocketRef s
, CFOptionFlags flags
) {
1389 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1391 #if defined(LOG_CFSOCKET)
1392 fprintf(stdout
, "setting flags for socket %d, from 0x%x to 0x%lx\n", s
->_socket
, s
->_f
.client
, flags
);
1394 s
->_f
.client
= flags
;
1395 __CFSocketUnlock(s
);
1398 void CFSocketDisableCallBacks(CFSocketRef s
, CFOptionFlags callBackTypes
) {
1400 Boolean wakeup
= false;
1401 uint8_t readCallBackType
;
1402 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1404 if (__CFSocketIsValid(s
) && __CFSocketIsScheduled(s
)) {
1405 callBackTypes
&= __CFSocketCallBackTypes(s
);
1406 readCallBackType
= __CFSocketReadCallBackType(s
);
1407 s
->_f
.disabled
|= callBackTypes
;
1408 #if defined(LOG_CFSOCKET)
1409 fprintf(stdout
, "unscheduling socket %d with flags 0x%x disabled 0x%x connected 0x%x for types 0x%lx\n", s
->_socket
, s
->_f
.client
, s
->_f
.disabled
, s
->_f
.connected
, callBackTypes
);
1411 __CFSpinLock(&__CFActiveSocketsLock
);
1412 if ((readCallBackType
== kCFSocketAcceptCallBack
) || !__CFSocketIsConnectionOriented(s
)) s
->_f
.connected
= TRUE
;
1413 if (((callBackTypes
& kCFSocketWriteCallBack
) != 0) || (((callBackTypes
& kCFSocketConnectCallBack
) != 0) && !s
->_f
.connected
)) {
1414 if (__CFSocketClearFDForWrite(s
)) {
1415 // do not wake up the socket manager thread if all relevant write callbacks are disabled
1416 CFOptionFlags writeCallBacksAvailable
= __CFSocketCallBackTypes(s
) & (kCFSocketWriteCallBack
| kCFSocketConnectCallBack
);
1417 if (s
->_f
.connected
) writeCallBacksAvailable
&= ~kCFSocketConnectCallBack
;
1418 if ((s
->_f
.disabled
& writeCallBacksAvailable
) != writeCallBacksAvailable
) wakeup
= true;
1421 if (readCallBackType
!= kCFSocketNoCallBack
&& (callBackTypes
& readCallBackType
) != 0) {
1422 if (__CFSocketClearFDForRead(s
)) {
1423 // do not wake up the socket manager thread if callback type is read
1424 if (readCallBackType
!= kCFSocketReadCallBack
) wakeup
= true;
1427 __CFSpinUnlock(&__CFActiveSocketsLock
);
1429 __CFSocketUnlock(s
);
1430 if (wakeup
&& __CFSocketManagerThread
) {
1432 send(__CFWakeupSocketPair
[0], &c
, sizeof(c
), 0);
1436 // "force" means to clear the disabled bits set by DisableCallBacks and always reenable.
1437 // if (!force) we respect those bits, meaning they may stop us from enabling.
1438 // In addition, if !force we assume that the sockets have already been added to the
1439 // __CFReadSockets and __CFWriteSockets arrays. This is true because the callbacks start
1440 // enabled when the CFSocket is created (at which time we enable with force).
1441 // Called with SocketLock held, returns with it released!
1442 void __CFSocketEnableCallBacks(CFSocketRef s
, CFOptionFlags callBackTypes
, Boolean force
, uint8_t wakeupChar
) {
1444 Boolean wakeup
= FALSE
;
1445 if (!callBackTypes
) {
1446 __CFSocketUnlock(s
);
1449 if (__CFSocketIsValid(s
) && __CFSocketIsScheduled(s
)) {
1450 Boolean turnOnWrite
= FALSE
, turnOnConnect
= FALSE
, turnOnRead
= FALSE
;
1451 uint8_t readCallBackType
= __CFSocketReadCallBackType(s
);
1452 callBackTypes
&= __CFSocketCallBackTypes(s
);
1453 if (force
) s
->_f
.disabled
&= ~callBackTypes
;
1454 #if defined(LOG_CFSOCKET)
1455 fprintf(stdout
, "rescheduling socket %d with flags 0x%x disabled 0x%x connected 0x%x for types 0x%lx\n", s
->_socket
, s
->_f
.client
, s
->_f
.disabled
, s
->_f
.connected
, callBackTypes
);
1457 /* We will wait for connection only for connection-oriented, non-rendezvous sockets that are not already connected. Mark others as already connected. */
1458 if ((readCallBackType
== kCFSocketAcceptCallBack
) || !__CFSocketIsConnectionOriented(s
)) s
->_f
.connected
= TRUE
;
1460 // First figure out what to turn on
1461 if (s
->_f
.connected
|| (callBackTypes
& kCFSocketConnectCallBack
) == 0) {
1462 // if we want write callbacks and they're not disabled...
1463 if ((callBackTypes
& kCFSocketWriteCallBack
) != 0 && (s
->_f
.disabled
& kCFSocketWriteCallBack
) == 0) turnOnWrite
= TRUE
;
1465 // if we want connect callbacks and they're not disabled...
1466 if ((callBackTypes
& kCFSocketConnectCallBack
) != 0 && (s
->_f
.disabled
& kCFSocketConnectCallBack
) == 0) turnOnConnect
= TRUE
;
1468 // if we want read callbacks and they're not disabled...
1469 if (readCallBackType
!= kCFSocketNoCallBack
&& (callBackTypes
& readCallBackType
) != 0 && (s
->_f
.disabled
& kCFSocketReadCallBack
) == 0) turnOnRead
= TRUE
;
1471 // Now turn on the callbacks we've determined that we want on
1472 if (turnOnRead
|| turnOnWrite
|| turnOnConnect
) {
1473 __CFSpinLock(&__CFActiveSocketsLock
);
1474 if (turnOnWrite
|| turnOnConnect
) {
1476 SInt32 idx
= CFArrayGetFirstIndexOfValue(__CFWriteSockets
, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets
)), s
);
1477 if (kCFNotFound
== idx
) CFArrayAppendValue(__CFWriteSockets
, s
);
1479 if (__CFSocketSetFDForWrite(s
)) wakeup
= true;
1483 SInt32 idx
= CFArrayGetFirstIndexOfValue(__CFReadSockets
, CFRangeMake(0, CFArrayGetCount(__CFReadSockets
)), s
);
1484 if (kCFNotFound
== idx
) CFArrayAppendValue(__CFReadSockets
, s
);
1486 if (__CFSocketSetFDForRead(s
)) wakeup
= true;
1488 if (wakeup
&& NULL
== __CFSocketManagerThread
) __CFSocketManagerThread
= __CFStartSimpleThread(__CFSocketManager
, 0);
1489 __CFSpinUnlock(&__CFActiveSocketsLock
);
1492 __CFSocketUnlock(s
);
1493 if (wakeup
) send(__CFWakeupSocketPair
[0], &wakeupChar
, sizeof(wakeupChar
), 0);
1496 void CFSocketEnableCallBacks(CFSocketRef s
, CFOptionFlags callBackTypes
) {
1498 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1500 __CFSocketEnableCallBacks(s
, callBackTypes
, TRUE
, 'r');
1503 static void __CFSocketSchedule(void *info
, CFRunLoopRef rl
, CFStringRef mode
) {
1504 CFSocketRef s
= info
;
1506 //??? also need to arrange delivery of all pending data
1507 if (__CFSocketIsValid(s
)) {
1508 CFArrayAppendValue(s
->_runLoops
, rl
);
1509 s
->_socketSetCount
++;
1510 // Since the v0 source is listened to on the SocketMgr thread, no matter how many modes it
1511 // is added to we just need to enable it there once (and _socketSetCount gives us a refCount
1512 // to know when we can finally disable it).
1513 if (1 == s
->_socketSetCount
) {
1514 #if defined(LOG_CFSOCKET)
1515 fprintf(stdout
, "scheduling socket %d\n", s
->_socket
);
1517 __CFSocketEnableCallBacks(s
, __CFSocketCallBackTypes(s
), TRUE
, 's'); // unlocks s
1519 __CFSocketUnlock(s
);
1521 __CFSocketUnlock(s
);
1524 static void __CFSocketCancel(void *info
, CFRunLoopRef rl
, CFStringRef mode
) {
1525 CFSocketRef s
= info
;
1528 s
->_socketSetCount
--;
1529 if (0 == s
->_socketSetCount
) {
1530 __CFSpinLock(&__CFActiveSocketsLock
);
1531 idx
= CFArrayGetFirstIndexOfValue(__CFWriteSockets
, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets
)), s
);
1533 CFArrayRemoveValueAtIndex(__CFWriteSockets
, idx
);
1534 __CFSocketClearFDForWrite(s
);
1536 idx
= CFArrayGetFirstIndexOfValue(__CFReadSockets
, CFRangeMake(0, CFArrayGetCount(__CFReadSockets
)), s
);
1538 CFArrayRemoveValueAtIndex(__CFReadSockets
, idx
);
1539 __CFSocketClearFDForRead(s
);
1541 __CFSpinUnlock(&__CFActiveSocketsLock
);
1543 if (NULL
!= s
->_runLoops
) {
1544 idx
= CFArrayGetFirstIndexOfValue(s
->_runLoops
, CFRangeMake(0, CFArrayGetCount(s
->_runLoops
)), rl
);
1545 if (0 <= idx
) CFArrayRemoveValueAtIndex(s
->_runLoops
, idx
);
1547 __CFSocketUnlock(s
);
1550 // Note: must be called with socket lock held, then returns with it released
1551 // Used by both the v0 and v1 RunLoopSource perform routines
1552 static void __CFSocketDoCallback(CFSocketRef s
, CFDataRef data
, CFDataRef address
, CFSocketNativeHandle sock
) {
1553 CFSocketCallBack callout
= NULL
;
1554 void *contextInfo
= NULL
;
1555 SInt32 errorCode
= 0;
1556 Boolean readSignalled
= false, writeSignalled
= false, connectSignalled
= false, calledOut
= false;
1557 uint8_t readCallBackType
, callBackTypes
;
1559 callBackTypes
= __CFSocketCallBackTypes(s
);
1560 readCallBackType
= __CFSocketReadCallBackType(s
);
1561 readSignalled
= __CFSocketIsReadSignalled(s
);
1562 writeSignalled
= __CFSocketIsWriteSignalled(s
);
1563 connectSignalled
= writeSignalled
&& !s
->_f
.connected
;
1564 __CFSocketUnsetReadSignalled(s
);
1565 __CFSocketUnsetWriteSignalled(s
);
1566 callout
= s
->_callout
;
1567 contextInfo
= s
->_context
.info
;
1568 #if defined(LOG_CFSOCKET)
1569 fprintf(stdout
, "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
);
1571 if (writeSignalled
) {
1572 errorCode
= s
->_errorCode
;
1573 s
->_f
.connected
= TRUE
;
1575 __CFSocketUnlock(s
);
1576 if ((callBackTypes
& kCFSocketConnectCallBack
) != 0) {
1577 if (connectSignalled
&& (!calledOut
|| CFSocketIsValid(s
))) {
1579 #if defined(LOG_CFSOCKET)
1580 fprintf(stdout
, "perform calling out error %ld to socket %d\n", errorCode
, s
->_socket
);
1582 if (callout
) callout(s
, kCFSocketConnectCallBack
, NULL
, &errorCode
, contextInfo
);
1585 #if defined(LOG_CFSOCKET)
1586 fprintf(stdout
, "perform calling out connect to socket %d\n", s
->_socket
);
1588 if (callout
) callout(s
, kCFSocketConnectCallBack
, NULL
, NULL
, contextInfo
);
1593 if (kCFSocketDataCallBack
== readCallBackType
) {
1594 if (NULL
!= data
&& (!calledOut
|| CFSocketIsValid(s
))) {
1595 SInt32 datalen
= CFDataGetLength(data
);
1596 #if defined(LOG_CFSOCKET)
1597 fprintf(stdout
, "perform calling out data of length %ld to socket %d\n", datalen
, s
->_socket
);
1599 if (callout
) callout(s
, kCFSocketDataCallBack
, address
, data
, contextInfo
);
1601 if (0 == datalen
) CFSocketInvalidate(s
);
1603 } else if (kCFSocketAcceptCallBack
== readCallBackType
) {
1604 if (INVALID_SOCKET
!= sock
&& (!calledOut
|| CFSocketIsValid(s
))) {
1605 #if defined(LOG_CFSOCKET)
1606 fprintf(stdout
, "perform calling out accept of socket %d to socket %d\n", sock
, s
->_socket
);
1608 if (callout
) callout(s
, kCFSocketAcceptCallBack
, address
, &sock
, contextInfo
);
1611 } else if (kCFSocketReadCallBack
== readCallBackType
) {
1612 if (readSignalled
&& (!calledOut
|| CFSocketIsValid(s
))) {
1613 #if defined(LOG_CFSOCKET)
1614 fprintf(stdout
, "perform calling out read to socket %d\n", s
->_socket
);
1616 if (callout
) callout(s
, kCFSocketReadCallBack
, NULL
, NULL
, contextInfo
);
1620 if ((callBackTypes
& kCFSocketWriteCallBack
) != 0) {
1621 if (writeSignalled
&& !errorCode
&& (!calledOut
|| CFSocketIsValid(s
))) {
1622 #if defined(LOG_CFSOCKET)
1623 fprintf(stdout
, "perform calling out write to socket %d\n", s
->_socket
);
1625 if (callout
) callout(s
, kCFSocketWriteCallBack
, NULL
, NULL
, contextInfo
);
1631 static void __CFSocketPerformV0(void *info
) {
1632 CFSocketRef s
= info
;
1633 CFDataRef data
= NULL
;
1634 CFDataRef address
= NULL
;
1635 CFSocketNativeHandle sock
= INVALID_SOCKET
;
1636 uint8_t readCallBackType
, callBackTypes
;
1637 CFRunLoopRef rl
= NULL
;
1640 if (!__CFSocketIsValid(s
)) {
1641 __CFSocketUnlock(s
);
1644 callBackTypes
= __CFSocketCallBackTypes(s
);
1645 readCallBackType
= __CFSocketReadCallBackType(s
);
1646 CFOptionFlags callBacksSignalled
= 0;
1647 if (__CFSocketIsReadSignalled(s
)) callBacksSignalled
|= readCallBackType
;
1648 if (__CFSocketIsWriteSignalled(s
)) callBacksSignalled
|= kCFSocketWriteCallBack
;
1650 if (kCFSocketDataCallBack
== readCallBackType
) {
1651 if (NULL
!= s
->_dataQueue
&& 0 < CFArrayGetCount(s
->_dataQueue
)) {
1652 data
= CFArrayGetValueAtIndex(s
->_dataQueue
, 0);
1654 CFArrayRemoveValueAtIndex(s
->_dataQueue
, 0);
1655 address
= CFArrayGetValueAtIndex(s
->_addressQueue
, 0);
1657 CFArrayRemoveValueAtIndex(s
->_addressQueue
, 0);
1659 } else if (kCFSocketAcceptCallBack
== readCallBackType
) {
1660 if (NULL
!= s
->_dataQueue
&& 0 < CFArrayGetCount(s
->_dataQueue
)) {
1661 sock
= (CFSocketNativeHandle
)(uintptr_t)CFArrayGetValueAtIndex(s
->_dataQueue
, 0);
1662 CFArrayRemoveValueAtIndex(s
->_dataQueue
, 0);
1663 address
= CFArrayGetValueAtIndex(s
->_addressQueue
, 0);
1665 CFArrayRemoveValueAtIndex(s
->_addressQueue
, 0);
1669 __CFSocketDoCallback(s
, data
, address
, sock
); // does __CFSocketUnlock(s)
1670 if (NULL
!= data
) CFRelease(data
);
1671 if (NULL
!= address
) CFRelease(address
);
1674 if (__CFSocketIsValid(s
) && kCFSocketNoCallBack
!= readCallBackType
) {
1675 // if there's still more data, we want to wake back up right away
1676 if ((kCFSocketDataCallBack
== readCallBackType
|| kCFSocketAcceptCallBack
== readCallBackType
) && NULL
!= s
->_dataQueue
&& 0 < CFArrayGetCount(s
->_dataQueue
)) {
1677 CFRunLoopSourceSignal(s
->_source0
);
1678 #if defined(LOG_CFSOCKET)
1679 fprintf(stdout
, "perform short-circuit signaling source for socket %d with flags 0x%x disabled 0x%x connected 0x%x\n", s
->_socket
, s
->_f
.client
, s
->_f
.disabled
, s
->_f
.connected
);
1681 rl
= __CFSocketCopyRunLoopToWakeUp(s
);
1684 // Only reenable callbacks that are auto-reenabled
1685 __CFSocketEnableCallBacks(s
, callBacksSignalled
& s
->_f
.client
, FALSE
, 'p'); // unlocks s
1688 CFRunLoopWakeUp(rl
);
1693 CFRunLoopSourceRef
CFSocketCreateRunLoopSource(CFAllocatorRef allocator
, CFSocketRef s
, CFIndex order
) {
1695 CFRunLoopSourceRef result
= NULL
;
1696 __CFGenericValidateType(s
, __kCFSocketTypeID
);
1698 if (__CFSocketIsValid(s
)) {
1699 if (NULL
== s
->_source0
) {
1700 CFRunLoopSourceContext context
;
1701 context
.version
= 0;
1703 context
.retain
= CFRetain
;
1704 context
.release
= CFRelease
;
1705 context
.copyDescription
= CFCopyDescription
;
1706 context
.equal
= CFEqual
;
1707 context
.hash
= CFHash
;
1708 context
.schedule
= __CFSocketSchedule
;
1709 context
.cancel
= __CFSocketCancel
;
1710 context
.perform
= __CFSocketPerformV0
;
1711 s
->_source0
= CFRunLoopSourceCreate(allocator
, order
, &context
);
1713 CFRetain(s
->_source0
); /* This retain is for the receiver */
1714 result
= s
->_source0
;
1716 __CFSocketUnlock(s
);
1720 #endif /* NEW_SOCKET */
1722 static CFSpinLock_t __CFSocketWriteLock_
= CFSpinLockInit
;
1723 //#warning can only send on one socket at a time now
1725 CF_INLINE
void __CFSocketWriteLock(CFSocketRef s
) {
1726 __CFSpinLock(& __CFSocketWriteLock_
);
1729 CF_INLINE
void __CFSocketWriteUnlock(CFSocketRef s
) {
1730 __CFSpinUnlock(& __CFSocketWriteLock_
);
1733 //??? need timeout, error handling, retries
1734 CFSocketError
CFSocketSendData(CFSocketRef s
, CFDataRef address
, CFDataRef data
, CFTimeInterval timeout
) {
1736 const uint8_t *dataptr
, *addrptr
= NULL
;
1737 SInt32 datalen
, addrlen
= 0, size
= 0;
1738 CFSocketNativeHandle sock
= INVALID_SOCKET
;
1740 __CFGenericValidateType(s
, CFSocketGetTypeID());
1742 addrptr
= CFDataGetBytePtr(address
);
1743 addrlen
= CFDataGetLength(address
);
1745 dataptr
= CFDataGetBytePtr(data
);
1746 datalen
= CFDataGetLength(data
);
1747 if (CFSocketIsValid(s
)) sock
= CFSocketGetNative(s
);
1748 if (INVALID_SOCKET
!= sock
) {
1750 __CFSocketWriteLock(s
);
1751 tv
.tv_sec
= (0 >= timeout
|| INT_MAX
<= timeout
) ? INT_MAX
: (int)(float)floor(timeout
);
1752 tv
.tv_usec
= (int)((timeout
- floor(timeout
)) * 1.0E6
);
1753 setsockopt(sock
, SOL_SOCKET
, SO_SNDTIMEO
, (void *)&tv
, sizeof(tv
)); // cast for WinSock bad API
1754 if (NULL
!= addrptr
&& 0 < addrlen
) {
1755 size
= sendto(sock
, dataptr
, datalen
, 0, (struct sockaddr
*)addrptr
, addrlen
);
1757 size
= send(sock
, dataptr
, datalen
, 0);
1759 #if defined(LOG_CFSOCKET)
1760 fprintf(stdout
, "wrote %ld bytes to socket %d\n", size
, sock
);
1762 __CFSocketWriteUnlock(s
);
1765 return (size
> 0) ? kCFSocketSuccess
: kCFSocketError
;
1768 CFSocketError
CFSocketSetAddress(CFSocketRef s
, CFDataRef address
) {
1770 const uint8_t *name
;
1771 SInt32 namelen
, result
= 0;
1772 __CFGenericValidateType(s
, CFSocketGetTypeID());
1773 if (NULL
== address
) return -1;
1774 if (!CFSocketIsValid(s
)) return 0;
1775 name
= CFDataGetBytePtr(address
);
1776 namelen
= CFDataGetLength(address
);
1777 if (!name
|| namelen
<= 0) return 0;
1778 CFSocketNativeHandle sock
= CFSocketGetNative(s
);
1779 result
= bind(sock
, (struct sockaddr
*)name
, namelen
);
1783 //??? should return errno
1787 CFSocketError
CFSocketConnectToAddress(CFSocketRef s
, CFDataRef address
, CFTimeInterval timeout
) {
1789 //??? need error handling, retries
1790 const uint8_t *name
;
1791 SInt32 namelen
, result
= -1, connect_err
= 0, select_err
= 0;
1792 UInt32 yes
= 1, no
= 0;
1793 Boolean wasBlocking
= true;
1795 __CFGenericValidateType(s
, CFSocketGetTypeID());
1796 if (!CFSocketIsValid(s
)) return 0;
1797 name
= CFDataGetBytePtr(address
);
1798 namelen
= CFDataGetLength(address
);
1799 if (!name
|| namelen
<= 0) return 0;
1800 CFSocketNativeHandle sock
= CFSocketGetNative(s
);
1802 SInt32 flags
= fcntl(sock
, F_GETFL
, 0);
1803 if (flags
>= 0) wasBlocking
= ((flags
& O_NONBLOCK
) == 0);
1804 if (wasBlocking
&& (timeout
> 0.0 || timeout
< 0.0)) ioctlsocket(sock
, FIONBIO
, &yes
);
1805 result
= connect(sock
, (struct sockaddr
*)name
, namelen
);
1807 connect_err
= __CFSocketLastError();
1809 #if defined(LOG_CFSOCKET)
1810 fprintf(stdout
, "connection attempt returns %ld error %ld on socket %d (flags 0x%lx blocking %d)\n", result
, connect_err
, sock
, flags
, wasBlocking
);
1812 if (EINPROGRESS
== connect_err
&& timeout
>= 0.0) {
1813 /* select on socket */
1815 int error_size
= sizeof(select_err
);
1817 CFMutableDataRef fds
= CFDataCreateMutable(kCFAllocatorSystemDefault
, 0);
1818 __CFSocketFdSet(sock
, fds
);
1819 tv
.tv_sec
= (0 >= timeout
|| INT_MAX
<= timeout
) ? INT_MAX
: (int)(float)floor(timeout
);
1820 tv
.tv_usec
= (int)((timeout
- floor(timeout
)) * 1.0E6
);
1821 nrfds
= select(__CFSocketFdGetSize(fds
), NULL
, (fd_set
*)CFDataGetMutableBytePtr(fds
), NULL
, &tv
);
1823 select_err
= __CFSocketLastError();
1825 } else if (nrfds
== 0) {
1828 if (0 != getsockopt(sock
, SOL_SOCKET
, SO_ERROR
, (void *)&select_err
, (socklen_t
*)&error_size
)) select_err
= 0;
1829 result
= (select_err
== 0) ? 0 : -1;
1832 #if defined(LOG_CFSOCKET)
1833 fprintf(stdout
, "timed connection attempt %s on socket %d, result %ld, select returns %ld error %ld\n", (result
== 0) ? "succeeds" : "fails", sock
, result
, nrfds
, select_err
);
1836 if (wasBlocking
&& (timeout
> 0.0 || timeout
< 0.0)) ioctlsocket(sock
, FIONBIO
, &no
);
1837 if (EINPROGRESS
== connect_err
&& timeout
< 0.0) {
1839 #if defined(LOG_CFSOCKET)
1840 fprintf(stdout
, "connection attempt continues in background on socket %d\n", sock
);
1844 //??? should return errno
1848 CFSocketRef
CFSocketCreate(CFAllocatorRef allocator
, SInt32 protocolFamily
, SInt32 socketType
, SInt32 protocol
, CFOptionFlags callBackTypes
, CFSocketCallBack callout
, const CFSocketContext
*context
) {
1850 CFSocketNativeHandle sock
= INVALID_SOCKET
;
1851 CFSocketRef s
= NULL
;
1852 if (0 >= protocolFamily
) protocolFamily
= PF_INET
;
1853 if (PF_INET
== protocolFamily
) {
1854 if (0 >= socketType
) socketType
= SOCK_STREAM
;
1855 if (0 >= protocol
&& SOCK_STREAM
== socketType
) protocol
= IPPROTO_TCP
;
1856 if (0 >= protocol
&& SOCK_DGRAM
== socketType
) protocol
= IPPROTO_UDP
;
1858 if (PF_LOCAL
== protocolFamily
&& 0 >= socketType
) socketType
= SOCK_STREAM
;
1859 sock
= socket(protocolFamily
, socketType
, protocol
);
1860 if (INVALID_SOCKET
!= sock
) {
1861 s
= _CFSocketCreateWithNative(allocator
, sock
, callBackTypes
, callout
, context
, FALSE
);
1866 CFSocketRef
CFSocketCreateWithSocketSignature(CFAllocatorRef allocator
, const CFSocketSignature
*signature
, CFOptionFlags callBackTypes
, CFSocketCallBack callout
, const CFSocketContext
*context
) {
1868 CFSocketRef s
= CFSocketCreate(allocator
, signature
->protocolFamily
, signature
->socketType
, signature
->protocol
, callBackTypes
, callout
, context
);
1869 if (NULL
!= s
&& (!CFSocketIsValid(s
) || kCFSocketSuccess
!= CFSocketSetAddress(s
, signature
->address
))) {
1870 CFSocketInvalidate(s
);
1877 CFSocketRef
CFSocketCreateConnectedToSocketSignature(CFAllocatorRef allocator
, const CFSocketSignature
*signature
, CFOptionFlags callBackTypes
, CFSocketCallBack callout
, const CFSocketContext
*context
, CFTimeInterval timeout
) {
1879 CFSocketRef s
= CFSocketCreate(allocator
, signature
->protocolFamily
, signature
->socketType
, signature
->protocol
, callBackTypes
, callout
, context
);
1880 if (NULL
!= s
&& (!CFSocketIsValid(s
) || kCFSocketSuccess
!= CFSocketConnectToAddress(s
, signature
->address
, timeout
))) {
1881 CFSocketInvalidate(s
);
1889 CFSocketError
*error
;
1890 CFPropertyListRef
*value
;
1892 } __CFSocketNameRegistryResponse
;
1894 static void __CFSocketHandleNameRegistryReply(CFSocketRef s
, CFSocketCallBackType type
, CFDataRef address
, const void *data
, void *info
) {
1895 CFDataRef replyData
= (CFDataRef
)data
;
1896 __CFSocketNameRegistryResponse
*response
= (__CFSocketNameRegistryResponse
*)info
;
1897 CFDictionaryRef replyDictionary
= NULL
;
1898 CFPropertyListRef value
;
1899 replyDictionary
= CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault
, replyData
, kCFPropertyListImmutable
, NULL
);
1900 if (NULL
!= response
->error
) *(response
->error
) = kCFSocketError
;
1901 if (NULL
!= replyDictionary
) {
1902 if (CFGetTypeID((CFTypeRef
)replyDictionary
) == CFDictionaryGetTypeID() && NULL
!= (value
= CFDictionaryGetValue(replyDictionary
, kCFSocketResultKey
))) {
1903 if (NULL
!= response
->error
) *(response
->error
) = kCFSocketSuccess
;
1904 if (NULL
!= response
->value
) *(response
->value
) = CFRetain(value
);
1905 if (NULL
!= response
->address
) *(response
->address
) = address
? CFDataCreateCopy(kCFAllocatorSystemDefault
, address
) : NULL
;
1907 CFRelease(replyDictionary
);
1909 CFSocketInvalidate(s
);
1912 static void __CFSocketSendNameRegistryRequest(CFSocketSignature
*signature
, CFDictionaryRef requestDictionary
, __CFSocketNameRegistryResponse
*response
, CFTimeInterval timeout
) {
1913 CFDataRef requestData
= NULL
;
1914 CFSocketContext context
= {0, response
, NULL
, NULL
, NULL
};
1915 CFSocketRef s
= NULL
;
1916 CFRunLoopSourceRef source
= NULL
;
1917 if (NULL
!= response
->error
) *(response
->error
) = kCFSocketError
;
1918 requestData
= CFPropertyListCreateXMLData(kCFAllocatorSystemDefault
, requestDictionary
);
1919 if (NULL
!= requestData
) {
1920 if (NULL
!= response
->error
) *(response
->error
) = kCFSocketTimeout
;
1921 s
= CFSocketCreateConnectedToSocketSignature(kCFAllocatorSystemDefault
, signature
, kCFSocketDataCallBack
, __CFSocketHandleNameRegistryReply
, &context
, timeout
);
1923 if (kCFSocketSuccess
== CFSocketSendData(s
, NULL
, requestData
, timeout
)) {
1924 source
= CFSocketCreateRunLoopSource(kCFAllocatorSystemDefault
, s
, 0);
1925 CFRunLoopAddSource(CFRunLoopGetCurrent(), source
, __kCFSocketRegistryRequestRunLoopMode
);
1926 CFRunLoopRunInMode(__kCFSocketRegistryRequestRunLoopMode
, timeout
, false);
1929 CFSocketInvalidate(s
);
1932 CFRelease(requestData
);
1936 static void __CFSocketValidateSignature(const CFSocketSignature
*providedSignature
, CFSocketSignature
*signature
, uint16_t defaultPortNumber
) {
1937 struct sockaddr_in sain
, *sainp
;
1938 memset(&sain
, 0, sizeof(sain
));
1939 sain
.sin_len
= sizeof(sain
);
1940 sain
.sin_family
= AF_INET
;
1941 sain
.sin_port
= htons(__CFSocketDefaultNameRegistryPortNumber
);
1942 sain
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1943 if (NULL
== providedSignature
) {
1944 signature
->protocolFamily
= PF_INET
;
1945 signature
->socketType
= SOCK_STREAM
;
1946 signature
->protocol
= IPPROTO_TCP
;
1947 signature
->address
= CFDataCreate(kCFAllocatorSystemDefault
, (uint8_t *)&sain
, sizeof(sain
));
1949 signature
->protocolFamily
= providedSignature
->protocolFamily
;
1950 signature
->socketType
= providedSignature
->socketType
;
1951 signature
->protocol
= providedSignature
->protocol
;
1952 if (0 >= signature
->protocolFamily
) signature
->protocolFamily
= PF_INET
;
1953 if (PF_INET
== signature
->protocolFamily
) {
1954 if (0 >= signature
->socketType
) signature
->socketType
= SOCK_STREAM
;
1955 if (0 >= signature
->protocol
&& SOCK_STREAM
== signature
->socketType
) signature
->protocol
= IPPROTO_TCP
;
1956 if (0 >= signature
->protocol
&& SOCK_DGRAM
== signature
->socketType
) signature
->protocol
= IPPROTO_UDP
;
1958 if (NULL
== providedSignature
->address
) {
1959 signature
->address
= CFDataCreate(kCFAllocatorSystemDefault
, (uint8_t *)&sain
, sizeof(sain
));
1961 sainp
= (struct sockaddr_in
*)CFDataGetBytePtr(providedSignature
->address
);
1962 if ((int)sizeof(struct sockaddr_in
) <= CFDataGetLength(providedSignature
->address
) && (AF_INET
== sainp
->sin_family
|| 0 == sainp
->sin_family
)) {
1963 sain
.sin_len
= sizeof(sain
);
1964 sain
.sin_family
= AF_INET
;
1965 sain
.sin_port
= sainp
->sin_port
;
1966 if (0 == sain
.sin_port
) sain
.sin_port
= htons(defaultPortNumber
);
1967 sain
.sin_addr
.s_addr
= sainp
->sin_addr
.s_addr
;
1968 if (htonl(INADDR_ANY
) == sain
.sin_addr
.s_addr
) sain
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1969 signature
->address
= CFDataCreate(kCFAllocatorSystemDefault
, (uint8_t *)&sain
, sizeof(sain
));
1971 signature
->address
= CFRetain(providedSignature
->address
);
1977 CFSocketError
CFSocketRegisterValue(const CFSocketSignature
*nameServerSignature
, CFTimeInterval timeout
, CFStringRef name
, CFPropertyListRef value
) {
1978 CFSocketSignature signature
;
1979 CFMutableDictionaryRef dictionary
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 3, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1980 CFSocketError retval
= kCFSocketError
;
1981 __CFSocketNameRegistryResponse response
= {&retval
, NULL
, NULL
};
1982 CFDictionaryAddValue(dictionary
, kCFSocketCommandKey
, kCFSocketRegisterCommand
);
1983 CFDictionaryAddValue(dictionary
, kCFSocketNameKey
, name
);
1984 if (NULL
!= value
) CFDictionaryAddValue(dictionary
, kCFSocketValueKey
, value
);
1985 __CFSocketValidateSignature(nameServerSignature
, &signature
, __CFSocketDefaultNameRegistryPortNumber
);
1986 __CFSocketSendNameRegistryRequest(&signature
, dictionary
, &response
, timeout
);
1987 CFRelease(dictionary
);
1988 CFRelease(signature
.address
);
1992 CFSocketError
CFSocketCopyRegisteredValue(const CFSocketSignature
*nameServerSignature
, CFTimeInterval timeout
, CFStringRef name
, CFPropertyListRef
*value
, CFDataRef
*serverAddress
) {
1993 CFSocketSignature signature
;
1994 CFMutableDictionaryRef dictionary
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 2, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1995 CFSocketError retval
= kCFSocketError
;
1996 __CFSocketNameRegistryResponse response
= {&retval
, value
, serverAddress
};
1997 CFDictionaryAddValue(dictionary
, kCFSocketCommandKey
, kCFSocketRetrieveCommand
);
1998 CFDictionaryAddValue(dictionary
, kCFSocketNameKey
, name
);
1999 __CFSocketValidateSignature(nameServerSignature
, &signature
, __CFSocketDefaultNameRegistryPortNumber
);
2000 __CFSocketSendNameRegistryRequest(&signature
, dictionary
, &response
, timeout
);
2001 CFRelease(dictionary
);
2002 CFRelease(signature
.address
);
2006 CFSocketError
CFSocketRegisterSocketSignature(const CFSocketSignature
*nameServerSignature
, CFTimeInterval timeout
, CFStringRef name
, const CFSocketSignature
*signature
) {
2007 CFSocketSignature validatedSignature
;
2008 CFMutableDataRef data
= NULL
;
2009 CFSocketError retval
;
2012 if (NULL
== signature
) {
2013 retval
= CFSocketUnregister(nameServerSignature
, timeout
, name
);
2015 __CFSocketValidateSignature(signature
, &validatedSignature
, 0);
2016 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
) {
2017 retval
= kCFSocketError
;
2019 data
= CFDataCreateMutable(kCFAllocatorSystemDefault
, sizeof(bytes
) + length
);
2020 bytes
[0] = validatedSignature
.protocolFamily
;
2021 bytes
[1] = validatedSignature
.socketType
;
2022 bytes
[2] = validatedSignature
.protocol
;
2024 CFDataAppendBytes(data
, bytes
, sizeof(bytes
));
2025 CFDataAppendBytes(data
, CFDataGetBytePtr(validatedSignature
.address
), length
);
2026 retval
= CFSocketRegisterValue(nameServerSignature
, timeout
, name
, data
);
2029 CFRelease(validatedSignature
.address
);
2034 CFSocketError
CFSocketCopyRegisteredSocketSignature(const CFSocketSignature
*nameServerSignature
, CFTimeInterval timeout
, CFStringRef name
, CFSocketSignature
*signature
, CFDataRef
*nameServerAddress
) {
2035 CFDataRef data
= NULL
;
2036 CFSocketSignature returnedSignature
;
2037 const uint8_t *ptr
= NULL
, *aptr
= NULL
;
2040 CFDataRef serverAddress
= NULL
;
2041 CFSocketError retval
= CFSocketCopyRegisteredValue(nameServerSignature
, timeout
, name
, (CFPropertyListRef
*)&data
, &serverAddress
);
2042 if (NULL
== data
|| CFGetTypeID(data
) != CFDataGetTypeID() || NULL
== (ptr
= CFDataGetBytePtr(data
)) || (length
= CFDataGetLength(data
)) < 4) retval
= kCFSocketError
;
2043 if (kCFSocketSuccess
== retval
&& NULL
!= signature
) {
2044 returnedSignature
.protocolFamily
= (SInt32
)*ptr
++;
2045 returnedSignature
.socketType
= (SInt32
)*ptr
++;
2046 returnedSignature
.protocol
= (SInt32
)*ptr
++;
2048 returnedSignature
.address
= CFDataCreate(kCFAllocatorSystemDefault
, ptr
, length
- 4);
2049 __CFSocketValidateSignature(&returnedSignature
, signature
, 0);
2050 CFRelease(returnedSignature
.address
);
2051 ptr
= CFDataGetBytePtr(signature
->address
);
2052 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
) {
2053 CFMutableDataRef address
= CFDataCreateMutableCopy(kCFAllocatorSystemDefault
, CFDataGetLength(signature
->address
), signature
->address
);
2054 mptr
= CFDataGetMutableBytePtr(address
);
2055 ((struct sockaddr_in
*)mptr
)->sin_addr
= ((struct sockaddr_in
*)aptr
)->sin_addr
;
2056 CFRelease(signature
->address
);
2057 signature
->address
= address
;
2059 if (NULL
!= nameServerAddress
) *nameServerAddress
= serverAddress
? CFRetain(serverAddress
) : NULL
;
2061 if (NULL
!= data
) CFRelease(data
);
2062 if (NULL
!= serverAddress
) CFRelease(serverAddress
);
2066 CFSocketError
CFSocketUnregister(const CFSocketSignature
*nameServerSignature
, CFTimeInterval timeout
, CFStringRef name
) {
2067 return CFSocketRegisterValue(nameServerSignature
, timeout
, name
, NULL
);
2070 CF_EXPORT
void CFSocketSetDefaultNameRegistryPortNumber(uint16_t port
) {
2071 __CFSocketDefaultNameRegistryPortNumber
= port
;
2074 CF_EXPORT
uint16_t CFSocketGetDefaultNameRegistryPortNumber(void) {
2075 return __CFSocketDefaultNameRegistryPortNumber
;