+#elif defined(__APPLE__)
+static void network_change_callback(SCDynamicStoreRef store, CFArrayRef keys, void *info) {
+ (void)store;
+ (void)keys;
+
+ meshlink_handle_t *mesh = info;
+
+ pthread_mutex_lock(&mesh->mutex);
+
+ logger(mesh, MESHLINK_ERROR, "Network change detected!");
+ scan_ifaddrs(mesh);
+
+ if(mesh->loop.now.tv_sec > mesh->discovery.last_update + 5) {
+ mesh->discovery.last_update = mesh->loop.now.tv_sec;
+ handle_network_change(mesh, 1);
+ }
+
+ pthread_mutex_unlock(&mesh->mutex);
+}
+
+static void *network_change_handler(void *arg) {
+ meshlink_handle_t *mesh = arg;
+
+ mesh->discovery.runloop = CFRunLoopGetCurrent();
+
+ SCDynamicStoreContext context = {0, mesh, NULL, NULL, NULL};
+ SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("network_change_handler"), network_change_callback, &context);
+ CFStringRef interfaces = SCDynamicStoreKeyCreate(NULL, CFSTR("State:/Network/Interface"), kCFStringEncodingUTF8);
+ CFStringRef ipv4 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4);
+ CFStringRef ipv6 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6);
+ CFMutableArrayRef keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ CFMutableArrayRef patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ CFRunLoopSourceRef runloop_source = NULL;
+
+ if(!store) {
+ logger(mesh, MESHLINK_ERROR, "Error setting up network change handler: %s\n", SCErrorString(SCError()));
+ goto exit;
+ }
+
+ if(!interfaces || !ipv4 || !ipv6 || !keys || !patterns) {
+ logger(mesh, MESHLINK_ERROR, "Error setting up network change handler: %s\n", SCErrorString(SCError()));
+ goto exit;
+ }
+
+ CFArrayAppendValue(keys, interfaces);
+ CFArrayAppendValue(patterns, ipv4);
+ CFArrayAppendValue(patterns, ipv6);
+
+ if(!SCDynamicStoreSetNotificationKeys(store, keys, patterns)) {
+ logger(mesh, MESHLINK_ERROR, "Error setting up network change handler: %s\n", SCErrorString(SCError()));
+ goto exit;
+ }
+
+ runloop_source = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
+
+ if(!runloop_source) {
+ logger(mesh, MESHLINK_ERROR, "Error setting up network change handler: %s\n", SCErrorString(SCError()));
+ goto exit;
+ }
+
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), runloop_source, kCFRunLoopDefaultMode);
+ CFRunLoopRun();
+
+exit:
+
+ if(runloop_source) {
+ CFRelease(runloop_source);
+ }
+
+ if(interfaces) {
+ CFRelease(interfaces);
+ }
+
+ if(ipv4) {
+ CFRelease(ipv4);
+ }
+
+ if(ipv6) {
+ CFRelease(ipv6);
+ }
+
+ if(keys) {
+ CFRelease(keys);
+ }
+
+ if(patterns) {
+ CFRelease(patterns);
+ }
+
+ if(store) {
+ CFRelease(store);
+ }
+
+ mesh->discovery.runloop = NULL;
+
+ return NULL;
+
+}