comm: Stop SyncLogicHandler from fetching own LSAs

refs: #2005

Change-Id: I717a5258673dd5308fdf6561dbdb626ae4c74e9f
diff --git a/src/communication/sync-logic-handler.cpp b/src/communication/sync-logic-handler.cpp
index 2570d2d..c0638c7 100644
--- a/src/communication/sync-logic-handler.cpp
+++ b/src/communication/sync-logic-handler.cpp
@@ -20,11 +20,18 @@
  * \author A K M Mahmudul Hoque <ahoque1@memphis.edu>
  *
  **/
-#include "nlsr.hpp"
 #include "sync-logic-handler.hpp"
-#include "utility/name-helper.hpp"
-#include "lsa.hpp"
+
+#include "conf-parameter.hpp"
 #include "logger.hpp"
+#include "lsa.hpp"
+#include "lsdb.hpp"
+#include "sequencing-manager.hpp"
+#include "utility/name-helper.hpp"
+
+#include <boost/serialization/shared_ptr.hpp>
+
+using namespace boost::serialization;
 
 namespace nlsr {
 
@@ -33,88 +40,161 @@
 using namespace ndn;
 using namespace std;
 
+class SyncUpdate
+{
+public:
+  class Error : public std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
+  };
+
+public:
+  SyncUpdate(const ndn::Name& name, uint64_t seqNo)
+    : m_name(name)
+    , m_seqManager(seqNo)
+  {
+  }
+
+  const ndn::Name&
+  getName() const
+  {
+    return m_name;
+  }
+
+  const ndn::Name
+  getOriginRouter() const
+  {
+    int32_t nlsrPosition = util::getNameComponentPosition(m_name, NLSR_COMPONENT);
+    int32_t lsaPosition = util::getNameComponentPosition(m_name, LSA_COMPONENT);
+
+    if (nlsrPosition < 0 || lsaPosition < 0) {
+      throw Error("Cannot parse update name because expected components are missing");
+    }
+
+    ndn::Name networkName = m_name.getSubName(0, nlsrPosition);
+    ndn::Name routerName = m_name.getSubName(lsaPosition + 1);
+
+    ndn::Name originRouter = networkName;
+    originRouter.append(routerName);
+
+    return originRouter;
+  }
+
+  uint64_t
+  getNameLsaSeqNo() const
+  {
+    return m_seqManager.getNameLsaSeq();
+  }
+
+  uint64_t
+  getAdjLsaSeqNo() const
+  {
+    return m_seqManager.getAdjLsaSeq();
+  }
+
+  uint64_t
+  getCorLsaSeqNo() const
+  {
+    return m_seqManager.getCorLsaSeq();
+  }
+
+  const SequencingManager&
+  getSequencingManager() const
+  {
+    return m_seqManager;
+  }
+
+private:
+  const ndn::Name m_name;
+  SequencingManager m_seqManager;
+
+  static const std::string NLSR_COMPONENT;
+  static const std::string LSA_COMPONENT;
+};
+
+const std::string SyncUpdate::NLSR_COMPONENT = "NLSR";
+const std::string SyncUpdate::LSA_COMPONENT = "LSA";
+
+const std::string SyncLogicHandler::NAME_COMPONENT = "name";
+const std::string SyncLogicHandler::ADJACENCY_COMPONENT = "adjacency";
+const std::string SyncLogicHandler::COORDINATE_COMPONENT = "coordinate";
+
 void
-SyncLogicHandler::createSyncSocket(Nlsr& pnlsr)
+SyncLogicHandler::createSyncSocket()
 {
   _LOG_DEBUG("Creating Sync socket. Sync Prefix: " << m_syncPrefix);
-  m_syncSocket = ndn::make_shared<Sync::SyncSocket>(m_syncPrefix, m_validator,
-                                                    m_syncFace,
-                                                    ndn::bind(&SyncLogicHandler::nsyncUpdateCallBack,
-                                                              this, _1, _2, ndn::ref(pnlsr)),
-                                                    ndn::bind(&SyncLogicHandler::nsyncRemoveCallBack,
-                                                              this, _1, ndn::ref(pnlsr)));
+
+  // The face's lifetime is managed in main.cpp; SyncSocket should not manage the memory
+  // of the object
+  ndn::shared_ptr<ndn::Face> facePtr(&m_syncFace, null_deleter());
+
+  m_syncSocket = ndn::make_shared<Sync::SyncSocket>(m_syncPrefix, m_validator, facePtr,
+                                                    ndn::bind(&SyncLogicHandler::onNsyncUpdate,
+                                                              this, _1, _2),
+                                                    ndn::bind(&SyncLogicHandler::onNsyncRemoval,
+                                                              this, _1));
 }
 
 void
