src: change initialization order

Send Hello Interest after route to neighbor is successfully registered
--> First Hello interval is eliminated
--> After Hello Nack, wait exponentially before processing it as a timeout
Register sync route for each neighbor after its Hello Data is validated

refs: #5009

Change-Id: Ice39a591f1e58e474b494d93c913fa45e10f24f2
diff --git a/src/adjacency-list.cpp b/src/adjacency-list.cpp
index 0cf8ff3..d2ada2b 100644
--- a/src/adjacency-list.cpp
+++ b/src/adjacency-list.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2018,  The University of Memphis,
+ * Copyright (c) 2014-2019,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -186,9 +186,8 @@
 AdjacencyList::getNumOfActiveNeighbor() const
 {
   int32_t actNbrCount = 0;
-  for (std::list<Adjacent>::const_iterator it = m_adjList.begin(); it != m_adjList.end(); it++) {
-
-    if (it->getStatus() == Adjacent::STATUS_ACTIVE) {
+  for (const auto& adjacent: m_adjList) {
+    if (adjacent.getStatus() == Adjacent::STATUS_ACTIVE) {
       actNbrCount++;
     }
   }
@@ -198,24 +197,19 @@
 std::list<Adjacent>::iterator
 AdjacencyList::find(const ndn::Name& adjName)
 {
-  std::list<Adjacent>::iterator it = std::find_if(m_adjList.begin(),
-                                                  m_adjList.end(),
-                                                  std::bind(&Adjacent::compare,
-                                                            _1, std::cref(adjName)));
-  return it;
+  return std::find_if(m_adjList.begin(),
+                      m_adjList.end(),
+                      std::bind(&Adjacent::compare, _1, std::cref(adjName)));
 }
 
 std::list<Adjacent>::const_iterator
 AdjacencyList::find(const ndn::Name& adjName) const
 {
-  std::list<Adjacent>::const_iterator it = std::find_if(m_adjList.cbegin(),
-                                                        m_adjList.cend(),
-                                                        std::bind(&Adjacent::compare,
-                                                                  _1, std::cref(adjName)));
-  return it;
+  return std::find_if(m_adjList.cbegin(),
+                      m_adjList.cend(),
+                      std::bind(&Adjacent::compare, _1, std::cref(adjName)));
 }
 
-
 AdjacencyList::iterator
 AdjacencyList::findAdjacent(const ndn::Name& adjName)
 {
@@ -250,20 +244,16 @@
                                                   m_adjList.end(),
                                                   std::bind(&Adjacent::compareFaceUri,
                                                             _1, faceUri));
-  if (it != m_adjList.end()) {
-    return it->getFaceId();
-  }
 
-  return 0;
+  return it != m_adjList.end() ? it->getFaceId() : 0;
 }
 
 void
 AdjacencyList::writeLog()
 {
   NLSR_LOG_DEBUG("-------Adjacency List--------");
-  for (std::list<Adjacent>::iterator it = m_adjList.begin();
-       it != m_adjList.end(); it++) {
-    (*it).writeLog();
+  for (const auto& adjacent : m_adjList) {
+    NLSR_LOG_DEBUG(adjacent);
   }
 }
 
diff --git a/src/adjacent.cpp b/src/adjacent.cpp
index af1f926..1ae047e 100644
--- a/src/adjacent.cpp
+++ b/src/adjacent.cpp
@@ -104,10 +104,4 @@
   return os;
 }
 
-void
-Adjacent::writeLog()
-{
-  NLSR_LOG_DEBUG(*this);
-}
-
 } // namespace nlsr
diff --git a/src/adjacent.hpp b/src/adjacent.hpp
index c85f0ff..7930791 100644
--- a/src/adjacent.hpp
+++ b/src/adjacent.hpp
@@ -153,9 +153,6 @@
     return m_faceUri == faceUri;
   }
 
-  void
-  writeLog();
-
 public:
   static const double DEFAULT_LINK_COST;
   static const double NON_ADJACENT_COST;
diff --git a/src/communication/sync-logic-handler.cpp b/src/communication/sync-logic-handler.cpp
index 1784267..308457e 100644
--- a/src/communication/sync-logic-handler.cpp
+++ b/src/communication/sync-logic-handler.cpp
@@ -33,59 +33,29 @@
 
 INIT_LOGGER(SyncLogicHandler);
 
-template<class T>
-class NullDeleter
-{
-public:
-  void
-  operator()(T*)
-  {
-  }
-};
-
 SyncLogicHandler::SyncLogicHandler(ndn::Face& face, const IsLsaNew& isLsaNew,
                                    const ConfParameter& conf)
   : onNewLsa(std::make_unique<OnNewLsa>())
   , m_syncFace(face)
   , m_isLsaNew(isLsaNew)
   , m_confParam(conf)
+  , m_nameLsaUserPrefix(ndn::Name(m_confParam.getSyncUserPrefix()).append(std::to_string(Lsa::Type::NAME)))
+  , m_syncLogic(m_syncFace, m_confParam.getSyncProtocol(), m_confParam.getSyncPrefix(),
+                m_nameLsaUserPrefix, m_confParam.getSyncInterestLifetime(),
+                std::bind(&SyncLogicHandler::processUpdate, this, _1, _2))
 {
-  createSyncLogic(conf.getSyncPrefix());
-}
+  m_adjLsaUserPrefix = ndn::Name(m_confParam.getSyncUserPrefix())
+                         .append(std::to_string(Lsa::Type::ADJACENCY));
+  m_coorLsaUserPrefix = ndn::Name(m_confParam.getSyncUserPrefix())
+                         .append(std::to_string(Lsa::Type::COORDINATE));
 
-void
-SyncLogicHandler::createSyncLogic(const ndn::Name& syncPrefix, const ndn::time::milliseconds& syncInterestLifetime)
-{
-  if (m_syncLogic != nullptr) {
-    NLSR_LOG_WARN("Trying to create Sync Logic object, but Sync Logic object already exists");
-    return;
+  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF ||
+      m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_DRY_RUN) {
+    m_syncLogic.addUserNode(m_adjLsaUserPrefix);
   }
-
-  // Build LSA sync update prefix
-  buildUpdatePrefix();
-
-  NLSR_LOG_DEBUG("Creating Sync Logic object. Sync Prefix: " << syncPrefix);
-
-  // The face's lifetime is managed in main.cpp; Logic should not manage the memory
-  // of the object
-  std::shared_ptr<ndn::Face> facePtr(&m_syncFace, NullDeleter<ndn::Face>());
-
-  m_syncLogic = std::make_shared<SyncProtocolAdapter>(*facePtr,
-                  m_confParam.getSyncProtocol(),
-                  syncPrefix,
-                  m_nameLsaUserPrefix,
-                  syncInterestLifetime,
-                  std::bind(&SyncLogicHandler::processUpdate, this, _1, _2));
-
-  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) {
-    m_syncLogic->addUserNode(m_adjLsaUserPrefix);
-  }
-  else if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
-    m_syncLogic->addUserNode(m_coorLsaUserPrefix);
-  }
-  else {
-    m_syncLogic->addUserNode(m_adjLsaUserPrefix);
-    m_syncLogic->addUserNode(m_coorLsaUserPrefix);
+  else if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON ||
+           m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_DRY_RUN) {
+    m_syncLogic.addUserNode(m_coorLsaUserPrefix);
   }
 }
 
@@ -148,42 +118,19 @@
 void
 SyncLogicHandler::publishRoutingUpdate(const Lsa::Type& type, const uint64_t& seqNo)
 {
-  if (m_syncLogic == nullptr) {
-    NLSR_LOG_FATAL("Cannot publish routing update; SyncLogic does not exist");
-
-    BOOST_THROW_EXCEPTION(SyncLogicHandler::Error("Cannot publish routing update; SyncLogic does not exist"));
-  }
-
   switch (type) {
   case Lsa::Type::ADJACENCY:
-    m_syncLogic->publishUpdate(m_adjLsaUserPrefix, seqNo);
+    m_syncLogic.publishUpdate(m_adjLsaUserPrefix, seqNo);
     break;
   case Lsa::Type::COORDINATE:
-    m_syncLogic->publishUpdate(m_coorLsaUserPrefix, seqNo);
+    m_syncLogic.publishUpdate(m_coorLsaUserPrefix, seqNo);
     break;
   case Lsa::Type::NAME:
-    m_syncLogic->publishUpdate(m_nameLsaUserPrefix, seqNo);
+    m_syncLogic.publishUpdate(m_nameLsaUserPrefix, seqNo);
     break;
   default:
     break;
   }
 }
 
