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