tools: refactor nfd-status
refs #3658
Change-Id: Ia347074bea802eba5f539208e276e849a60db8a4
diff --git a/tools/nfd-status.cpp b/tools/nfd-status.cpp
deleted file mode 100644
index 21c62a1..0000000
--- a/tools/nfd-status.cpp
+++ /dev/null
@@ -1,926 +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 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 "common.hpp"
-
-#include <ndn-cxx/face.hpp>
-#include <ndn-cxx/name.hpp>
-#include <ndn-cxx/interest.hpp>
-#include <ndn-cxx/encoding/buffer-stream.hpp>
-
-#include <ndn-cxx/management/nfd-forwarder-status.hpp>
-#include <ndn-cxx/management/nfd-channel-status.hpp>
-#include <ndn-cxx/management/nfd-face-status.hpp>
-#include <ndn-cxx/management/nfd-fib-entry.hpp>
-#include <ndn-cxx/management/nfd-rib-entry.hpp>
-#include <ndn-cxx/management/nfd-strategy-choice.hpp>
-#include <ndn-cxx/util/segment-fetcher.hpp>
-#include <ndn-cxx/security/validator-null.hpp>
-
-#include <boost/algorithm/string/replace.hpp>
-#include <list>
-
-namespace ndn {
-
-using util::SegmentFetcher;
-
-/** \brief custom validator for the purpose of obtaining nfdId.
- */
-class ForwarderStatusValidator : public Validator
-{
-protected:
- virtual void
- checkPolicy(const Data& data,
- int nSteps,
- const OnDataValidated& onValidated,
- const OnDataValidationFailed& onValidationFailed,
- std::vector<shared_ptr<ValidationRequest>>& nextSteps) override
- {
- const ndn::KeyLocator& locator = data.getSignature().getKeyLocator();
- if (nfdId.empty() && locator.getType() == KeyLocator::KeyLocator_Name)
- nfdId = locator.getName();
- onValidated(data.shared_from_this());
- }
-
- virtual void
- checkPolicy(const Interest& interest,
- int nSteps,
- const OnInterestValidated& onValidated,
- const OnInterestValidationFailed& onValidationFailed,
- std::vector<shared_ptr<ValidationRequest>>& nextSteps) override
- {
- BOOST_ASSERT(false);
- }
-
-public:
- Name nfdId;
-};
-
-
-class NfdStatus
-{
-public:
- explicit
- NfdStatus(char* toolName)
- : m_toolName(toolName)
- , m_needVersionRetrieval(false)
- , m_needChannelStatusRetrieval(false)
- , m_needFaceStatusRetrieval(false)
- , m_needFibEnumerationRetrieval(false)
- , m_needRibStatusRetrieval(false)
- , m_needStrategyChoiceRetrieval(false)
- , m_isOutputXml(false)
- {
- }
-
- void
- usage()
- {
- std::cout << "Usage: \n " << m_toolName << " [options]\n\n"
- "Show NFD version and status information\n\n"
- "Options:\n"
- " [-h] - print this help message\n"
- " [-v] - retrieve version information\n"
- " [-c] - retrieve channel status information\n"
- " [-f] - retrieve face status information\n"
- " [-b] - retrieve FIB information\n"
- " [-r] - retrieve RIB information\n"
- " [-s] - retrieve configured strategy choice for NDN namespaces\n"
- " [-x] - output NFD status information in XML format\n"
- "\n"
- " [-V] - show version information of nfd-status and exit\n"
- "\n"
- "If no options are provided, all information is retrieved.\n"
- "If -x is provided, other options(-v, -c, etc.) are ignored, and all information is printed in XML format.\n"
- ;
- }
-
- void
- enableVersionRetrieval()
- {
- m_needVersionRetrieval = true;
- }
-
- void
- enableChannelStatusRetrieval()
- {
- m_needChannelStatusRetrieval = true;
- }
-
- void
- enableFaceStatusRetrieval()
- {
- m_needFaceStatusRetrieval = true;
- }
-
- void
- enableFibEnumerationRetrieval()
- {
- m_needFibEnumerationRetrieval = true;
- }
-
- void
- enableStrategyChoiceRetrieval()
- {
- m_needStrategyChoiceRetrieval = true;
- }
-
- void
- enableRibStatusRetrieval()
- {
- m_needRibStatusRetrieval = true;
- }
-
- void
- enableXmlOutput()
- {
- m_isOutputXml = true;
- }
-
- void
- onTimeout()
- {
- std::cerr << "Request timed out" << std::endl;
-
- runNextStep();
- }
-
-
- void
- onFetchError(uint32_t errorCode, const std::string& errorMsg)
- {
- std::cerr << "Error code:" << errorCode << ", message:" << errorMsg << std::endl;
-
- runNextStep();
- }
-
- void
- escapeSpecialCharacters(std::string *data)
- {
- using boost::algorithm::replace_all;
- replace_all(*data, "&", "&");
- replace_all(*data, "\"", """);
- replace_all(*data, "\'", "'");
- replace_all(*data, "<", "<");
- replace_all(*data, ">", ">");
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////////
-
- void
- fetchVersionInformation()
- {
- Interest interest("/localhost/nfd/status/general");
- interest.setChildSelector(1);
- interest.setMustBeFresh(true);
- SegmentFetcher::fetch(m_face, interest,
- m_forwarderStatusValidator,
- bind(&NfdStatus::afterFetchedVersionInformation, this, _1),
- bind(&NfdStatus::onFetchError, this, _1, _2));
- }
-
- void
- afterFetchedVersionInformation(const ConstBufferPtr& dataset)
- {
- Block block(tlv::Content, dataset);
- nfd::ForwarderStatus status(block);
-
- if (m_isOutputXml) {
- std::cout << "<generalStatus>";
- std::cout << "<nfdId>"
- << m_forwarderStatusValidator.nfdId << "</nfdId>";
- std::cout << "<version>"
- << status.getNfdVersion() << "</version>";
- std::cout << "<startTime>"
- << time::toString(status.getStartTimestamp(), "%Y-%m-%dT%H:%M:%S%F")
- << "</startTime>";
- std::cout << "<currentTime>"
- << time::toString(status.getCurrentTimestamp(), "%Y-%m-%dT%H:%M:%S%F")
- << "</currentTime>";
- std::cout << "<uptime>PT"
- << time::duration_cast<time::seconds>(status.getCurrentTimestamp() -
- status.getStartTimestamp()).count()
- << "S</uptime>";
- std::cout << "<nNameTreeEntries>" << status.getNNameTreeEntries()
- << "</nNameTreeEntries>";
- std::cout << "<nFibEntries>" << status.getNFibEntries()
- << "</nFibEntries>";
- std::cout << "<nPitEntries>" << status.getNPitEntries()
- << "</nPitEntries>";
- std::cout << "<nMeasurementsEntries>" << status.getNMeasurementsEntries()
- << "</nMeasurementsEntries>";
- std::cout << "<nCsEntries>" << status.getNCsEntries()
- << "</nCsEntries>";
- std::cout << "<packetCounters>";
- std::cout << "<incomingPackets>";
- std::cout << "<nInterests>" << status.getNInInterests()
- << "</nInterests>";
- std::cout << "<nDatas>" << status.getNInDatas()
- << "</nDatas>";
- std::cout << "<nNacks>" << status.getNInNacks()
- << "</nNacks>";
- std::cout << "</incomingPackets>";
- std::cout << "<outgoingPackets>";
- std::cout << "<nInterests>" << status.getNOutInterests()
- << "</nInterests>";
- std::cout << "<nDatas>" << status.getNOutDatas()
- << "</nDatas>";
- std::cout << "<nNacks>" << status.getNOutNacks()
- << "</nNacks>";
- std::cout << "</outgoingPackets>";
- std::cout << "</packetCounters>";
- std::cout << "</generalStatus>";
- }
- else {
- std::cout << "General NFD status:" << std::endl;
- std::cout << " nfdId="
- << m_forwarderStatusValidator.nfdId << std::endl;
- std::cout << " version="
- << status.getNfdVersion() << std::endl;
- std::cout << " startTime="
- << time::toIsoString(status.getStartTimestamp()) << std::endl;
- std::cout << " currentTime="
- << time::toIsoString(status.getCurrentTimestamp()) << std::endl;
- std::cout << " uptime="
- << time::duration_cast<time::seconds>(status.getCurrentTimestamp() -
- status.getStartTimestamp()) << std::endl;
-
- std::cout << " nNameTreeEntries=" << status.getNNameTreeEntries() << std::endl;
- std::cout << " nFibEntries=" << status.getNFibEntries() << std::endl;
- std::cout << " nPitEntries=" << status.getNPitEntries() << std::endl;
- std::cout << " nMeasurementsEntries=" << status.getNMeasurementsEntries() << std::endl;
- std::cout << " nCsEntries=" << status.getNCsEntries() << std::endl;
- std::cout << " nInInterests=" << status.getNInInterests() << std::endl;
- std::cout << " nOutInterests=" << status.getNOutInterests() << std::endl;
- std::cout << " nInDatas=" << status.getNInDatas() << std::endl;
- std::cout << " nOutDatas=" << status.getNOutDatas() << std::endl;
- std::cout << " nInNacks=" << status.getNInNacks() << std::endl;
- std::cout << " nOutNacks=" << status.getNOutNacks() << std::endl;
- }
-
- runNextStep();
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////////
-
- void
- fetchChannelStatusInformation()
- {
- m_buffer = make_shared<OBufferStream>();
-
- Interest interest("/localhost/nfd/faces/channels");
- interest.setChildSelector(1);
- interest.setMustBeFresh(true);
-
- SegmentFetcher::fetch(m_face, interest,
- m_validator,
- bind(&NfdStatus::afterFetchedChannelStatusInformation, this, _1),
- bind(&NfdStatus::onFetchError, this, _1, _2));
- }
-
- void
- afterFetchedChannelStatusInformation(const ConstBufferPtr& dataset)
- {
- if (m_isOutputXml) {
- std::cout << "<channels>";
-
- size_t offset = 0;
- while (offset < dataset->size()) {
- bool isOk = false;
- Block block;
- std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
- if (!isOk) {
- std::cerr << "ERROR: cannot decode ChannelStatus TLV" << std::endl;
- break;
- }
-
- offset += block.size();
-
- nfd::ChannelStatus channelStatus(block);
-
- std::cout << "<channel>";
- std::string localUri(channelStatus.getLocalUri());
- escapeSpecialCharacters(&localUri);
- std::cout << "<localUri>" << localUri << "</localUri>";
- std::cout << "</channel>";
- }
-
- std::cout << "</channels>";
- }
- else {
- std::cout << "Channels:" << std::endl;
-
- size_t offset = 0;
- while (offset < dataset->size()) {
- bool isOk = false;
- Block block;
- std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
- if (!isOk) {
- std::cerr << "ERROR: cannot decode ChannelStatus TLV" << std::endl;
- break;
- }
-
- offset += block.size();
-
- nfd::ChannelStatus channelStatus(block);
- std::cout << " " << channelStatus.getLocalUri() << std::endl;
- }
- }
-
- runNextStep();
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////////
-
- void
- fetchFaceStatusInformation()
- {
- m_buffer = make_shared<OBufferStream>();
-
- Interest interest("/localhost/nfd/faces/list");
- interest.setChildSelector(1);
- interest.setMustBeFresh(true);
-
- SegmentFetcher::fetch(m_face, interest,
- m_validator,
- bind(&NfdStatus::afterFetchedFaceStatusInformation, this, _1),
- bind(&NfdStatus::onFetchError, this, _1, _2));
- }
-
- void
- afterFetchedFaceStatusInformation(const ConstBufferPtr& dataset)
- {
- if (m_isOutputXml) {
- std::cout << "<faces>";
-
- size_t offset = 0;
- while (offset < dataset->size()) {
- bool isOk = false;
- Block block;
- std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
- if (!isOk) {
- std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
- break;
- }
-
- offset += block.size();
-
- nfd::FaceStatus faceStatus(block);
-
- std::cout << "<face>";
- std::cout << "<faceId>" << faceStatus.getFaceId() << "</faceId>";
-
- std::string remoteUri(faceStatus.getRemoteUri());
- escapeSpecialCharacters(&remoteUri);
- std::cout << "<remoteUri>" << remoteUri << "</remoteUri>";
-
- std::string localUri(faceStatus.getLocalUri());
- escapeSpecialCharacters(&localUri);
- std::cout << "<localUri>" << localUri << "</localUri>";
-
- if (faceStatus.hasExpirationPeriod()) {
- std::cout << "<expirationPeriod>PT"
- << time::duration_cast<time::seconds>(faceStatus.getExpirationPeriod())
- .count() << "S"
- << "</expirationPeriod>";
- }
-
- std::cout << "<faceScope>" << faceStatus.getFaceScope()
- << "</faceScope>";
- std::cout << "<facePersistency>" << faceStatus.getFacePersistency()
- << "</facePersistency>";
- std::cout << "<linkType>" << faceStatus.getLinkType()
- << "</linkType>";
-
- std::cout << "<packetCounters>";
- std::cout << "<incomingPackets>";
- std::cout << "<nInterests>" << faceStatus.getNInInterests()
- << "</nInterests>";
- std::cout << "<nDatas>" << faceStatus.getNInDatas()
- << "</nDatas>";
- std::cout << "<nNacks>" << faceStatus.getNInNacks()
- << "</nNacks>";
- std::cout << "</incomingPackets>";
- std::cout << "<outgoingPackets>";
- std::cout << "<nInterests>" << faceStatus.getNOutInterests()
- << "</nInterests>";
- std::cout << "<nDatas>" << faceStatus.getNOutDatas()
- << "</nDatas>";
- std::cout << "<nNacks>" << faceStatus.getNOutNacks()
- << "</nNacks>";
- std::cout << "</outgoingPackets>";
- std::cout << "</packetCounters>";
-
- std::cout << "<byteCounters>";
- std::cout << "<incomingBytes>" << faceStatus.getNInBytes()
- << "</incomingBytes>";
- std::cout << "<outgoingBytes>" << faceStatus.getNOutBytes()
- << "</outgoingBytes>";
- std::cout << "</byteCounters>";
-
- std::cout << "</face>";
- }
- std::cout << "</faces>";
- }
- else {
- std::cout << "Faces:" << std::endl;
-
- size_t offset = 0;
- while (offset < dataset->size()) {
- bool isOk = false;
- Block block;
- std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
- if (!isOk) {
- std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
- break;
- }
-
- offset += block.size();
-
- nfd::FaceStatus faceStatus(block);
-
- std::cout << " faceid=" << faceStatus.getFaceId()
- << " remote=" << faceStatus.getRemoteUri()
- << " local=" << faceStatus.getLocalUri();
- if (faceStatus.hasExpirationPeriod()) {
- std::cout << " expires="
- << time::duration_cast<time::seconds>(faceStatus.getExpirationPeriod())
- .count() << "s";
- }
- std::cout << " counters={"
- << "in={" << faceStatus.getNInInterests() << "i "
- << faceStatus.getNInDatas() << "d "
- << faceStatus.getNInNacks() << "n "
- << faceStatus.getNInBytes() << "B}"
- << " out={" << faceStatus.getNOutInterests() << "i "
- << faceStatus.getNOutDatas() << "d "
- << faceStatus.getNOutNacks() << "n "
- << faceStatus.getNOutBytes() << "B}"
- << "}";
- std::cout << " " << faceStatus.getFaceScope()
- << " " << faceStatus.getFacePersistency()
- << " " << faceStatus.getLinkType();
- std::cout << std::endl;
- }
- }
-
- runNextStep();
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////////
-
- void
- fetchFibEnumerationInformation()
- {
- m_buffer = make_shared<OBufferStream>();
-
- Interest interest("/localhost/nfd/fib/list");
- interest.setChildSelector(1);
- interest.setMustBeFresh(true);
-
- SegmentFetcher::fetch(m_face, interest,
- m_validator,
- bind(&NfdStatus::afterFetchedFibEnumerationInformation, this, _1),
- bind(&NfdStatus::onFetchError, this, _1, _2));
- }
-
- void
- afterFetchedFibEnumerationInformation(const ConstBufferPtr& dataset)
- {
- if (m_isOutputXml) {
- std::cout << "<fib>";
-
- size_t offset = 0;
- while (offset < dataset->size()) {
- bool isOk = false;
- Block block;
- std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
- if (!isOk) {
- std::cerr << "ERROR: cannot decode FibEntry TLV";
- break;
- }
- offset += block.size();
-
- nfd::FibEntry fibEntry(block);
-
- std::cout << "<fibEntry>";
- std::string prefix(fibEntry.getPrefix().toUri());
- escapeSpecialCharacters(&prefix);
- std::cout << "<prefix>" << prefix << "</prefix>";
- std::cout << "<nextHops>";
- for (const nfd::NextHopRecord& nextHop : fibEntry.getNextHopRecords()) {
- std::cout << "<nextHop>" ;
- std::cout << "<faceId>" << nextHop.getFaceId() << "</faceId>";
- std::cout << "<cost>" << nextHop.getCost() << "</cost>";
- std::cout << "</nextHop>";
- }
- std::cout << "</nextHops>";
- std::cout << "</fibEntry>";
- }
-
- std::cout << "</fib>";
- }
- else {
- std::cout << "FIB:" << std::endl;
-
- size_t offset = 0;
- while (offset < dataset->size()) {
- bool isOk = false;
- Block block;
- std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
- if (!isOk) {
- std::cerr << "ERROR: cannot decode FibEntry TLV" << std::endl;
- break;
- }
- offset += block.size();
-
- nfd::FibEntry fibEntry(block);
-
- std::cout << " " << fibEntry.getPrefix() << " nexthops={";
- bool isFirst = true;
- for (const nfd::NextHopRecord& nextHop : fibEntry.getNextHopRecords()) {
- if (isFirst)
- isFirst = false;
- else
- std::cout << ", ";
-
- std::cout << "faceid=" << nextHop.getFaceId()
- << " (cost=" << nextHop.getCost() << ")";
- }
- std::cout << "}" << std::endl;
- }
- }
-
- runNextStep();
- }
-
- //////////////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////////////
-
- void
- fetchStrategyChoiceInformation()
- {
- m_buffer = make_shared<OBufferStream>();
-
- Interest interest("/localhost/nfd/strategy-choice/list");
- interest.setChildSelector(1);
- interest.setMustBeFresh(true);
-
- SegmentFetcher::fetch(m_face, interest,
- m_validator,
- bind(&NfdStatus::afterFetchedStrategyChoiceInformationInformation, this, _1),
- bind(&NfdStatus::onFetchError, this, _1, _2));
- }
-
- void
- afterFetchedStrategyChoiceInformationInformation(const ConstBufferPtr& dataset)
- {
- if (m_isOutputXml) {
- std::cout << "<strategyChoices>";
-
- size_t offset = 0;
- while (offset < dataset->size()) {
- bool isOk = false;
- Block block;
- std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
- if (!isOk) {
- std::cerr << "ERROR: cannot decode StrategyChoice TLV";
- break;
- }
- offset += block.size();
-
- nfd::StrategyChoice strategyChoice(block);
-
- std::cout << "<strategyChoice>";
-
- std::string name(strategyChoice.getName().toUri());
- escapeSpecialCharacters(&name);
- std::cout << "<namespace>" << name << "</namespace>";
- std::cout << "<strategy>";
-
- std::string strategy(strategyChoice.getStrategy().toUri());
- escapeSpecialCharacters(&strategy);
-
- std::cout << "<name>" << strategy << "</name>";
- std::cout << "</strategy>";
- std::cout << "</strategyChoice>";
- }
-
- std::cout << "</strategyChoices>";
- }
- else {
- std::cout << "Strategy choices:" << std::endl;
-
- size_t offset = 0;
- while (offset < dataset->size()) {
- bool isOk = false;
- Block block;
- std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
- if (!isOk) {
- std::cerr << "ERROR: cannot decode StrategyChoice TLV" << std::endl;
- break;
- }
- offset += block.size();
-
- nfd::StrategyChoice strategyChoice(block);
-
- std::cout << " " << strategyChoice.getName()
- << " strategy=" << strategyChoice.getStrategy() << std::endl;
- }
- }
-
- runNextStep();
- }
-
- void
- fetchRibStatusInformation()
- {
- m_buffer = make_shared<OBufferStream>();
-
- Interest interest("/localhost/nfd/rib/list");
- interest.setChildSelector(1);
- interest.setMustBeFresh(true);
-
- SegmentFetcher::fetch(m_face, interest,
- m_validator,
- bind(&NfdStatus::afterFetchedRibStatusInformation, this, _1),
- bind(&NfdStatus::onFetchError, this, _1, _2));
- }
-
- void
- afterFetchedRibStatusInformation(const ConstBufferPtr& dataset)
- {
- if (m_isOutputXml) {
- std::cout << "<rib>";
-
- size_t offset = 0;
- while (offset < dataset->size()) {
- bool isOk = false;
- Block block;
- std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
- if (!isOk) {
- std::cerr << "ERROR: cannot decode RibEntry TLV";
- break;
- }
- offset += block.size();
-
- nfd::RibEntry ribEntry(block);
-
- std::cout << "<ribEntry>";
- std::string prefix(ribEntry.getName().toUri());
- escapeSpecialCharacters(&prefix);
- std::cout << "<prefix>" << prefix << "</prefix>";
- std::cout << "<routes>";
- for (const nfd::Route& nextRoute : ribEntry) {
- std::cout << "<route>" ;
- std::cout << "<faceId>" << nextRoute.getFaceId() << "</faceId>";
- std::cout << "<origin>" << nextRoute.getOrigin() << "</origin>";
- std::cout << "<cost>" << nextRoute.getCost() << "</cost>";
-
- std::cout << "<flags>";
- if (nextRoute.isChildInherit())
- std::cout << "<childInherit/>";
- if (nextRoute.isRibCapture())
- std::cout << "<ribCapture/>";
- std::cout << "</flags>";
-
- if (!nextRoute.hasInfiniteExpirationPeriod()) {
- std::cout << "<expirationPeriod>PT"
- << time::duration_cast<time::seconds>(nextRoute.getExpirationPeriod())
- .count() << "S"
- << "</expirationPeriod>";
- }
- std::cout << "</route>";
- }
- std::cout << "</routes>";
- std::cout << "</ribEntry>";
- }
-
- std::cout << "</rib>";
- }
- else {
- std::cout << "RIB:" << std::endl;
-
- size_t offset = 0;
- while (offset < dataset->size()) {
- bool isOk = false;
- Block block;
- std::tie(isOk, block) = Block::fromBuffer(dataset, offset);
- if (!isOk) {
- std::cerr << "ERROR: cannot decode RibEntry TLV" << std::endl;
- break;
- }
-
- offset += block.size();
-
- nfd::RibEntry ribEntry(block);
-
- std::cout << " " << ribEntry.getName().toUri() << " route={";
- bool isFirst = true;
- for (const nfd::Route& nextRoute : ribEntry) {
- if (isFirst)
- isFirst = false;
- else
- std::cout << ", ";
-
- std::cout << "faceid=" << nextRoute.getFaceId()
- << " (origin=" << nextRoute.getOrigin()
- << " cost=" << nextRoute.getCost();
- if (!nextRoute.hasInfiniteExpirationPeriod()) {
- std::cout << " expires="
- << time::duration_cast<time::seconds>(nextRoute.getExpirationPeriod())
- .count() << "s";
- }
-
- if (nextRoute.isChildInherit())
- std::cout << " ChildInherit";
- if (nextRoute.isRibCapture())
- std::cout << " RibCapture";
-
- std::cout << ")";
- }
- std::cout << "}" << std::endl;
- }
- }
-
- runNextStep();
- }
-
-
- void
- fetchInformation()
- {
- if (m_isOutputXml ||
- (!m_needVersionRetrieval &&
- !m_needChannelStatusRetrieval &&
- !m_needFaceStatusRetrieval &&
- !m_needFibEnumerationRetrieval &&
- !m_needRibStatusRetrieval &&
- !m_needStrategyChoiceRetrieval))
- {
- enableVersionRetrieval();
- enableChannelStatusRetrieval();
- enableFaceStatusRetrieval();
- enableFibEnumerationRetrieval();
- enableRibStatusRetrieval();
- enableStrategyChoiceRetrieval();
- }
-
- if (m_isOutputXml)
- m_fetchSteps.push_back(bind(&NfdStatus::printXmlHeader, this));
-
- if (m_needVersionRetrieval)
- m_fetchSteps.push_back(bind(&NfdStatus::fetchVersionInformation, this));
-
- if (m_needChannelStatusRetrieval)
- m_fetchSteps.push_back(bind(&NfdStatus::fetchChannelStatusInformation, this));
-
- if (m_needFaceStatusRetrieval)
- m_fetchSteps.push_back(bind(&NfdStatus::fetchFaceStatusInformation, this));
-
- if (m_needFibEnumerationRetrieval)
- m_fetchSteps.push_back(bind(&NfdStatus::fetchFibEnumerationInformation, this));
-
- if (m_needRibStatusRetrieval)
- m_fetchSteps.push_back(bind(&NfdStatus::fetchRibStatusInformation, this));
-
- if (m_needStrategyChoiceRetrieval)
- m_fetchSteps.push_back(bind(&NfdStatus::fetchStrategyChoiceInformation, this));
-
- if (m_isOutputXml)
- m_fetchSteps.push_back(bind(&NfdStatus::printXmlFooter, this));
-
- runNextStep();
- m_face.processEvents();
- }
-
-private:
- void
- printXmlHeader()
- {
- std::cout << "<?xml version=\"1.0\"?>";
- std::cout << "<nfdStatus xmlns=\"ndn:/localhost/nfd/status/1\">";
-
- runNextStep();
- }
-
- void
- printXmlFooter()
- {
- std::cout << "</nfdStatus>";
-
- runNextStep();
- }
-
- void
- runNextStep()
- {
- if (m_fetchSteps.empty())
- return;
-
- function<void()> nextStep = m_fetchSteps.front();
- m_fetchSteps.pop_front();
- nextStep();
- }
-
-private:
- std::string m_toolName;
- bool m_needVersionRetrieval;
- bool m_needChannelStatusRetrieval;
- bool m_needFaceStatusRetrieval;
- bool m_needFibEnumerationRetrieval;
- bool m_needRibStatusRetrieval;
- bool m_needStrategyChoiceRetrieval;
- bool m_isOutputXml;
- Face m_face;
-
- shared_ptr<OBufferStream> m_buffer;
-
- std::deque<function<void()>> m_fetchSteps;
-
- ndn::ValidatorNull m_validator;
-
- ForwarderStatusValidator m_forwarderStatusValidator;
-};
-
-} // namespace ndn
-
-int main(int argc, char* argv[])
-{
- int option;
- ndn::NfdStatus nfdStatus(argv[0]);
-
- while ((option = getopt(argc, argv, "hvcfbrsxV")) != -1) {
- switch (option) {
- case 'h':
- nfdStatus.usage();
- return 0;
- case 'v':
- nfdStatus.enableVersionRetrieval();
- break;
- case 'c':
- nfdStatus.enableChannelStatusRetrieval();
- break;
- case 'f':
- nfdStatus.enableFaceStatusRetrieval();
- break;
- case 'b':
- nfdStatus.enableFibEnumerationRetrieval();
- break;
- case 'r':
- nfdStatus.enableRibStatusRetrieval();
- break;
- case 's':
- nfdStatus.enableStrategyChoiceRetrieval();
- break;
- case 'x':
- nfdStatus.enableXmlOutput();
- break;
- case 'V':
- std::cout << NFD_VERSION_BUILD_STRING << std::endl;
- return 0;
- default:
- nfdStatus.usage();
- return 1;
- }
- }
-
- try {
- nfdStatus.fetchInformation();
- }
- catch (std::exception& e) {
- std::cerr << "ERROR: " << e.what() << std::endl;
- return 2;
- }
-
- return 0;
-}
diff --git a/tools/nfd-status/channel-module.cpp b/tools/nfd-status/channel-module.cpp
new file mode 100644
index 0000000..4cd5484
--- /dev/null
+++ b/tools/nfd-status/channel-module.cpp
@@ -0,0 +1,83 @@
+/* -*- 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 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/>.
+ */
+
+#include "channel-module.hpp"
+#include "format-helpers.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+void
+ChannelModule::fetchStatus(Controller& controller,
+ const function<void()>& onSuccess,
+ const Controller::CommandFailCallback& onFailure,
+ const CommandOptions& options)
+{
+ controller.fetch<ndn::nfd::ChannelDataset>(
+ [this, onSuccess] (const std::vector<ChannelStatus>& result) {
+ m_status = result;
+ onSuccess();
+ },
+ onFailure, options);
+}
+
+void
+ChannelModule::formatStatusXml(std::ostream& os) const
+{
+ os << "<channels>";
+ for (const ChannelStatus& item : m_status) {
+ this->formatItemXml(os, item);
+ }
+ os << "</channels>";
+}
+
+void
+ChannelModule::formatItemXml(std::ostream& os, const ChannelStatus& item) const
+{
+ os << "<channel>";
+ os << "<localUri>" << xml::Text{item.getLocalUri()} << "</localUri>";
+ os << "</channel>";
+}
+
+void
+ChannelModule::formatStatusText(std::ostream& os) const
+{
+ os << "Channels:\n";
+ for (const ChannelStatus& item : m_status) {
+ this->formatItemText(os, item);
+ }
+}
+
+void
+ChannelModule::formatItemText(std::ostream& os, const ChannelStatus& item) const
+{
+ os << " " << item.getLocalUri();
+ os << "\n";
+}
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
diff --git a/tools/nfd-status/channel-module.hpp b/tools/nfd-status/channel-module.hpp
new file mode 100644
index 0000000..1230554
--- /dev/null
+++ b/tools/nfd-status/channel-module.hpp
@@ -0,0 +1,77 @@
+/* -*- 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 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_TOOLS_NFD_STATUS_CHANNEL_MODULE_HPP
+#define NFD_TOOLS_NFD_STATUS_CHANNEL_MODULE_HPP
+
+#include "module.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+using ndn::nfd::ChannelStatus;
+
+/** \brief provides access to NFD channel dataset
+ * \sa https://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Channel-Dataset
+ */
+class ChannelModule : public Module, noncopyable
+{
+public:
+ virtual void
+ fetchStatus(Controller& controller,
+ const function<void()>& onSuccess,
+ const Controller::CommandFailCallback& onFailure,
+ const CommandOptions& options) override;
+
+ virtual void
+ formatStatusXml(std::ostream& os) const override;
+
+ /** \brief format a single status item as XML
+ * \param os output stream
+ * \param item status item
+ */
+ void
+ formatItemXml(std::ostream& os, const ChannelStatus& item) const;
+
+ virtual void
+ formatStatusText(std::ostream& os) const override;
+
+ /** \brief format a single status item as text
+ * \param os output stream
+ * \param item status item
+ */
+ void
+ formatItemText(std::ostream& os, const ChannelStatus& item) const;
+
+private:
+ std::vector<ChannelStatus> m_status;
+};
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
+
+#endif // NFD_TOOLS_NFD_STATUS_CHANNEL_MODULE_HPP
diff --git a/tools/nfd-status/face-module.cpp b/tools/nfd-status/face-module.cpp
new file mode 100644
index 0000000..3ec0467
--- /dev/null
+++ b/tools/nfd-status/face-module.cpp
@@ -0,0 +1,154 @@
+/* -*- 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 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/>.
+ */
+
+/** \todo
+ * #2542 plans to merge nfd-status with nfdc.
+ * FaceModule class should be changed as follows:
+ * (1) move into ndn::nfd::nfdc namespace
+ * (2) assuming command syntax is similar to Windows NT \p netsh ,
+ * this class can handle command argument parsing as soon as
+ * 'face' sub-command is detected
+ * (3) introduce methods to create and destroy faces, and update face attributes
+ *
+ * \todo
+ * #3444 aims at improving output texts of nfdc.
+ * Assuming it's worked with or after #2542:
+ * (1) introduce an \p style parameter on formatItemText method to specify desired text style,
+ * such as human friendly style vs. porcelain style for script consumption
+ * (2) upon successful command execute, convert the command result into FaceStatus type,
+ * and use formatItemText to render the result, so that output from status retrieval
+ * and command execution have consistent styles
+ * }
+ */
+
+#include "face-module.hpp"
+#include "format-helpers.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+void
+FaceModule::fetchStatus(Controller& controller,
+ const function<void()>& onSuccess,
+ const Controller::CommandFailCallback& onFailure,
+ const CommandOptions& options)
+{
+ controller.fetch<ndn::nfd::FaceDataset>(
+ [this, onSuccess] (const std::vector<FaceStatus>& result) {
+ m_status = result;
+ onSuccess();
+ },
+ onFailure, options);
+}
+
+void
+FaceModule::formatStatusXml(std::ostream& os) const
+{
+ os << "<faces>";
+ for (const FaceStatus& item : m_status) {
+ this->formatItemXml(os, item);
+ }
+ os << "</faces>";
+}
+
+void
+FaceModule::formatItemXml(std::ostream& os, const FaceStatus& item) const
+{
+ os << "<face>";
+
+ os << "<faceId>" << item.getFaceId() << "</faceId>";
+ os << "<remoteUri>" << xml::Text{item.getRemoteUri()} << "</remoteUri>";
+ os << "<localUri>" << xml::Text{item.getLocalUri()} << "</localUri>";
+
+ if (item.hasExpirationPeriod()) {
+ os << "<expirationPeriod>" << xml::formatDuration(item.getExpirationPeriod())
+ << "</expirationPeriod>";
+ }
+ os << "<faceScope>" << item.getFaceScope() << "</faceScope>";
+ os << "<facePersistency>" << item.getFacePersistency() << "</facePersistency>";
+ os << "<linkType>" << item.getLinkType() << "</linkType>";
+
+ os << "<packetCounters>";
+ os << "<incomingPackets>"
+ << "<nInterests>" << item.getNInInterests() << "</nInterests>"
+ << "<nDatas>" << item.getNInDatas() << "</nDatas>"
+ << "<nNacks>" << item.getNInNacks() << "</nNacks>"
+ << "</incomingPackets>";
+ os << "<outgoingPackets>"
+ << "<nInterests>" << item.getNOutInterests() << "</nInterests>"
+ << "<nDatas>" << item.getNOutDatas() << "</nDatas>"
+ << "<nNacks>" << item.getNOutNacks() << "</nNacks>"
+ << "</outgoingPackets>";
+ os << "</packetCounters>";
+
+ os << "<byteCounters>";
+ os << "<incomingBytes>" << item.getNInBytes() << "</incomingBytes>";
+ os << "<outgoingBytes>" << item.getNOutBytes() << "</outgoingBytes>";
+ os << "</byteCounters>";
+
+ os << "</face>";
+}
+
+void
+FaceModule::formatStatusText(std::ostream& os) const
+{
+ os << "Faces:\n";
+ for (const FaceStatus& item : m_status) {
+ this->formatItemText(os, item);
+ }
+}
+
+void
+FaceModule::formatItemText(std::ostream& os, const FaceStatus& item) const
+{
+ os << " faceid=" << item.getFaceId();
+ os << " remote=" << item.getRemoteUri();
+ os << " local=" << item.getLocalUri();
+
+ if (item.hasExpirationPeriod()) {
+ os << " expires=" << text::formatDuration(item.getExpirationPeriod());
+ }
+
+ os << " counters={in={"
+ << item.getNInInterests() << "i "
+ << item.getNInDatas() << "d "
+ << item.getNInNacks() << "n "
+ << item.getNInBytes() << "B} ";
+ os << "out={"
+ << item.getNOutInterests() << "i "
+ << item.getNOutDatas() << "d "
+ << item.getNOutNacks() << "n "
+ << item.getNOutBytes() << "B}}";
+
+ os << " " << item.getFaceScope();
+ os << " " << item.getFacePersistency();
+ os << " " << item.getLinkType();
+ os << "\n";
+}
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
diff --git a/tools/nfd-status/face-module.hpp b/tools/nfd-status/face-module.hpp
new file mode 100644
index 0000000..58bb5ee
--- /dev/null
+++ b/tools/nfd-status/face-module.hpp
@@ -0,0 +1,77 @@
+/* -*- 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 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_TOOLS_NFD_STATUS_FACE_MODULE_HPP
+#define NFD_TOOLS_NFD_STATUS_FACE_MODULE_HPP
+
+#include "module.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+using ndn::nfd::FaceStatus;
+
+/** \brief provides access to NFD face management
+ * \sa https://redmine.named-data.net/projects/nfd/wiki/FaceMgmt
+ */
+class FaceModule : public Module, noncopyable
+{
+public:
+ virtual void
+ fetchStatus(Controller& controller,
+ const function<void()>& onSuccess,
+ const Controller::CommandFailCallback& onFailure,
+ const CommandOptions& options) override;
+
+ virtual void
+ formatStatusXml(std::ostream& os) const override;
+
+ /** \brief format a single status item as XML
+ * \param os output stream
+ * \param item status item
+ */
+ void
+ formatItemXml(std::ostream& os, const FaceStatus& item) const;
+
+ virtual void
+ formatStatusText(std::ostream& os) const override;
+
+ /** \brief format a single status item as text
+ * \param os output stream
+ * \param item status item
+ */
+ void
+ formatItemText(std::ostream& os, const FaceStatus& item) const;
+
+private:
+ std::vector<FaceStatus> m_status;
+};
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
+
+#endif // NFD_TOOLS_NFD_STATUS_FACE_MODULE_HPP
diff --git a/tools/nfd-status/fib-module.cpp b/tools/nfd-status/fib-module.cpp
new file mode 100644
index 0000000..a1c7f94
--- /dev/null
+++ b/tools/nfd-status/fib-module.cpp
@@ -0,0 +1,103 @@
+/* -*- 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 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/>.
+ */
+
+#include "fib-module.hpp"
+#include "format-helpers.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+void
+FibModule::fetchStatus(Controller& controller,
+ const function<void()>& onSuccess,
+ const Controller::CommandFailCallback& onFailure,
+ const CommandOptions& options)
+{
+ controller.fetch<ndn::nfd::FibDataset>(
+ [this, onSuccess] (const std::vector<FibEntry>& result) {
+ m_status = result;
+ onSuccess();
+ },
+ onFailure, options);
+}
+
+void
+FibModule::formatStatusXml(std::ostream& os) const
+{
+ os << "<fib>";
+ for (const FibEntry& item : m_status) {
+ this->formatItemXml(os, item);
+ }
+ os << "</fib>";
+}
+
+void
+FibModule::formatItemXml(std::ostream& os, const FibEntry& item) const
+{
+ os << "<fibEntry>";
+
+ os << "<prefix>" << xml::Text{item.getPrefix().toUri()} << "</prefix>";
+
+ os << "<nextHops>";
+ for (const NextHopRecord& nh : item.getNextHopRecords()) {
+ os << "<nextHop>"
+ << "<faceId>" << nh.getFaceId() << "</faceId>"
+ << "<cost>" << nh.getCost() << "</cost>"
+ << "</nextHop>";
+ }
+ os << "</nextHops>";
+
+ os << "</fibEntry>";
+}
+
+void
+FibModule::formatStatusText(std::ostream& os) const
+{
+ os << "FIB:\n";
+ for (const FibEntry& item : m_status) {
+ this->formatItemText(os, item);
+ }
+}
+
+void
+FibModule::formatItemText(std::ostream& os, const FibEntry& item) const
+{
+ os << " " << item.getPrefix() << " nexthops={";
+
+ text::Separator sep(", ");
+ for (const NextHopRecord& nh : item.getNextHopRecords()) {
+ os << sep
+ << "faceid=" << nh.getFaceId()
+ << " (cost=" << nh.getCost() << ")";
+ }
+
+ os << "}";
+ os << "\n";
+}
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
diff --git a/tools/nfd-status/fib-module.hpp b/tools/nfd-status/fib-module.hpp
new file mode 100644
index 0000000..353e594
--- /dev/null
+++ b/tools/nfd-status/fib-module.hpp
@@ -0,0 +1,78 @@
+/* -*- 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 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_TOOLS_NFD_STATUS_FIB_MODULE_HPP
+#define NFD_TOOLS_NFD_STATUS_FIB_MODULE_HPP
+
+#include "module.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+using ndn::nfd::FibEntry;
+using ndn::nfd::NextHopRecord;
+
+/** \brief provides access to NFD FIB management
+ * \sa https://redmine.named-data.net/projects/nfd/wiki/FibMgmt
+ */
+class FibModule : public Module, noncopyable
+{
+public:
+ virtual void
+ fetchStatus(Controller& controller,
+ const function<void()>& onSuccess,
+ const Controller::CommandFailCallback& onFailure,
+ const CommandOptions& options) override;
+
+ virtual void
+ formatStatusXml(std::ostream& os) const override;
+
+ /** \brief format a single status item as XML
+ * \param os output stream
+ * \param item status item
+ */
+ void
+ formatItemXml(std::ostream& os, const FibEntry& item) const;
+
+ virtual void
+ formatStatusText(std::ostream& os) const override;
+
+ /** \brief format a single status item as text
+ * \param os output stream
+ * \param item status item
+ */
+ void
+ formatItemText(std::ostream& os, const FibEntry& item) const;
+
+private:
+ std::vector<FibEntry> m_status;
+};
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
+
+#endif // NFD_TOOLS_NFD_STATUS_FIB_MODULE_HPP
diff --git a/tools/nfd-status/format-helpers.cpp b/tools/nfd-status/format-helpers.cpp
new file mode 100644
index 0000000..c7e595b
--- /dev/null
+++ b/tools/nfd-status/format-helpers.cpp
@@ -0,0 +1,128 @@
+/* -*- 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 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/>.
+ */
+
+#include "format-helpers.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+namespace xml {
+
+void
+printHeader(std::ostream& os)
+{
+ os << "<?xml version=\"1.0\"?>"
+ << "<nfdStatus xmlns=\"ndn:/localhost/nfd/status/1\">";
+}
+
+void
+printFooter(std::ostream& os)
+{
+ os << "</nfdStatus>";
+}
+
+std::ostream&
+operator<<(std::ostream& os, const Text& text)
+{
+ for (char ch : text.s) {
+ switch (ch) {
+ case '"':
+ os << """;
+ break;
+ case '&':
+ os << "&";
+ break;
+ case '\'':
+ os << "'";
+ break;
+ case '<':
+ os << "<";
+ break;
+ case '>':
+ os << ">";
+ break;
+ default:
+ os << ch;
+ break;
+ }
+ }
+ return os;
+}
+
+std::string
+formatSeconds(time::seconds d)
+{
+ return "PT" + to_string(d.count()) + "S";
+}
+
+std::string
+formatTimestamp(time::system_clock::TimePoint t)
+{
+ return time::toString(t, "%Y-%m-%dT%H:%M:%S%F");
+}
+
+} // namespace xml
+
+namespace text {
+
+Separator::Separator(const std::string& first, const std::string& subsequent)
+ : m_first(first)
+ , m_subsequent(subsequent)
+ , m_count(0)
+{
+}
+
+Separator::Separator(const std::string& subsequent)
+ : Separator("", subsequent)
+{
+}
+
+std::ostream&
+operator<<(std::ostream& os, Separator& sep)
+{
+ if (++sep.m_count == 1) {
+ return os << sep.m_first;
+ }
+ return os << sep.m_subsequent;
+}
+
+std::string
+formatSeconds(time::seconds d, bool isLong)
+{
+ return to_string(d.count()) + (isLong ? " seconds" : "s");
+}
+
+std::string
+formatTimestamp(time::system_clock::TimePoint t)
+{
+ return time::toIsoString(t);
+}
+
+} // namespace text
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
diff --git a/tools/nfd-status/format-helpers.hpp b/tools/nfd-status/format-helpers.hpp
new file mode 100644
index 0000000..11d3d5a
--- /dev/null
+++ b/tools/nfd-status/format-helpers.hpp
@@ -0,0 +1,118 @@
+/* -*- 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 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_TOOLS_NFD_STATUS_FORMAT_HELPERS_HPP
+#define NFD_TOOLS_NFD_STATUS_FORMAT_HELPERS_HPP
+
+#include "common.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+namespace xml {
+
+void
+printHeader(std::ostream& os);
+
+void
+printFooter(std::ostream& os);
+
+struct Text
+{
+ const std::string& s;
+};
+
+/** \brief print XML text with special character represented as predefined entities
+ */
+std::ostream&
+operator<<(std::ostream& os, const Text& text);
+
+std::string
+formatSeconds(time::seconds d);
+
+template<typename DURATION>
+std::string
+formatDuration(DURATION d)
+{
+ return formatSeconds(time::duration_cast<time::seconds>(d));
+}
+
+std::string
+formatTimestamp(time::system_clock::TimePoint t);
+
+} // namespace xml
+
+namespace text {
+
+/** \brief print different string on first and subsequent usage
+ *
+ * \code
+ * Separator sep(",");
+ * for (int i = 1; i <= 3; ++i) {
+ * os << sep << i;
+ * }
+ * // prints: 1,2,3
+ * \endcode
+ */
+class Separator
+{
+public:
+ Separator(const std::string& first, const std::string& subsequent);
+
+ explicit
+ Separator(const std::string& subsequent);
+
+private:
+ std::string m_first;
+ std::string m_subsequent;
+ int m_count;
+
+ friend std::ostream& operator<<(std::ostream& os, Separator& sep);
+};
+
+std::ostream&
+operator<<(std::ostream& os, Separator& sep);
+
+std::string
+formatSeconds(time::seconds d, bool isLong = false);
+
+template<typename DURATION>
+std::string
+formatDuration(DURATION d, bool isLong = false)
+{
+ return formatSeconds(time::duration_cast<time::seconds>(d), isLong);
+}
+
+std::string
+formatTimestamp(time::system_clock::TimePoint t);
+
+} // namespace text
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
+
+#endif // NFD_TOOLS_NFD_STATUS_FORMAT_HELPERS_HPP
diff --git a/tools/nfd-status/forwarder-general-module.cpp b/tools/nfd-status/forwarder-general-module.cpp
new file mode 100644
index 0000000..41b715a
--- /dev/null
+++ b/tools/nfd-status/forwarder-general-module.cpp
@@ -0,0 +1,190 @@
+/* -*- 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 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/>.
+ */
+
+#include "forwarder-general-module.hpp"
+#include "format-helpers.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+ForwarderGeneralModule::ForwarderGeneralModule()
+ : m_nfdIdCollector(nullptr)
+{
+}
+
+void
+ForwarderGeneralModule::fetchStatus(Controller& controller,
+ const function<void()>& onSuccess,
+ const Controller::CommandFailCallback& onFailure,
+ const CommandOptions& options)
+{
+ controller.fetch<ndn::nfd::ForwarderGeneralStatusDataset>(
+ [this, onSuccess] (const ForwarderStatus& result) {
+ m_status = result;
+ onSuccess();
+ },
+ onFailure, options);
+}
+
+static time::system_clock::Duration
+calculateUptime(const ForwarderStatus& status)
+{
+ return status.getCurrentTimestamp() - status.getStartTimestamp();
+}
+
+const Name&
+ForwarderGeneralModule::getNfdId() const
+{
+ if (m_nfdIdCollector != nullptr && m_nfdIdCollector->hasNfdId()) {
+ return m_nfdIdCollector->getNfdId();
+ }
+
+ static Name unavailable("/nfdId-unavailable");
+ return unavailable;
+}
+
+void
+ForwarderGeneralModule::formatStatusXml(std::ostream& os) const
+{
+ this->formatItemXml(os, m_status, this->getNfdId());
+}
+
+void
+ForwarderGeneralModule::formatItemXml(std::ostream& os, const ForwarderStatus& item,
+ const Name& nfdId) const
+{
+ os << "<generalStatus>";
+
+ os << "<nfdId>" << nfdId << "</nfdId>";
+ os << "<version>" << xml::Text{item.getNfdVersion()} << "</version>";
+ os << "<startTime>" << xml::formatTimestamp(item.getStartTimestamp()) << "</startTime>";
+ os << "<currentTime>" << xml::formatTimestamp(item.getCurrentTimestamp()) << "</currentTime>";
+ os << "<uptime>" << xml::formatDuration(calculateUptime(item)) << "</uptime>";
+
+ os << "<nNameTreeEntries>" << item.getNNameTreeEntries() << "</nNameTreeEntries>";
+ os << "<nFibEntries>" << item.getNFibEntries() << "</nFibEntries>";
+ os << "<nPitEntries>" << item.getNPitEntries() << "</nPitEntries>";
+ os << "<nMeasurementsEntries>" << item.getNMeasurementsEntries() << "</nMeasurementsEntries>";
+ os << "<nCsEntries>" << item.getNCsEntries() << "</nCsEntries>";
+
+ os << "<packetCounters>";
+ os << "<incomingPackets>"
+ << "<nInterests>" << item.getNInInterests() << "</nInterests>"
+ << "<nDatas>" << item.getNInDatas() << "</nDatas>"
+ << "<nNacks>" << item.getNInNacks() << "</nNacks>"
+ << "</incomingPackets>";
+ os << "<outgoingPackets>"
+ << "<nInterests>" << item.getNOutInterests() << "</nInterests>"
+ << "<nDatas>" << item.getNOutDatas() << "</nDatas>"
+ << "<nNacks>" << item.getNOutNacks() << "</nNacks>"
+ << "</outgoingPackets>";
+ os << "</packetCounters>";
+
+ os << "</generalStatus>";
+}
+
+void
+ForwarderGeneralModule::formatStatusText(std::ostream& os) const
+{
+ os << "General NFD status:\n";
+ this->formatItemText(os, m_status, this->getNfdId());
+}
+
+void
+ForwarderGeneralModule::formatItemText(std::ostream& os, const ForwarderStatus& item,
+ const Name& nfdId) const
+{
+ os << " nfdId=" << nfdId << "\n";
+ os << " version=" << item.getNfdVersion() << "\n";
+ os << " startTime=" << text::formatTimestamp(item.getStartTimestamp()) << "\n";
+ os << " currentTime=" << text::formatTimestamp(item.getCurrentTimestamp()) << "\n";
+ os << " uptime=" << text::formatDuration(calculateUptime(item), true) << "\n";
+
+ os << " nNameTreeEntries=" << item.getNNameTreeEntries() << "\n";
+ os << " nFibEntries=" << item.getNFibEntries() << "\n";
+ os << " nPitEntries=" << item.getNPitEntries() << "\n";
+ os << " nMeasurementsEntries=" << item.getNMeasurementsEntries() << "\n";
+ os << " nCsEntries=" << item.getNCsEntries() << "\n";
+
+ os << " nInInterests=" << item.getNInInterests() << "\n";
+ os << " nOutInterests=" << item.getNOutInterests() << "\n";
+ os << " nInDatas=" << item.getNInDatas() << "\n";
+ os << " nOutDatas=" << item.getNOutDatas() << "\n";
+ os << " nInNacks=" << item.getNInNacks() << "\n";
+ os << " nOutNacks=" << item.getNOutNacks() << "\n";
+}
+
+NfdIdCollector::NfdIdCollector(unique_ptr<ndn::Validator> inner)
+ : m_inner(std::move(inner))
+ , m_hasNfdId(false)
+{
+ BOOST_ASSERT(m_inner != nullptr);
+}
+
+const Name&
+NfdIdCollector::getNfdId() const
+{
+ if (!m_hasNfdId) {
+ BOOST_THROW_EXCEPTION(std::runtime_error("NfdId is unavailable"));
+ }
+
+ return m_nfdId;
+}
+
+void
+NfdIdCollector::checkPolicy(const Data& data, int nSteps,
+ const ndn::OnDataValidated& accept,
+ const ndn::OnDataValidationFailed& reject,
+ std::vector<shared_ptr<ndn::ValidationRequest>>& nextSteps)
+{
+ ndn::OnDataValidated accepted = [this, accept] (const shared_ptr<const Data>& data) {
+ accept(data); // pass the Data to Validator user's validated callback
+
+ if (m_hasNfdId) {
+ return;
+ }
+
+ const ndn::Signature& sig = data->getSignature();
+ if (!sig.hasKeyLocator()) {
+ return;
+ }
+
+ const ndn::KeyLocator& kl = sig.getKeyLocator();
+ if (kl.getType() != ndn::KeyLocator::KeyLocator_Name) {
+ return;
+ }
+
+ m_nfdId = kl.getName();
+ m_hasNfdId = true;
+ };
+
+ BOOST_ASSERT(nSteps == 0);
+ m_inner->validate(data, accepted, reject);
+}
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
diff --git a/tools/nfd-status/forwarder-general-module.hpp b/tools/nfd-status/forwarder-general-module.hpp
new file mode 100644
index 0000000..a55bc21
--- /dev/null
+++ b/tools/nfd-status/forwarder-general-module.hpp
@@ -0,0 +1,140 @@
+/* -*- 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 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_TOOLS_NFD_STATUS_FORWARDER_GENERAL_MODULE_HPP
+#define NFD_TOOLS_NFD_STATUS_FORWARDER_GENERAL_MODULE_HPP
+
+#include "module.hpp"
+#include <ndn-cxx/security/validator.hpp>
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+using ndn::nfd::ForwarderStatus;
+
+class NfdIdCollector;
+
+/** \brief provides access to NFD forwarder general status
+ * \sa https://redmine.named-data.net/projects/nfd/wiki/ForwarderStatus
+ */
+class ForwarderGeneralModule : public Module, noncopyable
+{
+public:
+ ForwarderGeneralModule();
+
+ virtual void
+ fetchStatus(Controller& controller,
+ const function<void()>& onSuccess,
+ const Controller::CommandFailCallback& onFailure,
+ const CommandOptions& options) override;
+
+ void
+ setNfdIdCollector(const NfdIdCollector& nfdIdCollector)
+ {
+ m_nfdIdCollector = &nfdIdCollector;
+ }
+
+ virtual void
+ formatStatusXml(std::ostream& os) const override;
+
+ /** \brief format a single status item as XML
+ * \param os output stream
+ * \param item status item
+ * \param nfdId NFD's signing certificate name
+ */
+ void
+ formatItemXml(std::ostream& os, const ForwarderStatus& item, const Name& nfdId) const;
+
+ virtual void
+ formatStatusText(std::ostream& os) const override;
+
+ /** \brief format a single status item as text
+ * \param os output stream
+ * \param item status item
+ * \param nfdId NFD's signing certificate name
+ */
+ void
+ formatItemText(std::ostream& os, const ForwarderStatus& item, const Name& nfdId) const;
+
+private:
+ const Name&
+ getNfdId() const;
+
+private:
+ const NfdIdCollector* m_nfdIdCollector;
+ ForwarderStatus m_status;
+};
+
+
+/** \brief a validator that can collect NFD's signing certificate name
+ *
+ * This validator redirects all validation requests to an inner validator.
+ * For the first Data packet accepted by the inner validator that has a Name in KeyLocator,
+ * this Name is collected as NFD's signing certificate name.
+ */
+class NfdIdCollector : public ndn::Validator
+{
+public:
+ explicit
+ NfdIdCollector(unique_ptr<ndn::Validator> inner);
+
+ bool
+ hasNfdId() const
+ {
+ return m_hasNfdId;
+ }
+
+ const Name&
+ getNfdId() const;
+
+protected:
+ virtual void
+ checkPolicy(const Interest& interest, int nSteps,
+ const ndn::OnInterestValidated& accept,
+ const ndn::OnInterestValidationFailed& reject,
+ std::vector<shared_ptr<ndn::ValidationRequest>>& nextSteps) override
+ {
+ BOOST_ASSERT(nSteps == 0);
+ m_inner->validate(interest, accept, reject);
+ }
+
+ virtual void
+ checkPolicy(const Data& data, int nSteps,
+ const ndn::OnDataValidated& accept,
+ const ndn::OnDataValidationFailed& reject,
+ std::vector<shared_ptr<ndn::ValidationRequest>>& nextSteps) override;
+
+private:
+ unique_ptr<ndn::Validator> m_inner;
+ bool m_hasNfdId;
+ Name m_nfdId;
+};
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
+
+#endif // NFD_TOOLS_NFD_STATUS_FORWARDER_GENERAL_MODULE_HPP
diff --git a/tools/nfd-status/main.cpp b/tools/nfd-status/main.cpp
new file mode 100644
index 0000000..a3033a6
--- /dev/null
+++ b/tools/nfd-status/main.cpp
@@ -0,0 +1,199 @@
+/* -*- 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 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/>.
+ */
+
+#include "version.hpp"
+#include <ndn-cxx/security/validator-null.hpp>
+
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/program_options/parsers.hpp>
+
+#include "status-report.hpp"
+#include "forwarder-general-module.hpp"
+#include "channel-module.hpp"
+#include "face-module.hpp"
+#include "fib-module.hpp"
+#include "rib-module.hpp"
+#include "strategy-choice-module.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+enum class OutputFormat
+{
+ XML = 1,
+ TEXT = 2
+};
+
+struct Options
+{
+ OutputFormat output = OutputFormat::TEXT;
+ bool wantForwarderGeneral = false;
+ bool wantChannels = false;
+ bool wantFaces = false;
+ bool wantFib = false;
+ bool wantRib = false;
+ bool wantStrategyChoice = false;
+};
+
+static void
+showUsage(std::ostream& os, const boost::program_options::options_description& cmdOptions)
+{
+ os << "Usage: nfd-status [options]\n\n"
+ << "Show NFD version and status information.\n\n"
+ << cmdOptions;
+}
+
+/** \brief parse command line, and show usage if necessary
+ * \return if first item is -1, caller should retrieve and display StatusReport;
+ * otherwise, caller should immediately exit with the specified exit code
+ */
+static std::tuple<int, Options>
+parseCommandLine(int argc, const char* const* argv)
+{
+ Options options;
+
+ namespace po = boost::program_options;
+ po::options_description cmdOptions("Options");
+ cmdOptions.add_options()
+ ("help,h", "print this help message")
+ ("version,V", "show program version")
+ ("general,v", po::bool_switch(&options.wantForwarderGeneral), "show general status")
+ ("channels,c", po::bool_switch(&options.wantChannels), "show channels")
+ ("faces,f", po::bool_switch(&options.wantFaces), "show faces")
+ ("fib,b", po::bool_switch(&options.wantFib), "show FIB entries")
+ ("rib,r", po::bool_switch(&options.wantRib), "show RIB routes")
+ ("sc,s", po::bool_switch(&options.wantStrategyChoice), "show strategy choice entries")
+ ("xml,x", "output as XML instead of text (implies -vcfbrs)");
+ po::variables_map vm;
+ try {
+ po::store(po::parse_command_line(argc, argv, cmdOptions), vm);
+ }
+ catch (const po::error& e) {
+ std::cerr << e.what() << "\n";
+ showUsage(std::cerr, cmdOptions);
+ return std::make_tuple(2, options);
+ }
+ po::notify(vm);
+
+ if (vm.count("help") > 0) {
+ showUsage(std::cout, cmdOptions);
+ return std::make_tuple(0, options);
+ }
+ if (vm.count("version") > 0) {
+ std::cout << "nfd-status " << NFD_VERSION_BUILD_STRING << "\n";
+ return std::make_tuple(0, options);
+ }
+
+ if (vm.count("xml") > 0) {
+ options.output = OutputFormat::XML;
+ }
+ if (options.output == OutputFormat::XML ||
+ (!options.wantForwarderGeneral && !options.wantChannels && !options.wantFaces &&
+ !options.wantFib && !options.wantRib && !options.wantStrategyChoice)) {
+ options.wantForwarderGeneral = options.wantChannels = options.wantFaces =
+ options.wantFib = options.wantRib = options.wantStrategyChoice = true;
+ }
+
+ return std::make_tuple(-1, options);
+}
+
+static int
+main(int argc, char** argv)
+{
+ int exitCode = -1;
+ Options options;
+ std::tie(exitCode, options) = parseCommandLine(argc, argv);
+ if (exitCode >= 0) {
+ return exitCode;
+ }
+
+ Face face;
+ KeyChain keyChain;
+ unique_ptr<Validator> validator = make_unique<ndn::ValidatorNull>();
+ CommandOptions ctrlOptions;
+
+ StatusReport report;
+
+ if (options.wantForwarderGeneral) {
+ auto nfdIdCollector = make_unique<NfdIdCollector>(std::move(validator));
+ auto forwarderGeneralModule = make_unique<ForwarderGeneralModule>();
+ forwarderGeneralModule->setNfdIdCollector(*nfdIdCollector);
+ report.sections.push_back(std::move(forwarderGeneralModule));
+ validator = std::move(nfdIdCollector);
+ }
+
+ if (options.wantChannels) {
+ report.sections.push_back(make_unique<ChannelModule>());
+ }
+
+ if (options.wantFaces) {
+ report.sections.push_back(make_unique<FaceModule>());
+ }
+
+ if (options.wantFib) {
+ report.sections.push_back(make_unique<FibModule>());
+ }
+
+ if (options.wantRib) {
+ report.sections.push_back(make_unique<RibModule>());
+ }
+
+ if (options.wantStrategyChoice) {
+ report.sections.push_back(make_unique<StrategyChoiceModule>());
+ }
+
+ uint32_t code = report.collect(face, keyChain, *validator, ctrlOptions);
+ if (code != 0) {
+ // Give a simple error code for end user.
+ // Technical support personnel:
+ // 1. get the exact command from end user
+ // 2. code div 1000000 is zero-based section index
+ // 3. code mod 1000000 is a Controller.fetch error code
+ std::cerr << "Error while collecting status report (" << code << ").\n";
+ return 1;
+ }
+
+ switch (options.output) {
+ case OutputFormat::XML:
+ report.formatXml(std::cout);
+ break;
+ case OutputFormat::TEXT:
+ report.formatText(std::cout);
+ break;
+ }
+ return 0;
+}
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
+
+int
+main(int argc, char** argv)
+{
+ return nfd::tools::nfd_status::main(argc, argv);
+}
diff --git a/tools/nfd-status/module.hpp b/tools/nfd-status/module.hpp
new file mode 100644
index 0000000..07d5647
--- /dev/null
+++ b/tools/nfd-status/module.hpp
@@ -0,0 +1,80 @@
+/* -*- 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 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_TOOLS_NFD_STATUS_MODULE_HPP
+#define NFD_TOOLS_NFD_STATUS_MODULE_HPP
+
+#include "common.hpp"
+#include <ndn-cxx/management/nfd-controller.hpp>
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+using ndn::nfd::Controller;
+using ndn::nfd::CommandOptions;
+
+/** \brief provides access to an NFD management module
+ * \note This type is an interface. It should not have member fields.
+ */
+class Module
+{
+public:
+ virtual
+ ~Module() = default;
+
+ /** \brief collect status from NFD
+ * \pre no other fetchStatus is in progress
+ * \param controller a controller through which StatusDataset can be requested
+ * \param onSuccess invoked when status has been collected into this instance
+ * \param onFailure passed to controller.fetch
+ * \param options passed to controller.fetch
+ */
+ virtual void
+ fetchStatus(Controller& controller,
+ const function<void()>& onSuccess,
+ const Controller::CommandFailCallback& onFailure,
+ const CommandOptions& options) = 0;
+
+ /** \brief format collected status as XML
+ * \pre fetchStatus has been successful
+ * \param os output stream
+ */
+ virtual void
+ formatStatusXml(std::ostream& os) const = 0;
+
+ /** \brief format collected status as text
+ * \pre fetchStatus has been successful
+ * \param os output stream
+ */
+ virtual void
+ formatStatusText(std::ostream& os) const = 0;
+};
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
+
+#endif // NFD_TOOLS_NFD_STATUS_MODULE_HPP
diff --git a/tools/nfd-status/rib-module.cpp b/tools/nfd-status/rib-module.cpp
new file mode 100644
index 0000000..fe254cc
--- /dev/null
+++ b/tools/nfd-status/rib-module.cpp
@@ -0,0 +1,133 @@
+/* -*- 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 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/>.
+ */
+
+#include "rib-module.hpp"
+#include "format-helpers.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+void
+RibModule::fetchStatus(Controller& controller,
+ const function<void()>& onSuccess,
+ const Controller::CommandFailCallback& onFailure,
+ const CommandOptions& options)
+{
+ controller.fetch<ndn::nfd::RibDataset>(
+ [this, onSuccess] (const std::vector<RibEntry>& result) {
+ m_status = result;
+ onSuccess();
+ },
+ onFailure, options);
+}
+
+void
+RibModule::formatStatusXml(std::ostream& os) const
+{
+ os << "<rib>";
+ for (const RibEntry& item : m_status) {
+ this->formatItemXml(os, item);
+ }
+ os << "</rib>";
+}
+
+void
+RibModule::formatItemXml(std::ostream& os, const RibEntry& item) const
+{
+ os << "<ribEntry>";
+
+ os << "<prefix>" << xml::Text{item.getName().toUri()} << "</prefix>";
+
+ os << "<routes>";
+ for (const Route& route : item.getRoutes()) {
+ os << "<route>"
+ << "<faceId>" << route.getFaceId() << "</faceId>"
+ << "<origin>" << route.getOrigin() << "</origin>"
+ << "<cost>" << route.getCost() << "</cost>";
+ if (route.getFlags() == ndn::nfd::ROUTE_FLAGS_NONE) {
+ os << "<flags/>";
+ }
+ else {
+ os << "<flags>";
+ if (route.isChildInherit()) {
+ os << "<childInherit/>";
+ }
+ if (route.isRibCapture()) {
+ os << "<ribCapture/>";
+ }
+ os << "</flags>";
+ }
+ if (!route.hasInfiniteExpirationPeriod()) {
+ os << "<expirationPeriod>"
+ << xml::formatDuration(route.getExpirationPeriod())
+ << "</expirationPeriod>";
+ }
+ os << "</route>";
+ }
+ os << "</routes>";
+
+ os << "</ribEntry>";
+}
+
+void
+RibModule::formatStatusText(std::ostream& os) const
+{
+ os << "RIB:\n";
+ for (const RibEntry& item : m_status) {
+ this->formatItemText(os, item);
+ }
+}
+
+void
+RibModule::formatItemText(std::ostream& os, const RibEntry& item) const
+{
+ os << " " << item.getName() << " route={";
+
+ text::Separator sep(", ");
+ for (const Route& route : item.getRoutes()) {
+ os << sep
+ << "faceid=" << route.getFaceId()
+ << " (origin=" << route.getOrigin()
+ << " cost=" << route.getCost();
+ if (!route.hasInfiniteExpirationPeriod()) {
+ os << " expires=" << text::formatDuration(route.getExpirationPeriod());
+ }
+ if (route.isChildInherit()) {
+ os << " ChildInherit";
+ }
+ if (route.isRibCapture()) {
+ os << " RibCapture";
+ }
+ os << ")";
+ }
+
+ os << "}";
+ os << "\n";
+}
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
diff --git a/tools/nfd-status/rib-module.hpp b/tools/nfd-status/rib-module.hpp
new file mode 100644
index 0000000..6a4ddd1
--- /dev/null
+++ b/tools/nfd-status/rib-module.hpp
@@ -0,0 +1,78 @@
+/* -*- 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 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_TOOLS_NFD_STATUS_RIB_MODULE_HPP
+#define NFD_TOOLS_NFD_STATUS_RIB_MODULE_HPP
+
+#include "module.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+using ndn::nfd::RibEntry;
+using ndn::nfd::Route;
+
+/** \brief provides access to NFD RIB management
+ * \sa https://redmine.named-data.net/projects/nfd/wiki/RibMgmt
+ */
+class RibModule : public Module, noncopyable
+{
+public:
+ virtual void
+ fetchStatus(Controller& controller,
+ const function<void()>& onSuccess,
+ const Controller::CommandFailCallback& onFailure,
+ const CommandOptions& options) override;
+
+ virtual void
+ formatStatusXml(std::ostream& os) const override;
+
+ /** \brief format a single status item as XML
+ * \param os output stream
+ * \param item status item
+ */
+ void
+ formatItemXml(std::ostream& os, const RibEntry& item) const;
+
+ virtual void
+ formatStatusText(std::ostream& os) const override;
+
+ /** \brief format a single status item as text
+ * \param os output stream
+ * \param item status item
+ */
+ void
+ formatItemText(std::ostream& os, const RibEntry& item) const;
+
+private:
+ std::vector<RibEntry> m_status;
+};
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
+
+#endif // NFD_TOOLS_NFD_STATUS_RIB_MODULE_HPP
diff --git a/tools/nfd-status/status-report.cpp b/tools/nfd-status/status-report.cpp
new file mode 100644
index 0000000..ff04e1f
--- /dev/null
+++ b/tools/nfd-status/status-report.cpp
@@ -0,0 +1,80 @@
+/* -*- 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 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/>.
+ */
+
+#include "status-report.hpp"
+#include "format-helpers.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+uint32_t
+StatusReport::collect(Face& face, KeyChain& keyChain, Validator& validator, const CommandOptions& options)
+{
+ Controller controller(face, keyChain, validator);
+ uint32_t errorCode = 0;
+
+ for (size_t i = 0; i < sections.size(); ++i) {
+ Module& module = *sections[i];
+ module.fetchStatus(
+ controller,
+ [] {},
+ [i, &errorCode] (uint32_t code, const std::string& reason) {
+ errorCode = i * 1000000 + code;
+ },
+ options);
+ }
+
+ this->processEvents(face);
+ return errorCode;
+}
+
+void
+StatusReport::processEvents(Face& face)
+{
+ face.processEvents();
+}
+
+void
+StatusReport::formatXml(std::ostream& os) const
+{
+ xml::printHeader(os);
+ for (const unique_ptr<Module>& module : sections) {
+ module->formatStatusXml(os);
+ }
+ xml::printFooter(os);
+}
+
+void
+StatusReport::formatText(std::ostream& os) const
+{
+ for (const unique_ptr<Module>& module : sections) {
+ module->formatStatusText(os);
+ }
+}
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
diff --git a/tools/nfd-status/status-report.hpp b/tools/nfd-status/status-report.hpp
new file mode 100644
index 0000000..80aaee7
--- /dev/null
+++ b/tools/nfd-status/status-report.hpp
@@ -0,0 +1,85 @@
+/* -*- 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 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_TOOLS_NFD_STATUS_STATUS_REPORT_HPP
+#define NFD_TOOLS_NFD_STATUS_STATUS_REPORT_HPP
+
+#include "module.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+using ndn::Face;
+using ndn::security::KeyChain;
+using ndn::Validator;
+
+/** \brief collects and prints NFD status report
+ */
+class StatusReport : noncopyable
+{
+public:
+#ifdef WITH_TESTS
+ virtual
+ ~StatusReport() = default;
+#endif
+
+ /** \brief collect status via chosen \p sections
+ *
+ * This function is blocking. It has exclusive use of \p face.
+ *
+ * \return if status has been fetched successfully, 0;
+ * otherwise, error code from any failed section, plus 1000000 * section index
+ */
+ uint32_t
+ collect(Face& face, KeyChain& keyChain, Validator& validator, const CommandOptions& options);
+
+ /** \brief print an XML report
+ * \param os output stream
+ */
+ void
+ formatXml(std::ostream& os) const;
+
+ /** \brief print a text report
+ * \param os output stream
+ */
+ void
+ formatText(std::ostream& os) const;
+
+private:
+ VIRTUAL_WITH_TESTS void
+ processEvents(Face& face);
+
+public:
+ /** \brief modules through which status is collected
+ */
+ std::vector<unique_ptr<Module>> sections;
+};
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
+
+#endif // NFD_TOOLS_NFD_STATUS_STATUS_REPORT_HPP
diff --git a/tools/nfd-status/strategy-choice-module.cpp b/tools/nfd-status/strategy-choice-module.cpp
new file mode 100644
index 0000000..efdff50
--- /dev/null
+++ b/tools/nfd-status/strategy-choice-module.cpp
@@ -0,0 +1,85 @@
+/* -*- 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 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/>.
+ */
+
+#include "strategy-choice-module.hpp"
+#include "format-helpers.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+void
+StrategyChoiceModule::fetchStatus(Controller& controller,
+ const function<void()>& onSuccess,
+ const Controller::CommandFailCallback& onFailure,
+ const CommandOptions& options)
+{
+ controller.fetch<ndn::nfd::StrategyChoiceDataset>(
+ [this, onSuccess] (const std::vector<StrategyChoice>& result) {
+ m_status = result;
+ onSuccess();
+ },
+ onFailure, options);
+}
+
+void
+StrategyChoiceModule::formatStatusXml(std::ostream& os) const
+{
+ os << "<strategyChoices>";
+ for (const StrategyChoice& item : m_status) {
+ this->formatItemXml(os, item);
+ }
+ os << "</strategyChoices>";
+}
+
+void
+StrategyChoiceModule::formatItemXml(std::ostream& os, const StrategyChoice& item) const
+{
+ os << "<strategyChoice>";
+ os << "<namespace>" << xml::Text{item.getName().toUri()} << "</namespace>";
+ os << "<strategy><name>" << xml::Text{item.getStrategy().toUri()} << "</name></strategy>";
+ os << "</strategyChoice>";
+}
+
+void
+StrategyChoiceModule::formatStatusText(std::ostream& os) const
+{
+ os << "Strategy choices:\n";
+ for (const StrategyChoice& item : m_status) {
+ this->formatItemText(os, item);
+ }
+}
+
+void
+StrategyChoiceModule::formatItemText(std::ostream& os, const StrategyChoice& item) const
+{
+ os << " " << item.getName()
+ << " strategy=" << item.getStrategy()
+ << "\n";
+}
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
diff --git a/tools/nfd-status/strategy-choice-module.hpp b/tools/nfd-status/strategy-choice-module.hpp
new file mode 100644
index 0000000..be84374
--- /dev/null
+++ b/tools/nfd-status/strategy-choice-module.hpp
@@ -0,0 +1,77 @@
+/* -*- 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 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_TOOLS_NFD_STATUS_STARTEGY_CHOICE_MODULE_HPP
+#define NFD_TOOLS_NFD_STATUS_STARTEGY_CHOICE_MODULE_HPP
+
+#include "module.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfd_status {
+
+using ndn::nfd::StrategyChoice;
+
+/** \brief provides access to NFD Strategy Choice management
+ * \sa https://redmine.named-data.net/projects/nfd/wiki/StrategyChoice
+ */
+class StrategyChoiceModule : public Module, noncopyable
+{
+public:
+ virtual void
+ fetchStatus(Controller& controller,
+ const function<void()>& onSuccess,
+ const Controller::CommandFailCallback& onFailure,
+ const CommandOptions& options) override;
+
+ virtual void
+ formatStatusXml(std::ostream& os) const override;
+
+ /** \brief format a single status item as XML
+ * \param os output stream
+ * \param item status item
+ */
+ void
+ formatItemXml(std::ostream& os, const StrategyChoice& item) const;
+
+ virtual void
+ formatStatusText(std::ostream& os) const override;
+
+ /** \brief format a single status item as text
+ * \param os output stream
+ * \param item status item
+ */
+ void
+ formatItemText(std::ostream& os, const StrategyChoice& item) const;
+
+private:
+ std::vector<StrategyChoice> m_status;
+};
+
+} // namespace nfd_status
+} // namespace tools
+} // namespace nfd
+
+#endif // NFD_TOOLS_NFD_STATUS_STARTEGY_CHOICE_MODULE_HPP
diff --git a/tools/wscript b/tools/wscript
index ee1909e..f3dd5c9 100644
--- a/tools/wscript
+++ b/tools/wscript
@@ -4,26 +4,59 @@
top = '..'
+TOOLS_DEPENDENCY = 'core-objects NDN_CXX BOOST LIBRESOLV'
+
def build(bld):
- # List all .cpp files (whole tool should be in one .cpp)
+ # single object tools
+ # tools/example-tool.cpp should a self-contained tool with a main function
+ # and it's built into build/bin/example-tool.
+ # These tools cannot be unit-tested.
for i in bld.path.ant_glob(['*.cpp']):
name = str(i)[:-len(".cpp")]
- bld(features=['cxx', 'cxxprogram'],
+ bld(features='cxx cxxprogram',
target="../bin/%s" % name,
- source=[i] + bld.path.ant_glob(['%s/**/*.cpp' % name]),
- use='core-objects NDN_CXX BOOST LIBRESOLV'
+ source=[i],
+ use=TOOLS_DEPENDENCY
)
- # List all directories files (tool can has multiple .cpp in the directory)
+
+ # sub-directory tools
+ # tools/example-tool/**/*.cpp is compiled and linked into build/bin/example-tool
+ # tools/example-tool/main.cpp must exist and it should contain the main function.
+ # All other objects are collected into 'tools-objects' and can be unit-tested.
+ testableObjects = []
for name in bld.path.ant_glob(['*'], dir=True, src=False):
- srcFiles = bld.path.ant_glob(['%s/**/*.cpp' % name])
+ mainFile = bld.path.find_node(['%s/main.cpp' % name])
+ if mainFile is None:
+ continue # not a C++ tool
+ srcFiles = bld.path.ant_glob(['%s/**/*.cpp' % name], excl=['%s/main.cpp' % name])
if len(srcFiles) > 0:
- bld(features=['cxx', 'cxxprogram'],
- target="../bin/%s" % name,
+ srcObjects = 'tools-%s-objects' % name
+ bld(features='cxx',
+ name=srcObjects,
source=srcFiles,
- use='core-objects NDN_CXX BOOST LIBRESOLV',
+ use=TOOLS_DEPENDENCY,
includes='%s' % name,
)
+ testableObjects.append(srcObjects)
+
+ bld(features='cxx cxxprogram',
+ target="../bin/%s" % name,
+ source=[mainFile],
+ use=TOOLS_DEPENDENCY + ' ' + srcObjects,
+ includes='%s' % name,
+ )
+ else:
+ bld(features='cxx cxxprogram',
+ target="../bin/%s" % name,
+ source=[mainFile],
+ use=TOOLS_DEPENDENCY,
+ includes='%s' % name,
+ )
+
+ bld(name='tools-objects',
+ export_includes='.',
+ use=testableObjects)
bld(features="subst",
source=bld.path.ant_glob(['*.sh', '*.py']),