]> git.saurik.com Git - apple/cf.git/blob - CFSocket.c
CF-476.17.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: Christopher Kane
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 __CFReadSocketsTimeoutInvalid = true;
288 return __CFSocketFdSet(s->_socket, __CFReadSocketsFds);
289 }
290
291 CF_INLINE Boolean __CFSocketClearFDForRead(CFSocketRef s) {
292 __CFReadSocketsTimeoutInvalid = true;
293 return __CFSocketFdClr(s->_socket, __CFReadSocketsFds);
294 }
295
296 CF_INLINE Boolean __CFSocketSetFDForWrite(CFSocketRef s) {
297 return __CFSocketFdSet(s->_socket, __CFWriteSocketsFds);
298 }
299
300 CF_INLINE Boolean __CFSocketClearFDForWrite(CFSocketRef s) {
301 return __CFSocketFdClr(s->_socket, __CFWriteSocketsFds);
302 }
303
304
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!!!"));
314 } else {
315 UInt32 yes = 1;
316 /* wakeup sockets must be non-blocking */
317 ioctlsocket(__CFWakeupSocketPair[0], FIONBIO, &yes);
318 ioctlsocket(__CFWakeupSocketPair[1], FIONBIO, &yes);
319 __CFSocketFdSet(__CFWakeupSocketPair[1], __CFReadSocketsFds);
320 }
321 }
322
323 static CFRunLoopRef __CFSocketCopyRunLoopToWakeUp(CFSocketRef s) {
324 CFRunLoopRef rl = NULL;
325 SInt32 idx, cnt = CFArrayGetCount(s->_runLoops);
326 if (0 < cnt) {
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;
331 }
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;
340 SInt32 foundIdx = 0;
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)) {
347 foundIdx = idx;
348 foundIt = true;
349 } else if (!foundBackup) {
350 foundIdx = idx;
351 foundBackup = true;
352 }
353 }
354 CFRelease(currentMode);
355 }
356 }
357 rl = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, foundIdx);
358 CFRetain(rl);
359 CFArrayRemoveValueAtIndex(s->_runLoops, foundIdx);
360 CFArrayAppendValue(s->_runLoops, rl);
361 } else {
362 CFRetain(rl);
363 }
364 }
365 return rl;
366 }
367
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;
374
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);
379 #endif
380 __CFSocketLock(s);
381 writeCallBacksAvailable = __CFSocketCallBackTypes(s) & (kCFSocketWriteCallBack | kCFSocketConnectCallBack);
382 if ((s->_f.client & kCFSocketConnectCallBack) != 0) writeCallBacksAvailable &= ~kCFSocketConnectCallBack;
383 if (!__CFSocketIsValid(s) || ((s->_f.disabled & writeCallBacksAvailable) == writeCallBacksAvailable)) {
384 __CFSocketUnlock(s);
385 return;
386 }
387 s->_errorCode = errorCode;
388 __CFSocketSetWriteSignalled(s);
389 #if defined(LOG_CFSOCKET)
390 fprintf(stdout, "write signaling source for socket %d\n", s->_socket);
391 #endif
392 if (callBackNow) {
393 __CFSocketDoCallback(s, NULL, NULL, 0);
394 } else {
395 CFRunLoopRef rl;
396 CFRunLoopSourceSignal(s->_source0);
397 rl = __CFSocketCopyRunLoopToWakeUp(s);
398 __CFSocketUnlock(s);
399 if (NULL != rl) {
400 CFRunLoopWakeUp(rl);
401 CFRelease(rl);
402 }
403 }
404 }
405
406 static void __CFSocketHandleRead(CFSocketRef s, Boolean causedByTimeout)
407 {
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);
415 SInt32 recvlen = 0;
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);
419 } else {
420 buffer = malloc(MAX_DATA_SIZE);
421 if (buffer) recvlen = recvfrom(s->_socket, buffer, MAX_DATA_SIZE, 0, (struct sockaddr *)name, (socklen_t *)&namelen);
422 }
423 #if defined(LOG_CFSOCKET)
424 fprintf(stdout, "read %ld bytes on socket %d\n", recvlen, s->_socket);
425 #endif
426 if (0 >= recvlen) {
427 //??? should return error if <0
428 /* zero-length data is the signal for perform to invalidate */
429 data = CFRetain(zeroLengthData);
430 } else {
431 data = CFDataCreate(CFGetAllocator(s), buffer, recvlen);
432 }
433 if (buffer && buffer != bufferArray) free(buffer);
434 __CFSocketLock(s);
435 if (!__CFSocketIsValid(s)) {
436 CFRelease(data);
437 __CFSocketUnlock(s);
438 return;
439 }
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);
447 }
448 if (NULL == address) {
449 address = CFRetain(zeroLengthData);
450 }
451 if (NULL == s->_dataQueue) {
452 s->_dataQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
453 }
454 if (NULL == s->_addressQueue) {
455 s->_addressQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
456 }
457 CFArrayAppendValue(s->_dataQueue, data);
458 CFRelease(data);
459 CFArrayAppendValue(s->_addressQueue, address);
460 CFRelease(address);
461 if (0 < recvlen
462 && (s->_f.client & kCFSocketDataCallBack) != 0 && (s->_f.disabled & kCFSocketDataCallBack) == 0
463 && __CFSocketIsScheduled(s)
464 ) {
465 __CFSpinLock(&__CFActiveSocketsLock);
466 /* restore socket to fds */
467 __CFSocketSetFDForRead(s);
468 __CFSpinUnlock(&__CFActiveSocketsLock);
469 }
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
476 return;
477 }
478 if (NULL != name && 0 < namelen) {
479 address = CFDataCreate(CFGetAllocator(s), name, namelen);
480 } else {
481 address = CFRetain(zeroLengthData);
482 }
483 __CFSocketLock(s);
484 if (!__CFSocketIsValid(s)) {
485 closesocket(sock);
486 CFRelease(address);
487 __CFSocketUnlock(s);
488 return;
489 }
490 __CFSocketSetReadSignalled(s);
491 if (NULL == s->_dataQueue) {
492 s->_dataQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, NULL);
493 }
494 if (NULL == s->_addressQueue) {
495 s->_addressQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
496 }
497 CFArrayAppendValue(s->_dataQueue, (void *)(uintptr_t)sock);
498 CFArrayAppendValue(s->_addressQueue, address);
499 CFRelease(address);
500 if ((s->_f.client & kCFSocketAcceptCallBack) != 0 && (s->_f.disabled & kCFSocketAcceptCallBack) == 0
501 && __CFSocketIsScheduled(s)
502 ) {
503 __CFSpinLock(&__CFActiveSocketsLock);
504 /* restore socket to fds */
505 __CFSocketSetFDForRead(s);
506 __CFSpinUnlock(&__CFActiveSocketsLock);
507 }
508 } else {
509 __CFSocketLock(s);
510 if (!__CFSocketIsValid(s) || (s->_f.disabled & kCFSocketReadCallBack) != 0) {
511 __CFSocketUnlock(s);
512 return;
513 }
514
515 if (causedByTimeout) {
516 #if defined(LOG_CFSOCKET)
517 fprintf(stdout, "TIMEOUT RECEIVED - WILL SIGNAL IMMEDIATELY TO FLUSH (%d buffered)\n", s->_bytesToBufferPos);
518 #endif
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");
523 fflush(stdout);
524 #endif
525
526 __CFSpinLock(&__CFActiveSocketsLock);
527 /* restore socket to fds */
528 __CFSocketSetFDForRead(s);
529 __CFSpinUnlock(&__CFActiveSocketsLock);
530 __CFSocketUnlock(s);
531 return;
532 }
533 } else if (s->_bytesToBuffer != 0 && ! s->_atEOF) {
534 UInt8* base;
535 CFIndex ctRead;
536 CFIndex ctRemaining = s->_bytesToBuffer - s->_bytesToBufferPos;
537
538 /* if our buffer has room, we go ahead and buffer */
539 if (ctRemaining > 0) {
540 base = CFDataGetMutableBytePtr(s->_readBuffer);
541
542 do {
543 ctRead = read(CFSocketGetNative(s), &base[s->_bytesToBufferPos], ctRemaining);
544 } while (ctRead == -1 && errno == EAGAIN);
545
546 switch (ctRead) {
547 case -1:
548 s->_bufferedReadError = errno;
549 s->_atEOF = true;
550 #if defined(LOG_CFSOCKET)
551 fprintf(stderr, "BUFFERED READ GOT ERROR %d\n", errno);
552 #endif
553 break;
554
555 case 0:
556 #if defined(LOG_CFSOCKET)
557 fprintf(stdout, "DONE READING (EOF) - GOING TO SIGNAL\n");
558 #endif
559 s->_atEOF = true;
560 break;
561
562 default:
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);
567 #endif
568 __CFSpinLock(&__CFActiveSocketsLock);
569 /* restore socket to fds */
570 __CFSocketSetFDForRead(s);
571 __CFSpinUnlock(&__CFActiveSocketsLock);
572 __CFSocketUnlock(s);
573 return;
574 } else {
575 #if defined(LOG_CFSOCKET)
576 fprintf(stdout, "DONE READING (read %d bytes) - GOING TO SIGNAL\n", ctRead);
577 #endif
578 }
579 }
580 }
581 }
582
583 __CFSocketSetReadSignalled(s);
584 }
585 #if defined(LOG_CFSOCKET)
586 fprintf(stdout, "read signaling source for socket %d\n", s->_socket);
587 #endif
588 CFRunLoopSourceSignal(s->_source0);
589 CFRunLoopRef rl = __CFSocketCopyRunLoopToWakeUp(s);
590 __CFSocketUnlock(s);
591 if (NULL != rl) {
592 CFRunLoopWakeUp(rl);
593 CFRelease(rl);
594 }
595 }
596
597 static struct timeval* intervalToTimeval(CFTimeInterval timeout, struct timeval* tv)
598 {
599 if (timeout == 0.0)
600 timerclear(tv);
601 else {
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);
604 }
605 return tv;
606 }
607
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)
611 {
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;
620 }
621 }
622
623 void __CFSocketSetSocketReadBufferAttrs(CFSocketRef s, CFTimeInterval timeout, CFIndex length)
624 {
625 struct timeval timeoutVal;
626
627 intervalToTimeval(timeout, &timeoutVal);
628
629 /* lock ordering is socket lock, activesocketslock */
630 /* activesocketslock protects our timeout calculation */
631 __CFSocketLock(s);
632 __CFSpinLock(&__CFActiveSocketsLock);
633
634 #if defined(LOG_CFSOCKET)
635 s->didLogSomething = false;
636 #endif
637
638 if (s->_bytesToBuffer != length) {
639 CFIndex ctBuffer = s->_bytesToBufferPos - s->_bytesToBufferReadPos;
640
641 if (ctBuffer) {
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.
647 */
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);
650 #endif
651
652 if (s->_leftoverBytes == NULL)
653 s->_leftoverBytes = CFDataCreateMutable(CFGetAllocator(s), 0);
654
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;
659
660 s->_bytesToBuffer = 0;
661 s->_bytesToBufferPos = 0;
662 s->_bytesToBufferReadPos = 0;
663 }
664 if (length == 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;
671 }
672 // Zero length buffer, smash the timeout
673 timeoutVal = (struct timeval) { 0, 0 };
674 } else {
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;
680 }
681 }
682
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);
689 }
690 }
691 }
692
693 if (timercmp(&s->_readBufferTimeout, &timeoutVal, !=)) {
694 s->_readBufferTimeout = timeoutVal;
695 __CFReadSocketsTimeoutInvalid = true;
696 }
697
698 __CFSpinUnlock(&__CFActiveSocketsLock);
699 __CFSocketUnlock(s);
700 }
701
702 void __CFSocketSetReadBufferTimeout(CFSocketRef s, CFTimeInterval timeout)
703 {
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);
706 #endif
707
708 __CFSocketSetSocketReadBufferAttrs(s, timeout, s->_bytesToBuffer);
709 }
710
711 void __CFSocketSetReadBufferLength(CFSocketRef s, CFIndex length)
712 {
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);
715 #endif
716
717 CFTimeInterval timeout;
718
719 if (! timerisset(&s->_readBufferTimeout))
720 timeout = 0;
721 else
722 timeout = 0.1;
723
724 __CFSocketSetSocketReadBufferAttrs(s, timeout, length);
725 }
726
727
728 CFIndex __CFSocketRead(CFSocketRef s, UInt8* buffer, CFIndex length, int* error)
729 {
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);
732 #endif
733
734 CFIndex result = -1;
735
736 __CFSocketLock(s);
737
738 *error = 0;
739
740 /* Any leftover buffered bytes? */
741 if (s->_leftoverBytes) {
742 CFIndex ctBuffer = CFDataGetLength(s->_leftoverBytes);
743 #if defined(DEBUG)
744 fprintf(stderr, "%s(%ld): WARNING: Draining %d leftover bytes first\n\n", __FUNCTION__, __LINE__, (long)ctBuffer);
745 #endif
746 if (ctBuffer > length)
747 ctBuffer = length;
748 memcpy(buffer, CFDataGetBytePtr(s->_leftoverBytes), ctBuffer);
749 if (ctBuffer < CFDataGetLength(s->_leftoverBytes))
750 CFDataReplaceBytes(s->_leftoverBytes, CFRangeMake(0, ctBuffer), NULL, 0);
751 else {
752 CFRelease(s->_leftoverBytes);
753 s->_leftoverBytes = NULL;
754 }
755 result = ctBuffer;
756 goto unlock;
757 }
758
759 /* return whatever we've buffered */
760 if (s->_bytesToBuffer != 0) {
761 CFIndex ctBuffer = s->_bytesToBufferPos - s->_bytesToBufferReadPos;
762 if (ctBuffer > 0) {
763 /* drain our buffer first */
764 if (ctBuffer > length)
765 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");
771 #endif
772 s->_bytesToBufferPos = 0;
773 s->_bytesToBufferReadPos = 0;
774 }
775
776 #if defined(LOG_CFSOCKET)
777 fprintf(stdout, "SLURPED %d BYTES FROM BUFFER %d LEFT TO READ!\n", ctBuffer, length);
778 #endif
779
780 result = ctBuffer;
781 goto unlock;
782 }
783 }
784 /* nothing buffered, or no buffer selected */
785
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);
790 #endif
791 *error = s->_bufferedReadError;
792 result = -1;
793 goto unlock;
794 }
795
796 /* nothing buffered, if we've hit eof, don't bother reading any more */
797 if (s->_atEOF) {
798 #if defined(LOG_CFSOCKET)
799 fprintf(stdout, "RETURNING EOF\n");
800 #endif
801 result = 0;
802 goto unlock;
803 }
804
805 /* normal read */
806 result = read(CFSocketGetNative(s), buffer, length);
807 #if defined(LOG_CFSOCKET)
808 fprintf(stdout, "READ %d bytes", result);
809 #endif
810
811 if (result == 0) {
812 /* note that we hit EOF */
813 s->_atEOF = true;
814 } else if (result < 0) {
815 *error = errno;
816
817 /* if it wasn't EAGAIN, record it (although we shouldn't get called again) */
818 if (*error != EAGAIN) {
819 s->_bufferedReadError = *error;
820 }
821 }
822
823 unlock:
824 __CFSocketUnlock(s);
825
826 return result;
827 }
828
829 Boolean __CFSocketGetBytesAvailable(CFSocketRef s, CFIndex* ctBytesAvailable)
830 {
831 CFIndex ctBuffer = s->_bytesToBufferPos - s->_bytesToBufferReadPos;
832 if (ctBuffer != 0) {
833 *ctBytesAvailable = ctBuffer;
834 return true;
835 } else {
836 int result;
837 #if DEPLOYMENT_TARGET_WINDOWS
838 int bytesAvailable, intLen = sizeof(bytesAvailable);
839 result = getsockopt(CFSocketGetNative(s), SOL_SOCKET, SO_NREAD, &bytesAvailable, (void *)&intLen);
840 #else
841 unsigned long bytesAvailable;
842 result = ioctlsocket(CFSocketGetNative(s), FIONREAD, &bytesAvailable);
843 #endif
844 if (result < 0)
845 return false;
846 *ctBytesAvailable = (CFIndex) bytesAvailable;
847 return true;
848 }
849 }
850
851 #if defined(LOG_CFSOCKET)
852 static void __CFSocketWriteSocketList(CFArrayRef sockets, CFDataRef fdSet, Boolean onlyIfSet) {
853 fd_set *tempfds = (fd_set *)CFDataGetBytePtr(fdSet);
854 SInt32 idx, cnt;
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);
861 }
862 }
863 }
864 #endif
865
866 #ifdef __GNUC__
867 __attribute__ ((noreturn)) // mostly interesting for shutting up a warning
868 #endif /* __GNUC__ */
869 static void __CFSocketManager(void * arg)
870 {
871 if (objc_collecting_enabled()) auto_zone_register_thread(auto_zone());
872 SInt32 nrfds, maxnrfds, fdentries = 1;
873 SInt32 rfds, wfds;
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);
877 fd_set *tempfds;
878 SInt32 idx, cnt;
879 uint8_t buffer[256];
880 CFMutableArrayRef selectedWriteSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
881 CFMutableArrayRef selectedReadSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
882 CFIndex selectedWriteSocketsIndex = 0, selectedReadSocketsIndex = 0;
883
884 struct timeval tv;
885 struct timeval* pTimeout = NULL;
886 struct timeval timeBeforeSelect;
887
888 for (;;) {
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);
897 }
898 fprintf(stdout, "\n");
899 #endif
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);
907 }
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);
912
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");
918 #endif
919 CFArrayApplyFunction(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), _calcMinTimeout_locked, (void*) &minTimeout);
920
921 if (minTimeout == NULL) {
922 #if defined(LOG_CFSOCKET)
923 fprintf(stdout, "No one wants a timeout!\n");
924 #endif
925 pTimeout = NULL;
926 } else {
927 #if defined(LOG_CFSOCKET)
928 fprintf(stdout, "timeout will be %d, %d!\n", minTimeout->tv_sec, minTimeout->tv_usec);
929 #endif
930 tv = *minTimeout;
931 pTimeout = &tv;
932 }
933 }
934
935 if (pTimeout) {
936 #if defined(LOG_CFSOCKET)
937 fprintf(stdout, "select will have a %d, %d timeout\n", pTimeout->tv_sec, pTimeout->tv_usec);
938 #endif
939 gettimeofday(&timeBeforeSelect, NULL);
940 }
941
942 __CFSpinUnlock(&__CFActiveSocketsLock);
943
944 nrfds = select(maxnrfds, readfds, writefds, exceptfds, pTimeout);
945
946 #if defined(LOG_CFSOCKET)
947 fprintf(stdout, "socket manager woke from select, ret=%ld\n", nrfds);
948 #endif
949
950 /*
951 * select returned a timeout
952 */
953 if (0 == nrfds) {
954 struct timeval timeAfterSelect;
955 struct timeval deltaTime;
956 gettimeofday(&timeAfterSelect, NULL);
957 /* timeBeforeSelect becomes the delta */
958 timersub(&timeAfterSelect, &timeBeforeSelect, &deltaTime);
959
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);
962 #endif
963
964 __CFSpinLock(&__CFActiveSocketsLock);
965
966 tempfds = NULL;
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);
980 #endif
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);
986 }
987 }
988 }
989
990 __CFSpinUnlock(&__CFActiveSocketsLock);
991
992 /* and below, we dispatch through the normal read dispatch mechanism */
993 }
994
995 if (0 > nrfds) {
996 SInt32 selectError = __CFSocketLastError();
997 #if defined(LOG_CFSOCKET)
998 fprintf(stdout, "socket manager received error %ld from select\n", selectError);
999 #endif
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);
1009 #endif
1010 CFArrayAppendValue(invalidSockets, s);
1011 }
1012 }
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);
1019 #endif
1020 CFArrayAppendValue(invalidSockets, s);
1021 }
1022 }
1023 __CFSpinUnlock(&__CFActiveSocketsLock);
1024
1025 cnt = CFArrayGetCount(invalidSockets);
1026 for (idx = 0; idx < cnt; idx++) {
1027 CFSocketInvalidate(((CFSocketRef)CFArrayGetValueAtIndex(invalidSockets, idx)));
1028 }
1029 CFRelease(invalidSockets);
1030 }
1031 continue;
1032 }
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]);
1037 #endif
1038 }
1039 __CFSpinLock(&__CFActiveSocketsLock);
1040 tempfds = NULL;
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);
1056 }
1057 }
1058 }
1059 tempfds = NULL;
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);
1074 }
1075 }
1076 __CFSpinUnlock(&__CFActiveSocketsLock);
1077
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);
1083 #endif
1084 __CFSocketHandleWrite(s, FALSE);
1085 CFArraySetValueAtIndex(selectedWriteSockets, idx, kCFNull);
1086 }
1087 selectedWriteSocketsIndex = 0;
1088
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);
1094 #endif
1095 __CFSocketHandleRead(s, nrfds == 0);
1096 CFArraySetValueAtIndex(selectedReadSockets, idx, kCFNull);
1097 }
1098 selectedReadSocketsIndex = 0;
1099 }
1100 if (objc_collecting_enabled()) auto_zone_unregister_thread(auto_zone());
1101 }
1102
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);
1110 __CFSocketLock(s);
1111 void *addr = s->_callout;
1112 Dl_info info;
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);
1120 }
1121 if (NULL == contextDesc) {
1122 contextDesc = CFStringCreateWithFormat(CFGetAllocator(s), NULL, CFSTR("<CFSocket context %p>"), contextInfo);
1123 }
1124 CFStringAppend(result, contextDesc);
1125 CFStringAppend(result, CFSTR("}"));
1126 CFRelease(contextDesc);
1127 return result;
1128 }
1129
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);
1135 s->_address = NULL;
1136 }
1137 if (NULL != s->_readBuffer) {
1138 CFRelease(s->_readBuffer);
1139 s->_readBuffer = NULL;
1140 }
1141 if (NULL != s->_leftoverBytes) {
1142 CFRelease(s->_leftoverBytes);
1143 s->_leftoverBytes = NULL;
1144 }
1145 timerclear(&s->_readBufferTimeout);
1146 s->_bytesToBuffer = 0;
1147 s->_bytesToBufferPos = 0;
1148 s->_bytesToBufferReadPos = 0;
1149 s->_atEOF = true;
1150 s->_bufferedReadError = 0;
1151 }
1152
1153 static const CFRuntimeClass __CFSocketClass = {
1154 0,
1155 "CFSocket",
1156 NULL, // init
1157 NULL, // copy
1158 __CFSocketDeallocate,
1159 NULL, // equal
1160 NULL, // hash
1161 NULL, //
1162 __CFSocketCopyDescription
1163 };
1164
1165 __private_extern__ void __CFSocketInitialize(void) {
1166 __kCFSocketTypeID = _CFRuntimeRegisterClass(&__CFSocketClass);
1167 }
1168
1169 CFTypeID CFSocketGetTypeID(void) {
1170 return __kCFSocketTypeID;
1171 }
1172
1173 static CFSocketRef _CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHandle sock, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context, Boolean useExistingInstance) {
1174 CHECK_FOR_FORK();
1175 CFSocketRef memory;
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);
1183 }
1184 if (INVALID_SOCKET != sock && CFDictionaryGetValueIfPresent(__CFAllSockets, (void *)(uintptr_t)sock, (const void **)&memory)) {
1185 if (useExistingInstance) {
1186 __CFSpinUnlock(&__CFAllSocketsLock);
1187 CFRetain(memory);
1188 return memory;
1189 } else {
1190 #if defined(LOG_CFSOCKET)
1191 fprintf(stdout, "useExistingInstance is FALSE, removing existing instance %d from __CFAllSockets\n", (int)memory);
1192 #endif
1193 __CFSpinUnlock(&__CFAllSocketsLock);
1194 CFSocketInvalidate(memory);
1195 __CFSpinLock(&__CFAllSocketsLock);
1196 }
1197 }
1198 memory = (CFSocketRef)_CFRuntimeCreateInstance(allocator, __kCFSocketTypeID, sizeof(struct __CFSocket) - sizeof(CFRuntimeBase), NULL);
1199 if (NULL == memory) {
1200 __CFSpinUnlock(&__CFAllSocketsLock);
1201 return NULL;
1202 }
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);
1223 } else {
1224 memory->_runLoops = NULL;
1225 }
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;
1241
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);
1252 }
1253 return memory;
1254 }
1255
1256 CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHandle sock, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
1257 return _CFSocketCreateWithNative(allocator, sock, callBackTypes, callout, context, TRUE);
1258 }
1259
1260 void CFSocketInvalidate(CFSocketRef s) {
1261 CHECK_FOR_FORK();
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);
1266 #endif
1267 CFRetain(s);
1268 __CFSpinLock(&__CFAllSocketsLock);
1269 __CFSocketLock(s);
1270 if (__CFSocketIsValid(s)) {
1271 SInt32 idx;
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);
1280 if (0 <= idx) {
1281 CFArrayRemoveValueAtIndex(__CFWriteSockets, idx);
1282 __CFSocketClearFDForWrite(s);
1283 }
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);
1286 if (0 <= idx) {
1287 CFArrayRemoveValueAtIndex(__CFReadSockets, idx);
1288 __CFSocketClearFDForRead(s);
1289 }
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;
1298 }
1299 if (NULL != s->_dataQueue) {
1300 CFRelease(s->_dataQueue);
1301 s->_dataQueue = NULL;
1302 }
1303 if (NULL != s->_addressQueue) {
1304 CFRelease(s->_addressQueue);
1305 s->_addressQueue = NULL;
1306 }
1307 s->_socketSetCount = 0;
1308 for (idx = CFArrayGetCount(s->_runLoops); idx--;) {
1309 CFRunLoopWakeUp((CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, idx));
1310 }
1311 CFRelease(s->_runLoops);
1312 s->_runLoops = NULL;
1313 source0 = s->_source0;
1314 s->_source0 = NULL;
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);
1324 }
1325 if (NULL != source0) {
1326 CFRunLoopSourceInvalidate(source0);
1327 CFRelease(source0);
1328 }
1329 } else {
1330 __CFSocketUnlock(s);
1331 }
1332 __CFSpinUnlock(&__CFAllSocketsLock);
1333 CFRelease(s);
1334 }
1335
1336 Boolean CFSocketIsValid(CFSocketRef s) {
1337 CHECK_FOR_FORK();
1338 __CFGenericValidateType(s, __kCFSocketTypeID);
1339 return __CFSocketIsValid(s);
1340 }
1341
1342 CFSocketNativeHandle CFSocketGetNative(CFSocketRef s) {
1343 CHECK_FOR_FORK();
1344 __CFGenericValidateType(s, __kCFSocketTypeID);
1345 return s->_socket;
1346 }
1347
1348 CFDataRef CFSocketCopyAddress(CFSocketRef s) {
1349 CHECK_FOR_FORK();
1350 CFDataRef result = NULL;
1351 __CFGenericValidateType(s, __kCFSocketTypeID);
1352 __CFSocketLock(s);
1353 __CFSocketEstablishAddress(s);
1354 if (NULL != s->_address) {
1355 result = CFRetain(s->_address);
1356 }
1357 __CFSocketUnlock(s);
1358 return result;
1359 }
1360
1361 CFDataRef CFSocketCopyPeerAddress(CFSocketRef s) {
1362 CHECK_FOR_FORK();
1363 CFDataRef result = NULL;
1364 __CFGenericValidateType(s, __kCFSocketTypeID);
1365 __CFSocketLock(s);
1366 __CFSocketEstablishPeerAddress(s);
1367 if (NULL != s->_peerAddress) {
1368 result = CFRetain(s->_peerAddress);
1369 }
1370 __CFSocketUnlock(s);
1371 return result;
1372 }
1373
1374 void CFSocketGetContext(CFSocketRef s, CFSocketContext *context) {
1375 CHECK_FOR_FORK();
1376 __CFGenericValidateType(s, __kCFSocketTypeID);
1377 CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__);
1378 *context = s->_context;
1379 }
1380
1381 CFOptionFlags CFSocketGetSocketFlags(CFSocketRef s) {
1382 CHECK_FOR_FORK();
1383 __CFGenericValidateType(s, __kCFSocketTypeID);
1384 return s->_f.client;
1385 }
1386
1387 void CFSocketSetSocketFlags(CFSocketRef s, CFOptionFlags flags) {
1388 CHECK_FOR_FORK();
1389 __CFGenericValidateType(s, __kCFSocketTypeID);
1390 __CFSocketLock(s);
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);
1393 #endif
1394 s->_f.client = flags;
1395 __CFSocketUnlock(s);
1396 }
1397
1398 void CFSocketDisableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) {
1399 CHECK_FOR_FORK();
1400 Boolean wakeup = false;
1401 uint8_t readCallBackType;
1402 __CFGenericValidateType(s, __kCFSocketTypeID);
1403 __CFSocketLock(s);
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);
1410 #endif
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;
1419 }
1420 }
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;
1425 }
1426 }
1427 __CFSpinUnlock(&__CFActiveSocketsLock);
1428 }
1429 __CFSocketUnlock(s);
1430 if (wakeup && __CFSocketManagerThread) {
1431 uint8_t c = 'u';
1432 send(__CFWakeupSocketPair[0], &c, sizeof(c), 0);
1433 }
1434 }
1435
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) {
1443 CHECK_FOR_FORK();
1444 Boolean wakeup = FALSE;
1445 if (!callBackTypes) {
1446 __CFSocketUnlock(s);
1447 return;
1448 }
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);
1456 #endif
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;
1459
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;
1464 } else {
1465 // if we want connect callbacks and they're not disabled...
1466 if ((callBackTypes & kCFSocketConnectCallBack) != 0 && (s->_f.disabled & kCFSocketConnectCallBack) == 0) turnOnConnect = TRUE;
1467 }
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;
1470
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) {
1475 if (force) {
1476 SInt32 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
1477 if (kCFNotFound == idx) CFArrayAppendValue(__CFWriteSockets, s);
1478 }
1479 if (__CFSocketSetFDForWrite(s)) wakeup = true;
1480 }
1481 if (turnOnRead) {
1482 if (force) {
1483 SInt32 idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
1484 if (kCFNotFound == idx) CFArrayAppendValue(__CFReadSockets, s);
1485 }
1486 if (__CFSocketSetFDForRead(s)) wakeup = true;
1487 }
1488 if (wakeup && NULL == __CFSocketManagerThread) __CFSocketManagerThread = __CFStartSimpleThread(__CFSocketManager, 0);
1489 __CFSpinUnlock(&__CFActiveSocketsLock);
1490 }
1491 }
1492 __CFSocketUnlock(s);
1493 if (wakeup) send(__CFWakeupSocketPair[0], &wakeupChar, sizeof(wakeupChar), 0);
1494 }
1495
1496 void CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) {
1497 CHECK_FOR_FORK();
1498 __CFGenericValidateType(s, __kCFSocketTypeID);
1499 __CFSocketLock(s);
1500 __CFSocketEnableCallBacks(s, callBackTypes, TRUE, 'r');
1501 }
1502
1503 static void __CFSocketSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) {
1504 CFSocketRef s = info;
1505 __CFSocketLock(s);
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);
1516 #endif
1517 __CFSocketEnableCallBacks(s, __CFSocketCallBackTypes(s), TRUE, 's'); // unlocks s
1518 } else
1519 __CFSocketUnlock(s);
1520 } else
1521 __CFSocketUnlock(s);
1522 }
1523
1524 static void __CFSocketCancel(void *info, CFRunLoopRef rl, CFStringRef mode) {
1525 CFSocketRef s = info;
1526 SInt32 idx;
1527 __CFSocketLock(s);
1528 s->_socketSetCount--;
1529 if (0 == s->_socketSetCount) {
1530 __CFSpinLock(&__CFActiveSocketsLock);
1531 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
1532 if (0 <= idx) {
1533 CFArrayRemoveValueAtIndex(__CFWriteSockets, idx);
1534 __CFSocketClearFDForWrite(s);
1535 }
1536 idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
1537 if (0 <= idx) {
1538 CFArrayRemoveValueAtIndex(__CFReadSockets, idx);
1539 __CFSocketClearFDForRead(s);
1540 }
1541 __CFSpinUnlock(&__CFActiveSocketsLock);
1542 }
1543 if (NULL != s->_runLoops) {
1544 idx = CFArrayGetFirstIndexOfValue(s->_runLoops, CFRangeMake(0, CFArrayGetCount(s->_runLoops)), rl);
1545 if (0 <= idx) CFArrayRemoveValueAtIndex(s->_runLoops, idx);
1546 }
1547 __CFSocketUnlock(s);
1548 }
1549
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;
1558
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);
1570 #endif
1571 if (writeSignalled) {
1572 errorCode = s->_errorCode;
1573 s->_f.connected = TRUE;
1574 }
1575 __CFSocketUnlock(s);
1576 if ((callBackTypes & kCFSocketConnectCallBack) != 0) {
1577 if (connectSignalled && (!calledOut || CFSocketIsValid(s))) {
1578 if (errorCode) {
1579 #if defined(LOG_CFSOCKET)
1580 fprintf(stdout, "perform calling out error %ld to socket %d\n", errorCode, s->_socket);
1581 #endif
1582 if (callout) callout(s, kCFSocketConnectCallBack, NULL, &errorCode, contextInfo);
1583 calledOut = true;
1584 } else {
1585 #if defined(LOG_CFSOCKET)
1586 fprintf(stdout, "perform calling out connect to socket %d\n", s->_socket);
1587 #endif
1588 if (callout) callout(s, kCFSocketConnectCallBack, NULL, NULL, contextInfo);
1589 calledOut = true;
1590 }
1591 }
1592 }
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);
1598 #endif
1599 if (callout) callout(s, kCFSocketDataCallBack, address, data, contextInfo);
1600 calledOut = true;
1601 if (0 == datalen) CFSocketInvalidate(s);
1602 }
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);
1607 #endif
1608 if (callout) callout(s, kCFSocketAcceptCallBack, address, &sock, contextInfo);
1609 calledOut = true;
1610 }
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);
1615 #endif
1616 if (callout) callout(s, kCFSocketReadCallBack, NULL, NULL, contextInfo);
1617 calledOut = true;
1618 }
1619 }
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);
1624 #endif
1625 if (callout) callout(s, kCFSocketWriteCallBack, NULL, NULL, contextInfo);
1626 calledOut = true;
1627 }
1628 }
1629 }
1630
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;
1638
1639 __CFSocketLock(s);
1640 if (!__CFSocketIsValid(s)) {
1641 __CFSocketUnlock(s);
1642 return;
1643 }
1644 callBackTypes = __CFSocketCallBackTypes(s);
1645 readCallBackType = __CFSocketReadCallBackType(s);
1646 CFOptionFlags callBacksSignalled = 0;
1647 if (__CFSocketIsReadSignalled(s)) callBacksSignalled |= readCallBackType;
1648 if (__CFSocketIsWriteSignalled(s)) callBacksSignalled |= kCFSocketWriteCallBack;
1649
1650 if (kCFSocketDataCallBack == readCallBackType) {
1651 if (NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
1652 data = CFArrayGetValueAtIndex(s->_dataQueue, 0);
1653 CFRetain(data);
1654 CFArrayRemoveValueAtIndex(s->_dataQueue, 0);
1655 address = CFArrayGetValueAtIndex(s->_addressQueue, 0);
1656 CFRetain(address);
1657 CFArrayRemoveValueAtIndex(s->_addressQueue, 0);
1658 }
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);
1664 CFRetain(address);
1665 CFArrayRemoveValueAtIndex(s->_addressQueue, 0);
1666 }
1667 }
1668
1669 __CFSocketDoCallback(s, data, address, sock); // does __CFSocketUnlock(s)
1670 if (NULL != data) CFRelease(data);
1671 if (NULL != address) CFRelease(address);
1672
1673 __CFSocketLock(s);
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);
1680 #endif
1681 rl = __CFSocketCopyRunLoopToWakeUp(s);
1682 }
1683 }
1684 // Only reenable callbacks that are auto-reenabled
1685 __CFSocketEnableCallBacks(s, callBacksSignalled & s->_f.client, FALSE, 'p'); // unlocks s
1686
1687 if (NULL != rl) {
1688 CFRunLoopWakeUp(rl);
1689 CFRelease(rl);
1690 }
1691 }
1692
1693 CFRunLoopSourceRef CFSocketCreateRunLoopSource(CFAllocatorRef allocator, CFSocketRef s, CFIndex order) {
1694 CHECK_FOR_FORK();
1695 CFRunLoopSourceRef result = NULL;
1696 __CFGenericValidateType(s, __kCFSocketTypeID);
1697 __CFSocketLock(s);
1698 if (__CFSocketIsValid(s)) {
1699 if (NULL == s->_source0) {
1700 CFRunLoopSourceContext context;
1701 context.version = 0;
1702 context.info = s;
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);
1712 }
1713 CFRetain(s->_source0); /* This retain is for the receiver */
1714 result = s->_source0;
1715 }
1716 __CFSocketUnlock(s);
1717 return result;
1718 }
1719
1720 #endif /* NEW_SOCKET */
1721
1722 static CFSpinLock_t __CFSocketWriteLock_ = CFSpinLockInit;
1723 //#warning can only send on one socket at a time now
1724
1725 CF_INLINE void __CFSocketWriteLock(CFSocketRef s) {
1726 __CFSpinLock(& __CFSocketWriteLock_);
1727 }
1728
1729 CF_INLINE void __CFSocketWriteUnlock(CFSocketRef s) {
1730 __CFSpinUnlock(& __CFSocketWriteLock_);
1731 }
1732
1733 //??? need timeout, error handling, retries
1734 CFSocketError CFSocketSendData(CFSocketRef s, CFDataRef address, CFDataRef data, CFTimeInterval timeout) {
1735 CHECK_FOR_FORK();
1736 const uint8_t *dataptr, *addrptr = NULL;
1737 SInt32 datalen, addrlen = 0, size = 0;
1738 CFSocketNativeHandle sock = INVALID_SOCKET;
1739 struct timeval tv;
1740 __CFGenericValidateType(s, CFSocketGetTypeID());
1741 if (address) {
1742 addrptr = CFDataGetBytePtr(address);
1743 addrlen = CFDataGetLength(address);
1744 }
1745 dataptr = CFDataGetBytePtr(data);
1746 datalen = CFDataGetLength(data);
1747 if (CFSocketIsValid(s)) sock = CFSocketGetNative(s);
1748 if (INVALID_SOCKET != sock) {
1749 CFRetain(s);
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);
1756 } else {
1757 size = send(sock, dataptr, datalen, 0);
1758 }
1759 #if defined(LOG_CFSOCKET)
1760 fprintf(stdout, "wrote %ld bytes to socket %d\n", size, sock);
1761 #endif
1762 __CFSocketWriteUnlock(s);
1763 CFRelease(s);
1764 }
1765 return (size > 0) ? kCFSocketSuccess : kCFSocketError;
1766 }
1767
1768 CFSocketError CFSocketSetAddress(CFSocketRef s, CFDataRef address) {
1769 CHECK_FOR_FORK();
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);
1780 if (0 == result) {
1781 listen(sock, 256);
1782 }
1783 //??? should return errno
1784 return result;
1785 }
1786
1787 CFSocketError CFSocketConnectToAddress(CFSocketRef s, CFDataRef address, CFTimeInterval timeout) {
1788 CHECK_FOR_FORK();
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;
1794
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);
1801 {
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);
1806 if (result != 0) {
1807 connect_err = __CFSocketLastError();
1808 }
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);
1811 #endif
1812 if (EINPROGRESS == connect_err && timeout >= 0.0) {
1813 /* select on socket */
1814 SInt32 nrfds;
1815 int error_size = sizeof(select_err);
1816 struct timeval tv;
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);
1822 if (nrfds < 0) {
1823 select_err = __CFSocketLastError();
1824 result = -1;
1825 } else if (nrfds == 0) {
1826 result = -2;
1827 } else {
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;
1830 }
1831 CFRelease(fds);
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);
1834 #endif
1835 }
1836 if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(sock, FIONBIO, &no);
1837 if (EINPROGRESS == connect_err && timeout < 0.0) {
1838 result = 0;
1839 #if defined(LOG_CFSOCKET)
1840 fprintf(stdout, "connection attempt continues in background on socket %d\n", sock);
1841 #endif
1842 }
1843 }
1844 //??? should return errno
1845 return result;
1846 }
1847
1848 CFSocketRef CFSocketCreate(CFAllocatorRef allocator, SInt32 protocolFamily, SInt32 socketType, SInt32 protocol, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
1849 CHECK_FOR_FORK();
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;
1857 }
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);
1862 }
1863 return s;
1864 }
1865
1866 CFSocketRef CFSocketCreateWithSocketSignature(CFAllocatorRef allocator, const CFSocketSignature *signature, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
1867 CHECK_FOR_FORK();
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);
1871 CFRelease(s);
1872 s = NULL;
1873 }
1874 return s;
1875 }
1876
1877 CFSocketRef CFSocketCreateConnectedToSocketSignature(CFAllocatorRef allocator, const CFSocketSignature *signature, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context, CFTimeInterval timeout) {
1878 CHECK_FOR_FORK();
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);
1882 CFRelease(s);
1883 s = NULL;
1884 }
1885 return s;
1886 }
1887
1888 typedef struct {
1889 CFSocketError *error;
1890 CFPropertyListRef *value;
1891 CFDataRef *address;
1892 } __CFSocketNameRegistryResponse;
1893
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;
1906 }
1907 CFRelease(replyDictionary);
1908 }
1909 CFSocketInvalidate(s);
1910 }
1911
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);
1922 if (NULL != s) {
1923 if (kCFSocketSuccess == CFSocketSendData(s, NULL, requestData, timeout)) {
1924 source = CFSocketCreateRunLoopSource(kCFAllocatorSystemDefault, s, 0);
1925 CFRunLoopAddSource(CFRunLoopGetCurrent(), source, __kCFSocketRegistryRequestRunLoopMode);
1926 CFRunLoopRunInMode(__kCFSocketRegistryRequestRunLoopMode, timeout, false);
1927 CFRelease(source);
1928 }
1929 CFSocketInvalidate(s);
1930 CFRelease(s);
1931 }
1932 CFRelease(requestData);
1933 }
1934 }
1935
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));
1948 } else {
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;
1957 }
1958 if (NULL == providedSignature->address) {
1959 signature->address = CFDataCreate(kCFAllocatorSystemDefault, (uint8_t *)&sain, sizeof(sain));
1960 } else {
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));
1970 } else {
1971 signature->address = CFRetain(providedSignature->address);
1972 }
1973 }
1974 }
1975 }
1976
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);
1989 return retval;
1990 }
1991
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);
2003 return retval;
2004 }
2005
2006 CFSocketError CFSocketRegisterSocketSignature(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, const CFSocketSignature *signature) {
2007 CFSocketSignature validatedSignature;
2008 CFMutableDataRef data = NULL;
2009 CFSocketError retval;
2010 CFIndex length;
2011 uint8_t bytes[4];
2012 if (NULL == signature) {
2013 retval = CFSocketUnregister(nameServerSignature, timeout, name);
2014 } else {
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;
2018 } else {
2019 data = CFDataCreateMutable(kCFAllocatorSystemDefault, sizeof(bytes) + length);
2020 bytes[0] = validatedSignature.protocolFamily;
2021 bytes[1] = validatedSignature.socketType;
2022 bytes[2] = validatedSignature.protocol;
2023 bytes[3] = length;
2024 CFDataAppendBytes(data, bytes, sizeof(bytes));
2025 CFDataAppendBytes(data, CFDataGetBytePtr(validatedSignature.address), length);
2026 retval = CFSocketRegisterValue(nameServerSignature, timeout, name, data);
2027 CFRelease(data);
2028 }
2029 CFRelease(validatedSignature.address);
2030 }
2031 return retval;
2032 }
2033
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;
2038 uint8_t *mptr;
2039 CFIndex length = 0;
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++;
2047 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;
2058 }
2059 if (NULL != nameServerAddress) *nameServerAddress = serverAddress ? CFRetain(serverAddress) : NULL;
2060 }
2061 if (NULL != data) CFRelease(data);
2062 if (NULL != serverAddress) CFRelease(serverAddress);
2063 return retval;
2064 }
2065
2066 CFSocketError CFSocketUnregister(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name) {
2067 return CFSocketRegisterValue(nameServerSignature, timeout, name, NULL);
2068 }
2069
2070 CF_EXPORT void CFSocketSetDefaultNameRegistryPortNumber(uint16_t port) {
2071 __CFSocketDefaultNameRegistryPortNumber = port;
2072 }
2073
2074 CF_EXPORT uint16_t CFSocketGetDefaultNameRegistryPortNumber(void) {
2075 return __CFSocketDefaultNameRegistryPortNumber;
2076 }
2077
2078