mgmt: move management/nfd-* to mgmt/nfd/
refs #3760
Change-Id: Ib4bde3412b5c39b9f4f46113199cebe78704505e
diff --git a/src/mgmt/nfd/channel-status.cpp b/src/mgmt/nfd/channel-status.cpp
new file mode 100644
index 0000000..bbbfdf4
--- /dev/null
+++ b/src/mgmt/nfd/channel-status.cpp
@@ -0,0 +1,109 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "channel-status.hpp"
+#include "encoding/tlv-nfd.hpp"
+#include "encoding/block-helpers.hpp"
+#include "util/concepts.hpp"
+
+namespace ndn {
+namespace nfd {
+
+//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<ChannelStatus>));
+BOOST_CONCEPT_ASSERT((WireEncodable<ChannelStatus>));
+BOOST_CONCEPT_ASSERT((WireDecodable<ChannelStatus>));
+static_assert(std::is_base_of<tlv::Error, ChannelStatus::Error>::value,
+ "ChannelStatus::Error must inherit from tlv::Error");
+
+ChannelStatus::ChannelStatus()
+{
+}
+
+ChannelStatus::ChannelStatus(const Block& payload)
+{
+ this->wireDecode(payload);
+}
+
+template<encoding::Tag TAG>
+size_t
+ChannelStatus::wireEncode(EncodingImpl<TAG>& encoder) const
+{
+ size_t totalLength = 0;
+
+ totalLength += encoder.prependByteArrayBlock(tlv::nfd::LocalUri,
+ reinterpret_cast<const uint8_t*>(m_localUri.c_str()), m_localUri.size());
+
+ totalLength += encoder.prependVarNumber(totalLength);
+ totalLength += encoder.prependVarNumber(tlv::nfd::ChannelStatus);
+ return totalLength;
+}
+
+template size_t
+ChannelStatus::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>&) const;
+
+template size_t
+ChannelStatus::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>&) const;
+
+const Block&
+ChannelStatus::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+ChannelStatus::wireDecode(const Block& block)
+{
+ if (block.type() != tlv::nfd::ChannelStatus) {
+ BOOST_THROW_EXCEPTION(Error("Expecting ChannelStatus block"));
+ }
+ m_wire = block;
+ m_wire.parse();
+ Block::element_const_iterator val = m_wire.elements_begin();
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::LocalUri) {
+ m_localUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Missing required LocalUri field"));
+ }
+}
+
+ChannelStatus&
+ChannelStatus::setLocalUri(const std::string localUri)
+{
+ m_wire.reset();
+ m_localUri = localUri;
+ return *this;
+}
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/mgmt/nfd/channel-status.hpp b/src/mgmt/nfd/channel-status.hpp
new file mode 100644
index 0000000..5a2aae8
--- /dev/null
+++ b/src/mgmt/nfd/channel-status.hpp
@@ -0,0 +1,82 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_CHANNEL_STATUS_HPP
+#define NDN_MGMT_NFD_CHANNEL_STATUS_HPP
+
+#include "../../encoding/block.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * @ingroup management
+ * @brief represents NFD Channel Status dataset
+ * @sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Channel-Dataset
+ */
+class ChannelStatus
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+ ChannelStatus();
+
+ explicit
+ ChannelStatus(const Block& payload);
+
+ template<encoding::Tag TAG>
+ size_t
+ wireEncode(EncodingImpl<TAG>& encoder) const;
+
+ const Block&
+ wireEncode() const;
+
+ void
+ wireDecode(const Block& wire);
+
+public: // getters & setters
+ const std::string&
+ getLocalUri() const
+ {
+ return m_localUri;
+ }
+
+ ChannelStatus&
+ setLocalUri(const std::string localUri);
+
+private:
+ std::string m_localUri;
+
+ mutable Block m_wire;
+};
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_CHANNEL_STATUS_HPP
diff --git a/src/mgmt/nfd/command-options.cpp b/src/mgmt/nfd/command-options.cpp
new file mode 100644
index 0000000..557cce3
--- /dev/null
+++ b/src/mgmt/nfd/command-options.cpp
@@ -0,0 +1,141 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "command-options.hpp"
+
+#ifdef NDN_MANAGEMENT_NFD_COMMAND_OPTIONS_KEEP_DEPRECATED_SIGNING_PARAMS
+#include "../../security/v1/identity-certificate.hpp"
+#include "../../security/signing-helpers.hpp"
+#endif // NDN_MANAGEMENT_NFD_COMMAND_OPTIONS_KEEP_DEPRECATED_SIGNING_PARAMS
+
+namespace ndn {
+namespace nfd {
+
+const time::milliseconds CommandOptions::DEFAULT_TIMEOUT(10000);
+const Name CommandOptions::DEFAULT_PREFIX("ndn:/localhost/nfd");
+
+CommandOptions::CommandOptions()
+ : m_timeout(DEFAULT_TIMEOUT)
+ , m_prefix(DEFAULT_PREFIX)
+{
+}
+
+CommandOptions&
+CommandOptions::setTimeout(const time::milliseconds& timeout)
+{
+ if (timeout <= time::milliseconds::zero()) {
+ BOOST_THROW_EXCEPTION(std::out_of_range("Timeout must be positive"));
+ }
+
+ m_timeout = timeout;
+ return *this;
+}
+
+CommandOptions&
+CommandOptions::setPrefix(const Name& prefix)
+{
+ m_prefix = prefix;
+ return *this;
+}
+
+CommandOptions&
+CommandOptions::setSigningInfo(const security::SigningInfo& signingInfo)
+{
+ m_signingInfo = signingInfo;
+ return *this;
+}
+
+#ifdef NDN_MANAGEMENT_NFD_COMMAND_OPTIONS_KEEP_DEPRECATED_SIGNING_PARAMS
+
+CommandOptions::SigningParamsKind
+CommandOptions::getSigningParamsKind() const
+{
+ switch (m_signingInfo.getSignerType()) {
+ case security::SigningInfo::SIGNER_TYPE_NULL:
+ return SIGNING_PARAMS_DEFAULT;
+ case security::SigningInfo::SIGNER_TYPE_ID:
+ return SIGNING_PARAMS_IDENTITY;
+ case security::SigningInfo::SIGNER_TYPE_CERT:
+ return SIGNING_PARAMS_CERTIFICATE;
+ default:
+ BOOST_THROW_EXCEPTION(std::out_of_range("SigningInfo::SignerType is not convertible to "
+ "CommandOptions::SigningParamsKind"));
+ }
+}
+
+const Name&
+CommandOptions::getSigningIdentity() const
+{
+ BOOST_ASSERT(m_signingInfo.getSignerType() == security::SigningInfo::SIGNER_TYPE_ID);
+ return m_signingInfo.getSignerName();
+}
+
+const Name&
+CommandOptions::getSigningCertificate() const
+{
+ BOOST_ASSERT(m_signingInfo.getSignerType() == security::SigningInfo::SIGNER_TYPE_CERT);
+ return m_signingInfo.getSignerName();
+}
+
+CommandOptions&
+CommandOptions::setSigningDefault()
+{
+ m_signingInfo = security::SigningInfo();
+ return *this;
+}
+
+CommandOptions&
+CommandOptions::setSigningIdentity(const Name& identityName)
+{
+ m_signingInfo = security::signingByIdentity(identityName);
+ return *this;
+}
+
+static security::SigningInfo
+makeSigningInfoFromIdentityCertificate(const Name& certificateName)
+{
+ // A valid IdentityCertificate has at least 4 name components,
+ // as it follows `<...>/KEY/<...>/<key-id>/ID-CERT/<version>` naming model.
+ if (certificateName.size() < 4) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Certificate is invalid"));
+ }
+
+ return security::signingByCertificate(certificateName);
+}
+
+CommandOptions&
+CommandOptions::setSigningCertificate(const Name& certificateName)
+{
+ m_signingInfo = makeSigningInfoFromIdentityCertificate(certificateName);
+ return *this;
+}
+
+CommandOptions&
+CommandOptions::setSigningCertificate(const security::v1::IdentityCertificate& certificate)
+{
+ m_signingInfo = makeSigningInfoFromIdentityCertificate(certificate.getName());
+ return *this;
+}
+
+#endif // NDN_MANAGEMENT_NFD_COMMAND_OPTIONS_KEEP_DEPRECATED_SIGNING_PARAMS
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/mgmt/nfd/command-options.hpp b/src/mgmt/nfd/command-options.hpp
new file mode 100644
index 0000000..efde928
--- /dev/null
+++ b/src/mgmt/nfd/command-options.hpp
@@ -0,0 +1,196 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_COMMAND_OPTIONS_HPP
+#define NDN_MGMT_NFD_COMMAND_OPTIONS_HPP
+
+#include "../../security/signing-info.hpp"
+
+#define NDN_MGMT_NFD_COMMAND_OPTIONS_KEEP_DEPRECATED_SIGNING_PARAMS
+
+namespace ndn {
+
+namespace security {
+namespace v1 {
+class IdentityCertificate;
+} // namespace v1
+} // namespace security
+
+namespace nfd {
+
+/** \ingroup management
+ * \brief contains options for ControlCommand execution
+ * \note This type is intentionally copyable
+ */
+class CommandOptions
+{
+public:
+ /** \brief constructs CommandOptions
+ * \post getTimeout() == DEFAULT_TIMEOUT
+ * \post getPrefix() == DEFAULT_PREFIX
+ * \post getSigningInfo().getSignerType() == SIGNER_TYPE_NULL
+ */
+ CommandOptions();
+
+ /** \return command timeout
+ */
+ const time::milliseconds&
+ getTimeout() const
+ {
+ return m_timeout;
+ }
+
+ /** \brief sets command timeout
+ * \param timeout the new command timeout, must be positive
+ * \throw std::out_of_range if timeout is non-positive
+ * \return self
+ */
+ CommandOptions&
+ setTimeout(const time::milliseconds& timeout);
+
+ /** \return command prefix
+ */
+ const Name&
+ getPrefix() const
+ {
+ return m_prefix;
+ }
+
+ /** \brief sets command prefix
+ * \return self
+ */
+ CommandOptions&
+ setPrefix(const Name& prefix);
+
+ /** \return signing parameters
+ */
+ const security::SigningInfo&
+ getSigningInfo() const
+ {
+ return m_signingInfo;
+ }
+
+ /** \brief sets signing parameters
+ * \return self
+ */
+ CommandOptions&
+ setSigningInfo(const security::SigningInfo& signingInfo);
+
+#ifdef NDN_MGMT_NFD_COMMAND_OPTIONS_KEEP_DEPRECATED_SIGNING_PARAMS
+public: // signing parameters
+ /** \deprecated use getSigningInfo and setSigningInfo
+ * \brief indicates the selection of signing parameters
+ */
+ enum SigningParamsKind {
+ /** \brief picks the default signing identity and certificate
+ */
+ SIGNING_PARAMS_DEFAULT,
+ /** \brief picks the default certificate of a specific identity Name
+ */
+ SIGNING_PARAMS_IDENTITY,
+ /** \brief picks a specific identity certificate
+ */
+ SIGNING_PARAMS_CERTIFICATE
+ };
+
+ /** \deprecated use getSigningInfo and setSigningInfo
+ * \return selection of signing parameters
+ */
+ DEPRECATED(
+ SigningParamsKind
+ getSigningParamsKind() const);
+
+ /** \deprecated use getSigningInfo and setSigningInfo
+ * \return identity Name
+ * \pre getSigningParamsKind() == SIGNING_PARAMS_IDENTITY
+ */
+ DEPRECATED(
+ const Name&
+ getSigningIdentity() const);
+
+ /** \deprecated use getSigningInfo and setSigningInfo
+ * \return certificate Name
+ * \pre getSigningParamsKind() == SIGNING_PARAMS_CERTIFICATE
+ */
+ DEPRECATED(
+ const Name&
+ getSigningCertificate() const);
+
+ /** \deprecated use getSigningInfo and setSigningInfo
+ * \brief chooses to use default identity and certificate
+ * \post getSigningParamsKind() == SIGNING_PARAMS_DEFAULT
+ * \return self
+ */
+ DEPRECATED(
+ CommandOptions&
+ setSigningDefault());
+
+ /** \deprecated use getSigningInfo and setSigningInfo
+ * \brief chooses to use a specific identity and its default certificate
+ * \post getSigningParamsKind() == SIGNING_PARAMS_IDENTITY
+ * \post getIdentityName() == identityName
+ * \return self
+ */
+ DEPRECATED(
+ CommandOptions&
+ setSigningIdentity(const Name& identityName));
+
+ /** \deprecated use getSigningInfo and setSigningInfo
+ * \brief chooses to use a specific identity certificate
+ * \param certificateName identity certificate Name
+ * \throw std::invalid_argument if certificateName is invalid
+ * \post getSigningParamsKind() == SIGNING_PARAMS_CERTIFICATE
+ * \post getSigningCertificate() == certificateName
+ * \return self
+ */
+ DEPRECATED(
+ CommandOptions&
+ setSigningCertificate(const Name& certificateName));
+
+ /** \deprecated use getSigningInfo and setSigningInfo
+ * \brief chooses to use a specific identity certificate
+ * \details This is equivalent to .setIdentityCertificate(certificate.getName())
+ */
+ DEPRECATED(
+ CommandOptions&
+ setSigningCertificate(const security::v1::IdentityCertificate& certificate));
+
+#endif // NDN_MGMT_NFD_COMMAND_OPTIONS_KEEP_DEPRECATED_SIGNING_PARAMS
+
+public:
+ /** \brief gives the default command timeout: 10000ms
+ */
+ static const time::milliseconds DEFAULT_TIMEOUT;
+
+ /** \brief gives the default command prefix: ndn:/localhost/nfd
+ */
+ static const Name DEFAULT_PREFIX;
+
+private:
+ time::milliseconds m_timeout;
+ Name m_prefix;
+ security::SigningInfo m_signingInfo;
+};
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_COMMAND_OPTIONS_HPP
diff --git a/src/mgmt/nfd/control-command.cpp b/src/mgmt/nfd/control-command.cpp
new file mode 100644
index 0000000..2a6eda7
--- /dev/null
+++ b/src/mgmt/nfd/control-command.cpp
@@ -0,0 +1,422 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "control-command.hpp"
+#include "command-options.hpp" // only used in deprecated functions
+
+namespace ndn {
+namespace nfd {
+
+ControlCommand::ControlCommand(const std::string& module, const std::string& verb)
+ : m_module(module)
+ , m_verb(verb)
+{
+}
+
+ControlCommand::~ControlCommand() = default;
+
+void
+ControlCommand::validateRequest(const ControlParameters& parameters) const
+{
+ m_requestValidator.validate(parameters);
+}
+
+void
+ControlCommand::applyDefaultsToRequest(ControlParameters& parameters) const
+{
+}
+
+void
+ControlCommand::validateResponse(const ControlParameters& parameters) const
+{
+ m_responseValidator.validate(parameters);
+}
+
+void
+ControlCommand::applyDefaultsToResponse(ControlParameters& parameters) const
+{
+}
+
+Name
+ControlCommand::getRequestName(const Name& commandPrefix,
+ const ControlParameters& parameters) const
+{
+ this->validateRequest(parameters);
+
+ Name name = commandPrefix;
+ name.append(m_module).append(m_verb);
+ name.append(parameters.wireEncode());
+ return name;
+}
+
+ControlCommand::FieldValidator::FieldValidator()
+ : m_required(CONTROL_PARAMETER_UBOUND)
+ , m_optional(CONTROL_PARAMETER_UBOUND)
+{
+}
+
+void
+ControlCommand::FieldValidator::validate(const ControlParameters& parameters) const
+{
+ const std::vector<bool>& presentFields = parameters.getPresentFields();
+
+ for (size_t i = 0; i < CONTROL_PARAMETER_UBOUND; ++i) {
+ bool isPresent = presentFields[i];
+ if (m_required[i]) {
+ if (!isPresent) {
+ BOOST_THROW_EXCEPTION(ArgumentError(CONTROL_PARAMETER_FIELD[i] + " is required but "
+ "missing"));
+ }
+ }
+ else if (isPresent && !m_optional[i]) {
+ BOOST_THROW_EXCEPTION(ArgumentError(CONTROL_PARAMETER_FIELD[i] + " is forbidden but "
+ "present"));
+ }
+ }
+}
+
+FaceCreateCommand::FaceCreateCommand()
+ : ControlCommand("faces", "create")
+{
+ m_requestValidator
+ .required(CONTROL_PARAMETER_URI)
+ .optional(CONTROL_PARAMETER_FACE_PERSISTENCY)
+ .optional(CONTROL_PARAMETER_FLAGS)
+ .optional(CONTROL_PARAMETER_MASK);
+ m_responseValidator
+ .required(CONTROL_PARAMETER_FACE_ID)
+ .required(CONTROL_PARAMETER_FACE_PERSISTENCY)
+ .optional(CONTROL_PARAMETER_FLAGS)
+ .optional(CONTROL_PARAMETER_URI);
+}
+
+void
+FaceCreateCommand::applyDefaultsToRequest(ControlParameters& parameters) const
+{
+ parameters.setFaceId(0);
+
+ if (!parameters.hasFacePersistency()) {
+ parameters.setFacePersistency(FacePersistency::FACE_PERSISTENCY_PERSISTENT);
+ }
+}
+
+void
+FaceCreateCommand::validateRequest(const ControlParameters& parameters) const
+{
+ this->ControlCommand::validateRequest(parameters);
+
+ if (parameters.hasFlags() != parameters.hasMask()) {
+ BOOST_THROW_EXCEPTION(ArgumentError("Flags must be accompanied by Mask"));
+ }
+}
+
+void
+FaceCreateCommand::validateResponse(const ControlParameters& parameters) const
+{
+ this->ControlCommand::validateResponse(parameters);
+
+ if (parameters.getFaceId() == 0) {
+ BOOST_THROW_EXCEPTION(ArgumentError("FaceId must not be zero"));
+ }
+}
+
+FaceUpdateCommand::FaceUpdateCommand()
+ : ControlCommand("faces", "update")
+{
+ m_requestValidator
+ .optional(CONTROL_PARAMETER_FACE_ID)
+ .optional(CONTROL_PARAMETER_FACE_PERSISTENCY)
+ .optional(CONTROL_PARAMETER_FLAGS)
+ .optional(CONTROL_PARAMETER_MASK);
+ m_responseValidator
+ .required(CONTROL_PARAMETER_FACE_ID)
+ .required(CONTROL_PARAMETER_FACE_PERSISTENCY)
+ .required(CONTROL_PARAMETER_FLAGS);
+}
+
+void
+FaceUpdateCommand::applyDefaultsToRequest(ControlParameters& parameters) const
+{
+ if (!parameters.hasFaceId()) {
+ parameters.setFaceId(0);
+ }
+}
+
+void
+FaceUpdateCommand::validateRequest(const ControlParameters& parameters) const
+{
+ this->ControlCommand::validateRequest(parameters);
+
+ if (parameters.hasFlags() != parameters.hasMask()) {
+ BOOST_THROW_EXCEPTION(ArgumentError("Flags must be accompanied by Mask"));
+ }
+}
+
+void
+FaceUpdateCommand::validateResponse(const ControlParameters& parameters) const
+{
+ this->ControlCommand::validateResponse(parameters);
+
+ if (parameters.getFaceId() == 0) {
+ BOOST_THROW_EXCEPTION(ArgumentError("FaceId must not be zero"));
+ }
+}
+
+FaceDestroyCommand::FaceDestroyCommand()
+ : ControlCommand("faces", "destroy")
+{
+ m_requestValidator
+ .required(CONTROL_PARAMETER_FACE_ID);
+ m_responseValidator = m_requestValidator;
+}
+
+void
+FaceDestroyCommand::validateRequest(const ControlParameters& parameters) const
+{
+ this->ControlCommand::validateRequest(parameters);
+
+ if (parameters.getFaceId() == 0) {
+ BOOST_THROW_EXCEPTION(ArgumentError("FaceId must not be zero"));
+ }
+}
+
+void
+FaceDestroyCommand::validateResponse(const ControlParameters& parameters) const
+{
+ this->validateRequest(parameters);
+}
+
+FaceLocalControlCommand::FaceLocalControlCommand(const std::string& verb)
+ : ControlCommand("faces", verb)
+{
+ m_requestValidator
+ .required(CONTROL_PARAMETER_LOCAL_CONTROL_FEATURE);
+ m_responseValidator = m_requestValidator;
+}
+
+void
+FaceLocalControlCommand::validateRequest(const ControlParameters& parameters) const
+{
+ this->ControlCommand::validateRequest(parameters);
+
+ switch (parameters.getLocalControlFeature()) {
+ case LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID:
+ case LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID:
+ break;
+ default:
+ BOOST_THROW_EXCEPTION(ArgumentError("LocalControlFeature is invalid"));
+ }
+}
+
+void
+FaceLocalControlCommand::validateResponse(const ControlParameters& parameters) const
+{
+ this->validateRequest(parameters);
+}
+
+FaceEnableLocalControlCommand::FaceEnableLocalControlCommand()
+ : FaceLocalControlCommand("enable-local-control")
+{
+}
+
+FaceDisableLocalControlCommand::FaceDisableLocalControlCommand()
+ : FaceLocalControlCommand("disable-local-control")
+{
+}
+
+FibAddNextHopCommand::FibAddNextHopCommand()
+ : ControlCommand("fib", "add-nexthop")
+{
+ m_requestValidator
+ .required(CONTROL_PARAMETER_NAME)
+ .optional(CONTROL_PARAMETER_FACE_ID)
+ .optional(CONTROL_PARAMETER_COST);
+ m_responseValidator
+ .required(CONTROL_PARAMETER_NAME)
+ .required(CONTROL_PARAMETER_FACE_ID)
+ .required(CONTROL_PARAMETER_COST);
+}
+
+void
+FibAddNextHopCommand::applyDefaultsToRequest(ControlParameters& parameters) const
+{
+ if (!parameters.hasFaceId()) {
+ parameters.setFaceId(0);
+ }
+ if (!parameters.hasCost()) {
+ parameters.setCost(0);
+ }
+}
+
+void
+FibAddNextHopCommand::validateResponse(const ControlParameters& parameters) const
+{
+ this->ControlCommand::validateResponse(parameters);
+
+ if (parameters.getFaceId() == 0) {
+ BOOST_THROW_EXCEPTION(ArgumentError("FaceId must not be zero"));
+ }
+}
+
+FibRemoveNextHopCommand::FibRemoveNextHopCommand()
+ : ControlCommand("fib", "remove-nexthop")
+{
+ m_requestValidator
+ .required(CONTROL_PARAMETER_NAME)
+ .optional(CONTROL_PARAMETER_FACE_ID);
+ m_responseValidator
+ .required(CONTROL_PARAMETER_NAME)
+ .required(CONTROL_PARAMETER_FACE_ID);
+}
+
+void
+FibRemoveNextHopCommand::applyDefaultsToRequest(ControlParameters& parameters) const
+{
+ if (!parameters.hasFaceId()) {
+ parameters.setFaceId(0);
+ }
+}
+
+void
+FibRemoveNextHopCommand::validateResponse(const ControlParameters& parameters) const
+{
+ this->ControlCommand::validateResponse(parameters);
+
+ if (parameters.getFaceId() == 0) {
+ BOOST_THROW_EXCEPTION(ArgumentError("FaceId must not be zero"));
+ }
+}
+
+StrategyChoiceSetCommand::StrategyChoiceSetCommand()
+ : ControlCommand("strategy-choice", "set")
+{
+ m_requestValidator
+ .required(CONTROL_PARAMETER_NAME)
+ .required(CONTROL_PARAMETER_STRATEGY);
+ m_responseValidator = m_requestValidator;
+}
+
+StrategyChoiceUnsetCommand::StrategyChoiceUnsetCommand()
+ : ControlCommand("strategy-choice", "unset")
+{
+ m_requestValidator
+ .required(CONTROL_PARAMETER_NAME);
+ m_responseValidator = m_requestValidator;
+}
+
+void
+StrategyChoiceUnsetCommand::validateRequest(const ControlParameters& parameters) const
+{
+ this->ControlCommand::validateRequest(parameters);
+
+ if (parameters.getName().size() == 0) {
+ BOOST_THROW_EXCEPTION(ArgumentError("Name must not be ndn:/"));
+ }
+}
+
+void
+StrategyChoiceUnsetCommand::validateResponse(const ControlParameters& parameters) const
+{
+ this->validateRequest(parameters);
+}
+
+RibRegisterCommand::RibRegisterCommand()
+ : ControlCommand("rib", "register")
+{
+ m_requestValidator
+ .required(CONTROL_PARAMETER_NAME)
+ .optional(CONTROL_PARAMETER_FACE_ID)
+ .optional(CONTROL_PARAMETER_ORIGIN)
+ .optional(CONTROL_PARAMETER_COST)
+ .optional(CONTROL_PARAMETER_FLAGS)
+ .optional(CONTROL_PARAMETER_EXPIRATION_PERIOD);
+ m_responseValidator
+ .required(CONTROL_PARAMETER_NAME)
+ .required(CONTROL_PARAMETER_FACE_ID)
+ .required(CONTROL_PARAMETER_ORIGIN)
+ .required(CONTROL_PARAMETER_COST)
+ .required(CONTROL_PARAMETER_FLAGS)
+ .optional(CONTROL_PARAMETER_EXPIRATION_PERIOD);
+}
+
+void
+RibRegisterCommand::applyDefaultsToRequest(ControlParameters& parameters) const
+{
+ if (!parameters.hasFaceId()) {
+ parameters.setFaceId(0);
+ }
+ if (!parameters.hasOrigin()) {
+ parameters.setOrigin(ROUTE_ORIGIN_APP);
+ }
+ if (!parameters.hasCost()) {
+ parameters.setCost(0);
+ }
+ if (!parameters.hasFlags()) {
+ parameters.setFlags(ROUTE_FLAG_CHILD_INHERIT);
+ }
+}
+
+void
+RibRegisterCommand::validateResponse(const ControlParameters& parameters) const
+{
+ this->ControlCommand::validateResponse(parameters);
+
+ if (parameters.getFaceId() == 0) {
+ BOOST_THROW_EXCEPTION(ArgumentError("FaceId must not be zero"));
+ }
+}
+
+RibUnregisterCommand::RibUnregisterCommand()
+ : ControlCommand("rib", "unregister")
+{
+ m_requestValidator
+ .required(CONTROL_PARAMETER_NAME)
+ .optional(CONTROL_PARAMETER_FACE_ID)
+ .optional(CONTROL_PARAMETER_ORIGIN);
+ m_responseValidator
+ .required(CONTROL_PARAMETER_NAME)
+ .required(CONTROL_PARAMETER_FACE_ID)
+ .required(CONTROL_PARAMETER_ORIGIN);
+}
+
+void
+RibUnregisterCommand::applyDefaultsToRequest(ControlParameters& parameters) const
+{
+ if (!parameters.hasFaceId()) {
+ parameters.setFaceId(0);
+ }
+ if (!parameters.hasOrigin()) {
+ parameters.setOrigin(ROUTE_ORIGIN_APP);
+ }
+}
+
+void
+RibUnregisterCommand::validateResponse(const ControlParameters& parameters) const
+{
+ this->ControlCommand::validateResponse(parameters);
+
+ if (parameters.getFaceId() == 0) {
+ BOOST_THROW_EXCEPTION(ArgumentError("FaceId must not be zero"));
+ }
+}
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/mgmt/nfd/control-command.hpp b/src/mgmt/nfd/control-command.hpp
new file mode 100644
index 0000000..7544156
--- /dev/null
+++ b/src/mgmt/nfd/control-command.hpp
@@ -0,0 +1,348 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_CONTROL_COMMAND_HPP
+#define NDN_MGMT_NFD_CONTROL_COMMAND_HPP
+
+#include "control-parameters.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * \ingroup management
+ * \brief base class of NFD ControlCommand
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
+ */
+class ControlCommand : noncopyable
+{
+public:
+ /** \brief represents an error in ControlParameters
+ */
+ class ArgumentError : public std::invalid_argument
+ {
+ public:
+ explicit
+ ArgumentError(const std::string& what)
+ : std::invalid_argument(what)
+ {
+ }
+ };
+
+ virtual
+ ~ControlCommand();
+
+ /** \brief validate request parameters
+ * \throw ArgumentError if parameters are invalid
+ */
+ virtual void
+ validateRequest(const ControlParameters& parameters) const;
+
+ /** \brief apply default values to missing fields in request
+ */
+ virtual void
+ applyDefaultsToRequest(ControlParameters& parameters) const;
+
+ /** \brief validate response parameters
+ * \throw ArgumentError if parameters are invalid
+ */
+ virtual void
+ validateResponse(const ControlParameters& parameters) const;
+
+ /** \brief apply default values to missing fields in response
+ */
+ virtual void
+ applyDefaultsToResponse(ControlParameters& parameters) const;
+
+ /** \brief construct the Name for a request Interest
+ * \throw ArgumentError if parameters are invalid
+ */
+ Name
+ getRequestName(const Name& commandPrefix, const ControlParameters& parameters) const;
+
+protected:
+ ControlCommand(const std::string& module, const std::string& verb);
+
+ class FieldValidator
+ {
+ public:
+ FieldValidator();
+
+ /** \brief declare a required field
+ */
+ FieldValidator&
+ required(ControlParameterField field)
+ {
+ m_required[field] = true;
+ return *this;
+ }
+
+ /** \brief declare an optional field
+ */
+ FieldValidator&
+ optional(ControlParameterField field)
+ {
+ m_optional[field] = true;
+ return *this;
+ }
+
+ /** \brief verify that all required fields are present,
+ * and all present fields are either required or optional
+ * \throw ArgumentError
+ */
+ void
+ validate(const ControlParameters& parameters) const;
+
+ private:
+ std::vector<bool> m_required;
+ std::vector<bool> m_optional;
+ };
+
+protected:
+ /** \brief FieldValidator for request ControlParameters
+ *
+ * Constructor of subclass should populate this validator.
+ */
+ FieldValidator m_requestValidator;
+ /** \brief FieldValidator for response ControlParameters
+ *
+ * Constructor of subclass should populate this validator.
+ */
+ FieldValidator m_responseValidator;
+
+private:
+ name::Component m_module;
+ name::Component m_verb;
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a faces/create command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Create-a-face
+ */
+class FaceCreateCommand : public ControlCommand
+{
+public:
+ FaceCreateCommand();
+
+ virtual void
+ applyDefaultsToRequest(ControlParameters& parameters) const override;
+
+ virtual void
+ validateRequest(const ControlParameters& parameters) const override;
+
+ virtual void
+ validateResponse(const ControlParameters& parameters) const override;
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a faces/update command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Update-a-face
+ */
+class FaceUpdateCommand : public ControlCommand
+{
+public:
+ FaceUpdateCommand();
+
+ virtual void
+ applyDefaultsToRequest(ControlParameters& parameters) const override;
+
+ virtual void
+ validateRequest(const ControlParameters& parameters) const override;
+
+ /**
+ * \note This can only validate ControlParameters in a success response.
+ * Failure responses should be validated with validateRequest.
+ */
+ virtual void
+ validateResponse(const ControlParameters& parameters) const override;
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a faces/destroy command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Destroy-a-face
+ */
+class FaceDestroyCommand : public ControlCommand
+{
+public:
+ FaceDestroyCommand();
+
+ virtual void
+ validateRequest(const ControlParameters& parameters) const override;
+
+ virtual void
+ validateResponse(const ControlParameters& parameters) const override;
+};
+
+
+/**
+ * \ingroup management
+ * \brief Base class for faces/[*]-local-control commands
+ */
+class FaceLocalControlCommand : public ControlCommand
+{
+public:
+ virtual void
+ validateRequest(const ControlParameters& parameters) const override;
+
+ virtual void
+ validateResponse(const ControlParameters& parameters) const override;
+
+protected:
+ explicit
+ FaceLocalControlCommand(const std::string& verb);
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a faces/enable-local-control command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Enable-a-LocalControlHeader-feature
+ */
+class FaceEnableLocalControlCommand : public FaceLocalControlCommand
+{
+public:
+ FaceEnableLocalControlCommand();
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a faces/disable-local-control command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Disable-a-LocalControlHeader-feature
+ */
+class FaceDisableLocalControlCommand : public FaceLocalControlCommand
+{
+public:
+ FaceDisableLocalControlCommand();
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a fib/add-nexthop command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#Add-a-nexthop
+ */
+class FibAddNextHopCommand : public ControlCommand
+{
+public:
+ FibAddNextHopCommand();
+
+ virtual void
+ applyDefaultsToRequest(ControlParameters& parameters) const override;
+
+ virtual void
+ validateResponse(const ControlParameters& parameters) const override;
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a fib/remove-nexthop command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#Remove-a-nexthop
+ */
+class FibRemoveNextHopCommand : public ControlCommand
+{
+public:
+ FibRemoveNextHopCommand();
+
+ virtual void
+ applyDefaultsToRequest(ControlParameters& parameters) const override;
+
+ virtual void
+ validateResponse(const ControlParameters& parameters) const override;
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a strategy-choice/set command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice#Set-the-strategy-for-a-namespace
+ */
+class StrategyChoiceSetCommand : public ControlCommand
+{
+public:
+ StrategyChoiceSetCommand();
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a strategy-choice/set command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice#Unset-the-strategy-for-a-namespace
+ */
+class StrategyChoiceUnsetCommand : public ControlCommand
+{
+public:
+ StrategyChoiceUnsetCommand();
+
+ virtual void
+ validateRequest(const ControlParameters& parameters) const override;
+
+ virtual void
+ validateResponse(const ControlParameters& parameters) const override;
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a rib/register command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/RibMgmt#Register-a-route
+ */
+class RibRegisterCommand : public ControlCommand
+{
+public:
+ RibRegisterCommand();
+
+ virtual void
+ applyDefaultsToRequest(ControlParameters& parameters) const override;
+
+ virtual void
+ validateResponse(const ControlParameters& parameters) const override;
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a rib/unregister command
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/RibMgmt#Unregister-a-route
+ */
+class RibUnregisterCommand : public ControlCommand
+{
+public:
+ RibUnregisterCommand();
+
+ virtual void
+ applyDefaultsToRequest(ControlParameters& parameters) const override;
+
+ virtual void
+ validateResponse(const ControlParameters& parameters) const override;
+};
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_CONTROL_COMMAND_HPP
diff --git a/src/mgmt/nfd/control-parameters.cpp b/src/mgmt/nfd/control-parameters.cpp
new file mode 100644
index 0000000..30f8fe9
--- /dev/null
+++ b/src/mgmt/nfd/control-parameters.cpp
@@ -0,0 +1,335 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "control-parameters.hpp"
+#include "encoding/tlv-nfd.hpp"
+#include "encoding/block-helpers.hpp"
+#include "util/concepts.hpp"
+
+namespace ndn {
+namespace nfd {
+
+//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<ControlParameters>));
+BOOST_CONCEPT_ASSERT((WireEncodable<ControlParameters>));
+BOOST_CONCEPT_ASSERT((WireDecodable<ControlParameters>));
+static_assert(std::is_base_of<tlv::Error, ControlParameters::Error>::value,
+ "ControlParameters::Error must inherit from tlv::Error");
+
+ControlParameters::ControlParameters()
+ : m_hasFields(CONTROL_PARAMETER_UBOUND)
+{
+}
+
+ControlParameters::ControlParameters(const Block& block)
+ : m_hasFields(CONTROL_PARAMETER_UBOUND)
+{
+ wireDecode(block);
+}
+
+template<encoding::Tag TAG>
+size_t
+ControlParameters::wireEncode(EncodingImpl<TAG>& encoder) const
+{
+ size_t totalLength = 0;
+
+ if (this->hasFacePersistency()) {
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::FacePersistency, m_facePersistency);
+ }
+ if (this->hasExpirationPeriod()) {
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::ExpirationPeriod, m_expirationPeriod.count());
+ }
+ if (this->hasStrategy()) {
+ totalLength += prependNestedBlock(encoder, tlv::nfd::Strategy, m_strategy);
+ }
+ if (this->hasMask()) {
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::Mask, m_mask);
+ }
+ if (this->hasFlags()) {
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::Flags, m_flags);
+ }
+ if (this->hasCost()) {
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::Cost, m_cost);
+ }
+ if (this->hasOrigin()) {
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::Origin, m_origin);
+ }
+ if (this->hasLocalControlFeature()) {
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::LocalControlFeature, m_localControlFeature);
+ }
+ if (this->hasUri()) {
+ size_t valLength = encoder.prependByteArray(
+ reinterpret_cast<const uint8_t*>(m_uri.c_str()), m_uri.size());
+ totalLength += valLength;
+ totalLength += encoder.prependVarNumber(valLength);
+ totalLength += encoder.prependVarNumber(tlv::nfd::Uri);
+ }
+ if (this->hasFaceId()) {
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::FaceId, m_faceId);
+ }
+ if (this->hasName()) {
+ totalLength += m_name.wireEncode(encoder);
+ }
+
+ totalLength += encoder.prependVarNumber(totalLength);
+ totalLength += encoder.prependVarNumber(tlv::nfd::ControlParameters);
+ return totalLength;
+}
+
+template size_t
+ControlParameters::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>&) const;
+
+template size_t
+ControlParameters::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>&) const;
+
+Block
+ControlParameters::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+ControlParameters::wireDecode(const Block& block)
+{
+ if (block.type() != tlv::nfd::ControlParameters) {
+ BOOST_THROW_EXCEPTION(Error("Expecting TLV-TYPE ControlParameters"));
+ }
+ m_wire = block;
+ m_wire.parse();
+ Block::element_const_iterator val;
+
+ val = m_wire.find(tlv::Name);
+ m_hasFields[CONTROL_PARAMETER_NAME] = val != m_wire.elements_end();
+ if (this->hasName()) {
+ m_name.wireDecode(*val);
+ }
+
+ val = m_wire.find(tlv::nfd::FaceId);
+ m_hasFields[CONTROL_PARAMETER_FACE_ID] = val != m_wire.elements_end();
+ if (this->hasFaceId()) {
+ m_faceId = static_cast<uint64_t>(readNonNegativeInteger(*val));
+ }
+
+ val = m_wire.find(tlv::nfd::Uri);
+ m_hasFields[CONTROL_PARAMETER_URI] = val != m_wire.elements_end();
+ if (this->hasUri()) {
+ m_uri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ }
+
+ val = m_wire.find(tlv::nfd::LocalControlFeature);
+ m_hasFields[CONTROL_PARAMETER_LOCAL_CONTROL_FEATURE] = val != m_wire.elements_end();
+ if (this->hasLocalControlFeature()) {
+ m_localControlFeature = static_cast<LocalControlFeature>(readNonNegativeInteger(*val));
+ }
+
+ val = m_wire.find(tlv::nfd::Origin);
+ m_hasFields[CONTROL_PARAMETER_ORIGIN] = val != m_wire.elements_end();
+ if (this->hasOrigin()) {
+ m_origin = static_cast<uint64_t>(readNonNegativeInteger(*val));
+ }
+
+ val = m_wire.find(tlv::nfd::Cost);
+ m_hasFields[CONTROL_PARAMETER_COST] = val != m_wire.elements_end();
+ if (this->hasCost()) {
+ m_cost = static_cast<uint64_t>(readNonNegativeInteger(*val));
+ }
+
+ val = m_wire.find(tlv::nfd::Flags);
+ m_hasFields[CONTROL_PARAMETER_FLAGS] = val != m_wire.elements_end();
+ if (this->hasFlags()) {
+ m_flags = static_cast<uint64_t>(readNonNegativeInteger(*val));
+ }
+
+ val = m_wire.find(tlv::nfd::Mask);
+ m_hasFields[CONTROL_PARAMETER_MASK] = val != m_wire.elements_end();
+ if (this->hasMask()) {
+ m_mask = static_cast<uint64_t>(readNonNegativeInteger(*val));
+ }
+
+ val = m_wire.find(tlv::nfd::Strategy);
+ m_hasFields[CONTROL_PARAMETER_STRATEGY] = val != m_wire.elements_end();
+ if (this->hasStrategy()) {
+ val->parse();
+ if (val->elements().empty()) {
+ BOOST_THROW_EXCEPTION(Error("Expecting Strategy/Name"));
+ }
+ else {
+ m_strategy.wireDecode(*val->elements_begin());
+ }
+ }
+
+ val = m_wire.find(tlv::nfd::ExpirationPeriod);
+ m_hasFields[CONTROL_PARAMETER_EXPIRATION_PERIOD] = val != m_wire.elements_end();
+ if (this->hasExpirationPeriod()) {
+ m_expirationPeriod = time::milliseconds(readNonNegativeInteger(*val));
+ }
+
+ val = m_wire.find(tlv::nfd::FacePersistency);
+ m_hasFields[CONTROL_PARAMETER_FACE_PERSISTENCY] = val != m_wire.elements_end();
+ if (this->hasFacePersistency()) {
+ m_facePersistency = static_cast<FacePersistency>(readNonNegativeInteger(*val));
+ }
+}
+
+bool
+ControlParameters::hasFlagBit(size_t bit) const
+{
+ if (bit >= 64) {
+ BOOST_THROW_EXCEPTION(std::out_of_range("bit must be within range [0, 64)"));
+ }
+
+ if (!hasMask()) {
+ return false;
+ }
+
+ return getMask() & (1 << bit);
+}
+
+bool
+ControlParameters::getFlagBit(size_t bit) const
+{
+ if (bit >= 64) {
+ BOOST_THROW_EXCEPTION(std::out_of_range("bit must be within range [0, 64)"));
+ }
+
+ if (!hasFlags()) {
+ return false;
+ }
+
+ return getFlags() & (1 << bit);
+}
+
+ControlParameters&
+ControlParameters::setFlagBit(size_t bit, bool value, bool wantMask/* = true*/)
+{
+ if (bit >= 64) {
+ BOOST_THROW_EXCEPTION(std::out_of_range("bit must be within range [0, 64)"));
+ }
+
+ uint64_t flags = hasFlags() ? getFlags() : 0;
+ if (value) {
+ flags |= (1 << bit);
+ }
+ else {
+ flags &= ~(1 << bit);
+ }
+ setFlags(flags);
+
+ if (wantMask) {
+ uint64_t mask = hasMask() ? getMask() : 0;
+ mask |= (1 << bit);
+ setMask(mask);
+ }
+
+ return *this;
+}
+
+ControlParameters&
+ControlParameters::unsetFlagBit(size_t bit)
+{
+ if (bit >= 64) {
+ BOOST_THROW_EXCEPTION(std::out_of_range("bit must be within range [0, 64)"));
+ }
+
+ uint64_t mask = hasMask() ? getMask() : 0;
+ mask &= ~(1 << bit);
+ if (mask == 0) {
+ unsetMask();
+ unsetFlags();
+ }
+ else {
+ setMask(mask);
+ }
+
+ return *this;
+}
+
+std::ostream&
+operator<<(std::ostream& os, const ControlParameters& parameters)
+{
+ os << "ControlParameters(";
+
+ if (parameters.hasName()) {
+ os << "Name: " << parameters.getName() << ", ";
+ }
+
+ if (parameters.hasFaceId()) {
+ os << "FaceId: " << parameters.getFaceId() << ", ";
+ }
+
+ if (parameters.hasUri()) {
+ os << "Uri: " << parameters.getUri() << ", ";
+ }
+
+ if (parameters.hasLocalControlFeature()) {
+ os << "LocalControlFeature: " << parameters.getLocalControlFeature() << ", ";
+ }
+
+ if (parameters.hasOrigin()) {
+ os << "Origin: " << parameters.getOrigin() << ", ";
+ }
+
+ if (parameters.hasCost()) {
+ os << "Cost: " << parameters.getCost() << ", ";
+ }
+
+ if (parameters.hasFlags()) {
+ std::ios_base::fmtflags osFlags = os.flags();
+ os << "Flags: " << std::showbase << std::hex << parameters.getFlags() << ", ";
+ os.flags(osFlags);
+ }
+
+ if (parameters.hasMask()) {
+ std::ios_base::fmtflags osFlags = os.flags();
+ os << "Mask: " << std::showbase << std::hex << parameters.getMask() << ", ";
+ os.flags(osFlags);
+ }
+
+ if (parameters.hasStrategy()) {
+ os << "Strategy: " << parameters.getStrategy() << ", ";
+ }
+
+ if (parameters.hasExpirationPeriod()) {
+ os << "ExpirationPeriod: " << parameters.getExpirationPeriod() << ", ";
+ }
+
+ if (parameters.hasFacePersistency()) {
+ os << "FacePersistency: " << parameters.getFacePersistency() << ", ";
+ }
+
+ os << ")";
+ return os;
+}
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/mgmt/nfd/control-parameters.hpp b/src/mgmt/nfd/control-parameters.hpp
new file mode 100644
index 0000000..d57c75d
--- /dev/null
+++ b/src/mgmt/nfd/control-parameters.hpp
@@ -0,0 +1,514 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_CONTROL_PARAMETERS_HPP
+#define NDN_MGMT_NFD_CONTROL_PARAMETERS_HPP
+
+#include "../../encoding/nfd-constants.hpp"
+#include "../../name.hpp"
+#include "../../util/time.hpp"
+#include "../control-parameters.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * \ingroup management
+ */
+enum ControlParameterField {
+ CONTROL_PARAMETER_NAME,
+ CONTROL_PARAMETER_FACE_ID,
+ CONTROL_PARAMETER_URI,
+ CONTROL_PARAMETER_LOCAL_CONTROL_FEATURE,
+ CONTROL_PARAMETER_ORIGIN,
+ CONTROL_PARAMETER_COST,
+ CONTROL_PARAMETER_FLAGS,
+ CONTROL_PARAMETER_MASK,
+ CONTROL_PARAMETER_STRATEGY,
+ CONTROL_PARAMETER_EXPIRATION_PERIOD,
+ CONTROL_PARAMETER_FACE_PERSISTENCY,
+ CONTROL_PARAMETER_UBOUND
+};
+
+const std::string CONTROL_PARAMETER_FIELD[CONTROL_PARAMETER_UBOUND] = {
+ "Name",
+ "FaceId",
+ "Uri",
+ "LocalControlFeature",
+ "Origin",
+ "Cost",
+ "Flags",
+ "Mask",
+ "Strategy",
+ "ExpirationPeriod",
+ "FacePersistency"
+};
+
+/**
+ * \ingroup management
+ * \deprecated use Flags+Mask fields instead
+ */
+enum LocalControlFeature {
+ LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID = 1,
+ LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID = 2
+};
+
+/**
+ * \ingroup management
+ * \brief represents parameters in a ControlCommand request or response
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/ControlCommand#ControlParameters
+ * \details This type is copyable because it's an abstraction of a TLV type.
+ */
+class ControlParameters : public ndn::mgmt::ControlParameters
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+ ControlParameters();
+
+ explicit
+ ControlParameters(const Block& block);
+
+ template<encoding::Tag TAG>
+ size_t
+ wireEncode(EncodingImpl<TAG>& encoder) const;
+
+ virtual Block
+ wireEncode() const final;
+
+ virtual void
+ wireDecode(const Block& wire) final;
+
+public: // getters & setters
+ bool
+ hasName() const
+ {
+ return m_hasFields[CONTROL_PARAMETER_NAME];
+ }
+
+ const Name&
+ getName() const
+ {
+ BOOST_ASSERT(this->hasName());
+ return m_name;
+ }
+
+ ControlParameters&
+ setName(const Name& name)
+ {
+ m_wire.reset();
+ m_name = name;
+ m_hasFields[CONTROL_PARAMETER_NAME] = true;
+ return *this;
+ }
+
+ ControlParameters&
+ unsetName()
+ {
+ m_wire.reset();
+ m_hasFields[CONTROL_PARAMETER_NAME] = false;
+ return *this;
+ }
+
+ bool
+ hasFaceId() const
+ {
+ return m_hasFields[CONTROL_PARAMETER_FACE_ID];
+ }
+
+ uint64_t
+ getFaceId() const
+ {
+ BOOST_ASSERT(this->hasFaceId());
+ return m_faceId;
+ }
+
+ ControlParameters&
+ setFaceId(uint64_t faceId)
+ {
+ m_wire.reset();
+ m_faceId = faceId;
+ m_hasFields[CONTROL_PARAMETER_FACE_ID] = true;
+ return *this;
+ }
+
+ ControlParameters&
+ unsetFaceId()
+ {
+ m_wire.reset();
+ m_hasFields[CONTROL_PARAMETER_FACE_ID] = false;
+ return *this;
+ }
+
+ bool
+ hasUri() const
+ {
+ return m_hasFields[CONTROL_PARAMETER_URI];
+ }
+
+ const std::string&
+ getUri() const
+ {
+ BOOST_ASSERT(this->hasUri());
+ return m_uri;
+ }
+
+ ControlParameters&
+ setUri(const std::string& uri)
+ {
+ m_wire.reset();
+ m_uri = uri;
+ m_hasFields[CONTROL_PARAMETER_URI] = true;
+ return *this;
+ }
+
+ ControlParameters&
+ unsetUri()
+ {
+ m_wire.reset();
+ m_hasFields[CONTROL_PARAMETER_URI] = false;
+ return *this;
+ }
+
+ /**
+ * \deprecated use Flags+Mask fields instead
+ */
+ bool
+ hasLocalControlFeature() const
+ {
+ return m_hasFields[CONTROL_PARAMETER_LOCAL_CONTROL_FEATURE];
+ }
+
+ /**
+ * \deprecated use Flags+Mask fields instead
+ */
+ LocalControlFeature
+ getLocalControlFeature() const
+ {
+ BOOST_ASSERT(this->hasLocalControlFeature());
+ return m_localControlFeature;
+ }
+
+ /**
+ * \deprecated use Flags+Mask fields instead
+ */
+ ControlParameters&
+ setLocalControlFeature(LocalControlFeature localControlFeature)
+ {
+ m_wire.reset();
+ m_localControlFeature = localControlFeature;
+ m_hasFields[CONTROL_PARAMETER_LOCAL_CONTROL_FEATURE] = true;
+ return *this;
+ }
+
+ /**
+ * \deprecated use Flags+Mask fields instead
+ */
+ ControlParameters&
+ unsetLocalControlFeature()
+ {
+ m_wire.reset();
+ m_hasFields[CONTROL_PARAMETER_LOCAL_CONTROL_FEATURE] = false;
+ return *this;
+ }
+
+ bool
+ hasOrigin() const
+ {
+ return m_hasFields[CONTROL_PARAMETER_ORIGIN];
+ }
+
+ uint64_t
+ getOrigin() const
+ {
+ BOOST_ASSERT(this->hasOrigin());
+ return m_origin;
+ }
+
+ ControlParameters&
+ setOrigin(uint64_t origin)
+ {
+ m_wire.reset();
+ m_origin = origin;
+ m_hasFields[CONTROL_PARAMETER_ORIGIN] = true;
+ return *this;
+ }
+
+ ControlParameters&
+ unsetOrigin()
+ {
+ m_wire.reset();
+ m_hasFields[CONTROL_PARAMETER_ORIGIN] = false;
+ return *this;
+ }
+
+ bool
+ hasCost() const
+ {
+ return m_hasFields[CONTROL_PARAMETER_COST];
+ }
+
+ uint64_t
+ getCost() const
+ {
+ BOOST_ASSERT(this->hasCost());
+ return m_cost;
+ }
+
+ ControlParameters&
+ setCost(uint64_t cost)
+ {
+ m_wire.reset();
+ m_cost = cost;
+ m_hasFields[CONTROL_PARAMETER_COST] = true;
+ return *this;
+ }
+
+ ControlParameters&
+ unsetCost()
+ {
+ m_wire.reset();
+ m_hasFields[CONTROL_PARAMETER_COST] = false;
+ return *this;
+ }
+
+ bool
+ hasFlags() const
+ {
+ return m_hasFields[CONTROL_PARAMETER_FLAGS];
+ }
+
+ uint64_t
+ getFlags() const
+ {
+ BOOST_ASSERT(this->hasFlags());
+ return m_flags;
+ }
+
+ ControlParameters&
+ setFlags(uint64_t flags)
+ {
+ m_wire.reset();
+ m_flags = flags;
+ m_hasFields[CONTROL_PARAMETER_FLAGS] = true;
+ return *this;
+ }
+
+ ControlParameters&
+ unsetFlags()
+ {
+ m_wire.reset();
+ m_hasFields[CONTROL_PARAMETER_FLAGS] = false;
+ return *this;
+ }
+
+ bool
+ hasMask() const
+ {
+ return m_hasFields[CONTROL_PARAMETER_MASK];
+ }
+
+ uint64_t
+ getMask() const
+ {
+ BOOST_ASSERT(this->hasMask());
+ return m_mask;
+ }
+
+ ControlParameters&
+ setMask(uint64_t mask)
+ {
+ m_wire.reset();
+ m_mask = mask;
+ m_hasFields[CONTROL_PARAMETER_MASK] = true;
+ return *this;
+ }
+
+ ControlParameters&
+ unsetMask()
+ {
+ m_wire.reset();
+ m_hasFields[CONTROL_PARAMETER_MASK] = false;
+ return *this;
+ }
+
+ bool
+ hasStrategy() const
+ {
+ return m_hasFields[CONTROL_PARAMETER_STRATEGY];
+ }
+
+ const Name&
+ getStrategy() const
+ {
+ BOOST_ASSERT(this->hasStrategy());
+ return m_strategy;
+ }
+
+ ControlParameters&
+ setStrategy(const Name& strategy)
+ {
+ m_wire.reset();
+ m_strategy = strategy;
+ m_hasFields[CONTROL_PARAMETER_STRATEGY] = true;
+ return *this;
+ }
+
+ ControlParameters&
+ unsetStrategy()
+ {
+ m_wire.reset();
+ m_hasFields[CONTROL_PARAMETER_STRATEGY] = false;
+ return *this;
+ }
+
+ bool
+ hasExpirationPeriod() const
+ {
+ return m_hasFields[CONTROL_PARAMETER_EXPIRATION_PERIOD];
+ }
+
+ const time::milliseconds&
+ getExpirationPeriod() const
+ {
+ BOOST_ASSERT(this->hasExpirationPeriod());
+ return m_expirationPeriod;
+ }
+
+ ControlParameters&
+ setExpirationPeriod(const time::milliseconds& expirationPeriod)
+ {
+ m_wire.reset();
+ m_expirationPeriod = expirationPeriod;
+ m_hasFields[CONTROL_PARAMETER_EXPIRATION_PERIOD] = true;
+ return *this;
+ }
+
+ ControlParameters&
+ unsetExpirationPeriod()
+ {
+ m_wire.reset();
+ m_hasFields[CONTROL_PARAMETER_EXPIRATION_PERIOD] = false;
+ return *this;
+ }
+
+ bool
+ hasFacePersistency() const
+ {
+ return m_hasFields[CONTROL_PARAMETER_FACE_PERSISTENCY];
+ }
+
+ FacePersistency
+ getFacePersistency() const
+ {
+ BOOST_ASSERT(this->hasFacePersistency());
+ return m_facePersistency;
+ }
+
+ ControlParameters&
+ setFacePersistency(FacePersistency persistency)
+ {
+ m_wire.reset();
+ m_facePersistency = persistency;
+ m_hasFields[CONTROL_PARAMETER_FACE_PERSISTENCY] = true;
+ return *this;
+ }
+
+ ControlParameters&
+ unsetFacePersistency()
+ {
+ m_wire.reset();
+ m_hasFields[CONTROL_PARAMETER_FACE_PERSISTENCY] = false;
+ return *this;
+ }
+
+ const std::vector<bool>&
+ getPresentFields() const
+ {
+ return m_hasFields;
+ }
+
+public: // Flags and Mask helpers
+ /**
+ * \return whether bit is enabled in Mask
+ * \param bit bit position within range [0, 64) (least significant bit is 0)
+ */
+ bool
+ hasFlagBit(size_t bit) const;
+
+ /**
+ * \return bit at a position in Flags
+ * \param bit bit position within range [0, 64) (least significant bit is 0)
+ */
+ bool
+ getFlagBit(size_t bit) const;
+
+ /**
+ * \brief set a bit in Flags
+ * \param bit bit position within range [0, 64) (least significant bit is 0)
+ * \param value new value in Flags
+ * \param wantMask if true, enable the bit in Mask
+ */
+ ControlParameters&
+ setFlagBit(size_t bit, bool value, bool wantMask = true);
+
+ /**
+ * \brief disable a bit in Mask
+ * \param bit bit position within range [0, 64) (least significant bit is 0)
+ * \post If all bits are disabled, Flags and Mask fields are deleted.
+ */
+ ControlParameters&
+ unsetFlagBit(size_t bit);
+
+private: // fields
+ std::vector<bool> m_hasFields;
+
+ Name m_name;
+ uint64_t m_faceId;
+ std::string m_uri;
+ LocalControlFeature m_localControlFeature;
+ uint64_t m_origin;
+ uint64_t m_cost;
+ uint64_t m_flags;
+ uint64_t m_mask;
+ Name m_strategy;
+ time::milliseconds m_expirationPeriod;
+ FacePersistency m_facePersistency;
+
+private:
+ mutable Block m_wire;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const ControlParameters& parameters);
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_CONTROL_PARAMETERS_HPP
diff --git a/src/mgmt/nfd/control-response.hpp b/src/mgmt/nfd/control-response.hpp
new file mode 100644
index 0000000..8234e2d
--- /dev/null
+++ b/src/mgmt/nfd/control-response.hpp
@@ -0,0 +1,35 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MANAGEMENT_CONTROL_RESPONSE_HPP
+#define NDN_MANAGEMENT_CONTROL_RESPONSE_HPP
+
+#include "../dispatcher.hpp"
+
+namespace ndn {
+namespace nfd {
+
+typedef ndn::mgmt::ControlResponse ControlResponse;
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MANAGEMENT_CONTROL_RESPONSE_HPP
diff --git a/src/mgmt/nfd/controller.cpp b/src/mgmt/nfd/controller.cpp
new file mode 100644
index 0000000..cfb7956
--- /dev/null
+++ b/src/mgmt/nfd/controller.cpp
@@ -0,0 +1,171 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "controller.hpp"
+#include "../../face.hpp"
+#include "../../security/key-chain.hpp"
+#include "../../util/segment-fetcher.hpp"
+
+namespace ndn {
+namespace nfd {
+
+using ndn::util::SegmentFetcher;
+
+const uint32_t Controller::ERROR_TIMEOUT = 10060; // WinSock ESAETIMEDOUT
+const uint32_t Controller::ERROR_NACK = 10800; // 10000 + TLV-TYPE of Nack header
+const uint32_t Controller::ERROR_VALIDATION = 10021; // 10000 + TLS1_ALERT_DECRYPTION_FAILED
+const uint32_t Controller::ERROR_SERVER = 500;
+const uint32_t Controller::ERROR_LBOUND = 400;
+ValidatorNull Controller::s_validatorNull;
+
+Controller::Controller(Face& face, KeyChain& keyChain, Validator& validator)
+ : m_face(face)
+ , m_keyChain(keyChain)
+ , m_validator(validator)
+{
+}
+
+void
+Controller::startCommand(const shared_ptr<ControlCommand>& command,
+ const ControlParameters& parameters,
+ const CommandSucceedCallback& onSuccess1,
+ const CommandFailCallback& onFailure1,
+ const CommandOptions& options)
+{
+ const CommandSucceedCallback& onSuccess = onSuccess1 ?
+ onSuccess1 : [] (const ControlParameters&) {};
+ const CommandFailCallback& onFailure = onFailure1 ?
+ onFailure1 : [] (const ControlResponse&) {};
+
+ Name requestName = command->getRequestName(options.getPrefix(), parameters);
+ Interest interest(requestName);
+ interest.setInterestLifetime(options.getTimeout());
+ m_keyChain.sign(interest, options.getSigningInfo());
+
+ m_face.expressInterest(interest,
+ [=] (const Interest&, const Data& data) {
+ this->processCommandResponse(data, command, onSuccess, onFailure);
+ },
+ [=] (const Interest&, const lp::Nack&) {
+ onFailure(ControlResponse(Controller::ERROR_NACK, "network Nack received"));
+ },
+ [=] (const Interest&) {
+ onFailure(ControlResponse(Controller::ERROR_TIMEOUT, "request timed out"));
+ });
+}
+
+void
+Controller::processCommandResponse(const Data& data,
+ const shared_ptr<ControlCommand>& command,
+ const CommandSucceedCallback& onSuccess,
+ const CommandFailCallback& onFailure)
+{
+ m_validator.validate(data,
+ [=] (const shared_ptr<const Data>& data) {
+ this->processValidatedCommandResponse(*data, command, onSuccess, onFailure);
+ },
+ [=] (const shared_ptr<const Data>&, const std::string& msg) {
+ onFailure(ControlResponse(ERROR_VALIDATION, msg));
+ }
+ );
+}
+
+void
+Controller::processValidatedCommandResponse(const Data& data,
+ const shared_ptr<ControlCommand>& command,
+ const CommandSucceedCallback& onSuccess,
+ const CommandFailCallback& onFailure)
+{
+ ControlResponse response;
+ try {
+ response.wireDecode(data.getContent().blockFromValue());
+ }
+ catch (const tlv::Error& e) {
+ onFailure(ControlResponse(ERROR_SERVER, e.what()));
+ return;
+ }
+
+ uint32_t code = response.getCode();
+ if (code >= ERROR_LBOUND) {
+ onFailure(response);
+ return;
+ }
+
+ ControlParameters parameters;
+ try {
+ parameters.wireDecode(response.getBody());
+ }
+ catch (const tlv::Error& e) {
+ onFailure(ControlResponse(ERROR_SERVER, e.what()));
+ return;
+ }
+
+ try {
+ command->validateResponse(parameters);
+ }
+ catch (const ControlCommand::ArgumentError& e) {
+ onFailure(ControlResponse(ERROR_SERVER, e.what()));
+ return;
+ }
+
+ onSuccess(parameters);
+}
+
+void
+Controller::fetchDataset(const Name& prefix,
+ const std::function<void(const ConstBufferPtr&)>& processResponse,
+ const DatasetFailCallback& onFailure,
+ const CommandOptions& options)
+{
+ Interest baseInterest(prefix);
+ baseInterest.setInterestLifetime(options.getTimeout());
+
+ SegmentFetcher::fetch(m_face, baseInterest, m_validator, processResponse,
+ bind(&Controller::processDatasetFetchError, this, onFailure, _1, _2));
+}
+
+void
+Controller::processDatasetFetchError(const DatasetFailCallback& onFailure,
+ uint32_t code, std::string msg)
+{
+ switch (static_cast<SegmentFetcher::ErrorCode>(code)) {
+ // It's intentional to cast as SegmentFetcher::ErrorCode, and to not have a 'default' clause.
+ // This forces the switch statement to handle every defined SegmentFetcher::ErrorCode,
+ // and breaks compilation if it does not.
+ case SegmentFetcher::ErrorCode::INTEREST_TIMEOUT:
+ onFailure(ERROR_TIMEOUT, msg);
+ break;
+ case SegmentFetcher::ErrorCode::DATA_HAS_NO_SEGMENT:
+ onFailure(ERROR_SERVER, msg);
+ break;
+ case SegmentFetcher::ErrorCode::SEGMENT_VALIDATION_FAIL:
+ /// \todo When SegmentFetcher exposes validator error code, Controller::ERROR_VALIDATION
+ /// should be replaced with a range that corresponds to validator error codes.
+ onFailure(ERROR_VALIDATION, msg);
+ break;
+ case SegmentFetcher::ErrorCode::NACK_ERROR:
+ onFailure(ERROR_NACK, msg);
+ break;
+ }
+}
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/mgmt/nfd/controller.hpp b/src/mgmt/nfd/controller.hpp
new file mode 100644
index 0000000..3d3808c
--- /dev/null
+++ b/src/mgmt/nfd/controller.hpp
@@ -0,0 +1,221 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_CONTROLLER_HPP
+#define NDN_MGMT_NFD_CONTROLLER_HPP
+
+#include "control-command.hpp"
+#include "control-response.hpp"
+#include "status-dataset.hpp"
+#include "command-options.hpp"
+#include "../../security/validator-null.hpp"
+
+namespace ndn {
+
+namespace security {
+class KeyChain;
+class Validator;
+} // namespace security
+class Face;
+
+namespace nfd {
+
+/**
+ * \defgroup management Management
+ * \brief Classes and data structures to manage NDN forwarder
+ */
+
+/**
+ * \ingroup management
+ * \brief NFD Management protocol client
+ * \sa https://redmine.named-data.net/projects/nfd/wiki/Management
+ */
+class Controller : noncopyable
+{
+public:
+ /** \brief a callback on command success
+ */
+ typedef function<void(const ControlParameters&)> CommandSucceedCallback;
+
+ /** \brief a callback on command failure
+ */
+ typedef function<void(const ControlResponse&)> CommandFailCallback;
+
+ /** \brief a callback on dataset retrieval failure
+ */
+ typedef function<void(uint32_t code, const std::string& reason)> DatasetFailCallback;
+
+ /** \brief construct a Controller that uses face for transport,
+ * and uses the passed KeyChain to sign commands
+ */
+ Controller(Face& face, security::KeyChain& keyChain, security::Validator& validator = s_validatorNull);
+
+ /** \brief start command execution
+ */
+ template<typename Command>
+ void
+ start(const ControlParameters& parameters,
+ const CommandSucceedCallback& onSuccess,
+ const CommandFailCallback& onFailure,
+ const CommandOptions& options = CommandOptions())
+ {
+ shared_ptr<ControlCommand> command = make_shared<Command>();
+ this->startCommand(command, parameters, onSuccess, onFailure, options);
+ }
+
+ /** \brief start dataset fetching
+ */
+ template<typename Dataset>
+ typename std::enable_if<std::is_default_constructible<Dataset>::value>::type
+ fetch(const std::function<void(typename Dataset::ResultType)>& onSuccess,
+ const DatasetFailCallback& onFailure,
+ const CommandOptions& options = CommandOptions())
+ {
+ this->fetchDataset(make_shared<Dataset>(), onSuccess, onFailure, options);
+ }
+
+ /** \brief start dataset fetching
+ */
+ template<typename Dataset, typename ParamType = typename Dataset::ParamType>
+ void
+ fetch(const ParamType& param,
+ const std::function<void(typename Dataset::ResultType)>& onSuccess,
+ const DatasetFailCallback& onFailure,
+ const CommandOptions& options = CommandOptions())
+ {
+ this->fetchDataset(make_shared<Dataset>(param), onSuccess, onFailure, options);
+ }
+
+private:
+ void
+ startCommand(const shared_ptr<ControlCommand>& command,
+ const ControlParameters& parameters,
+ const CommandSucceedCallback& onSuccess,
+ const CommandFailCallback& onFailure,
+ const CommandOptions& options);
+
+ void
+ processCommandResponse(const Data& data,
+ const shared_ptr<ControlCommand>& command,
+ const CommandSucceedCallback& onSuccess,
+ const CommandFailCallback& onFailure);
+
+ void
+ processValidatedCommandResponse(const Data& data,
+ const shared_ptr<ControlCommand>& command,
+ const CommandSucceedCallback& onSuccess,
+ const CommandFailCallback& onFailure);
+
+ template<typename Dataset>
+ void
+ fetchDataset(shared_ptr<Dataset> dataset,
+ const std::function<void(typename Dataset::ResultType)>& onSuccess,
+ const DatasetFailCallback& onFailure,
+ const CommandOptions& options);
+
+ void
+ fetchDataset(const Name& prefix,
+ const std::function<void(const ConstBufferPtr&)>& processResponse,
+ const DatasetFailCallback& onFailure,
+ const CommandOptions& options);
+
+ template<typename Dataset>
+ void
+ processDatasetResponse(shared_ptr<Dataset> dataset,
+ const std::function<void(typename Dataset::ResultType)>& onSuccess,
+ const DatasetFailCallback& onFailure,
+ ConstBufferPtr payload);
+
+ void
+ processDatasetFetchError(const DatasetFailCallback& onFailure, uint32_t code, std::string msg);
+
+public:
+ /** \brief error code for timeout
+ */
+ static const uint32_t ERROR_TIMEOUT;
+
+ /** \brief error code for network Nack
+ */
+ static const uint32_t ERROR_NACK;
+
+ /** \brief error code for response validation failure
+ */
+ static const uint32_t ERROR_VALIDATION;
+
+ /** \brief error code for server error
+ */
+ static const uint32_t ERROR_SERVER;
+
+ /** \brief inclusive lower bound of error codes
+ */
+ static const uint32_t ERROR_LBOUND;
+
+protected:
+ Face& m_face;
+ security::KeyChain& m_keyChain;
+ security::Validator& m_validator;
+
+private:
+ static ValidatorNull s_validatorNull;
+};
+
+template<typename Dataset>
+inline void
+Controller::fetchDataset(shared_ptr<Dataset> dataset,
+ const std::function<void(typename Dataset::ResultType)>& onSuccess1,
+ const DatasetFailCallback& onFailure1,
+ const CommandOptions& options)
+{
+ const std::function<void(typename Dataset::ResultType)>& onSuccess = onSuccess1 ?
+ onSuccess1 : [] (const typename Dataset::ResultType&) {};
+ const DatasetFailCallback& onFailure = onFailure1 ?
+ onFailure1 : [] (uint32_t, const std::string&) {};
+
+ Name prefix = dataset->getDatasetPrefix(options.getPrefix());
+ this->fetchDataset(prefix,
+ bind(&Controller::processDatasetResponse<Dataset>, this, dataset, onSuccess, onFailure, _1),
+ onFailure,
+ options);
+}
+
+template<typename Dataset>
+inline void
+Controller::processDatasetResponse(shared_ptr<Dataset> dataset,
+ const std::function<void(typename Dataset::ResultType)>& onSuccess,
+ const DatasetFailCallback& onFailure,
+ ConstBufferPtr payload)
+{
+ typename Dataset::ResultType result;
+ try {
+ result = dataset->parseResult(payload);
+ }
+ catch (const tlv::Error& e) {
+ onFailure(ERROR_SERVER, e.what());
+ return;
+ }
+
+ onSuccess(result);
+}
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_CONTROLLER_HPP
diff --git a/src/mgmt/nfd/face-event-notification.cpp b/src/mgmt/nfd/face-event-notification.cpp
new file mode 100644
index 0000000..3422ee8
--- /dev/null
+++ b/src/mgmt/nfd/face-event-notification.cpp
@@ -0,0 +1,195 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "face-event-notification.hpp"
+#include "encoding/tlv-nfd.hpp"
+#include "encoding/block-helpers.hpp"
+#include "util/concepts.hpp"
+
+namespace ndn {
+namespace nfd {
+
+//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<FaceEventNotification>));
+BOOST_CONCEPT_ASSERT((WireEncodable<FaceEventNotification>));
+BOOST_CONCEPT_ASSERT((WireDecodable<FaceEventNotification>));
+static_assert(std::is_base_of<tlv::Error, FaceEventNotification::Error>::value,
+ "FaceEventNotification::Error must inherit from tlv::Error");
+
+FaceEventNotification::FaceEventNotification()
+ : m_kind(static_cast<FaceEventKind>(0))
+{
+}
+
+FaceEventNotification::FaceEventNotification(const Block& block)
+{
+ this->wireDecode(block);
+}
+
+template<encoding::Tag TAG>
+size_t
+FaceEventNotification::wireEncode(EncodingImpl<TAG>& encoder) const
+{
+ size_t totalLength = 0;
+
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::LinkType, m_linkType);
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::FacePersistency, m_facePersistency);
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::FaceScope, m_faceScope);
+ totalLength += encoder.prependByteArrayBlock(tlv::nfd::LocalUri,
+ reinterpret_cast<const uint8_t*>(m_localUri.c_str()), m_localUri.size());
+ totalLength += encoder.prependByteArrayBlock(tlv::nfd::Uri,
+ reinterpret_cast<const uint8_t*>(m_remoteUri.c_str()), m_remoteUri.size());
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::FaceId, m_faceId);
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::FaceEventKind, m_kind);
+
+ totalLength += encoder.prependVarNumber(totalLength);
+ totalLength += encoder.prependVarNumber(tlv::nfd::FaceEventNotification);
+ return totalLength;
+}
+
+const Block&
+FaceEventNotification::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+FaceEventNotification::wireDecode(const Block& block)
+{
+ if (block.type() != tlv::nfd::FaceEventNotification) {
+ BOOST_THROW_EXCEPTION(Error("expecting FaceEventNotification block"));
+ }
+ m_wire = block;
+ m_wire.parse();
+ Block::element_const_iterator val = m_wire.elements_begin();
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceEventKind) {
+ m_kind = static_cast<FaceEventKind>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required FaceEventKind field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceId) {
+ m_faceId = readNonNegativeInteger(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required FaceId field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::Uri) {
+ m_remoteUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required Uri field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::LocalUri) {
+ m_localUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required LocalUri field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceScope) {
+ m_faceScope = static_cast<FaceScope>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required FaceScope field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::FacePersistency) {
+ m_facePersistency = static_cast<FacePersistency>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required FacePersistency field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::LinkType) {
+ m_linkType = static_cast<LinkType>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required LinkType field"));
+ }
+}
+
+FaceEventNotification&
+FaceEventNotification::setKind(FaceEventKind kind)
+{
+ m_wire.reset();
+ m_kind = kind;
+ return *this;
+}
+
+void
+FaceEventNotification::wireReset() const
+{
+ m_wire.reset();
+}
+
+std::ostream&
+operator<<(std::ostream& os, const FaceEventNotification& notification)
+{
+ os << "FaceEventNotification(";
+
+ switch (notification.getKind())
+ {
+ case FACE_EVENT_CREATED:
+ os << "Kind: created, ";
+ break;
+ case FACE_EVENT_DESTROYED:
+ os << "Kind: destroyed, ";
+ break;
+ }
+
+ os << "FaceID: " << notification.getFaceId() << ", "
+ << "RemoteUri: " << notification.getRemoteUri() << ", "
+ << "LocalUri: " << notification.getLocalUri() << ", "
+ << "FaceScope: " << notification.getFaceScope() << ", "
+ << "FacePersistency: " << notification.getFacePersistency() << ", "
+ << "LinkType: " << notification.getLinkType()
+ << ")";
+ return os;
+}
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/mgmt/nfd/face-event-notification.hpp b/src/mgmt/nfd/face-event-notification.hpp
new file mode 100644
index 0000000..a4d1ea7
--- /dev/null
+++ b/src/mgmt/nfd/face-event-notification.hpp
@@ -0,0 +1,94 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_FACE_EVENT_NOTIFICATION_HPP
+#define NDN_MGMT_NFD_FACE_EVENT_NOTIFICATION_HPP
+
+#include "face-traits.hpp"
+#include "../../encoding/block.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * \ingroup management
+ */
+enum FaceEventKind {
+ FACE_EVENT_CREATED = 1,
+ FACE_EVENT_DESTROYED = 2
+};
+
+/**
+ * \ingroup management
+ * \brief represents a Face status change notification
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Face-Status-Change-Notification
+ */
+class FaceEventNotification : public FaceTraits<FaceEventNotification>
+{
+public:
+ FaceEventNotification();
+
+ explicit
+ FaceEventNotification(const Block& block);
+
+ /** \brief prepend FaceEventNotification to the encoder
+ */
+ template<encoding::Tag TAG>
+ size_t
+ wireEncode(EncodingImpl<TAG>& encoder) const;
+
+ /** \brief encode FaceEventNotification
+ */
+ const Block&
+ wireEncode() const;
+
+ /** \brief decode FaceEventNotification
+ */
+ void
+ wireDecode(const Block& wire);
+
+public: // getters & setters
+ FaceEventKind
+ getKind() const
+ {
+ return m_kind;
+ }
+
+ FaceEventNotification&
+ setKind(FaceEventKind kind);
+
+protected:
+ void
+ wireReset() const;
+
+private:
+ FaceEventKind m_kind;
+
+ mutable Block m_wire;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const FaceEventNotification& notification);
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_FACE_EVENT_NOTIFICATION_HPP
diff --git a/src/mgmt/nfd/face-monitor.hpp b/src/mgmt/nfd/face-monitor.hpp
new file mode 100644
index 0000000..5429ea1
--- /dev/null
+++ b/src/mgmt/nfd/face-monitor.hpp
@@ -0,0 +1,72 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+/**
+ * Original copyright notice from NFD:
+ *
+ * Copyright (c) 2014, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NDN_MGMT_NFD_FACE_MONITOR_HPP
+#define NDN_MGMT_NFD_FACE_MONITOR_HPP
+
+#include "../../util/notification-subscriber.hpp"
+#include "face-event-notification.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/** \brief A subscriber for Face status change notification stream
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Face-Status-Change-Notification
+ */
+class FaceMonitor : public util::NotificationSubscriber<FaceEventNotification>
+{
+public:
+ FaceMonitor(Face& face)
+ : NotificationSubscriber<nfd::FaceEventNotification>(face, "ndn:/localhost/nfd/faces/events")
+ {
+ }
+};
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_FACE_MONITOR_HPP
diff --git a/src/mgmt/nfd/face-query-filter.cpp b/src/mgmt/nfd/face-query-filter.cpp
new file mode 100644
index 0000000..ffaae90
--- /dev/null
+++ b/src/mgmt/nfd/face-query-filter.cpp
@@ -0,0 +1,352 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "face-query-filter.hpp"
+#include "encoding/tlv-nfd.hpp"
+#include "encoding/block-helpers.hpp"
+#include "util/concepts.hpp"
+
+namespace ndn {
+namespace nfd {
+
+//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<FaceQueryFilter>));
+BOOST_CONCEPT_ASSERT((WireEncodable<FaceQueryFilter>));
+BOOST_CONCEPT_ASSERT((WireDecodable<FaceQueryFilter>));
+static_assert(std::is_base_of<tlv::Error, FaceQueryFilter::Error>::value,
+ "FaceQueryFilter::Error must inherit from tlv::Error");
+
+FaceQueryFilter::FaceQueryFilter()
+ : m_hasFaceId(false)
+ , m_hasUriScheme(false)
+ , m_hasRemoteUri(false)
+ , m_hasLocalUri(false)
+ , m_hasFaceScope(false)
+ , m_hasFacePersistency(false)
+ , m_hasLinkType(false)
+{
+}
+
+FaceQueryFilter::FaceQueryFilter(const Block& block)
+{
+ this->wireDecode(block);
+}
+
+template<encoding::Tag TAG>
+size_t
+FaceQueryFilter::wireEncode(EncodingImpl<TAG>& encoder) const
+{
+ size_t totalLength = 0;
+
+ if (m_hasLinkType) {
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::LinkType, m_linkType);
+ }
+
+ if (m_hasFacePersistency) {
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::FacePersistency, m_facePersistency);
+ }
+
+ if (m_hasFaceScope) {
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::FaceScope, m_faceScope);
+ }
+
+ if (m_hasLocalUri) {
+ totalLength += encoder.prependByteArrayBlock(tlv::nfd::LocalUri,
+ reinterpret_cast<const uint8_t*>(m_localUri.c_str()), m_localUri.size());
+ }
+
+ if (m_hasRemoteUri) {
+ totalLength += encoder.prependByteArrayBlock(tlv::nfd::Uri,
+ reinterpret_cast<const uint8_t*>(m_remoteUri.c_str()), m_remoteUri.size());
+ }
+
+ if (m_hasUriScheme) {
+ totalLength += encoder.prependByteArrayBlock(tlv::nfd::UriScheme,
+ reinterpret_cast<const uint8_t*>(m_uriScheme.c_str()), m_uriScheme.size());
+ }
+
+ if (m_hasFaceId) {
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::FaceId, m_faceId);
+ }
+
+ totalLength += encoder.prependVarNumber(totalLength);
+ totalLength += encoder.prependVarNumber(tlv::nfd::FaceQueryFilter);
+ return totalLength;
+}
+
+template size_t
+FaceQueryFilter::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>&) const;
+
+template size_t
+FaceQueryFilter::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>&) const;
+
+const Block&
+FaceQueryFilter::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+FaceQueryFilter::wireDecode(const Block& block)
+{
+ //all fields are optional
+ if (block.type() != tlv::nfd::FaceQueryFilter) {
+ BOOST_THROW_EXCEPTION(Error("expecting FaceQueryFilter block"));
+ }
+
+ m_wire = block;
+ m_wire.parse();
+ Block::element_const_iterator val = m_wire.elements_begin();
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceId) {
+ m_faceId = readNonNegativeInteger(*val);
+ m_hasFaceId = true;
+ ++val;
+ }
+ else {
+ m_hasFaceId = false;
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::UriScheme) {
+ m_uriScheme.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ m_hasUriScheme = true;
+ ++val;
+ }
+ else {
+ m_hasUriScheme = false;
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::Uri) {
+ m_remoteUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ m_hasRemoteUri = true;
+ ++val;
+ }
+ else {
+ m_hasRemoteUri = false;
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::LocalUri) {
+ m_localUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ m_hasLocalUri = true;
+ ++val;
+ }
+ else {
+ m_hasLocalUri = false;
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceScope) {
+ m_faceScope = static_cast<FaceScope>(readNonNegativeInteger(*val));
+ m_hasFaceScope = true;
+ ++val;
+ }
+ else {
+ m_hasFaceScope = false;
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::FacePersistency) {
+ m_facePersistency = static_cast<FacePersistency>(readNonNegativeInteger(*val));
+ m_hasFacePersistency = true;
+ ++val;
+ }
+ else {
+ m_hasFacePersistency = false;
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::LinkType) {
+ m_linkType = static_cast<LinkType>(readNonNegativeInteger(*val));
+ m_hasLinkType = true;
+ ++val;
+ }
+ else {
+ m_hasLinkType = false;
+ }
+
+}
+
+FaceQueryFilter&
+FaceQueryFilter::setFaceId(uint64_t faceId)
+{
+ m_wire.reset();
+ m_faceId = faceId;
+ m_hasFaceId = true;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::unsetFaceId()
+{
+ m_wire.reset();
+ m_hasFaceId = false;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::setUriScheme(const std::string& uriScheme)
+{
+ m_wire.reset();
+ m_uriScheme = uriScheme;
+ m_hasUriScheme = true;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::unsetUriScheme()
+{
+ m_wire.reset();
+ m_hasUriScheme = false;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::setRemoteUri(const std::string& remoteUri)
+{
+ m_wire.reset();
+ m_remoteUri = remoteUri;
+ m_hasRemoteUri = true;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::unsetRemoteUri()
+{
+ m_wire.reset();
+ m_hasRemoteUri = false;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::setLocalUri(const std::string& localUri)
+{
+ m_wire.reset();
+ m_localUri = localUri;
+ m_hasLocalUri = true;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::unsetLocalUri()
+{
+ m_wire.reset();
+ m_hasLocalUri = false;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::setFaceScope(FaceScope faceScope)
+{
+ m_wire.reset();
+ m_faceScope = faceScope;
+ m_hasFaceScope = true;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::unsetFaceScope()
+{
+ m_wire.reset();
+ m_hasFaceScope = false;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::setFacePersistency(FacePersistency facePersistency)
+{
+ m_wire.reset();
+ m_facePersistency = facePersistency;
+ m_hasFacePersistency = true;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::unsetFacePersistency()
+{
+ m_wire.reset();
+ m_hasFacePersistency = false;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::setLinkType(LinkType linkType)
+{
+ m_wire.reset();
+ m_linkType = linkType;
+ m_hasLinkType = true;
+ return *this;
+}
+
+FaceQueryFilter&
+FaceQueryFilter::unsetLinkType()
+{
+ m_wire.reset();
+ m_hasLinkType = false;
+ return *this;
+}
+
+std::ostream&
+operator<<(std::ostream& os, const FaceQueryFilter& filter)
+{
+ os << "FaceQueryFilter(";
+ if (filter.hasFaceId()) {
+ os << "FaceID: " << filter.getFaceId() << ",\n";
+ }
+
+ if (filter.hasUriScheme()) {
+ os << "UriScheme: " << filter.getUriScheme() << ",\n";
+ }
+
+ if (filter.hasRemoteUri()) {
+ os << "RemoteUri: " << filter.getRemoteUri() << ",\n";
+ }
+
+ if (filter.hasLocalUri()) {
+ os << "LocalUri: " << filter.getLocalUri() << ",\n";
+ }
+
+ if (filter.hasFaceScope()) {
+ os << "FaceScope: " << filter.getFaceScope() << ",\n";
+ }
+
+ if (filter.hasFacePersistency()) {
+ os << "FacePersistency: " << filter.getFacePersistency() << ",\n";
+ }
+
+ if (filter.hasLinkType()) {
+ os << "LinkType: " << filter.getLinkType() << ",\n";
+ }
+ os << ")";
+ return os;
+}
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/mgmt/nfd/face-query-filter.hpp b/src/mgmt/nfd/face-query-filter.hpp
new file mode 100644
index 0000000..e0bb393
--- /dev/null
+++ b/src/mgmt/nfd/face-query-filter.hpp
@@ -0,0 +1,231 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_FACE_QUERY_FILTER_HPP
+#define NDN_MGMT_NFD_FACE_QUERY_FILTER_HPP
+
+#include "../../encoding/block.hpp"
+#include "../../encoding/nfd-constants.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * \ingroup management
+ * \brief represents Face Query Filter
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Query-Operation
+ */
+class FaceQueryFilter
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+ FaceQueryFilter();
+
+ explicit
+ FaceQueryFilter(const Block& block);
+
+ /** \brief prepend FaceQueryFilter to the encoder
+ */
+ template<encoding::Tag TAG>
+ size_t
+ wireEncode(EncodingImpl<TAG>& encoder) const;
+
+ /** \brief encode FaceQueryFilter
+ */
+ const Block&
+ wireEncode() const;
+
+ /** \brief decode FaceQueryFilter
+ */
+ void
+ wireDecode(const Block& wire);
+
+public: // getters & setters
+
+ bool
+ hasFaceId() const
+ {
+ return m_hasFaceId;
+ }
+
+ uint64_t
+ getFaceId() const
+ {
+ BOOST_ASSERT(this->hasFaceId());
+ return m_faceId;
+ }
+
+ FaceQueryFilter&
+ setFaceId(uint64_t faceId);
+
+ FaceQueryFilter&
+ unsetFaceId();
+
+ bool
+ hasUriScheme() const
+ {
+ return m_hasUriScheme;
+ }
+
+ const std::string&
+ getUriScheme() const
+ {
+ BOOST_ASSERT(this->hasUriScheme());
+ return m_uriScheme;
+ }
+
+ FaceQueryFilter&
+ setUriScheme(const std::string& uriScheme);
+
+ FaceQueryFilter&
+ unsetUriScheme();
+
+ bool
+ hasRemoteUri() const
+ {
+ return m_hasRemoteUri;
+ }
+
+ const std::string&
+ getRemoteUri() const
+ {
+ BOOST_ASSERT(this->hasRemoteUri());
+ return m_remoteUri;
+ }
+
+ FaceQueryFilter&
+ setRemoteUri(const std::string& remoteUri);
+
+ FaceQueryFilter&
+ unsetRemoteUri();
+
+ bool
+ hasLocalUri() const
+ {
+ return m_hasLocalUri;
+ }
+
+ const std::string&
+ getLocalUri() const
+ {
+ BOOST_ASSERT(this->hasLocalUri());
+ return m_localUri;
+ }
+
+ FaceQueryFilter&
+ setLocalUri(const std::string& localUri);
+
+ FaceQueryFilter&
+ unsetLocalUri();
+
+ bool
+ hasFaceScope() const
+ {
+ return m_hasFaceScope;
+ }
+
+ FaceScope
+ getFaceScope() const
+ {
+ BOOST_ASSERT(this->hasFaceScope());
+ return m_faceScope;
+ }
+
+ FaceQueryFilter&
+ setFaceScope(FaceScope faceScope);
+
+ FaceQueryFilter&
+ unsetFaceScope();
+
+ bool
+ hasFacePersistency() const
+ {
+ return m_hasFacePersistency;
+ }
+
+ FacePersistency
+ getFacePersistency() const
+ {
+ BOOST_ASSERT(this->hasFacePersistency());
+ return m_facePersistency;
+ }
+
+ FaceQueryFilter&
+ setFacePersistency(FacePersistency facePersistency);
+
+ FaceQueryFilter&
+ unsetFacePersistency();
+
+ bool
+ hasLinkType() const
+ {
+ return m_hasLinkType;
+ }
+
+ LinkType
+ getLinkType() const
+ {
+ BOOST_ASSERT(this->hasLinkType());
+ return m_linkType;
+ }
+
+ FaceQueryFilter&
+ setLinkType(LinkType linkType);
+
+ FaceQueryFilter&
+ unsetLinkType();
+
+private:
+ uint64_t m_faceId;
+ std::string m_uriScheme;
+ std::string m_remoteUri;
+ std::string m_localUri;
+ FaceScope m_faceScope;
+ FacePersistency m_facePersistency;
+ LinkType m_linkType;
+
+ bool m_hasFaceId;
+ bool m_hasUriScheme;
+ bool m_hasRemoteUri;
+ bool m_hasLocalUri;
+ bool m_hasFaceScope;
+ bool m_hasFacePersistency;
+ bool m_hasLinkType;
+
+ mutable Block m_wire;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const FaceQueryFilter& filter);
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_FACE_QUERY_FILTER_HPP
diff --git a/src/mgmt/nfd/face-status.cpp b/src/mgmt/nfd/face-status.cpp
new file mode 100644
index 0000000..bdc7404
--- /dev/null
+++ b/src/mgmt/nfd/face-status.cpp
@@ -0,0 +1,363 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "face-status.hpp"
+#include "encoding/tlv-nfd.hpp"
+#include "encoding/block-helpers.hpp"
+#include "util/concepts.hpp"
+
+namespace ndn {
+namespace nfd {
+
+//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<FaceStatus>));
+BOOST_CONCEPT_ASSERT((WireEncodable<FaceStatus>));
+BOOST_CONCEPT_ASSERT((WireDecodable<FaceStatus>));
+static_assert(std::is_base_of<tlv::Error, FaceStatus::Error>::value,
+ "FaceStatus::Error must inherit from tlv::Error");
+
+FaceStatus::FaceStatus()
+ : m_hasExpirationPeriod(false)
+ , m_nInInterests(0)
+ , m_nInDatas(0)
+ , m_nInNacks(0)
+ , m_nOutInterests(0)
+ , m_nOutDatas(0)
+ , m_nOutNacks(0)
+ , m_nInBytes(0)
+ , m_nOutBytes(0)
+{
+}
+
+FaceStatus::FaceStatus(const Block& block)
+{
+ this->wireDecode(block);
+}
+
+template<encoding::Tag TAG>
+size_t
+FaceStatus::wireEncode(EncodingImpl<TAG>& encoder) const
+{
+ size_t totalLength = 0;
+
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::NOutBytes, m_nOutBytes);
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::NInBytes, m_nInBytes);
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::NOutNacks, m_nOutNacks);
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::NOutDatas, m_nOutDatas);
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::NOutInterests, m_nOutInterests);
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::NInNacks, m_nInNacks);
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::NInDatas, m_nInDatas);
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::NInInterests, m_nInInterests);
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::LinkType, m_linkType);
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::FacePersistency, m_facePersistency);
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::FaceScope, m_faceScope);
+ if (m_hasExpirationPeriod) {
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::ExpirationPeriod, m_expirationPeriod.count());
+ }
+ totalLength += encoder.prependByteArrayBlock(tlv::nfd::LocalUri,
+ reinterpret_cast<const uint8_t*>(m_localUri.c_str()), m_localUri.size());
+ totalLength += encoder.prependByteArrayBlock(tlv::nfd::Uri,
+ reinterpret_cast<const uint8_t*>(m_remoteUri.c_str()), m_remoteUri.size());
+ totalLength += prependNonNegativeIntegerBlock(encoder,
+ tlv::nfd::FaceId, m_faceId);
+
+ totalLength += encoder.prependVarNumber(totalLength);
+ totalLength += encoder.prependVarNumber(tlv::nfd::FaceStatus);
+ return totalLength;
+}
+
+template size_t
+FaceStatus::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block) const;
+
+template size_t
+FaceStatus::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block) const;
+
+const Block&
+FaceStatus::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+FaceStatus::wireDecode(const Block& block)
+{
+ if (block.type() != tlv::nfd::FaceStatus) {
+ BOOST_THROW_EXCEPTION(Error("expecting FaceStatus block"));
+ }
+ m_wire = block;
+ m_wire.parse();
+ Block::element_const_iterator val = m_wire.elements_begin();
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceId) {
+ m_faceId = readNonNegativeInteger(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required FaceId field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::Uri) {
+ m_remoteUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required Uri field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::LocalUri) {
+ m_localUri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required LocalUri field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::ExpirationPeriod) {
+ m_expirationPeriod = time::milliseconds(readNonNegativeInteger(*val));
+ m_hasExpirationPeriod = true;
+ ++val;
+ }
+ else {
+ m_hasExpirationPeriod = false;
+ // ExpirationPeriod is optional
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceScope) {
+ m_faceScope = static_cast<FaceScope>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required FaceScope field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::FacePersistency) {
+ m_facePersistency = static_cast<FacePersistency>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required FacePersistency field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::LinkType) {
+ m_linkType = static_cast<LinkType>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required LinkType field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NInInterests) {
+ m_nInInterests = readNonNegativeInteger(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NInInterests field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NInDatas) {
+ m_nInDatas = readNonNegativeInteger(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NInDatas field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NInNacks) {
+ m_nInNacks = readNonNegativeInteger(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NInNacks field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NOutInterests) {
+ m_nOutInterests = readNonNegativeInteger(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NOutInterests field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NOutDatas) {
+ m_nOutDatas = readNonNegativeInteger(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NOutDatas field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NOutNacks) {
+ m_nOutNacks = readNonNegativeInteger(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NOutNacks field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NInBytes) {
+ m_nInBytes = readNonNegativeInteger(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NInBytes field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NOutBytes) {
+ m_nOutBytes = readNonNegativeInteger(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NOutBytes field"));
+ }
+}
+
+FaceStatus&
+FaceStatus::setExpirationPeriod(const time::milliseconds& expirationPeriod)
+{
+ m_wire.reset();
+ m_expirationPeriod = expirationPeriod;
+ m_hasExpirationPeriod = true;
+ return *this;
+}
+
+FaceStatus&
+FaceStatus::setNInInterests(uint64_t nInInterests)
+{
+ m_wire.reset();
+ m_nInInterests = nInInterests;
+ return *this;
+}
+
+FaceStatus&
+FaceStatus::setNInDatas(uint64_t nInDatas)
+{
+ m_wire.reset();
+ m_nInDatas = nInDatas;
+ return *this;
+}
+
+FaceStatus&
+FaceStatus::setNInNacks(uint64_t nInNacks)
+{
+ m_wire.reset();
+ m_nInNacks = nInNacks;
+ return *this;
+}
+
+FaceStatus&
+FaceStatus::setNOutInterests(uint64_t nOutInterests)
+{
+ m_wire.reset();
+ m_nOutInterests = nOutInterests;
+ return *this;
+}
+
+FaceStatus&
+FaceStatus::setNOutDatas(uint64_t nOutDatas)
+{
+ m_wire.reset();
+ m_nOutDatas = nOutDatas;
+ return *this;
+}
+
+FaceStatus&
+FaceStatus::setNOutNacks(uint64_t nOutNacks)
+{
+ m_wire.reset();
+ m_nOutNacks = nOutNacks;
+ return *this;
+}
+
+FaceStatus&
+FaceStatus::setNInBytes(uint64_t nInBytes)
+{
+ m_wire.reset();
+ m_nInBytes = nInBytes;
+ return *this;
+}
+
+FaceStatus&
+FaceStatus::setNOutBytes(uint64_t nOutBytes)
+{
+ m_wire.reset();
+ m_nOutBytes = nOutBytes;
+ return *this;
+}
+
+void
+FaceStatus::wireReset() const
+{
+ m_wire.reset();
+}
+
+std::ostream&
+operator<<(std::ostream& os, const FaceStatus& status)
+{
+ os << "FaceStatus("
+ << "FaceID: " << status.getFaceId() << ",\n"
+ << "RemoteUri: " << status.getRemoteUri() << ",\n"
+ << "LocalUri: " << status.getLocalUri() << ",\n";
+
+ if (status.hasExpirationPeriod()) {
+ os << "ExpirationPeriod: " << status.getExpirationPeriod() << ",\n";
+ }
+ else {
+ os << "ExpirationPeriod: infinite,\n";
+ }
+
+ os << "FaceScope: " << status.getFaceScope() << ",\n"
+ << "FacePersistency: " << status.getFacePersistency() << ",\n"
+ << "LinkType: " << status.getLinkType() << ",\n"
+ << "Counters: { Interests: {in: " << status.getNInInterests() << ", "
+ << "out: " << status.getNOutInterests() << "},\n"
+ << " Data: {in: " << status.getNInDatas() << ", "
+ << "out: " << status.getNOutDatas() << "},\n"
+ << " Nack: {in: " << status.getNInNacks() << ", "
+ << "out: " << status.getNOutNacks() << "},\n"
+ << " bytes: {in: " << status.getNInBytes() << ", "
+ << "out: " << status.getNOutBytes() << "} }\n"
+ << ")";
+ return os;
+}
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/mgmt/nfd/face-status.hpp b/src/mgmt/nfd/face-status.hpp
new file mode 100644
index 0000000..4f20e53
--- /dev/null
+++ b/src/mgmt/nfd/face-status.hpp
@@ -0,0 +1,175 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_FACE_STATUS_HPP
+#define NDN_MGMT_NFD_FACE_STATUS_HPP
+
+#include "face-traits.hpp" // include this first, to ensure it compiles on its own.
+#include "../../encoding/block.hpp"
+#include "../../util/time.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * \ingroup management
+ * \brief represents Face status
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Face-Dataset
+ */
+class FaceStatus : public FaceTraits<FaceStatus>
+{
+public:
+ FaceStatus();
+
+ explicit
+ FaceStatus(const Block& block);
+
+ /** \brief prepend FaceStatus to the encoder
+ */
+ template<encoding::Tag TAG>
+ size_t
+ wireEncode(EncodingImpl<TAG>& encoder) const;
+
+ /** \brief encode FaceStatus
+ */
+ const Block&
+ wireEncode() const;
+
+ /** \brief decode FaceStatus
+ */
+ void
+ wireDecode(const Block& wire);
+
+public: // getters & setters
+ bool
+ hasExpirationPeriod() const
+ {
+ return m_hasExpirationPeriod;
+ }
+
+ const time::milliseconds&
+ getExpirationPeriod() const
+ {
+ BOOST_ASSERT(m_hasExpirationPeriod);
+ return m_expirationPeriod;
+ }
+
+ FaceStatus&
+ setExpirationPeriod(const time::milliseconds& expirationPeriod);
+
+ uint64_t
+ getNInInterests() const
+ {
+ return m_nInInterests;
+ }
+
+ FaceStatus&
+ setNInInterests(uint64_t nInInterests);
+
+ uint64_t
+ getNInDatas() const
+ {
+ return m_nInDatas;
+ }
+
+ FaceStatus&
+ setNInDatas(uint64_t nInDatas);
+
+ uint64_t
+ getNInNacks() const
+ {
+ return m_nInNacks;
+ }
+
+ FaceStatus&
+ setNInNacks(uint64_t nInNacks);
+
+ uint64_t
+ getNOutInterests() const
+ {
+ return m_nOutInterests;
+ }
+
+ FaceStatus&
+ setNOutInterests(uint64_t nOutInterests);
+
+ uint64_t
+ getNOutDatas() const
+ {
+ return m_nOutDatas;
+ }
+
+ FaceStatus&
+ setNOutDatas(uint64_t nOutDatas);
+
+ uint64_t
+ getNOutNacks() const
+ {
+ return m_nOutNacks;
+ }
+
+ FaceStatus&
+ setNOutNacks(uint64_t nOutNacks);
+
+ uint64_t
+ getNInBytes() const
+ {
+ return m_nInBytes;
+ }
+
+ FaceStatus&
+ setNInBytes(uint64_t nInBytes);
+
+ uint64_t
+ getNOutBytes() const
+ {
+ return m_nOutBytes;
+ }
+
+ FaceStatus&
+ setNOutBytes(uint64_t nOutBytes);
+
+protected:
+ void
+ wireReset() const;
+
+private:
+ time::milliseconds m_expirationPeriod;
+ bool m_hasExpirationPeriod;
+ uint64_t m_nInInterests;
+ uint64_t m_nInDatas;
+ uint64_t m_nInNacks;
+ uint64_t m_nOutInterests;
+ uint64_t m_nOutDatas;
+ uint64_t m_nOutNacks;
+ uint64_t m_nInBytes;
+ uint64_t m_nOutBytes;
+
+ mutable Block m_wire;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const FaceStatus& status);
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_FACE_STATUS_HPP
diff --git a/src/mgmt/nfd/face-traits.hpp b/src/mgmt/nfd/face-traits.hpp
new file mode 100644
index 0000000..d9422c3
--- /dev/null
+++ b/src/mgmt/nfd/face-traits.hpp
@@ -0,0 +1,157 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_FACE_TRAITS_HPP
+#define NDN_MGMT_NFD_FACE_TRAITS_HPP
+
+#include "../../encoding/tlv-nfd.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/** \ingroup management
+ * \brief providers getters and setters of face information fields
+ * \tparam C the concrete class; it must provide .wireReset() method
+ to clear wire encoding when a field changes
+ */
+template<class C>
+class FaceTraits
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+ FaceTraits()
+ : m_faceId(0)
+ , m_faceScope(FACE_SCOPE_NON_LOCAL)
+ , m_facePersistency(FACE_PERSISTENCY_PERSISTENT)
+ , m_linkType(LINK_TYPE_POINT_TO_POINT)
+ {
+ }
+
+ uint64_t
+ getFaceId() const
+ {
+ return m_faceId;
+ }
+
+ C&
+ setFaceId(uint64_t faceId)
+ {
+ wireReset();
+ m_faceId = faceId;
+ return static_cast<C&>(*this);
+ }
+
+ const std::string&
+ getRemoteUri() const
+ {
+ return m_remoteUri;
+ }
+
+ C&
+ setRemoteUri(const std::string& remoteUri)
+ {
+ wireReset();
+ m_remoteUri = remoteUri;
+ return static_cast<C&>(*this);
+ }
+
+ const std::string&
+ getLocalUri() const
+ {
+ return m_localUri;
+ }
+
+ C&
+ setLocalUri(const std::string& localUri)
+ {
+ wireReset();
+ m_localUri = localUri;
+ return static_cast<C&>(*this);
+ }
+
+ FaceScope
+ getFaceScope() const
+ {
+ return m_faceScope;
+ }
+
+ C&
+ setFaceScope(FaceScope faceScope)
+ {
+ wireReset();
+ m_faceScope = faceScope;
+ return static_cast<C&>(*this);
+ }
+
+ FacePersistency
+ getFacePersistency() const
+ {
+ return m_facePersistency;
+ }
+
+ C&
+ setFacePersistency(FacePersistency facePersistency)
+ {
+ wireReset();
+ m_facePersistency = facePersistency;
+ return static_cast<C&>(*this);
+ }
+
+ LinkType
+ getLinkType() const
+ {
+ return m_linkType;
+ }
+
+ C&
+ setLinkType(LinkType linkType)
+ {
+ wireReset();
+ m_linkType = linkType;
+ return static_cast<C&>(*this);
+ }
+
+protected:
+ virtual void
+ wireReset() const = 0;
+
+protected:
+ uint64_t m_faceId;
+ std::string m_remoteUri;
+ std::string m_localUri;
+ FaceScope m_faceScope;
+ FacePersistency m_facePersistency;
+ LinkType m_linkType;
+};
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_FACE_TRAITS_HPP
diff --git a/src/mgmt/nfd/fib-entry.cpp b/src/mgmt/nfd/fib-entry.cpp
new file mode 100644
index 0000000..dd1092f
--- /dev/null
+++ b/src/mgmt/nfd/fib-entry.cpp
@@ -0,0 +1,268 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "fib-entry.hpp"
+#include <sstream>
+#include "encoding/tlv-nfd.hpp"
+#include "encoding/block-helpers.hpp"
+#include "util/concepts.hpp"
+
+namespace ndn {
+namespace nfd {
+
+//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<NextHopRecord>));
+BOOST_CONCEPT_ASSERT((WireEncodable<NextHopRecord>));
+BOOST_CONCEPT_ASSERT((WireDecodable<NextHopRecord>));
+static_assert(std::is_base_of<tlv::Error, NextHopRecord::Error>::value,
+ "NextHopRecord::Error must inherit from tlv::Error");
+
+//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<FibEntry>));
+BOOST_CONCEPT_ASSERT((WireEncodable<FibEntry>));
+BOOST_CONCEPT_ASSERT((WireDecodable<FibEntry>));
+static_assert(std::is_base_of<tlv::Error, FibEntry::Error>::value,
+ "FibEntry::Error must inherit from tlv::Error");
+
+// NextHopRecord := NEXT-HOP-RECORD TLV-LENGTH
+// FaceId
+// Cost
+
+NextHopRecord::NextHopRecord()
+ : m_faceId(std::numeric_limits<uint64_t>::max())
+ , m_cost(0)
+{
+}
+
+NextHopRecord::NextHopRecord(const Block& block)
+{
+ this->wireDecode(block);
+}
+
+NextHopRecord&
+NextHopRecord::setFaceId(uint64_t faceId)
+{
+ m_faceId = faceId;
+ m_wire.reset();
+ return *this;
+}
+
+NextHopRecord&
+NextHopRecord::setCost(uint64_t cost)
+{
+ m_cost = cost;
+ m_wire.reset();
+ return *this;
+}
+
+template<encoding::Tag TAG>
+size_t
+NextHopRecord::wireEncode(EncodingImpl<TAG>& block) const
+{
+ size_t totalLength = 0;
+ totalLength += prependNonNegativeIntegerBlock(block,
+ ndn::tlv::nfd::Cost,
+ m_cost);
+
+ totalLength += prependNonNegativeIntegerBlock(block,
+ ndn::tlv::nfd::FaceId,
+ m_faceId);
+
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(ndn::tlv::nfd::NextHopRecord);
+ return totalLength;
+}
+
+template size_t
+NextHopRecord::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block) const;
+
+template size_t
+NextHopRecord::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block) const;
+
+const Block&
+NextHopRecord::wireEncode() const
+{
+ if (m_wire.hasWire()) {
+ return m_wire;
+ }
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+NextHopRecord::wireDecode(const Block& wire)
+{
+ m_faceId = std::numeric_limits<uint64_t>::max();
+ m_cost = 0;
+
+ m_wire = wire;
+
+ if (m_wire.type() != tlv::nfd::NextHopRecord) {
+ std::stringstream error;
+ error << "Requested decoding of NextHopRecord, but Block is of a different type: #"
+ << m_wire.type();
+ BOOST_THROW_EXCEPTION(Error(error.str()));
+ }
+ m_wire.parse();
+
+ Block::element_const_iterator val = m_wire.elements_begin();
+ if (val == m_wire.elements_end()) {
+ BOOST_THROW_EXCEPTION(Error("Unexpected end of NextHopRecord"));
+ }
+ else if (val->type() != tlv::nfd::FaceId) {
+ std::stringstream error;
+ error << "Expected FaceId, but Block is of a different type: #"
+ << val->type();
+ BOOST_THROW_EXCEPTION(Error(error.str()));
+ }
+ m_faceId = readNonNegativeInteger(*val);
+ ++val;
+
+ if (val == m_wire.elements_end()) {
+ BOOST_THROW_EXCEPTION(Error("Unexpected end of NextHopRecord"));
+ }
+ else if (val->type() != tlv::nfd::Cost) {
+ std::stringstream error;
+ error << "Expected Cost, but Block is of a different type: #"
+ << m_wire.type();
+ BOOST_THROW_EXCEPTION(Error(error.str()));
+ }
+ m_cost = readNonNegativeInteger(*val);
+}
+
+// FibEntry := FIB-ENTRY-TYPE TLV-LENGTH
+// Name
+// NextHopRecord*
+
+FibEntry::FibEntry()
+{
+}
+
+FibEntry::FibEntry(const Block& block)
+{
+ this->wireDecode(block);
+}
+
+FibEntry&
+FibEntry::setPrefix(const Name& prefix)
+{
+ m_prefix = prefix;
+ m_wire.reset();
+ return *this;
+}
+
+FibEntry&
+FibEntry::addNextHopRecord(const NextHopRecord& nextHopRecord)
+{
+ m_nextHopRecords.push_back(nextHopRecord);
+ m_wire.reset();
+ return *this;
+}
+
+template<encoding::Tag TAG>
+size_t
+FibEntry::wireEncode(EncodingImpl<TAG>& block) const
+{
+ size_t totalLength = 0;
+
+ for (auto i = m_nextHopRecords.rbegin(); i != m_nextHopRecords.rend(); ++i) {
+ totalLength += i->wireEncode(block);
+ }
+
+ totalLength += m_prefix.wireEncode(block);
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::nfd::FibEntry);
+
+ return totalLength;
+}
+
+template size_t
+FibEntry::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block) const;
+
+template size_t
+FibEntry::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block) const;
+
+const Block&
+FibEntry::wireEncode() const
+{
+ if (m_wire.hasWire()) {
+ return m_wire;
+ }
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+
+ return m_wire;
+}
+
+void
+FibEntry::wireDecode(const Block& wire)
+{
+ m_prefix.clear();
+ m_nextHopRecords.clear();
+
+ m_wire = wire;
+
+ if (m_wire.type() != tlv::nfd::FibEntry) {
+ std::stringstream error;
+ error << "Requested decoding of FibEntry, but Block is of a different type: #"
+ << m_wire.type();
+ BOOST_THROW_EXCEPTION(Error(error.str()));
+ }
+
+ m_wire.parse();
+
+ Block::element_const_iterator val = m_wire.elements_begin();
+ if (val == m_wire.elements_end()) {
+ BOOST_THROW_EXCEPTION(Error("Unexpected end of FibEntry"));
+ }
+ else if (val->type() != tlv::Name) {
+ std::stringstream error;
+ error << "Expected Name, but Block is of a different type: #"
+ << val->type();
+ BOOST_THROW_EXCEPTION(Error(error.str()));
+ }
+ m_prefix.wireDecode(*val);
+ ++val;
+
+ for (; val != m_wire.elements_end(); ++val) {
+ if (val->type() != tlv::nfd::NextHopRecord) {
+ std::stringstream error;
+ error << "Expected NextHopRecords, but Block is of a different type: #"
+ << val->type();
+ BOOST_THROW_EXCEPTION(Error(error.str()));
+ }
+ m_nextHopRecords.push_back(NextHopRecord(*val));
+ }
+}
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/mgmt/nfd/fib-entry.hpp b/src/mgmt/nfd/fib-entry.hpp
new file mode 100644
index 0000000..6a7304c
--- /dev/null
+++ b/src/mgmt/nfd/fib-entry.hpp
@@ -0,0 +1,155 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_FIB_ENTRY_HPP
+#define NDN_MGMT_NFD_FIB_ENTRY_HPP
+
+#include "../../encoding/block.hpp"
+#include "../../name.hpp"
+#include <list>
+
+namespace ndn {
+namespace nfd {
+
+/** @ingroup management
+ */
+class NextHopRecord
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+ NextHopRecord();
+
+ explicit
+ NextHopRecord(const Block& block);
+
+ uint64_t
+ getFaceId() const
+ {
+ return m_faceId;
+ }
+
+ NextHopRecord&
+ setFaceId(uint64_t faceId);
+
+ uint64_t
+ getCost() const
+ {
+ return m_cost;
+ }
+
+ NextHopRecord&
+ setCost(uint64_t cost);
+
+ template<encoding::Tag TAG>
+ size_t
+ wireEncode(EncodingImpl<TAG>& block) const;
+
+ const Block&
+ wireEncode() const;
+
+ void
+ wireDecode(const Block& wire);
+
+private:
+ uint64_t m_faceId;
+ uint64_t m_cost;
+
+ mutable Block m_wire;
+};
+
+/** @ingroup management
+ */
+class FibEntry
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+ FibEntry();
+
+ explicit
+ FibEntry(const Block& block);
+
+ const Name&
+ getPrefix() const
+ {
+ return m_prefix;
+ }
+
+ FibEntry&
+ setPrefix(const Name& prefix);
+
+ const std::list<NextHopRecord>&
+ getNextHopRecords() const
+ {
+ return m_nextHopRecords;
+ }
+
+ FibEntry&
+ addNextHopRecord(const NextHopRecord& nextHopRecord);
+
+ template<typename T>
+ FibEntry&
+ setNextHopRecords(const T& begin, const T& end)
+ {
+ m_nextHopRecords.clear();
+ m_nextHopRecords.assign(begin, end);
+ m_wire.reset();
+ return *this;
+ }
+
+ template<encoding::Tag TAG>
+ size_t
+ wireEncode(EncodingImpl<TAG>& block) const;
+
+ const Block&
+ wireEncode() const;
+
+ void
+ wireDecode(const Block& wire);
+
+private:
+ Name m_prefix;
+ std::list<NextHopRecord> m_nextHopRecords;
+
+ mutable Block m_wire;
+};
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_FIB_ENTRY_HPP
diff --git a/src/mgmt/nfd/forwarder-status.cpp b/src/mgmt/nfd/forwarder-status.cpp
new file mode 100644
index 0000000..21fee56
--- /dev/null
+++ b/src/mgmt/nfd/forwarder-status.cpp
@@ -0,0 +1,357 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "forwarder-status.hpp"
+#include "encoding/tlv-nfd.hpp"
+#include "encoding/block-helpers.hpp"
+#include "util/concepts.hpp"
+
+namespace ndn {
+namespace nfd {
+
+//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<ForwarderStatus>));
+BOOST_CONCEPT_ASSERT((WireEncodable<ForwarderStatus>));
+BOOST_CONCEPT_ASSERT((WireDecodable<ForwarderStatus>));
+static_assert(std::is_base_of<tlv::Error, ForwarderStatus::Error>::value,
+ "ForwarderStatus::Error must inherit from tlv::Error");
+
+ForwarderStatus::ForwarderStatus()
+ : m_startTimestamp(time::system_clock::TimePoint::min())
+ , m_currentTimestamp(time::system_clock::TimePoint::min())
+ , m_nNameTreeEntries(0)
+ , m_nFibEntries(0)
+ , m_nPitEntries(0)
+ , m_nMeasurementsEntries(0)
+ , m_nCsEntries(0)
+ , m_nInInterests(0)
+ , m_nInDatas(0)
+ , m_nInNacks(0)
+ , m_nOutInterests(0)
+ , m_nOutDatas(0)
+ , m_nOutNacks(0)
+{
+}
+
+ForwarderStatus::ForwarderStatus(const Block& payload)
+{
+ this->wireDecode(payload);
+}
+
+template<encoding::Tag TAG>
+size_t
+ForwarderStatus::wireEncode(EncodingImpl<TAG>& encoder) const
+{
+ size_t totalLength = 0;
+
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::NOutNacks,
+ m_nOutNacks);
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::NOutDatas,
+ m_nOutDatas);
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::NOutInterests,
+ m_nOutInterests);
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::NInNacks,
+ m_nInNacks);
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::NInDatas,
+ m_nInDatas);
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::NInInterests,
+ m_nInInterests);
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::NCsEntries,
+ m_nCsEntries);
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::NMeasurementsEntries,
+ m_nMeasurementsEntries);
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::NPitEntries,
+ m_nPitEntries);
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::NFibEntries,
+ m_nFibEntries);
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::NNameTreeEntries,
+ m_nNameTreeEntries);
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::CurrentTimestamp,
+ time::toUnixTimestamp(m_currentTimestamp).count());
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::nfd::StartTimestamp,
+ time::toUnixTimestamp(m_startTimestamp).count());
+ totalLength += encoder.prependByteArrayBlock(tlv::nfd::NfdVersion,
+ reinterpret_cast<const uint8_t*>(m_nfdVersion.c_str()),
+ m_nfdVersion.size());
+
+ totalLength += encoder.prependVarNumber(totalLength);
+ totalLength += encoder.prependVarNumber(tlv::Content);
+ return totalLength;
+}
+
+template size_t
+ForwarderStatus::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>&) const;
+
+template size_t
+ForwarderStatus::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>&) const;
+
+const Block&
+ForwarderStatus::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+ForwarderStatus::wireDecode(const Block& block)
+{
+ if (block.type() != tlv::Content) {
+ BOOST_THROW_EXCEPTION(Error("expecting Content block for Status payload"));
+ }
+ m_wire = block;
+ m_wire.parse();
+ Block::element_const_iterator val = m_wire.elements_begin();
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NfdVersion) {
+ m_nfdVersion.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NfdVersion field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::StartTimestamp) {
+ m_startTimestamp = time::fromUnixTimestamp(time::milliseconds(readNonNegativeInteger(*val)));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required StartTimestamp field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::CurrentTimestamp) {
+ m_currentTimestamp = time::fromUnixTimestamp(time::milliseconds(readNonNegativeInteger(*val)));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required CurrentTimestamp field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NNameTreeEntries) {
+ m_nNameTreeEntries = static_cast<size_t>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NNameTreeEntries field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NFibEntries) {
+ m_nFibEntries = static_cast<size_t>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NFibEntries field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NPitEntries) {
+ m_nPitEntries = static_cast<size_t>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NPitEntries field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NMeasurementsEntries) {
+ m_nMeasurementsEntries = static_cast<size_t>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NMeasurementsEntries field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NCsEntries) {
+ m_nCsEntries = static_cast<size_t>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NCsEntries field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NInInterests) {
+ m_nInInterests = static_cast<uint64_t>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NInInterests field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NInDatas) {
+ m_nInDatas = static_cast<uint64_t>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NInDatas field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NInNacks) {
+ m_nInNacks = static_cast<uint64_t>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NInNacks field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NOutInterests) {
+ m_nOutInterests = static_cast<uint64_t>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NOutInterests field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NOutDatas) {
+ m_nOutDatas = static_cast<uint64_t>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NOutDatas field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::NOutNacks) {
+ m_nOutNacks = static_cast<uint64_t>(readNonNegativeInteger(*val));
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required NInNacks field"));
+ }
+}
+
+ForwarderStatus&
+ForwarderStatus::setNfdVersion(const std::string& nfdVersion)
+{
+ m_wire.reset();
+ m_nfdVersion = nfdVersion;
+ return *this;
+}
+
+ForwarderStatus&
+ForwarderStatus::setStartTimestamp(const time::system_clock::TimePoint& startTimestamp)
+{
+ m_wire.reset();
+ m_startTimestamp = startTimestamp;
+ return *this;
+}
+
+ForwarderStatus&
+ForwarderStatus::setCurrentTimestamp(const time::system_clock::TimePoint& currentTimestamp)
+{
+ m_wire.reset();
+ m_currentTimestamp = currentTimestamp;
+ return *this;
+}
+
+ForwarderStatus&
+ForwarderStatus::setNNameTreeEntries(size_t nNameTreeEntries)
+{
+ m_wire.reset();
+ m_nNameTreeEntries = nNameTreeEntries;
+ return *this;
+}
+
+ForwarderStatus&
+ForwarderStatus::setNFibEntries(size_t nFibEntries)
+{
+ m_wire.reset();
+ m_nFibEntries = nFibEntries;
+ return *this;
+}
+
+ForwarderStatus&
+ForwarderStatus::setNPitEntries(size_t nPitEntries)
+{
+ m_wire.reset();
+ m_nPitEntries = nPitEntries;
+ return *this;
+}
+
+ForwarderStatus&
+ForwarderStatus::setNMeasurementsEntries(size_t nMeasurementsEntries)
+{
+ m_wire.reset();
+ m_nMeasurementsEntries = nMeasurementsEntries;
+ return *this;
+}
+
+ForwarderStatus&
+ForwarderStatus::setNCsEntries(size_t nCsEntries)
+{
+ m_wire.reset();
+ m_nCsEntries = nCsEntries;
+ return *this;
+}
+
+ForwarderStatus&
+ForwarderStatus::setNInInterests(uint64_t nInInterests)
+{
+ m_wire.reset();
+ m_nInInterests = nInInterests;
+ return *this;
+}
+
+ForwarderStatus&
+ForwarderStatus::setNInDatas(uint64_t nInDatas)
+{
+ m_wire.reset();
+ m_nInDatas = nInDatas;
+ return *this;
+}
+
+ForwarderStatus&
+ForwarderStatus::setNInNacks(uint64_t nInNacks)
+{
+ m_wire.reset();
+ m_nInNacks = nInNacks;
+ return *this;
+}
+
+ForwarderStatus&
+ForwarderStatus::setNOutInterests(uint64_t nOutInterests)
+{
+ m_wire.reset();
+ m_nOutInterests = nOutInterests;
+ return *this;
+}
+
+ForwarderStatus&
+ForwarderStatus::setNOutDatas(uint64_t nOutDatas)
+{
+ m_wire.reset();
+ m_nOutDatas = nOutDatas;
+ return *this;
+}
+
+ForwarderStatus&
+ForwarderStatus::setNOutNacks(uint64_t nOutNacks)
+{
+ m_wire.reset();
+ m_nOutNacks = nOutNacks;
+ return *this;
+}
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/mgmt/nfd/forwarder-status.hpp b/src/mgmt/nfd/forwarder-status.hpp
new file mode 100644
index 0000000..4601610
--- /dev/null
+++ b/src/mgmt/nfd/forwarder-status.hpp
@@ -0,0 +1,225 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_FORWARDER_STATUS_HPP
+#define NDN_MGMT_NFD_FORWARDER_STATUS_HPP
+
+#include "../../encoding/block.hpp"
+#include "../../util/time.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * \ingroup management
+ * \brief represents NFD Forwarder Status
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/ForwarderStatus
+ */
+class ForwarderStatus
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+ ForwarderStatus();
+
+ explicit
+ ForwarderStatus(const Block& payload);
+
+ /** \brief prepend ForwarderStatus as a Content block to the encoder
+ *
+ * The outermost Content element isn't part of ForwardStatus structure.
+ */
+ template<encoding::Tag TAG>
+ size_t
+ wireEncode(EncodingImpl<TAG>& encoder) const;
+
+ /** \brief encode ForwarderStatus as a Content block
+ *
+ * The outermost Content element isn't part of ForwardStatus structure.
+ */
+ const Block&
+ wireEncode() const;
+
+ /** \brief decode ForwarderStatus from a Content block
+ *
+ * The outermost Content element isn't part of ForwardStatus structure.
+ */
+ void
+ wireDecode(const Block& wire);
+
+public: // getters & setters
+ const std::string&
+ getNfdVersion() const
+ {
+ return m_nfdVersion;
+ }
+
+ ForwarderStatus&
+ setNfdVersion(const std::string& nfdVersion);
+
+ const time::system_clock::TimePoint&
+ getStartTimestamp() const
+ {
+ return m_startTimestamp;
+ }
+
+ ForwarderStatus&
+ setStartTimestamp(const time::system_clock::TimePoint& startTimestamp);
+
+ const time::system_clock::TimePoint&
+ getCurrentTimestamp() const
+ {
+ return m_currentTimestamp;
+ }
+
+ ForwarderStatus&
+ setCurrentTimestamp(const time::system_clock::TimePoint& currentTimestamp);
+
+ size_t
+ getNNameTreeEntries() const
+ {
+ return m_nNameTreeEntries;
+ }
+
+ ForwarderStatus&
+ setNNameTreeEntries(size_t nNameTreeEntries);
+
+ size_t
+ getNFibEntries() const
+ {
+ return m_nFibEntries;
+ }
+
+ ForwarderStatus&
+ setNFibEntries(size_t nFibEntries);
+
+ size_t
+ getNPitEntries() const
+ {
+ return m_nPitEntries;
+ }
+
+ ForwarderStatus&
+ setNPitEntries(size_t nPitEntries);
+
+ size_t
+ getNMeasurementsEntries() const
+ {
+ return m_nMeasurementsEntries;
+ }
+
+ ForwarderStatus&
+ setNMeasurementsEntries(size_t nMeasurementsEntries);
+
+ size_t
+ getNCsEntries() const
+ {
+ return m_nCsEntries;
+ }
+
+ ForwarderStatus&
+ setNCsEntries(size_t nCsEntries);
+
+ uint64_t
+ getNInInterests() const
+ {
+ return m_nInInterests;
+ }
+
+ ForwarderStatus&
+ setNInInterests(uint64_t nInInterests);
+
+ uint64_t
+ getNInDatas() const
+ {
+ return m_nInDatas;
+ }
+
+ ForwarderStatus&
+ setNInDatas(uint64_t nInDatas);
+
+ uint64_t
+ getNInNacks() const
+ {
+ return m_nInNacks;
+ }
+
+ ForwarderStatus&
+ setNInNacks(uint64_t nInNacks);
+
+ uint64_t
+ getNOutInterests() const
+ {
+ return m_nOutInterests;
+ }
+
+ ForwarderStatus&
+ setNOutInterests(uint64_t nOutInterests);
+
+ uint64_t
+ getNOutDatas() const
+ {
+ return m_nOutDatas;
+ }
+
+ ForwarderStatus&
+ setNOutDatas(uint64_t nOutDatas);
+
+ uint64_t
+ getNOutNacks() const
+ {
+ return m_nOutNacks;
+ }
+
+ ForwarderStatus&
+ setNOutNacks(uint64_t nOutNacks);
+
+private:
+ std::string m_nfdVersion;
+ time::system_clock::TimePoint m_startTimestamp;
+ time::system_clock::TimePoint m_currentTimestamp;
+ size_t m_nNameTreeEntries;
+ size_t m_nFibEntries;
+ size_t m_nPitEntries;
+ size_t m_nMeasurementsEntries;
+ size_t m_nCsEntries;
+ uint64_t m_nInInterests;
+ uint64_t m_nInDatas;
+ uint64_t m_nInNacks;
+ uint64_t m_nOutInterests;
+ uint64_t m_nOutDatas;
+ uint64_t m_nOutNacks;
+
+ mutable Block m_wire;
+};
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_FORWARDER_STATUS_HPP
diff --git a/src/mgmt/nfd/rib-entry.cpp b/src/mgmt/nfd/rib-entry.cpp
new file mode 100644
index 0000000..d47d316
--- /dev/null
+++ b/src/mgmt/nfd/rib-entry.cpp
@@ -0,0 +1,320 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "rib-entry.hpp"
+#include "encoding/tlv-nfd.hpp"
+#include "encoding/block-helpers.hpp"
+#include "util/concepts.hpp"
+
+namespace ndn {
+namespace nfd {
+
+//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Route>));
+BOOST_CONCEPT_ASSERT((WireEncodable<Route>));
+BOOST_CONCEPT_ASSERT((WireDecodable<Route>));
+static_assert(std::is_base_of<tlv::Error, Route::Error>::value,
+ "Route::Error must inherit from tlv::Error");
+
+//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<RibEntry>));
+BOOST_CONCEPT_ASSERT((WireEncodable<RibEntry>));
+BOOST_CONCEPT_ASSERT((WireDecodable<RibEntry>));
+static_assert(std::is_base_of<tlv::Error, RibEntry::Error>::value,
+ "RibEntry::Error must inherit from tlv::Error");
+
+const time::milliseconds Route::INFINITE_EXPIRATION_PERIOD(time::milliseconds::max());
+
+Route::Route()
+ : m_faceId(0)
+ , m_origin(0)
+ , m_cost(0)
+ , m_flags(ROUTE_FLAG_CHILD_INHERIT)
+ , m_expirationPeriod(INFINITE_EXPIRATION_PERIOD)
+ , m_hasInfiniteExpirationPeriod(true)
+{
+}
+
+Route::Route(const Block& block)
+{
+ wireDecode(block);
+}
+
+template<encoding::Tag TAG>
+size_t
+Route::wireEncode(EncodingImpl<TAG>& block) const
+{
+ size_t totalLength = 0;
+
+ // Absence of an ExpirationPeriod signifies non-expiration
+ if (!m_hasInfiniteExpirationPeriod) {
+ totalLength += prependNonNegativeIntegerBlock(block,
+ ndn::tlv::nfd::ExpirationPeriod,
+ m_expirationPeriod.count());
+ }
+
+ totalLength += prependNonNegativeIntegerBlock(block,
+ ndn::tlv::nfd::Flags,
+ m_flags);
+
+ totalLength += prependNonNegativeIntegerBlock(block,
+ ndn::tlv::nfd::Cost,
+ m_cost);
+
+ totalLength += prependNonNegativeIntegerBlock(block,
+ ndn::tlv::nfd::Origin,
+ m_origin);
+
+ totalLength += prependNonNegativeIntegerBlock(block,
+ ndn::tlv::nfd::FaceId,
+ m_faceId);
+
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(ndn::tlv::nfd::Route);
+
+ return totalLength;
+}
+
+template size_t
+Route::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block) const;
+
+template size_t
+Route::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block) const;
+
+const Block&
+Route::wireEncode() const
+{
+ if (m_wire.hasWire()) {
+ return m_wire;
+ }
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+
+ return m_wire;
+}
+
+void
+Route::wireDecode(const Block& wire)
+{
+ m_faceId = 0;
+ m_origin = 0;
+ m_cost = 0;
+ m_flags = 0;
+ m_expirationPeriod = time::milliseconds::min();
+
+ m_wire = wire;
+
+ if (m_wire.type() != tlv::nfd::Route) {
+ std::stringstream error;
+ error << "Expected Route Block, but Block is of a different type: #"
+ << m_wire.type();
+ BOOST_THROW_EXCEPTION(Error(error.str()));
+ }
+
+ m_wire.parse();
+
+ Block::element_const_iterator val = m_wire.elements_begin();
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceId) {
+ m_faceId = readNonNegativeInteger(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Missing required FaceId field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::Origin) {
+ m_origin = readNonNegativeInteger(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Missing required Origin field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::Cost) {
+ m_cost = readNonNegativeInteger(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Missing required Cost field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::Flags) {
+ m_flags = readNonNegativeInteger(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Missing required Flags field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::ExpirationPeriod) {
+ m_expirationPeriod = time::milliseconds(readNonNegativeInteger(*val));
+ m_hasInfiniteExpirationPeriod = false;
+ }
+ else {
+ m_expirationPeriod = INFINITE_EXPIRATION_PERIOD;
+ m_hasInfiniteExpirationPeriod = true;
+ }
+}
+
+std::ostream&
+operator<<(std::ostream& os, const Route& route)
+{
+ os << "Route("
+ << "FaceId: " << route.getFaceId() << ", "
+ << "Origin: " << route.getOrigin() << ", "
+ << "Cost: " << route.getCost() << ", "
+ << "Flags: " << route.getFlags() << ", ";
+
+ if (!route.hasInfiniteExpirationPeriod()) {
+ os << "ExpirationPeriod: " << route.getExpirationPeriod();
+ }
+ else {
+ os << "ExpirationPeriod: Infinity";
+ }
+
+ os << ")";
+
+ return os;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////
+
+
+RibEntry::RibEntry()
+{
+}
+
+RibEntry::RibEntry(const Block& block)
+{
+ wireDecode(block);
+}
+
+
+template<encoding::Tag TAG>
+size_t
+RibEntry::wireEncode(EncodingImpl<TAG>& block) const
+{
+ size_t totalLength = 0;
+
+ for (std::list<Route>::const_reverse_iterator it = m_routes.rbegin();
+ it != m_routes.rend(); ++it)
+ {
+ totalLength += it->wireEncode(block);
+ }
+
+ totalLength += m_prefix.wireEncode(block);
+
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::nfd::RibEntry);
+
+ return totalLength;
+}
+
+template size_t
+RibEntry::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block) const;
+
+template size_t
+RibEntry::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block) const;
+
+const Block&
+RibEntry::wireEncode() const
+{
+ if (m_wire.hasWire()) {
+ return m_wire;
+ }
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+
+ return m_wire;
+}
+
+void
+RibEntry::wireDecode(const Block& wire)
+{
+ m_prefix.clear();
+ m_routes.clear();
+
+ m_wire = wire;
+
+ if (m_wire.type() != tlv::nfd::RibEntry) {
+ std::stringstream error;
+ error << "Expected RibEntry Block, but Block is of a different type: #"
+ << m_wire.type();
+ BOOST_THROW_EXCEPTION(Error(error.str()));
+ }
+
+ m_wire.parse();
+
+ Block::element_const_iterator val = m_wire.elements_begin();
+
+ if (val != m_wire.elements_end() && val->type() == tlv::Name) {
+ m_prefix.wireDecode(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("Missing required Name field"));
+ }
+
+ for (; val != m_wire.elements_end(); ++val) {
+
+ if (val->type() == tlv::nfd::Route) {
+ m_routes.push_back(Route(*val));
+ }
+ else {
+ std::stringstream error;
+ error << "Expected Route Block, but Block is of a different type: #"
+ << m_wire.type();
+ BOOST_THROW_EXCEPTION(Error(error.str()));
+ }
+ }
+}
+
+std::ostream&
+operator<<(std::ostream& os, const RibEntry& entry)
+{
+ os << "RibEntry{\n"
+ << " Name: " << entry.getName() << "\n";
+
+ for (RibEntry::iterator it = entry.begin(); it != entry.end(); ++it) {
+ os << " " << *it << "\n";
+ }
+
+ os << "}";
+
+ return os;
+}
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/mgmt/nfd/rib-entry.hpp b/src/mgmt/nfd/rib-entry.hpp
new file mode 100644
index 0000000..6c1c5a2
--- /dev/null
+++ b/src/mgmt/nfd/rib-entry.hpp
@@ -0,0 +1,287 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_RIB_ENTRY_HPP
+#define NDN_MGMT_NFD_RIB_ENTRY_HPP
+
+#include "rib-flags.hpp" // include this first, to ensure it compiles on its own.
+#include "../../name.hpp"
+#include "../../util/time.hpp"
+
+#include <list>
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * @ingroup management
+ *
+ * @brief Data abstraction for Route
+ *
+ * A route indicates the availability of content via a certain face and
+ * provides meta-information about the face.
+ *
+ * Route := ROUTE-TYPE TLV-LENGTH
+ * FaceId
+ * Origin
+ * Cost
+ * Flags
+ * ExpirationPeriod?
+ *
+ * @sa http://redmine.named-data.net/projects/nfd/wiki/RibMgmt
+ */
+class Route : public RibFlagsTraits<Route>
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what) : tlv::Error(what)
+ {
+ }
+ };
+
+ Route();
+
+ explicit
+ Route(const Block& block);
+
+ uint64_t
+ getFaceId() const
+ {
+ return m_faceId;
+ }
+
+ Route&
+ setFaceId(uint64_t faceId)
+ {
+ m_faceId = faceId;
+ m_wire.reset();
+ return *this;
+ }
+
+ uint64_t
+ getOrigin() const
+ {
+ return m_origin;
+ }
+
+ /** @brief set Origin
+ * @param origin a code defined in ndn::nfd::RouteOrigin
+ */
+ Route&
+ setOrigin(uint64_t origin)
+ {
+ m_origin = origin;
+ m_wire.reset();
+ return *this;
+ }
+
+ uint64_t
+ getCost() const
+ {
+ return m_cost;
+ }
+
+ Route&
+ setCost(uint64_t cost)
+ {
+ m_cost = cost;
+ m_wire.reset();
+ return *this;
+ }
+
+ uint64_t
+ getFlags() const
+ {
+ return m_flags;
+ }
+
+ /** @brief set route inheritance flags
+ * @param flags a bitwise OR'ed code from ndn::nfd::RouteFlags
+ */
+ Route&
+ setFlags(uint64_t flags)
+ {
+ m_flags = flags;
+ m_wire.reset();
+ return *this;
+ }
+
+ static const time::milliseconds INFINITE_EXPIRATION_PERIOD;
+
+ const time::milliseconds&
+ getExpirationPeriod() const
+ {
+ return m_expirationPeriod;
+ }
+
+ Route&
+ setExpirationPeriod(const time::milliseconds& expirationPeriod)
+ {
+ m_expirationPeriod = expirationPeriod;
+
+ m_hasInfiniteExpirationPeriod = m_expirationPeriod == INFINITE_EXPIRATION_PERIOD;
+
+ m_wire.reset();
+ return *this;
+ }
+
+ bool
+ hasInfiniteExpirationPeriod() const
+ {
+ return m_hasInfiniteExpirationPeriod;
+ }
+
+ template<encoding::Tag TAG>
+ size_t
+ wireEncode(EncodingImpl<TAG>& block) const;
+
+ const Block&
+ wireEncode() const;
+
+ void
+ wireDecode(const Block& wire);
+
+private:
+ uint64_t m_faceId;
+ uint64_t m_origin;
+ uint64_t m_cost;
+ uint64_t m_flags;
+ time::milliseconds m_expirationPeriod;
+ bool m_hasInfiniteExpirationPeriod;
+
+ mutable Block m_wire;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const Route& route);
+
+/**
+ * @ingroup management
+ *
+ * @brief Data abstraction for RIB entry
+ *
+ * A RIB entry contains one or more routes for the name prefix
+ *
+ * RibEntry := RIB-ENTRY-TYPE TLV-LENGTH
+ * Name
+ * Route+
+ *
+ * @sa http://redmine.named-data.net/projects/nfd/wiki/RibMgmt
+ */
+class RibEntry
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ Error(const std::string& what) : tlv::Error(what)
+ {
+ }
+ };
+
+ typedef std::list<Route> RouteList;
+ typedef RouteList::const_iterator iterator;
+
+ RibEntry();
+
+ explicit
+ RibEntry(const Block& block);
+
+ const Name&
+ getName() const
+ {
+ return m_prefix;
+ }
+
+ RibEntry&
+ setName(const Name& prefix)
+ {
+ m_prefix = prefix;
+ m_wire.reset();
+ return *this;
+ }
+
+ const std::list<Route>&
+ getRoutes() const
+ {
+ return m_routes;
+ }
+
+ RibEntry&
+ addRoute(const Route& route)
+ {
+ m_routes.push_back(route);
+ m_wire.reset();
+ return *this;
+ }
+
+ RibEntry&
+ clearRoutes()
+ {
+ m_routes.clear();
+ return *this;
+ }
+
+ template<encoding::Tag TAG>
+ size_t
+ wireEncode(EncodingImpl<TAG>& block) const;
+
+ const Block&
+ wireEncode() const;
+
+ void
+ wireDecode(const Block& wire);
+
+ iterator
+ begin() const;
+
+ iterator
+ end() const;
+
+private:
+ Name m_prefix;
+ RouteList m_routes;
+
+ mutable Block m_wire;
+};
+
+inline RibEntry::iterator
+RibEntry::begin() const
+{
+ return m_routes.begin();
+}
+
+inline RibEntry::iterator
+RibEntry::end() const
+{
+ return m_routes.end();
+}
+
+std::ostream&
+operator<<(std::ostream& os, const RibEntry& entry);
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_RIB_ENTRY_HPP
diff --git a/src/mgmt/nfd/rib-flags.hpp b/src/mgmt/nfd/rib-flags.hpp
new file mode 100644
index 0000000..158048f
--- /dev/null
+++ b/src/mgmt/nfd/rib-flags.hpp
@@ -0,0 +1,57 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_RIB_FLAGS_HPP
+#define NDN_MGMT_NFD_RIB_FLAGS_HPP
+
+#include "../../encoding/nfd-constants.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * \ingroup management
+ * \brief implements getters to each RIB flag
+ *
+ * \tparam T class containing a RibFlags field and implements
+ * `RibFlags getFlags() const` method
+ */
+template<typename T>
+class RibFlagsTraits
+{
+public:
+ bool
+ isChildInherit() const
+ {
+ return static_cast<const T*>(this)->getFlags() & ROUTE_FLAG_CHILD_INHERIT;
+ }
+
+ bool
+ isRibCapture() const
+ {
+ return static_cast<const T*>(this)->getFlags() & ROUTE_FLAG_CAPTURE;
+ }
+};
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_RIB_FLAGS_HPP
diff --git a/src/mgmt/nfd/status-dataset.cpp b/src/mgmt/nfd/status-dataset.cpp
new file mode 100644
index 0000000..ca5f5df
--- /dev/null
+++ b/src/mgmt/nfd/status-dataset.cpp
@@ -0,0 +1,162 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "status-dataset.hpp"
+#include "../../util/concepts.hpp"
+
+namespace ndn {
+namespace nfd {
+
+StatusDataset::StatusDataset(const PartialName& datasetName)
+ : m_datasetName(datasetName)
+{
+}
+
+Name
+StatusDataset::getDatasetPrefix(const Name& prefix) const
+{
+ Name name;
+ name.append(prefix).append(m_datasetName);
+ this->addParameters(name);
+ return name;
+}
+
+void
+StatusDataset::addParameters(Name& name) const
+{
+}
+
+/**
+ * \brief parses elements into a vector of T
+ * \tparam T element type
+ * \param payload pointer to a buffer of zero or more blocks of decodable by T
+ * \return a vector of T
+ * \throw tlv::Error cannot parse payload
+ */
+template<typename T>
+static std::vector<T>
+parseDatasetVector(ConstBufferPtr payload)
+{
+ BOOST_CONCEPT_ASSERT((WireDecodable<T>));
+
+ std::vector<T> result;
+
+ size_t offset = 0;
+ while (offset < payload->size()) {
+ bool isOk = false;
+ Block block;
+ std::tie(isOk, block) = Block::fromBuffer(payload, offset);
+ if (!isOk) {
+ BOOST_THROW_EXCEPTION(StatusDataset::ParseResultError("cannot decode Block"));
+ }
+
+ offset += block.size();
+ result.emplace_back(block);
+ }
+
+ return result;
+}
+
+ForwarderGeneralStatusDataset::ForwarderGeneralStatusDataset()
+ : StatusDataset("status/general")
+{
+}
+
+ForwarderGeneralStatusDataset::ResultType
+ForwarderGeneralStatusDataset::parseResult(ConstBufferPtr payload) const
+{
+ return ForwarderStatus(Block(tlv::Content, payload));
+}
+
+FaceDatasetBase::FaceDatasetBase(const PartialName& datasetName)
+ : StatusDataset(datasetName)
+{
+}
+
+FaceDatasetBase::ResultType
+FaceDatasetBase::parseResult(ConstBufferPtr payload) const
+{
+ return parseDatasetVector<FaceStatus>(payload);
+}
+
+FaceDataset::FaceDataset()
+ : FaceDatasetBase("faces/list")
+{
+}
+
+FaceQueryDataset::FaceQueryDataset(const FaceQueryFilter& filter)
+ : FaceDatasetBase("faces/query")
+ , m_filter(filter)
+{
+}
+
+void
+FaceQueryDataset::addParameters(Name& name) const
+{
+ name.append(m_filter.wireEncode());
+}
+
+ChannelDataset::ChannelDataset()
+ : StatusDataset("faces/channels")
+{
+}
+
+ChannelDataset::ResultType
+ChannelDataset::parseResult(ConstBufferPtr payload) const
+{
+ return parseDatasetVector<ChannelStatus>(payload);
+}
+
+FibDataset::FibDataset()
+ : StatusDataset("fib/list")
+{
+}
+
+FibDataset::ResultType
+FibDataset::parseResult(ConstBufferPtr payload) const
+{
+ return parseDatasetVector<FibEntry>(payload);
+}
+
+StrategyChoiceDataset::StrategyChoiceDataset()
+ : StatusDataset("strategy-choice/list")
+{
+}
+
+StrategyChoiceDataset::ResultType
+StrategyChoiceDataset::parseResult(ConstBufferPtr payload) const
+{
+ return parseDatasetVector<StrategyChoice>(payload);
+}
+
+RibDataset::RibDataset()
+ : StatusDataset("rib/list")
+{
+}
+
+RibDataset::ResultType
+RibDataset::parseResult(ConstBufferPtr payload) const
+{
+ return parseDatasetVector<RibEntry>(payload);
+}
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/mgmt/nfd/status-dataset.hpp b/src/mgmt/nfd/status-dataset.hpp
new file mode 100644
index 0000000..9eb43d4
--- /dev/null
+++ b/src/mgmt/nfd/status-dataset.hpp
@@ -0,0 +1,252 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_STATUS_DATASET_HPP
+#define NDN_MGMT_NFD_STATUS_DATASET_HPP
+
+#include "../../name.hpp"
+#include "forwarder-status.hpp"
+#include "face-status.hpp"
+#include "face-query-filter.hpp"
+#include "channel-status.hpp"
+#include "fib-entry.hpp"
+#include "strategy-choice.hpp"
+#include "rib-entry.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * \ingroup management
+ * \brief base class of NFD StatusDataset
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/StatusDataset
+ */
+class StatusDataset : noncopyable
+{
+public:
+#ifdef DOXYGEN
+ /**
+ * \brief if defined, specifies constructor argument type;
+ * otherwise, constructor has no argument
+ */
+ typedef int ParamType;
+#endif
+
+ /**
+ * \brief constructs a name prefix for the dataset
+ * \param prefix top-level prefix, such as ndn:/localhost/nfd
+ * \return name prefix without version and segment components
+ */
+ Name
+ getDatasetPrefix(const Name& prefix) const;
+
+#ifdef DOXYGEN
+ /**
+ * \brief provides the result type, usually a vector
+ */
+ typedef std::vector<int> ResultType;
+#endif
+
+ /**
+ * \brief indicates reassembled payload cannot be parsed as ResultType
+ */
+ class ParseResultError : public tlv::Error
+ {
+ public:
+ explicit
+ ParseResultError(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+#ifdef DOXYGEN
+ /**
+ * \brief parses a result from reassembled payload
+ * \param payload reassembled payload
+ * \throw tlv::Error cannot parse payload
+ */
+ ResultType
+ parseResult(ConstBufferPtr payload) const;
+#endif
+
+protected:
+ /**
+ * \brief constructs a StatusDataset instance with given sub-prefix
+ * \param datasetName dataset name after top-level prefix, such as faces/list
+ */
+ explicit
+ StatusDataset(const PartialName& datasetName);
+
+private:
+ /**
+ * \brief appends parameters to the dataset name prefix
+ * \param[in,out] the dataset name prefix onto which parameter components can be appended
+ */
+ virtual void
+ addParameters(Name& name) const;
+
+private:
+ PartialName m_datasetName;
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a status/general dataset
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/ForwarderStatus#General-Status-Dataset
+ */
+class ForwarderGeneralStatusDataset : public StatusDataset
+{
+public:
+ ForwarderGeneralStatusDataset();
+
+ typedef ForwarderStatus ResultType;
+
+ ResultType
+ parseResult(ConstBufferPtr payload) const;
+};
+
+
+/**
+ * \ingroup management
+ * \brief provides common functionality among FaceDataset and FaceQueryDataset
+ */
+class FaceDatasetBase : public StatusDataset
+{
+public:
+ typedef std::vector<FaceStatus> ResultType;
+
+ ResultType
+ parseResult(ConstBufferPtr payload) const;
+
+protected:
+ explicit
+ FaceDatasetBase(const PartialName& datasetName);
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a faces/list dataset
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Face-Dataset
+ */
+class FaceDataset : public FaceDatasetBase
+{
+public:
+ FaceDataset();
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a faces/query dataset
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Query-Operation
+ */
+class FaceQueryDataset : public FaceDatasetBase
+{
+public:
+ typedef FaceQueryFilter ParamType;
+
+ explicit
+ FaceQueryDataset(const FaceQueryFilter& filter);
+
+private:
+ virtual void
+ addParameters(Name& name) const override;
+
+private:
+ FaceQueryFilter m_filter;
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a faces/channels dataset
+ * \sa https://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#Channel-Dataset
+ */
+class ChannelDataset : public StatusDataset
+{
+public:
+ ChannelDataset();
+
+ typedef std::vector<ChannelStatus> ResultType;
+
+ ResultType
+ parseResult(ConstBufferPtr payload) const;
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a fib/list dataset
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/FibMgmt#FIB-Dataset
+ */
+class FibDataset : public StatusDataset
+{
+public:
+ FibDataset();
+
+ typedef std::vector<FibEntry> ResultType;
+
+ ResultType
+ parseResult(ConstBufferPtr payload) const;
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a strategy-choice/list dataset
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice#Strategy-Choice-Dataset
+ */
+class StrategyChoiceDataset : public StatusDataset
+{
+public:
+ StrategyChoiceDataset();
+
+ typedef std::vector<StrategyChoice> ResultType;
+
+ ResultType
+ parseResult(ConstBufferPtr payload) const;
+};
+
+
+/**
+ * \ingroup management
+ * \brief represents a rib/list dataset
+ * \sa http://redmine.named-data.net/projects/nfd/wiki/RibMgmt#RIB-Dataset
+ */
+class RibDataset : public StatusDataset
+{
+public:
+ RibDataset();
+
+ typedef std::vector<RibEntry> ResultType;
+
+ ResultType
+ parseResult(ConstBufferPtr payload) const;
+};
+
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_STATUS_DATASET_HPP
diff --git a/src/mgmt/nfd/strategy-choice.cpp b/src/mgmt/nfd/strategy-choice.cpp
new file mode 100644
index 0000000..2e294d7
--- /dev/null
+++ b/src/mgmt/nfd/strategy-choice.cpp
@@ -0,0 +1,131 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "strategy-choice.hpp"
+#include "encoding/tlv-nfd.hpp"
+#include "encoding/block-helpers.hpp"
+#include "util/concepts.hpp"
+
+namespace ndn {
+namespace nfd {
+
+//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<StrategyChoice>));
+BOOST_CONCEPT_ASSERT((WireEncodable<StrategyChoice>));
+BOOST_CONCEPT_ASSERT((WireDecodable<StrategyChoice>));
+static_assert(std::is_base_of<tlv::Error, StrategyChoice::Error>::value,
+ "StrategyChoice::Error must inherit from tlv::Error");
+
+StrategyChoice::StrategyChoice()
+{
+}
+
+StrategyChoice::StrategyChoice(const Block& payload)
+{
+ this->wireDecode(payload);
+}
+
+template<encoding::Tag TAG>
+size_t
+StrategyChoice::wireEncode(EncodingImpl<TAG>& encoder) const
+{
+ size_t totalLength = 0;
+
+ totalLength += prependNestedBlock(encoder, tlv::nfd::Strategy, m_strategy);
+ totalLength += m_name.wireEncode(encoder);
+
+ totalLength += encoder.prependVarNumber(totalLength);
+ totalLength += encoder.prependVarNumber(tlv::nfd::StrategyChoice);
+ return totalLength;
+}
+
+template size_t
+StrategyChoice::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>&) const;
+
+template size_t
+StrategyChoice::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>&) const;
+
+const Block&
+StrategyChoice::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+StrategyChoice::wireDecode(const Block& block)
+{
+ if (block.type() != tlv::nfd::StrategyChoice) {
+ BOOST_THROW_EXCEPTION(Error("expecting StrategyChoice block"));
+ }
+ m_wire = block;
+ m_wire.parse();
+ Block::element_const_iterator val = m_wire.elements_begin();
+
+ if (val != m_wire.elements_end() && val->type() == tlv::Name) {
+ m_name.wireDecode(*val);
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required Name field"));
+ }
+
+ if (val != m_wire.elements_end() && val->type() == tlv::nfd::Strategy) {
+ val->parse();
+ if (val->elements().empty()) {
+ BOOST_THROW_EXCEPTION(Error("expecting Strategy/Name"));
+ }
+ else {
+ m_strategy.wireDecode(*val->elements_begin());
+ }
+ ++val;
+ }
+ else {
+ BOOST_THROW_EXCEPTION(Error("missing required Strategy field"));
+ }
+}
+
+StrategyChoice&
+StrategyChoice::setName(const Name& name)
+{
+ m_wire.reset();
+ m_name = name;
+ return *this;
+}
+
+StrategyChoice&
+StrategyChoice::setStrategy(const Name& strategy)
+{
+ m_wire.reset();
+ m_strategy = strategy;
+ return *this;
+}
+
+} // namespace nfd
+} // namespace ndn
diff --git a/src/mgmt/nfd/strategy-choice.hpp b/src/mgmt/nfd/strategy-choice.hpp
new file mode 100644
index 0000000..8cdaa59
--- /dev/null
+++ b/src/mgmt/nfd/strategy-choice.hpp
@@ -0,0 +1,93 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2016 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_MGMT_NFD_STRATEGY_CHOICE_HPP
+#define NDN_MGMT_NFD_STRATEGY_CHOICE_HPP
+
+#include "../../encoding/block.hpp"
+#include "../../name.hpp"
+
+namespace ndn {
+namespace nfd {
+
+/**
+ * @ingroup management
+ * @brief represents NFD StrategyChoice dataset
+ * @sa http://redmine.named-data.net/projects/nfd/wiki/StrategyChoice#Strategy-Choice-Dataset
+ */
+class StrategyChoice
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+ StrategyChoice();
+
+ explicit
+ StrategyChoice(const Block& payload);
+
+ template<encoding::Tag TAG>
+ size_t
+ wireEncode(EncodingImpl<TAG>& encoder) const;
+
+ const Block&
+ wireEncode() const;
+
+ void
+ wireDecode(const Block& wire);
+
+public: // getters & setters
+ const Name&
+ getName() const
+ {
+ return m_name;
+ }
+
+ StrategyChoice&
+ setName(const Name& name);
+
+ const Name&
+ getStrategy() const
+ {
+ return m_strategy;
+ }
+
+ StrategyChoice&
+ setStrategy(const Name& strategy);
+
+private:
+ Name m_name; // namespace
+ Name m_strategy; // strategy for the namespace
+
+ mutable Block m_wire;
+};
+
+} // namespace nfd
+} // namespace ndn
+
+#endif // NDN_MGMT_NFD_STRATEGY_CHOICE_HPP