Fix socket

Change-Id: I0076010933c0edd3f5a0960ca55e02e5fff809be
diff --git a/src/socket.cpp b/src/socket.cpp
new file mode 100644
index 0000000..55296ab
--- /dev/null
+++ b/src/socket.cpp
@@ -0,0 +1,150 @@
+/* -*- 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 "socket.hpp"
+#include "logger.hpp"
+
+INIT_LOGGER("Socket");
+
+
+namespace chronosync {
+
+Socket::Socket(const Name& syncPrefix,
+               const Name& userPrefix,
+               ndn::Face& face,
+               const UpdateCallback& updateCallback)
+  : m_userPrefix(userPrefix)
+  , m_face(face)
+  , m_logic(face,
+            syncPrefix,
+            userPrefix,
+            updateCallback)
+{
+}
+
+
+void
+Socket::publishData(const uint8_t* buf, size_t len, const ndn::time::milliseconds& freshness)
+{
+  publishData(ndn::dataBlock(ndn::tlv::Content, buf, len), freshness);
+}
+
+void
+Socket::publishData(const Block& content, const ndn::time::milliseconds& freshness)
+{
+  shared_ptr<Data> data = make_shared<Data>();
+  data->setContent(content);
+  data->setFreshnessPeriod(freshness);
+
+  SeqNo newSeq = m_logic.getSeqNo() + 1;
+  Name dataName;
+  dataName.append(m_logic.getSessionName()).appendNumber(newSeq);
+  data->setName(dataName);
+
+  m_keyChain.sign(*data);
+
+  m_face.put(*data);
+
+  m_logic.updateSeqNo(newSeq);
+}
+
+void
+Socket::fetchData(const Name& sessionName, const SeqNo& seqNo,
+                  const ndn::OnDataValidated& dataCallback,
+                  int nRetries)
+{
+  Name interestName;
+  interestName.append(sessionName).appendNumber(seqNo);
+
+  Interest interest(interestName);
+  interest.setMustBeFresh(true);
+
+  ndn::OnDataValidationFailed failureCallback =
+    bind(&Socket::onDataValidationFailed, this, _1, _2);
+
+  m_face.expressInterest(interest,
+                         bind(&Socket::onData, this, _1, _2, dataCallback, failureCallback),
+                         bind(&Socket::onDataTimeout, this, _1, nRetries,
+                              dataCallback, failureCallback));
+}
+
+void
+Socket::fetchData(const Name& sessionName, const SeqNo& seqNo,
+                  const ndn::OnDataValidated& dataCallback,
+                  const ndn::OnDataValidationFailed& failureCallback,
+                  const ndn::OnTimeout& onTimeout,
+                  int nRetries)
+{
+  _LOG_DEBUG(">> Socket::fetchData");
+  Name interestName;
+  interestName.append(sessionName).appendNumber(seqNo);
+
+  Interest interest(interestName);
+  interest.setMustBeFresh(true);
+
+  m_face.expressInterest(interest,
+                         bind(&Socket::onData, this, _1, _2, dataCallback, failureCallback),
+                         onTimeout);
+
+  _LOG_DEBUG("<< Socket::fetchData");
+}
+
+void
+Socket::onData(const Interest& interest, Data& data,
+               const ndn::OnDataValidated& onValidated,
+               const ndn::OnDataValidationFailed& onFailed)
+{
+  _LOG_DEBUG("Socket::onData");
+  // Placeholder for validator
+  onValidated(data.shared_from_this());
+}
+
+void
+Socket::onDataTimeout(const Interest& interest, int nRetries,
+                      const ndn::OnDataValidated& onValidated,
+                      const ndn::OnDataValidationFailed& onFailed)
+{
+  _LOG_DEBUG("Socket::onDataTimeout");
+  if (nRetries <= 0)
+    return;
+
+  m_face.expressInterest(interest,
+                         bind(&Socket::onData, this, _1, _2, onValidated, onFailed),
+                         bind(&Socket::onDataTimeout, this, _1, nRetries - 1,
+                              onValidated, onFailed));
+}
+
+void
+Socket::onDataValidationFailed(const shared_ptr<const Data>& data,
+                               const std::string& failureInfo)
+{
+}
+
+ndn::ConstBufferPtr
+Socket::getRootDigest() const
+{
+  return m_logic.getRootDigest();
+}
+
+} // namespace chronosync
diff --git a/src/socket.hpp b/src/socket.hpp
new file mode 100644
index 0000000..11dc684
--- /dev/null
+++ b/src/socket.hpp
@@ -0,0 +1,158 @@
+/* -*- 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_SOCKET_HPP
+#define CHRONOSYNC_SOCKET_HPP
+
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/security/validation-request.hpp>
+
+#include "logic.hpp"
+
+namespace chronosync {
+
+/**
+ * @brief A simple interface to interact with client code
+ *
+ * Though it is called Socket, it is not a real socket. It just trying to provide
+ * a simplified interface for data publishing and fetching.
+ *
+ * This interface simplify data publishing.  Client can simply dump raw data
+ * into this interface without handling the ChronoSync specific details, such
+ * as sequence number and session id.
+ *
+ * This interface also simplify data fetching.  Client only needs to provide a
+ * data fetching strategy (through a updateCallback).
+ */
+class Socket : noncopyable
+{
+public:
+  class Error : public std::runtime_error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
+  };
+
+  Socket(const Name& syncPrefix,
+         const Name& userPrefix,
+         ndn::Face& face,
+         const UpdateCallback& updateCallback);
+
+  /**
+   * @brief Publish a data packet in the session and trigger synchronization updates
+   *
+   * This method will create a data packet with the supplied content.
+   * The packet name is the local session + seqNo.
+   * The seqNo is automatically maintained by internal Logic.
+   *
+   * @param buf Pointer to the bytes in content
+   * @param len size of the bytes in content
+   * @param freshness FreshnessPeriod of the data packet.
+   */
+  void
+  publishData(const uint8_t* buf, size_t len, const ndn::time::milliseconds& freshness);
+
+  /**
+   * @brief Publish a data packet in the session and trigger synchronization updates
+   *
+   * This method will create a data packet with the supplied content.
+   * The packet name is the local session + seqNo.
+   * The seqNo is automatically maintained by internal Logic.
+   *
+   * @param content Block that will be set as the content of the data packet.
+   * @param freshness FreshnessPeriod of the data packet.
+   */
+  void
+  publishData(const Block& content, const ndn::time::milliseconds& freshness);
+
+  /**
+   * @brief Retrive a data packet with a particular seqNo from a session
+   *
+   * @param sessionName The name of the target session.
+   * @param seq The seqNo of the data packet.
+   * @param onValidated The callback when the retrieved packet has been validated.
+   * @param nRetries The number of retries.
+   */
+  void
+  fetchData(const Name& sessionName, const SeqNo& seq,
+            const ndn::OnDataValidated& onValidated,
+            int nRetries = 0);
+
+  /**
+   * @brief Retrive a data packet with a particular seqNo from a session
+   *
+   * @param sessionName The name of the target session.
+   * @param seq The seqNo of the data packet.
+   * @param onValidated The callback when the retrieved packet has been validated.
+   * @param nRetries The number of retries.
+   */
+  void
+  fetchData(const Name& sessionName, const SeqNo& seq,
+            const ndn::OnDataValidated& onValidated,
+            const ndn::OnDataValidationFailed& onValidationFailed,
+            const ndn::OnTimeout& onTimeout,
+            int nRetries = 0);
+
+  /// @brief Get the root digest of current sync tree
+  ndn::ConstBufferPtr
+  getRootDigest() const;
+
+  Logic&
+  getLogic()
+  {
+    return m_logic;
+  }
+
+private:
+  void
+  onData(const Interest& interest, Data& data,
+         const ndn::OnDataValidated& dataCallback,
+         const ndn::OnDataValidationFailed& failCallback);
+
+  void
+  onDataTimeout(const Interest& interest, int nRetries,
+                const ndn::OnDataValidated& dataCallback,
+                const ndn::OnDataValidationFailed& failCallback);
+
+  void
+  onDataValidationFailed(const shared_ptr<const Data>& data,
+                         const std::string& failureInfo);
+
+private:
+
+  Name m_userPrefix;
+  ndn::Face& m_face;
+
+  Logic m_logic;
+
+  ndn::KeyChain m_keyChain;
+};
+
+} // namespace chronosync
+
+#endif // CHRONOSYNC_SOCKET_HPP
diff --git a/src/sync-socket.cc b/src/sync-socket.cc
deleted file mode 100644
index b344a3e..0000000
--- a/src/sync-socket.cc
+++ /dev/null
@@ -1,245 +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>
- * @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>
- */
-
-#include "sync-socket.h"
-#include "sync-logging.h"
-
-using namespace ndn;
-
-INIT_LOGGER ("SyncSocket")
-
-namespace Sync {
-
-using ndn::shared_ptr;
-
-static const uint8_t ROUTING_PREFIX_SEPARATOR[2] = {0xF0, 0x2E};
-
-const Name SyncSocket::EMPTY_NAME = Name();
-
-SyncSocket::SyncSocket (const Name& syncPrefix,
-                        const Name& dataPrefix,
-                        uint64_t dataSession,
-                        bool withRoutingPrefix,
-                        const Name& routingPrefix,
-                        shared_ptr<Face> face,
-                        const IdentityCertificate& myCertificate,
-                        shared_ptr<SecRuleRelative> dataRule,
-                        NewDataCallback dataCallback,
-                        RemoveCallback rmCallback )
-  : m_dataPrefix(dataPrefix)
-  , m_dataSession(dataSession)
-  , m_withRoutingPrefix(false)
-  , m_newDataCallback(dataCallback)
-  , m_myCertificate(myCertificate)
-  , m_face(face)
-  , m_ioService(face->getIoService())
-{
-  if(withRoutingPrefix && !routingPrefix.isPrefixOf(m_dataPrefix))
-    {
-      m_withRoutingPrefix = true;
-      m_routableDataPrefix.append(routingPrefix).append(ROUTING_PREFIX_SEPARATOR, 2).append(m_dataPrefix);
-    }
-
-
-  if(static_cast<bool>(dataRule))
-    {
-      m_withSecurity = true;
-      m_syncValidator = shared_ptr<Validator>(new SyncValidator(syncPrefix,
-                                                                m_myCertificate,
-                                                                *m_face,
-                                                                bind(&SyncSocket::publishData, this, _1, _2, _3, true),
-                                                                dataRule));
-    }
-  else
-    {
-      m_withSecurity = false;
-      m_syncValidator = shared_ptr<Validator>(new ValidatorNull());
-    }
-
-
-  m_syncLogic = shared_ptr<SyncLogic>(new SyncLogic(syncPrefix,
-                                                    myCertificate,
-                                                    m_syncValidator,
-                                                    m_face,
-                                                    bind(&SyncSocket::passCallback, this, _1),
-                                                    rmCallback));
-}
-
-SyncSocket::~SyncSocket()
-{
-}
-
-void
-SyncSocket::publishData(const uint8_t* buf, size_t len, int freshness, bool isCert)
-{
-  shared_ptr<Data> data = make_shared<Data>();
-  data->setContent(reinterpret_cast<const uint8_t*>(buf), len);
-  data->setFreshnessPeriod(time::milliseconds(1000*freshness));
-
-  m_ioService.post(bind(&SyncSocket::publishDataInternal, this,
-                        data, isCert));
-}
-
-void
-SyncSocket::publishDataInternal(shared_ptr<Data> data, bool isCert)
-{
-  Name dataPrefix = (m_withRoutingPrefix ? m_routableDataPrefix : m_dataPrefix);
-
-  uint64_t sequence = getNextSeq();
-
-  Name dataName;
-  dataName.append(m_dataPrefix)
-    .append(boost::lexical_cast<std::string>(m_dataSession))
-    .append(boost::lexical_cast<std::string>(sequence));
-  if(isCert)
-    dataName.append("INTRO-CERT");
-  data->setName(dataName);
-  m_keyChain.sign(*data, m_myCertificate.getName());
-
-  if(m_withRoutingPrefix)
-    {
-      Name wrappedName;
-      wrappedName.append(m_routableDataPrefix)
-        .append(boost::lexical_cast<std::string>(m_dataSession))
-        .append(boost::lexical_cast<std::string>(sequence));
-
-      Data wrappedData(wrappedName);
-      wrappedData.setContent(data->wireEncode());
-      m_keyChain.sign(wrappedData, m_myCertificate.getName());
-
-      m_face->put(wrappedData);
-    }
-  else
-    {
-      m_face->put(*data);
-    }
-
-  SeqNo s(m_dataSession, sequence + 1);
-  m_sequenceLog[dataPrefix] = s;
-  m_syncLogic->addLocalNames (dataPrefix, m_dataSession, sequence); // If DNS works, we should use pure m_dataprefix rather than the one with routing prefix.
-}
-
-void
-SyncSocket::fetchData(const Name& prefix, const SeqNo& seq, const OnDataValidated& dataCallback, int retry)
-{
-  Name interestName = prefix;
-  interestName.append(boost::lexical_cast<std::string>(seq.getSession())).append(boost::lexical_cast<std::string>(seq.getSeq()));
-
-  ndn::Interest interest(interestName);
-  interest.setMustBeFresh(true);
-
-  m_face->expressInterest(interest,
-                          bind(&SyncSocket::onData, this, _1, _2, dataCallback),
-                          bind(&SyncSocket::onDataTimeout, this, _1, retry, dataCallback));
-
-}
-
-void
-SyncSocket::onData(const ndn::Interest& interest, Data& data, const OnDataValidated& dataCallback)
-{
-  bool encaped = false;
-
-  Name interestName = interest.getName();
-  Name::const_iterator it = interestName.begin();
-  Name::const_iterator end = interestName.end();
-
-  size_t offset = interestName.size();
-  for(; it != end; it++)
-    {
-      offset--;
-      if(it->toUri() == "%F0.")
-        {
-          encaped = true;
-          break;
-        }
-    }
-
-  if(!encaped)
-    offset = interestName.size();
-
-  const OnDataValidated& onValidated = bind(&SyncSocket::onDataValidated, this, _1, offset, dataCallback);
-  const OnDataValidationFailed& onValidationFailed = bind(&SyncSocket::onDataValidationFailed, this, _1, _2);
-
-  if(encaped)
-    {
-      shared_ptr<Data> innerData = make_shared<Data>();
-      innerData->wireDecode(data.getContent().blockFromValue());
-      m_syncValidator->validate(*innerData, onValidated, onValidationFailed);
-    }
-  else
-    m_syncValidator->validate(data, onValidated, onValidationFailed);
-}
-
-void
-SyncSocket::onDataTimeout(const ndn::Interest& interest, int retry, const OnDataValidated& dataCallback)
-{
-  if(retry > 0)
-    {
-      m_face->expressInterest(interest,
-                              bind(&SyncSocket::onData,
-                                   this,
-                                   _1,
-                                   _2,
-                                   dataCallback),
-                              bind(&SyncSocket::onDataTimeout,
-                                   this,
-                                   _1,
-                                   retry - 1,
-                                   dataCallback));
-
-    }
-  else
-    _LOG_DEBUG("interest eventually time out!");
-}
-
-void
-SyncSocket::onDataValidated(const shared_ptr<const Data>& data,
-                            size_t interestNameSize,
-                            const OnDataValidated& onValidated)
-{
-  if(data->getName().size() > interestNameSize
-     && data->getName().get(interestNameSize).toUri() == "INTRO-CERT")
-    {
-      if(!m_withSecurity)
-        return;
-
-      Data rawData;
-      rawData.wireDecode(data->getContent().blockFromValue());
-      IntroCertificate introCert(rawData);
-      dynamic_pointer_cast<SyncValidator>(m_syncValidator)->addParticipant(introCert);
-    }
-  else
-    {
-      onValidated(data);
-    }
-}
-
-void
-SyncSocket::onDataValidationFailed(const shared_ptr<const Data>& data,
-                                   const std::string& failureInfo)
-{
-  _LOG_DEBUG("data cannot be verified!: " << failureInfo);
-}
-
-}//Sync
diff --git a/src/sync-socket.h b/src/sync-socket.h
deleted file mode 100644
index 5e66ac6..0000000
--- a/src/sync-socket.h
+++ /dev/null
@@ -1,204 +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>
- * @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_SOCKET_H
-#define _SYNC_SOCKET_H
-
-#include <ndn-cxx/face.hpp>
-#include <ndn-cxx/security/validator.hpp>
-#include <ndn-cxx/security/validator-null.hpp>
-#include <ndn-cxx/security/key-chain.hpp>
-
-#include "sync-logic.h"
-#include "sync-seq-no.h"
-#include "sync-validator.h"
-
-#include <utility>
-#include <map>
-#include <vector>
-#include <sstream>
-
-namespace Sync {
-
-/**
- * \ingroup sync
- * @brief A simple interface to interact with client code
- */
-class SyncSocket
-{
-public:
-  struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
-
-  typedef ndn::function< void (const std::vector<MissingDataInfo> &, SyncSocket * ) > NewDataCallback;
-  typedef ndn::function< void (const std::string &/*prefix*/ ) > RemoveCallback;
-
-  static const ndn::Name EMPTY_NAME;
-
-  SyncSocket(const ndn::Name& syncPrefix,
-             const ndn::Name& dataPrefix,
-             uint64_t dataSession,
-             bool withRoutingPrefix,
-             const ndn::Name& routingPrefix,
-             ndn::shared_ptr<ndn::Face> face,
-             const ndn::IdentityCertificate& myCertificate,
-             ndn::shared_ptr<ndn::SecRuleRelative> dataRule,
-             NewDataCallback dataCallback,
-             RemoveCallback rmCallback);
-
-  ~SyncSocket();
-
-  void
-  publishData(const uint8_t* buf, size_t len, int freshness, bool isCert = false);
-
-  void
-  leave()
-  {
-    m_syncLogic->remove(m_withRoutingPrefix ? m_routableDataPrefix : m_dataPrefix);
-  }
-
-  void
-  remove(const ndn::Name& prefix)
-  {
-    m_syncLogic->remove(prefix);
-  }
-
-  void
-  fetchData(const ndn::Name &prefix, const SeqNo &seq, const ndn::OnDataValidated& onValidated, int retry = 0);
-
-  std::string
-  getRootDigest()
-  {
-    return m_syncLogic->getRootDigest();
-  }
-
-  uint64_t
-  getNextSeq()
-  {
-    // If DNS works, we should use pure m_dataprefix rather than the one with routing prefix.
-    SequenceLog::iterator i = m_sequenceLog.find (m_withRoutingPrefix ? m_routableDataPrefix : m_dataPrefix);
-
-    if (i != m_sequenceLog.end ())
-      {
-        SeqNo s = i->second;
-        if (s.getSession() == m_dataSession)
-          return s.getSeq();
-      }
-    return 0;
-  }
-
-  SyncLogic &
-  getLogic()
-  {
-    return *m_syncLogic;
-  }
-
-  void
-  addParticipant(const ndn::IdentityCertificate& introducee)
-  {
-    if(m_withSecurity)
-      {
-        ndn::dynamic_pointer_cast<SyncValidator>(m_syncValidator)->addParticipant(introducee);
-      }
-  }
-
-  void
-  addParticipant(const IntroCertificate& introCert)
-  {
-    if(m_withSecurity)
-      {
-        ndn::dynamic_pointer_cast<SyncValidator>(m_syncValidator)->addParticipant(introCert);
-      }
-  }
-
-  void
-  getIntroCertNames(std::vector<ndn::Name>& list)
-  {
-    if(m_withSecurity)
-      {
-        ndn::dynamic_pointer_cast<SyncValidator>(m_syncValidator)->getIntroCertNames(list);
-      }
-  }
-
-  const IntroCertificate&
-  getIntroCertificate(const ndn::Name& name)
-  {
-    if(m_withSecurity)
-      {
-        return ndn::dynamic_pointer_cast<SyncValidator>(m_syncValidator)->getIntroCertificate(name);
-      }
-    throw Error("You are running SyncSocket without security!");
-  }
-
-  // // make this a static function so we don't have to create socket instance without
-  // // knowing the local prefix. it's a wrong place for this function anyway
-  // static std::string
-  // GetLocalPrefix ();
-
-private:
-  void
-  publishDataInternal(ndn::shared_ptr<ndn::Data> data, bool isCert);
-
-  void
-  passCallback(const std::vector<MissingDataInfo> &v)
-  {
-    m_newDataCallback(v, this);
-  }
-
-  void
-  onData(const ndn::Interest& interest, ndn::Data& data, const ndn::OnDataValidated& dataCallback);
-
-  void
-  onDataTimeout(const ndn::Interest& interest, int retry, const ndn::OnDataValidated& dataCallback);
-
-
-  void
-  onDataValidated(const ndn::shared_ptr<const ndn::Data>& data,
-                  size_t interestNameSize,
-                  const ndn::OnDataValidated& onValidated);
-
-  void
-  onDataValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
-                         const std::string& failureInfo);
-
-private:
-  typedef std::map<ndn::Name, SeqNo> SequenceLog;
-
-  ndn::Name m_dataPrefix;
-  uint64_t m_dataSession;
-  ndn::Name m_routableDataPrefix;
-  bool m_withRoutingPrefix;
-  NewDataCallback m_newDataCallback;
-  SequenceLog m_sequenceLog;
-  ndn::IdentityCertificate m_myCertificate;
-  ndn::KeyChain m_keyChain;
-  ndn::shared_ptr<ndn::Face> m_face;
-  boost::asio::io_service& m_ioService;
-  bool m_withSecurity;
-  ndn::shared_ptr<ndn::Validator> m_syncValidator;
-  ndn::shared_ptr<SyncLogic>      m_syncLogic;
-};
-
-} // Sync
-
-#endif // SYNC_SOCKET_H
diff --git a/tests/integrated-tests/test-data-fetch-and-publish.cpp.outdated b/tests/integrated-tests/test-data-fetch-and-publish.cpp.outdated
deleted file mode 100644
index 583717c..0000000
--- a/tests/integrated-tests/test-data-fetch-and-publish.cpp.outdated
+++ /dev/null
@@ -1,108 +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/>.
- */
-
-/*
-#include <boost/test/unit_test.hpp>
-#include <boost/test/output_test_stream.hpp>
-#include <map>
-using boost::test_tools::output_test_stream;
-
-#include <boost/make_shared.hpp>
-
-#include "sync-ccnx-wrapper.h"
-#include "sync-app-data-fetch.h"
-#include "sync-app-data-publish.h"
-
-using namespace Sync;
-using namespace std;
-using namespace boost;
-
-class TestStructApp {
-public:
-  map<string, string> data;
-  void set(string str1, string str2) {
-    data.insert(make_pair(str1, str2));
-  }
-
-  void erase(string str1, string str2) {
-    data.erase(str1);
-  }
-
-  string toString(){
-    map<string, string>::iterator it = data.begin();
-    string str = "";
-    for (; it != data.end(); ++it){
-      str += "<";
-      str += it->first;
-      str += "|";
-      str += it->second;
-      str += ">";
-    }
-    return str;
-  }
-
-};
-
-BOOST_AUTO_TEST_CASE (AppDataPublishAndFetchTest)
-{
-  TestStructApp foo;
-  TestStructApp bar;
-
-  string interest = "/april/fool";
-  string seq[5] = {"0", "1", "2", "3", "4" };
-  string str[5] = {"panda", "express", "tastes", "so", "good"};
-
-  for (int i = 0; i < 5; i++) {
-    foo.set(interest + "/" + "0/" + seq[i], str[i]);
-  }
-
-  boost::function<void (string, string)> setFunc =
-    bind(&TestStructApp::set, &bar, _1, _2);
-
-  shared_ptr<CcnxWrapper> handle(new CcnxWrapper());
-
-  AppDataFetch fetcher(handle, setFunc);
-  AppDataPublish publisher(handle);
-
-  for (int i = 1; i <= 5; i++) {
-    publisher.publishData(interest, 0, str[i - 1], 5);
-  }
-
-  BOOST_CHECK_EQUAL(publisher.getNextSeq(interest, 0), 5);
-  BOOST_CHECK_EQUAL(publisher.getRecentData(interest, 0), str[4]);
-
-  fetcher.onUpdate (interest, SeqNo (0,4), SeqNo (0,-1));
-  // give time for ccnd to react
-  sleep(1);
-  BOOST_CHECK_EQUAL(foo.toString(), bar.toString());
-
-
-  boost::function<void (string, string)> eraseFunc =
-    bind(&TestStructApp::erase, &bar, _1, _2);
-  fetcher.setDataCallback(eraseFunc);
-
-  fetcher.onUpdate (interest, SeqNo (0,4), SeqNo (0,-1));
-  // give time for ccnd to react
-  sleep(1);
-  TestStructApp poo;
-
-  BOOST_CHECK_EQUAL(poo.toString(), bar.toString());
-
-}
-*/
diff --git a/tests/integrated-tests/test-socket.cpp b/tests/integrated-tests/test-socket.cpp
new file mode 100644
index 0000000..4b81554
--- /dev/null
+++ b/tests/integrated-tests/test-socket.cpp
@@ -0,0 +1,331 @@
+/* -*- 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/>.
+ */
+
+#include "socket.hpp"
+
+#include "boost-test.hpp"
+
+namespace chronosync {
+namespace test {
+
+using std::string;
+using std::vector;
+using std::map;
+
+/**
+ * @brief Emulate an app that use the Socket class
+ *
+ * The app has two types of data set: one is simply string while the other is integer array.
+ * For each type of data set, the app has a specific fetching strategy.
+ */
+class SocketTestApp : noncopyable
+{
+public:
+  SocketTestApp(const Name& syncPrefix,
+                const Name& userPrefix,
+                ndn::Face& face,
+                bool isNum)
+    : sum(0)
+    , socket(syncPrefix,
+             userPrefix,
+             face,
+             isNum ? bind(&SocketTestApp::fetchNumbers, this, _1) :
+                     bind(&SocketTestApp::fetchAll, this, _1))
+  {
+  }
+
+  void
+  set(const shared_ptr<const Data>& dataPacket)
+  {
+    // std::cerr << "set Data" << std::endl;
+    Name dataName(dataPacket->getName());
+    string str2(reinterpret_cast<const char*>(dataPacket->getContent().value()),
+                dataPacket->getContent().value_size());
+    data.insert(make_pair(dataName, str2));
+  }
+
+  void
+  set(Name name, const char* buf, int len)
+  {
+    string str2(buf, len);
+    data.insert(make_pair(name, str2));
+  }
+
+  void
+  setNum(const shared_ptr<const Data>& dataPacket)
+  {
+    // std::cerr << "setNum Data" << std::endl;
+    size_t n = dataPacket->getContent().value_size() / 4;
+    const uint32_t* numbers = reinterpret_cast<const uint32_t*>(dataPacket->getContent().value());
+    for (size_t i = 0; i < n; i++) {
+      sum += numbers[i];
+    }
+  }
+
+  void
+  setNum(Name name, const uint8_t* buf, int len)
+  {
+    BOOST_ASSERT(len >= 4);
+
+    int n = len / 4;
+    const uint32_t* numbers = reinterpret_cast<const uint32_t*>(buf);
+    for (int i = 0; i < n; i++) {
+      sum += numbers[i];
+    }
+  }
+
+  void
+  fetchAll(const vector<MissingDataInfo>& v)
+  {
+    // std::cerr << "fetchAll" << std::endl;
+    for (int i = 0; i < v.size(); i++) {
+      for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
+        socket.fetchData(v[i].session, s,
+                         bind(&SocketTestApp::set, this, _1));
+      }
+    }
+  }
+
+  void
+  fetchNumbers(const vector<MissingDataInfo> &v)
+  {
+    // std::cerr << "fetchNumbers" << std::endl;
+    for (int i = 0; i < v.size(); i++) {
+      for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
+        socket.fetchData(v[i].session, s,
+                         bind(&SocketTestApp::setNum, this, _1));
+      }
+    }
+  }
+
+  string
+  toString()
+  {
+    string str = "\n";
+    for (map<Name, string>::iterator it = data.begin(); it != data.end(); ++it) {
+      str += "<";
+      str += it->first.toUri();
+      str += "|";
+      str += it->second;
+      str += ">";
+      str += "\n";
+    }
+
+    return str;
+  }
+
+  map<ndn::Name, string> data;
+  uint32_t sum;
+  Socket socket;
+};
+
+class SocketFixture
+{
+public:
+  SocketFixture()
+    : syncPrefix("/ndn/broadcast/sync")
+    , scheduler(io)
+  {
+    syncPrefix.appendVersion();
+    userPrefix[0] = Name("/user0");
+    userPrefix[1] = Name("/user1");
+    userPrefix[2] = Name("/user2");
+
+    faces[0] = make_shared<ndn::Face>(ref(io));
+    faces[1] = make_shared<ndn::Face>(ref(io));
+    faces[2] = make_shared<ndn::Face>(ref(io));
+  }
+
+  void
+  createSocket(size_t idx, bool isNum)
+  {
+    app[idx] = make_shared<SocketTestApp>(syncPrefix, userPrefix[idx], ref(*faces[idx]), isNum);
+    sessionName[idx] = app[idx]->socket.getLogic().getSessionName();
+  }
+
+  void
+  publishAppData(size_t idx, const string& data)
+  {
+    app[idx]->socket.publishData(reinterpret_cast<const uint8_t*>(data.c_str()), data.size(),
+                                 ndn::time::milliseconds(1000));
+  }
+
+  void
+  setAppData(size_t idx, SeqNo seqNo, const string& data)
+  {
+    Name dataName = sessionName[idx];
+    dataName.appendNumber(seqNo);
+    app[idx]->set(dataName, data.c_str(), data.size());
+  }
+
+  void
+  publishAppNum(size_t idx, const uint8_t* buf, size_t size)
+  {
+    app[idx]->socket.publishData(buf, size, ndn::time::milliseconds(1000));
+  }
+
+  void
+  setAppNum(size_t idx, SeqNo seqNo, const uint8_t* buf, size_t size)
+  {
+    Name dataName = sessionName[idx];
+    dataName.appendNumber(seqNo);
+    app[idx]->setNum(dataName, buf, size);
+  }
+
+  void
+  check(int round)
+  {
+    BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
+    BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
+  }
+
+  void
+  check2Num(int num)
+  {
+    BOOST_CHECK_EQUAL(app[0]->sum, app[1]->sum);
+    BOOST_CHECK_EQUAL(app[1]->sum, num);
+  }
+
+  void
+  terminate()
+  {
+    io.stop();
+  }
+
+  Name syncPrefix;
+  Name userPrefix[3];
+  Name sessionName[3];
+
+  boost::asio::io_service io;
+  shared_ptr<ndn::Face> faces[3];
+  ndn::Scheduler scheduler;
+  shared_ptr<SocketTestApp> app[3];
+};
+
+
+
+BOOST_FIXTURE_TEST_SUITE(SocketTests, SocketFixture)
+
+BOOST_AUTO_TEST_CASE(BasicData)
+{
+  scheduler.scheduleEvent(ndn::time::milliseconds(0),
+                          bind(&SocketFixture::createSocket, this, 0, false));
+
+  scheduler.scheduleEvent(ndn::time::milliseconds(50),
+                          bind(&SocketFixture::createSocket, this, 1, false));
+
+  scheduler.scheduleEvent(ndn::time::milliseconds(100),
+                          bind(&SocketFixture::createSocket, this, 2, false));
+
+  string data0 = "Very funny Scotty, now beam down my clothes";
+  scheduler.scheduleEvent(ndn::time::milliseconds(150),
+                          bind(&SocketFixture::publishAppData, this, 0, data0));
+  scheduler.scheduleEvent(ndn::time::milliseconds(1150),
+                          bind(&SocketFixture::setAppData, this, 0, 1, data0));
+  scheduler.scheduleEvent(ndn::time::milliseconds(1160),
+                          bind(&SocketFixture::check, this, 1));
+
+  string data1 = "Yes, give me that ketchup";
+  string data2 = "Don't look conspicuous, it draws fire";
+  scheduler.scheduleEvent(ndn::time::milliseconds(1170),
+                          bind(&SocketFixture::publishAppData, this, 0, data1));
+  scheduler.scheduleEvent(ndn::time::milliseconds(1180),
+                          bind(&SocketFixture::publishAppData, this, 0, data2));
+  scheduler.scheduleEvent(ndn::time::milliseconds(2150),
+                          bind(&SocketFixture::setAppData, this, 0, 2, data1));
+  scheduler.scheduleEvent(ndn::time::milliseconds(2160),
+                          bind(&SocketFixture::setAppData, this, 0, 3, data2));
+  scheduler.scheduleEvent(ndn::time::milliseconds(2170),
+                          bind(&SocketFixture::check, this, 2));
+
+  string data3 = "You surf the Internet, I surf the real world";
+  string data4 = "I got a fortune cookie once that said 'You like Chinese food'";
+  string data5 = "Real men wear pink. Why? Because their wives make them";
+  scheduler.scheduleEvent(ndn::time::milliseconds(3180),
+                          bind(&SocketFixture::publishAppData, this, 2, data3));
+  scheduler.scheduleEvent(ndn::time::milliseconds(3200),
+                          bind(&SocketFixture::publishAppData, this, 1, data4));
+  scheduler.scheduleEvent(ndn::time::milliseconds(3210),
+                          bind(&SocketFixture::publishAppData, this, 1, data5));
+  scheduler.scheduleEvent(ndn::time::milliseconds(4710),
+                          bind(&SocketFixture::setAppData, this, 2, 1, data3));
+  scheduler.scheduleEvent(ndn::time::milliseconds(4720),
+                          bind(&SocketFixture::setAppData, this, 1, 1, data4));
+  scheduler.scheduleEvent(ndn::time::milliseconds(4730),
+                          bind(&SocketFixture::setAppData, this, 1, 2, data5));
+  scheduler.scheduleEvent(ndn::time::milliseconds(4800),
+                          bind(&SocketFixture::check, this, 3));
+
+  // not sure weither this is simultanous data generation from multiple sources
+  string data6 = "Shakespeare says: 'Prose before hos.'";
+  string data7 = "Pick good people, talent never wears out";
+  scheduler.scheduleEvent(ndn::time::milliseconds(5500),
+                          bind(&SocketFixture::publishAppData, this, 0, data6));
+  scheduler.scheduleEvent(ndn::time::milliseconds(5500),
+                          bind(&SocketFixture::publishAppData, this, 1, data7));
+  scheduler.scheduleEvent(ndn::time::milliseconds(6800),
+                          bind(&SocketFixture::setAppData, this, 0, 4, data6));
+  scheduler.scheduleEvent(ndn::time::milliseconds(6800),
+                          bind(&SocketFixture::setAppData, this, 1, 3, data7));
+  scheduler.scheduleEvent(ndn::time::milliseconds(6900),
+                          bind(&SocketFixture::check, this, 4));
+
+  scheduler.scheduleEvent(ndn::time::milliseconds(7000),
+                          bind(&SocketFixture::terminate, this));
+
+  io.run();
+}
+
+BOOST_AUTO_TEST_CASE(BasicNumber)
+{
+  scheduler.scheduleEvent(ndn::time::milliseconds(0),
+                          bind(&SocketFixture::createSocket, this, 0, true));
+  scheduler.scheduleEvent(ndn::time::milliseconds(50),
+                          bind(&SocketFixture::createSocket, this, 1, true));
+
+  uint32_t num1[5] = {0, 1, 2, 3, 4};
+  uint8_t* buf1 = reinterpret_cast<uint8_t*>(num1);
+  size_t size1 = sizeof(num1);
+  scheduler.scheduleEvent(ndn::time::milliseconds(100),
+                          bind(&SocketFixture::publishAppNum, this, 0, buf1, size1));
+  scheduler.scheduleEvent(ndn::time::milliseconds(150),
+                          bind(&SocketFixture::setAppNum, this, 0, 0, buf1, size1));
+  scheduler.scheduleEvent(ndn::time::milliseconds(1000),
+                          bind(&SocketFixture::check2Num, this, 10));
+
+  uint32_t num2[5] = {9, 7, 2, 1, 1};
+  uint8_t* buf2 = reinterpret_cast<uint8_t*>(num2);
+  size_t size2 = sizeof(num2);
+  scheduler.scheduleEvent(ndn::time::milliseconds(1100),
+                          bind(&SocketFixture::publishAppNum, this, 1, buf2, size2));
+  scheduler.scheduleEvent(ndn::time::milliseconds(1150),
+                          bind(&SocketFixture::setAppNum, this, 1, 0, buf2, size2));
+  scheduler.scheduleEvent(ndn::time::milliseconds(2000),
+                          bind(&SocketFixture::check2Num, this, 30));
+
+  scheduler.scheduleEvent(ndn::time::milliseconds(7000),
+                          bind(&SocketFixture::terminate, this));
+
+  io.run();
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace test
+} // namespace chronosync
diff --git a/tests/integrated-tests/test-socket.cpp.outdated b/tests/integrated-tests/test-socket.cpp.outdated
deleted file mode 100644
index d04ded9..0000000
--- a/tests/integrated-tests/test-socket.cpp.outdated
+++ /dev/null
@@ -1,619 +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/>.
- */
-
-#include <boost/test/unit_test.hpp>
-#include <boost/test/output_test_stream.hpp>
-using boost::test_tools::output_test_stream;
-
-#include <boost/make_shared.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
-
-#include "sync-logging.h"
-#include "sync-socket.h"
-#include "sync-validator.h"
-#include <ndn-cxx/security/validator-null.hpp>
-
-extern "C" {
-#include <unistd.h>
-}
-
-using namespace Sync;
-using namespace std;
-using namespace boost;
-
-INIT_LOGGER ("Test.AppSocket");
-
-#define PRINT
-// std::cout << "Line: " << __LINE__ << std::endl;
-
-class TestSocketApp {
-public:
-  TestSocketApp()
-    : sum(0)
-  {}
-
-  map<ndn::Name, string> data;
-  void set(const ndn::shared_ptr<const ndn::Data>& dataPacket) {
-    // _LOG_FUNCTION (this << ", " << str1);
-    ndn::Name dataName(dataPacket->getName());
-    string str2(reinterpret_cast<const char*>(dataPacket->getContent().value()), dataPacket->getContent().value_size());
-    data.insert(make_pair(dataName, str2));
-    // cout << str1 << ", " << str2 << endl;
-  }
-
-  void set(ndn::Name name, const char * buf, int len) {
-    string str2(buf, len);
-    data.insert(make_pair(name, str2));
-  }
-
-  void setNum(const ndn::shared_ptr<const ndn::Data>& data) {
-    int n = data->getContent().value_size() / 4;
-    uint32_t *numbers = new uint32_t [n];
-    memcpy(numbers, data->getContent().value(), data->getContent().value_size());
-    for (int i = 0; i < n; i++) {
-      sum += numbers[i];
-    }
-    delete numbers;
-
-  }
-
-  void setNum(ndn::Name name, const char * buf, int len) {
-    int n = len / 4;
-    int *numbers = new int [n];
-    memcpy(numbers, buf, len);
-    for (int i = 0; i < n; i++) {
-      sum += numbers[i];
-    }
-    delete numbers;
-  }
-
-  uint32_t sum;
-
-  void fetchAll(const vector<MissingDataInfo> &v, SyncSocket *socket) {
-    int n = v.size();
-
-    PRINT
-
-    for (int i = 0; i < n; i++) {
-      for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
-        //PRINT
-        socket->fetchData(v[i].prefix, s, bind(&TestSocketApp::set, this, _1));
-      }
-    }
-  }
-
-  void fetchNumbers(const vector<MissingDataInfo> &v, SyncSocket *socket) {
-    int n = v.size();
-
-    PRINT
-
-    // std::cout << "In fetchNumbers. size of v is:  " << n << std::endl;
-    for (int i = 0; i < n; i++) {
-      // std::cout << "In fetchNumbers. v[i].low is (" <<v[i].low.getSession() <<", " << v[i].low.getSeq() << ") v[i].high is ("<<v[i].high.getSession() <<", " <<v[i].high.getSeq()<<")" << std::endl;
-      for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
-        PRINT
-        socket->fetchData(v[i].prefix, s, bind(&TestSocketApp::setNum, this, _1));
-      }
-    }
-  }
-
-  void pass(const string &prefix) {
-  }
-
-  string toString(){
-    map<ndn::Name, string>::iterator it = data.begin();
-    string str = "\n";
-    for (; it != data.end(); ++it){
-      str += "<";
-      str += it->first.toUri();
-      str += "|";
-      str += it->second;
-      str += ">";
-      str += "\n";
-    }
-
-    return str;
-  }
-
-};
-
-class TestSet1{
-public:
-  TestSet1(ndn::shared_ptr<boost::asio::io_service> ioService)
-    : m_face1(new ndn::Face(*ioService))
-    , m_face2(new ndn::Face(*ioService))
-    , m_face3(new ndn::Face(*ioService))
-    , m_name1("/irl.cs.ucla.edu/" + boost::lexical_cast<std::string>(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count()))
-    , m_name2("/yakshi.org/" + boost::lexical_cast<std::string>(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count()))
-    , m_name3("/google.com/" + boost::lexical_cast<std::string>(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count()))
-  {
-    m_id1 = m_keyChain.getCertificate(m_keyChain.createIdentity(m_name1));
-    m_id2 = m_keyChain.getCertificate(m_keyChain.createIdentity(m_name2));
-    m_id3 = m_keyChain.getCertificate(m_keyChain.createIdentity(m_name3));
-
-    m_rule = ndn::make_shared<ndn::SecRuleRelative>("^(<>*)<><>$",
-                                                    "^(<>*)<><KEY><ksk-.*><ID-CERT>$",
-                                                    "==", "\\1", "\\1", true);
-  }
-
-  void
-  createSyncSocket1()
-  {
-    _LOG_DEBUG ("s1");
-
-    m_s1 = ndn::shared_ptr<SyncSocket>
-      (new SyncSocket("/let/us/sync",
-                      "/irl.cs.ucla.edu",
-                      0,
-                      false,
-                      "/",
-                      m_face1,
-                      *m_id1,
-                      m_rule,
-                      bind(&TestSocketApp::fetchAll, &m_a1, _1, _2),
-                      bind(&TestSocketApp::pass, &m_a1, _1)));
-
-    m_s1->addParticipant(*m_id2);
-  }
-
-  void
-  createSyncSocket2()
-  {
-    _LOG_DEBUG ("s2");
-
-    m_s2 = ndn::shared_ptr<SyncSocket>
-      (new SyncSocket("/let/us/sync",
-                      "/yakshi.org",
-                      0,
-                      false,
-                      "/",
-                      m_face2,
-                      *m_id2,
-                      m_rule,
-                      bind(&TestSocketApp::fetchAll, &m_a2, _1, _2),
-                      bind(&TestSocketApp::pass, &m_a2, _1)));
-
-    m_s2->addParticipant(*m_id1);
-    m_s2->addParticipant(*m_id3);
-  }
-
-  void
-  createSyncSocket3()
-  {
-    _LOG_DEBUG ("s3");
-
-    m_s3 = ndn::shared_ptr<SyncSocket>
-      (new SyncSocket("/let/us/sync",
-                      "/google.com",
-                      0,
-                      false,
-                      "/",
-                      m_face3,
-                      *m_id3,
-                      m_rule,
-                      bind(&TestSocketApp::fetchAll, &m_a3, _1, _2),
-                      bind(&TestSocketApp::pass, &m_a3, _1)));
-
-    m_s3->addParticipant(*m_id2);
-  }
-
-  void
-  publishSocket1(string data)
-  {
-    _LOG_DEBUG ("s1 publish");
-    m_s1->publishData (reinterpret_cast<const uint8_t*>(data.c_str()), data.size(), 1000);
-  }
-
-  void
-  publishSocket2(string data)
-  {
-    _LOG_DEBUG ("s2 publish");
-    m_s2->publishData (reinterpret_cast<const uint8_t*>(data.c_str()), data.size(), 1000);
-  }
-
-  void
-  publishSocket3(string data)
-  {
-    _LOG_DEBUG ("s3 publish");
-    m_s3->publishData (reinterpret_cast<const uint8_t*>(data.c_str()), data.size(), 1000);
-  }
-
-  void
-  setSocket1(string suffix, string data)
-  {
-    _LOG_DEBUG ("a1 set");
-    ndn::Name name("/irl.cs.ucla.edu");
-    name.append(suffix);
-    m_a1.set (name, data.c_str(), data.size());
-  }
-
-  void
-  setSocket2(string suffix, string data)
-  {
-    _LOG_DEBUG ("a2 set");
-    ndn::Name name("/yakshi.org");
-    name.append(suffix);
-    m_a2.set (name, data.c_str(), data.size());
-  }
-
-  void
-  setSocket3(string suffix, string data)
-  {
-    _LOG_DEBUG ("a3 set");
-    ndn::Name name("/google.com");
-    name.append(suffix);
-    m_a3.set (name, data.c_str(), data.size());
-  }
-
-  void
-  check(int round)
-  {
-    BOOST_CHECK_EQUAL(m_a1.toString(), m_a2.toString());
-    BOOST_CHECK_EQUAL(m_a2.toString(), m_a3.toString());
-  }
-
-  void
-  done(ndn::shared_ptr<boost::asio::io_service> ioService)
-  {
-    m_s1.reset();
-    m_s2.reset();
-    m_s3.reset();
-
-    m_keyChain.deleteIdentity(m_name1);
-    m_keyChain.deleteIdentity(m_name2);
-    m_keyChain.deleteIdentity(m_name3);
-
-    ioService->stop();
-  }
-
-  ndn::KeyChain m_keyChain;
-  ndn::shared_ptr<ndn::SecRuleRelative> m_rule;
-
-  ndn::shared_ptr<ndn::Face> m_face1, m_face2, m_face3;
-  ndn::Name m_name1, m_name2, m_name3;
-  TestSocketApp m_a1, m_a2, m_a3;
-  ndn::shared_ptr<ndn::IdentityCertificate> m_id1, m_id2, m_id3;
-  ndn::shared_ptr<SyncSocket> m_s1, m_s2, m_s3;
-};
-
-class TestSet2{
-public:
-  TestSet2(ndn::shared_ptr<boost::asio::io_service> ioService)
-    : m_face1(new ndn::Face(*ioService))
-    , m_face2(new ndn::Face(*ioService))
-    , m_name1("/xiaonei.com/" + boost::lexical_cast<std::string>(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count()))
-    , m_name2("/mitbbs.com/" + boost::lexical_cast<std::string>(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count()))
-  {
-    m_id1 = m_keyChain.getCertificate(m_keyChain.createIdentity(m_name1));
-    m_id2 = m_keyChain.getCertificate(m_keyChain.createIdentity(m_name2));
-
-    m_rule = ndn::make_shared<ndn::SecRuleRelative>("^(<>*)<><>$",
-                                                    "^(<>*)<><KEY><ksk-.*><ID-CERT>$",
-                                                    "==", "\\1", "\\1", true);
-  }
-
-  void
-  createSyncSocket1()
-  {
-    _LOG_DEBUG ("s1");
-
-    m_s1 = ndn::shared_ptr<SyncSocket>
-      (new SyncSocket("/this/is/the/prefix",
-                      "/xiaonei.com",
-                      0,
-                      false,
-                      "/",
-                      m_face1,
-                      *m_id1,
-                      m_rule,
-                      bind(&TestSocketApp::fetchNumbers, &m_a1, _1, _2),
-                      bind(&TestSocketApp::pass, &m_a1, _1)));
-
-    m_s1->addParticipant(*m_id2);
-  }
-
-  void
-  createSyncSocket2()
-  {
-    _LOG_DEBUG ("s2");
-
-    m_s2 = ndn::shared_ptr<SyncSocket>
-      (new SyncSocket("/this/is/the/prefix",
-                      "/mitbbs.com",
-                      0,
-                      false,
-                      "/",
-                      m_face2,
-                      *m_id2,
-                      m_rule,
-                      bind(&TestSocketApp::fetchNumbers, &m_a2, _1, _2),
-                      bind(&TestSocketApp::pass, &m_a2, _1)));
-
-    m_s2->addParticipant(*m_id1);
-  }
-
-  void
-  publishSocket1(string data)
-  {
-    _LOG_DEBUG ("s1 publish");
-    m_s1->publishData (reinterpret_cast<const uint8_t*>(data.c_str()), data.size(), 1000);
-  }
-
-  void
-  publishSocket2(string data)
-  {
-    _LOG_DEBUG ("s2 publish");
-    m_s2->publishData (reinterpret_cast<const uint8_t*>(data.c_str()), data.size(), 1000);
-  }
-
-  void
-  setSocket1(const char* ptr, size_t size)
-  {
-    _LOG_DEBUG ("a1 setNum");
-    m_a1.setNum ("/xiaonei.com", ptr, size);
-  }
-
-  void
-  setSocket2(const char* ptr, size_t size)
-  {
-    _LOG_DEBUG ("a2 setNum");
-    m_a2.setNum ("/mitbbs.com", ptr, size);
-  }
-
-  void
-  check(int num)
-  {
-    _LOG_DEBUG ("codnum " << num);
-    _LOG_DEBUG ("a1 sum " << m_a1.sum);
-    _LOG_DEBUG ("a2 sum " << m_a2.sum);
-
-    BOOST_CHECK(m_a1.sum == m_a2.sum && m_a1.sum == num);
-  }
-
-  void
-  done(ndn::shared_ptr<boost::asio::io_service> ioService)
-  {
-    m_s1.reset();
-    m_s2.reset();
-
-    m_keyChain.deleteIdentity(m_name1);
-    m_keyChain.deleteIdentity(m_name2);
-
-    ioService->stop();
-  }
-
-  ndn::KeyChain m_keyChain;
-  ndn::shared_ptr<ndn::SecRuleRelative> m_rule;
-
-  TestSocketApp m_a1, m_a2;
-  ndn::shared_ptr<ndn::IdentityCertificate> m_id1, m_id2;
-  ndn::shared_ptr<ndn::Face> m_face1, m_face2;
-  ndn::Name m_name1, m_name2;
-  ndn::shared_ptr<SyncSocket> m_s1, m_s2;
-};
-
-
-
-class TestSet3{
-public:
-  TestSet3(ndn::shared_ptr<boost::asio::io_service> ioService)
-    : m_face1(new ndn::Face(*ioService))
-    , m_face2(new ndn::Face(*ioService))
-    , m_name1("/xiaonei.com/" + boost::lexical_cast<std::string>(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count()))
-    , m_name2("/mitbbs.com/" + boost::lexical_cast<std::string>(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count()))
-  {
-    m_id1 = m_keyChain.getCertificate(m_keyChain.createIdentity(m_name1));
-    m_id2 = m_keyChain.getCertificate(m_keyChain.createIdentity(m_name2));
-
-    m_rule = ndn::make_shared<ndn::SecRuleRelative>("^(<>*)<><>$",
-                                                    "^(<>*)<><KEY><ksk-.*><ID-CERT>$",
-                                                    "==", "\\1", "\\1", true);
-  }
-
-  void
-  createSyncSocket1()
-  {
-    _LOG_DEBUG ("s1");
-
-    m_s1 = ndn::shared_ptr<SyncSocket>
-      (new SyncSocket("/this/is/the/prefix",
-                      "/xiaonei.com",
-                      1,
-                      true,
-                      "/abc",
-                      m_face1,
-                      *m_id1,
-                      m_rule,
-                      bind(&TestSocketApp::fetchNumbers, &m_a1, _1, _2),
-                      bind(&TestSocketApp::pass, &m_a1, _1)));
-
-    m_s1->addParticipant(*m_id2);
-  }
-
-  void
-  createSyncSocket2()
-  {
-    _LOG_DEBUG ("s2");
-
-    m_s2 = ndn::shared_ptr<SyncSocket>
-      (new SyncSocket("/this/is/the/prefix",
-                      "/mitbbs.com",
-                      1,
-                      false,
-                      "/",
-                      m_face2,
-                      *m_id2,
-                      m_rule,
-                      bind(&TestSocketApp::fetchNumbers, &m_a2, _1, _2),
-                      bind(&TestSocketApp::pass, &m_a2, _1)));
-
-    m_s2->addParticipant(*m_id1);
-  }
-
-  void
-  publishSocket1(string data)
-  {
-    _LOG_DEBUG ("s1 publish");
-    m_s1->publishData (reinterpret_cast<const uint8_t*>(data.c_str()), data.size(), 1000);
-  }
-
-  void
-  publishSocket2(string data)
-  {
-    _LOG_DEBUG ("s2 publish");
-    m_s2->publishData (reinterpret_cast<const uint8_t*>(data.c_str()), data.size(), 1000);
-  }
-
-  void
-  setSocket1(const char* ptr, size_t size)
-  {
-    _LOG_DEBUG ("a1 setNum");
-    m_a1.setNum ("/xiaonei.com", ptr, size);
-  }
-
-  void
-  setSocket2(const char* ptr, size_t size)
-  {
-    _LOG_DEBUG ("a2 setNum");
-    m_a2.setNum ("/mitbbs.com", ptr, size);
-  }
-
-  void
-  check(int num)
-  {
-    _LOG_DEBUG ("codnum " << num);
-    _LOG_DEBUG ("a1 sum " << m_a1.sum);
-    _LOG_DEBUG ("a2 sum " << m_a2.sum);
-
-    BOOST_CHECK(m_a1.sum == m_a2.sum && m_a1.sum == num);
-  }
-
-  void
-  done(ndn::shared_ptr<boost::asio::io_service> ioService)
-  {
-    m_s1.reset();
-    m_s2.reset();
-
-    m_keyChain.deleteIdentity(m_name1);
-    m_keyChain.deleteIdentity(m_name2);
-
-    ioService->stop();
-  }
-
-  ndn::KeyChain m_keyChain;
-  ndn::shared_ptr<ndn::SecRuleRelative> m_rule;
-
-  TestSocketApp m_a1, m_a2;
-  ndn::shared_ptr<ndn::IdentityCertificate> m_id1, m_id2;
-  ndn::shared_ptr<ndn::Face> m_face1, m_face2;
-  ndn::Name m_name1, m_name2;
-  ndn::shared_ptr<SyncSocket> m_s1, m_s2;
-};
-
-BOOST_AUTO_TEST_CASE (AppSocketTest1)
-{
-  INIT_LOGGERS ();
-
-  ndn::shared_ptr<boost::asio::io_service> ioService = ndn::make_shared<boost::asio::io_service>();
-  ndn::Scheduler scheduler(*ioService);
-  TestSet1 testSet1(ioService);
-
-  scheduler.scheduleEvent(ndn::time::milliseconds(0), ndn::bind(&TestSet1::createSyncSocket1, &testSet1));
-  scheduler.scheduleEvent(ndn::time::milliseconds(50), ndn::bind(&TestSet1::createSyncSocket2, &testSet1));
-  scheduler.scheduleEvent(ndn::time::milliseconds(100), ndn::bind(&TestSet1::createSyncSocket3, &testSet1));
-  string data0 = "Very funny Scotty, now beam down my clothes";
-  scheduler.scheduleEvent(ndn::time::milliseconds(150), ndn::bind(&TestSet1::publishSocket1, &testSet1, data0));
-  scheduler.scheduleEvent(ndn::time::milliseconds(1150), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/1", data0));
-  scheduler.scheduleEvent(ndn::time::milliseconds(1160), ndn::bind(&TestSet1::check, &testSet1, 1));
-  string data1 = "Yes, give me that ketchup";
-  string data2 = "Don't look conspicuous, it draws fire";
-  scheduler.scheduleEvent(ndn::time::milliseconds(1170), ndn::bind(&TestSet1::publishSocket1, &testSet1, data1));
-  scheduler.scheduleEvent(ndn::time::milliseconds(1180), ndn::bind(&TestSet1::publishSocket1, &testSet1, data2));
-  scheduler.scheduleEvent(ndn::time::milliseconds(2150), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/2", data1));
-  scheduler.scheduleEvent(ndn::time::milliseconds(2160), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/3", data2));
-  scheduler.scheduleEvent(ndn::time::milliseconds(2170), ndn::bind(&TestSet1::check, &testSet1, 2));
-  string data3 = "You surf the Internet, I surf the real world";
-  string data4 = "I got a fortune cookie once that said 'You like Chinese food'";
-  string data5 = "Real men wear pink. Why? Because their wives make them";
-  scheduler.scheduleEvent(ndn::time::milliseconds(3180), ndn::bind(&TestSet1::publishSocket3, &testSet1, data3));
-  scheduler.scheduleEvent(ndn::time::milliseconds(3200), ndn::bind(&TestSet1::publishSocket2, &testSet1, data4));
-  scheduler.scheduleEvent(ndn::time::milliseconds(3210), ndn::bind(&TestSet1::publishSocket2, &testSet1, data5));
-  scheduler.scheduleEvent(ndn::time::milliseconds(4710), ndn::bind(&TestSet1::setSocket3, &testSet1, "/0/1", data3));
-  scheduler.scheduleEvent(ndn::time::milliseconds(4720), ndn::bind(&TestSet1::setSocket2, &testSet1, "/0/2", data4));
-  scheduler.scheduleEvent(ndn::time::milliseconds(4730), ndn::bind(&TestSet1::setSocket2, &testSet1, "/0/3", data5));
-  scheduler.scheduleEvent(ndn::time::milliseconds(4800), ndn::bind(&TestSet1::check, &testSet1, 3));
-  // not sure weither this is simultanous data generation from multiple sources
-  _LOG_DEBUG ("Simultaneous publishing");
-  string data6 = "Shakespeare says: 'Prose before hos.'";
-  string data7 = "Pick good people, talent never wears out";
-  scheduler.scheduleEvent(ndn::time::milliseconds(5500), ndn::bind(&TestSet1::publishSocket1, &testSet1, data6));
-  scheduler.scheduleEvent(ndn::time::milliseconds(5500), ndn::bind(&TestSet1::publishSocket2, &testSet1, data7));
-  scheduler.scheduleEvent(ndn::time::milliseconds(6800), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/4", data6));
-  scheduler.scheduleEvent(ndn::time::milliseconds(6800), ndn::bind(&TestSet1::setSocket2, &testSet1, "/0/4", data7));
-  scheduler.scheduleEvent(ndn::time::milliseconds(6900), ndn::bind(&TestSet1::check, &testSet1, 4));
-  scheduler.scheduleEvent(ndn::time::milliseconds(7000), ndn::bind(&TestSet1::done, &testSet1, ioService));
-
-  ioService->run();
-}
-
-BOOST_AUTO_TEST_CASE (AppSocketTest2)
-{
-  ndn::shared_ptr<boost::asio::io_service> ioService = ndn::make_shared<boost::asio::io_service>();
-  ndn::Scheduler scheduler(*ioService);
-  TestSet2 testSet2(ioService);
-
-  scheduler.scheduleEvent(ndn::time::milliseconds(0), ndn::bind(&TestSet2::createSyncSocket1, &testSet2));
-  scheduler.scheduleEvent(ndn::time::milliseconds(50), ndn::bind(&TestSet2::createSyncSocket2, &testSet2));
-  uint32_t num[5] = {0, 1, 2, 3, 4};
-  string data0((const char *) num, sizeof(num));
-  scheduler.scheduleEvent(ndn::time::milliseconds(100), ndn::bind(&TestSet2::publishSocket1, &testSet2, data0));
-  scheduler.scheduleEvent(ndn::time::milliseconds(150), ndn::bind(&TestSet2::setSocket1, &testSet2, (const char *) num, sizeof (num)));
-  scheduler.scheduleEvent(ndn::time::milliseconds(1000), ndn::bind(&TestSet2::check, &testSet2, 10));
-  uint32_t newNum[5] = {9, 7, 2, 1, 1};
-  string data1((const char *) newNum, sizeof(newNum));
-  scheduler.scheduleEvent(ndn::time::milliseconds(1100), ndn::bind(&TestSet2::publishSocket2, &testSet2, data1));
-  scheduler.scheduleEvent(ndn::time::milliseconds(1150), ndn::bind(&TestSet2::setSocket2, &testSet2, (const char *) newNum, sizeof (newNum)));
-  scheduler.scheduleEvent(ndn::time::milliseconds(2000), ndn::bind(&TestSet2::check, &testSet2, 30));
-  scheduler.scheduleEvent(ndn::time::milliseconds(7000), ndn::bind(&TestSet2::done, &testSet2, ioService));
-
-  ioService->run();
-}
-
-BOOST_AUTO_TEST_CASE (AppSocketTest3)
-{
-  ndn::shared_ptr<boost::asio::io_service> ioService = ndn::make_shared<boost::asio::io_service>();
-  ndn::Scheduler scheduler(*ioService);
-  TestSet3 testSet3(ioService);
-
-  scheduler.scheduleEvent(ndn::time::milliseconds(0), ndn::bind(&TestSet3::createSyncSocket1, &testSet3));
-  scheduler.scheduleEvent(ndn::time::milliseconds(200), ndn::bind(&TestSet3::createSyncSocket2, &testSet3));
-  uint32_t num[5] = {0, 1, 2, 3, 4};
-  string data0((const char *) num, sizeof(num));
-  scheduler.scheduleEvent(ndn::time::milliseconds(1000), ndn::bind(&TestSet3::publishSocket1, &testSet3, data0));
-  scheduler.scheduleEvent(ndn::time::milliseconds(1500), ndn::bind(&TestSet3::setSocket1, &testSet3, (const char *) num, sizeof (num)));
-  scheduler.scheduleEvent(ndn::time::milliseconds(2000), ndn::bind(&TestSet3::check, &testSet3, 10));
-  uint32_t newNum[5] = {9, 7, 2, 1, 1};
-  string data1((const char *) newNum, sizeof(newNum));
-  scheduler.scheduleEvent(ndn::time::milliseconds(3000), ndn::bind(&TestSet3::publishSocket2, &testSet3, data1));
-  scheduler.scheduleEvent(ndn::time::milliseconds(3500), ndn::bind(&TestSet3::setSocket2, &testSet3, (const char *) newNum, sizeof (newNum)));
-  scheduler.scheduleEvent(ndn::time::milliseconds(5000), ndn::bind(&TestSet3::check, &testSet3, 30));
-  scheduler.scheduleEvent(ndn::time::milliseconds(7000), ndn::bind(&TestSet3::done, &testSet3, ioService));
-
-  ioService->run();
-}