forked from play175/wifiNotifier
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwifiNotifer_darwin.go
182 lines (149 loc) · 5.09 KB
/
wifiNotifer_darwin.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// +build darwin,!nowifi
package wifiNotifier
/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework SystemConfiguration -framework CoreWLAN -framework Foundation
#include <stdlib.h>
#import <Foundation/Foundation.h>
#import <CoreWLAN/CoreWLAN.h>
#import <SystemConfiguration/SystemConfiguration.h>
static inline char* nsstring2cstring(NSString *s){
if (s == NULL) { return NULL; }
char *cstr = strdup([s UTF8String]);
return cstr;
}
#define NOT_CONNECTED @""
static inline CWInterface * getCWInterface() {
CWWiFiClient *swc = [CWWiFiClient sharedWiFiClient];
if (swc == nil) return nil;
return [swc interface];
}
static inline void wifi_network_changed(SCDynamicStoreRef store, CFArrayRef changedKeys, void *ctx)
{
CWInterface * WiFiInterface = getCWInterface();
if (WiFiInterface == nil) return;
NSString *currentSSID = [WiFiInterface ssid] ? [WiFiInterface ssid] : NOT_CONNECTED;
extern void __onWifiChanged(char *);
__onWifiChanged(nsstring2cstring(currentSSID));
}
static inline char * getCurrentSSID(void) {
CWInterface * WiFiInterface = getCWInterface();
if (WiFiInterface == nil) return nsstring2cstring(NOT_CONNECTED);
NSString *ssid = [WiFiInterface ssid] ? [WiFiInterface ssid] : NOT_CONNECTED;
return nsstring2cstring(ssid);
}
static inline int getCurrentNetworkSecurity() {
CWInterface * WiFiInterface = getCWInterface();
if (WiFiInterface == nil) return 0xFFFFFFFF;
return [WiFiInterface security];
}
static inline char* getAvailableSSIDs(void) {
CWInterface * WiFiInterface = getCWInterface();
if (WiFiInterface == nil) return nil;
NSError *err = nil;
NSSet *scanset = [WiFiInterface scanForNetworksWithSSID:Nil error:&err];
if (err!=nil || scanset == nil || scanset.count == 0) return nil;
NSString *retString = nil;
int i=0;
for (CWNetwork * nw in scanset)
{
if (nw == nil || [nw ssid] == nil) continue;
NSString * ssid = [[[nw ssid] componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:@" "];
if (i++ == 0)
retString = ssid;
else
retString = [NSString stringWithFormat:@"%@\n%@", retString , ssid];
}
return nsstring2cstring(retString);
}
static inline void setWifiNotifier(void) {
CWInterface * WiFiInterface = getCWInterface();
if (WiFiInterface == nil) return;
NSArray* arr = [CWWiFiClient interfaceNames];
NSSet *wifiInterfaces = [NSSet setWithArray:arr];
NSMutableArray *scKeys = [[NSMutableArray alloc] init];
[wifiInterfaces enumerateObjectsUsingBlock:^(NSString *ifName, BOOL *stop)
{
[scKeys addObject: [NSString stringWithFormat:@"State:/Network/Interface/%@/AirPort", ifName]];
}];
SCDynamicStoreContext ctx = { 0, NULL, NULL, NULL, NULL };
SCDynamicStoreRef store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("myapp"), wifi_network_changed, &ctx);
SCDynamicStoreSetNotificationKeys(store, (__bridge CFArrayRef)scKeys, NULL);
CFRunLoopSourceRef src = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, store, 0);
CFRunLoopAddSource([[NSRunLoop currentRunLoop] getCFRunLoop], src, kCFRunLoopCommonModes);
CFRunLoopRun();
}
*/
import "C"
import (
"strings"
"time"
"unsafe"
)
var internalOnWifiChangedCb func(string)
//export __onWifiChanged
func __onWifiChanged(ssid *C.char) {
goSsid := C.GoString(ssid)
C.free(unsafe.Pointer(ssid))
if internalOnWifiChangedCb != nil {
internalOnWifiChangedCb(goSsid)
}
}
// GetAvailableSSIDs returns the list of the names of available Wi-Fi networks
func GetAvailableSSIDs() []string {
ssidList := C.getAvailableSSIDs()
goSsidList := C.GoString(ssidList)
C.free(unsafe.Pointer(ssidList))
return strings.Split(goSsidList, "\n")
}
// GetCurrentSSID returns current WiFi SSID
func GetCurrentSSID() string {
ssid := C.getCurrentSSID()
goSsid := C.GoString(ssid)
C.free(unsafe.Pointer(ssid))
return goSsid
}
// GetCurrentNetworkIsInsecure returns current security mode
func GetCurrentNetworkIsInsecure() bool {
const (
CWSecurityNone = 0
CWSecurityWEP = 1
CWSecurityWPAPersonal = 2
CWSecurityWPAPersonalMixed = 3
CWSecurityWPA2Personal = 4
CWSecurityPersonal = 5
CWSecurityDynamicWEP = 6
CWSecurityWPAEnterprise = 7
CWSecurityWPAEnterpriseMixed = 8
CWSecurityWPA2Enterprise = 9
CWSecurityEnterprise = 10
CWSecurityWPA3Personal = 11
CWSecurityWPA3Enterprise = 12
CWSecurityWPA3Transition = 13
)
security := C.getCurrentNetworkSecurity()
switch security {
case CWSecurityNone,
CWSecurityWEP,
CWSecurityPersonal,
CWSecurityDynamicWEP:
return true
}
return false
}
// SetWifiNotifier initializes a handler method 'OnWifiChanged'
func SetWifiNotifier(cb func(string)) error {
internalOnWifiChangedCb = cb
go func() {
for {
// Detection WiFi status change in infinite loop.
// C.setWifiNotifier() should never return.
//
// BUT! It can return in some corner cases (e.g. we call it on system boot when WiFi interface still not initialized)
// In this case - we waiting some delay and trying to call this function again
C.setWifiNotifier()
time.Sleep(time.Second)
}
}()
return nil
}