-void
-SyncLogicHandler::buildUpdatePrefix()
-{
-  ndn::Name updatePrefix = m_confParam.getLsaPrefix();
-  updatePrefix.append(m_confParam.getSiteName());
-  updatePrefix.append(m_confParam.getRouterName());
-
-  m_nameLsaUserPrefix = updatePrefix;
-  m_nameLsaUserPrefix.append(std::to_string(Lsa::Type::NAME));
-
-  m_adjLsaUserPrefix = updatePrefix;
-  m_adjLsaUserPrefix.append(std::to_string(Lsa::Type::ADJACENCY));
-
-  m_coorLsaUserPrefix = updatePrefix;
-  m_coorLsaUserPrefix.append(std::to_string(Lsa::Type::COORDINATE));
-}
-
 } // namespace nlsr
diff --git a/src/communication/sync-logic-handler.hpp b/src/communication/sync-logic-handler.hpp
index b9461c2..4dc2d3d 100644
--- a/src/communication/sync-logic-handler.hpp
+++ b/src/communication/sync-logic-handler.hpp
@@ -77,19 +77,6 @@
   publishRoutingUpdate(const Lsa::Type& type, const uint64_t& seqNo);
 
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-  /*! \brief Create and configure a Logic object to enable Sync for this NLSR.
-   *
-   * In a typical situation this only needs to be called once, when NLSR starts.
-   * \param syncPrefix The sync prefix you want this Sync to use
-   * \param syncInterestLifetime ChronoSync/PSync sends a periodic sync interest every
-   *        \p syncInterestLifetime / 2 ms
-   * \sa Nlsr::initialize
-   */
-  void
-  createSyncLogic(const ndn::Name& syncPrefix,
-                  const ndn::time::milliseconds& syncInterestLifetime =
-                    ndn::time::milliseconds(SYNC_INTEREST_LIFETIME_DEFAULT));
-
   /*! \brief Callback from Sync protocol
    *
    * In a typical situation this only needs to be called once, when NLSR starts.
@@ -99,11 +86,6 @@
   void
   processUpdate(const ndn::Name& updateName, uint64_t highSeq);
 
-  /*! \brief Simple function to glue Name components together
-   */
-  void
-  buildUpdatePrefix();
-
   /*! \brief Determine which kind of LSA was updated and fetch it.
    *
    * Checks that the received update is not from us, which can happen,
@@ -121,9 +103,6 @@
 
 private:
   ndn::Face& m_syncFace;
-PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-  std::shared_ptr<SyncProtocolAdapter> m_syncLogic;
-private:
   IsLsaNew m_isLsaNew;
   const ConfParameter& m_confParam;
 
@@ -132,6 +111,8 @@
   ndn::Name m_adjLsaUserPrefix;
   ndn::Name m_coorLsaUserPrefix;
 
+  SyncProtocolAdapter m_syncLogic;
+
 private:
   static const std::string NLSR_COMPONENT;
   static const std::string LSA_COMPONENT;
diff --git a/src/conf-file-processor.cpp b/src/conf-file-processor.cpp
index 1517a87..bbca665 100644
--- a/src/conf-file-processor.cpp
+++ b/src/conf-file-processor.cpp
@@ -451,17 +451,6 @@
     return false;
   }
 
-  // first-hello-interval
-  ConfigurationVariable<uint32_t> firstHelloInterval("first-hello-interval",
-                                                     std::bind(&ConfParameter::setFirstHelloInterval,
-                                                     &m_confParam, _1));
-  firstHelloInterval.setMinAndMaxValue(FIRST_HELLO_INTERVAL_MIN, FIRST_HELLO_INTERVAL_MAX);
-  firstHelloInterval.setOptional(FIRST_HELLO_INTERVAL_DEFAULT);
-
-  if (!firstHelloInterval.parseFromConfigSection(section)) {
-    return false;
-  }
-
   for (ConfigSection::const_iterator tn =
            section.begin(); tn != section.end(); ++tn) {
 
diff --git a/src/conf-parameter.cpp b/src/conf-parameter.cpp
index 67a5b4b..4938a8e 100644
--- a/src/conf-parameter.cpp
+++ b/src/conf-parameter.cpp
@@ -43,7 +43,6 @@
   : m_confFileName(confFileName)
   , m_lsaRefreshTime(LSA_REFRESH_TIME_DEFAULT)
   , m_adjLsaBuildInterval(ADJ_LSA_BUILD_INTERVAL_DEFAULT)
-  , m_firstHelloInterval(FIRST_HELLO_INTERVAL_DEFAULT)
   , m_routingCalcInterval(ROUTING_CALC_INTERVAL_DEFAULT)
   , m_faceDatasetFetchInterval(ndn::time::seconds(static_cast<int>(FACE_DATASET_FETCH_INTERVAL_DEFAULT)))
   , m_lsaInterestLifetime(ndn::time::seconds(static_cast<int>(LSA_INTEREST_LIFETIME_DEFAULT)))
@@ -80,17 +79,18 @@
   NLSR_LOG_INFO("LSA Interest lifetime: " << getLsaInterestLifetime());
   NLSR_LOG_INFO("Router dead interval: " << getRouterDeadInterval());
   NLSR_LOG_INFO("Max Faces Per Prefix: " << m_maxFacesPerPrefix);
-  NLSR_LOG_INFO("Hyperbolic Routing: " << m_hyperbolicState);
-  NLSR_LOG_INFO("Hyp R: " << m_corR);
-  int i=0;
-  for (auto const& value: m_corTheta) {
-    NLSR_LOG_INFO("Hyp Angle " << i++ << ": "<< value);
+  if (m_hyperbolicState == HYPERBOLIC_STATE_ON || m_hyperbolicState == HYPERBOLIC_STATE_DRY_RUN) {
+    NLSR_LOG_INFO("Hyperbolic Routing: " << m_hyperbolicState);
+    NLSR_LOG_INFO("Hyp R: " << m_corR);
+    int i=0;
+    for (auto const& value: m_corTheta) {
+      NLSR_LOG_INFO("Hyp Angle " << i++ << ": "<< value);
+    }
   }
   NLSR_LOG_INFO("State Directory: " << m_stateFileDir);
 
   // Event Intervals
   NLSR_LOG_INFO("Adjacency LSA build interval:  " << m_adjLsaBuildInterval);
-  NLSR_LOG_INFO("First Hello Interest interval: " << m_firstHelloInterval);
   NLSR_LOG_INFO("Routing calculation interval:  " << m_routingCalcInterval);
 }
 
diff --git a/src/conf-parameter.hpp b/src/conf-parameter.hpp
index 6b63937..df541a5 100644
--- a/src/conf-parameter.hpp
+++ b/src/conf-parameter.hpp
@@ -56,15 +56,9 @@
 };
 
 enum {
-  ADJ_LSA_BUILD_INTERVAL_MIN = 0,
-  ADJ_LSA_BUILD_INTERVAL_DEFAULT = 5,
-  ADJ_LSA_BUILD_INTERVAL_MAX = 5
-};
-
-enum {
-  FIRST_HELLO_INTERVAL_MIN = 0,
-  FIRST_HELLO_INTERVAL_DEFAULT = 10,
-  FIRST_HELLO_INTERVAL_MAX = 10
+  ADJ_LSA_BUILD_INTERVAL_MIN = 5,
+  ADJ_LSA_BUILD_INTERVAL_DEFAULT = 10,
+  ADJ_LSA_BUILD_INTERVAL_MAX = 30
 };
 
 enum {
@@ -94,7 +88,7 @@
 
 enum {
   HELLO_TIMEOUT_MIN = 1,
-  HELLO_TIMEOUT_DEFAULT = 3,
+  HELLO_TIMEOUT_DEFAULT = 1,
   HELLO_TIMEOUT_MAX = 15
 };
 
@@ -180,11 +174,15 @@
   }
 
   void
-  buildRouterPrefix()
+  buildRouterAndSyncUserPrefix()
   {
     m_routerPrefix = m_network;
     m_routerPrefix.append(m_siteName);
     m_routerPrefix.append(m_routerName);
+
+    m_syncUserPrefix = m_lsaPrefix;
+    m_syncUserPrefix.append(m_siteName);
+    m_syncUserPrefix.append(m_routerName);
   }
 
   const ndn::Name&
@@ -194,6 +192,12 @@
   }
 
   const ndn::Name&
+  getSyncUserPrefix() const
+  {
+    return m_syncUserPrefix;
+  }
+
+  const ndn::Name&
   getSyncPrefix() const
   {
     return m_syncPrefix;
@@ -256,18 +260,6 @@
   }
 
   void
-  setFirstHelloInterval(uint32_t interval)
-  {
-    m_firstHelloInterval = interval;
-  }
-
-  uint32_t
-  getFirstHelloInterval() const
-  {
-    return m_firstHelloInterval;
-  }
-
-  void
   setRoutingCalcInterval(uint32_t interval)
   {
     m_routingCalcInterval = interval;
@@ -481,7 +473,7 @@
   ndn::Name m_network;
 
   ndn::Name m_routerPrefix;
-  ndn::Name m_lsaRouterPrefix;
+  ndn::Name m_syncUserPrefix;
 
   ndn::Name m_syncPrefix;
   ndn::Name m_lsaPrefix;
@@ -489,7 +481,6 @@
   uint32_t  m_lsaRefreshTime;
 
   uint32_t m_adjLsaBuildInterval;
-  uint32_t m_firstHelloInterval;
   uint32_t m_routingCalcInterval;
 
   uint32_t m_faceDatasetFetchTries;
diff --git a/src/hello-protocol.cpp b/src/hello-protocol.cpp
index c068905..3d67771 100644
--- a/src/hello-protocol.cpp
+++ b/src/hello-protocol.cpp
@@ -42,55 +42,55 @@
   , m_confParam(confParam)
   , m_routingTable(routingTable)
   , m_lsdb(lsdb)
+  , m_adjacencyList(m_confParam.getAdjacencyList())
 {
 }
 
 void
 HelloProtocol::expressInterest(const ndn::Name& interestName, uint32_t seconds)
 {
-  NLSR_LOG_DEBUG("Expressing Interest :" << interestName);
+  NLSR_LOG_DEBUG("Expressing Interest: " << interestName);
   ndn::Interest interest(interestName);
   interest.setInterestLifetime(ndn::time::seconds(seconds));
   interest.setMustBeFresh(true);
   interest.setCanBePrefix(true);
   m_face.expressInterest(interest,
-                         std::bind(&HelloProtocol::onContent, this, _1, _2),
-                         [this] (const ndn::Interest& interest, const ndn::lp::Nack& nack)
-                         {
-                           NDN_LOG_TRACE("Received Nack with reason " << nack.getReason());
-                           NDN_LOG_TRACE("Treating as timeout");
-                           processInterestTimedOut(interest);
-                         },
-                         std::bind(&HelloProtocol::processInterestTimedOut, this, _1));
+    std::bind(&HelloProtocol::onContent, this, _1, _2),
+    [this, seconds] (const ndn::Interest& interest, const ndn::lp::Nack& nack)
+    {
+      NDN_LOG_TRACE("Received Nack with reason: " << nack.getReason());
+      NDN_LOG_TRACE("Will treat as timeout in " << 2 * seconds << " seconds");
+      m_scheduler.schedule(ndn::time::seconds(2 * seconds),
+        [this, interest] { processInterestTimedOut(interest); });
+    },
+    std::bind(&HelloProtocol::processInterestTimedOut, this, _1));
 
   // increment SENT_HELLO_INTEREST
   hpIncrementSignal(Statistics::PacketType::SENT_HELLO_INTEREST);
 }
 
 void
-HelloProtocol::sendScheduledInterest()
+HelloProtocol::sendHelloInterest(const ndn::Name& neighbor)
 {
-  for (const auto& adjacent : m_confParam.getAdjacencyList().getAdjList()) {
-    // If this adjacency has a Face, just proceed as usual.
-    if(adjacent.getFaceId() != 0) {
-      // interest name: /<neighbor>/NLSR/INFO/<router>
-      ndn::Name interestName = adjacent.getName() ;
-      interestName.append(NLSR_COMPONENT);
-      interestName.append(INFO_COMPONENT);
-      interestName.append(m_confParam.getRouterPrefix().wireEncode());
-      expressInterest(interestName, m_confParam.getInterestResendTime());
-      NLSR_LOG_DEBUG("Sending scheduled interest: " << interestName);
-    }
+  auto adjacent = m_adjacencyList.findAdjacent(neighbor);
+
+  if (adjacent == m_adjacencyList.end()) {
+    return;
   }
-  scheduleInterest(m_confParam.getInfoInterestInterval());
-}
 
-void
-HelloProtocol::scheduleInterest(uint32_t seconds)
-{
-  NLSR_LOG_DEBUG("Scheduling HELLO Interests in " << ndn::time::seconds(seconds));
+  // If this adjacency has a Face, just proceed as usual.
+  if(adjacent->getFaceId() != 0) {
+    // interest name: /<neighbor>/NLSR/INFO/<router>
+    ndn::Name interestName = adjacent->getName() ;
+    interestName.append(NLSR_COMPONENT);
+    interestName.append(INFO_COMPONENT);
+    interestName.append(m_confParam.getRouterPrefix().wireEncode());
+    expressInterest(interestName, m_confParam.getInterestResendTime());
+    NLSR_LOG_DEBUG("Sending HELLO interest: " << interestName);
+  }
 
-  m_scheduler.schedule(ndn::time::seconds(seconds), [this] { sendScheduledInterest(); });
+  m_scheduler.schedule(ndn::time::seconds(m_confParam.getInfoInterestInterval()),
+                       [this, neighbor] { sendHelloInterest(neighbor); });
 }
 
 void
@@ -113,7 +113,7 @@
   ndn::Name neighbor;
   neighbor.wireDecode(interestName.get(-1).blockFromValue());
   NLSR_LOG_DEBUG("Neighbor: " << neighbor);
-  if (m_confParam.getAdjacencyList().isNeighbor(neighbor)) {
+  if (m_adjacencyList.isNeighbor(neighbor)) {
     std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>();
     data->setName(ndn::Name(interest.getName()).appendVersion());
     data->setFreshnessPeriod(ndn::time::seconds(10)); // 10 sec
@@ -128,7 +128,7 @@
     // increment SENT_HELLO_DATA
     hpIncrementSignal(Statistics::PacketType::SENT_HELLO_DATA);
 
-    auto adjacent = m_confParam.getAdjacencyList().findAdjacent(neighbor);
+    auto adjacent = m_adjacencyList.findAdjacent(neighbor);
     // If this neighbor was previously inactive, send our own hello interest, too
     if (adjacent->getStatus() == Adjacent::STATUS_INACTIVE) {
       // We can only do that if the neighbor currently has a face.
@@ -155,15 +155,14 @@
   }
   ndn::Name neighbor = interestName.getPrefix(-3);
   NLSR_LOG_DEBUG("Neighbor: " << neighbor);
-  m_confParam.getAdjacencyList().incrementTimedOutInterestCount(neighbor);
+  m_adjacencyList.incrementTimedOutInterestCount(neighbor);
 
-  Adjacent::Status status = m_confParam.getAdjacencyList().getStatusOfNeighbor(neighbor);
+  Adjacent::Status status = m_adjacencyList.getStatusOfNeighbor(neighbor);
 
-  uint32_t infoIntTimedOutCount =
-    m_confParam.getAdjacencyList().getTimedOutInterestCount(neighbor);
+  uint32_t infoIntTimedOutCount = m_adjacencyList.getTimedOutInterestCount(neighbor);
   NLSR_LOG_DEBUG("Status: " << status);
   NLSR_LOG_DEBUG("Info Interest Timed out: " << infoIntTimedOutCount);
-  if (infoIntTimedOutCount < m_confParam.getInterestRetryNumber()) {
+  if (infoIntTimedOutCount <= m_confParam.getInterestRetryNumber()) {
     // interest name: /<neighbor>/NLSR/INFO/<router>
     ndn::Name interestName(neighbor);
     interestName.append(NLSR_COMPONENT);
@@ -174,7 +173,7 @@
   }
   else if ((status == Adjacent::STATUS_ACTIVE) &&
            (infoIntTimedOutCount == m_confParam.getInterestRetryNumber())) {
-    m_confParam.getAdjacencyList().setStatusOfNeighbor(neighbor, Adjacent::STATUS_INACTIVE);
+    m_adjacencyList.setStatusOfNeighbor(neighbor, Adjacent::STATUS_INACTIVE);
 
     NLSR_LOG_DEBUG("Neighbor: " << neighbor << " status changed to INACTIVE");
 
@@ -189,10 +188,9 @@
 HelloProtocol::onContent(const ndn::Interest& interest, const ndn::Data& data)
 {
   NLSR_LOG_DEBUG("Received data for INFO(name): " << data.getName());
-  if (data.getSignature().hasKeyLocator()) {
-    if (data.getSignature().getKeyLocator().getType() == ndn::KeyLocator::KeyLocator_Name) {
-      NLSR_LOG_DEBUG("Data signed with: " << data.getSignature().getKeyLocator().getName());
-    }
+  if (data.getSignature().hasKeyLocator() &&
+      data.getSignature().getKeyLocator().getType() == ndn::tlv::Name) {
+    NLSR_LOG_DEBUG("Data signed with: " << data.getSignature().getKeyLocator().getName());
   }
   m_confParam.getValidator().validate(data,
                                       std::bind(&HelloProtocol::onContentValidated, this, _1),
@@ -210,10 +208,10 @@
   if (dataName.get(-3).toUri() == INFO_COMPONENT) {
     ndn::Name neighbor = dataName.getPrefix(-4);
 
-    Adjacent::Status oldStatus = m_confParam.getAdjacencyList().getStatusOfNeighbor(neighbor);
-    m_confParam.getAdjacencyList().setStatusOfNeighbor(neighbor, Adjacent::STATUS_ACTIVE);
-    m_confParam.getAdjacencyList().setTimedOutInterestCount(neighbor, 0);
-    Adjacent::Status newStatus = m_confParam.getAdjacencyList().getStatusOfNeighbor(neighbor);
+    Adjacent::Status oldStatus = m_adjacencyList.getStatusOfNeighbor(neighbor);
+    m_adjacencyList.setStatusOfNeighbor(neighbor, Adjacent::STATUS_ACTIVE);
+    m_adjacencyList.setTimedOutInterestCount(neighbor, 0);
+    Adjacent::Status newStatus = m_adjacencyList.getStatusOfNeighbor(neighbor);
 
     NLSR_LOG_DEBUG("Neighbor : " << neighbor);
     NLSR_LOG_DEBUG("Old Status: " << oldStatus << " New Status: " << newStatus);
@@ -226,6 +224,8 @@
         m_lsdb.scheduleAdjLsaBuild();
       }
     }
+
+    onHelloDataValidated(neighbor);
   }
   // increment RCV_HELLO_DATA
   hpIncrementSignal(Statistics::PacketType::RCV_HELLO_DATA);
diff --git a/src/hello-protocol.hpp b/src/hello-protocol.hpp
index ff87a3b..3ba4ee7 100644
--- a/src/hello-protocol.hpp
+++ b/src/hello-protocol.hpp
@@ -45,18 +45,6 @@
                 ndn::security::SigningInfo& signingInfo,
                 ConfParameter& confParam, RoutingTable& routingTable, Lsdb& lsdb);
 
-  /*! \brief Schedules a Hello Interest event.
-   *
-   * This function serves as the Hello Interest loop, and must be
-   * explicitly called to start the Hello cycle. This is done at
-   * NLSR's initialization.
-   *
-   * \sa Nlsr::initialize
-   * \param seconds The number of seconds to wait before calling the event.
-   */
-  void
-  scheduleInterest(uint32_t seconds);
-
   /*! \brief Sends a Hello Interest packet.
    *
    * \param interestNamePrefix The name of the router that has published the
@@ -75,14 +63,12 @@
    *
    * This function is called as part of a schedule to regularly
    * determine the adjacency status of neighbors. This function
-   * creates and sends a Hello Interest to each neighbor in
-   * Nlsr::m_adjacencyList. If the neighbor has not been contacted
-   * before and currently has no Face in NFD, this method will call a
-   * different pipeline that creates the Face first, then registers
-   * prefixes.
+   * creates and sends a Hello Interest to the given adjacent.
+   *
+   * \param neighbor the name of the neighbor
    */
   void
