Add testbed connectivity status display

Change-Id: I13cf8a01258dab05347e78b51d25a493f45df07f
diff --git a/res/icon-connected-status-black.png b/res/icon-connected-status-black.png
new file mode 100644
index 0000000..e6f111b
--- /dev/null
+++ b/res/icon-connected-status-black.png
Binary files differ
diff --git a/res/tray-icon.psd b/res/tray-icon.psd
new file mode 100644
index 0000000..d1c4103
--- /dev/null
+++ b/res/tray-icon.psd
Binary files differ
diff --git a/src/main.cpp b/src/main.cpp
index e39e70c..3f8d238 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -27,7 +27,9 @@
 #include "tray-menu.hpp"
 
 #include <ndn-cxx/face.hpp>
+#include <ndn-cxx/name.hpp>
 #include <ndn-cxx/util/scheduler.hpp>
+#include <ndn-cxx/mgmt/nfd/fib-entry.hpp>
 #include <ndn-cxx/mgmt/nfd/controller.hpp>
 #include <ndn-cxx/mgmt/nfd/status-dataset.hpp>
 
@@ -40,6 +42,7 @@
 public:
   Ncc()
     : m_isActive(true)
+    , m_localhopFibEntry(Name("/localhop/nfd"))
     , m_face(nullptr, m_keyChain)
     , m_controller(m_face, m_keyChain)
     , m_scheduler(m_face.getIoService())
@@ -70,8 +73,7 @@
       while (m_isActive) {
         try {
           while (m_isActive) {
-            m_controller.fetch<ndn::nfd::ForwarderGeneralStatusDataset>(bind(&Ncc::onStatusRetrieved, this, _1),
-                                                                        bind(&Ncc::onStatusTimeout, this));
+            requestNfdStatus();
             m_face.processEvents(time::milliseconds::zero(), true);
           }
         }
@@ -97,10 +99,25 @@
     emit m_tray.nfdActivityUpdate(true);
     emit m_forwarderStatusModel.onDataReceived(status);
 
+    m_controller.fetch<ndn::nfd::FibDataset>(bind(&Ncc::onFibStatusRetrieved, this, _1),
+                                             bind(&Ncc::onStatusTimeout, this));
+
     m_scheduler.scheduleEvent(time::seconds(6), bind(&Ncc::requestNfdStatus, this));
   }
 
   void
+  onFibStatusRetrieved(const std::vector<nfd::FibEntry>& status)
+  {
+    bool isConnectedToHub = false;
+    for (auto const& fibEntry : status) {
+      if (fibEntry.getPrefix() == m_localhopFibEntry) {
+        isConnectedToHub = true;
+      }
+    }
+    emit m_tray.connectivityUpdate(isConnectedToHub);
+  }
+
+  void
   onStatusTimeout()
   {
     emit m_tray.nfdActivityUpdate(false);
@@ -124,12 +141,13 @@
   requestNfdStatus()
   {
     m_controller.fetch<ndn::nfd::ForwarderGeneralStatusDataset>(bind(&Ncc::onStatusRetrieved, this, _1),
-                                                       bind(&Ncc::onStatusTimeout, this));
+                                                                bind(&Ncc::onStatusTimeout, this));
   }
 
 private:
   volatile bool m_isActive;
   boost::thread m_nfdThread;
+  const Name m_localhopFibEntry;
 
   KeyChain m_keyChain;
   Face m_face;
diff --git a/src/qml.qrc b/src/qml.qrc
index d3586da..1f49bf8 100644
--- a/src/qml.qrc
+++ b/src/qml.qrc
@@ -9,5 +9,6 @@
         <file>../res/ToolbarAdvanced_22_128x128x32.png</file>
         <file>../res/icon-connected-black.png</file>
         <file>../res/icon-disconnected-black.png</file>
+        <file>../res/icon-connected-status-black.png</file>
     </qresource>
 </RCC>
diff --git a/src/tray-menu.cpp b/src/tray-menu.cpp
index 23102a4..28d3303 100644
--- a/src/tray-menu.cpp
+++ b/src/tray-menu.cpp
@@ -30,6 +30,7 @@
 #ifdef OSX_BUILD
 #define CONNECT_ICON ":/res/icon-connected-black.png"
 #define DISCONNECT_ICON ":/res/icon-disconnected-black.png"
+#define CONNECT_STATUS_ICON ":/res/icon-connected-status-black.png"
 
 #include <Security/Authorization.h>
 #include <Security/AuthorizationTags.h>
@@ -60,6 +61,7 @@
 TrayMenu::TrayMenu(QQmlContext* context, Face& face)
   : m_context(context)
   , m_isNfdRunning(false)
+  , m_isConnectedToHub(false)
   , m_menu(new QMenu(this))
   , m_entryPref(new QAction("Preferences...", m_menu))
   , m_entrySec(new QAction("Security...", m_menu))
@@ -80,6 +82,8 @@
 
   connect(this, SIGNAL(nfdActivityUpdate(bool)), this, SLOT(updateNfdActivityIcon(bool)),
           Qt::QueuedConnection);
+  connect(this, SIGNAL(connectivityUpdate(bool)), this, SLOT(updateConnectivity(bool)),
+          Qt::QueuedConnection);
 
   QString nccVersion = QString(NCC_VERSION) + " (ndn-cxx: " + NDN_CXX_VERSION_BUILD_STRING +
     ", NFD: " + NFD_VERSION_BUILD_STRING +
@@ -348,7 +352,12 @@
   m_isNfdRunning = isActive;
 
   if (isActive) {
-    m_tray->setIcon(QIcon(CONNECT_ICON));
+    if(m_isConnectedToHub) {
+      m_tray->setIcon(QIcon(CONNECT_STATUS_ICON));
+    }
+    else {
+      m_tray->setIcon(QIcon(CONNECT_ICON));
+    }
     if (isNdnAutoConfigEnabled()) {
       startNdnAutoConfig();
     }
@@ -359,6 +368,12 @@
 }
 
 void
+TrayMenu::updateConnectivity(bool isConnectedToHub)
+{
+  m_isConnectedToHub = isConnectedToHub;
+}
+
+void
 TrayMenu::enableCli()
 {
 #ifdef OSX_BUILD
diff --git a/src/tray-menu.hpp b/src/tray-menu.hpp
index 6015fe5..878c0a6 100644
--- a/src/tray-menu.hpp
+++ b/src/tray-menu.hpp
@@ -59,6 +59,9 @@
   void
   nfdActivityUpdate(bool isActive);
 
+  void
+  connectivityUpdate(bool isConnectedToHub);
+
 public:
   explicit
   TrayMenu(QQmlContext* context, Face& face);
@@ -118,6 +121,9 @@
   updateNfdActivityIcon(bool isActive);
 
   void
+  updateConnectivity(bool isConnectedToHub);
+
+  void
   enableCli();
 
   void
@@ -137,6 +143,7 @@
 private:
   QQmlContext* m_context;
   bool m_isNfdRunning;
+  bool m_isConnectedToHub;
   QSystemTrayIcon* m_tray;
   QMenu* m_menu;
   QAction* m_entryPref;