1/* 2 * Copyright (c) 2000-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * FDHandler.c 26 * - hides the details of how to get a callback when a file descriptor 27 * has data available 28 * - wraps the CFSocket run-loop source 29 */ 30 31/* 32 * Modification History 33 * 34 * October 26, 2001 Dieter Siegmund (dieter@apple.com) 35 * - created (based on bootp/IPConfiguration.tproj/FDSet.c) 36 */ 37 38#include <stdlib.h> 39#include <unistd.h> 40#include <string.h> 41#include <stdio.h> 42#include <sys/types.h> 43#include <sys/wait.h> 44#include <sys/errno.h> 45#include <sys/socket.h> 46#include <net/if_types.h> 47 48#include "FDHandler.h" 49 50#include <CoreFoundation/CFRunLoop.h> 51#include <CoreFoundation/CFSocket.h> 52 53struct FDHandler_s { 54 CFRunLoopSourceRef rls; 55 CFSocketRef socket; 56 int fd; 57 FDHandler_func * func; 58 void * arg1; 59 void * arg2; 60}; 61 62static void 63FDHandler_callback(CFSocketRef s, CFSocketCallBackType type, 64 CFDataRef address, const void * data, void * info) 65{ 66 FDHandler * handler = (FDHandler *)info; 67 68 if (handler->func) { 69 (*handler->func)(handler->arg1, handler->arg2); 70 } 71 return; 72} 73 74FDHandler * 75FDHandler_create(int fd) 76{ 77 CFSocketContext context = { 0, NULL, NULL, NULL, NULL }; 78 FDHandler * handler; 79 80 handler = malloc(sizeof(*handler)); 81 if (handler == NULL) 82 return (NULL); 83 bzero(handler, sizeof(*handler)); 84 85 context.info = handler; 86 handler->fd = fd; 87 handler->socket 88 = CFSocketCreateWithNative(NULL, fd, kCFSocketReadCallBack, 89 FDHandler_callback, &context); 90 handler->rls = CFSocketCreateRunLoopSource(NULL, handler->socket, 0); 91 CFRunLoopAddSource(CFRunLoopGetCurrent(), handler->rls, 92 kCFRunLoopDefaultMode); 93 return (handler); 94} 95 96void 97FDHandler_free(FDHandler * * handler_p) 98{ 99 FDHandler * handler; 100 101 if (handler_p == NULL) { 102 return; 103 } 104 handler = *handler_p; 105 if (handler) { 106 if (handler->rls) { 107 /* cancel further handlers */ 108 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), handler->rls, 109 kCFRunLoopDefaultMode); 110 111 /* remove one socket reference, close the file descriptor */ 112 CFSocketInvalidate(handler->socket); 113 114 /* release the socket */ 115 CFRelease(handler->socket); 116 handler->socket = NULL; 117 118 /* release the run loop source */ 119 CFRelease(handler->rls); 120 handler->rls = NULL; 121 } 122 free(handler); 123 } 124 *handler_p = NULL; 125 return; 126} 127 128void 129FDHandler_enable(FDHandler * handler, FDHandler_func * func, 130 void * arg1, void * arg2) 131{ 132 handler->func = func; 133 handler->arg1 = arg1; 134 handler->arg2 = arg2; 135 return; 136} 137 138void 139FDHandler_disable(FDHandler * handler) 140{ 141 handler->func = NULL; 142 handler->arg1 = NULL; 143 handler->arg2 = NULL; 144 return; 145} 146 147 148int 149FDHandler_fd(FDHandler * handler) 150{ 151 return (handler->fd); 152} 153