peek: Refactor ndnpeek and add unit tests
Change-Id: Ib34c4431bdc268c5a7ef2fccf0946b0d19d69ab6
Refs: #3558
diff --git a/tools/peek/ndn-peek.cpp b/tools/peek/ndn-peek.cpp
deleted file mode 100644
index f1d1d6f..0000000
--- a/tools/peek/ndn-peek.cpp
+++ /dev/null
@@ -1,358 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016, 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 ndn-tools (Named Data Networking Essential Tools).
- * See AUTHORS.md for complete list of ndn-tools authors and contributors.
- *
- * ndn-tools 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.
- *
- * ndn-tools 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
- * ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- */
-/**
- * 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 "core/version.hpp"
-#include "core/common.hpp"
-
-#include <ndn-cxx/util/io.hpp>
-
-namespace ndn {
-namespace peek {
-
-class NdnPeek : boost::noncopyable
-{
-public:
- explicit
- NdnPeek(char* programName)
- : isVerbose(false)
- , mustBeFresh(false)
- , wantRightmostChild(false)
- , wantPayloadOnly(false)
- , m_programName(programName)
- , m_minSuffixComponents(-1)
- , m_maxSuffixComponents(-1)
- , m_interestLifetime(-1)
- , m_timeout(-1)
- , m_prefixName("")
- , m_didReceiveData(false)
- , m_didReceiveNack(false)
- {
- }
-
- void
- usage(std::ostream& os ,const boost::program_options::options_description& options) const
- {
- os << "Usage: " << m_programName << " [options] ndn:/name\n"
- " Fetch one data item matching the name prefix and write it to standard output\n"
- "\n"
- << options;
- }
-
- void
- setMinSuffixComponents(int minSuffixComponents)
- {
- if (minSuffixComponents < 0)
- throw std::out_of_range("'minSuffixComponents' must be a non-negative integer");
-
- m_minSuffixComponents = minSuffixComponents;
- }
-
- void
- setMaxSuffixComponents(int maxSuffixComponents)
- {
- if (maxSuffixComponents < 0)
- throw std::out_of_range("'maxSuffixComponents' must be a non-negative integer");
-
- m_maxSuffixComponents = maxSuffixComponents;
- }
-
- void
- setInterestLifetime(int interestLifetime)
- {
- if (interestLifetime < 0)
- throw std::out_of_range("'lifetime' must be a non-negative integer");
-
- m_interestLifetime = time::milliseconds(interestLifetime);
- }
-
- void
- setTimeout(int timeout)
- {
- if (timeout < 0)
- throw std::out_of_range("'timeout' must be a non-negative integer");
-
- m_timeout = time::milliseconds(timeout);
- }
-
- void
- setLink(const std::string& file)
- {
- m_link = io::load<Link>(file);
- if (m_link == nullptr)
- throw std::runtime_error(file + " is either nonreadable or nonparseable");
- }
-
- void
- setPrefixName(const std::string& prefixName)
- {
- m_prefixName = prefixName;
- }
-
- time::milliseconds
- getDefaultInterestLifetime()
- {
- return time::seconds(4);
- }
-
- Interest
- createInterestPacket()
- {
- Name interestName(m_prefixName);
- Interest interestPacket(interestName);
-
- if (mustBeFresh)
- interestPacket.setMustBeFresh(true);
-
- if (wantRightmostChild)
- interestPacket.setChildSelector(1);
-
- if (m_minSuffixComponents >= 0)
- interestPacket.setMinSuffixComponents(m_minSuffixComponents);
-
- if (m_maxSuffixComponents >= 0)
- interestPacket.setMaxSuffixComponents(m_maxSuffixComponents);
-
- if (m_interestLifetime < time::milliseconds::zero())
- interestPacket.setInterestLifetime(getDefaultInterestLifetime());
- else
- interestPacket.setInterestLifetime(m_interestLifetime);
-
- if (m_link != nullptr)
- interestPacket.setLink(m_link->wireEncode());
-
- if (isVerbose) {
- std::cerr << "INTEREST: " << interestPacket << std::endl;
- }
-
- return interestPacket;
- }
-
- void
- onData(const Interest& interest, const Data& data)
- {
- m_didReceiveData = true;
-
- if (isVerbose) {
- std::cerr << "DATA, RTT: "
- << time::duration_cast<time::milliseconds>(time::steady_clock::now() - m_expressInterestTime).count()
- << "ms" << std::endl;
- }
-
- if (wantPayloadOnly) {
- const Block& block = data.getContent();
- std::cout.write(reinterpret_cast<const char*>(block.value()), block.value_size());
- }
- else {
- const Block& block = data.wireEncode();
- std::cout.write(reinterpret_cast<const char*>(block.wire()), block.size());
- }
- }
-
- void
- onNack(const Interest& interest, const lp::Nack& nack)
- {
- m_didReceiveNack = true;
- lp::NackHeader header = nack.getHeader();
-
- if (isVerbose) {
- std::cerr << "NACK, RTT: "
- << time::duration_cast<time::milliseconds>(time::steady_clock::now() - m_expressInterestTime).count()
- << "ms" << std::endl;
- }
-
- if (wantPayloadOnly) {
- std::cout << header.getReason() << std::endl;
- }
- else {
- const Block& block = header.wireEncode();
- std::cout.write(reinterpret_cast<const char*>(block.wire()), block.size());
- }
- }
-
- void
- onTimeout(const Interest& interest)
- {
- }
-
- int
- run()
- {
- try {
- m_face.expressInterest(createInterestPacket(),
- bind(&NdnPeek::onData, this, _1, _2),
- bind(&NdnPeek::onNack, this, _1, _2),
- bind(&NdnPeek::onTimeout, this, _1));
- m_expressInterestTime = time::steady_clock::now();
- if (m_timeout < time::milliseconds::zero()) {
- m_timeout = m_interestLifetime < time::milliseconds::zero() ?
- getDefaultInterestLifetime() : m_interestLifetime;
- }
- m_face.processEvents(m_timeout);
- }
- catch (const std::exception& e) {
- std::cerr << "ERROR: " << e.what() << std::endl;
- return 1;
- }
-
- if (m_didReceiveNack)
- return 4;
-
- if (isVerbose && !m_didReceiveData) {
- std::cerr << "TIMEOUT" << std::endl;
- return 3;
- }
-
- if (!m_didReceiveData)
- return 3;
-
- return 0;
- }
-
-public:
- bool isVerbose;
- bool mustBeFresh;
- bool wantRightmostChild;
- bool wantPayloadOnly;
-
-private:
- std::string m_programName;
- int m_minSuffixComponents;
- int m_maxSuffixComponents;
- time::milliseconds m_interestLifetime;
- time::milliseconds m_timeout;
- std::string m_prefixName;
- time::steady_clock::TimePoint m_expressInterestTime;
- shared_ptr<Link> m_link;
- bool m_didReceiveData;
- bool m_didReceiveNack;
- Face m_face;
-};
-
-int
-main(int argc, char* argv[])
-{
- NdnPeek program(argv[0]);
-
- namespace po = boost::program_options;
-
- po::options_description visibleOptDesc("Allowed options");
- visibleOptDesc.add_options()
- ("help,h", "print help and exit")
- ("version,V", "print version and exit")
- ("fresh,f", po::bool_switch(&program.mustBeFresh),
- "set MustBeFresh")
- ("rightmost,r", po::bool_switch(&program.wantRightmostChild),
- "set ChildSelector to rightmost")
- ("minsuffix,m", po::value<int>()->notifier(bind(&NdnPeek::setMinSuffixComponents, &program, _1)),
- "set MinSuffixComponents")
- ("maxsuffix,M", po::value<int>()->notifier(bind(&NdnPeek::setMaxSuffixComponents, &program, _1)),
- "set MaxSuffixComponents")
- ("lifetime,l", po::value<int>()->notifier(bind(&NdnPeek::setInterestLifetime, &program, _1)),
- "set InterestLifetime (in milliseconds)")
- ("payload,p", po::bool_switch(&program.wantPayloadOnly),
- "print payload only, instead of full packet")
- ("timeout,w", po::value<int>()->notifier(bind(&NdnPeek::setTimeout, &program, _1)),
- "set timeout (in milliseconds)")
- ("verbose,v", po::bool_switch(&program.isVerbose),
- "turn on verbose output")
- ("link-file", po::value<std::string>()->notifier(bind(&NdnPeek::setLink, &program, _1)),
- "set Link from a file")
- ;
-
- po::options_description hiddenOptDesc("Hidden options");
- hiddenOptDesc.add_options()
- ("prefix", po::value<std::string>(), "Interest name");
-
- po::options_description optDesc("Allowed options");
- optDesc.add(visibleOptDesc).add(hiddenOptDesc);
-
- po::positional_options_description optPos;
- optPos.add("prefix", -1);
-
- try {
- po::variables_map vm;
- po::store(po::command_line_parser(argc, argv).options(optDesc).positional(optPos).run(), vm);
- po::notify(vm);
-
- if (vm.count("help") > 0) {
- program.usage(std::cout, visibleOptDesc);
- return 0;
- }
-
- if (vm.count("version") > 0) {
- std::cout << "ndnpeek " << tools::VERSION << std::endl;
- return 0;
- }
-
- if (vm.count("prefix") > 0) {
- std::string prefixName = vm["prefix"].as<std::string>();
- program.setPrefixName(prefixName);
- }
- else {
- throw std::runtime_error("Required argument 'prefix' is missing");
- }
- }
- catch (const std::exception& e) {
- std::cerr << "ERROR: " << e.what() << std::endl;
- program.usage(std::cerr, visibleOptDesc);
- return 2;
- }
-
- return program.run();
-}
-
-} // namespace peek
-} // namespace ndn
-
-int
-main(int argc, char** argv)
-{
- return ndn::peek::main(argc, argv);
-}
diff --git a/tools/peek/ndnpeek/main.cpp b/tools/peek/ndnpeek/main.cpp
new file mode 100644
index 0000000..774d759
--- /dev/null
+++ b/tools/peek/ndnpeek/main.cpp
@@ -0,0 +1,201 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2016, 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 ndn-tools (Named Data Networking Essential Tools).
+ * See AUTHORS.md for complete list of ndn-tools authors and contributors.
+ *
+ * ndn-tools 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.
+ *
+ * ndn-tools 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
+ * ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
+ * @author Zhuo Li <zhuoli@email.arizona.edu>
+ */
+
+#include "ndnpeek.hpp"
+#include "core/version.hpp"
+
+#include <ndn-cxx/util/io.hpp>
+
+namespace ndn {
+namespace peek {
+
+namespace po = boost::program_options;
+
+static void
+usage(std::ostream& os, const po::options_description& options)
+{
+ os << "Usage: ndnpeek [options] ndn:/name\n"
+ "\n"
+ "Fetch one data item matching the name prefix and write it to standard output.\n"
+ "\n"
+ << options;
+}
+
+static int
+main(int argc, char* argv[])
+{
+ PeekOptions options;
+ options.isVerbose = false;
+ options.mustBeFresh = false;
+ options.wantRightmostChild = false;
+ options.wantPayloadOnly = false;
+ options.minSuffixComponents = -1;
+ options.maxSuffixComponents = -1;
+ options.interestLifetime = time::milliseconds(-1);
+ options.timeout = time::milliseconds(-1);
+
+ po::options_description genericOptDesc("Generic options");
+ genericOptDesc.add_options()
+ ("help,h", "print help and exit")
+ ("payload,p", po::bool_switch(&options.wantPayloadOnly),
+ "print payload only, instead of full packet")
+ ("timeout,w", po::value<int>(),
+ "set timeout (in milliseconds)")
+ ("verbose,v", po::bool_switch(&options.isVerbose),
+ "turn on verbose output")
+ ("version,V", "print version and exit")
+ ;
+
+ po::options_description interestOptDesc("Interest construction");
+ interestOptDesc.add_options()
+ ("fresh,f", po::bool_switch(&options.mustBeFresh),
+ "set MustBeFresh")
+ ("rightmost,r", po::bool_switch(&options.wantRightmostChild),
+ "set ChildSelector to rightmost")
+ ("minsuffix,m", po::value<int>(&options.minSuffixComponents),
+ "set MinSuffixComponents")
+ ("maxsuffix,M", po::value<int>(&options.maxSuffixComponents),
+ "set MaxSuffixComponents")
+ ("lifetime,l", po::value<int>(),
+ "set InterestLifetime (in milliseconds)")
+ ("link-file", po::value<std::string>(),
+ "set Link from a file")
+ ;
+
+ po::options_description visibleOptDesc;
+ visibleOptDesc.add(genericOptDesc).add(interestOptDesc);
+
+ po::options_description hiddenOptDesc;
+ hiddenOptDesc.add_options()
+ ("prefix", po::value<std::string>(), "Interest name");
+
+ po::options_description optDesc;
+ optDesc.add(visibleOptDesc).add(hiddenOptDesc);
+
+ po::positional_options_description optPos;
+ optPos.add("prefix", -1);
+
+ po::variables_map vm;
+ try {
+ po::store(po::command_line_parser(argc, argv).options(optDesc).positional(optPos).run(), vm);
+ po::notify(vm);
+ }
+ catch (const po::error& e) {
+ std::cerr << "ERROR: " << e.what() << std::endl;
+ return 2;
+ }
+
+ if (vm.count("help") > 0) {
+ usage(std::cout, visibleOptDesc);
+ return 0;
+ }
+
+ if (vm.count("version") > 0) {
+ std::cout << "ndnpeek " << tools::VERSION << std::endl;
+ return 0;
+ }
+
+ if (vm.count("prefix") > 0) {
+ options.prefix = vm["prefix"].as<std::string>();
+ }
+ else {
+ std::cerr << "ERROR: Interest name is missing" << std::endl;
+ usage(std::cerr, visibleOptDesc);
+ return 2;
+ }
+
+ if (vm.count("minsuffix") > 0 && options.minSuffixComponents < 0) {
+ std::cerr << "ERROR: MinSuffixComponents must be a non-negative integer" << std::endl;
+ usage(std::cerr, visibleOptDesc);
+ return 2;
+ }
+
+ if (vm.count("maxsuffix") > 0 && options.maxSuffixComponents < 0) {
+ std::cerr << "ERROR: MaxSuffixComponents must be a non-negative integer" << std::endl;
+ usage(std::cerr, visibleOptDesc);
+ return 2;
+ }
+
+ if (vm.count("lifetime") > 0) {
+ if (vm["lifetime"].as<int>() >= 0) {
+ options.interestLifetime = time::milliseconds(vm["lifetime"].as<int>());
+ }
+ else {
+ std::cerr << "ERROR: InterestLifetime must be a non-negative integer" << std::endl;
+ usage(std::cerr, visibleOptDesc);
+ return 2;
+ }
+ }
+
+ if (vm.count("timeout") > 0) {
+ if (vm["timeout"].as<int>() > 0) {
+ options.timeout = time::milliseconds(vm["timeout"].as<int>());
+ }
+ else {
+ std::cerr << "ERROR: Timeout must be a positive integer" << std::endl;
+ usage(std::cerr, visibleOptDesc);
+ return 2;
+ }
+ }
+
+ if (vm.count("link-file") > 0) {
+ options.link = io::load<Link>(vm["link-file"].as<std::string>());
+ if (options.link == nullptr) {
+ std::cerr << "ERROR: Cannot read Link object from the specified file" << std::endl;
+ usage(std::cerr, visibleOptDesc);
+ return 2;
+ }
+ }
+
+ Face face;
+ NdnPeek program(face, options);
+
+ try {
+ program.start();
+ face.processEvents(program.getTimeout());
+ }
+ catch (const std::exception& e) {
+ std::cerr << "ERROR: " << e.what() << std::endl;
+ return 1;
+ }
+
+ ResultCode result = program.getResultCode();
+ if (result == ResultCode::TIMEOUT && options.isVerbose) {
+ std::cerr << "TIMEOUT" << std::endl;
+ }
+ return static_cast<int>(result);
+}
+
+} // namespace peek
+} // namespace ndn
+
+int
+main(int argc, char** argv)
+{
+ return ndn::peek::main(argc, argv);
+}
diff --git a/tools/peek/ndnpeek/ndnpeek.cpp b/tools/peek/ndnpeek/ndnpeek.cpp
new file mode 100644
index 0000000..c9f89b2
--- /dev/null
+++ b/tools/peek/ndnpeek/ndnpeek.cpp
@@ -0,0 +1,141 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2016, 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 ndn-tools (Named Data Networking Essential Tools).
+ * See AUTHORS.md for complete list of ndn-tools authors and contributors.
+ *
+ * ndn-tools 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.
+ *
+ * ndn-tools 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
+ * ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
+ * @author Zhuo Li <zhuoli@email.arizona.edu>
+ */
+
+#include "ndnpeek.hpp"
+
+namespace ndn {
+namespace peek {
+
+NdnPeek::NdnPeek(Face& face, const PeekOptions& options)
+ : m_face(face)
+ , m_options(options)
+ , m_timeout(options.timeout)
+ , m_resultCode(ResultCode::TIMEOUT)
+{
+ if (m_timeout < time::milliseconds::zero()) {
+ m_timeout = m_options.interestLifetime < time::milliseconds::zero() ?
+ DEFAULT_INTEREST_LIFETIME : m_options.interestLifetime;
+ }
+}
+
+time::milliseconds
+NdnPeek::getTimeout() const
+{
+ return m_timeout;
+}
+
+ResultCode
+NdnPeek::getResultCode() const
+{
+ return m_resultCode;
+}
+
+void
+NdnPeek::start()
+{
+ m_face.expressInterest(createInterest(),
+ bind(&NdnPeek::onData, this, _2),
+ bind(&NdnPeek::onNack, this, _2),
+ nullptr);
+ m_expressInterestTime = time::steady_clock::now();
+}
+
+Interest
+NdnPeek::createInterest() const
+{
+ Interest interest(m_options.prefix);
+
+ if (m_options.minSuffixComponents >= 0)
+ interest.setMinSuffixComponents(m_options.minSuffixComponents);
+
+ if (m_options.maxSuffixComponents >= 0)
+ interest.setMaxSuffixComponents(m_options.maxSuffixComponents);
+
+ if (m_options.interestLifetime >= time::milliseconds::zero())
+ interest.setInterestLifetime(m_options.interestLifetime);
+
+ if (m_options.link != nullptr)
+ interest.setLink(m_options.link->wireEncode());
+
+ if (m_options.mustBeFresh)
+ interest.setMustBeFresh(true);
+
+ if (m_options.wantRightmostChild)
+ interest.setChildSelector(1);
+
+ if (m_options.isVerbose) {
+ std::cerr << "INTEREST: " << interest << std::endl;
+ }
+
+ return interest;
+}
+
+void
+NdnPeek::onData(const Data& data)
+{
+ m_resultCode = ResultCode::DATA;
+
+ if (m_options.isVerbose) {
+ std::cerr << "DATA, RTT: "
+ << time::duration_cast<time::milliseconds>(time::steady_clock::now() - m_expressInterestTime).count()
+ << "ms" << std::endl;
+ }
+
+ if (m_options.wantPayloadOnly) {
+ const Block& block = data.getContent();
+ std::cout.write(reinterpret_cast<const char*>(block.value()), block.value_size());
+ }
+ else {
+ const Block& block = data.wireEncode();
+ std::cout.write(reinterpret_cast<const char*>(block.wire()), block.size());
+ }
+}
+
+void
+NdnPeek::onNack(const lp::Nack& nack)
+{
+ m_resultCode = ResultCode::NACK;
+ lp::NackHeader header = nack.getHeader();
+
+ if (m_options.isVerbose) {
+ std::cerr << "NACK, RTT: "
+ << time::duration_cast<time::milliseconds>(time::steady_clock::now() - m_expressInterestTime).count()
+ << "ms" << std::endl;
+ }
+
+ if (m_options.wantPayloadOnly) {
+ std::cout << header.getReason() << std::endl;
+ }
+ else {
+ const Block& block = header.wireEncode();
+ std::cout.write(reinterpret_cast<const char*>(block.wire()), block.size());
+ }
+}
+
+} // namespace peek
+} // namespace ndn
diff --git a/tools/peek/ndnpeek/ndnpeek.hpp b/tools/peek/ndnpeek/ndnpeek.hpp
new file mode 100644
index 0000000..2b0a85e
--- /dev/null
+++ b/tools/peek/ndnpeek/ndnpeek.hpp
@@ -0,0 +1,112 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2016, 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 ndn-tools (Named Data Networking Essential Tools).
+ * See AUTHORS.md for complete list of ndn-tools authors and contributors.
+ *
+ * ndn-tools 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.
+ *
+ * ndn-tools 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
+ * ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
+ * @author Zhuo Li <zhuoli@email.arizona.edu>
+ */
+
+#ifndef NDN_TOOLS_NDNPEEK_NDNPEEK_HPP
+#define NDN_TOOLS_NDNPEEK_NDNPEEK_HPP
+
+#include "core/common.hpp"
+
+namespace ndn {
+namespace peek {
+
+/**
+ * @brief options for NdnPeek
+ */
+struct PeekOptions
+{
+ std::string prefix;
+ int minSuffixComponents;
+ int maxSuffixComponents;
+ time::milliseconds interestLifetime;
+ time::milliseconds timeout;
+ shared_ptr<Link> link;
+ bool isVerbose;
+ bool mustBeFresh;
+ bool wantRightmostChild;
+ bool wantPayloadOnly;
+};
+
+enum class ResultCode {
+ NONE = -1,
+ DATA = 0,
+ NACK = 4,
+ TIMEOUT = 3
+};
+
+class NdnPeek : boost::noncopyable
+{
+public:
+ NdnPeek(Face& face, const PeekOptions& options);
+
+ /**
+ * @return the timeout
+ */
+ time::milliseconds
+ getTimeout() const;
+
+ /**
+ * @return the result of Peek execution
+ */
+ ResultCode
+ getResultCode() const;
+
+ /**
+ * @brief express the Interest
+ * @note The caller must invoke face.processEvents() afterwards
+ */
+ void
+ start();
+
+private:
+ Interest
+ createInterest() const;
+
+ /**
+ * @brief called when a Data packet is received
+ */
+ void
+ onData(const Data& data);
+
+ /**
+ * @brief called when a Nack packet is received
+ */
+ void
+ onNack(const lp::Nack& nack);
+
+private:
+ Face& m_face;
+ const PeekOptions& m_options;
+ time::steady_clock::TimePoint m_expressInterestTime;
+ time::milliseconds m_timeout;
+ ResultCode m_resultCode;
+};
+
+} // namespace peek
+} // namespace ndn
+
+#endif // NDN_TOOLS_NDNPEEK_NDNPEEK_HPP
diff --git a/tools/peek/wscript b/tools/peek/wscript
index 45679a2..f701269 100644
--- a/tools/peek/wscript
+++ b/tools/peek/wscript
@@ -2,14 +2,24 @@
top = '../..'
def build(bld):
- bld.program(
- features='cxx',
- target='../../bin/ndnpeek',
- source='ndn-peek.cpp',
+
+ bld(features='cxx',
+ name='peek-ndnpeek-objects',
+ source=bld.path.ant_glob('ndnpeek/*.cpp', excl='ndnpeek/main.cpp'),
use='core-objects')
+ bld(features='cxx cxxprogram',
+ target='../../bin/ndnpeek',
+ source='ndnpeek/main.cpp',
+ use='peek-ndnpeek-objects')
+
bld.program(
features='cxx',
target='../../bin/ndnpoke',
source='ndn-poke.cpp',
use='core-objects')
+
+ ## (for unit tests)
+
+ bld(name='peek-objects',
+ use='peek-ndnpeek-objects')