cmd: Switch code to use ndn-cxx

Implementation moved to ndn::chronoshare namespace

Change-Id: I1d7a46f03133a8e382f0a2bb272311fbd18c95c4
diff --git a/cmd/csd.cpp b/cmd/csd.cpp
index 00cd434..65b1abc 100644
--- a/cmd/csd.cpp
+++ b/cmd/csd.cpp
@@ -18,41 +18,87 @@
  * See AUTHORS.md for complete list of ChronoShare authors and contributors.
  */
 
-#include <QtCore>
+#include "csd.hpp"
+#include <thread>
 
-#include "ccnx-wrapper.hpp"
-#include "dispatcher.hpp"
-#include "fs-watcher.hpp"
-#include "logging.hpp"
-
-#include <boost/make_shared.hpp>
-
-using namespace boost;
-using namespace std;
-using namespace Ndnx;
+namespace ndn {
+namespace chronoshare {
 
 int
 main(int argc, char* argv[])
 {
   QCoreApplication app(argc, argv);
+  Runner runner(&app);
+  QObject::connect(&runner, SIGNAL(terminateApp()), &app, SLOT(quit()), Qt::QueuedConnection);
 
   if (argc != 4) {
-    cerr << "Usage: ./csd <username> <shared-folder> <path>" << endl;
+    std::cerr << "Usage: ./csd <username> <shared-folder> <path>" << std::endl;
     return 1;
   }
 
-  string username = argv[1];
-  string sharedFolder = argv[2];
-  string path = argv[3];
+  std::string username = argv[1];
+  std::string sharedFolder = argv[2];
+  std::string path = argv[3];
 
-  cout << "Starting ChronoShare for [" << username << "] shared-folder [" << sharedFolder
-       << "] at [" << path << "]" << endl;
+  std::cout << "Starting ChronoShare for [" << username << "] shared-folder [" << sharedFolder
+            << "] at [" << path << "]" << std::endl;
 
-  Dispatcher dispatcher(username, sharedFolder, path, make_shared<CcnxWrapper>());
+  boost::asio::io_service ioService;
+  Face face(ioService);
 
-  FsWatcher watcher(path.c_str(),
+  Dispatcher dispatcher(username, sharedFolder, path, face);
+
+  std::thread ioThread([&ioService, &runner] {
+    try {
+      ioService.run();
+      runner.retval = 0;
+    }
+    catch (boost::exception& e) {
+      runner.retval = 2;
+      if (&dynamic_cast<std::exception&>(e) != nullptr) {
+        std::cerr << "ERROR: " << dynamic_cast<std::exception&>(e).what() << std::endl;
+      }
+      std::cerr << boost::diagnostic_information(e, true) << std::endl;
+    }
+    catch (std::exception& e) {
+      runner.retval = 2;
+      std::cerr << "ERROR: " << e.what() << std::endl;
+    }
+
+    QTimer::singleShot(0, &runner, SLOT(notifyAsioThread()));
+  });
+
+  FsWatcher watcher(ioService, path.c_str(),
                     bind(&Dispatcher::Did_LocalFile_AddOrModify, &dispatcher, _1),
                     bind(&Dispatcher::Did_LocalFile_Delete, &dispatcher, _1));
 
-  return app.exec();
+  int retval = 0;
+  try {
+    retval = app.exec();
+  }
+  catch (boost::exception& e) {
+    retval = 1;
+    if (&dynamic_cast<std::exception&>(e) != nullptr) {
+      std::cerr << "ERROR: " << dynamic_cast<std::exception&>(e).what() << std::endl;
+    }
+    std::cerr << boost::diagnostic_information(e, true) << std::endl;
+  }
+  catch (std::exception& e) {
+    retval = 1;
+    std::cerr << "ERROR: " << e.what() << std::endl;
+  }
+
+  ioService.stop();
+  ioThread.join();
+
+  return std::max(retval, runner.retval);
+}
+
+} // namespace chronoshare
+} // namespace ndn
+
+int
+main(int argc, char* argv[])
+{
+  return ndn::chronoshare::main(argc, argv);
 }
diff --git a/cmd/csd.hpp b/cmd/csd.hpp
new file mode 100644
index 0000000..2dbaeeb
--- /dev/null
+++ b/cmd/csd.hpp
@@ -0,0 +1,63 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017, Regents of the University of California.
+ *
+ * This file is part of ChronoShare, a decentralized file sharing application over NDN.
+ *
+ * ChronoShare 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.
+ *
+ * ChronoShare 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 copies of the GNU General Public License along with
+ * ChronoShare, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ChronoShare authors and contributors.
+ */
+
+#include "core/chronoshare-common.hpp"
+
+#include <QtCore>
+
+#ifndef Q_MOC_RUN
+#include "dispatcher.hpp"
+#include "fs-watcher/fs-watcher.hpp"
+#include "core/logging.hpp"
+
+#include <boost/asio/io_service.hpp>
+#endif // Q_MOC_RUN
+
+
+namespace ndn {
+namespace chronoshare {
+
+class Runner : public QObject
+{
+  Q_OBJECT
+public:
+  Runner(QObject* parent = 0)
+    : QObject(parent)
+    , retval(0)
+  {
+  }
+
+signals:
+  void
+  terminateApp();
+
+public slots:
+  void
+  notifyAsioThread()
+  {
+    emit terminateApp();
+  }
+
+public:
+  int retval;
+};
+
+} // namespace chronoshare
+} // namespace ndn
\ No newline at end of file
diff --git a/cmd/dump-db.cpp b/cmd/dump-db.cpp
index 3333507..cb78224 100644
--- a/cmd/dump-db.cpp
+++ b/cmd/dump-db.cpp
@@ -18,24 +18,31 @@
  * See AUTHORS.md for complete list of ChronoShare authors and contributors.
  */
 
-#include "ccnx-wrapper.hpp"
 #include "dispatcher.hpp"
-#include "fs-watcher.hpp"
-#include "logging.hpp"
+#include "sync-core.hpp"
+
+#include "core/logging.hpp"
+
+#include <ndn-cxx/util/string-helper.hpp>
 
 #include <boost/lexical_cast.hpp>
-#include <boost/make_shared.hpp>
 
-using namespace boost;
-using namespace std;
-using namespace Ndnx;
+namespace ndn {
+namespace chronoshare {
 
 _LOG_INIT(DumpDb);
 
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::setw;
+
+namespace fs = boost::filesystem;
+
 class StateLogDumper : public DbHelper
 {
 public:
-  StateLogDumper(const filesystem::path& path)
+  StateLogDumper(const fs::path& path)
     : DbHelper(path / ".chronoshare", "sync-log.db")
   {
   }
@@ -45,10 +52,10 @@
   {
     sqlite3_stmt* stmt;
     sqlite3_prepare_v2(m_db,
-                       "SELECT hash(device_name, seq_no) FROM (SELECT * FROM SyncNodes ORDER BY device_name)",
+                       "SELECT hash(device_name, seq_no) FROM(SELECT * FROM SyncNodes ORDER BY device_name)",
                        -1, &stmt, 0);
     sqlite3_step(stmt);
-    Hash hash(sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0));
+    ndn::Buffer hash(sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0));
     sqlite3_finalize(stmt);
 
     sqlite3_prepare_v2(m_db, "SELECT device_name, seq_no, last_known_locator, last_update "
@@ -57,7 +64,7 @@
                        -1, &stmt, 0);
 
     cout.setf(std::ios::left, std::ios::adjustfield);
-    cout << ">> SYNC NODES (" << hash.shortHash() << ") <<" << endl;
+    cout << ">> SYNC NODES(" << toHex(hash).substr(0, 8) << ") <<" << endl;
     cout << "===================================================================================="
          << endl;
     cout << setw(30) << "device_name"
@@ -68,12 +75,18 @@
 
     while (sqlite3_step(stmt) == SQLITE_ROW) {
       cout << setw(30)
-           << lexical_cast<string>(Name(sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0)))
+           << (Name(Block(sqlite3_column_blob(stmt, 0), (sqlite3_column_bytes(stmt, 0))))).toUri()
            << " | ";                                             // device_name
       cout << setw(6) << sqlite3_column_int64(stmt, 1) << " | "; // seq_no
-      cout << setw(20)
-           << lexical_cast<string>(Name(sqlite3_column_blob(stmt, 2), sqlite3_column_bytes(stmt, 2)))
-           << " | "; // locator
+      cout << setw(20);
+      if (sqlite3_column_bytes(stmt, 2) > 0) {
+        cout << (Name(Block(sqlite3_column_blob(stmt, 2), (sqlite3_column_bytes(stmt, 2))))).toUri();
+      }
+      else {
+        cout << "NULL";
+      }
+      cout << " | "; // locator
+
       if (sqlite3_column_bytes(stmt, 3) > 0) {
         cout << setw(10) << sqlite3_column_text(stmt, 3) << endl;
       }
@@ -88,7 +101,7 @@
   DumpLog()
   {
     sqlite3_stmt* stmt;
-    sqlite3_prepare_v2(m_db, "SELECT state_hash, last_update, state_id "
+    sqlite3_prepare_v2(m_db, "SELECT state_hash, last_update, state_id, last_update "
                              "   FROM SyncLog "
                              "   ORDER BY last_update",
                        -1, &stmt, 0);
@@ -104,7 +117,9 @@
 
     while (sqlite3_step(stmt) == SQLITE_ROW) {
       cout << setw(10)
-           << Hash(sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0)).shortHash()
+           << toHex(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt, 0)),
+                    sqlite3_column_bytes(stmt, 0))
+                .substr(0, 8)
            << " | "; // state hash
 
       sqlite3_stmt* stmt2;
@@ -118,8 +133,7 @@
       sqlite3_bind_int64(stmt2, 1, sqlite3_column_int64(stmt, 2));
 
       while (sqlite3_step(stmt2) == SQLITE_ROW) {
-        cout << lexical_cast<string>(
-                  Name(sqlite3_column_blob(stmt2, 0), sqlite3_column_bytes(stmt2, 0)))
+        cout << (Name(Block(sqlite3_column_blob(stmt2, 0), (sqlite3_column_bytes(stmt2, 0))))).toUri()
              << "(" << sqlite3_column_int64(stmt2, 1) << "); ";
       }
 
@@ -134,7 +148,7 @@
 class ActionLogDumper : public DbHelper
 {
 public:
-  ActionLogDumper(const filesystem::path& path)
+  ActionLogDumper(const fs::path& path)
     : DbHelper(path / ".chronoshare", "action-log.db")
   {
   }
@@ -162,7 +176,7 @@
 
     while (sqlite3_step(stmt) == SQLITE_ROW) {
       cout << setw(30)
-           << lexical_cast<string>(Name(sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0)))
+           << (Name(Block(sqlite3_column_blob(stmt, 0), (sqlite3_column_bytes(stmt, 0))))).toUri()
            << " | ";                                             // device_name
       cout << setw(6) << sqlite3_column_int64(stmt, 1) << " | "; // seq_no
       cout << setw(6) << (sqlite3_column_int(stmt, 2) == 0 ? "UPDATE" : "DELETE") << " | "; // action
@@ -171,7 +185,9 @@
 
       if (sqlite3_column_int(stmt, 2) == 0) {
         cout << setw(10)
-             << Hash(sqlite3_column_blob(stmt, 5), sqlite3_column_bytes(stmt, 5)).shortHash()
+             << toHex(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt, 5)),
+                      sqlite3_column_bytes(stmt, 5))
+                  .substr(0, 8)
              << " | ";
         cout << setw(7) << sqlite3_column_int64(stmt, 6) << " | "; // seg_num
       }
@@ -179,8 +195,8 @@
         cout << "           |         | ";
 
       if (sqlite3_column_bytes(stmt, 7) > 0) {
-        cout << setw(30) << lexical_cast<string>(
-                              Name(sqlite3_column_blob(stmt, 7), sqlite3_column_bytes(stmt, 7)))
+        cout << setw(30)
+             << (Name(Block(sqlite3_column_blob(stmt, 7), (sqlite3_column_bytes(stmt, 7))))).toUri()
              << " | ";                                    // parent_device_name
         cout << setw(5) << sqlite3_column_int64(stmt, 8); // seq_no
       }
@@ -194,45 +210,50 @@
   }
 
   void
-  DumpActionData(const Ccnx::Name& deviceName, int64_t seqno)
+  DumpActionData(const ndn::Name& deviceName, int64_t seqno)
   {
     sqlite3_stmt* stmt;
     sqlite3_prepare_v2(m_db,
                        "SELECT action_content_object, action_name FROM ActionLog WHERE device_name = ? and seq_no = ?",
                        -1, &stmt, 0);
-    Ccnx::CcnxCharbufPtr device_name = deviceName.toCcnxCharbuf();
-    sqlite3_bind_blob(stmt, 1, device_name->buf(), device_name->length(), SQLITE_STATIC);
+    const ndn::Block nameBlock = deviceName.wireEncode();
+    sqlite3_bind_blob(stmt, 1, nameBlock.wire(), nameBlock.size(), SQLITE_STATIC);
     sqlite3_bind_int64(stmt, 2, seqno);
     cout << "Dumping action data for: [" << deviceName << ", " << seqno << "]" << endl;
     if (sqlite3_step(stmt) == SQLITE_ROW) {
-      PcoPtr pco = make_shared<ParsedContentObject>(reinterpret_cast<const unsigned char*>(
-                                                      sqlite3_column_blob(stmt, 0)),
-                                                    sqlite3_column_bytes(stmt, 0));
-      Ccnx::Name actionName = Ccnx::Name(sqlite3_column_blob(stmt, 1), sqlite3_column_bytes(stmt, 0));
-      if (pco) {
-        ActionItemPtr action = deserializeMsg<ActionItem>(pco->content());
+      ndn::shared_ptr<ndn::Data> data = ndn::make_shared<ndn::Data>(
+        ndn::Block(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt, 0)),
+                   sqlite3_column_bytes(stmt, 0)));
+      ndn::Name actionName =
+        Name(Block(sqlite3_column_blob(stmt, 1), (sqlite3_column_bytes(stmt, 1))));
+      if (data) {
+        ActionItemPtr action = deserializeMsg<ActionItem>(
+          ndn::Buffer(data->getContent().value(), data->getContent().value_size()));
         if (action) {
-          cout << "Action data size : " << pco->content().size() << endl;
+          cout << "Action data size : " << data->getContent().size() << endl;
           cout << "Action data name : " << actionName << endl;
-          string type = action->action() == ActionItem::UPDATE ? "UPDATE" : "DELETE";
+          std::string type = action->action() == ActionItem::UPDATE ? "UPDATE" : "DELETE";
           cout << "Action Type = " << type << endl;
           cout << "Timestamp = " << action->timestamp() << endl;
-          string filename = action->filename();
+          std::string filename = action->filename();
           cout << "Filename = " << filename << endl;
           if (action->has_seg_num()) {
             cout << "Segment number = " << action->seg_num() << endl;
           }
           if (action->has_file_hash()) {
-            cout << "File hash = " << Hash(action->file_hash().c_str(), action->file_hash().size())
+            cout << "File hash = "
+                 << toHex(reinterpret_cast<const uint8_t*>(action->file_hash().data()),
+                          action->file_hash().size())
+                      .substr(0, 8)
                  << endl;
           }
         }
         else {
-          cerr << "Error! Failed to parse action from pco! " << endl;
+          cerr << "Error! Failed to parse action from data! " << endl;
         }
       }
       else {
-        cerr << "Error! Invalid pco! " << endl;
+        cerr << "Error! Invalid data! " << endl;
       }
     }
     else {
@@ -245,7 +266,7 @@
 class FileStateDumper : public DbHelper
 {
 public:
-  FileStateDumper(const filesystem::path& path)
+  FileStateDumper(const fs::path& path)
     : DbHelper(path / ".chronoshare", "file-state.db")
   {
   }
@@ -272,11 +293,14 @@
     while (sqlite3_step(stmt) == SQLITE_ROW) {
       cout << setw(40) << sqlite3_column_text(stmt, 0) << " | ";
       cout << setw(30)
-           << lexical_cast<string>(Name(sqlite3_column_blob(stmt, 1), sqlite3_column_bytes(stmt, 1)))
+           << Name(Block(sqlite3_column_blob(stmt, 1), (sqlite3_column_bytes(stmt, 1)))).toUri()
            << " | ";
       cout << setw(6) << sqlite3_column_int64(stmt, 2) << " | ";
       cout << setw(10)
-           << Hash(sqlite3_column_blob(stmt, 3), sqlite3_column_bytes(stmt, 3)).shortHash() << " | ";
+           << toHex(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt, 3)),
+                    sqlite3_column_bytes(stmt, 3))
+                .substr(0, 8)
+           << " | ";
       cout << setw(6) << sqlite3_column_int64(stmt, 6) << " | ";
       if (sqlite3_column_bytes(stmt, 7) == 0)
         cout << setw(20) << "<NULL>"
@@ -297,13 +321,13 @@
 int
 main(int argc, char* argv[])
 {
-  if (argc != 3 && !(argc == 5 && string(argv[1]) == "action")) {
+  if (argc != 3 && !(argc == 5 && std::string(argv[1]) == "action")) {
     cerr << "Usage: ./dump-db state|action|file|all <path-to-shared-folder>" << endl;
     cerr << "   or: ./dump-db action <path-to-shared-folder> <device-name> <seq-no>" << endl;
     return 1;
   }
 
-  string type = argv[1];
+  std::string type = argv[1];
   if (type == "state") {
     StateLogDumper dumper(argv[2]);
     dumper.DumpState();
@@ -312,7 +336,7 @@
   else if (type == "action") {
     ActionLogDumper dumper(argv[2]);
     if (argc == 5) {
-      dumper.DumpActionData(string(argv[3]), boost::lexical_cast<int64_t>(argv[4]));
+      dumper.DumpActionData(std::string(argv[3]), boost::lexical_cast<int64_t>(argv[4]));
     }
     else {
       dumper.Dump();
@@ -345,6 +369,14 @@
     return 1;
   }
 
-
   return 0;
 }
+
+} // namespace chronoshare
+} // namespace ndn
+
+int
+main(int argc, char* argv[])
+{
+  return ndn::chronoshare::main(argc, argv);
+}
diff --git a/wscript b/wscript
index 2195feb..5a9ebf4 100644
--- a/wscript
+++ b/wscript
@@ -191,22 +191,21 @@
 #         bld.install_files("${DATADIR}/ChronoShare", "gui/images/chronoshare-big.png")
     Logs.error("ChronoShare app compilation is temporary disabled")
 
-#     cmdline = bld(
-#         target = "csd",
-#         features = "qt5 cxx cxxprogram",
-#         defines = "WAF",
-#         source = bld.path.ant_glob(['cmd/csd.cpp']),
-#         use = "fs_watcher chronoshare http_server QT5CORE",
-#     )
-    Logs.error("csd app compilation is temporary disabled")
+    cmdline = bld(
+        target = "csd",
+        features = "qt5 cxx cxxprogram",
+        defines = "WAF",
+        source = 'cmd/csd.cpp',
+        moc = 'cmd/csd.hpp',
+        use = "fs-watcher chronoshare http_server QT5CORE",
+    )
 
-#     dump_db = bld(
-#         target = "dump-db",
-#         features = "cxx cxxprogram",
-#         source = bld.path.ant_glob(['cmd/dump-db.cpp']),
-#         use = "fs_watcher chronoshare http_server QT5CORE",
-#         )
-    Logs.error("dump-db app compilation is temporary disabled")
+    dump_db = bld(
+        target = "dump-db",
+        features = "cxx cxxprogram",
+        source = bld.path.ant_glob(['cmd/dump-db.cpp']),
+        use = "fs-watcher chronoshare http_server QT5CORE",
+        )
 
     bld.recurse('tests');