-  sendScheduledInterest();
+  sendHelloInterest(const ndn::Name& neighbor);
 
   /*! \brief Processes a Hello Interest from a neighbor.
    *
@@ -167,6 +153,9 @@
   onRegistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
                         const ndn::Name& neighbor, const ndn::time::milliseconds& timeout);
 
+public:
+  ndn::util::Signal<HelloProtocol, const ndn::Name&> onHelloDataValidated;
+
 private:
   ndn::Face& m_face;
   ndn::Scheduler m_scheduler;
@@ -175,6 +164,7 @@
   ConfParameter& m_confParam;
   RoutingTable& m_routingTable;
   Lsdb& m_lsdb;
+  AdjacencyList& m_adjacencyList;
 
   static const std::string INFO_COMPONENT;
   static const std::string NLSR_COMPONENT;
diff --git a/src/lsdb.cpp b/src/lsdb.cpp
index 1e3cf1b..d5ddd12 100644
--- a/src/lsdb.cpp
+++ b/src/lsdb.cpp
@@ -211,8 +211,8 @@
     if (nlsa.getOrigRouter() != m_confParam.getRouterPrefix()) {
       // If this name LSA is from another router, add the advertised
       // prefixes to the NPT.
-      m_namePrefixTable.addEntry(nlsa.getOrigRouter(),
-                                           nlsa.getOrigRouter());
+      m_namePrefixTable.addEntry(nlsa.getOrigRouter(), nlsa.getOrigRouter());
+
       for (const auto& name : nlsa.getNpl().getNames()) {
         if (name != m_confParam.getRouterPrefix()) {
           m_namePrefixTable.addEntry(name, nlsa.getOrigRouter());
@@ -523,6 +523,10 @@
 void
 Lsdb::writeCorLsdbLog()
 {
+  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_OFF) {
+    return;
+  }
+
   NLSR_LOG_DEBUG("---------------Cor LSDB-------------------");
   for (const auto& corLsa : m_corLsdb) {
     corLsa.writeLog();
@@ -558,12 +562,14 @@
     return;
   }
 
-  if (m_isBuildAdjLsaSheduled == false) {
+  if (m_isBuildAdjLsaSheduled) {
+    NLSR_LOG_DEBUG("Rescheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
+  }
+  else {
     NLSR_LOG_DEBUG("Scheduling Adjacency LSA build in " << m_adjLsaBuildInterval);
-
-    m_scheduler.schedule(m_adjLsaBuildInterval, [this] { buildAdjLsa(); });
     m_isBuildAdjLsaSheduled = true;
   }
+  m_scheduledAdjLsaBuild = m_scheduler.schedule(m_adjLsaBuildInterval, [this] { buildAdjLsa(); });
 }
 
 void
@@ -608,9 +614,9 @@
   // hopefully finished)
   else {
     m_isBuildAdjLsaSheduled = true;
-    int schedulingTime = m_confParam.getInterestRetryNumber() *
-                         m_confParam.getInterestResendTime();
-    m_scheduler.schedule(ndn::time::seconds(schedulingTime), [this] { buildAdjLsa(); });
+    auto schedulingTime = ndn::time::seconds(m_confParam.getInterestRetryNumber() *
+                                             m_confParam.getInterestResendTime());
+    m_scheduledAdjLsaBuild = m_scheduler.schedule(schedulingTime, [this] { buildAdjLsa(); });
   }
 }
 
@@ -1264,6 +1270,10 @@
 void
 Lsdb::writeAdjLsdbLog()
 {
+  if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
+    return;
+  }
+
   NLSR_LOG_DEBUG("---------------Adj LSDB-------------------");
   for (const auto& adj : m_adjLsdb) {
     adj.writeLog();
diff --git a/src/lsdb.hpp b/src/lsdb.hpp
index 9f37002..718ee55 100644
--- a/src/lsdb.hpp
+++ b/src/lsdb.hpp
@@ -207,7 +207,7 @@
     return m_isBuildAdjLsaSheduled;
   }
 
-  const SyncLogicHandler&
+  SyncLogicHandler&
   getSync() {
     return m_sync;
   }
@@ -412,6 +412,7 @@
 
   bool m_isBuildAdjLsaSheduled;
   int64_t m_adjBuildCount;
+  ndn::scheduler::ScopedEventId m_scheduledAdjLsaBuild;
 
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   ndn::InMemoryStoragePersistent m_lsaStorage;
diff --git a/src/main.cpp b/src/main.cpp
index b271298..d109582 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -20,7 +20,7 @@
  **/
 
 #include "conf-file-processor.hpp"
