Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Network Connection NSNotification for OSX?

I simply need to have a notification post when a valid IP address is assigned. I have tried polling via SCReachability, but that seems to be inefficient.

Any suggestions? This seems like it should be simple, but I've been struggling for several hours to get anything working.

like image 890
Andrew J. Freyer Avatar asked Dec 18 '22 00:12

Andrew J. Freyer


2 Answers

I know this is a bit old but the selected answer is not ideal.

The SCReachability API can be used to know when a particular host is reachable. If all you want to know is when a valid IP address is assigned (rather than a viable route to a target IP) then you should look at the SCDynamicStore* APIs instead. These functions allow you to subscribe to the system's configuration store for notification when certain values change. So, for notification when the IPv4 address changes on any interface you would do the following (error checking removed for readability)

  SCDynamicStoreRef dynStore;

  SCDynamicStoreContext context = {0, NULL, NULL, NULL, NULL};

  dynStore = SCDynamicStoreCreate(kCFAllocatorDefault,
                                  CFBundleGetIdentifier(CFBundleGetMainBundle()),
                                  scCallback,
                                  &context);

    const CFStringRef keys[3] = {
        CFSTR("State:/Network/Interface/.*/IPv4")
    };
    CFArrayRef watchedKeys = CFArrayCreate(kCFAllocatorDefault,
                                         (const void **)keys,
                                         1,
                                         &kCFTypeArrayCallBacks);
    if (!SCDynamicStoreSetNotificationKeys(dynStore,
                                         NULL,
                                         watchedKeys)) 
  {
       CFRelease(watchedKeys);
        fprintf(stderr, "SCDynamicStoreSetNotificationKeys() failed: %s", SCErrorString(SCError()));
        CFRelease(dynStore);
        dynStore = NULL;

        return -1;
    }
    CFRelease(watchedKeys);

    rlSrc = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, dynStore, 0);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), rlSrc, kCFRunLoopDefaultMode);
    CFRelease(rlSrc);

You will need to imlement the scCallback function which will be called whenever there is a change. Also you'll need to call CFRunLoopRun somewhere to make the code go.

like image 115
Jeremy Avatar answered Feb 09 '23 23:02

Jeremy


You don't have to poll with SCNetworkReachability. You register the callback, and the system calls the callback when the network state changes. It's not inefficient.

See Apple's sample code Reachability which shows how to integrate it into an Objective-C app. The code is for iPhone, but I think Reachability.{m,h} should work on OS X.

(See Apple's sample code SimpleReach. It's five years old, but should work.)

like image 30
Yuji Avatar answered Feb 09 '23 22:02

Yuji