Fix logic

Change-Id: I7bfb72e8bb245fab3e9a9d575abc7217bbae86d0
diff --git a/src/logger.hpp b/src/logger.hpp
index 64a8563..c4eee03 100644
--- a/src/logger.hpp
+++ b/src/logger.hpp
@@ -64,7 +64,7 @@
 
 #define _LOG_DEBUG(x) \
   std::clog << boost::get_system_time() << " " << boost::this_thread::get_id() << \
-               " " << x << std::endl;
+               " " << x << std::endl
 
 #else // _DEBUG
 
diff --git a/src/logic.cpp b/src/logic.cpp
new file mode 100644
index 0000000..f584da5
--- /dev/null
+++ b/src/logic.cpp
@@ -0,0 +1,593 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012-2014 University of California, Los Angeles
+ *
+ * This file is part of ChronoSync, synchronization library for distributed realtime
+ * applications for NDN.
+ *
+ * ChronoSync 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.
+ *
+ * ChronoSync 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
+ * ChronoSync, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
+ * @author Chaoyi Bian <bcy@pku.edu.cn>
+ * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+ * @author Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#include "logic.hpp"
+#include "logger.hpp"
+
+INIT_LOGGER("Logic");
+
+#ifdef _DEBUG
+#define _LOG_DEBUG_ID(v) _LOG_DEBUG("Instance" << m_instanceId << ": " << v)
+#else
+#define _LOG_DEBUG_ID(v) _LOG_DEBUG(v)
+#endif
+
+namespace chronosync {
+
+using ndn::ConstBufferPtr;
+using ndn::EventId;
+
+const uint8_t EMPTY_DIGEST_VALUE[] = {
+  0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
+  0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
+  0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
+  0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
+};
+
+#ifdef _DEBUG
+int Logic::m_instanceCounter = 0;
+#endif
+
+const time::steady_clock::Duration Logic::DEFAULT_RESET_TIMER = time::seconds(0);
+const time::steady_clock::Duration Logic::DEFAULT_CANCEL_RESET_TIMER = time::milliseconds(500);
+const time::milliseconds Logic::DEFAULT_RESET_INTEREST_LIFETIME(1000);
+const time::milliseconds Logic::DEFAULT_SYNC_INTEREST_LIFETIME(1000);
+const time::milliseconds Logic::DEFAULT_SYNC_REPLY_FRESHNESS(1000);
+
+const ndn::ConstBufferPtr Logic::EMPTY_DIGEST(new ndn::Buffer(EMPTY_DIGEST_VALUE, 32));
+const ndn::name::Component Logic::RESET_COMPONENT("reset");
+
+Logic::Logic(ndn::Face& face,
+             const Name& syncPrefix,
+             const Name& userPrefix,
+             const UpdateCallback& onUpdate,
+             const time::steady_clock::Duration& resetTimer,
+             const time::steady_clock::Duration& cancelResetTimer,
+             const time::milliseconds& resetInterestLifetime,
+             const time::milliseconds& syncInterestLifetime,
+             const time::milliseconds& syncReplyFreshness)
+  : m_face(face)
+  , m_syncPrefix(syncPrefix)
+  , m_userPrefix(userPrefix)
+  , m_interestTable(m_face.getIoService())
+  , m_outstandingInterestId(0)
+  , m_isInReset(false)
+  , m_needPeriodReset(resetTimer > time::steady_clock::Duration::zero())
+  , m_onUpdate(onUpdate)
+  , m_scheduler(m_face.getIoService())
+  , m_randomGenerator(static_cast<unsigned int>(std::time(0)))
+  , m_rangeUniformRandom(m_randomGenerator, boost::uniform_int<>(100,500))
+  , m_reexpressionJitter(m_randomGenerator, boost::uniform_int<>(100,500))
+  , m_resetTimer(resetTimer)
+  , m_cancelResetTimer(cancelResetTimer)
+  , m_resetInterestLifetime(resetInterestLifetime)
+  , m_syncInterestLifetime(syncInterestLifetime)
+  , m_syncReplyFreshness(syncReplyFreshness)
+{
+#ifdef _DEBUG
+  m_instanceId = m_instanceCounter++;
+#endif
+
+  _LOG_DEBUG_ID(">> Logic::Logic");
+
+  m_syncReset = m_syncPrefix;
+  m_syncReset.append("reset");
+
+  _LOG_DEBUG_ID("Listen to: " << m_syncPrefix);
+  m_syncRegisteredPrefixId =
+    m_face.setInterestFilter(m_syncPrefix,
+                             bind(&Logic::onSyncInterest, this, _1, _2),
+                             bind(&Logic::onSyncRegisterFailed, this, _1, _2));
+
+  setUserPrefix(m_userPrefix);
+
+  _LOG_DEBUG_ID("<< Logic::Logic");
+}
+
+Logic::~Logic()
+{
+  m_face.unsetInterestFilter(m_syncRegisteredPrefixId);
+  m_scheduler.cancelAllEvents();
+}
+
+void
+Logic::reset()
+{
+  m_isInReset = true;
+
+  m_state.reset();
+  m_log.clear();
+
+  sendResetInterest();
+
+  // reset outstanding interest name, so that data for previous interest will be dropped.
+  if (m_outstandingInterestId != 0) {
+    m_face.removePendingInterest(m_outstandingInterestId);
+    m_outstandingInterestId = 0;
+  }
+
+  sendSyncInterest();
+
+  if (static_cast<bool>(m_delayedInterestProcessingId))
+    m_scheduler.cancelEvent(m_delayedInterestProcessingId);
+
+  m_delayedInterestProcessingId =
+    m_scheduler.scheduleEvent(m_cancelResetTimer,
+                              bind(&Logic::cancelReset, this));
+}
+
+void
+Logic::setUserPrefix(const Name& userPrefix)
+{
+  m_userPrefix = userPrefix;
+
+  m_sessionName = m_userPrefix;
+  m_sessionName.appendNumber(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count());
+
+  m_seqNo = 0;
+
+  reset();
+}
+
+void
+Logic::updateSeqNo(const SeqNo& seqNo)
+{
+  _LOG_DEBUG_ID(">> Logic::updateSeqNo");
+  _LOG_DEBUG_ID("seqNo: " << seqNo << " m_seqNo: " << m_seqNo);
+  if (seqNo < m_seqNo || seqNo == 0)
+    return;
+
+  m_seqNo = seqNo;
+
+  _LOG_DEBUG_ID("updateSeqNo: m_seqNo " << m_seqNo);
+
+  if (!m_isInReset) {
+    _LOG_DEBUG_ID("updateSeqNo: not in Reset ");
+    ndn::ConstBufferPtr previousRoot = m_state.getRootDigest();
+    {
+      using namespace CryptoPP;
+
+      std::string hash;
+      StringSource(previousRoot->buf(), previousRoot->size(), true,
+                   new HexEncoder(new StringSink(hash), false));
+      _LOG_DEBUG_ID("Hash: " << hash);
+    }
+
+    bool isInserted = false;
+    bool isUpdated = false;
+    SeqNo oldSeq;
+    boost::tie(isInserted, isUpdated, oldSeq) = m_state.update(m_sessionName, seqNo);
+
+    _LOG_DEBUG_ID("Insert: " << std::boolalpha << isInserted);
+    _LOG_DEBUG_ID("Updated: " << std::boolalpha << isUpdated);
+    if (isInserted || isUpdated) {
+      DiffStatePtr commit = make_shared<DiffState>();
+      commit->update(m_sessionName, seqNo);
+      commit->setRootDigest(m_state.getRootDigest());
+      insertToDiffLog(commit, previousRoot);
+
+      satisfyPendingSyncInterests(commit);
+    }
+  }
+}
+
+ConstBufferPtr
+Logic::getRootDigest() const
+{
+  return m_state.getRootDigest();
+}
+
+void
+Logic::printState(std::ostream& os) const
+{
+  BOOST_FOREACH(ConstLeafPtr leaf, m_state.getLeaves())
+    {
+      os << *leaf << "\n";
+    }
+}
+
+std::set<Name>
+Logic::getSessionNames() const
+{
+  std::set<Name> sessionNames;
+
+  BOOST_FOREACH(ConstLeafPtr leaf, m_state.getLeaves())
+    {
+      sessionNames.insert(leaf->getSessionName());
+    }
+
+  return sessionNames;
+}
+
+void
+Logic::onSyncInterest(const Name& prefix, const Interest& interest)
+{
+  _LOG_DEBUG_ID(">> Logic::onSyncInterest");
+  Name name = interest.getName();
+
+  _LOG_DEBUG_ID("InterestName: " << name);
+
+  if (RESET_COMPONENT != name.get(-1)) {
+    // normal sync interest
+    processSyncInterest(interest.shared_from_this());
+  }
+  else
+    // reset interest
+    processResetInterest(interest);
+
+  _LOG_DEBUG_ID("<< Logic::onSyncInterest");
+}
+
+void
+Logic::onSyncRegisterFailed(const Name& prefix, const std::string& msg)
+{
+  //Sync prefix registration failed
+  _LOG_DEBUG_ID(">> Logic::onSyncRegisterFailed");
+}
+
+void
+Logic::onSyncData(const Interest& interest, Data& data)
+{
+  _LOG_DEBUG_ID(">> Logic::onSyncData");
+  // Place holder for validator.
+  onSyncDataValidated(data.shared_from_this());
+  _LOG_DEBUG_ID("<< Logic::onSyncData");
+}
+
+void
+Logic::onResetData(const Interest& interest, Data& data)
+{
+  // This should not happened, drop the received data.
+}
+
+void
+Logic::onSyncTimeout(const Interest& interest)
+{
+  // It is OK. Others will handle the time out situation.
+  _LOG_DEBUG_ID(">> Logic::onSyncTimeout");
+  _LOG_DEBUG_ID("Interest: " << interest.getName());
+  _LOG_DEBUG_ID("<< Logic::onSyncTimeout");
+}
+
+void
+Logic::onSyncDataValidationFailed(const shared_ptr<const Data>& data)
+{
+  // SyncReply cannot be validated.
+}
+
+void
+Logic::onSyncDataValidated(const shared_ptr<const Data>& data)
+{
+  Name name = data->getName();
+  ConstBufferPtr digest = make_shared<ndn::Buffer>(name.get(-1).value(), name.get(-1).value_size());
+
+  processSyncData(name, digest, data->getContent().blockFromValue());
+}
+
+void
+Logic::processSyncInterest(const shared_ptr<const Interest>& interest,
+                           bool isTimedProcessing/*=false*/)
+{
+  _LOG_DEBUG_ID(">> Logic::processSyncInterest");
+
+  const Name& name = interest->getName();
+  ConstBufferPtr digest =
+      make_shared<ndn::Buffer>(name.get(-1).value(), name.get(-1).value_size());
+
+  ConstBufferPtr rootDigest = m_state.getRootDigest();
+
+  // If the digest of the incoming interest is the same as root digest
+  // Put the interest into InterestTable
+  if (*rootDigest == *digest) {
+    _LOG_DEBUG_ID("Oh, we are in the same state");
+    m_interestTable.insert(interest, digest, false);
+
+    if (!m_isInReset)
+      return;
+
+    if (!isTimedProcessing) {
+      _LOG_DEBUG_ID("Non timed processing in reset");
+      // Still in reset, our own seq has not been put into state yet
+      // Do not hurry, some others may be also resetting and may send their reply
+      if (static_cast<bool>(m_delayedInterestProcessingId))
+        m_scheduler.cancelEvent(m_delayedInterestProcessingId);
+
+      time::milliseconds after(m_rangeUniformRandom());
+      _LOG_DEBUG_ID("After: " << after);
+      m_delayedInterestProcessingId =
+        m_scheduler.scheduleEvent(after,
+                                  bind(&Logic::processSyncInterest, this, interest, true));
+    }
+    else {
+      _LOG_DEBUG_ID("Timed processing in reset");
+      // Now we can get out of reset state by putting our own stuff into m_state.
+      cancelReset();
+    }
+
+    return;
+  }
+
+  // If the digest of incoming interest is an "empty" digest
+  if (digest == EMPTY_DIGEST) {
+    _LOG_DEBUG_ID("Poor guy, he knows nothing");
+    sendSyncData(name, m_state);
+    return;
+  }
+
+  DiffStateContainer::iterator stateIter = m_log.find(digest);
+  // If the digest of incoming interest can be found from the log
+  if (stateIter != m_log.end()) {
+    _LOG_DEBUG_ID("It is ok, you are so close");
+    sendSyncData(name, *(*stateIter)->diff());
+    return;
+  }
+
+  if (!isTimedProcessing) {
+    _LOG_DEBUG_ID("Let's wait, just wait for a while");
+    // Do not hurry, some incoming SyncReplies may help us to recognize the digest
+    bool doesExist = m_interestTable.insert(interest, digest, true);
+    if (doesExist)
+      // Original comment (not sure): somebody else replied, so restart random-game timer
+      // YY: Get the same SyncInterest again, refresh the timer
+      m_scheduler.cancelEvent(m_delayedInterestProcessingId);
+
+    m_delayedInterestProcessingId =
+      m_scheduler.scheduleEvent(time::milliseconds(m_rangeUniformRandom()),
+                                bind(&Logic::processSyncInterest, this, interest, true));
+  }
+  else {
+    // OK, nobody is helping us, just tell the truth.
+    _LOG_DEBUG_ID("OK, nobody is helping us, just tell the truth");
+    m_interestTable.erase(digest);
+    sendSyncData(name, m_state);
+  }
+
+  _LOG_DEBUG_ID("<< Logic::processSyncInterest");
+}
+
+void
+Logic::processResetInterest(const Interest& interest)
+{
+  _LOG_DEBUG_ID(">> Logic::processResetInterest");
+  reset();
+}
+
+void
+Logic::processSyncData(const Name& name,
+                       ndn::ConstBufferPtr digest,
+                       const Block& syncReplyBlock)
+{
+  _LOG_DEBUG_ID(">> Logic::processSyncData");
+
+  DiffStatePtr commit = make_shared<DiffState>();
+  ndn::ConstBufferPtr previousRoot = m_state.getRootDigest();
+
+  try {
+    m_interestTable.erase(digest); // Remove satisfied interest from PIT
+
+    State reply;
+    reply.wireDecode(syncReplyBlock);
+
+    std::vector<MissingDataInfo> v;
+    BOOST_FOREACH(ConstLeafPtr leaf, reply.getLeaves().get<ordered>())
+      {
+        BOOST_ASSERT(leaf != 0);
+
+        const Name& info = leaf->getSessionName();
+        SeqNo seq = leaf->getSeq();
+
+        bool isInserted = false;
+        bool isUpdated = false;
+        SeqNo oldSeq;
+        boost::tie(isInserted, isUpdated, oldSeq) = m_state.update(info, seq);
+
+        if (isInserted || isUpdated) {
+          commit->update(info, seq);
+
+          oldSeq++;
+          MissingDataInfo mdi = {info, oldSeq, seq};
+          v.push_back(mdi);
+        }
+      }
+
+    if (!v.empty()) {
+      m_onUpdate(v);
+
+      commit->setRootDigest(m_state.getRootDigest());
+      insertToDiffLog(commit, previousRoot);
+    }
+    else {
+      _LOG_DEBUG_ID("What? nothing new");
+    }
+  }
+  catch (State::Error&) {
+    _LOG_DEBUG_ID("Something really fishy happened during state decoding");
+    // Something really fishy happened during state decoding;
+    commit.reset();
+    return;
+  }
+
+  if (static_cast<bool>(commit) && !commit->getLeaves().empty()) {
+    // state changed and it is safe to express a new interest
+    time::steady_clock::Duration after = time::milliseconds(m_reexpressionJitter());
+    _LOG_DEBUG_ID("Reschedule sync interest after: " << after);
+    EventId eventId = m_scheduler.scheduleEvent(after,
+                                                bind(&Logic::sendSyncInterest, this));
+
+    m_scheduler.cancelEvent(m_reexpressingInterestId);
+    m_reexpressingInterestId = eventId;
+  }
+}
+
+void
+Logic::satisfyPendingSyncInterests(ConstDiffStatePtr commit)
+{
+  _LOG_DEBUG_ID(">> Logic::satisfyPendingSyncInterests");
+  try {
+    _LOG_DEBUG_ID("InterestTable size: " << m_interestTable.size());
+    for (InterestTable::const_iterator it = m_interestTable.begin();
+         it != m_interestTable.end(); it++) {
+      ConstUnsatisfiedInterestPtr request = *it;
+
+      if (request->isUnknown)
+        sendSyncData(request->interest->getName(), m_state);
+      else
+        sendSyncData(request->interest->getName(), *commit);
+    }
+    m_interestTable.clear();
+  }
+  catch (InterestTable::Error&) {
+    // ok. not really an error
+  }
+  _LOG_DEBUG_ID("<< Logic::satisfyPendingSyncInterests");
+}
+
+void
+Logic::insertToDiffLog(DiffStatePtr commit, ndn::ConstBufferPtr previousRoot)
+{
+  _LOG_DEBUG_ID(">> Logic::insertToDiffLog");
+  // Connect to the history
+  if (!m_log.empty())
+    (*m_log.find(previousRoot))->setNext(commit);
+
+  // Insert the commit
+  m_log.erase(commit->getRootDigest());
+  m_log.insert(commit);
+  _LOG_DEBUG_ID("<< Logic::insertToDiffLog");
+}
+
+void
+Logic::sendResetInterest()
+{
+  _LOG_DEBUG_ID(">> Logic::sendResetInterest");
+
+  if (m_needPeriodReset) {
+    _LOG_DEBUG_ID("Need Period Reset");
+    _LOG_DEBUG_ID("ResetTimer: " << m_resetTimer);
+
+    EventId eventId =
+      m_scheduler.scheduleEvent(m_resetTimer + ndn::time::milliseconds(m_reexpressionJitter()),
+                                bind(&Logic::sendResetInterest, this));
+    m_scheduler.cancelEvent(m_resetInterestId);
+    m_resetInterestId = eventId;
+  }
+
+  Interest interest(m_syncReset);
+  interest.setMustBeFresh(true);
+  interest.setInterestLifetime(m_resetInterestLifetime);
+  m_face.expressInterest(interest,
+                         bind(&Logic::onResetData, this, _1, _2),
+                         bind(&Logic::onSyncTimeout, this, _1));
+
+  _LOG_DEBUG_ID("<< Logic::sendResetInterest");
+}
+
+void
+Logic::sendSyncInterest()
+{
+  _LOG_DEBUG_ID(">> Logic::sendSyncInterest");
+
+  Name interestName;
+  interestName.append(m_syncPrefix)
+    .append(ndn::name::Component(*m_state.getRootDigest()));
+
+  m_outstandingInterestName = interestName;
+
+#ifdef _DEBUG
+  printDigest(m_state.getRootDigest());
+#endif
+
+  EventId eventId =
+    m_scheduler.scheduleEvent(m_syncInterestLifetime +
+                              ndn::time::milliseconds(m_reexpressionJitter()),
+                              bind(&Logic::sendSyncInterest, this));
+  m_scheduler.cancelEvent(m_reexpressingInterestId);
+  m_reexpressingInterestId = eventId;
+
+  Interest interest(interestName);
+  interest.setMustBeFresh(true);
+  interest.setInterestLifetime(m_syncInterestLifetime);
+
+  m_outstandingInterestId = m_face.expressInterest(interest,
+                                                   bind(&Logic::onSyncData, this, _1, _2),
+                                                   bind(&Logic::onSyncTimeout, this, _1));
+
+  _LOG_DEBUG_ID("Send interest: " << interest.getName());
+  _LOG_DEBUG_ID("<< Logic::sendSyncInterest");
+}
+
+void
+Logic::sendSyncData(const Name& name, const State& state)
+{
+  _LOG_DEBUG_ID(">> Logic::sendSyncData");
+  shared_ptr<Data> syncReply = make_shared<Data>(name);
+  syncReply->setContent(state.wireEncode());
+  syncReply->setFreshnessPeriod(m_syncReplyFreshness);
+  m_keyChain.sign(*syncReply);
+
+  m_face.put(*syncReply);
+
+  // checking if our own interest got satisfied
+  if (m_outstandingInterestName == name) {
+    // remove outstanding interest
+    if (m_outstandingInterestId != 0) {
+      m_face.removePendingInterest(m_outstandingInterestId);
+      m_outstandingInterestId = 0;
+    }
+
+    // re-schedule sending Sync interest
+    time::milliseconds after(m_reexpressionJitter());
+    _LOG_DEBUG_ID("Satisfy our own interest");
+    _LOG_DEBUG_ID("Reschedule sync interest after " << after);
+    EventId eventId = m_scheduler.scheduleEvent(after, bind(&Logic::sendSyncInterest, this));
+    m_scheduler.cancelEvent(m_reexpressingInterestId);
+    m_reexpressingInterestId = eventId;
+  }
+  _LOG_DEBUG_ID("<< Logic::sendSyncData");
+}
+
+void
+Logic::cancelReset()
+{
+  _LOG_DEBUG_ID(">> Logic::cancelReset");
+  if (!m_isInReset)
+    return;
+
+  m_isInReset = false;
+  updateSeqNo(m_seqNo);
+  _LOG_DEBUG_ID("<< Logic::cancelReset");
+}
+
+void
+Logic::printDigest(ndn::ConstBufferPtr digest)
+{
+  using namespace CryptoPP;
+
+  std::string hash;
+  StringSource(digest->buf(), digest->size(), true,
+               new HexEncoder(new StringSink(hash), false));
+  _LOG_DEBUG_ID("Hash: " << hash);
+}
+
+} // namespace chronosync
diff --git a/src/logic.hpp b/src/logic.hpp
new file mode 100644
index 0000000..2be8636
--- /dev/null
+++ b/src/logic.hpp
@@ -0,0 +1,388 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012-2014 University of California, Los Angeles
+ *
+ * This file is part of ChronoSync, synchronization library for distributed realtime
+ * applications for NDN.
+ *
+ * ChronoSync 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.
+ *
+ * ChronoSync 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
+ * ChronoSync, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
+ * @author Chaoyi Bian <bcy@pku.edu.cn>
+ * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+ * @author Yingdi Yu <yingdi@cs.ucla.edu>
+ */
+
+#ifndef CHRONOSYNC_LOGIC_HPP
+#define CHRONOSYNC_LOGIC_HPP
+
+#include "boost-header.h"
+#include <memory>
+#include <map>
+
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/util/scheduler.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
+
+#include "interest-table.hpp"
+#include "diff-state-container.hpp"
+
+namespace chronosync {
+
+/**
+ * @brief The missing sequence numbers for a session
+ *
+ * This class is used to notify the clients of Logic
+ * the details of state changes.
+ *
+ * Instances of this class is usually used as elements of some containers
+ * such as std::vector, thus it is copyable.
+ */
+class MissingDataInfo
+{
+public:
+  /// @brief session name
+  Name session;
+  /// @brief the lowest one of missing sequence numbers
+  SeqNo low;
+  /// @brief the highest one of missing sequence numbers
+  SeqNo high;
+};
+
+/**
+ * @brief The callback function to handle state updates
+ *
+ * The parameter is a set of MissingDataInfo, of which each corresponds to
+ * a session that has changed its state.
+ */
+typedef function<void(const std::vector<MissingDataInfo>&)> UpdateCallback;
+
+/**
+ * @brief Logic of ChronoSync
+ */
+class Logic : noncopyable
+{
+public:
+  static const time::steady_clock::Duration DEFAULT_RESET_TIMER;
+  static const time::steady_clock::Duration DEFAULT_CANCEL_RESET_TIMER;
+  static const time::milliseconds DEFAULT_RESET_INTEREST_LIFETIME;
+  static const time::milliseconds DEFAULT_SYNC_INTEREST_LIFETIME;
+  static const time::milliseconds DEFAULT_SYNC_REPLY_FRESHNESS;
+
+  /**
+   * @brief Constructor
+   *
+   * @param syncPrefix The prefix of the sync group
+   * @param userPrefix The prefix of the user who owns the session
+   * @param onUpdate The callback function to handle state updates
+   * @param resetTimer The timer to periodically send Reset Interest
+   * @param syncReplyFreshness The FreshnessPeriod of sync reply
+   * @param resetInterestLifetime The lifetime of sync interest
+   * @param resetInterestLifetime The lifetime of Reset Interest
+   * @param cancelResetTimer The timer to exit from Reset state
+   */
+  Logic(ndn::Face& face,
+        const Name& syncPrefix,
+        const Name& userPrefix,
+        const UpdateCallback& onUpdate,
+        const time::steady_clock::Duration& resetTimer = DEFAULT_RESET_TIMER,
+        const time::steady_clock::Duration& cancelResetTimer = DEFAULT_CANCEL_RESET_TIMER,
+        const time::milliseconds& resetInterestLifetime = DEFAULT_RESET_INTEREST_LIFETIME,
+        const time::milliseconds& syncInterestLifetime = DEFAULT_SYNC_INTEREST_LIFETIME,
+        const time::milliseconds& syncReplyFreshness = DEFAULT_SYNC_REPLY_FRESHNESS);
+
+  ~Logic();
+
+  /// @brief Reset the sync tree (and restart synchronization again)
+  void
+  reset();
+
+  /**
+   * @brief Set user prefix
+   *
+   * This method will also change the session name and trigger reset.
+   *
+   * @param userPrefix The prefix of user.
+   */
+  void
+  setUserPrefix(const Name& userPrefix);
+
+  /// @brief Get the name of the local session.
+  const Name&
+  getSessionName() const
+  {
+    return m_sessionName;
+  }
+
+  /// @brief Get current seqNo of the local session.
+  const SeqNo&
+  getSeqNo() const
+  {
+    return m_seqNo;
+  }
+
+  /**
+   * @brief Update the seqNo of the local session
+   *
+   * The method updates the existing seqNo with the supplied seqNo.
+   *
+   * @param seq The new seqNo.
+   */
+  void
+  updateSeqNo(const SeqNo& seq);
+
+  /// @brief Get root digest of current sync tree
+  ndn::ConstBufferPtr
+  getRootDigest() const;
+
+  /// @brief Get the name of all sessions
+  std::set<Name>
+  getSessionNames() const;
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+  void
+  printState(std::ostream& os) const;
+
+  ndn::Scheduler&
+  getScheduler()
+  {
+    return m_scheduler;
+  }
+
+  State&
+  getState()
+  {
+    return m_state;
+  }
+
+private:
+  /**
+   * @brief Callback to handle Sync Interest
+   *
+   * This method checks whether an incoming interest is a normal one or a reset
+   * and dispatches the incoming interest to corresponding processing methods.
+   *
+   * @param prefix   The prefix of the sync group.
+   * @param interest The incoming sync interest.
+   */
+  void
+  onSyncInterest(const Name& prefix, const Interest& interest);
+
+  /**
+   * @brief Callback to handle Sync prefix registration failure
+   *
+   * This method does nothing for now.
+   *
+   * @param prefix The prefix of the sync group.
+   * @param msg    The error message.
+   */
+  void
+  onSyncRegisterFailed(const Name& prefix, const std::string& msg);
+
+  /**
+   * @brief Callback to handle Sync Reply
+   *
+   * This method calls validator to validate Sync Reply.
+   * For now, validation is disabled, Logic::onSyncDataValidated is called
+   * directly.
+   *
+   * @param interest The Sync Interest
+   * @param data     The reply to the Sync Interest
+   */
+  void
+  onSyncData(const Interest& interest, Data& data);
+
+  /**
+   * @brief Callback to handle reply to Reset Interest.
+   *
+   * This method does nothing, since reply to Reset Interest is not useful for now.
+   *
+   * @param interest The Reset Interest
+   * @param data     The reply to the Reset Interest
+   */
+  void
+  onResetData(const Interest& interest, Data& data);
+
+  /**
+   * @brief Callback to handle Sync Interest timeout.
+   *
+   * This method does nothing, since Logic per se handles timeout explicitly.
+   *
+   * @param interest The Sync Interest
+   */
+  void
+  onSyncTimeout(const Interest& interest);
+
+  /**
+   * @brief Callback to invalid Sync Reply.
+   *
+   * This method does nothing but drops the invalid reply.
+   *
+   * @param data The invalid Sync Reply
+   */
+  void
+  onSyncDataValidationFailed(const shared_ptr<const Data>& data);
+
+  /**
+   * @brief Callback to valid Sync Reply.
+   *
+   * This method simply passes the valid reply to processSyncData.
+   *
+   * @param data The valid Sync Reply.
+   */
+  void
+  onSyncDataValidated(const shared_ptr<const Data>& data);
+
+  /**
+   * @brief Process normal Sync Interest
+   *
+   * This method extracts the digest from the incoming Sync Interest,
+   * compares it against current local digest, and process the Sync
+   * Interest according to the comparison result.  See docs/design.rst
+   * for more details.
+   *
+   * @param interest          The incoming interest
+   * @param isTimedProcessing True if the interest needs an immediate reply,
+   *                          otherwise hold the interest for a while before
+   *                          making a reply (to avoid unnecessary recovery)
+   */
+  void
+  processSyncInterest(const shared_ptr<const Interest>& interest,
+                      bool isTimedProcessing = false);
+
+  /**
+   * @brief Process reset Sync Interest
+   *
+   * This method simply call Logic::reset()
+   *
+   * @param interest The incoming interest.
+   */
+  void
+  processResetInterest(const Interest& interest);
+
+  /**
+   * @brief Process Sync Reply.
+   *
+   * This method extracts state update information from Sync Reply and applies
+   * it to the Sync Tree and re-express Sync Interest.
+   *
+   * @param name           The data name of the Sync Reply.
+   * @param digest         The digest in the data name.
+   * @param syncReplyBlock The content of the Sync Reply.
+   */
+  void
+  processSyncData(const Name& name,
+                  ndn::ConstBufferPtr digest,
+                  const Block& syncReplyBlock);
+
+  /**
+   * @brief Insert state diff into log
+   *
+   * @param diff         The diff .
+   * @param previousRoot The root digest before state changes.
+   */
+  void
+  insertToDiffLog(DiffStatePtr diff,
+                  ndn::ConstBufferPtr previousRoot);
+
+  /**
+   * @brief Reply to all pending Sync Interests with a particular commit (or diff)
+   *
+   * @param commit The diff.
+   */
+  void
+  satisfyPendingSyncInterests(ConstDiffStatePtr commit);
+
+  /// @brief Helper method to send normal Sync Interest
+  void
+  sendSyncInterest();
+
+  /// @brief Helper method to send reset Sync Interest
+  void
+  sendResetInterest();
+
+  /// @brief Helper method to send Sync Reply
+  void
+  sendSyncData(const Name& name, const State& state);
+
+  /**
+   * @brief Unset reset status
+   *
+   * By invoking this method, one can add its own state into the Sync Tree, thus
+   * jumping out of the reset status
+   */
+  void
+  cancelReset();
+
+  void
+  printDigest(ndn::ConstBufferPtr digest);
+
+private:
+
+  static const ndn::ConstBufferPtr EMPTY_DIGEST;
+  static const ndn::name::Component RESET_COMPONENT;
+
+  // Communication
+  ndn::Face& m_face;
+  Name m_syncPrefix;
+  const ndn::RegisteredPrefixId* m_syncRegisteredPrefixId;
+  Name m_syncReset;
+  Name m_userPrefix;
+
+  // State
+  Name m_sessionName;
+  SeqNo m_seqNo;
+  State m_state;
+  DiffStateContainer m_log;
+  InterestTable m_interestTable;
+  Name m_outstandingInterestName;
+  const ndn::PendingInterestId* m_outstandingInterestId;
+  bool m_isInReset;
+  bool m_needPeriodReset;
+
+  // Callback
+  UpdateCallback m_onUpdate;
+
+  // Event
+  ndn::Scheduler m_scheduler;
+  ndn::EventId m_delayedInterestProcessingId;
+  ndn::EventId m_reexpressingInterestId;
+  ndn::EventId m_resetInterestId;
+
+  // Timer
+  boost::mt19937 m_randomGenerator;
+  boost::variate_generator<boost::mt19937&, boost::uniform_int<> > m_rangeUniformRandom;
+  boost::variate_generator<boost::mt19937&, boost::uniform_int<> > m_reexpressionJitter;
+  /// @brief Timer to send next reset 0 for no reset
+  time::steady_clock::Duration m_resetTimer;
+  /// @brief Timer to cancel reset state
+  time::steady_clock::Duration m_cancelResetTimer;
+  /// @brief Lifetime of reset interest
+  time::milliseconds m_resetInterestLifetime;
+  /// @brief Lifetime of sync interest
+  time::milliseconds m_syncInterestLifetime;
+  /// @brief FreshnessPeriod of SyncReply
+  time::milliseconds m_syncReplyFreshness;
+
+  // Others
+  ndn::KeyChain m_keyChain;
+
+#ifdef _DEBUG
+  int m_instanceId;
+  static int m_instanceCounter;
+#endif
+};
+
+
+} // namespace chronosync
+
+#endif // CHRONOSYNC_LOGIC_HPP
diff --git a/src/sync-event.h b/src/sync-event.h
deleted file mode 100644
index bbe07bc..0000000
--- a/src/sync-event.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (c) 2012-2014 University of California, Los Angeles
- *
- * This file is part of ChronoSync, synchronization library for distributed realtime
- * applications for NDN.
- *
- * ChronoSync 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.
- *
- * ChronoSync 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
- * ChronoSync, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
- * @author Chaoyi Bian <bcy@pku.edu.cn>
- * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
- */
-
-#ifndef SYNC_EVENT_H
-#define SYNC_EVENT_H
-
-#include <boost/function.hpp>
-
-namespace Sync
-{
-
-typedef boost::function< void ( ) > Event;
-
-} // Sync
-
-#endif // SYNC_EVENT_H
diff --git a/src/sync-intro-certificate.h b/src/sync-intro-certificate.h
deleted file mode 100644
index d6783ce..0000000
--- a/src/sync-intro-certificate.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (c) 2012-2014 University of California, Los Angeles
- *
- * This file is part of ChronoSync, synchronization library for distributed realtime
- * applications for NDN.
- *
- * ChronoSync 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.
- *
- * ChronoSync 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
- * ChronoSync, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/web/index.html>
- */
-
-#ifndef SYNC_INTRO_CERTIFICATE_H
-#define SYNC_INTRO_CERTIFICATE_H
-
-#include <ndn-cxx/security/identity-certificate.hpp>
-#include <ndn-cxx/security/signature-sha256-with-rsa.hpp>
-
-namespace Sync {
-
-class IntroCertificate : public ndn::Data
-{
-  /**
-   * Naming convention of IntroCertificate:
-   * /<sync_prefix>/CHRONOS-INTRO-CERT/introducee_certname/introducer_certname/version
-   * Content: introducee's identity certificate;
-   * KeyLocator: introducer's identity certificate;
-   */
-public:
-  struct Error : public ndn::Data::Error { Error(const std::string &what) : ndn::Data::Error(what) {} };
-
-  IntroCertificate()
-  {}
-
-  /**
-   * @brief Construct IntroCertificate from IdentityCertificate
-   *
-   * @param syncPrefix
-   * @param introduceeCert
-   * @param introducerName
-   */
-  IntroCertificate(const ndn::Name& syncPrefix,
-                   const ndn::IdentityCertificate& introduceeCert,
-                   const ndn::Name& introducerCertName); //without version number
-
-  /**
-   * @brief Construct IntroCertificate using a plain data.
-   *
-   * if data is not actually IntroCertificate, Error will be thrown out.
-   *
-   * @param data
-   * @throws ndn::IntroCertificate::Error.
-   */
-  IntroCertificate(const ndn::Data& data);
-
-  virtual
-  ~IntroCertificate() {};
-
-  const ndn::IdentityCertificate&
-  getIntroduceeCert() const
-  {
-    return m_introduceeCert;
-  }
-
-  const ndn::Name&
-  getIntroducerCertName() const
-  {
-    return m_introducerCertName;
-  }
-
-  const ndn::Name&
-  getIntroduceeCertName() const
-  {
-    return m_introduceeCertName;
-  }
-
-private:
-  ndn::Name m_syncPrefix;
-  ndn::IdentityCertificate m_introduceeCert;
-  ndn::Name m_introducerCertName;
-  ndn::Name m_introduceeCertName;
-};
-
-inline
-IntroCertificate::IntroCertificate(const ndn::Name& syncPrefix,
-                                   const ndn::IdentityCertificate& introduceeCert,
-                                   const ndn::Name& introducerCertName)
-  : m_syncPrefix(syncPrefix)
-  , m_introduceeCert(introduceeCert)
-  , m_introducerCertName(introducerCertName)
-  , m_introduceeCertName(introduceeCert.getName().getPrefix(-1))
-{
-  // Naming convention /<sync_prefix>/CHRONOS-INTRO-CERT/introducee_certname/introducer_certname/version
-  ndn::Name dataName = m_syncPrefix;
-  dataName.append("CHRONOS-INTRO-CERT")
-    .append(m_introduceeCertName.wireEncode())
-    .append(m_introducerCertName.wireEncode())
-    .appendVersion();
-
-  setName(dataName);
-  setContent(m_introduceeCert.wireEncode());
-}
-
-inline
-IntroCertificate::IntroCertificate(const ndn::Data& data)
-  : Data(data)
-{
-  // Naming convention /<sync_prefix>/CHRONOS-INTRO-CERT/introducee_certname/introducer_certname/version
-  ndn::Name dataName = data.getName();
-
-  if(dataName.size() < 4 || dataName.get(-4).toUri() != "CHRONOS-INTRO-CERT")
-    throw Error("Not a Sync::IntroCertificate");
-
-  try
-    {
-      m_introduceeCert.wireDecode(data.getContent().blockFromValue());
-      m_introducerCertName.wireDecode(dataName.get(-2).blockFromValue());
-      m_introduceeCertName.wireDecode(dataName.get(-3).blockFromValue());
-      m_syncPrefix = dataName.getPrefix(-4);
-    }
-  catch(ndn::IdentityCertificate::Error& e)
-    {
-      throw Error("Cannot decode introducee cert");
-    }
-  catch(ndn::Name::Error& e)
-    {
-      throw Error("Cannot decode name");
-    }
-  catch(ndn::Block::Error& e)
-    {
-      throw Error("Cannot decode block name");
-    }
-
-  if(m_introduceeCertName != m_introduceeCert.getName().getPrefix(-1))
-    throw Error("Invalid Sync::IntroCertificate (inconsistent introducee name)");
-
-  ndn::Name keyLocatorName;
-  try
-    {
-      ndn::SignatureSha256WithRsa sig(data.getSignature());
-      keyLocatorName = sig.getKeyLocator().getName();
-    }
-  catch(ndn::KeyLocator::Error& e)
-    {
-      throw Error("Invalid Sync::IntroCertificate (inconsistent introducer name#1)");
-    }
-  catch(ndn::SignatureSha256WithRsa::Error& e)
-    {
-      throw Error("Invalid Sync::IntroCertificate (inconsistent introducer name#2)");
-    }
-
-  if(m_introducerCertName != keyLocatorName)
-    throw Error("Invalid Sync::IntroCertificate (inconsistent introducer name#3)");
-}
-
-
-} // namespace Sync
-
-#endif //SYNC_INTRO_CERTIFICATE_H
diff --git a/src/sync-logic-event-container.h b/src/sync-logic-event-container.h
deleted file mode 100644
index 015984d..0000000
--- a/src/sync-logic-event-container.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (c) 2012-2014 University of California, Los Angeles
- *
- * This file is part of ChronoSync, synchronization library for distributed realtime
- * applications for NDN.
- *
- * ChronoSync 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.
- *
- * ChronoSync 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
- * ChronoSync, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
- * @author Chaoyi Bian <bcy@pku.edu.cn>
- * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
- */
-
-#ifndef SYNC_LOGIC_EVENT_CONTAINER_H
-#define SYNC_LOGIC_EVENT_CONTAINER_H
-
-#include "sync-event.h"
-
-#include <boost/function.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
-
-#include <boost/multi_index_container.hpp>
-// #include <boost/multi_index/tag.hpp>
-#include <boost/multi_index/ordered_index.hpp>
-// #include <boost/multi_index/composite_key.hpp>
-// #include <boost/multi_index/hashed_index.hpp>
-// #include <boost/multi_index/random_access_index.hpp>
-#include <boost/multi_index/member.hpp>
-// #include <boost/multi_index/mem_fun.hpp>
-
-namespace mi = boost::multi_index;
-
-namespace Sync
-{
-
-struct LogicEvent
-{
-  LogicEvent (const boost::system_time &_time, Event _event, uint32_t _label)
-    : time (_time)
-    , event (_event)
-    , lbl (_label)
-  { }
-
-  boost::system_time time;
-  Event event;
-  uint32_t lbl;
-};
-
-/// @cond include_hidden
-struct byLabel { } ;
-/// @endcond
-
-/**
- * \ingroup sync
- * @brief ???
- */
-struct EventsContainer : public mi::multi_index_container<
-  LogicEvent,
-  mi::indexed_by<
-
-    mi::ordered_non_unique<
-      mi::member<LogicEvent, boost::system_time, &LogicEvent::time>
-      >,
-
-    mi::ordered_non_unique<
-      mi::tag<byLabel>,
-      mi::member<LogicEvent, uint32_t, &LogicEvent::lbl>
-      >
-    >
-  >
-{
-};
-
-} // Sync
-
-#endif // SYNC_LOGIC_EVENT_CONTAINER_H
diff --git a/src/sync-logic.cc b/src/sync-logic.cc
deleted file mode 100644
index 0567b60..0000000
--- a/src/sync-logic.cc
+++ /dev/null
@@ -1,714 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (c) 2012-2014 University of California, Los Angeles
- *
- * This file is part of ChronoSync, synchronization library for distributed realtime
- * applications for NDN.
- *
- * ChronoSync 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.
- *
- * ChronoSync 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
- * ChronoSync, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
- * @author Chaoyi Bian <bcy@pku.edu.cn>
- * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
- * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/web/index.html>
- */
-
-#include "sync-logic.h"
-#include "sync-diff-leaf.h"
-#include "sync-full-leaf.h"
-#include "sync-logging.h"
-#include "sync-state.h"
-
-#include <boost/foreach.hpp>
-#include <boost/lexical_cast.hpp>
-#include <vector>
-
-using namespace ndn;
-
-INIT_LOGGER ("SyncLogic")
-
-
-#ifdef _DEBUG
-#define _LOG_DEBUG_ID(v) _LOG_DEBUG(m_instanceId << " " << v)
-#else
-#define _LOG_DEBUG_ID(v) _LOG_DEBUG(v)
-#endif
-
-#define GET_RANDOM(var) var ()
-
-#define TIME_SECONDS_WITH_JITTER(sec) \
-  (time::seconds(sec) + time::milliseconds(GET_RANDOM (m_reexpressionJitter)))
-
-#define TIME_MILLISECONDS_WITH_JITTER(ms) \
-  (time::milliseconds(ms) + time::milliseconds(GET_RANDOM (m_reexpressionJitter)))
-
-namespace Sync {
-
-using ndn::shared_ptr;
-
-int SyncLogic::m_instanceCounter = 0;
-
-const int SyncLogic::m_syncResponseFreshness = 1000; // MUST BE dividable by 1000!!!
-const int SyncLogic::m_syncInterestReexpress = 4; // seconds
-
-SyncLogic::SyncLogic (const Name& syncPrefix,
-                      const IdentityCertificate& myCertificate,
-                      shared_ptr<Validator> validator,
-                      shared_ptr<Face> face,
-                      LogicUpdateCallback onUpdate,
-                      LogicRemoveCallback onRemove)
-  : m_state (new FullState)
-  , m_syncInterestTable (face->getIoService(), time::seconds(m_syncInterestReexpress))
-  , m_syncPrefix (syncPrefix)
-  , m_myCertificate(myCertificate)
-  , m_onUpdate (onUpdate)
-  , m_onRemove (onRemove)
-  , m_perBranch (false)
-  , m_validator(validator)
-  , m_face(face)
-  , m_scheduler(face->getIoService())
-  , m_randomGenerator (static_cast<unsigned int> (std::time (0)))
-  , m_rangeUniformRandom (m_randomGenerator, boost::uniform_int<> (200,1000))
-  , m_reexpressionJitter (m_randomGenerator, boost::uniform_int<> (100,500))
-  , m_recoveryRetransmissionInterval (m_defaultRecoveryRetransmitInterval)
-{
-  m_syncRegisteredPrefixId = m_face->setInterestFilter (m_syncPrefix,
-                                                        bind(&SyncLogic::onSyncInterest, this, _1, _2),
-                                                        bind(&SyncLogic::onSyncRegisterFailed, this, _1, _2));
-
-
-  m_reexpressingInterestId = m_scheduler.scheduleEvent (time::seconds (0), // no need to add jitter
-                                                        bind (&SyncLogic::sendSyncInterest, this));
-
-  m_instanceId = std::string("Instance " + boost::lexical_cast<std::string>(m_instanceCounter++) + " ");
-}
-
-SyncLogic::SyncLogic (const Name& syncPrefix,
-                      const IdentityCertificate& myCertificate,
-                      shared_ptr<Validator> validator,
-                      shared_ptr<Face> face,
-                      LogicPerBranchCallback onUpdateBranch)
-  : m_state (new FullState)
-  , m_syncInterestTable (face->getIoService(), time::seconds (m_syncInterestReexpress))
-  , m_syncPrefix (syncPrefix)
-  , m_myCertificate(myCertificate)
-  , m_onUpdateBranch (onUpdateBranch)
-  , m_perBranch(true)
-  , m_validator(validator)
-  , m_face(face)
-  , m_scheduler(face->getIoService())
-  , m_randomGenerator (static_cast<unsigned int> (std::time (0)))
-  , m_rangeUniformRandom (m_randomGenerator, boost::uniform_int<> (200,1000))
-  , m_reexpressionJitter (m_randomGenerator, boost::uniform_int<> (100,500))
-  , m_recoveryRetransmissionInterval (m_defaultRecoveryRetransmitInterval)
-{
-  m_syncRegisteredPrefixId = m_face->setInterestFilter (m_syncPrefix,
-                                                        bind(&SyncLogic::onSyncInterest, this, _1, _2),
-                                                        bind(&SyncLogic::onSyncRegisterFailed, this, _1, _2));
-
-  m_reexpressingInterestId = m_scheduler.scheduleEvent (time::seconds (0), // no need to add jitter
-                                                        bind (&SyncLogic::sendSyncInterest, this));
-}
-
-SyncLogic::~SyncLogic ()
-{
-  m_face->unsetInterestFilter(m_syncRegisteredPrefixId);
-  m_scheduler.cancelEvent (m_reexpressingInterestId);
-  m_scheduler.cancelEvent (m_delayedInterestProcessingId);
-}
-
-/**
- * Two types of intersts
- *
- * Normal name:    .../<hash>
- * Recovery name:  .../recovery/<hash>
- */
-boost::tuple<DigestConstPtr, std::string>
-SyncLogic::convertNameToDigestAndType (const Name &name)
-{
-  BOOST_ASSERT (m_syncPrefix.isPrefixOf(name));
-
-  int nameLengthDiff = name.size() - m_syncPrefix.size();
-  BOOST_ASSERT (nameLengthDiff > 0);
-  BOOST_ASSERT (nameLengthDiff < 3);
-
-  std::string hash = name.get(-1).toUri();
-  std::string interestType;
-
-  if(nameLengthDiff == 1)
-    interestType = "normal";
-  else
-    interestType = name.get(-2).toUri();
-
-  _LOG_DEBUG_ID (hash << ", " << interestType);
-
-  DigestPtr digest = boost::make_shared<Digest> ();
-  std::istringstream is (hash);
-  is >> *digest;
-
-  return make_tuple (digest, interestType);
-}
-
-void
-SyncLogic::onSyncInterest (const Name& prefix, const ndn::Interest& interest)
-{
-  Name name = interest.getName();
-
-  _LOG_DEBUG_ID("respondSyncInterest: " << name);
-
-  try
-    {
-      _LOG_DEBUG_ID ("<< I " << name);
-
-      if(name.get(m_syncPrefix.size()).toUri() == "CHRONOS-INTRO-CERT")
-        // it is a certificate, validator will take care of it.
-        return;
-
-      DigestConstPtr digest;
-      std::string type;
-      tie (digest, type) = convertNameToDigestAndType (name);
-
-      if (type == "normal") // kind of ineffective...
-        {
-          processSyncInterest (name, digest);
-        }
-      else if (type == "recovery")
-        {
-          processSyncRecoveryInterest (name, digest);
-        }
-    }
-  catch (Error::DigestCalculationError &e)
-    {
-      _LOG_DEBUG_ID ("Something fishy happened...");
-      // log error. ignoring it for now, later we should log it
-      return ;
-    }
-}
-
-void
-SyncLogic::onSyncRegisterFailed(const Name& prefix, const std::string& msg)
-{
-  _LOG_DEBUG_ID("Sync prefix registration failed! " << msg);
-}
-
-void
-SyncLogic::onSyncData(const ndn::Interest& interest, Data& data)
-{
-  OnDataValidated onValidated = bind(&SyncLogic::onSyncDataValidated, this, _1);
-  OnDataValidationFailed onValidationFailed = bind(&SyncLogic::onSyncDataValidationFailed, this, _1);
-  m_validator->validate(data, onValidated, onValidationFailed);
-}
-
-void
-SyncLogic::onSyncTimeout(const ndn::Interest& interest)
-{
-  // It is OK. Others will handle the time out situation.
-}
-
-void
-SyncLogic::onSyncDataValidationFailed(const shared_ptr<const Data>& data)
-{
-  _LOG_DEBUG_ID("Sync data cannot be verified!");
-}
-
-void
-SyncLogic::onSyncDataValidated(const shared_ptr<const Data>& data)
-{
-  Name name = data->getName();
-  const char* wireData = (const char*)data->getContent().value();
-  size_t len = data->getContent().value_size();
-
-  try
-    {
-      _LOG_DEBUG_ID ("<< D " << name);
-
-      DigestConstPtr digest;
-      std::string type;
-      tie (digest, type) = convertNameToDigestAndType (name);
-
-      if (type == "normal")
-        {
-          processSyncData (name, digest, wireData, len);
-        }
-      else
-        {
-          // timer is always restarted when we schedule recovery
-          m_scheduler.cancelEvent (m_reexpressingRecoveryInterestId);
-          processSyncData (name, digest, wireData, len);
-        }
-    }
-  catch (Error::DigestCalculationError &e)
-    {
-      _LOG_DEBUG_ID ("Something fishy happened...");
-      // log error. ignoring it for now, later we should log it
-      return;
-    }
-}
-
-void
-SyncLogic::processSyncInterest (const Name &name, DigestConstPtr digest, bool timedProcessing/*=false*/)
-{
-  _LOG_DEBUG_ID("processSyncInterest");
-  DigestConstPtr rootDigest;
-  {
-    rootDigest = m_state->getDigest();
-  }
-
-  // Special case when state is not empty and we have received request with zero-root digest
-  if (digest->isZero () && !rootDigest->isZero ())
-    {
-
-      SyncStateMsg ssm;
-      {
-        ssm << (*m_state);
-      }
-      sendSyncData (name, digest, ssm);
-      return;
-    }
-
-  if (*rootDigest == *digest)
-    {
-      _LOG_DEBUG_ID ("processSyncInterest (): Same state. Adding to PIT");
-      m_syncInterestTable.insert (digest, name.toUri(), false);
-      return;
-    }
-
-  DiffStateContainer::iterator stateInDiffLog = m_log.find (digest);
-
-  if (stateInDiffLog != m_log.end ())
-  {
-    DiffStateConstPtr stateDiff = (*stateInDiffLog)->diff ();
-
-    sendSyncData (name, digest, stateDiff);
-    return;
-  }
-
-  if (!timedProcessing)
-    {
-      bool exists = m_syncInterestTable.insert (digest, name.toUri(), true);
-      if (exists) // somebody else replied, so restart random-game timer
-        {
-          _LOG_DEBUG_ID ("Unknown digest, but somebody may have already replied, so restart our timer");
-          m_scheduler.cancelEvent (m_delayedInterestProcessingId);
-        }
-
-      uint32_t waitDelay = GET_RANDOM (m_rangeUniformRandom);
-      _LOG_DEBUG_ID ("Digest is not in the log. Schedule processing after small delay: " << time::milliseconds (waitDelay));
-
-      m_delayedInterestProcessingId = m_scheduler.scheduleEvent (time::milliseconds (waitDelay),
-                                                                 bind (&SyncLogic::processSyncInterest, this, name, digest, true));
-    }
-  else
-    {
-      _LOG_DEBUG_ID ("                                                      (timed processing)");
-
-      m_recoveryRetransmissionInterval = m_defaultRecoveryRetransmitInterval;
-      sendSyncRecoveryInterests (digest);
-    }
-}
-
-void
-SyncLogic::processSyncData (const Name &name, DigestConstPtr digest, const char *wireData, size_t len)
-{
-  DiffStatePtr diffLog = boost::make_shared<DiffState> ();
-  bool ownInterestSatisfied = false;
-
-  try
-    {
-
-      m_syncInterestTable.remove (name.toUri()); // Remove satisfied interest from PIT
-
-      ownInterestSatisfied = (name == m_outstandingInterestName);
-
-      DiffState diff;
-      SyncStateMsg msg;
-      if (!msg.ParseFromArray(wireData, len) || !msg.IsInitialized())
-      {
-        //Throw
-        BOOST_THROW_EXCEPTION (Error::SyncStateMsgDecodingFailure () );
-      }
-      msg >> diff;
-
-      std::vector<MissingDataInfo> v;
-      BOOST_FOREACH (LeafConstPtr leaf, diff.getLeaves().get<ordered>())
-        {
-          DiffLeafConstPtr diffLeaf = boost::dynamic_pointer_cast<const DiffLeaf> (leaf);
-          BOOST_ASSERT (diffLeaf != 0);
-
-          NameInfoConstPtr info = diffLeaf->getInfo();
-          if (diffLeaf->getOperation() == UPDATE)
-            {
-              SeqNo seq = diffLeaf->getSeq();
-
-              bool inserted = false;
-              bool updated = false;
-              SeqNo oldSeq;
-              {
-                boost::tie (inserted, updated, oldSeq) = m_state->update (info, seq);
-              }
-
-              if (inserted || updated)
-                {
-                  diffLog->update (info, seq);
-                  if (!oldSeq.isValid())
-                  {
-                    oldSeq = SeqNo(seq.getSession(), 0);
-                  }
-                  else
-                  {
-                    ++oldSeq;
-                  }
-                  // there is no need for application to process update on forwarder node
-                  if (info->toString() != forwarderPrefix)
-                  {
-                    MissingDataInfo mdi = {info->toString(), oldSeq, seq};
-                    {
-                      std::ostringstream interestName;
-                      interestName << mdi.prefix << "/" << mdi.high.getSession() << "/" << mdi.high.getSeq();
-                      _LOG_DEBUG_ID("+++++++++++++++ " + interestName.str());
-                    }
-                    if (m_perBranch)
-                    {
-                      std::ostringstream interestName;
-                      interestName << mdi.prefix << "/" << mdi.high.getSession() << "/" << mdi.high.getSeq();
-                      m_onUpdateBranch(interestName.str());
-                    }
-                    else
-                    {
-                      v.push_back(mdi);
-                    }
-                  }
-                }
-            }
-          else if (diffLeaf->getOperation() == REMOVE)
-            {
-              if (m_state->remove (info))
-                {
-                  diffLog->remove (info);
-                  if (!m_perBranch)
-                  {
-                    m_onRemove (info->toString ());
-                  }
-                }
-            }
-          else
-            {
-            }
-        }
-
-      if (!v.empty())
-      {
-        if (!m_perBranch)
-        {
-           m_onUpdate(v);
-        }
-      }
-
-      insertToDiffLog (diffLog);
-    }
-  catch (Error::SyncStateMsgDecodingFailure &e)
-    {
-      _LOG_DEBUG_ID ("Something really fishy happened during state decoding " <<
-                  diagnostic_information (e));
-      diffLog.reset ();
-      // don't do anything
-    }
-
-  if ((diffLog != 0 && diffLog->getLeaves ().size () > 0) ||
-      ownInterestSatisfied)
-    {
-      _LOG_DEBUG_ID(" +++++++++++++++ state changed!!!");
-      // Do it only if everything went fine and state changed
-
-      // this is kind of wrong
-      // satisfyPendingSyncInterests (diffLog); // if there are interests in PIT, there is a point to satisfy them using new state
-
-      // if state has changed, then it is safe to express a new interest
-      time::system_clock::Duration after = time::milliseconds(GET_RANDOM (m_reexpressionJitter));
-      // cout << "------------ reexpress interest after: " << after << endl;
-      EventId eventId = m_scheduler.scheduleEvent (after,
-                                                   bind (&SyncLogic::sendSyncInterest, this));
-
-      m_scheduler.cancelEvent (m_reexpressingInterestId);
-      m_reexpressingInterestId = eventId;
-    }
-}
-
-void
-SyncLogic::processSyncRecoveryInterest (const Name &name, DigestConstPtr digest)
-{
-  _LOG_DEBUG_ID("processSyncRecoveryInterest");
-  DiffStateContainer::iterator stateInDiffLog = m_log.find (digest);
-
-  if (stateInDiffLog == m_log.end ())
-    {
-      _LOG_DEBUG_ID ("Could not find " << *digest << " in digest log");
-      return;
-    }
-
-  SyncStateMsg ssm;
-  {
-    ssm << (*m_state);
-  }
-  sendSyncData (name, digest, ssm);
-}
-
-void
-SyncLogic::satisfyPendingSyncInterests (DiffStateConstPtr diffLog)
-{
-  DiffStatePtr fullStateLog = boost::make_shared<DiffState> ();
-  {
-    BOOST_FOREACH (LeafConstPtr leaf, m_state->getLeaves ()/*.get<timed> ()*/)
-      {
-        fullStateLog->update (leaf->getInfo (), leaf->getSeq ());
-        /// @todo Impose limit on how many state info should be send out
-      }
-  }
-
-  try
-    {
-      uint32_t counter = 0;
-      while (m_syncInterestTable.size () > 0)
-        {
-          Sync::Interest interest = m_syncInterestTable.pop ();
-
-          if (!interest.m_unknown)
-            {
-              _LOG_DEBUG_ID (">> D " << interest.m_name);
-              sendSyncData (interest.m_name, interest.m_digest, diffLog);
-            }
-          else
-            {
-              _LOG_DEBUG_ID (">> D (unknown)" << interest.m_name);
-              sendSyncData (interest.m_name, interest.m_digest, fullStateLog);
-            }
-          counter ++;
-        }
-      _LOG_DEBUG_ID ("Satisfied " << counter << " pending interests");
-    }
-  catch (Error::InterestTableIsEmpty &e)
-    {
-      // ok. not really an error
-    }
-}
-
-void
-SyncLogic::insertToDiffLog (DiffStatePtr diffLog)
-{
-  diffLog->setDigest (m_state->getDigest());
-  if (m_log.size () > 0)
-    {
-      m_log.get<sequenced> ().front ()->setNext (diffLog);
-    }
-  m_log.erase (m_state->getDigest()); // remove diff state with the same digest.  next pointers are still valid
-  /// @todo Optimization
-  m_log.get<sequenced> ().push_front (diffLog);
-}
-
-void
-SyncLogic::addLocalNames (const Name &prefix, uint64_t session, uint64_t seq)
-{
-  DiffStatePtr diff;
-  {
-    //cout << "Add local names" <<endl;
-    NameInfoConstPtr info = StdNameInfo::FindOrCreate(prefix.toUri());
-
-    _LOG_DEBUG_ID ("addLocalNames (): old state " << *m_state->getDigest ());
-
-    SeqNo seqN (session, seq);
-    m_state->update(info, seqN);
-
-    _LOG_DEBUG_ID ("addLocalNames (): new state " << *m_state->getDigest ());
-
-    diff = boost::make_shared<DiffState>();
-    diff->update(info, seqN);
-    insertToDiffLog (diff);
-  }
-
-  // _LOG_DEBUG_ID ("PIT size: " << m_syncInterestTable.size ());
-  satisfyPendingSyncInterests (diff);
-}
-
-void
-SyncLogic::remove(const Name &prefix)
-{
-  DiffStatePtr diff;
-  {
-    NameInfoConstPtr info = StdNameInfo::FindOrCreate(prefix.toUri());
-    m_state->remove(info);
-
-    // increment the sequence number for the forwarder node
-    NameInfoConstPtr forwarderInfo = StdNameInfo::FindOrCreate(forwarderPrefix);
-
-    LeafContainer::iterator item = m_state->getLeaves ().find (forwarderInfo);
-    SeqNo seqNo (0);
-    if (item != m_state->getLeaves ().end ())
-      {
-        seqNo = (*item)->getSeq ();
-        ++seqNo;
-      }
-    m_state->update (forwarderInfo, seqNo);
-
-    diff = boost::make_shared<DiffState>();
-    diff->remove(info);
-    diff->update(forwarderInfo, seqNo);
-
-    insertToDiffLog (diff);
-  }
-
-  satisfyPendingSyncInterests (diff);
-}
-
-void
-SyncLogic::sendSyncInterest ()
-{
-  _LOG_DEBUG_ID("sendSyncInterest");
-
-  {
-    m_outstandingInterestName = m_syncPrefix;
-    std::ostringstream os;
-    os << *m_state->getDigest();
-    m_outstandingInterestName.append(os.str());
-    _LOG_DEBUG_ID (">> I " << m_outstandingInterestName);
-  }
-
-  _LOG_DEBUG_ID("sendSyncInterest: " << m_outstandingInterestName);
-
-  EventId eventId = m_scheduler.scheduleEvent (time::seconds(m_syncInterestReexpress) + time::milliseconds(GET_RANDOM (m_reexpressionJitter)),
-                                               bind (&SyncLogic::sendSyncInterest, this));
-  m_scheduler.cancelEvent (m_reexpressingInterestId);
-  m_reexpressingInterestId = eventId;
-
-  ndn::Interest interest(m_outstandingInterestName);
-  interest.setMustBeFresh(true);
-
-  m_face->expressInterest(interest,
-                          bind(&SyncLogic::onSyncData, this, _1, _2),
-                          bind(&SyncLogic::onSyncTimeout, this, _1));
-}
-
-void
-SyncLogic::sendSyncRecoveryInterests (DigestConstPtr digest)
-{
-  std::ostringstream os;
-  os << *digest;
-
-  Name interestName = m_syncPrefix;
-  interestName.append("recovery").append(os.str());
-
-  time::system_clock::Duration nextRetransmission = time::milliseconds (m_recoveryRetransmissionInterval + GET_RANDOM (m_reexpressionJitter));
-
-  m_recoveryRetransmissionInterval <<= 1;
-
-  m_scheduler.cancelEvent (m_reexpressingRecoveryInterestId);
-  if (m_recoveryRetransmissionInterval < 100*1000) // <100 seconds
-    m_reexpressingRecoveryInterestId = m_scheduler.scheduleEvent (nextRetransmission,
-                                                                  bind (&SyncLogic::sendSyncRecoveryInterests, this, digest));
-
-  ndn::Interest interest(interestName);
-  interest.setMustBeFresh(true);
-
-  m_face->expressInterest(interest,
-                          bind(&SyncLogic::onSyncData, this, _1, _2),
-                          bind(&SyncLogic::onSyncTimeout, this, _1));
-}
-
-
-void
-SyncLogic::sendSyncData (const Name &name, DigestConstPtr digest, StateConstPtr state)
-{
-  SyncStateMsg msg;
-  msg << (*state);
-  sendSyncData(name, digest, msg);
-}
-
-// pass in state msg instead of state, so that there is no need to lock the state until
-// this function returns
-void
-SyncLogic::sendSyncData (const Name &name, DigestConstPtr digest, SyncStateMsg &ssm)
-{
-  _LOG_DEBUG_ID (">> D " << name);
-  int size = ssm.ByteSize();
-  char *wireData = new char[size];
-  ssm.SerializeToArray(wireData, size);
-
-  Data syncData(name);
-  syncData.setContent(reinterpret_cast<const uint8_t*>(wireData), size);
-  syncData.setFreshnessPeriod(time::milliseconds(m_syncResponseFreshness));
-
-  m_keyChain.sign(syncData, m_myCertificate.getName());
-
-  m_face->put(syncData);
-
-  delete []wireData;
-
-  // checking if our own interest got satisfied
-  bool satisfiedOwnInterest = false;
-  {
-    satisfiedOwnInterest = (m_outstandingInterestName == name);
-  }
-
-  if (satisfiedOwnInterest)
-    {
-      _LOG_DEBUG_ID ("Satisfied our own Interest. Re-expressing (hopefully with a new digest)");
-
-      time::system_clock::Duration after = time::milliseconds(GET_RANDOM (m_reexpressionJitter));
-      // cout << "------------ reexpress interest after: " << after << endl;
-      EventId eventId = m_scheduler.scheduleEvent (after,
-                                                   bind (&SyncLogic::sendSyncInterest, this));
-      m_scheduler.cancelEvent (m_reexpressingInterestId);
-      m_reexpressingInterestId = eventId;
-    }
-}
-
-std::string
-SyncLogic::getRootDigest()
-{
-  std::ostringstream os;
-  os << *m_state->getDigest();
-  return os.str();
-}
-
-size_t
-SyncLogic::getNumberOfBranches () const
-{
-  return m_state->getLeaves ().size ();
-}
-
-void
-SyncLogic::printState () const
-{
-  BOOST_FOREACH (const boost::shared_ptr<Sync::Leaf> leaf, m_state->getLeaves ())
-    {
-      std::cout << *leaf << std::endl;
-    }
-}
-
-std::map<std::string, bool>
-SyncLogic::getBranchPrefixes() const
-{
-  std::map<std::string, bool> m;
-
-  BOOST_FOREACH (const boost::shared_ptr<Sync::Leaf> leaf, m_state->getLeaves ())
-    {
-      std::string prefix = leaf->getInfo()->toString();
-      // do not return forwarder prefix
-      if (prefix != forwarderPrefix)
-      {
-        m.insert(std::pair<std::string, bool>(prefix, false));
-      }
-    }
-
-  return m;
-}
-
-}
diff --git a/src/sync-logic.h b/src/sync-logic.h
deleted file mode 100644
index 181979b..0000000
--- a/src/sync-logic.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (c) 2012-2014 University of California, Los Angeles
- *
- * This file is part of ChronoSync, synchronization library for distributed realtime
- * applications for NDN.
- *
- * ChronoSync 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.
- *
- * ChronoSync 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
- * ChronoSync, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
- * @author Chaoyi Bian <bcy@pku.edu.cn>
- * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
- * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/web/index.html>
- */
-
-#ifndef SYNC_LOGIC_H
-#define SYNC_LOGIC_H
-
-#include "boost-header.h"
-#include <memory>
-#include <map>
-
-#include <ndn-cxx/face.hpp>
-#include <ndn-cxx/security/validator.hpp>
-#include <ndn-cxx/security/key-chain.hpp>
-#include <ndn-cxx/util/scheduler.hpp>
-
-#include "sync-interest-table.h"
-#include "sync-diff-state.h"
-#include "sync-full-state.h"
-#include "sync-std-name-info.h"
-
-#include "sync-diff-state-container.h"
-
-#ifdef _DEBUG
-#ifdef HAVE_LOG4CXX
-#include <log4cxx/logger.h>
-#endif
-#endif
-
-namespace Sync {
-
-struct MissingDataInfo {
-  std::string prefix;
-  SeqNo low;
-  SeqNo high;
-};
-
-/**
- * \ingroup sync
- * @brief A wrapper for SyncApp, which handles ccnx related things (process
- * interests and data)
- */
-
-class SyncLogic
-{
-public:
-  //typedef boost::function< void ( const std::string &/*prefix*/, const SeqNo &/*newSeq*/, const SeqNo &/*oldSeq*/ ) > LogicUpdateCallback;
-  typedef boost::function< void (const std::vector<MissingDataInfo> & ) > LogicUpdateCallback;
-  typedef boost::function< void (const std::string &/*prefix*/ ) > LogicRemoveCallback;
-  typedef boost::function< void (const std::string &)> LogicPerBranchCallback;
-
-  SyncLogic (const ndn::Name& syncPrefix,
-             const ndn::IdentityCertificate& myCertificate,
-             ndn::shared_ptr<ndn::Validator> validator,
-             ndn::shared_ptr<ndn::Face> face,
-             LogicUpdateCallback onUpdate,
-             LogicRemoveCallback onRemove);
-
-  SyncLogic (const ndn::Name& syncPrefix,
-             const ndn::IdentityCertificate& myCertificate,
-             ndn::shared_ptr<ndn::Validator> validator,
-             ndn::shared_ptr<ndn::Face> face,
-             LogicPerBranchCallback onUpdateBranch);
-
-  ~SyncLogic ();
-
-  /**
-   * a wrapper for the same func in SyncApp
-   */
-  void addLocalNames (const ndn::Name &prefix, uint64_t session, uint64_t seq);
-
-  /**
-   * @brief remove a participant's subtree from the sync tree
-   * @param prefix the name prefix for the participant
-   */
-  void remove (const ndn::Name &prefix);
-
-  std::string
-  getRootDigest();
-
-#ifdef _DEBUG
-  ndn::Scheduler &
-  getScheduler () { return m_scheduler; }
-#endif
-
-  void
-  printState () const;
-
-  std::map<std::string, bool>
-  getBranchPrefixes() const;
-
-private:
-  void
-  delayedChecksLoop ();
-
-  void
-  onSyncInterest (const ndn::Name& prefix, const ndn::Interest& interest);
-
-  void
-  onSyncRegisterFailed(const ndn::Name& prefix, const std::string& msg);
-
-  void
-  onSyncData(const ndn::Interest& interest, ndn::Data& data);
-
-  void
-  onSyncTimeout(const ndn::Interest& interest);
-
-  void
-  onSyncDataValidationFailed(const ndn::shared_ptr<const ndn::Data>& data);
-
-  void
-  onSyncDataValidated(const ndn::shared_ptr<const ndn::Data>& data);
-
-  void
-  processSyncInterest (const ndn::Name &name,
-                       DigestConstPtr digest, bool timedProcessing=false);
-
-  void
-  processSyncData (const ndn::Name &name,
-                   DigestConstPtr digest, const char *wireData, size_t len);
-
-  void
-  processSyncRecoveryInterest (const ndn::Name &name,
-                               DigestConstPtr digest);
-
-  void
-  insertToDiffLog (DiffStatePtr diff);
-
-  void
-  satisfyPendingSyncInterests (DiffStateConstPtr diff);
-
-  boost::tuple<DigestConstPtr, std::string>
-  convertNameToDigestAndType (const ndn::Name &name);
-
-  void
-  sendSyncInterest ();
-
-  void
-  sendSyncRecoveryInterests (DigestConstPtr digest);
-
-  void
-  sendSyncData (const ndn::Name &name,
-                DigestConstPtr digest, StateConstPtr state);
-
-  void
-  sendSyncData (const ndn::Name &name,
-                DigestConstPtr digest, SyncStateMsg &msg);
-
-  size_t
-  getNumberOfBranches () const;
-
-private:
-  FullStatePtr m_state;
-  DiffStateContainer m_log;
-
-  ndn::Name m_outstandingInterestName;
-  SyncInterestTable m_syncInterestTable;
-
-  ndn::Name m_syncPrefix;
-  ndn::IdentityCertificate m_myCertificate;
-  LogicUpdateCallback m_onUpdate;
-  LogicRemoveCallback m_onRemove;
-  LogicPerBranchCallback m_onUpdateBranch;
-  bool m_perBranch;
-  ndn::shared_ptr<ndn::Validator> m_validator;
-  ndn::KeyChain m_keyChain;
-  ndn::shared_ptr<ndn::Face> m_face;
-  const ndn::RegisteredPrefixId* m_syncRegisteredPrefixId;
-
-  ndn::Scheduler m_scheduler;
-
-  boost::mt19937 m_randomGenerator;
-  boost::variate_generator<boost::mt19937&, boost::uniform_int<> > m_rangeUniformRandom;
-  boost::variate_generator<boost::mt19937&, boost::uniform_int<> > m_reexpressionJitter;
-
-  static const int m_unknownDigestStoreTime = 10; // seconds
-  static const int m_syncResponseFreshness; // MUST BE dividable by 1000!!!
-  static const int m_syncInterestReexpress; // seconds
-
-  static const int m_defaultRecoveryRetransmitInterval = 200; // milliseconds
-  uint32_t m_recoveryRetransmissionInterval; // milliseconds
-
-  ndn::EventId m_delayedInterestProcessingId;
-  ndn::EventId m_reexpressingInterestId;
-  ndn::EventId m_reexpressingRecoveryInterestId;
-
-  std::string m_instanceId;
-  static int m_instanceCounter;
-};
-
-
-} // Sync
-
-#endif // SYNC_APP_WRAPPER_H
diff --git a/src/sync-validator.cc b/src/sync-validator.cc
deleted file mode 100644
index e5cc0f5..0000000
--- a/src/sync-validator.cc
+++ /dev/null
@@ -1,240 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (c) 2012-2014 University of California, Los Angeles
- *
- * This file is part of ChronoSync, synchronization library for distributed realtime
- * applications for NDN.
- *
- * ChronoSync 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.
- *
- * ChronoSync 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
- * ChronoSync, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/web/index.html>
- */
-
-#include "sync-validator.h"
-#include "sync-logging.h"
-#include <ndn-cxx/security/certificate-cache-ttl.hpp>
-#include <queue>
-
-using namespace ndn;
-
-INIT_LOGGER ("SyncValidator")
-
-namespace Sync {
-
-using ndn::shared_ptr;
-
-const shared_ptr<CertificateCache> SyncValidator::DefaultCertificateCache = shared_ptr<CertificateCache>();
-const shared_ptr<SecRuleRelative> SyncValidator::DefaultDataRule = shared_ptr<SecRuleRelative>();
-
-SyncValidator::SyncValidator(const Name& prefix,
-                             const IdentityCertificate& anchor,
-                             Face& face,
-                             const PublishCertCallback& publishCertCallback,
-                             shared_ptr<SecRuleRelative> rule,
-                             shared_ptr<CertificateCache> certificateCache,
-                             const int stepLimit)
-  : Validator(face)
-  , m_prefix(prefix)
-  , m_anchor(anchor)
-  , m_stepLimit(stepLimit)
-  , m_certificateCache(certificateCache)
-  , m_publishCertCallback(publishCertCallback)
-  , m_dataRule(rule)
-{
-  if(!static_cast<bool>(m_certificateCache))
-    m_certificateCache = make_shared<CertificateCacheTtl>(boost::ref(m_face.getIoService()));
-
-  Name certPrefix = prefix;
-  certPrefix.append("CHRONOS-INTRO-CERT");
-  m_prefixId = m_face.setInterestFilter(certPrefix,
-                                         bind(&SyncValidator::onCertInterest, this, _1, _2),
-                                         bind(&SyncValidator::onCertRegisterFailed, this, _1, _2));
-
-  setAnchor(m_anchor);
-}
-
-void
-SyncValidator::deriveTrustNodes()
-{
-  std::queue<Name> nodeQueue;
-
-  // Clear existing trust nodes.
-  m_trustedNodes.clear();
-
-  // Add the trust anchor.
-  IntroNode origin(m_anchor);
-  m_trustedNodes[origin.name()] = m_anchor.getPublicKeyInfo();
-  nodeQueue.push(origin.name());
-
-  // BFS trusted nodes.
-  while(!nodeQueue.empty())
-    {
-      // Get next trusted node to process.
-      Nodes::const_iterator it = m_introNodes.find(nodeQueue.front());
-      const PublicKey& publicKey = m_trustedNodes[nodeQueue.front()];
-
-      if(it != m_introNodes.end())
-        {
-          // If the trusted node exists in the graph.
-          IntroNode::const_iterator eeIt = it->second.introduceeBegin();
-          IntroNode::const_iterator eeEnd = it->second.introduceeEnd();
-          for(; eeIt != eeEnd; eeIt++)
-            {
-              // Check the nodes introduced by the trusted node.
-              Edges::const_iterator edgeIt = m_introCerts.find(*eeIt);
-              if(edgeIt != m_introCerts.end()
-                 && m_trustedNodes.find(edgeIt->second.getIntroduceeCertName()) == m_trustedNodes.end()
-                 && verifySignature(edgeIt->second, publicKey))
-                {
-                  // If the introduced node can be validated, add it into trusted node set and the node queue.
-                  m_trustedNodes[edgeIt->second.getIntroduceeCertName()] = edgeIt->second.getIntroduceeCert().getPublicKeyInfo();
-                  nodeQueue.push(edgeIt->second.getIntroduceeCertName());
-                }
-            }
-        }
-      nodeQueue.pop();
-    }
-}
-
-void
-SyncValidator::checkPolicy (const Data& data,
-                            int stepCount,
-                            const OnDataValidated& onValidated,
-                            const OnDataValidationFailed& onValidationFailed,
-                            std::vector<shared_ptr<ValidationRequest> >& nextSteps)
-{
-  if(m_stepLimit == stepCount)
-    return onValidationFailed(data.shared_from_this(),
-                              "Maximum steps of validation reached: " + data.getName().toUri());
-
-  if(m_prefix.isPrefixOf(data.getName()) || (static_cast<bool>(m_dataRule) && m_dataRule->satisfy(data)))
-    {
-      try
-        {
-          SignatureSha256WithRsa sig(data.getSignature());
-          Name keyLocatorName = sig.getKeyLocator().getName();
-
-          TrustNodes::const_iterator it = m_trustedNodes.find(keyLocatorName);
-          if(m_trustedNodes.end() != it)
-            {
-              if(verifySignature(data, sig, it->second))
-                return onValidated(data.shared_from_this());
-              else
-                return onValidationFailed(data.shared_from_this(),
-                                          "Cannot verify signature: " + data.getName().toUri());
-            }
-          else
-            {
-              _LOG_DEBUG("I am: " << m_anchor.getName().get(0).toUri() << " for " << data.getName());
-
-              Name interestName = m_prefix;
-              interestName.append("CHRONOS-INTRO-CERT").append(keyLocatorName.wireEncode());
-              Interest interest(interestName);
-              interest.setInterestLifetime(time::milliseconds(500));
-
-              OnDataValidated onKeyValidated = bind(&SyncValidator::onCertificateValidated, this,
-                                                    _1, data.shared_from_this(), onValidated, onValidationFailed);
-
-              OnDataValidationFailed onKeyValidationFailed = bind(&SyncValidator::onCertificateValidationFailed, this,
-                                                                  _1, _2, data.shared_from_this(), onValidationFailed);
-
-              shared_ptr<ValidationRequest> nextStep = make_shared<ValidationRequest>(interest,
-                                                                                      onKeyValidated,
-                                                                                      onKeyValidationFailed,
-                                                                                      1,
-                                                                                      stepCount + 1);
-              nextSteps.push_back(nextStep);
-
-              return;
-            }
-        }
-      catch(SignatureSha256WithRsa::Error& e)
-        {
-          return onValidationFailed(data.shared_from_this(),
-                                    "Not SignatureSha256WithRsa signature: " + std::string(e.what()));
-        }
-      catch(KeyLocator::Error& e)
-        {
-          return onValidationFailed(data.shared_from_this(),
-                                    "Key Locator is not a name: " + data.getName().toUri());
-        }
-    }
-  else
-    return onValidationFailed(data.shared_from_this(),
-                              "No rule or rule is not satisfied: " + data.getName().toUri());
-}
-
-void
-SyncValidator::checkPolicy (const Interest& interest,
-                            int stepCount,
-                            const OnInterestValidated& onValidated,
-                            const OnInterestValidationFailed& onValidationFailed,
-                            std::vector<shared_ptr<ValidationRequest> >& nextSteps)
-{
-  onValidationFailed(interest.shared_from_this(),  "No policy for signed interest checking");
-}
-
-void
-SyncValidator::onCertificateValidated(const shared_ptr<const Data>& signCertificate,
-                                      const shared_ptr<const Data>& data,
-                                      const OnDataValidated& onValidated,
-                                      const OnDataValidationFailed& onValidationFailed)
-{
-  try
-    {
-      IntroCertificate introCert(*signCertificate);
-      addParticipant(introCert);
-
-      if(verifySignature(*data, introCert.getIntroduceeCert().getPublicKeyInfo()))
-        return onValidated(data);
-      else
-        return onValidationFailed(data,
-                                  "Cannot verify signature: " + data->getName().toUri());
-    }
-  catch(IntroCertificate::Error& e)
-    {
-      return onValidationFailed(data,
-                                "Intro cert decoding error: " + std::string(e.what()));
-    }
-}
-
-void
-SyncValidator::onCertificateValidationFailed(const shared_ptr<const Data>& signCertificate,
-                                             const std::string& failureInfo,
-                                             const shared_ptr<const Data>& data,
-                                             const OnDataValidationFailed& onValidationFailed)
-{
-  onValidationFailed(data, failureInfo);
-}
-
-void
-SyncValidator::onCertInterest(const Name& prefix, const Interest& interest)
-{
-  Name name = interest.getName();
-  Edges::const_iterator it = m_introCerts.begin();
-  for(; it != m_introCerts.end(); it++)
-    {
-      if(name.isPrefixOf(it->first))
-        {
-          m_face.put(it->second);
-          return;
-        }
-    }
-}
-
-void
-SyncValidator::onCertRegisterFailed(const Name& prefix, const std::string& msg)
-{
-  _LOG_DEBUG("SyncValidator::onCertRegisterFailed: " << msg);
-}
-
-} // namespace Sync
diff --git a/src/sync-validator.h b/src/sync-validator.h
deleted file mode 100644
index 9e5f4df..0000000
--- a/src/sync-validator.h
+++ /dev/null
@@ -1,341 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
-/*
- * Copyright (c) 2012-2014 University of California, Los Angeles
- *
- * This file is part of ChronoSync, synchronization library for distributed realtime
- * applications for NDN.
- *
- * ChronoSync 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.
- *
- * ChronoSync 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
- * ChronoSync, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/web/index.html>
- */
-
-#ifndef SYNC_VALIDATOR_H
-#define SYNC_VALIDATOR_H
-
-#include "sync-intro-certificate.h"
-#include <ndn-cxx/security/validator.hpp>
-#include <ndn-cxx/security/key-chain.hpp>
-#include <ndn-cxx/security/sec-rule-relative.hpp>
-#include <ndn-cxx/security/certificate-cache.hpp>
-#include <map>
-
-namespace Sync {
-
-class SyncValidator : public ndn::Validator
-{
-public:
-  typedef ndn::function< void (const uint8_t*, size_t, int) > PublishCertCallback;
-
-  struct Error : public ndn::Validator::Error { Error(const std::string &what) : ndn::Validator::Error(what) {} };
-
-  static const ndn::shared_ptr<ndn::CertificateCache> DefaultCertificateCache;
-  static const ndn::shared_ptr<ndn::SecRuleRelative> DefaultDataRule;
-
-  SyncValidator(const ndn::Name& prefix,
-                const ndn::IdentityCertificate& anchor,
-                ndn::Face& face,
-                const PublishCertCallback& publishCertCallback,
-                ndn::shared_ptr<ndn::SecRuleRelative> rule = DefaultDataRule,
-                ndn::shared_ptr<ndn::CertificateCache> certificateCache = DefaultCertificateCache,
-                const int stepLimit = 10);
-
-  virtual
-  ~SyncValidator()
-  {
-    m_face.unsetInterestFilter(m_prefixId);
-  }
-
-  /**
-   * @brief Set the trust anchor
-   *
-   * The anchor should be the participant's own certificate.
-   * This anchor node is the origin of the derived trust graph.
-   * Once the new anchor is set, derive the TrustNode set.
-   *
-   * @param anchor.
-   */
-  inline void
-  setAnchor(const ndn::IdentityCertificate& anchor);
-
-  /**
-   * @brief Add a node into the trust graph.
-   *
-   * The method also create an edge from trust anchor to the node.
-   *
-   * @param introducee.
-   * @return IntroCertificate for the introducee.
-   */
-  inline ndn::shared_ptr<const IntroCertificate>
-  addParticipant(const ndn::IdentityCertificate& introducee);
-
-  /**
-   * @brief Add an edge into the trust graph.
-   *
-   * Create nodes if it is one of the edge's ends and does not exist in the graph.
-   *
-   * @param introCert.
-   */
-  inline void
-  addParticipant(const IntroCertificate& introCert);
-
-  inline void
-  getIntroCertNames(std::vector<ndn::Name>& list);
-
-  inline const IntroCertificate&
-  getIntroCertificate(const ndn::Name& name);
-
-#ifdef _TEST
-  bool
-  canTrust(const ndn::Name& certName)
-  {
-    return (m_trustedNodes.find(certName.getPrefix(-1)) != m_trustedNodes.end());
-  }
-#endif //_DEBUG
-
-protected:
-  /***********************
-   * From ndn::Validator *
-   ***********************/
-  virtual void
-  checkPolicy (const ndn::Data& data,
-               int stepCount,
-               const ndn::OnDataValidated& onValidated,
-               const ndn::OnDataValidationFailed& onValidationFailed,
-               std::vector<ndn::shared_ptr<ndn::ValidationRequest> >& nextSteps);
-
-  virtual void
-  checkPolicy (const ndn::Interest& interest,
-               int stepCount,
-               const ndn::OnInterestValidated& onValidated,
-               const ndn::OnInterestValidationFailed& onValidationFailed,
-               std::vector<ndn::shared_ptr<ndn::ValidationRequest> >& nextSteps);
-private:
-  void
-  deriveTrustNodes();
-
-
-  void
-  onCertificateValidated(const ndn::shared_ptr<const ndn::Data>& signCertificate,
-                         const ndn::shared_ptr<const ndn::Data>& data,
-                         const ndn::OnDataValidated& onValidated,
-                         const ndn::OnDataValidationFailed& onValidationFailed);
-
-  void
-  onCertificateValidationFailed(const ndn::shared_ptr<const ndn::Data>& signCertificate,
-                                const std::string& failureInfo,
-                                const ndn::shared_ptr<const ndn::Data>& data,
-                                const ndn::OnDataValidationFailed& onValidationFailed);
-
-  void
-  onCertInterest (const ndn::Name& prefix, const ndn::Interest& interest);
-
-  void
-  onCertRegisterFailed(const ndn::Name& prefix, const std::string& msg);
-
-private:
-  class IntroNode;
-
-  // Syncprefix
-  ndn::Name m_prefix;
-
-  // The map
-  typedef std::map<const ndn::Name, IntroNode> Nodes;
-  typedef std::map<const ndn::Name, IntroCertificate> Edges;
-  Nodes m_introNodes;
-  Edges m_introCerts;
-
-  // The derived trust info
-  typedef std::map<const ndn::Name, ndn::PublicKey> TrustNodes;
-  ndn::IdentityCertificate m_anchor;
-  TrustNodes m_trustedNodes;
-
-  // others
-  int m_stepLimit;
-  ndn::shared_ptr<ndn::CertificateCache> m_certificateCache;
-  ndn::KeyChain m_keychain;
-  const ndn::RegisteredPrefixId* m_prefixId;
-  PublishCertCallback m_publishCertCallback;
-  ndn::shared_ptr<ndn::SecRuleRelative> m_dataRule;
-
-  class IntroNode
-  {
-  public:
-    typedef std::vector<ndn::Name>::const_iterator const_iterator;
-
-    IntroNode()
-    {}
-
-    IntroNode(const ndn::IdentityCertificate& idCert)
-      : m_nodeName(idCert.getName().getPrefix(-1))
-    {}
-
-    IntroNode(const IntroCertificate& introCert, bool isIntroducer)
-    {
-      if(isIntroducer)
-        {
-          m_nodeName = introCert.getIntroducerCertName();
-          m_introduceeCerts.push_back(introCert.getName());
-        }
-      else
-        {
-          m_nodeName = introCert.getIntroduceeCertName();
-          m_introducerCerts.push_back(introCert.getName());
-        }
-    }
-
-    ~IntroNode()
-    {}
-
-    const ndn::Name&
-    name() const
-    {
-      return m_nodeName;
-    }
-
-    const_iterator
-    introducerBegin() const
-    {
-      return m_introducerCerts.begin();
-    }
-
-    const_iterator
-    introducerEnd() const
-    {
-      return m_introducerCerts.end();
-    }
-
-    const_iterator
-    introduceeBegin() const
-    {
-      return m_introduceeCerts.begin();
-    }
-
-    const_iterator
-    introduceeEnd() const
-    {
-      return m_introduceeCerts.end();
-    }
-
-    void
-    addIntroCertAsIntroducer(const ndn::Name& introCertName)
-    {
-      if(std::find(m_introduceeCerts.begin(), m_introduceeCerts.end(), introCertName) == m_introduceeCerts.end())
-        m_introduceeCerts.push_back(introCertName);
-    }
-
-    void
-    addIntroCertAsIntroducee(const ndn::Name& introCertName)
-    {
-      if(std::find(m_introducerCerts.begin(), m_introducerCerts.end(), introCertName) == m_introducerCerts.end())
-        m_introducerCerts.push_back(introCertName);
-    }
-
-  private:
-    ndn::Name m_nodeName;
-    std::vector<ndn::Name> m_introducerCerts;
-    std::vector<ndn::Name> m_introduceeCerts;
-  };
-
-};
-
-inline void
-SyncValidator::setAnchor(const ndn::IdentityCertificate& anchor)
-{
-  m_anchor = anchor;
-
-  // Add anchor into trust graph if it does not exist.
-  IntroNode origin(m_anchor);
-  Nodes::const_iterator nodeIt = m_introNodes.find(origin.name());
-  if(nodeIt == m_introNodes.end())
-    m_introNodes[origin.name()] = origin;
-
-  deriveTrustNodes();
-}
-
-inline void
-SyncValidator::addParticipant(const IntroCertificate& introCert)
-{
-  // Check if the edge has been added before.
-  ndn::Name certName = introCert.getName();
-  Edges::const_iterator edgeIt = m_introCerts.find(certName);
-  if(edgeIt != m_introCerts.end())
-    return; // the edge has been added before.
-
-  m_introCerts[certName] = introCert;
-
-  // Check if the introducer has been added.
-  Nodes::iterator nodeIt = m_introNodes.find(introCert.getIntroducerCertName());
-  if(nodeIt == m_introNodes.end())
-    {
-      IntroNode node(introCert, true);
-      m_introNodes[node.name()] = node;
-    }
-  else
-    nodeIt->second.addIntroCertAsIntroducer(certName);
-
-  // Check if the introducee has been added.
-  nodeIt = m_introNodes.find(introCert.getIntroduceeCertName());
-  if(nodeIt == m_introNodes.end())
-    {
-      IntroNode node(introCert, false);
-      m_introNodes[node.name()] = node;
-    }
-  else
-    nodeIt->second.addIntroCertAsIntroducee(certName);
-
-  // Check if the introducer is one of the trusted nodes.
-  TrustNodes::const_iterator trustNodeIt = m_trustedNodes.find(introCert.getIntroducerCertName());
-  if(trustNodeIt != m_trustedNodes.end() && verifySignature(introCert, trustNodeIt->second))
-    // If the introducee, add it into trusted node set.
-    m_trustedNodes[introCert.getIntroduceeCertName()] = introCert.getIntroduceeCert().getPublicKeyInfo();
-}
-
-inline ndn::shared_ptr<const IntroCertificate>
-SyncValidator::addParticipant(const ndn::IdentityCertificate& introducee)
-{
-  ndn::shared_ptr<IntroCertificate> introCert
-    = ndn::shared_ptr<IntroCertificate>(new IntroCertificate(m_prefix, introducee, m_anchor.getName().getPrefix(-1)));
-
-  m_keychain.sign(*introCert, m_anchor.getName());
-
-  addParticipant(*introCert);
-
-  // Publish certificate as normal data.
-  ndn::Block block = introCert->wireEncode();
-  m_publishCertCallback(block.wire(), block.size(), 1000);
-
-  return introCert;
-}
-
-inline void
-SyncValidator::getIntroCertNames(std::vector<ndn::Name>& list)
-{
-  Edges::const_iterator it = m_introCerts.begin();
-  Edges::const_iterator end = m_introCerts.end();
-  for(; it != end; it++)
-    list.push_back(it->first);
-}
-
-inline const IntroCertificate&
-SyncValidator::getIntroCertificate(const ndn::Name& name)
-{
-  Edges::const_iterator it = m_introCerts.find(name);
-  if(it != m_introCerts.end())
-    return it->second;
-  else
-    throw Error("No cert");
-}
-
-} // namespace Sync
-
-#endif //SYNC_VALIDATOR_H