MacWifiScanner.mm (3172B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #import <Cocoa/Cocoa.h> 6 #import <CoreWLAN/CoreWLAN.h> 7 8 #include <dlfcn.h> 9 #include <unistd.h> 10 11 #include <objc/objc.h> 12 #include <objc/objc-runtime.h> 13 14 #include "nsObjCExceptions.h" 15 #include "nsCOMArray.h" 16 #include "nsWifiMonitor.h" 17 #include "nsWifiAccessPoint.h" 18 #include "MacWifiScanner.h" 19 20 namespace mozilla { 21 22 nsresult WifiScannerImpl::GetAccessPointsFromWLAN( 23 nsTArray<RefPtr<nsIWifiAccessPoint>>& accessPoints) { 24 NS_OBJC_BEGIN_TRY_BLOCK_RETURN; 25 26 accessPoints.Clear(); 27 28 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 29 30 @try { 31 NSBundle* bundle = [[[NSBundle alloc] 32 initWithPath:@"/System/Library/Frameworks/CoreWLAN.framework"] 33 autorelease]; 34 if (!bundle) { 35 [pool release]; 36 return NS_ERROR_NOT_AVAILABLE; 37 } 38 39 Class CWI_class = [bundle classNamed:@"CWInterface"]; 40 if (!CWI_class) { 41 [pool release]; 42 return NS_ERROR_NOT_AVAILABLE; 43 } 44 45 id scanResult = [[CWI_class interface] scanForNetworksWithSSID:nil 46 error:nil]; 47 if (!scanResult) { 48 [pool release]; 49 return NS_ERROR_NOT_AVAILABLE; 50 } 51 52 NSArray* scan = [NSMutableArray arrayWithArray:scanResult]; 53 NSEnumerator* enumerator = [scan objectEnumerator]; 54 55 while (id anObject = [enumerator nextObject]) { 56 auto* ap = new nsWifiAccessPoint(); 57 if (!ap) { 58 [pool release]; 59 return NS_ERROR_OUT_OF_MEMORY; 60 } 61 62 // [CWInterface bssidData] is deprecated on OS X 10.7 and up. Which is 63 // is a pain, so we'll use it for as long as it's available. 64 unsigned char macData[6] = {0}; 65 if ([anObject respondsToSelector:@selector(bssidData)]) { 66 #pragma clang diagnostic push 67 #pragma clang diagnostic ignored "-Wobjc-method-access" 68 NSData* data = [anObject bssidData]; 69 #pragma clang diagnostic pop 70 if (data) { 71 memcpy(macData, [data bytes], 6); 72 } 73 } else { 74 // [CWInterface bssid] returns a string formatted "00:00:00:00:00:00". 75 NSString* macString = [anObject bssid]; 76 if (macString && ([macString length] == 17)) { 77 for (NSUInteger i = 0; i < 6; ++i) { 78 NSString* part = 79 [macString substringWithRange:NSMakeRange(i * 3, 2)]; 80 NSScanner* scanner = [NSScanner scannerWithString:part]; 81 unsigned int data = 0; 82 if (![scanner scanHexInt:&data]) { 83 data = 0; 84 } 85 macData[i] = (unsigned char)data; 86 } 87 } 88 } 89 90 int signal = (int)((NSInteger)[anObject rssiValue]); 91 ap->setMac(macData); 92 ap->setSignal(signal); 93 ap->setSSID([[anObject ssid] UTF8String], 32); 94 95 accessPoints.AppendElement(ap); 96 } 97 } @catch (NSException*) { 98 [pool release]; 99 return NS_ERROR_NOT_AVAILABLE; 100 } 101 102 [pool release]; 103 104 return NS_OK; 105 106 NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_NOT_AVAILABLE); 107 } 108 109 } // namespace mozilla