]> git.saurik.com Git - apple/cf.git/blob - RunLoop.subproj/CFSocket.c
CF-299.35.tar.gz
[apple/cf.git] / RunLoop.subproj / CFSocket.c
1 /*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* CFSocket.c
26 Copyright 1999-2002, Apple, Inc. All rights reserved.
27 Responsibility: Doug Davidson
28 */
29
30 #include <CoreFoundation/CFSocket.h>
31 #include <sys/types.h>
32 #include <math.h>
33 #include <limits.h>
34 #include <CoreFoundation/CFArray.h>
35 #include <CoreFoundation/CFData.h>
36 #include <CoreFoundation/CFDictionary.h>
37 #include <CoreFoundation/CFRunLoop.h>
38 #include <CoreFoundation/CFString.h>
39 #include <CoreFoundation/CFPropertyList.h>
40 #include "CFInternal.h"
41 #if defined(__WIN32__)
42 #include <winsock.h>
43 #define EINPROGRESS 36
44 //#include <errno.h>
45 #elif defined(__MACH__)
46 #include <libc.h>
47 #else
48 #include <sys/filio.h>
49 #include <sys/time.h>
50 #include <sys/socket.h>
51 #include <netinet/in.h>
52 #include <netdb.h>
53 #endif
54
55 //#define LOG_CFSOCKET
56
57 #if !defined(__WIN32__)
58 #define INVALID_SOCKET (CFSocketNativeHandle)(-1)
59 #endif /* __WIN32__ */
60
61 #define MAX_SOCKADDR_LEN 256
62 #define MAX_DATA_SIZE 32768
63
64 static uint16_t __CFSocketDefaultNameRegistryPortNumber = 2454;
65
66 CONST_STRING_DECL(kCFSocketCommandKey, "Command")
67 CONST_STRING_DECL(kCFSocketNameKey, "Name")
68 CONST_STRING_DECL(kCFSocketValueKey, "Value")
69 CONST_STRING_DECL(kCFSocketResultKey, "Result")
70 CONST_STRING_DECL(kCFSocketErrorKey, "Error")
71 CONST_STRING_DECL(kCFSocketRegisterCommand, "Register")
72 CONST_STRING_DECL(kCFSocketRetrieveCommand, "Retrieve")
73 CONST_STRING_DECL(__kCFSocketRegistryRequestRunLoopMode, "CFSocketRegistryRequest")
74
75 /* locks are to be acquired in the following order:
76 (1) __CFAllSocketsLock
77 (2) an individual CFSocket's lock
78 (3) __CFActiveSocketsLock
79 */
80 static CFSpinLock_t __CFAllSocketsLock = 0; /* controls __CFAllSockets */
81 static CFMutableDictionaryRef __CFAllSockets = NULL;
82 static CFSpinLock_t __CFActiveSocketsLock = 0; /* controls __CFRead/WriteSockets and __CFRead/WriteSocketsFds */
83 static CFMutableArrayRef __CFWriteSockets = NULL;
84 static CFMutableArrayRef __CFReadSockets = NULL;
85 static CFMutableDataRef __CFWriteSocketsFds = NULL;
86 static CFMutableDataRef __CFReadSocketsFds = NULL;
87
88 static CFSocketNativeHandle __CFWakeupSocketPair[2] = {0, 0};
89 static void *__CFSocketManagerThread = NULL;
90
91 #if defined(__WIN32__)
92 static Boolean __CFSocketWinSockInitialized = false;
93 #else
94 #define CFSOCKET_USE_SOCKETPAIR
95 #define closesocket(a) close((a))
96 #define ioctlsocket(a,b,c) ioctl((a),(b),(c))
97 #endif
98
99 static CFTypeID __kCFSocketTypeID = _kCFRuntimeNotATypeID;
100
101 struct __CFSocket {
102 CFRuntimeBase _base;
103 uint32_t _flags;
104 CFSpinLock_t _lock;
105 CFSpinLock_t _writeLock;
106 CFSocketNativeHandle _socket; /* immutable */
107 SInt32 _socketType;
108 SInt32 _errorCode;
109 CFDataRef _address;
110 CFDataRef _peerAddress;
111 SInt32 _socketSetCount;
112 CFRunLoopSourceRef _source;
113 CFMutableArrayRef _runLoops;
114 CFSocketCallBack _callout; /* immutable */
115 CFSocketContext _context; /* immutable */
116 CFIndex _maxQueueLen;
117 CFMutableArrayRef _dataQueue;
118 CFMutableArrayRef _addressQueue;
119 };
120
121 /* Bit 6 in the base reserved bits is used for write-signalled state (mutable) */
122 /* Bit 5 in the base reserved bits is used for read-signalled state (mutable) */
123 /* Bit 4 in the base reserved bits is used for invalid state (mutable) */
124 /* Bits 0-3 in the base reserved bits are used for callback types (immutable) */
125 /* Of this, bits 0-1 are used for the read callback type. */
126
127 CF_INLINE Boolean __CFSocketIsWriteSignalled(CFSocketRef s) {
128 return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_info, 6, 6);
129 }
130
131 CF_INLINE void __CFSocketSetWriteSignalled(CFSocketRef s) {
132 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_info, 6, 6, 1);
133 }
134
135 CF_INLINE void __CFSocketUnsetWriteSignalled(CFSocketRef s) {
136 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_info, 6, 6, 0);
137 }
138
139 CF_INLINE Boolean __CFSocketIsReadSignalled(CFSocketRef s) {
140 return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_info, 5, 5);
141 }
142
143 CF_INLINE void __CFSocketSetReadSignalled(CFSocketRef s) {
144 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_info, 5, 5, 1);
145 }
146
147 CF_INLINE void __CFSocketUnsetReadSignalled(CFSocketRef s) {
148 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_info, 5, 5, 0);
149 }
150
151 CF_INLINE Boolean __CFSocketIsValid(CFSocketRef s) {
152 return (Boolean)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_info, 4, 4);
153 }
154
155 CF_INLINE void __CFSocketSetValid(CFSocketRef s) {
156 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_info, 4, 4, 1);
157 }
158
159 CF_INLINE void __CFSocketUnsetValid(CFSocketRef s) {
160 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_info, 4, 4, 0);
161 }
162
163 CF_INLINE uint8_t __CFSocketCallBackTypes(CFSocketRef s) {
164 return (uint8_t)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_info, 3, 0);
165 }
166
167 CF_INLINE uint8_t __CFSocketReadCallBackType(CFSocketRef s) {
168 return (uint8_t)__CFBitfieldGetValue(((const CFRuntimeBase *)s)->_info, 1, 0);
169 }
170
171 CF_INLINE void __CFSocketSetCallBackTypes(CFSocketRef s, uint8_t types) {
172 __CFBitfieldSetValue(((CFRuntimeBase *)s)->_info, 3, 0, types & 0xF);
173 }
174
175 CF_INLINE void __CFSocketLock(CFSocketRef s) {
176 __CFSpinLock(&(s->_lock));
177 }
178
179 CF_INLINE void __CFSocketUnlock(CFSocketRef s) {
180 __CFSpinUnlock(&(s->_lock));
181 }
182
183 CF_INLINE void __CFSocketWriteLock(CFSocketRef s) {
184 __CFSpinLock(&(s->_writeLock));
185 }
186
187 CF_INLINE void __CFSocketWriteUnlock(CFSocketRef s) {
188 __CFSpinUnlock(&(s->_writeLock));
189 }
190
191 CF_INLINE Boolean __CFSocketIsConnectionOriented(CFSocketRef s) {
192 return (SOCK_STREAM == s->_socketType || SOCK_SEQPACKET == s->_socketType);
193 }
194
195 CF_INLINE void __CFSocketEstablishAddress(CFSocketRef s) {
196 /* socket should already be locked */
197 uint8_t name[MAX_SOCKADDR_LEN];
198 int namelen = sizeof(name);
199 if (__CFSocketIsValid(s) && NULL == s->_address && INVALID_SOCKET != s->_socket && 0 == getsockname(s->_socket, (struct sockaddr *)name, &namelen) && NULL != name && 0 < namelen) {
200 s->_address = CFDataCreate(CFGetAllocator(s), name, namelen);
201 }
202 }
203
204 CF_INLINE void __CFSocketEstablishPeerAddress(CFSocketRef s) {
205 /* socket should already be locked */
206 uint8_t name[MAX_SOCKADDR_LEN];
207 int namelen = sizeof(name);
208 if (__CFSocketIsValid(s) && NULL == s->_peerAddress && INVALID_SOCKET != s->_socket && 0 == getpeername(s->_socket, (struct sockaddr *)name, &namelen) && NULL != name && 0 < namelen) {
209 s->_peerAddress = CFDataCreate(CFGetAllocator(s), name, namelen);
210 }
211 }
212
213 CF_INLINE CFIndex __CFSocketFdGetSize(CFDataRef fdSet) {
214 #if defined(__WIN32__)
215 fd_set* set = CFDataGetBytePtr(fdSet);
216 return set ? set->fd_count : 0;
217 #else
218 return NBBY * CFDataGetLength(fdSet);
219 #endif
220 }
221
222 CF_INLINE Boolean __CFSocketFdSet(CFSocketNativeHandle sock, CFMutableDataRef fdSet) {
223 /* returns true if a change occurred, false otherwise */
224 Boolean retval = false;
225 if (INVALID_SOCKET != sock && 0 <= sock) {
226 #if defined(__WIN32__)
227 fd_set* set = (fd_set*)CFDataGetMutableBytePtr(fdSet);
228 if ((set->fd_count * sizeof(SOCKET) + sizeof(u_int)) >= CFDataGetLength(fdSet)) {
229 CFDataIncreaseLength(fdSet, sizeof(SOCKET));
230 set = (fd_set*)CFDataGetMutableBytePtr(fdSet);
231 }
232 if (!FD_ISSET(sock, set)) {
233 retval = true;
234 FD_SET(sock, set);
235 }
236 #else
237 CFIndex numFds = NBBY * CFDataGetLength(fdSet);
238 fd_mask *fds_bits;
239 if (sock >= numFds) {
240 CFIndex oldSize = numFds / NFDBITS, newSize = (sock + NFDBITS) / NFDBITS, changeInBytes = (newSize - oldSize) * sizeof(fd_mask);
241 CFDataIncreaseLength(fdSet, changeInBytes);
242 fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
243 memset(fds_bits + oldSize, 0, changeInBytes);
244 } else {
245 fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
246 }
247 if (!FD_ISSET(sock, (fd_set *)fds_bits)) {
248 retval = true;
249 FD_SET(sock, (fd_set *)fds_bits);
250 }
251 #endif
252 }
253 return retval;
254 }
255
256 CF_INLINE Boolean __CFSocketFdClr(CFSocketNativeHandle sock, CFMutableDataRef fdSet) {
257 /* returns true if a change occurred, false otherwise */
258 Boolean retval = false;
259 if (INVALID_SOCKET != sock && 0 <= sock) {
260 #if defined(__WIN32__)
261 fd_set* set = (fd_set*)CFDataGetMutableBytePtr(fdSet);
262 if (FD_ISSET(sock, set)) {
263 retval = true;
264 FD_CLR(sock, set);
265 }
266 #else
267 CFIndex numFds = NBBY * CFDataGetLength(fdSet);
268 fd_mask *fds_bits;
269 if (sock < numFds) {
270 fds_bits = (fd_mask *)CFDataGetMutableBytePtr(fdSet);
271 if (FD_ISSET(sock, (fd_set *)fds_bits)) {
272 retval = true;
273 FD_CLR(sock, (fd_set *)fds_bits);
274 }
275 }
276 #endif
277 }
278 return retval;
279 }
280
281 static SInt32 __CFSocketCreateWakeupSocketPair(void) {
282 #if defined(CFSOCKET_USE_SOCKETPAIR)
283 return socketpair(PF_LOCAL, SOCK_DGRAM, 0, __CFWakeupSocketPair);
284 #else
285 //??? should really use native Win32 facilities
286 UInt32 i;
287 SInt32 error = 0;
288 struct sockaddr_in address[2];
289 int namelen = sizeof(struct sockaddr_in);
290 for (i = 0; i < 2; i++) {
291 __CFWakeupSocketPair[i] = socket(PF_INET, SOCK_DGRAM, 0);
292 memset(&(address[i]), 0, sizeof(struct sockaddr_in));
293 address[i].sin_family = AF_INET;
294 address[i].sin_addr.s_addr = htonl(INADDR_LOOPBACK);
295 if (0 <= error) error = bind(__CFWakeupSocketPair[i], (struct sockaddr *)&(address[i]), sizeof(struct sockaddr_in));
296 if (0 <= error) error = getsockname(__CFWakeupSocketPair[i], (struct sockaddr *)&(address[i]), &namelen);
297 if (sizeof(struct sockaddr_in) != namelen) error = -1;
298 }
299 if (0 <= error) error = connect(__CFWakeupSocketPair[0], (struct sockaddr *)&(address[1]), sizeof(struct sockaddr_in));
300 if (0 <= error) error = connect(__CFWakeupSocketPair[1], (struct sockaddr *)&(address[0]), sizeof(struct sockaddr_in));
301 if (0 > error) {
302 closesocket(__CFWakeupSocketPair[0]);
303 closesocket(__CFWakeupSocketPair[1]);
304 }
305 return error;
306 #endif
307 }
308
309 static void __CFSocketInitializeSockets(void) {
310 UInt32 yes = 1;
311 #if defined(__WIN32__)
312 if (!__CFSocketWinSockInitialized) {
313 WORD versionRequested = MAKEWORD(1, 1);
314 WSADATA wsaData;
315 int errorStatus = WSAStartup(versionRequested, &wsaData);
316 if (errorStatus != 0 || LOBYTE(wsaData.wVersion) != LOBYTE(versionRequested) || HIBYTE(wsaData.wVersion) != HIBYTE(versionRequested)) {
317 WSACleanup();
318 CFLog(0, CFSTR("*** Could not initialize WinSock subsystem!!!"));
319 }
320 __CFSocketWinSockInitialized = true;
321 }
322 #endif
323 __CFWriteSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
324 __CFReadSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, NULL);
325 __CFWriteSocketsFds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
326 __CFReadSocketsFds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
327 #if defined(__WIN32__)
328 CFDataIncreaseLength(__CFWriteSocketsFds, sizeof(u_int) + sizeof(SOCKET));
329 CFDataIncreaseLength(__CFReadSocketsFds, sizeof(u_int) + sizeof(SOCKET));
330 #endif
331 if (0 > __CFSocketCreateWakeupSocketPair()) {
332 CFLog(0, CFSTR("*** Could not create wakeup socket pair for CFSocket!!!"));
333 } else {
334 /* wakeup sockets must be non-blocking */
335 ioctlsocket(__CFWakeupSocketPair[0], FIONBIO, &yes);
336 ioctlsocket(__CFWakeupSocketPair[1], FIONBIO, &yes);
337 __CFSocketFdSet(__CFWakeupSocketPair[1], __CFReadSocketsFds);
338 }
339 }
340
341 static CFRunLoopRef __CFSocketCopyRunLoopToWakeUp(CFSocketRef s) {
342 CFRunLoopRef rl = NULL;
343 SInt32 idx, cnt = CFArrayGetCount(s->_runLoops);
344 if (0 < cnt) {
345 rl = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, 0);
346 for (idx = 1; NULL != rl && idx < cnt; idx++) {
347 CFRunLoopRef value = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, idx);
348 if (value != rl) rl = NULL;
349 }
350 if (NULL == rl) { /* more than one different rl, so we must pick one */
351 for (idx = 0; idx < cnt; idx++) {
352 CFRunLoopRef value = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, idx);
353 CFStringRef currentMode = CFRunLoopCopyCurrentMode(value);
354 if (NULL != currentMode && CFRunLoopIsWaiting(value) && CFRunLoopContainsSource(value, s->_source, currentMode)) {
355 CFRelease(currentMode);
356 /* ideally, this would be a run loop which isn't also in a
357 * signaled state for this or another source, but that's tricky;
358 * we move this run loop to the end of the list to scramble them
359 * a bit, and always search from the front */
360 CFArrayRemoveValueAtIndex(s->_runLoops, idx);
361 rl = value;
362 break;
363 }
364 if (NULL != currentMode) CFRelease(currentMode);
365 }
366 if (NULL == rl) { /* didn't choose one above, so choose first */
367 rl = (CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, 0);
368 CFArrayRemoveValueAtIndex(s->_runLoops, 0);
369 }
370 CFArrayAppendValue(s->_runLoops, rl);
371 }
372 }
373 if (NULL != rl) CFRetain(rl);
374 return rl;
375 }
376
377 static void __CFSocketHandleWrite(CFSocketRef s) {
378 SInt32 errorCode = 0;
379 int errorSize = sizeof(errorCode);
380 CFRunLoopRef rl = NULL;
381 CFOptionFlags writeCallBacksAvailable;
382
383 if (!CFSocketIsValid(s)) return;
384 if (0 != getsockopt(s->_socket, SOL_SOCKET, SO_ERROR, &errorCode, &errorSize)) errorCode = 0;
385 #if defined(LOG_CFSOCKET)
386 if (errorCode) printf("error %d on socket %d\n", errorCode, s->_socket);
387 #endif
388 __CFSocketLock(s);
389 writeCallBacksAvailable = __CFSocketCallBackTypes(s) & (kCFSocketWriteCallBack | kCFSocketConnectCallBack);
390 if ((s->_flags & kCFSocketConnectCallBack) != 0) writeCallBacksAvailable &= ~kCFSocketConnectCallBack;
391 if (!__CFSocketIsValid(s) || (((s->_flags >> 24) & writeCallBacksAvailable) == writeCallBacksAvailable)) {
392 __CFSocketUnlock(s);
393 return;
394 }
395 s->_errorCode = errorCode;
396 __CFSocketSetWriteSignalled(s);
397 CFRunLoopSourceSignal(s->_source);
398 #if defined(LOG_CFSOCKET)
399 printf("write signaling source for socket %d\n", s->_socket);
400 #endif
401 rl = __CFSocketCopyRunLoopToWakeUp(s);
402 __CFSocketUnlock(s);
403 if (NULL != rl) {
404 CFRunLoopWakeUp(rl);
405 CFRelease(rl);
406 }
407 }
408
409 static void __CFSocketHandleRead(CFSocketRef s) {
410 static CFDataRef zeroLengthData = NULL;
411 CFRunLoopRef rl = NULL;
412 if (NULL == zeroLengthData) zeroLengthData = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
413 if (!CFSocketIsValid(s)) return;
414 if (__CFSocketReadCallBackType(s) == kCFSocketDataCallBack) {
415 uint8_t buffer[MAX_DATA_SIZE];
416 #if !defined(__WIN32__)
417 uint8_t name[MAX_SOCKADDR_LEN];
418 int namelen = sizeof(name);
419 #else
420 struct sockaddr* name = NULL;
421 int namelen = 0;
422 #endif
423 SInt32 recvlen = recvfrom(s->_socket, buffer, sizeof(buffer), 0, (struct sockaddr *)name, &namelen);
424 CFDataRef data, address = NULL;
425 #if defined(LOG_CFSOCKET)
426 printf("read %d bytes on socket %d\n", recvlen, s->_socket);
427 #endif
428 if (0 >= recvlen) {
429 //??? should return error if <0
430 /* zero-length data is the signal for perform to invalidate */
431 data = CFRetain(zeroLengthData);
432 } else {
433 data = CFDataCreate(CFGetAllocator(s), buffer, recvlen);
434 }
435 __CFSocketLock(s);
436 if (!__CFSocketIsValid(s)) {
437 CFRelease(data);
438 __CFSocketUnlock(s);
439 return;
440 }
441 __CFSocketSetReadSignalled(s);
442 if (NULL != name && 0 < namelen) {
443 //??? possible optimizations: uniquing; storing last value
444 address = CFDataCreate(CFGetAllocator(s), name, namelen);
445 } else if (__CFSocketIsConnectionOriented(s)) {
446 if (NULL == s->_peerAddress) __CFSocketEstablishPeerAddress(s);
447 if (NULL != s->_peerAddress) address = CFRetain(s->_peerAddress);
448 }
449 if (NULL == address) {
450 address = CFRetain(zeroLengthData);
451 }
452 if (NULL == s->_dataQueue) {
453 s->_dataQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
454 }
455 if (NULL == s->_addressQueue) {
456 s->_addressQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
457 }
458 CFArrayAppendValue(s->_dataQueue, data);
459 CFRelease(data);
460 CFArrayAppendValue(s->_addressQueue, address);
461 CFRelease(address);
462 if (0 < recvlen && 0 < s->_socketSetCount && (s->_flags & kCFSocketDataCallBack) != 0 && ((s->_flags >> 24) & kCFSocketDataCallBack) == 0 && (0 == s->_maxQueueLen || CFArrayGetCount(s->_dataQueue) < s->_maxQueueLen)) {
463 __CFSpinLock(&__CFActiveSocketsLock);
464 /* restore socket to fds */
465 __CFSocketFdSet(s->_socket, __CFReadSocketsFds);
466 __CFSpinUnlock(&__CFActiveSocketsLock);
467 }
468 } else if (__CFSocketReadCallBackType(s) == kCFSocketAcceptCallBack) {
469 uint8_t name[MAX_SOCKADDR_LEN];
470 int namelen = sizeof(name);
471 CFSocketNativeHandle sock = accept(s->_socket, (struct sockaddr *)name, &namelen);
472 CFDataRef address;
473 if (INVALID_SOCKET == sock) {
474 //??? should return error
475 return;
476 }
477 if (NULL != name && 0 < namelen) {
478 address = CFDataCreate(CFGetAllocator(s), name, namelen);
479 } else {
480 address = CFRetain(zeroLengthData);
481 }
482 __CFSocketLock(s);
483 if (!__CFSocketIsValid(s)) {
484 closesocket(sock);
485 CFRelease(address);
486 __CFSocketUnlock(s);
487 return;
488 }
489 __CFSocketSetReadSignalled(s);
490 if (NULL == s->_dataQueue) {
491 s->_dataQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, NULL);
492 }
493 if (NULL == s->_addressQueue) {
494 s->_addressQueue = CFArrayCreateMutable(CFGetAllocator(s), 0, &kCFTypeArrayCallBacks);
495 }
496 CFArrayAppendValue(s->_dataQueue, (void *)sock);
497 CFArrayAppendValue(s->_addressQueue, address);
498 CFRelease(address);
499 if (0 < s->_socketSetCount && (s->_flags & kCFSocketAcceptCallBack) != 0 && ((s->_flags >> 24) & kCFSocketAcceptCallBack) == 0 && (0 == s->_maxQueueLen || CFArrayGetCount(s->_dataQueue) < s->_maxQueueLen)) {
500 __CFSpinLock(&__CFActiveSocketsLock);
501 /* restore socket to fds */
502 __CFSocketFdSet(s->_socket, __CFReadSocketsFds);
503 __CFSpinUnlock(&__CFActiveSocketsLock);
504 }
505 } else {
506 __CFSocketLock(s);
507 if (!__CFSocketIsValid(s) || ((s->_flags >> 24) & kCFSocketReadCallBack) != 0) {
508 __CFSocketUnlock(s);
509 return;
510 }
511 __CFSocketSetReadSignalled(s);
512 }
513 CFRunLoopSourceSignal(s->_source);
514 #if defined(LOG_CFSOCKET)
515 printf("read signaling source for socket %d\n", s->_socket);
516 #endif
517 rl = __CFSocketCopyRunLoopToWakeUp(s);
518 __CFSocketUnlock(s);
519 if (NULL != rl) {
520 CFRunLoopWakeUp(rl);
521 CFRelease(rl);
522 }
523 }
524
525 static void * __CFSocketManager(void * arg) {
526 SInt32 nrfds, maxnrfds, fdentries = 1;
527 #if defined(__WIN32__)
528 fd_set *writefds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(SOCKET) + sizeof(u_int), 0);
529 fd_set *readfds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(SOCKET) + sizeof(u_int), 0);
530 #else
531 fd_set *writefds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(fd_mask), 0);
532 fd_set *readfds = (fd_set *)CFAllocatorAllocate(kCFAllocatorSystemDefault, fdentries * sizeof(fd_mask), 0);
533 #endif
534 fd_set *tempfds;
535 SInt32 idx, cnt;
536 uint8_t buffer[256];
537 CFMutableArrayRef selectedWriteSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
538 CFMutableArrayRef selectedReadSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
539
540 for (;;) {
541 __CFSpinLock(&__CFActiveSocketsLock);
542 #if defined(LOG_CFSOCKET)
543 printf("socket manager looking at read sockets ");
544 tempfds = (fd_set *)CFDataGetBytePtr(__CFReadSocketsFds);
545 for (idx = 0, cnt = CFArrayGetCount(__CFReadSockets); idx < cnt; idx++) {
546 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx);
547 if (FD_ISSET(s->_socket, tempfds)) {
548 printf("%d ", s->_socket);
549 } else {
550 printf("(%d) ", s->_socket);
551 }
552 }
553 if (0 < CFArrayGetCount(__CFWriteSockets)) printf(" and write sockets ");
554 tempfds = (fd_set *)CFDataGetBytePtr(__CFWriteSocketsFds);
555 for (idx = 0, cnt = CFArrayGetCount(__CFWriteSockets); idx < cnt; idx++) {
556 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFWriteSockets, idx);
557 if (FD_ISSET(s->_socket, tempfds)) {
558 printf("%d ", s->_socket);
559 } else {
560 printf("(%d) ", s->_socket);
561 }
562 }
563 printf("\n");
564 #endif
565 maxnrfds = MAX(__CFSocketFdGetSize(__CFWriteSocketsFds), __CFSocketFdGetSize(__CFReadSocketsFds));
566 #if defined(__WIN32__)
567 if (maxnrfds > fdentries) {
568 fdentries = maxnrfds;
569 writefds = (fd_set *)CFAllocatorReallocate(kCFAllocatorSystemDefault, writefds, fdentries * sizeof(SOCKET) + sizeof(u_int), 0);
570 readfds = (fd_set *)CFAllocatorReallocate(kCFAllocatorSystemDefault, readfds, fdentries * sizeof(SOCKET) + sizeof(u_int), 0);
571 }
572 memset(writefds, 0, fdentries * sizeof(SOCKET) + sizeof(u_int));
573 memset(readfds, 0, fdentries * sizeof(SOCKET) + sizeof(u_int));
574 #else
575 if (maxnrfds > fdentries * (int)NFDBITS) {
576 fdentries = (maxnrfds + NFDBITS - 1) / NFDBITS;
577 writefds = (fd_set *)CFAllocatorReallocate(kCFAllocatorSystemDefault, writefds, fdentries * sizeof(fd_mask), 0);
578 readfds = (fd_set *)CFAllocatorReallocate(kCFAllocatorSystemDefault, readfds, fdentries * sizeof(fd_mask), 0);
579 }
580 memset(writefds, 0, fdentries * sizeof(fd_mask));
581 memset(readfds, 0, fdentries * sizeof(fd_mask));
582 #endif
583 CFDataGetBytes(__CFWriteSocketsFds, CFRangeMake(0, CFDataGetLength(__CFWriteSocketsFds)), (UInt8 *)writefds);
584 CFDataGetBytes(__CFReadSocketsFds, CFRangeMake(0, CFDataGetLength(__CFReadSocketsFds)), (UInt8 *)readfds);
585 __CFSpinUnlock(&__CFActiveSocketsLock);
586
587 nrfds = select(maxnrfds, readfds, writefds, NULL, NULL);
588 if (0 == nrfds) continue;
589 if (0 > nrfds) {
590 SInt32 selectError = thread_errno();
591 #if defined(LOG_CFSOCKET)
592 printf("socket manager received error %d from select\n", selectError);
593 #endif
594 if (EBADF == selectError) {
595 CFMutableArrayRef invalidSockets = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
596 __CFSpinLock(&__CFActiveSocketsLock);
597 cnt = CFArrayGetCount(__CFWriteSockets);
598 for (idx = 0; idx < cnt; idx++) {
599 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFWriteSockets, idx);
600 SInt32 flags = fcntl(s->_socket, F_GETFL, 0);
601 if (0 > flags && EBADF == thread_errno()) {
602 #if defined(LOG_CFSOCKET)
603 printf("socket manager found write socket %d invalid\n", s->_socket);
604 #endif
605 CFArrayAppendValue(invalidSockets, s);
606 }
607 }
608 cnt = CFArrayGetCount(__CFReadSockets);
609 for (idx = 0; idx < cnt; idx++) {
610 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx);
611 SInt32 flags = fcntl(s->_socket, F_GETFL, 0);
612 if (0 > flags && EBADF == thread_errno()) {
613 #if defined(LOG_CFSOCKET)
614 printf("socket manager found read socket %d invalid\n", s->_socket);
615 #endif
616 CFArrayAppendValue(invalidSockets, s);
617 }
618 }
619 __CFSpinUnlock(&__CFActiveSocketsLock);
620
621 cnt = CFArrayGetCount(invalidSockets);
622 for (idx = 0; idx < cnt; idx++) {
623 CFSocketInvalidate((CFSocketRef)CFArrayGetValueAtIndex(invalidSockets, idx));
624 }
625 CFRelease(invalidSockets);
626 }
627 continue;
628 }
629 if (FD_ISSET(__CFWakeupSocketPair[1], readfds)) {
630 recv(__CFWakeupSocketPair[1], buffer, sizeof(buffer), 0);
631 #if defined(LOG_CFSOCKET)
632 printf("socket manager received %c on wakeup socket\n", buffer[0]);
633 #endif
634 }
635 __CFSpinLock(&__CFActiveSocketsLock);
636 tempfds = NULL;
637 cnt = CFArrayGetCount(__CFWriteSockets);
638 for (idx = 0; idx < cnt; idx++) {
639 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFWriteSockets, idx);
640 CFSocketNativeHandle sock = s->_socket;
641 if (INVALID_SOCKET != sock && 0 <= sock && sock < maxnrfds && FD_ISSET(sock, writefds)) {
642 CFArrayAppendValue(selectedWriteSockets, s);
643 /* socket is removed from fds here, restored by CFSocketReschedule */
644 if (!tempfds) tempfds = (fd_set *)CFDataGetMutableBytePtr(__CFWriteSocketsFds);
645 FD_CLR(sock, tempfds);
646 }
647 }
648 tempfds = NULL;
649 cnt = CFArrayGetCount(__CFReadSockets);
650 for (idx = 0; idx < cnt; idx++) {
651 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(__CFReadSockets, idx);
652 CFSocketNativeHandle sock = s->_socket;
653 if (INVALID_SOCKET != sock && 0 <= sock && sock < maxnrfds && FD_ISSET(sock, readfds)) {
654 CFArrayAppendValue(selectedReadSockets, s);
655 /* socket is removed from fds here, will be restored in read handling or in perform function */
656 if (!tempfds) tempfds = (fd_set *)CFDataGetMutableBytePtr(__CFReadSocketsFds);
657 FD_CLR(sock, tempfds);
658 }
659 }
660 __CFSpinUnlock(&__CFActiveSocketsLock);
661
662 cnt = CFArrayGetCount(selectedWriteSockets);
663 for (idx = 0; idx < cnt; idx++) {
664 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(selectedWriteSockets, idx);
665 #if defined(LOG_CFSOCKET)
666 printf("socket manager signaling socket %d for write\n", s->_socket);
667 #endif
668 __CFSocketHandleWrite(s);
669 }
670 if (0 < cnt) CFArrayRemoveAllValues(selectedWriteSockets);
671 cnt = CFArrayGetCount(selectedReadSockets);
672 for (idx = 0; idx < cnt; idx++) {
673 CFSocketRef s = (CFSocketRef)CFArrayGetValueAtIndex(selectedReadSockets, idx);
674 #if defined(LOG_CFSOCKET)
675 printf("socket manager signaling socket %d for read\n", s->_socket);
676 #endif
677 __CFSocketHandleRead(s);
678 }
679 if (0 < cnt) CFArrayRemoveAllValues(selectedReadSockets);
680 }
681 return (void *)0;
682 }
683
684 static CFStringRef __CFSocketCopyDescription(CFTypeRef cf) {
685 CFSocketRef s = (CFSocketRef)cf;
686 CFMutableStringRef result;
687 CFStringRef contextDesc = NULL;
688 void *contextInfo = NULL;
689 CFStringRef (*contextCopyDescription)(const void *info) = NULL;
690 result = CFStringCreateMutable(CFGetAllocator(s), 0);
691 __CFSocketLock(s);
692 CFStringAppendFormat(result, NULL, CFSTR("<CFSocket %p [%p]>{valid = %s, type = %d, socket = %d, socket set count = %d\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->_source, s->_runLoops);
693 contextInfo = s->_context.info;
694 contextCopyDescription = s->_context.copyDescription;
695 __CFSocketUnlock(s);
696 if (NULL != contextInfo && NULL != contextCopyDescription) {
697 contextDesc = (CFStringRef)contextCopyDescription(contextInfo);
698 }
699 if (NULL == contextDesc) {
700 contextDesc = CFStringCreateWithFormat(CFGetAllocator(s), NULL, CFSTR("<CFSocket context %p>"), contextInfo);
701 }
702 CFStringAppend(result, contextDesc);
703 CFRelease(contextDesc);
704 return result;
705 }
706
707 static void __CFSocketDeallocate(CFTypeRef cf) {
708 /* Since CFSockets are cached, we can only get here sometime after being invalidated */
709 CFSocketRef s = (CFSocketRef)cf;
710 if (NULL != s->_address) {
711 CFRelease(s->_address);
712 s->_address = NULL;
713 }
714 }
715
716 static const CFRuntimeClass __CFSocketClass = {
717 0,
718 "CFSocket",
719 NULL, // init
720 NULL, // copy
721 __CFSocketDeallocate,
722 NULL, // equal
723 NULL, // hash
724 NULL, //
725 __CFSocketCopyDescription
726 };
727
728 __private_extern__ void __CFSocketInitialize(void) {
729 __kCFSocketTypeID = _CFRuntimeRegisterClass(&__CFSocketClass);
730 }
731
732 CFTypeID CFSocketGetTypeID(void) {
733 return __kCFSocketTypeID;
734 }
735
736 CFSocketError CFSocketSetAddress(CFSocketRef s, CFDataRef address) {
737 const uint8_t *name;
738 SInt32 namelen, result = 0;
739 __CFGenericValidateType(s, __kCFSocketTypeID);
740 if (NULL == address) return -1;
741 name = CFDataGetBytePtr(address);
742 namelen = CFDataGetLength(address);
743 __CFSocketLock(s);
744 if (__CFSocketIsValid(s) && INVALID_SOCKET != s->_socket && NULL != name && 0 < namelen) {
745 result = bind(s->_socket, (struct sockaddr *)name, namelen);
746 if (0 == result) {
747 __CFSocketEstablishAddress(s);
748 listen(s->_socket, 256);
749 }
750 }
751 if (NULL == s->_address && NULL != name && 0 < namelen && 0 == result) {
752 s->_address = CFDataCreateCopy(CFGetAllocator(s), address);
753 }
754 __CFSocketUnlock(s);
755 //??? should return errno
756 return result;
757 }
758
759 __private_extern__ void CFSocketSetAcceptBacklog(CFSocketRef s, CFIndex limit) {
760 __CFGenericValidateType(s, __kCFSocketTypeID);
761 __CFSocketLock(s);
762 if (__CFSocketIsValid(s) && INVALID_SOCKET != s->_socket) {
763 listen(s->_socket, limit);
764 }
765 __CFSocketUnlock(s);
766 }
767
768 __private_extern__ void CFSocketSetMaximumQueueLength(CFSocketRef s, CFIndex length) {
769 __CFGenericValidateType(s, __kCFSocketTypeID);
770 __CFSocketLock(s);
771 if (__CFSocketIsValid(s)) {
772 s->_maxQueueLen = length;
773 }
774 __CFSocketUnlock(s);
775 }
776
777 CFSocketError CFSocketConnectToAddress(CFSocketRef s, CFDataRef address, CFTimeInterval timeout) {
778 //??? need error handling, retries
779 const uint8_t *name;
780 SInt32 namelen, result = 0, connect_err = 0, flags;
781 UInt32 yes = 1, no = 0;
782 Boolean wasBlocking = true;
783 #if !defined(__WIN32__)
784 __CFGenericValidateType(s, __kCFSocketTypeID);
785 name = CFDataGetBytePtr(address);
786 namelen = CFDataGetLength(address);
787 __CFSocketLock(s);
788 if (__CFSocketIsValid(s) && INVALID_SOCKET != s->_socket && NULL != name && 0 < namelen) {
789 #if !defined(__WIN32__)
790 flags = fcntl(s->_socket, F_GETFL, 0);
791 if (flags >= 0) wasBlocking = ((flags & O_NONBLOCK) == 0);
792 #endif
793 if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(s->_socket, FIONBIO, &yes);
794 result = connect(s->_socket, (struct sockaddr *)name, namelen);
795 #if defined(__WIN32__)
796 if (result != 0 && WSAGetLastError() == WSAEWOULDBLOCK) connect_err = EINPROGRESS;
797 #else
798 if (result != 0) connect_err = thread_errno();
799 #endif
800 #if defined(LOG_CFSOCKET)
801 printf("connection attempt returns %d error %d on socket %d (flags 0x%x blocking %d)\n", result, connect_err, s->_socket, flags, wasBlocking);
802 #endif
803 if (EINPROGRESS == connect_err && timeout >= 0.0) {
804 /* select on socket */
805 CFMutableDataRef fds = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
806 SInt32 nrfds;
807 struct timeval tv;
808 __CFSocketFdSet(s->_socket, fds);
809 tv.tv_sec = (0 >= timeout || INT_MAX <= timeout) ? INT_MAX : (int)(float)floor(timeout);
810 tv.tv_usec = (int)((timeout - floor(timeout)) * 1.0E6);
811 nrfds = select(__CFSocketFdGetSize(fds), NULL, (fd_set *)CFDataGetMutableBytePtr(fds), NULL, &tv);
812 result = (nrfds > 0) ? 0 : -1;
813 CFRelease(fds);
814 #if defined(LOG_CFSOCKET)
815 printf("timed connection attempt %s on socket %d\n", (result == 0) ? "succeeds" : "fails", s->_socket);
816 #endif
817 }
818 if (wasBlocking && (timeout > 0.0 || timeout < 0.0)) ioctlsocket(s->_socket, FIONBIO, &no);
819 if (0 == result) {
820 __CFSocketEstablishPeerAddress(s);
821 if (NULL == s->_peerAddress && NULL != name && 0 < namelen && __CFSocketIsConnectionOriented(s)) {
822 s->_peerAddress = CFDataCreateCopy(CFGetAllocator(s), address);
823 }
824 }
825 if (EINPROGRESS == connect_err && timeout < 0.0) {
826 result = 0;
827 #if defined(LOG_CFSOCKET)
828 printf("connection attempt continues in background on socket %d\n", s->_socket);
829 #endif
830 }
831 }
832 __CFSocketUnlock(s);
833 //??? should return errno
834 #endif
835 return result;
836 }
837
838 CFSocketRef CFSocketCreate(CFAllocatorRef allocator, SInt32 protocolFamily, SInt32 socketType, SInt32 protocol, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
839 CFSocketNativeHandle sock = INVALID_SOCKET;
840 CFSocketRef s = NULL;
841 if (0 >= protocolFamily) protocolFamily = PF_INET;
842 if (PF_INET == protocolFamily) {
843 if (0 >= socketType) socketType = SOCK_STREAM;
844 if (0 >= protocol && SOCK_STREAM == socketType) protocol = IPPROTO_TCP;
845 if (0 >= protocol && SOCK_DGRAM == socketType) protocol = IPPROTO_UDP;
846 }
847 #if !defined(__WIN32__)
848 if (PF_LOCAL == protocolFamily && 0 >= socketType) socketType = SOCK_STREAM;
849 #endif
850 /* Needs to be initialized at this point for Windows, before socket() */
851 if (NULL == __CFReadSockets) __CFSocketInitializeSockets();
852 sock = socket(protocolFamily, socketType, protocol);
853 if (INVALID_SOCKET != sock) {
854 s = CFSocketCreateWithNative(allocator, sock, callBackTypes, callout, context);
855 }
856 return s;
857 }
858
859 CFSocketRef CFSocketCreateWithNative(CFAllocatorRef allocator, CFSocketNativeHandle sock, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
860 CFSocketRef memory;
861 int typeSize = sizeof(memory->_socketType);
862 __CFSpinLock(&__CFActiveSocketsLock);
863 if (NULL == __CFReadSockets) __CFSocketInitializeSockets();
864 __CFSpinUnlock(&__CFActiveSocketsLock);
865 __CFSpinLock(&__CFAllSocketsLock);
866 if (NULL == __CFAllSockets) {
867 __CFAllSockets = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
868 }
869 if (INVALID_SOCKET != sock && CFDictionaryGetValueIfPresent(__CFAllSockets, (void *)sock, (const void **)&memory)) {
870 __CFSpinUnlock(&__CFAllSocketsLock);
871 CFRetain(memory);
872 return memory;
873 }
874 memory = (CFSocketRef)_CFRuntimeCreateInstance(allocator, __kCFSocketTypeID, sizeof(struct __CFSocket) - sizeof(CFRuntimeBase), NULL);
875 if (NULL == memory) {
876 __CFSpinUnlock(&__CFAllSocketsLock);
877 return NULL;
878 }
879 __CFSocketSetCallBackTypes(memory, callBackTypes);
880 if (INVALID_SOCKET != sock) __CFSocketSetValid(memory);
881 __CFSocketUnsetWriteSignalled(memory);
882 __CFSocketUnsetReadSignalled(memory);
883 memory->_flags = ((callBackTypes & (~kCFSocketConnectCallBack)) & (~kCFSocketWriteCallBack)) | kCFSocketCloseOnInvalidate;
884 memory->_lock = 0;
885 memory->_writeLock = 0;
886 memory->_socket = sock;
887 if (INVALID_SOCKET == sock || 0 != getsockopt(sock, SOL_SOCKET, SO_TYPE, &(memory->_socketType), &typeSize)) memory->_socketType = 0;
888 memory->_errorCode = 0;
889 memory->_address = NULL;
890 memory->_peerAddress = NULL;
891 memory->_socketSetCount = 0;
892 memory->_source = NULL;
893 if (INVALID_SOCKET != sock) {
894 memory->_runLoops = CFArrayCreateMutable(allocator, 0, NULL);
895 } else {
896 memory->_runLoops = NULL;
897 }
898 memory->_callout = callout;
899 memory->_dataQueue = NULL;
900 memory->_addressQueue = NULL;
901 memory->_maxQueueLen = 0;
902 memory->_context.info = 0;
903 memory->_context.retain = 0;
904 memory->_context.release = 0;
905 memory->_context.copyDescription = 0;
906 if (INVALID_SOCKET != sock) CFDictionaryAddValue(__CFAllSockets, (void *)sock, memory);
907 __CFSpinUnlock(&__CFAllSocketsLock);
908 if (NULL != context) {
909 void *contextInfo = context->retain ? (void *)context->retain(context->info) : context->info;
910 __CFSocketLock(memory);
911 memory->_context.retain = context->retain;
912 memory->_context.release = context->release;
913 memory->_context.copyDescription = context->copyDescription;
914 memory->_context.info = contextInfo;
915 __CFSocketUnlock(memory);
916 }
917 return memory;
918 }
919
920 CFSocketRef CFSocketCreateWithSocketSignature(CFAllocatorRef allocator, const CFSocketSignature *signature, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context) {
921 CFSocketRef s = CFSocketCreate(allocator, signature->protocolFamily, signature->socketType, signature->protocol, callBackTypes, callout, context);
922 if (NULL != s && (!CFSocketIsValid(s) || kCFSocketSuccess != CFSocketSetAddress(s, signature->address))) {
923 CFSocketInvalidate(s);
924 CFRelease(s);
925 s = NULL;
926 }
927 return s;
928 }
929
930 CFSocketRef CFSocketCreateConnectedToSocketSignature(CFAllocatorRef allocator, const CFSocketSignature *signature, CFOptionFlags callBackTypes, CFSocketCallBack callout, const CFSocketContext *context, CFTimeInterval timeout) {
931 CFSocketRef s = CFSocketCreate(allocator, signature->protocolFamily, signature->socketType, signature->protocol, callBackTypes, callout, context);
932 if (NULL != s && (!CFSocketIsValid(s) || kCFSocketSuccess != CFSocketConnectToAddress(s, signature->address, timeout))) {
933 CFSocketInvalidate(s);
934 CFRelease(s);
935 s = NULL;
936 }
937 return s;
938 }
939
940 void CFSocketInvalidate(CFSocketRef s) {
941 __CFGenericValidateType(s, __kCFSocketTypeID);
942 CFRetain(s);
943 __CFSpinLock(&__CFAllSocketsLock);
944 __CFSocketLock(s);
945 if (__CFSocketIsValid(s)) {
946 SInt32 idx;
947 CFRunLoopSourceRef source;
948 void *contextInfo = NULL;
949 void (*contextRelease)(const void *info) = NULL;
950 __CFSocketUnsetValid(s);
951 __CFSocketUnsetWriteSignalled(s);
952 __CFSocketUnsetReadSignalled(s);
953 __CFSpinLock(&__CFActiveSocketsLock);
954 if (NULL == __CFReadSockets) __CFSocketInitializeSockets();
955 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
956 if (0 <= idx) {
957 CFArrayRemoveValueAtIndex(__CFWriteSockets, idx);
958 __CFSocketFdClr(s->_socket, __CFWriteSocketsFds);
959 }
960 idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
961 if (0 <= idx) {
962 CFArrayRemoveValueAtIndex(__CFReadSockets, idx);
963 __CFSocketFdClr(s->_socket, __CFReadSocketsFds);
964 }
965 __CFSpinUnlock(&__CFActiveSocketsLock);
966 CFDictionaryRemoveValue(__CFAllSockets, (void *)(s->_socket));
967 if ((s->_flags & kCFSocketCloseOnInvalidate) != 0) closesocket(s->_socket);
968 s->_socket = INVALID_SOCKET;
969 if (NULL != s->_peerAddress) {
970 CFRelease(s->_peerAddress);
971 s->_peerAddress = NULL;
972 }
973 if (NULL != s->_dataQueue) {
974 CFRelease(s->_dataQueue);
975 s->_dataQueue = NULL;
976 }
977 if (NULL != s->_addressQueue) {
978 CFRelease(s->_addressQueue);
979 s->_addressQueue = NULL;
980 }
981 s->_socketSetCount = 0;
982 for (idx = CFArrayGetCount(s->_runLoops); idx--;) {
983 CFRunLoopWakeUp((CFRunLoopRef)CFArrayGetValueAtIndex(s->_runLoops, idx));
984 }
985 CFRelease(s->_runLoops);
986 s->_runLoops = NULL;
987 source = s->_source;
988 s->_source = NULL;
989 contextInfo = s->_context.info;
990 contextRelease = s->_context.release;
991 s->_context.info = 0;
992 s->_context.retain = 0;
993 s->_context.release = 0;
994 s->_context.copyDescription = 0;
995 __CFSocketUnlock(s);
996 if (NULL != contextRelease) {
997 contextRelease(contextInfo);
998 }
999 if (NULL != source) {
1000 CFRunLoopSourceInvalidate(source);
1001 CFRelease(source);
1002 }
1003 } else {
1004 __CFSocketUnlock(s);
1005 }
1006 __CFSpinUnlock(&__CFAllSocketsLock);
1007 CFRelease(s);
1008 }
1009
1010 Boolean CFSocketIsValid(CFSocketRef s) {
1011 __CFGenericValidateType(s, __kCFSocketTypeID);
1012 return __CFSocketIsValid(s);
1013 }
1014
1015 CFSocketNativeHandle CFSocketGetNative(CFSocketRef s) {
1016 __CFGenericValidateType(s, __kCFSocketTypeID);
1017 return s->_socket;
1018 }
1019
1020 CFDataRef CFSocketCopyAddress(CFSocketRef s) {
1021 CFDataRef result = NULL;
1022 __CFGenericValidateType(s, __kCFSocketTypeID);
1023 __CFSocketLock(s);
1024 __CFSocketEstablishAddress(s);
1025 if (NULL != s->_address) {
1026 result = CFRetain(s->_address);
1027 }
1028 __CFSocketUnlock(s);
1029 return result;
1030 }
1031
1032 CFDataRef CFSocketCopyPeerAddress(CFSocketRef s) {
1033 CFDataRef result = NULL;
1034 __CFGenericValidateType(s, __kCFSocketTypeID);
1035 __CFSocketLock(s);
1036 __CFSocketEstablishPeerAddress(s);
1037 if (NULL != s->_peerAddress) {
1038 result = CFRetain(s->_peerAddress);
1039 }
1040 __CFSocketUnlock(s);
1041 return result;
1042 }
1043
1044 void CFSocketGetContext(CFSocketRef s, CFSocketContext *context) {
1045 __CFGenericValidateType(s, __kCFSocketTypeID);
1046 CFAssert1(0 == context->version, __kCFLogAssertion, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__);
1047 *context = s->_context;
1048 }
1049
1050 __private_extern__ void CFSocketReschedule(CFSocketRef s) {
1051 CFSocketEnableCallBacks(s, __CFSocketCallBackTypes(s));
1052 }
1053
1054 CFOptionFlags CFSocketGetSocketFlags(CFSocketRef s) {
1055 __CFGenericValidateType(s, __kCFSocketTypeID);
1056 return (s->_flags & (~(kCFSocketConnectCallBack | (0xff << 24))));
1057 }
1058
1059 void CFSocketSetSocketFlags(CFSocketRef s, CFOptionFlags flags) {
1060 __CFGenericValidateType(s, __kCFSocketTypeID);
1061 __CFSocketLock(s);
1062 flags &= ~(kCFSocketConnectCallBack | (0xff << 24));
1063 #if defined(LOG_CFSOCKET)
1064 printf("setting flags for socket %d with %x, flags going from %x to %x\n", s->_socket, flags, s->_flags, (s->_flags & (kCFSocketConnectCallBack | (0xff << 24))) | flags);
1065 #endif
1066 s->_flags &= (kCFSocketConnectCallBack | (0xff << 24));
1067 s->_flags |= flags;
1068 __CFSocketUnlock(s);
1069 }
1070
1071 void CFSocketDisableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) {
1072 Boolean wakeup = false;
1073 uint8_t c = 'u', readCallBackType;
1074 __CFGenericValidateType(s, __kCFSocketTypeID);
1075 __CFSocketLock(s);
1076 if (__CFSocketIsValid(s) && 0 < s->_socketSetCount) {
1077 callBackTypes &= __CFSocketCallBackTypes(s);
1078 readCallBackType = __CFSocketReadCallBackType(s);
1079 s->_flags |= (callBackTypes << 24);
1080 #if defined(LOG_CFSOCKET)
1081 printf("unscheduling socket %d with flags 0x%x for types 0x%x\n", s->_socket, s->_flags, callBackTypes);
1082 #endif
1083 __CFSpinLock(&__CFActiveSocketsLock);
1084 if (NULL == __CFReadSockets) __CFSocketInitializeSockets();
1085 if ((readCallBackType == kCFSocketAcceptCallBack) || !__CFSocketIsConnectionOriented(s)) s->_flags |= kCFSocketConnectCallBack;
1086 if (((callBackTypes & kCFSocketWriteCallBack) != 0) || (((callBackTypes & kCFSocketConnectCallBack) != 0) && ((s->_flags & kCFSocketConnectCallBack) == 0))) {
1087 if (__CFSocketFdClr(s->_socket, __CFWriteSocketsFds)) {
1088 // do not wake up the socket manager thread if all relevant write callbacks are disabled
1089 CFOptionFlags writeCallBacksAvailable = __CFSocketCallBackTypes(s) & (kCFSocketWriteCallBack | kCFSocketConnectCallBack);
1090 if ((s->_flags & kCFSocketConnectCallBack) != 0) writeCallBacksAvailable &= ~kCFSocketConnectCallBack;
1091 if (((s->_flags >> 24) & writeCallBacksAvailable) != writeCallBacksAvailable) wakeup = true;
1092 }
1093 }
1094 if (readCallBackType != kCFSocketNoCallBack && (callBackTypes & readCallBackType) != 0) {
1095 if (__CFSocketFdClr(s->_socket, __CFReadSocketsFds)) {
1096 // do not wake up the socket manager thread if callback type is read
1097 if (readCallBackType != kCFSocketReadCallBack) wakeup = true;
1098 }
1099 }
1100 __CFSpinUnlock(&__CFActiveSocketsLock);
1101 }
1102 __CFSocketUnlock(s);
1103 if (wakeup) {
1104 if (NULL == __CFSocketManagerThread) {
1105 __CFSocketManagerThread = __CFStartSimpleThread(__CFSocketManager, 0);
1106 }
1107 send(__CFWakeupSocketPair[0], &c, sizeof(c), 0);
1108 }
1109 }
1110
1111 void CFSocketEnableCallBacks(CFSocketRef s, CFOptionFlags callBackTypes) {
1112 Boolean wakeup = false;
1113 uint8_t c = 'r', readCallBackType;
1114 __CFGenericValidateType(s, __kCFSocketTypeID);
1115 __CFSocketLock(s);
1116 if (__CFSocketIsValid(s) && 0 < s->_socketSetCount) {
1117 callBackTypes &= __CFSocketCallBackTypes(s);
1118 readCallBackType = __CFSocketReadCallBackType(s);
1119 s->_flags &= ~(callBackTypes << 24);
1120 #if defined(LOG_CFSOCKET)
1121 printf("rescheduling socket %d with flags 0x%x for types 0x%x\n", s->_socket, s->_flags, callBackTypes);
1122 #endif
1123 __CFSpinLock(&__CFActiveSocketsLock);
1124 if (NULL == __CFReadSockets) __CFSocketInitializeSockets();
1125 /* we will wait for connection only for connection-oriented, non-rendezvous sockets that are not already connected */
1126 if ((readCallBackType == kCFSocketAcceptCallBack) || !__CFSocketIsConnectionOriented(s)) s->_flags |= kCFSocketConnectCallBack;
1127 if (((callBackTypes & kCFSocketWriteCallBack) != 0) || (((callBackTypes & kCFSocketConnectCallBack) != 0) && ((s->_flags & kCFSocketConnectCallBack) == 0))) {
1128 SInt32 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
1129 if (kCFNotFound == idx) CFArrayAppendValue(__CFWriteSockets, s);
1130 if (__CFSocketFdSet(s->_socket, __CFWriteSocketsFds)) wakeup = true;
1131 }
1132 if (readCallBackType != kCFSocketNoCallBack && (callBackTypes & readCallBackType) != 0) {
1133 SInt32 idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
1134 if (kCFNotFound == idx) CFArrayAppendValue(__CFReadSockets, s);
1135 if (__CFSocketFdSet(s->_socket, __CFReadSocketsFds)) wakeup = true;
1136 }
1137 __CFSpinUnlock(&__CFActiveSocketsLock);
1138 }
1139 __CFSocketUnlock(s);
1140 if (wakeup) {
1141 if (NULL == __CFSocketManagerThread) {
1142 __CFSocketManagerThread = __CFStartSimpleThread(__CFSocketManager, 0);
1143 }
1144 send(__CFWakeupSocketPair[0], &c, sizeof(c), 0);
1145 }
1146 }
1147
1148 static void __CFSocketSchedule(void *info, CFRunLoopRef rl, CFStringRef mode) {
1149 CFSocketRef s = info;
1150 Boolean wakeup = false;
1151 uint8_t c = 's', readCallBackType, callBackTypes;
1152 __CFSocketLock(s);
1153 //??? also need to arrange delivery of all pending data
1154 if (__CFSocketIsValid(s)) {
1155 CFArrayAppendValue(s->_runLoops, rl);
1156 s->_socketSetCount++;
1157 if (1 == s->_socketSetCount) {
1158 #if defined(LOG_CFSOCKET)
1159 printf("scheduling socket %d\n", s->_socket);
1160 #endif
1161 callBackTypes = __CFSocketCallBackTypes(s);
1162 readCallBackType = __CFSocketReadCallBackType(s);
1163 __CFSpinLock(&__CFActiveSocketsLock);
1164 if (NULL == __CFReadSockets) __CFSocketInitializeSockets();
1165 /* we will wait for connection only for connection-oriented, non-rendezvous sockets that are not already connected */
1166 if ((readCallBackType == kCFSocketAcceptCallBack) || !__CFSocketIsConnectionOriented(s)) s->_flags |= kCFSocketConnectCallBack;
1167 if (((callBackTypes & kCFSocketWriteCallBack) != 0) || (((callBackTypes & kCFSocketConnectCallBack) != 0) && ((s->_flags & kCFSocketConnectCallBack) == 0))) {
1168 SInt32 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
1169 if (kCFNotFound == idx) CFArrayAppendValue(__CFWriteSockets, s);
1170 if (__CFSocketFdSet(s->_socket, __CFWriteSocketsFds)) wakeup = true;
1171 }
1172 if (readCallBackType != kCFSocketNoCallBack) {
1173 SInt32 idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
1174 if (kCFNotFound == idx) CFArrayAppendValue(__CFReadSockets, s);
1175 if (__CFSocketFdSet(s->_socket, __CFReadSocketsFds)) wakeup = true;
1176 }
1177 __CFSpinUnlock(&__CFActiveSocketsLock);
1178 }
1179 }
1180 __CFSocketUnlock(s);
1181 if (wakeup) {
1182 if (NULL == __CFSocketManagerThread) {
1183 __CFSocketManagerThread = __CFStartSimpleThread(__CFSocketManager, 0);
1184 }
1185 send(__CFWakeupSocketPair[0], &c, sizeof(c), 0);
1186 }
1187 }
1188
1189 static void __CFSocketCancel(void *info, CFRunLoopRef rl, CFStringRef mode) {
1190 CFSocketRef s = info;
1191 SInt32 idx;
1192 __CFSocketLock(s);
1193 s->_socketSetCount--;
1194 if (0 == s->_socketSetCount) {
1195 __CFSpinLock(&__CFActiveSocketsLock);
1196 if (NULL == __CFReadSockets) __CFSocketInitializeSockets();
1197 idx = CFArrayGetFirstIndexOfValue(__CFWriteSockets, CFRangeMake(0, CFArrayGetCount(__CFWriteSockets)), s);
1198 if (0 <= idx) {
1199 CFArrayRemoveValueAtIndex(__CFWriteSockets, idx);
1200 __CFSocketFdClr(s->_socket, __CFWriteSocketsFds);
1201 }
1202 idx = CFArrayGetFirstIndexOfValue(__CFReadSockets, CFRangeMake(0, CFArrayGetCount(__CFReadSockets)), s);
1203 if (0 <= idx) {
1204 CFArrayRemoveValueAtIndex(__CFReadSockets, idx);
1205 __CFSocketFdClr(s->_socket, __CFReadSocketsFds);
1206 }
1207 __CFSpinUnlock(&__CFActiveSocketsLock);
1208 }
1209 if (NULL != s->_runLoops) {
1210 idx = CFArrayGetFirstIndexOfValue(s->_runLoops, CFRangeMake(0, CFArrayGetCount(s->_runLoops)), rl);
1211 if (0 <= idx) CFArrayRemoveValueAtIndex(s->_runLoops, idx);
1212 }
1213 __CFSocketUnlock(s);
1214 }
1215
1216 static void __CFSocketPerform(void *info) {
1217 CFSocketRef s = info;
1218 CFDataRef data = NULL;
1219 CFDataRef address = NULL;
1220 CFSocketNativeHandle sock = INVALID_SOCKET;
1221 CFSocketCallBack callout = NULL;
1222 void *contextInfo = NULL;
1223 SInt32 errorCode = 0;
1224 Boolean wakeup = false, readSignalled = false, writeSignalled = false, connectSignalled = false, calledOut = false;
1225 uint8_t c = 'p', readCallBackType, callBackTypes;
1226 CFRunLoopRef rl = NULL;
1227
1228 __CFSocketLock(s);
1229 if (!__CFSocketIsValid(s)) {
1230 __CFSocketUnlock(s);
1231 return;
1232 }
1233 callBackTypes = __CFSocketCallBackTypes(s);
1234 readCallBackType = __CFSocketReadCallBackType(s);
1235 readSignalled = __CFSocketIsReadSignalled(s);
1236 writeSignalled = __CFSocketIsWriteSignalled(s);
1237 connectSignalled = writeSignalled && ((s->_flags & kCFSocketConnectCallBack) == 0);
1238 __CFSocketUnsetReadSignalled(s);
1239 __CFSocketUnsetWriteSignalled(s);
1240 callout = s->_callout;
1241 contextInfo = s->_context.info;
1242 #if defined(LOG_CFSOCKET)
1243 printf("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);
1244 #endif
1245 if (kCFSocketDataCallBack == readCallBackType) {
1246 if (NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
1247 data = CFArrayGetValueAtIndex(s->_dataQueue, 0);
1248 CFRetain(data);
1249 CFArrayRemoveValueAtIndex(s->_dataQueue, 0);
1250 address = CFArrayGetValueAtIndex(s->_addressQueue, 0);
1251 CFRetain(address);
1252 CFArrayRemoveValueAtIndex(s->_addressQueue, 0);
1253 }
1254 } else if (kCFSocketAcceptCallBack == readCallBackType) {
1255 if (NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
1256 sock = (CFSocketNativeHandle)CFArrayGetValueAtIndex(s->_dataQueue, 0);
1257 CFArrayRemoveValueAtIndex(s->_dataQueue, 0);
1258 address = CFArrayGetValueAtIndex(s->_addressQueue, 0);
1259 CFRetain(address);
1260 CFArrayRemoveValueAtIndex(s->_addressQueue, 0);
1261 }
1262 }
1263 if (writeSignalled) {
1264 errorCode = s->_errorCode;
1265 s->_flags |= kCFSocketConnectCallBack;
1266 }
1267 __CFSocketUnlock(s);
1268 if ((callBackTypes & kCFSocketConnectCallBack) != 0) {
1269 if (connectSignalled && (!calledOut || CFSocketIsValid(s))) {
1270 if (errorCode) {
1271 #if defined(LOG_CFSOCKET)
1272 printf("perform calling out error %d to socket %d\n", errorCode, s->_socket);
1273 #endif
1274 if (callout) callout(s, kCFSocketConnectCallBack, NULL, &errorCode, contextInfo);
1275 calledOut = true;
1276 } else {
1277 #if defined(LOG_CFSOCKET)
1278 printf("perform calling out connect to socket %d\n", s->_socket);
1279 #endif
1280 if (callout) callout(s, kCFSocketConnectCallBack, NULL, NULL, contextInfo);
1281 calledOut = true;
1282 }
1283 }
1284 }
1285 if (kCFSocketDataCallBack == readCallBackType) {
1286 if (NULL != data && (!calledOut || CFSocketIsValid(s))) {
1287 SInt32 datalen = CFDataGetLength(data);
1288 #if defined(LOG_CFSOCKET)
1289 printf("perform calling out data of length %d to socket %d\n", datalen, s->_socket);
1290 #endif
1291 if (callout) callout(s, kCFSocketDataCallBack, address, data, contextInfo);
1292 calledOut = true;
1293 CFRelease(data);
1294 CFRelease(address);
1295 if (0 == datalen) CFSocketInvalidate(s);
1296 }
1297 } else if (kCFSocketAcceptCallBack == readCallBackType) {
1298 if (INVALID_SOCKET != sock && (!calledOut || CFSocketIsValid(s))) {
1299 #if defined(LOG_CFSOCKET)
1300 printf("perform calling out accept of socket %d to socket %d\n", sock, s->_socket);
1301 #endif
1302 if (callout) callout(s, kCFSocketAcceptCallBack, address, &sock, contextInfo);
1303 calledOut = true;
1304 CFRelease(address);
1305 }
1306 } else if (kCFSocketReadCallBack == readCallBackType) {
1307 if (readSignalled && (!calledOut || CFSocketIsValid(s))) {
1308 #if defined(LOG_CFSOCKET)
1309 printf("perform calling out read to socket %d\n", s->_socket);
1310 #endif
1311 if (callout) callout(s, kCFSocketReadCallBack, NULL, NULL, contextInfo);
1312 calledOut = true;
1313 }
1314 }
1315 if ((callBackTypes & kCFSocketWriteCallBack) != 0) {
1316 if (writeSignalled && !errorCode && (!calledOut || CFSocketIsValid(s))) {
1317 #if defined(LOG_CFSOCKET)
1318 printf("perform calling out write to socket %d\n", s->_socket);
1319 #endif
1320 if (callout) callout(s, kCFSocketWriteCallBack, NULL, NULL, contextInfo);
1321 calledOut = true;
1322 }
1323 }
1324 __CFSocketLock(s);
1325 if (__CFSocketIsValid(s) && kCFSocketNoCallBack != readCallBackType) {
1326 if ((kCFSocketDataCallBack == readCallBackType || kCFSocketAcceptCallBack == readCallBackType) && NULL != s->_dataQueue && 0 < CFArrayGetCount(s->_dataQueue)) {
1327 CFRunLoopSourceSignal(s->_source);
1328 #if defined(LOG_CFSOCKET)
1329 printf("perform signaling source for socket %d with flags 0x%x\n", s->_socket, s->_flags);
1330 #endif
1331 rl = __CFSocketCopyRunLoopToWakeUp(s);
1332 }
1333 if (readSignalled && 0 < s->_socketSetCount && (s->_flags & readCallBackType) != 0 && ((s->_flags >> 24) & readCallBackType) == 0) {
1334 __CFSpinLock(&__CFActiveSocketsLock);
1335 /* restore socket to fds */
1336 if (__CFSocketFdSet(s->_socket, __CFReadSocketsFds)) wakeup = true;
1337 __CFSpinUnlock(&__CFActiveSocketsLock);
1338 }
1339 }
1340 if (__CFSocketIsValid(s) && (callBackTypes & kCFSocketWriteCallBack) != 0) {
1341 if (writeSignalled && 0 < s->_socketSetCount && (s->_flags & kCFSocketWriteCallBack) != 0 && ((s->_flags >> 24) & kCFSocketWriteCallBack) == 0) {
1342 __CFSpinLock(&__CFActiveSocketsLock);
1343 /* restore socket to fds */
1344 if (__CFSocketFdSet(s->_socket, __CFWriteSocketsFds)) wakeup = true;
1345 __CFSpinUnlock(&__CFActiveSocketsLock);
1346 }
1347 }
1348 __CFSocketUnlock(s);
1349 if (wakeup) {
1350 if (NULL == __CFSocketManagerThread) {
1351 __CFSocketManagerThread = __CFStartSimpleThread(__CFSocketManager, 0);
1352 }
1353 send(__CFWakeupSocketPair[0], &c, sizeof(c), 0);
1354 }
1355 if (NULL != rl) {
1356 CFRunLoopWakeUp(rl);
1357 CFRelease(rl);
1358 }
1359 }
1360
1361 CFRunLoopSourceRef CFSocketCreateRunLoopSource(CFAllocatorRef allocator, CFSocketRef s, CFIndex order) {
1362 CFRunLoopSourceRef result = NULL;
1363 __CFGenericValidateType(s, __kCFSocketTypeID);
1364 __CFSocketLock(s);
1365 if (__CFSocketIsValid(s)) {
1366 if (NULL == s->_source) {
1367 CFRunLoopSourceContext context;
1368 context.version = 0;
1369 context.info = (void *)s;
1370 context.retain = (const void *(*)(const void *))CFRetain;
1371 context.release = (void (*)(const void *))CFRelease;
1372 context.copyDescription = (CFStringRef (*)(const void *))CFCopyDescription;
1373 context.equal = (Boolean (*)(const void *, const void *))CFEqual;
1374 context.hash = (CFHashCode (*)(const void *))CFHash;
1375 context.schedule = __CFSocketSchedule;
1376 context.cancel = __CFSocketCancel;
1377 context.perform = __CFSocketPerform;
1378 s->_source = CFRunLoopSourceCreate(allocator, order, &context);
1379 }
1380 CFRetain(s->_source); /* This retain is for the receiver */
1381 result = s->_source;
1382 }
1383 __CFSocketUnlock(s);
1384 return result;
1385 }
1386
1387 //??? need timeout, error handling, retries
1388 CFSocketError CFSocketSendData(CFSocketRef s, CFDataRef address, CFDataRef data, CFTimeInterval timeout) {
1389 const uint8_t *dataptr, *addrptr = NULL;
1390 SInt32 datalen, addrlen = 0, size = 0;
1391 CFSocketNativeHandle sock = INVALID_SOCKET;
1392 struct timeval tv;
1393 __CFGenericValidateType(s, __kCFSocketTypeID);
1394 if (address) {
1395 addrptr = CFDataGetBytePtr(address);
1396 addrlen = CFDataGetLength(address);
1397 }
1398 dataptr = CFDataGetBytePtr(data);
1399 datalen = CFDataGetLength(data);
1400 __CFSocketLock(s);
1401 if (__CFSocketIsValid(s)) sock = s->_socket;
1402 __CFSocketUnlock(s);
1403 if (INVALID_SOCKET != sock) {
1404 CFRetain(s);
1405 __CFSocketWriteLock(s);
1406 tv.tv_sec = (0 >= timeout || INT_MAX <= timeout) ? INT_MAX : (int)(float)floor(timeout);
1407 tv.tv_usec = (int)((timeout - floor(timeout)) * 1.0E6);
1408 setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
1409 if (NULL != addrptr && 0 < addrlen) {
1410 size = sendto(sock, dataptr, datalen, 0, (struct sockaddr *)addrptr, addrlen);
1411 } else {
1412 size = send(sock, dataptr, datalen, 0);
1413 }
1414 #if defined(LOG_CFSOCKET)
1415 printf("wrote %d bytes to socket %d\n", size, s->_socket);
1416 #endif
1417 __CFSocketWriteUnlock(s);
1418 CFRelease(s);
1419 }
1420 return (size > 0) ? kCFSocketSuccess : kCFSocketError;
1421 }
1422
1423 typedef struct {
1424 CFSocketError *error;
1425 CFPropertyListRef *value;
1426 CFDataRef *address;
1427 } __CFSocketNameRegistryResponse;
1428
1429 static void __CFSocketHandleNameRegistryReply(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) {
1430 CFDataRef replyData = (CFDataRef)data;
1431 __CFSocketNameRegistryResponse *response = (__CFSocketNameRegistryResponse *)info;
1432 CFDictionaryRef replyDictionary = NULL;
1433 CFPropertyListRef value;
1434 replyDictionary = CFPropertyListCreateFromXMLData(NULL, replyData, kCFPropertyListImmutable, NULL);
1435 if (NULL != response->error) *(response->error) = kCFSocketError;
1436 if (NULL != replyDictionary) {
1437 if (CFGetTypeID((CFTypeRef)replyDictionary) == CFDictionaryGetTypeID() && NULL != (value = CFDictionaryGetValue(replyDictionary, kCFSocketResultKey))) {
1438 if (NULL != response->error) *(response->error) = kCFSocketSuccess;
1439 if (NULL != response->value) *(response->value) = CFRetain(value);
1440 if (NULL != response->address) *(response->address) = address ? CFDataCreateCopy(NULL, address) : NULL;
1441 }
1442 CFRelease(replyDictionary);
1443 }
1444 CFSocketInvalidate(s);
1445 }
1446
1447 static void __CFSocketSendNameRegistryRequest(CFSocketSignature *signature, CFDictionaryRef requestDictionary, __CFSocketNameRegistryResponse *response, CFTimeInterval timeout) {
1448 CFDataRef requestData = NULL;
1449 CFSocketContext context = {0, response, NULL, NULL, NULL};
1450 CFSocketRef s = NULL;
1451 CFRunLoopSourceRef source = NULL;
1452 if (NULL != response->error) *(response->error) = kCFSocketError;
1453 requestData = CFPropertyListCreateXMLData(NULL, requestDictionary);
1454 if (NULL != requestData) {
1455 if (NULL != response->error) *(response->error) = kCFSocketTimeout;
1456 s = CFSocketCreateConnectedToSocketSignature(NULL, signature, kCFSocketDataCallBack, __CFSocketHandleNameRegistryReply, &context, timeout);
1457 if (NULL != s) {
1458 if (kCFSocketSuccess == CFSocketSendData(s, NULL, requestData, timeout)) {
1459 source = CFSocketCreateRunLoopSource(NULL, s, 0);
1460 CFRunLoopAddSource(CFRunLoopGetCurrent(), source, __kCFSocketRegistryRequestRunLoopMode);
1461 CFRunLoopRunInMode(__kCFSocketRegistryRequestRunLoopMode, timeout, false);
1462 CFRelease(source);
1463 }
1464 CFSocketInvalidate(s);
1465 CFRelease(s);
1466 }
1467 CFRelease(requestData);
1468 }
1469 }
1470
1471 static void __CFSocketValidateSignature(const CFSocketSignature *providedSignature, CFSocketSignature *signature, uint16_t defaultPortNumber) {
1472 struct sockaddr_in sain, *sainp;
1473 memset(&sin, 0, sizeof(sain));
1474 #if !defined(__WIN32__)
1475 sain.sin_len = sizeof(sain);
1476 #endif
1477 sain.sin_family = AF_INET;
1478 sain.sin_port = htons(__CFSocketDefaultNameRegistryPortNumber);
1479 sain.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1480 if (NULL == providedSignature) {
1481 signature->protocolFamily = PF_INET;
1482 signature->socketType = SOCK_STREAM;
1483 signature->protocol = IPPROTO_TCP;
1484 signature->address = CFDataCreate(NULL, (uint8_t *)&sain, sizeof(sain));
1485 } else {
1486 signature->protocolFamily = providedSignature->protocolFamily;
1487 signature->socketType = providedSignature->socketType;
1488 signature->protocol = providedSignature->protocol;
1489 if (0 >= signature->protocolFamily) signature->protocolFamily = PF_INET;
1490 if (PF_INET == signature->protocolFamily) {
1491 if (0 >= signature->socketType) signature->socketType = SOCK_STREAM;
1492 if (0 >= signature->protocol && SOCK_STREAM == signature->socketType) signature->protocol = IPPROTO_TCP;
1493 if (0 >= signature->protocol && SOCK_DGRAM == signature->socketType) signature->protocol = IPPROTO_UDP;
1494 }
1495 if (NULL == providedSignature->address) {
1496 signature->address = CFDataCreate(NULL, (uint8_t *)&sain, sizeof(sain));
1497 } else {
1498 sainp = (struct sockaddr_in *)CFDataGetBytePtr(providedSignature->address);
1499 if ((int)sizeof(struct sockaddr_in) <= CFDataGetLength(providedSignature->address) && (AF_INET == sainp->sin_family || 0 == sainp->sin_family)) {
1500 #if !defined(__WIN32__)
1501 sain.sin_len = sizeof(sain);
1502 #endif
1503 sain.sin_family = AF_INET;
1504 sain.sin_port = sainp->sin_port;
1505 if (0 == sain.sin_port) sain.sin_port = htons(defaultPortNumber);
1506 sain.sin_addr.s_addr = sainp->sin_addr.s_addr;
1507 if (htonl(INADDR_ANY) == sain.sin_addr.s_addr) sain.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1508 signature->address = CFDataCreate(NULL, (uint8_t *)&sain, sizeof(sain));
1509 } else {
1510 signature->address = CFRetain(providedSignature->address);
1511 }
1512 }
1513 }
1514 }
1515
1516 CFSocketError CFSocketRegisterValue(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFPropertyListRef value) {
1517 CFSocketSignature signature;
1518 CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1519 CFSocketError retval = kCFSocketError;
1520 __CFSocketNameRegistryResponse response = {&retval, NULL, NULL};
1521 CFDictionaryAddValue(dictionary, kCFSocketCommandKey, kCFSocketRegisterCommand);
1522 CFDictionaryAddValue(dictionary, kCFSocketNameKey, name);
1523 if (NULL != value) CFDictionaryAddValue(dictionary, kCFSocketValueKey, value);
1524 __CFSocketValidateSignature(nameServerSignature, &signature, __CFSocketDefaultNameRegistryPortNumber);
1525 __CFSocketSendNameRegistryRequest(&signature, dictionary, &response, timeout);
1526 CFRelease(dictionary);
1527 CFRelease(signature.address);
1528 return retval;
1529 }
1530
1531 CFSocketError CFSocketCopyRegisteredValue(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFPropertyListRef *value, CFDataRef *serverAddress) {
1532 CFSocketSignature signature;
1533 CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(NULL, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1534 CFSocketError retval = kCFSocketError;
1535 __CFSocketNameRegistryResponse response = {&retval, value, serverAddress};
1536 CFDictionaryAddValue(dictionary, kCFSocketCommandKey, kCFSocketRetrieveCommand);
1537 CFDictionaryAddValue(dictionary, kCFSocketNameKey, name);
1538 __CFSocketValidateSignature(nameServerSignature, &signature, __CFSocketDefaultNameRegistryPortNumber);
1539 __CFSocketSendNameRegistryRequest(&signature, dictionary, &response, timeout);
1540 CFRelease(dictionary);
1541 CFRelease(signature.address);
1542 return retval;
1543 }
1544
1545 CFSocketError CFSocketRegisterSocketSignature(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, const CFSocketSignature *signature) {
1546 CFSocketSignature validatedSignature;
1547 CFMutableDataRef data = NULL;
1548 CFSocketError retval;
1549 CFIndex length;
1550 uint8_t bytes[4];
1551 if (NULL == signature) {
1552 retval = CFSocketUnregister(nameServerSignature, timeout, name);
1553 } else {
1554 __CFSocketValidateSignature(signature, &validatedSignature, 0);
1555 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) {
1556 retval = kCFSocketError;
1557 } else {
1558 data = CFDataCreateMutable(NULL, sizeof(bytes) + length);
1559 bytes[0] = validatedSignature.protocolFamily;
1560 bytes[1] = validatedSignature.socketType;
1561 bytes[2] = validatedSignature.protocol;
1562 bytes[3] = length;
1563 CFDataAppendBytes(data, bytes, sizeof(bytes));
1564 CFDataAppendBytes(data, CFDataGetBytePtr(validatedSignature.address), length);
1565 retval = CFSocketRegisterValue(nameServerSignature, timeout, name, data);
1566 CFRelease(data);
1567 }
1568 CFRelease(validatedSignature.address);
1569 }
1570 return retval;
1571 }
1572
1573 CFSocketError CFSocketCopyRegisteredSocketSignature(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name, CFSocketSignature *signature, CFDataRef *nameServerAddress) {
1574 CFDataRef data = NULL;
1575 CFSocketSignature returnedSignature;
1576 const uint8_t *ptr = NULL, *aptr = NULL;
1577 uint8_t *mptr;
1578 CFIndex length = 0;
1579 CFDataRef serverAddress = NULL;
1580 CFSocketError retval = CFSocketCopyRegisteredValue(nameServerSignature, timeout, name, (CFPropertyListRef *)&data, &serverAddress);
1581 if (NULL == data || CFGetTypeID(data) != CFDataGetTypeID() || NULL == (ptr = CFDataGetBytePtr(data)) || (length = CFDataGetLength(data)) < 4) retval = kCFSocketError;
1582 if (kCFSocketSuccess == retval && NULL != signature) {
1583 returnedSignature.protocolFamily = (SInt32)*ptr++;
1584 returnedSignature.socketType = (SInt32)*ptr++;
1585 returnedSignature.protocol = (SInt32)*ptr++;
1586 ptr++;
1587 returnedSignature.address = CFDataCreate(NULL, ptr, length - 4);
1588 __CFSocketValidateSignature(&returnedSignature, signature, 0);
1589 CFRelease(returnedSignature.address);
1590 ptr = CFDataGetBytePtr(signature->address);
1591 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) {
1592 CFMutableDataRef address = CFDataCreateMutableCopy(NULL, CFDataGetLength(signature->address), signature->address);
1593 mptr = CFDataGetMutableBytePtr(address);
1594 ((struct sockaddr_in *)mptr)->sin_addr = ((struct sockaddr_in *)aptr)->sin_addr;
1595 CFRelease(signature->address);
1596 signature->address = address;
1597 }
1598 if (NULL != nameServerAddress) *nameServerAddress = serverAddress ? CFRetain(serverAddress) : NULL;
1599 }
1600 if (NULL != data) CFRelease(data);
1601 if (NULL != serverAddress) CFRelease(serverAddress);
1602 return retval;
1603 }
1604
1605 CFSocketError CFSocketUnregister(const CFSocketSignature *nameServerSignature, CFTimeInterval timeout, CFStringRef name) {
1606 return CFSocketRegisterValue(nameServerSignature, timeout, name, NULL);
1607 }
1608
1609 CF_EXPORT void CFSocketSetDefaultNameRegistryPortNumber(uint16_t port) {
1610 __CFSocketDefaultNameRegistryPortNumber = port;
1611 }
1612
1613 CF_EXPORT uint16_t CFSocketGetDefaultNameRegistryPortNumber(void) {
1614 return __CFSocketDefaultNameRegistryPortNumber;
1615 }