Я пытаюсь написать простую утилиту, которая следит за текущим состоянием SystemConfiguration сетевых интерфейсов и завершает работу при возникновении любого из следующих событий:
- Сетевой интерфейс появляется или исчезает
- IPv4 или IPv6-адрес в сетевом интерфейсе изменяется
Я написал программу, которая компилируется и запускается, но когда я запускаю / останавливаю свой VPN, программа не обнаруживает никаких изменений, т.е. обратный вызовникогда не называется. Кто-нибудь знает, в чем может быть проблема? Вот код ...
import Foundation
import CoreFoundation
import SystemConfiguration
var nwChange = false
func displayUsage() {
print("\nUsage:\n")
print(" netwatcher\n")
exit(20)
}
func CreateIPAddressListChangeCallbackSCF(
_ rl:CFRunLoop
) -> Int
{
var ctxt = SCDynamicStoreContext()
var patterns = [CFString]()
let callback: SCDynamicStoreCallBack = { (cstore, _, _) in
nwChange = true
print("Something changed!")
}
let store = SCDynamicStoreCreate( nil, "netwatcher" as CFString, callback, &ctxt )
if store == nil {
print("error: failed to create dynamic store");
return 9
}
patterns.append( SCDynamicStoreKeyCreateNetworkInterfaceEntity( nil, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetInterface ) )
patterns.append( SCDynamicStoreKeyCreateNetworkInterfaceEntity( nil, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4 ) )
patterns.append( SCDynamicStoreKeyCreateNetworkInterfaceEntity( nil, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6 ) )
if !SCDynamicStoreSetNotificationKeys( store!, nil, patterns as CFArray ) {
print("error: failed to set notification keys");
return 5
}
if let rls = SCDynamicStoreCreateRunLoopSource( nil, store!, 0 ) {
CFRunLoopAddSource( rl, rls, .commonModes )
} else {
print("error: failed to create run loop source")
return 4
}
return 0
}
let args = CommandLine.arguments
if args.count > 1 {
displayUsage()
}
let runLoop = CFRunLoopGetCurrent()
if runLoop == nil {
print("error: unable to get my run loop")
exit( 10 )
}
let ret = CreateIPAddressListChangeCallbackSCF( runLoop! )
if ret != 0 {
exit( Int32(ret) )
}
while !nwChange {
sleep( 1 )
}
exit( 0 )