src: Recreating face in case of face deletion by NFD

Change-Id: Idd1d0b7f521e574ace38d6f671a682622d98209d
diff --git a/src/adjacency-list.cpp b/src/adjacency-list.cpp
index a905a7d..9d026af 100644
--- a/src/adjacency-list.cpp
+++ b/src/adjacency-list.cpp
@@ -233,6 +233,34 @@
   return it;
 }
 
+Adjacent *
+AdjacencyList::findAdjacent(const ndn::Name& adjName)
+{
+  std::list<Adjacent>::iterator it = std::find_if(m_adjList.begin(),
+                                                  m_adjList.end(),
+                                                  ndn::bind(&Adjacent::compare,
+                                                            _1, ndn::cref(adjName)));
+  if (it != m_adjList.end()) {
+    return &(*it);
+  }
+
+  return 0;
+}
+
+Adjacent *
+AdjacencyList::findAdjacent(uint64_t faceId)
+{
+  std::list<Adjacent>::iterator it = std::find_if(m_adjList.begin(),
+                                                  m_adjList.end(),
+                                                  ndn::bind(&Adjacent::compareFaceId,
+                                                            _1, faceId));
+  if (it != m_adjList.end()) {
+    return &(*it);
+  }
+
+  return 0;
+}
+
 void
 AdjacencyList::writeLog()
 {
diff --git a/src/adjacency-list.hpp b/src/adjacency-list.hpp
index 85bec25..38debed 100644
--- a/src/adjacency-list.hpp
+++ b/src/adjacency-list.hpp
@@ -98,6 +98,12 @@
     }
   }
 
+  Adjacent*
+  findAdjacent(const ndn::Name& adjName);
+
+  Adjacent*
+  findAdjacent(uint64_t faceId);
+
   void
   writeLog();
 
diff --git a/src/adjacent.cpp b/src/adjacent.cpp
index ddee24f..f551686 100644
--- a/src/adjacent.cpp
+++ b/src/adjacent.cpp
@@ -43,6 +43,7 @@
     , m_linkCost(DEFAULT_LINK_COST)
     , m_status(ADJACENT_STATUS_INACTIVE)
     , m_interestTimedOutNo(0)
+    , m_faceId(0)
 {
 }
 
@@ -52,18 +53,21 @@
     , m_linkCost(DEFAULT_LINK_COST)
     , m_status(ADJACENT_STATUS_INACTIVE)
     , m_interestTimedOutNo(0)
+    , m_faceId(0)
   {
   }
 
 Adjacent::Adjacent(const ndn::Name& an, const std::string& cfu,  double lc,
-          uint32_t s, uint32_t iton)
-{
-  m_name = an;
-  m_connectingFaceUri = cfu;
-  m_linkCost = lc;
-  m_status = s;
-  m_interestTimedOutNo = iton;
-}
+          uint32_t s, uint32_t iton, uint64_t faceId)
+    : m_name(an)
+    , m_connectingFaceUri(cfu)
+    , m_linkCost(lc)
+    , m_status(s)
+    , m_interestTimedOutNo(iton)
+    , m_faceId(faceId)
+  {
+
+  }
 
 bool
 Adjacent::operator==(const Adjacent& adjacent) const
@@ -74,12 +78,6 @@
           std::numeric_limits<double>::epsilon()) ;
 }
 
-bool
-Adjacent::compare(const ndn::Name& adjacencyName)
-{
-  return m_name == adjacencyName;
-}
-
 void
 Adjacent::writeLog()
 {
diff --git a/src/adjacent.hpp b/src/adjacent.hpp
index 90a0460..dd2c2e2 100644
--- a/src/adjacent.hpp
+++ b/src/adjacent.hpp
@@ -43,7 +43,7 @@
   Adjacent(const ndn::Name& an);
 
   Adjacent(const ndn::Name& an, const std::string& cfu,  double lc,
-          uint32_t s, uint32_t iton);
+          uint32_t s, uint32_t iton, uint64_t faceId);
 
   const ndn::Name&
   getName() const
