]> git.saurik.com Git - apple/cf.git/blob - RunLoop.subproj/CFSocket.c
CF-368.18.tar.gz
[apple/cf.git] / RunLoop.subproj / CFSocket.c
1 /*
2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /* CFSocket.c
24 Copyright 1999-2002, Apple, Inc. All rights reserved.
25 Responsibility: Doug Davidson
26 */
27
28 #include <CoreFoundation/CFSocket.h>
29 #include <sys/types.h>
30 #include <math.h>
31 #include <limits.h>
32 #include <CoreFoundation/CFArray.h>
33 #include <CoreFoundation/CFData.h>
34 #include <CoreFoundation/CFDictionary.h>
35 #include <CoreFoundation/CFRunLoop.h>
36 #include <CoreFoundation/CFString.h>
37 #include <CoreFoundation/CFPropertyList.h>
38 #include "CFInternal.h"
39 #if defined(__WIN32__)
40 #include <winsock2.h>
41 #include <stdio.h>
42 // Careful with remapping these - different WinSock routines return different errors than
43 // on BSD, so if these are used many places they won't work.
44 #define EINPROGRESS WSAEINPROGRESS
45 #ifdef EBADF
46 #undef EBADF
47 #endif
48 #define EBADF WSAENOTSOCK
49 #elif defined(__MACH__)
50 #include <libc.h>
51 #else
52 #include <sys/filio.h>
53 #include <sys/time.h>
54 #include <sys/socket.h>
55 #include <netinet/in.h>
56 #include <netdb.h>
57 #endif
58
59 // On Mach we use a v0 RunLoopSource to make client callbacks. That source is signalled by a
60 // separate SocketManager thread who uses select() to watch the sockets' fds.
61 //
62 // On Win32 we (primarily) use a v1 RunLoopSource. Code protected by USE_V1_RUN_LOOP_SOURCE currently
63 // assumes __WIN32__ is defined. The Win32 v1 RunLoopSource uses a Windows event object to be notified
64 // of socket events like FD_READ, FD_CONNECT, etc, at which point it can immediately make client
65 // callbacks instead of doing any inter-thread signaling.
66 //
67 // Because of the peculiar way that FD_WRITE is signalled (see WSAEventSelect doc in MSDN), we
68 // could not implement the current CFSocket client write callback semantics on top of the FD_WRITE
69 // events received by the v1 source. However, because the performance gains on the read side
70 // were so great with the v1 source, we use a hybrid approach to implement the write side. Read
71 // callbacks are triggered straightforwardly by FD_READ events. Write callbacks are triggered in
72 // two ways. Most commonly, as we return to the core run loop we poll a socket's writability
73 // using select(). If it can accept bytes, we signal our v1 RunLoopSource such that it will be
74 // immediately fired, and we can make the write callback. Alternatively, if the socket is full,
75 // we then use the old v0-style approach of notifying the SocketManager thread to listen for
76 // notification that the socket can accept bytes using select(). Of course these two modes also
77 // must respect the various write callback settings and autoenabling flags setup by the client.
78 // The net effect is that we rarely must interact with the SocketMgr thread, which leads to a
79 // performance win.
80 //
81 // Because of this hybrid, we end up needing both a v1 RunLoopSource (to watch the Windows FD_*
82 // events) and a v0 RunLoopSource (to be signaled from the socket manager). Since our API exports
83 // a single RunLoopSource that clients may schedule, we hand out the v0 RunLoopSource, and as it
84 // is scheduled and canceled we install the v1 RunLoopSource in the same modes.
85 #if defined(__WIN32__)
86 #define USE_V1_RUN_LOOP_SOURCE
87 #endif
88
89 //#define LOG_CFSOCKET
90
91 #if !defined(__WIN32__)
92 #define INVALID_SOCKET (CFSocketNativeHandle)(-1)
93 #endif /* __WIN32__ */
94
95 #define MAX_SOCKADDR_LEN 256
96 #define MAX_DATA_SIZE 32768
97
98 static uint16_t __CFSocketDefaultNameRegistryPortNumber = 2454;
99
100 CONST_STRING_DECL(kCFSocketCommandKey, "Command")
101 CONST_STRING_DECL(kCFSocketNameKey, "Name")
102 CONST_STRING_DECL(kCFSocketValueKey, "Value")
103 CONST_STRING_DECL(kCFSocketResultKey, "Result")
104 CONST_STRING_DECL(kCFSocketErrorKey, "Error")
105 CONST_STRING_DECL(kCFSocketRegisterCommand, "Register")
106 CONST_STRING_DECL(kCFSocketRetrieveCommand, "Retrieve")
107 CONST_STRING_DECL(__kCFSocketRegistryRequestRunLoopMode, "CFSocketRegistryRequest")
108
109 /* locks are to be acquired in the following order:
110 (1) __CFAllSocketsLock
111 (2) an individual CFSocket's lock
112 (3) __CFActiveSocketsLock
113 */
114 static CFSpinLock_t __CFAllSocketsLock = 0; /* controls __CFAllSockets */
115 static CFMutableDictionaryRef __CFAllSockets = NULL;
116 static CFSpinLock_t __CFActiveSocketsLock = 0; /* controls __CFRead/WriteSockets, __CFRead/WriteSocketsFds, __CFSocketManagerThread, and __CFSocketManagerIteration */
117 static volatile UInt32 __CFSocketManagerIteration = 0;
118 static CFMutableArrayRef __CFWriteSockets = NULL;
119 static CFMutableArrayRef __CFReadSockets = NULL;
120 static CFMutableDataRef __CFWriteSocketsFds = NULL;
121 static CFMutableDataRef __CFReadSocketsFds = NULL;
122 #if defined(__WIN32__)
123 // We need to select on exceptFDs on Win32 to hear of connect failures
124 static CFMutableDataRef __CFExceptSocketsFds = NULL;
125 #endif
126 static CFDataRef zeroLengthData = NULL;
127
128 static CFSocketNativeHandle __CFWakeupSocketPair[2] = {INVALID_SOCKET, INVALID_SOCKET};
129 static void *__CFSocketManagerThread = NULL;
130
131 #if !defined(__WIN32__)
132 #define CFSOCKET_USE_SOCKETPAIR
133 #define closesocket(a) close((a))
134 #define ioctlsocket(a,b,c) ioctl((a),(b),(c))
135 #endif
136
137 static CFTypeID __kCFSocketTypeID = _kCFRuntimeNotATypeID;
138 static void __CFSocketDoCallback(CFSocketRef s, CFDataRef data, CFDataRef address, CFSocketNativeHandle sock);
139 static void __CFSocketInvalidate(CFSocketRef s, Boolean wakeup);
140
141 struct __CFSocket {
142 CFRuntimeBase _base;
143 struct {
144 unsigned client:8; // flags set by client (reenable, CloseOnInvalidate)
145 unsigned disabled:8; // flags marking disabled callbacks
146 unsigned connected:1; // Are we connected yet? (also true for connectionless sockets)
147 unsigned writableHint:1; // Did the polling the socket show it to be writable?
148 unsigned closeSignaled:1; // Have we seen FD_CLOSE? (only used on Win32)
149 unsigned unused:13;
150 } _f;
151 CFSpinLock_t _lock;
152 CFSpinLock_t _writeLock;
153 CFSocketNativeHandle _socket; /* immutable */
154 SInt32 _socketType;
155 SInt32 _errorCode;
156 CFDataRef _address;
157 CFDataRef _peerAddress;
158 SInt32 _socketSetCount;
159 CFRunLoopSourceRef _source0; // v0 RLS, messaged from SocketMgr
160 CFMutableArrayRef _runLoops;
161 CFSocketCallBack _callout; /* immutable */
162 CFSocketContext _context; /* immutable */
163 #if !defined(USE_V1_RUN_LOOP_SOURCE)
164 CFIndex _maxQueueLen; // queues to pass data from SocketMgr thread
165 CFMutableArrayRef _dataQueue;
166 CFMutableArrayRef _addressQueue;
167 #else
168 CFRunLoopSourceRef _source1; // v1 RLS, triggered by _event happenings
169 HANDLE _event; // used to hear about socket events
170 long _oldEventMask; // last event mask value set with WSAEventSelect
171 #endif
172 };
173
174 /* Bit 6 in the base reserved bits is used for write-signalled state (mutable) */
175 /* Bit 5 in the base reserved bits is used for read-signalled state (mutable) */
176 /* Bit 4 in the base reserved bits is used for invalid state (mutable) */
177 /* Bits 0-3 in the base reserved bits are used for callback types (immutable) */
178 /* Of this, bits 0-1 are used for the read callback type. */
179
180 CF_INLINE Boolean __CFSocketIsWriteSignalled(CFSocketRef s) {
181 return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_info, 6, 6);
182 }
183
184 CF_INLINE void __CFSocketSetWriteSignalled(CFSocketRef s) {
185 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_info, 6, 6, 1);
186 }
187
188 CF_INLINE void __CFSocketUnsetWriteSignalled(CFSocketRef s) {
189 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_info, 6, 6, 0);
190 }
191
192 CF_INLINE Boolean __CFSocketIsReadSignalled(CFSocketRef s) {
193 return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_info, 5, 5);
194 }
195
196 CF_INLINE void __CFSocketSetReadSignalled(CFSocketRef s) {
197 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_info, 5, 5, 1);
198 }
199
200 CF_INLINE void __CFSocketUnsetReadSignalled(CFSocketRef s) {
201 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_info, 5, 5, 0);
202 }
203
204 CF_INLINE Boolean __CFSocketIsValid(CFSocketRef s) {
205 return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_info, 4, 4);
206 }
207
208 CF_INLINE void __CFSocketSetValid(CFSocketRef s) {
209 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_info, 4, 4, 1);
210 }
211
212 CF_INLINE void __CFSocketUnsetValid(CFSocketRef s) {
213 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_info, 4, 4, 0);
214 }
215
216 CF_INLINE uint8_t __CFSocketCallBackTypes(CFSocketRef s) {
217 return (uint8_t)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_info, 3, 0);
218 }
219
220 CF_INLINE uint8_t __CFSocketReadCallBackType(CFSocketRef s) {
221 return (uint8_t)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_info, 1, 0);
222 }
223
224 CF_INLINE void __CFSocketSetCallBackTypes(CFSocketRef s, uint8_t types) {
225 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_info, 3, 0, types & 0xF);
226 }
227
228 CF_INLINE void __CFSocketLock(CFSocketRef s) {
229 __CFSpinLock(&(s->_lock));
230 }
231
232 CF_INLINE void __CFSocketUnlock(CFSocketRef s) {
233 __CFSpinUnlock(&(s->_lock));
234 }
235
236 CF_INLINE void __CFSocketWriteLock(CFSocketRef s) {
237 __CFSpinLock(&(s->_writeLock));
238 }
239
240 CF_INLINE void __CFSocketWriteUnlock(CFSocketRef s) {
241 __CFSpinUnlock(&(s->_writeLock));
242 }
243
244 CF_INLINE Boolean __CFSocketIsConnectionOriented(CFSocketRef s) {
245 return (SOCK_STREAM == s->_socketType || SOCK_SEQPACKET == s->_socketType);
246 }
247
248 CF_INLINE Boolean __CFSocketIsScheduled(CFSocketRef s) {
249 return (s->_socketSetCount > 0);
250 }
251
252 CF_INLINE void __CFSocketEstablishAddress(CFSocketRef s) {
253 /* socket should already be locked */
254 uint8_t name[MAX_SOCKADDR_LEN];
255 int namelen = sizeof(name);
256 if (__CFSocketIsValid(s) && NULL == s->_address && INVALID_SOCKET != s->_socket && 0 == getsockname(s->_socket, (struct sockaddr *)name, &namelen) && NULL != name && 0 < namelen) {
257 s->_address = CFDataCreate(CFGetAllocator(s), name, namelen);
258 }
259 }
260
261 CF_INLINE void __CFSocketEstablishPeerAddress(CFSocketRef s) {
262 /* socket should already be locked */
263 uint8_t name[MAX_SOCKADDR_LEN];
264 int namelen = sizeof(name);
265 if (__CFSocketIsValid(s) && NULL == s->_peerAddress && INVALID_SOCKET != s->_socket && 0 == getpeername(s->_socket, (struct sockaddr *)name, &namelen) && NULL != name && 0 < namelen) {
266 s->_peerAddress = CFDataCreate(CFGetAllocator(s), name, namelen);
267 }
268 }
269
270 CF_INLINE CFIndex __CFSocketFdGetSize(CFDataRef fdSet) {
271 #if defined(__WIN32__)
272 fd_set* set = (fd_set*)CFDataGetBytePtr(fdSet);
273 return set ? set->fd_count : 0;
274 #else
275 return NBBY * CFDataGetLength(fdSet);
276 #endif
277 }
278
279 CF_INLINE int __CFSocketLastError(void) {
280 #if defined(__WIN32__)
281 return WSAGetLastError();
282 #else
283 return thread_errno();
284 #endif
285 }
286
287 static Boolean __CFNativeSocketIsValid(CFSocketNativeHandle sock) {
288 #if defined(__WIN32__)
289 SInt32 errorCode = 0;
290 int errorSize = sizeof(errorCode);
291 return !(0 != getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&errorCode, &errorSize) && WSAGetLastError() == WSAENOTSOCK);
292 #else
293 SInt32 flags = fcntl(sock, F_GETFL, 0);
294 return !(0 > flags && EBADF == thread_errno());
295 #endif
296 }
297
298 CF_INLINE Boolean __CFSocketFdSet(CFSocketNativeHandle sock, CFMutableDataRef fdSet) {
299 /* returns true if a change occurred, false otherwise */
300 Boolean retval = false;
301 if (INVALID_SOCKET != sock && 0 <= sock) {
302 #if defined(__WIN32__)
303 fd_set* set = (fd_set*)CFDataGetMutableBytePtr(fdSet);
304 if ((set->fd_count * sizeof(SOCKET) + sizeof(u_int)) >= CFDataGetLength(fdSet)) {
305 CFDataIncreaseLength(fdSet, sizeof(SOCKET));
306 set = (fd_set*)CFDataGetMutableBytePtr(fdSet);
307 }
308 if (!FD_ISSET(sock, set)) {
309 retval = true;
310 FD_SET(sock, set);
311 }
312 #else
313 CFIndex numFds = NBBY * CFDataGetLength(fdSet);
314 fd_mask *fds_bits;
315 if (sock >= numFds) {
316 CFIndex oldSize = numFds / NFDBITS, newSize = (sock + NFDBITS) / NFDBITS, changeInBytes = (newSize - oldSize) * sizeof(fd_mask);
317 CFDataIncreaseLength(fdSet, changeInBytes);
318 fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
319 memset(fds_bits + oldSize, 0, changeInBytes);
320 } else {
321 fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
322 }
323 if (!FD_ISSET(sock, (fd_set *)fds_bits)) {
324 retval = true;
325 FD_SET(sock, (fd_set *)fds_bits);
326 }
327 #endif
328 }
329 return retval;
330 }
331
332 CF_INLINE Boolean __CFSocketFdClr(CFSocketNativeHandle sock, CFMutableDataRef fdSet) {
333 /* returns true if a change occurred, false otherwise */
334 Boolean retval = false;
335 if (INVALID_SOCKET != sock && 0 <= sock) {
336 #if defined(__WIN32__)
337 fd_set* set = (fd_set*)CFDataGetMutableBytePtr(fdSet);
338 if (FD_ISSET(sock, set)) {
339 retval = true;
340 FD_CLR(sock, set);
341 }
342 #else
343 CFIndex numFds = NBBY * CFDataGetLength(fdSet);
344 fd_mask *fds_bits;
345 if (sock < numFds) {
346 fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
347 if (FD_ISSET(sock, (fd_set *)fds_bits)) {
348 retval = true;
349 FD_CLR(sock, (fd_set *)fds_bits);
350 }
351 }
352 #endif
353 }
354 return retval;
355 }
356
357 static SInt32 __CFSocketCreateWakeupSocketPair(void) {
358 #if defined(CFSOCKET_USE_SOCKETPAIR)
359 return socketpair(PF_LOCAL, SOCK_DGRAM, 0, __CFWakeupSocketPair);
360 #else
361 //??? should really use native Win32 facilities
362 UInt32 i;
363 SInt32 error = 0;
364 struct sockaddr_in address[2];
365 int namelen = sizeof(struct sockaddr_in);
366 for (i = 0; i < 2; i++) {
367 __CFWakeupSocketPair[i] = socket(PF_INET, SOCK_DGRAM, 0);
368 memset(&(address[i]), 0, sizeof(struct sockaddr_in));
369 address[i].sin_family = AF_INET;
370 address[i].sin_addr.s_addr = htonl(INADDR_LOOPBACK);
371 if (0 <= error) error = bind(__CFWakeupSocketPair[i], (struct sockaddr *)&(address[i]), sizeof(struct sockaddr_in));
372 if (0 <= error) error = getsockname(__CFWakeupSocketPair[i], (struct sockaddr *)&(address[i]), &namelen);
373 if (sizeof(struct sockaddr_in) != namelen) error = -1;
374 }
375 if (0 <= error) error = connect(__CFWakeupSocketPair[0], (struct sockaddr *)&(address[1]), sizeof(struct sockaddr_in));
376 if (0 <= error) error = connect(__CFWakeupSocketPair[1], (struct sockaddr *)&(address[0]), sizeof(struct sockaddr_in));
377 if (0 > error) {
378 closesocket(__CFWakeupSocketPair[0]);
379 closesocket(__CFWakeupSocketPair[1]);
380 __CFWakeupSocketPair[0] = INVALID_SOCKET;
381 __CFWakeupSocketPair[1] = INVALID_SOCKET;
382 }
383 return error;
384 #endif
385 }
386
387 #if defined(USE_V1_RUN_LOOP_SOURCE)
388 // Version 1 RunLoopSources set a mask in a Windows System Event to control what socket activity we
389 // hear about. Because you can only set the mask as a whole, we must remember the previous value so
390 // set can make relative changes to it. The way we enable/disable precludes calculating the whole
391 // mask from scratch from the current state we keep.
392
393 static Boolean __CFSocketSetWholeEventMask(CFSocketRef s, long newMask) {
394 if (s->_oldEventMask != newMask) {
395 int err;
396 #if defined(LOG_CFSOCKET)
397 fprintf(stdout, "calling WSAEventSelect for socket/event %d/%d with event flags 0x%lx\n", s->_socket, (int)s->_event, newMask);
398 #endif
399 err = WSAEventSelect(s->_socket, s->_event, newMask);
400 CFAssert2(0 == err, __kCFLogAssertion, "%s(): WSAEventSelect failed: %d", __PRETTY_FUNCTION__, WSAGetLastError());
401 s->_oldEventMask = newMask;
402 return TRUE;
403 } else
404 return FALSE;
405 }
406
407 CF_INLINE Boolean __CFSocketSetFDForRead(CFSocketRef s) {
408 long bitToSet;
409 // we assume that some read bits are set - all callers have checked this
410 CFAssert1(0 != __CFSocketReadCallBackType(s), __kCFLogAssertion, "%s(): __CFSocketReadCallBackType is zero", __PRETTY_FUNCTION__);
411 bitToSet = (__CFSocketReadCallBackType(s) == kCFSocketAcceptCallBack) ? FD_ACCEPT : FD_READ;
412 return __CFSocketSetWholeEventMask(s, s->_oldEventMask | bitToSet);
413 }
414
415 CF_INLINE Boolean __CFSocketClearFDForRead(CFSocketRef s) {
416 long bitToClear;
417 // we assume that some read bits are set - all callers have checked this
418 CFAssert1(0 != __CFSocketReadCallBackType(s), __kCFLogAssertion, "%s(): __CFSocketReadCallBackType is zero", __PRETTY_FUNCTION__);
419 bitToClear = (__CFSocketReadCallBackType(s) == kCFSocketAcceptCallBack) ? FD_ACCEPT : FD_READ;
420 return __CFSocketSetWholeEventMask(s, s->_oldEventMask & ~bitToClear);
421 }
422
423 #else // !USE_V1_RUN_LOOP_SOURCE
424 // Version 0 RunLoopSources set a mask in an FD set to control what socket activity we hear about.
425 CF_INLINE Boolean __CFSocketSetFDForRead(CFSocketRef s) {
426 return __CFSocketFdSet(s->_socket, __CFReadSocketsFds);
427 }
428
429 CF_INLINE Boolean __CFSocketClearFDForRead(CFSocketRef s) {
430 return __CFSocketFdClr(s->_socket, __CFReadSocketsFds);
431 }
432 #endif
433
434 CF_INLINE Boolean __CFSocketSetFDForWrite(CFSocketRef s) {
435 return __CFSocketFdSet(s->_socket, __CFWriteSocketsFds);
436 }
437
438 CF_INLINE Boolean __CFSocketClearFDForWrite(CFSocketRef s) {
439 return __CFSocketFdClr(s->_socket, __CFWriteSocketsFds);
440 }
441
442 #if defined(USE_V1_RUN_LOOP_SOURCE)
443 static Boolean __CFSocketCanAcceptBytes(CFSocketRef s) {
444 struct timeval timeout = {0, 0};
445 fd_set set;
446 int result;
447 FD_ZERO(&set);
448 FD_SET(s->_socket, &set);
449 result = select(s->_socket + 1, NULL, &set, NULL, &timeout);
450 #if defined(LOG_CFSOCKET)
451 fprintf(stdout, "polling writability of %d yields %d\n", s->_socket, result);
452 #endif
453 return result == 1;
454 }
455
456 static Boolean __CFSocketHasBytesToRead(CFSocketRef s) {
457 unsigned long avail;
458 int err = ioctlsocket(s->_socket, FIONREAD, &avail);
459 CFAssert3(0 == err, __kCFLogAssertion, "%s(): unexpected error from ioctlsocket(%d, FIONREAD,...): %d", __PRETTY_FUNCTION__, s->_socket, WSAGetLastError());
460 #if defined(LOG_CFSOCKET)
461 fprintf(stdout, "polling readability of %d yields %ld\n", s->_socket, avail);
462 #endif
463 return (0 == err) && avail > 0;
464 }
465 #endif
466
467 #if defined(__WIN32__)
468 static Boolean WinSockUsed = FALSE;
469
470 static void __CFSocketInitializeWinSock_Guts(void) {
471 if (!WinSockUsed) {
472 WinSockUsed = TRUE;
473 WORD versionRequested = MAKEWORD(2, 0);
474 WSADATA wsaData;
475 int errorStatus = WSAStartup(versionRequested, &wsaData);
476 if (errorStatus != 0 || LOBYTE(wsaData.wVersion) != LOBYTE(versionRequested) || HIBYTE(wsaData.wVersion) != HIBYTE(versionRequested)) {
477 WSACleanup();
478 CFLog(0, CFSTR("*** Could not initialize WinSock subsystem!!!"));
479 }
480 }
481 }
482
483 CF_EXPORT void __CFSocketInitializeWinSock(void) {
484 __CFSpinLock(&__CFActiveSocketsLock);
485 __CFSocketInitializeWinSock_Guts();
486 __CFSpinUnlock(&__CFActiveSocketsLock);
487 }
488
489 __private_extern__ void __CFSocketCleanup(void) {
490 __CFSpinLock(&__CFActiveSocketsLock);
491 if (NULL != __CFReadSockets) {
492 CFRelease(__CFWriteSockets);
493 __CFWriteSockets = NULL;
494 CFRelease(__CFReadSockets);
495 __CFReadSockets = NULL;
496 CFRelease(__CFWriteSocketsFds);
497 __CFWriteSocketsFds = NULL;
498 CFRelease(__CFReadSocketsFds);
499 __CFReadSocketsFds = NULL;
500 CFRelease(__CFExceptSocketsFds);
501 __CFExceptSocketsFds = NULL;
502 CFRelease(zeroLengthData);
503 zeroLengthData = NULL;
504 }
505 if (NULL != __CFAllSockets) {
506 CFRelease(__CFAllSockets);
507 __CFAllSockets = NULL;
508 }
509 if (INVALID_SOCKET != __CFWakeupSocketPair[0]) {
510 closesocket(__CFWakeupSocketPair[0]);
511 __CFWakeupSocketPair[0] = INVALID_SOCKET;
512 }
513 if (INVALID_SOCKET != __CFWakeupSocketPair[1]) {
514 closesocket(__CFWakeupSocketPair[1]);
515 __CFWakeupSocketPair[1] = INVALID_SOCKET;
516 }
517 if (WinSockUsed) {
518 WSACleanup();
519 }
520 __CFSpinUnlock(&__CFActiveSocketsLock);
521 }
522 #endif
523
524 // CFNetwork needs to call this, especially for Win32 to get WSAStartup
525 static void __CFSocketInitializeSockets(void) {
526 __CFWriteSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
527 __CFReadSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
528 __CFWriteSocketsFds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
529 __CFReadSocketsFds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
530 zeroLengthData = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
531 #if defined(__WIN32__)
532 __CFSocketInitializeWinSock_Guts();
533 // make sure we have space for the count field and the first socket
534 CFDataIncreaseLength(__CFWriteSocketsFds, sizeof(u_int) + sizeof(SOCKET));
535 CFDataIncreaseLength(__CFReadSocketsFds, sizeof(u_int) + sizeof(SOCKET));
536 __CFExceptSocketsFds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
537 CFDataIncreaseLength(__CFExceptSocketsFds, sizeof(u_int) + sizeof(SOCKET));
538 #endif
539 if (0 > __CFSocketCreateWakeupSocketPair()) {
540 CFLog(0, CFSTR("*** Could not create wakeup socket pair for CFSocket!!!"));
541 } else {
542 UInt32 yes = 1;
543 /* wakeup sockets must be non-blocking */
544 ioctlsocket(__CFWakeupSocketPair[0], FIONBIO, &yes);
545 ioctlsocket(__CFWakeupSocketPair[1], FIONBIO, &yes);
546 __CFSocketFdSet(__CFWakeupSocketPair[1], __CFReadSocketsFds);
547 }
548 }
549
550 static CFRunLoopRef __CFSocketCopyRunLoopToWakeUp(CFSocketRef s) {
551 CFRunLoopRef rl = NULL;
552 SInt32 idx, cnt = CFArrayGetCount(s->_runLoops);
553 if (0 < cnt) {
554 rl = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, 0);
555 for (idx = 1; NULL != rl && idx < cnt; idx++) {
556 CFRunLoopRef value = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, idx);
557 if (value != rl) rl = NULL;
558 }
559 if (NULL == rl) { /* more than one different rl, so we must pick one */
560 /* ideally, this would be a run loop which isn't also in a
561 * signaled state for this or another source, but that's tricky;
562 * we pick one that is running in an appropriate mode for this
563 * source, and from those if possible one that is waiting; then
564 * we move this run loop to the end of the list to scramble them
565 * a bit, and always search from the front */
566 Boolean foundIt = false, foundBackup = false;
567 SInt32 foundIdx = 0;
568 for (idx = 0; !foundIt && idx < cnt; idx++) {
569 CFRunLoopRef value = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, idx);
570 CFStringRef currentMode = CFRunLoopCopyCurrentMode(value);
571 if (NULL != currentMode) {
572 if (CFRunLoopContainsSource(value, s->_source0, currentMode)) {
573 if (CFRunLoopIsWaiting(value)) {
574 foundIdx = idx;
575 foundIt = true;
576 } else if (!foundBackup) {
577 foundIdx = idx;
578 foundBackup = true;
579 }
580 }
581 CFRelease(currentMode);
582 }
583 }
584 rl = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, foundIdx);
585 CFRetain(rl);
586 CFArrayRemoveValueAtIndex(s->_runLoops, foundIdx);
587 CFArrayAppendValue(s->_runLoops, rl);
588 } else {
589 CFRetain(rl);
590 }
591 }
592 return rl;
593 }
594
595 // If callBackNow, we immediately do client callbacks, else we have to signal a v0 RunLoopSource so the
596 // callbacks can happen in another thread.
597 static void __CFSocketHandleWrite(CFSocketRef s, Boolean callBackNow) {
598 SInt32 errorCode = 0;
599 int errorSize = sizeof(errorCode);
600 CFOptionFlags writeCallBacksAvailable;
601
602 if (!CFSocketIsValid(s)) return;
603 if (0 != getsockopt(s->_socket, SOL_SOCKET, SO_ERROR, (void *)&errorCode, &errorSize)) errorCode = 0; // cast for WinSock bad API
604 #if defined(LOG_CFSOCKET)
605 if (errorCode) fprintf(stdout, "error %ld on socket %d\n", errorCode, s->_socket);
606 #endif
607 __CFSocketLock(s);
608 writeCallBacksAvailable = __CFSocketCallBackTypes(s) & (kCFSocketWriteCallBack | kCFSocketConnectCallBack);
609 if ((s->_f.client & kCFSocketConnectCallBack) != 0) writeCallBacksAvailable &= ~kCFSocketConnectCallBack;
610 if (!__CFSocketIsValid(s) || ((s->_f.disabled & writeCallBacksAvailable) == writeCallBacksAvailable)) {
611 __CFSocketUnlock(s);
612 return;
613 }
614 s->_errorCode = errorCode;
615 __CFSocketSetWriteSignalled(s);
616 #if defined(LOG_CFSOCKET)
617 fprintf(stdout, "write signaling source for socket %d\n", s->_socket);
618 #endif
619 if (callBackNow) {
620 __CFSocketDoCallback(s, NULL, NULL, 0);
621 } else {
622 CFRunLoopRef rl;
623 CFRunLoopSourceSignal(s->_source0);
624 rl = __CFSocketCopyRunLoopToWakeUp(s);
625 __CFSocketUnlock(s);
626 if (NULL != rl) {
627 CFRunLoopWakeUp(rl);
628 CFRelease(rl);
629 }
630 }
631 }
632
633 static void __CFSocketHandleRead(CFSocketRef s) {
634 CFDataRef data = NULL, address = NULL;
635 CFSocketNativeHandle sock = INVALID_SOCKET;
636 if (!CFSocketIsValid(s)) return;
637 if (__CFSocketReadCallBackType(s) == kCFSocketDataCallBack) {
638 uint8_t buffer[MAX_DATA_SIZE];
639 uint8_t name[MAX_SOCKADDR_LEN];
640 int namelen = sizeof(name);
641 SInt32 recvlen = recvfrom(s->_socket, buffer, sizeof(buffer), 0, (struct sockaddr *)name, &namelen);
642 #if defined(LOG_CFSOCKET)
643 fprintf(stdout, "read %ld bytes on socket %d\n", recvlen, s->_socket);
644 #endif
645 if (0 >= recvlen) {
646 //??? should return error if <0
647 /* zero-length data is the signal for perform to invalidate */
648 data = CFRetain(zeroLengthData);
649 } else {
650 data = CFDataCreate(CFGetAllocator(s), buffer, recvlen);
651 }
652 __CFSocketLock(s);
653 if (!__CFSocketIsValid(s)) {
654 CFRelease(data);
655 __CFSocketUnlock(s);
656 return;
657 }
658 __CFSocketSetReadSignalled(s);
659 if (NULL != name && 0 < namelen) {
660 //??? possible optimizations: uniquing; storing last value
661 address = CFDataCreate(CFGetAllocator(s), name, namelen);
662 } else if (__CFSocketIsConnectionOriented(s)) {
663 if (NULL == s->_peerAddress) __CFSocketEstablishPeerAddress(s);
664 if (NULL != s->_peerAddress) address = CFRetain(s->_peerAddress);
665 }
666 if (NULL == address) {
667 address = CFRetain(zeroLengthData);
668 }
669 #if !defined(USE_V1_RUN_LOOP_SOURCE)
670 if (NULL == s->_dataQueue) {
671 s->_dataQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
672 }
673 if (NULL == s->_addressQueue) {
674 s->_addressQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
675 }
676 CFArrayAppendValue(s->_dataQueue, data);
677 CFRelease(data);
678 CFArrayAppendValue(s->_addressQueue, address);
679 CFRelease(address);
680 #endif // !USE_V1_RUN_LOOP_SOURCE
681 if (0 < recvlen
682 && (s->_f.client & kCFSocketDataCallBack) != 0 && (s->_f.disabled & kCFSocketDataCallBack) == 0
683 && __CFSocketIsScheduled(s)
684 #if !defined(USE_V1_RUN_LOOP_SOURCE)
685 && (0 == s->_maxQueueLen || CFArrayGetCount(s->_dataQueue) < s->_maxQueueLen)
686 #endif // !USE_V1_RUN_LOOP_SOURCE
687 ) {
688 __CFSpinLock(&__CFActiveSocketsLock);
689 /* restore socket to fds */
690 __CFSocketSetFDForRead(s);
691 __CFSpinUnlock(&__CFActiveSocketsLock);
692 }
693 } else if (__CFSocketReadCallBackType(s) == kCFSocketAcceptCallBack) {
694 uint8_t name[MAX_SOCKADDR_LEN];
695 int namelen = sizeof(name);
696 sock = accept(s->_socket, (struct sockaddr *)name, &namelen);
697 if (INVALID_SOCKET == sock) {
698 //??? should return error
699 return;
700 }
701 if (NULL != name && 0 < namelen) {
702 address = CFDataCreate(CFGetAllocator(s), name, namelen);
703 } else {
704 address = CFRetain(zeroLengthData);
705 }
706 __CFSocketLock(s);
707 if (!__CFSocketIsValid(s)) {
708 closesocket(sock);
709 CFRelease(address);
710 __CFSocketUnlock(s);
711 return;
712 }
713 __CFSocketSetReadSignalled(s);
714 #if !defined(USE_V1_RUN_LOOP_SOURCE)
715 if (NULL == s->_dataQueue) {
716 s->_dataQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, NULL);
717 }
718 if (NULL == s->_addressQueue) {
719 s->_addressQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
720 }
721 CFArrayAppendValue(s->_dataQueue, (void *)sock);
722 CFArrayAppendValue(s->_addressQueue, address);
723 CFRelease(address);
724 #endif // !USE_V1_RUN_LOOP_SOURCE
725 if ((s->_f.client & kCFSocketAcceptCallBack) != 0 && (s->_f.disabled & kCFSocketAcceptCallBack) == 0
726 && __CFSocketIsScheduled(s)
727 #if !defined(USE_V1_RUN_LOOP_SOURCE)
728 && (0 == s->_maxQueueLen || CFArrayGetCount(s->_dataQueue) < s->_maxQueueLen)
729 #endif // !USE_V1_RUN_LOOP_SOURCE
730 ) {
731 __CFSpinLock(&__CFActiveSocketsLock);
732 /* restore socket to fds */
733 __CFSocketSetFDForRead(s);
734 __CFSpinUnlock(&__CFActiveSocketsLock);
735 }
736 } else {
737 __CFSocketLock(s);
738 if (!__CFSocketIsValid(s) || (s->_f.disabled & kCFSocketReadCallBack) != 0) {
739 __CFSocketUnlock(s);
740 return;
741 }
742 __CFSocketSetReadSignalled(s);
743 }
744 #if defined(LOG_CFSOCKET)
745 fprintf(stdout, "read signaling source for socket %d\n", s->_socket);
746 #endif
747 #if defined(USE_V1_RUN_LOOP_SOURCE)
748 // since in the v0 case data and sock come from the same queue, only one could be set
749 CFAssert1(NULL == data || 0 == sock, __kCFLogAssertion, "%s(): both data and sock are set", __PRETTY_FUNCTION__);
750 __CFSocketDoCallback(s, data, address, sock); // does __CFSocketUnlock(s)
751 if (NULL != data) CFRelease(data);
752 if (NULL != address) CFRelease(address);
753 #else
754 CFRunLoopSourceSignal(s->_source0);
755 CFRunLoopRef rl = __CFSocketCopyRunLoopToWakeUp(s);
756 __CFSocketUnlock(s);
757 if (NULL != rl) {
758 CFRunLoopWakeUp(rl);
759 CFRelease(rl);
760 }
761 #endif // !USE_V1_RUN_LOOP_SOURCE
762 }
763
764 #if defined(LOG_CFSOCKET)
765 static void __CFSocketWriteSocketList(CFArrayRef sockets, CFDataRef fdSet, Boolean onlyIfSet) {
766 fd_set *tempfds = (fd_set *)CFDataGetBytePtr(fdSet);
767 SInt32 idx, cnt;
768 for (idx = 0, cnt = CFArrayGetCount(sockets); idx < cnt; idx++) {
769 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(sockets, idx);
770 if (FD_ISSET(s->_socket, tempfds)) {
771 fprintf(stdout, "%d ", s->_socket);
772 } else if (!onlyIfSet) {
773 fprintf(stdout, "(%d) ", s->_socket);
774 }
775 }
776 }
777 #endif
778
779 #ifdef __GNUC__
780 __attribute__ ((noreturn)) // mostly interesting for shutting up a warning
781 #endif
782 static void __CFSocketManager(void * arg)
783 {
784 SInt32 nrfds, maxnrfds, fdentries = 1;
785 SInt32 rfds, wfds;
786 #if defined(__WIN32__)
787 fd_set *exceptfds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(SOCKET) + sizeof(u_int), 0);
788 fd_set *writefds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(SOCKET) + sizeof(u_int), 0);
789 fd_set *readfds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(SOCKET) + sizeof(u_int), 0);
790 #else
791 fd_set *exceptfds = NULL;
792 fd_set *writefds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(fd_mask), 0);
793 fd_set *readfds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(fd_mask), 0);
794 #endif
795 fd_set *tempfds;
796 SInt32 idx, cnt;
797 uint8_t buffer[256];
798 CFMutableArrayRef selectedWriteSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
799 CFMutableArrayRef selectedReadSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
800
801 for (;;) {
802 __CFSpinLock(&__CFActiveSocketsLock);
803 __CFSocketManagerIteration++;
804 #if defined(LOG_CFSOCKET)
805 fprintf(stdout, "socket manager iteration %lu looking at read sockets ", __CFSocketManagerIteration);
806 __CFSocketWriteSocketList(__CFReadSockets, __CFReadSocketsFds, FALSE);
807 if (0 < CFArrayGetCount(__CFWriteSockets)) {
808 fprintf(stdout, " and write sockets ");
809 __CFSocketWriteSocketList(__CFWriteSockets, __CFWriteSocketsFds, FALSE);
810 #if defined(__WIN32__)
811 fprintf(stdout, " and except sockets ");
812 __CFSocketWriteSocketList(__CFWriteSockets, __CFExceptSocketsFds, TRUE);
813 #endif
814 }
815 fprintf(stdout, "\n");
816 #endif
817 rfds = __CFSocketFdGetSize(__CFReadSocketsFds);
818 wfds = __CFSocketFdGetSize(__CFWriteSocketsFds);
819 maxnrfds = __CFMax(rfds, wfds);
820 #if defined(__WIN32__)
821 if (maxnrfds > fdentries) {
822 fdentries = maxnrfds;
823 exceptfds = (fd_set *)CFAllocatorReallocate(kCFAllocatorSystemDefault, exceptfds, fdentries * sizeof(SOCKET) + sizeof(u_int), 0);
824 writefds = (fd_set *)CFAllocatorReallocate(kCFAllocatorSystemDefault, writefds, fdentries * sizeof(SOCKET) + sizeof(u_int), 0);
825 readfds = (fd_set *)CFAllocatorReallocate(kCFAllocatorSystemDefault, readfds, fdentries * sizeof(SOCKET) + sizeof(u_int), 0);
826 }
827 memset(exceptfds, 0, fdentries * sizeof(SOCKET) + sizeof(u_int));
828 memset(writefds, 0, fdentries * sizeof(SOCKET) + sizeof(u_int));
829 memset(readfds, 0, fdentries * sizeof(SOCKET) + sizeof(u_int));
830 CFDataGetBytes(__CFExceptSocketsFds, CFRangeMake(0, __CFSocketFdGetSize(__CFExceptSocketsFds) * sizeof(SOCKET) + sizeof(u_int)), (UInt8 *)exceptfds);
831 CFDataGetBytes(__CFWriteSocketsFds, CFRangeMake(0, wfds * sizeof(SOCKET) + sizeof(u_int)), (UInt8 *)writefds);
832 CFDataGetBytes(__CFReadSocketsFds, CFRangeMake(0, rfds * sizeof(SOCKET) + sizeof(u_int)), (UInt8 *)readfds);
833 #else
834 if (maxnrfds > fdentries * (int)NFDBITS) {
835 fdentries = (maxnrfds + NFDBITS - 1) / NFDBITS;
836 writefds = (fd_set *)CFAllocatorReallocate(kCFAllocatorSystemDefault, writefds, fdentries * sizeof(fd_mask), 0);
837 readfds = (fd_set *)CFAllocatorReallocate(kCFAllocatorSystemDefault, readfds, fdentries * sizeof(fd_mask), 0);
838 }
839 memset(writefds, 0, fdentries * sizeof(fd_mask));
840 memset(readfds, 0, fdentries * sizeof(fd_mask));
841 CFDataGetBytes(__CFWriteSocketsFds, CFRangeMake(0, CFDataGetLength(__CFWriteSocketsFds)), (UInt8 *)writefds);
842 CFDataGetBytes(__CFReadSocketsFds, CFRangeMake(0, CFDataGetLength(__CFReadSocketsFds)), (UInt8 *)readfds);
843 #endif
844 __CFSpinUnlock(&__CFActiveSocketsLock);
845
846 nrfds = select(maxnrfds, readfds, writefds, exceptfds, NULL);
847 #if defined(LOG_CFSOCKET)
848 fprintf(stdout, "socket manager woke from select, ret=%ld\n", nrfds);
849 #endif
850 if (0 == nrfds) continue;
851 if (0 > nrfds) {
852 SInt32 selectError = __CFSocketLastError();
853 #if defined(LOG_CFSOCKET)
854 fprintf(stdout, "socket manager received error %ld from select\n", selectError);
855 #endif
856 if (EBADF == selectError) {
857 CFMutableArrayRef invalidSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
858 __CFSpinLock(&__CFActiveSocketsLock);
859 cnt = CFArrayGetCount(__CFWriteSockets);
860 for (idx = 0; idx < cnt; idx++) {
861 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFWriteSockets, idx);
862 if (!__CFNativeSocketIsValid(s->_socket)) {
863 #if defined(LOG_CFSOCKET)
864 fprintf(stdout, "socket manager found write socket %d invalid\n", s->_socket);
865 #endif
866 CFArrayAppendValue(invalidSockets, s);
867 }
868 }
869 cnt = CFArrayGetCount(__CFReadSockets);
870 for (idx = 0; idx < cnt; idx++) {
871 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx);
872 if (!__CFNativeSocketIsValid(s->_socket)) {
873 #if defined(LOG_CFSOCKET)
874 fprintf(stdout, "socket manager found read socket %d invalid\n", s->_socket);
875 #endif
876 CFArrayAppendValue(invalidSockets, s);
877 }
878 }
879 __CFSpinUnlock(&__CFActiveSocketsLock);
880
881 cnt = CFArrayGetCount(invalidSockets);
882 for (idx = 0; idx < cnt; idx++) {
883 __CFSocketInvalidate(((CFSocketRef)CFArrayGetValueAtIndex(invalidSockets, idx)), false);
884 }
885 CFRelease(invalidSockets);
886 }
887 continue;
888 }
889 if (FD_ISSET(__CFWakeupSocketPair[1], readfds)) {
890 recv(__CFWakeupSocketPair[1], buffer, sizeof(buffer), 0);
891 #if defined(LOG_CFSOCKET)
892 fprintf(stdout, "socket manager received %c on wakeup socket\n", buffer[0]);
893 #endif
894 }
895 __CFSpinLock(&__CFActiveSocketsLock);
896 tempfds = NULL;
897 cnt = CFArrayGetCount(__CFWriteSockets);
898 for (idx = 0; idx < cnt; idx++) {
899 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFWriteSockets, idx);
900 CFSocketNativeHandle sock = s->_socket;
901 #if !defined(__WIN32__)
902 // We might have an new element in __CFWriteSockets that we weren't listening to,
903 // in which case we must be sure not to test a bit in the fdset that is
904 // outside our mask size.
905 Boolean sockInBounds = (0 <= sock && sock < maxnrfds);
906 #else
907 // fdset's are arrays, so we don't have that issue above
908 Boolean sockInBounds = true;
909 #endif
910 if (INVALID_SOCKET != sock && sockInBounds) {
911 if (FD_ISSET(sock, writefds)) {
912 CFArrayAppendValue(selectedWriteSockets, s);
913 /* socket is removed from fds here, restored by CFSocketReschedule */
914 if (!tempfds) tempfds = (fd_set *)CFDataGetMutableBytePtr(__CFWriteSocketsFds);
915 FD_CLR(sock, tempfds);
916 #if defined(__WIN32__)
917 fd_set *exfds = (fd_set *)CFDataGetMutableBytePtr(__CFExceptSocketsFds);
918 FD_CLR(sock, exfds);
919 #endif
920 }
921 #if defined(__WIN32__)
922 else if (FD_ISSET(sock, exceptfds)) {
923 // On Win32 connect errors come in on exceptFDs. We treat these as if
924 // they had come on writeFDs, since the rest of our Unix-based code
925 // expects that.
926 CFArrayAppendValue(selectedWriteSockets, s);
927 fd_set *exfds = (fd_set *)CFDataGetMutableBytePtr(__CFExceptSocketsFds);
928 FD_CLR(sock, exfds);
929 }
930 #endif
931 }
932 }
933 tempfds = NULL;
934 cnt = CFArrayGetCount(__CFReadSockets);
935 for (idx = 0; idx < cnt; idx++) {
936 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx);
937 CFSocketNativeHandle sock = s->_socket;
938 #if !defined(__WIN32__)
939 // We might have an new element in __CFReadSockets that we weren't listening to,
940 // in which case we must be sure not to test a bit in the fdset that is
941 // outside our mask size.
942 Boolean sockInBounds = (0 <= sock && sock < maxnrfds);
943 #else
944 // fdset's are arrays, so we don't have that issue above
945 Boolean sockInBounds = true;
946 #endif
947 if (INVALID_SOCKET != sock && sockInBounds && FD_ISSET(sock, readfds)) {
948 CFArrayAppendValue(selectedReadSockets, s);
949 /* socket is removed from fds here, will be restored in read handling or in perform function */
950 if (!tempfds) tempfds = (fd_set *)CFDataGetMutableBytePtr(__CFReadSocketsFds);
951 FD_CLR(sock, tempfds);
952 }
953 }
954 __CFSpinUnlock(&__CFActiveSocketsLock);
955
956 cnt = CFArrayGetCount(selectedWriteSockets);
957 for (idx = 0; idx < cnt; idx++) {
958 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(selectedWriteSockets, idx);
959 #if defined(LOG_CFSOCKET)
960 fprintf(stdout, "socket manager signaling socket %d for write\n", s->_socket);
961 #endif
962 __CFSocketHandleWrite(s, FALSE);
963 }
964 if (0 < cnt) CFArrayRemoveAllValues(selectedWriteSockets);
965 cnt = CFArrayGetCount(selectedReadSockets);
966 for (idx = 0; idx < cnt; idx++) {
967 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(selectedReadSockets, idx);
968 #if defined(LOG_CFSOCKET)
969 fprintf(stdout, "socket manager signaling socket %d for read\n", s->_socket);
970 #endif
971 __CFSocketHandleRead(s);
972 }
973 if (0 < cnt) CFArrayRemoveAllValues(selectedReadSockets);
974 }
975 }
976
977 static CFStringRef __CFSocketCopyDescription(CFTypeRef cf) {
978 CFSocketRef s = (CFSocketRef)cf;
979 CFMutableStringRef result;
980 CFStringRef contextDesc = NULL;
981 void *contextInfo = NULL;
982 CFStringRef (*contextCopyDescription)(const void *info) = NULL;
983 result = CFStringCreateMutable(CFGetAllocator(s), 0);
984 __CFSocketLock(s);
985 CFStringAppendFormat(result, NULL, CFSTR("<CFSocket %p [%p]>{valid = %s, type = %d, socket = %d, socket set count = %ld\n callback types = 0x%x, callout = %x, source = %p,\n run loops = %@,\n context = "), cf, CFGetAllocator(s), (__CFSocketIsValid(s) ? "Yes" : "No"), s->_socketType, s->_socket, s->_socketSetCount, __CFSocketCallBackTypes(s), s->_callout, s->_source0, s->_runLoops);
986 contextInfo = s->_context.info;
987 contextCopyDescription = s->_context.copyDescription;
988 __CFSocketUnlock(s);
989 if (NULL != contextInfo && NULL != contextCopyDescription) {
990 contextDesc = (CFStringRef)contextCopyDescription(contextInfo);
991 }
992 if (NULL == contextDesc) {
993 contextDesc = CFStringCreateWithFormat(CFGetAllocator(s), NULL, CFSTR("<CFSocket context %p>"), contextInfo);
994 }
995 CFStringAppend(result, contextDesc);
996 CFRelease(contextDesc);
997 return result;
998 }
999
1000 static void __CFSocketDeallocate(CFTypeRef cf) {
1001 /* Since CFSockets are cached, we can only get here sometime after being invalidated */
1002 CFSocketRef s = (CFSocketRef)cf;
1003 if (NULL != s->_address) {
1004 CFRelease(s->_address);
1005 s->_address = NULL;
1006 }
1007 }
1008
1009 static const CFRuntimeClass __CFSocketClass = {
1010 0,
1011 "CFSocket",
1012 NULL, // init
1013 NULL, // copy
1014 __CFSocketDeallocate,
1015 NULL, // equal
1016 NULL, // hash
1017 NULL, //
1018 __CFSocketCopyDescription
1019 };
1020
1021 __private_extern__ void __CFSocketInitialize(void) {
1022 __kCFSocketTypeID = _CFRuntimeRegisterClass(&__CFSocketClass);
1023 }
1024
1025 CFTypeID CFSocketGetTypeID(void) {
1026 return __kCFSocketTypeID;
1027 }
1028
1029 CFSocketError CFSocketSetAddress(CFSocketRef s, CFDataRef address) {
1030 const uint8_t *name;
1031 SInt32 namelen, result = 0;
1032 __CFGenericValidateType(s, __kCFSocketTypeID);
1033 if (NULL == address) return -1;
1034 name = CFDataGetBytePtr(address);
1035 namelen = CFDataGetLength(address);
1036 __CFSocketLock(s);
1037 if (__CFSocketIsValid(s) && INVALID_SOCKET != s->_socket && NULL != name && 0 < namelen) {
1038 result = bind(s->_socket, (struct sockaddr *)name, namelen);
1039 if (0 == result) {
1040 __CFSocketEstablishAddress(s);
1041 listen(s->_socket, 256);
1042 }
1043 }
1044 if (NULL == s->_address && NULL != name && 0 < namelen && 0 == result) {
1045 s->_address = CFDataCreateCopy(CFGetAllocator(s), address);
1046 }
1047 __CFSocketUnlock(s);
1048 //??? should return errno
1049 return result;
1050 }
1051
1052 __private_extern__ void CFSocketSetAcceptBacklog(CFSocketRef s, CFIndex limit) {
1053 __CFGenericValidateType(s, __kCFSocketTypeID);
1054 __CFSocketLock(s);
1055 if (__CFSocketIsValid(s) && INVALID_SOCKET != s->_socket) {
1056 listen(s->_socket, limit);
1057 }
1058 __CFSocketUnlock(s);
1059 }
1060
1061 __private_extern__ void CFSocketSetMaximumQueueLength(CFSocketRef s, CFIndex length) {
1062 __CFGenericValidateType(s, __kCFSocketTypeID);
1063 #if !defined(USE_V1_RUN_LOOP_SOURCE)
1064 __CFSocketLock(s);
1065 if (__CFSocketIsValid(s)) {
1066 s->_maxQueueLen = length;
1067 }
1068 __CFSocketUnlock(s);
1069 #endif
1070 }
1071
1072 CFSocketError CFSocketConnectToAddress(CFSocketRef s, CFDataRef address, CFTimeInterval timeout) {
1073 //??? need error handling, retries
1074 const uint8_t *name;
1075 SInt32 namelen, result = -1, connect_err = 0, select_err = 0;
1076 UInt32 yes = 1, no = 0;
1077 Boolean wasBlocking = true;
1078
1079 __CFGenericValidateType(s, __kCFSocketTypeID);
1080 name = CFDataGetBytePtr(address);
1081 namelen = CFDataGetLength(address);
1082 __CFSocketLock(s);
1083 if (__CFSocketIsValid(s) && INVALID_SOCKET != s->_socket && NULL != name && 0 < namelen) {
1084 #if !defined(__WIN32__)
1085 SInt32 flags = fcntl(s->_socket, F_GETFL, 0);
1086 if (flags >= 0) wasBlocking = ((flags & O_NONBLOCK) == 0);
1087 if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(s->_socket, FIONBIO, &yes);
1088 #else
1089 // You can set but not get this flag in WIN32, so assume it was in non-blocking mode.
1090 // The downside is that when we leave this routine we'll leave it non-blocking,
1091 // whether it started that way or not.
1092 if (timeout > 0.0 || timeout < 0.0) ioctlsocket(s->_socket, FIONBIO, &yes);
1093 wasBlocking = false;
1094 #endif
1095 result = connect(s->_socket, (struct sockaddr *)name, namelen);
1096 if (result != 0) {
1097 connect_err = __CFSocketLastError();
1098 #if defined(__WIN32__)
1099 if (connect_err == WSAEWOULDBLOCK) connect_err = EINPROGRESS;
1100 #endif
1101 }
1102 #if defined(LOG_CFSOCKET)
1103 #if !defined(__WIN32__)
1104 fprintf(stdout, "connection attempt returns %ld error %ld on socket %d (flags 0x%lx blocking %d)\n", result, connect_err, s->_socket, flags, wasBlocking);
1105 #else
1106 fprintf(stdout, "connection attempt returns %ld error %ld on socket %d\n", result, connect_err, s->_socket);
1107 #endif
1108 #endif
1109 if (EINPROGRESS == connect_err && timeout >= 0.0) {
1110 /* select on socket */
1111 SInt32 nrfds;
1112 int error_size = sizeof(select_err);
1113 struct timeval tv;
1114 CFMutableDataRef fds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
1115 #if defined(__WIN32__)
1116 CFDataIncreaseLength(fds , sizeof(u_int) + sizeof(SOCKET));
1117 #endif
1118 __CFSocketFdSet(s->_socket, fds);
1119 tv.tv_sec = (0 >= timeout || INT_MAX <= timeout) ? INT_MAX : (int)(float)floor(timeout);
1120 tv.tv_usec = (int)((timeout - floor(timeout)) * 1.0E6);
1121 nrfds = select(__CFSocketFdGetSize(fds), NULL, (fd_set *)CFDataGetMutableBytePtr(fds), NULL, &tv);
1122 if (nrfds < 0) {
1123 select_err = __CFSocketLastError();
1124 result = -1;
1125 } else if (nrfds == 0) {
1126 result = -2;
1127 } else {
1128 if (0 != getsockopt(s->_socket, SOL_SOCKET, SO_ERROR, (void *)&select_err, &error_size)) select_err = 0;
1129 result = (select_err == 0) ? 0 : -1;
1130 }
1131 CFRelease(fds);
1132 #if defined(LOG_CFSOCKET)
1133 fprintf(stdout, "timed connection attempt %s on socket %d, result %ld, select returns %ld error %ld\n", (result == 0) ? "succeeds" : "fails", s->_socket, result, nrfds, select_err);
1134 #endif
1135 }
1136 if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(s->_socket, FIONBIO, &no);
1137 if (0 == result) {
1138 __CFSocketEstablishPeerAddress(s);
1139 if (NULL == s->_peerAddress && NULL != name && 0 < namelen && __CFSocketIsConnectionOriented(s)) {
1140 s->_peerAddress = CFDataCreateCopy(CFGetAllocator(s), address);
1141 }
1142 }
1143 if (EINPROGRESS == connect_err && timeout < 0.0) {
1144 result = 0;
1145 #if defined(LOG_CFSOCKET)
1146 fprintf(stdout, "connection attempt continues in background on socket %d\n", s->_socket);
1147 #endif
1148 }
1149 }
1150 __CFSocketUnlock(s);
1151 //??? should return errno
1152 return result;
1153 }
1154
1155 CFSocketRef CFSocketCreate(CFAllocatorRef allocator, SInt32 protocolFamily, SInt32 socketType, SInt32 protocol, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
1156 CFSocketNativeHandle sock = INVALID_SOCKET;
1157 CFSocketRef s = NULL;
1158 if (0 >= protocolFamily) protocolFamily = PF_INET;
1159 if (PF_INET == protocolFamily) {
1160 if (0 >= socketType) socketType = SOCK_STREAM;
1161 if (0 >= protocol && SOCK_STREAM == socketType) protocol = IPPROTO_TCP;
1162 if (0 >= protocol && SOCK_DGRAM == socketType) protocol = IPPROTO_UDP;
1163 }
1164 #if !defined(__WIN32__)
1165 if (PF_LOCAL == protocolFamily && 0 >= socketType) socketType = SOCK_STREAM;
1166 #else
1167 /* WinSock needs to be initialized at this point for Windows, before socket() */
1168 __CFSocketInitializeWinSock();
1169 #endif
1170 sock = socket(protocolFamily, socketType, protocol);
1171 if (INVALID_SOCKET != sock) {
1172 s = CFSocketCreateWithNative(allocator, sock, callBackTypes, callout, context);
1173 }
1174 return s;
1175 }
1176
1177 CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHandle sock, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
1178 CFSocketRef memory;
1179 int typeSize = sizeof(memory->_socketType);
1180 __CFSpinLock(&__CFActiveSocketsLock);
1181 if (NULL == __CFReadSockets) __CFSocketInitializeSockets();
1182 __CFSpinUnlock(&__CFActiveSocketsLock);
1183 __CFSpinLock(&__CFAllSocketsLock);
1184 if (NULL == __CFAllSockets) {
1185 __CFAllSockets = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
1186 }
1187 if (INVALID_SOCKET != sock && CFDictionaryGetValueIfPresent(__CFAllSockets, (void *)sock, (const void **)&memory)) {
1188 __CFSpinUnlock(&__CFAllSocketsLock);
1189 CFRetain(memory);
1190 return memory;
1191 }
1192 memory = (CFSocketRef)_CFRuntimeCreateInstance(allocator, __kCFSocketTypeID, sizeof(struct __CFSocket) - sizeof(CFRuntimeBase), NULL);
1193 if (NULL == memory) {
1194 __CFSpinUnlock(&__CFAllSocketsLock);
1195 return NULL;
1196 }
1197 __CFSocketSetCallBackTypes(memory, callBackTypes);
1198 if (INVALID_SOCKET != sock) __CFSocketSetValid(memory);
1199 __CFSocketUnsetWriteSignalled(memory);
1200 __CFSocketUnsetReadSignalled(memory);
1201 memory->_f.client = ((callBackTypes & (~kCFSocketConnectCallBack)) & (~kCFSocketWriteCallBack)) | kCFSocketCloseOnInvalidate;
1202 memory->_f.disabled = 0;
1203 memory->_f.connected = FALSE;
1204 memory->_f.writableHint = FALSE;
1205 memory->_f.closeSignaled = FALSE;
1206 memory->_lock = 0;
1207 memory->_writeLock = 0;
1208 memory->_socket = sock;
1209 if (INVALID_SOCKET == sock || 0 != getsockopt(sock, SOL_SOCKET, SO_TYPE, (void *)&(memory->_socketType), &typeSize)) memory->_socketType = 0; // cast for WinSock bad API
1210 memory->_errorCode = 0;
1211 memory->_address = NULL;
1212 memory->_peerAddress = NULL;
1213 memory->_socketSetCount = 0;
1214 memory->_source0 = NULL;
1215 if (INVALID_SOCKET != sock) {
1216 memory->_runLoops = CFArrayCreateMutable(allocator, 0, NULL);
1217 } else {
1218 memory->_runLoops = NULL;
1219 }
1220 memory->_callout = callout;
1221 #if defined(USE_V1_RUN_LOOP_SOURCE)
1222 memory->_event = CreateEvent(NULL, true, false, NULL);
1223 CFAssert1(NULL != memory->_event, __kCFLogAssertion, "%s(): could not create event", __PRETTY_FUNCTION__);
1224 memory->_oldEventMask = 0;
1225 __CFSocketSetWholeEventMask(memory, FD_CLOSE|FD_CONNECT); // always listen for closes, connects
1226 memory->_source1 = NULL;
1227 #else // !USE_V1_RUN_LOOP_SOURCE
1228 memory->_dataQueue = NULL;
1229 memory->_addressQueue = NULL;
1230 memory->_maxQueueLen = 0;
1231 #endif // !USE_V1_RUN_LOOP_SOURCE
1232 memory->_context.info = 0;
1233 memory->_context.retain = 0;
1234 memory->_context.release = 0;
1235 memory->_context.copyDescription = 0;
1236 if (INVALID_SOCKET != sock) CFDictionaryAddValue(__CFAllSockets, (void *)sock, memory);
1237 __CFSpinUnlock(&__CFAllSocketsLock);
1238 if (NULL != context) {
1239 void *contextInfo = context->retain ? (void *)context->retain(context->info) : context->info;
1240 __CFSocketLock(memory);
1241 memory->_context.retain = context->retain;
1242 memory->_context.release = context->release;
1243 memory->_context.copyDescription = context->copyDescription;
1244 memory->_context.info = contextInfo;
1245 __CFSocketUnlock(memory);
1246 }
1247 return memory;
1248 }
1249
1250 CFSocketRef CFSocketCreateWithSocketSignature(CFAllocatorRef allocator, const CFSocketSignature *signature, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
1251 CFSocketRef s = CFSocketCreate(allocator, signature->protocolFamily, signature->socketType, signature->protocol, callBackTypes, callout, context);
1252 if (NULL != s && (!CFSocketIsValid(s) || kCFSocketSuccess != CFSocketSetAddress(s, signature->address))) {
1253 CFSocketInvalidate(s);
1254 CFRelease(s);
1255 s = NULL;
1256 }
1257 return s;
1258 }
1259
1260 CFSocketRef CFSocketCreateConnectedToSocketSignature(CFAllocatorRef allocator, const CFSocketSignature *signature, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context, CFTimeInterval timeout) {
1261 CFSocketRef s = CFSocketCreate(allocator, signature->protocolFamily, signature->socketType, signature->protocol, callBackTypes, callout, context);
1262 if (NULL != s && (!CFSocketIsValid(s) || kCFSocketSuccess != CFSocketConnectToAddress(s, signature->address, timeout))) {
1263 CFSocketInvalidate(s);
1264 CFRelease(s);
1265 s = NULL;
1266 }
1267 return s;
1268 }
1269
1270 static void __CFSocketInvalidate(CFSocketRef s, Boolean wakeup) {
1271 UInt32 previousSocketManagerIteration;
1272 __CFGenericValidateType(s, __kCFSocketTypeID);
1273 #if defined(LOG_CFSOCKET)
1274 fprintf(stdout, "invalidating socket %d with flags 0x%x disabled 0x%x connected 0x%x wakeup %d\n", s->_socket, s->_f.client, s->_f.disabled, s->_f.connected, wakeup);
1275 #endif
1276 CFRetain(s);
1277 __CFSpinLock(&__CFAllSocketsLock);
1278 __CFSocketLock(s);
1279 if (__CFSocketIsValid(s)) {
1280 SInt32 idx;
1281 CFRunLoopSourceRef source0;
1282 void *contextInfo = NULL;
1283 void (*contextRelease)(const void *info) = NULL;
1284 __CFSocketUnsetValid(s);
1285 __CFSocketUnsetWriteSignalled(s);
1286 __CFSocketUnsetReadSignalled(s);
1287 __CFSpinLock(&__CFActiveSocketsLock);
1288 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
1289 if (0 <= idx) {
1290 CFArrayRemoveValueAtIndex(__CFWriteSockets, idx);
1291 __CFSocketClearFDForWrite(s);
1292 #if defined(__WIN32__)
1293 __CFSocketFdClr(s->_socket, __CFExceptSocketsFds);
1294 #endif
1295 }
1296 #if !defined(USE_V1_RUN_LOOP_SOURCE)
1297 // No need to clear FD's for V1 sources, since we'll just throw the whole event away
1298 idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
1299 if (0 <= idx) {
1300 CFArrayRemoveValueAtIndex(__CFReadSockets, idx);
1301 __CFSocketClearFDForRead(s);
1302 }
1303 #endif // !USE_V1_RUN_LOOP_SOURCE
1304 previousSocketManagerIteration = __CFSocketManagerIteration;
1305 __CFSpinUnlock(&__CFActiveSocketsLock);
1306 #if 0
1307 if (wakeup && __CFSocketManagerThread) {
1308 Boolean doneWaiting = false;
1309 uint8_t c = 'i';
1310 #if defined(LOG_CFSOCKET)
1311 fprintf(stdout, "invalidation wants socket iteration to change from %lu\n", previousSocketManagerIteration);
1312 #endif
1313 send(__CFWakeupSocketPair[0], &c, sizeof(c), 0);
1314 #if !defined(__WIN32__)
1315 while (!doneWaiting) {
1316 __CFSpinLock(&__CFActiveSocketsLock);
1317 if (previousSocketManagerIteration != __CFSocketManagerIteration) doneWaiting = true;
1318 #if defined(LOG_CFSOCKET)
1319 fprintf(stdout, "invalidation comparing socket iteration %lu to previous %lu\n", __CFSocketManagerIteration, previousSocketManagerIteration);
1320 #endif
1321 __CFSpinUnlock(&__CFActiveSocketsLock);
1322 if (!doneWaiting) {
1323 struct timespec ts = {0, 1};
1324 // ??? depress priority
1325 nanosleep(&ts, NULL);
1326 }
1327 }
1328 #endif
1329 }
1330 #endif
1331 CFDictionaryRemoveValue(__CFAllSockets, (void *)(s->_socket));
1332 if ((s->_f.client & kCFSocketCloseOnInvalidate) != 0) closesocket(s->_socket);
1333 s->_socket = INVALID_SOCKET;
1334 if (NULL != s->_peerAddress) {
1335 CFRelease(s->_peerAddress);
1336 s->_peerAddress = NULL;
1337 }
1338 #if !defined(USE_V1_RUN_LOOP_SOURCE)
1339 if (NULL != s->_dataQueue) {
1340 CFRelease(s->_dataQueue);
1341 s->_dataQueue = NULL;
1342 }
1343 if (NULL != s->_addressQueue) {
1344 CFRelease(s->_addressQueue);
1345 s->_addressQueue = NULL;
1346 }
1347 s->_socketSetCount = 0;
1348 #endif // !USE_V1_RUN_LOOP_SOURCE
1349 for (idx = CFArrayGetCount(s->_runLoops); idx--;) {
1350 CFRunLoopWakeUp((CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, idx));
1351 }
1352 CFRelease(s->_runLoops);
1353 s->_runLoops = NULL;
1354 source0 = s->_source0;
1355 s->_source0 = NULL;
1356 contextInfo = s->_context.info;
1357 contextRelease = s->_context.release;
1358 s->_context.info = 0;
1359 s->_context.retain = 0;
1360 s->_context.release = 0;
1361 s->_context.copyDescription = 0;
1362 __CFSocketUnlock(s);
1363 if (NULL != contextRelease) {
1364 contextRelease(contextInfo);
1365 }
1366 if (NULL != source0) {
1367 CFRunLoopSourceInvalidate(source0);
1368 CFRelease(source0);
1369 }
1370 #if defined(USE_V1_RUN_LOOP_SOURCE)
1371 // Important to do the v1 source after the v0 source, since cancelling the v0 source
1372 // references the v1 source (since the v1 source is added/removed from RunLoops as a
1373 // side-effect of the v0 source being added/removed).
1374 if (NULL != s->_source1) {
1375 CFRunLoopSourceInvalidate(s->_source1);
1376 CFRelease(s->_source1);
1377 s->_source1 = NULL;
1378 }
1379 CloseHandle(s->_event);
1380 #endif
1381 } else {
1382 __CFSocketUnlock(s);
1383 }
1384 __CFSpinUnlock(&__CFAllSocketsLock);
1385 CFRelease(s);
1386 }
1387
1388 void CFSocketInvalidate(CFSocketRef s) {__CFSocketInvalidate(s, true);}
1389
1390 Boolean CFSocketIsValid(CFSocketRef s) {
1391 __CFGenericValidateType(s, __kCFSocketTypeID);
1392 return __CFSocketIsValid(s);
1393 }
1394
1395 CFSocketNativeHandle CFSocketGetNative(CFSocketRef s) {
1396 __CFGenericValidateType(s, __kCFSocketTypeID);
1397 return s->_socket;
1398 }
1399
1400 CFDataRef CFSocketCopyAddress(CFSocketRef s) {
1401 CFDataRef result = NULL;
1402 __CFGenericValidateType(s, __kCFSocketTypeID);
1403 __CFSocketLock(s);
1404 __CFSocketEstablishAddress(s);
1405 if (NULL != s->_address) {
1406 result = CFRetain(s->_address);
1407 }
1408 __CFSocketUnlock(s);
1409 return result;
1410 }
1411
1412 CFDataRef CFSocketCopyPeerAddress(CFSocketRef s) {
1413 CFDataRef result = NULL;
1414 __CFGenericValidateType(s, __kCFSocketTypeID);
1415 __CFSocketLock(s);
1416 __CFSocketEstablishPeerAddress(s);
1417 if (NULL != s->_peerAddress) {
1418 result = CFRetain(s->_peerAddress);
1419 }
1420 __CFSocketUnlock(s);
1421 return result;
1422 }
1423
1424 void CFSocketGetContext(CFSocketRef s, CFSocketContext *context) {
1425 __CFGenericValidateType(s, __kCFSocketTypeID);
1426 CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__);
1427 *context = s->_context;
1428 }
1429
1430 __private_extern__ void CFSocketReschedule(CFSocketRef s) {
1431 CFSocketEnableCallBacks(s, __CFSocketCallBackTypes(s));
1432 }
1433
1434 CFOptionFlags CFSocketGetSocketFlags(CFSocketRef s) {
1435 __CFGenericValidateType(s, __kCFSocketTypeID);
1436 return s->_f.client;
1437 }
1438
1439 void CFSocketSetSocketFlags(CFSocketRef s, CFOptionFlags flags) {
1440 __CFGenericValidateType(s, __kCFSocketTypeID);
1441 __CFSocketLock(s);
1442 #if defined(LOG_CFSOCKET)
1443 fprintf(stdout, "setting flags for socket %d, from 0x%x to 0x%lx\n", s->_socket, s->_f.client, flags);
1444 #endif
1445 s->_f.client = flags;
1446 __CFSocketUnlock(s);
1447 }
1448
1449 void CFSocketDisableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) {
1450 Boolean wakeup = false;
1451 uint8_t readCallBackType;
1452 __CFGenericValidateType(s, __kCFSocketTypeID);
1453 __CFSocketLock(s);
1454 if (__CFSocketIsValid(s) && __CFSocketIsScheduled(s)) {
1455 callBackTypes &= __CFSocketCallBackTypes(s);
1456 readCallBackType = __CFSocketReadCallBackType(s);
1457 s->_f.disabled |= callBackTypes;
1458 #if defined(LOG_CFSOCKET)
1459 fprintf(stdout, "unscheduling socket %d with flags 0x%x disabled 0x%x connected 0x%x for types 0x%lx\n", s->_socket, s->_f.client, s->_f.disabled, s->_f.connected, callBackTypes);
1460 #endif
1461 __CFSpinLock(&__CFActiveSocketsLock);
1462 if ((readCallBackType == kCFSocketAcceptCallBack) || !__CFSocketIsConnectionOriented(s)) s->_f.connected = TRUE;
1463 if (((callBackTypes & kCFSocketWriteCallBack) != 0) || (((callBackTypes & kCFSocketConnectCallBack) != 0) && !s->_f.connected)) {
1464 if (__CFSocketClearFDForWrite(s)) {
1465 // do not wake up the socket manager thread if all relevant write callbacks are disabled
1466 CFOptionFlags writeCallBacksAvailable = __CFSocketCallBackTypes(s) & (kCFSocketWriteCallBack | kCFSocketConnectCallBack);
1467 if (s->_f.connected) writeCallBacksAvailable &= ~kCFSocketConnectCallBack;
1468 if ((s->_f.disabled & writeCallBacksAvailable) != writeCallBacksAvailable) wakeup = true;
1469 #if defined(__WIN32__)
1470 __CFSocketFdClr(s->_socket, __CFExceptSocketsFds);
1471 #endif
1472 }
1473 }
1474 if (readCallBackType != kCFSocketNoCallBack && (callBackTypes & readCallBackType) != 0) {
1475 if (__CFSocketClearFDForRead(s)) {
1476 #if !defined(USE_V1_RUN_LOOP_SOURCE)
1477 // do not wake up the socket manager thread if callback type is read
1478 if (readCallBackType != kCFSocketReadCallBack) wakeup = true;
1479 #endif
1480 }
1481 }
1482 __CFSpinUnlock(&__CFActiveSocketsLock);
1483 }
1484 __CFSocketUnlock(s);
1485 if (wakeup && __CFSocketManagerThread) {
1486 uint8_t c = 'u';
1487 send(__CFWakeupSocketPair[0], &c, sizeof(c), 0);
1488 }
1489 }
1490
1491 // "force" means to clear the disabled bits set by DisableCallBacks and always reenable.
1492 // if (!force) we respect those bits, meaning they may stop us from enabling.
1493 // In addition, if !force we assume that the sockets have already been added to the
1494 // __CFReadSockets and __CFWriteSockets arrays. This is true because the callbacks start
1495 // enabled when the CFSocket is created (at which time we enable with force).
1496 // Called with SocketLock held, returns with it released!
1497 void __CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes, Boolean force, uint8_t wakeupChar) {
1498 Boolean wakeup = FALSE;
1499 if (!callBackTypes) {
1500 __CFSocketUnlock(s);
1501 return;
1502 }
1503 if (__CFSocketIsValid(s) && __CFSocketIsScheduled(s)) {
1504 Boolean turnOnWrite = FALSE, turnOnConnect = FALSE, turnOnRead = FALSE;
1505 uint8_t readCallBackType = __CFSocketReadCallBackType(s);
1506 callBackTypes &= __CFSocketCallBackTypes(s);
1507 if (force) s->_f.disabled &= ~callBackTypes;
1508 #if defined(LOG_CFSOCKET)
1509 fprintf(stdout, "rescheduling socket %d with flags 0x%x disabled 0x%x connected 0x%x for types 0x%lx\n", s->_socket, s->_f.client, s->_f.disabled, s->_f.connected, callBackTypes);
1510 #endif
1511 /* We will wait for connection only for connection-oriented, non-rendezvous sockets that are not already connected. Mark others as already connected. */
1512 if ((readCallBackType == kCFSocketAcceptCallBack) || !__CFSocketIsConnectionOriented(s)) s->_f.connected = TRUE;
1513
1514 // First figure out what to turn on
1515 if (s->_f.connected || (callBackTypes & kCFSocketConnectCallBack) == 0) {
1516 // if we want write callbacks and they're not disabled...
1517 if ((callBackTypes & kCFSocketWriteCallBack) != 0 && (s->_f.disabled & kCFSocketWriteCallBack) == 0) turnOnWrite = TRUE;
1518 } else {
1519 // if we want connect callbacks and they're not disabled...
1520 if ((callBackTypes & kCFSocketConnectCallBack) != 0 && (s->_f.disabled & kCFSocketConnectCallBack) == 0) turnOnConnect = TRUE;
1521 }
1522 // if we want read callbacks and they're not disabled...
1523 if (readCallBackType != kCFSocketNoCallBack && (callBackTypes & readCallBackType) != 0 && (s->_f.disabled & kCFSocketReadCallBack) == 0) turnOnRead = TRUE;
1524
1525 // Now turn on the callbacks we've determined that we want on
1526 if (turnOnRead || turnOnWrite || turnOnConnect) {
1527 __CFSpinLock(&__CFActiveSocketsLock);
1528 #if defined(USE_V1_RUN_LOOP_SOURCE)
1529 if (turnOnWrite) {
1530 if (force) {
1531 SInt32 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
1532 if (kCFNotFound == idx) CFArrayAppendValue(__CFWriteSockets, s);
1533 }
1534 // If we can tell the socket is writable, just reschedule the v1 source. Else we need
1535 // a real notification from the OS, so enable the SocketManager's listening.
1536 if (__CFSocketCanAcceptBytes(s)) {
1537 SetEvent(s->_event);
1538 s->_f.writableHint = TRUE;
1539 } else {
1540 if (__CFSocketSetFDForWrite(s)) wakeup = true;
1541 }
1542 }
1543 if (turnOnConnect) __CFSocketSetWholeEventMask(s, s->_oldEventMask | FD_CONNECT);
1544 if (turnOnRead) __CFSocketSetFDForRead(s);
1545 #else // !USE_V1_RUN_LOOP_SOURCE
1546 if (turnOnWrite || turnOnConnect) {
1547 if (force) {
1548 SInt32 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
1549 if (kCFNotFound == idx) CFArrayAppendValue(__CFWriteSockets, s);
1550 }
1551 if (__CFSocketSetFDForWrite(s)) wakeup = true;
1552 #if defined(__WIN32__)
1553 if ((callBackTypes & kCFSocketConnectCallBack) != 0 && !s->_f.connected) __CFSocketFdSet(s->_socket, __CFExceptSocketsFds);
1554 #endif
1555 }
1556 if (turnOnRead) {
1557 if (force) {
1558 SInt32 idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
1559 if (kCFNotFound == idx) CFArrayAppendValue(__CFReadSockets, s);
1560 }
1561 if (__CFSocketSetFDForRead(s)) wakeup = true;
1562 }
1563 #endif
1564 if (wakeup && NULL == __CFSocketManagerThread) __CFSocketManagerThread = __CFStartSimpleThread(__CFSocketManager, 0);
1565 __CFSpinUnlock(&__CFActiveSocketsLock);
1566 }
1567 }
1568 __CFSocketUnlock(s);
1569 if (wakeup) send(__CFWakeupSocketPair[0], &wakeupChar, sizeof(wakeupChar), 0);
1570 }
1571
1572 void CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) {
1573 __CFGenericValidateType(s, __kCFSocketTypeID);
1574 __CFSocketLock(s);
1575 __CFSocketEnableCallBacks(s, callBackTypes, TRUE, 'r');
1576 }
1577
1578 static void __CFSocketSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) {
1579 CFSocketRef s = info;
1580 __CFSocketLock(s);
1581 //??? also need to arrange delivery of all pending data
1582 if (__CFSocketIsValid(s)) {
1583 CFArrayAppendValue(s->_runLoops, rl);
1584 s->_socketSetCount++;
1585 // Since the v0 source is listened to on the SocketMgr thread, no matter how many modes it
1586 // is added to we just need to enable it there once (and _socketSetCount gives us a refCount
1587 // to know when we can finally disable it).
1588 if (1 == s->_socketSetCount) {
1589 #if defined(LOG_CFSOCKET)
1590 fprintf(stdout, "scheduling socket %d\n", s->_socket);
1591 #endif
1592 __CFSocketEnableCallBacks(s, __CFSocketCallBackTypes(s), TRUE, 's'); // unlocks s
1593 } else
1594 __CFSocketUnlock(s);
1595 #if defined(USE_V1_RUN_LOOP_SOURCE)
1596 // Since the v1 source is listened to in rl on this thread, we need to add it to all modes
1597 // the v0 source is added to.
1598 CFRunLoopAddSource(rl, s->_source1, mode);
1599 CFRunLoopWakeUp(rl);
1600 #endif
1601 } else
1602 __CFSocketUnlock(s);
1603 }
1604
1605 static void __CFSocketCancel(void *info, CFRunLoopRef rl, CFStringRef mode) {
1606 CFSocketRef s = info;
1607 SInt32 idx;
1608 __CFSocketLock(s);
1609 s->_socketSetCount--;
1610 if (0 == s->_socketSetCount) {
1611 __CFSpinLock(&__CFActiveSocketsLock);
1612 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
1613 if (0 <= idx) {
1614 CFArrayRemoveValueAtIndex(__CFWriteSockets, idx);
1615 __CFSocketClearFDForWrite(s);
1616 #if defined(__WIN32__)
1617 __CFSocketFdClr(s->_socket, __CFExceptSocketsFds);
1618 #endif
1619 }
1620 #if !defined(USE_V1_RUN_LOOP_SOURCE)
1621 idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
1622 if (0 <= idx) {
1623 CFArrayRemoveValueAtIndex(__CFReadSockets, idx);
1624 __CFSocketClearFDForRead(s);
1625 }
1626 #endif
1627 __CFSpinUnlock(&__CFActiveSocketsLock);
1628 }
1629 #if defined(USE_V1_RUN_LOOP_SOURCE)
1630 CFRunLoopRemoveSource(rl, s->_source1, mode);
1631 CFRunLoopWakeUp(rl);
1632 if (0 == s->_socketSetCount && s->_socket != INVALID_SOCKET) {
1633 __CFSocketSetWholeEventMask(s, FD_CLOSE|FD_CONNECT);
1634 }
1635 #endif
1636 if (NULL != s->_runLoops) {
1637 idx = CFArrayGetFirstIndexOfValue(s->_runLoops, CFRangeMake(0, CFArrayGetCount(s->_runLoops)), rl);
1638 if (0 <= idx) CFArrayRemoveValueAtIndex(s->_runLoops, idx);
1639 }
1640 __CFSocketUnlock(s);
1641 }
1642
1643 // Note: must be called with socket lock held, then returns with it released
1644 // Used by both the v0 and v1 RunLoopSource perform routines
1645 static void __CFSocketDoCallback(CFSocketRef s, CFDataRef data, CFDataRef address, CFSocketNativeHandle sock) {
1646 CFSocketCallBack callout = NULL;
1647 void *contextInfo = NULL;
1648 SInt32 errorCode = 0;
1649 Boolean readSignalled = false, writeSignalled = false, connectSignalled = false, calledOut = false;
1650 uint8_t readCallBackType, callBackTypes;
1651
1652 callBackTypes = __CFSocketCallBackTypes(s);
1653 readCallBackType = __CFSocketReadCallBackType(s);
1654 readSignalled = __CFSocketIsReadSignalled(s);
1655 writeSignalled = __CFSocketIsWriteSignalled(s);
1656 connectSignalled = writeSignalled && !s->_f.connected;
1657 __CFSocketUnsetReadSignalled(s);
1658 __CFSocketUnsetWriteSignalled(s);
1659 callout = s->_callout;
1660 contextInfo = s->_context.info;
1661 #if defined(LOG_CFSOCKET)
1662 fprintf(stdout, "entering perform for socket %d with read signalled %d write signalled %d connect signalled %d callback types %d\n", s->_socket, readSignalled, writeSignalled, connectSignalled, callBackTypes);
1663 #endif
1664 if (writeSignalled) {
1665 errorCode = s->_errorCode;
1666 s->_f.connected = TRUE;
1667 }
1668 __CFSocketUnlock(s);
1669 if ((callBackTypes & kCFSocketConnectCallBack) != 0) {
1670 if (connectSignalled && (!calledOut || CFSocketIsValid(s))) {
1671 if (errorCode) {
1672 #if defined(LOG_CFSOCKET)
1673 fprintf(stdout, "perform calling out error %ld to socket %d\n", errorCode, s->_socket);
1674 #endif
1675 if (callout) callout(s, kCFSocketConnectCallBack, NULL, &errorCode, contextInfo);
1676 calledOut = true;
1677 } else {
1678 #if defined(LOG_CFSOCKET)
1679 fprintf(stdout, "perform calling out connect to socket %d\n", s->_socket);
1680 #endif
1681 if (callout) callout(s, kCFSocketConnectCallBack, NULL, NULL, contextInfo);
1682 calledOut = true;
1683 }
1684 }
1685 }
1686 if (kCFSocketDataCallBack == readCallBackType) {
1687 if (NULL != data && (!calledOut || CFSocketIsValid(s))) {
1688 SInt32 datalen = CFDataGetLength(data);
1689 #if defined(LOG_CFSOCKET)
1690 fprintf(stdout, "perform calling out data of length %ld to socket %d\n", datalen, s->_socket);
1691 #endif
1692 if (callout) callout(s, kCFSocketDataCallBack, address, data, contextInfo);
1693 calledOut = true;
1694 if (0 == datalen) __CFSocketInvalidate(s, true);
1695 }
1696 } else if (kCFSocketAcceptCallBack == readCallBackType) {
1697 if (INVALID_SOCKET != sock && (!calledOut || CFSocketIsValid(s))) {
1698 #if defined(LOG_CFSOCKET)
1699 fprintf(stdout, "perform calling out accept of socket %d to socket %d\n", sock, s->_socket);
1700 #endif
1701 if (callout) callout(s, kCFSocketAcceptCallBack, address, &sock, contextInfo);
1702 calledOut = true;
1703 }
1704 } else if (kCFSocketReadCallBack == readCallBackType) {
1705 if (readSignalled && (!calledOut || CFSocketIsValid(s))) {
1706 #if defined(LOG_CFSOCKET)
1707 fprintf(stdout, "perform calling out read to socket %d\n", s->_socket);
1708 #endif
1709 if (callout) callout(s, kCFSocketReadCallBack, NULL, NULL, contextInfo);
1710 calledOut = true;
1711 }
1712 }
1713 if ((callBackTypes & kCFSocketWriteCallBack) != 0) {
1714 if (writeSignalled && !errorCode && (!calledOut || CFSocketIsValid(s))) {
1715 #if defined(LOG_CFSOCKET)
1716 fprintf(stdout, "perform calling out write to socket %d\n", s->_socket);
1717 #endif
1718 if (callout) callout(s, kCFSocketWriteCallBack, NULL, NULL, contextInfo);
1719 calledOut = true;
1720 }
1721 }
1722 }
1723
1724 #if defined(USE_V1_RUN_LOOP_SOURCE)
1725 static HANDLE __CFSocketGetPort(void *info) {
1726 CFSocketRef s = info;
1727 return s->_event;
1728 }
1729
1730 static void __CFSocketPerformV1(void *info) {
1731 CFSocketRef s = info;
1732 WSANETWORKEVENTS eventsTranspired;
1733 uint8_t readCallBackType = __CFSocketReadCallBackType(s);
1734 CFOptionFlags callBacksSignalled = 0;
1735
1736 int err = WSAEnumNetworkEvents(s->_socket, s->_event, &eventsTranspired);
1737 CFAssert2(0 == err, __kCFLogAssertion, "%s(): WSAEnumNetworkEvents failed: %d", __PRETTY_FUNCTION__, WSAGetLastError());
1738 #if defined(LOG_CFSOCKET)
1739 fprintf(stdout, "socket %d with flags 0x%x disabled 0x%x connected 0x%x received NetworkEvents 0x%lx\n", s->_socket, s->_f.client, s->_f.disabled, s->_f.connected, eventsTranspired.lNetworkEvents);
1740 #endif
1741 // Get these bits cleared before any callouts, just as the SocketMgr thread used to
1742 if (eventsTranspired.lNetworkEvents & FD_READ) {
1743 __CFSpinLock(&__CFActiveSocketsLock);
1744 __CFSocketClearFDForRead(s);
1745 __CFSpinUnlock(&__CFActiveSocketsLock);
1746 }
1747
1748 if (eventsTranspired.lNetworkEvents & FD_READ || eventsTranspired.lNetworkEvents & FD_ACCEPT) callBacksSignalled |= readCallBackType;
1749 if (eventsTranspired.lNetworkEvents & FD_CONNECT || s->_f.writableHint) callBacksSignalled |= kCFSocketWriteCallBack;
1750 s->_f.writableHint = FALSE;
1751 CFAssert2(0 == (eventsTranspired.lNetworkEvents & FD_WRITE), __kCFLogAssertion, "%s(): WSAEnumNetworkEvents returned unexpected events: %lx", __PRETTY_FUNCTION__, eventsTranspired.lNetworkEvents);
1752
1753 #if defined(LOG_CFSOCKET)
1754 // I believe all these errors will be re-found in __CFSocketHandleRead and __CFSocketHandleWrite
1755 // so we don't need to check for them here.
1756 if (eventsTranspired.lNetworkEvents & FD_READ && eventsTranspired.iErrorCode[FD_READ_BIT] != 0)
1757 fprintf(stdout, "socket %d has error %d for FD_READ\n", s->_socket, eventsTranspired.iErrorCode[FD_READ_BIT]);
1758 if (eventsTranspired.lNetworkEvents & FD_WRITE && eventsTranspired.iErrorCode[FD_WRITE_BIT] != 0)
1759 fprintf(stdout, "socket %d has error %d for FD_WRITE\n", s->_socket, eventsTranspired.iErrorCode[FD_WRITE_BIT]);
1760 if (eventsTranspired.lNetworkEvents & FD_CLOSE && eventsTranspired.iErrorCode[FD_CLOSE_BIT] != 0)
1761 fprintf(stdout, "socket %d has error %d for FD_CLOSE\n", s->_socket, eventsTranspired.iErrorCode[FD_CLOSE_BIT]);
1762 if (eventsTranspired.lNetworkEvents & FD_CONNECT && eventsTranspired.iErrorCode[FD_CONNECT_BIT] != 0)
1763 fprintf(stdout, "socket %d has error %d for FD_CONNECT\n", s->_socket, eventsTranspired.iErrorCode[FD_CONNECT_BIT]);
1764 #endif
1765
1766 if (0 != (eventsTranspired.lNetworkEvents & FD_CLOSE)) s->_f.closeSignaled = TRUE;
1767 if (0 != (callBacksSignalled & readCallBackType)) __CFSocketHandleRead(s);
1768 if (0 != (callBacksSignalled & kCFSocketWriteCallBack)) __CFSocketHandleWrite(s, TRUE);
1769 // FD_CLOSE is edge triggered (sent once). FD_READ is level triggered (sent as long as there are
1770 // bytes). Event after we get FD_CLOSE, if there are still bytes to be read we'll keep getting
1771 // FD_READ until the pipe is drained. However, an EOF condition on the socket will -not-
1772 // trigger an FD_READ, so we must be careful not to stall out after the last bytes are read.
1773 // Finally, a client may have already noticed the EOF in the Read callout just done, so we don't
1774 // call him again if the socket has been invalidated.
1775 // All this implies that once we have seen FD_CLOSE, we need to keep checking for EOF on the read
1776 // side to give the client one last callback for that case.
1777 if (__CFSocketIsValid(s) && (eventsTranspired.lNetworkEvents == FD_CLOSE || (s->_f.closeSignaled && !__CFSocketHasBytesToRead(s)))) {
1778 if (readCallBackType != kCFSocketNoCallBack) {
1779 __CFSocketHandleRead(s);
1780 } else if ((__CFSocketCallBackTypes(s) & kCFSocketWriteCallBack) != 0) {
1781 __CFSocketHandleWrite(s, TRUE);
1782 }
1783 }
1784
1785 // Only reenable callbacks that are auto-reenabled
1786 __CFSocketLock(s);
1787 __CFSocketEnableCallBacks(s, callBacksSignalled & s->_f.client, FALSE, 'P'); // unlocks s
1788 }
1789 #endif // USE_V1_RUN_LOOP_SOURCE
1790
1791 static void __CFSocketPerformV0(void *info) {
1792 CFSocketRef s = info;
1793 CFDataRef data = NULL;
1794 CFDataRef address = NULL;
1795 CFSocketNativeHandle sock = INVALID_SOCKET;
1796 uint8_t readCallBackType, callBackTypes;
1797 CFRunLoopRef rl = NULL;
1798
1799 __CFSocketLock(s);
1800 if (!__CFSocketIsValid(s)) {
1801 __CFSocketUnlock(s);
1802 return;
1803 }
1804 callBackTypes = __CFSocketCallBackTypes(s);
1805 readCallBackType = __CFSocketReadCallBackType(s);
1806 CFOptionFlags callBacksSignalled = 0;
1807 if (__CFSocketIsReadSignalled(s)) callBacksSignalled |= readCallBackType;
1808 if (__CFSocketIsWriteSignalled(s)) callBacksSignalled |= kCFSocketWriteCallBack;
1809
1810 #if !defined(USE_V1_RUN_LOOP_SOURCE)
1811 if (kCFSocketDataCallBack == readCallBackType) {
1812 if (NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
1813 data = CFArrayGetValueAtIndex(s->_dataQueue, 0);
1814 CFRetain(data);
1815 CFArrayRemoveValueAtIndex(s->_dataQueue, 0);
1816 address = CFArrayGetValueAtIndex(s->_addressQueue, 0);
1817 CFRetain(address);
1818 CFArrayRemoveValueAtIndex(s->_addressQueue, 0);
1819 }
1820 } else if (kCFSocketAcceptCallBack == readCallBackType) {
1821 if (NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
1822 sock = (CFSocketNativeHandle)CFArrayGetValueAtIndex(s->_dataQueue, 0);
1823 CFArrayRemoveValueAtIndex(s->_dataQueue, 0);
1824 address = CFArrayGetValueAtIndex(s->_addressQueue, 0);
1825 CFRetain(address);
1826 CFArrayRemoveValueAtIndex(s->_addressQueue, 0);
1827 }
1828 }
1829 #endif
1830
1831 __CFSocketDoCallback(s, data, address, sock); // does __CFSocketUnlock(s)
1832 if (NULL != data) CFRelease(data);
1833 if (NULL != address) CFRelease(address);
1834
1835 __CFSocketLock(s);
1836 #if !defined(USE_V1_RUN_LOOP_SOURCE)
1837 if (__CFSocketIsValid(s) && kCFSocketNoCallBack != readCallBackType) {
1838 // if there's still more data, we want to wake back up right away
1839 if ((kCFSocketDataCallBack == readCallBackType || kCFSocketAcceptCallBack == readCallBackType) && NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
1840 CFRunLoopSourceSignal(s->_source0);
1841 #if defined(LOG_CFSOCKET)
1842 fprintf(stdout, "perform short-circuit signaling source for socket %d with flags 0x%x disabled 0x%x connected 0x%x\n", s->_socket, s->_f.client, s->_f.disabled, s->_f.connected);
1843 #endif
1844 rl = __CFSocketCopyRunLoopToWakeUp(s);
1845 }
1846 }
1847 #endif
1848 // Only reenable callbacks that are auto-reenabled
1849 __CFSocketEnableCallBacks(s, callBacksSignalled & s->_f.client, FALSE, 'p'); // unlocks s
1850
1851 if (NULL != rl) {
1852 CFRunLoopWakeUp(rl);
1853 CFRelease(rl);
1854 }
1855 }
1856
1857 CFRunLoopSourceRef CFSocketCreateRunLoopSource(CFAllocatorRef allocator, CFSocketRef s, CFIndex order) {
1858 CFRunLoopSourceRef result = NULL;
1859 __CFGenericValidateType(s, __kCFSocketTypeID);
1860 __CFSocketLock(s);
1861 if (__CFSocketIsValid(s)) {
1862 if (NULL == s->_source0) {
1863 CFRunLoopSourceContext context;
1864 #if defined(USE_V1_RUN_LOOP_SOURCE)
1865 CFRunLoopSourceContext1 context1;
1866 context1.version = 1;
1867 context1.info = s;
1868 context1.retain = CFRetain;
1869 context1.release = CFRelease;
1870 context1.copyDescription = CFCopyDescription;
1871 context1.equal = CFEqual;
1872 context1.hash = CFHash;
1873 context1.getPort = __CFSocketGetPort;
1874 context1.perform = __CFSocketPerformV1;
1875 s->_source1 = CFRunLoopSourceCreate(allocator, order, (CFRunLoopSourceContext*)&context1);
1876 #endif
1877 context.version = 0;
1878 context.info = s;
1879 context.retain = CFRetain;
1880 context.release = CFRelease;
1881 context.copyDescription = CFCopyDescription;
1882 context.equal = CFEqual;
1883 context.hash = CFHash;
1884 context.schedule = __CFSocketSchedule;
1885 context.cancel = __CFSocketCancel;
1886 context.perform = __CFSocketPerformV0;
1887 s->_source0 = CFRunLoopSourceCreate(allocator, order, &context);
1888 }
1889 CFRetain(s->_source0); /* This retain is for the receiver */
1890 result = s->_source0;
1891 }
1892 __CFSocketUnlock(s);
1893 return result;
1894 }
1895
1896 //??? need timeout, error handling, retries
1897 CFSocketError CFSocketSendData(CFSocketRef s, CFDataRef address, CFDataRef data, CFTimeInterval timeout) {
1898 const uint8_t *dataptr, *addrptr = NULL;
1899 SInt32 datalen, addrlen = 0, size = 0;
1900 CFSocketNativeHandle sock = INVALID_SOCKET;
1901 struct timeval tv;
1902 __CFGenericValidateType(s, __kCFSocketTypeID);
1903 if (address) {
1904 addrptr = CFDataGetBytePtr(address);
1905 addrlen = CFDataGetLength(address);
1906 }
1907 dataptr = CFDataGetBytePtr(data);
1908 datalen = CFDataGetLength(data);
1909 __CFSocketLock(s);
1910 if (__CFSocketIsValid(s)) sock = s->_socket;
1911 __CFSocketUnlock(s);
1912 if (INVALID_SOCKET != sock) {
1913 CFRetain(s);
1914 __CFSocketWriteLock(s);
1915 tv.tv_sec = (0 >= timeout || INT_MAX <= timeout) ? INT_MAX : (int)(float)floor(timeout);
1916 tv.tv_usec = (int)((timeout - floor(timeout)) * 1.0E6);
1917 setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv, sizeof(tv)); // cast for WinSock bad API
1918 if (NULL != addrptr && 0 < addrlen) {
1919 size = sendto(sock, dataptr, datalen, 0, (struct sockaddr *)addrptr, addrlen);
1920 } else {
1921 size = send(sock, dataptr, datalen, 0);
1922 }
1923 #if defined(LOG_CFSOCKET)
1924 fprintf(stdout, "wrote %ld bytes to socket %d\n", size, s->_socket);
1925 #endif
1926 __CFSocketWriteUnlock(s);
1927 CFRelease(s);
1928 }
1929 return (size > 0) ? kCFSocketSuccess : kCFSocketError;
1930 }
1931
1932 typedef struct {
1933 CFSocketError *error;
1934 CFPropertyListRef *value;
1935 CFDataRef *address;
1936 } __CFSocketNameRegistryResponse;
1937
1938 static void __CFSocketHandleNameRegistryReply(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {
1939 CFDataRef replyData = (CFDataRef)data;
1940 __CFSocketNameRegistryResponse *response = (__CFSocketNameRegistryResponse *)info;
1941 CFDictionaryRef replyDictionary = NULL;
1942 CFPropertyListRef value;
1943 replyDictionary = CFPropertyListCreateFromXMLData(NULL, replyData, kCFPropertyListImmutable, NULL);
1944 if (NULL != response->error) *(response->error) = kCFSocketError;
1945 if (NULL != replyDictionary) {
1946 if (CFGetTypeID((CFTypeRef)replyDictionary) == CFDictionaryGetTypeID() && NULL != (value = CFDictionaryGetValue(replyDictionary, kCFSocketResultKey))) {
1947 if (NULL != response->error) *(response->error) = kCFSocketSuccess;
1948 if (NULL != response->value) *(response->value) = CFRetain(value);
1949 if (NULL != response->address) *(response->address) = address ? CFDataCreateCopy(NULL, address) : NULL;
1950 }
1951 CFRelease(replyDictionary);
1952 }
1953 CFSocketInvalidate(s);
1954 }
1955
1956 static void __CFSocketSendNameRegistryRequest(CFSocketSignature *signature, CFDictionaryRef requestDictionary, __CFSocketNameRegistryResponse *response, CFTimeInterval timeout) {
1957 CFDataRef requestData = NULL;
1958 CFSocketContext context = {0, response, NULL, NULL, NULL};
1959 CFSocketRef s = NULL;
1960 CFRunLoopSourceRef source = NULL;
1961 if (NULL != response->error) *(response->error) = kCFSocketError;
1962 requestData = CFPropertyListCreateXMLData(NULL, requestDictionary);
1963 if (NULL != requestData) {
1964 if (NULL != response->error) *(response->error) = kCFSocketTimeout;
1965 s = CFSocketCreateConnectedToSocketSignature(NULL, signature, kCFSocketDataCallBack, __CFSocketHandleNameRegistryReply, &context, timeout);
1966 if (NULL != s) {
1967 if (kCFSocketSuccess == CFSocketSendData(s, NULL, requestData, timeout)) {
1968 source = CFSocketCreateRunLoopSource(NULL, s, 0);
1969 CFRunLoopAddSource(CFRunLoopGetCurrent(), source, __kCFSocketRegistryRequestRunLoopMode);
1970 CFRunLoopRunInMode(__kCFSocketRegistryRequestRunLoopMode, timeout, false);
1971 CFRelease(source);
1972 }
1973 CFSocketInvalidate(s);
1974 CFRelease(s);
1975 }
1976 CFRelease(requestData);
1977 }
1978 }
1979
1980 static void __CFSocketValidateSignature(const CFSocketSignature *providedSignature, CFSocketSignature *signature, uint16_t defaultPortNumber) {
1981 struct sockaddr_in sain, *sainp;
1982 memset(&sain, 0, sizeof(sain));
1983 #if !defined(__WIN32__)
1984 sain.sin_len = sizeof(sain);
1985 #endif
1986 sain.sin_family = AF_INET;
1987 sain.sin_port = htons(__CFSocketDefaultNameRegistryPortNumber);
1988 sain.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1989 if (NULL == providedSignature) {
1990 signature->protocolFamily = PF_INET;
1991 signature->socketType = SOCK_STREAM;
1992 signature->protocol = IPPROTO_TCP;
1993 signature->address = CFDataCreate(NULL, (uint8_t *)&sain, sizeof(sain));
1994 } else {
1995 signature->protocolFamily = providedSignature->protocolFamily;
1996 signature->socketType = providedSignature->socketType;
1997 signature->protocol = providedSignature->protocol;
1998 if (0 >= signature->protocolFamily) signature->protocolFamily = PF_INET;
1999 if (PF_INET == signature->protocolFamily) {
2000 if (0 >= signature->socketType) signature->socketType = SOCK_STREAM;
2001 if (0 >= signature->protocol && SOCK_STREAM == signature->socketType) signature->protocol = IPPROTO_TCP;
2002 if (0 >= signature->protocol && SOCK_DGRAM == signature->socketType) signature->protocol = IPPROTO_UDP;
2003 }
2004 if (NULL == providedSignature->address) {
2005 signature->address = CFDataCreate(NULL, (uint8_t *)&sain, sizeof(sain));
2006 } else {
2007 sainp = (struct sockaddr_in *)CFDataGetBytePtr(providedSignature->address);
2008 if ((int)sizeof(struct sockaddr_in) <= CFDataGetLength(providedSignature->address) && (AF_INET == sainp->sin_family || 0 == sainp->sin_family)) {
2009 #if !defined(__WIN32__)
2010 sain.sin_len = sizeof(sain);
2011 #endif
2012 sain.sin_family = AF_INET;
2013 sain.sin_port = sainp->sin_port;
2014 if (0 == sain.sin_port) sain.sin_port = htons(defaultPortNumber);
2015 sain.sin_addr.s_addr = sainp->sin_addr.s_addr;
2016 if (htonl(INADDR_ANY) == sain.sin_addr.s_addr) sain.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2017 signature->address = CFDataCreate(NULL, (uint8_t *)&sain, sizeof(sain));
2018 } else {
2019 signature->address = CFRetain(providedSignature->address);
2020 }
2021 }
2022 }
2023 }
2024
2025 CFSocketError CFSocketRegisterValue(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFPropertyListRef value) {
2026 CFSocketSignature signature;
2027 CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2028 CFSocketError retval = kCFSocketError;
2029 __CFSocketNameRegistryResponse response = {&retval, NULL, NULL};
2030 CFDictionaryAddValue(dictionary, kCFSocketCommandKey, kCFSocketRegisterCommand);
2031 CFDictionaryAddValue(dictionary, kCFSocketNameKey, name);
2032 if (NULL != value) CFDictionaryAddValue(dictionary, kCFSocketValueKey, value);
2033 __CFSocketValidateSignature(nameServerSignature, &signature, __CFSocketDefaultNameRegistryPortNumber);
2034 __CFSocketSendNameRegistryRequest(&signature, dictionary, &response, timeout);
2035 CFRelease(dictionary);
2036 CFRelease(signature.address);
2037 return retval;
2038 }
2039
2040 CFSocketError CFSocketCopyRegisteredValue(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFPropertyListRef *value, CFDataRef *serverAddress) {
2041 CFSocketSignature signature;
2042 CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2043 CFSocketError retval = kCFSocketError;
2044 __CFSocketNameRegistryResponse response = {&retval, value, serverAddress};
2045 CFDictionaryAddValue(dictionary, kCFSocketCommandKey, kCFSocketRetrieveCommand);
2046 CFDictionaryAddValue(dictionary, kCFSocketNameKey, name);
2047 __CFSocketValidateSignature(nameServerSignature, &signature, __CFSocketDefaultNameRegistryPortNumber);
2048 __CFSocketSendNameRegistryRequest(&signature, dictionary, &response, timeout);
2049 CFRelease(dictionary);
2050 CFRelease(signature.address);
2051 return retval;
2052 }
2053
2054 CFSocketError CFSocketRegisterSocketSignature(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, const CFSocketSignature *signature) {
2055 CFSocketSignature validatedSignature;
2056 CFMutableDataRef data = NULL;
2057 CFSocketError retval;
2058 CFIndex length;
2059 uint8_t bytes[4];
2060 if (NULL == signature) {
2061 retval = CFSocketUnregister(nameServerSignature, timeout, name);
2062 } else {
2063 __CFSocketValidateSignature(signature, &validatedSignature, 0);
2064 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) {
2065 retval = kCFSocketError;
2066 } else {
2067 data = CFDataCreateMutable(NULL, sizeof(bytes) + length);
2068 bytes[0] = validatedSignature.protocolFamily;
2069 bytes[1] = validatedSignature.socketType;
2070 bytes[2] = validatedSignature.protocol;
2071 bytes[3] = length;
2072 CFDataAppendBytes(data, bytes, sizeof(bytes));
2073 CFDataAppendBytes(data, CFDataGetBytePtr(validatedSignature.address), length);
2074 retval = CFSocketRegisterValue(nameServerSignature, timeout, name, data);
2075 CFRelease(data);
2076 }
2077 CFRelease(validatedSignature.address);
2078 }
2079 return retval;
2080 }
2081
2082 CFSocketError CFSocketCopyRegisteredSocketSignature(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFSocketSignature *signature, CFDataRef *nameServerAddress) {
2083 CFDataRef data = NULL;
2084 CFSocketSignature returnedSignature;
2085 const uint8_t *ptr = NULL, *aptr = NULL;
2086 uint8_t *mptr;
2087 CFIndex length = 0;
2088 CFDataRef serverAddress = NULL;
2089 CFSocketError retval = CFSocketCopyRegisteredValue(nameServerSignature, timeout, name, (CFPropertyListRef *)&data, &serverAddress);
2090 if (NULL == data || CFGetTypeID(data) != CFDataGetTypeID() || NULL == (ptr = CFDataGetBytePtr(data)) || (length = CFDataGetLength(data)) < 4) retval = kCFSocketError;
2091 if (kCFSocketSuccess == retval && NULL != signature) {
2092 returnedSignature.protocolFamily = (SInt32)*ptr++;
2093 returnedSignature.socketType = (SInt32)*ptr++;
2094 returnedSignature.protocol = (SInt32)*ptr++;
2095 ptr++;
2096 returnedSignature.address = CFDataCreate(NULL, ptr, length - 4);
2097 __CFSocketValidateSignature(&returnedSignature, signature, 0);
2098 CFRelease(returnedSignature.address);
2099 ptr = CFDataGetBytePtr(signature->address);
2100 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) {
2101 CFMutableDataRef address = CFDataCreateMutableCopy(NULL, CFDataGetLength(signature->address), signature->address);
2102 mptr = CFDataGetMutableBytePtr(address);
2103 ((struct sockaddr_in *)mptr)->sin_addr = ((struct sockaddr_in *)aptr)->sin_addr;
2104 CFRelease(signature->address);
2105 signature->address = address;
2106 }
2107 if (NULL != nameServerAddress) *nameServerAddress = serverAddress ? CFRetain(serverAddress) : NULL;
2108 }
2109 if (NULL != data) CFRelease(data);
2110 if (NULL != serverAddress) CFRelease(serverAddress);
2111 return retval;
2112 }
2113
2114 CFSocketError CFSocketUnregister(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name) {
2115 return CFSocketRegisterValue(nameServerSignature, timeout, name, NULL);
2116 }
2117
2118 CF_EXPORT void CFSocketSetDefaultNameRegistryPortNumber(uint16_t port) {
2119 __CFSocketDefaultNameRegistryPortNumber = port;
2120 }
2121
2122 CF_EXPORT uint16_t CFSocketGetDefaultNameRegistryPortNumber(void) {
2123 return __CFSocketDefaultNameRegistryPortNumber;
2124 }