simulator_support.c [plain text]
#include <TargetConditionals.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCPrivate.h>
#include <SystemConfiguration/SCValidation.h>
#include <dns_sd.h>
#include <dns_sd_private.h>
#include "cache.h"
#if TARGET_OS_SIMULATOR && !TARGET_OS_IOSMAC
static CFMutableArrayRef mirror_keys = NULL;
static CFMutableArrayRef mirror_patterns = NULL;
static SCDynamicStoreRef store_host = NULL;
static SCDynamicStoreRef store_sim = NULL;
#pragma mark -
#pragma mark Logging
__private_extern__ os_log_t
__log_SimulatorSupport(void)
{
static os_log_t log = NULL;
if (log == NULL) {
log = os_log_create("com.apple.SystemConfiguration", "SimulatorSupport");
}
return log;
}
#pragma mark -
#pragma mark iOS Simulator Support
static void
mirror(SCDynamicStoreRef store, CFArrayRef changes, void *info)
{
#pragma unused(store)
CFDictionaryRef content_host;
CFDictionaryRef content_sim;
CFIndex i;
CFIndex n;
n = CFArrayGetCount(changes);
if (n == 0) {
return;
}
if (info == NULL) {
content_host = SCDynamicStoreCopyMultiple(store_host, changes, NULL);
} else {
content_host = (CFDictionaryRef)info;
}
content_sim = SCDynamicStoreCopyMultiple(store_sim, changes, NULL);
cache_open();
for (i = 0; i < n; i++) {
CFStringRef key;
CFPropertyListRef val;
key = CFArrayGetValueAtIndex(changes, i);
val = (content_host != NULL) ? CFDictionaryGetValue(content_host, key) : NULL;
if (val != NULL) {
cache_SCDynamicStoreSetValue(store_sim, key, val);
} else {
val = (content_sim != NULL) ? CFDictionaryGetValue(content_sim, key) : NULL;
if (val != NULL) {
cache_SCDynamicStoreRemoveValue(store_sim, key);
} else {
cache_SCDynamicStoreNotifyValue(store_sim, key);
}
}
}
cache_write(store_sim);
cache_close();
if ((info == NULL) && (content_host != NULL)) {
CFRelease(content_host);
}
if (content_sim != NULL) {
CFRelease(content_sim);
}
return;
}
static void
mirror_setup()
{
CFStringRef key;
CFStringRef pattern;
mirror_keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
mirror_patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
key = SCDynamicStoreKeyCreate(NULL,
CFSTR("%@" "InterfaceNamer"),
kSCDynamicStoreDomainPlugin);
CFArrayAppendValue(mirror_keys, key);
CFRelease(key);
pattern = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
kSCDynamicStoreDomainSetup,
kSCCompAnyRegex);
CFArrayAppendValue(mirror_patterns, pattern);
CFRelease(pattern);
pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL,
kSCCompAnyRegex,
CFSTR(".*"),
NULL);
CFArrayAppendValue(mirror_patterns, pattern);
CFRelease(pattern);
pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
kSCCompAnyRegex,
CFSTR(".*"),
NULL);
CFArrayAppendValue(mirror_patterns, pattern);
CFRelease(pattern);
key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@"),
kSCDynamicStoreDomainState,
kSCCompNetwork,
CFSTR(kDNSServiceCompMulticastDNS));
CFArrayAppendValue(mirror_keys, key);
CFRelease(key);
key = SCDynamicStoreKeyCreate(NULL, CFSTR("%@/%@/%@"),
kSCDynamicStoreDomainState,
kSCCompNetwork,
CFSTR(kDNSServiceCompPrivateDNS));
CFArrayAppendValue(mirror_keys, key);
CFRelease(key);
return;
}
#define N_QUICK 64
__private_extern__
void
prime_SimulatorSupport()
{
CFDictionaryRef content_host;
CFIndex n;
SC_log(LOG_DEBUG, "prime() called");
content_host = SCDynamicStoreCopyMultiple(store_host, mirror_keys, mirror_patterns);
CFRelease(mirror_keys);
mirror_keys = NULL;
CFRelease(mirror_patterns);
mirror_patterns = NULL;
if (content_host == NULL) {
return;
}
n = CFDictionaryGetCount(content_host);
if (n > 0) {
CFArrayRef changes;
const void * keys_host_q[N_QUICK];
const void ** keys_host = keys_host_q;
if (n > (CFIndex)(sizeof(keys_host_q) / sizeof(CFStringRef))) {
keys_host = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0);
}
CFDictionaryGetKeysAndValues(content_host, keys_host, NULL);
changes = CFArrayCreate(NULL, keys_host, n, &kCFTypeArrayCallBacks);
mirror(store_host, changes, (void *)content_host);
CFRelease(changes);
if (keys_host != keys_host_q) {
CFAllocatorDeallocate(NULL, keys_host);
}
}
CFRelease(content_host);
return;
}
__private_extern__
void
load_SimulatorSupport(CFBundleRef bundle, Boolean bundleVerbose)
{
#pragma unused(bundleVerbose)
Boolean ok;
CFMutableDictionaryRef options;
CFRunLoopSourceRef rls;
SC_log(LOG_DEBUG, "load() called");
SC_log(LOG_DEBUG, " bundle ID = %@", CFBundleGetIdentifier(bundle));
mirror_setup();
options = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(options, kSCDynamicStoreUseHostServer, kCFBooleanTrue);
store_host = SCDynamicStoreCreateWithOptions(NULL,
CFSTR("SimulatorSupport(host)"),
options,
mirror,
NULL);
CFRelease(options);
assert(store_host != NULL);
ok = SCDynamicStoreSetNotificationKeys(store_host, mirror_keys, mirror_patterns);
assert(ok);
rls = SCDynamicStoreCreateRunLoopSource(NULL, store_host, 0);
assert(rls != NULL);
CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
CFRelease(rls);
store_sim = SCDynamicStoreCreate(NULL,
CFSTR("SimulatorSupport(sim)"),
NULL,
NULL);
return;
}
#ifdef MAIN
#pragma mark -
#pragma mark Standalone test code
int
main(int argc, char **argv)
{
_sc_log = FALSE;
_sc_verbose = (argc > 1) ? TRUE : FALSE;
load_SimulatorSupport(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
prime_SimulatorSupport();
CFRunLoopRun();
exit(0);
return 0;
}
#endif
#endif // TARGET_OS_SIMULATOR && !TARGET_OS_IOSMAC