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