]> git.saurik.com Git - apple/cf.git/blob - CFSocket.c
CF-476.15.tar.gz
[apple/cf.git] / CFSocket.c
1 /*
2 * Copyright (c) 2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /* CFSocket.c
24 Copyright (c) 1999-2007 Apple Inc. All rights reserved.
25 Responsibility: Doug Davidson
26 */
27
28 #define _DARWIN_UNLIMITED_SELECT 1
29
30 #include <CoreFoundation/CFSocket.h>
31 #include <sys/types.h>
32 #include <math.h>
33 #include <limits.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 #include <libc.h>
42 #include <dlfcn.h>
43 #include "auto_stubs.h"
44
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.
47
48 //#define LOG_CFSOCKET
49
50 #define INVALID_SOCKET (CFSocketNativeHandle)(-1)
51
52 enum {
53 kCFSocketLeaveErrors = 64 // candidate for publicization in future
54 };
55
56 static uint16_t __CFSocketDefaultNameRegistryPortNumber = 2454;
57
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")
66
67 #define closesocket(a) close((a))
68 #define ioctlsocket(a,b,c) ioctl((a),(b),(c))
69
70 CF_INLINE int __CFSocketLastError(void) {
71 return thread_errno();
72 }
73
74 CF_INLINE CFIndex __CFSocketFdGetSize(CFDataRef fdSet) {
75 return NBBY * CFDataGetLength(fdSet);
76 }
77
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);
83 fd_mask *fds_bits;
84 if (sock >= numFds) {
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);
89 } else {
90 fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
91 }
92 if (!FD_ISSET(sock, (fd_set *)fds_bits)) {
93 retval = true;
94 FD_SET(sock, (fd_set *)fds_bits);
95 }
96 }
97 return retval;
98 }
99
100
101 #define NEW_SOCKET 0
102 #if NEW_SOCKET
103
104 __private_extern__ void __CFSocketInitialize(void) {}
105
106 #else
107
108 #define MAX_SOCKADDR_LEN 256
109 #define MAX_DATA_SIZE 65535
110 #define MAX_CONNECTION_ORIENTED_DATA_SIZE 32768
111
112 /* locks are to be acquired in the following order:
113 (1) __CFAllSocketsLock
114 (2) an individual CFSocket's lock
115 (3) __CFActiveSocketsLock
116 */
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 */
127
128 static CFSocketNativeHandle __CFWakeupSocketPair[2] = {INVALID_SOCKET, INVALID_SOCKET};
129 static void *__CFSocketManagerThread = NULL;
130
131 static CFTypeID __kCFSocketTypeID = _kCFRuntimeNotATypeID;
132 static void __CFSocketDoCallback(CFSocketRef s, CFDataRef data, CFDataRef address, CFSocketNativeHandle sock);
133
134 struct __CFSocket {
135 CFRuntimeBase _base;
136 struct {
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)
142 unsigned unused:13;
143 } _f;
144 CFSpinLock_t _lock;
145 CFSpinLock_t _writeLock;
146 CFSocketNativeHandle _socket; /* immutable */
147 SInt32 _socketType;
148 SInt32 _errorCode;
149 CFDataRef _address;
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;
158
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) */
164 Boolean _atEOF;
165 int _bufferedReadError;
166
167 CFMutableDataRef _leftoverBytes;
168 };
169
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. */
175
176 CF_INLINE Boolean __CFSocketIsWriteSignalled(CFSocketRef s) {
177 return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 6, 6);
178 }
179
180 CF_INLINE void __CFSocketSetWriteSignalled(CFSocketRef s) {
181 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 6, 6, 1);
182 }
183
184 CF_INLINE void __CFSocketUnsetWriteSignalled(CFSocketRef s) {
185 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 6, 6, 0);
186 }
187
188 CF_INLINE Boolean __CFSocketIsReadSignalled(CFSocketRef s) {
189 return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 5, 5);
190 }
191
192 CF_INLINE void __CFSocketSetReadSignalled(CFSocketRef s) {
193 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 5, 5, 1);
194 }
195
196 CF_INLINE void __CFSocketUnsetReadSignalled(CFSocketRef s) {
197 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 5, 5, 0);
198 }
199
200 CF_INLINE Boolean __CFSocketIsValid(CFSocketRef s) {
201 return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 4, 4);
202 }
203
204 CF_INLINE void __CFSocketSetValid(CFSocketRef s) {
205 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 4, 4, 1);
206 }
207
208 CF_INLINE void __CFSocketUnsetValid(CFSocketRef s) {
209 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 4, 4, 0);
210 }
211
212 CF_INLINE uint8_t __CFSocketCallBackTypes(CFSocketRef s) {
213 return (uint8_t)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 3, 0);
214 }
215
216 CF_INLINE uint8_t __CFSocketReadCallBackType(CFSocketRef s) {
217 return (uint8_t)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 1, 0);
218 }
219
220 CF_INLINE void __CFSocketSetCallBackTypes(CFSocketRef s, uint8_t types) {
221 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 3, 0, types & 0xF);
222 }
223
224 CF_INLINE void __CFSocketLock(CFSocketRef s) {
225 __CFSpinLock(&(s->_lock));
226 }
227
228 CF_INLINE void __CFSocketUnlock(CFSocketRef s) {
229 __CFSpinUnlock(&(s->_lock));
230 }
231
232 CF_INLINE Boolean __CFSocketIsConnectionOriented(CFSocketRef s) {
233 return (SOCK_STREAM == s->_socketType || SOCK_SEQPACKET == s->_socketType);
234 }
235
236 CF_INLINE Boolean __CFSocketIsScheduled(CFSocketRef s) {
237 return (s->_socketSetCount > 0);
238 }
239
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);
246 }
247 }
248
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);
255 }
256 }
257
258 static Boolean __CFNativeSocketIsValid(CFSocketNativeHandle sock) {
259 SInt32 flags = fcntl(sock, F_GETFL, 0);
260 return !(0 > flags && EBADF == thread_errno());
261 }
262
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);
268 fd_mask *fds_bits;
269 if (sock < numFds) {
270 fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
271 if (FD_ISSET(sock, (fd_set *)fds_bits)) {
272 retval = true;
273 FD_CLR(sock, (fd_set *)fds_bits);
274 }
275 }
276 }
277 return retval;
278 }
279
280 static SInt32 __CFSocketCreateWakeupSocketPair(void) {
281 return socketpair(PF_LOCAL, SOCK_DGRAM, 0, __CFWakeupSocketPair);
282 }
283
284
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 return __CFSocketFdSet(s->_socket, __CFReadSocketsFds);
288 }
289
290 CF_INLINE Boolean __CFSocketClearFDForRead(CFSocketRef s) {
291 return __CFSocketFdClr(s->_socket, __CFReadSocketsFds);
292 }
293
294 CF_INLINE Boolean __CFSocketSetFDForWrite(CFSocketRef s) {
295 return __CFSocketFdSet(s->_socket, __CFWriteSocketsFds);
296 }
297
298 CF_INLINE Boolean __CFSocketClearFDForWrite(CFSocketRef s) {
299 return __CFSocketFdClr(s->_socket, __CFWriteSocketsFds);
300 }
301
302
303 // CFNetwork needs to call this, especially for Win32 to get WSAStartup
304 static void __CFSocketInitializeSockets(void) {
305 __CFWriteSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
306 __CFReadSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
307 __CFWriteSocketsFds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
308 __CFReadSocketsFds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
309 zeroLengthData = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
310 if (0 > __CFSocketCreateWakeupSocketPair()) {
311 CFLog(kCFLogLevelWarning, CFSTR("*** Could not create wakeup socket pair for CFSocket!!!"));
312 } else {
313 UInt32 yes = 1;
314 /* wakeup sockets must be non-blocking */
315 ioctlsocket(__CFWakeupSocketPair[0], FIONBIO, &yes);
316 ioctlsocket(__CFWakeupSocketPair[1], FIONBIO, &yes);
317 __CFSocketFdSet(__CFWakeupSocketPair[1], __CFReadSocketsFds);
318 }
319 }
320
321 static CFRunLoopRef __CFSocketCopyRunLoopToWakeUp(CFSocketRef s) {
322 CFRunLoopRef rl = NULL;
323 SInt32 idx, cnt = CFArrayGetCount(s->_runLoops);
324 if (0 < cnt) {
325 rl = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, 0);
326 for (idx = 1; NULL != rl && idx < cnt; idx++) {
327 CFRunLoopRef value = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, idx);
328 if (value != rl) rl = NULL;
329 }
330 if (NULL == rl) { /* more than one different rl, so we must pick one */
331 /* ideally, this would be a run loop which isn't also in a
332 * signaled state for this or another source, but that's tricky;
333 * we pick one that is running in an appropriate mode for this
334 * source, and from those if possible one that is waiting; then
335 * we move this run loop to the end of the list to scramble them
336 * a bit, and always search from the front */
337 Boolean foundIt = false, foundBackup = false;
338 SInt32 foundIdx = 0;
339 for (idx = 0; !foundIt && idx < cnt; idx++) {
340 CFRunLoopRef value = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, idx);
341 CFStringRef currentMode = CFRunLoopCopyCurrentMode(value);
342 if (NULL != currentMode) {
343 if (CFRunLoopContainsSource(value, s->_source0, currentMode)) {
344 if (CFRunLoopIsWaiting(value)) {
345 foundIdx = idx;
346 foundIt = true;
347 } else if (!foundBackup) {
348 foundIdx = idx;
349 foundBackup = true;
350 }
351 }
352 CFRelease(currentMode);
353 }
354 }
355 rl = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, foundIdx);
356 CFRetain(rl);
357 CFArrayRemoveValueAtIndex(s->_runLoops, foundIdx);
358 CFArrayAppendValue(s->_runLoops, rl);
359 } else {
360 CFRetain(rl);
361 }
362 }
363 return rl;
364 }
365
366 // If callBackNow, we immediately do client callbacks, else we have to signal a v0 RunLoopSource so the
367 // callbacks can happen in another thread.
368 static void __CFSocketHandleWrite(CFSocketRef s, Boolean callBackNow) {
369 SInt32 errorCode = 0;
370 int errorSize = sizeof(errorCode);
371 CFOptionFlags writeCallBacksAvailable;
372
373 if (!CFSocketIsValid(s)) return;
374 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
375 #if defined(LOG_CFSOCKET)
376 if (errorCode) fprintf(stdout, "error %ld on socket %d\n", errorCode, s->_socket);
377 #endif /* LOG_CFSOCKET */
378 __CFSocketLock(s);
379 writeCallBacksAvailable = __CFSocketCallBackTypes(s) & (kCFSocketWriteCallBack | kCFSocketConnectCallBack);
380 if ((s->_f.client & kCFSocketConnectCallBack) != 0) writeCallBacksAvailable &= ~kCFSocketConnectCallBack;
381 if (!__CFSocketIsValid(s) || ((s->_f.disabled & writeCallBacksAvailable) == writeCallBacksAvailable)) {
382 __CFSocketUnlock(s);
383 return;
384 }
385 s->_errorCode = errorCode;
386 __CFSocketSetWriteSignalled(s);
387 #if defined(LOG_CFSOCKET)
388 fprintf(stdout, "write signaling source for socket %d\n", s->_socket);
389 #endif /* LOG_CFSOCKET */
390 if (callBackNow) {
391 __CFSocketDoCallback(s, NULL, NULL, 0);
392 } else {
393 CFRunLoopRef rl;
394 CFRunLoopSourceSignal(s->_source0);
395 rl = __CFSocketCopyRunLoopToWakeUp(s);
396 __CFSocketUnlock(s);
397 if (NULL != rl) {
398 CFRunLoopWakeUp(rl);
399 CFRelease(rl);
400 }
401 }
402 }
403
404 static void __CFSocketHandleRead(CFSocketRef s, Boolean causedByTimeout)
405 {
406 CFDataRef data = NULL, address = NULL;
407 CFSocketNativeHandle sock = INVALID_SOCKET;
408 if (!CFSocketIsValid(s)) return;
409 if (__CFSocketReadCallBackType(s) == kCFSocketDataCallBack) {
410 uint8_t bufferArray[MAX_CONNECTION_ORIENTED_DATA_SIZE], *buffer;
411 uint8_t name[MAX_SOCKADDR_LEN];
412 int namelen = sizeof(name);
413 SInt32 recvlen = 0;
414 if (__CFSocketIsConnectionOriented(s)) {
415 buffer = bufferArray;
416 recvlen = recvfrom(s->_socket, buffer, MAX_CONNECTION_ORIENTED_DATA_SIZE, 0, (struct sockaddr *)name, (socklen_t *)&namelen);
417 } else {
418 buffer = malloc(MAX_DATA_SIZE);
419 if (buffer) recvlen = recvfrom(s->_socket, buffer, MAX_DATA_SIZE, 0, (struct sockaddr *)name, (socklen_t *)&namelen);
420 }
421 #if defined(LOG_CFSOCKET)
422 fprintf(stdout, "read %ld bytes on socket %d\n", recvlen, s->_socket);
423 #endif /* LOG_CFSOCKET */
424 if (0 >= recvlen) {
425 //??? should return error if <0
426 /* zero-length data is the signal for perform to invalidate */
427 data = CFRetain(zeroLengthData);
428 } else {
429 data = CFDataCreate(CFGetAllocator(s), buffer, recvlen);
430 }
431 if (buffer && buffer != bufferArray) free(buffer);
432 __CFSocketLock(s);
433 if (!__CFSocketIsValid(s)) {
434 CFRelease(data);
435 __CFSocketUnlock(s);
436 return;
437 }
438 __CFSocketSetReadSignalled(s);
439 if (NULL != name && 0 < namelen) {
440 //??? possible optimizations: uniquing; storing last value
441 address = CFDataCreate(CFGetAllocator(s), name, namelen);
442 } else if (__CFSocketIsConnectionOriented(s)) {
443 if (NULL == s->_peerAddress) __CFSocketEstablishPeerAddress(s);
444 if (NULL != s->_peerAddress) address = CFRetain(s->_peerAddress);
445 }
446 if (NULL == address) {
447 address = CFRetain(zeroLengthData);
448 }
449 if (NULL == s->_dataQueue) {
450 s->_dataQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
451 }
452 if (NULL == s->_addressQueue) {
453 s->_addressQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
454 }
455 CFArrayAppendValue(s->_dataQueue, data);
456 CFRelease(data);
457 CFArrayAppendValue(s->_addressQueue, address);
458 CFRelease(address);
459 if (0 < recvlen
460 && (s->_f.client & kCFSocketDataCallBack) != 0 && (s->_f.disabled & kCFSocketDataCallBack) == 0
461 && __CFSocketIsScheduled(s)
462 ) {
463 __CFSpinLock(&__CFActiveSocketsLock);
464 /* restore socket to fds */
465 __CFSocketSetFDForRead(s);
466 __CFSpinUnlock(&__CFActiveSocketsLock);
467 }
468 } else if (__CFSocketReadCallBackType(s) == kCFSocketAcceptCallBack) {
469 uint8_t name[MAX_SOCKADDR_LEN];
470 int namelen = sizeof(name);
471 sock = accept(s->_socket, (struct sockaddr *)name, (socklen_t *)&namelen);
472 if (INVALID_SOCKET == sock) {
473 //??? should return error
474 return;
475 }
476 if (NULL != name && 0 < namelen) {
477 address = CFDataCreate(CFGetAllocator(s), name, namelen);
478 } else {
479 address = CFRetain(zeroLengthData);
480 }
481 __CFSocketLock(s);
482 if (!__CFSocketIsValid(s)) {
483 closesocket(sock);
484 CFRelease(address);
485 __CFSocketUnlock(s);
486 return;
487 }
488 __CFSocketSetReadSignalled(s);
489 if (NULL == s->_dataQueue) {
490 s->_dataQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, NULL);
491 }
492 if (NULL == s->_addressQueue) {
493 s->_addressQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
494 }
495 CFArrayAppendValue(s->_dataQueue, (void *)(uintptr_t)sock);
496 CFArrayAppendValue(s->_addressQueue, address);
497 CFRelease(address);
498 if ((s->_f.client & kCFSocketAcceptCallBack) != 0 && (s->_f.disabled & kCFSocketAcceptCallBack) == 0
499 && __CFSocketIsScheduled(s)
500 ) {
501 __CFSpinLock(&__CFActiveSocketsLock);
502 /* restore socket to fds */
503 __CFSocketSetFDForRead(s);
504 __CFSpinUnlock(&__CFActiveSocketsLock);
505 }
506 } else {
507 __CFSocketLock(s);
508 if (!__CFSocketIsValid(s) || (s->_f.disabled & kCFSocketReadCallBack) != 0) {
509 __CFSocketUnlock(s);
510 return;
511 }
512
513 if (causedByTimeout) {
514 #if defined(LOG_CFSOCKET)
515 fprintf(stdout, "TIMEOUT RECEIVED - WILL SIGNAL IMMEDIATELY TO FLUSH (%d buffered)\n", s->_bytesToBufferPos);
516 #endif /* LOG_CFSOCKET */
517 /* we've got a timeout, but no bytes read. Ignore the timeout. */
518 if (s->_bytesToBufferPos == 0) {
519 #if defined(LOG_CFSOCKET)
520 fprintf(stdout, "TIMEOUT - but no bytes, restoring to active set\n");
521 fflush(stdout);
522 #endif
523
524 __CFSpinLock(&__CFActiveSocketsLock);
525 /* restore socket to fds */
526 __CFSocketSetFDForRead(s);
527 __CFSpinUnlock(&__CFActiveSocketsLock);
528 __CFSocketUnlock(s);
529 return;
530 }
531 } else if (s->_bytesToBuffer != 0 && ! s->_atEOF) {
532 UInt8* base;
533 CFIndex ctRead;
534 CFIndex ctRemaining = s->_bytesToBuffer - s->_bytesToBufferPos;
535
536 /* if our buffer has room, we go ahead and buffer */
537 if (ctRemaining > 0) {
538 base = CFDataGetMutableBytePtr(s->_readBuffer);
539
540 do {
541 ctRead = read(CFSocketGetNative(s), &base[s->_bytesToBufferPos], ctRemaining);
542 } while (ctRead == -1 && errno == EAGAIN);
543
544 switch (ctRead) {
545 case -1:
546 s->_bufferedReadError = errno;
547 s->_atEOF = true;
548 #if defined(LOG_CFSOCKET)
549 fprintf(stderr, "BUFFERED READ GOT ERROR %d\n", errno);
550 #endif /* LOG_CFSOCKET */
551 break;
552
553 case 0:
554 #if defined(LOG_CFSOCKET)
555 fprintf(stdout, "DONE READING (EOF) - GOING TO SIGNAL\n");
556 #endif /* LOG_CFSOCKET */
557 s->_atEOF = true;
558 break;
559
560 default:
561 s->_bytesToBufferPos += ctRead;
562 if (s->_bytesToBuffer != s->_bytesToBufferPos) {
563 #if defined(LOG_CFSOCKET)
564 fprintf(stdout, "READ %d - need %d MORE - GOING BACK FOR MORE\n", ctRead, s->_bytesToBuffer - s->_bytesToBufferPos);
565 #endif /* LOG_CFSOCKET */
566 __CFSpinLock(&__CFActiveSocketsLock);
567 /* restore socket to fds */
568 __CFSocketSetFDForRead(s);
569 __CFSpinUnlock(&__CFActiveSocketsLock);
570 __CFSocketUnlock(s);
571 return;
572 } else {
573 #if defined(LOG_CFSOCKET)
574 fprintf(stdout, "DONE READING (read %d bytes) - GOING TO SIGNAL\n", ctRead);
575 #endif /* LOG_CFSOCKET */
576 }
577 }
578 }
579 }
580
581 __CFSocketSetReadSignalled(s);
582 }
583 #if defined(LOG_CFSOCKET)
584 fprintf(stdout, "read signaling source for socket %d\n", s->_socket);
585 #endif /* LOG_CFSOCKET */
586 CFRunLoopSourceSignal(s->_source0);
587 CFRunLoopRef rl = __CFSocketCopyRunLoopToWakeUp(s);
588 __CFSocketUnlock(s);
589 if (NULL != rl) {
590 CFRunLoopWakeUp(rl);
591 CFRelease(rl);
592 }
593 }
594
595 static struct timeval* intervalToTimeval(CFTimeInterval timeout, struct timeval* tv)
596 {
597 if (timeout == 0.0)
598 timerclear(tv);
599 else {
600 tv->tv_sec = (0 >= timeout || INT_MAX <= timeout) ? INT_MAX : (int)(float)floor(timeout);
601 tv->tv_usec = (int)((timeout - floor(timeout)) * 1.0E6);
602 }
603 return tv;
604 }
605
606 /* note that this returns a pointer to the min value, which won't have changed during
607 the dictionary apply, since we've got the active sockets lock held */
608 static void _calcMinTimeout_locked(const void* val, void* ctxt)
609 {
610 CFSocketRef s = (CFSocketRef) val;
611 struct timeval** minTime = (struct timeval**) ctxt;
612 if (timerisset(&s->_readBufferTimeout) && (*minTime == NULL || timercmp(&s->_readBufferTimeout, *minTime, <)))
613 *minTime = &s->_readBufferTimeout;
614 }
615
616 void __CFSocketSetReadBufferTimeout(CFSocketRef s, CFTimeInterval timeout)
617 {
618 struct timeval timeoutVal;
619
620 intervalToTimeval(timeout, &timeoutVal);
621
622 /* lock ordering is socket lock, activesocketslock */
623 /* activesocketslock protects our timeout calculation */
624 __CFSocketLock(s);
625 __CFSpinLock(&__CFActiveSocketsLock);
626 if (timercmp(&s->_readBufferTimeout, &timeoutVal, !=)) {
627 s->_readBufferTimeout = timeoutVal;
628 __CFReadSocketsTimeoutInvalid = true;
629 }
630 __CFSpinUnlock(&__CFActiveSocketsLock);
631 __CFSocketUnlock(s);
632 }
633
634 void __CFSocketSetReadBufferLength(CFSocketRef s, CFIndex length)
635 {
636 __CFSocketLock(s);
637 if (s->_bytesToBuffer != length) {
638 if (s->_bytesToBufferPos != 0 && s->_bytesToBufferReadPos != 0) {
639 /* As originally envisaged, you were supposed to be sure to drain the buffer before
640 * issuing another request on the socket. In practice, there seem to be times when we want to re-use
641 * the stream (or perhaps, are on our way to closing it out) and this policy doesn't work so well.
642 * So, if someone changes the buffer size while we have bytes already buffered, we put them
643 * aside and use them to satisfy any subsequent reads.
644 */
645 #if defined(DEBUG)
646 fprintf(stderr, "%s(%d): WARNING: shouldn't set read buffer length while data is still in the read buffer\n\n", __FUNCTION__, __LINE__);
647 #endif
648 if (s->_leftoverBytes == NULL)
649 s->_leftoverBytes = CFDataCreateMutable(CFGetAllocator(s), 0);
650
651 /* append the current buffered bytes over. We'll keep draining _leftoverBytes while we have them... */
652 CFDataAppendBytes(s->_leftoverBytes, CFDataGetBytePtr(s->_readBuffer) + s->_bytesToBufferPos, s->_bytesToBufferReadPos - s->_bytesToBufferPos);
653 CFRelease(s->_readBuffer);
654 s->_readBuffer = NULL;
655
656 s->_bytesToBuffer = 0;
657 s->_bytesToBufferPos = 0;
658 s->_bytesToBufferReadPos = 0;
659 }
660 if (length == 0) {
661 s->_bytesToBuffer = 0;
662 s->_bytesToBufferPos = 0;
663 s->_bytesToBufferReadPos = 0;
664 if (s->_readBuffer) {
665 CFRelease(s->_readBuffer);
666 s->_readBuffer = NULL;
667 }
668 } else {
669 /* if the buffer shrank, we can re-use the old one */
670 if (length > s->_bytesToBuffer) {
671 if (s->_readBuffer) {
672 CFRelease(s->_readBuffer);
673 s->_readBuffer = NULL;
674 }
675 }
676
677 s->_bytesToBuffer = length;
678 s->_bytesToBufferPos = 0;
679 s->_bytesToBufferReadPos = 0;
680 if (s->_readBuffer == NULL) {
681 s->_readBuffer = CFDataCreateMutable(kCFAllocatorDefault, length);
682 CFDataSetLength(s->_readBuffer, length);
683 }
684 }
685 }
686 __CFSocketUnlock(s);
687 if (length == 0)
688 __CFSocketSetReadBufferTimeout(s, 0.0);
689 }
690
691 CFIndex __CFSocketRead(CFSocketRef s, UInt8* buffer, CFIndex length, int* error)
692 {
693 #if defined(LOG_CFSOCKET)
694 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);
695 #endif /* LOG_CFSOCKET */
696
697 CFIndex result = -1;
698
699 __CFSocketLock(s);
700
701 *error = 0;
702
703 /* Any leftover buffered bytes? */
704 if (s->_leftoverBytes) {
705 CFIndex ctBuffer = CFDataGetLength(s->_leftoverBytes);
706 #if defined(DEBUG)
707 fprintf(stderr, "%s(%d): WARNING: Draining %d leftover bytes first\n\n", __FUNCTION__, __LINE__, ctBuffer);
708 #endif
709 if (ctBuffer > length)
710 ctBuffer = length;
711 memcpy(buffer, CFDataGetBytePtr(s->_leftoverBytes), ctBuffer);
712 if (ctBuffer < CFDataGetLength(s->_leftoverBytes))
713 CFDataReplaceBytes(s->_leftoverBytes, CFRangeMake(0, ctBuffer), NULL, 0);
714 else {
715 CFRelease(s->_leftoverBytes);
716 s->_leftoverBytes = NULL;
717 }
718 result = ctBuffer;
719 goto unlock;
720 }
721
722 /* return whatever we've buffered */
723 if (s->_bytesToBuffer != 0) {
724 CFIndex ctBuffer = s->_bytesToBufferPos - s->_bytesToBufferReadPos;
725 if (ctBuffer > 0) {
726 /* drain our buffer first */
727 if (ctBuffer > length)
728 ctBuffer = length;
729 memcpy(buffer, CFDataGetBytePtr(s->_readBuffer) + s->_bytesToBufferReadPos, ctBuffer);
730 s->_bytesToBufferReadPos += ctBuffer;
731 if (s->_bytesToBufferReadPos == s->_bytesToBufferPos) {
732 #if defined(LOG_CFSOCKET)
733 fprintf(stdout, "DRAINED BUFFER - SHOULD START BUFFERING AGAIN!\n");
734 #endif /* LOG_CFSOCKET */
735 s->_bytesToBufferPos = 0;
736 s->_bytesToBufferReadPos = 0;
737 }
738
739 #if defined(LOG_CFSOCKET)
740 fprintf(stdout, "SLURPED %d BYTES FROM BUFFER %d LEFT TO READ!\n", ctBuffer, length);
741 #endif /* LOG_CFSOCKET */
742
743 result = ctBuffer;
744 goto unlock;
745 }
746 }
747 /* nothing buffered, or no buffer selected */
748
749 /* Did we get an error on a previous read (or buffered read)? */
750 if (s->_bufferedReadError != 0) {
751 #if defined(LOG_CFSOCKET)
752 fprintf(stdout, "RETURNING ERROR %d\n", s->_bufferedReadError);
753 #endif /* LOG_CFSOCKET */
754 *error = s->_bufferedReadError;
755 result = -1;
756 goto unlock;
757 }
758
759 /* nothing buffered, if we've hit eof, don't bother reading any more */
760 if (s->_atEOF) {
761 #if defined(LOG_CFSOCKET)
762 fprintf(stdout, "RETURNING EOF\n");
763 #endif /* LOG_CFSOCKET */
764 result = 0;
765 goto unlock;
766 }
767
768 /* normal read */
769 result = read(CFSocketGetNative(s), buffer, length);
770 #if defined(LOG_CFSOCKET)
771 fprintf(stdout, "READ %d bytes", result);
772 #endif /* LOG_CFSOCKET */
773
774 if (result == 0) {
775 /* note that we hit EOF */
776 s->_atEOF = true;
777 } else if (result < 0) {
778 *error = errno;
779
780 /* if it wasn't EAGAIN, record it (although we shouldn't get called again) */
781 if (*error != EAGAIN) {
782 s->_bufferedReadError = *error;
783 }
784 }
785
786 unlock:
787 __CFSocketUnlock(s);
788
789 return result;
790 }
791
792 Boolean __CFSocketGetBytesAvailable(CFSocketRef s, CFIndex* ctBytesAvailable)
793 {
794 CFIndex ctBuffer = s->_bytesToBufferPos - s->_bytesToBufferReadPos;
795 if (ctBuffer != 0) {
796 *ctBytesAvailable = ctBuffer;
797 return true;
798 } else {
799 int result;
800 #if ! defined(__WIN32__)
801 int bytesAvailable, intLen = sizeof(bytesAvailable);
802 result = getsockopt(CFSocketGetNative(s), SOL_SOCKET, SO_NREAD, &bytesAvailable, (void *)&intLen);
803 #else
804 unsigned long bytesAvailable;
805 result = ioctlsocket(CFSocketGetNative(s), FIONREAD, &bytesAvailable);
806 #endif
807 if (result < 0)
808 return false;
809 *ctBytesAvailable = (CFIndex) bytesAvailable;
810 return true;
811 }
812 }
813
814 #if defined(LOG_CFSOCKET)
815 static void __CFSocketWriteSocketList(CFArrayRef sockets, CFDataRef fdSet, Boolean onlyIfSet) {
816 fd_set *tempfds = (fd_set *)CFDataGetBytePtr(fdSet);
817 SInt32 idx, cnt;
818 for (idx = 0, cnt = CFArrayGetCount(sockets); idx < cnt; idx++) {
819 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(sockets, idx);
820 if (FD_ISSET(s->_socket, tempfds)) {
821 fprintf(stdout, "%d ", s->_socket);
822 } else if (!onlyIfSet) {
823 fprintf(stdout, "(%d) ", s->_socket);
824 }
825 }
826 }
827 #endif /* LOG_CFSOCKET */
828
829 #ifdef __GNUC__
830 __attribute__ ((noreturn)) // mostly interesting for shutting up a warning
831 #endif /* __GNUC__ */
832 static void __CFSocketManager(void * arg)
833 {
834 if (objc_collecting_enabled()) auto_zone_register_thread(auto_zone());
835 SInt32 nrfds, maxnrfds, fdentries = 1;
836 SInt32 rfds, wfds;
837 fd_set *exceptfds = NULL;
838 fd_set *writefds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(fd_mask), 0);
839 fd_set *readfds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(fd_mask), 0);
840 fd_set *tempfds;
841 SInt32 idx, cnt;
842 uint8_t buffer[256];
843 CFMutableArrayRef selectedWriteSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
844 CFMutableArrayRef selectedReadSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
845 CFIndex selectedWriteSocketsIndex = 0, selectedReadSocketsIndex = 0;
846
847 struct timeval tv;
848 struct timeval* pTimeout = NULL;
849 struct timeval timeBeforeSelect;
850
851 for (;;) {
852 __CFSpinLock(&__CFActiveSocketsLock);
853 __CFSocketManagerIteration++;
854 #if defined(LOG_CFSOCKET)
855 fprintf(stdout, "socket manager iteration %lu looking at read sockets ", __CFSocketManagerIteration);
856 __CFSocketWriteSocketList(__CFReadSockets, __CFReadSocketsFds, FALSE);
857 if (0 < CFArrayGetCount(__CFWriteSockets)) {
858 fprintf(stdout, " and write sockets ");
859 __CFSocketWriteSocketList(__CFWriteSockets, __CFWriteSocketsFds, FALSE);
860 }
861 fprintf(stdout, "\n");
862 #endif /* LOG_CFSOCKET */
863 rfds = __CFSocketFdGetSize(__CFReadSocketsFds);
864 wfds = __CFSocketFdGetSize(__CFWriteSocketsFds);
865 maxnrfds = __CFMax(rfds, wfds);
866 if (maxnrfds > fdentries * (int)NFDBITS) {
867 fdentries = (maxnrfds + NFDBITS - 1) / NFDBITS;
868 writefds = (fd_set *)CFAllocatorReallocate(kCFAllocatorSystemDefault, writefds, fdentries * sizeof(fd_mask), 0);
869 readfds = (fd_set *)CFAllocatorReallocate(kCFAllocatorSystemDefault, readfds, fdentries * sizeof(fd_mask), 0);
870 }
871 memset(writefds, 0, fdentries * sizeof(fd_mask));
872 memset(readfds, 0, fdentries * sizeof(fd_mask));
873 CFDataGetBytes(__CFWriteSocketsFds, CFRangeMake(0, CFDataGetLength(__CFWriteSocketsFds)), (UInt8 *)writefds);
874 CFDataGetBytes(__CFReadSocketsFds, CFRangeMake(0, CFDataGetLength(__CFReadSocketsFds)), (UInt8 *)readfds);
875
876 if (__CFReadSocketsTimeoutInvalid) {
877 struct timeval* minTimeout = NULL;
878 __CFReadSocketsTimeoutInvalid = false;
879 #if defined(LOG_CFSOCKET)
880 fprintf(stdout, "Figuring out which sockets have timeouts...\n");
881 #endif /* LOG_CFSOCKET */
882 CFArrayApplyFunction(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), _calcMinTimeout_locked, (void*) &minTimeout);
883
884 if (minTimeout == NULL) {
885 #if defined(LOG_CFSOCKET)
886 fprintf(stdout, "No one wants a timeout!\n");
887 #endif /* LOG_CFSOCKET */
888 pTimeout = NULL;
889 } else {
890 #if defined(LOG_CFSOCKET)
891 fprintf(stdout, "timeout will be %d, %d!\n", minTimeout->tv_sec, minTimeout->tv_usec);
892 #endif /* LOG_CFSOCKET */
893 tv = *minTimeout;
894 pTimeout = &tv;
895 }
896 }
897
898 if (pTimeout) {
899 #if defined(LOG_CFSOCKET)
900 fprintf(stdout, "select will have a %d, %d timeout\n", pTimeout->tv_sec, pTimeout->tv_usec);
901 #endif /* LOG_CFSOCKET */
902 gettimeofday(&timeBeforeSelect, NULL);
903 }
904
905 __CFSpinUnlock(&__CFActiveSocketsLock);
906
907 nrfds = select(maxnrfds, readfds, writefds, exceptfds, pTimeout);
908
909 #if defined(LOG_CFSOCKET)
910 fprintf(stdout, "socket manager woke from select, ret=%ld\n", nrfds);
911 #endif /* LOG_CFSOCKET */
912
913 /*
914 * select returned a timeout
915 */
916 if (0 == nrfds) {
917 struct timeval timeAfterSelect;
918 struct timeval deltaTime;
919 gettimeofday(&timeAfterSelect, NULL);
920 /* timeBeforeSelect becomes the delta */
921 timersub(&timeAfterSelect, &timeBeforeSelect, &deltaTime);
922
923 #if defined(LOG_CFSOCKET)
924 fprintf(stdout, "Socket manager received timeout - kicking off expired reads (expired delta %d, %d)\n", deltaTime.tv_sec, deltaTime.tv_usec);
925 #endif /* LOG_CFSOCKET */
926
927 __CFSpinLock(&__CFActiveSocketsLock);
928
929 tempfds = NULL;
930 cnt = CFArrayGetCount(__CFReadSockets);
931 for (idx = 0; idx < cnt; idx++) {
932 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx);
933 if (timerisset(&s->_readBufferTimeout)) {
934 CFSocketNativeHandle sock = s->_socket;
935 // We might have an new element in __CFReadSockets that we weren't listening to,
936 // in which case we must be sure not to test a bit in the fdset that is
937 // outside our mask size.
938 Boolean sockInBounds = (0 <= sock && sock < maxnrfds);
939 /* if this sockets timeout is less than or equal elapsed time, then signal it */
940 if (INVALID_SOCKET != sock && sockInBounds && timercmp(&s->_readBufferTimeout, &deltaTime, <=)) {
941 #if defined(LOG_CFSOCKET)
942 fprintf(stdout, "Expiring socket %d (delta %d, %d)\n", sock, s->_readBufferTimeout.tv_sec, s->_readBufferTimeout.tv_usec);
943 #endif /* LOG_CFSOCKET */
944 CFArraySetValueAtIndex(selectedReadSockets, selectedReadSocketsIndex, s);
945 selectedReadSocketsIndex++;
946 /* socket is removed from fds here, will be restored in read handling or in perform function */
947 if (!tempfds) tempfds = (fd_set *)CFDataGetMutableBytePtr(__CFReadSocketsFds);
948 FD_CLR(sock, tempfds);
949 }
950 }
951 }
952
953 __CFSpinUnlock(&__CFActiveSocketsLock);
954
955 /* and below, we dispatch through the normal read dispatch mechanism */
956 }
957
958 if (0 > nrfds) {
959 SInt32 selectError = __CFSocketLastError();
960 #if defined(LOG_CFSOCKET)
961 fprintf(stdout, "socket manager received error %ld from select\n", selectError);
962 #endif /* LOG_CFSOCKET */
963 if (EBADF == selectError) {
964 CFMutableArrayRef invalidSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
965 __CFSpinLock(&__CFActiveSocketsLock);
966 cnt = CFArrayGetCount(__CFWriteSockets);
967 for (idx = 0; idx < cnt; idx++) {
968 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFWriteSockets, idx);
969 if (!__CFNativeSocketIsValid(s->_socket)) {
970 #if defined(LOG_CFSOCKET)
971 fprintf(stdout, "socket manager found write socket %d invalid\n", s->_socket);
972 #endif /* LOG_CFSOCKET */
973 CFArrayAppendValue(invalidSockets, s);
974 }
975 }
976 cnt = CFArrayGetCount(__CFReadSockets);
977 for (idx = 0; idx < cnt; idx++) {
978 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx);
979 if (!__CFNativeSocketIsValid(s->_socket)) {
980 #if defined(LOG_CFSOCKET)
981 fprintf(stdout, "socket manager found read socket %d invalid\n", s->_socket);
982 #endif /* LOG_CFSOCKET */
983 CFArrayAppendValue(invalidSockets, s);
984 }
985 }
986 __CFSpinUnlock(&__CFActiveSocketsLock);
987
988 cnt = CFArrayGetCount(invalidSockets);
989 for (idx = 0; idx < cnt; idx++) {
990 CFSocketInvalidate(((CFSocketRef)CFArrayGetValueAtIndex(invalidSockets, idx)));
991 }
992 CFRelease(invalidSockets);
993 }
994 continue;
995 }
996 if (FD_ISSET(__CFWakeupSocketPair[1], readfds)) {
997 recv(__CFWakeupSocketPair[1], buffer, sizeof(buffer), 0);
998 #if defined(LOG_CFSOCKET)
999 fprintf(stdout, "socket manager received %c on wakeup socket\n", buffer[0]);
1000 #endif /* LOG_CFSOCKET */
1001 }
1002 __CFSpinLock(&__CFActiveSocketsLock);
1003 tempfds = NULL;
1004 cnt = CFArrayGetCount(__CFWriteSockets);
1005 for (idx = 0; idx < cnt; idx++) {
1006 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFWriteSockets, idx);
1007 CFSocketNativeHandle sock = s->_socket;
1008 // We might have an new element in __CFWriteSockets that we weren't listening to,
1009 // in which case we must be sure not to test a bit in the fdset that is
1010 // outside our mask size.
1011 Boolean sockInBounds = (0 <= sock && sock < maxnrfds);
1012 if (INVALID_SOCKET != sock && sockInBounds) {
1013 if (FD_ISSET(sock, writefds)) {
1014 CFArraySetValueAtIndex(selectedWriteSockets, selectedWriteSocketsIndex, s);
1015 selectedWriteSocketsIndex++;
1016 /* socket is removed from fds here, restored by CFSocketReschedule */
1017 if (!tempfds) tempfds = (fd_set *)CFDataGetMutableBytePtr(__CFWriteSocketsFds);
1018 FD_CLR(sock, tempfds);
1019 }
1020 }
1021 }
1022 tempfds = NULL;
1023 cnt = CFArrayGetCount(__CFReadSockets);
1024 for (idx = 0; idx < cnt; idx++) {
1025 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx);
1026 CFSocketNativeHandle sock = s->_socket;
1027 // We might have an new element in __CFReadSockets that we weren't listening to,
1028 // in which case we must be sure not to test a bit in the fdset that is
1029 // outside our mask size.
1030 Boolean sockInBounds = (0 <= sock && sock < maxnrfds);
1031 if (INVALID_SOCKET != sock && sockInBounds && FD_ISSET(sock, readfds)) {
1032 CFArraySetValueAtIndex(selectedReadSockets, selectedReadSocketsIndex, s);
1033 selectedReadSocketsIndex++;
1034 /* socket is removed from fds here, will be restored in read handling or in perform function */
1035 if (!tempfds) tempfds = (fd_set *)CFDataGetMutableBytePtr(__CFReadSocketsFds);
1036 FD_CLR(sock, tempfds);
1037 }
1038 }
1039 __CFSpinUnlock(&__CFActiveSocketsLock);
1040
1041 for (idx = 0; idx < selectedWriteSocketsIndex; idx++) {
1042 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(selectedWriteSockets, idx);
1043 if (kCFNull == (CFNullRef)s) continue;
1044 #if defined(LOG_CFSOCKET)
1045 fprintf(stdout, "socket manager signaling socket %d for write\n", s->_socket);
1046 #endif /* LOG_CFSOCKET */
1047 __CFSocketHandleWrite(s, FALSE);
1048 CFArraySetValueAtIndex(selectedWriteSockets, idx, kCFNull);
1049 }
1050 selectedWriteSocketsIndex = 0;
1051
1052 for (idx = 0; idx < selectedReadSocketsIndex; idx++) {
1053 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(selectedReadSockets, idx);
1054 if (kCFNull == (CFNullRef)s) continue;
1055 #if defined(LOG_CFSOCKET)
1056 fprintf(stdout, "socket manager signaling socket %d for read\n", s->_socket);
1057 #endif /* LOG_CFSOCKET */
1058 __CFSocketHandleRead(s, nrfds == 0);
1059 CFArraySetValueAtIndex(selectedReadSockets, idx, kCFNull);
1060 }
1061 selectedReadSocketsIndex = 0;
1062 }
1063 if (objc_collecting_enabled()) auto_zone_unregister_thread(auto_zone());
1064 }
1065
1066 static CFStringRef __CFSocketCopyDescription(CFTypeRef cf) {
1067 CFSocketRef s = (CFSocketRef)cf;
1068 CFMutableStringRef result;
1069 CFStringRef contextDesc = NULL;
1070 void *contextInfo = NULL;
1071 CFStringRef (*contextCopyDescription)(const void *info) = NULL;
1072 result = CFStringCreateMutable(CFGetAllocator(s), 0);
1073 __CFSocketLock(s);
1074 void *addr = s->_callout;
1075 Dl_info info;
1076 const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???";
1077 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);
1078 contextInfo = s->_context.info;
1079 contextCopyDescription = s->_context.copyDescription;
1080 __CFSocketUnlock(s);
1081 if (NULL != contextInfo && NULL != contextCopyDescription) {
1082 contextDesc = (CFStringRef)contextCopyDescription(contextInfo);
1083 }
1084 if (NULL == contextDesc) {
1085 contextDesc = CFStringCreateWithFormat(CFGetAllocator(s), NULL, CFSTR("<CFSocket context %p>"), contextInfo);
1086 }
1087 CFStringAppend(result, contextDesc);
1088 CFStringAppend(result, CFSTR("}"));
1089 CFRelease(contextDesc);
1090 return result;
1091 }
1092
1093 static void __CFSocketDeallocate(CFTypeRef cf) {
1094 /* Since CFSockets are cached, we can only get here sometime after being invalidated */
1095 CFSocketRef s = (CFSocketRef)cf;
1096 if (NULL != s->_address) {
1097 CFRelease(s->_address);
1098 s->_address = NULL;
1099 }
1100 if (NULL != s->_readBuffer) {
1101 CFRelease(s->_readBuffer);
1102 s->_readBuffer = NULL;
1103 }
1104 if (NULL != s->_leftoverBytes) {
1105 CFRelease(s->_leftoverBytes);
1106 s->_leftoverBytes = NULL;
1107 }
1108 timerclear(&s->_readBufferTimeout);
1109 s->_bytesToBuffer = 0;
1110 s->_bytesToBufferPos = 0;
1111 s->_bytesToBufferReadPos = 0;
1112 s->_atEOF = true;
1113 s->_bufferedReadError = 0;
1114 }
1115
1116 static const CFRuntimeClass __CFSocketClass = {
1117 0,
1118 "CFSocket",
1119 NULL, // init
1120 NULL, // copy
1121 __CFSocketDeallocate,
1122 NULL, // equal
1123 NULL, // hash
1124 NULL, //
1125 __CFSocketCopyDescription
1126 };
1127
1128 __private_extern__ void __CFSocketInitialize(void) {
1129 __kCFSocketTypeID = _CFRuntimeRegisterClass(&__CFSocketClass);
1130 }
1131
1132 CFTypeID CFSocketGetTypeID(void) {
1133 return __kCFSocketTypeID;
1134 }
1135 static CFSocketRef _CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHandle sock, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context, Boolean useExistingInstance) {
1136 CHECK_FOR_FORK();
1137 CFSocketRef memory;
1138 int typeSize = sizeof(memory->_socketType);
1139 __CFSpinLock(&__CFActiveSocketsLock);
1140 if (NULL == __CFReadSockets) __CFSocketInitializeSockets();
1141 __CFSpinUnlock(&__CFActiveSocketsLock);
1142 __CFSpinLock(&__CFAllSocketsLock);
1143 if (NULL == __CFAllSockets) {
1144 __CFAllSockets = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
1145 }
1146 if (INVALID_SOCKET != sock && CFDictionaryGetValueIfPresent(__CFAllSockets, (void *)(uintptr_t)sock, (const void **)&memory)) {
1147 if (useExistingInstance) {
1148 __CFSpinUnlock(&__CFAllSocketsLock);
1149 CFRetain(memory);
1150 return memory;
1151 } else {
1152 #if defined(LOG_CFSOCKET)
1153 fprintf(stdout, "useExistingInstance is FALSE, removing existing instance %d from __CFAllSockets\n", (int)memory);
1154 #endif /* LOG_CFSOCKET */
1155 __CFSpinUnlock(&__CFAllSocketsLock);
1156 CFSocketInvalidate(memory);
1157 __CFSpinLock(&__CFAllSocketsLock);
1158 }
1159 }
1160 memory = (CFSocketRef)_CFRuntimeCreateInstance(allocator, __kCFSocketTypeID, sizeof(struct __CFSocket) - sizeof(CFRuntimeBase), NULL);
1161 if (NULL == memory) {
1162 __CFSpinUnlock(&__CFAllSocketsLock);
1163 return NULL;
1164 }
1165 __CFSocketSetCallBackTypes(memory, callBackTypes);
1166 if (INVALID_SOCKET != sock) __CFSocketSetValid(memory);
1167 __CFSocketUnsetWriteSignalled(memory);
1168 __CFSocketUnsetReadSignalled(memory);
1169 memory->_f.client = ((callBackTypes & (~kCFSocketConnectCallBack)) & (~kCFSocketWriteCallBack)) | kCFSocketCloseOnInvalidate;
1170 memory->_f.disabled = 0;
1171 memory->_f.connected = FALSE;
1172 memory->_f.writableHint = FALSE;
1173 memory->_f.closeSignaled = FALSE;
1174 memory->_lock = CFSpinLockInit;
1175 memory->_writeLock = CFSpinLockInit;
1176 memory->_socket = sock;
1177 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
1178 memory->_errorCode = 0;
1179 memory->_address = NULL;
1180 memory->_peerAddress = NULL;
1181 memory->_socketSetCount = 0;
1182 memory->_source0 = NULL;
1183 if (INVALID_SOCKET != sock) {
1184 memory->_runLoops = CFArrayCreateMutable(allocator, 0, NULL);
1185 } else {
1186 memory->_runLoops = NULL;
1187 }
1188 memory->_callout = callout;
1189 memory->_dataQueue = NULL;
1190 memory->_addressQueue = NULL;
1191 memory->_context.info = 0;
1192 memory->_context.retain = 0;
1193 memory->_context.release = 0;
1194 memory->_context.copyDescription = 0;
1195 timerclear(&memory->_readBufferTimeout);
1196 memory->_readBuffer = NULL;
1197 memory->_bytesToBuffer = 0;
1198 memory->_bytesToBufferPos = 0;
1199 memory->_bytesToBufferReadPos = 0;
1200 memory->_atEOF = false;
1201 memory->_bufferedReadError = 0;
1202
1203 if (INVALID_SOCKET != sock) CFDictionaryAddValue(__CFAllSockets, (void *)(uintptr_t)sock, memory);
1204 __CFSpinUnlock(&__CFAllSocketsLock);
1205 if (NULL != context) {
1206 void *contextInfo = context->retain ? (void *)context->retain(context->info) : context->info;
1207 __CFSocketLock(memory);
1208 memory->_context.retain = context->retain;
1209 memory->_context.release = context->release;
1210 memory->_context.copyDescription = context->copyDescription;
1211 memory->_context.info = contextInfo;
1212 __CFSocketUnlock(memory);
1213 }
1214 return memory;
1215 }
1216
1217 CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHandle sock, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
1218 return _CFSocketCreateWithNative(allocator, sock, callBackTypes, callout, context, TRUE);
1219 }
1220
1221 void CFSocketInvalidate(CFSocketRef s) {
1222 CHECK_FOR_FORK();
1223 UInt32 previousSocketManagerIteration;
1224 __CFGenericValidateType(s, __kCFSocketTypeID);
1225 #if defined(LOG_CFSOCKET)
1226 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);
1227 #endif /* LOG_CFSOCKET */
1228 CFRetain(s);
1229 __CFSpinLock(&__CFAllSocketsLock);
1230 __CFSocketLock(s);
1231 if (__CFSocketIsValid(s)) {
1232 SInt32 idx;
1233 CFRunLoopSourceRef source0;
1234 void *contextInfo = NULL;
1235 void (*contextRelease)(const void *info) = NULL;
1236 __CFSocketUnsetValid(s);
1237 __CFSocketUnsetWriteSignalled(s);
1238 __CFSocketUnsetReadSignalled(s);
1239 __CFSpinLock(&__CFActiveSocketsLock);
1240 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
1241 if (0 <= idx) {
1242 CFArrayRemoveValueAtIndex(__CFWriteSockets, idx);
1243 __CFSocketClearFDForWrite(s);
1244 }
1245 // No need to clear FD's for V1 sources, since we'll just throw the whole event away
1246 idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
1247 if (0 <= idx) {
1248 CFArrayRemoveValueAtIndex(__CFReadSockets, idx);
1249 __CFSocketClearFDForRead(s);
1250 }
1251 previousSocketManagerIteration = __CFSocketManagerIteration;
1252 __CFSpinUnlock(&__CFActiveSocketsLock);
1253 CFDictionaryRemoveValue(__CFAllSockets, (void *)(uintptr_t)(s->_socket));
1254 if ((s->_f.client & kCFSocketCloseOnInvalidate) != 0) closesocket(s->_socket);
1255 s->_socket = INVALID_SOCKET;
1256 if (NULL != s->_peerAddress) {
1257 CFRelease(s->_peerAddress);
1258 s->_peerAddress = NULL;
1259 }
1260 if (NULL != s->_dataQueue) {
1261 CFRelease(s->_dataQueue);
1262 s->_dataQueue = NULL;
1263 }
1264 if (NULL != s->_addressQueue) {
1265 CFRelease(s->_addressQueue);
1266 s->_addressQueue = NULL;
1267 }
1268 s->_socketSetCount = 0;
1269 for (idx = CFArrayGetCount(s->_runLoops); idx--;) {
1270 CFRunLoopWakeUp((CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, idx));
1271 }
1272 CFRelease(s->_runLoops);
1273 s->_runLoops = NULL;
1274 source0 = s->_source0;
1275 s->_source0 = NULL;
1276 contextInfo = s->_context.info;
1277 contextRelease = s->_context.release;
1278 s->_context.info = 0;
1279 s->_context.retain = 0;
1280 s->_context.release = 0;
1281 s->_context.copyDescription = 0;
1282 __CFSocketUnlock(s);
1283 if (NULL != contextRelease) {
1284 contextRelease(contextInfo);
1285 }
1286 if (NULL != source0) {
1287 CFRunLoopSourceInvalidate(source0);
1288 CFRelease(source0);
1289 }
1290 } else {
1291 __CFSocketUnlock(s);
1292 }
1293 __CFSpinUnlock(&__CFAllSocketsLock);
1294 CFRelease(s);
1295 }
1296
1297 Boolean CFSocketIsValid(CFSocketRef s) {
1298 CHECK_FOR_FORK();
1299 __CFGenericValidateType(s, __kCFSocketTypeID);
1300 return __CFSocketIsValid(s);
1301 }
1302
1303 CFSocketNativeHandle CFSocketGetNative(CFSocketRef s) {
1304 CHECK_FOR_FORK();
1305 __CFGenericValidateType(s, __kCFSocketTypeID);
1306 return s->_socket;
1307 }
1308
1309 CFDataRef CFSocketCopyAddress(CFSocketRef s) {
1310 CHECK_FOR_FORK();
1311 CFDataRef result = NULL;
1312 __CFGenericValidateType(s, __kCFSocketTypeID);
1313 __CFSocketLock(s);
1314 __CFSocketEstablishAddress(s);
1315 if (NULL != s->_address) {
1316 result = CFRetain(s->_address);
1317 }
1318 __CFSocketUnlock(s);
1319 return result;
1320 }
1321
1322 CFDataRef CFSocketCopyPeerAddress(CFSocketRef s) {
1323 CHECK_FOR_FORK();
1324 CFDataRef result = NULL;
1325 __CFGenericValidateType(s, __kCFSocketTypeID);
1326 __CFSocketLock(s);
1327 __CFSocketEstablishPeerAddress(s);
1328 if (NULL != s->_peerAddress) {
1329 result = CFRetain(s->_peerAddress);
1330 }
1331 __CFSocketUnlock(s);
1332 return result;
1333 }
1334
1335 void CFSocketGetContext(CFSocketRef s, CFSocketContext *context) {
1336 CHECK_FOR_FORK();
1337 __CFGenericValidateType(s, __kCFSocketTypeID);
1338 CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__);
1339 *context = s->_context;
1340 }
1341
1342 CFOptionFlags CFSocketGetSocketFlags(CFSocketRef s) {
1343 CHECK_FOR_FORK();
1344 __CFGenericValidateType(s, __kCFSocketTypeID);
1345 return s->_f.client;
1346 }
1347
1348 void CFSocketSetSocketFlags(CFSocketRef s, CFOptionFlags flags) {
1349 CHECK_FOR_FORK();
1350 __CFGenericValidateType(s, __kCFSocketTypeID);
1351 __CFSocketLock(s);
1352 #if defined(LOG_CFSOCKET)
1353 fprintf(stdout, "setting flags for socket %d, from 0x%x to 0x%lx\n", s->_socket, s->_f.client, flags);
1354 #endif /* LOG_CFSOCKET */
1355 s->_f.client = flags;
1356 __CFSocketUnlock(s);
1357 }
1358
1359 void CFSocketDisableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) {
1360 CHECK_FOR_FORK();
1361 Boolean wakeup = false;
1362 uint8_t readCallBackType;
1363 __CFGenericValidateType(s, __kCFSocketTypeID);
1364 __CFSocketLock(s);
1365 if (__CFSocketIsValid(s) && __CFSocketIsScheduled(s)) {
1366 callBackTypes &= __CFSocketCallBackTypes(s);
1367 readCallBackType = __CFSocketReadCallBackType(s);
1368 s->_f.disabled |= callBackTypes;
1369 #if defined(LOG_CFSOCKET)
1370 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);
1371 #endif /* LOG_CFSOCKET */
1372 __CFSpinLock(&__CFActiveSocketsLock);
1373 if ((readCallBackType == kCFSocketAcceptCallBack) || !__CFSocketIsConnectionOriented(s)) s->_f.connected = TRUE;
1374 if (((callBackTypes & kCFSocketWriteCallBack) != 0) || (((callBackTypes & kCFSocketConnectCallBack) != 0) && !s->_f.connected)) {
1375 if (__CFSocketClearFDForWrite(s)) {
1376 // do not wake up the socket manager thread if all relevant write callbacks are disabled
1377 CFOptionFlags writeCallBacksAvailable = __CFSocketCallBackTypes(s) & (kCFSocketWriteCallBack | kCFSocketConnectCallBack);
1378 if (s->_f.connected) writeCallBacksAvailable &= ~kCFSocketConnectCallBack;
1379 if ((s->_f.disabled & writeCallBacksAvailable) != writeCallBacksAvailable) wakeup = true;
1380 }
1381 }
1382 if (readCallBackType != kCFSocketNoCallBack && (callBackTypes & readCallBackType) != 0) {
1383 if (__CFSocketClearFDForRead(s)) {
1384 // do not wake up the socket manager thread if callback type is read
1385 if (readCallBackType != kCFSocketReadCallBack) wakeup = true;
1386 }
1387 }
1388 __CFSpinUnlock(&__CFActiveSocketsLock);
1389 }
1390 __CFSocketUnlock(s);
1391 if (wakeup && __CFSocketManagerThread) {
1392 uint8_t c = 'u';
1393 send(__CFWakeupSocketPair[0], &c, sizeof(c), 0);
1394 }
1395 }
1396
1397 // "force" means to clear the disabled bits set by DisableCallBacks and always reenable.
1398 // if (!force) we respect those bits, meaning they may stop us from enabling.
1399 // In addition, if !force we assume that the sockets have already been added to the
1400 // __CFReadSockets and __CFWriteSockets arrays. This is true because the callbacks start
1401 // enabled when the CFSocket is created (at which time we enable with force).
1402 // Called with SocketLock held, returns with it released!
1403 void __CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes, Boolean force, uint8_t wakeupChar) {
1404 CHECK_FOR_FORK();
1405 Boolean wakeup = FALSE;
1406 if (!callBackTypes) {
1407 __CFSocketUnlock(s);
1408 return;
1409 }
1410 if (__CFSocketIsValid(s) && __CFSocketIsScheduled(s)) {
1411 Boolean turnOnWrite = FALSE, turnOnConnect = FALSE, turnOnRead = FALSE;
1412 uint8_t readCallBackType = __CFSocketReadCallBackType(s);
1413 callBackTypes &= __CFSocketCallBackTypes(s);
1414 if (force) s->_f.disabled &= ~callBackTypes;
1415 #if defined(LOG_CFSOCKET)
1416 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);
1417 #endif /* LOG_CFSOCKET */
1418 /* We will wait for connection only for connection-oriented, non-rendezvous sockets that are not already connected. Mark others as already connected. */
1419 if ((readCallBackType == kCFSocketAcceptCallBack) || !__CFSocketIsConnectionOriented(s)) s->_f.connected = TRUE;
1420
1421 // First figure out what to turn on
1422 if (s->_f.connected || (callBackTypes & kCFSocketConnectCallBack) == 0) {
1423 // if we want write callbacks and they're not disabled...
1424 if ((callBackTypes & kCFSocketWriteCallBack) != 0 && (s->_f.disabled & kCFSocketWriteCallBack) == 0) turnOnWrite = TRUE;
1425 } else {
1426 // if we want connect callbacks and they're not disabled...
1427 if ((callBackTypes & kCFSocketConnectCallBack) != 0 && (s->_f.disabled & kCFSocketConnectCallBack) == 0) turnOnConnect = TRUE;
1428 }
1429 // if we want read callbacks and they're not disabled...
1430 if (readCallBackType != kCFSocketNoCallBack && (callBackTypes & readCallBackType) != 0 && (s->_f.disabled & kCFSocketReadCallBack) == 0) turnOnRead = TRUE;
1431
1432 // Now turn on the callbacks we've determined that we want on
1433 if (turnOnRead || turnOnWrite || turnOnConnect) {
1434 __CFSpinLock(&__CFActiveSocketsLock);
1435 if (turnOnWrite || turnOnConnect) {
1436 if (force) {
1437 SInt32 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
1438 if (kCFNotFound == idx) CFArrayAppendValue(__CFWriteSockets, s);
1439 }
1440 if (__CFSocketSetFDForWrite(s)) wakeup = true;
1441 }
1442 if (turnOnRead) {
1443 if (force) {
1444 SInt32 idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
1445 if (kCFNotFound == idx) CFArrayAppendValue(__CFReadSockets, s);
1446 }
1447 if (__CFSocketSetFDForRead(s)) wakeup = true;
1448 }
1449 if (wakeup && NULL == __CFSocketManagerThread) __CFSocketManagerThread = __CFStartSimpleThread(__CFSocketManager, 0);
1450 __CFSpinUnlock(&__CFActiveSocketsLock);
1451 }
1452 }
1453 __CFSocketUnlock(s);
1454 if (wakeup) send(__CFWakeupSocketPair[0], &wakeupChar, sizeof(wakeupChar), 0);
1455 }
1456
1457 void CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) {
1458 CHECK_FOR_FORK();
1459 __CFGenericValidateType(s, __kCFSocketTypeID);
1460 __CFSocketLock(s);
1461 __CFSocketEnableCallBacks(s, callBackTypes, TRUE, 'r');
1462 }
1463
1464 static void __CFSocketSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) {
1465 CFSocketRef s = info;
1466 __CFSocketLock(s);
1467 //??? also need to arrange delivery of all pending data
1468 if (__CFSocketIsValid(s)) {
1469 CFArrayAppendValue(s->_runLoops, rl);
1470 s->_socketSetCount++;
1471 // Since the v0 source is listened to on the SocketMgr thread, no matter how many modes it
1472 // is added to we just need to enable it there once (and _socketSetCount gives us a refCount
1473 // to know when we can finally disable it).
1474 if (1 == s->_socketSetCount) {
1475 #if defined(LOG_CFSOCKET)
1476 fprintf(stdout, "scheduling socket %d\n", s->_socket);
1477 #endif /* LOG_CFSOCKET */
1478 __CFSocketEnableCallBacks(s, __CFSocketCallBackTypes(s), TRUE, 's'); // unlocks s
1479 } else
1480 __CFSocketUnlock(s);
1481 } else
1482 __CFSocketUnlock(s);
1483 }
1484
1485 static void __CFSocketCancel(void *info, CFRunLoopRef rl, CFStringRef mode) {
1486 CFSocketRef s = info;
1487 SInt32 idx;
1488 __CFSocketLock(s);
1489 s->_socketSetCount--;
1490 if (0 == s->_socketSetCount) {
1491 __CFSpinLock(&__CFActiveSocketsLock);
1492 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
1493 if (0 <= idx) {
1494 CFArrayRemoveValueAtIndex(__CFWriteSockets, idx);
1495 __CFSocketClearFDForWrite(s);
1496 }
1497 idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
1498 if (0 <= idx) {
1499 CFArrayRemoveValueAtIndex(__CFReadSockets, idx);
1500 __CFSocketClearFDForRead(s);
1501 }
1502 __CFSpinUnlock(&__CFActiveSocketsLock);
1503 }
1504 if (NULL != s->_runLoops) {
1505 idx = CFArrayGetFirstIndexOfValue(s->_runLoops, CFRangeMake(0, CFArrayGetCount(s->_runLoops)), rl);
1506 if (0 <= idx) CFArrayRemoveValueAtIndex(s->_runLoops, idx);
1507 }
1508 __CFSocketUnlock(s);
1509 }
1510
1511 // Note: must be called with socket lock held, then returns with it released
1512 // Used by both the v0 and v1 RunLoopSource perform routines
1513 static void __CFSocketDoCallback(CFSocketRef s, CFDataRef data, CFDataRef address, CFSocketNativeHandle sock) {
1514 CFSocketCallBack callout = NULL;
1515 void *contextInfo = NULL;
1516 SInt32 errorCode = 0;
1517 Boolean readSignalled = false, writeSignalled = false, connectSignalled = false, calledOut = false;
1518 uint8_t readCallBackType, callBackTypes;
1519
1520 callBackTypes = __CFSocketCallBackTypes(s);
1521 readCallBackType = __CFSocketReadCallBackType(s);
1522 readSignalled = __CFSocketIsReadSignalled(s);
1523 writeSignalled = __CFSocketIsWriteSignalled(s);
1524 connectSignalled = writeSignalled && !s->_f.connected;
1525 __CFSocketUnsetReadSignalled(s);
1526 __CFSocketUnsetWriteSignalled(s);
1527 callout = s->_callout;
1528 contextInfo = s->_context.info;
1529 #if defined(LOG_CFSOCKET)
1530 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);
1531 #endif /* LOG_CFSOCKET */
1532 if (writeSignalled) {
1533 errorCode = s->_errorCode;
1534 s->_f.connected = TRUE;
1535 }
1536 __CFSocketUnlock(s);
1537 if ((callBackTypes & kCFSocketConnectCallBack) != 0) {
1538 if (connectSignalled && (!calledOut || CFSocketIsValid(s))) {
1539 if (errorCode) {
1540 #if defined(LOG_CFSOCKET)
1541 fprintf(stdout, "perform calling out error %ld to socket %d\n", errorCode, s->_socket);
1542 #endif /* LOG_CFSOCKET */
1543 if (callout) callout(s, kCFSocketConnectCallBack, NULL, &errorCode, contextInfo);
1544 calledOut = true;
1545 } else {
1546 #if defined(LOG_CFSOCKET)
1547 fprintf(stdout, "perform calling out connect to socket %d\n", s->_socket);
1548 #endif /* LOG_CFSOCKET */
1549 if (callout) callout(s, kCFSocketConnectCallBack, NULL, NULL, contextInfo);
1550 calledOut = true;
1551 }
1552 }
1553 }
1554 if (kCFSocketDataCallBack == readCallBackType) {
1555 if (NULL != data && (!calledOut || CFSocketIsValid(s))) {
1556 SInt32 datalen = CFDataGetLength(data);
1557 #if defined(LOG_CFSOCKET)
1558 fprintf(stdout, "perform calling out data of length %ld to socket %d\n", datalen, s->_socket);
1559 #endif /* LOG_CFSOCKET */
1560 if (callout) callout(s, kCFSocketDataCallBack, address, data, contextInfo);
1561 calledOut = true;
1562 if (0 == datalen) CFSocketInvalidate(s);
1563 }
1564 } else if (kCFSocketAcceptCallBack == readCallBackType) {
1565 if (INVALID_SOCKET != sock && (!calledOut || CFSocketIsValid(s))) {
1566 #if defined(LOG_CFSOCKET)
1567 fprintf(stdout, "perform calling out accept of socket %d to socket %d\n", sock, s->_socket);
1568 #endif /* LOG_CFSOCKET */
1569 if (callout) callout(s, kCFSocketAcceptCallBack, address, &sock, contextInfo);
1570 calledOut = true;
1571 }
1572 } else if (kCFSocketReadCallBack == readCallBackType) {
1573 if (readSignalled && (!calledOut || CFSocketIsValid(s))) {
1574 #if defined(LOG_CFSOCKET)
1575 fprintf(stdout, "perform calling out read to socket %d\n", s->_socket);
1576 #endif /* LOG_CFSOCKET */
1577 if (callout) callout(s, kCFSocketReadCallBack, NULL, NULL, contextInfo);
1578 calledOut = true;
1579 }
1580 }
1581 if ((callBackTypes & kCFSocketWriteCallBack) != 0) {
1582 if (writeSignalled && !errorCode && (!calledOut || CFSocketIsValid(s))) {
1583 #if defined(LOG_CFSOCKET)
1584 fprintf(stdout, "perform calling out write to socket %d\n", s->_socket);
1585 #endif /* LOG_CFSOCKET */
1586 if (callout) callout(s, kCFSocketWriteCallBack, NULL, NULL, contextInfo);
1587 calledOut = true;
1588 }
1589 }
1590 }
1591
1592 static void __CFSocketPerformV0(void *info) {
1593 CFSocketRef s = info;
1594 CFDataRef data = NULL;
1595 CFDataRef address = NULL;
1596 CFSocketNativeHandle sock = INVALID_SOCKET;
1597 uint8_t readCallBackType, callBackTypes;
1598 CFRunLoopRef rl = NULL;
1599
1600 __CFSocketLock(s);
1601 if (!__CFSocketIsValid(s)) {
1602 __CFSocketUnlock(s);
1603 return;
1604 }
1605 callBackTypes = __CFSocketCallBackTypes(s);
1606 readCallBackType = __CFSocketReadCallBackType(s);
1607 CFOptionFlags callBacksSignalled = 0;
1608 if (__CFSocketIsReadSignalled(s)) callBacksSignalled |= readCallBackType;
1609 if (__CFSocketIsWriteSignalled(s)) callBacksSignalled |= kCFSocketWriteCallBack;
1610
1611 if (kCFSocketDataCallBack == readCallBackType) {
1612 if (NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
1613 data = CFArrayGetValueAtIndex(s->_dataQueue, 0);
1614 CFRetain(data);
1615 CFArrayRemoveValueAtIndex(s->_dataQueue, 0);
1616 address = CFArrayGetValueAtIndex(s->_addressQueue, 0);
1617 CFRetain(address);
1618 CFArrayRemoveValueAtIndex(s->_addressQueue, 0);
1619 }
1620 } else if (kCFSocketAcceptCallBack == readCallBackType) {
1621 if (NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
1622 sock = (CFSocketNativeHandle)(uintptr_t)CFArrayGetValueAtIndex(s->_dataQueue, 0);
1623 CFArrayRemoveValueAtIndex(s->_dataQueue, 0);
1624 address = CFArrayGetValueAtIndex(s->_addressQueue, 0);
1625 CFRetain(address);
1626 CFArrayRemoveValueAtIndex(s->_addressQueue, 0);
1627 }
1628 }
1629
1630 __CFSocketDoCallback(s, data, address, sock); // does __CFSocketUnlock(s)
1631 if (NULL != data) CFRelease(data);
1632 if (NULL != address) CFRelease(address);
1633
1634 __CFSocketLock(s);
1635 if (__CFSocketIsValid(s) && kCFSocketNoCallBack != readCallBackType) {
1636 // if there's still more data, we want to wake back up right away
1637 if ((kCFSocketDataCallBack == readCallBackType || kCFSocketAcceptCallBack == readCallBackType) && NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
1638 CFRunLoopSourceSignal(s->_source0);
1639 #if defined(LOG_CFSOCKET)
1640 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);
1641 #endif /* LOG_CFSOCKET */
1642 rl = __CFSocketCopyRunLoopToWakeUp(s);
1643 }
1644 }
1645 // Only reenable callbacks that are auto-reenabled
1646 __CFSocketEnableCallBacks(s, callBacksSignalled & s->_f.client, FALSE, 'p'); // unlocks s
1647
1648 if (NULL != rl) {
1649 CFRunLoopWakeUp(rl);
1650 CFRelease(rl);
1651 }
1652 }
1653
1654 CFRunLoopSourceRef CFSocketCreateRunLoopSource(CFAllocatorRef allocator, CFSocketRef s, CFIndex order) {
1655 CHECK_FOR_FORK();
1656 CFRunLoopSourceRef result = NULL;
1657 __CFGenericValidateType(s, __kCFSocketTypeID);
1658 __CFSocketLock(s);
1659 if (__CFSocketIsValid(s)) {
1660 if (NULL == s->_source0) {
1661 CFRunLoopSourceContext context;
1662 context.version = 0;
1663 context.info = s;
1664 context.retain = CFRetain;
1665 context.release = CFRelease;
1666 context.copyDescription = CFCopyDescription;
1667 context.equal = CFEqual;
1668 context.hash = CFHash;
1669 context.schedule = __CFSocketSchedule;
1670 context.cancel = __CFSocketCancel;
1671 context.perform = __CFSocketPerformV0;
1672 s->_source0 = CFRunLoopSourceCreate(allocator, order, &context);
1673 }
1674 CFRetain(s->_source0); /* This retain is for the receiver */
1675 result = s->_source0;
1676 }
1677 __CFSocketUnlock(s);
1678 return result;
1679 }
1680
1681 #endif /* NEW_SOCKET */
1682
1683 static CFSpinLock_t __CFSocketWriteLock_ = CFSpinLockInit;
1684 //#warning can only send on one socket at a time now
1685
1686 CF_INLINE void __CFSocketWriteLock(CFSocketRef s) {
1687 __CFSpinLock(& __CFSocketWriteLock_);
1688 }
1689
1690 CF_INLINE void __CFSocketWriteUnlock(CFSocketRef s) {
1691 __CFSpinUnlock(& __CFSocketWriteLock_);
1692 }
1693
1694 //??? need timeout, error handling, retries
1695 CFSocketError CFSocketSendData(CFSocketRef s, CFDataRef address, CFDataRef data, CFTimeInterval timeout) {
1696 CHECK_FOR_FORK();
1697 const uint8_t *dataptr, *addrptr = NULL;
1698 SInt32 datalen, addrlen = 0, size = 0;
1699 CFSocketNativeHandle sock = INVALID_SOCKET;
1700 struct timeval tv;
1701 __CFGenericValidateType(s, CFSocketGetTypeID());
1702 if (address) {
1703 addrptr = CFDataGetBytePtr(address);
1704 addrlen = CFDataGetLength(address);
1705 }
1706 dataptr = CFDataGetBytePtr(data);
1707 datalen = CFDataGetLength(data);
1708 if (CFSocketIsValid(s)) sock = CFSocketGetNative(s);
1709 if (INVALID_SOCKET != sock) {
1710 CFRetain(s);
1711 __CFSocketWriteLock(s);
1712 tv.tv_sec = (0 >= timeout || INT_MAX <= timeout) ? INT_MAX : (int)(float)floor(timeout);
1713 tv.tv_usec = (int)((timeout - floor(timeout)) * 1.0E6);
1714 setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, sizeof(tv)); // cast for WinSock bad API
1715 if (NULL != addrptr && 0 < addrlen) {
1716 size = sendto(sock, dataptr, datalen, 0, (struct sockaddr *)addrptr, addrlen);
1717 } else {
1718 size = send(sock, dataptr, datalen, 0);
1719 }
1720 #if defined(LOG_CFSOCKET)
1721 fprintf(stdout, "wrote %ld bytes to socket %d\n", size, sock);
1722 #endif /* LOG_CFSOCKET */
1723 __CFSocketWriteUnlock(s);
1724 CFRelease(s);
1725 }
1726 return (size > 0) ? kCFSocketSuccess : kCFSocketError;
1727 }
1728
1729 CFSocketError CFSocketSetAddress(CFSocketRef s, CFDataRef address) {
1730 CHECK_FOR_FORK();
1731 const uint8_t *name;
1732 SInt32 namelen, result = 0;
1733 __CFGenericValidateType(s, CFSocketGetTypeID());
1734 if (NULL == address) return -1;
1735 if (!CFSocketIsValid(s)) return 0;
1736 name = CFDataGetBytePtr(address);
1737 namelen = CFDataGetLength(address);
1738 if (!name || namelen <= 0) return 0;
1739 CFSocketNativeHandle sock = CFSocketGetNative(s);
1740 result = bind(sock, (struct sockaddr *)name, namelen);
1741 if (0 == result) {
1742 listen(sock, 256);
1743 }
1744 //??? should return errno
1745 return result;
1746 }
1747
1748 CFSocketError CFSocketConnectToAddress(CFSocketRef s, CFDataRef address, CFTimeInterval timeout) {
1749 CHECK_FOR_FORK();
1750 //??? need error handling, retries
1751 const uint8_t *name;
1752 SInt32 namelen, result = -1, connect_err = 0, select_err = 0;
1753 UInt32 yes = 1, no = 0;
1754 Boolean wasBlocking = true;
1755
1756 __CFGenericValidateType(s, CFSocketGetTypeID());
1757 if (!CFSocketIsValid(s)) return 0;
1758 name = CFDataGetBytePtr(address);
1759 namelen = CFDataGetLength(address);
1760 if (!name || namelen <= 0) return 0;
1761 CFSocketNativeHandle sock = CFSocketGetNative(s);
1762 {
1763 SInt32 flags = fcntl(sock, F_GETFL, 0);
1764 if (flags >= 0) wasBlocking = ((flags & O_NONBLOCK) == 0);
1765 if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(sock, FIONBIO, &yes);
1766 result = connect(sock, (struct sockaddr *)name, namelen);
1767 if (result != 0) {
1768 connect_err = __CFSocketLastError();
1769 }
1770 #if defined(LOG_CFSOCKET)
1771 fprintf(stdout, "connection attempt returns %ld error %ld on socket %d (flags 0x%lx blocking %d)\n", result, connect_err, sock, flags, wasBlocking);
1772 #endif /* LOG_CFSOCKET */
1773 if (EINPROGRESS == connect_err && timeout >= 0.0) {
1774 /* select on socket */
1775 SInt32 nrfds;
1776 int error_size = sizeof(select_err);
1777 struct timeval tv;
1778 CFMutableDataRef fds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
1779 __CFSocketFdSet(sock, fds);
1780 tv.tv_sec = (0 >= timeout || INT_MAX <= timeout) ? INT_MAX : (int)(float)floor(timeout);
1781 tv.tv_usec = (int)((timeout - floor(timeout)) * 1.0E6);
1782 nrfds = select(__CFSocketFdGetSize(fds), NULL, (fd_set *)CFDataGetMutableBytePtr(fds), NULL, &tv);
1783 if (nrfds < 0) {
1784 select_err = __CFSocketLastError();
1785 result = -1;
1786 } else if (nrfds == 0) {
1787 result = -2;
1788 } else {
1789 if (0 != getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&select_err, (socklen_t *)&error_size)) select_err = 0;
1790 result = (select_err == 0) ? 0 : -1;
1791 }
1792 CFRelease(fds);
1793 #if defined(LOG_CFSOCKET)
1794 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);
1795 #endif /* LOG_CFSOCKET */
1796 }
1797 if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(sock, FIONBIO, &no);
1798 if (EINPROGRESS == connect_err && timeout < 0.0) {
1799 result = 0;
1800 #if defined(LOG_CFSOCKET)
1801 fprintf(stdout, "connection attempt continues in background on socket %d\n", sock);
1802 #endif /* LOG_CFSOCKET */
1803 }
1804 }
1805 //??? should return errno
1806 return result;
1807 }
1808
1809 CFSocketRef CFSocketCreate(CFAllocatorRef allocator, SInt32 protocolFamily, SInt32 socketType, SInt32 protocol, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
1810 CHECK_FOR_FORK();
1811 CFSocketNativeHandle sock = INVALID_SOCKET;
1812 CFSocketRef s = NULL;
1813 if (0 >= protocolFamily) protocolFamily = PF_INET;
1814 if (PF_INET == protocolFamily) {
1815 if (0 >= socketType) socketType = SOCK_STREAM;
1816 if (0 >= protocol && SOCK_STREAM == socketType) protocol = IPPROTO_TCP;
1817 if (0 >= protocol && SOCK_DGRAM == socketType) protocol = IPPROTO_UDP;
1818 }
1819 if (PF_LOCAL == protocolFamily && 0 >= socketType) socketType = SOCK_STREAM;
1820 sock = socket(protocolFamily, socketType, protocol);
1821 if (INVALID_SOCKET != sock) {
1822 s = _CFSocketCreateWithNative(allocator, sock, callBackTypes, callout, context, FALSE);
1823 }
1824 return s;
1825 }
1826
1827 CFSocketRef CFSocketCreateWithSocketSignature(CFAllocatorRef allocator, const CFSocketSignature *signature, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
1828 CHECK_FOR_FORK();
1829 CFSocketRef s = CFSocketCreate(allocator, signature->protocolFamily, signature->socketType, signature->protocol, callBackTypes, callout, context);
1830 if (NULL != s && (!CFSocketIsValid(s) || kCFSocketSuccess != CFSocketSetAddress(s, signature->address))) {
1831 CFSocketInvalidate(s);
1832 CFRelease(s);
1833 s = NULL;
1834 }
1835 return s;
1836 }
1837
1838 CFSocketRef CFSocketCreateConnectedToSocketSignature(CFAllocatorRef allocator, const CFSocketSignature *signature, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context, CFTimeInterval timeout) {
1839 CHECK_FOR_FORK();
1840 CFSocketRef s = CFSocketCreate(allocator, signature->protocolFamily, signature->socketType, signature->protocol, callBackTypes, callout, context);
1841 if (NULL != s && (!CFSocketIsValid(s) || kCFSocketSuccess != CFSocketConnectToAddress(s, signature->address, timeout))) {
1842 CFSocketInvalidate(s);
1843 CFRelease(s);
1844 s = NULL;
1845 }
1846 return s;
1847 }
1848
1849 typedef struct {
1850 CFSocketError *error;
1851 CFPropertyListRef *value;
1852 CFDataRef *address;
1853 } __CFSocketNameRegistryResponse;
1854
1855 static void __CFSocketHandleNameRegistryReply(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {
1856 CFDataRef replyData = (CFDataRef)data;
1857 __CFSocketNameRegistryResponse *response = (__CFSocketNameRegistryResponse *)info;
1858 CFDictionaryRef replyDictionary = NULL;
1859 CFPropertyListRef value;
1860 replyDictionary = CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, replyData, kCFPropertyListImmutable, NULL);
1861 if (NULL != response->error) *(response->error) = kCFSocketError;
1862 if (NULL != replyDictionary) {
1863 if (CFGetTypeID((CFTypeRef)replyDictionary) == CFDictionaryGetTypeID() && NULL != (value = CFDictionaryGetValue(replyDictionary, kCFSocketResultKey))) {
1864 if (NULL != response->error) *(response->error) = kCFSocketSuccess;
1865 if (NULL != response->value) *(response->value) = CFRetain(value);
1866 if (NULL != response->address) *(response->address) = address ? CFDataCreateCopy(kCFAllocatorSystemDefault, address) : NULL;
1867 }
1868 CFRelease(replyDictionary);
1869 }
1870 CFSocketInvalidate(s);
1871 }
1872
1873 static void __CFSocketSendNameRegistryRequest(CFSocketSignature *signature, CFDictionaryRef requestDictionary, __CFSocketNameRegistryResponse *response, CFTimeInterval timeout) {
1874 CFDataRef requestData = NULL;
1875 CFSocketContext context = {0, response, NULL, NULL, NULL};
1876 CFSocketRef s = NULL;
1877 CFRunLoopSourceRef source = NULL;
1878 if (NULL != response->error) *(response->error) = kCFSocketError;
1879 requestData = CFPropertyListCreateXMLData(kCFAllocatorSystemDefault, requestDictionary);
1880 if (NULL != requestData) {
1881 if (NULL != response->error) *(response->error) = kCFSocketTimeout;
1882 s = CFSocketCreateConnectedToSocketSignature(kCFAllocatorSystemDefault, signature, kCFSocketDataCallBack, __CFSocketHandleNameRegistryReply, &context, timeout);
1883 if (NULL != s) {
1884 if (kCFSocketSuccess == CFSocketSendData(s, NULL, requestData, timeout)) {
1885 source = CFSocketCreateRunLoopSource(kCFAllocatorSystemDefault, s, 0);
1886 CFRunLoopAddSource(CFRunLoopGetCurrent(), source, __kCFSocketRegistryRequestRunLoopMode);
1887 CFRunLoopRunInMode(__kCFSocketRegistryRequestRunLoopMode, timeout, false);
1888 CFRelease(source);
1889 }
1890 CFSocketInvalidate(s);
1891 CFRelease(s);
1892 }
1893 CFRelease(requestData);
1894 }
1895 }
1896
1897 static void __CFSocketValidateSignature(const CFSocketSignature *providedSignature, CFSocketSignature *signature, uint16_t defaultPortNumber) {
1898 struct sockaddr_in sain, *sainp;
1899 memset(&sain, 0, sizeof(sain));
1900 sain.sin_len = sizeof(sain);
1901 sain.sin_family = AF_INET;
1902 sain.sin_port = htons(__CFSocketDefaultNameRegistryPortNumber);
1903 sain.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1904 if (NULL == providedSignature) {
1905 signature->protocolFamily = PF_INET;
1906 signature->socketType = SOCK_STREAM;
1907 signature->protocol = IPPROTO_TCP;
1908 signature->address = CFDataCreate(kCFAllocatorSystemDefault, (uint8_t *)&sain, sizeof(sain));
1909 } else {
1910 signature->protocolFamily = providedSignature->protocolFamily;
1911 signature->socketType = providedSignature->socketType;
1912 signature->protocol = providedSignature->protocol;
1913 if (0 >= signature->protocolFamily) signature->protocolFamily = PF_INET;
1914 if (PF_INET == signature->protocolFamily) {
1915 if (0 >= signature->socketType) signature->socketType = SOCK_STREAM;
1916 if (0 >= signature->protocol && SOCK_STREAM == signature->socketType) signature->protocol = IPPROTO_TCP;
1917 if (0 >= signature->protocol && SOCK_DGRAM == signature->socketType) signature->protocol = IPPROTO_UDP;
1918 }
1919 if (NULL == providedSignature->address) {
1920 signature->address = CFDataCreate(kCFAllocatorSystemDefault, (uint8_t *)&sain, sizeof(sain));
1921 } else {
1922 sainp = (struct sockaddr_in *)CFDataGetBytePtr(providedSignature->address);
1923 if ((int)sizeof(struct sockaddr_in) <= CFDataGetLength(providedSignature->address) && (AF_INET == sainp->sin_family || 0 == sainp->sin_family)) {
1924 sain.sin_len = sizeof(sain);
1925 sain.sin_family = AF_INET;
1926 sain.sin_port = sainp->sin_port;
1927 if (0 == sain.sin_port) sain.sin_port = htons(defaultPortNumber);
1928 sain.sin_addr.s_addr = sainp->sin_addr.s_addr;
1929 if (htonl(INADDR_ANY) == sain.sin_addr.s_addr) sain.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1930 signature->address = CFDataCreate(kCFAllocatorSystemDefault, (uint8_t *)&sain, sizeof(sain));
1931 } else {
1932 signature->address = CFRetain(providedSignature->address);
1933 }
1934 }
1935 }
1936 }
1937
1938 CFSocketError CFSocketRegisterValue(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFPropertyListRef value) {
1939 CFSocketSignature signature;
1940 CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1941 CFSocketError retval = kCFSocketError;
1942 __CFSocketNameRegistryResponse response = {&retval, NULL, NULL};
1943 CFDictionaryAddValue(dictionary, kCFSocketCommandKey, kCFSocketRegisterCommand);
1944 CFDictionaryAddValue(dictionary, kCFSocketNameKey, name);
1945 if (NULL != value) CFDictionaryAddValue(dictionary, kCFSocketValueKey, value);
1946 __CFSocketValidateSignature(nameServerSignature, &signature, __CFSocketDefaultNameRegistryPortNumber);
1947 __CFSocketSendNameRegistryRequest(&signature, dictionary, &response, timeout);
1948 CFRelease(dictionary);
1949 CFRelease(signature.address);
1950 return retval;
1951 }
1952
1953 CFSocketError CFSocketCopyRegisteredValue(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFPropertyListRef *value, CFDataRef *serverAddress) {
1954 CFSocketSignature signature;
1955 CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1956 CFSocketError retval = kCFSocketError;
1957 __CFSocketNameRegistryResponse response = {&retval, value, serverAddress};
1958 CFDictionaryAddValue(dictionary, kCFSocketCommandKey, kCFSocketRetrieveCommand);
1959 CFDictionaryAddValue(dictionary, kCFSocketNameKey, name);
1960 __CFSocketValidateSignature(nameServerSignature, &signature, __CFSocketDefaultNameRegistryPortNumber);
1961 __CFSocketSendNameRegistryRequest(&signature, dictionary, &response, timeout);
1962 CFRelease(dictionary);
1963 CFRelease(signature.address);
1964 return retval;
1965 }
1966
1967 CFSocketError CFSocketRegisterSocketSignature(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, const CFSocketSignature *signature) {
1968 CFSocketSignature validatedSignature;
1969 CFMutableDataRef data = NULL;
1970 CFSocketError retval;
1971 CFIndex length;
1972 uint8_t bytes[4];
1973 if (NULL == signature) {
1974 retval = CFSocketUnregister(nameServerSignature, timeout, name);
1975 } else {
1976 __CFSocketValidateSignature(signature, &validatedSignature, 0);
1977 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) {
1978 retval = kCFSocketError;
1979 } else {
1980 data = CFDataCreateMutable(kCFAllocatorSystemDefault, sizeof(bytes) + length);
1981 bytes[0] = validatedSignature.protocolFamily;
1982 bytes[1] = validatedSignature.socketType;
1983 bytes[2] = validatedSignature.protocol;
1984 bytes[3] = length;
1985 CFDataAppendBytes(data, bytes, sizeof(bytes));
1986 CFDataAppendBytes(data, CFDataGetBytePtr(validatedSignature.address), length);
1987 retval = CFSocketRegisterValue(nameServerSignature, timeout, name, data);
1988 CFRelease(data);
1989 }
1990 CFRelease(validatedSignature.address);
1991 }
1992 return retval;
1993 }
1994
1995 CFSocketError CFSocketCopyRegisteredSocketSignature(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFSocketSignature *signature, CFDataRef *nameServerAddress) {
1996 CFDataRef data = NULL;
1997 CFSocketSignature returnedSignature;
1998 const uint8_t *ptr = NULL, *aptr = NULL;
1999 uint8_t *mptr;
2000 CFIndex length = 0;
2001 CFDataRef serverAddress = NULL;
2002 CFSocketError retval = CFSocketCopyRegisteredValue(nameServerSignature, timeout, name, (CFPropertyListRef *)&data, &serverAddress);
2003 if (NULL == data || CFGetTypeID(data) != CFDataGetTypeID() || NULL == (ptr = CFDataGetBytePtr(data)) || (length = CFDataGetLength(data)) < 4) retval = kCFSocketError;
2004 if (kCFSocketSuccess == retval && NULL != signature) {
2005 returnedSignature.protocolFamily = (SInt32)*ptr++;
2006 returnedSignature.socketType = (SInt32)*ptr++;
2007 returnedSignature.protocol = (SInt32)*ptr++;
2008 ptr++;
2009 returnedSignature.address = CFDataCreate(kCFAllocatorSystemDefault, ptr, length - 4);
2010 __CFSocketValidateSignature(&returnedSignature, signature, 0);
2011 CFRelease(returnedSignature.address);
2012 ptr = CFDataGetBytePtr(signature->address);
2013 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) {
2014 CFMutableDataRef address = CFDataCreateMutableCopy(kCFAllocatorSystemDefault, CFDataGetLength(signature->address), signature->address);
2015 mptr = CFDataGetMutableBytePtr(address);
2016 ((struct sockaddr_in *)mptr)->sin_addr = ((struct sockaddr_in *)aptr)->sin_addr;
2017 CFRelease(signature->address);
2018 signature->address = address;
2019 }
2020 if (NULL != nameServerAddress) *nameServerAddress = serverAddress ? CFRetain(serverAddress) : NULL;
2021 }
2022 if (NULL != data) CFRelease(data);
2023 if (NULL != serverAddress) CFRelease(serverAddress);
2024 return retval;
2025 }
2026
2027 CFSocketError CFSocketUnregister(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name) {
2028 return CFSocketRegisterValue(nameServerSignature, timeout, name, NULL);
2029 }
2030
2031 CF_EXPORT void CFSocketSetDefaultNameRegistryPortNumber(uint16_t port) {
2032 __CFSocketDefaultNameRegistryPortNumber = port;
2033 }
2034
2035 CF_EXPORT uint16_t CFSocketGetDefaultNameRegistryPortNumber(void) {
2036 return __CFSocketDefaultNameRegistryPortNumber;
2037 }
2038
2039