face-helpers.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2024, Regents of the University of California,
4  * Arizona Board of Regents,
5  * Colorado State University,
6  * University Pierre & Marie Curie, Sorbonne University,
7  * Washington University in St. Louis,
8  * Beijing Institute of Technology,
9  * The University of Memphis.
10  *
11  * This file is part of NFD (Named Data Networking Forwarding Daemon).
12  * See AUTHORS.md for complete list of NFD authors and contributors.
13  *
14  * NFD is free software: you can redistribute it and/or modify it under the terms
15  * of the GNU General Public License as published by the Free Software Foundation,
16  * either version 3 of the License, or (at your option) any later version.
17  *
18  * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20  * PURPOSE. See the GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along with
23  * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 #include "face-helpers.hpp"
27 #include "format-helpers.hpp"
28 
29 #include <ndn-cxx/mgmt/nfd/status-dataset.hpp>
30 #include <ndn-cxx/util/logger.hpp>
31 
32 namespace nfd::tools::nfdc {
33 
34 NDN_LOG_INIT(nfdc.FindFace);
35 
37  : m_ctx(ctx)
38 {
39 }
40 
42 FindFace::execute(const FaceUri& faceUri, bool allowMulti)
43 {
44  FaceQueryFilter filter;
45  filter.setRemoteUri(faceUri.toString());
46  return this->execute(filter, allowMulti);
47 }
48 
50 FindFace::execute(uint64_t faceId)
51 {
52  FaceQueryFilter filter;
53  filter.setFaceId(faceId);
54  return this->execute(filter);
55 }
56 
58 FindFace::execute(const std::any& faceIdOrUri, bool allowMulti)
59 {
60  const uint64_t* faceId = std::any_cast<uint64_t>(&faceIdOrUri);
61  if (faceId != nullptr) {
62  return this->execute(*faceId);
63  }
64  else {
65  return this->execute(std::any_cast<FaceUri>(faceIdOrUri), allowMulti);
66  }
67 }
68 
70 FindFace::execute(const FaceQueryFilter& filter, bool allowMulti)
71 {
72  BOOST_ASSERT(m_res == Code::NOT_STARTED);
73  m_res = Code::IN_PROGRESS;
74  m_filter = filter;
75 
76  if (m_filter.hasRemoteUri()) {
77  auto remoteUri = canonize("remote FaceUri", FaceUri(m_filter.getRemoteUri()));
78  if (!remoteUri) {
79  return m_res;
80  }
81  m_filter.setRemoteUri(remoteUri->toString());
82  }
83 
84  if (m_filter.hasLocalUri()) {
85  auto localUri = canonize("local FaceUri", FaceUri(m_filter.getLocalUri()));
86  if (!localUri) {
87  return m_res;
88  }
89  m_filter.setLocalUri(localUri->toString());
90  }
91 
92  this->query();
93  if (m_res == Code::OK) {
94  if (m_results.size() == 0) {
95  m_res = Code::NOT_FOUND;
96  m_errorReason = "Face not found";
97  }
98  else if (m_results.size() > 1 && !allowMulti) {
99  m_res = Code::AMBIGUOUS;
100  m_errorReason = "Multiple faces match the query";
101  }
102  }
103  return m_res;
104 }
105 
106 std::optional<FaceUri>
107 FindFace::canonize(const std::string& fieldName, const FaceUri& uri)
108 {
109  // We use a wrapper because we want to accept FaceUris that cannot be canonized
110  if (!FaceUri::canCanonize(uri.getScheme())) {
111  NDN_LOG_DEBUG("Using " << fieldName << "=" << uri << " without canonization");
112  return uri;
113  }
114 
115  auto [result, error] = nfdc::canonize(m_ctx, uri);
116  if (result) {
117  // Canonization succeeded
118  return result;
119  }
120  else {
121  // Canonization failed
122  std::tie(m_res, m_errorReason) = canonizeErrorHelper(uri, error);
123  return std::nullopt;
124  }
125 }
126 
127 void
128 FindFace::query()
129 {
130  auto datasetCb = [this] (const auto& result) {
131  m_res = Code::OK;
132  m_results = result;
133  };
134  auto failureCb = [this] (uint32_t code, const auto& reason) {
135  m_res = Code::ERROR;
136  m_errorReason = "Error " + std::to_string(code) + " when querying face: " + reason;
137  };
138 
139  if (m_filter.empty()) {
140  m_ctx.controller.fetch<ndn::nfd::FaceDataset>(
141  datasetCb, failureCb, m_ctx.makeCommandOptions());
142  }
143  else {
144  m_ctx.controller.fetch<ndn::nfd::FaceQueryDataset>(
145  m_filter, datasetCb, failureCb, m_ctx.makeCommandOptions());
146  }
147  m_ctx.face.processEvents();
148 }
149 
150 std::set<uint64_t>
152 {
153  std::set<uint64_t> faceIds;
154  for (const FaceStatus& faceStatus : m_results) {
155  faceIds.insert(faceStatus.getFaceId());
156  }
157  return faceIds;
158 }
159 
160 const FaceStatus&
162 {
163  BOOST_ASSERT(m_results.size() == 1);
164  return m_results.front();
165 }
166 
167 void
169 {
170  text::Separator sep(" ", ", ");
171  for (const auto& item : m_results) {
172  os << sep;
173  switch (style) {
175  os << item.getFaceId() << " (local=" << item.getLocalUri() << ')';
176  break;
177  }
178  }
179 }
180 
181 std::pair<std::optional<FaceUri>, std::string>
182 canonize(ExecuteContext& ctx, const FaceUri& uri)
183 {
184  std::optional<FaceUri> result;
185  std::string error;
186  uri.canonize(
187  [&result] (const auto& canonicalUri) { result = canonicalUri; },
188  [&error] (const auto& errorReason) { error = errorReason; },
189  ctx.face.getIoContext(), ctx.getTimeout());
190  ctx.face.processEvents();
191 
192  return {result, error};
193 }
194 
195 std::pair<FindFace::Code, std::string>
196 canonizeErrorHelper(const FaceUri& uri,
197  const std::string& error,
198  const std::string& field)
199 {
200  std::string msg = "Error during canonization of ";
201  if (!field.empty()) {
202  msg += field + " ";
203  }
204  msg += "'" + uri.toString() + "': " + error;
205  return {FindFace::Code::CANONIZE_ERROR, msg};
206 }
207 
208 } // namespace nfd::tools::nfdc
Context for command execution.
ndn::nfd::Controller & controller
ndn::nfd::CommandOptions makeCommandOptions() const
ndn::time::nanoseconds getTimeout() const
std::set< uint64_t > getFaceIds() const
const FaceStatus & getFaceStatus() const
FindFace(ExecuteContext &ctx)
@ AMBIGUOUS
found multiple faces and allowMulti is false
@ CANONIZE_ERROR
error during FaceUri canonization
@ OK
found exactly one face, or found multiple faces when allowMulti is true
Code execute(const FaceUri &faceUri, bool allowMulti=false)
Find face by FaceUri.
void printDisambiguation(std::ostream &os, DisambiguationStyle style) const
Print results for disambiguation.
Print different string on first and subsequent usage.
std::pair< FindFace::Code, std::string > canonizeErrorHelper(const FaceUri &uri, const std::string &error, const std::string &field)
Helper to generate exit code and error message for face canonization failures.
std::pair< std::optional< FaceUri >, std::string > canonize(ExecuteContext &ctx, const FaceUri &uri)
Canonize a FaceUri.
NDN_LOG_INIT(nfdc.CommandDefinition)