peek: import code from NFD repository

This is an exact copy of code from NFD:commit:2231ab526f9f04a568116b624ca18a8ffa7dc91a

refs #2525

Change-Id: I3fc3cea6472a679d863409716fb5024b9f263b97
diff --git a/tools/peek/ndn-peek.cpp b/tools/peek/ndn-peek.cpp
new file mode 100644
index 0000000..5460096
--- /dev/null
+++ b/tools/peek/ndn-peek.cpp
@@ -0,0 +1,279 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014,  Regents of the University of California,
+ *                      Arizona Board of Regents,
+ *                      Colorado State University,
+ *                      University Pierre & Marie Curie, Sorbonne University,
+ *                      Washington University in St. Louis,
+ *                      Beijing Institute of Technology,
+ *                      The University of Memphis
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD 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.
+ *
+ * NFD 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
+ * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
+ */
+
+#include "version.hpp"
+
+#include <boost/noncopyable.hpp>
+
+#include <ndn-cxx/face.hpp>
+
+namespace ndntlvpeek {
+
+class NdnTlvPeek : boost::noncopyable
+{
+public:
+  explicit
+  NdnTlvPeek(char* programName)
+    : m_programName(programName)
+    , m_mustBeFresh(false)
+    , m_isChildSelectorRightmost(false)
+    , m_minSuffixComponents(-1)
+    , m_maxSuffixComponents(-1)
+    , m_interestLifetime(-1)
+    , m_isPayloadOnlySet(false)
+    , m_timeout(-1)
+    , m_prefixName("")
+    , m_isDataReceived(false)
+  {
+  }
+
+  void
+  usage()
+  {
+    std::cout << "\n Usage:\n " << m_programName << " "
+      "[-f] [-r] [-m min] [-M max] [-l lifetime] [-p] [-w timeout] ndn:/name\n"
+      "   Get one data item matching the name prefix and write it to stdout\n"
+      "   [-f]          - set MustBeFresh\n"
+      "   [-r]          - set ChildSelector to select rightmost child\n"
+      "   [-m min]      - set MinSuffixComponents\n"
+      "   [-M max]      - set MaxSuffixComponents\n"
+      "   [-l lifetime] - set InterestLifetime in time::milliseconds\n"
+      "   [-p]          - print payload only, not full packet\n"
+      "   [-w timeout]  - set Timeout in time::milliseconds\n"
+      "   [-h]          - print help and exit\n"
+      "   [-V]          - print version and exit\n"
+      "\n";
+    exit(1);
+  }
+
+  void
+  setMustBeFresh()
+  {
+    m_mustBeFresh = true;
+  }
+
+  void
+  setRightmostChildSelector()
+  {
+    m_isChildSelectorRightmost = true;
+  }
+
+  void
+  setMinSuffixComponents(int minSuffixComponents)
+  {
+    if (minSuffixComponents < 0)
+      usage();
+    m_minSuffixComponents = minSuffixComponents;
+  }
+
+  void
+  setMaxSuffixComponents(int maxSuffixComponents)
+  {
+    if (maxSuffixComponents < 0)
+      usage();
+    m_maxSuffixComponents = maxSuffixComponents;
+  }
+
+  void
+  setInterestLifetime(int interestLifetime)
+  {
+    if (interestLifetime < 0)
+      usage();
+    m_interestLifetime = ndn::time::milliseconds(interestLifetime);
+  }
+
+  void
+  setPayloadOnly()
+  {
+    m_isPayloadOnlySet = true;
+  }
+
+  void
+  setTimeout(int timeout)
+  {
+    if (timeout < 0)
+      usage();
+    m_timeout = ndn::time::milliseconds(timeout);
+  }
+
+  void
+  setPrefixName(char* prefixName)
+  {
+    m_prefixName = prefixName;
+    if (m_prefixName.length() == 0)
+      usage();
+  }
+
+  ndn::time::milliseconds
+  getDefaultInterestLifetime()
+  {
+    return ndn::time::seconds(4);
+  }
+
+  ndn::Interest
+  createInterestPacket()
+  {
+    ndn::Name interestName(m_prefixName);
+    ndn::Interest interestPacket(interestName);
+    if (m_mustBeFresh)
+      interestPacket.setMustBeFresh(true);
+    if (m_isChildSelectorRightmost)
+      interestPacket.setChildSelector(1);
+    if (m_minSuffixComponents >= 0)
+      interestPacket.setMinSuffixComponents(m_minSuffixComponents);
+    if (m_maxSuffixComponents >= 0)
+      interestPacket.setMaxSuffixComponents(m_maxSuffixComponents);
+    if (m_interestLifetime < ndn::time::milliseconds::zero())
+      interestPacket.setInterestLifetime(getDefaultInterestLifetime());
+    else
+      interestPacket.setInterestLifetime(m_interestLifetime);
+    return interestPacket;
+  }
+
+  void
+  onData(const ndn::Interest& interest, ndn::Data& data)
+  {
+    m_isDataReceived = true;
+    if (m_isPayloadOnlySet)
+      {
+        const ndn::Block& block = data.getContent();
+        std::cout.write(reinterpret_cast<const char*>(block.value()), block.value_size());
+      }
+    else
+      {
+        const ndn::Block& block = data.wireEncode();
+        std::cout.write(reinterpret_cast<const char*>(block.wire()), block.size());
+      }
+  }
+
+  void
+  onTimeout(const ndn::Interest& interest)
+  {
+  }
+
+  void
+  run()
+  {
+    try
+      {
+        m_face.expressInterest(createInterestPacket(),
+                               bind(&NdnTlvPeek::onData, this, _1, _2),
+                               bind(&NdnTlvPeek::onTimeout, this, _1));
+        if (m_timeout < ndn::time::milliseconds::zero())
+          {
+            if (m_interestLifetime < ndn::time::milliseconds::zero())
+              m_face.processEvents(getDefaultInterestLifetime());
+            else
+              m_face.processEvents(m_interestLifetime);
+          }
+        else
+          m_face.processEvents(m_timeout);
+      }
+    catch (std::exception& e)
+      {
+        std::cerr << "ERROR: " << e.what() << "\n" << std::endl;
+        exit(1);
+      }
+  }
+
+  bool
+  isDataReceived() const
+  {
+    return m_isDataReceived;
+  }
+
+private:
+
+  std::string m_programName;
+  bool m_mustBeFresh;
+  bool m_isChildSelectorRightmost;
+  int m_minSuffixComponents;
+  int m_maxSuffixComponents;
+  ndn::time::milliseconds m_interestLifetime;
+  bool m_isPayloadOnlySet;
+  ndn::time::milliseconds m_timeout;
+  std::string m_prefixName;
+  bool m_isDataReceived;
+  ndn::Face m_face;
+};
+
+}
+
+int
+main(int argc, char* argv[])
+{
+  ndntlvpeek::NdnTlvPeek ndnTlvPeek(argv[0]);
+  int option;
+  while ((option = getopt(argc, argv, "hfrm:M:l:pw:V")) != -1) {
+    switch (option) {
+    case 'h':
+      ndnTlvPeek.usage();
+      break;
+    case 'f':
+      ndnTlvPeek.setMustBeFresh();
+      break;
+    case 'r':
+      ndnTlvPeek.setRightmostChildSelector();
+      break;
+    case 'm':
+      ndnTlvPeek.setMinSuffixComponents(atoi(optarg));
+      break;
+    case 'M':
+      ndnTlvPeek.setMaxSuffixComponents(atoi(optarg));
+      break;
+    case 'l':
+      ndnTlvPeek.setInterestLifetime(atoi(optarg));
+      break;
+    case 'p':
+      ndnTlvPeek.setPayloadOnly();
+      break;
+    case 'w':
+      ndnTlvPeek.setTimeout(atoi(optarg));
+      break;
+    case 'V':
+      std::cout << NFD_VERSION_BUILD_STRING << std::endl;
+      return 0;
+    default:
+      ndnTlvPeek.usage();
+      break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argv[0] == 0)
+    ndnTlvPeek.usage();
+
+  ndnTlvPeek.setPrefixName(argv[0]);
+  ndnTlvPeek.run();
+
+  if (ndnTlvPeek.isDataReceived())
+    return 0;
+  else
+    return 1;
+}
diff --git a/tools/peek/ndn-poke.cpp b/tools/peek/ndn-poke.cpp
new file mode 100644
index 0000000..45db702
--- /dev/null
+++ b/tools/peek/ndn-poke.cpp
@@ -0,0 +1,277 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014,  Regents of the University of California,
+ *                      Arizona Board of Regents,
+ *                      Colorado State University,
+ *                      University Pierre & Marie Curie, Sorbonne University,
+ *                      Washington University in St. Louis,
+ *                      Beijing Institute of Technology,
+ *                      The University of Memphis
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD 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.
+ *
+ * NFD 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
+ * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
+ */
+
+#include "version.hpp"
+
+#include <boost/noncopyable.hpp>
+
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
+
+namespace ndntlvpoke {
+
+class NdnTlvPoke : boost::noncopyable
+{
+public:
+  explicit
+  NdnTlvPoke(char* programName)
+    : m_programName(programName)
+    , m_isForceDataSet(false)
+    , m_isUseDigestSha256Set(false)
+    , m_isLastAsFinalBlockIdSet(false)
+    , m_freshnessPeriod(-1)
+    , m_timeout(-1)
+    , m_isDataSent(false)
+  {
+  }
+
+  void
+  usage()
+  {
+    std::cout << "\n Usage:\n " << m_programName << " "
+      "[-f] [-D] [-i identity] [-F] [-x freshness] [-w timeout] ndn:/name\n"
+      "   Reads payload from stdin and sends it to local NDN forwarder as a "
+      "single Data packet\n"
+      "   [-f]          - force, send Data without waiting for Interest\n"
+      "   [-D]          - use DigestSha256 signing method instead of "
+      "SignatureSha256WithRsa\n"
+      "   [-i identity] - set identity to be used for signing\n"
+      "   [-F]          - set FinalBlockId to the last component of Name\n"
+      "   [-x]          - set FreshnessPeriod in time::milliseconds\n"
+      "   [-w timeout]  - set Timeout in time::milliseconds\n"
+      "   [-h]          - print help and exit\n"
+      "   [-V]          - print version and exit\n"
+      "\n";
+    exit(1);
+  }
+
+  void
+  setForceData()
+  {
+    m_isForceDataSet = true;
+  }
+
+  void
+  setUseDigestSha256()
+  {
+    m_isUseDigestSha256Set = true;
+  }
+
+  void
+  setIdentityName(char* identityName)
+  {
+    m_identityName = ndn::make_shared<ndn::Name>(identityName);
+  }
+
+  void
+  setLastAsFinalBlockId()
+  {
+    m_isLastAsFinalBlockIdSet = true;
+  }
+
+  void
+  setFreshnessPeriod(int freshnessPeriod)
+  {
+    if (freshnessPeriod < 0)
+      usage();
+    m_freshnessPeriod = ndn::time::milliseconds(freshnessPeriod);
+  }
+
+  void
+  setTimeout(int timeout)
+  {
+    if (timeout < 0)
+      usage();
+    m_timeout = ndn::time::milliseconds(timeout);
+  }
+
+  void
+  setPrefixName(char* prefixName)
+  {
+    m_prefixName = ndn::Name(prefixName);
+  }
+
+  ndn::time::milliseconds
+  getDefaultTimeout()
+  {
+    return ndn::time::seconds(10);
+  }
+
+  ndn::Data
+  createDataPacket()
+  {
+    ndn::Data dataPacket(m_prefixName);
+    std::stringstream payloadStream;
+    payloadStream << std::cin.rdbuf();
+    std::string payload = payloadStream.str();
+    dataPacket.setContent(reinterpret_cast<const uint8_t*>(payload.c_str()), payload.length());
+    if (m_freshnessPeriod >= ndn::time::milliseconds::zero())
+      dataPacket.setFreshnessPeriod(m_freshnessPeriod);
+    if (m_isLastAsFinalBlockIdSet)
+      {
+        if (!m_prefixName.empty())
+          dataPacket.setFinalBlockId(m_prefixName.get(-1));
+        else
+          {
+            std::cerr << "Name Provided Has 0 Components" << std::endl;
+            exit(1);
+          }
+      }
+    if (m_isUseDigestSha256Set)
+      m_keyChain.signWithSha256(dataPacket);
+    else
+      {
+        if (!static_cast<bool>(m_identityName))
+          m_keyChain.sign(dataPacket);
+        else
+          m_keyChain.signByIdentity(dataPacket, *m_identityName);
+      }
+    return dataPacket;
+  }
+
+  void
+  onInterest(const ndn::Name& name,
+             const ndn::Interest& interest,
+             const ndn::Data& dataPacket)
+  {
+    m_face.put(dataPacket);
+    m_isDataSent = true;
+    m_face.shutdown();
+  }
+
+  void
+  onRegisterFailed(const ndn::Name& prefix, const std::string& reason)
+  {
+    std::cerr << "Prefix Registration Failure." << std::endl;
+    std::cerr << "Reason = " << reason << std::endl;
+  }
+
+  void
+  run()
+  {
+    try
+      {
+        ndn::Data dataPacket = createDataPacket();
+        if (m_isForceDataSet)
+          {
+            m_face.put(dataPacket);
+            m_isDataSent = true;
+          }
+        else
+          {
+            m_face.setInterestFilter(m_prefixName,
+                                     bind(&NdnTlvPoke::onInterest, this, _1, _2, dataPacket),
+                                     ndn::RegisterPrefixSuccessCallback(),
+                                     bind(&NdnTlvPoke::onRegisterFailed, this, _1, _2));
+          }
+        if (m_timeout < ndn::time::milliseconds::zero())
+          m_face.processEvents(getDefaultTimeout());
+        else
+          m_face.processEvents(m_timeout);
+      }
+    catch (std::exception& e)
+      {
+        std::cerr << "ERROR: " << e.what() << "\n" << std::endl;
+        exit(1);
+      }
+  }
+
+  bool
+  isDataSent() const
+  {
+    return m_isDataSent;
+  }
+
+private:
+
+  ndn::KeyChain m_keyChain;
+  std::string m_programName;
+  bool m_isForceDataSet;
+  bool m_isUseDigestSha256Set;
+  ndn::shared_ptr<ndn::Name> m_identityName;
+  bool m_isLastAsFinalBlockIdSet;
+  ndn::time::milliseconds m_freshnessPeriod;
+  ndn::time::milliseconds m_timeout;
+  ndn::Name m_prefixName;
+  bool m_isDataSent;
+  ndn::Face m_face;
+
+};
+
+}
+
+int
+main(int argc, char* argv[])
+{
+  int option;
+  ndntlvpoke::NdnTlvPoke ndnTlvPoke(argv[0]);
+  while ((option = getopt(argc, argv, "hfDi:Fx:w:V")) != -1) {
+    switch (option) {
+    case 'h':
+      ndnTlvPoke.usage();
+      break;
+    case 'f':
+      ndnTlvPoke.setForceData();
+      break;
+    case 'D':
+      ndnTlvPoke.setUseDigestSha256();
+      break;
+    case 'i':
+      ndnTlvPoke.setIdentityName(optarg);
+      break;
+    case 'F':
+      ndnTlvPoke.setLastAsFinalBlockId();
+      break;
+    case 'x':
+      ndnTlvPoke.setFreshnessPeriod(atoi(optarg));
+      break;
+    case 'w':
+      ndnTlvPoke.setTimeout(atoi(optarg));
+      break;
+    case 'V':
+      std::cout << NFD_VERSION_BUILD_STRING << std::endl;
+      return 0;
+    default:
+      ndnTlvPoke.usage();
+      break;
+    }
+  }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argv[0] == 0)
+    ndnTlvPoke.usage();
+
+  ndnTlvPoke.setPrefixName(argv[0]);
+  ndnTlvPoke.run();
+
+  if (ndnTlvPoke.isDataSent())
+    return 0;
+  else
+    return 1;
+}
diff --git a/tools/peek/version.hpp b/tools/peek/version.hpp
new file mode 100644
index 0000000..4baf76e
--- /dev/null
+++ b/tools/peek/version.hpp
@@ -0,0 +1,74 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014,  Regents of the University of California,
+ *                      Arizona Board of Regents,
+ *                      Colorado State University,
+ *                      University Pierre & Marie Curie, Sorbonne University,
+ *                      Washington University in St. Louis,
+ *                      Beijing Institute of Technology,
+ *                      The University of Memphis
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD 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.
+ *
+ * NFD 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
+ * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NFD_VERSION_HPP
+#define NFD_VERSION_HPP
+
+namespace nfd {
+
+/** NFD version follows Semantic Versioning 2.0.0 specification
+ *  http://semver.org/
+ */
+
+// To change version number, modify VERSION variable in top-level wscript.
+
+/** \brief NFD version represented as an integer
+ *
+ *  MAJOR*1000000 + MINOR*1000 + PATCH
+ */
+#define NFD_VERSION 3001
+
+/** \brief NFD version represented as a string
+ *
+ *  MAJOR.MINOR.PATCH
+ */
+#define NFD_VERSION_STRING "0.3.1"
+
+/** \brief NFD version string, including git commit information, if NFD is build from
+ *         specific git commit
+ *
+ * NFD_VERSION_BUILD_STRING is obtained using the following command (`NFD-` prefix is
+ * afterwards removed):
+ *
+ *    `git describe --match 'NFD-*'`
+ *
+ * When NFD is built not from git, NFD_VERSION_BUILD_STRING equals NFD_VERSION_STRING
+ *
+ * MAJOR.MINOR.PATCH(-release-candidate-tag)(-(number-of-commits-since-tag)-COMMIT-HASH)
+ *
+ * Example, 0.1.0-rc1-1-g5c86570
+ */
+#define NFD_VERSION_BUILD_STRING "0.3.1-7-g2231ab5"
+
+/// MAJOR version
+#define NFD_VERSION_MAJOR 0
+/// MINOR version
+#define NFD_VERSION_MINOR 3
+/// PATCH version
+#define NFD_VERSION_PATCH 1
+
+} // namespace nfd
+
+#endif // NFD_VERSION_HPP
diff --git a/tools/peek/wscript b/tools/peek/wscript
new file mode 100644
index 0000000..99b874e
--- /dev/null
+++ b/tools/peek/wscript
@@ -0,0 +1,17 @@
+# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+top = '../..'
+
+def build(bld):
+    bld.program(
+        features='cxx',
+        target='../../bin/ndnpeek',
+        source='ndn-peek.cpp',
+        use='core-objects',
+        )
+
+    bld.program(
+        features='cxx',
+        target='../../bin/ndnpoke',
+        source='ndn-poke.cpp',
+        use='core-objects',
+        )