@@ -105,11 +105,32 @@
     m_interestTimedOutNo = iton;
   }
 
+  void
+  setFaceId(uint64_t faceId)
+  {
+    m_faceId = faceId;
+  }
+
+  uint64_t
+  getFaceId()
+  {
+    return m_faceId;
+  }
+
   bool
   operator==(const Adjacent& adjacent) const;
 
-  bool
-  compare(const ndn::Name& adjacencyName);
+  inline bool
+  compare(const ndn::Name& adjacencyName)
+  {
+    return m_name == adjacencyName;
+  }
+
+  inline bool
+  compareFaceId(uint64_t faceId)
+  {
+    return m_faceId == faceId;
+  }
 
   void
   writeLog();
@@ -123,6 +144,7 @@
   double m_linkCost;
   uint32_t m_status;
   uint32_t m_interestTimedOutNo;
+  uint64_t m_faceId;
 };
 
 } // namespace nlsr
diff --git a/src/conf-file-processor.cpp b/src/conf-file-processor.cpp
index d07b2e2..8949b42 100644
--- a/src/conf-file-processor.cpp
+++ b/src/conf-file-processor.cpp
@@ -324,7 +324,7 @@
                                                        Adjacent::DEFAULT_LINK_COST);
         ndn::Name neighborName(name);
         if (!neighborName.empty()) {
-          Adjacent adj(name, faceUri, linkCost, ADJACENT_STATUS_INACTIVE, 0);
+          Adjacent adj(name, faceUri, linkCost, ADJACENT_STATUS_INACTIVE, 0, 0);
           m_nlsr.getAdjacencyList().insert(adj);
         }
         else {
diff --git a/src/face-monitor.cpp b/src/face-monitor.cpp
new file mode 100644
index 0000000..7685471
--- /dev/null
+++ b/src/face-monitor.cpp
@@ -0,0 +1,83 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014  University of Memphis,
+ *                     Regents of the University of California
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * \author A K M Mahmudul Hoque <ahoque1@memphis.edu>
+ *
+ **/
+#include "face-monitor.hpp"
+#include "logger.hpp"
+
+
+namespace nlsr {
+
+INIT_LOGGER("FaceMonitor");
+
+void
+FaceMonitor::startNotification()
+{
+  ndn::Interest interest("/localhost/nfd/faces/events");
+  interest
+    .setMustBeFresh(true)
+    .setChildSelector(1)
+    .setInterestLifetime(ndn::time::seconds(60));
+
+  _LOG_DEBUG("FaceMonitor::startNotification sending interest: " << interest);
+
+  m_face.expressInterest(interest,
+                         ndn::bind(&nlsr::FaceMonitor::onData, this, _2),
+                         ndn::bind(&nlsr::FaceMonitor::onTimeout, this));
+}
+
+void
+FaceMonitor::onTimeout()
+{
+  ndn::Interest interest("/localhost/nfd/faces/events");
+  interest
+    .setMustBeFresh(true)
+    .setChildSelector(1)
+    .setInterestLifetime(ndn::time::seconds(60));
+
+  _LOG_DEBUG("FaceMonitor::onTimeout sending interest: " << interest);
+
+  m_face.expressInterest(interest,
+                         ndn::bind(&nlsr::FaceMonitor::onData, this, _2),
+                         ndn::bind(&nlsr::FaceMonitor::onTimeout, this));
+}
+void
+FaceMonitor::onData(const ndn::Data& data)
+{
+  m_lastSequence = data.getName().get(-1).toSegment();
+  ndn::nfd::FaceEventNotification notification(data.getContent().blockFromValue());
+  m_notificationCallBack(notification);
+
+  ndn::Name nextNotification("/localhost/nfd/faces/events");
+  nextNotification.appendSegment(m_lastSequence + 1);
+
+  ndn::Interest interest(nextNotification);
+  interest.setInterestLifetime(ndn::time::seconds(60));
+
+  _LOG_DEBUG("FaceMonitor::onData Interest sent: " <<  interest);
+
+  m_face.expressInterest(interest,
+                         ndn::bind(&nlsr::FaceMonitor::onData, this, _2),
+                         ndn::bind(&nlsr::FaceMonitor::onTimeout, this));
+}
+
+
+} // namespace nlsr
diff --git a/src/face-monitor.hpp b/src/face-monitor.hpp
new file mode 100644
index 0000000..1344f60
--- /dev/null
+++ b/src/face-monitor.hpp
@@ -0,0 +1,65 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014  University of Memphis,
+ *                     Regents of the University of California
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * \author A K M Mahmudul Hoque <ahoque1@memphis.edu>
+ *
+ **/
+#ifndef FACE_MONITOR_HPP
+#define FACE_MONITOR_HPP
+
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/management/nfd-face-event-notification.hpp>
+
+namespace nlsr {
+
+class FaceMonitor
+{
+public:
+  typedef ndn::function<void(const ndn::nfd::FaceEventNotification&)> NotificationCallback;
+  typedef ndn::function<void()> TimeoutCallback;
+
+  FaceMonitor(boost::asio::io_service& ioService, const NotificationCallback& notificationCallBack)
+    : m_face(ioService)
+    , m_notificationCallBack(notificationCallBack)
+  {
+  }
+
+  ~FaceMonitor()
+  {
+  }
+
+  void
+  startNotification();
+
+private:
+  void
+  onTimeout();
+
+  void
+  onData(const ndn::Data& data);
+
+private:
+  ndn::Face m_face;
+  NotificationCallback m_notificationCallBack;
+  uint64_t m_lastSequence;
+};
+
+} // namespace nlsr
+
+ #endif //FACE_MONITOR_HPP
diff --git a/src/hello-protocol.cpp b/src/hello-protocol.cpp
index 1cd86ae..ebbfd3e 100644
--- a/src/hello-protocol.cpp
+++ b/src/hello-protocol.cpp
@@ -54,13 +54,19 @@
   std::list<Adjacent> adjList = m_nlsr.getAdjacencyList().getAdjList();
   for (std::list<Adjacent>::iterator it = adjList.begin(); it != adjList.end();
        ++it) {
-    /* interest name: /<neighbor>/NLSR/INFO/<router> */
-    ndn::Name interestName = (*it).getName() ;
-    interestName.append(NLSR_COMPONENT);
-    interestName.append(INFO_COMPONENT);
-    interestName.append(m_nlsr.getConfParameter().getRouterPrefix().wireEncode());
-    expressInterest(interestName,
-                    m_nlsr.getConfParameter().getInterestResendTime());
+    if((*it).getFaceId() != 0) {
+      /* interest name: /<neighbor>/NLSR/INFO/<router> */
+      ndn::Name interestName = (*it).getName() ;
+      interestName.append(NLSR_COMPONENT);
+      interestName.append(INFO_COMPONENT);
+      interestName.append(m_nlsr.getConfParameter().getRouterPrefix().wireEncode());
+      expressInterest(interestName,
+                      m_nlsr.getConfParameter().getInterestResendTime());
+    }
+    else {
+      registerPrefixes((*it).getName(), (*it).getConnectingFaceUri(),
+                       (*it).getLinkCost(), 31536000);
+    }
   }
   scheduleInterest(m_nlsr.getConfParameter().getInfoInterestInterval());
 }
