CFSocket.c
   1  /*	CFSocket.c
   2  	Copyright (c) 1999-2019, Apple Inc.  and the Swift project authors
   3   
   4  	Portions Copyright (c) 2014-2019, Apple Inc. and the Swift project authors
   5  	Licensed under Apache License v2.0 with Runtime Library Exception
   6  	See http://swift.org/LICENSE.txt for license information
   7  	See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
   8  	Responsibility: Michael LeHew
   9  */
  10  
  11  #include <CoreFoundation/CFSocket.h>
  12  #include <sys/types.h>
  13  #include <math.h>
  14  #include <limits.h>
  15  #if TARGET_OS_MAC
  16  #include <sys/sysctl.h>
  17  #include <sys/un.h>
  18  #include <libc.h>
  19  #include <dlfcn.h>
  20  #if TARGET_OS_CYGWIN
  21  #include <sys/socket.h>
  22  #endif
  23  #endif
  24  #if TARGET_OS_CYGWIN || TARGET_OS_BSD
  25  #include <sys/socket.h>
  26  #endif
  27  #if TARGET_OS_WIN32
  28  #include <WinSock2.h>
  29  #else
  30  #include <arpa/inet.h>
  31  #include <netinet/in.h>
  32  #endif
  33  #if !TARGET_OS_WIN32
  34  #include <sys/ioctl.h>
  35  #endif
  36  #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
  37  #include <unistd.h>
  38  #endif
  39  #include <fcntl.h>
  40  #include <CoreFoundation/CFArray.h>
  41  #include <CoreFoundation/CFData.h>
  42  #include <CoreFoundation/CFDictionary.h>
  43  #include <CoreFoundation/CFRunLoop.h>
  44  #include <CoreFoundation/CFString.h>
  45  #include <CoreFoundation/CFPropertyList.h>
  46  #include "CFInternal.h"
  47  #include "CFRuntime_Internal.h"
  48  #if TARGET_OS_WIN32
  49  #include <process.h>
  50  #endif
  51  
  52  #ifndef NBBY
  53  #define NBBY 8
  54  #endif
  55  
  56  #if TARGET_OS_WIN32
  57  
  58  // redefine this to the winsock error in this file
  59  #undef EINPROGRESS
  60  #define EINPROGRESS WSAEINPROGRESS
  61  
  62  // redefine this to the winsock error in this file
  63  #undef EBADF
  64  #define EBADF WSAENOTSOCK
  65  
  66  #define NFDBITS	(sizeof(int32_t) * NBBY)
  67  
  68  typedef int32_t fd_mask;
  69  typedef int socklen_t;
  70  
  71  #define gettimeofday _NS_gettimeofday
  72  struct timezone;
  73  CF_PRIVATE int _NS_gettimeofday(struct timeval *tv, struct timezone *tz);
  74  
  75  // although this is only used for debug info, we define it for compatibility
  76  #define	timersub(tvp, uvp, vvp) \
  77      do { \
  78          (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;		\
  79          (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec;	\
  80          if ((vvp)->tv_usec < 0) {				\
  81              (vvp)->tv_sec--;				\
  82              (vvp)->tv_usec += 1000000;			\
  83          }							\
  84      } while (0)
  85  
  86  static void timeradd(struct timeval *a, struct timeval *b, struct timeval *res) {
  87    res->tv_sec = a->tv_sec + b->tv_sec;
  88    res->tv_usec = a->tv_usec + b->tv_usec;
  89    if (res->tv_usec > 1e06) {
  90      res->tv_sec++;
  91      res->tv_usec -= 1e06;
  92    }
  93  }
  94  
  95  #endif // TARGET_OS_WIN32
  96  
  97  
  98  // On Mach we use a v0 RunLoopSource to make client callbacks.  That source is signalled by a
  99  // separate SocketManager thread who uses select() to watch the sockets' fds.
 100  
 101  #undef LOG_CFSOCKET
 102  //#define LOG_CFSOCKET            1
 103  #define DEBUG_POLLING_SELECT    1
 104  
 105  #if defined(LOG_CFSOCKET)
 106  
 107  #include <sys/syslog.h>
 108  
 109  static _CFThreadRef __cfSocketTid()
 110  {
 111  #if TARGET_OS_MAC
 112      uint64_t tid = 0;
 113      if (0 != pthread_threadid_np(NULL, &tid))
 114          tid = pthread_mach_thread_np(pthread_self());
 115      return (_CFThreadRef) tid;
 116  #elif TARGET_OS_WIN32
 117      return (_CFThreadRef) GetCurrentThreadId();
 118  #else
 119      return (_CFThreadRef) pthread_self();
 120  #endif
 121  }
 122  
 123  static void __cfSocketLog(const char* function, int line, const char* fmt, ...)
 124  {
 125  #if 0
 126      char* p = nil;
 127      va_list args;
 128      va_start(args, fmt);
 129      vasprintf(&p, fmt, args);
 130      va_end(args);
 131  
 132  //    CFLog(kCFLogLevelNotice, CFSTR("CFSocket:%d %s"), line, p);
 133      char* s = nil;
 134      asprintf(&s, "CFSocket:%d %s", line, p);
 135      syslog(LOG_NOTICE, "%s", s);
 136      free(s);
 137      
 138      free(p);
 139  #else
 140      va_list args;
 141      va_start(args, fmt);
 142      CFStringRef fmtString = CFStringCreateWithCString(kCFAllocatorDefault, fmt, kCFStringEncodingUTF8);
 143      CFStringRef payload = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, fmtString, args);
 144      if (fmtString)
 145          CFRelease(fmtString);
 146  
 147      if (payload == NULL)
 148          syslog(LOG_NOTICE, "CFSocket[%p]:%s:%d - no payload?", __cfSocketTid(),function, line);
 149      else {
 150          CFDataRef payloadData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, payload, kCFStringEncodingUTF8, '.');
 151          CFRelease(payload);
 152  
 153          if (payloadData == NULL)
 154              syslog(LOG_NOTICE, "CFSocket[%p]:%s:%d - no payload?", __cfSocketTid(),function, line);
 155          else {
 156              syslog(LOG_NOTICE, "CFSocket[%p]:%s:%d - %.*s", __cfSocketTid(),function, line, (int) CFDataGetLength(payloadData), CFDataGetBytePtr(payloadData));
 157              CFRelease(payloadData);
 158          }
 159      }
 160  
 161  #endif
 162  }
 163  
 164  static void __cfSocketLogWithSocket(CFSocketRef s, const char* function, int line, const char* fmt, ...)
 165  {
 166      va_list args;
 167      va_start(args, fmt);
 168      CFStringRef fmtString = CFStringCreateWithCString(kCFAllocatorDefault, fmt, kCFStringEncodingUTF8);
 169      CFStringRef payload = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, fmtString, args);
 170      if (fmtString)
 171          CFRelease(fmtString);
 172  
 173      if (payload == NULL)
 174          syslog(LOG_NOTICE, "CFSocket[%p]:%s:%d (%p, fd %d) - no payload?", __cfSocketTid(), function, line, s, CFSocketGetNative(s));
 175      else {
 176          CFDataRef payloadData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, payload, kCFStringEncodingUTF8, '.');
 177          CFRelease(payload);
 178  
 179          if (payloadData == NULL)
 180              syslog(LOG_NOTICE, "CFSocket[%p]:%s:%d (%p, fd %d) - no payload?", __cfSocketTid(), function, line, s, CFSocketGetNative(s));
 181          else {
 182              syslog(LOG_NOTICE, "CFSocket[%p]:%s:%d (%p, fd %d) - %.*s", __cfSocketTid(), function, line, s, CFSocketGetNative(s), (int) CFDataGetLength(payloadData), CFDataGetBytePtr(payloadData));
 183              CFRelease(payloadData);
 184          }
 185      }
 186  }
 187  
 188  #define __CFSOCKETLOG(xxx...)  __cfSocketLog(__FUNCTION__, __LINE__, xxx)
 189  #define __CFSOCKETLOG_WS(S, xxx...)  __cfSocketLogWithSocket(S, __FUNCTION__, __LINE__, xxx)
 190  
 191  #else
 192  
 193  #define __CFSOCKETLOG(xxx...)  /**/
 194  #define __CFSOCKETLOG_WS(S, xxx...) /**/
 195  
 196  #endif
 197  
 198  
 199  #if TARGET_OS_MAC || TARGET_OS_LINUX || TARGET_OS_BSD
 200  #define INVALID_SOCKET (CFSocketNativeHandle)(-1)
 201  #define closesocket(a) close((a))
 202  #define ioctlsocket(a,b,c) ioctl((a),(b),(c))
 203  #endif
 204  
 205  CF_INLINE int __CFSocketLastError(void) {
 206  #if TARGET_OS_WIN32
 207      return WSAGetLastError();
 208  #else
 209      return thread_errno();
 210  #endif
 211  }
 212  
 213  CF_INLINE CFIndex __CFSocketFdGetSize(CFDataRef fdSet) {
 214      return NBBY * CFDataGetLength(fdSet);
 215  }
 216  
 217  CF_INLINE Boolean __CFSocketFdSet(CFSocketNativeHandle sock, CFMutableDataRef fdSet) {
 218      /* returns true if a change occurred, false otherwise */
 219      Boolean retval = false;
 220      if (INVALID_SOCKET != sock && 0 <= sock) {
 221          CFIndex numFds = NBBY * CFDataGetLength(fdSet);
 222          fd_mask *fds_bits;
 223          if (sock >= numFds) {
 224              CFIndex oldSize = numFds / NFDBITS, newSize = (sock + NFDBITS) / NFDBITS, changeInBytes = (newSize - oldSize) * sizeof(fd_mask);
 225              CFDataIncreaseLength(fdSet, changeInBytes);
 226              fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
 227              memset(fds_bits + oldSize, 0, changeInBytes);
 228          } else {
 229              fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
 230          }
 231          if (!FD_ISSET(sock, (fd_set *)fds_bits)) {
 232              retval = true;
 233              FD_SET(sock, (fd_set *)fds_bits);
 234          }
 235      }
 236      return retval;
 237  }
 238  
 239  
 240  #define MAX_SOCKADDR_LEN 256
 241  #define MAX_DATA_SIZE 65535
 242  #define MAX_CONNECTION_ORIENTED_DATA_SIZE 32768
 243  
 244  /* locks are to be acquired in the following order:
 245     (1) __CFAllSocketsLock
 246     (2) an individual CFSocket's lock
 247     (3) __CFActiveSocketsLock
 248  */
 249  static CFLock_t __CFAllSocketsLock = CFLockInit; /* controls __CFAllSockets */
 250  static CFMutableDictionaryRef __CFAllSockets = NULL;
 251  static CFLock_t __CFActiveSocketsLock = CFLockInit; /* controls __CFRead/WriteSockets, __CFRead/WriteSocketsFds, __CFSocketManagerThread, and __CFSocketManagerIteration */
 252  static volatile UInt32 __CFSocketManagerIteration = 0;
 253  static CFMutableArrayRef __CFWriteSockets = NULL;
 254  static CFMutableArrayRef __CFReadSockets = NULL;
 255  static CFMutableDataRef __CFWriteSocketsFds = NULL;
 256  static CFMutableDataRef __CFReadSocketsFds = NULL;
 257  static CFDataRef zeroLengthData = NULL;
 258  static Boolean __CFReadSocketsTimeoutInvalid = true;  /* rebuild the timeout value before calling select */
 259  
 260  static CFSocketNativeHandle __CFWakeupSocketPair[2] = {INVALID_SOCKET, INVALID_SOCKET};
 261  static void *__CFSocketManagerThread = NULL;
 262  
 263  static void __CFSocketDoCallback(CFSocketRef s, CFDataRef data, CFDataRef address, CFSocketNativeHandle sock);
 264  
 265  struct __CFSocket {
 266      CFRuntimeBase _base;
 267      struct {
 268          unsigned client:8;	// flags set by client (reenable, CloseOnInvalidate)
 269          unsigned disabled:8;	// flags marking disabled callbacks
 270          unsigned connected:1;	// Are we connected yet?  (also true for connectionless sockets)
 271          unsigned writableHint:1;  // Did the polling the socket show it to be writable?
 272          unsigned closeSignaled:1;  // Have we seen FD_CLOSE? (only used on Win32)
 273          unsigned unused:13;
 274      } _f;
 275      CFLock_t _lock;
 276      CFLock_t _writeLock;
 277      CFSocketNativeHandle _socket;	/* immutable */
 278      SInt32 _socketType;
 279      SInt32 _errorCode;
 280      CFDataRef _address;
 281      CFDataRef _peerAddress;
 282      SInt32 _socketSetCount;
 283      CFRunLoopSourceRef _source0;	// v0 RLS, messaged from SocketMgr
 284      CFMutableArrayRef _runLoops;
 285      CFSocketCallBack _callout;		/* immutable */
 286      CFSocketContext _context;		/* immutable */
 287      CFMutableArrayRef _dataQueue;	// queues to pass data from SocketMgr thread
 288      CFMutableArrayRef _addressQueue;
 289  	
 290  	struct timeval _readBufferTimeout;
 291  	CFMutableDataRef _readBuffer;
 292  	CFIndex _bytesToBuffer;			/* is length of _readBuffer */
 293  	CFIndex _bytesToBufferPos;		/* where the next _CFSocketRead starts from */
 294  	CFIndex _bytesToBufferReadPos;	/* Where the buffer will next be read into (always after _bytesToBufferPos, but less than _bytesToBuffer) */
 295  	Boolean _atEOF;
 296      int _bufferedReadError;
 297  	
 298  	CFMutableDataRef _leftoverBytes;
 299  
 300      // <rdar://problem/17849895>
 301      // If the timeout is set on the CFSocketRef but we never get select() timeout
 302      // because we always have some network events so select never times out (e.g. while having a large download).
 303      // We need to notify any waiting buffered read clients if there is data available without relying on select timing out.
 304      struct timeval _readBufferTimeoutNotificationTime;
 305      Boolean _hitTheTimeout;
 306  };
 307  
 308  /* Bit 6 in the base reserved bits is used for write-signalled state (mutable) */
 309  /* Bit 5 in the base reserved bits is used for read-signalled state (mutable) */
 310  /* Bit 4 in the base reserved bits is used for invalid state (mutable) */
 311  /* Bits 0-3 in the base reserved bits are used for callback types (immutable) */
 312  /* Of this, bits 0-1 are used for the read callback type. */
 313  
 314  CF_INLINE Boolean __CFSocketIsWriteSignalled(CFSocketRef s) {
 315      return __CFRuntimeGetFlag(s, 6);
 316  }
 317  
 318  CF_INLINE void __CFSocketSetWriteSignalled(CFSocketRef s) {
 319      __CFRuntimeSetFlag(s, 6, true);
 320  }
 321  
 322  CF_INLINE void __CFSocketUnsetWriteSignalled(CFSocketRef s) {
 323      __CFRuntimeSetFlag(s, 6, false);
 324  }
 325  
 326  CF_INLINE Boolean __CFSocketIsReadSignalled(CFSocketRef s) {
 327      return __CFRuntimeGetFlag(s, 5);
 328  }
 329  
 330  CF_INLINE void __CFSocketSetReadSignalled(CFSocketRef s) {
 331      __CFRuntimeSetFlag(s, 5, true);
 332  }
 333  
 334  CF_INLINE void __CFSocketUnsetReadSignalled(CFSocketRef s) {
 335      __CFRuntimeSetFlag(s, 5, false);
 336  }
 337  
 338  CF_INLINE Boolean __CFSocketIsValid(CFSocketRef s) {
 339      return __CFRuntimeGetFlag(s, 4);
 340  }
 341  
 342  CF_INLINE void __CFSocketSetValid(CFSocketRef s) {
 343      __CFRuntimeSetFlag(s, 4, true);
 344  }
 345  
 346  CF_INLINE void __CFSocketUnsetValid(CFSocketRef s) {
 347      __CFRuntimeSetFlag(s, 4, false);
 348  }
 349  
 350  CF_INLINE uint8_t __CFSocketCallBackTypes(CFSocketRef s) {
 351      return (uint8_t)__CFRuntimeGetValue(s, 3, 0);
 352  }
 353  
 354  CF_INLINE uint8_t __CFSocketReadCallBackType(CFSocketRef s) {
 355      return (uint8_t)__CFRuntimeGetValue(s, 1, 0);
 356  }
 357  
 358  CF_INLINE void __CFSocketSetCallBackTypes(CFSocketRef s, uint8_t types) {
 359      __CFRuntimeSetValue(s, 3, 0, types & 0xF);
 360  }
 361  
 362  CF_INLINE void __CFSocketLock(CFSocketRef s) {
 363      __CFLock(&(s->_lock));
 364  }
 365  
 366  CF_INLINE void __CFSocketUnlock(CFSocketRef s) {
 367      __CFUnlock(&(s->_lock));
 368  }
 369  
 370  CF_INLINE Boolean __CFSocketIsConnectionOriented(CFSocketRef s) {
 371      return (SOCK_STREAM == s->_socketType);
 372  }
 373  
 374  CF_INLINE Boolean __CFSocketIsScheduled(CFSocketRef s) {
 375      return (s->_socketSetCount > 0);
 376  }
 377  
 378  CF_INLINE void __CFSocketEstablishAddress(CFSocketRef s) {
 379      /* socket should already be locked */
 380      uint8_t name[MAX_SOCKADDR_LEN];
 381      int namelen = sizeof(name);
 382      if (__CFSocketIsValid(s) && NULL == s->_address && INVALID_SOCKET != s->_socket && 0 == getsockname(s->_socket, (struct sockaddr *)name, (socklen_t *)&namelen) && 0 < namelen) {
 383          s->_address = CFDataCreate(CFGetAllocator(s), name, namelen);
 384      }
 385  }
 386  
 387  CF_INLINE void __CFSocketEstablishPeerAddress(CFSocketRef s) {
 388      /* socket should already be locked */
 389      uint8_t name[MAX_SOCKADDR_LEN];
 390      int namelen = sizeof(name);
 391      if (__CFSocketIsValid(s) && NULL == s->_peerAddress && INVALID_SOCKET != s->_socket && 0 == getpeername(s->_socket, (struct sockaddr *)name, (socklen_t *)&namelen) && 0 < namelen) {
 392          s->_peerAddress = CFDataCreate(CFGetAllocator(s), name, namelen);
 393      }
 394  }
 395  
 396  static Boolean __CFNativeSocketIsValid(CFSocketNativeHandle sock) {
 397      Boolean result;
 398  
 399  #if TARGET_OS_WIN32
 400      SInt32 errorCode = 0;
 401      int errorSize = sizeof(errorCode);
 402      result = !(0 != getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&errorCode, &errorSize) && __CFSocketLastError() == WSAENOTSOCK);
 403  #else    
 404      SInt32 flags = fcntl(sock, F_GETFL, 0);
 405      result = !(0 > flags && EBADF == __CFSocketLastError());
 406  #endif
 407  
 408      __CFSOCKETLOG("socket fd %d => %d", sock, result);
 409  
 410      return result;
 411  }
 412  
 413  CF_INLINE Boolean __CFSocketFdClr(CFSocketNativeHandle sock, CFMutableDataRef fdSet) {
 414      /* returns true if a change occurred, false otherwise */
 415      Boolean retval = false;
 416      if (INVALID_SOCKET != sock && 0 <= sock) {
 417          CFIndex numFds = NBBY * CFDataGetLength(fdSet);
 418          fd_mask *fds_bits;
 419          if (sock < numFds) {
 420              fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
 421              if (FD_ISSET(sock, (fd_set *)fds_bits)) {
 422                  retval = true;
 423                  FD_CLR(sock, (fd_set *)fds_bits);
 424              }
 425          }
 426      }
 427      return retval;
 428  }
 429  
 430  static SInt32 __CFSocketCreateWakeupSocketPair(void) {
 431  #if TARGET_OS_MAC
 432      SInt32 error;
 433  
 434      error = socketpair(PF_LOCAL, SOCK_DGRAM, 0, __CFWakeupSocketPair);
 435      if (0 <= error) error = fcntl(__CFWakeupSocketPair[0], F_SETFD, FD_CLOEXEC);
 436      if (0 <= error) error = fcntl(__CFWakeupSocketPair[1], F_SETFD, FD_CLOEXEC);
 437      if (0 > error) {
 438          closesocket(__CFWakeupSocketPair[0]);
 439          closesocket(__CFWakeupSocketPair[1]);
 440          __CFWakeupSocketPair[0] = INVALID_SOCKET;
 441          __CFWakeupSocketPair[1] = INVALID_SOCKET;
 442      }
 443  #else
 444      UInt32 i;
 445      SInt32 error = 0;
 446      struct sockaddr_in address[2];
 447      int namelen = sizeof(struct sockaddr_in);
 448      for (i = 0; i < 2; i++) {
 449          __CFWakeupSocketPair[i] = socket(PF_INET, SOCK_DGRAM, 0);
 450          memset(&(address[i]), 0, sizeof(struct sockaddr_in));
 451          address[i].sin_family = AF_INET;
 452          address[i].sin_addr.s_addr = htonl(INADDR_LOOPBACK);
 453          if (0 <= error) error = bind(__CFWakeupSocketPair[i], (struct sockaddr *)&(address[i]), sizeof(struct sockaddr_in));
 454          if (0 <= error) error = getsockname(__CFWakeupSocketPair[i], (struct sockaddr *)&(address[i]), (socklen_t *)&namelen);
 455          if (sizeof(struct sockaddr_in) != namelen) error = -1;
 456      }
 457      if (0 <= error) error = connect(__CFWakeupSocketPair[0], (struct sockaddr *)&(address[1]), sizeof(struct sockaddr_in));
 458      if (0 <= error) error = connect(__CFWakeupSocketPair[1], (struct sockaddr *)&(address[0]), sizeof(struct sockaddr_in));
 459      if (0 > error) {
 460          closesocket(__CFWakeupSocketPair[0]);
 461          closesocket(__CFWakeupSocketPair[1]);
 462          __CFWakeupSocketPair[0] = INVALID_SOCKET;
 463          __CFWakeupSocketPair[1] = INVALID_SOCKET;
 464      }
 465  #endif
 466  
 467      __CFSOCKETLOG("wakeup socket pair is %d / %d\n", __CFWakeupSocketPair[0], __CFWakeupSocketPair[1]);
 468  
 469      return error;
 470  }
 471  
 472  
 473  // Version 0 RunLoopSources set a mask in an FD set to control what socket activity we hear about.
 474  // Changes to the master fs_sets occur via these 4 functions.
 475  CF_INLINE Boolean __CFSocketSetFDForRead(CFSocketRef s) {
 476      __CFSOCKETLOG_WS(s, "");
 477      __CFReadSocketsTimeoutInvalid = true;
 478      Boolean b = __CFSocketFdSet(s->_socket, __CFReadSocketsFds);
 479      if (b && INVALID_SOCKET != __CFWakeupSocketPair[0]) {
 480          uint8_t c = 'r';
 481          send(__CFWakeupSocketPair[0], (const char *)&c, sizeof(c), 0);
 482      }
 483      return b;
 484  }
 485  
 486  CF_INLINE Boolean __CFSocketClearFDForRead(CFSocketRef s) {
 487      __CFSOCKETLOG_WS(s, "");
 488      __CFReadSocketsTimeoutInvalid = true;
 489      Boolean b = __CFSocketFdClr(s->_socket, __CFReadSocketsFds);
 490      if (b && INVALID_SOCKET != __CFWakeupSocketPair[0]) {
 491          uint8_t c = 's';
 492          send(__CFWakeupSocketPair[0], (const char *)&c, sizeof(c), 0);
 493      }
 494      return b;
 495  }
 496  
 497  CF_INLINE Boolean __CFSocketSetFDForWrite(CFSocketRef s) {
 498      __CFSOCKETLOG_WS(s, "");
 499      Boolean b = __CFSocketFdSet(s->_socket, __CFWriteSocketsFds);
 500      if (b && INVALID_SOCKET != __CFWakeupSocketPair[0]) {
 501          uint8_t c = 'w';
 502          send(__CFWakeupSocketPair[0], (const char *)&c, sizeof(c), 0);
 503      }
 504      return b;
 505  }
 506  
 507  CF_INLINE Boolean __CFSocketClearFDForWrite(CFSocketRef s) {
 508      __CFSOCKETLOG_WS(s, "");
 509      Boolean b = __CFSocketFdClr(s->_socket, __CFWriteSocketsFds);
 510      if (b && INVALID_SOCKET != __CFWakeupSocketPair[0]) {
 511          uint8_t c = 'x';
 512          send(__CFWakeupSocketPair[0], (const char *)&c, sizeof(c), 0);
 513      }
 514      return b;
 515  }
 516  
 517  #if TARGET_OS_WIN32
 518  static Boolean WinSockUsed = FALSE;
 519  
 520  static void __CFSocketInitializeWinSock_Guts(void) {
 521      if (!WinSockUsed) {
 522          WinSockUsed = TRUE;
 523          WORD versionRequested = MAKEWORD(2, 2);
 524          WSADATA wsaData;
 525          int errorStatus = WSAStartup(versionRequested, &wsaData);
 526          if (errorStatus != 0 || LOBYTE(wsaData.wVersion) != LOBYTE(versionRequested) || HIBYTE(wsaData.wVersion) != HIBYTE(versionRequested)) {
 527              WSACleanup();
 528              CFLog(kCFLogLevelWarning, CFSTR("*** Could not initialize WinSock subsystem!!!"));
 529          }
 530      }
 531  }
 532  
 533  CF_EXPORT void __CFSocketInitializeWinSock(void) {
 534      __CFLock(&__CFActiveSocketsLock);
 535      __CFSocketInitializeWinSock_Guts();
 536      __CFUnlock(&__CFActiveSocketsLock);
 537  }
 538  
 539  CF_PRIVATE void __CFSocketCleanup(void) {
 540      if (INVALID_SOCKET != __CFWakeupSocketPair[0]) {
 541          closesocket(__CFWakeupSocketPair[0]);
 542          __CFWakeupSocketPair[0] = INVALID_SOCKET;
 543      }
 544      if (INVALID_SOCKET != __CFWakeupSocketPair[1]) {
 545          closesocket(__CFWakeupSocketPair[1]);
 546          __CFWakeupSocketPair[1] = INVALID_SOCKET;
 547      }
 548      if (WinSockUsed) {
 549          // 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
 550          WSACleanup();
 551      }
 552  }
 553  
 554  #endif
 555  
 556  // CFNetwork needs to call this, especially for Win32 to get WSAStartup
 557  static void __CFSocketInitializeSockets(void) {
 558      __CFWriteSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
 559      __CFReadSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
 560      __CFWriteSocketsFds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
 561      __CFReadSocketsFds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
 562      zeroLengthData = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
 563  #if TARGET_OS_WIN32
 564      __CFSocketInitializeWinSock_Guts();
 565  #endif
 566      if (0 > __CFSocketCreateWakeupSocketPair()) {
 567          CFLog(kCFLogLevelWarning, CFSTR("*** Could not create wakeup socket pair for CFSocket!!!"));
 568      } else {
 569          UInt32 yes = 1;
 570          /* wakeup sockets must be non-blocking */
 571          ioctlsocket(__CFWakeupSocketPair[0], FIONBIO, (u_long *)&yes);
 572          ioctlsocket(__CFWakeupSocketPair[1], FIONBIO, (u_long *)&yes);
 573          __CFSocketFdSet(__CFWakeupSocketPair[1], __CFReadSocketsFds);
 574      }
 575  }
 576  
 577  static CFRunLoopRef __CFSocketCopyRunLoopToWakeUp(CFRunLoopSourceRef src, CFMutableArrayRef runLoops) {
 578      if (!src) return NULL;
 579      CFRunLoopRef rl = NULL;
 580      SInt32 idx, cnt = CFArrayGetCount(runLoops);
 581      if (0 < cnt) {
 582          rl = (CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, 0);
 583          for (idx = 1; NULL != rl && idx < cnt; idx++) {
 584              CFRunLoopRef value = (CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, idx);
 585              if (value != rl) rl = NULL;
 586          }
 587          if (NULL == rl) {	/* more than one different rl, so we must pick one */
 588              /* ideally, this would be a run loop which isn't also in a
 589              * signaled state for this or another source, but that's tricky;
 590              * we pick one that is running in an appropriate mode for this
 591              * source, and from those if possible one that is waiting; then
 592              * we move this run loop to the end of the list to scramble them
 593              * a bit, and always search from the front */
 594              Boolean foundIt = false, foundBackup = false;
 595              SInt32 foundIdx = 0;
 596              for (idx = 0; !foundIt && idx < cnt; idx++) {
 597                  CFRunLoopRef value = (CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, idx);
 598                  CFStringRef currentMode = CFRunLoopCopyCurrentMode(value);
 599                  if (NULL != currentMode) {
 600                      if (CFRunLoopContainsSource(value, src, currentMode)) {
 601                          if (CFRunLoopIsWaiting(value)) {
 602                              foundIdx = idx;
 603                              foundIt = true;
 604                          } else if (!foundBackup) {
 605                              foundIdx = idx;
 606                              foundBackup = true;
 607                          }
 608                      }
 609                      CFRelease(currentMode);
 610                  }
 611              }
 612              rl = (CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, foundIdx);
 613              CFRetain(rl);
 614              CFArrayRemoveValueAtIndex(runLoops, foundIdx);
 615              CFArrayAppendValue(runLoops, rl);
 616          } else {
 617              CFRetain(rl);
 618          }
 619      }
 620      return rl;
 621  }
 622  
 623  // If callBackNow, we immediately do client callbacks, else we have to signal a v0 RunLoopSource so the
 624  // callbacks can happen in another thread.
 625  static void __CFSocketHandleWrite(CFSocketRef s, Boolean callBackNow) {
 626      SInt32 errorCode = 0;
 627      int errorSize = sizeof(errorCode);
 628      CFOptionFlags writeCallBacksAvailable;
 629      
 630      if (!CFSocketIsValid(s)) return;
 631      if (0 != (s->_f.client & kCFSocketLeaveErrors) || 0 != getsockopt(s->_socket, SOL_SOCKET, SO_ERROR, (char *)&errorCode, (socklen_t *)&errorSize)) errorCode = 0;
 632      // cast for WinSock bad API
 633  
 634      if (errorCode) {
 635          __CFSOCKETLOG_WS(s, "error %ld", (long)errorCode);
 636      }
 637  
 638      __CFSocketLock(s);
 639      writeCallBacksAvailable = __CFSocketCallBackTypes(s) & (kCFSocketWriteCallBack | kCFSocketConnectCallBack);
 640      if ((s->_f.client & kCFSocketConnectCallBack) != 0) writeCallBacksAvailable &= ~kCFSocketConnectCallBack;
 641      if (!__CFSocketIsValid(s) || ((s->_f.disabled & writeCallBacksAvailable) == writeCallBacksAvailable)) {
 642          __CFSocketUnlock(s);
 643          return;
 644      }
 645      s->_errorCode = errorCode;
 646      __CFSocketSetWriteSignalled(s);
 647      __CFSOCKETLOG_WS(s, "signalling write");
 648  
 649      if (callBackNow) {
 650          __CFSocketDoCallback(s, NULL, NULL, 0);
 651      } else {
 652          CFRunLoopSourceSignal(s->_source0);
 653          CFMutableArrayRef runLoopsOrig = (CFMutableArrayRef)CFRetain(s->_runLoops);
 654          CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops);
 655          CFRunLoopSourceRef source0 = s->_source0;
 656          if (NULL != source0 && !CFRunLoopSourceIsValid(source0)) {
 657              source0 = NULL;
 658          }
 659          if (source0) CFRetain(source0);
 660          __CFSocketUnlock(s);
 661          CFRunLoopRef rl = __CFSocketCopyRunLoopToWakeUp(source0, runLoopsCopy);
 662          if (source0) CFRelease(source0);
 663          if (NULL != rl) {
 664              CFRunLoopWakeUp(rl);
 665              CFRelease(rl);
 666          }
 667          __CFSocketLock(s);
 668          if (runLoopsOrig == s->_runLoops) {
 669              s->_runLoops = runLoopsCopy;
 670              runLoopsCopy = NULL;
 671              CFRelease(runLoopsOrig);
 672          }
 673          __CFSocketUnlock(s);
 674          CFRelease(runLoopsOrig);
 675          if (runLoopsCopy) CFRelease(runLoopsCopy);
 676      }
 677  }
 678  
 679  
 680  #if defined(LOG_CFSOCKET)
 681  
 682  static CFStringRef someAddrToString(CFAllocatorRef alloc, int (*fun) (int, struct sockaddr*, socklen_t*), const char* name, CFSocketNativeHandle s)
 683  {
 684      CFStringRef resultString = NULL;
 685      union {
 686          struct sockaddr		sa;
 687          struct sockaddr_in  sa4b;
 688          struct sockaddr_in6 sa6b;
 689          UInt8			static_buffer[SOCK_MAXADDRLEN];
 690      } u;
 691      socklen_t addrlen = sizeof(u.static_buffer);
 692      
 693      uint16_t* pPort = NULL;
 694      char buffer[1024];
 695      
 696      if ((*fun) (s, &u.sa, &addrlen) != 0)
 697          snprintf(buffer, sizeof(buffer), "error %d resolving %s address for socket %d", errno, name, s);
 698      else {
 699          void* pAddr = NULL;
 700          
 701          switch (u.sa.sa_family) {
 702              case AF_INET:
 703                  pAddr = &u.sa4b.sin_addr;
 704                  pPort = &u.sa4b.sin_port;
 705                  break;
 706              case AF_INET6:
 707                  pAddr = &u.sa6b.sin6_addr;
 708                  pPort = &u.sa6b.sin6_port;
 709                  break;
 710          }
 711          
 712          if (pAddr == NULL || inet_ntop(u.sa.sa_family, pAddr, buffer, sizeof(buffer)) == NULL)
 713              snprintf(buffer, sizeof(buffer), "[error %d converting %s address for socket %d]", pAddr != NULL? errno : EBADF, name, s);
 714      }
 715      if (pPort) {
 716          resultString = CFStringCreateWithFormat(alloc, NULL, CFSTR("%s:%d"), buffer, htons(*pPort));
 717      } else {
 718          resultString = CFStringCreateWithFormat(alloc, NULL, CFSTR("%s"), buffer);
 719      }
 720      return resultString;
 721  }
 722  
 723  static CFStringRef copyPeerAddress(CFAllocatorRef alloc, CFSocketNativeHandle s)
 724  {
 725      return someAddrToString(alloc, getpeername, "peer", s);
 726  }
 727  
 728  static CFStringRef copyLocalAddress(CFAllocatorRef alloc, CFSocketNativeHandle s)
 729  {
 730      return someAddrToString(alloc, getsockname, "local", s);
 731  }
 732  
 733  #endif
 734  
 735  static void __CFSocketHandleRead(CFSocketRef s, Boolean causedByTimeout)
 736  {
 737      CFDataRef data = NULL, address = NULL;
 738      CFSocketNativeHandle sock = INVALID_SOCKET;
 739      if (!CFSocketIsValid(s)) return;
 740      if (__CFSocketReadCallBackType(s) == kCFSocketDataCallBack) {
 741          uint8_t bufferArray[MAX_CONNECTION_ORIENTED_DATA_SIZE], *buffer;
 742          uint8_t name[MAX_SOCKADDR_LEN];
 743          int namelen = sizeof(name);
 744          SInt32 recvlen = 0;
 745          if (__CFSocketIsConnectionOriented(s)) {
 746              buffer = bufferArray;
 747              recvlen = recvfrom(s->_socket, (char *)buffer, MAX_CONNECTION_ORIENTED_DATA_SIZE, 0, (struct sockaddr *)name, (socklen_t *)&namelen);
 748          } else {
 749              buffer = (uint8_t *)malloc(MAX_DATA_SIZE);
 750              if (buffer) recvlen = recvfrom(s->_socket, (char *)buffer, MAX_DATA_SIZE, 0, (struct sockaddr *)name, (socklen_t *)&namelen);
 751          }
 752  
 753          __CFSOCKETLOG_WS(s, "read %ld", (long) recvlen);
 754  
 755          if (0 >= recvlen) {
 756              //??? should return error if <0
 757              /* zero-length data is the signal for perform to invalidate if socket is connection oriented */
 758              data = (CFDataRef)CFRetain(zeroLengthData);
 759          } else {
 760              data = CFDataCreate(CFGetAllocator(s), buffer, recvlen);
 761          }
 762          if (buffer && buffer != bufferArray) free(buffer);
 763          __CFSocketLock(s);
 764          if (!__CFSocketIsValid(s)) {
 765              CFRelease(data);
 766              __CFSocketUnlock(s);
 767              return;
 768          }
 769          __CFSocketSetReadSignalled(s);
 770          if (0 < namelen) {
 771              //??? possible optimizations:  uniquing; storing last value
 772              address = CFDataCreate(CFGetAllocator(s), name, namelen);
 773          } else if (__CFSocketIsConnectionOriented(s)) {
 774              if (NULL == s->_peerAddress) __CFSocketEstablishPeerAddress(s);
 775              if (NULL != s->_peerAddress) address = (CFDataRef)CFRetain(s->_peerAddress);
 776          }
 777          if (NULL == address) {
 778              address = (CFDataRef)CFRetain(zeroLengthData);
 779          }
 780          if (NULL == s->_dataQueue) {
 781              s->_dataQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
 782          }
 783          if (NULL == s->_addressQueue) {
 784              s->_addressQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
 785          }
 786          CFArrayAppendValue(s->_dataQueue, data);
 787          CFRelease(data);
 788          CFArrayAppendValue(s->_addressQueue, address);
 789          CFRelease(address);
 790          if (0 < recvlen
 791              && (s->_f.client & kCFSocketDataCallBack) != 0 && (s->_f.disabled & kCFSocketDataCallBack) == 0
 792              && __CFSocketIsScheduled(s)
 793          ) {
 794              __CFLock(&__CFActiveSocketsLock);
 795              /* restore socket to fds */
 796              __CFSocketSetFDForRead(s);
 797              __CFUnlock(&__CFActiveSocketsLock);
 798          }
 799      } else if (__CFSocketReadCallBackType(s) == kCFSocketAcceptCallBack) {
 800          uint8_t name[MAX_SOCKADDR_LEN];
 801          int namelen = sizeof(name);
 802          sock = accept(s->_socket, (struct sockaddr *)name, (socklen_t *)&namelen);
 803          if (INVALID_SOCKET == sock) {
 804              //??? should return error
 805              return;
 806          }
 807          if (0 < namelen) {
 808              address = CFDataCreate(CFGetAllocator(s), name, namelen);
 809          } else {
 810              address = (CFDataRef)CFRetain(zeroLengthData);
 811          }
 812          __CFSocketLock(s);
 813          if (!__CFSocketIsValid(s)) {
 814              closesocket(sock);
 815              CFRelease(address);
 816              __CFSocketUnlock(s);
 817              return;
 818          }
 819          __CFSocketSetReadSignalled(s);
 820          if (NULL == s->_dataQueue) {
 821              s->_dataQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, NULL);
 822          }
 823          if (NULL == s->_addressQueue) {
 824              s->_addressQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
 825          }
 826          CFArrayAppendValue(s->_dataQueue, (void *)(uintptr_t)sock);
 827          CFArrayAppendValue(s->_addressQueue, address);
 828          CFRelease(address);
 829          if ((s->_f.client & kCFSocketAcceptCallBack) != 0 && (s->_f.disabled & kCFSocketAcceptCallBack) == 0
 830              && __CFSocketIsScheduled(s)
 831          ) {
 832              __CFLock(&__CFActiveSocketsLock);
 833              /* restore socket to fds */
 834              __CFSocketSetFDForRead(s);
 835              __CFUnlock(&__CFActiveSocketsLock);
 836          }
 837      } else {
 838          __CFSocketLock(s);
 839          if (!__CFSocketIsValid(s) || (s->_f.disabled & kCFSocketReadCallBack) != 0) {
 840              __CFSocketUnlock(s);
 841              return;
 842          }
 843          if (causedByTimeout) {
 844              __CFSOCKETLOG_WS(s, "TIMEOUT RECEIVED - WILL SIGNAL IMMEDIATELY TO FLUSH (%ld buffered)", s->_bytesToBufferPos);
 845  
 846              /* we've got a timeout, but no bytes read, and we don't have any bytes to send.  Ignore the timeout. */
 847              if (s->_bytesToBufferPos == 0 && s->_leftoverBytes == NULL) {
 848  
 849                  __CFSOCKETLOG_WS(s, "TIMEOUT - but no bytes, restoring to active set", s->_bytesToBufferPos);
 850  
 851                  // Clear the timeout notification time if there is no prefetched data left
 852                  timerclear(&s->_readBufferTimeoutNotificationTime);
 853  
 854                  __CFLock(&__CFActiveSocketsLock);
 855                  /* restore socket to fds */
 856                  __CFSocketSetFDForRead(s);
 857                  __CFUnlock(&__CFActiveSocketsLock);
 858                  __CFSocketUnlock(s);
 859                  return;
 860              }
 861          } else if (s->_bytesToBuffer != 0 && ! s->_atEOF) {
 862              UInt8* base;
 863              CFIndex ctRead;
 864              CFIndex ctRemaining = s->_bytesToBuffer - s->_bytesToBufferPos;
 865  
 866              /* if our buffer has room, we go ahead and buffer */
 867              if (ctRemaining > 0) {
 868                  base = CFDataGetMutableBytePtr(s->_readBuffer);
 869  
 870                  ctRead = read(CFSocketGetNative(s), &base[s->_bytesToBufferPos], ctRemaining);
 871  
 872                  switch (ctRead) {
 873                      case -1:
 874                          if (errno == EAGAIN) { // no error
 875                              __CFLock(&__CFActiveSocketsLock);
 876                              /* restore socket to fds */
 877                              __CFSocketSetFDForRead(s);
 878                              __CFUnlock(&__CFActiveSocketsLock);
 879                              __CFSocketUnlock(s);
 880                              return;
 881                          } else {
 882                              s->_bufferedReadError = errno;
 883                              s->_atEOF = true;
 884                          }
 885  
 886                          __CFSOCKETLOG_WS(s, "BUFFERED READ GOT ERROR %d", errno);
 887                          break;
 888  
 889                      case 0:
 890                          __CFSOCKETLOG_WS(s, "DONE READING (EOF) - GOING TO SIGNAL");
 891                          s->_atEOF = true;
 892                          break;
 893  
 894                      default:
 895                          s->_bytesToBufferPos += ctRead;
 896                          if (s->_bytesToBuffer != s->_bytesToBufferPos) {
 897  
 898                              // Update the timeout notification time
 899                              struct timeval timeNow = { 0 };
 900                              gettimeofday(&timeNow, NULL);
 901                              timeradd(&timeNow, &s->_readBufferTimeout, &s->_readBufferTimeoutNotificationTime);
 902  
 903                              __CFSOCKETLOG_WS(s, "READ %ld - need %ld MORE - GOING BACK FOR MORE", ctRead, s->_bytesToBuffer - s->_bytesToBufferPos);
 904  
 905                              __CFLock(&__CFActiveSocketsLock);
 906                              /* restore socket to fds */
 907                              __CFSocketSetFDForRead(s);
 908                              __CFUnlock(&__CFActiveSocketsLock);
 909                              __CFSocketUnlock(s);
 910                              return;
 911                          } else {
 912                              // Clear the timeout notification time if the buffer is full
 913                              timerclear(&s->_readBufferTimeoutNotificationTime);
 914  
 915                              __CFSOCKETLOG_WS(s, "DONE READING (read %ld bytes) - GOING TO SIGNAL", ctRead);
 916                          }
 917                  }
 918              }
 919          }
 920          
 921          __CFSocketSetReadSignalled(s);
 922      }
 923  
 924      __CFSOCKETLOG_WS(s, "read signaling source");
 925  
 926      CFRunLoopSourceSignal(s->_source0);
 927      CFMutableArrayRef runLoopsOrig = (CFMutableArrayRef)CFRetain(s->_runLoops);
 928      CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops);
 929      CFRunLoopSourceRef source0 = s->_source0;
 930      if (NULL != source0 && !CFRunLoopSourceIsValid(source0)) {
 931          source0 = NULL;
 932      }
 933      if (source0) CFRetain(source0);
 934      __CFSocketUnlock(s);
 935      CFRunLoopRef rl = __CFSocketCopyRunLoopToWakeUp(source0, runLoopsCopy);
 936      if (source0) CFRelease(source0);
 937      if (NULL != rl) {
 938          CFRunLoopWakeUp(rl);
 939          CFRelease(rl);
 940      }
 941          __CFSocketLock(s);
 942          if (runLoopsOrig == s->_runLoops) {
 943              s->_runLoops = runLoopsCopy;
 944              runLoopsCopy = NULL;
 945              CFRelease(runLoopsOrig);
 946          }
 947          __CFSocketUnlock(s);
 948          CFRelease(runLoopsOrig);
 949          if (runLoopsCopy) CFRelease(runLoopsCopy);
 950  }
 951  
 952  static struct timeval* intervalToTimeval(CFTimeInterval timeout, struct timeval* tv)
 953  {
 954      if (timeout == 0.0)
 955          timerclear(tv);
 956      else {
 957          tv->tv_sec = (0 >= timeout || INT_MAX <= timeout) ? INT_MAX : (int)(float)floor(timeout);
 958          tv->tv_usec = (int)((timeout - floor(timeout)) * 1.0E6);
 959      }
 960      return tv;
 961  }
 962  
 963  /* note that this returns a pointer to the min value, which won't have changed during
 964   the dictionary apply, since we've got the active sockets lock held */
 965  static void _calcMinTimeout_locked(const void* val, void* ctxt)
 966  {
 967      CFSocketRef s = (CFSocketRef) val;
 968      struct timeval** minTime = (struct timeval**) ctxt;
 969      if (timerisset(&s->_readBufferTimeout) && (*minTime == NULL || timercmp(&s->_readBufferTimeout, *minTime, <)))
 970          *minTime = &s->_readBufferTimeout;
 971      else if (s->_leftoverBytes) {
 972          /* If there's anyone with leftover bytes, they'll need to be awoken immediately */
 973          static struct timeval sKickerTime = { 0, 0 };
 974          *minTime = &sKickerTime;
 975      }
 976  }
 977  
 978  void __CFSocketSetSocketReadBufferAttrs(CFSocketRef s, CFTimeInterval timeout, CFIndex length)
 979  {
 980      struct timeval timeoutVal;
 981      
 982      intervalToTimeval(timeout, &timeoutVal);
 983      
 984      /* lock ordering is socket lock, activesocketslock */
 985      /* activesocketslock protects our timeout calculation */
 986      __CFSocketLock(s);
 987      __CFLock(&__CFActiveSocketsLock);
 988  
 989      if (s->_bytesToBuffer != length) {
 990          CFIndex ctBuffer = s->_bytesToBufferPos - s->_bytesToBufferReadPos;
 991          
 992          if (ctBuffer) {
 993              /* As originally envisaged, you were supposed to be sure to drain the buffer before 
 994               * issuing another request on the socket.  In practice, there seem to be times when we want to re-use 
 995               * the stream (or perhaps, are on our way to closing it out) and this policy doesn't work so well.  
 996               * So, if someone changes the buffer size while we have bytes already buffered, we put them 
 997               * aside and use them to satisfy any subsequent reads. 
 998               */
 999              __CFSOCKETLOG_WS(s, "WARNING: shouldn't set read buffer length while data (%ld bytes) is still in the read buffer (leftover total %ld)", ctBuffer, s->_leftoverBytes? CFDataGetLength(s->_leftoverBytes) : 0);
1000  
1001              if (s->_leftoverBytes == NULL)
1002                  s->_leftoverBytes = CFDataCreateMutable(CFGetAllocator(s), 0);
1003              
1004              /* append the current buffered bytes over.  We'll keep draining _leftoverBytes while we have them... */
1005              CFDataAppendBytes(s->_leftoverBytes, CFDataGetBytePtr(s->_readBuffer) + s->_bytesToBufferReadPos, ctBuffer);
1006              CFRelease(s->_readBuffer);
1007              s->_readBuffer = NULL;
1008              
1009              s->_bytesToBuffer = 0;
1010              s->_bytesToBufferPos = 0;
1011              s->_bytesToBufferReadPos = 0;
1012          }
1013          if (length == 0) {
1014              s->_bytesToBuffer = 0;
1015              s->_bytesToBufferPos = 0;
1016              s->_bytesToBufferReadPos = 0;
1017              if (s->_readBuffer) {
1018                  CFRelease(s->_readBuffer);
1019                  s->_readBuffer = NULL;
1020              }
1021              // Zero length buffer, smash the timeout
1022              timeoutVal.tv_sec = 0;
1023              timeoutVal.tv_usec = 0;
1024          } else {
1025              /* if the buffer shrank, we can re-use the old one */
1026              if (length > s->_bytesToBuffer) {
1027                  if (s->_readBuffer) {
1028                      CFRelease(s->_readBuffer);
1029                      s->_readBuffer = NULL;
1030                  }
1031              }
1032              
1033              s->_bytesToBuffer = length;
1034              s->_bytesToBufferPos = 0;
1035              s->_bytesToBufferReadPos = 0;
1036              if (s->_readBuffer == NULL) {
1037                  s->_readBuffer = CFDataCreateMutable(kCFAllocatorSystemDefault, length);
1038                  CFDataSetLength(s->_readBuffer, length);
1039              }
1040          }
1041      }
1042      
1043      if (timercmp(&s->_readBufferTimeout, &timeoutVal, !=)) {
1044          s->_readBufferTimeout = timeoutVal;
1045          __CFReadSocketsTimeoutInvalid = true;
1046      }
1047      
1048      __CFUnlock(&__CFActiveSocketsLock);
1049      __CFSocketUnlock(s);
1050  }
1051  
1052  CFIndex __CFSocketRead(CFSocketRef s, UInt8* buffer, CFIndex length, int* error)
1053  {
1054      __CFSOCKETLOG_WS(s, "READING BYTES (%ld buffered, out of %ld desired, eof = %d, err = %d)", s->_bytesToBufferPos, s->_bytesToBuffer, s->_atEOF, s->_bufferedReadError);
1055  
1056      CFIndex result = -1;
1057  
1058      __CFSocketLock(s);
1059  
1060      *error = 0;
1061  
1062      /* Any leftover buffered bytes? */
1063      if (s->_leftoverBytes) {
1064          CFIndex ctBuffer = CFDataGetLength(s->_leftoverBytes);
1065  #if defined(DEBUG)
1066          fprintf(stderr, "%s(%ld): WARNING: Draining %ld leftover bytes first\n\n", __FUNCTION__, (long)__LINE__, (long)ctBuffer);
1067  #endif
1068          if (ctBuffer > length)
1069              ctBuffer = length;
1070          memcpy(buffer, CFDataGetBytePtr(s->_leftoverBytes), ctBuffer);
1071          if (ctBuffer < CFDataGetLength(s->_leftoverBytes))
1072              CFDataReplaceBytes(s->_leftoverBytes, CFRangeMake(0, ctBuffer), NULL, 0);
1073          else {
1074              CFRelease(s->_leftoverBytes);
1075              s->_leftoverBytes = NULL;
1076          }
1077          result = ctBuffer;
1078          goto unlock;
1079      }
1080  
1081      /* return whatever we've buffered */
1082      if (s->_bytesToBuffer != 0) {
1083          CFIndex ctBuffer = s->_bytesToBufferPos - s->_bytesToBufferReadPos;
1084          if (ctBuffer > 0) {
1085              /* drain our buffer first */
1086              if (ctBuffer > length)
1087                  ctBuffer = length;
1088              memcpy(buffer, CFDataGetBytePtr(s->_readBuffer) + s->_bytesToBufferReadPos, ctBuffer);
1089              s->_bytesToBufferReadPos += ctBuffer;
1090              if (s->_bytesToBufferReadPos == s->_bytesToBufferPos) {
1091                  __CFSOCKETLOG_WS(s, "DRAINED BUFFER - SHOULD START BUFFERING AGAIN");
1092                  s->_bytesToBufferPos = 0;
1093                  s->_bytesToBufferReadPos = 0;
1094              }
1095  
1096              __CFSOCKETLOG_WS(s, "SLURPED %ld BYTES FROM BUFFER %ld LEFT TO READ", ctBuffer, length);
1097  
1098              result = ctBuffer;
1099              goto unlock;
1100          }
1101      }
1102      /* nothing buffered, or no buffer selected */
1103  
1104      /* Did we get an error on a previous read (or buffered read)? */
1105      if (s->_bufferedReadError != 0) {
1106          __CFSOCKETLOG_WS(s, "RETURNING ERROR %d", s->_bufferedReadError);
1107          *error = s->_bufferedReadError;
1108          result = -1;
1109          goto unlock;
1110      }
1111  
1112      /* nothing buffered, if we've hit eof, don't bother reading any more */
1113      if (s->_atEOF) {
1114  
1115          __CFSOCKETLOG_WS(s, "RETURNING EOF");
1116  
1117          result = 0;
1118          goto unlock;
1119      }
1120  
1121      /* normal read */
1122      result = read(CFSocketGetNative(s), buffer, length);
1123  
1124      __CFSOCKETLOG_WS(s, "READ %ld bytes", result);
1125  
1126      if (result == 0) {
1127          /* note that we hit EOF */
1128          s->_atEOF = true;
1129      } else if (result < 0) {
1130          *error = errno;
1131          
1132          /* if it wasn't EAGAIN, record it (although we shouldn't get called again) */
1133          if (*error != EAGAIN) {
1134              s->_bufferedReadError = *error;
1135          }
1136      }
1137      
1138  unlock:
1139      __CFSocketUnlock(s);
1140      
1141      return result;
1142  }
1143  
1144  Boolean __CFSocketGetBytesAvailable(CFSocketRef s, CFIndex* ctBytesAvailable)
1145  {
1146  	CFIndex ctBuffer = s->_bytesToBufferPos - s->_bytesToBufferReadPos;
1147  	if (ctBuffer != 0) {
1148  		*ctBytesAvailable = ctBuffer;
1149  		return true;
1150  	} else {
1151  		int result;
1152  	    unsigned long bytesAvailable;
1153  	    result = ioctlsocket(CFSocketGetNative(s), FIONREAD, &bytesAvailable);
1154  		if (result < 0)
1155  			return false;
1156  		*ctBytesAvailable = (CFIndex) bytesAvailable;
1157  		return true;
1158  	}
1159  }
1160  
1161  #if defined(LOG_CFSOCKET)
1162  static void __CFSocketWriteSocketList(CFArrayRef sockets, CFDataRef fdSet, char* dst, CFIndex dstCount, Boolean onlyIfSet) {
1163      int len = snprintf(dst, dstCount, "{");
1164      dst += len;
1165      dstCount -= len;
1166  
1167      fd_set *tempfds = (fd_set *)CFDataGetBytePtr(fdSet);
1168      SInt32 idx, cnt;
1169      for (idx = 0, cnt = CFArrayGetCount(sockets); idx < cnt; idx++) {
1170          CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(sockets, idx);
1171          len = 0;
1172          if (FD_ISSET(s->_socket, tempfds)) {
1173              len = snprintf(dst, dstCount, " %d ", s->_socket);
1174          } else if (!onlyIfSet) {
1175              len = snprintf(dst, dstCount, " (%d) ", s->_socket);
1176          }
1177          dst += len;
1178          dstCount -= len;
1179      }
1180  
1181      snprintf(dst, dstCount, "}");
1182  }
1183  #endif
1184  
1185  static void
1186  clearInvalidFileDescriptors(CFMutableDataRef d)
1187  {
1188      if (d) {
1189          SInt32 count = __CFSocketFdGetSize(d);
1190          fd_set* s = (fd_set*) CFDataGetMutableBytePtr(d);
1191          for (SInt32 idx = 0;  idx < count;  idx++) {
1192              if (FD_ISSET(idx, s))
1193                  if (! __CFNativeSocketIsValid(idx)) {
1194                      FD_CLR(idx, s);
1195                  }
1196          }
1197      }
1198  }
1199  
1200  static void
1201  manageSelectError()
1202  {
1203      SInt32 selectError = __CFSocketLastError();
1204  
1205      __CFSOCKETLOG("socket manager received error %ld from select", (long)selectError);
1206  
1207      if (EBADF == selectError) {
1208          CFMutableArrayRef invalidSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
1209  
1210          __CFLock(&__CFActiveSocketsLock);
1211          CFIndex cnt = CFArrayGetCount(__CFWriteSockets);
1212          CFIndex idx;
1213          for (idx = 0; idx < cnt; idx++) {
1214              CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFWriteSockets, idx);
1215              if (!__CFNativeSocketIsValid(s->_socket)) {
1216                  __CFSOCKETLOG_WS(s, "socket manager found write socket invalid");
1217                  CFArrayAppendValue(invalidSockets, s);
1218              }
1219          }
1220          cnt = CFArrayGetCount(__CFReadSockets);
1221          for (idx = 0; idx < cnt; idx++) {
1222              CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx);
1223              if (!__CFNativeSocketIsValid(s->_socket)) {
1224                  __CFSOCKETLOG_WS(s, "socket manager found read socket invalid");
1225                  CFArrayAppendValue(invalidSockets, s);
1226              }
1227          }
1228  
1229  
1230          cnt = CFArrayGetCount(invalidSockets);
1231  
1232          /* Note that we're doing this only when we got EBADF but otherwise
1233           * don't have an explicit bad descriptor.  Note that the lock is held now.
1234           * Finally, note that cnt == 0 doesn't necessarily mean
1235           * that this loop will do anything, since fd's may have been invalidated
1236           * while we were in select.
1237           */
1238          if (cnt == 0) {
1239              __CFSOCKETLOG("socket manager received EBADF(1): No sockets were marked as invalid, cleaning out fdsets");
1240  
1241              clearInvalidFileDescriptors(__CFReadSocketsFds);
1242              clearInvalidFileDescriptors(__CFWriteSocketsFds);
1243          }
1244  
1245          __CFUnlock(&__CFActiveSocketsLock);
1246  
1247          for (idx = 0; idx < cnt; idx++) {
1248              CFSocketInvalidate(((CFSocketRef)CFArrayGetValueAtIndex(invalidSockets, idx)));
1249          }
1250          CFRelease(invalidSockets);
1251      }
1252  }
1253  
1254  static void *__CFSocketManager(void * arg)
1255  {
1256  #if TARGET_OS_LINUX && !TARGET_OS_CYGWIN
1257      pthread_setname_np(pthread_self(), "com.apple.CFSocket.private");
1258  #elif !TARGET_OS_CYGWIN && !TARGET_OS_BSD
1259      pthread_setname_np("com.apple.CFSocket.private");
1260  #endif
1261      SInt32 nrfds, maxnrfds, fdentries = 1;
1262      SInt32 rfds, wfds;
1263      fd_set *exceptfds = NULL;
1264      fd_set *writefds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(fd_mask), 0);
1265      fd_set *readfds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(fd_mask), 0);
1266      fd_set *tempfds;
1267      SInt32 idx, cnt;
1268      uint8_t buffer[256];
1269      CFMutableArrayRef selectedWriteSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
1270      CFMutableArrayRef selectedReadSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
1271      CFIndex selectedWriteSocketsIndex = 0, selectedReadSocketsIndex = 0;
1272      
1273      struct timeval tv;
1274      struct timeval* pTimeout = NULL;
1275      struct timeval timeBeforeSelect = {0, 0};
1276      
1277      for (;;) {
1278          __CFLock(&__CFActiveSocketsLock);
1279          __CFSocketManagerIteration++;
1280  
1281  #if defined(LOG_CFSOCKET)
1282          char* readBuffer = (char*) malloc(16384);
1283          __CFSocketWriteSocketList(__CFReadSockets, __CFReadSocketsFds, readBuffer, 16384, FALSE);
1284          char* writeBuffer = (char*) malloc(16384);
1285          __CFSocketWriteSocketList(__CFWriteSockets, __CFWriteSocketsFds, writeBuffer, 16384, FALSE);
1286          __CFSOCKETLOG("socket manager iteration %lu looking at: read sockets %s, write sockets %s", (unsigned long)__CFSocketManagerIteration, readBuffer, writeBuffer);
1287  
1288          free(readBuffer);
1289          free(writeBuffer);
1290  #endif
1291          rfds = __CFSocketFdGetSize(__CFReadSocketsFds);
1292          wfds = __CFSocketFdGetSize(__CFWriteSocketsFds);
1293          maxnrfds = __CFMax(rfds, wfds);
1294          if (maxnrfds > fdentries * (int)NFDBITS) {
1295              fdentries = (maxnrfds + NFDBITS - 1) / NFDBITS;
1296              writefds = __CFSafelyReallocateWithAllocator(kCFAllocatorSystemDefault, writefds, fdentries * sizeof(fd_mask), 0, NULL);
1297              readfds = __CFSafelyReallocateWithAllocator(kCFAllocatorSystemDefault, readfds, fdentries * sizeof(fd_mask), 0, NULL);
1298          }
1299          memset(writefds, 0, fdentries * sizeof(fd_mask)); 
1300          memset(readfds, 0, fdentries * sizeof(fd_mask));
1301          CFDataGetBytes(__CFWriteSocketsFds, CFRangeMake(0, CFDataGetLength(__CFWriteSocketsFds)), (UInt8 *)writefds);
1302          CFDataGetBytes(__CFReadSocketsFds, CFRangeMake(0, CFDataGetLength(__CFReadSocketsFds)), (UInt8 *)readfds); 
1303  		
1304          if (__CFReadSocketsTimeoutInvalid) {
1305              struct timeval* minTimeout = NULL;
1306              __CFReadSocketsTimeoutInvalid = false;
1307  
1308              __CFSOCKETLOG("Figuring out which sockets have timeouts...");
1309  
1310              CFArrayApplyFunction(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), _calcMinTimeout_locked, (void*) &minTimeout);
1311  
1312              if (minTimeout == NULL) {
1313                  __CFSOCKETLOG("No one wants a timeout!");
1314                  pTimeout = NULL;
1315              } else {
1316                  __CFSOCKETLOG("timeout will be %ld, %d!", minTimeout->tv_sec, minTimeout->tv_usec);
1317                  tv = *minTimeout;
1318                  pTimeout = &tv;
1319              }
1320          }
1321  
1322          if (pTimeout) {
1323              __CFSOCKETLOG("select will have a %ld, %d timeout", pTimeout->tv_sec, pTimeout->tv_usec);
1324              gettimeofday(&timeBeforeSelect, NULL);
1325          }
1326  		
1327          __CFUnlock(&__CFActiveSocketsLock);
1328  
1329  #if TARGET_OS_WIN32
1330          // On Windows, select checks connection failed sockets via the exceptfds parameter. connection succeeded is checked via writefds. We need both.
1331          exceptfds = writefds;
1332  #elif defined(LOG_CFSOCKET) && defined(DEBUG_POLLING_SELECT)
1333          if (pTimeout == NULL) {
1334              /* If there's anyone with leftover bytes, they'll need to be awoken immediately */
1335              static struct timeval sKickerTime = { 5, 0 };
1336              pTimeout = &sKickerTime;
1337              __CFSOCKETLOG("Setting 5s select timeout as debug measure");
1338          }
1339  
1340          if (exceptfds == NULL) {
1341              exceptfds = (fd_set*) malloc(maxnrfds * NFDBITS);
1342              bzero(exceptfds, maxnrfds * NFDBITS);
1343          }
1344  #endif
1345  
1346          nrfds = select(maxnrfds, readfds, writefds, exceptfds, pTimeout);
1347  
1348  #if defined(LOG_CFSOCKET) && defined(DEBUG_POLLING_SELECT)
1349          __CFSOCKETLOG("socket manager woke from select, ret=%ld", (long)nrfds);
1350  
1351          if (nrfds < 0 && exceptfds && exceptfds != writefds) {
1352              CFMutableStringRef s = NULL;
1353              for (int i = 0;  i < nrfds;  i++) {
1354                  if (FD_ISSET(i, exceptfds)) {
1355                      if (s == NULL) {
1356                          s = CFStringCreateMutable(kCFAllocatorDefault, 0);
1357                          CFStringAppendCString(s, "Error set { ", kCFStringEncodingUTF8);
1358                      }
1359                      CFStringAppendFormat(s, NULL, CFSTR("%d "), i);
1360                  }
1361              }
1362              if (s == NULL)
1363                  __CFSOCKETLOG("Error from select errno %d, but no fds specified", errno);
1364              else {
1365                  CFStringAppendFormat(s, NULL, CFSTR("}"));
1366                  __CFSOCKETLOG("Error from select errno %d, %@", errno, s);
1367                  CFRelease(s);
1368              }
1369              free(exceptfds);
1370              exceptfds = nil;
1371          }
1372  #endif
1373  		/*
1374  		 * select returned a timeout
1375  		 */
1376          if (0 == nrfds) {
1377              Boolean didFindOne = false;
1378              struct timeval timeAfterSelect;
1379              struct timeval deltaTime;
1380              gettimeofday(&timeAfterSelect, NULL);
1381              /* timeBeforeSelect becomes the delta */
1382              timersub(&timeAfterSelect, &timeBeforeSelect, &deltaTime);
1383  
1384              __CFSOCKETLOG("Socket manager received timeout - kicking off expired reads (expired delta %ld, %d)", deltaTime.tv_sec, deltaTime.tv_usec);
1385  
1386              __CFLock(&__CFActiveSocketsLock);
1387  
1388              tempfds = NULL;
1389              cnt = CFArrayGetCount(__CFReadSockets);
1390              for (idx = 0; idx < cnt; idx++) {
1391                  CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx);
1392  
1393                  if (timerisset(&s->_readBufferTimeout) || s->_leftoverBytes) {
1394                      didFindOne = true;
1395  
1396                      CFSocketNativeHandle sock = s->_socket;
1397                      // We might have an new element in __CFReadSockets that we weren't listening to,
1398                      // in which case we must be sure not to test a bit in the fdset that is
1399                      // outside our mask size.
1400                      Boolean sockInBounds = (0 <= sock && sock < maxnrfds);
1401                      /* if this sockets timeout is less than or equal elapsed time, then signal it */
1402                      if (INVALID_SOCKET != sock && sockInBounds) {
1403                          __CFSOCKETLOG_WS(s, "Expiring socket (delta %ld, %d)", s->_readBufferTimeout.tv_sec, s->_readBufferTimeout.tv_usec);
1404  
1405                          CFArraySetValueAtIndex(selectedReadSockets, selectedReadSocketsIndex, s);
1406                          selectedReadSocketsIndex++;
1407                          /* socket is removed from fds here, will be restored in read handling or in perform function */
1408                          if (!tempfds) tempfds = (fd_set *)CFDataGetMutableBytePtr(__CFReadSocketsFds);
1409                          FD_CLR(sock, tempfds);
1410                      }
1411                  }
1412              }
1413              
1414              __CFUnlock(&__CFActiveSocketsLock);
1415              
1416              /* and below, we dispatch through the normal read dispatch mechanism */
1417              if (! didFindOne) {
1418  #if defined(LOG_CFSOCKET) && defined(DEBUG_POLLING_SELECT)
1419                  __CFSOCKETLOG("select() timeout - but no sockets actually timed out.  Iteration %lu", (unsigned long) __CFSocketManagerIteration);
1420                  CFAbsoluteTime endTime = CFAbsoluteTimeGetCurrent() + 3;
1421                  CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopDefaultMode, ^{
1422                      CFTimeInterval dt = CFAbsoluteTimeGetCurrent() - endTime;
1423                      if (dt > 0) {
1424                          __CFSOCKETLOG("select() timeout %lu - took %.05f for the main runloop (TOO LONG!)", __CFSocketManagerIteration, dt);
1425                      } else {
1426                          __CFSOCKETLOG("select() timeout %lu - took %.05f for the main runloop", __CFSocketManagerIteration, dt < 0? -dt : dt);
1427                      }
1428                  });
1429                  CFRunLoopWakeUp(CFRunLoopGetMain());
1430  #endif
1431              }
1432          }
1433  
1434          if (0 > nrfds) {
1435              manageSelectError();
1436              continue;
1437          }
1438          if (FD_ISSET(__CFWakeupSocketPair[1], readfds)) {
1439              recv(__CFWakeupSocketPair[1], (char *)buffer, sizeof(buffer), 0);
1440              __CFSOCKETLOG("socket manager received %c on wakeup socket\n", buffer[0]);
1441          }
1442          __CFLock(&__CFActiveSocketsLock);
1443          tempfds = NULL;
1444          cnt = CFArrayGetCount(__CFWriteSockets);
1445          for (idx = 0; idx < cnt; idx++) {
1446              CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFWriteSockets, idx);
1447              CFSocketNativeHandle sock = s->_socket;
1448              // We might have an new element in __CFWriteSockets that we weren't listening to,
1449              // in which case we must be sure not to test a bit in the fdset that is
1450              // outside our mask size.
1451              Boolean sockInBounds = (0 <= sock && sock < maxnrfds);
1452              if (INVALID_SOCKET != sock && sockInBounds) {
1453                  if (FD_ISSET(sock, writefds)) {
1454                      CFArraySetValueAtIndex(selectedWriteSockets, selectedWriteSocketsIndex, s);
1455                      selectedWriteSocketsIndex++;
1456                      /* socket is removed from fds here, restored by CFSocketReschedule */
1457                      if (!tempfds) tempfds = (fd_set *)CFDataGetMutableBytePtr(__CFWriteSocketsFds);
1458                      FD_CLR(sock, tempfds);
1459                      __CFSOCKETLOG_WS(s, "Manager: cleared socket from write fds");
1460                  }
1461              }
1462          }
1463          tempfds = NULL;
1464          cnt = CFArrayGetCount(__CFReadSockets);
1465          
1466          struct timeval timeNow = { 0 };
1467          if (pTimeout) {
1468              gettimeofday(&timeNow, NULL);
1469          }
1470          
1471          for (idx = 0; idx < cnt; idx++) {
1472              CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx);
1473              CFSocketNativeHandle sock = s->_socket;
1474              // We might have an new element in __CFReadSockets that we weren't listening to,
1475              // in which case we must be sure not to test a bit in the fdset that is
1476              // outside our mask size.
1477              Boolean sockInBounds = (0 <= sock && sock < maxnrfds);
1478  
1479              // Check if we hit the timeout
1480              s->_hitTheTimeout = false;
1481              if (pTimeout && sockInBounds && 0 != nrfds && !FD_ISSET(sock, readfds) &&
1482                  timerisset(&s->_readBufferTimeoutNotificationTime) &&
1483                  timercmp(&timeNow, &s->_readBufferTimeoutNotificationTime, >))
1484              {
1485                  s->_hitTheTimeout = true;
1486              }
1487  
1488              if (INVALID_SOCKET != sock && sockInBounds && (FD_ISSET(sock, readfds) || s->_hitTheTimeout)) {
1489                  CFArraySetValueAtIndex(selectedReadSockets, selectedReadSocketsIndex, s);
1490                  selectedReadSocketsIndex++;
1491                  /* socket is removed from fds here, will be restored in read handling or in perform function */
1492                  if (!tempfds) tempfds = (fd_set *)CFDataGetMutableBytePtr(__CFReadSocketsFds);
1493                  FD_CLR(sock, tempfds);
1494              }
1495          }
1496          __CFUnlock(&__CFActiveSocketsLock);
1497          
1498          for (idx = 0; idx < selectedWriteSocketsIndex; idx++) {
1499              CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(selectedWriteSockets, idx);
1500              if (kCFNull == (CFNullRef)s) continue;
1501              __CFSOCKETLOG_WS(s, "socket manager signaling for write", s, s->_socket);
1502              __CFSocketHandleWrite(s, FALSE);
1503              CFArraySetValueAtIndex(selectedWriteSockets, idx, kCFNull);
1504          }
1505          selectedWriteSocketsIndex = 0;
1506          
1507          for (idx = 0; idx < selectedReadSocketsIndex; idx++) {
1508              CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(selectedReadSockets, idx);
1509              if (kCFNull == (CFNullRef)s) continue;
1510              __CFSOCKETLOG_WS(s, "socket manager signaling for read", s, s->_socket);
1511              __CFSocketHandleRead(s, nrfds == 0 || s->_hitTheTimeout);
1512              CFArraySetValueAtIndex(selectedReadSockets, idx, kCFNull);
1513          }
1514          selectedReadSocketsIndex = 0;
1515      }
1516      return NULL;
1517  }
1518  
1519  static CFStringRef __CFSocketCopyDescription(CFTypeRef cf) {
1520      CFSocketRef s = (CFSocketRef)cf;
1521      CFMutableStringRef result;
1522      CFStringRef contextDesc = NULL;
1523      void *contextInfo = NULL;
1524      CFStringRef (*contextCopyDescription)(const void *info) = NULL;
1525      result = CFStringCreateMutable(CFGetAllocator(s), 0);
1526      __CFSocketLock(s);
1527      void *addr = s->_callout;
1528  #if TARGET_OS_MAC
1529      Dl_info info;
1530      const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???";
1531  #else
1532      // don't bother trying to figure out callout names
1533      const char *name = "<unknown>";
1534  #endif
1535      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);
1536      contextInfo = s->_context.info;
1537      contextCopyDescription = s->_context.copyDescription;
1538      __CFSocketUnlock(s);
1539      if (NULL != contextInfo && NULL != contextCopyDescription) {
1540          contextDesc = (CFStringRef)contextCopyDescription(contextInfo);
1541      }
1542      if (NULL == contextDesc) {
1543          contextDesc = CFStringCreateWithFormat(CFGetAllocator(s), NULL, CFSTR("<CFSocket context %p>"), contextInfo);
1544      }
1545      CFStringAppend(result, contextDesc);
1546      CFStringAppend(result, CFSTR("}"));
1547      CFRelease(contextDesc);
1548      return result;
1549  }
1550  
1551  static void __CFSocketDeallocate(CFTypeRef cf) {
1552      /* Since CFSockets are cached, we can only get here sometime after being invalidated */
1553      CFSocketRef s = (CFSocketRef)cf;
1554      if (NULL != s->_address) {
1555          CFRelease(s->_address);
1556          s->_address = NULL;
1557      }
1558      if (NULL != s->_readBuffer) {
1559          CFRelease(s->_readBuffer);
1560          s->_readBuffer = NULL;
1561      }
1562  	if (NULL != s->_leftoverBytes) {
1563  		CFRelease(s->_leftoverBytes);
1564  		s->_leftoverBytes = NULL;
1565  	}
1566      timerclear(&s->_readBufferTimeout);
1567      s->_bytesToBuffer = 0;
1568      s->_bytesToBufferPos = 0;
1569      s->_bytesToBufferReadPos = 0;
1570      s->_atEOF = true;
1571  	s->_bufferedReadError = 0;
1572  }
1573  
1574  const CFRuntimeClass __CFSocketClass = {
1575      0,
1576      "CFSocket",
1577      NULL,      // init
1578      NULL,      // copy
1579      __CFSocketDeallocate,
1580      NULL,      // equal
1581      NULL,      // hash
1582      NULL,      // 
1583      __CFSocketCopyDescription
1584  };
1585  
1586  CFTypeID CFSocketGetTypeID(void) {
1587      static dispatch_once_t initOnce;
1588      dispatch_once(&initOnce, ^{
1589  #if TARGET_OS_MAC
1590          struct rlimit lim1;
1591          int ret1 = getrlimit(RLIMIT_NOFILE, &lim1);
1592          int mib[] = {CTL_KERN, KERN_MAXFILESPERPROC};
1593          int maxfd = 0;
1594          size_t len = sizeof(int);
1595          int ret0 = sysctl(mib, 2, &maxfd, &len, NULL, 0);
1596          if (0 == ret0 && 0 == ret1 && lim1.rlim_max < maxfd) maxfd = lim1.rlim_max;
1597          if (0 == ret1 && lim1.rlim_cur < maxfd) {
1598              struct rlimit lim2 = lim1;
1599              lim2.rlim_cur += 2304;
1600              if (maxfd < lim2.rlim_cur) lim2.rlim_cur = maxfd;
1601              setrlimit(RLIMIT_NOFILE, &lim2);
1602              // we try, but do not go to extraordinary measures
1603          }
1604  #endif
1605      });
1606      return _kCFRuntimeIDCFSocket;
1607  }
1608  
1609  #if TARGET_OS_WIN32
1610  struct _args {
1611      void *func;
1612      void *arg;
1613      HANDLE handle;
1614  };
1615  static unsigned __stdcall __CFWinThreadFunc(void *arg) {
1616      struct _args *args = (struct _args*)arg;
1617      ((void (*)(void *))args->func)(args->arg);
1618      CloseHandle(args->handle);
1619      CFAllocatorDeallocate(kCFAllocatorSystemDefault, arg);
1620      _endthreadex(0);
1621      return 0;
1622  }
1623  #endif
1624  
1625  static CFSocketRef _CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHandle sock, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context, Boolean useExistingInstance) {
1626      CHECK_FOR_FORK();
1627      CFSocketRef memory;
1628      int typeSize = sizeof(memory->_socketType);
1629      __CFLock(&__CFActiveSocketsLock);
1630      if (NULL == __CFReadSockets) __CFSocketInitializeSockets();
1631      __CFUnlock(&__CFActiveSocketsLock);
1632      __CFLock(&__CFAllSocketsLock);
1633      if (NULL == __CFAllSockets) {
1634          __CFAllSockets = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
1635      }
1636      if (INVALID_SOCKET != sock && CFDictionaryGetValueIfPresent(__CFAllSockets, (void *)(uintptr_t)sock, (const void **)&memory)) {
1637          if (useExistingInstance) {
1638  			__CFUnlock(&__CFAllSocketsLock);
1639  			CFRetain(memory);
1640  			return memory;
1641  		} else {
1642  			__CFSOCKETLOG("useExistingInstance is FALSE, removing existing instance %p from __CFAllSockets\n", memory);
1643  			__CFUnlock(&__CFAllSocketsLock);
1644  			CFSocketInvalidate(memory);
1645  			__CFLock(&__CFAllSocketsLock);
1646  		}
1647      }
1648      memory = (CFSocketRef)_CFRuntimeCreateInstance(allocator, CFSocketGetTypeID(), sizeof(struct __CFSocket) - sizeof(CFRuntimeBase), NULL);
1649      if (NULL == memory) {
1650          __CFUnlock(&__CFAllSocketsLock);
1651          return NULL;
1652      }
1653      __CFSocketSetCallBackTypes(memory, callBackTypes);
1654      if (INVALID_SOCKET != sock) __CFSocketSetValid(memory);
1655      __CFSocketUnsetWriteSignalled(memory);
1656      __CFSocketUnsetReadSignalled(memory);
1657      memory->_f.client = ((callBackTypes & (~kCFSocketConnectCallBack)) & (~kCFSocketWriteCallBack)) | kCFSocketCloseOnInvalidate;
1658      memory->_lock = CFLockInit;
1659      memory->_writeLock = CFLockInit;
1660      memory->_socket = sock;
1661      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
1662      if (INVALID_SOCKET != sock) {
1663          CFArrayCallBacks retainingCallbacks = kCFTypeArrayCallBacks;
1664          retainingCallbacks.copyDescription = NULL;
1665          memory->_runLoops = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &retainingCallbacks);
1666      }
1667      memory->_callout = callout;
1668      timerclear(&memory->_readBufferTimeout);
1669      timerclear(&memory->_readBufferTimeoutNotificationTime);
1670      
1671      if (INVALID_SOCKET != sock) CFDictionaryAddValue(__CFAllSockets, (void *)(uintptr_t)sock, memory);
1672      if (NULL == __CFSocketManagerThread) {
1673  #if TARGET_OS_MAC || TARGET_OS_LINUX || TARGET_OS_BSD
1674          _CFThreadRef tid = 0;
1675          pthread_attr_t attr;
1676          pthread_attr_init(&attr);
1677          pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
1678          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1679  #if TARGET_OS_MAC
1680          pthread_attr_set_qos_class_np(&attr, qos_class_main(), 0);
1681  #endif
1682          pthread_create(&tid, &attr, __CFSocketManager, 0);
1683          pthread_attr_destroy(&attr);
1684          _Static_assert(sizeof(_CFThreadRef) == sizeof(void *), "_CFThreadRef is not pointer sized");
1685          __CFSocketManagerThread = (void *)tid;
1686  #elif TARGET_OS_WIN32
1687          unsigned tid;
1688          struct _args *args = (struct _args*)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(struct _args), 0);
1689          if (__CFOASafe) __CFSetLastAllocationEventName(args, "CFUtilities (thread-args)");
1690          HANDLE handle;
1691          args->func = __CFSocketManager;
1692          args->arg = 0;
1693          /* The thread is created suspended, because otherwise there would be a race between the assignment below of the handle field, and it's possible use in the thread func above. */
1694          args->handle = (HANDLE)_beginthreadex(NULL, 0, __CFWinThreadFunc, args, CREATE_SUSPENDED, &tid);
1695          handle = args->handle;
1696          ResumeThread(handle);
1697          __CFSocketManagerThread = handle;
1698  #endif
1699      }
1700      __CFUnlock(&__CFAllSocketsLock);
1701      if (NULL != context) {
1702          void *contextInfo = context->retain ? (void *)context->retain(context->info) : context->info;
1703          __CFSocketLock(memory);
1704          memory->_context.retain = context->retain;
1705          memory->_context.release = context->release;
1706          memory->_context.copyDescription = context->copyDescription;
1707          memory->_context.info = contextInfo;
1708          __CFSocketUnlock(memory);
1709      }
1710      __CFSOCKETLOG("created socket %p (%d) with callbacks 0x%x, callout %p", memory, memory->_socket, callBackTypes, callout);
1711      return memory;
1712  }
1713  
1714  CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHandle sock, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
1715  	return _CFSocketCreateWithNative(allocator, sock, callBackTypes, callout, context, TRUE);
1716  }
1717  
1718  void CFSocketInvalidate(CFSocketRef s) {
1719      CF_ASSERT_TYPE(CFSocketGetTypeID(), s);
1720      CHECK_FOR_FORK();
1721      UInt32 previousSocketManagerIteration;
1722      __CFGenericValidateType(s, CFSocketGetTypeID());
1723      __CFSOCKETLOG_WS(s, "flags 0x%x disabled 0x%x connected 0x%x\n", s->_f.client, s->_f.disabled, s->_f.connected);
1724      CFRetain(s);
1725      __CFLock(&__CFAllSocketsLock);
1726      __CFSocketLock(s);
1727      if (__CFSocketIsValid(s)) {
1728          SInt32 idx;
1729          CFRunLoopSourceRef source0;
1730          void *contextInfo = NULL;
1731          void (*contextRelease)(const void *info) = NULL;
1732          __CFSocketUnsetValid(s);
1733          __CFSocketUnsetWriteSignalled(s);
1734          __CFSocketUnsetReadSignalled(s);
1735          __CFLock(&__CFActiveSocketsLock);
1736          idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
1737          if (0 <= idx) {
1738              CFArrayRemoveValueAtIndex(__CFWriteSockets, idx);
1739              __CFSocketClearFDForWrite(s);
1740          }
1741          // No need to clear FD's for V1 sources, since we'll just throw the whole event away
1742          idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
1743          if (0 <= idx) {
1744              CFArrayRemoveValueAtIndex(__CFReadSockets, idx);
1745              __CFSocketClearFDForRead(s);
1746          }
1747          previousSocketManagerIteration = __CFSocketManagerIteration;
1748          __CFUnlock(&__CFActiveSocketsLock);
1749          CFDictionaryRemoveValue(__CFAllSockets, (void *)(uintptr_t)(s->_socket));
1750          if ((s->_f.client & kCFSocketCloseOnInvalidate) != 0) closesocket(s->_socket);
1751          s->_socket = INVALID_SOCKET;
1752          if (NULL != s->_peerAddress) {
1753              CFRelease(s->_peerAddress);
1754              s->_peerAddress = NULL;
1755          }
1756          if (NULL != s->_dataQueue) {
1757              CFRelease(s->_dataQueue);
1758              s->_dataQueue = NULL;
1759          }
1760          if (NULL != s->_addressQueue) {
1761              CFRelease(s->_addressQueue);
1762              s->_addressQueue = NULL;
1763          }
1764          s->_socketSetCount = 0;
1765          
1766          // we'll need this later
1767          CFArrayRef runLoops = (CFArrayRef)CFRetain(s->_runLoops);        
1768          CFRelease(s->_runLoops);
1769          
1770          s->_runLoops = NULL;
1771          source0 = s->_source0;
1772          s->_source0 = NULL;
1773          contextInfo = s->_context.info;
1774          contextRelease = s->_context.release;
1775          s->_context.info = 0;
1776          s->_context.retain = 0;
1777          s->_context.release = 0;
1778          s->_context.copyDescription = 0;
1779          __CFSocketUnlock(s);
1780          
1781          // Do this after the socket unlock to avoid deadlock (10462525)
1782          for (idx = CFArrayGetCount(runLoops); idx--;) {
1783              CFRunLoopWakeUp((CFRunLoopRef)CFArrayGetValueAtIndex(runLoops, idx));
1784          }
1785          CFRelease(runLoops);
1786  
1787          if (NULL != contextRelease) {
1788              contextRelease(contextInfo);
1789          }
1790          if (NULL != source0) {
1791              CFRunLoopSourceInvalidate(source0);
1792              CFRelease(source0);
1793          }
1794      } else {
1795          __CFSocketUnlock(s);
1796      }
1797      __CFUnlock(&__CFAllSocketsLock);
1798      __CFSOCKETLOG("done for %p", s);
1799      CFRelease(s);
1800  }
1801  
1802  Boolean CFSocketIsValid(CFSocketRef s) {
1803      CF_ASSERT_TYPE(CFSocketGetTypeID(), s);
1804      CHECK_FOR_FORK();
1805      return __CFSocketIsValid(s);
1806  }
1807  
1808  CFSocketNativeHandle CFSocketGetNative(CFSocketRef s) {
1809      CF_ASSERT_TYPE_OR_NULL(CFSocketGetTypeID(), s);
1810      CHECK_FOR_FORK();
1811      return s == NULL? -1 : s->_socket;
1812  }
1813  
1814  CFDataRef CFSocketCopyAddress(CFSocketRef s) {
1815      CF_ASSERT_TYPE(CFSocketGetTypeID(), s);
1816      CHECK_FOR_FORK();
1817      CFDataRef result = NULL;
1818      __CFSocketLock(s);
1819      __CFSocketEstablishAddress(s);
1820      if (NULL != s->_address) {
1821          result = (CFDataRef)CFRetain(s->_address);
1822      }
1823      __CFSocketUnlock(s);
1824  #if defined(LOG_CFSOCKET)
1825      CFStringRef local = copyLocalAddress(kCFAllocatorDefault, s->_socket);
1826      CFStringRef peer = copyPeerAddress(kCFAllocatorDefault, s->_socket);
1827      __CFSOCKETLOG_WS(s, "addresses local %@ peer %@", local, peer);
1828      if (local)
1829          CFRelease(local);
1830      if (peer)
1831          CFRelease(peer);
1832  #endif
1833      return result;
1834  }
1835  
1836  CFDataRef CFSocketCopyPeerAddress(CFSocketRef s) {
1837      CF_ASSERT_TYPE(CFSocketGetTypeID(), s);
1838      CHECK_FOR_FORK();
1839      CFDataRef result = NULL;
1840      __CFSocketLock(s);
1841      __CFSocketEstablishPeerAddress(s);
1842      if (NULL != s->_peerAddress) {
1843          result = (CFDataRef)CFRetain(s->_peerAddress);
1844      }
1845      __CFSocketUnlock(s);
1846  #if defined(LOG_CFSOCKET)
1847      CFStringRef local = copyLocalAddress(kCFAllocatorDefault, s->_socket);
1848      CFStringRef peer = copyPeerAddress(kCFAllocatorDefault, s->_socket);
1849      __CFSOCKETLOG_WS(s, "addresses local %@ peer %@", local, peer);
1850      if (local)
1851          CFRelease(local);
1852      if (peer)
1853          CFRelease(peer);
1854  #endif
1855      return result;
1856  }
1857  
1858  void CFSocketGetContext(CFSocketRef s, CFSocketContext *context) {
1859      CF_ASSERT_TYPE(CFSocketGetTypeID(), s);
1860      CHECK_FOR_FORK();
1861      CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__);
1862      *context = s->_context;
1863  }
1864  
1865  CFOptionFlags CFSocketGetSocketFlags(CFSocketRef s) {
1866      CF_ASSERT_TYPE(CFSocketGetTypeID(), s);
1867      CHECK_FOR_FORK();
1868      return s->_f.client;
1869  }
1870  
1871  void CFSocketSetSocketFlags(CFSocketRef s, CFOptionFlags flags) {
1872      CF_ASSERT_TYPE(CFSocketGetTypeID(), s);
1873      CHECK_FOR_FORK();
1874      __CFSocketLock(s);
1875  #if LOG_CFSOCKET
1876      CFOptionFlags oldFlags = s->_f.client;
1877  #endif
1878      s->_f.client = flags;
1879      __CFSocketUnlock(s);
1880      __CFSOCKETLOG_WS(s, "set flags 0x%x (was 0x%x)", flags, oldFlags);
1881  }
1882  
1883  void CFSocketDisableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) {
1884      CF_ASSERT_TYPE(CFSocketGetTypeID(), s);
1885      CHECK_FOR_FORK();
1886      Boolean wakeup = false;
1887      uint8_t readCallBackType;
1888      __CFSocketLock(s);
1889      if (__CFSocketIsValid(s) && __CFSocketIsScheduled(s)) {
1890          callBackTypes &= __CFSocketCallBackTypes(s);
1891          readCallBackType = __CFSocketReadCallBackType(s);
1892          s->_f.disabled |= callBackTypes;
1893          __CFSOCKETLOG_WS(s, "unscheduling with flags 0x%x disabled 0x%x connected 0x%x for types 0x%lx\n", s->_f.client, s->_f.disabled, s->_f.connected, callBackTypes);
1894          __CFLock(&__CFActiveSocketsLock);
1895          if ((readCallBackType == kCFSocketAcceptCallBack) || !__CFSocketIsConnectionOriented(s)) s->_f.connected = TRUE;
1896          if (((callBackTypes & kCFSocketWriteCallBack) != 0) || (((callBackTypes & kCFSocketConnectCallBack) != 0) && !s->_f.connected)) {
1897              if (__CFSocketClearFDForWrite(s)) {
1898                  // do not wake up the socket manager thread if all relevant write callbacks are disabled
1899                  CFOptionFlags writeCallBacksAvailable = __CFSocketCallBackTypes(s) & (kCFSocketWriteCallBack | kCFSocketConnectCallBack);
1900                  if (s->_f.connected) writeCallBacksAvailable &= ~kCFSocketConnectCallBack;
1901                  if ((s->_f.disabled & writeCallBacksAvailable) != writeCallBacksAvailable) wakeup = true;
1902              }
1903          }
1904          if (readCallBackType != kCFSocketNoCallBack && (callBackTypes & readCallBackType) != 0) {
1905              if (__CFSocketClearFDForRead(s)) {
1906                  // do not wake up the socket manager thread if callback type is read
1907                  if (readCallBackType != kCFSocketReadCallBack) wakeup = true;
1908              }
1909          }
1910          __CFUnlock(&__CFActiveSocketsLock);
1911      }
1912      __CFSocketUnlock(s);
1913  }
1914  
1915  // "force" means to clear the disabled bits set by DisableCallBacks and always reenable.
1916  // if (!force) we respect those bits, meaning they may stop us from enabling.
1917  // In addition, if !force we assume that the sockets have already been added to the
1918  // __CFReadSockets and __CFWriteSockets arrays.  This is true because the callbacks start
1919  // enabled when the CFSocket is created (at which time we enable with force).
1920  // Called with SocketLock held, returns with it released!
1921  void __CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes, Boolean force, uint8_t wakeupChar) {
1922      CHECK_FOR_FORK();
1923      Boolean wakeup = FALSE;
1924      if (!callBackTypes) {
1925          __CFSocketUnlock(s);
1926          return;
1927      }
1928      if (__CFSocketIsValid(s) && __CFSocketIsScheduled(s)) {
1929          Boolean turnOnWrite = FALSE, turnOnConnect = FALSE, turnOnRead = FALSE;
1930          uint8_t readCallBackType = __CFSocketReadCallBackType(s);        
1931          callBackTypes &= __CFSocketCallBackTypes(s);
1932          if (force) s->_f.disabled &= ~callBackTypes;
1933          __CFSOCKETLOG_WS(s, "rescheduling with flags 0x%x disabled 0x%x connected 0x%x for types 0x%lx\n", s->_f.client, s->_f.disabled, s->_f.connected, callBackTypes);
1934          /* We will wait for connection only for connection-oriented, non-rendezvous sockets that are not already connected.  Mark others as already connected. */
1935          if ((readCallBackType == kCFSocketAcceptCallBack) || !__CFSocketIsConnectionOriented(s)) s->_f.connected = TRUE;
1936  
1937          // First figure out what to turn on
1938          if (s->_f.connected || (callBackTypes & kCFSocketConnectCallBack) == 0) {
1939              // if we want write callbacks and they're not disabled...
1940              if ((callBackTypes & kCFSocketWriteCallBack) != 0 && (s->_f.disabled & kCFSocketWriteCallBack) == 0) turnOnWrite = TRUE;
1941          } else {
1942              // if we want connect callbacks and they're not disabled...
1943              if ((callBackTypes & kCFSocketConnectCallBack) != 0 && (s->_f.disabled & kCFSocketConnectCallBack) == 0) turnOnConnect = TRUE;
1944          }
1945          // if we want read callbacks and they're not disabled...
1946          if (readCallBackType != kCFSocketNoCallBack && (callBackTypes & readCallBackType) != 0 && (s->_f.disabled & kCFSocketReadCallBack) == 0) turnOnRead = TRUE;
1947  
1948          // Now turn on the callbacks we've determined that we want on
1949          if (turnOnRead || turnOnWrite || turnOnConnect) {
1950              __CFLock(&__CFActiveSocketsLock);
1951              if (turnOnWrite || turnOnConnect) {
1952                  if (force) {
1953                      SInt32 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
1954                      if (kCFNotFound == idx)
1955                          CFArrayAppendValue(__CFWriteSockets, s);
1956                      if (kCFNotFound == idx)
1957                          __CFSOCKETLOG_WS(s, "put %p __CFWriteSockets list due to force and non-presence");
1958                  }
1959                  if (__CFSocketSetFDForWrite(s)) wakeup = true;
1960              }
1961              if (turnOnRead) {
1962                  if (force) {
1963                      SInt32 idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
1964                      if (kCFNotFound == idx) CFArrayAppendValue(__CFReadSockets, s);
1965                  }
1966                  if (__CFSocketSetFDForRead(s)) wakeup = true;
1967              }
1968              __CFUnlock(&__CFActiveSocketsLock);
1969          }
1970      }
1971      __CFSocketUnlock(s);
1972  }
1973  
1974  void CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) {
1975      CF_ASSERT_TYPE(CFSocketGetTypeID(), s);
1976      CHECK_FOR_FORK();
1977      __CFSocketLock(s);
1978      __CFSocketEnableCallBacks(s, callBackTypes, TRUE, 'r');
1979      __CFSOCKETLOG_WS(s, "done for callbackTypes %x", callBackTypes);
1980  }
1981  
1982  static void __CFSocketSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) {
1983      CFSocketRef s = (CFSocketRef)info;
1984      __CFSocketLock(s);
1985      //??? also need to arrange delivery of all pending data
1986      if (__CFSocketIsValid(s)) {
1987          CFMutableArrayRef runLoopsOrig = s->_runLoops;
1988          CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops);
1989          CFArrayAppendValue(runLoopsCopy, rl);
1990          s->_runLoops = runLoopsCopy;
1991          CFRelease(runLoopsOrig);
1992          s->_socketSetCount++;
1993          // Since the v0 source is listened to on the SocketMgr thread, no matter how many modes it
1994          // is added to we just need to enable it there once (and _socketSetCount gives us a refCount
1995          // to know when we can finally disable it).
1996          if (1 == s->_socketSetCount) {
1997              __CFSOCKETLOG_WS(s, "rl %p (%s), mode %@", rl, (CFRunLoopGetCurrent() == rl? "current" : CFRunLoopGetMain() == rl? "main" : ""), mode);
1998              __CFSocketEnableCallBacks(s, __CFSocketCallBackTypes(s), TRUE, 's');  // unlocks s
1999          } else
2000              __CFSocketUnlock(s);
2001      } else
2002          __CFSocketUnlock(s);
2003  }
2004  
2005  static void __CFSocketCancel(void *info, CFRunLoopRef rl, CFStringRef mode) {
2006      CFSocketRef s = (CFSocketRef)info;
2007      SInt32 idx;
2008      __CFSocketLock(s);
2009      s->_socketSetCount--;
2010      if (0 == s->_socketSetCount) {
2011          __CFLock(&__CFActiveSocketsLock);
2012          idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
2013          if (0 <= idx) {
2014              __CFSOCKETLOG_WS(s, "removing from __CFWriteSockets list");
2015              CFArrayRemoveValueAtIndex(__CFWriteSockets, idx);
2016              __CFSocketClearFDForWrite(s);
2017          }
2018          idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
2019          if (0 <= idx) {
2020              CFArrayRemoveValueAtIndex(__CFReadSockets, idx);
2021              __CFSocketClearFDForRead(s);
2022          }
2023          __CFUnlock(&__CFActiveSocketsLock);
2024      }
2025      if (NULL != s->_runLoops) {
2026          CFMutableArrayRef runLoopsOrig = s->_runLoops;
2027          CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops);
2028          idx = CFArrayGetFirstIndexOfValue(runLoopsCopy, CFRangeMake(0, CFArrayGetCount(runLoopsCopy)), rl);
2029          if (0 <= idx) CFArrayRemoveValueAtIndex(runLoopsCopy, idx);
2030          s->_runLoops = runLoopsCopy;
2031          CFRelease(runLoopsOrig);
2032      }
2033      __CFSocketUnlock(s);
2034  }
2035  
2036  // Note:  must be called with socket lock held, then returns with it released
2037  // Used by both the v0 and v1 RunLoopSource perform routines
2038  static void __CFSocketDoCallback(CFSocketRef s, CFDataRef data, CFDataRef address, CFSocketNativeHandle sock) {
2039      CFSocketCallBack callout = NULL;
2040      void *contextInfo = NULL;
2041      SInt32 errorCode = 0;
2042      Boolean readSignalled = false, writeSignalled = false, connectSignalled = false, calledOut = false;
2043      uint8_t readCallBackType, callBackTypes;
2044      
2045      callBackTypes = __CFSocketCallBackTypes(s);
2046      readCallBackType = __CFSocketReadCallBackType(s);
2047      readSignalled = __CFSocketIsReadSignalled(s);
2048      writeSignalled = __CFSocketIsWriteSignalled(s);
2049      connectSignalled = writeSignalled && !s->_f.connected;
2050      __CFSocketUnsetReadSignalled(s);
2051      __CFSocketUnsetWriteSignalled(s);
2052      callout = s->_callout;
2053      contextInfo = s->_context.info;
2054      __CFSOCKETLOG_WS(s, "entering perform with read signalled %d write signalled %d connect signalled %d callback types %d", readSignalled, writeSignalled, connectSignalled, callBackTypes);
2055      if (writeSignalled) {
2056          errorCode = s->_errorCode;
2057          s->_f.connected = TRUE;
2058      }
2059      __CFSocketUnlock(s);
2060      if ((callBackTypes & kCFSocketConnectCallBack) != 0) {
2061          if (connectSignalled && (!calledOut || CFSocketIsValid(s))) {
2062              __CFSOCKETLOG_WS(s, "doing connect callback (%p), error: %d", callout, errorCode);
2063              if (errorCode) {
2064                  if (callout) callout(s, kCFSocketConnectCallBack, NULL, &errorCode, contextInfo);
2065                  calledOut = true;
2066              } else {
2067                  if (callout) callout(s, kCFSocketConnectCallBack, NULL, NULL, contextInfo);
2068                  calledOut = true;
2069              }
2070          }
2071      }
2072      if (kCFSocketDataCallBack == readCallBackType) {
2073          if (NULL != data && (!calledOut || CFSocketIsValid(s))) {
2074              SInt32 datalen = CFDataGetLength(data);
2075              __CFSOCKETLOG_WS(s, "perform calling out data of length %ld", (long)datalen);
2076              if (callout) callout(s, kCFSocketDataCallBack, address, data, contextInfo);
2077              calledOut = true;
2078              if (0 == datalen && __CFSocketIsConnectionOriented(s)) CFSocketInvalidate(s);
2079          }
2080      } else if (kCFSocketAcceptCallBack == readCallBackType) {
2081          if (INVALID_SOCKET != sock && (!calledOut || CFSocketIsValid(s))) {
2082              __CFSOCKETLOG_WS(s, "perform calling out accept");
2083              if (callout) callout(s, kCFSocketAcceptCallBack, address, &sock, contextInfo);
2084              calledOut = true;
2085          }
2086      } else if (kCFSocketReadCallBack == readCallBackType) {
2087          if (readSignalled && (!calledOut || CFSocketIsValid(s))) {
2088              __CFSOCKETLOG_WS(s, "doing read callback");
2089              __CFSOCKETLOG("__CFSocketPerformV0(%p)  for socket %d", s, s->_socket);
2090              if (callout) callout(s, kCFSocketReadCallBack, NULL, NULL, contextInfo);
2091              calledOut = true;
2092          }
2093      }
2094      if ((callBackTypes & kCFSocketWriteCallBack) != 0) {
2095          if (writeSignalled && !errorCode && (!calledOut || CFSocketIsValid(s))) {
2096              __CFSOCKETLOG_WS(s, "doing write callback");
2097              if (callout) callout(s, kCFSocketWriteCallBack, NULL, NULL, contextInfo);
2098              calledOut = true;
2099          }
2100      }
2101  }
2102  
2103  static void __CFSocketPerformV0(void *info) {
2104      CFSocketRef s = (CFSocketRef)info;
2105      CFDataRef data = NULL;
2106      CFDataRef address = NULL;
2107      CFSocketNativeHandle sock = INVALID_SOCKET;
2108      uint8_t readCallBackType, callBackTypes;
2109      CFRunLoopRef rl = NULL;
2110      void *contextInfo = NULL;
2111      void (*contextRelease)(const void *) = NULL;
2112      __CFSOCKETLOG_WS(s, "Starting");
2113  
2114      __CFSocketLock(s);
2115      if (!__CFSocketIsValid(s)) {
2116          __CFSocketUnlock(s);
2117          return;
2118      }
2119      callBackTypes = __CFSocketCallBackTypes(s);
2120      readCallBackType = __CFSocketReadCallBackType(s);
2121      CFOptionFlags callBacksSignalled = 0;
2122      if (__CFSocketIsReadSignalled(s)) callBacksSignalled |= readCallBackType;
2123      if (__CFSocketIsWriteSignalled(s)) callBacksSignalled |= kCFSocketWriteCallBack;
2124  
2125      if (kCFSocketDataCallBack == readCallBackType) {
2126          if (NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
2127              data = (CFDataRef)CFArrayGetValueAtIndex(s->_dataQueue, 0);
2128              CFRetain(data);
2129              CFArrayRemoveValueAtIndex(s->_dataQueue, 0);
2130              address = (CFDataRef)CFArrayGetValueAtIndex(s->_addressQueue, 0);
2131              CFRetain(address);
2132              CFArrayRemoveValueAtIndex(s->_addressQueue, 0);
2133          }
2134      } else if (kCFSocketAcceptCallBack == readCallBackType) {
2135          if (NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
2136              sock = (CFSocketNativeHandle)(uintptr_t)CFArrayGetValueAtIndex(s->_dataQueue, 0);
2137              CFArrayRemoveValueAtIndex(s->_dataQueue, 0);
2138              address = (CFDataRef)CFArrayGetValueAtIndex(s->_addressQueue, 0);
2139              CFRetain(address);
2140              CFArrayRemoveValueAtIndex(s->_addressQueue, 0);
2141          }
2142      }
2143  
2144      if (NULL != s->_context.retain) {
2145          contextInfo = s->_context.info;
2146          contextRelease = s->_context.release;
2147          s->_context.retain(contextInfo);
2148      }
2149  
2150      __CFSocketDoCallback(s, data, address, sock);	// does __CFSocketUnlock(s)
2151  
2152      if (NULL != contextRelease) {
2153          contextRelease(contextInfo);
2154      }
2155  
2156      if (NULL != data) CFRelease(data);
2157      if (NULL != address) CFRelease(address);
2158  
2159      __CFSocketLock(s);
2160      if (__CFSocketIsValid(s) && kCFSocketNoCallBack != readCallBackType) {
2161          // if there's still more data, we want to wake back up right away
2162          if ((kCFSocketDataCallBack == readCallBackType || kCFSocketAcceptCallBack == readCallBackType) && NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
2163              __CFSOCKETLOG_WS(s, "perform short-circuit signaling source with flags 0x%x disabled 0x%x connected 0x%x\n", s->_f.client, s->_f.disabled, s->_f.connected);
2164              CFRunLoopSourceSignal(s->_source0);
2165              CFMutableArrayRef runLoopsOrig = (CFMutableArrayRef)CFRetain(s->_runLoops);
2166              CFMutableArrayRef runLoopsCopy = CFArrayCreateMutableCopy(kCFAllocatorSystemDefault, 0, s->_runLoops);
2167              CFRunLoopSourceRef source0 = s->_source0;
2168              if (NULL != source0 && !CFRunLoopSourceIsValid(source0)) {
2169                  source0 = NULL;
2170              }
2171              if (source0) CFRetain(source0);
2172              __CFSocketUnlock(s);
2173              rl = __CFSocketCopyRunLoopToWakeUp(source0, runLoopsCopy);
2174              if (source0) CFRelease(source0);
2175              __CFSocketLock(s);
2176              if (runLoopsOrig == s->_runLoops) {
2177                  s->_runLoops = runLoopsCopy;
2178                  runLoopsCopy = NULL;
2179                  CFRelease(runLoopsOrig);
2180              }
2181              CFRelease(runLoopsOrig);
2182              if (runLoopsCopy) CFRelease(runLoopsCopy);
2183          }
2184      }
2185      // Only reenable callbacks that are auto-reenabled
2186      __CFSocketEnableCallBacks(s, callBacksSignalled & s->_f.client, FALSE, 'p');  // unlocks s
2187  
2188      if (NULL != rl) {
2189          CFRunLoopWakeUp(rl);
2190          CFRelease(rl);
2191      }
2192      __CFSOCKETLOG_WS(s, "Done");
2193  }
2194  
2195  CFRunLoopSourceRef CFSocketCreateRunLoopSource(CFAllocatorRef allocator, CFSocketRef s, CFIndex order) {
2196      CF_ASSERT_TYPE(CFSocketGetTypeID(), s);
2197      CHECK_FOR_FORK();
2198      CFRunLoopSourceRef result = NULL;
2199      __CFSocketLock(s);
2200      if (__CFSocketIsValid(s)) {
2201          if (NULL != s->_source0 && !CFRunLoopSourceIsValid(s->_source0)) {
2202              CFRelease(s->_source0);
2203              s->_source0 = NULL;
2204          }
2205          if (NULL == s->_source0) {
2206              CFRunLoopSourceContext context;
2207              context.version = 0;
2208              context.info = s;
2209              context.retain = CFRetain;
2210              context.release = CFRelease;
2211              context.copyDescription = CFCopyDescription;
2212              context.equal = CFEqual;
2213              context.hash = CFHash;
2214              context.schedule = __CFSocketSchedule;
2215              context.cancel = __CFSocketCancel;
2216              context.perform = __CFSocketPerformV0;
2217              s->_source0 = CFRunLoopSourceCreate(allocator, order, &context);
2218          }
2219          CFRetain(s->_source0);        /* This retain is for the receiver */
2220          result = s->_source0;
2221      }
2222      __CFSocketUnlock(s);
2223      return result;
2224  }
2225  
2226  
2227  
2228  static uint16_t __CFSocketDefaultNameRegistryPortNumber = 2454;
2229  
2230  CONST_STRING_DECL(kCFSocketCommandKey, "Command")
2231  CONST_STRING_DECL(kCFSocketNameKey, "Name")
2232  CONST_STRING_DECL(kCFSocketValueKey, "Value")
2233  CONST_STRING_DECL(kCFSocketResultKey, "Result")
2234  CONST_STRING_DECL(kCFSocketErrorKey, "Error")
2235  CONST_STRING_DECL(kCFSocketRegisterCommand, "Register")
2236  CONST_STRING_DECL(kCFSocketRetrieveCommand, "Retrieve")
2237  CONST_STRING_DECL(__kCFSocketRegistryRequestRunLoopMode, "CFSocketRegistryRequest")
2238  
2239  static os_unfair_lock __CFSocketWriteLock_ = OS_UNFAIR_LOCK_INIT;
2240  //#warning can only send on one socket at a time now
2241  
2242  CF_INLINE void __CFSocketWriteLock(CFSocketRef s) {
2243      os_unfair_lock_lock(& __CFSocketWriteLock_);
2244  }
2245  
2246  CF_INLINE void __CFSocketWriteUnlock(CFSocketRef s) {
2247      os_unfair_lock_unlock(& __CFSocketWriteLock_);
2248  }
2249  
2250  //??? need timeout, error handling, retries
2251  CFSocketError CFSocketSendData(CFSocketRef s, CFDataRef address, CFDataRef data, CFTimeInterval timeout) {
2252      CF_ASSERT_TYPE(CFSocketGetTypeID(), s);
2253      CHECK_FOR_FORK();
2254      const uint8_t *dataptr, *addrptr = NULL;
2255      SInt32 datalen, addrlen = 0, size = 0;
2256      CFSocketNativeHandle sock = INVALID_SOCKET;
2257      struct timeval tv;
2258      if (address) {
2259          addrptr = CFDataGetBytePtr(address);
2260          addrlen = CFDataGetLength(address);
2261      }
2262      dataptr = CFDataGetBytePtr(data);
2263      datalen = CFDataGetLength(data);
2264      if (CFSocketIsValid(s)) sock = CFSocketGetNative(s);
2265      if (INVALID_SOCKET != sock) {
2266          CFRetain(s);
2267          __CFSocketWriteLock(s);
2268          tv.tv_sec = (timeout <= 0.0 || (CFTimeInterval)INT_MAX <= timeout) ? INT_MAX : (int)floor(timeout);
2269          tv.tv_usec = (int)floor(1.0e+6 * (timeout - floor(timeout)));
2270          setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv));	// cast for WinSock bad API
2271          if (NULL != addrptr && 0 < addrlen) {
2272              size = sendto(sock, (char *)dataptr, datalen, 0, (struct sockaddr *)addrptr, addrlen);
2273          } else {
2274              size = send(sock, (char *)dataptr, datalen, 0);
2275          }
2276          __CFSOCKETLOG_WS(s, "wrote %ld bytes", (long)size);
2277          __CFSocketWriteUnlock(s);
2278          CFRelease(s);
2279      }
2280      return (size > 0) ? kCFSocketSuccess : kCFSocketError;
2281  }
2282  
2283  CFSocketError CFSocketSetAddress(CFSocketRef s, CFDataRef address) {
2284      CF_ASSERT_TYPE(CFSocketGetTypeID(), s);
2285      CHECK_FOR_FORK();
2286      struct sockaddr *name;
2287      socklen_t namelen;
2288      __CFGenericValidateType(s, CFSocketGetTypeID());
2289      if (NULL == address) return kCFSocketError;
2290      if (!CFSocketIsValid(s)) return kCFSocketError;
2291      
2292      name = (struct sockaddr *)CFDataGetBytePtr(address);
2293      namelen = (socklen_t)CFDataGetLength(address);
2294      if (!name || namelen <= 0) return kCFSocketError;
2295      
2296      CFSocketNativeHandle sock = CFSocketGetNative(s);
2297  #if TARGET_OS_MAC
2298      // 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.
2299      // Max size is a size byte, plus family byte, plus path of 255, plus a null byte.
2300      char newName[255];
2301      if (namelen > 2 && name->sa_family == AF_UNIX) {
2302          // 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)
2303          socklen_t realLength = (sizeof(*((struct sockaddr_un *)name)) - sizeof(((struct sockaddr_un *)name)->sun_path) + strnlen(((struct sockaddr_un *)name)->sun_path, namelen - 2));
2304          if (realLength > 255) return kCFSocketError;
2305          
2306          // 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.
2307          namelen = (socklen_t)(((struct sockaddr_un *)name)->sun_len);
2308          
2309          if (realLength != namelen) {
2310              // 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.
2311              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."));
2312              memcpy(newName, name, realLength);
2313              namelen = realLength;
2314              ((struct sockaddr_un *)newName)->sun_len = realLength;
2315              name = (struct sockaddr *)newName;
2316          }
2317      }
2318  #endif
2319      const int bindResult = bind(sock, name, namelen);
2320      if (0 == bindResult) {
2321          const int listenResult = listen(sock, 256);
2322          if (listenResult != 0) {
2323              CFLog(kCFLogLevelDebug, CFSTR("CFSocketSetAddress listen failure: %d"), errno);
2324          }
2325      }
2326      else {
2327          CFLog(kCFLogLevelDebug, CFSTR("CFSocketSetAddress bind failure: %d"), errno);
2328      }
2329      
2330      //??? should return errno; historically this never looked at the listenResult
2331      return (CFIndex)bindResult;
2332  }
2333  
2334  CFSocketError CFSocketConnectToAddress(CFSocketRef s, CFDataRef address, CFTimeInterval timeout) {
2335      CF_ASSERT_TYPE(CFSocketGetTypeID(), s);
2336      CHECK_FOR_FORK();
2337      //??? need error handling, retries
2338      const uint8_t *name;
2339      SInt32 namelen, result = -1, connect_err = 0, select_err = 0;
2340      UInt32 yes = 1, no = 0;
2341      Boolean wasBlocking = true;
2342  
2343      __CFGenericValidateType(s, CFSocketGetTypeID());
2344      if (!CFSocketIsValid(s)) return kCFSocketError;
2345      name = CFDataGetBytePtr(address);
2346      namelen = CFDataGetLength(address);
2347      if (!name || namelen <= 0) return kCFSocketError;
2348      CFSocketNativeHandle sock = CFSocketGetNative(s);
2349      {
2350  #if TARGET_OS_MAC
2351          SInt32 flags = fcntl(sock, F_GETFL, 0);
2352          if (flags >= 0) wasBlocking = ((flags & O_NONBLOCK) == 0);
2353          if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(sock, FIONBIO, (u_long *)&yes);
2354  #else
2355          // You can set but not get this flag in WIN32, so assume it was in non-blocking mode.
2356          // The downside is that when we leave this routine we'll leave it non-blocking,
2357          // whether it started that way or not.
2358          SInt32 flags = 0;
2359          if (timeout > 0.0 || timeout < 0.0) ioctlsocket(sock, FIONBIO, (u_long *)&yes);
2360          wasBlocking = false;
2361  #endif
2362          result = connect(sock, (struct sockaddr *)name, namelen);
2363          if (result != 0) {
2364              connect_err = __CFSocketLastError();
2365  #if TARGET_OS_WIN32
2366              if (connect_err == WSAEWOULDBLOCK) connect_err = EINPROGRESS;
2367  #endif
2368          }
2369          __CFSOCKETLOG_WS(s, "connection attempt returns %d error %d on socket %d (flags 0x%x blocking %d)", (int) result, (int) connect_err, sock, (int) flags, wasBlocking);
2370          if (EINPROGRESS == connect_err && timeout >= 0.0) {
2371              /* select on socket */
2372              SInt32 nrfds;
2373              int error_size = sizeof(select_err);
2374              struct timeval tv;
2375              CFMutableDataRef fds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
2376              __CFSocketFdSet(sock, fds);
2377              tv.tv_sec = (timeout <= 0.0 || (CFTimeInterval)INT_MAX <= timeout) ? INT_MAX : (int)floor(timeout);
2378              tv.tv_usec = (int)floor(1.0e+6 * (timeout - floor(timeout)));
2379              nrfds = select(__CFSocketFdGetSize(fds), NULL, (fd_set *)CFDataGetMutableBytePtr(fds), NULL, &tv);
2380              if (nrfds < 0) {
2381                  select_err = __CFSocketLastError();
2382                  result = -1;
2383              } else if (nrfds == 0) {
2384                  result = -2;
2385              } else {
2386                  if (0 != getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&select_err, (socklen_t *)&error_size)) select_err = 0;
2387                  result = (select_err == 0) ? 0 : -1;
2388              }
2389              CFRelease(fds);
2390              __CFSOCKETLOG_WS(s, "timed connection attempt %s result %d, select returns %d error %d\n", (result == 0) ? "succeeds" : "fails", (int) result, (int) nrfds, (int) select_err);
2391          }
2392          if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(sock, FIONBIO, (u_long *)&no);
2393          if (EINPROGRESS == connect_err && timeout < 0.0) {
2394              result = 0;
2395              __CFSOCKETLOG_WS(s, "connection attempt continues in background\n");
2396          }
2397      }
2398      //??? should return errno
2399      return result;
2400  }
2401  
2402  CFSocketRef CFSocketCreate(CFAllocatorRef allocator, SInt32 protocolFamily, SInt32 socketType, SInt32 protocol, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
2403      CHECK_FOR_FORK();
2404      CFSocketNativeHandle sock = INVALID_SOCKET;
2405      CFSocketRef s = NULL;
2406      if (0 >= protocolFamily) protocolFamily = PF_INET;
2407      if (PF_INET == protocolFamily) {
2408          if (0 >= socketType) socketType = SOCK_STREAM;
2409          if (0 >= protocol && SOCK_STREAM == socketType) protocol = IPPROTO_TCP;
2410          if (0 >= protocol && SOCK_DGRAM == socketType) protocol = IPPROTO_UDP;
2411      }
2412  #if TARGET_OS_MAC
2413      if (PF_LOCAL == protocolFamily && 0 >= socketType) socketType = SOCK_STREAM;
2414  #endif
2415  #if TARGET_OS_WIN32
2416      // make sure we've called proper Win32 startup facilities before socket()
2417      __CFSocketInitializeWinSock();
2418  #endif
2419      sock = socket(protocolFamily, socketType, protocol);
2420      if (INVALID_SOCKET != sock) {
2421          s = CFSocketCreateWithNative(allocator, sock, callBackTypes, callout, context);
2422      }
2423      return s;
2424  }
2425  
2426  CFSocketRef CFSocketCreateWithSocketSignature(CFAllocatorRef allocator, const CFSocketSignature *signature, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
2427      CHECK_FOR_FORK();
2428      CFSocketRef s = CFSocketCreate(allocator, signature->protocolFamily, signature->socketType, signature->protocol, callBackTypes, callout, context);
2429      if (NULL != s && (!CFSocketIsValid(s) || kCFSocketSuccess != CFSocketSetAddress(s, signature->address))) {
2430          CFSocketInvalidate(s);
2431          CFRelease(s);
2432          s = NULL;
2433      }
2434      return s;
2435  }
2436  
2437  CFSocketRef CFSocketCreateConnectedToSocketSignature(CFAllocatorRef allocator, const CFSocketSignature *signature, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context, CFTimeInterval timeout) {
2438      CHECK_FOR_FORK();
2439      CFSocketRef s = CFSocketCreate(allocator, signature->protocolFamily, signature->socketType, signature->protocol, callBackTypes, callout, context);
2440      if (NULL != s && (!CFSocketIsValid(s) || kCFSocketSuccess != CFSocketConnectToAddress(s, signature->address, timeout))) {
2441          CFSocketInvalidate(s);
2442          CFRelease(s);
2443          s = NULL;
2444      }
2445      return s;
2446  }
2447  
2448  typedef struct {
2449      CFSocketError *error;
2450      CFPropertyListRef *value;
2451      CFDataRef *address;
2452  } __CFSocketNameRegistryResponse;
2453  
2454  static void __CFSocketHandleNameRegistryReply(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {
2455      CFDataRef replyData = (CFDataRef)data;
2456      __CFSocketNameRegistryResponse *response = (__CFSocketNameRegistryResponse *)info;
2457      CFDictionaryRef replyDictionary = NULL;
2458      CFPropertyListRef value;
2459      replyDictionary = (CFDictionaryRef)CFPropertyListCreateWithData(kCFAllocatorSystemDefault, replyData, kCFPropertyListImmutable, NULL, NULL);
2460      if (NULL != response->error) *(response->error) = kCFSocketError;
2461      if (NULL != replyDictionary) {
2462          if (CFGetTypeID((CFTypeRef)replyDictionary) == CFDictionaryGetTypeID() && NULL != (value = CFDictionaryGetValue(replyDictionary, kCFSocketResultKey))) {
2463              if (NULL != response->error) *(response->error) = kCFSocketSuccess;
2464              if (NULL != response->value) *(response->value) = CFRetain(value);
2465              if (NULL != response->address) *(response->address) = address ? CFDataCreateCopy(kCFAllocatorSystemDefault, address) : NULL;
2466          }
2467          CFRelease(replyDictionary);
2468      }
2469      CFSocketInvalidate(s);
2470  }
2471  
2472  static void __CFSocketSendNameRegistryRequest(CFSocketSignature *signature, CFDictionaryRef requestDictionary, __CFSocketNameRegistryResponse *response, CFTimeInterval timeout) {
2473      CFDataRef requestData = NULL;
2474      CFSocketContext context = {0, response, NULL, NULL, NULL};
2475      CFSocketRef s = NULL;
2476      CFRunLoopSourceRef source = NULL;
2477      if (NULL != response->error) *(response->error) = kCFSocketError;
2478      requestData = CFPropertyListCreateData(kCFAllocatorSystemDefault, requestDictionary, kCFPropertyListXMLFormat_v1_0, 0, NULL);
2479      if (NULL != requestData) {
2480          if (NULL != response->error) *(response->error) = kCFSocketTimeout;
2481          s = CFSocketCreateConnectedToSocketSignature(kCFAllocatorSystemDefault, signature, kCFSocketDataCallBack, __CFSocketHandleNameRegistryReply, &context, timeout);
2482          if (NULL != s) {
2483              if (kCFSocketSuccess == CFSocketSendData(s, NULL, requestData, timeout)) {
2484                  source = CFSocketCreateRunLoopSource(kCFAllocatorSystemDefault, s, 0);
2485                  CFRunLoopAddSource(CFRunLoopGetCurrent(), source, __kCFSocketRegistryRequestRunLoopMode);
2486                  CFRunLoopRunInMode(__kCFSocketRegistryRequestRunLoopMode, timeout, false);
2487                  CFRelease(source);
2488              }
2489              CFSocketInvalidate(s);
2490              CFRelease(s);
2491          }
2492          CFRelease(requestData);
2493      }
2494  }
2495  
2496  static void __CFSocketValidateSignature(const CFSocketSignature *providedSignature, CFSocketSignature *signature, uint16_t defaultPortNumber) {
2497      struct sockaddr_in sain, *sainp;
2498      memset(&sain, 0, sizeof(sain));
2499  #if TARGET_OS_MAC
2500      sain.sin_len = sizeof(sain);
2501  #endif
2502      sain.sin_family = AF_INET;
2503      sain.sin_port = htons(__CFSocketDefaultNameRegistryPortNumber);
2504      sain.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2505      if (NULL == providedSignature) {
2506          signature->protocolFamily = PF_INET;
2507          signature->socketType = SOCK_STREAM;
2508          signature->protocol = IPPROTO_TCP;
2509          signature->address = CFDataCreate(kCFAllocatorSystemDefault, (uint8_t *)&sain, sizeof(sain));
2510      } else {
2511          signature->protocolFamily = providedSignature->protocolFamily;
2512          signature->socketType = providedSignature->socketType;
2513          signature->protocol = providedSignature->protocol;
2514          if (0 >= signature->protocolFamily) signature->protocolFamily = PF_INET;
2515          if (PF_INET == signature->protocolFamily) {
2516              if (0 >= signature->socketType) signature->socketType = SOCK_STREAM;
2517              if (0 >= signature->protocol && SOCK_STREAM == signature->socketType) signature->protocol = IPPROTO_TCP;
2518              if (0 >= signature->protocol && SOCK_DGRAM == signature->socketType) signature->protocol = IPPROTO_UDP;
2519          }
2520          if (NULL == providedSignature->address) {
2521              signature->address = CFDataCreate(kCFAllocatorSystemDefault, (uint8_t *)&sain, sizeof(sain));
2522          } else {
2523              sainp = (struct sockaddr_in *)CFDataGetBytePtr(providedSignature->address);
2524              if ((int)sizeof(struct sockaddr_in) <= CFDataGetLength(providedSignature->address) && (AF_INET == sainp->sin_family || 0 == sainp->sin_family)) {
2525  #if TARGET_OS_MAC
2526                  sain.sin_len = sizeof(sain);
2527  #endif
2528                  sain.sin_family = AF_INET;
2529                  sain.sin_port = sainp->sin_port;
2530                  if (0 == sain.sin_port) sain.sin_port = htons(defaultPortNumber);
2531                  sain.sin_addr.s_addr = sainp->sin_addr.s_addr;
2532                  if (htonl(INADDR_ANY) == sain.sin_addr.s_addr) sain.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2533                  signature->address = CFDataCreate(kCFAllocatorSystemDefault, (uint8_t *)&sain, sizeof(sain));
2534              } else {
2535                  signature->address = (CFDataRef)CFRetain(providedSignature->address);
2536              }
2537          }
2538      }
2539  }
2540  
2541  CFSocketError CFSocketRegisterValue(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFPropertyListRef value) {
2542      CFSocketSignature signature;
2543      CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2544      CFSocketError retval = kCFSocketError;
2545      __CFSocketNameRegistryResponse response = {&retval, NULL, NULL};
2546      CFDictionaryAddValue(dictionary, kCFSocketCommandKey, kCFSocketRegisterCommand);
2547      CFDictionaryAddValue(dictionary, kCFSocketNameKey, name);
2548      if (NULL != value) CFDictionaryAddValue(dictionary, kCFSocketValueKey, value);
2549      __CFSocketValidateSignature(nameServerSignature, &signature, __CFSocketDefaultNameRegistryPortNumber);
2550      __CFSocketSendNameRegistryRequest(&signature, dictionary, &response, timeout);
2551      CFRelease(dictionary);
2552      CFRelease(signature.address);
2553      return retval;
2554  }
2555  
2556  CFSocketError CFSocketCopyRegisteredValue(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFPropertyListRef *value, CFDataRef *serverAddress) {
2557      CFSocketSignature signature;
2558      CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2559      CFSocketError retval = kCFSocketError;
2560      __CFSocketNameRegistryResponse response = {&retval, value, serverAddress};
2561      CFDictionaryAddValue(dictionary, kCFSocketCommandKey, kCFSocketRetrieveCommand);
2562      CFDictionaryAddValue(dictionary, kCFSocketNameKey, name);
2563      __CFSocketValidateSignature(nameServerSignature, &signature, __CFSocketDefaultNameRegistryPortNumber);
2564      __CFSocketSendNameRegistryRequest(&signature, dictionary, &response, timeout);
2565      CFRelease(dictionary);
2566      CFRelease(signature.address);
2567      return retval;
2568  }
2569  
2570  CFSocketError CFSocketRegisterSocketSignature(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, const CFSocketSignature *signature) {
2571      CFSocketSignature validatedSignature;
2572      CFMutableDataRef data = NULL;
2573      CFSocketError retval;
2574      CFIndex length;
2575      uint8_t bytes[4];
2576      if (NULL == signature) {
2577          retval = CFSocketUnregister(nameServerSignature, timeout, name);
2578      } else {
2579          __CFSocketValidateSignature(signature, &validatedSignature, 0);
2580          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) {
2581              retval = kCFSocketError;
2582          } else {
2583              data = CFDataCreateMutable(kCFAllocatorSystemDefault, sizeof(bytes) + length);
2584              bytes[0] = validatedSignature.protocolFamily;
2585              bytes[1] = validatedSignature.socketType;
2586              bytes[2] = validatedSignature.protocol;
2587              bytes[3] = length;
2588              CFDataAppendBytes(data, bytes, sizeof(bytes));
2589              CFDataAppendBytes(data, CFDataGetBytePtr(validatedSignature.address), length);
2590              retval = CFSocketRegisterValue(nameServerSignature, timeout, name, data);
2591              CFRelease(data);
2592          }
2593          if (validatedSignature.address) CFRelease(validatedSignature.address);
2594      }
2595      return retval;
2596  }
2597  
2598  CFSocketError CFSocketCopyRegisteredSocketSignature(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFSocketSignature *signature, CFDataRef *nameServerAddress) {
2599      CFDataRef data = NULL;
2600      CFSocketSignature returnedSignature;
2601      const uint8_t *ptr = NULL, *aptr = NULL;
2602      uint8_t *mptr;
2603      CFIndex length = 0;
2604      CFDataRef serverAddress = NULL;
2605      CFSocketError retval = CFSocketCopyRegisteredValue(nameServerSignature, timeout, name, (CFPropertyListRef *)&data, &serverAddress);
2606      if (NULL == data || CFGetTypeID(data) != CFDataGetTypeID() || NULL == (ptr = CFDataGetBytePtr(data)) || (length = CFDataGetLength(data)) < 4) retval = kCFSocketError;
2607      if (kCFSocketSuccess == retval && NULL != signature) {
2608          returnedSignature.protocolFamily = (SInt32)*ptr++;
2609          returnedSignature.socketType = (SInt32)*ptr++;
2610          returnedSignature.protocol = (SInt32)*ptr++;
2611          ptr++;
2612          returnedSignature.address = CFDataCreate(kCFAllocatorSystemDefault, ptr, length - 4);
2613          __CFSocketValidateSignature(&returnedSignature, signature, 0);
2614          CFRelease(returnedSignature.address);
2615          ptr = CFDataGetBytePtr(signature->address);
2616          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) {
2617              CFMutableDataRef address = CFDataCreateMutableCopy(kCFAllocatorSystemDefault, CFDataGetLength(signature->address), signature->address);
2618              mptr = CFDataGetMutableBytePtr(address);
2619              ((struct sockaddr_in *)mptr)->sin_addr = ((struct sockaddr_in *)aptr)->sin_addr;
2620              CFRelease(signature->address);
2621              signature->address = address;
2622          }
2623          if (NULL != nameServerAddress) *nameServerAddress = serverAddress ? (CFDataRef)CFRetain(serverAddress) : NULL;
2624      }
2625      if (NULL != data) CFRelease(data);
2626      if (NULL != serverAddress) CFRelease(serverAddress);
2627      return retval;
2628  }
2629  
2630  CFSocketError CFSocketUnregister(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name) {
2631      return CFSocketRegisterValue(nameServerSignature, timeout, name, NULL);
2632  }
2633  
2634  CF_EXPORT void CFSocketSetDefaultNameRegistryPortNumber(uint16_t port) {
2635      __CFSocketDefaultNameRegistryPortNumber = port;
2636  }
2637  
2638  CF_EXPORT uint16_t CFSocketGetDefaultNameRegistryPortNumber(void) {
2639      return __CFSocketDefaultNameRegistryPortNumber;
2640  }
2641