-#include "nlsr-runner.hpp"
+#include "nlsr.hpp"
 #include "version.hpp"
 
 #include <boost/exception/get_error_info.hpp>
@@ -85,6 +85,7 @@
 
   boost::asio::io_service ioService;
   ndn::Face face(ioService);
+  ndn::KeyChain keyChain;
 
   nlsr::ConfParameter confParam(face, configFileName);
   nlsr::ConfFileProcessor configProcessor(confParam);
@@ -94,15 +95,16 @@
     return 2;
   }
 
-  confParam.buildRouterPrefix();
+  confParam.buildRouterAndSyncUserPrefix();
   confParam.writeLog();
 
-  nlsr::NlsrRunner runner(face, confParam);
+  nlsr::Nlsr nlsr(face, keyChain, confParam);
 
   try {
-    runner.run();
+    face.processEvents();
   }
   catch (const std::exception& e) {
+    nlsr.getFib().clean();
     std::cerr << "FATAL: " << getExtendedErrorMessage(e) << std::endl;
     return 1;
   }
diff --git a/src/nlsr-runner.cpp b/src/nlsr-runner.cpp
deleted file mode 100644
index 41c0f8c..0000000
--- a/src/nlsr-runner.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2019,  The University of Memphis,
- *                           Regents of the University of California,
- *                           Arizona Board of Regents.
- *
- * 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/>.
- **/
-
-#include "nlsr-runner.hpp"
-
-namespace nlsr {
-
-NlsrRunner::NlsrRunner(ndn::Face& face, ConfParameter& confParam)
-  : m_face(face)
-  , m_confParam(confParam)
-  , m_nlsr(m_face, m_keyChain, m_confParam)
-{
-}
-
-void
-NlsrRunner::run()
-{
-  m_nlsr.initialize();
-
-  try {
-    m_face.processEvents();
-  }
-  catch (...) {
-    m_nlsr.getFib().clean();
-    throw;
-  }
-}
-
-} // namespace nlsr
diff --git a/src/nlsr-runner.hpp b/src/nlsr-runner.hpp
deleted file mode 100644
index afe653e..0000000
--- a/src/nlsr-runner.hpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2019,  The University of Memphis,
- *                           Regents of the University of California,
- *                           Arizona Board of Regents.
- *
- * 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/>.
- **/
-
-#ifndef NLSR_NLSR_RUNNER_HPP
-#define NLSR_NLSR_RUNNER_HPP
-
-#include "nlsr.hpp"
-#include "conf-parameter.hpp"
-
-#include <ndn-cxx/face.hpp>
-#include <ndn-cxx/util/scheduler.hpp>
-
-namespace nlsr {
-
-/*! \brief A wrapper class to instantiate and configure an NLSR object.
- *
- * As its name suggests, this class is responsible for running
- * NLSR. It creates an nlsr::ConfFileProcessor to read a configuration
- * file and uses that to configure and then start an NLSR process.
- * This class only exists to provide this functionality, and there is
- * no special reliance of NLSR on this class.
- */
-class NlsrRunner
-{
-public:
-  explicit
-  NlsrRunner(ndn::Face& face, ConfParameter& confParam);
-
-  /*! \brief Instantiate, configure, and start the NLSR process.
-   *
-   * Each NlsrRunner is uniquely paired to the Face it's instantiated
-   * with. This is *not* a factory-type class, but a one-to-one
-   * relationship. If one wants to create multiple NLSR classes,
-   * multiple NLSR runners need to be created, too.
-   *
-   * \throws ConfFileError The configuration file cannot be processed.
-   *                       NLSR is not started.
-   * \sa Nlsr::canonizeNeighborUris
-   */
-  void
-  run();
-
-private:
-  ndn::Face& m_face;
-  ndn::KeyChain m_keyChain;
-  ConfParameter& m_confParam;
-  Nlsr m_nlsr;
-};
-
-} // namespace nlsr
-
-#endif // NLSR_NLSR_RUNNER_HPP
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index cbd981e..3094e32 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -50,36 +50,77 @@
   , m_fib(m_face, m_scheduler, m_adjacencyList, m_confParam, m_keyChain)
   , m_routingTable(m_scheduler, m_fib, m_lsdb, m_namePrefixTable, m_confParam)
   , m_namePrefixTable(m_fib, m_routingTable, m_routingTable.afterRoutingChange)
