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