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