@@ -94,15 +100,21 @@
     m_nlsr.getKeyChain().sign(data, m_nlsr.getDefaultCertName());
     _LOG_DEBUG("Sending out data for name: " << data.getName());
     m_nlsr.getNlsrFace().put(data);
-    int status = m_nlsr.getAdjacencyList().getStatusOfNeighbor(neighbor);
-    if (status == 0) {
-      /* interest name: /<neighbor>/NLSR/INFO/<router> */
-      ndn::Name interestName(neighbor);
-      interestName.append(NLSR_COMPONENT);
-      interestName.append(INFO_COMPONENT);
-      interestName.append(m_nlsr.getConfParameter().getRouterPrefix().wireEncode());
-      expressInterest(interestName,
-                      m_nlsr.getConfParameter().getInterestResendTime());
+    Adjacent *adjacent = m_nlsr.getAdjacencyList().findAdjacent(neighbor);
+    if (adjacent->getStatus() == 0) {
+      if(adjacent->getFaceId() != 0){
+        /* interest name: /<neighbor>/NLSR/INFO/<router> */
+        ndn::Name interestName(neighbor);
+        interestName.append(NLSR_COMPONENT);
+        interestName.append(INFO_COMPONENT);
+        interestName.append(m_nlsr.getConfParameter().getRouterPrefix().wireEncode());
+        expressInterest(interestName,
+                        m_nlsr.getConfParameter().getInterestResendTime());
+      }
+      else {
+        registerPrefixes(adjacent->getName(), adjacent->getConnectingFaceUri(),
+                         adjacent->getLinkCost(), 31536000);
+      }
     }
   }
 }