-  , m_lsdb(m_face, m_keyChain, m_signingInfo,
-           m_confParam, m_namePrefixTable, m_routingTable)
+  , m_lsdb(m_face, m_keyChain, m_signingInfo, m_confParam, m_namePrefixTable, m_routingTable)
+  , m_helloProtocol(m_face, m_keyChain, m_signingInfo, confParam, m_routingTable, m_lsdb)
   , m_afterSegmentValidatedConnection(m_lsdb.afterSegmentValidatedSignal.connect(
                                       std::bind(&Nlsr::afterFetcherSignalEmitted, this, _1)))
   , m_onNewLsaConnection(m_lsdb.getSync().onNewLsa->connect(
-                          [this] (const ndn::Name& updateName, uint64_t sequenceNumber,
-                                  const ndn::Name& originRouter) {
-                            registerStrategyForCerts(originRouter);
-                          }))
+      [this] (const ndn::Name& updateName, uint64_t sequenceNumber,
+              const ndn::Name& originRouter) {
+        registerStrategyForCerts(originRouter);
+      }))
+  , m_onPrefixRegistrationSuccess(m_fib.onPrefixRegistrationSuccess.connect(
+      [this] (const ndn::Name& name) {
+        m_helloProtocol.sendHelloInterest(name);
+      }))
+  , m_onHelloDataValidated(m_helloProtocol.onHelloDataValidated.connect(
+      [this] (const ndn::Name& neighbor) {
+        auto it = m_adjacencyList.findAdjacent(neighbor);
+        if (it != m_adjacencyList.end()) {
+          m_fib.registerPrefix(m_confParam.getSyncPrefix(), it->getFaceUri(), it->getLinkCost(),
+                               ndn::time::milliseconds::max(), ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
+        }
+      }))
   , m_dispatcher(m_face, m_keyChain)
   , m_datasetHandler(m_dispatcher, m_lsdb, m_routingTable)
-  , m_helloProtocol(m_face, m_keyChain, m_signingInfo, confParam, m_routingTable, m_lsdb)
   , m_certStore(m_confParam.getCertStore())
   , m_controller(m_face, m_keyChain)
   , m_faceDatasetController(m_face, m_keyChain)
   , m_prefixUpdateProcessor(m_dispatcher,
-                            m_confParam.getPrefixUpdateValidator(),
-                            m_namePrefixList,
-                            m_lsdb,
-                            m_confParam.getConfFileNameDynamic())
+      m_confParam.getPrefixUpdateValidator(),
+      m_namePrefixList,
+      m_lsdb,
+      m_confParam.getConfFileNameDynamic())
   , m_nfdRibCommandProcessor(m_dispatcher,
-                             m_namePrefixList,
-                             m_lsdb)
+      m_namePrefixList,
+      m_lsdb)
   , m_statsCollector(m_lsdb, m_helloProtocol)
   , m_faceMonitor(m_face)
 {
+  NLSR_LOG_DEBUG("Initializing Nlsr");
+
   m_faceMonitor.onNotification.connect(std::bind(&Nlsr::onFaceEventNotification, this, _1));
   m_faceMonitor.start();
 
+  // Do key initialization and registrations first, then initialize faces
+  // which will create routes to neighbor
+
   setStrategies();
+
+  initializeKey();
+
+  NLSR_LOG_DEBUG("Default NLSR identity: " << m_signingInfo.getSignerName());
+
+  // Can be moved to HelloProtocol and Lsdb ctor if initializeKey is set
+  // earlier in the Nlsr constructor so as to set m_signingInfo
+  setInfoInterestFilter();
+  setLsaInterestFilter();
+
+  // add top-level prefixes: router and localhost prefix
+  addDispatcherTopPrefix(ndn::Name(m_confParam.getRouterPrefix()).append("nlsr"));
+  addDispatcherTopPrefix(LOCALHOST_PREFIX);
+
+  enableIncomingFaceIdIndication();
+
+  registerKeyPrefix();
+  registerLocalhostPrefix();
+  registerRouterPrefix();
+
+  initializeFaces(std::bind(&Nlsr::processFaceDataset, this, _1),
+                  std::bind(&Nlsr::onFaceDatasetFetchTimeout, this, _1, _2, 0));
+
+  // Could be moved into ctor, but unit tests need to be modified
+  initialize();
 }
 
 void
