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