peek: add --hop-limit option

Change-Id: I1d0179f498ce70166085e6934e015ff4c00b4858
diff --git a/manpages/ndnpeek.rst b/manpages/ndnpeek.rst
index bebfbd1..0c3eb81 100644
--- a/manpages/ndnpeek.rst
+++ b/manpages/ndnpeek.rst
@@ -4,7 +4,8 @@
 Synopsis
 --------
 
-**ndnpeek** [-h] [-P] [-f] [-l *lifetime*] [-A *parameters*] [-p] [-w *timeout*] [-v] [-V] *name*
+**ndnpeek** [-h] [-P] [-f] [-l *lifetime*] [-H *hops*] [-A *parameters*]
+[-p] [-w *timeout*] [-v] [-V] *name*
 
 Description
 -----------
@@ -33,6 +34,9 @@
 ``-l, --lifetime <lifetime>``
   Set ``lifetime`` (in milliseconds) as the ``InterestLifetime``.
 
+``-H, --hop-limit <hops>``
+  Set the Interest's ``HopLimit`` to the specified number of hops.
+
 ``-A, --app-params <parameters>``
   Set the Interest's ``ApplicationParameters`` from a base64-encoded string.
 
diff --git a/tests/peek/ndnpeek.t.cpp b/tests/peek/ndnpeek.t.cpp
index f144d5a..3d72664 100644
--- a/tests/peek/ndnpeek.t.cpp
+++ b/tests/peek/ndnpeek.t.cpp
@@ -154,7 +154,8 @@
   BOOST_CHECK_EQUAL(face.sentInterests.back().getMustBeFresh(), false);
   BOOST_CHECK_EQUAL(face.sentInterests.back().getForwardingHint().empty(), true);
   BOOST_CHECK_EQUAL(face.sentInterests.back().getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
-  BOOST_CHECK_EQUAL(face.sentInterests.back().hasApplicationParameters(), false);
+  BOOST_CHECK(face.sentInterests.back().getHopLimit() == nullopt);
+  BOOST_CHECK(!face.sentInterests.back().hasApplicationParameters());
   BOOST_CHECK(peek->getResult() == NdnPeek::Result::DATA);
 }
 
@@ -164,6 +165,7 @@
   options.canBePrefix = true;
   options.mustBeFresh = true;
   options.interestLifetime = 200_ms;
+  options.hopLimit = 64;
   initialize(options);
 
   auto data = makeData(Name(options.name).append("suffix"));
@@ -184,7 +186,8 @@
   BOOST_CHECK_EQUAL(face.sentInterests.back().getMustBeFresh(), true);
   BOOST_CHECK_EQUAL(face.sentInterests.back().getForwardingHint().empty(), true);
   BOOST_CHECK_EQUAL(face.sentInterests.back().getInterestLifetime(), 200_ms);
-  BOOST_CHECK_EQUAL(face.sentInterests.back().hasApplicationParameters(), false);
+  BOOST_CHECK(face.sentInterests.back().getHopLimit() == 64);
+  BOOST_CHECK(!face.sentInterests.back().hasApplicationParameters());
   BOOST_CHECK(peek->getResult() == NdnPeek::Result::DATA);
 }
 
diff --git a/tools/peek/ndnpeek/main.cpp b/tools/peek/ndnpeek/main.cpp
index 89b2222..5a8bc19 100644
--- a/tools/peek/ndnpeek/main.cpp
+++ b/tools/peek/ndnpeek/main.cpp
@@ -84,6 +84,7 @@
     ("link-file",  po::value<std::string>(), "set ForwardingHint from a raw binary file")
     ("lifetime,l", po::value<time::milliseconds::rep>()->default_value(options.interestLifetime.count()),
                    "set InterestLifetime, in milliseconds")
+    ("hop-limit,H",     po::value<int>(), "set HopLimit")
     ("app-params,A",    po::value<std::string>(), "set ApplicationParameters from a base64-encoded string")
     ("app-params-file", po::value<std::string>(), "set ApplicationParameters from a file")
   ;
@@ -158,10 +159,19 @@
 
   options.interestLifetime = time::milliseconds(vm["lifetime"].as<time::milliseconds::rep>());
   if (options.interestLifetime < 0_ms) {
-    std::cerr << "ERROR: lifetime cannot be negative" << std::endl;
+    std::cerr << "ERROR: InterestLifetime cannot be negative" << std::endl;
     return 2;
   }
 
+  if (vm.count("hop-limit") > 0) {
+    auto hopLimit = vm["hop-limit"].as<int>();
+    if (hopLimit < 0 || hopLimit > 255) {
+      std::cerr << "ERROR: HopLimit must be between 0 and 255" << std::endl;
+      return 2;
+    }
+    options.hopLimit = static_cast<uint8_t>(hopLimit);
+  }
+
   if (vm.count("app-params") > 0) {
     if (vm.count("app-params-file") > 0) {
       std::cerr << "ERROR: cannot specify both '--app-params' and '--app-params-file'" << std::endl;
diff --git a/tools/peek/ndnpeek/ndnpeek.cpp b/tools/peek/ndnpeek/ndnpeek.cpp
index 7bcb137..cc9286c 100644
--- a/tools/peek/ndnpeek/ndnpeek.cpp
+++ b/tools/peek/ndnpeek/ndnpeek.cpp
@@ -63,10 +63,11 @@
   Interest interest(m_options.name);
   interest.setCanBePrefix(m_options.canBePrefix);
   interest.setMustBeFresh(m_options.mustBeFresh);
-  interest.setInterestLifetime(m_options.interestLifetime);
   if (m_options.link) {
     interest.setForwardingHint(m_options.link->getDelegationList());
   }
+  interest.setInterestLifetime(m_options.interestLifetime);
+  interest.setHopLimit(m_options.hopLimit);
   if (m_options.applicationParameters) {
     interest.setApplicationParameters(m_options.applicationParameters);
   }
diff --git a/tools/peek/ndnpeek/ndnpeek.hpp b/tools/peek/ndnpeek/ndnpeek.hpp
index 357597e..998d049 100644
--- a/tools/peek/ndnpeek/ndnpeek.hpp
+++ b/tools/peek/ndnpeek/ndnpeek.hpp
@@ -49,6 +49,7 @@
   bool mustBeFresh = false;
   shared_ptr<Link> link;
   time::milliseconds interestLifetime = DEFAULT_INTEREST_LIFETIME;
+  optional<uint8_t> hopLimit;
   shared_ptr<Buffer> applicationParameters;
 
   // program behavior options