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