@@ -194,4 +206,46 @@
   _LOG_DEBUG("Validation Error: " << msg);
 }
 
+void
+HelloProtocol::registerPrefixes(const ndn::Name adjName, const std::string& faceUri,
+                               double linkCost, uint64_t timeout)
+{
+  ndn::Name broadcastKeyPrefix = DEFAULT_BROADCAST_PREFIX;
+  broadcastKeyPrefix.append("KEYS");
+  m_nlsr.getFib().registerPrefix(adjName, faceUri, linkCost, timeout,
+                                 ndn::bind(&HelloProtocol::onRegistrationSuccess,
+                                           this, _1, ndn::cref(adjName)),
+                                 ndn::bind(&HelloProtocol::onRegistrationFailure,
+                                           this, _1, _2));
+  m_nlsr.getFib().registerPrefix(m_nlsr.getConfParameter().getChronosyncPrefix(),
+                                 faceUri, linkCost, timeout);
+  m_nlsr.getFib().registerPrefix(m_nlsr.getConfParameter().getLsaPrefix(),
+                                 faceUri, linkCost, timeout);
+  m_nlsr.getFib().registerPrefix(broadcastKeyPrefix,
+                                 faceUri, linkCost, timeout);
+}
+
+void
+HelloProtocol::onRegistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
+                                     const ndn::Name neighbor)
+{
+  Adjacent *adjacent = m_nlsr.getAdjacencyList().findAdjacent(neighbor);
+  if (adjacent != 0) {
+    adjacent->setFaceId(commandSuccessResult.getFaceId());
+    /* interest name: /<neighbor>/NLSR/INFO/<router> */
+    ndn::Name interestName(neighbor);
+    interestName.append(NLSR_COMPONENT);
+    interestName.append(INFO_COMPONENT);
+    interestName.append(m_nlsr.getConfParameter().getRouterPrefix().wireEncode());
+    expressInterest(interestName,
+                    m_nlsr.getConfParameter().getInterestResendTime());
+  }
+}
+
+void
+HelloProtocol::onRegistrationFailure(uint32_t code, const std::string& error)
+{
+  _LOG_DEBUG(error << " (code: " << code << ")");
+}
+
 } //namespace nlsr
diff --git a/src/hello-protocol.hpp b/src/hello-protocol.hpp
index 5f1cc7d..fd8ef09 100644
--- a/src/hello-protocol.hpp
+++ b/src/hello-protocol.hpp
@@ -67,6 +67,16 @@
   onContentValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
                             const std::string& msg);
 
+  void
+  onRegistrationFailure(uint32_t code, const std::string& error);
+
+  void
+  onRegistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
+                        const ndn::Name neighbor);
+
+  void
+  registerPrefixes(const ndn::Name adjName, const std::string& faceUri,
+                   double linkCost, uint64_t timeout);
 private:
   Nlsr& m_nlsr;
   static const std::string INFO_COMPONENT;
diff --git a/src/lsa.cpp b/src/lsa.cpp
index 90f3188..854d89f 100644
--- a/src/lsa.cpp
+++ b/src/lsa.cpp
@@ -286,7 +286,7 @@
       ndn::Name adjName(*tok_iter++);
       std::string connectingFaceUri(*tok_iter++);
       double linkCost = boost::lexical_cast<double>(*tok_iter++);
