face-module.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2017, 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-module.hpp"
27 #include "find-face.hpp"
28 #include "format-helpers.hpp"
29 
30 namespace nfd {
31 namespace tools {
32 namespace nfdc {
33 
34 void
36 {
37  CommandDefinition defFaceList("face", "list");
38  defFaceList
39  .setTitle("print face list")
43  parser.addCommand(defFaceList, &FaceModule::list);
44 
45  CommandDefinition defFaceShow("face", "show");
46  defFaceShow
47  .setTitle("show face information")
49  parser.addCommand(defFaceShow, &FaceModule::show);
50 
51  CommandDefinition defFaceCreate("face", "create");
52  defFaceCreate
53  .setTitle("create a face")
58  parser.addCommand(defFaceCreate, &FaceModule::create);
59 
60  CommandDefinition defFaceDestroy("face", "destroy");
61  defFaceDestroy
62  .setTitle("destroy a face")
64  parser.addCommand(defFaceDestroy, &FaceModule::destroy);
65 }
66 
67 void
69 {
70  auto remoteUri = ctx.args.getOptional<FaceUri>("remote");
71  auto localUri = ctx.args.getOptional<FaceUri>("local");
72  auto uriScheme = ctx.args.getOptional<std::string>("scheme");
73 
74  FaceQueryFilter filter;
75  if (remoteUri) {
76  filter.setRemoteUri(remoteUri->toString());
77  }
78  if (localUri) {
79  filter.setLocalUri(localUri->toString());
80  }
81  if (uriScheme) {
82  filter.setUriScheme(*uriScheme);
83  }
84 
85  FindFace findFace(ctx);
86  FindFace::Code res = findFace.execute(filter, true);
87 
88  ctx.exitCode = static_cast<int>(res);
89  switch (res) {
90  case FindFace::Code::OK:
91  for (const FaceStatus& item : findFace.getResults()) {
92  formatItemText(ctx.out, item, false);
93  ctx.out << '\n';
94  }
95  break;
99  ctx.err << findFace.getErrorReason() << '\n';
100  break;
101  default:
102  BOOST_ASSERT_MSG(false, "unexpected FindFace result");
103  break;
104  }
105 }
106 
107 void
109 {
110  uint64_t faceId = ctx.args.get<uint64_t>("id");
111 
112  FindFace findFace(ctx);
113  FindFace::Code res = findFace.execute(faceId);
114 
115  ctx.exitCode = static_cast<int>(res);
116  switch (res) {
117  case FindFace::Code::OK:
118  formatItemText(ctx.out, findFace.getFaceStatus(), true);
119  break;
122  ctx.err << findFace.getErrorReason() << '\n';
123  break;
124  default:
125  BOOST_ASSERT_MSG(false, "unexpected FindFace result");
126  break;
127  }
128 }
129 
132 static bool
133 persistencyLessThan(FacePersistency x, FacePersistency y)
134 {
135  switch (x) {
136  case FacePersistency::FACE_PERSISTENCY_NONE:
137  return y != FacePersistency::FACE_PERSISTENCY_NONE;
138  case FacePersistency::FACE_PERSISTENCY_ON_DEMAND:
139  return y == FacePersistency::FACE_PERSISTENCY_PERSISTENT ||
140  y == FacePersistency::FACE_PERSISTENCY_PERMANENT;
141  case FacePersistency::FACE_PERSISTENCY_PERSISTENT:
142  return y == FacePersistency::FACE_PERSISTENCY_PERMANENT;
143  case FacePersistency::FACE_PERSISTENCY_PERMANENT:
144  return false;
145  }
146  return static_cast<int>(x) < static_cast<int>(y);
147 }
148 
149 void
151 {
152  auto remoteUri = ctx.args.get<FaceUri>("remote");
153  auto localUri = ctx.args.getOptional<FaceUri>("local");
154  auto persistency = ctx.args.get<FacePersistency>("persistency", FacePersistency::FACE_PERSISTENCY_PERSISTENT);
155  auto lpReliability = ctx.args.getTribool("reliability");
156 
157  FaceUri canonicalRemote;
158  ndn::optional<FaceUri> canonicalLocal;
159 
160  auto handleCanonizeError = [&] (const FaceUri& faceUri, const std::string& error) {
161  ctx.exitCode = 4;
162  ctx.err << "Error when canonizing '" << faceUri << "': " << error << '\n';
163  };
164 
165  auto printPositiveResult = [&] (const std::string& actionSummary, const ControlParameters& resp) {
167  ctx.out << actionSummary << ' '
168  << ia("id") << resp.getFaceId()
169  << ia("local") << resp.getLocalUri()
170  << ia("remote") << resp.getUri()
171  << ia("persistency") << resp.getFacePersistency()
172  << ia("reliability") << (resp.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED) ? "on" : "off")
173  << '\n';
174  };
175 
176  auto updateFace = [&printPositiveResult] (ControlParameters respParams, ControlParameters resp) {
177  // faces/update response does not have FaceUris, copy from faces/create response
178  resp.setLocalUri(respParams.getLocalUri())
179  .setUri(respParams.getUri());
180  printPositiveResult("face-updated", resp);
181  };
182 
183  auto handle409 = [&] (const ControlResponse& resp) {
184  ControlParameters respParams(resp.getBody());
185  if (respParams.getUri() != canonicalRemote.toString()) {
186  // we are conflicting with a different face, which is a general error
187  return false;
188  }
189 
190  if (persistencyLessThan(respParams.getFacePersistency(), persistency)) {
191  // need to upgrade persistency
192  ControlParameters params;
193  params.setFaceId(respParams.getFaceId()).setFacePersistency(persistency);
194  if (!boost::logic::indeterminate(lpReliability)) {
195  params.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, lpReliability);
196  }
197  ctx.controller.start<ndn::nfd::FaceUpdateCommand>(
198  params,
199  bind(updateFace, respParams, _1),
200  ctx.makeCommandFailureHandler("upgrading face persistency"),
201  ctx.makeCommandOptions());
202  }
203  else if (lpReliability && !respParams.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
204  // enable reliability
205  ControlParameters params;
206  params.setFaceId(respParams.getFaceId()).setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, true);
207  ctx.controller.start<ndn::nfd::FaceUpdateCommand>(
208  params,
209  bind(updateFace, respParams, _1),
210  ctx.makeCommandFailureHandler("enabling reliability"),
211  ctx.makeCommandOptions());
212  }
213  else if (!lpReliability && respParams.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
214  // disable reliability
215  ControlParameters params;
216  params.setFaceId(respParams.getFaceId()).setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, false);
217  ctx.controller.start<ndn::nfd::FaceUpdateCommand>(
218  params,
219  bind(updateFace, respParams, _1),
220  ctx.makeCommandFailureHandler("disabling reliability"),
221  ctx.makeCommandOptions());
222  }
223  else {
224  // don't do anything
225  printPositiveResult("face-exists", respParams);
226  }
227  return true;
228  };
229 
230  auto doCreateFace = [&] {
231  ControlParameters params;
232  params.setUri(canonicalRemote.toString());
233  if (canonicalLocal) {
234  params.setLocalUri(canonicalLocal->toString());
235  }
236  params.setFacePersistency(persistency);
237  if (!boost::logic::indeterminate(lpReliability)) {
238  params.setFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED, lpReliability);
239  }
240 
241  ctx.controller.start<ndn::nfd::FaceCreateCommand>(
242  params,
243  bind(printPositiveResult, "face-created", _1),
244  [&] (const ControlResponse& resp) {
245  if (resp.getCode() == 409 && handle409(resp)) {
246  return;
247  }
248  ctx.makeCommandFailureHandler("creating face")(resp); // invoke general error handler
249  },
250  ctx.makeCommandOptions());
251  };
252 
253  remoteUri.canonize(
254  [&] (const FaceUri& canonicalUri) {
255  canonicalRemote = canonicalUri;
256  if (localUri) {
257  localUri->canonize(
258  [&] (const FaceUri& canonicalUri) {
259  canonicalLocal = canonicalUri;
260  doCreateFace();
261  },
262  bind(handleCanonizeError, *localUri, _1),
263  ctx.face.getIoService(), ctx.getTimeout());
264  }
265  else {
266  doCreateFace();
267  }
268  },
269  bind(handleCanonizeError, remoteUri, _1),
270  ctx.face.getIoService(), ctx.getTimeout());
271 
272  ctx.face.processEvents();
273 }
274 
275 void
277 {
278  const boost::any& faceIdOrUri = ctx.args.at("face");
279 
280  FindFace findFace(ctx);
281  FindFace::Code res = findFace.execute(faceIdOrUri);
282 
283  ctx.exitCode = static_cast<int>(res);
284  switch (res) {
285  case FindFace::Code::OK:
286  break;
290  ctx.err << findFace.getErrorReason() << '\n';
291  return;
293  ctx.err << "Multiple faces match specified remote FaceUri. Re-run the command with a FaceId:";
295  ctx.err << '\n';
296  return;
297  default:
298  BOOST_ASSERT_MSG(false, "unexpected FindFace result");
299  return;
300  }
301 
302  const FaceStatus& face = findFace.getFaceStatus();
303 
304  ctx.controller.start<ndn::nfd::FaceDestroyCommand>(
305  ControlParameters().setFaceId(face.getFaceId()),
306  [&] (const ControlParameters& resp) {
307  ctx.out << "face-destroyed ";
309  ctx.out << ia("id") << face.getFaceId()
310  << ia("local") << face.getLocalUri()
311  << ia("remote") << face.getRemoteUri()
312  << ia("persistency") << face.getFacePersistency()
313  << ia("reliability") << (resp.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED) ? "on" : "off")
314  << '\n';
315  },
316  ctx.makeCommandFailureHandler("destroying face"),
317  ctx.makeCommandOptions());
318 
319  ctx.face.processEvents();
320 }
321 
322 void
323 FaceModule::fetchStatus(Controller& controller,
324  const function<void()>& onSuccess,
325  const Controller::DatasetFailCallback& onFailure,
326  const CommandOptions& options)
327 {
328  controller.fetch<ndn::nfd::FaceDataset>(
329  [this, onSuccess] (const std::vector<FaceStatus>& result) {
330  m_status = result;
331  onSuccess();
332  },
333  onFailure, options);
334 }
335 
336 void
337 FaceModule::formatStatusXml(std::ostream& os) const
338 {
339  os << "<faces>";
340  for (const FaceStatus& item : m_status) {
341  this->formatItemXml(os, item);
342  }
343  os << "</faces>";
344 }
345 
346 void
347 FaceModule::formatItemXml(std::ostream& os, const FaceStatus& item) const
348 {
349  os << "<face>";
350 
351  os << "<faceId>" << item.getFaceId() << "</faceId>";
352  os << "<remoteUri>" << xml::Text{item.getRemoteUri()} << "</remoteUri>";
353  os << "<localUri>" << xml::Text{item.getLocalUri()} << "</localUri>";
354 
355  if (item.hasExpirationPeriod()) {
356  os << "<expirationPeriod>" << xml::formatDuration(item.getExpirationPeriod())
357  << "</expirationPeriod>";
358  }
359  os << "<faceScope>" << item.getFaceScope() << "</faceScope>";
360  os << "<facePersistency>" << item.getFacePersistency() << "</facePersistency>";
361  os << "<linkType>" << item.getLinkType() << "</linkType>";
362 
363  if (item.getFlags() == 0) {
364  os << "<flags/>";
365  }
366  else {
367  os << "<flags>";
368  if (item.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)) {
369  os << "<localFieldsEnabled/>";
370  }
371  if (item.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
372  os << "<lpReliabilityEnabled/>";
373  }
374  os << "</flags>";
375  }
376 
377  os << "<packetCounters>";
378  os << "<incomingPackets>"
379  << "<nInterests>" << item.getNInInterests() << "</nInterests>"
380  << "<nData>" << item.getNInData() << "</nData>"
381  << "<nNacks>" << item.getNInNacks() << "</nNacks>"
382  << "</incomingPackets>";
383  os << "<outgoingPackets>"
384  << "<nInterests>" << item.getNOutInterests() << "</nInterests>"
385  << "<nData>" << item.getNOutData() << "</nData>"
386  << "<nNacks>" << item.getNOutNacks() << "</nNacks>"
387  << "</outgoingPackets>";
388  os << "</packetCounters>";
389 
390  os << "<byteCounters>";
391  os << "<incomingBytes>" << item.getNInBytes() << "</incomingBytes>";
392  os << "<outgoingBytes>" << item.getNOutBytes() << "</outgoingBytes>";
393  os << "</byteCounters>";
394 
395  os << "</face>";
396 }
397 
398 void
399 FaceModule::formatStatusText(std::ostream& os) const
400 {
401  os << "Faces:\n";
402  for (const FaceStatus& item : m_status) {
403  os << " ";
404  formatItemText(os, item, false);
405  os << '\n';
406  }
407 }
408 
409 void
410 FaceModule::formatItemText(std::ostream& os, const FaceStatus& item, bool wantMultiLine)
411 {
412  text::ItemAttributes ia(wantMultiLine, 8);
413 
414  os << ia("faceid") << item.getFaceId();
415  os << ia("remote") << item.getRemoteUri();
416  os << ia("local") << item.getLocalUri();
417 
418  if (item.hasExpirationPeriod()) {
419  os << ia("expires") << text::formatDuration(item.getExpirationPeriod());
420  }
421 
422  os << ia("counters")
423  << "{in={"
424  << item.getNInInterests() << "i "
425  << item.getNInData() << "d "
426  << item.getNInNacks() << "n "
427  << item.getNInBytes() << "B} "
428  << "out={"
429  << item.getNOutInterests() << "i "
430  << item.getNOutData() << "d "
431  << item.getNOutNacks() << "n "
432  << item.getNOutBytes() << "B}}";
433 
434  os << ia("flags") << '{';
435  text::Separator flagSep("", " ");
436  os << flagSep << item.getFaceScope();
437  os << flagSep << item.getFacePersistency();
438  os << flagSep << item.getLinkType();
439  if (item.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)) {
440  os << flagSep << "local-fields";
441  }
442  if (item.getFlagBit(ndn::nfd::BIT_LP_RELIABILITY_ENABLED)) {
443  os << flagSep << "lp-reliability";
444  }
445  os << '}';
446 
447  os << ia.end();
448 }
449 
450 } // namespace nfdc
451 } // namespace tools
452 } // namespace nfd
const CommandArguments & args
void formatStatusText(std::ostream &os) const override
format collected status as text
ndn::nfd::CommandOptions makeCommandOptions() const
void fetchStatus(Controller &controller, const function< void()> &onSuccess, const Controller::DatasetFailCallback &onFailure, const CommandOptions &options) override
collect status from NFD
Controller::CommandFailCallback makeCommandFailureHandler(const std::string &commandName)
declares semantics of a command
std::ostream & out
output stream
context for command execution
void formatStatusXml(std::ostream &os) const override
format collected status as XML
time::nanoseconds getTimeout() const
T get(const std::string &key, const T &defaultValue=T()) const
found exactly one face, or found multiple faces when allowMulti is true
error during FaceUri canonization
static bool persistencyLessThan(FacePersistency x, FacePersistency y)
order persistency in NONE < ON_DEMAND < PERSISTENCY < PERMANENT
CommandDefinition & setTitle(const std::string &title)
set one-line description
found multiple faces and allowMulti is false
static void create(ExecuteContext &ctx)
the &#39;face create&#39; command
void printDisambiguation(std::ostream &os, DisambiguationStyle style) const
print results for disambiguation
Definition: find-face.cpp:169
std::string formatDuration(DURATION d)
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
Definition: algorithm.hpp:32
procedure to find a face
Definition: find-face.hpp:40
face persistency &#39;persistent&#39; or &#39;permanent&#39;
Code execute(const FaceUri &faceUri, bool allowMulti=false)
find face by FaceUri
Definition: find-face.cpp:42
static void registerCommands(CommandParser &parser)
register &#39;face list&#39;, &#39;face show&#39;, &#39;face create&#39;, &#39;face destroy&#39; commands
Definition: face-module.cpp:35
CommandDefinition & addArg(const std::string &name, ArgValueType valueType, Required isRequired=Required::NO, Positional allowPositional=Positional::NO, const std::string &metavar="")
declare an argument
print attributes of an item
argument is required
static void show(ExecuteContext &ctx)
the &#39;face show&#39; command
void formatItemXml(std::ostream &os, const FaceStatus &item) const
format a single status item as XML
std::string formatDuration(DURATION d, bool isLong=false)
std::ostream & err
error stream
const FaceStatus & getFaceStatus() const
Definition: find-face.cpp:162
CommandParser & addCommand(const CommandDefinition &def, const ExecuteCommand &execute, std::underlying_type< AvailableIn >::type modes=AVAILABLE_IN_ALL)
add an available command
boost::logic::tribool getTribool(const std::string &key) const
get an optional boolean argument as tribool
static void formatItemText(std::ostream &os, const FaceStatus &item, bool wantMultiLine)
format a single status item as text
static void list(ExecuteContext &ctx)
the &#39;face list&#39; command
Definition: face-module.cpp:68
ndn::optional< T > getOptional(const std::string &key) const
argument is optional
static void destroy(ExecuteContext &ctx)
the &#39;face destroy&#39; command
const std::string & getErrorReason() const
Definition: find-face.hpp:113
const std::vector< FaceStatus > & getResults() const
Definition: find-face.hpp:90
print different string on first and subsequent usage