tools: nfdc face destroy command
refs #3864
Change-Id: I1d070570c14364529c566273eba44b87413942b1
diff --git a/tools/nfdc/face-module.cpp b/tools/nfdc/face-module.cpp
index 3c087f4..4dc732e 100644
--- a/tools/nfdc/face-module.cpp
+++ b/tools/nfdc/face-module.cpp
@@ -24,6 +24,7 @@
*/
#include "face-module.hpp"
+#include "find-face.hpp"
#include "format-helpers.hpp"
namespace nfd {
@@ -45,6 +46,12 @@
.addArg("remote", ArgValueType::FACE_URI, Required::YES, Positional::YES)
.addArg("persistency", ArgValueType::FACE_PERSISTENCY, Required::NO, Positional::YES);
parser.addCommand(defFaceCreate, &FaceModule::create);
+
+ CommandDefinition defFaceDestroy("face", "destroy");
+ defFaceDestroy
+ .setTitle("destroy a face")
+ .addArg("face", ArgValueType::FACE_ID_OR_URI, Required::YES, Positional::YES);
+ parser.addCommand(defFaceDestroy, &FaceModule::destroy);
}
void
@@ -101,6 +108,58 @@
}
void
+FaceModule::destroy(ExecuteContext& ctx)
+{
+ const boost::any faceIdOrUri = ctx.args.at("face");
+
+ FindFace findFace(ctx);
+ FindFace::Code res = FindFace::Code::ERROR;
+ const uint64_t* faceId = boost::any_cast<uint64_t>(&faceIdOrUri);
+ if (faceId != nullptr) {
+ res = findFace.execute(*faceId);
+ }
+ else {
+ res = findFace.execute(boost::any_cast<FaceUri>(faceIdOrUri));
+ }
+
+ ctx.exitCode = static_cast<int>(res);
+ switch (res) {
+ case FindFace::Code::OK:
+ break;
+ case FindFace::Code::ERROR:
+ case FindFace::Code::CANONIZE_ERROR:
+ case FindFace::Code::NOT_FOUND:
+ ctx.err << findFace.getErrorReason() << '\n';
+ return;
+ case FindFace::Code::AMBIGUOUS:
+ ctx.err << "Multiple faces match specified remote FaceUri. Re-run the command with a FaceId:";
+ findFace.printDisambiguation(ctx.err, FindFace::DisambiguationStyle::LOCAL_URI);
+ ctx.err << '\n';
+ return;
+ default:
+ BOOST_ASSERT_MSG(false, "unexpected FindFace result");
+ return;
+ }
+
+ const FaceStatus& face = findFace.getFaceStatus();
+
+ ctx.controller.start<ndn::nfd::FaceDestroyCommand>(
+ ControlParameters().setFaceId(face.getFaceId()),
+ [&] (const ControlParameters& resp) {
+ ctx.out << "face-destroyed ";
+ text::ItemAttributes ia;
+ ctx.out << ia("id") << face.getFaceId()
+ << ia("local") << face.getLocalUri()
+ << ia("remote") << face.getRemoteUri()
+ << ia("persistency") << face.getFacePersistency() << '\n';
+ },
+ ctx.makeCommandFailureHandler("destroying face"),
+ ctx.makeCommandOptions());
+
+ ctx.face.processEvents();
+}
+
+void
FaceModule::fetchStatus(Controller& controller,
const function<void()>& onSuccess,
const Controller::DatasetFailCallback& onFailure,
diff --git a/tools/nfdc/face-module.hpp b/tools/nfdc/face-module.hpp
index 1bbc31b..3f70d48 100644
--- a/tools/nfdc/face-module.hpp
+++ b/tools/nfdc/face-module.hpp
@@ -56,6 +56,11 @@
static void
create(ExecuteContext& ctx);
+ /** \brief the 'face destroy' command
+ */
+ static void
+ destroy(ExecuteContext& ctx);
+
void
fetchStatus(Controller& controller,
const function<void()>& onSuccess,
diff --git a/tools/nfdc/find-face.cpp b/tools/nfdc/find-face.cpp
new file mode 100644
index 0000000..c03e6dc
--- /dev/null
+++ b/tools/nfdc/find-face.cpp
@@ -0,0 +1,149 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "find-face.hpp"
+#include "format-helpers.hpp"
+#include <ndn-cxx/util/logger.hpp>
+
+namespace nfd {
+namespace tools {
+namespace nfdc {
+
+NDN_LOG_INIT(nfdc.FindFace);
+
+FindFace::FindFace(ExecuteContext& ctx)
+ : m_ctx(ctx)
+{
+}
+
+FindFace::Code
+FindFace::execute(const FaceUri& faceUri, bool allowMulti)
+{
+ FaceQueryFilter filter;
+ filter.setRemoteUri(faceUri.toString());
+ return this->execute(filter);
+}
+
+FindFace::Code
+FindFace::execute(uint64_t faceId)
+{
+ FaceQueryFilter filter;
+ filter.setFaceId(faceId);
+ return this->execute(filter);
+}
+
+FindFace::Code
+FindFace::execute(const FaceQueryFilter& filter, bool allowMulti)
+{
+ BOOST_ASSERT(m_res == Code::NOT_STARTED);
+ m_res = Code::IN_PROGRESS;
+ m_filter = filter;
+
+ if (m_filter.hasRemoteUri()) {
+ auto remoteUri = this->canonize("remote", FaceUri(m_filter.getRemoteUri()));
+ if (!remoteUri) {
+ m_res = Code::CANONIZE_ERROR;
+ return m_res;
+ }
+ m_filter.setRemoteUri(remoteUri->toString());
+ }
+
+ ///\todo #3864 canonize localUri
+
+ this->query();
+ if (m_res == Code::OK) {
+ if (m_results.size() == 0) {
+ m_res = Code::NOT_FOUND;
+ m_errorReason = "Face not found";
+ }
+ else if (m_results.size() > 1 && !allowMulti) {
+ m_res = Code::AMBIGUOUS;
+ m_errorReason = "Multiple faces match the query";
+ }
+ }
+ return m_res;
+}
+
+ndn::optional<FaceUri>
+FindFace::canonize(const std::string& fieldName, const FaceUri& input)
+{
+ if (!FaceUri::canCanonize(input.getScheme())) {
+ NDN_LOG_DEBUG("Using " << fieldName << '=' << input << " without canonization");
+ return input;
+ }
+
+ ndn::optional<FaceUri> result;
+ input.canonize(
+ [&result] (const FaceUri& canonicalUri) { result = canonicalUri; },
+ [this, fieldName] (const std::string& errorReason) {
+ m_errorReason = "Error during " + fieldName + " FaceUri canonization: " + errorReason;
+ },
+ m_ctx.face.getIoService(), m_ctx.getTimeout());
+ m_ctx.face.processEvents();
+
+ return result;
+}
+
+void
+FindFace::query()
+{
+ m_ctx.controller.fetch<ndn::nfd::FaceQueryDataset>(
+ m_filter,
+ [this] (const std::vector<ndn::nfd::FaceStatus>& result) {
+ m_res = Code::OK;
+ m_results = result;
+ },
+ [this] (uint32_t code, const std::string& reason) {
+ m_res = Code::ERROR;
+ m_errorReason = "Error " + std::to_string(code) + " when querying face: " + reason;
+ },
+ m_ctx.makeCommandOptions());
+ m_ctx.face.processEvents();
+}
+
+const FaceStatus&
+FindFace::getFaceStatus() const
+{
+ BOOST_ASSERT(m_results.size() == 1);
+ return m_results.front();
+}
+
+void
+FindFace::printDisambiguation(std::ostream& os, DisambiguationStyle style) const
+{
+ text::Separator sep(" ", ", ");
+ for (const auto& item : m_results) {
+ os << sep;
+ switch (style) {
+ case DisambiguationStyle::LOCAL_URI:
+ os << item.getFaceId() << " (local=" << item.getLocalUri() << ')';
+ break;
+ }
+ }
+}
+
+} // namespace nfdc
+} // namespace tools
+} // namespace nfd
diff --git a/tools/nfdc/find-face.hpp b/tools/nfdc/find-face.hpp
new file mode 100644
index 0000000..57eb0f0
--- /dev/null
+++ b/tools/nfdc/find-face.hpp
@@ -0,0 +1,137 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NFD_TOOLS_NFDC_FIND_FACE_HPP
+#define NFD_TOOLS_NFDC_FIND_FACE_HPP
+
+#include "execute-command.hpp"
+
+namespace nfd {
+namespace tools {
+namespace nfdc {
+
+using ndn::nfd::FaceQueryFilter;
+using ndn::nfd::FaceStatus;
+
+/** \brief procedure to find a face
+ */
+class FindFace : noncopyable
+{
+public:
+ enum class Code {
+ OK = 0, ///< found exactly one face, or found multiple faces when allowMulti is true
+ ERROR = 1, ///< unspecified error
+ NOT_FOUND = 3, ///< found zero face
+ CANONIZE_ERROR = 4, ///< error during FaceUri canonization
+ AMBIGUOUS = 5, ///< found multiple faces and allowMulti is false
+ NOT_STARTED = -1, ///< for internal use
+ IN_PROGRESS = -2, ///< for internal use
+ };
+
+ enum class DisambiguationStyle
+ {
+ LOCAL_URI = 1 ///< print FaceId and LocalUri
+ };
+
+ explicit
+ FindFace(ExecuteContext& ctx);
+
+ /** \brief find face by FaceUri
+ * \pre execute has not been invoked
+ */
+ Code
+ execute(const FaceUri& faceUri, bool allowMulti = false);
+
+ /** \brief find face by FaceId
+ * \pre execute has not been invoked
+ */
+ Code
+ execute(uint64_t faceId);
+
+ /** \brief find face by FaceQueryFilter
+ * \pre execute has not been invoked
+ */
+ Code
+ execute(const FaceQueryFilter& filter, bool allowMulti = false);
+
+ /** \return face status for all results
+ */
+ const std::vector<FaceStatus>&
+ getResults() const
+ {
+ return m_results;
+ }
+
+ /** \return a single face status
+ * \pre getResults().size() == 1
+ */
+ const FaceStatus&
+ getFaceStatus() const;
+
+ uint64_t
+ getFaceId() const
+ {
+ return this->getFaceStatus().getFaceId();
+ }
+
+ const std::string&
+ getErrorReason() const
+ {
+ return m_errorReason;
+ }
+
+ /** \brief print results for disambiguation
+ */
+ void
+ printDisambiguation(std::ostream& os, DisambiguationStyle style) const;
+
+private:
+ /** \brief canonize FaceUri
+ * \return canonical FaceUri if canonization succeeds, input if canonization is unsupported
+ * \retval nullopt canonization fails; m_errorReason describes the failure
+ */
+ ndn::optional<FaceUri>
+ canonize(const std::string& fieldName, const FaceUri& input);
+
+ /** \brief retrieve FaceStatus from filter
+ * \post m_res == Code::OK and m_results is populated if retrieval succeeds
+ * \post m_res == Code::ERROR and m_errorReason is set if retrieval fails
+ */
+ void
+ query();
+
+private:
+ ExecuteContext& m_ctx;
+ FaceQueryFilter m_filter;
+ Code m_res = Code::NOT_STARTED;
+ std::vector<FaceStatus> m_results;
+ std::string m_errorReason;
+};
+
+} // namespace nfdc
+} // namespace tools
+} // namespace nfd
+
+#endif // NFD_TOOLS_NFDC_FIND_FACE_HPP