-SyncLogicHandler::nsyncUpdateCallBack(const vector<Sync::MissingDataInfo>& v,
-                                      Sync::SyncSocket* socket, Nlsr& pnlsr)
+SyncLogicHandler::onNsyncUpdate(const vector<Sync::MissingDataInfo>& v, Sync::SyncSocket* socket)
 {
-  _LOG_DEBUG("nsyncUpdateCallBack called ....");
-  int32_t n = v.size();
-  for (int32_t i = 0; i < n; i++){
-    _LOG_DEBUG("Update Name: " << v[i].prefix << " Seq: " << v[i].high.getSeq());
-    processUpdateFromSync(v[i].prefix, v[i].high.getSeq(), pnlsr);
+  _LOG_DEBUG("Received Nsync update event");
+
+  for (size_t i = 0; i < v.size(); i++){
+    _LOG_DEBUG("Update Name: " << v[i].prefix << " Seq no: " << v[i].high.getSeq());
+
+    SyncUpdate update(v[i].prefix, v[i].high.getSeq());
+
+    processUpdateFromSync(update);
   }
 }
 
 void
-SyncLogicHandler::nsyncRemoveCallBack(const string& prefix, Nlsr& pnlsr)
+SyncLogicHandler::onNsyncRemoval(const string& prefix)
 {
-  _LOG_DEBUG("nsyncRemoveCallBack called ....");
+  _LOG_DEBUG("Received Nsync removal event");
 }
 
 void
-SyncLogicHandler::removeRouterFromSyncing(const ndn::Name& routerPrefix)
+SyncLogicHandler::processUpdateFromSync(const SyncUpdate& update)
 {
-}
+  ndn::Name originRouter;
 
-void
-SyncLogicHandler::processUpdateFromSync(const ndn::Name& updateName,
-                                        uint64_t seqNo,  Nlsr& pnlsr)
-{
-  string chkString("LSA");
-  int32_t lasPosition = util::getNameComponentPosition(updateName, chkString);
-  if (lasPosition >= 0) {
-    ndn::Name routerName = updateName.getSubName(lasPosition + 1);
-    processRoutingUpdateFromSync(routerName, seqNo, pnlsr);
+  try {
+    originRouter = update.getOriginRouter();
+  }
+  catch (std::exception& e) {
+    _LOG_WARN("Received malformed sync update");
     return;
   }
-}
 
-void
-SyncLogicHandler::processRoutingUpdateFromSync(const ndn::Name& routerName,
-                                               uint64_t seqNo,  Nlsr& pnlsr)
-{
-  ndn::Name rName = routerName;
-  if (routerName != pnlsr.getConfParameter().getRouterPrefix()) {
-    SequencingManager sm(seqNo);
-    sm.writeLog();
-    _LOG_DEBUG(routerName);
+  // A router should not try to fetch its own LSA
+  if (originRouter != m_confParam.getRouterPrefix()) {
+
+    update.getSequencingManager().writeLog();
+
     try {
-      if (pnlsr.getLsdb().isNameLsaNew(rName.append("name"), sm.getNameLsaSeq())) {
-        _LOG_DEBUG("Updated Name LSA. Need to fetch it");
-        ndn::Name interestName(pnlsr.getConfParameter().getLsaPrefix());
-        interestName.append(routerName);
-        interestName.append("name");
-        interestName.appendNumber(sm.getNameLsaSeq());
-        pnlsr.getLsdb().expressInterest(interestName, 0);
+      if (isLsaNew(originRouter, NAME_COMPONENT, update.getNameLsaSeqNo())) {
+        _LOG_DEBUG("Received sync update with higher Name LSA sequence number than entry in LSDB");
+
+        expressInterestForLsa(update, NAME_COMPONENT, update.getNameLsaSeqNo());
       }
-      if (pnlsr.getLsdb().isAdjLsaNew(rName.append("adjacency"), sm.getAdjLsaSeq())) {
-        _LOG_DEBUG("Updated Adj LSA. Need to fetch it");
-        ndn::Name interestName(pnlsr.getConfParameter().getLsaPrefix());
-        interestName.append(routerName);
-        interestName.append("adjacency");
-        interestName.appendNumber(sm.getAdjLsaSeq());
-        pnlsr.getLsdb().expressInterest(interestName, 0);
+
+      if (isLsaNew(originRouter, ADJACENCY_COMPONENT, update.getAdjLsaSeqNo())) {
+        _LOG_DEBUG("Received sync update with higher Adj LSA sequence number than entry in LSDB");
+
+        expressInterestForLsa(update, ADJACENCY_COMPONENT, update.getAdjLsaSeqNo());
       }
-      if (pnlsr.getLsdb().isCoordinateLsaNew(rName.append("coordinate"),
-                                             sm.getCorLsaSeq())) {
-        _LOG_DEBUG("Updated Cor LSA. Need to fetch it");
-        ndn::Name interestName(pnlsr.getConfParameter().getLsaPrefix());
-        interestName.append(routerName);
-        interestName.append("coordinate");
-        interestName.appendNumber(sm.getCorLsaSeq());
-        pnlsr.getLsdb().expressInterest(interestName, 0);
+
+      if (isLsaNew(originRouter, COORDINATE_COMPONENT, update.getCorLsaSeqNo())) {
+        _LOG_DEBUG("Received sync update with higher Cor LSA sequence number than entry in LSDB");
+
+        expressInterestForLsa(update, COORDINATE_COMPONENT, update.getCorLsaSeqNo());
       }
     }
     catch (std::exception& e) {
@@ -124,24 +204,56 @@
   }
 }
 
-void
-SyncLogicHandler::publishRoutingUpdate(SequencingManager& sm,
-                                       const ndn::Name& updatePrefix)
+bool
+SyncLogicHandler::isLsaNew(const ndn::Name& originRouter, const std::string& lsaType,
+                           uint64_t seqNo)
 {
-  sm.writeSeqNoToFile();
-  publishSyncUpdate(updatePrefix, sm.getCombinedSeqNo());
+  ndn::Name lsaKey = originRouter;
+  lsaKey.append(lsaType);
+
+  if (lsaType == NAME_COMPONENT)
+  {
+    return m_lsdb.isNameLsaNew(lsaKey, seqNo);
+  }
+  else if (lsaType == ADJACENCY_COMPONENT)
+  {
+    return m_lsdb.isAdjLsaNew(lsaKey, seqNo);
+  }
+  else if (lsaType == COORDINATE_COMPONENT)
+  {
+    return m_lsdb.isCoordinateLsaNew(lsaKey, seqNo);
+  }
+
+  return false;
 }
 
 void
-SyncLogicHandler::publishSyncUpdate(const ndn::Name& updatePrefix,
-                                    uint64_t seqNo)
+SyncLogicHandler::expressInterestForLsa(const SyncUpdate& update, std::string lsaType,
+                                        uint64_t seqNo)
 {
-  _LOG_DEBUG("Publishing Sync Update. Prefix: " << updatePrefix << "Seq no: " << seqNo);
+  ndn::Name interest(update.getName());
+  interest.append(lsaType);
+  interest.appendNumber(seqNo);
+
+  m_lsdb.expressInterest(interest, 0);
+}
+
+void
+SyncLogicHandler::publishRoutingUpdate(SequencingManager& manager, const ndn::Name& updatePrefix)
+{
+  manager.writeSeqNoToFile();
+  publishSyncUpdate(updatePrefix, manager.getCombinedSeqNo());
+}
+
+void
+SyncLogicHandler::publishSyncUpdate(const ndn::Name& updatePrefix, uint64_t seqNo)
+{
+  _LOG_DEBUG("Publishing Sync Update. Prefix: " << updatePrefix << " Seq No: " << seqNo);
+
   ndn::Name updateName(updatePrefix);
   string data("NoData");
-  m_syncSocket->publishData(updateName.toUri(), 0, data.c_str(), data.size(),
-                            1000,
-                            seqNo);
+
+  m_syncSocket->publishData(updateName.toUri(), 0, data.c_str(), data.size(), 1000, seqNo);
 }
 
 }//namespace nlsr
diff --git a/src/communication/sync-logic-handler.hpp b/src/communication/sync-logic-handler.hpp
index d790a04..70fd07e 100644
--- a/src/communication/sync-logic-handler.hpp
+++ b/src/communication/sync-logic-handler.hpp
@@ -17,55 +17,49 @@
  * 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 NLSR_SYNC_LOGIC_HANDLER_HPP
 #define NLSR_SYNC_LOGIC_HANDLER_HPP
 
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/security/validator-null.hpp>
+#include <nsync/sync-socket.h>
+
 #include <iostream>
+#include <unistd.h>
 #include <boost/cstdint.hpp>
 
-#include <ndn-cxx/face.hpp>
-#include <nsync/sync-socket.h>
-#include <ndn-cxx/security/validator-null.hpp>
-
-#include "sequencing-manager.hpp"
-
-extern "C" {
-#include <unistd.h>
-}
-
 class InterestManager;
-class ConfParameter;
 
 namespace nlsr {
 
+class ConfParameter;
+class Lsdb;
+class SequencingManager;
+class SyncUpdate;
+
 class SyncLogicHandler
 {
 public:
-  SyncLogicHandler(boost::asio::io_service& ioService)
+  SyncLogicHandler(ndn::Face& face, Lsdb& lsdb, ConfParameter& conf)
     : m_validator(new ndn::ValidatorNull())
-    , m_syncFace(new ndn::Face(ioService))
+    , m_syncFace(face)
+    , m_lsdb(lsdb)
+    , m_confParam(conf)
   {
   }
 
+  void
+  createSyncSocket();
 
   void
-  createSyncSocket(Nlsr& pnlsr);
+  onNsyncUpdate(const std::vector<Sync::MissingDataInfo>& v, Sync::SyncSocket* socket);
 
   void
-  nsyncUpdateCallBack(const std::vector<Sync::MissingDataInfo>& v,
-                      Sync::SyncSocket* socket, Nlsr& pnlsr);
+  onNsyncRemoval(const std::string& prefix);
 
   void
-  nsyncRemoveCallBack(const std::string& prefix, Nlsr& pnlsr);
-
-  void
-  removeRouterFromSyncing(const ndn::Name& routerPrefix);
-
-  void
-  publishRoutingUpdate(SequencingManager& sm, const ndn::Name& updatePrefix);
+  publishRoutingUpdate(SequencingManager& manager, const ndn::Name& updatePrefix);
 
   void
   setSyncPrefix(const std::string& sp)
@@ -76,21 +70,32 @@
 
 private:
   void
-  processUpdateFromSync(const ndn::Name& updateName, uint64_t seqNo,
-                        Nlsr& pnlsr);
+  processUpdateFromSync(const SyncUpdate& updateName);
+
+  bool
+  isLsaNew(const ndn::Name& originRouter, const std::string& lsaType, uint64_t seqNo);
 
   void
-  processRoutingUpdateFromSync(const ndn::Name& routerName, uint64_t seqNo,
-                               Nlsr& pnlsr);
+  expressInterestForLsa(const SyncUpdate& updateName, std::string lsaType, uint64_t seqNo);
 
   void
   publishSyncUpdate(const ndn::Name& updatePrefix, uint64_t seqNo);
 
 private:
   ndn::shared_ptr<ndn::ValidatorNull> m_validator;
-  ndn::shared_ptr<ndn::Face> m_syncFace;
+  ndn::Face& m_syncFace;
   ndn::shared_ptr<Sync::SyncSocket> m_syncSocket;
   ndn::Name m_syncPrefix;
+
+  Lsdb& m_lsdb;
+  ConfParameter& m_confParam;
+
+  static const std::string NLSR_COMPONENT;
+  static const std::string LSA_COMPONENT;
+  static const std::string NAME_COMPONENT;
+  static const std::string ADJACENCY_COMPONENT;
+  static const std::string COORDINATE_COMPONENT;
+
 };
 
 } //namespace nlsr
diff --git a/src/lsdb.cpp b/src/lsdb.cpp
index 0490276..427cc0b 100644
--- a/src/lsdb.cpp
+++ b/src/lsdb.cpp
@@ -564,16 +564,24 @@
                 getLsaExpirationTimePoint(),
                 m_nlsr.getAdjacencyList().getNumOfActiveNeighbor(),
                 m_nlsr.getAdjacencyList());
+
   m_nlsr.getSequencingManager().increaseAdjLsaSeq();
-  // publish routing update
-  //ndn::Name lsaPrefix = m_nlsr.getConfParameter().getLsaPrefix();
-  //lsaPrefix.append(m_nlsr.getConfParameter().getRouterPrefix());
+
+  bool isInstalled = installAdjLsa(adjLsa);
+
+  // Delay Sync prefix registration until the first Adjacency LSA is built
+  if (isInstalled && !m_hasSyncPrefixBeenRegistered) {
+    m_nlsr.getSyncLogicHandler().createSyncSocket();
+    m_hasSyncPrefixBeenRegistered = true;
+  }
+
   ndn::Name lsaPrefix = m_nlsr.getConfParameter().getLsaPrefix();
   lsaPrefix.append(m_nlsr.getConfParameter().getSiteName());
   lsaPrefix.append(m_nlsr.getConfParameter().getRouterName());
-  m_nlsr.getSyncLogicHandler().publishRoutingUpdate(m_nlsr.getSequencingManager(),
-                                                    lsaPrefix);
-  return installAdjLsa(adjLsa);
+
+  m_nlsr.getSyncLogicHandler().publishRoutingUpdate(m_nlsr.getSequencingManager(), lsaPrefix);
+
+  return isInstalled;
 }
 
 bool
diff --git a/src/lsdb.hpp b/src/lsdb.hpp
index 8f1e779..c6ab5e8 100644
--- a/src/lsdb.hpp
+++ b/src/lsdb.hpp
@@ -42,11 +42,11 @@
   Lsdb(Nlsr& nlsr, ndn::Scheduler& scheduler)
     : m_nlsr(nlsr)
     , m_scheduler(scheduler)
+    , m_hasSyncPrefixBeenRegistered(false)
     , m_lsaRefreshTime(0)
   {
   }
 
-
   bool
   doesLsaExist(const ndn::Name& key, const std::string& lsType);
   // function related to Name LSDB
@@ -239,6 +239,8 @@
   std::list<AdjLsa> m_adjLsdb;
   std::list<CoordinateLsa> m_corLsdb;
 
+  bool m_hasSyncPrefixBeenRegistered;
+
   seconds m_lsaRefreshTime;
   std::string m_thisRouterPrefix;
 
diff --git a/src/main.cpp b/src/main.cpp
index a06fcee..319e622 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -38,8 +38,9 @@
 {
   boost::asio::io_service ioService;
   ndn::Scheduler scheduler(ioService);
+  ndn::Face face(ioService);
 
-  Nlsr nlsr(ioService, scheduler);
+  Nlsr nlsr(ioService, scheduler, face);
 
   std::string programName(argv[0]);
   nlsr.setConfFileName("nlsr.conf");
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index 057fb12..e4e37fb 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -140,7 +140,7 @@
   setLsaInterestFilter();
   m_nlsrLsdb.buildAndInstallOwnNameLsa();
   m_nlsrLsdb.buildAndInstallOwnCoordinateLsa();
-  m_syncLogicHandler.createSyncSocket(boost::ref(*this));
+
   registerKeyPrefix();
   m_helloProtocol.scheduleInterest(10);
 }
diff --git a/src/nlsr.hpp b/src/nlsr.hpp
index e013930..240fffb 100644
--- a/src/nlsr.hpp
+++ b/src/nlsr.hpp
@@ -64,8 +64,8 @@
   };
 
 public:
-  Nlsr(boost::asio::io_service& ioService, ndn::Scheduler& scheduler)
-    : m_nlsrFace(ioService)
+  Nlsr(boost::asio::io_service& ioService, ndn::Scheduler& scheduler, ndn::Face& face)
+    : m_nlsrFace(face)
     , m_scheduler(scheduler)
     , m_confParam()
     , m_adjacencyList()
@@ -81,7 +81,7 @@
     , m_routingTable(scheduler)
     , m_fib(*this, m_nlsrFace, scheduler)
     , m_namePrefixTable(*this)
-    , m_syncLogicHandler(ioService)
+    , m_syncLogicHandler(m_nlsrFace, m_nlsrLsdb, m_confParam)
     , m_helloProtocol(*this, scheduler)
     , m_certificateCache(new ndn::CertificateCacheTtl(ioService))
     , m_validator(m_nlsrFace, DEFAULT_BROADCAST_PREFIX, m_certificateCache)
@@ -335,7 +335,7 @@
 private:
   typedef std::map<ndn::Name, ndn::shared_ptr<ndn::IdentityCertificate> > CertMap;
 
-  ndn::Face m_nlsrFace;
+  ndn::Face& m_nlsrFace;
   ndn::Scheduler& m_scheduler;
   ConfParameter m_confParam;
   AdjacencyList m_adjacencyList;
diff --git a/src/sequencing-manager.cpp b/src/sequencing-manager.cpp
index b5bd89c..01a22fa 100644
--- a/src/sequencing-manager.cpp
+++ b/src/sequencing-manager.cpp
@@ -102,7 +102,7 @@
 }
 
 void
-SequencingManager::writeLog()
+SequencingManager::writeLog() const
 {
   _LOG_DEBUG("----SequencingManager----");
   _LOG_DEBUG("Adj LSA seq no: " << m_adjLsaSeq);
diff --git a/src/sequencing-manager.hpp b/src/sequencing-manager.hpp
index 50795b2..c91cec4 100644
--- a/src/sequencing-manager.hpp
+++ b/src/sequencing-manager.hpp
@@ -134,7 +134,7 @@
   getUserHomeDirectory();
 
   void
-  writeLog();
+  writeLog() const;
 
 private:
   void
diff --git a/tests/dummy-face.hpp b/tests/dummy-face.hpp
new file mode 100644
index 0000000..a3a9402
--- /dev/null
+++ b/tests/dummy-face.hpp
@@ -0,0 +1,116 @@
+/* -*- 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/>.
+ *
+ **/
+
+#ifndef NLSR_TEST_DUMMY_FACE_HPP
+#define NLSR_TEST_DUMMY_FACE_HPP
+
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/transport/transport.hpp>
+
+namespace ndn {
+
+class DummyTransport : public Transport
+{
+public:
+  void
+  receive(const Block& block)
+  {
+    m_receiveCallback(block);
+  }
+
+  virtual void
+  close()
+  {
+  }
+
+  virtual void
+  pause()
+  {
+  }
+
+  virtual void
+  resume()
+  {
+  }
+
+  virtual void
+  send(const Block& wire)
+  {
+    if (wire.type() == Tlv::Interest) {
+      m_sentInterests->push_back(Interest(wire));
+    }
+    else if (wire.type() == Tlv::Data) {
+      m_sentDatas->push_back(Data(wire));
+    }
+  }
+
+  virtual void
+  send(const Block& header, const Block& payload)
+  {
+    this->send(payload);
+  }
+
+public:
+  std::vector<Interest>* m_sentInterests;
+  std::vector<Data>*     m_sentDatas;
+};
+
+
+/** \brief a Face for unit testing
+ */
+class DummyFace : public Face
+{
+public:
+  explicit
+  DummyFace(shared_ptr<DummyTransport> transport)
+    : Face(transport)
+    , m_transport(transport)
+  {
+    m_transport->m_sentInterests = &m_sentInterests;
+    m_transport->m_sentDatas     = &m_sentDatas;
+  }
+
+  /** \brief cause the Face to receive a packet
+   */
+  template<typename Packet>
+  void
+  receive(const Packet& packet)
+  {
+    m_transport->receive(packet.wireEncode());
+  }
+
+public:
+  std::vector<Interest> m_sentInterests;
+  std::vector<Data>     m_sentDatas;
+
+private:
+  shared_ptr<DummyTransport> m_transport;
+};
+
+inline shared_ptr<DummyFace>
+makeDummyFace()
+{
+  return make_shared<DummyFace>(make_shared<DummyTransport>());
+}
+
+} // namespace ndn
+
+#endif // NLSR_TEST_DUMMY_FACE_HPP
\ No newline at end of file
diff --git a/tests/test-common.hpp b/tests/test-common.hpp
index cbb83d9..dc60c90 100644
--- a/tests/test-common.hpp
+++ b/tests/test-common.hpp
@@ -24,6 +24,7 @@
 #define NLSR_TEST_COMMON_HPP
 
 #include <boost/asio.hpp>
+#include <boost/test/unit_test.hpp>
 #include <ndn-cxx/util/scheduler.hpp>
 
 namespace nlsr {
diff --git a/tests/test-conf-file-processor.cpp b/tests/test-conf-file-processor.cpp
index 44987de..d05e39c 100644
--- a/tests/test-conf-file-processor.cpp
+++ b/tests/test-conf-file-processor.cpp
@@ -22,6 +22,7 @@
  **/
 
 #include "test-common.hpp"
+#include "dummy-face.hpp"
 
 #include <fstream>
 #include "conf-file-processor.hpp"
@@ -31,11 +32,16 @@
 namespace nlsr {
 namespace test {
 
+using ndn::DummyFace;
+using ndn::shared_ptr;
+
 BOOST_FIXTURE_TEST_SUITE(TestConfFileProcessor, BaseFixture)
 
 BOOST_AUTO_TEST_CASE(ConfFileProcessorSample)
 {
-  Nlsr nlsr1(g_ioService, g_scheduler);
+  shared_ptr<DummyFace> face = ndn::makeDummyFace();
+
+  Nlsr nlsr1(g_ioService, g_scheduler, ndn::ref(*face));
 
   const std::string CONFIG =
      "general\n"
diff --git a/tests/test-lsdb.cpp b/tests/test-lsdb.cpp
index 84493d2..1caefcf 100644
--- a/tests/test-lsdb.cpp
+++ b/tests/test-lsdb.cpp
@@ -22,6 +22,7 @@
  **/
 
 #include "test-common.hpp"
+#include "dummy-face.hpp"
 
 #include "lsdb.hpp"
 #include "nlsr.hpp"
@@ -31,16 +32,49 @@
 #include <ndn-cxx/util/time.hpp>
 
 namespace nlsr {
-
 namespace test {
 
-BOOST_FIXTURE_TEST_SUITE(TestLsdb, BaseFixture)
+using ndn::DummyFace;
+using ndn::shared_ptr;
+
+class LsdbFixture : public BaseFixture
+{
+public:
+  LsdbFixture()
+    : face(ndn::makeDummyFace())
+    , nlsr(g_ioService, g_scheduler, ndn::ref(*face))
+    , sync(*face, nlsr.getLsdb(), nlsr.getConfParameter())
+    , REGISTER_COMMAND_PREFIX("/localhost/nfd/rib")
+    , REGISTER_VERB("register")
+  {
+  }
+
+  void extractParameters(ndn::Interest& interest, ndn::Name::Component& verb,
+                         ndn::nfd::ControlParameters& extractedParameters)
+  {
+    const ndn::Name& name = interest.getName();
+    verb = name[REGISTER_COMMAND_PREFIX.size()];
+    const ndn::Name::Component& parameterComponent = name[REGISTER_COMMAND_PREFIX.size() + 1];
+
+    ndn::Block rawParameters = parameterComponent.blockFromValue();
+    extractedParameters.wireDecode(rawParameters);
+  }
+
+public:
+  shared_ptr<DummyFace> face;
+  Nlsr nlsr;
+  SyncLogicHandler sync;
+
+  ndn::Name REGISTER_COMMAND_PREFIX;
+  ndn::Name::Component REGISTER_VERB;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestLsdb, LsdbFixture)
 
 BOOST_AUTO_TEST_CASE(LsdbRemoveAndExists)
 {
   INIT_LOGGERS("/tmp", "DEBUG");
 
-  Nlsr nlsr1(g_ioService, g_scheduler);
   ndn::time::system_clock::TimePoint testTimePoint =  ndn::time::system_clock::now();
   NamePrefixList npl1;
 
@@ -51,12 +85,12 @@
   npl1.insert(s1);
   npl1.insert(s2);
 
-//For NameLsa lsType is name.
-//12 is seqNo, randomly generated.
-//1800 is the default life time.
+  //For NameLsa lsType is name.
+  //12 is seqNo, randomly generated.
+  //1800 is the default life time.
   NameLsa nlsa1(ndn::Name("/router1/1"), std::string("name"), 12, testTimePoint, npl1);
 
-  Lsdb lsdb1(nlsr1, g_scheduler);
+  Lsdb lsdb1(nlsr, g_scheduler);
 
   lsdb1.installNameLsa(nlsa1);
   lsdb1.writeNameLsdbLog();
@@ -68,6 +102,42 @@
   BOOST_CHECK_EQUAL(lsdb1.doesLsaExist(ndn::Name("/router1/1"), std::string("name")), false);
 }
 
+BOOST_AUTO_TEST_CASE(RegisterSyncPrefixOnFirstAdjLsaBuild)
+{
+  ConfParameter& conf = nlsr.getConfParameter();
+  conf.setNetwork("/ndn");
+  conf.setSiteName("/site");
+  conf.setRouterName("/%C1.router/this-router");
+
+  nlsr.initialize();
+
+  Lsdb& lsdb = nlsr.getLsdb();
+  face->processEvents(ndn::time::milliseconds(1));
+  face->m_sentInterests.clear();
+
+  // Should register Sync prefix
+  lsdb.buildAndInstallOwnAdjLsa();
+  face->processEvents(ndn::time::milliseconds(1));
+
+  std::vector<ndn::Interest>& interests = face->m_sentInterests;
+
+  BOOST_REQUIRE(interests.size() > 0);
+
+  ndn::nfd::ControlParameters extractedParameters;
+  ndn::Name::Component verb;
+  extractParameters(interests[0], verb, extractedParameters);
+
+  BOOST_CHECK_EQUAL(verb, REGISTER_VERB);
+  BOOST_CHECK_EQUAL(extractedParameters.getName(), conf.getChronosyncPrefix());
+
+  // Should not register Sync prefix
+  face->m_sentInterests.clear();
+  lsdb.buildAndInstallOwnAdjLsa();
+  face->processEvents(ndn::time::milliseconds(1));
+
+  BOOST_CHECK_EQUAL(interests.size(), 0);
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 
 } //namespace test
diff --git a/tests/test-sync-logic-handler.cpp b/tests/test-sync-logic-handler.cpp
new file mode 100644
index 0000000..00839b1
--- /dev/null
+++ b/tests/test-sync-logic-handler.cpp
@@ -0,0 +1,172 @@
+/* -*- 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/>.
+ *
+ **/
+
+#include "test-common.hpp"
+#include "dummy-face.hpp"
+
+#include "nlsr.hpp"
+#include "communication/sync-logic-handler.hpp"
+
+namespace nlsr {
+namespace test {
+
+using ndn::DummyFace;
+using ndn::shared_ptr;
+
+class SyncLogicFixture : public BaseFixture
+{
+public:
+  SyncLogicFixture()
+    : face(ndn::makeDummyFace())
+    , nlsr(g_ioService, g_scheduler, ndn::ref(*face))
+    , sync(*face, nlsr.getLsdb(), nlsr.getConfParameter())
+    , CONFIG_NETWORK("/ndn")
+    , CONFIG_SITE("/site")
+    , CONFIG_ROUTER_NAME("/%C1.Router/this-router")
+  {
+    nlsr.getConfParameter().setNetwork(CONFIG_NETWORK);
+    nlsr.getConfParameter().setSiteName(CONFIG_SITE);
+    nlsr.getConfParameter().setRouterName(CONFIG_ROUTER_NAME);
+    nlsr.getConfParameter().buildRouterPrefix();
+  }
+
+  void
+  receiveUpdate(std::string prefix, uint64_t seqNo)
+  {
+    Sync::MissingDataInfo info = {prefix, 0, seqNo};
+
+    std::vector<Sync::MissingDataInfo> updates;
+    updates.push_back(info);
+
+    face->processEvents(ndn::time::milliseconds(1));
+    face->m_sentInterests.clear();
+
+    sync.onNsyncUpdate(updates, NULL);
+
+    face->processEvents(ndn::time::milliseconds(1));
+  }
+
+public:
+  shared_ptr<DummyFace> face;
+  Nlsr nlsr;
+  SyncLogicHandler sync;
+
+  const std::string CONFIG_NETWORK;
+  const std::string CONFIG_SITE;
+  const std::string CONFIG_ROUTER_NAME;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestSyncLogicHandler, SyncLogicFixture)
+
+BOOST_AUTO_TEST_CASE(UpdateForOther)
+{
+  std::string updateName = nlsr.getConfParameter().getLsaPrefix().toUri() +
+                           CONFIG_SITE + "/%C1.Router/other-router/";
+
+  receiveUpdate(updateName, 1);
+
+  std::vector<ndn::Interest>& interests = face->m_sentInterests;
+  BOOST_REQUIRE_EQUAL(interests.size(), 3);
+
+  std::vector<ndn::Interest>::iterator it = interests.begin();
+  BOOST_CHECK_EQUAL(it->getName().getPrefix(-1), updateName + "name/");
+
+  ++it;
+  BOOST_CHECK_EQUAL(it->getName().getPrefix(-1), updateName + "adjacency/");
+
+  ++it;
+  BOOST_CHECK_EQUAL(it->getName().getPrefix(-1), updateName + "coordinate/");
+}
+
+BOOST_AUTO_TEST_CASE(NoUpdateForSelf)
+{
+  std::string updateName = nlsr.getConfParameter().getLsaPrefix().toUri() +
+                           CONFIG_SITE + CONFIG_ROUTER_NAME;
+
+  receiveUpdate(updateName, 1);
+
+  std::vector<ndn::Interest>& interests = face->m_sentInterests;
+  BOOST_CHECK_EQUAL(interests.size(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(MalformedUpdate)
+{
+  std::string updateName = CONFIG_SITE + nlsr.getConfParameter().getLsaPrefix().toUri() +
+                           CONFIG_ROUTER_NAME;
+
+  std::vector<ndn::Interest>& interests = face->m_sentInterests;
+  BOOST_CHECK_EQUAL(interests.size(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(SequenceNumber)
+{
+  std::string originRouter = CONFIG_NETWORK + CONFIG_SITE + "/%C1.Router/other-router/";
+
+  Lsdb& lsdb = nlsr.getLsdb();
+
+  // Install Name LSA
+  NamePrefixList nameList;
+  NameLsa lsa(originRouter, "name", 999, ndn::time::system_clock::TimePoint::max(), nameList);
+  lsdb.installNameLsa(lsa);
+
+  // Install Adj LSA
+  AdjacencyList adjList;
+  AdjLsa adjLsa(originRouter, "adjacency", 1000, ndn::time::system_clock::TimePoint::max(),
+                3 , adjList);
+  lsdb.installAdjLsa(adjLsa);
+
+  // Install Cor LSA
+  CoordinateLsa corLsa(originRouter, "coordinate", 1000, ndn::time::system_clock::TimePoint::max(),
+                       0,0);
+  lsdb.installCoordinateLsa(corLsa);
+
+  std::string updateName = nlsr.getConfParameter().getLsaPrefix().toUri() +
+                           CONFIG_SITE + "/%C1.Router/other-router/";
+
+  // Lower NameLSA sequence number
+  uint64_t lowerSeqNo = static_cast<uint64_t>(998) << 40;
+  receiveUpdate(updateName, lowerSeqNo);
+
+  std::vector<ndn::Interest>& interests = face->m_sentInterests;
+  BOOST_REQUIRE_EQUAL(interests.size(), 0);
+
+  // Same NameLSA sequence number
+  uint64_t sameSeqNo = static_cast<uint64_t>(999) << 40;
+  receiveUpdate(updateName, sameSeqNo);
+
+  interests = face->m_sentInterests;
+  BOOST_REQUIRE_EQUAL(interests.size(), 0);
+
+  // Higher NameLSA sequence number
+  uint64_t higherSeqNo = static_cast<uint64_t>(1000) << 40;
+  receiveUpdate(updateName, higherSeqNo);
+
+  interests = face->m_sentInterests;
+  BOOST_REQUIRE_EQUAL(interests.size(), 1);
+
+  std::vector<ndn::Interest>::iterator it = interests.begin();
+  BOOST_CHECK_EQUAL(it->getName().getPrefix(-1), updateName + "name/");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace test
+} // namespace nlsr