-      Adjacent adjacent(adjName, connectingFaceUri, linkCost, 0, 0);
+      Adjacent adjacent(adjName, connectingFaceUri, linkCost, 0, 0, 0);
       addAdjacent(adjacent);
     }
     catch (std::exception& e) {
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index ed95631..703b494 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -76,7 +76,7 @@
 }
 
 void
-Nlsr::registerPrefixes()
+Nlsr::setStrategies()
 {
   std::string strategy("ndn:/localhost/nfd/strategy/broadcast");
   ndn::Name broadcastKeyPrefix = DEFAULT_BROADCAST_PREFIX;
@@ -84,14 +84,6 @@
   std::list<Adjacent>& adjacents = m_adjacencyList.getAdjList();
   for (std::list<Adjacent>::iterator it = adjacents.begin();
        it != adjacents.end(); it++) {
-    m_fib.registerPrefix((*it).getName(), (*it).getConnectingFaceUri(),
-                         (*it).getLinkCost(), 31536000); /* One Year in seconds */
-    m_fib.registerPrefix(m_confParam.getChronosyncPrefix(),
-                         (*it).getConnectingFaceUri(), (*it).getLinkCost(), 31536000);
-    m_fib.registerPrefix(m_confParam.getLsaPrefix(),
-                         (*it).getConnectingFaceUri(), (*it).getLinkCost(), 31536000);
-    m_fib.registerPrefix(broadcastKeyPrefix,
-                         (*it).getConnectingFaceUri(), (*it).getLinkCost(), 31536000);
     m_fib.setStrategy((*it).getName(), strategy);
   }
 
@@ -111,20 +103,13 @@
   m_sequencingManager.setSeqFileName(m_confParam.getSeqFileDir());
   m_sequencingManager.initiateSeqNoFromFile();
   m_syncLogicHandler.setSyncPrefix(m_confParam.getChronosyncPrefix().toUri());
-  intializeKey();
   /* Logging start */
   m_confParam.writeLog();
   m_adjacencyList.writeLog();
   m_namePrefixList.writeLog();
   /* Logging end */
-
-  createFaces();
-}
-
-void
-Nlsr::start()
-{
-  registerPrefixes();
+  intializeKey();
+  setStrategies();
   setInfoInterestFilter();
   setLsaInterestFilter();
   m_nlsrLsdb.buildAndInstallOwnNameLsa();
@@ -196,54 +181,8 @@
 }
 
 void
-Nlsr::createFace(const std::string& faceUri,
-                 const CommandSucceedCallback& onSuccess,
-                 const CommandFailCallback& onFailure)
-{
-  ndn::nfd::ControlParameters faceParameters;
-  faceParameters
-    .setUri(faceUri);
-  m_controller.start<ndn::nfd::FaceCreateCommand>(faceParameters,
-                                                  onSuccess,
-                                                  onFailure);
-}
-
-void
-Nlsr::onCreateFaceSuccess(const ndn::nfd::ControlParameters& commandSuccessResult)
-{
-  m_nFacesCreated++;
-  if (m_nFacesToCreate == m_nFacesCreated)
-  {
-    start();
-  }
-}
-
-void
-Nlsr::onCreateFaceFailure(int32_t code, const std::string& error)
-{
-  _LOG_DEBUG(error << " (code: " << code << ")");
-  destroyFaces();
-  throw Error("Error: Face creation failed");
-}
-
-void
-Nlsr::createFaces()
-{
-  std::list<Adjacent>& adjacents = m_adjacencyList.getAdjList();
-  for (std::list<Adjacent>::iterator it = adjacents.begin();
-       it != adjacents.end(); it++) {
-    createFace((*it).getConnectingFaceUri(),
-               ndn::bind(&Nlsr::onCreateFaceSuccess, this, _1),
-               ndn::bind(&Nlsr::onCreateFaceFailure, this, _1, _2));
-    m_nFacesToCreate++;
-  }
-}
-
-
-void
 Nlsr::onDestroyFaceSuccess(const ndn::nfd::ControlParameters& commandSuccessResult)
 {
-
 }
 
 void
