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