ndn-tlv-peek: simple consumer program that sends one interest and expects one response
refs: #1349

Change-Id: I5b98baf63ffdea5ec1c9bf1e98953e2035339e41
diff --git a/tools/ndn-tlv-peek.cpp b/tools/ndn-tlv-peek.cpp
new file mode 100644
index 0000000..8ed429d
--- /dev/null
+++ b/tools/ndn-tlv-peek.cpp
@@ -0,0 +1,257 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2014 University of Arizona.
+ *
+ * Author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
+ */
+ 
+#include <boost/asio.hpp>
+
+#include <ndn-cpp-dev/face.hpp>
+
+namespace ndntlvpeek {
+
+class NdnTlvPeek
+{
+public:
+  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)
+    , m_ioService(new boost::asio::io_service)
+    , m_face(m_ioService)
+  {
+  }
+
+  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 milliseconds\n"
+      "   [-p]          - print payload only, not full packet\n"
+      "   [-w timeout]  - set Timeout in milliseconds\n"
+      "   [-h]          - print help 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 = interestLifetime;
+  }
+
+  void
+  setPayloadOnly()
+  {
+    m_isPayloadOnlySet = true;
+  }
+
+  void
+  setTimeout(int timeout)
+  {
+    if (timeout < 0)
+      usage();
+    m_timeout = timeout;
+  }
+
+  void
+  setPrefixName(char* prefixName)
+  {
+    m_prefixName = prefixName;
+    if (m_prefixName.length() == 0)
+      usage();
+  }
+
+  int
+  getDefaultInterestLifetime()
+  {
+    return 4000;
+  }
+
+  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 < 0)
+      interestPacket.setInterestLifetime(getDefaultInterestLifetime());
+    else
+      interestPacket.setInterestLifetime(m_interestLifetime);
+    return interestPacket;
+  }
+
+  void
+  onData(const ndn::Interest& interest, ndn::Data& data)
+  {
+    int returnValue;
+    m_isDataReceived = true;
+    if (m_isPayloadOnlySet)
+      {
+        ndn::Block block = data.getContent();
+        returnValue = write(1, block.value(), block.value_size());
+      }
+    else
+      {
+        ndn::Block block = data.wireEncode();
+        returnValue = write(1, block.wire(), block.size());
+      }
+  }
+
+  void
+  onTimeout(const ndn::Interest& interest)
+  {
+  }
+
+  void
+  run()
+  {
+    try
+      {
+        m_face.expressInterest(createInterestPacket(),
+                               ndn::func_lib::bind(&NdnTlvPeek::onData,
+                                                   this, _1, _2),
+                               ndn::func_lib::bind(&NdnTlvPeek::onTimeout,
+                                                   this, _1));
+        if (m_timeout < 0)
+          {
+            if (m_interestLifetime < 0)
+              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;
+  int m_interestLifetime;
+  bool m_isPayloadOnlySet;
+  int m_timeout;
+  std::string m_prefixName;
+  bool m_isDataReceived;
+  ndn::ptr_lib::shared_ptr<boost::asio::io_service> m_ioService;
+  ndn::Face m_face;
+};
+
+}
+
+int
+main(int argc, char* argv[])
+{
+  int option;
+  ndntlvpeek::NdnTlvPeek ndnTlvPeek (argv[0]);
+  while ((option = getopt(argc, argv, "hfrm:M:l:pw:")) != -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;
+        default:
+          ndnTlvPeek.usage();
+      }
+    }
+
+  argc -= optind;
+  argv += optind;
+
+  if (argv[0] == 0)
+    ndnTlvPeek.usage();
+
+  ndnTlvPeek.setPrefixName(argv[0]);
+  ndnTlvPeek.run();
+
+  if (ndnTlvPeek.isDataReceived())
+    return 0;
+  else
+    return 1;
+}