@@ -259,34 +198,27 @@
   std::list<Adjacent>& adjacents = m_adjacencyList.getAdjList();
   for (std::list<Adjacent>::iterator it = adjacents.begin();
        it != adjacents.end(); it++) {
-    destroyFace((*it).getConnectingFaceUri());
+    m_fib.destroyFace((*it).getConnectingFaceUri(),
+                      ndn::bind(&Nlsr::onDestroyFaceSuccess, this, _1),
+                      ndn::bind(&Nlsr::onDestroyFaceFailure, this, _1, _2));
   }
 }
 
-void
-Nlsr::destroyFace(const std::string& faceUri)
-{
-  ndn::nfd::ControlParameters faceParameters;
-  faceParameters
-    .setUri(faceUri);
-  m_controller.start<ndn::nfd::FaceCreateCommand>(faceParameters,
-                                                  ndn::bind(&Nlsr::destroyFaceInNfd,
-                                                            this, _1),
-                                                  ndn::bind(&Nlsr::onDestroyFaceFailure,
-                                                            this, _1, _2));
-}
+
+
 
 void
-Nlsr::destroyFaceInNfd(const ndn::nfd::ControlParameters& faceDestroyResult)
+Nlsr::onFaceEventNotification(const ndn::nfd::FaceEventNotification& faceEventNotification)
 {
-  ndn::nfd::ControlParameters faceParameters;
-  faceParameters
-    .setFaceId(faceDestroyResult.getFaceId());
-  m_controller.start<ndn::nfd::FaceDestroyCommand>(faceParameters,
-                                                   ndn::bind(&Nlsr::onDestroyFaceSuccess,
-                                                             this, _1),
-                                                   ndn::bind(&Nlsr::onDestroyFaceFailure,
-                                                             this, _1, _2));
+  ndn::nfd::FaceEventKind kind = faceEventNotification.getKind();
+  if (kind == ndn::nfd::FACE_EVENT_DESTROYED) {
+    uint64_t faceId = faceEventNotification.getFaceId();
+    Adjacent *adjacent = m_adjacencyList.findAdjacent(faceId);
+    if (adjacent != 0) {
+      _LOG_DEBUG("Face to " << adjacent->getName() << "deleted");
+      adjacent->setFaceId(0);
+    }
+  }
 }
 
 
diff --git a/src/nlsr.hpp b/src/nlsr.hpp
index dd56c1b..c3b4795 100644
--- a/src/nlsr.hpp
+++ b/src/nlsr.hpp
@@ -30,6 +30,7 @@
 #include <ndn-cxx/security/key-chain.hpp>
 #include <ndn-cxx/security/certificate-cache-ttl.hpp>
 #include <ndn-cxx/util/scheduler.hpp>
+#include <ndn-cxx/management/nfd-face-event-notification.hpp>
 
 #include "conf-parameter.hpp"
 #include "adjacency-list.hpp"
@@ -41,6 +42,7 @@
 #include "route/fib.hpp"
 #include "communication/sync-logic-handler.hpp"
 #include "hello-protocol.hpp"
+#include "face-monitor.hpp"
 
 #include "validator.hpp"
 
@@ -62,10 +64,6 @@
   };
 
 public:
-  typedef ndn::function<void(const ndn::nfd::ControlParameters&)> CommandSucceedCallback;
-
-  typedef ndn::function<void(uint32_t/*code*/,const std::string&/*reason*/)> CommandFailCallback;
-
   Nlsr()
     : m_scheduler(m_nlsrFace.getIoService())
     , m_confParam()
@@ -88,9 +86,8 @@
     , m_certificateCache(new ndn::CertificateCacheTtl(m_nlsrFace.getIoService()))
     , m_validator(m_nlsrFace, DEFAULT_BROADCAST_PREFIX, m_certificateCache)
 
