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