Running auto-configuration whenever computer wakes up or network change is detected

Change-Id: I2af25aa61a9d5dedb6c30f62f7157c15ba843895
diff --git a/osx/menu-delegate.h b/osx/menu-delegate.h
index d6051cd..3b2260c 100644
--- a/osx/menu-delegate.h
+++ b/osx/menu-delegate.h
@@ -8,6 +8,7 @@
 
 #import <Cocoa/Cocoa.h>
 #import "preference-delegate.h"
+#import "system-events.h"
 
 @interface MenuDelegate : NSObject <NSApplicationDelegate>
 {
@@ -44,6 +45,7 @@
   
   IBOutlet PreferenceDelegate *preferencesDelegate;
 
+  SystemEvents *m_systemEvents;
   bool m_autoconfInProgress;
 }
 
diff --git a/osx/menu-delegate.mm b/osx/menu-delegate.mm
index b46a07d..e92c82b 100644
--- a/osx/menu-delegate.mm
+++ b/osx/menu-delegate.mm
@@ -41,6 +41,13 @@
            userInfo: nil
            repeats:YES];
   [self updateStatus];
+
+  m_systemEvents = [[SystemEvents alloc] init];
+}
+
+- (void)applicationWillTerminate:(NSNotification *)aNotification
+{
+  [m_systemEvents disable];
 }
 
 -(void)awakeFromNib
@@ -159,7 +166,6 @@
   NSArray *autoconf = [[statusFibXml rootElement] nodesForXPath:@"//fib/prefix[text()='ndn:/autoconf-route']" error:nil];
   if ([autoconf count] == 0)
     {
-      NSLog (@"No automatically detected route configured, trying to get one");
       [self restartDaemon:nil];
     }
 }
@@ -206,6 +212,8 @@
   if (m_autoconfInProgress)
     return;
 
+  NSLog (@"No automatically detected route configured, trying to get one");
+  
   m_autoconfInProgress = true;
   [m_operationQueue addOperationWithBlock:^{
       NSTask *task = [[NSTask alloc] init];
diff --git a/osx/system-events.h b/osx/system-events.h
new file mode 100644
index 0000000..52370ce
--- /dev/null
+++ b/osx/system-events.h
@@ -0,0 +1,15 @@
+/* -*- Mode: objc; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * @copyright See LICENCE for copyright and license information.
+ *
+ * @author Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ * @author Ilya Moiseenko <iliamo@ucla.edu>
+ */
+
+#import <Cocoa/Cocoa.h>
+
+@interface SystemEvents : NSObject <NSObject>
+
+-(void)disable;
+
+@end
diff --git a/osx/system-events.mm b/osx/system-events.mm
new file mode 100644
index 0000000..b7297f8
--- /dev/null
+++ b/osx/system-events.mm
@@ -0,0 +1,85 @@
+/* -*- Mode: objc; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * @copyright See LICENCE for copyright and license information.
+ *
+ * @author Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ * @author Ilya Moiseenko <iliamo@ucla.edu>
+ */
+
+/*
+  Potentially useful System Configuration regex patterns:
+
+  (backslash quoting below is only to protect the C comment)
+  State:/Network/Interface/.*\/Link 
+  State:/Network/Interface/.*\/IPv4
+  State:/Network/Interface/.*\/IPv6
+        
+  State:/Network/Global/DNS
+  State:/Network/Global/IPv4
+        
+  Potentially useful notifications from Darwin Notify Center:
+    
+  com.apple.system.config.network_change
+*/
+
+#import "system-events.h"
+#import "menu-delegate.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+
+@implementation SystemEvents
+
+-(void)scheduleDaemonRestart
+{
+  [NSTimer scheduledTimerWithTimeInterval: 3.0
+                                   target: (MenuDelegate*)[[NSApplication sharedApplication] delegate]
+                                   selector:@selector(restartDaemon:)
+                                   userInfo: nil
+                                   repeats:NO];
+}
+
+- (void)wakeUpNotification:(NSNotification*) note
+{
+  [self scheduleDaemonRestart];
+}
+
+static void
+NotificationCenterCallback(CFNotificationCenterRef center,
+                           void *observer,
+                           CFStringRef name,
+                           const void *object,
+                           CFDictionaryRef userInfo)
+{
+  [(__bridge SystemEvents*)observer scheduleDaemonRestart];
+}
+
+-(id)init
+{
+  if (![super init]) {
+    return nil;
+  }
+
+  [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self 
+            selector: @selector(wakeUpNotification:) 
+            name: NSWorkspaceDidWakeNotification object: NULL];
+
+  CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
+                                  (__bridge void*)self,
+                                  NotificationCenterCallback,
+                                  CFSTR ("com.apple.system.config.network_change"), // name of notification
+                                  NULL, // object to observe
+                                  NSNotificationSuspensionBehaviorDeliverImmediately);
+  
+  return self;
+}
+
+-(void)disable
+{
+  [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self];
+
+  CFNotificationCenterRemoveEveryObserver(CFNotificationCenterGetDarwinNotifyCenter(),
+                                          (__bridge void*)self);
+}
+
+@end