blob: 857956efb0f653b0810c0f5fcfb9d4f75792f8e7 [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 Shi0d976922017-04-01 14:35:21 +0000166 << ia("remote") << canonicalRemote
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000167 << ia("persistency") << resp.getFacePersistency()
168 << '\n';
Junxiao Shi0d976922017-04-01 14:35:21 +0000169 ///\todo #3956 display local FaceUri before 'remote' field
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),
183 bind(printPositiveResult, "face-updated", _1),
184 ctx.makeCommandFailureHandler("upgrading face persistency"),
185 ctx.makeCommandOptions());
186 }
187 else {
188 // don't downgrade persistency
189 printPositiveResult("face-exists", respParams);
190 }
191 return true;
192 };
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000193
Junxiao Shi0d976922017-04-01 14:35:21 +0000194 auto doCreateFace = [&] {
195 ControlParameters params;
196 params.setUri(canonicalRemote.toString());
197 if (canonicalLocal) {
198 params.setLocalUri(canonicalLocal->toString());
199 }
200 params.setFacePersistency(persistency);
201
202 ctx.controller.start<ndn::nfd::FaceCreateCommand>(
203 params,
204 bind(printPositiveResult, "face-created", _1),
205 [&] (const ControlResponse& resp) {
206 if (resp.getCode() == 409 && handle409(resp)) {
207 return;
208 }
209 ctx.makeCommandFailureHandler("creating face")(resp); // invoke general error handler
210 },
211 ctx.makeCommandOptions());
212 };
213
214 remoteUri.canonize(
215 [&] (const FaceUri& canonicalUri) {
216 canonicalRemote = canonicalUri;
217 if (localUri) {
218 localUri->canonize(
219 [&] (const FaceUri& canonicalUri) {
220 canonicalLocal = canonicalUri;
221 doCreateFace();
222 },
223 bind(handleCanonizeError, *localUri, _1),
224 ctx.face.getIoService(), ctx.getTimeout());
225 }
226 else {
227 doCreateFace();
228 }
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000229 },
Junxiao Shi0d976922017-04-01 14:35:21 +0000230 bind(handleCanonizeError, remoteUri, _1),
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000231 ctx.face.getIoService(), ctx.getTimeout());
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000232
233 ctx.face.processEvents();
234}
235
236void
Junxiao Shi05dd4442017-02-06 22:50:07 +0000237FaceModule::destroy(ExecuteContext& ctx)
238{
Junxiao Shi918e5d42017-02-25 03:58:21 +0000239 const boost::any& faceIdOrUri = ctx.args.at("face");
Junxiao Shi05dd4442017-02-06 22:50:07 +0000240
241 FindFace findFace(ctx);
Junxiao Shi918e5d42017-02-25 03:58:21 +0000242 FindFace::Code res = findFace.execute(faceIdOrUri);
Junxiao Shi05dd4442017-02-06 22:50:07 +0000243
244 ctx.exitCode = static_cast<int>(res);
245 switch (res) {
246 case FindFace::Code::OK:
247 break;
248 case FindFace::Code::ERROR:
249 case FindFace::Code::CANONIZE_ERROR:
250 case FindFace::Code::NOT_FOUND:
251 ctx.err << findFace.getErrorReason() << '\n';
252 return;
253 case FindFace::Code::AMBIGUOUS:
254 ctx.err << "Multiple faces match specified remote FaceUri. Re-run the command with a FaceId:";
255 findFace.printDisambiguation(ctx.err, FindFace::DisambiguationStyle::LOCAL_URI);
256 ctx.err << '\n';
257 return;
258 default:
259 BOOST_ASSERT_MSG(false, "unexpected FindFace result");
260 return;
261 }
262
263 const FaceStatus& face = findFace.getFaceStatus();
264
265 ctx.controller.start<ndn::nfd::FaceDestroyCommand>(
266 ControlParameters().setFaceId(face.getFaceId()),
267 [&] (const ControlParameters& resp) {
268 ctx.out << "face-destroyed ";
269 text::ItemAttributes ia;
270 ctx.out << ia("id") << face.getFaceId()
271 << ia("local") << face.getLocalUri()
272 << ia("remote") << face.getRemoteUri()
273 << ia("persistency") << face.getFacePersistency() << '\n';
274 },
275 ctx.makeCommandFailureHandler("destroying face"),
276 ctx.makeCommandOptions());
277
278 ctx.face.processEvents();
279}
280
281void
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000282FaceModule::fetchStatus(Controller& controller,
283 const function<void()>& onSuccess,
Junxiao Shi29b41282016-08-22 03:47:02 +0000284 const Controller::DatasetFailCallback& onFailure,
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000285 const CommandOptions& options)
286{
287 controller.fetch<ndn::nfd::FaceDataset>(
288 [this, onSuccess] (const std::vector<FaceStatus>& result) {
289 m_status = result;
290 onSuccess();
291 },
292 onFailure, options);
293}
294
295void
296FaceModule::formatStatusXml(std::ostream& os) const
297{
298 os << "<faces>";
299 for (const FaceStatus& item : m_status) {
300 this->formatItemXml(os, item);
301 }
302 os << "</faces>";
303}
304
305void
306FaceModule::formatItemXml(std::ostream& os, const FaceStatus& item) const
307{
308 os << "<face>";
309
310 os << "<faceId>" << item.getFaceId() << "</faceId>";
311 os << "<remoteUri>" << xml::Text{item.getRemoteUri()} << "</remoteUri>";
312 os << "<localUri>" << xml::Text{item.getLocalUri()} << "</localUri>";
313
314 if (item.hasExpirationPeriod()) {
315 os << "<expirationPeriod>" << xml::formatDuration(item.getExpirationPeriod())
316 << "</expirationPeriod>";
317 }
318 os << "<faceScope>" << item.getFaceScope() << "</faceScope>";
319 os << "<facePersistency>" << item.getFacePersistency() << "</facePersistency>";
320 os << "<linkType>" << item.getLinkType() << "</linkType>";
321
Eric Newberry6d932e82016-11-24 05:05:43 +0000322 if (item.getFlags() == 0) {
323 os << "<flags/>";
324 }
325 else {
326 os << "<flags>";
327 if (item.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)) {
328 os << "<localFieldsEnabled/>";
329 }
330 os << "</flags>";
331 }
332
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000333 os << "<packetCounters>";
334 os << "<incomingPackets>"
335 << "<nInterests>" << item.getNInInterests() << "</nInterests>"
Junxiao Shif03d4792017-04-06 16:41:22 +0000336 << "<nData>" << item.getNInData() << "</nData>"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000337 << "<nNacks>" << item.getNInNacks() << "</nNacks>"
338 << "</incomingPackets>";
339 os << "<outgoingPackets>"
340 << "<nInterests>" << item.getNOutInterests() << "</nInterests>"
Junxiao Shif03d4792017-04-06 16:41:22 +0000341 << "<nData>" << item.getNOutData() << "</nData>"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000342 << "<nNacks>" << item.getNOutNacks() << "</nNacks>"
343 << "</outgoingPackets>";
344 os << "</packetCounters>";
345
346 os << "<byteCounters>";
347 os << "<incomingBytes>" << item.getNInBytes() << "</incomingBytes>";
348 os << "<outgoingBytes>" << item.getNOutBytes() << "</outgoingBytes>";
349 os << "</byteCounters>";
350
351 os << "</face>";
352}
353
354void
355FaceModule::formatStatusText(std::ostream& os) const
356{
357 os << "Faces:\n";
358 for (const FaceStatus& item : m_status) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000359 os << " ";
360 formatItemText(os, item, false);
361 os << '\n';
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000362 }
363}
364
365void
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000366FaceModule::formatItemText(std::ostream& os, const FaceStatus& item, bool wantMultiLine)
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000367{
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000368 text::ItemAttributes ia(wantMultiLine, 8);
369
370 os << ia("faceid") << item.getFaceId();
371 os << ia("remote") << item.getRemoteUri();
372 os << ia("local") << item.getLocalUri();
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000373
374 if (item.hasExpirationPeriod()) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000375 os << ia("expires") << text::formatDuration(item.getExpirationPeriod());
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000376 }
377
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000378 os << ia("counters")
379 << "{in={"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000380 << item.getNInInterests() << "i "
Junxiao Shif03d4792017-04-06 16:41:22 +0000381 << item.getNInData() << "d "
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000382 << item.getNInNacks() << "n "
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000383 << item.getNInBytes() << "B} "
384 << "out={"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000385 << item.getNOutInterests() << "i "
Junxiao Shif03d4792017-04-06 16:41:22 +0000386 << item.getNOutData() << "d "
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000387 << item.getNOutNacks() << "n "
388 << item.getNOutBytes() << "B}}";
389
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000390 os << ia("flags") << '{';
391 text::Separator flagSep("", " ");
392 os << flagSep << item.getFaceScope();
393 os << flagSep << item.getFacePersistency();
394 os << flagSep << item.getLinkType();
Eric Newberry6d932e82016-11-24 05:05:43 +0000395 if (item.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000396 os << flagSep << "local-fields";
Eric Newberry6d932e82016-11-24 05:05:43 +0000397 }
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000398 os << '}';
Eric Newberry6d932e82016-11-24 05:05:43 +0000399
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000400 os << ia.end();
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000401}
402
Junxiao Shi331ade72016-08-19 14:07:19 +0000403} // namespace nfdc
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000404} // namespace tools
405} // namespace nfd