nkeynes@998: /** nkeynes@998: * $Id: net_osx.m 1018 2009-03-19 12:29:06Z nkeynes $ nkeynes@998: * nkeynes@998: * OS X networking support functions. Currently this is just for activity callbacks. nkeynes@998: * nkeynes@998: * Copyright (c) 2009 Nathan Keynes. nkeynes@998: * nkeynes@998: * This program is free software; you can redistribute it and/or modify nkeynes@998: * it under the terms of the GNU General Public License as published by nkeynes@998: * the Free Software Foundation; either version 2 of the License, or nkeynes@998: * (at your option) any later version. nkeynes@998: * nkeynes@998: * This program is distributed in the hope that it will be useful, nkeynes@998: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@998: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@998: * GNU General Public License for more details. nkeynes@998: */ nkeynes@998: nkeynes@998: #include nkeynes@998: #include "netutil.h" nkeynes@998: nkeynes@998: struct net_osx_cbinfo { nkeynes@998: net_callback_t callback; nkeynes@998: void * cbdata; nkeynes@998: void (*cbdealloc)(void *); nkeynes@998: CFSocketRef sockRef; nkeynes@998: CFRunLoopSourceRef sourceRef; nkeynes@998: }; nkeynes@998: nkeynes@998: static void net_osx_callback( CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *unused, void *data ) nkeynes@998: { nkeynes@998: struct net_osx_cbinfo *cbinfo = (struct net_osx_cbinfo *)data; nkeynes@998: if(!cbinfo->callback( CFSocketGetNative(s), cbinfo->cbdata) ) { nkeynes@998: CFRunLoopRemoveSource( CFRunLoopGetCurrent(), cbinfo->sourceRef, kCFRunLoopCommonModes ); nkeynes@998: CFRelease(cbinfo->sourceRef); nkeynes@998: cbinfo->sourceRef = NULL; nkeynes@998: CFRelease(cbinfo->sockRef); nkeynes@998: } nkeynes@998: } nkeynes@998: nkeynes@998: static void net_osx_release( const void *data ) nkeynes@998: { nkeynes@998: struct net_osx_cbinfo *cbinfo = (struct net_osx_cbinfo *)data; nkeynes@998: if( cbinfo->cbdealloc != NULL ) { nkeynes@998: cbinfo->cbdealloc(cbinfo->cbdata); nkeynes@998: } nkeynes@998: free( cbinfo ); nkeynes@998: } nkeynes@998: nkeynes@998: /** nkeynes@998: * Register a TCP server socket listener on an already open (and listening) nkeynes@998: * socket. The socket must not have been previously registered. nkeynes@998: * @return TRUE on success, FALSE on failure. nkeynes@998: * nkeynes@998: * Defined in netutil.h nkeynes@998: */ nkeynes@998: gboolean net_register_tcp_listener( int fd, net_callback_t callback, void *data, void (*dealloc)(void*) ) nkeynes@998: { nkeynes@998: CFSocketContext socketContext; nkeynes@998: struct net_osx_cbinfo *cbinfo = malloc( sizeof(struct net_osx_cbinfo) ); nkeynes@998: assert(cbinfo != NULL); nkeynes@998: nkeynes@998: cbinfo->callback = callback; nkeynes@998: cbinfo->cbdata = data; nkeynes@998: cbinfo->cbdealloc = dealloc; nkeynes@998: socketContext.version = 0; nkeynes@998: socketContext.info = cbinfo; nkeynes@998: socketContext.retain = NULL; nkeynes@998: socketContext.release = net_osx_release; nkeynes@998: socketContext.copyDescription = NULL; nkeynes@998: nkeynes@998: cbinfo->sockRef = CFSocketCreateWithNative( kCFAllocatorDefault, fd, kCFSocketReadCallBack, nkeynes@998: net_osx_callback, &socketContext ); nkeynes@998: cbinfo->sourceRef = CFSocketCreateRunLoopSource( kCFAllocatorDefault, cbinfo->sockRef, 0 ); nkeynes@998: CFRunLoopAddSource( CFRunLoopGetCurrent(), cbinfo->sourceRef, kCFRunLoopCommonModes ); nkeynes@998: }