@@ -120,7 +161,7 @@
 void
 Nlsr::registrationFailed(const ndn::Name& name)
 {
-  NLSR_LOG_ERROR("ERROR: Failed to register prefix in local hub's daemon");
+  NLSR_LOG_ERROR("ERROR: Failed to register prefix " << name << " in local hub's daemon");
   BOOST_THROW_EXCEPTION(Error("Error: Prefix registration failed"));
 }
 
@@ -234,30 +275,10 @@
 void
 Nlsr::initialize()
 {
-  NLSR_LOG_DEBUG("Initializing Nlsr");
-
   // Logging start
   m_adjacencyList.writeLog();
   NLSR_LOG_DEBUG(m_namePrefixList);
 
-  initializeKey();
-
-  NLSR_LOG_DEBUG("Default NLSR identity: " << m_signingInfo.getSignerName());
-
-  // Can be moved to HelloProtocol and Lsdb ctor if initializeKey is set
-  // earlier in the Nlsr constructor so as to set m_signingInfo
-  setInfoInterestFilter();
-  setLsaInterestFilter();
-
-  // add top-level prefixes: router and localhost prefix
-  addDispatcherTopPrefix(ndn::Name(m_confParam.getRouterPrefix()).append("nlsr"));
-  addDispatcherTopPrefix(LOCALHOST_PREFIX);
-
-  initializeFaces(std::bind(&Nlsr::processFaceDataset, this, _1),
-                  std::bind(&Nlsr::onFaceDatasetFetchTimeout, this, _1, _2, 0));
-
-  enableIncomingFaceIdIndication();
-
   m_lsdb.buildAndInstallOwnNameLsa();
 
   // Install coordinate LSAs if using HR or dry-run HR.
@@ -265,19 +286,10 @@
     m_lsdb.buildAndInstallOwnCoordinateLsa();
   }
 
-  registerKeyPrefix();
-  registerLocalhostPrefix();
-  registerRouterPrefix();
-
-  m_helloProtocol.scheduleInterest(m_confParam.getFirstHelloInterval());
-
   // Need to set direct neighbors' costs to 0 for hyperbolic routing
   if (m_confParam.getHyperbolicState() == HYPERBOLIC_STATE_ON) {
-
-    std::list<Adjacent>& neighbors = m_adjacencyList.getAdjList();
-
-    for (std::list<Adjacent>::iterator it = neighbors.begin(); it != neighbors.end(); ++it) {
-      it->setLinkCost(0);
+    for (auto&& neighbor : m_adjacencyList.getAdjList()) {
+      neighbor.setLinkCost(0);
     }
   }
 }
@@ -302,8 +314,9 @@
     nlsrInstanceIdentity = m_keyChain.createIdentity(nlsrInstanceName);
   }
   catch (const std::exception& e) {
+    NLSR_LOG_ERROR(e.what());
     NLSR_LOG_ERROR("Unable to create identity, NLSR will run without security!");
-    NLSR_LOG_DEBUG("Can be ignored if running in non-production environments.");
+    NLSR_LOG_ERROR("Can be ignored if running in non-production environments.");
     return;
   }
   auto nlsrInstanceKey = nlsrInstanceIdentity.getDefaultKey();