-    , m_controller(m_nlsrFace)
-    , m_nFacesToCreate(0)
-    , m_nFacesCreated(0)
+    , m_faceMonitor(m_nlsrFace.getIoService(),
+                    ndn::bind(&Nlsr::onFaceEventNotification, this, _1))
   {}
 
   void
@@ -272,9 +269,6 @@
   initialize();
 
   void
-  start();
-
-  void
   intializeKey();
 
   void
@@ -333,7 +327,7 @@
 
 private:
   void
-  registerPrefixes();
+  setStrategies();
 
   void
   registerKeyPrefix();
@@ -345,25 +339,13 @@
   onKeyPrefixRegSuccess(const ndn::Name& name);
 
   void
-  onCreateFaceSuccess(const ndn::nfd::ControlParameters& commandSuccessResult);
-
-  void
-  onCreateFaceFailure(int32_t code, const std::string& error);
-
-  void
-  createFaces();
-
-  void
   onDestroyFaceSuccess(const ndn::nfd::ControlParameters& commandSuccessResult);
 
   void
   onDestroyFaceFailure(int32_t code, const std::string& error);
 
   void
-  destroyFace(const std::string& faceUri);
-
-  void
-  destroyFaceInNfd(const ndn::nfd::ControlParameters& faceDestroyResult);
+  onFaceEventNotification(const ndn::nfd::FaceEventNotification& faceEventNotification);
 
 private:
   typedef std::map<ndn::Name, ndn::shared_ptr<ndn::IdentityCertificate> > CertMap;
@@ -395,9 +377,7 @@
   ndn::Name m_defaultIdentity;
   ndn::Name m_defaultCertName;
 
-  ndn::nfd::Controller m_controller;
-  int32_t m_nFacesToCreate;
-  int32_t m_nFacesCreated;
+  FaceMonitor m_faceMonitor;
 };
 
 } //namespace nlsr
diff --git a/src/route/fib.cpp b/src/route/fib.cpp
index 8b5d668..48af899 100644
--- a/src/route/fib.cpp
+++ b/src/route/fib.cpp
@@ -256,19 +256,62 @@
 }
 
 void
-Fib::registerPrefix(const ndn::Name& namePrefix, const std::string& faceUri,
-                    uint64_t faceCost, uint64_t timeout)
+Fib::createFace(const std::string& faceUri,
+                const CommandSucceedCallback& onSuccess,
+                const CommandFailCallback& onFailure)
 {
   ndn::nfd::ControlParameters faceParameters;
   faceParameters
-  .setUri(faceUri);
-
+    .setUri(faceUri);
   m_controller.start<ndn::nfd::FaceCreateCommand>(faceParameters,
-                                                  ndn::bind(&Fib::registerPrefixInNfd, this,_1,
-                                                            namePrefix, faceCost, timeout),
-                                                  ndn::bind(&Fib::onFailure, this, _1, _2,
-                                                             "Failed in name registration"));
-  
+                                                  onSuccess,
+                                                  onFailure);
+}
+
+void
+Fib::destroyFace(const std::string& faceUri,
+                 const CommandSucceedCallback& onSuccess,
+                 const CommandFailCallback& onFailure)
+{
+  createFace(faceUri,
+             ndn::bind(&Fib::destroyFaceInNfd, this, _1, onSuccess, onFailure),
+             onFailure);
+}
+
+void
+Fib::destroyFaceInNfd(const ndn::nfd::ControlParameters& faceDestroyResult,
+                        const CommandSucceedCallback& onSuccess,
+                        const CommandFailCallback& onFailure)
+{
+  ndn::nfd::ControlParameters faceParameters;
+  faceParameters
+    .setFaceId(faceDestroyResult.getFaceId());
+  m_controller.start<ndn::nfd::FaceDestroyCommand>(faceParameters,
+                                                   onSuccess,
+                                                   onFailure);
+}
+
+void
+Fib::registerPrefix(const ndn::Name& namePrefix, const std::string& faceUri,
+                    uint64_t faceCost, uint64_t timeout)
+{
+  createFace(faceUri,
+             ndn::bind(&Fib::registerPrefixInNfd, this,_1, namePrefix, faceCost, timeout),
+             ndn::bind(&Fib::onFailure, this, _1, _2,"Failed in name registration"));
+}
+
+void
+Fib::registerPrefix(const ndn::Name& namePrefix,
+                    const std::string& faceUri,
+                    uint64_t faceCost, uint64_t timeout,
+                    const CommandSucceedCallback& onSuccess,
+                    const CommandFailCallback& onFailure)
+
+{
+ createFace(faceUri,
+            ndn::bind(&Fib::registerPrefixInNfd, this,_1,
+                      namePrefix, faceCost, timeout, onSuccess, onFailure),
+            onFailure);
 }
 
 void
