// // NetworkMonitor.m // PlayGround // // Created by Simon Urbanek on 10/15/10. // Copyright 2010 Simon Urbanek. All rights reserved. // #import "NetworkMonitor.h" #import /* needed for vm_deallocate */ struct CTServerConnection { int a; int b; CFMachPortRef port; // direct port for use with _CTNetworkMonitor...() calls (via CFMachPortGetPort()) int c; mach_port_t srv_port; // this is actaully what _CTServerConnectionGetPort() returns - but we'll be nice and use the API // we don't care about the rest - the actual structure may be longer! }; CTServerConnectionRef _CTServerConnectionCreate(CFAllocatorRef, void *, int *); //the void* is a callback mach_port_t _CTServerConnectionGetPort(CTServerConnectionRef); int *_CTServerConnectionNetworkMonitorStart(CFMachPortRef, CTServerConnectionRef); int *_CTServerConnectionNetworkMonitorStop(CFMachPortRef, CTServerConnectionRef); void _CTServerConnectionNetworkMonitorCopyFieldTestInfo(CFMachPortRef port, CTServerConnectionRef conn, int *status, /* if I read the code correctly this is actually *char so I suggest using int succ=0; ...≻ it will be 1 on success */ CFPropertyListRef *data); /* this is the direct API call so the port will have to come from CTServerConnection->port */ void _CTCellMonitorCopyFieldTestInfo(mach_port_t port, int *res, void *data, int *len); /* alternative and unused parts: extern void * _CTServerConnectionCreate(CFAllocatorRef, int (*)(void *, CFStringRef, CFDictionaryRef, void *), int *); int *_CTServerConnectionNetworkMonitorGetNetworkCount(CFMachPortRef,struct CTServerConnection *,int *); int *_CTServerConnectionNetworkMonitorGetNetworkInfo(CFMachPortRef,struct CTServerConnection *,int, struct NetworkInfo *); //3rd is cell tower num int *_CTServerConnectionRegisterForNotification(void *, struct CTServerConnection *, void *); extern NSString* kCTNetworkMonitorUpdateNotification; */ static int CreateCallback() { return 0; } @implementation NetworkMonitor - (id) init { self = [super init]; if (self != nil) { running = NO; conn = _CTServerConnectionCreate(kCFAllocatorDefault, CreateCallback, NULL); port = NULL; if (conn) { mach_port_t port_num = _CTServerConnectionGetPort(conn); port = CFMachPortCreateWithPort(kCFAllocatorDefault, port_num, NULL, NULL, NULL); } } return self; } - (void) dealloc { if (running) [self stop]; if (port) CFRelease(port); if (conn) CFRelease(conn); [super dealloc]; } - (void) start { _CTServerConnectionNetworkMonitorStart(port, conn); running = YES; } - (void) stop { _CTServerConnectionNetworkMonitorStop(port, conn); running = NO; } - (BOOL) isRunning { return running; } // return the (decoded) dictionary with the current field test info // FIXME: we may want to use _CTServerConnectionNetworkMonitorCopyFieldTestInfo() instead... - (NSDictionary*) fieldTestInfo { NSDictionary *res = nil; void *dataPtr; int len = 0; if (![self getRawFieldTestInfo:&dataPtr length:&len] || len == 0) return nil; CFDataRef dc = CFDataCreateWithBytesNoCopy(NULL, dataPtr, len, kCFAllocatorNull); if (dc) { CFStringRef errstr = NULL; CFPropertyListRef pl = CFPropertyListCreateFromXMLData(NULL, dc, kCFPropertyListImmutable, &errstr); res = (NSDictionary*) pl; CFRelease(dc); } vm_deallocate(mach_task_self(), (vm_address_t)dataPtr, len); if (res) [res autorelease]; return res; } // this is the raw info = serialized plist -- very low level // the high-level uses CFDataCreateWithBytesNoCopy() followed by CFPropertyListCreateFromXMLData() to get the decoded plist object // but this direct API is a bit more useful where we just want to store the serialized representation // note that you own the returned memory and you need to release it using // vm_deallocate(mach_task_self(), (vm_address_t)dataPtr, length); - (BOOL) getRawFieldTestInfo: (void*) dataPtr length: (int*) lengthPtr { if (conn) { int res = 0; _CTCellMonitorCopyFieldTestInfo(CFMachPortGetPort(conn->port), &res, dataPtr, lengthPtr); if (res == 1) return YES; } return NO; } @end