1/*
2 * Copyright (c) 2014 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
24/*	CFSocket.c
25	Copyright (c) 1999-2013, Apple Inc.  All rights reserved.
26	Responsibility: Christopher Kane
27*/
28
29#define NEW_SOCKET 0
30
31#if NEW_SOCKET
32/*
33
34#include <CoreFoundation/CFSocket.h>
35#include "CFInternal.h"
36#include <dispatch/dispatch.h>
37#include <dispatch/private.h>
38#include <netinet/in.h>
39#include <sys/sysctl.h>
40#include <sys/socket.h>
41#include <sys/ioctl.h>
42#include <sys/stat.h>
43#include <unistd.h>
44#include <dlfcn.h>
45#include <sys/select.h>
46
47
48extern void _CFRunLoopSourceWakeUpRunLoops(CFRunLoopSourceRef rls);
49
50#define INVALID_SOCKET (CFSocketNativeHandle)(-1)
51#define MAX_SOCKADDR_LEN 256
52
53
54DISPATCH_HELPER_FUNCTIONS(sock, CFSocket)
55
56static Boolean sockfd_is_readable(int fd) {
57    if (fd < 0 || 1048576 <= fd) HALT;
58    size_t sz = ((fd + CHAR_BIT) / CHAR_BIT) + 7; // generous
59    fd_set *fdset = malloc(sz);
60    int ret;
61    do {
62        memset(fdset, 0, sz);
63        FD_SET(fd, fdset);
64        struct timespec ts = {0, 1000UL}; // 1 us
65        ret = pselect(fd + 1, fdset, NULL, NULL, &ts, NULL);
66    } while (ret < 0 && (EINTR == errno || EAGAIN == errno));
67    Boolean isSet = ((0 < ret) && FD_ISSET(fd, fdset));
68    free(fdset);
69    return isSet;
70}
71
72static Boolean sockfd_is_writeable(int fd) {
73    if (fd < 0 || 1048576 <= fd) HALT;
74    size_t sz = ((fd + CHAR_BIT) / CHAR_BIT) + 7; // generous
75    fd_set *fdset = malloc(sz);
76    int ret;
77    do {
78        memset(fdset, 0, sz);
79        FD_SET(fd, fdset);
80        struct timespec ts = {0, 1000UL}; // 1 us
81        ret = pselect(fd + 1, NULL, fdset, NULL, &ts, NULL);
82    } while (ret < 0 && (EINTR == errno || EAGAIN == errno));
83    Boolean isSet = ((0 < ret) && FD_ISSET(fd, fdset));
84    free(fdset);
85    return isSet;
86}
87
88
89enum {
90    kCFSocketStateReady = 0,
91    kCFSocketStateInvalidating = 1,
92    kCFSocketStateInvalid = 2,
93    kCFSocketStateDeallocating = 3
94};
95
96struct __shared_blob {
97    dispatch_source_t _rdsrc;
98    dispatch_source_t _wrsrc;
99    CFRunLoopSourceRef _source;
100    CFSocketNativeHandle _socket;
101    uint8_t _closeFD;
102    uint8_t _refCnt;
103};
104
105struct __CFSocket {
106    CFRuntimeBase _base;
107    struct __shared_blob *_shared; // non-NULL when valid, NULL when invalid
108
109    uint8_t _state:2;         // mutable, not written safely
110    uint8_t _isSaneFD:1;      // immutable
111    uint8_t _connOriented:1;  // immutable
112    uint8_t _wantConnect:1;   // immutable
113    uint8_t _wantWrite:1;     // immutable
114    uint8_t _wantReadType:2;  // immutable
115
116    uint8_t _error;
117
118    uint8_t _rsuspended:1;
119    uint8_t _wsuspended:1;
120    uint8_t _readable:1;
121    uint8_t _writeable:1;
122    uint8_t _unused:4;
123
124    uint8_t _reenableRead:1;
125    uint8_t _readDisabled:1;
126    uint8_t _reenableWrite:1;
127    uint8_t _writeDisabled:1;
128    uint8_t _connectDisabled:1;
129    uint8_t _connected:1;
130    uint8_t _leaveErrors:1;
131    uint8_t _closeOnInvalidate:1;
132
133    int32_t _runLoopCounter;
134
135    CFDataRef _address;         // immutable, once created
136    CFDataRef _peerAddress;     // immutable, once created
137    CFSocketCallBack _callout;  // immutable
138    CFSocketContext _context;   // immutable
139};
140
141
142CF_INLINE Boolean __CFSocketIsValid(CFSocketRef sock) {
143    return kCFSocketStateReady == sock->_state;
144}
145
146static CFStringRef __CFSocketCopyDescription(CFTypeRef cf) {
147    CFSocketRef sock = (CFSocketRef)cf;
148    CFStringRef contextDesc = NULL;
149    if (NULL != sock->_context.info && NULL != sock->_context.copyDescription) {
150        contextDesc = sock->_context.copyDescription(sock->_context.info);
151    }
152    if (NULL == contextDesc) {
153        contextDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFSocket context %p>"), sock->_context.info);
154    }
155    Dl_info info;
156    void *addr = sock->_callout;
157    const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???";
158    int avail = -1;
159    ioctlsocket(sock->_shared ? sock->_shared->_socket : -1, FIONREAD, &avail);
160    CFStringRef result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR(
161            "<CFSocket %p [%p]>{valid = %s, socket = %d, "
162            "want connect = %s, connect disabled = %s, "
163            "want write = %s, reenable write = %s, write disabled = %s, "
164            "want read = %s, reenable read = %s, read disabled = %s, "
165            "leave errors = %s, close on invalidate = %s, connected = %s, "
166            "last error code = %d, bytes available for read = %d, "
167            "source = %p, callout = %s (%p), context = %@}"),
168        cf, CFGetAllocator(sock), __CFSocketIsValid(sock) ? "Yes" : "No", sock->_shared ? sock->_shared->_socket : -1,
169        sock->_wantConnect ? "Yes" : "No", sock->_connectDisabled ? "Yes" : "No",
170        sock->_wantWrite ? "Yes" : "No", sock->_reenableWrite ? "Yes" : "No", sock->_writeDisabled ? "Yes" : "No",
171        sock->_wantReadType ? "Yes" : "No", sock->_reenableRead ? "Yes" : "No", sock->_readDisabled? "Yes" : "No",
172        sock->_leaveErrors ? "Yes" : "No", sock->_closeOnInvalidate ? "Yes" : "No", sock->_connected ? "Yes" : "No",
173        sock->_error, avail,
174        sock->_shared ? sock->_shared->_source : NULL, name, addr, contextDesc);
175    if (NULL != contextDesc) {
176        CFRelease(contextDesc);
177    }
178    return result;
179}
180
181static void __CFSocketDeallocate(CFTypeRef cf) {
182    CHECK_FOR_FORK_RET();
183    CFSocketRef sock = (CFSocketRef)cf;
184    // Since CFSockets are cached, we can only get here sometime after being invalidated
185    sock->_state = kCFSocketStateDeallocating;
186    if (sock->_peerAddress) {
187        CFRelease(sock->_peerAddress);
188        sock->_peerAddress = NULL;
189    }
190    if (sock->_address) {
191        CFRelease(sock->_address);
192        sock->_address = NULL;
193    }
194}
195
196static CFTypeID __kCFSocketTypeID = _kCFRuntimeNotATypeID;
197
198static const CFRuntimeClass __CFSocketClass = {
199    0,
200    "CFSocket",
201    NULL,      // init
202    NULL,      // copy
203    __CFSocketDeallocate,
204    NULL,      // equal
205    NULL,      // hash
206    NULL,      //
207    __CFSocketCopyDescription
208};
209
210static CFMutableArrayRef __CFAllSockets = NULL;
211
212CFTypeID CFSocketGetTypeID(void) {
213    if (_kCFRuntimeNotATypeID == __kCFSocketTypeID) {
214        __kCFSocketTypeID = _CFRuntimeRegisterClass(&__CFSocketClass);
215        __CFAllSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
216        struct rlimit lim1;
217        int ret1 = getrlimit(RLIMIT_NOFILE, &lim1);
218        int mib[] = {CTL_KERN, KERN_MAXFILESPERPROC};
219        int maxfd = 0;
220        size_t len = sizeof(int);
221        int ret0 = sysctl(mib, 2, &maxfd, &len, NULL, 0);
222        if (0 == ret0 && 0 == ret1 && lim1.rlim_max < maxfd) maxfd = lim1.rlim_max;
223        if (0 == ret1 && lim1.rlim_cur < maxfd) {
224            struct rlimit lim2 = lim1;
225            lim2.rlim_cur += 2304;
226            if (maxfd < lim2.rlim_cur) lim2.rlim_cur = maxfd;
227            setrlimit(RLIMIT_NOFILE, &lim2);
228            // we try, but do not go to extraordinary measures
229        }
230    }
231    return __kCFSocketTypeID;
232}
233
234CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHandle ufd, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
235    CHECK_FOR_FORK_RET(NULL);
236
237    CFSocketGetTypeID(); // cause initialization if necessary
238
239    struct stat statbuf;
240    int ret = fstat(ufd, &statbuf);
241    if (ret < 0) ufd = INVALID_SOCKET;
242
243    Boolean sane = false;
244    if (INVALID_SOCKET != ufd) {
245        uint32_t type = (statbuf.st_mode & S_IFMT);
246        sane = (S_IFSOCK == type) || (S_IFIFO == type) || (S_IFCHR == type);
247        if (1 && !sane) {
248            CFLog(kCFLogLevelWarning, CFSTR("*** CFSocketCreateWithNative(): creating CFSocket with silly fd type (%07o) -- may or may not work"), type);
249        }
250    }
251
252    if (INVALID_SOCKET != ufd) {
253        Boolean canHandle = false;
254        int tmp_kq = kqueue();
255        if (0 <= tmp_kq) {
256            struct kevent ev[2];
257            EV_SET(&ev[0], ufd, EVFILT_READ, EV_ADD, 0, 0, 0);
258            EV_SET(&ev[1], ufd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
259            int ret = kevent(tmp_kq, ev, 2, NULL, 0, NULL);
260            canHandle = (0 <= ret); // if kevent(ADD) succeeds, can handle
261            close(tmp_kq);
262        }
263        if (1 && !canHandle) {
264            CFLog(kCFLogLevelWarning, CFSTR("*** CFSocketCreateWithNative(): creating CFSocket with unsupported fd type -- may or may not work"));
265        }
266    }
267
268    if (INVALID_SOCKET == ufd) {
269        // Historically, bad ufd was allowed, but gave an uncached and already-invalid CFSocketRef
270        SInt32 size = sizeof(struct __CFSocket) - sizeof(CFRuntimeBase);
271        CFSocketRef memory = (CFSocketRef)_CFRuntimeCreateInstance(allocator, CFSocketGetTypeID(), size, NULL);
272        if (NULL == memory) {
273            return NULL;
274        }
275        memory->_callout = callout;
276        memory->_state = kCFSocketStateInvalid;
277        return memory;
278    }
279
280    __block CFSocketRef sock = NULL;
281    dispatch_sync(__sockQueue(), ^{
282            for (CFIndex idx = 0, cnt = CFArrayGetCount(__CFAllSockets); idx < cnt; idx++) {
283                CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFAllSockets, idx);
284                if (s->_shared->_socket == ufd) {
285                    CFRetain(s);
286                    sock = s;
287                    return;
288                }
289            }
290
291            SInt32 size = sizeof(struct __CFSocket) - sizeof(CFRuntimeBase);
292            CFSocketRef memory = (CFSocketRef)_CFRuntimeCreateInstance(allocator, CFSocketGetTypeID(), size, NULL);
293            if (NULL == memory) {
294                return;
295            }
296
297            int socketType = 0;
298            if (INVALID_SOCKET != ufd) {
299                socklen_t typeSize = sizeof(socketType);
300                int ret = getsockopt(ufd, SOL_SOCKET, SO_TYPE, (void *)&socketType, (socklen_t *)&typeSize);
301                if (ret < 0) socketType = 0;
302            }
303
304            memory->_rsuspended = true;
305            memory->_wsuspended = true;
306            memory->_readable = false;
307            memory->_writeable = false;
308
309            memory->_isSaneFD = sane ? 1 : 0;
310            memory->_wantReadType = (callBackTypes & 0x3);
311            memory->_reenableRead = memory->_wantReadType ? true : false;
312            memory->_readDisabled = false;
313            memory->_wantWrite = (callBackTypes & kCFSocketWriteCallBack) ? true : false;
314            memory->_reenableWrite = false;
315            memory->_writeDisabled = false;
316            memory->_wantConnect = (callBackTypes & kCFSocketConnectCallBack) ? true : false;
317            memory->_connectDisabled = false;
318            memory->_leaveErrors = false;
319            memory->_closeOnInvalidate = true;
320            memory->_connOriented = (SOCK_STREAM == socketType || SOCK_SEQPACKET == socketType);
321            memory->_connected = (memory->_wantReadType == kCFSocketAcceptCallBack || !memory->_connOriented) ? true : false;
322
323            memory->_error = 0;
324            memory->_runLoopCounter = 0;
325            memory->_address = NULL;
326            memory->_peerAddress = NULL;
327            memory->_context.info = NULL;
328            memory->_context.retain = NULL;
329            memory->_context.release = NULL;
330            memory->_context.copyDescription = NULL;
331            memory->_callout = callout;
332            if (NULL != context) {
333                objc_memmove_collectable(&memory->_context, context, sizeof(CFSocketContext));
334                memory->_context.info = context->retain ? (void *)context->retain(context->info) : context->info;
335            }
336
337            struct __shared_blob *shared = malloc(sizeof(struct __shared_blob));
338            shared->_rdsrc = NULL;
339            shared->_wrsrc = NULL;
340            shared->_source = NULL;
341            shared->_socket = ufd;
342            shared->_closeFD = true; // copy of _closeOnInvalidate
343            shared->_refCnt = 1; // one for the CFSocket
344            memory->_shared = shared;
345
346            if (memory->_wantReadType) {
347                dispatch_source_t dsrc = NULL;
348                if (sane) {
349                    dsrc = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, ufd, 0, __sockQueue());
350                } else {
351                    dsrc = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, __sockQueue());
352                    dispatch_source_set_timer(dsrc, dispatch_time(DISPATCH_TIME_NOW, 0), NSEC_PER_SEC / 2, NSEC_PER_SEC);
353                }
354                dispatch_block_t event_block = ^{
355                        memory->_readable = true;
356                        if (!memory->_rsuspended) {
357                            dispatch_suspend(dsrc);
358// CFLog(5, CFSTR("suspend %p due to read event block"), memory);
359                            memory->_rsuspended = true;
360                        }
361                        if (shared->_source) {
362                            CFRunLoopSourceSignal(shared->_source);
363                            _CFRunLoopSourceWakeUpRunLoops(shared->_source);
364                        }
365                    };
366                dispatch_block_t cancel_block = ^{
367                        shared->_rdsrc = NULL;
368                        shared->_refCnt--;
369                        if (0 == shared->_refCnt) {
370                            if (shared->_closeFD) {
371                                // thoroughly stop anything else from using the fd
372                                (void)shutdown(shared->_socket, SHUT_RDWR);
373                                int nullfd = open("/dev/null", O_RDONLY);
374                                dup2(nullfd, shared->_socket);
375                                close(nullfd);
376                                close(shared->_socket);
377                            }
378                            free(shared);
379                        }
380                        dispatch_release(dsrc);
381                    };
382                dispatch_source_set_event_handler(dsrc, event_block);
383                dispatch_source_set_cancel_handler(dsrc, cancel_block);
384                shared->_rdsrc = dsrc;
385            }
386            if (memory->_wantWrite || memory->_wantConnect) {
387                dispatch_source_t dsrc = NULL;
388                if (sane) {
389                    dsrc = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, ufd, 0, __sockQueue());
390                } else {
391                    dsrc = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, __sockQueue());
392                    dispatch_source_set_timer(dsrc, dispatch_time(DISPATCH_TIME_NOW, 0), NSEC_PER_SEC / 2, NSEC_PER_SEC);
393                }
394                dispatch_block_t event_block = ^{
395                        memory->_writeable = true;
396                        if (!memory->_wsuspended) {
397                            dispatch_suspend(dsrc);
398// CFLog(5, CFSTR("suspend %p due to write event block"), memory);
399                            memory->_wsuspended = true;
400                        }
401                        if (shared->_source) {
402                            CFRunLoopSourceSignal(shared->_source);
403                            _CFRunLoopSourceWakeUpRunLoops(shared->_source);
404                        }
405                    };
406                dispatch_block_t cancel_block = ^{
407                        shared->_wrsrc = NULL;
408                        shared->_refCnt--;
409                        if (0 == shared->_refCnt) {
410                            if (shared->_closeFD) {
411                                // thoroughly stop anything else from using the fd
412                                (void)shutdown(shared->_socket, SHUT_RDWR);
413                                int nullfd = open("/dev/null", O_RDONLY);
414                                dup2(nullfd, shared->_socket);
415                                close(nullfd);
416                                close(shared->_socket);
417                            }
418                            free(shared);
419                        }
420                        dispatch_release(dsrc);
421                    };
422                dispatch_source_set_event_handler(dsrc, event_block);
423                dispatch_source_set_cancel_handler(dsrc, cancel_block);
424                shared->_wrsrc = dsrc;
425            }
426
427            if (shared->_rdsrc) {
428                shared->_refCnt++;
429            }
430            if (shared->_wrsrc) {
431                shared->_refCnt++;
432            }
433
434            memory->_state = kCFSocketStateReady;
435            CFArrayAppendValue(__CFAllSockets, memory);
436            sock = memory;
437        });
438// CFLog(5, CFSTR("CFSocketCreateWithNative(): created socket %p with callbacks 0x%x"), sock, callBackTypes);
439    if (sock && !CFSocketIsValid(sock)) { // must do this outside lock to avoid deadlock
440        CFRelease(sock);
441        sock = NULL;
442    }
443    return sock;
444}
445
446CFSocketNativeHandle CFSocketGetNative(CFSocketRef sock) {
447    CHECK_FOR_FORK_RET(INVALID_SOCKET);
448    __CFGenericValidateType(sock, CFSocketGetTypeID());
449    return sock->_shared ? sock->_shared->_socket : INVALID_SOCKET;
450}
451
452void CFSocketGetContext(CFSocketRef sock, CFSocketContext *context) {
453    __CFGenericValidateType(sock, CFSocketGetTypeID());
454    CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__);
455    objc_memmove_collectable(context, &sock->_context, sizeof(CFSocketContext));
456}
457
458CFDataRef CFSocketCopyAddress(CFSocketRef sock) {
459    CHECK_FOR_FORK_RET(NULL);
460    __CFGenericValidateType(sock, CFSocketGetTypeID());
461    __block CFDataRef result = NULL;
462    dispatch_sync(__sockQueue(), ^{
463            if (!sock->_address) {
464                if (!__CFSocketIsValid(sock)) return;
465                uint8_t name[MAX_SOCKADDR_LEN];
466                socklen_t namelen = sizeof(name);
467                int ret = getsockname(sock->_shared->_socket, (struct sockaddr *)name, (socklen_t *)&namelen);
468                if (0 == ret && 0 < namelen) {
469                    sock->_address = CFDataCreate(CFGetAllocator(sock), name, namelen);
470                }
471            }
472            result = sock->_address ? (CFDataRef)CFRetain(sock->_address) : NULL;
473        });
474    return result;
475}
476
477CFDataRef CFSocketCopyPeerAddress(CFSocketRef sock) {
478    CHECK_FOR_FORK_RET(NULL);
479    __CFGenericValidateType(sock, CFSocketGetTypeID());
480    __block CFDataRef result = NULL;
481    dispatch_sync(__sockQueue(), ^{
482            if (!sock->_peerAddress) {
483                if (!__CFSocketIsValid(sock)) return;
484                uint8_t name[MAX_SOCKADDR_LEN];
485                socklen_t namelen = sizeof(name);
486                int ret = getpeername(sock->_shared->_socket, (struct sockaddr *)name, (socklen_t *)&namelen);
487                if (0 == ret && 0 < namelen) {
488                    sock->_peerAddress = CFDataCreate(CFGetAllocator(sock), name, namelen);
489                }
490            }
491            result = sock->_peerAddress ? (CFDataRef)CFRetain(sock->_peerAddress) : NULL;
492        });
493    return result;
494}
495
496CFOptionFlags CFSocketGetSocketFlags(CFSocketRef sock) {
497    CHECK_FOR_FORK();
498    __CFGenericValidateType(sock, CFSocketGetTypeID());
499    __block CFOptionFlags flags = 0;
500    dispatch_sync(__sockQueue(), ^{
501            if (sock->_reenableRead) flags |= sock->_wantReadType; // flags are same as types here
502            if (sock->_reenableWrite) flags |= kCFSocketAutomaticallyReenableWriteCallBack;
503            if (sock->_leaveErrors) flags |= kCFSocketLeaveErrors;
504            if (sock->_closeOnInvalidate) flags |= kCFSocketCloseOnInvalidate;
505        });
506    return flags;
507}
508
509void CFSocketSetSocketFlags(CFSocketRef sock, CFOptionFlags flags) {
510    CHECK_FOR_FORK();
511// CFLog(5, CFSTR("CFSocketSetSocketFlags(%p, 0x%x) starting"), sock, flags);
512    __CFGenericValidateType(sock, CFSocketGetTypeID());
513    dispatch_sync(__sockQueue(), ^{
514            sock->_reenableRead = (sock->_wantReadType && ((flags & 0x3) == sock->_wantReadType)) ? true : false;
515            sock->_reenableWrite = (sock->_wantWrite && (flags & kCFSocketAutomaticallyReenableWriteCallBack)) ? true : false;
516            sock->_leaveErrors = (flags & kCFSocketLeaveErrors) ? true : false;
517            sock->_closeOnInvalidate = (flags & kCFSocketCloseOnInvalidate) ? true : false;
518            if (sock->_shared) sock->_shared->_closeFD = sock->_closeOnInvalidate;
519        });
520// CFLog(5, CFSTR("CFSocketSetSocketFlags(%p, 0x%x) done"), sock, flags);
521}
522
523void CFSocketEnableCallBacks(CFSocketRef sock, CFOptionFlags callBackTypes) {
524    CHECK_FOR_FORK_RET();
525    __CFGenericValidateType(sock, CFSocketGetTypeID());
526// CFLog(5, CFSTR("CFSocketEnableCallBacks(%p, 0x%x) starting"), sock, callBackTypes);
527    dispatch_sync(__sockQueue(), ^{
528            if (!__CFSocketIsValid(sock)) return;
529            if (sock->_wantReadType && (callBackTypes & 0x3) == sock->_wantReadType) {
530                if (sockfd_is_readable(sock->_shared->_socket)) {
531                    sock->_readable = true;
532// CFLog(5, CFSTR("CFSocketEnableCallBacks(%p, 0x%x) socket is readable"), sock, callBackTypes);
533                    if (!sock->_rsuspended) {
534                        dispatch_suspend(sock->_shared->_rdsrc);
535                        sock->_rsuspended = true;
536                    }
537                    // If the source exists, but is now invalid, this next stuff is relatively harmless.
538                    if (sock->_shared->_source) {
539                        CFRunLoopSourceSignal(sock->_shared->_source);
540                        _CFRunLoopSourceWakeUpRunLoops(sock->_shared->_source);
541                    }
542                } else if (sock->_rsuspended && sock->_shared->_rdsrc) {
543                    sock->_rsuspended = false;
544                    dispatch_resume(sock->_shared->_rdsrc);
545                }
546                sock->_readDisabled = false;
547            }
548            if (sock->_wantWrite && (callBackTypes & kCFSocketWriteCallBack)) {
549                if (sockfd_is_writeable(sock->_shared->_socket)) {
550                    sock->_writeable = true;
551                    if (!sock->_wsuspended) {
552                        dispatch_suspend(sock->_shared->_wrsrc);
553                        sock->_wsuspended = true;
554                    }
555                    // If the source exists, but is now invalid, this next stuff is relatively harmless.
556                    if (sock->_shared->_source) {
557                        CFRunLoopSourceSignal(sock->_shared->_source);
558                        _CFRunLoopSourceWakeUpRunLoops(sock->_shared->_source);
559                    }
560                } else if (sock->_wsuspended && sock->_shared->_wrsrc) {
561                    sock->_wsuspended = false;
562                    dispatch_resume(sock->_shared->_wrsrc);
563                }
564                sock->_writeDisabled = false;
565            }
566            if (sock->_wantConnect && !sock->_connected && (callBackTypes & kCFSocketConnectCallBack)) {
567                if (sockfd_is_writeable(sock->_shared->_socket)) {
568                    sock->_writeable = true;
569                    if (!sock->_wsuspended) {
570                        dispatch_suspend(sock->_shared->_wrsrc);
571                        sock->_wsuspended = true;
572                    }
573                    // If the source exists, but is now invalid, this next stuff is relatively harmless.
574                    if (sock->_shared->_source) {
575                        CFRunLoopSourceSignal(sock->_shared->_source);
576                        _CFRunLoopSourceWakeUpRunLoops(sock->_shared->_source);
577                    }
578                } else if (sock->_wsuspended && sock->_shared->_wrsrc) {
579                    sock->_wsuspended = false;
580                    dispatch_resume(sock->_shared->_wrsrc);
581                }
582                sock->_connectDisabled = false;
583            }
584        });
585// CFLog(5, CFSTR("CFSocketEnableCallBacks(%p, 0x%x) done"), sock, callBackTypes);
586}
587
588void CFSocketDisableCallBacks(CFSocketRef sock, CFOptionFlags callBackTypes) {
589    CHECK_FOR_FORK_RET();
590    __CFGenericValidateType(sock, CFSocketGetTypeID());
591// CFLog(5, CFSTR("CFSocketDisableCallBacks(%p, 0x%x) starting"), sock, callBackTypes);
592    dispatch_sync(__sockQueue(), ^{
593            if (!__CFSocketIsValid(sock)) return;
594            if (sock->_wantReadType && (callBackTypes & 0x3) == sock->_wantReadType) {
595                if (!sock->_rsuspended && sock->_shared->_rdsrc) {
596                    dispatch_suspend(sock->_shared->_rdsrc);
597                    sock->_rsuspended = true;
598                }
599                sock->_readDisabled = true;
600            }
601            if (sock->_wantWrite && (callBackTypes & kCFSocketWriteCallBack)) {
602                if (!sock->_wsuspended && sock->_shared->_wrsrc) {
603                    dispatch_suspend(sock->_shared->_wrsrc);
604                    sock->_wsuspended = true;
605                }
606                sock->_writeDisabled = true;
607            }
608            if (sock->_wantConnect && !sock->_connected && (callBackTypes & kCFSocketConnectCallBack)) {
609                if (!sock->_wsuspended && sock->_shared->_wrsrc) {
610                    dispatch_suspend(sock->_shared->_wrsrc);
611                    sock->_wsuspended = true;
612                }
613                sock->_connectDisabled = true;
614            }
615        });
616// CFLog(5, CFSTR("CFSocketDisableCallBacks(%p, 0x%x) done"), sock, callBackTypes);
617}
618
619void CFSocketInvalidate(CFSocketRef sock) {
620    CHECK_FOR_FORK_RET();
621    __CFGenericValidateType(sock, CFSocketGetTypeID());
622    CFRetain(sock);
623// CFLog(5, CFSTR("CFSocketInvalidate(%p) starting"), sock);
624    __block CFRunLoopSourceRef source = NULL;
625    __block Boolean wasReady = false;
626    dispatch_sync(__sockQueue(), ^{
627            wasReady = (sock->_state == kCFSocketStateReady);
628            if (wasReady) {
629                sock->_state = kCFSocketStateInvalidating;
630                OSMemoryBarrier();
631                for (CFIndex idx = 0, cnt = CFArrayGetCount(__CFAllSockets); idx < cnt; idx++) {
632                    CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFAllSockets, idx);
633                    if (s == sock) {
634                        CFArrayRemoveValueAtIndex(__CFAllSockets, idx);
635                        break;
636                    }
637                }
638                if (sock->_shared->_rdsrc) {
639                    dispatch_source_cancel(sock->_shared->_rdsrc);
640                    if (sock->_rsuspended) {
641                        sock->_rsuspended = false;
642                        dispatch_resume(sock->_shared->_rdsrc);
643                    }
644                }
645                if (sock->_shared->_wrsrc) {
646                    dispatch_source_cancel(sock->_shared->_wrsrc);
647                    if (sock->_wsuspended) {
648                        sock->_wsuspended = false;
649                        dispatch_resume(sock->_shared->_wrsrc);
650                    }
651                }
652                source = sock->_shared->_source;
653                sock->_shared->_source = NULL;
654                sock->_shared->_refCnt--;
655                if (0 == sock->_shared->_refCnt) {
656                    if (sock->_shared->_closeFD) {
657                        // thoroughly stop anything else from using the fd
658                        (void)shutdown(sock->_shared->_socket, SHUT_RDWR);
659                        int nullfd = open("/dev/null", O_RDONLY);
660                        dup2(nullfd, sock->_shared->_socket);
661                        close(nullfd);
662                        close(sock->_shared->_socket);
663                    }
664                    free(sock->_shared);
665                }
666                sock->_shared = NULL;
667            }
668        });
669    if (wasReady) {
670        if (NULL != source) {
671            CFRunLoopSourceInvalidate(source);
672            CFRelease(source);
673        }
674        void *info = sock->_context.info;
675        sock->_context.info = NULL;
676        if (sock->_context.release) {
677            sock->_context.release(info);
678        }
679        sock->_state = kCFSocketStateInvalid;
680        OSMemoryBarrier();
681    }
682// CFLog(5, CFSTR("CFSocketInvalidate(%p) done%s"), sock, wasReady ? " -- done on this thread" : "");
683    CFRelease(sock);
684}
685
686Boolean CFSocketIsValid(CFSocketRef sock) {
687    __CFGenericValidateType(sock, CFSocketGetTypeID());
688    if (!__CFSocketIsValid(sock)) return false;
689    struct stat statbuf;
690    int ret = sock->_shared ? fstat(sock->_shared->_socket, &statbuf) : -1;
691    if (ret < 0) {
692	CFSocketInvalidate(sock);
693	return false;
694    }
695    return true;
696}
697
698
699static void __CFSocketPerform(void *info) { // CFRunLoop should only call this on one thread at a time
700    CHECK_FOR_FORK_RET();
701    CFSocketRef sock = (CFSocketRef)info;
702
703// CFLog(5, CFSTR("__CFSocketPerform(%p) starting '%@'"), sock, sock);
704    __block Boolean doRead = false, doWrite = false, doConnect = false, isValid = false;
705    __block int fd = INVALID_SOCKET;
706    __block SInt32 errorCode = 0;
707    __block int new_fd = INVALID_SOCKET;
708    __block CFDataRef address = NULL;
709    __block CFMutableDataRef data = NULL;
710    __block void *context_info = NULL;
711    __block void (*context_release)(const void *) = NULL;
712    dispatch_sync(__sockQueue(), ^{
713            isValid = __CFSocketIsValid(sock);
714            if (!isValid) return;
715            fd = sock->_shared->_socket;
716            doRead = sock->_readable && sock->_wantReadType && !sock->_readDisabled;
717            if (doRead) {
718                sock->_readable = false;
719                doRead = sockfd_is_readable(fd);
720// if (!doRead) CFLog(5, CFSTR("__CFSocketPerform(%p) socket is not actually readable"), sock);
721            }
722            doWrite = sock->_writeable && sock->_wantWrite && !sock->_writeDisabled;
723            doConnect = sock->_writeable && sock->_wantConnect && !sock->_connectDisabled && !sock->_connected;
724            if (doWrite || doConnect) {
725                sock->_writeable = false;
726                if (doWrite) doWrite = sockfd_is_writeable(fd);
727                if (doConnect) doConnect = sockfd_is_writeable(fd);
728            }
729            if (!sock->_leaveErrors && (doWrite || doConnect)) { // not on read, for whatever reason
730                int errorSize = sizeof(errorCode);
731                int ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&errorCode, (socklen_t *)&errorSize);
732                if (0 != ret) errorCode = 0;
733                sock->_error = errorCode;
734            }
735            sock->_connected = true;
736// CFLog(5, CFSTR("__CFSocketPerform(%p) doing %d %d %d"), sock, doRead, doWrite, doConnect);
737            if (doRead) {
738                switch (sock->_wantReadType) {
739                case kCFSocketReadCallBack:
740                    break;
741                case kCFSocketAcceptCallBack: {
742                    uint8_t name[MAX_SOCKADDR_LEN];
743                    socklen_t namelen = sizeof(name);
744                    new_fd = accept(fd, (struct sockaddr *)name, (socklen_t *)&namelen);
745                    if (INVALID_SOCKET != new_fd) {
746                        address = CFDataCreate(CFGetAllocator(sock), name, namelen);
747                    }
748                    break;
749                }
750                case kCFSocketDataCallBack: {
751                    uint8_t name[MAX_SOCKADDR_LEN];
752                    socklen_t namelen = sizeof(name);
753                    int avail = 0;
754                    int ret = ioctlsocket(fd, FIONREAD, &avail);
755                    if (ret < 0 || avail < 256) avail = 256;
756                    if ((1 << 20) < avail) avail = (1 << 20);
757                    data = CFDataCreateMutable(CFGetAllocator(sock), 0);
758                    CFDataSetLength(data, avail);
759                    ssize_t len = recvfrom(fd, CFDataGetMutableBytePtr(data), avail, 0, (struct sockaddr *)name, (socklen_t *)&namelen);
760                    CFIndex datalen = (len < 0) ? 0 : len;
761                    CFDataSetLength(data, datalen);
762                    if (0 < namelen) {
763                        address = CFDataCreate(CFGetAllocator(sock), name, namelen);
764                    } else if (sock->_connOriented) {
765                        // cannot call CFSocketCopyPeerAddress(), or deadlock
766                        if (!sock->_peerAddress) {
767                            uint8_t name[MAX_SOCKADDR_LEN];
768                            socklen_t namelen = sizeof(name);
769                            int ret = getpeername(sock->_shared->_socket, (struct sockaddr *)name, (socklen_t *)&namelen);
770                            if (0 == ret && 0 < namelen) {
771                                sock->_peerAddress = CFDataCreate(CFGetAllocator(sock), name, namelen);
772                            }
773                        }
774                        address = sock->_peerAddress ? (CFDataRef)CFRetain(sock->_peerAddress) : NULL;
775                    }
776                    if (NULL == address) {
777                        address = CFDataCreate(CFGetAllocator(sock), NULL, 0);
778                    }
779                    break;
780                }
781                }
782            }
783            if (sock->_reenableRead) {
784// CFLog(5, CFSTR("__CFSocketPerform(%p) reenabling read %d %p"), sock, sock->_rsuspended, sock->_shared->_rdsrc);
785                if (sock->_rsuspended && sock->_shared->_rdsrc) {
786                    sock->_rsuspended = false;
787                    dispatch_resume(sock->_shared->_rdsrc);
788                }
789            }
790            if (sock->_reenableWrite) {
791                if (sock->_wsuspended && sock->_shared->_wrsrc) {
792                    sock->_wsuspended = false;
793                    dispatch_resume(sock->_shared->_wrsrc);
794                }
795            }
796            if (sock->_context.retain && (doConnect || doRead || doWrite)) {
797                context_info = (void *)sock->_context.retain(sock->_context.info);
798                context_release = sock->_context.release;
799            } else {
800                context_info = sock->_context.info;
801            }
802        });
803// CFLog(5, CFSTR("__CFSocketPerform(%p) isValid:%d, doRead:%d, doWrite:%d, doConnect:%d error:%d"), sock, isValid, doRead, doWrite, doConnect, errorCode);
804    if (!isValid || !(doConnect || doRead || doWrite)) return;
805
806    Boolean calledOut = false;
807    if (doConnect) {
808        if (sock->_callout) sock->_callout(sock, kCFSocketConnectCallBack, NULL, (0 != errorCode) ? &errorCode : NULL, context_info);
809        calledOut = true;
810    }
811    if (doRead && (!calledOut || __CFSocketIsValid(sock))) {
812        switch (sock->_wantReadType) {
813        case kCFSocketReadCallBack:
814            if (sock->_callout) sock->_callout(sock, kCFSocketReadCallBack, NULL, NULL, context_info);
815            calledOut = true;
816            break;
817        case kCFSocketAcceptCallBack:
818            if (INVALID_SOCKET != new_fd) {
819                if (sock->_callout) sock->_callout(sock, kCFSocketAcceptCallBack, address, &new_fd, context_info);
820                calledOut = true;
821            }
822            break;
823        case kCFSocketDataCallBack:
824            if (sock->_callout) sock->_callout(sock, kCFSocketDataCallBack, address, data, context_info);
825            calledOut = true;
826            break;
827        }
828    }
829    if (doWrite && (!calledOut || __CFSocketIsValid(sock))) {
830        if (0 == errorCode) {
831            if (sock->_callout) sock->_callout(sock, kCFSocketWriteCallBack, NULL, NULL, context_info);
832            calledOut = true;
833        }
834    }
835
836    if (data && 0 == CFDataGetLength(data)) CFSocketInvalidate(sock);
837    if (address) CFRelease(address);
838    if (data) CFRelease(data);
839    if (context_release) {
840        context_release(context_info);
841    }
842
843    CHECK_FOR_FORK_RET();
844// CFLog(5, CFSTR("__CFSocketPerform(%p) done"), sock);
845}
846
847static void __CFSocketSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) {
848    CFSocketRef sock = (CFSocketRef)info;
849    int32_t newVal = OSAtomicIncrement32Barrier(&sock->_runLoopCounter);
850    if (1 == newVal) { // on a transition from 0->1, the old code forced all desired callbacks enabled
851        CFOptionFlags types = sock->_wantReadType | (sock->_wantWrite ? kCFSocketWriteCallBack : 0) | (sock->_wantConnect ? kCFSocketConnectCallBack : 0);
852        CFSocketEnableCallBacks(sock, types);
853    }
854    CFRunLoopWakeUp(rl);
855}
856
857static void __CFSocketCancel(void *info, CFRunLoopRef rl, CFStringRef mode) {
858    CFSocketRef sock = (CFSocketRef)info;
859    OSAtomicDecrement32Barrier(&sock->_runLoopCounter);
860    CFRunLoopWakeUp(rl);
861}
862
863CFRunLoopSourceRef CFSocketCreateRunLoopSource(CFAllocatorRef allocator, CFSocketRef sock, CFIndex order) {
864    CHECK_FOR_FORK_RET(NULL);
865    __CFGenericValidateType(sock, CFSocketGetTypeID());
866    if (!CFSocketIsValid(sock)) return NULL;
867    __block CFRunLoopSourceRef result = NULL;
868    dispatch_sync(__sockQueue(), ^{
869            if (!__CFSocketIsValid(sock)) return;
870            if (NULL != sock->_shared->_source && !CFRunLoopSourceIsValid(sock->_shared->_source)) {
871                CFRelease(sock->_shared->_source);
872                sock->_shared->_source = NULL;
873            }
874            if (NULL == sock->_shared->_source) {
875                CFRunLoopSourceContext context;
876                context.version = 0;
877                context.info = (void *)sock;
878                context.retain = (const void *(*)(const void *))CFRetain;
879                context.release = (void (*)(const void *))CFRelease;
880                context.copyDescription = (CFStringRef (*)(const void *))__CFSocketCopyDescription;
881                context.equal = NULL;
882                context.hash = NULL;
883                context.schedule = __CFSocketSchedule;
884                context.cancel = __CFSocketCancel;
885                context.perform = __CFSocketPerform;
886                sock->_shared->_source = CFRunLoopSourceCreate(allocator, order, (CFRunLoopSourceContext *)&context);
887                if (sock->_shared->_source) {
888                    if (sock->_wantReadType) {
889                        if (sockfd_is_readable(sock->_shared->_socket)) {
890                            sock->_readable = true;
891                            if (!sock->_rsuspended) {
892                                dispatch_suspend(sock->_shared->_rdsrc);
893                                sock->_rsuspended = true;
894                            }
895                            if (sock->_shared->_source) {
896                                CFRunLoopSourceSignal(sock->_shared->_source);
897                                _CFRunLoopSourceWakeUpRunLoops(sock->_shared->_source);
898                            }
899                        } else if (sock->_rsuspended && sock->_shared->_rdsrc) {
900                            sock->_rsuspended = false;
901                            dispatch_resume(sock->_shared->_rdsrc);
902                        }
903                    }
904                    if (sock->_wantWrite || (sock->_wantConnect && !sock->_connected)) {
905                        if (sockfd_is_writeable(sock->_shared->_socket)) {
906                            sock->_writeable = true;
907                            if (!sock->_wsuspended) {
908                                dispatch_suspend(sock->_shared->_wrsrc);
909                                sock->_wsuspended = true;
910                            }
911                            if (sock->_shared->_source) {
912                                CFRunLoopSourceSignal(sock->_shared->_source);
913                                _CFRunLoopSourceWakeUpRunLoops(sock->_shared->_source);
914                            }
915                        } else if (sock->_wsuspended && sock->_shared->_wrsrc) {
916                            sock->_wsuspended = false;
917                            dispatch_resume(sock->_shared->_wrsrc);
918                        }
919                    }
920                }
921            }
922            result = sock->_shared->_source ? (CFRunLoopSourceRef)CFRetain(sock->_shared->_source) : NULL;
923        });
924// CFLog(5, CFSTR("CFSocketCreateRunLoopSource(%p) => %p"), sock, result);
925    return result;
926}
927
928
929void __CFSocketSetSocketReadBufferAttrs(CFSocketRef s, CFTimeInterval timeout, CFIndex length) {
930}
931
932CFIndex __CFSocketRead(CFSocketRef s, UInt8* buffer, CFIndex length, int* error) {
933    *error = 0;
934    int ret = read(CFSocketGetNative(s), buffer, length);
935    if (ret < 0) {
936        *error = errno;
937    }
938    return ret;
939}
940
941Boolean __CFSocketGetBytesAvailable(CFSocketRef s, CFIndex* ctBytesAvailable) {
942    int bytesAvailable;
943    int ret = ioctlsocket(CFSocketGetNative(s), FIONREAD, &bytesAvailable);
944    if (ret < 0) return false;
945    *ctBytesAvailable = (CFIndex)bytesAvailable;
946    return true;
947}
948
949*/
950#else /* not NEW_SOCKET */
951
952
953#include <CoreFoundation/CFSocket.h>
954#include <sys/types.h>
955#include <math.h>
956#include <limits.h>
957#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
958#include <sys/sysctl.h>
959#include <sys/un.h>
960#include <libc.h>
961#include <dlfcn.h>
962#endif
963#include <CoreFoundation/CFArray.h>
964#include <CoreFoundation/CFData.h>
965#include <CoreFoundation/CFDictionary.h>
966#include <CoreFoundation/CFRunLoop.h>
967#include <CoreFoundation/CFString.h>
968#include <CoreFoundation/CFPropertyList.h>
969#include "CFInternal.h"
970
971#if DEPLOYMENT_TARGET_WINDOWS
972
973#define EINPROGRESS WSAEINPROGRESS
974
975// redefine this to the winsock error in this file
976#undef EBADF
977#define EBADF WSAENOTSOCK
978
979#define NBBY 8
980#define NFDBITS	(sizeof(int32_t) * NBBY)
981
982typedef int32_t fd_mask;
983typedef int socklen_t;
984
985#define gettimeofday _NS_gettimeofday
986CF_PRIVATE int _NS_gettimeofday(struct timeval *tv, struct timezone *tz);
987
988// although this is only used for debug info, we define it for compatibility
989#define	timersub(tvp, uvp, vvp) \
990    do { \
991        (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;		\
992        (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec;	\
993        if ((vvp)->tv_usec < 0) {				\
994            (vvp)->tv_sec--;				\
995            (vvp)->tv_usec += 1000000;			\
996        }							\
997    } while (0)
998
999
1000#endif // DEPLOYMENT_TARGET_WINDOWS
1001
1002
1003// On Mach we use a v0 RunLoopSource to make client callbacks.  That source is signalled by a
1004// separate SocketManager thread who uses select() to watch the sockets' fds.
1005
1006//#define LOG_CFSOCKET
1007
1008#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1009#define INVALID_SOCKET (CFSocketNativeHandle)(-1)
1010#define closesocket(a) close((a))
1011#define ioctlsocket(a,b,c) ioctl((a),(b),(c))
1012#endif
1013
1014CF_INLINE int __CFSocketLastError(void) {
1015#if DEPLOYMENT_TARGET_WINDOWS
1016    return WSAGetLastError();
1017#else
1018    return thread_errno();
1019#endif
1020}
1021
1022CF_INLINE CFIndex __CFSocketFdGetSize(CFDataRef fdSet) {
1023    return NBBY * CFDataGetLength(fdSet);
1024}
1025
1026CF_INLINE Boolean __CFSocketFdSet(CFSocketNativeHandle sock, CFMutableDataRef fdSet) {
1027    /* returns true if a change occurred, false otherwise */
1028    Boolean retval = false;
1029    if (INVALID_SOCKET != sock && 0 <= sock) {
1030        CFIndex numFds = NBBY * CFDataGetLength(fdSet);
1031        fd_mask *fds_bits;
1032        if (sock >= numFds) {
1033            CFIndex oldSize = numFds / NFDBITS, newSize = (sock + NFDBITS) / NFDBITS, changeInBytes = (newSize - oldSize) * sizeof(fd_mask);
1034            CFDataIncreaseLength(fdSet, changeInBytes);
1035            fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
1036            memset(fds_bits + oldSize, 0, changeInBytes);
1037        } else {
1038            fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
1039        }
1040        if (!FD_ISSET(sock, (fd_set *)fds_bits)) {
1041            retval = true;
1042            FD_SET(sock, (fd_set *)fds_bits);
1043        }
1044    }
1045    return retval;
1046}
1047
1048
1049#define MAX_SOCKADDR_LEN 256
1050#define MAX_DATA_SIZE 65535
1051#define MAX_CONNECTION_ORIENTED_DATA_SIZE 32768
1052
1053/* locks are to be acquired in the following order:
1054   (1) __CFAllSocketsLock
1055   (2) an individual CFSocket's lock
1056   (3) __CFActiveSocketsLock
1057*/
1058static CFSpinLock_t __CFAllSocketsLock = CFSpinLockInit; /* controls __CFAllSockets */
1059static CFMutableDictionaryRef __CFAllSockets = NULL;
1060static CFSpinLock_t __CFActiveSocketsLock = CFSpinLockInit; /* controls __CFRead/WriteSockets, __CFRead/WriteSocketsFds, __CFSocketManagerThread, and __CFSocketManagerIteration */
1061static volatile UInt32 __CFSocketManagerIteration = 0;
1062static CFMutableArrayRef __CFWriteSockets = NULL;
1063static CFMutableArrayRef __CFReadSockets = NULL;
1064static CFMutableDataRef __CFWriteSocketsFds = NULL;
1065static CFMutableDataRef __CFReadSocketsFds = NULL;
1066static CFDataRef zeroLengthData = NULL;
1067static Boolean __CFReadSocketsTimeoutInvalid = true;  /* rebuild the timeout value before calling select */
1068
1069static CFSocketNativeHandle __CFWakeupSocketPair[2] = {INVALID_SOCKET, INVALID_SOCKET};
1070static void *__CFSocketManagerThread = NULL;
1071
1072static void __CFSocketDoCallback(CFSocketRef s, CFDataRef data, CFDataRef address, CFSocketNativeHandle sock);
1073
1074struct __CFSocket {
1075    CFRuntimeBase _base;
1076    struct {
1077        unsigned client:8;	// flags set by client (reenable, CloseOnInvalidate)
1078        unsigned disabled:8;	// flags marking disabled callbacks
1079        unsigned connected:1;	// Are we connected yet?  (also true for connectionless sockets)
1080        unsigned writableHint:1;  // Did the polling the socket show it to be writable?
1081        unsigned closeSignaled:1;  // Have we seen FD_CLOSE? (only used on Win32)
1082        unsigned unused:13;
1083    } _f;
1084    CFSpinLock_t _lock;
1085    CFSpinLock_t _writeLock;
1086    CFSocketNativeHandle _socket;	/* immutable */
1087    SInt32 _socketType;
1088    SInt32 _errorCode;
1089    CFDataRef _address;
1090    CFDataRef _peerAddress;
1091    SInt32 _socketSetCount;
1092    CFRunLoopSourceRef _source0;	// v0 RLS, messaged from SocketMgr
1093    CFMutableArrayRef _runLoops;
1094    CFSocketCallBack _callout;		/* immutable */
1095    CFSocketContext _context;		/* immutable */
1096    CFMutableArrayRef _dataQueue;	// queues to pass data from SocketMgr thread
1097    CFMutableArrayRef _addressQueue;
1098
1099	struct timeval _readBufferTimeout;
1100	CFMutableDataRef _readBuffer;
1101	CFIndex _bytesToBuffer;			/* is length of _readBuffer */
1102	CFIndex _bytesToBufferPos;		/* where the next _CFSocketRead starts from */
1103	CFIndex _bytesToBufferReadPos;	/* Where the buffer will next be read into (always after _bytesToBufferPos, but less than _bytesToBuffer) */
1104	Boolean _atEOF;
1105    int _bufferedReadError;
1106
1107	CFMutableDataRef _leftoverBytes;
1108};
1109
1110/* Bit 6 in the base reserved bits is used for write-signalled state (mutable) */
1111/* Bit 5 in the base reserved bits is used for read-signalled state (mutable) */
1112/* Bit 4 in the base reserved bits is used for invalid state (mutable) */
1113/* Bits 0-3 in the base reserved bits are used for callback types (immutable) */
1114/* Of this, bits 0-1 are used for the read callback type. */
1115
1116CF_INLINE Boolean __CFSocketIsWriteSignalled(CFSocketRef s) {
1117    return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 6, 6);
1118}
1119
1120CF_INLINE void __CFSocketSetWriteSignalled(CFSocketRef s) {
1121    __CFBitfieldSetValue(((CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 6, 6, 1);
1122}
1123
1124CF_INLINE void __CFSocketUnsetWriteSignalled(CFSocketRef s) {
1125    __CFBitfieldSetValue(((CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 6, 6, 0);
1126}
1127
1128CF_INLINE Boolean __CFSocketIsReadSignalled(CFSocketRef s) {
1129    return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 5, 5);
1130}
1131
1132CF_INLINE void __CFSocketSetReadSignalled(CFSocketRef s) {
1133    __CFBitfieldSetValue(((CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 5, 5, 1);
1134}
1135
1136CF_INLINE void __CFSocketUnsetReadSignalled(CFSocketRef s) {
1137    __CFBitfieldSetValue(((CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 5, 5, 0);
1138}
1139
1140CF_INLINE Boolean __CFSocketIsValid(CFSocketRef s) {
1141    return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 4, 4);
1142}
1143
1144CF_INLINE void __CFSocketSetValid(CFSocketRef s) {
1145    __CFBitfieldSetValue(((CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 4, 4, 1);
1146}
1147
1148CF_INLINE void __CFSocketUnsetValid(CFSocketRef s) {
1149    __CFBitfieldSetValue(((CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 4, 4, 0);
1150}
1151
1152CF_INLINE uint8_t __CFSocketCallBackTypes(CFSocketRef s) {
1153    return (uint8_t)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 3, 0);
1154}
1155
1156CF_INLINE uint8_t __CFSocketReadCallBackType(CFSocketRef s) {
1157    return (uint8_t)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 1, 0);
1158}
1159
1160CF_INLINE void __CFSocketSetCallBackTypes(CFSocketRef s, uint8_t types) {
1161    __CFBitfieldSetValue(((CFRuntimeBase *)s)->_cfinfo[CF_INFO_BITS], 3, 0, types & 0xF);
1162}
1163
1164CF_INLINE void __CFSocketLock(CFSocketRef s) {
1165    __CFSpinLock(&(s->_lock));
1166}
1167
1168CF_INLINE void __CFSocketUnlock(CFSocketRef s) {
1169    __CFSpinUnlock(&(s->_lock));
1170}
1171
1172CF_INLINE Boolean __CFSocketIsConnectionOriented(CFSocketRef s) {
1173    return (SOCK_STREAM == s->_socketType || SOCK_SEQPACKET == s->_socketType);
1174}
1175
1176CF_INLINE Boolean __CFSocketIsScheduled(CFSocketRef s) {
1177    return (s->_socketSetCount > 0);
1178}
1179
1180CF_INLINE void __CFSocketEstablishAddress(CFSocketRef s) {
1181    /* socket should already be locked */
1182    uint8_t name[MAX_SOCKADDR_LEN];
1183    int namelen = sizeof(name);
1184    if (__CFSocketIsValid(s) && NULL == s->_address && INVALID_SOCKET != s->_socket && 0 == getsockname(s->_socket, (struct sockaddr *)name, (socklen_t *)&namelen) && NULL != name && 0 < namelen) {
1185        s->_address = CFDataCreate(CFGetAllocator(s), name, namelen);
1186    }
1187}
1188
1189CF_INLINE void __CFSocketEstablishPeerAddress(CFSocketRef s) {
1190    /* socket should already be locked */
1191    uint8_t name[MAX_SOCKADDR_LEN];
1192    int namelen = sizeof(name);
1193    if (__CFSocketIsValid(s) && NULL == s->_peerAddress && INVALID_SOCKET != s->_socket && 0 == getpeername(s->_socket, (struct sockaddr *)name, (socklen_t *)&namelen) && NULL != name && 0 < namelen) {
1194        s->_peerAddress = CFDataCreate(CFGetAllocator(s), name, namelen);
1195    }
1196}
1197
1198static Boolean __CFNativeSocketIsValid(CFSocketNativeHandle sock) {
1199#if DEPLOYMENT_TARGET_WINDOWS
1200    SInt32 errorCode = 0;
1201    int errorSize = sizeof(errorCode);
1202    return !(0 != getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&errorCode, &errorSize) && __CFSocketLastError() == WSAENOTSOCK);
1203#else
1204    SInt32 flags = fcntl(sock, F_GETFL, 0);
1205    return !(0 > flags && EBADF == __CFSocketLastError());
1206#endif
1207}
1208
1209CF_INLINE Boolean __CFSocketFdClr(CFSocketNativeHandle sock, CFMutableDataRef fdSet) {
1210    /* returns true if a change occurred, false otherwise */
1211    Boolean retval = false;
1212    if (INVALID_SOCKET != sock && 0 <= sock) {
1213        CFIndex numFds = NBBY * CFDataGetLength(fdSet);
1214        fd_mask *fds_bits;
1215        if (sock < numFds) {
1216            fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
1217            if (FD_ISSET(sock, (fd_set *)fds_bits)) {
1218                retval = true;
1219                FD_CLR(sock, (fd_set *)fds_bits);
1220            }
1221        }
1222    }
1223    return retval;
1224}
1225
1226static SInt32 __CFSocketCreateWakeupSocketPair(void) {
1227#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1228    SInt32 error;
1229
1230    error = socketpair(PF_LOCAL, SOCK_DGRAM, 0, __CFWakeupSocketPair);
1231    if (0 <= error) error = fcntl(__CFWakeupSocketPair[0], F_SETFD, FD_CLOEXEC);
1232    if (0 <= error) error = fcntl(__CFWakeupSocketPair[1], F_SETFD, FD_CLOEXEC);
1233    if (0 > error) {
1234        closesocket(__CFWakeupSocketPair[0]);
1235        closesocket(__CFWakeupSocketPair[1]);
1236        __CFWakeupSocketPair[0] = INVALID_SOCKET;
1237        __CFWakeupSocketPair[1] = INVALID_SOCKET;
1238    }
1239#else
1240    UInt32 i;
1241    SInt32 error = 0;
1242    struct sockaddr_in address[2];
1243    int namelen = sizeof(struct sockaddr_in);
1244    for (i = 0; i < 2; i++) {
1245        __CFWakeupSocketPair[i] = socket(PF_INET, SOCK_DGRAM, 0);
1246        memset(&(address[i]), 0, sizeof(struct sockaddr_in));
1247        address[i].sin_family = AF_INET;
1248        address[i].sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1249        if (0 <= error) error = bind(__CFWakeupSocketPair[i], (struct sockaddr *)&(address[i]), sizeof(struct sockaddr_in));
1250        if (0 <= error) error = getsockname(__CFWakeupSocketPair[i], (struct sockaddr *)&(address[i]), &namelen);
1251        if (sizeof(struct sockaddr_in) != namelen) error = -1;
1252    }
1253    if (0 <= error) error = connect(__CFWakeupSocketPair[0], (struct sockaddr *)&(address[1]), sizeof(struct sockaddr_in));
1254    if (0 <= error) error = connect(__CFWakeupSocketPair[1], (struct sockaddr *)&(address[0]), sizeof(struct sockaddr_in));
1255    if (0 > error) {
1256        closesocket(__CFWakeupSocketPair[0]);
1257        closesocket(__CFWakeupSocketPair[1]);
1258        __CFWakeupSocketPair[0] = INVALID_SOCKET;
1259        __CFWakeupSocketPair[1] = INVALID_SOCKET;
1260    }
1261#endif
1262#if defined(LOG_CFSOCKET)
1263    fprintf(stdout, "wakeup socket pair is %d / %d\n", __CFWakeupSocketPair[0], __CFWakeupSocketPair[1]);
1264#endif
1265    return error;
1266}
1267
1268
1269// Version 0 RunLoopSources set a mask in an FD set to control what socket activity we hear about.
1270// Changes to the master fs_sets occur via these 4 functions.
1271CF_INLINE Boolean __CFSocketSetFDForRead(CFSocketRef s) {
1272    __CFReadSocketsTimeoutInvalid = true;
1273    Boolean b = __CFSocketFdSet(s->_socket, __CFReadSocketsFds);
1274    if (b && INVALID_SOCKET != __CFWakeupSocketPair[0]) {
1275        uint8_t c = 'r';
1276        send(__CFWakeupSocketPair[0], (const char *)&c, sizeof(c), 0);
1277    }
1278    return b;
1279}
1280
1281CF_INLINE Boolean __CFSocketClearFDForRead(CFSocketRef s) {
1282    __CFReadSocketsTimeoutInvalid = true;
1283    Boolean b = __CFSocketFdClr(s->_socket, __CFReadSocketsFds);
1284    if (b && INVALID_SOCKET != __CFWakeupSocketPair[0]) {
1285        uint8_t c = 's';
1286        send(__CFWakeupSocketPair[0], (const char *)&c, sizeof(c), 0);
1287    }
1288    return b;
1289}
1290
1291CF_INLINE Boolean __CFSocketSetFDForWrite(CFSocketRef s) {
1292// CFLog(5, CFSTR("__CFSocketSetFDForWrite(%p)"), s);
1293    Boolean b = __CFSocketFdSet(s->_socket, __CFWriteSocketsFds);
1294    if (b && INVALID_SOCKET != __CFWakeupSocketPair[0]) {
1295        uint8_t c = 'w';
1296        send(__CFWakeupSocketPair[0], (const char *)&c, sizeof(c), 0);
1297    }
1298    return b;
1299}
1300
1301CF_INLINE Boolean __CFSocketClearFDForWrite(CFSocketRef s) {
1302// CFLog(5, CFSTR("__CFSocketClearFDForWrite(%p)"), s);
1303    Boolean b = __CFSocketFdClr(s->_socket, __CFWriteSocketsFds);
1304    if (b && INVALID_SOCKET != __CFWakeupSocketPair[0]) {
1305        uint8_t c = 'x';
1306        send(__CFWakeupSocketPair[0], (const char *)&c, sizeof(c), 0);
1307    }
1308    return b;
1309}
1310
1311#if DEPLOYMENT_TARGET_WINDOWS
1312static Boolean WinSockUsed = FALSE;
1313
1314static void __CFSocketInitializeWinSock_Guts(void) {
1315    if (!WinSockUsed) {
1316        WinSockUsed = TRUE;
1317        WORD versionRequested = MAKEWORD(2, 2);
1318        WSADATA wsaData;
1319        int errorStatus = WSAStartup(versionRequested, &wsaData);
1320        if (errorStatus != 0 || LOBYTE(wsaData.wVersion) != LOBYTE(versionRequested) || HIBYTE(wsaData.wVersion) != HIBYTE(versionRequested)) {
1321            WSACleanup();
1322            CFLog(kCFLogLevelWarning, CFSTR("*** Could not initialize WinSock subsystem!!!"));
1323        }
1324    }
1325}
1326
1327CF_EXPORT void __CFSocketInitializeWinSock(void) {
1328    __CFSpinLock(&__CFActiveSocketsLock);
1329    __CFSocketInitializeWinSock_Guts();
1330    __CFSpinUnlock(&__CFActiveSocketsLock);
1331}
1332
1333CF_PRIVATE void __CFSocketCleanup(void) {
1334    if (INVALID_SOCKET != __CFWakeupSocketPair[0]) {
1335        closesocket(__CFWakeupSocketPair[0]);
1336        __CFWakeupSocketPair[0] = INVALID_SOCKET;
1337    }
1338    if (INVALID_SOCKET != __CFWakeupSocketPair[1]) {
1339        closesocket(__CFWakeupSocketPair[1]);
1340        __CFWakeupSocketPair[1] = INVALID_SOCKET;
1341    }
1342    if (WinSockUsed) {
1343        // technically this is not supposed to be called here since it will be called from dllmain, but I don't know where else to put it
1344        WSACleanup();
1345    }
1346}
1347
1348#endif
1349
1350// CFNetwork needs to call this, especially for Win32 to get WSAStartup
1351static void __CFSocketInitializeSockets(void) {
1352    __CFWriteSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
1353    __CFReadSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
1354    __CFWriteSocketsFds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
1355    __CFReadSocketsFds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
1356    zeroLengthData = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
1357#if DEPLOYMENT_TARGET_WINDOWS
1358    __CFSocketInitializeWinSock_Guts();
1359#endif
1360    if (0 > __CFSocketCreateWakeupSocketPair()) {
1361        CFLog(kCFLogLevelWarning, CFSTR("*** Could not create wakeup socket pair for CFSocket!!!"));
1362    } else {
1363        UInt32 yes = 1;
1364        /* wakeup sockets must be non-blocking */
1365        ioctlsocket(__CFWakeupSocketPair[0], FIONBIO, (u_long *)&yes);
1366        ioctlsocket(__CFWakeupSocketPair[1], FIONBIO, (u_long *)&yes);
1367        __CFSocketFdSet(__CFWakeupSocketPair[1], __CFReadSocketsFds);
1368    }
1369}
1370
1371static CFRunLoopRef __CFSocketCopyRunLoopToWakeUp(CFRunLoopSourceRef src, CFMutableArrayRef runLoops) {
1372    if (!src) return NULL;
1373    CFRunLoopRef rl = NULL;
1374    SInt32 idx, cnt = CFArrayGetCount(runLoops);
1375    if (0 < cnt) {
1376        rl = (CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, 0);
1377        for (idx = 1; NULL != rl && idx < cnt; idx++) {
1378            CFRunLoopRef value = (CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, idx);
1379            if (value != rl) rl = NULL;
1380        }
1381        if (NULL == rl) {	/* more than one different rl, so we must pick one */
1382            /* ideally, this would be a run loop which isn't also in a
1383            * signaled state for this or another source, but that's tricky;
1384            * we pick one that is running in an appropriate mode for this
1385            * source, and from those if possible one that is waiting; then
1386            * we move this run loop to the end of the list to scramble them
1387            * a bit, and always search from the front */
1388            Boolean foundIt = false, foundBackup = false;
1389            SInt32 foundIdx = 0;
1390            for (idx = 0; !foundIt && idx < cnt; idx++) {
1391                CFRunLoopRef value = (CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, idx);
1392                CFStringRef currentMode = CFRunLoopCopyCurrentMode(value);
1393                if (NULL != currentMode) {
1394                    if (CFRunLoopContainsSource(value, src, currentMode)) {
1395                        if (CFRunLoopIsWaiting(value)) {
1396                            foundIdx = idx;
1397                            foundIt = true;
1398                        } else if (!foundBackup) {
1399                            foundIdx = idx;
1400                            foundBackup = true;
1401                        }
1402                    }
1403                    CFRelease(currentMode);
1404                }
1405            }
1406            rl = (CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, foundIdx);
1407            CFRetain(rl);
1408            CFArrayRemoveValueAtIndex(runLoops, foundIdx);
1409            CFArrayAppendValue(runLoops, rl);
1410        } else {
1411            CFRetain(rl);
1412        }
1413    }
1414    return rl;
1415}
1416
1417// If callBackNow, we immediately do client callbacks, else we have to signal a v0 RunLoopSource so the
1418// callbacks can happen in another thread.
1419static void __CFSocketHandleWrite(CFSocketRef s, Boolean callBackNow) {
1420    SInt32 errorCode = 0;
1421    int errorSize = sizeof(errorCode);
1422    CFOptionFlags writeCallBacksAvailable;
1423
1424    if (!CFSocketIsValid(s)) return;
1425    if (0 != (s->_f.client & kCFSocketLeaveErrors) || 0 != getsockopt(s->_socket, SOL_SOCKET, SO_ERROR, (char *)&errorCode, (socklen_t *)&errorSize)) errorCode = 0;
1426    // cast for WinSock bad API
1427#if defined(LOG_CFSOCKET)
1428    if (errorCode) fprintf(stdout, "error %ld on socket %d\n", (long)errorCode, s->_socket);
1429#endif
1430    __CFSocketLock(s);
1431    writeCallBacksAvailable = __CFSocketCallBackTypes(s) & (kCFSocketWriteCallBack | kCFSocketConnectCallBack);
1432    if ((s->_f.client & kCFSocketConnectCallBack) != 0) writeCallBacksAvailable &= ~kCFSocketConnectCallBack;
1433    if (!__CFSocketIsValid(s) || ((s->_f.disabled & writeCallBacksAvailable) == writeCallBacksAvailable)) {
1434        __CFSocketUnlock(s);
1435        return;
1436    }
1437    s->_errorCode = errorCode;
1438    __CFSocketSetWriteSignalled(s);
1439// CFLog(5, CFSTR("__CFSocketHandleWrite() signalling write on socket %p"), s);
1440#if defined(LOG_CFSOCKET)
1441    fprintf(stdout, "write signaling source for socket %d\n", s->_socket);
1442#endif
1443    if (callBackNow) {
1444        __CFSocketDoCallback(s, NULL, NULL, 0);
1445    } else {
1446        CFRunLoopSourceSignal(s->_source0);
1447        CFMutableArrayRef runLoopsOrig = (CFMutableArrayRef)CFRetain(s->_runLoops);
1448        CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops);
1449        CFRunLoopSourceRef source0 = s->_source0;
1450        if (NULL != source0 && !CFRunLoopSourceIsValid(source0)) {
1451            source0 = NULL;
1452        }
1453        if (source0) CFRetain(source0);
1454        __CFSocketUnlock(s);
1455        CFRunLoopRef rl = __CFSocketCopyRunLoopToWakeUp(source0, runLoopsCopy);
1456        if (source0) CFRelease(source0);
1457        if (NULL != rl) {
1458            CFRunLoopWakeUp(rl);
1459            CFRelease(rl);
1460        }
1461        __CFSocketLock(s);
1462        if (runLoopsOrig == s->_runLoops) {
1463            s->_runLoops = runLoopsCopy;
1464            runLoopsCopy = NULL;
1465            CFRelease(runLoopsOrig);
1466        }
1467        __CFSocketUnlock(s);
1468        CFRelease(runLoopsOrig);
1469        if (runLoopsCopy) CFRelease(runLoopsCopy);
1470    }
1471}
1472
1473static void __CFSocketHandleRead(CFSocketRef s, Boolean causedByTimeout)
1474{
1475    CFDataRef data = NULL, address = NULL;
1476    CFSocketNativeHandle sock = INVALID_SOCKET;
1477    if (!CFSocketIsValid(s)) return;
1478    if (__CFSocketReadCallBackType(s) == kCFSocketDataCallBack) {
1479        uint8_t bufferArray[MAX_CONNECTION_ORIENTED_DATA_SIZE], *buffer;
1480        uint8_t name[MAX_SOCKADDR_LEN];
1481        int namelen = sizeof(name);
1482        SInt32 recvlen = 0;
1483        if (__CFSocketIsConnectionOriented(s)) {
1484            buffer = bufferArray;
1485            recvlen = recvfrom(s->_socket, (char *)buffer, MAX_CONNECTION_ORIENTED_DATA_SIZE, 0, (struct sockaddr *)name, (socklen_t *)&namelen);
1486        } else {
1487            buffer = (uint8_t *)malloc(MAX_DATA_SIZE);
1488            if (buffer) recvlen = recvfrom(s->_socket, (char *)buffer, MAX_DATA_SIZE, 0, (struct sockaddr *)name, (socklen_t *)&namelen);
1489        }
1490#if defined(LOG_CFSOCKET)
1491        fprintf(stdout, "read %ld bytes on socket %d\n", (long)recvlen, s->_socket);
1492#endif
1493        if (0 >= recvlen) {
1494            //??? should return error if <0
1495            /* zero-length data is the signal for perform to invalidate */
1496            data = (CFDataRef)CFRetain(zeroLengthData);
1497        } else {
1498            data = CFDataCreate(CFGetAllocator(s), buffer, recvlen);
1499        }
1500        if (buffer && buffer != bufferArray) free(buffer);
1501        __CFSocketLock(s);
1502        if (!__CFSocketIsValid(s)) {
1503            CFRelease(data);
1504            __CFSocketUnlock(s);
1505            return;
1506        }
1507        __CFSocketSetReadSignalled(s);
1508        if (NULL != name && 0 < namelen) {
1509            //??? possible optimizations:  uniquing; storing last value
1510            address = CFDataCreate(CFGetAllocator(s), name, namelen);
1511        } else if (__CFSocketIsConnectionOriented(s)) {
1512            if (NULL == s->_peerAddress) __CFSocketEstablishPeerAddress(s);
1513            if (NULL != s->_peerAddress) address = (CFDataRef)CFRetain(s->_peerAddress);
1514        }
1515        if (NULL == address) {
1516            address = (CFDataRef)CFRetain(zeroLengthData);
1517        }
1518        if (NULL == s->_dataQueue) {
1519            s->_dataQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
1520        }
1521        if (NULL == s->_addressQueue) {
1522            s->_addressQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
1523        }
1524        CFArrayAppendValue(s->_dataQueue, data);
1525        CFRelease(data);
1526        CFArrayAppendValue(s->_addressQueue, address);
1527        CFRelease(address);
1528        if (0 < recvlen
1529            && (s->_f.client & kCFSocketDataCallBack) != 0 && (s->_f.disabled & kCFSocketDataCallBack) == 0
1530            && __CFSocketIsScheduled(s)
1531        ) {
1532            __CFSpinLock(&__CFActiveSocketsLock);
1533            /* restore socket to fds */
1534            __CFSocketSetFDForRead(s);
1535            __CFSpinUnlock(&__CFActiveSocketsLock);
1536        }
1537    } else if (__CFSocketReadCallBackType(s) == kCFSocketAcceptCallBack) {
1538        uint8_t name[MAX_SOCKADDR_LEN];
1539        int namelen = sizeof(name);
1540        sock = accept(s->_socket, (struct sockaddr *)name, (socklen_t *)&namelen);
1541        if (INVALID_SOCKET == sock) {
1542            //??? should return error
1543            return;
1544        }
1545        if (NULL != name && 0 < namelen) {
1546            address = CFDataCreate(CFGetAllocator(s), name, namelen);
1547        } else {
1548            address = (CFDataRef)CFRetain(zeroLengthData);
1549        }
1550        __CFSocketLock(s);
1551        if (!__CFSocketIsValid(s)) {
1552            closesocket(sock);
1553            CFRelease(address);
1554            __CFSocketUnlock(s);
1555            return;
1556        }
1557        __CFSocketSetReadSignalled(s);
1558        if (NULL == s->_dataQueue) {
1559            s->_dataQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, NULL);
1560        }
1561        if (NULL == s->_addressQueue) {
1562            s->_addressQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
1563        }
1564        CFArrayAppendValue(s->_dataQueue, (void *)(uintptr_t)sock);
1565        CFArrayAppendValue(s->_addressQueue, address);
1566        CFRelease(address);
1567        if ((s->_f.client & kCFSocketAcceptCallBack) != 0 && (s->_f.disabled & kCFSocketAcceptCallBack) == 0
1568            && __CFSocketIsScheduled(s)
1569        ) {
1570            __CFSpinLock(&__CFActiveSocketsLock);
1571            /* restore socket to fds */
1572            __CFSocketSetFDForRead(s);
1573            __CFSpinUnlock(&__CFActiveSocketsLock);
1574        }
1575    } else {
1576        __CFSocketLock(s);
1577        if (!__CFSocketIsValid(s) || (s->_f.disabled & kCFSocketReadCallBack) != 0) {
1578            __CFSocketUnlock(s);
1579            return;
1580        }
1581
1582		if (causedByTimeout) {
1583#if defined(LOG_CFSOCKET)
1584			fprintf(stdout, "TIMEOUT RECEIVED - WILL SIGNAL IMMEDIATELY TO FLUSH (%ld buffered)\n", s->_bytesToBufferPos);
1585#endif
1586                    /* we've got a timeout, but no bytes read, and we don't have any bytes to send.  Ignore the timeout. */
1587                    if (s->_bytesToBufferPos == 0 && s->_leftoverBytes == NULL) {
1588#if defined(LOG_CFSOCKET)
1589                fprintf(stdout, "TIMEOUT - but no bytes, restoring to active set\n");
1590                fflush(stdout);
1591#endif
1592
1593                __CFSpinLock(&__CFActiveSocketsLock);
1594                /* restore socket to fds */
1595                __CFSocketSetFDForRead(s);
1596                __CFSpinUnlock(&__CFActiveSocketsLock);
1597                __CFSocketUnlock(s);
1598                return;
1599            }
1600		} else if (s->_bytesToBuffer != 0 && ! s->_atEOF) {
1601			UInt8* base;
1602			CFIndex ctRead;
1603			CFIndex ctRemaining = s->_bytesToBuffer - s->_bytesToBufferPos;
1604
1605			/* if our buffer has room, we go ahead and buffer */
1606			if (ctRemaining > 0) {
1607				base = CFDataGetMutableBytePtr(s->_readBuffer);
1608
1609				do {
1610					ctRead = read(CFSocketGetNative(s), &base[s->_bytesToBufferPos], ctRemaining);
1611				} while (ctRead == -1 && errno == EAGAIN);
1612
1613				switch (ctRead) {
1614				case -1:
1615					s->_bufferedReadError = errno;
1616					s->_atEOF = true;
1617#if defined(LOG_CFSOCKET)
1618					fprintf(stderr, "BUFFERED READ GOT ERROR %d\n", errno);
1619#endif
1620					break;
1621
1622				case 0:
1623	#if defined(LOG_CFSOCKET)
1624					fprintf(stdout, "DONE READING (EOF) - GOING TO SIGNAL\n");
1625	#endif
1626					s->_atEOF = true;
1627					break;
1628
1629				default:
1630					s->_bytesToBufferPos += ctRead;
1631					if (s->_bytesToBuffer != s->_bytesToBufferPos) {
1632	#if defined(LOG_CFSOCKET)
1633						fprintf(stdout, "READ %ld - need %ld MORE - GOING BACK FOR MORE\n", ctRead, s->_bytesToBuffer - s->_bytesToBufferPos);
1634	#endif
1635						__CFSpinLock(&__CFActiveSocketsLock);
1636						/* restore socket to fds */
1637						__CFSocketSetFDForRead(s);
1638						__CFSpinUnlock(&__CFActiveSocketsLock);
1639						__CFSocketUnlock(s);
1640						return;
1641					} else {
1642	#if defined(LOG_CFSOCKET)
1643						fprintf(stdout, "DONE READING (read %ld bytes) - GOING TO SIGNAL\n", ctRead);
1644	#endif
1645					}
1646				}
1647			}
1648		}
1649
1650		__CFSocketSetReadSignalled(s);
1651    }
1652#if defined(LOG_CFSOCKET)
1653    fprintf(stdout, "read signaling source for socket %d\n", s->_socket);
1654#endif
1655    CFRunLoopSourceSignal(s->_source0);
1656    CFMutableArrayRef runLoopsOrig = (CFMutableArrayRef)CFRetain(s->_runLoops);
1657    CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops);
1658    CFRunLoopSourceRef source0 = s->_source0;
1659    if (NULL != source0 && !CFRunLoopSourceIsValid(source0)) {
1660        source0 = NULL;
1661    }
1662    if (source0) CFRetain(source0);
1663    __CFSocketUnlock(s);
1664    CFRunLoopRef rl = __CFSocketCopyRunLoopToWakeUp(source0, runLoopsCopy);
1665    if (source0) CFRelease(source0);
1666    if (NULL != rl) {
1667        CFRunLoopWakeUp(rl);
1668        CFRelease(rl);
1669    }
1670        __CFSocketLock(s);
1671        if (runLoopsOrig == s->_runLoops) {
1672            s->_runLoops = runLoopsCopy;
1673            runLoopsCopy = NULL;
1674            CFRelease(runLoopsOrig);
1675        }
1676        __CFSocketUnlock(s);
1677        CFRelease(runLoopsOrig);
1678        if (runLoopsCopy) CFRelease(runLoopsCopy);
1679}
1680
1681static struct timeval* intervalToTimeval(CFTimeInterval timeout, struct timeval* tv)
1682{
1683    if (timeout == 0.0)
1684        timerclear(tv);
1685    else {
1686        tv->tv_sec = (0 >= timeout || INT_MAX <= timeout) ? INT_MAX : (int)(float)floor(timeout);
1687        tv->tv_usec = (int)((timeout - floor(timeout)) * 1.0E6);
1688    }
1689    return tv;
1690}
1691
1692/* note that this returns a pointer to the min value, which won't have changed during
1693 the dictionary apply, since we've got the active sockets lock held */
1694static void _calcMinTimeout_locked(const void* val, void* ctxt)
1695{
1696    CFSocketRef s = (CFSocketRef) val;
1697    struct timeval** minTime = (struct timeval**) ctxt;
1698    if (timerisset(&s->_readBufferTimeout) && (*minTime == NULL || timercmp(&s->_readBufferTimeout, *minTime, <)))
1699        *minTime = &s->_readBufferTimeout;
1700    else if (s->_leftoverBytes) {
1701        /* If there's anyone with leftover bytes, they'll need to be awoken immediately */
1702        static struct timeval sKickerTime = { 0, 0 };
1703        *minTime = &sKickerTime;
1704    }
1705}
1706
1707void __CFSocketSetSocketReadBufferAttrs(CFSocketRef s, CFTimeInterval timeout, CFIndex length)
1708{
1709    struct timeval timeoutVal;
1710
1711    intervalToTimeval(timeout, &timeoutVal);
1712
1713    /* lock ordering is socket lock, activesocketslock */
1714    /* activesocketslock protects our timeout calculation */
1715    __CFSocketLock(s);
1716    __CFSpinLock(&__CFActiveSocketsLock);
1717
1718    if (s->_bytesToBuffer != length) {
1719        CFIndex ctBuffer = s->_bytesToBufferPos - s->_bytesToBufferReadPos;
1720
1721        if (ctBuffer) {
1722            /* As originally envisaged, you were supposed to be sure to drain the buffer before
1723             * issuing another request on the socket.  In practice, there seem to be times when we want to re-use
1724             * the stream (or perhaps, are on our way to closing it out) and this policy doesn't work so well.
1725             * So, if someone changes the buffer size while we have bytes already buffered, we put them
1726             * aside and use them to satisfy any subsequent reads.
1727             */
1728#if defined(LOG_CFSOCKET)
1729            fprintf(stdout, "%s(%d): WARNING: shouldn't set read buffer length while data (%ld bytes) is still in the read buffer (leftover total %ld)", __FUNCTION__, __LINE__, ctBuffer, s->_leftoverBytes? CFDataGetLength(s->_leftoverBytes) : 0);
1730#endif
1731
1732            if (s->_leftoverBytes == NULL)
1733                s->_leftoverBytes = CFDataCreateMutable(CFGetAllocator(s), 0);
1734
1735            /* append the current buffered bytes over.  We'll keep draining _leftoverBytes while we have them... */
1736            CFDataAppendBytes(s->_leftoverBytes, CFDataGetBytePtr(s->_readBuffer) + s->_bytesToBufferReadPos, ctBuffer);
1737            CFRelease(s->_readBuffer);
1738            s->_readBuffer = NULL;
1739
1740            s->_bytesToBuffer = 0;
1741            s->_bytesToBufferPos = 0;
1742            s->_bytesToBufferReadPos = 0;
1743        }
1744        if (length == 0) {
1745            s->_bytesToBuffer = 0;
1746            s->_bytesToBufferPos = 0;
1747            s->_bytesToBufferReadPos = 0;
1748            if (s->_readBuffer) {
1749                CFRelease(s->_readBuffer);
1750                s->_readBuffer = NULL;
1751            }
1752            // Zero length buffer, smash the timeout
1753            timeoutVal.tv_sec = 0;
1754            timeoutVal.tv_usec = 0;
1755        } else {
1756            /* if the buffer shrank, we can re-use the old one */
1757            if (length > s->_bytesToBuffer) {
1758                if (s->_readBuffer) {
1759                    CFRelease(s->_readBuffer);
1760                    s->_readBuffer = NULL;
1761                }
1762            }
1763
1764            s->_bytesToBuffer = length;
1765            s->_bytesToBufferPos = 0;
1766            s->_bytesToBufferReadPos = 0;
1767            if (s->_readBuffer == NULL) {
1768                s->_readBuffer = CFDataCreateMutable(kCFAllocatorSystemDefault, length);
1769                CFDataSetLength(s->_readBuffer, length);
1770            }
1771        }
1772    }
1773
1774    if (timercmp(&s->_readBufferTimeout, &timeoutVal, !=)) {
1775        s->_readBufferTimeout = timeoutVal;
1776        __CFReadSocketsTimeoutInvalid = true;
1777    }
1778
1779    __CFSpinUnlock(&__CFActiveSocketsLock);
1780    __CFSocketUnlock(s);
1781}
1782
1783CFIndex __CFSocketRead(CFSocketRef s, UInt8* buffer, CFIndex length, int* error)
1784{
1785#if defined(LOG_CFSOCKET)
1786	fprintf(stdout, "READING BYTES FOR SOCKET %d (%ld buffered, out of %ld desired, eof = %d, err = %d)\n", s->_socket, s->_bytesToBufferPos, s->_bytesToBuffer, s->_atEOF, s->_bufferedReadError);
1787#endif
1788
1789    CFIndex result = -1;
1790
1791    __CFSocketLock(s);
1792
1793	*error = 0;
1794
1795	/* Any leftover buffered bytes? */
1796	if (s->_leftoverBytes) {
1797		CFIndex ctBuffer = CFDataGetLength(s->_leftoverBytes);
1798#if defined(DEBUG)
1799		fprintf(stderr, "%s(%ld): WARNING: Draining %ld leftover bytes first\n\n", __FUNCTION__, (long)__LINE__, (long)ctBuffer);
1800#endif
1801		if (ctBuffer > length)
1802			ctBuffer = length;
1803		memcpy(buffer, CFDataGetBytePtr(s->_leftoverBytes), ctBuffer);
1804		if (ctBuffer < CFDataGetLength(s->_leftoverBytes))
1805			CFDataReplaceBytes(s->_leftoverBytes, CFRangeMake(0, ctBuffer), NULL, 0);
1806		else {
1807			CFRelease(s->_leftoverBytes);
1808			s->_leftoverBytes = NULL;
1809		}
1810		result = ctBuffer;
1811		goto unlock;
1812	}
1813
1814	/* return whatever we've buffered */
1815	if (s->_bytesToBuffer != 0) {
1816		CFIndex ctBuffer = s->_bytesToBufferPos - s->_bytesToBufferReadPos;
1817		if (ctBuffer > 0) {
1818			/* drain our buffer first */
1819			if (ctBuffer > length)
1820				ctBuffer = length;
1821			memcpy(buffer, CFDataGetBytePtr(s->_readBuffer) + s->_bytesToBufferReadPos, ctBuffer);
1822			s->_bytesToBufferReadPos += ctBuffer;
1823			if (s->_bytesToBufferReadPos == s->_bytesToBufferPos) {
1824#if defined(LOG_CFSOCKET)
1825				fprintf(stdout, "DRAINED BUFFER - SHOULD START BUFFERING AGAIN!\n");
1826#endif
1827				s->_bytesToBufferPos = 0;
1828				s->_bytesToBufferReadPos = 0;
1829			}
1830
1831#if defined(LOG_CFSOCKET)
1832			fprintf(stdout, "SLURPED %ld BYTES FROM BUFFER %ld LEFT TO READ!\n", ctBuffer, length);
1833#endif
1834
1835			result = ctBuffer;
1836            goto unlock;
1837		}
1838	}
1839	/* nothing buffered, or no buffer selected */
1840
1841	/* Did we get an error on a previous read (or buffered read)? */
1842	if (s->_bufferedReadError != 0) {
1843#if defined(LOG_CFSOCKET)
1844		fprintf(stdout, "RETURNING ERROR %d\n", s->_bufferedReadError);
1845#endif
1846		*error = s->_bufferedReadError;
1847        result = -1;
1848        goto unlock;
1849	}
1850
1851	/* nothing buffered, if we've hit eof, don't bother reading any more */
1852	if (s->_atEOF) {
1853#if defined(LOG_CFSOCKET)
1854		fprintf(stdout, "RETURNING EOF\n");
1855#endif
1856		result = 0;
1857        goto unlock;
1858	}
1859
1860	/* normal read */
1861	result = read(CFSocketGetNative(s), buffer, length);
1862#if defined(LOG_CFSOCKET)
1863	fprintf(stdout, "READ %ld bytes", result);
1864#endif
1865
1866    if (result == 0) {
1867        /* note that we hit EOF */
1868        s->_atEOF = true;
1869    } else if (result < 0) {
1870        *error = errno;
1871
1872        /* if it wasn't EAGAIN, record it (although we shouldn't get called again) */
1873        if (*error != EAGAIN) {
1874            s->_bufferedReadError = *error;
1875        }
1876    }
1877
1878unlock:
1879    __CFSocketUnlock(s);
1880
1881    return result;
1882}
1883
1884Boolean __CFSocketGetBytesAvailable(CFSocketRef s, CFIndex* ctBytesAvailable)
1885{
1886	CFIndex ctBuffer = s->_bytesToBufferPos - s->_bytesToBufferReadPos;
1887	if (ctBuffer != 0) {
1888		*ctBytesAvailable = ctBuffer;
1889		return true;
1890	} else {
1891		int result;
1892	    unsigned long bytesAvailable;
1893	    result = ioctlsocket(CFSocketGetNative(s), FIONREAD, &bytesAvailable);
1894		if (result < 0)
1895			return false;
1896		*ctBytesAvailable = (CFIndex) bytesAvailable;
1897		return true;
1898	}
1899}
1900
1901#if defined(LOG_CFSOCKET)
1902static void __CFSocketWriteSocketList(CFArrayRef sockets, CFDataRef fdSet, Boolean onlyIfSet) {
1903    fd_set *tempfds = (fd_set *)CFDataGetBytePtr(fdSet);
1904    SInt32 idx, cnt;
1905    for (idx = 0, cnt = CFArrayGetCount(sockets); idx < cnt; idx++) {
1906        CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(sockets, idx);
1907        if (FD_ISSET(s->_socket, tempfds)) {
1908            fprintf(stdout, "%d ", s->_socket);
1909        } else if (!onlyIfSet) {
1910            fprintf(stdout, "(%d) ", s->_socket);
1911        }
1912    }
1913}
1914#endif
1915
1916static void
1917clearInvalidFileDescriptors(CFMutableDataRef d)
1918{
1919    if (d) {
1920        SInt32 count = __CFSocketFdGetSize(d);
1921        fd_set* s = (fd_set*) CFDataGetMutableBytePtr(d);
1922        for (SInt32 idx = 0;  idx < count;  idx++) {
1923            if (FD_ISSET(idx, s))
1924                if (! __CFNativeSocketIsValid(idx)) {
1925                    FD_CLR(idx, s);
1926                }
1927        }
1928    }
1929}
1930
1931static void
1932manageSelectError()
1933{
1934    SInt32 selectError = __CFSocketLastError();
1935#if defined(LOG_CFSOCKET)
1936    fprintf(stdout, "socket manager received error %ld from select\n", (long)selectError);
1937#endif
1938    if (EBADF == selectError) {
1939        CFMutableArrayRef invalidSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
1940
1941        __CFSpinLock(&__CFActiveSocketsLock);
1942        CFIndex cnt = CFArrayGetCount(__CFWriteSockets);
1943        CFIndex idx;
1944        for (idx = 0; idx < cnt; idx++) {
1945            CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFWriteSockets, idx);
1946            if (!__CFNativeSocketIsValid(s->_socket)) {
1947#if defined(LOG_CFSOCKET)
1948                fprintf(stdout, "socket manager found write socket %d invalid\n", s->_socket);
1949#endif
1950                CFArrayAppendValue(invalidSockets, s);
1951            }
1952        }
1953        cnt = CFArrayGetCount(__CFReadSockets);
1954        for (idx = 0; idx < cnt; idx++) {
1955            CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx);
1956            if (!__CFNativeSocketIsValid(s->_socket)) {
1957#if defined(LOG_CFSOCKET)
1958                fprintf(stdout, "socket manager found read socket %d invalid\n", s->_socket);
1959#endif
1960                CFArrayAppendValue(invalidSockets, s);
1961            }
1962        }
1963
1964
1965        cnt = CFArrayGetCount(invalidSockets);
1966
1967        /* Note that we're doing this only when we got EBADF but otherwise
1968         * don't have an explicit bad descriptor.  Note that the lock is held now.
1969         * Finally, note that cnt == 0 doesn't necessarily mean
1970         * that this loop will do anything, since fd's may have been invalidated
1971         * while we were in select.
1972         */
1973        if (cnt == 0) {
1974#if defined(LOG_CFSOCKET)
1975            fprintf(stdout, "socket manager received EBADF(1): No sockets were marked as invalid, cleaning out fdsets\n");
1976#endif
1977
1978            clearInvalidFileDescriptors(__CFReadSocketsFds);
1979            clearInvalidFileDescriptors(__CFWriteSocketsFds);
1980        }
1981
1982        __CFSpinUnlock(&__CFActiveSocketsLock);
1983
1984        for (idx = 0; idx < cnt; idx++) {
1985            CFSocketInvalidate(((CFSocketRef)CFArrayGetValueAtIndex(invalidSockets, idx)));
1986        }
1987        CFRelease(invalidSockets);
1988    }
1989}
1990
1991#ifdef __GNUC__
1992__attribute__ ((noreturn))	// mostly interesting for shutting up a warning
1993#endif /* __GNUC__ */
1994static void __CFSocketManager(void * arg)
1995{
1996    pthread_setname_np("com.apple.CFSocket.private");
1997    if (objc_collectingEnabled()) objc_registerThreadWithCollector();
1998    SInt32 nrfds, maxnrfds, fdentries = 1;
1999    SInt32 rfds, wfds;
2000    fd_set *exceptfds = NULL;
2001    fd_set *writefds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(fd_mask), 0);
2002    fd_set *readfds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(fd_mask), 0);
2003    fd_set *tempfds;
2004    SInt32 idx, cnt;
2005    uint8_t buffer[256];
2006    CFMutableArrayRef selectedWriteSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
2007    CFMutableArrayRef selectedReadSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
2008    CFIndex selectedWriteSocketsIndex = 0, selectedReadSocketsIndex = 0;
2009
2010    struct timeval tv;
2011    struct timeval* pTimeout = NULL;
2012    struct timeval timeBeforeSelect;
2013
2014    for (;;) {
2015        __CFSpinLock(&__CFActiveSocketsLock);
2016        __CFSocketManagerIteration++;
2017#if defined(LOG_CFSOCKET)
2018        fprintf(stdout, "socket manager iteration %lu looking at read sockets ", (unsigned long)__CFSocketManagerIteration);
2019        __CFSocketWriteSocketList(__CFReadSockets, __CFReadSocketsFds, FALSE);
2020        if (0 < CFArrayGetCount(__CFWriteSockets)) {
2021            fprintf(stdout, " and write sockets ");
2022            __CFSocketWriteSocketList(__CFWriteSockets, __CFWriteSocketsFds, FALSE);
2023        }
2024        fprintf(stdout, "\n");
2025#endif
2026        rfds = __CFSocketFdGetSize(__CFReadSocketsFds);
2027        wfds = __CFSocketFdGetSize(__CFWriteSocketsFds);
2028        maxnrfds = __CFMax(rfds, wfds);
2029        if (maxnrfds > fdentries * (int)NFDBITS) {
2030            fdentries = (maxnrfds + NFDBITS - 1) / NFDBITS;
2031            writefds = (fd_set *)CFAllocatorReallocate(kCFAllocatorSystemDefault, writefds, fdentries * sizeof(fd_mask), 0);
2032            readfds = (fd_set *)CFAllocatorReallocate(kCFAllocatorSystemDefault, readfds, fdentries * sizeof(fd_mask), 0);
2033        }
2034        memset(writefds, 0, fdentries * sizeof(fd_mask));
2035        memset(readfds, 0, fdentries * sizeof(fd_mask));
2036        CFDataGetBytes(__CFWriteSocketsFds, CFRangeMake(0, CFDataGetLength(__CFWriteSocketsFds)), (UInt8 *)writefds);
2037        CFDataGetBytes(__CFReadSocketsFds, CFRangeMake(0, CFDataGetLength(__CFReadSocketsFds)), (UInt8 *)readfds);
2038
2039        if (__CFReadSocketsTimeoutInvalid) {
2040            struct timeval* minTimeout = NULL;
2041            __CFReadSocketsTimeoutInvalid = false;
2042#if defined(LOG_CFSOCKET)
2043            fprintf(stdout, "Figuring out which sockets have timeouts...\n");
2044#endif
2045            CFArrayApplyFunction(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), _calcMinTimeout_locked, (void*) &minTimeout);
2046
2047            if (minTimeout == NULL) {
2048#if defined(LOG_CFSOCKET)
2049                fprintf(stdout, "No one wants a timeout!\n");
2050#endif
2051                pTimeout = NULL;
2052            } else {
2053#if defined(LOG_CFSOCKET)
2054                fprintf(stdout, "timeout will be %ld, %d!\n", minTimeout->tv_sec, minTimeout->tv_usec);
2055#endif
2056                tv = *minTimeout;
2057                pTimeout = &tv;
2058            }
2059        }
2060
2061        if (pTimeout) {
2062#if defined(LOG_CFSOCKET)
2063            fprintf(stdout, "select will have a %ld, %d timeout\n", pTimeout->tv_sec, pTimeout->tv_usec);
2064#endif
2065            gettimeofday(&timeBeforeSelect, NULL);
2066        }
2067
2068		__CFSpinUnlock(&__CFActiveSocketsLock);
2069
2070#if DEPLOYMENT_TARGET_WINDOWS
2071        // On Windows, select checks connection failed sockets via the exceptfds parameter. connection succeeded is checked via writefds. We need both.
2072        exceptfds = writefds;
2073#endif
2074        nrfds = select(maxnrfds, readfds, writefds, exceptfds, pTimeout);
2075
2076#if defined(LOG_CFSOCKET)
2077        fprintf(stdout, "socket manager woke from select, ret=%ld\n", (long)nrfds);
2078#endif
2079
2080		/*
2081		 * select returned a timeout
2082		 */
2083        if (0 == nrfds) {
2084			struct timeval timeAfterSelect;
2085			struct timeval deltaTime;
2086			gettimeofday(&timeAfterSelect, NULL);
2087			/* timeBeforeSelect becomes the delta */
2088			timersub(&timeAfterSelect, &timeBeforeSelect, &deltaTime);
2089
2090#if defined(LOG_CFSOCKET)
2091			fprintf(stdout, "Socket manager received timeout - kicking off expired reads (expired delta %ld, %d)\n", deltaTime.tv_sec, deltaTime.tv_usec);
2092#endif
2093
2094			__CFSpinLock(&__CFActiveSocketsLock);
2095
2096			tempfds = NULL;
2097			cnt = CFArrayGetCount(__CFReadSockets);
2098			for (idx = 0; idx < cnt; idx++) {
2099				CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx);
2100				if (timerisset(&s->_readBufferTimeout) || s->_leftoverBytes) {
2101					CFSocketNativeHandle sock = s->_socket;
2102					// We might have an new element in __CFReadSockets that we weren't listening to,
2103					// in which case we must be sure not to test a bit in the fdset that is
2104					// outside our mask size.
2105					Boolean sockInBounds = (0 <= sock && sock < maxnrfds);
2106					/* if this sockets timeout is less than or equal elapsed time, then signal it */
2107					if (INVALID_SOCKET != sock && sockInBounds) {
2108#if defined(LOG_CFSOCKET)
2109						fprintf(stdout, "Expiring socket %d (delta %ld, %d)\n", sock, s->_readBufferTimeout.tv_sec, s->_readBufferTimeout.tv_usec);
2110#endif
2111						CFArraySetValueAtIndex(selectedReadSockets, selectedReadSocketsIndex, s);
2112						selectedReadSocketsIndex++;
2113						/* socket is removed from fds here, will be restored in read handling or in perform function */
2114						if (!tempfds) tempfds = (fd_set *)CFDataGetMutableBytePtr(__CFReadSocketsFds);
2115						FD_CLR(sock, tempfds);
2116					}
2117				}
2118			}
2119
2120			__CFSpinUnlock(&__CFActiveSocketsLock);
2121
2122			/* and below, we dispatch through the normal read dispatch mechanism */
2123		}
2124
2125        if (0 > nrfds) {
2126            manageSelectError();
2127            continue;
2128        }
2129        if (FD_ISSET(__CFWakeupSocketPair[1], readfds)) {
2130            recv(__CFWakeupSocketPair[1], (char *)buffer, sizeof(buffer), 0);
2131#if defined(LOG_CFSOCKET)
2132            fprintf(stdout, "socket manager received %c on wakeup socket\n", buffer[0]);
2133#endif
2134        }
2135        __CFSpinLock(&__CFActiveSocketsLock);
2136        tempfds = NULL;
2137        cnt = CFArrayGetCount(__CFWriteSockets);
2138        for (idx = 0; idx < cnt; idx++) {
2139            CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFWriteSockets, idx);
2140            CFSocketNativeHandle sock = s->_socket;
2141            // We might have an new element in __CFWriteSockets that we weren't listening to,
2142            // in which case we must be sure not to test a bit in the fdset that is
2143            // outside our mask size.
2144            Boolean sockInBounds = (0 <= sock && sock < maxnrfds);
2145            if (INVALID_SOCKET != sock && sockInBounds) {
2146                if (FD_ISSET(sock, writefds)) {
2147                    CFArraySetValueAtIndex(selectedWriteSockets, selectedWriteSocketsIndex, s);
2148                    selectedWriteSocketsIndex++;
2149                    /* socket is removed from fds here, restored by CFSocketReschedule */
2150                    if (!tempfds) tempfds = (fd_set *)CFDataGetMutableBytePtr(__CFWriteSocketsFds);
2151                    FD_CLR(sock, tempfds);
2152// CFLog(5, CFSTR("Manager: cleared socket %p from write fds"), s);
2153                }
2154            }
2155        }
2156        tempfds = NULL;
2157        cnt = CFArrayGetCount(__CFReadSockets);
2158        for (idx = 0; idx < cnt; idx++) {
2159            CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx);
2160            CFSocketNativeHandle sock = s->_socket;
2161            // We might have an new element in __CFReadSockets that we weren't listening to,
2162            // in which case we must be sure not to test a bit in the fdset that is
2163            // outside our mask size.
2164            Boolean sockInBounds = (0 <= sock && sock < maxnrfds);
2165            if (INVALID_SOCKET != sock && sockInBounds && FD_ISSET(sock, readfds)) {
2166                CFArraySetValueAtIndex(selectedReadSockets, selectedReadSocketsIndex, s);
2167                selectedReadSocketsIndex++;
2168                /* socket is removed from fds here, will be restored in read handling or in perform function */
2169                if (!tempfds) tempfds = (fd_set *)CFDataGetMutableBytePtr(__CFReadSocketsFds);
2170                FD_CLR(sock, tempfds);
2171            }
2172        }
2173        __CFSpinUnlock(&__CFActiveSocketsLock);
2174
2175        for (idx = 0; idx < selectedWriteSocketsIndex; idx++) {
2176            CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(selectedWriteSockets, idx);
2177            if (kCFNull == (CFNullRef)s) continue;
2178#if defined(LOG_CFSOCKET)
2179            fprintf(stdout, "socket manager signaling socket %d for write\n", s->_socket);
2180#endif
2181            __CFSocketHandleWrite(s, FALSE);
2182            CFArraySetValueAtIndex(selectedWriteSockets, idx, kCFNull);
2183        }
2184        selectedWriteSocketsIndex = 0;
2185
2186        for (idx = 0; idx < selectedReadSocketsIndex; idx++) {
2187            CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(selectedReadSockets, idx);
2188            if (kCFNull == (CFNullRef)s) continue;
2189#if defined(LOG_CFSOCKET)
2190            fprintf(stdout, "socket manager signaling socket %d for read\n", s->_socket);
2191#endif
2192            __CFSocketHandleRead(s, nrfds == 0);
2193            CFArraySetValueAtIndex(selectedReadSockets, idx, kCFNull);
2194        }
2195        selectedReadSocketsIndex = 0;
2196    }
2197}
2198
2199static CFStringRef __CFSocketCopyDescription(CFTypeRef cf) {
2200    CFSocketRef s = (CFSocketRef)cf;
2201    CFMutableStringRef result;
2202    CFStringRef contextDesc = NULL;
2203    void *contextInfo = NULL;
2204    CFStringRef (*contextCopyDescription)(const void *info) = NULL;
2205    result = CFStringCreateMutable(CFGetAllocator(s), 0);
2206    __CFSocketLock(s);
2207    void *addr = s->_callout;
2208#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
2209    Dl_info info;
2210    const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???";
2211#else
2212    // don't bother trying to figure out callout names
2213    const char *name = "<unknown>";
2214#endif
2215    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"), (int)(s->_socketType), s->_socket, (long)s->_socketSetCount, __CFSocketCallBackTypes(s), name, addr, s->_source0, s->_runLoops);
2216    contextInfo = s->_context.info;
2217    contextCopyDescription = s->_context.copyDescription;
2218    __CFSocketUnlock(s);
2219    if (NULL != contextInfo && NULL != contextCopyDescription) {
2220        contextDesc = (CFStringRef)contextCopyDescription(contextInfo);
2221    }
2222    if (NULL == contextDesc) {
2223        contextDesc = CFStringCreateWithFormat(CFGetAllocator(s), NULL, CFSTR("<CFSocket context %p>"), contextInfo);
2224    }
2225    CFStringAppend(result, contextDesc);
2226    CFStringAppend(result, CFSTR("}"));
2227    CFRelease(contextDesc);
2228    return result;
2229}
2230
2231static void __CFSocketDeallocate(CFTypeRef cf) {
2232    /* Since CFSockets are cached, we can only get here sometime after being invalidated */
2233    CFSocketRef s = (CFSocketRef)cf;
2234    if (NULL != s->_address) {
2235        CFRelease(s->_address);
2236        s->_address = NULL;
2237    }
2238    if (NULL != s->_readBuffer) {
2239        CFRelease(s->_readBuffer);
2240        s->_readBuffer = NULL;
2241    }
2242	if (NULL != s->_leftoverBytes) {
2243		CFRelease(s->_leftoverBytes);
2244		s->_leftoverBytes = NULL;
2245	}
2246    timerclear(&s->_readBufferTimeout);
2247    s->_bytesToBuffer = 0;
2248    s->_bytesToBufferPos = 0;
2249    s->_bytesToBufferReadPos = 0;
2250    s->_atEOF = true;
2251	s->_bufferedReadError = 0;
2252}
2253
2254static CFTypeID __kCFSocketTypeID = _kCFRuntimeNotATypeID;
2255
2256static const CFRuntimeClass __CFSocketClass = {
2257    0,
2258    "CFSocket",
2259    NULL,      // init
2260    NULL,      // copy
2261    __CFSocketDeallocate,
2262    NULL,      // equal
2263    NULL,      // hash
2264    NULL,      //
2265    __CFSocketCopyDescription
2266};
2267
2268CFTypeID CFSocketGetTypeID(void) {
2269    if (_kCFRuntimeNotATypeID == __kCFSocketTypeID) {
2270	__kCFSocketTypeID = _CFRuntimeRegisterClass(&__CFSocketClass);
2271#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
2272        struct rlimit lim1;
2273        int ret1 = getrlimit(RLIMIT_NOFILE, &lim1);
2274        int mib[] = {CTL_KERN, KERN_MAXFILESPERPROC};
2275        int maxfd = 0;
2276        size_t len = sizeof(int);
2277        int ret0 = sysctl(mib, 2, &maxfd, &len, NULL, 0);
2278        if (0 == ret0 && 0 == ret1 && lim1.rlim_max < maxfd) maxfd = lim1.rlim_max;
2279        if (0 == ret1 && lim1.rlim_cur < maxfd) {
2280            struct rlimit lim2 = lim1;
2281            lim2.rlim_cur += 2304;
2282            if (maxfd < lim2.rlim_cur) lim2.rlim_cur = maxfd;
2283            setrlimit(RLIMIT_NOFILE, &lim2);
2284            // we try, but do not go to extraordinary measures
2285        }
2286#endif
2287    }
2288    return __kCFSocketTypeID;
2289}
2290
2291static CFSocketRef _CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHandle sock, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context, Boolean useExistingInstance) {
2292    CHECK_FOR_FORK();
2293    CFSocketRef memory;
2294    int typeSize = sizeof(memory->_socketType);
2295    __CFSpinLock(&__CFActiveSocketsLock);
2296    if (NULL == __CFReadSockets) __CFSocketInitializeSockets();
2297    __CFSpinUnlock(&__CFActiveSocketsLock);
2298    __CFSpinLock(&__CFAllSocketsLock);
2299    if (NULL == __CFAllSockets) {
2300        __CFAllSockets = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
2301    }
2302    if (INVALID_SOCKET != sock && CFDictionaryGetValueIfPresent(__CFAllSockets, (void *)(uintptr_t)sock, (const void **)&memory)) {
2303        if (useExistingInstance) {
2304			__CFSpinUnlock(&__CFAllSocketsLock);
2305			CFRetain(memory);
2306			return memory;
2307		} else {
2308#if defined(LOG_CFSOCKET)
2309			fprintf(stdout, "useExistingInstance is FALSE, removing existing instance %p from __CFAllSockets\n", memory);
2310#endif
2311			__CFSpinUnlock(&__CFAllSocketsLock);
2312			CFSocketInvalidate(memory);
2313			__CFSpinLock(&__CFAllSocketsLock);
2314		}
2315    }
2316    memory = (CFSocketRef)_CFRuntimeCreateInstance(allocator, CFSocketGetTypeID(), sizeof(struct __CFSocket) - sizeof(CFRuntimeBase), NULL);
2317    if (NULL == memory) {
2318        __CFSpinUnlock(&__CFAllSocketsLock);
2319        return NULL;
2320    }
2321    __CFSocketSetCallBackTypes(memory, callBackTypes);
2322    if (INVALID_SOCKET != sock) __CFSocketSetValid(memory);
2323    __CFSocketUnsetWriteSignalled(memory);
2324    __CFSocketUnsetReadSignalled(memory);
2325    memory->_f.client = ((callBackTypes & (~kCFSocketConnectCallBack)) & (~kCFSocketWriteCallBack)) | kCFSocketCloseOnInvalidate;
2326    memory->_f.disabled = 0;
2327    memory->_f.connected = FALSE;
2328    memory->_f.writableHint = FALSE;
2329    memory->_f.closeSignaled = FALSE;
2330    memory->_lock = CFSpinLockInit;
2331    memory->_writeLock = CFSpinLockInit;
2332    memory->_socket = sock;
2333    if (INVALID_SOCKET == sock || 0 != getsockopt(sock, SOL_SOCKET, SO_TYPE, (char *)&(memory->_socketType), (socklen_t *)&typeSize)) memory->_socketType = 0;		// cast for WinSock bad API
2334    memory->_errorCode = 0;
2335    memory->_address = NULL;
2336    memory->_peerAddress = NULL;
2337    memory->_socketSetCount = 0;
2338    memory->_source0 = NULL;
2339    if (INVALID_SOCKET != sock) {
2340        memory->_runLoops = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
2341    } else {
2342        memory->_runLoops = NULL;
2343    }
2344    memory->_callout = callout;
2345    memory->_dataQueue = NULL;
2346    memory->_addressQueue = NULL;
2347    memory->_context.info = 0;
2348    memory->_context.retain = 0;
2349    memory->_context.release = 0;
2350    memory->_context.copyDescription = 0;
2351    timerclear(&memory->_readBufferTimeout);
2352    memory->_readBuffer = NULL;
2353    memory->_bytesToBuffer = 0;
2354    memory->_bytesToBufferPos = 0;
2355    memory->_bytesToBufferReadPos = 0;
2356    memory->_atEOF = false;
2357    memory->_bufferedReadError = 0;
2358    memory->_leftoverBytes = NULL;
2359
2360    if (INVALID_SOCKET != sock) CFDictionaryAddValue(__CFAllSockets, (void *)(uintptr_t)sock, memory);
2361    if (NULL == __CFSocketManagerThread) __CFSocketManagerThread = __CFStartSimpleThread(__CFSocketManager, 0);
2362    __CFSpinUnlock(&__CFAllSocketsLock);
2363    if (NULL != context) {
2364        void *contextInfo = context->retain ? (void *)context->retain(context->info) : context->info;
2365        __CFSocketLock(memory);
2366        memory->_context.retain = context->retain;
2367        memory->_context.release = context->release;
2368        memory->_context.copyDescription = context->copyDescription;
2369        memory->_context.info = contextInfo;
2370        __CFSocketUnlock(memory);
2371    }
2372#if defined(LOG_CFSOCKET)
2373    CFLog(5, CFSTR("CFSocketCreateWithNative(): created socket %p (%d) with callbacks 0x%x"), memory, memory->_socket, callBackTypes);
2374#endif
2375    return memory;
2376}
2377
2378CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHandle sock, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
2379	return _CFSocketCreateWithNative(allocator, sock, callBackTypes, callout, context, TRUE);
2380}
2381
2382void CFSocketInvalidate(CFSocketRef s) {
2383// CFLog(5, CFSTR("CFSocketInvalidate(%p) starting"), s);
2384    CHECK_FOR_FORK();
2385    UInt32 previousSocketManagerIteration;
2386    __CFGenericValidateType(s, CFSocketGetTypeID());
2387#if defined(LOG_CFSOCKET)
2388    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);
2389#endif
2390    CFRetain(s);
2391    __CFSpinLock(&__CFAllSocketsLock);
2392    __CFSocketLock(s);
2393    if (__CFSocketIsValid(s)) {
2394        SInt32 idx;
2395        CFRunLoopSourceRef source0;
2396        void *contextInfo = NULL;
2397        void (*contextRelease)(const void *info) = NULL;
2398        __CFSocketUnsetValid(s);
2399        __CFSocketUnsetWriteSignalled(s);
2400        __CFSocketUnsetReadSignalled(s);
2401        __CFSpinLock(&__CFActiveSocketsLock);
2402        idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
2403        if (0 <= idx) {
2404            CFArrayRemoveValueAtIndex(__CFWriteSockets, idx);
2405            __CFSocketClearFDForWrite(s);
2406        }
2407        // No need to clear FD's for V1 sources, since we'll just throw the whole event away
2408        idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
2409        if (0 <= idx) {
2410            CFArrayRemoveValueAtIndex(__CFReadSockets, idx);
2411            __CFSocketClearFDForRead(s);
2412        }
2413        previousSocketManagerIteration = __CFSocketManagerIteration;
2414        __CFSpinUnlock(&__CFActiveSocketsLock);
2415        CFDictionaryRemoveValue(__CFAllSockets, (void *)(uintptr_t)(s->_socket));
2416        if ((s->_f.client & kCFSocketCloseOnInvalidate) != 0) closesocket(s->_socket);
2417        s->_socket = INVALID_SOCKET;
2418        if (NULL != s->_peerAddress) {
2419            CFRelease(s->_peerAddress);
2420            s->_peerAddress = NULL;
2421        }
2422        if (NULL != s->_dataQueue) {
2423            CFRelease(s->_dataQueue);
2424            s->_dataQueue = NULL;
2425        }
2426        if (NULL != s->_addressQueue) {
2427            CFRelease(s->_addressQueue);
2428            s->_addressQueue = NULL;
2429        }
2430        s->_socketSetCount = 0;
2431
2432        // we'll need this later
2433        CFArrayRef runLoops = (CFArrayRef)CFRetain(s->_runLoops);
2434        CFRelease(s->_runLoops);
2435
2436        s->_runLoops = NULL;
2437        source0 = s->_source0;
2438        s->_source0 = NULL;
2439        contextInfo = s->_context.info;
2440        contextRelease = s->_context.release;
2441        s->_context.info = 0;
2442        s->_context.retain = 0;
2443        s->_context.release = 0;
2444        s->_context.copyDescription = 0;
2445        __CFSocketUnlock(s);
2446
2447        // Do this after the socket unlock to avoid deadlock (10462525)
2448        for (idx = CFArrayGetCount(runLoops); idx--;) {
2449            CFRunLoopWakeUp((CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, idx));
2450        }
2451        CFRelease(runLoops);
2452
2453        if (NULL != contextRelease) {
2454            contextRelease(contextInfo);
2455        }
2456        if (NULL != source0) {
2457            CFRunLoopSourceInvalidate(source0);
2458            CFRelease(source0);
2459        }
2460    } else {
2461        __CFSocketUnlock(s);
2462    }
2463    __CFSpinUnlock(&__CFAllSocketsLock);
2464    CFRelease(s);
2465#if defined(LOG_CFSOCKET)
2466    CFLog(5, CFSTR("CFSocketInvalidate(%p) done"), s);
2467#endif
2468}
2469
2470Boolean CFSocketIsValid(CFSocketRef s) {
2471    CHECK_FOR_FORK();
2472    __CFGenericValidateType(s, CFSocketGetTypeID());
2473    return __CFSocketIsValid(s);
2474}
2475
2476CFSocketNativeHandle CFSocketGetNative(CFSocketRef s) {
2477    CHECK_FOR_FORK();
2478    __CFGenericValidateType(s, CFSocketGetTypeID());
2479    return s->_socket;
2480}
2481
2482CFDataRef CFSocketCopyAddress(CFSocketRef s) {
2483    CHECK_FOR_FORK();
2484    CFDataRef result = NULL;
2485    __CFGenericValidateType(s, CFSocketGetTypeID());
2486    __CFSocketLock(s);
2487    __CFSocketEstablishAddress(s);
2488    if (NULL != s->_address) {
2489        result = (CFDataRef)CFRetain(s->_address);
2490    }
2491    __CFSocketUnlock(s);
2492#if defined(LOG_CFSOCKET)
2493    CFLog(5, CFSTR("CFSocketCopyAddress(): created socket %p address %@"), s, result);
2494#endif
2495    return result;
2496}
2497
2498CFDataRef CFSocketCopyPeerAddress(CFSocketRef s) {
2499    CHECK_FOR_FORK();
2500    CFDataRef result = NULL;
2501    __CFGenericValidateType(s, CFSocketGetTypeID());
2502    __CFSocketLock(s);
2503    __CFSocketEstablishPeerAddress(s);
2504    if (NULL != s->_peerAddress) {
2505        result = (CFDataRef)CFRetain(s->_peerAddress);
2506    }
2507    __CFSocketUnlock(s);
2508#if defined(LOG_CFSOCKET)
2509    CFLog(5, CFSTR("CFSocketCopyAddress(): created socket %p peer address %@"), s, result);
2510#endif
2511    return result;
2512}
2513
2514void CFSocketGetContext(CFSocketRef s, CFSocketContext *context) {
2515    CHECK_FOR_FORK();
2516    __CFGenericValidateType(s, CFSocketGetTypeID());
2517    CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__);
2518    *context = s->_context;
2519}
2520
2521CFOptionFlags CFSocketGetSocketFlags(CFSocketRef s) {
2522    CHECK_FOR_FORK();
2523    __CFGenericValidateType(s, CFSocketGetTypeID());
2524    return s->_f.client;
2525}
2526
2527void CFSocketSetSocketFlags(CFSocketRef s, CFOptionFlags flags) {
2528    CHECK_FOR_FORK();
2529    __CFGenericValidateType(s, CFSocketGetTypeID());
2530    __CFSocketLock(s);
2531#if defined(LOG_CFSOCKET)
2532        fprintf(stdout, "setting flags for socket %d, from 0x%x to 0x%lx\n", s->_socket, s->_f.client, flags);
2533#endif
2534    s->_f.client = flags;
2535    __CFSocketUnlock(s);
2536// CFLog(5, CFSTR("CFSocketSetSocketFlags(%p, 0x%x)"), s, flags);
2537}
2538
2539void CFSocketDisableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) {
2540    CHECK_FOR_FORK();
2541    Boolean wakeup = false;
2542    uint8_t readCallBackType;
2543    __CFGenericValidateType(s, CFSocketGetTypeID());
2544    __CFSocketLock(s);
2545    if (__CFSocketIsValid(s) && __CFSocketIsScheduled(s)) {
2546        callBackTypes &= __CFSocketCallBackTypes(s);
2547        readCallBackType = __CFSocketReadCallBackType(s);
2548        s->_f.disabled |= callBackTypes;
2549#if defined(LOG_CFSOCKET)
2550        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);
2551#endif
2552        __CFSpinLock(&__CFActiveSocketsLock);
2553        if ((readCallBackType == kCFSocketAcceptCallBack) || !__CFSocketIsConnectionOriented(s)) s->_f.connected = TRUE;
2554        if (((callBackTypes & kCFSocketWriteCallBack) != 0) || (((callBackTypes & kCFSocketConnectCallBack) != 0) && !s->_f.connected)) {
2555            if (__CFSocketClearFDForWrite(s)) {
2556                // do not wake up the socket manager thread if all relevant write callbacks are disabled
2557                CFOptionFlags writeCallBacksAvailable = __CFSocketCallBackTypes(s) & (kCFSocketWriteCallBack | kCFSocketConnectCallBack);
2558                if (s->_f.connected) writeCallBacksAvailable &= ~kCFSocketConnectCallBack;
2559                if ((s->_f.disabled & writeCallBacksAvailable) != writeCallBacksAvailable) wakeup = true;
2560            }
2561        }
2562        if (readCallBackType != kCFSocketNoCallBack && (callBackTypes & readCallBackType) != 0) {
2563            if (__CFSocketClearFDForRead(s)) {
2564                // do not wake up the socket manager thread if callback type is read
2565                if (readCallBackType != kCFSocketReadCallBack) wakeup = true;
2566            }
2567        }
2568        __CFSpinUnlock(&__CFActiveSocketsLock);
2569    }
2570    __CFSocketUnlock(s);
2571}
2572
2573// "force" means to clear the disabled bits set by DisableCallBacks and always reenable.
2574// if (!force) we respect those bits, meaning they may stop us from enabling.
2575// In addition, if !force we assume that the sockets have already been added to the
2576// __CFReadSockets and __CFWriteSockets arrays.  This is true because the callbacks start
2577// enabled when the CFSocket is created (at which time we enable with force).
2578// Called with SocketLock held, returns with it released!
2579void __CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes, Boolean force, uint8_t wakeupChar) {
2580    CHECK_FOR_FORK();
2581    Boolean wakeup = FALSE;
2582    if (!callBackTypes) {
2583        __CFSocketUnlock(s);
2584        return;
2585    }
2586    if (__CFSocketIsValid(s) && __CFSocketIsScheduled(s)) {
2587        Boolean turnOnWrite = FALSE, turnOnConnect = FALSE, turnOnRead = FALSE;
2588        uint8_t readCallBackType = __CFSocketReadCallBackType(s);
2589        callBackTypes &= __CFSocketCallBackTypes(s);
2590        if (force) s->_f.disabled &= ~callBackTypes;
2591#if defined(LOG_CFSOCKET)
2592        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);
2593#endif
2594        /* We will wait for connection only for connection-oriented, non-rendezvous sockets that are not already connected.  Mark others as already connected. */
2595        if ((readCallBackType == kCFSocketAcceptCallBack) || !__CFSocketIsConnectionOriented(s)) s->_f.connected = TRUE;
2596
2597        // First figure out what to turn on
2598        if (s->_f.connected || (callBackTypes & kCFSocketConnectCallBack) == 0) {
2599            // if we want write callbacks and they're not disabled...
2600            if ((callBackTypes & kCFSocketWriteCallBack) != 0 && (s->_f.disabled & kCFSocketWriteCallBack) == 0) turnOnWrite = TRUE;
2601        } else {
2602            // if we want connect callbacks and they're not disabled...
2603            if ((callBackTypes & kCFSocketConnectCallBack) != 0 && (s->_f.disabled & kCFSocketConnectCallBack) == 0) turnOnConnect = TRUE;
2604        }
2605        // if we want read callbacks and they're not disabled...
2606        if (readCallBackType != kCFSocketNoCallBack && (callBackTypes & readCallBackType) != 0 && (s->_f.disabled & kCFSocketReadCallBack) == 0) turnOnRead = TRUE;
2607
2608        // Now turn on the callbacks we've determined that we want on
2609        if (turnOnRead || turnOnWrite || turnOnConnect) {
2610            __CFSpinLock(&__CFActiveSocketsLock);
2611            if (turnOnWrite || turnOnConnect) {
2612                if (force) {
2613                    SInt32 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
2614                    if (kCFNotFound == idx) CFArrayAppendValue(__CFWriteSockets, s);
2615//                     if (kCFNotFound == idx) CFLog(5, CFSTR("__CFSocketEnableCallBacks: put %p in __CFWriteSockets list due to force and non-presence"), s);
2616                }
2617                if (__CFSocketSetFDForWrite(s)) wakeup = true;
2618            }
2619            if (turnOnRead) {
2620                if (force) {
2621                    SInt32 idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
2622                    if (kCFNotFound == idx) CFArrayAppendValue(__CFReadSockets, s);
2623                }
2624                if (__CFSocketSetFDForRead(s)) wakeup = true;
2625            }
2626            __CFSpinUnlock(&__CFActiveSocketsLock);
2627        }
2628    }
2629    __CFSocketUnlock(s);
2630}
2631
2632void CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) {
2633    CHECK_FOR_FORK();
2634    __CFGenericValidateType(s, CFSocketGetTypeID());
2635    __CFSocketLock(s);
2636    __CFSocketEnableCallBacks(s, callBackTypes, TRUE, 'r');
2637// CFLog(5, CFSTR("CFSocketEnableCallBacks(%p, 0x%x) done"), s, callBackTypes);
2638}
2639
2640static void __CFSocketSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) {
2641    CFSocketRef s = (CFSocketRef)info;
2642    __CFSocketLock(s);
2643    //??? also need to arrange delivery of all pending data
2644    if (__CFSocketIsValid(s)) {
2645        CFMutableArrayRef runLoopsOrig = s->_runLoops;
2646        CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops);
2647        CFArrayAppendValue(runLoopsCopy, rl);
2648        s->_runLoops = runLoopsCopy;
2649        CFRelease(runLoopsOrig);
2650        s->_socketSetCount++;
2651        // Since the v0 source is listened to on the SocketMgr thread, no matter how many modes it
2652        // is added to we just need to enable it there once (and _socketSetCount gives us a refCount
2653        // to know when we can finally disable it).
2654        if (1 == s->_socketSetCount) {
2655#if defined(LOG_CFSOCKET)
2656            fprintf(stdout, "scheduling socket %d\n", s->_socket);
2657#endif
2658// CFLog(5, CFSTR("__CFSocketSchedule(%p, %p, %p)"), s, rl, mode);
2659            __CFSocketEnableCallBacks(s, __CFSocketCallBackTypes(s), TRUE, 's');  // unlocks s
2660        } else
2661            __CFSocketUnlock(s);
2662    } else
2663        __CFSocketUnlock(s);
2664}
2665
2666static void __CFSocketCancel(void *info, CFRunLoopRef rl, CFStringRef mode) {
2667    CFSocketRef s = (CFSocketRef)info;
2668    SInt32 idx;
2669    __CFSocketLock(s);
2670    s->_socketSetCount--;
2671    if (0 == s->_socketSetCount) {
2672        __CFSpinLock(&__CFActiveSocketsLock);
2673        idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
2674        if (0 <= idx) {
2675// CFLog(5, CFSTR("__CFSocketCancel: removing %p from __CFWriteSockets list"), s);
2676            CFArrayRemoveValueAtIndex(__CFWriteSockets, idx);
2677            __CFSocketClearFDForWrite(s);
2678        }
2679        idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
2680        if (0 <= idx) {
2681            CFArrayRemoveValueAtIndex(__CFReadSockets, idx);
2682            __CFSocketClearFDForRead(s);
2683        }
2684        __CFSpinUnlock(&__CFActiveSocketsLock);
2685    }
2686    if (NULL != s->_runLoops) {
2687        CFMutableArrayRef runLoopsOrig = s->_runLoops;
2688        CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops);
2689        idx = CFArrayGetFirstIndexOfValue(runLoopsCopy, CFRangeMake(0, CFArrayGetCount(runLoopsCopy)), rl);
2690        if (0 <= idx) CFArrayRemoveValueAtIndex(runLoopsCopy, idx);
2691        s->_runLoops = runLoopsCopy;
2692        CFRelease(runLoopsOrig);
2693    }
2694    __CFSocketUnlock(s);
2695}
2696
2697// Note:  must be called with socket lock held, then returns with it released
2698// Used by both the v0 and v1 RunLoopSource perform routines
2699static void __CFSocketDoCallback(CFSocketRef s, CFDataRef data, CFDataRef address, CFSocketNativeHandle sock) {
2700    CFSocketCallBack callout = NULL;
2701    void *contextInfo = NULL;
2702    SInt32 errorCode = 0;
2703    Boolean readSignalled = false, writeSignalled = false, connectSignalled = false, calledOut = false;
2704    uint8_t readCallBackType, callBackTypes;
2705
2706    callBackTypes = __CFSocketCallBackTypes(s);
2707    readCallBackType = __CFSocketReadCallBackType(s);
2708    readSignalled = __CFSocketIsReadSignalled(s);
2709    writeSignalled = __CFSocketIsWriteSignalled(s);
2710    connectSignalled = writeSignalled && !s->_f.connected;
2711    __CFSocketUnsetReadSignalled(s);
2712    __CFSocketUnsetWriteSignalled(s);
2713    callout = s->_callout;
2714    contextInfo = s->_context.info;
2715#if defined(LOG_CFSOCKET)
2716    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);
2717#endif
2718    if (writeSignalled) {
2719        errorCode = s->_errorCode;
2720        s->_f.connected = TRUE;
2721    }
2722    __CFSocketUnlock(s);
2723    if ((callBackTypes & kCFSocketConnectCallBack) != 0) {
2724        if (connectSignalled && (!calledOut || CFSocketIsValid(s))) {
2725// CFLog(5, CFSTR("__CFSocketPerformV0(%p) doing connect callback, error: %d"), s, errorCode);
2726            if (errorCode) {
2727#if defined(LOG_CFSOCKET)
2728                fprintf(stdout, "perform calling out error %ld to socket %d\n", (long)errorCode, s->_socket);
2729#endif
2730                if (callout) callout(s, kCFSocketConnectCallBack, NULL, &errorCode, contextInfo);
2731                calledOut = true;
2732            } else {
2733#if defined(LOG_CFSOCKET)
2734                fprintf(stdout, "perform calling out connect to socket %d\n", s->_socket);
2735#endif
2736                if (callout) callout(s, kCFSocketConnectCallBack, NULL, NULL, contextInfo);
2737                calledOut = true;
2738            }
2739        }
2740    }
2741    if (kCFSocketDataCallBack == readCallBackType) {
2742        if (NULL != data && (!calledOut || CFSocketIsValid(s))) {
2743            SInt32 datalen = CFDataGetLength(data);
2744#if defined(LOG_CFSOCKET)
2745            fprintf(stdout, "perform calling out data of length %ld to socket %d\n", (long)datalen, s->_socket);
2746#endif
2747            if (callout) callout(s, kCFSocketDataCallBack, address, data, contextInfo);
2748            calledOut = true;
2749            if (0 == datalen) CFSocketInvalidate(s);
2750        }
2751    } else if (kCFSocketAcceptCallBack == readCallBackType) {
2752        if (INVALID_SOCKET != sock && (!calledOut || CFSocketIsValid(s))) {
2753#if defined(LOG_CFSOCKET)
2754            fprintf(stdout, "perform calling out accept of socket %d to socket %d\n", sock, s->_socket);
2755#endif
2756            if (callout) callout(s, kCFSocketAcceptCallBack, address, &sock, contextInfo);
2757            calledOut = true;
2758        }
2759    } else if (kCFSocketReadCallBack == readCallBackType) {
2760        if (readSignalled && (!calledOut || CFSocketIsValid(s))) {
2761#if defined(LOG_CFSOCKET)
2762            fprintf(stdout, "perform calling out read to socket %d\n", s->_socket);
2763#endif
2764// CFLog(5, CFSTR("__CFSocketPerformV0(%p) doing read callback"), s);
2765            if (callout) callout(s, kCFSocketReadCallBack, NULL, NULL, contextInfo);
2766            calledOut = true;
2767        }
2768    }
2769    if ((callBackTypes & kCFSocketWriteCallBack) != 0) {
2770        if (writeSignalled && !errorCode && (!calledOut || CFSocketIsValid(s))) {
2771#if defined(LOG_CFSOCKET)
2772            fprintf(stdout, "perform calling out write to socket %d\n", s->_socket);
2773#endif
2774// CFLog(5, CFSTR("__CFSocketPerformV0(%p) doing write callback"), s);
2775            if (callout) callout(s, kCFSocketWriteCallBack, NULL, NULL, contextInfo);
2776            calledOut = true;
2777        }
2778    }
2779}
2780
2781static void __CFSocketPerformV0(void *info) {
2782    CFSocketRef s = (CFSocketRef)info;
2783    CFDataRef data = NULL;
2784    CFDataRef address = NULL;
2785    CFSocketNativeHandle sock = INVALID_SOCKET;
2786    uint8_t readCallBackType, callBackTypes;
2787    CFRunLoopRef rl = NULL;
2788// CFLog(5, CFSTR("__CFSocketPerformV0(%p) starting"), s);
2789
2790    __CFSocketLock(s);
2791    if (!__CFSocketIsValid(s)) {
2792        __CFSocketUnlock(s);
2793        return;
2794    }
2795    callBackTypes = __CFSocketCallBackTypes(s);
2796    readCallBackType = __CFSocketReadCallBackType(s);
2797    CFOptionFlags callBacksSignalled = 0;
2798    if (__CFSocketIsReadSignalled(s)) callBacksSignalled |= readCallBackType;
2799    if (__CFSocketIsWriteSignalled(s)) callBacksSignalled |= kCFSocketWriteCallBack;
2800
2801    if (kCFSocketDataCallBack == readCallBackType) {
2802        if (NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
2803            data = (CFDataRef)CFArrayGetValueAtIndex(s->_dataQueue, 0);
2804            CFRetain(data);
2805            CFArrayRemoveValueAtIndex(s->_dataQueue, 0);
2806            address = (CFDataRef)CFArrayGetValueAtIndex(s->_addressQueue, 0);
2807            CFRetain(address);
2808            CFArrayRemoveValueAtIndex(s->_addressQueue, 0);
2809        }
2810    } else if (kCFSocketAcceptCallBack == readCallBackType) {
2811        if (NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
2812            sock = (CFSocketNativeHandle)(uintptr_t)CFArrayGetValueAtIndex(s->_dataQueue, 0);
2813            CFArrayRemoveValueAtIndex(s->_dataQueue, 0);
2814            address = (CFDataRef)CFArrayGetValueAtIndex(s->_addressQueue, 0);
2815            CFRetain(address);
2816            CFArrayRemoveValueAtIndex(s->_addressQueue, 0);
2817        }
2818    }
2819
2820    __CFSocketDoCallback(s, data, address, sock);	// does __CFSocketUnlock(s)
2821    if (NULL != data) CFRelease(data);
2822    if (NULL != address) CFRelease(address);
2823
2824    __CFSocketLock(s);
2825    if (__CFSocketIsValid(s) && kCFSocketNoCallBack != readCallBackType) {
2826        // if there's still more data, we want to wake back up right away
2827        if ((kCFSocketDataCallBack == readCallBackType || kCFSocketAcceptCallBack == readCallBackType) && NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
2828#if defined(LOG_CFSOCKET)
2829            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);
2830#endif
2831            CFRunLoopSourceSignal(s->_source0);
2832            CFMutableArrayRef runLoopsOrig = (CFMutableArrayRef)CFRetain(s->_runLoops);
2833            CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops);
2834            CFRunLoopSourceRef source0 = s->_source0;
2835            if (NULL != source0 && !CFRunLoopSourceIsValid(source0)) {
2836                source0 = NULL;
2837            }
2838            if (source0) CFRetain(source0);
2839            __CFSocketUnlock(s);
2840            rl = __CFSocketCopyRunLoopToWakeUp(source0, runLoopsCopy);
2841            if (source0) CFRelease(source0);
2842            __CFSocketLock(s);
2843            if (runLoopsOrig == s->_runLoops) {
2844                s->_runLoops = runLoopsCopy;
2845                runLoopsCopy = NULL;
2846                CFRelease(runLoopsOrig);
2847            }
2848            CFRelease(runLoopsOrig);
2849            if (runLoopsCopy) CFRelease(runLoopsCopy);
2850        }
2851    }
2852    // Only reenable callbacks that are auto-reenabled
2853    __CFSocketEnableCallBacks(s, callBacksSignalled & s->_f.client, FALSE, 'p');  // unlocks s
2854
2855    if (NULL != rl) {
2856        CFRunLoopWakeUp(rl);
2857        CFRelease(rl);
2858    }
2859// CFLog(5, CFSTR("__CFSocketPerformV0(%p) done"), s);
2860}
2861
2862CFRunLoopSourceRef CFSocketCreateRunLoopSource(CFAllocatorRef allocator, CFSocketRef s, CFIndex order) {
2863    CHECK_FOR_FORK();
2864    CFRunLoopSourceRef result = NULL;
2865    __CFGenericValidateType(s, CFSocketGetTypeID());
2866    __CFSocketLock(s);
2867    if (__CFSocketIsValid(s)) {
2868        if (NULL != s->_source0 && !CFRunLoopSourceIsValid(s->_source0)) {
2869            CFRelease(s->_source0);
2870            s->_source0 = NULL;
2871        }
2872        if (NULL == s->_source0) {
2873            CFRunLoopSourceContext context;
2874            context.version = 0;
2875            context.info = s;
2876            context.retain = CFRetain;
2877            context.release = CFRelease;
2878            context.copyDescription = CFCopyDescription;
2879            context.equal = CFEqual;
2880            context.hash = CFHash;
2881            context.schedule = __CFSocketSchedule;
2882            context.cancel = __CFSocketCancel;
2883            context.perform = __CFSocketPerformV0;
2884            s->_source0 = CFRunLoopSourceCreate(allocator, order, &context);
2885        }
2886        CFRetain(s->_source0);        /* This retain is for the receiver */
2887        result = s->_source0;
2888    }
2889    __CFSocketUnlock(s);
2890    return result;
2891}
2892
2893#endif /* NEW_SOCKET */
2894
2895
2896
2897static uint16_t __CFSocketDefaultNameRegistryPortNumber = 2454;
2898
2899CONST_STRING_DECL(kCFSocketCommandKey, "Command")
2900CONST_STRING_DECL(kCFSocketNameKey, "Name")
2901CONST_STRING_DECL(kCFSocketValueKey, "Value")
2902CONST_STRING_DECL(kCFSocketResultKey, "Result")
2903CONST_STRING_DECL(kCFSocketErrorKey, "Error")
2904CONST_STRING_DECL(kCFSocketRegisterCommand, "Register")
2905CONST_STRING_DECL(kCFSocketRetrieveCommand, "Retrieve")
2906CONST_STRING_DECL(__kCFSocketRegistryRequestRunLoopMode, "CFSocketRegistryRequest")
2907
2908static CFSpinLock_t __CFSocketWriteLock_ = CFSpinLockInit;
2909//#warning can only send on one socket at a time now
2910
2911CF_INLINE void __CFSocketWriteLock(CFSocketRef s) {
2912    __CFSpinLock(& __CFSocketWriteLock_);
2913}
2914
2915CF_INLINE void __CFSocketWriteUnlock(CFSocketRef s) {
2916    __CFSpinUnlock(& __CFSocketWriteLock_);
2917}
2918
2919#if NEW_SOCKET
2920
2921CF_INLINE CFIndex __CFSocketFdGetSize(CFDataRef fdSet) {
2922    return NBBY * CFDataGetLength(fdSet);
2923}
2924
2925CF_INLINE Boolean __CFSocketFdSet(CFSocketNativeHandle sock, CFMutableDataRef fdSet) {
2926    /* returns true if a change occurred, false otherwise */
2927    Boolean retval = false;
2928    if (INVALID_SOCKET != sock && 0 <= sock) {
2929        CFIndex numFds = NBBY * CFDataGetLength(fdSet);
2930        fd_mask *fds_bits;
2931        if (sock >= numFds) {
2932            CFIndex oldSize = numFds / NFDBITS, newSize = (sock + NFDBITS) / NFDBITS, changeInBytes = (newSize - oldSize) * sizeof(fd_mask);
2933            CFDataIncreaseLength(fdSet, changeInBytes);
2934            fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
2935            memset(fds_bits + oldSize, 0, changeInBytes);
2936        } else {
2937            fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
2938        }
2939        if (!FD_ISSET(sock, (fd_set *)fds_bits)) {
2940            retval = true;
2941            FD_SET(sock, (fd_set *)fds_bits);
2942        }
2943    }
2944    return retval;
2945}
2946
2947#endif
2948
2949//??? need timeout, error handling, retries
2950CFSocketError CFSocketSendData(CFSocketRef s, CFDataRef address, CFDataRef data, CFTimeInterval timeout) {
2951    CHECK_FOR_FORK();
2952    const uint8_t *dataptr, *addrptr = NULL;
2953    SInt32 datalen, addrlen = 0, size = 0;
2954    CFSocketNativeHandle sock = INVALID_SOCKET;
2955    struct timeval tv;
2956    __CFGenericValidateType(s, CFSocketGetTypeID());
2957    if (address) {
2958        addrptr = CFDataGetBytePtr(address);
2959        addrlen = CFDataGetLength(address);
2960    }
2961    dataptr = CFDataGetBytePtr(data);
2962    datalen = CFDataGetLength(data);
2963    if (CFSocketIsValid(s)) sock = CFSocketGetNative(s);
2964    if (INVALID_SOCKET != sock) {
2965        CFRetain(s);
2966        __CFSocketWriteLock(s);
2967        tv.tv_sec = (timeout <= 0.0 || (CFTimeInterval)INT_MAX <= timeout) ? INT_MAX : (int)floor(timeout);
2968        tv.tv_usec = (int)floor(1.0e+6 * (timeout - floor(timeout)));
2969        setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv));	// cast for WinSock bad API
2970        if (NULL != addrptr && 0 < addrlen) {
2971            size = sendto(sock, (char *)dataptr, datalen, 0, (struct sockaddr *)addrptr, addrlen);
2972        } else {
2973            size = send(sock, (char *)dataptr, datalen, 0);
2974        }
2975#if defined(LOG_CFSOCKET)
2976        fprintf(stdout, "wrote %ld bytes to socket %d\n", (long)size, sock);
2977#endif
2978        __CFSocketWriteUnlock(s);
2979        CFRelease(s);
2980    }
2981    return (size > 0) ? kCFSocketSuccess : kCFSocketError;
2982}
2983
2984CFSocketError CFSocketSetAddress(CFSocketRef s, CFDataRef address) {
2985    CHECK_FOR_FORK();
2986    struct sockaddr *name;
2987    socklen_t namelen;
2988    __CFGenericValidateType(s, CFSocketGetTypeID());
2989    if (NULL == address) return kCFSocketError;
2990    if (!CFSocketIsValid(s)) return kCFSocketError;
2991
2992    name = (struct sockaddr *)CFDataGetBytePtr(address);
2993    namelen = (socklen_t)CFDataGetLength(address);
2994    if (!name || namelen <= 0) return kCFSocketError;
2995
2996    CFSocketNativeHandle sock = CFSocketGetNative(s);
2997#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
2998    // Verify that the namelen is correct. If not, we have to fix it up. Developers will often incorrectly use 0 or strlen(path). See 9217961 and the second half of 9098274.
2999    // Max size is a size byte, plus family byte, plus path of 255, plus a null byte.
3000    char newName[255];
3001    if (namelen > 2 && name->sa_family == AF_UNIX) {
3002        // Don't use the SUN_LEN macro, because strnlen is safer and we know the max length of the string (from CFData, minus 2 bytes for len and addr)
3003        socklen_t realLength = (sizeof(*((struct sockaddr_un *)name)) - sizeof(((struct sockaddr_un *)name)->sun_path) + strnlen(((struct sockaddr_un *)name)->sun_path, namelen - 2));
3004        if (realLength > 255) return kCFSocketError;
3005
3006        // For a UNIX domain socket, we must pass the value of name.sun_len to bind in order for getsockname() to return a result that makes sense.
3007        namelen = (socklen_t)(((struct sockaddr_un *)name)->sun_len);
3008
3009        if (realLength != namelen) {
3010            // We got a different answer for length than was supplied by the caller. Fix it up so we don't end up truncating the path.
3011            CFLog(kCFLogLevelWarning, CFSTR("WARNING: The sun_len field of a sockaddr_un structure passed to CFSocketSetAddress was not set correctly using the SUN_LEN macro."));
3012            memcpy(newName, name, realLength);
3013            namelen = realLength;
3014            ((struct sockaddr_un *)newName)->sun_len = realLength;
3015            name = (struct sockaddr *)newName;
3016        }
3017    }
3018#endif
3019    int result = bind(sock, name, namelen);
3020    if (0 == result) {
3021        listen(sock, 256);
3022    }
3023    //??? should return errno
3024    return (CFIndex)result;
3025}
3026
3027CFSocketError CFSocketConnectToAddress(CFSocketRef s, CFDataRef address, CFTimeInterval timeout) {
3028    CHECK_FOR_FORK();
3029    //??? need error handling, retries
3030    const uint8_t *name;
3031    SInt32 namelen, result = -1, connect_err = 0, select_err = 0;
3032    UInt32 yes = 1, no = 0;
3033    Boolean wasBlocking = true;
3034
3035    __CFGenericValidateType(s, CFSocketGetTypeID());
3036    if (!CFSocketIsValid(s)) return kCFSocketError;
3037    name = CFDataGetBytePtr(address);
3038    namelen = CFDataGetLength(address);
3039    if (!name || namelen <= 0) return kCFSocketError;
3040    CFSocketNativeHandle sock = CFSocketGetNative(s);
3041    {
3042#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
3043        SInt32 flags = fcntl(sock, F_GETFL, 0);
3044        if (flags >= 0) wasBlocking = ((flags & O_NONBLOCK) == 0);
3045        if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(sock, FIONBIO, (u_long *)&yes);
3046#else
3047        // You can set but not get this flag in WIN32, so assume it was in non-blocking mode.
3048        // The downside is that when we leave this routine we'll leave it non-blocking,
3049        // whether it started that way or not.
3050        SInt32 flags = 0;
3051        if (timeout > 0.0 || timeout < 0.0) ioctlsocket(sock, FIONBIO, (u_long *)&yes);
3052        wasBlocking = false;
3053#endif
3054        result = connect(sock, (struct sockaddr *)name, namelen);
3055        if (result != 0) {
3056            connect_err = __CFSocketLastError();
3057#if DEPLOYMENT_TARGET_WINDOWS
3058            if (connect_err == WSAEWOULDBLOCK) connect_err = EINPROGRESS;
3059#endif
3060        }
3061#if defined(LOG_CFSOCKET)
3062        fprintf(stdout, "connection attempt returns %d error %d on socket %d (flags 0x%x blocking %d)\n", (int) result, (int) connect_err, sock, (int) flags, wasBlocking);
3063#endif
3064        if (EINPROGRESS == connect_err && timeout >= 0.0) {
3065            /* select on socket */
3066            SInt32 nrfds;
3067            int error_size = sizeof(select_err);
3068            struct timeval tv;
3069            CFMutableDataRef fds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
3070            __CFSocketFdSet(sock, fds);
3071            tv.tv_sec = (timeout <= 0.0 || (CFTimeInterval)INT_MAX <= timeout) ? INT_MAX : (int)floor(timeout);
3072            tv.tv_usec = (int)floor(1.0e+6 * (timeout - floor(timeout)));
3073            nrfds = select(__CFSocketFdGetSize(fds), NULL, (fd_set *)CFDataGetMutableBytePtr(fds), NULL, &tv);
3074            if (nrfds < 0) {
3075                select_err = __CFSocketLastError();
3076                result = -1;
3077            } else if (nrfds == 0) {
3078                result = -2;
3079            } else {
3080                if (0 != getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&select_err, (socklen_t *)&error_size)) select_err = 0;
3081                result = (select_err == 0) ? 0 : -1;
3082            }
3083            CFRelease(fds);
3084#if defined(LOG_CFSOCKET)
3085            fprintf(stdout, "timed connection attempt %s on socket %d, result %d, select returns %d error %d\n", (result == 0) ? "succeeds" : "fails", sock, (int) result, (int) nrfds, (int) select_err);
3086#endif
3087        }
3088        if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(sock, FIONBIO, (u_long *)&no);
3089        if (EINPROGRESS == connect_err && timeout < 0.0) {
3090            result = 0;
3091#if defined(LOG_CFSOCKET)
3092            fprintf(stdout, "connection attempt continues in background on socket %d\n", sock);
3093#endif
3094        }
3095    }
3096    //??? should return errno
3097    return result;
3098}
3099
3100CFSocketRef CFSocketCreate(CFAllocatorRef allocator, SInt32 protocolFamily, SInt32 socketType, SInt32 protocol, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
3101    CHECK_FOR_FORK();
3102    CFSocketNativeHandle sock = INVALID_SOCKET;
3103    CFSocketRef s = NULL;
3104    if (0 >= protocolFamily) protocolFamily = PF_INET;
3105    if (PF_INET == protocolFamily) {
3106        if (0 >= socketType) socketType = SOCK_STREAM;
3107        if (0 >= protocol && SOCK_STREAM == socketType) protocol = IPPROTO_TCP;
3108        if (0 >= protocol && SOCK_DGRAM == socketType) protocol = IPPROTO_UDP;
3109    }
3110#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
3111    if (PF_LOCAL == protocolFamily && 0 >= socketType) socketType = SOCK_STREAM;
3112#endif
3113#if DEPLOYMENT_TARGET_WINDOWS
3114    // make sure we've called proper Win32 startup facilities before socket()
3115    __CFSocketInitializeWinSock();
3116#endif
3117    sock = socket(protocolFamily, socketType, protocol);
3118    if (INVALID_SOCKET != sock) {
3119        s = CFSocketCreateWithNative(allocator, sock, callBackTypes, callout, context);
3120    }
3121    return s;
3122}
3123
3124CFSocketRef CFSocketCreateWithSocketSignature(CFAllocatorRef allocator, const CFSocketSignature *signature, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
3125    CHECK_FOR_FORK();
3126    CFSocketRef s = CFSocketCreate(allocator, signature->protocolFamily, signature->socketType, signature->protocol, callBackTypes, callout, context);
3127    if (NULL != s && (!CFSocketIsValid(s) || kCFSocketSuccess != CFSocketSetAddress(s, signature->address))) {
3128        CFSocketInvalidate(s);
3129        CFRelease(s);
3130        s = NULL;
3131    }
3132    return s;
3133}
3134
3135CFSocketRef CFSocketCreateConnectedToSocketSignature(CFAllocatorRef allocator, const CFSocketSignature *signature, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context, CFTimeInterval timeout) {
3136    CHECK_FOR_FORK();
3137    CFSocketRef s = CFSocketCreate(allocator, signature->protocolFamily, signature->socketType, signature->protocol, callBackTypes, callout, context);
3138    if (NULL != s && (!CFSocketIsValid(s) || kCFSocketSuccess != CFSocketConnectToAddress(s, signature->address, timeout))) {
3139        CFSocketInvalidate(s);
3140        CFRelease(s);
3141        s = NULL;
3142    }
3143    return s;
3144}
3145
3146typedef struct {
3147    CFSocketError *error;
3148    CFPropertyListRef *value;
3149    CFDataRef *address;
3150} __CFSocketNameRegistryResponse;
3151
3152static void __CFSocketHandleNameRegistryReply(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {
3153    CFDataRef replyData = (CFDataRef)data;
3154    __CFSocketNameRegistryResponse *response = (__CFSocketNameRegistryResponse *)info;
3155    CFDictionaryRef replyDictionary = NULL;
3156    CFPropertyListRef value;
3157    replyDictionary = (CFDictionaryRef)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, replyData, kCFPropertyListImmutable, NULL);
3158    if (NULL != response->error) *(response->error) = kCFSocketError;
3159    if (NULL != replyDictionary) {
3160        if (CFGetTypeID((CFTypeRef)replyDictionary) == CFDictionaryGetTypeID() && NULL != (value = CFDictionaryGetValue(replyDictionary, kCFSocketResultKey))) {
3161            if (NULL != response->error) *(response->error) = kCFSocketSuccess;
3162            if (NULL != response->value) *(response->value) = CFRetain(value);
3163            if (NULL != response->address) *(response->address) = address ? CFDataCreateCopy(kCFAllocatorSystemDefault, address) : NULL;
3164        }
3165        CFRelease(replyDictionary);
3166    }
3167    CFSocketInvalidate(s);
3168}
3169
3170static void __CFSocketSendNameRegistryRequest(CFSocketSignature *signature, CFDictionaryRef requestDictionary, __CFSocketNameRegistryResponse *response, CFTimeInterval timeout) {
3171    CFDataRef requestData = NULL;
3172    CFSocketContext context = {0, response, NULL, NULL, NULL};
3173    CFSocketRef s = NULL;
3174    CFRunLoopSourceRef source = NULL;
3175    if (NULL != response->error) *(response->error) = kCFSocketError;
3176    requestData = CFPropertyListCreateXMLData(kCFAllocatorSystemDefault, requestDictionary);
3177    if (NULL != requestData) {
3178        if (NULL != response->error) *(response->error) = kCFSocketTimeout;
3179        s = CFSocketCreateConnectedToSocketSignature(kCFAllocatorSystemDefault, signature, kCFSocketDataCallBack, __CFSocketHandleNameRegistryReply, &context, timeout);
3180        if (NULL != s) {
3181            if (kCFSocketSuccess == CFSocketSendData(s, NULL, requestData, timeout)) {
3182                source = CFSocketCreateRunLoopSource(kCFAllocatorSystemDefault, s, 0);
3183                CFRunLoopAddSource(CFRunLoopGetCurrent(), source, __kCFSocketRegistryRequestRunLoopMode);
3184                CFRunLoopRunInMode(__kCFSocketRegistryRequestRunLoopMode, timeout, false);
3185                CFRelease(source);
3186            }
3187            CFSocketInvalidate(s);
3188            CFRelease(s);
3189        }
3190        CFRelease(requestData);
3191    }
3192}
3193
3194static void __CFSocketValidateSignature(const CFSocketSignature *providedSignature, CFSocketSignature *signature, uint16_t defaultPortNumber) {
3195    struct sockaddr_in sain, *sainp;
3196    memset(&sain, 0, sizeof(sain));
3197#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
3198    sain.sin_len = sizeof(sain);
3199#endif
3200    sain.sin_family = AF_INET;
3201    sain.sin_port = htons(__CFSocketDefaultNameRegistryPortNumber);
3202    sain.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
3203    if (NULL == providedSignature) {
3204        signature->protocolFamily = PF_INET;
3205        signature->socketType = SOCK_STREAM;
3206        signature->protocol = IPPROTO_TCP;
3207        signature->address = CFDataCreate(kCFAllocatorSystemDefault, (uint8_t *)&sain, sizeof(sain));
3208    } else {
3209        signature->protocolFamily = providedSignature->protocolFamily;
3210        signature->socketType = providedSignature->socketType;
3211        signature->protocol = providedSignature->protocol;
3212        if (0 >= signature->protocolFamily) signature->protocolFamily = PF_INET;
3213        if (PF_INET == signature->protocolFamily) {
3214            if (0 >= signature->socketType) signature->socketType = SOCK_STREAM;
3215            if (0 >= signature->protocol && SOCK_STREAM == signature->socketType) signature->protocol = IPPROTO_TCP;
3216            if (0 >= signature->protocol && SOCK_DGRAM == signature->socketType) signature->protocol = IPPROTO_UDP;
3217        }
3218        if (NULL == providedSignature->address) {
3219            signature->address = CFDataCreate(kCFAllocatorSystemDefault, (uint8_t *)&sain, sizeof(sain));
3220        } else {
3221            sainp = (struct sockaddr_in *)CFDataGetBytePtr(providedSignature->address);
3222            if ((int)sizeof(struct sockaddr_in) <= CFDataGetLength(providedSignature->address) && (AF_INET == sainp->sin_family || 0 == sainp->sin_family)) {
3223#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
3224                sain.sin_len = sizeof(sain);
3225#endif
3226                sain.sin_family = AF_INET;
3227                sain.sin_port = sainp->sin_port;
3228                if (0 == sain.sin_port) sain.sin_port = htons(defaultPortNumber);
3229                sain.sin_addr.s_addr = sainp->sin_addr.s_addr;
3230                if (htonl(INADDR_ANY) == sain.sin_addr.s_addr) sain.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
3231                signature->address = CFDataCreate(kCFAllocatorSystemDefault, (uint8_t *)&sain, sizeof(sain));
3232            } else {
3233                signature->address = (CFDataRef)CFRetain(providedSignature->address);
3234            }
3235        }
3236    }
3237}
3238
3239CFSocketError CFSocketRegisterValue(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFPropertyListRef value) {
3240    CFSocketSignature signature;
3241    CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
3242    CFSocketError retval = kCFSocketError;
3243    __CFSocketNameRegistryResponse response = {&retval, NULL, NULL};
3244    CFDictionaryAddValue(dictionary, kCFSocketCommandKey, kCFSocketRegisterCommand);
3245    CFDictionaryAddValue(dictionary, kCFSocketNameKey, name);
3246    if (NULL != value) CFDictionaryAddValue(dictionary, kCFSocketValueKey, value);
3247    __CFSocketValidateSignature(nameServerSignature, &signature, __CFSocketDefaultNameRegistryPortNumber);
3248    __CFSocketSendNameRegistryRequest(&signature, dictionary, &response, timeout);
3249    CFRelease(dictionary);
3250    CFRelease(signature.address);
3251    return retval;
3252}
3253
3254CFSocketError CFSocketCopyRegisteredValue(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFPropertyListRef *value, CFDataRef *serverAddress) {
3255    CFSocketSignature signature;
3256    CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
3257    CFSocketError retval = kCFSocketError;
3258    __CFSocketNameRegistryResponse response = {&retval, value, serverAddress};
3259    CFDictionaryAddValue(dictionary, kCFSocketCommandKey, kCFSocketRetrieveCommand);
3260    CFDictionaryAddValue(dictionary, kCFSocketNameKey, name);
3261    __CFSocketValidateSignature(nameServerSignature, &signature, __CFSocketDefaultNameRegistryPortNumber);
3262    __CFSocketSendNameRegistryRequest(&signature, dictionary, &response, timeout);
3263    CFRelease(dictionary);
3264    CFRelease(signature.address);
3265    return retval;
3266}
3267
3268CFSocketError CFSocketRegisterSocketSignature(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, const CFSocketSignature *signature) {
3269    CFSocketSignature validatedSignature;
3270    CFMutableDataRef data = NULL;
3271    CFSocketError retval;
3272    CFIndex length;
3273    uint8_t bytes[4];
3274    if (NULL == signature) {
3275        retval = CFSocketUnregister(nameServerSignature, timeout, name);
3276    } else {
3277        __CFSocketValidateSignature(signature, &validatedSignature, 0);
3278        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) {
3279            retval = kCFSocketError;
3280        } else {
3281            data = CFDataCreateMutable(kCFAllocatorSystemDefault, sizeof(bytes) + length);
3282            bytes[0] = validatedSignature.protocolFamily;
3283            bytes[1] = validatedSignature.socketType;
3284            bytes[2] = validatedSignature.protocol;
3285            bytes[3] = length;
3286            CFDataAppendBytes(data, bytes, sizeof(bytes));
3287            CFDataAppendBytes(data, CFDataGetBytePtr(validatedSignature.address), length);
3288            retval = CFSocketRegisterValue(nameServerSignature, timeout, name, data);
3289            CFRelease(data);
3290        }
3291        CFRelease(validatedSignature.address);
3292    }
3293    return retval;
3294}
3295
3296CFSocketError CFSocketCopyRegisteredSocketSignature(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFSocketSignature *signature, CFDataRef *nameServerAddress) {
3297    CFDataRef data = NULL;
3298    CFSocketSignature returnedSignature;
3299    const uint8_t *ptr = NULL, *aptr = NULL;
3300    uint8_t *mptr;
3301    CFIndex length = 0;
3302    CFDataRef serverAddress = NULL;
3303    CFSocketError retval = CFSocketCopyRegisteredValue(nameServerSignature, timeout, name, (CFPropertyListRef *)&data, &serverAddress);
3304    if (NULL == data || CFGetTypeID(data) != CFDataGetTypeID() || NULL == (ptr = CFDataGetBytePtr(data)) || (length = CFDataGetLength(data)) < 4) retval = kCFSocketError;
3305    if (kCFSocketSuccess == retval && NULL != signature) {
3306        returnedSignature.protocolFamily = (SInt32)*ptr++;
3307        returnedSignature.socketType = (SInt32)*ptr++;
3308        returnedSignature.protocol = (SInt32)*ptr++;
3309        ptr++;
3310        returnedSignature.address = CFDataCreate(kCFAllocatorSystemDefault, ptr, length - 4);
3311        __CFSocketValidateSignature(&returnedSignature, signature, 0);
3312        CFRelease(returnedSignature.address);
3313        ptr = CFDataGetBytePtr(signature->address);
3314        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) {
3315            CFMutableDataRef address = CFDataCreateMutableCopy(kCFAllocatorSystemDefault, CFDataGetLength(signature->address), signature->address);
3316            mptr = CFDataGetMutableBytePtr(address);
3317            ((struct sockaddr_in *)mptr)->sin_addr = ((struct sockaddr_in *)aptr)->sin_addr;
3318            CFRelease(signature->address);
3319            signature->address = address;
3320        }
3321        if (NULL != nameServerAddress) *nameServerAddress = serverAddress ? (CFDataRef)CFRetain(serverAddress) : NULL;
3322    }
3323    if (NULL != data) CFRelease(data);
3324    if (NULL != serverAddress) CFRelease(serverAddress);
3325    return retval;
3326}
3327
3328CFSocketError CFSocketUnregister(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name) {
3329    return CFSocketRegisterValue(nameServerSignature, timeout, name, NULL);
3330}
3331
3332CF_EXPORT void CFSocketSetDefaultNameRegistryPortNumber(uint16_t port) {
3333    __CFSocketDefaultNameRegistryPortNumber = port;
3334}
3335
3336CF_EXPORT uint16_t CFSocketGetDefaultNameRegistryPortNumber(void) {
3337    return __CFSocketDefaultNameRegistryPortNumber;
3338}
3339
3340