@@ -291,6 +334,24 @@
 }
 
 void
+Fib::registerPrefixInNfd(const ndn::nfd::ControlParameters& faceCreateResult,
+                         const ndn::Name& namePrefix, uint64_t faceCost, uint64_t timeout,
+                         const CommandSucceedCallback& onSuccess,
+                         const CommandFailCallback& onFailure)
+{
+  ndn::nfd::ControlParameters controlParameters;
+  controlParameters
+    .setName(namePrefix)
+    .setFaceId(faceCreateResult.getFaceId())
+    .setCost(faceCost)
+    .setExpirationPeriod(ndn::time::milliseconds(timeout * 1000))
+    .setOrigin(128);
+  m_controller.start<ndn::nfd::RibRegisterCommand>(controlParameters,
+                                                   onSuccess,
+                                                   onFailure);
+}
+
+void
 Fib::unregisterPrefix(const ndn::Name& namePrefix, const std::string& faceUri)
 {
   uint32_t faceId = m_faceMap.getFaceId(faceUri);
diff --git a/src/route/fib.hpp b/src/route/fib.hpp
index 9ffd44c..ecc5030 100644
--- a/src/route/fib.hpp
+++ b/src/route/fib.hpp
@@ -33,6 +33,9 @@
 
 namespace nlsr {
 
+typedef ndn::function<void(const ndn::nfd::ControlParameters&)> CommandSucceedCallback;
+typedef ndn::function<void(uint32_t/*code*/,const std::string&/*reason*/)> CommandFailCallback;
+
 class Nlsr;
 
 
@@ -90,8 +93,11 @@
                  uint64_t faceCost, uint64_t timeout);
 
   void
-  registerPrefixInNfd(const ndn::nfd::ControlParameters& faceCreateResult,
-                      const ndn::Name& namePrefix, uint64_t faceCost, uint64_t timeout);
+  registerPrefix(const ndn::Name& namePrefix,
+                 const std::string& faceUri,
+                 uint64_t faceCost, uint64_t timeout,
+                 const CommandSucceedCallback& onSuccess,
+                 const CommandFailCallback& onFailure);
   
   void
   setStrategy(const ndn::Name& name, const std::string& strategy);
@@ -99,8 +105,33 @@
   void
   writeLog();
 
+  void
+  destroyFace(const std::string& faceUri,
+              const CommandSucceedCallback& onSuccess,
+              const CommandFailCallback& onFailure);
+
 private:
   void
+  createFace(const std::string& faceUri,
+             const CommandSucceedCallback& onSuccess,
+             const CommandFailCallback& onFailure);
+
+  void
+  registerPrefixInNfd(const ndn::nfd::ControlParameters& faceCreateResult,
+                      const ndn::Name& namePrefix, uint64_t faceCost, uint64_t timeout);
+
+  void
+  registerPrefixInNfd(const ndn::nfd::ControlParameters& faceCreateResult,
+                      const ndn::Name& namePrefix, uint64_t faceCost, uint64_t timeout,
+                      const CommandSucceedCallback& onSuccess,
+                      const CommandFailCallback& onFailure);
+
+  void
+  destroyFaceInNfd(const ndn::nfd::ControlParameters& faceDestroyResult,
+                   const CommandSucceedCallback& onSuccess,
+                   const CommandFailCallback& onFailure);
+
+  void
   unregisterPrefix(const ndn::Name& namePrefix, const std::string& faceUri);
 
   void