Skip to content

Commit 13dbd65

Browse files
authored
chore: update network finder for macOS (#961)
1 parent 5987d49 commit 13dbd65

File tree

2 files changed

+76
-6
lines changed

2 files changed

+76
-6
lines changed

composeApp/src/desktopMain/c/NetworkTypeFinder.m

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,68 @@ - (NSString *)getNetworkType {
5252
}
5353

5454
NSString *result = @"unknown";
55-
5655
nw_path_t currentPath = _currentPath;
56+
5757
if (currentPath && nw_path_get_status(currentPath) == nw_path_status_satisfied) {
5858
if (nw_path_uses_interface_type(currentPath, nw_interface_type_wifi)) {
5959
result = @"wifi";
6060
} else if (nw_path_uses_interface_type(currentPath, nw_interface_type_cellular)) {
6161
result = @"mobile";
6262
} else if (nw_path_uses_interface_type(currentPath, nw_interface_type_wired)) {
6363
result = @"wired_ethernet";
64+
} else if (nw_path_uses_interface_type(currentPath, nw_interface_type_loopback)) {
65+
result = [self getNetworkTypeFallback];
6466
} else {
65-
result = @"unknown";
67+
result = [self getNetworkTypeFallback];
6668
}
69+
} else {
70+
result = [self getNetworkTypeFallback];
6771
}
6872

6973
return result;
7074
}
7175

76+
- (NSString *)getNetworkTypeFallback {
77+
SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("NetworkTypeFinder"), NULL, NULL);
78+
if (!store) return @"unknown";
79+
80+
CFStringRef primaryService = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
81+
CFDictionaryRef globalIPv4 = SCDynamicStoreCopyValue(store, primaryService);
82+
CFRelease(primaryService);
83+
84+
if (globalIPv4) {
85+
CFStringRef serviceID = CFDictionaryGetValue(globalIPv4, kSCDynamicStorePropNetPrimaryService);
86+
if (serviceID) {
87+
CFStringRef interfaceKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, serviceID, kSCEntNetInterface);
88+
CFDictionaryRef interface = SCDynamicStoreCopyValue(store, interfaceKey);
89+
CFRelease(interfaceKey);
90+
91+
if (interface) {
92+
CFStringRef hardwareType = CFDictionaryGetValue(interface, kSCPropNetInterfaceHardware);
93+
NSString *result = @"unknown";
94+
if (hardwareType) {
95+
if (CFEqual(hardwareType, kSCEntNetAirPort)) {
96+
result = @"wifi";
97+
} else if (CFEqual(hardwareType, kSCEntNetEthernet)) {
98+
result = @"wired_ethernet";
99+
} else if (CFEqual(hardwareType, kSCEntNetModem)) {
100+
result = @"mobile";
101+
}
102+
}
103+
CFRelease(interface);
104+
CFRelease(globalIPv4);
105+
CFRelease(store);
106+
return result;
107+
}
108+
CFRelease(globalIPv4);
109+
} else {
110+
CFRelease(globalIPv4);
111+
}
112+
}
113+
CFRelease(store);
114+
return @"unknown";
115+
}
116+
72117
- (BOOL)isVpnActive {
73118
NSDictionary *proxySettings = CFBridgingRelease(CFNetworkCopySystemProxySettings());
74119
NSDictionary *scoped = proxySettings[@"__SCOPED__"];
@@ -82,17 +127,42 @@ - (BOOL)isVpnActive {
82127
}
83128
}
84129
}
130+
131+
SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("VPNCheck"), NULL, NULL);
132+
if (!store) return NO;
133+
134+
CFPropertyListRef globalIPv4 = SCDynamicStoreCopyValue(store, CFSTR("State:/Network/Global/IPv4"));
135+
if (globalIPv4) {
136+
CFStringRef primaryService = CFDictionaryGetValue(globalIPv4, kSCDynamicStorePropNetPrimaryService);
137+
if (primaryService) {
138+
CFStringRef vpnKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("State:/Network/Service/%@/VPN"), primaryService);
139+
CFPropertyListRef vpnSettings = SCDynamicStoreCopyValue(store, vpnKey);
140+
CFRelease(vpnKey);
141+
if (vpnSettings) {
142+
CFRelease(vpnSettings);
143+
CFRelease(globalIPv4);
144+
CFRelease(store);
145+
return YES;
146+
}
147+
}
148+
CFRelease(globalIPv4);
149+
}
150+
CFRelease(store);
85151

86152
return NO;
87153
}
88154
@end
89155

156+
static NetworkTypeFinder *sharedFinder = nil;
157+
90158
const char* getNetworkTypeImpl() {
91159
@autoreleasepool {
92-
NetworkTypeFinder *finder = [[NetworkTypeFinder alloc] init];
93-
NSString *networkType = [finder getNetworkType];
94-
// Return pointer valid for JNI lifetime, no need to free
95-
return [networkType UTF8String];
160+
if (!sharedFinder) {
161+
sharedFinder = [[NetworkTypeFinder alloc] init];
162+
usleep(100000);
163+
}
164+
NSString *networkType = [sharedFinder getNetworkType];
165+
return strdup([networkType UTF8String]);
96166
}
97167
}
98168
#elif defined(_WIN32)
Binary file not shown.

0 commit comments

Comments
 (0)