blob: 39ca5c205ec05def36c4c5910631a3015c9f72e5 [file] [log] [blame]
Junxiao Shi38f4ce92016-08-04 10:01:52 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shi1f481fa2017-01-26 15:14:43 +00003 * Copyright (c) 2014-2017, Regents of the University of California,
Junxiao Shi38f4ce92016-08-04 10:01:52 +00004 * 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
Junxiao Shi38f4ce92016-08-04 10:01:52 +000026#include "face-module.hpp"
Junxiao Shi05dd4442017-02-06 22:50:07 +000027#include "find-face.hpp"
Junxiao Shi38f4ce92016-08-04 10:01:52 +000028#include "format-helpers.hpp"
29
30namespace nfd {
31namespace tools {
Junxiao Shi331ade72016-08-19 14:07:19 +000032namespace nfdc {
Junxiao Shi38f4ce92016-08-04 10:01:52 +000033
34void
Junxiao Shi1f481fa2017-01-26 15:14:43 +000035FaceModule::registerCommands(CommandParser& parser)
36{
Junxiao Shi36e54292017-02-17 18:43:16 +000037 CommandDefinition defFaceList("face", "list");
38 defFaceList
39 .setTitle("print face list")
40 .addArg("remote", ArgValueType::FACE_URI, Required::NO, Positional::YES)
41 .addArg("local", ArgValueType::FACE_URI, Required::NO, Positional::NO)
42 .addArg("scheme", ArgValueType::STRING, Required::NO, Positional::NO, "scheme");
43 parser.addCommand(defFaceList, &FaceModule::list);
44
Junxiao Shi1f481fa2017-01-26 15:14:43 +000045 CommandDefinition defFaceShow("face", "show");
46 defFaceShow
47 .setTitle("show face information")
48 .addArg("id", ArgValueType::UNSIGNED, Required::YES, Positional::YES);
49 parser.addCommand(defFaceShow, &FaceModule::show);
Junxiao Shi1d7fef52017-02-02 05:33:14 +000050
51 CommandDefinition defFaceCreate("face", "create");
52 defFaceCreate
53 .setTitle("create a face")
54 .addArg("remote", ArgValueType::FACE_URI, Required::YES, Positional::YES)
Junxiao Shi0d976922017-04-01 14:35:21 +000055 .addArg("persistency", ArgValueType::FACE_PERSISTENCY, Required::NO, Positional::YES)
56 .addArg("local", ArgValueType::FACE_URI, Required::NO, Positional::NO);
Junxiao Shi1d7fef52017-02-02 05:33:14 +000057 parser.addCommand(defFaceCreate, &FaceModule::create);
Junxiao Shi05dd4442017-02-06 22:50:07 +000058
59 CommandDefinition defFaceDestroy("face", "destroy");
60 defFaceDestroy
61 .setTitle("destroy a face")
62 .addArg("face", ArgValueType::FACE_ID_OR_URI, Required::YES, Positional::YES);
63 parser.addCommand(defFaceDestroy, &FaceModule::destroy);
Junxiao Shi1f481fa2017-01-26 15:14:43 +000064}
65
66void
Junxiao Shi36e54292017-02-17 18:43:16 +000067FaceModule::list(ExecuteContext& ctx)
68{
69 auto remoteUri = ctx.args.getOptional<FaceUri>("remote");
70 auto localUri = ctx.args.getOptional<FaceUri>("local");
71 auto uriScheme = ctx.args.getOptional<std::string>("scheme");
72
73 FaceQueryFilter filter;
74 if (remoteUri) {
75 filter.setRemoteUri(remoteUri->toString());
76 }
77 if (localUri) {
78 filter.setLocalUri(localUri->toString());
79 }
80 if (uriScheme) {
81 filter.setUriScheme(*uriScheme);
82 }
83
84 FindFace findFace(ctx);
85 FindFace::Code res = findFace.execute(filter, true);
86
87 ctx.exitCode = static_cast<int>(res);
88 switch (res) {
89 case FindFace::Code::OK:
90 for (const FaceStatus& item : findFace.getResults()) {
91 formatItemText(ctx.out, item, false);
92 ctx.out << '\n';
93 }
94 break;
95 case FindFace::Code::ERROR:
96 case FindFace::Code::NOT_FOUND:
97 case FindFace::Code::CANONIZE_ERROR:
98 ctx.err << findFace.getErrorReason() << '\n';
99 break;
100 default:
101 BOOST_ASSERT_MSG(false, "unexpected FindFace result");
102 break;
103 }
104}
105
106void
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000107FaceModule::show(ExecuteContext& ctx)
108{
109 uint64_t faceId = ctx.args.get<uint64_t>("id");
110
Junxiao Shi8f803f22017-02-10 03:04:28 +0000111 FindFace findFace(ctx);
112 FindFace::Code res = findFace.execute(faceId);
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000113
Junxiao Shi8f803f22017-02-10 03:04:28 +0000114 ctx.exitCode = static_cast<int>(res);
115 switch (res) {
116 case FindFace::Code::OK:
117 formatItemText(ctx.out, findFace.getFaceStatus(), true);
118 break;
119 case FindFace::Code::ERROR:
120 case FindFace::Code::NOT_FOUND:
121 ctx.err << findFace.getErrorReason() << '\n';
122 break;
123 default:
124 BOOST_ASSERT_MSG(false, "unexpected FindFace result");
125 break;
126 }
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000127}
128
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000129/** \brief order persistency in NONE < ON_DEMAND < PERSISTENCY < PERMANENT
130 */
131static bool
132persistencyLessThan(FacePersistency x, FacePersistency y)
133{
134 switch (x) {
135 case FacePersistency::FACE_PERSISTENCY_NONE:
136 return y != FacePersistency::FACE_PERSISTENCY_NONE;
137 case FacePersistency::FACE_PERSISTENCY_ON_DEMAND:
138 return y == FacePersistency::FACE_PERSISTENCY_PERSISTENT ||
139 y == FacePersistency::FACE_PERSISTENCY_PERMANENT;
140 case FacePersistency::FACE_PERSISTENCY_PERSISTENT:
141 return y == FacePersistency::FACE_PERSISTENCY_PERMANENT;
142 case FacePersistency::FACE_PERSISTENCY_PERMANENT:
143 return false;
144 }
145 return static_cast<int>(x) < static_cast<int>(y);
146}
147
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000148void
149FaceModule::create(ExecuteContext& ctx)
150{
Junxiao Shi0d976922017-04-01 14:35:21 +0000151 auto remoteUri = ctx.args.get<FaceUri>("remote");
152 auto localUri = ctx.args.getOptional<FaceUri>("local");
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000153 auto persistency = ctx.args.get<FacePersistency>("persistency", FacePersistency::FACE_PERSISTENCY_PERSISTENT);
Junxiao Shi0d976922017-04-01 14:35:21 +0000154 FaceUri canonicalRemote;
155 ndn::optional<FaceUri> canonicalLocal;
156
157 auto handleCanonizeError = [&] (const FaceUri& faceUri, const std::string& error) {
158 ctx.exitCode = 4;
159 ctx.err << "Error when canonizing '" << faceUri << "': " << error << '\n';
160 };
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000161
162 auto printPositiveResult = [&] (const std::string& actionSummary, const ControlParameters& resp) {
163 text::ItemAttributes ia;
164 ctx.out << actionSummary << ' '
165 << ia("id") << resp.getFaceId()
Junxiao Shi1cce2a32017-05-02 02:39:55 +0000166 << ia("local") << resp.getLocalUri()
167 << ia("remote") << resp.getUri()
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000168 << ia("persistency") << resp.getFacePersistency()
169 << '\n';
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000170 };
171
172 auto handle409 = [&] (const ControlResponse& resp) {
173 ControlParameters respParams(resp.getBody());
Junxiao Shi0d976922017-04-01 14:35:21 +0000174 if (respParams.getUri() != canonicalRemote.toString()) {
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000175 // we are conflicting with a different face, which is a general error
176 return false;
177 }
178
179 if (persistencyLessThan(respParams.getFacePersistency(), persistency)) {
180 // need to upgrade persistency
181 ctx.controller.start<ndn::nfd::FaceUpdateCommand>(
182 ControlParameters().setFaceId(respParams.getFaceId()).setFacePersistency(persistency),
Junxiao Shi1cce2a32017-05-02 02:39:55 +0000183 [respParams, &printPositiveResult] (ControlParameters resp2) {
184 // faces/update response does not have FaceUris, copy from faces/create response
185 resp2.setLocalUri(respParams.getLocalUri())
186 .setUri(respParams.getUri());
187 printPositiveResult("face-updated", resp2);
188 },
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000189 ctx.makeCommandFailureHandler("upgrading face persistency"),
190 ctx.makeCommandOptions());
191 }
192 else {
193 // don't downgrade persistency
194 printPositiveResult("face-exists", respParams);
195 }
196 return true;
197 };
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000198
Junxiao Shi0d976922017-04-01 14:35:21 +0000199 auto doCreateFace = [&] {
200 ControlParameters params;
201 params.setUri(canonicalRemote.toString());
202 if (canonicalLocal) {
203 params.setLocalUri(canonicalLocal->toString());
204 }
205 params.setFacePersistency(persistency);
206
207 ctx.controller.start<ndn::nfd::FaceCreateCommand>(
208 params,
209 bind(printPositiveResult, "face-created", _1),
210 [&] (const ControlResponse& resp) {
211 if (resp.getCode() == 409 && handle409(resp)) {
212 return;
213 }
214 ctx.makeCommandFailureHandler("creating face")(resp); // invoke general error handler
215 },
216 ctx.makeCommandOptions());
217 };
218
219 remoteUri.canonize(
220 [&] (const FaceUri& canonicalUri) {
221 canonicalRemote = canonicalUri;
222 if (localUri) {
223 localUri->canonize(
224 [&] (const FaceUri& canonicalUri) {
225 canonicalLocal = canonicalUri;
226 doCreateFace();
227 },
228 bind(handleCanonizeError, *localUri, _1),
229 ctx.face.getIoService(), ctx.getTimeout());
230 }
231 else {
232 doCreateFace();
233 }
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000234 },
Junxiao Shi0d976922017-04-01 14:35:21 +0000235 bind(handleCanonizeError, remoteUri, _1),
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000236 ctx.face.getIoService(), ctx.getTimeout());
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000237
238 ctx.face.processEvents();
239}
240
241void
Junxiao Shi05dd4442017-02-06 22:50:07 +0000242FaceModule::destroy(ExecuteContext& ctx)
243{
Junxiao Shi918e5d42017-02-25 03:58:21 +0000244 const boost::any& faceIdOrUri = ctx.args.at("face");
Junxiao Shi05dd4442017-02-06 22:50:07 +0000245
246 FindFace findFace(ctx);
Junxiao Shi918e5d42017-02-25 03:58:21 +0000247 FindFace::Code res = findFace.execute(faceIdOrUri);
Junxiao Shi05dd4442017-02-06 22:50:07 +0000248
249 ctx.exitCode = static_cast<int>(res);
250 switch (res) {
251 case FindFace::Code::OK:
252 break;
253 case FindFace::Code::ERROR:
254 case FindFace::Code::CANONIZE_ERROR:
255 case FindFace::Code::NOT_FOUND:
256 ctx.err << findFace.getErrorReason() << '\n';
257 return;
258 case FindFace::Code::AMBIGUOUS:
259 ctx.err << "Multiple faces match specified remote FaceUri. Re-run the command with a FaceId:";
260 findFace.printDisambiguation(ctx.err, FindFace::DisambiguationStyle::LOCAL_URI);
261 ctx.err << '\n';
262 return;
263 default:
264 BOOST_ASSERT_MSG(false, "unexpected FindFace result");
265 return;
266 }
267
268 const FaceStatus& face = findFace.getFaceStatus();
269
270 ctx.controller.start<ndn::nfd::FaceDestroyCommand>(
271 ControlParameters().setFaceId(face.getFaceId()),
272 [&] (const ControlParameters& resp) {
273 ctx.out << "face-destroyed ";
274 text::ItemAttributes ia;
275 ctx.out << ia("id") << face.getFaceId()
276 << ia("local") << face.getLocalUri()
277 << ia("remote") << face.getRemoteUri()
278 << ia("persistency") << face.getFacePersistency() << '\n';
279 },
280 ctx.makeCommandFailureHandler("destroying face"),
281 ctx.makeCommandOptions());
282
283 ctx.face.processEvents();
284}
285
286void
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000287FaceModule::fetchStatus(Controller& controller,
288 const function<void()>& onSuccess,
Junxiao Shi29b41282016-08-22 03:47:02 +0000289 const Controller::DatasetFailCallback& onFailure,
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000290 const CommandOptions& options)
291{
292 controller.fetch<ndn::nfd::FaceDataset>(
293 [this, onSuccess] (const std::vector<FaceStatus>& result) {
294 m_status = result;
295 onSuccess();
296 },
297 onFailure, options);
298}
299
300void
301FaceModule::formatStatusXml(std::ostream& os) const
302{
303 os << "<faces>";
304 for (const FaceStatus& item : m_status) {
305 this->formatItemXml(os, item);
306 }
307 os << "</faces>";
308}
309
310void
311FaceModule::formatItemXml(std::ostream& os, const FaceStatus& item) const
312{
313 os << "<face>";
314
315 os << "<faceId>" << item.getFaceId() << "</faceId>";
316 os << "<remoteUri>" << xml::Text{item.getRemoteUri()} << "</remoteUri>";
317 os << "<localUri>" << xml::Text{item.getLocalUri()} << "</localUri>";
318
319 if (item.hasExpirationPeriod()) {
320 os << "<expirationPeriod>" << xml::formatDuration(item.getExpirationPeriod())
321 << "</expirationPeriod>";
322 }
323 os << "<faceScope>" << item.getFaceScope() << "</faceScope>";
324 os << "<facePersistency>" << item.getFacePersistency() << "</facePersistency>";
325 os << "<linkType>" << item.getLinkType() << "</linkType>";
326
Eric Newberry6d932e82016-11-24 05:05:43 +0000327 if (item.getFlags() == 0) {
328 os << "<flags/>";
329 }
330 else {
331 os << "<flags>";
332 if (item.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)) {
333 os << "<localFieldsEnabled/>";
334 }
335 os << "</flags>";
336 }
337
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000338 os << "<packetCounters>";
339 os << "<incomingPackets>"
340 << "<nInterests>" << item.getNInInterests() << "</nInterests>"
Junxiao Shif03d4792017-04-06 16:41:22 +0000341 << "<nData>" << item.getNInData() << "</nData>"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000342 << "<nNacks>" << item.getNInNacks() << "</nNacks>"
343 << "</incomingPackets>";
344 os << "<outgoingPackets>"
345 << "<nInterests>" << item.getNOutInterests() << "</nInterests>"
Junxiao Shif03d4792017-04-06 16:41:22 +0000346 << "<nData>" << item.getNOutData() << "</nData>"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000347 << "<nNacks>" << item.getNOutNacks() << "</nNacks>"
348 << "</outgoingPackets>";
349 os << "</packetCounters>";
350
351 os << "<byteCounters>";
352 os << "<incomingBytes>" << item.getNInBytes() << "</incomingBytes>";
353 os << "<outgoingBytes>" << item.getNOutBytes() << "</outgoingBytes>";
354 os << "</byteCounters>";
355
356 os << "</face>";
357}
358
359void
360FaceModule::formatStatusText(std::ostream& os) const
361{
362 os << "Faces:\n";
363 for (const FaceStatus& item : m_status) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000364 os << " ";
365 formatItemText(os, item, false);
366 os << '\n';
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000367 }
368}
369
370void
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000371FaceModule::formatItemText(std::ostream& os, const FaceStatus& item, bool wantMultiLine)
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000372{
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000373 text::ItemAttributes ia(wantMultiLine, 8);
374
375 os << ia("faceid") << item.getFaceId();
376 os << ia("remote") << item.getRemoteUri();
377 os << ia("local") << item.getLocalUri();
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000378
379 if (item.hasExpirationPeriod()) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000380 os << ia("expires") << text::formatDuration(item.getExpirationPeriod());
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000381 }
382
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000383 os << ia("counters")
384 << "{in={"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000385 << item.getNInInterests() << "i "
Junxiao Shif03d4792017-04-06 16:41:22 +0000386 << item.getNInData() << "d "
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000387 << item.getNInNacks() << "n "
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000388 << item.getNInBytes() << "B} "
389 << "out={"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000390 << item.getNOutInterests() << "i "
Junxiao Shif03d4792017-04-06 16:41:22 +0000391 << item.getNOutData() << "d "
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000392 << item.getNOutNacks() << "n "
393 << item.getNOutBytes() << "B}}";
394
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000395 os << ia("flags") << '{';
396 text::Separator flagSep("", " ");
397 os << flagSep << item.getFaceScope();
398 os << flagSep << item.getFacePersistency();
399 os << flagSep << item.getLinkType();
Eric Newberry6d932e82016-11-24 05:05:43 +0000400 if (item.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000401 os << flagSep << "local-fields";
Eric Newberry6d932e82016-11-24 05:05:43 +0000402 }
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000403 os << '}';
Eric Newberry6d932e82016-11-24 05:05:43 +0000404
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000405 os << ia.end();
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000406}
407
Junxiao Shi331ade72016-08-19 14:07:19 +0000408} // namespace nfdc
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000409} // namespace tools
410} // namespace nfd