@@ -333,13 +346,8 @@
                                                .setSignatureInfo(signatureInfo));
   }
   catch (const std::exception& e) {
-    NLSR_LOG_WARN("ERROR: Router's " << e.what()
-                  << "NLSR is running without security."
-                  << " If security is enabled NLSR will not converge.");
-
-    std::cerr << "Router's " << e.what() << ". NLSR is running without security "
-              << "(Only for testing, should not be used in production.)"
-              << " If security is enabled NLSR will not converge." << std::endl;
+    NLSR_LOG_ERROR("Router's " << e.what() << "NLSR is running without security." <<
+                   " If security is enabled NLSR will not converge.");
   }
 
   m_signingInfo = ndn::security::SigningInfo(ndn::security::SigningInfo::SIGNER_TYPE_ID,
@@ -535,11 +543,11 @@
   NLSR_LOG_DEBUG("Processing face dataset");
 
   // Iterate over each neighbor listed in nlsr.conf
-  for (auto& adjacent : m_adjacencyList.getAdjList()) {
+  for (auto&& adjacent : m_adjacencyList.getAdjList()) {
 
-    const std::string faceUriString = adjacent.getFaceUri().toString();
+    const std::string& faceUriString = adjacent.getFaceUri().toString();
     // Check the list of FaceStatus objects we got for a match
-    for (const ndn::nfd::FaceStatus& faceStatus : faces) {
+    for (const auto& faceStatus : faces) {
       // Set the adjacency FaceID if we find a URI match and it was
       // previously unset. Change the boolean to true.
       if (adjacent.getFaceId() == 0 && faceUriString == faceStatus.getRemoteUri()) {
@@ -574,10 +582,6 @@
   m_fib.registerPrefix(adjName, faceUri, linkCost,
                        timeout, ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
 
-  m_fib.registerPrefix(m_confParam.getSyncPrefix(),
-                       faceUri, linkCost, timeout,
-                       ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
-
   m_fib.registerPrefix(m_confParam.getLsaPrefix(),
                        faceUri, linkCost, timeout,
                        ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
diff --git a/src/nlsr.hpp b/src/nlsr.hpp
index 2124ceb..bc82d01 100644
--- a/src/nlsr.hpp
+++ b/src/nlsr.hpp
@@ -272,21 +272,24 @@
   bool m_isDaemonProcess;
   ndn::security::ValidatorConfig& m_validator;
   std::vector<ndn::Name> m_strategySetOnRouters;
+  uint16_t m_numSyncPrefixRegistered = 0;
 
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   Fib m_fib;
   RoutingTable m_routingTable;
   NamePrefixTable m_namePrefixTable;
   Lsdb m_lsdb;
+  HelloProtocol m_helloProtocol;
 
 private:
   ndn::util::signal::ScopedConnection m_afterSegmentValidatedConnection;
   ndn::util::signal::ScopedConnection m_onNewLsaConnection;
+  ndn::util::signal::ScopedConnection m_onPrefixRegistrationSuccess;
+  ndn::util::signal::ScopedConnection m_onHelloDataValidated;
 
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   ndn::mgmt::Dispatcher m_dispatcher;
   DatasetInterestHandler m_datasetHandler;
-  HelloProtocol m_helloProtocol;
 
 private:
   /*! \brief Where NLSR stores certificates it claims to be
diff --git a/src/route/face-map.cpp b/src/route/face-map.cpp
deleted file mode 100644
index 52026d0..0000000
--- a/src/route/face-map.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2018,  The 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-map.hpp"
-#include "common.hpp"
-#include "logger.hpp"
-
-#include <iostream>
-#include <utility>
-
-namespace nlsr {
-
-INIT_LOGGER(route.FaceMap);
-
-void
-FaceMap::writeLog()
-{
-  NLSR_LOG_DEBUG("------- Face Map-----------");
-  for (const auto& it : m_table) {
-    NLSR_LOG_DEBUG("Face Map Entry (FaceUri: " << (it.second).getFaceUri()
-               << " Face Id: " << (it.second).getFaceId() << ")");
-  }
-}
-
-} // namespace nlsr
diff --git a/src/route/face-map.hpp b/src/route/face-map.hpp
deleted file mode 100644
index 9505229..0000000
--- a/src/route/face-map.hpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017,  The 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/>.
- *
- **/
-
-#ifndef NLSR_FACE_MAP_HPP
-#define NLSR_FACE_MAP_HPP
-
-#include "common.hpp"
-
-#include <map>
-
-namespace nlsr {
-
-class FaceMapEntry
-{
-
-public:
-  FaceMapEntry(const std::string& faceUri, uint32_t faceId)
-    : m_faceUri(faceUri)
-    , m_faceId(faceId)
-  {
-  }
-
-  void
-  setFaceUri(const std::string& faceUri)
-  {
-    m_faceUri = faceUri;
-  }
-
-  const std::string&
-  getFaceUri() const
-  {
-    return m_faceUri;
-  }
-
-  void
-  setFaceId(uint32_t faceId)
-  {
-    m_faceId = faceId;
-  }
-
-  uint32_t
-  getFaceId() const
-  {
-    return m_faceId;
-  }
-
-  bool
-  compare(const FaceMapEntry& fme)
-  {
-    return m_faceUri == fme.getFaceUri();
-  }
-
-private:
-  std::string m_faceUri;
-  uint32_t m_faceId;
-};
-
-class FaceMap
-{
-
-public:
-  FaceMap()
-  {
-  }
-
-  ~FaceMap()
-  {
-  }
-
-  inline void
-  update(const std::string& faceUri, uint32_t faceId)
-  {
-    FaceMapEntry fme(faceUri, faceId);
-    std::map<std::string, FaceMapEntry>::iterator it = m_table.find(faceUri);
-    if (it == m_table.end()) {
-      m_table.emplace(faceUri, fme);
-    }
-    else {
-      (it->second).setFaceId(fme.getFaceId());
-    }
-  }
-
-  inline uint32_t
-  getFaceId(const std::string& faceUri)
-  {
-    FaceMapEntry fme(faceUri, 0);
-    std::map<std::string, FaceMapEntry>::iterator it = m_table.find(faceUri);
-    if (it != m_table.end()) {
-      return (it->second).getFaceId();
-    }
-    return 0;
-  }
-
-  void
-  writeLog();
-
-private:
-  std::map<std::string, FaceMapEntry> m_table;
-};
-
-} // namespace nlsr
-
-#endif // NLSR_FACE_MAP_HPP
diff --git a/src/route/fib.cpp b/src/route/fib.cpp
index 9ee14c7..cd2b28c 100644
--- a/src/route/fib.cpp
+++ b/src/route/fib.cpp
@@ -202,9 +202,9 @@
                     uint64_t faceCost, const ndn::time::milliseconds& timeout,
                     uint64_t flags, uint8_t times)
 {
-  uint64_t faceId = m_adjacencyList.getFaceId(ndn::FaceUri(faceUri));
+  uint64_t faceId = m_adjacencyList.getFaceId(faceUri);
 
-  if (faceId != 0) {
+  if (faceId > 0) {
     ndn::nfd::ControlParameters faceParameters;
     faceParameters
      .setName(namePrefix)
@@ -216,13 +216,9 @@
 
     NLSR_LOG_DEBUG("Registering prefix: " << faceParameters.getName() << " faceUri: " << faceUri);
     m_controller.start<ndn::nfd::RibRegisterCommand>(faceParameters,
-                                                     std::bind(&Fib::onRegistrationSuccess, this, _1,
-                                                               "Successful in name registration",
-                                                               faceUri),
-                                                     std::bind(&Fib::onRegistrationFailure, this, _1,
-                                                               "Failed in name registration",
-                                                               faceParameters,
-                                                               faceUri, times));
+      std::bind(&Fib::onRegistrationSuccess, this, _1, faceUri),
+      std::bind(&Fib::onRegistrationFailure, this, _1,
+                faceParameters, faceUri, times));
   }
   else {
     NLSR_LOG_WARN("Error: No Face Id for face uri: " << faceUri);
@@ -230,31 +226,28 @@
 }
 
 void
-Fib::onRegistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
-                           const std::string& message, const ndn::FaceUri& faceUri)
+Fib::onRegistrationSuccess(const ndn::nfd::ControlParameters& param,
+                           const ndn::FaceUri& faceUri)
 {
-  NLSR_LOG_DEBUG(message << ": " << commandSuccessResult.getName() <<
-                 " Face Uri: " << faceUri << " faceId: " << commandSuccessResult.getFaceId());
+  NLSR_LOG_DEBUG("Successful in name registration: " << param.getName() <<
+                 " Face Uri: " << faceUri << " faceId: " << param.getFaceId());
 
   auto adjacent = m_adjacencyList.findAdjacent(faceUri);
   if (adjacent != m_adjacencyList.end()) {
-    adjacent->setFaceId(commandSuccessResult.getFaceId());
+    adjacent->setFaceId(param.getFaceId());
   }
-
-  // Update the fast-access FaceMap with the new Face ID, too
-  m_faceMap.update(faceUri.toString(), commandSuccessResult.getFaceId());
-  m_faceMap.writeLog();
+  onPrefixRegistrationSuccess(param.getName());
 }
 
 void
 Fib::onRegistrationFailure(const ndn::nfd::ControlResponse& response,
-                           const std::string& message,
                            const ndn::nfd::ControlParameters& parameters,
                            const ndn::FaceUri& faceUri,
                            uint8_t times)
 {
-  NLSR_LOG_DEBUG(message << ": " << response.getText() << " (code: " << response.getCode() << ")");
-  NLSR_LOG_DEBUG("Prefix: " << parameters.getName() << " failed for: " << times);
+  NLSR_LOG_DEBUG("Failed in name registration: " << response.getText() <<
+                 " (code: " << response.getCode() << ")");
+  NLSR_LOG_DEBUG("Prefix: " << parameters.getName() << " failed for: " << +times);
   if (times < 3) {
     NLSR_LOG_DEBUG("Trying to register again...");
     registerPrefix(parameters.getName(), faceUri,
@@ -270,7 +263,12 @@
 void
 Fib::unregisterPrefix(const ndn::Name& namePrefix, const std::string& faceUri)
 {
-  uint32_t faceId = m_faceMap.getFaceId(faceUri);
+  uint64_t faceId = 0;
+  auto adjacent = m_adjacencyList.findAdjacent(ndn::FaceUri(faceUri));
+  if (adjacent != m_adjacencyList.end()) {
+    faceId = adjacent->getFaceId();
+  }
+
   NLSR_LOG_DEBUG("Unregister prefix: " << namePrefix << " Face Uri: " << faceUri);
   if (faceId > 0) {
     ndn::nfd::ControlParameters controlParameters;
@@ -278,31 +276,20 @@
       .setName(namePrefix)
       .setFaceId(faceId)
       .setOrigin(ndn::nfd::ROUTE_ORIGIN_NLSR);
+
     m_controller.start<ndn::nfd::RibUnregisterCommand>(controlParameters,
-                                                       std::bind(&Fib::onUnregistrationSuccess, this, _1,
-                                                                 "Successful in unregistering name"),
-                                                       std::bind(&Fib::onUnregistrationFailure,
-                                                                 this, _1,
-                                                                 "Failed in unregistering name"));
+      [] (const ndn::nfd::ControlParameters& commandSuccessResult) {
+        NLSR_LOG_DEBUG("Unregister successful Prefix: " << commandSuccessResult.getName() <<
+                       " Face Id: " << commandSuccessResult.getFaceId());
+      },
+      [] (const ndn::nfd::ControlResponse& response) {
+        NLSR_LOG_DEBUG("Failed in unregistering name" << ": " << response.getText() <<
+                 " (code: " << response.getCode() << ")");
+      });
   }
 }
 
 void
-Fib::onUnregistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
-                             const std::string& message)
-{
-  NLSR_LOG_DEBUG("Unregister successful Prefix: " << commandSuccessResult.getName() <<
-                 " Face Id: " << commandSuccessResult.getFaceId());
-}
-
-void
-Fib::onUnregistrationFailure(const ndn::nfd::ControlResponse& response,
-                             const std::string& message)
-{
-  NLSR_LOG_DEBUG(message << ": " << response.getText() << " (code: " << response.getCode() << ")");
-}
-
-void
 Fib::setStrategy(const ndn::Name& name, const std::string& strategy, uint32_t count)
 {
   ndn::nfd::ControlParameters parameters;
diff --git a/src/route/fib.hpp b/src/route/fib.hpp
index f2d952a..25677e3 100644
--- a/src/route/fib.hpp
+++ b/src/route/fib.hpp
@@ -22,7 +22,6 @@
 #ifndef NLSR_ROUTE_FIB_HPP
 #define NLSR_ROUTE_FIB_HPP
 
-#include "face-map.hpp"
 #include "fib-entry.hpp"
 #include "test-access-control.hpp"
 
@@ -164,30 +163,17 @@
   /*! \brief Log registration success, and update the Face ID associated with a URI.
    */
   void
-  onRegistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
-                        const std::string& message, const ndn::FaceUri& faceUri);
+  onRegistrationSuccess(const ndn::nfd::ControlParameters& param,
+                        const ndn::FaceUri& faceUri);
 
   /*! \brief Retry a prefix (next-hop) registration up to three (3) times.
    */
   void
   onRegistrationFailure(const ndn::nfd::ControlResponse& response,
-                        const std::string& message,
                         const ndn::nfd::ControlParameters& parameters,
                         const ndn::FaceUri& faceUri,
                         uint8_t times);
 
-  /*! \brief Log a successful unregistration.
-   */
-  void
-  onUnregistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
-                          const std::string& message);
-
-  /*! \brief Log an unregistration failure. Does not retry.
-   */
-  void
-  onUnregistrationFailure(const ndn::nfd::ControlResponse& response,
-                               const std::string& message);
-
   /*! \brief Log a successful strategy setting.
    */
   void
@@ -240,6 +226,7 @@
 public:
   static const std::string MULTICAST_STRATEGY;
   static const std::string BEST_ROUTE_V2_STRATEGY;
+  ndn::util::Signal<Fib, const ndn::Name&> onPrefixRegistrationSuccess;
 
 private:
   ndn::Scheduler& m_scheduler;
@@ -247,7 +234,6 @@
   ndn::nfd::Controller m_controller;
 
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-  FaceMap m_faceMap;
   std::map<ndn::Name, FibEntry> m_table;
 
 private:
diff --git a/src/route/routing-table-calculator.cpp b/src/route/routing-table-calculator.cpp
index a079933..eb821e8 100644
--- a/src/route/routing-table-calculator.cpp
+++ b/src/route/routing-table-calculator.cpp
@@ -142,8 +142,13 @@
   for (size_t i = 0; i < m_nRouters; i++) {
     std::string line;
     for (size_t j = 0; j < m_nRouters; j++) {
-      line += boost::lexical_cast<std::string>(adjMatrix[i][j]);
-      line += " ";
+      if (adjMatrix[i][j] == LinkStateRoutingTableCalculator::NO_NEXT_HOP) {
+        line += "0 ";
+      }
+      else {
+        line += boost::lexical_cast<std::string>(adjMatrix[i][j]);
+        line += " ";
+      }
     }
     line = boost::lexical_cast<std::string>(i) + "|" + line;
     NLSR_LOG_DEBUG(line);
diff --git a/src/route/routing-table-calculator.hpp b/src/route/routing-table-calculator.hpp
index 0a40a1c..683eb58 100644
--- a/src/route/routing-table-calculator.hpp
+++ b/src/route/routing-table-calculator.hpp
@@ -200,6 +200,7 @@
   static const int EMPTY_PARENT;
   static const double INF_DISTANCE;
   static const int NO_MAPPING_NUM;
+public:
   static const int NO_NEXT_HOP;
 
 };
diff --git a/src/route/routing-table-entry.hpp b/src/route/routing-table-entry.hpp
index 6e01c45..fd98c32 100644
--- a/src/route/routing-table-entry.hpp
+++ b/src/route/routing-table-entry.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2019,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -66,9 +66,8 @@
   inline bool
   operator==(RoutingTableEntry& rhs)
   {
-    return ((*this).getDestination() == rhs.getDestination()
-            &&
-           (*this).getNexthopList() == rhs.getNexthopList());
+    return ((*this).getDestination() == rhs.getDestination() &&
+            (*this).getNexthopList() == rhs.getNexthopList());
   }
 
 protected:
diff --git a/src/route/routing-table-pool-entry.cpp b/src/route/routing-table-pool-entry.cpp
index 7e081ae..9102ed0 100644
--- a/src/route/routing-table-pool-entry.cpp
+++ b/src/route/routing-table-pool-entry.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2019,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -43,8 +43,7 @@
 bool
 operator==(const RoutingTablePoolEntry& lhs, const RoutingTablePoolEntry& rhs)
 {
-  return (lhs.getDestination() == rhs.getDestination()
-          &&
+  return (lhs.getDestination() == rhs.getDestination() &&
           lhs.getNexthopList() == rhs.getNexthopList());
 }
 
diff --git a/src/route/routing-table.cpp b/src/route/routing-table.cpp
index f0e4aac..60b05f9 100644
--- a/src/route/routing-table.cpp
+++ b/src/route/routing-table.cpp
@@ -27,7 +27,6 @@
 #include "name-prefix-table.hpp"
 #include "logger.hpp"
 
-#include <iostream>
 #include <list>
 #include <string>
 
@@ -42,7 +41,6 @@
   , m_fib(fib)
   , m_lsdb(lsdb)
   , m_namePrefixTable(namePrefixTable)
-  , m_NO_NEXT_HOP{-12345}
   , m_routingCalcInterval{confParam.getRoutingCalcInterval()}
   , m_isRoutingTableCalculating(false)
   , m_isRouteCalculationScheduled(false)
diff --git a/src/route/routing-table.hpp b/src/route/routing-table.hpp
index f43ad11..c149eb7 100644
--- a/src/route/routing-table.hpp
+++ b/src/route/routing-table.hpp
@@ -75,12 +75,6 @@
   void
   scheduleRoutingTableCalculation();
 
-  int
-  getNoNextHop()
-  {
-    return m_NO_NEXT_HOP;
-  }
-
   void
   setRoutingCalcInterval(uint32_t interval)
   {
@@ -141,8 +135,6 @@
   Lsdb& m_lsdb;
   NamePrefixTable& m_namePrefixTable;
 
-  const int m_NO_NEXT_HOP;
-
   std::list<RoutingTableEntry> m_dryTable;
 
   ndn::time::seconds m_routingCalcInterval;
diff --git a/src/sequencing-manager.cpp b/src/sequencing-manager.cpp
index 2aa8e98..bae9e68 100644
--- a/src/sequencing-manager.cpp
+++ b/src/sequencing-manager.cpp
@@ -138,8 +138,14 @@
 SequencingManager::writeLog() const
 {
   NLSR_LOG_DEBUG("----SequencingManager----");
-  NLSR_LOG_DEBUG("Adj LSA seq no: " << m_adjLsaSeq);
-  NLSR_LOG_DEBUG("Cor LSA Seq no: " << m_corLsaSeq);
+  if (m_hyperbolicState == HYPERBOLIC_STATE_OFF ||
+      m_hyperbolicState == HYPERBOLIC_STATE_DRY_RUN) {
+    NLSR_LOG_DEBUG("Adj LSA seq no: " << m_adjLsaSeq);
+  }
+  if (m_hyperbolicState == HYPERBOLIC_STATE_ON ||
+      m_hyperbolicState == HYPERBOLIC_STATE_DRY_RUN) {
+    NLSR_LOG_DEBUG("Cor LSA Seq no: " << m_corLsaSeq);
+  }
   NLSR_LOG_DEBUG("Name LSA Seq no: " << m_nameLsaSeq);
 }