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