blob: 216ded65498763cc6e490e53424cd3de978cd159 [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)
55 .addArg("persistency", ArgValueType::FACE_PERSISTENCY, Required::NO, Positional::YES);
56 parser.addCommand(defFaceCreate, &FaceModule::create);
Junxiao Shi05dd4442017-02-06 22:50:07 +000057
58 CommandDefinition defFaceDestroy("face", "destroy");
59 defFaceDestroy
60 .setTitle("destroy a face")
61 .addArg("face", ArgValueType::FACE_ID_OR_URI, Required::YES, Positional::YES);
62 parser.addCommand(defFaceDestroy, &FaceModule::destroy);
Junxiao Shi1f481fa2017-01-26 15:14:43 +000063}
64
65void
Junxiao Shi36e54292017-02-17 18:43:16 +000066FaceModule::list(ExecuteContext& ctx)
67{
68 auto remoteUri = ctx.args.getOptional<FaceUri>("remote");
69 auto localUri = ctx.args.getOptional<FaceUri>("local");
70 auto uriScheme = ctx.args.getOptional<std::string>("scheme");
71
72 FaceQueryFilter filter;
73 if (remoteUri) {
74 filter.setRemoteUri(remoteUri->toString());
75 }
76 if (localUri) {
77 filter.setLocalUri(localUri->toString());
78 }
79 if (uriScheme) {
80 filter.setUriScheme(*uriScheme);
81 }
82
83 FindFace findFace(ctx);
84 FindFace::Code res = findFace.execute(filter, true);
85
86 ctx.exitCode = static_cast<int>(res);
87 switch (res) {
88 case FindFace::Code::OK:
89 for (const FaceStatus& item : findFace.getResults()) {
90 formatItemText(ctx.out, item, false);
91 ctx.out << '\n';
92 }
93 break;
94 case FindFace::Code::ERROR:
95 case FindFace::Code::NOT_FOUND:
96 case FindFace::Code::CANONIZE_ERROR:
97 ctx.err << findFace.getErrorReason() << '\n';
98 break;
99 default:
100 BOOST_ASSERT_MSG(false, "unexpected FindFace result");
101 break;
102 }
103}
104
105void
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000106FaceModule::show(ExecuteContext& ctx)
107{
108 uint64_t faceId = ctx.args.get<uint64_t>("id");
109
Junxiao Shi8f803f22017-02-10 03:04:28 +0000110 FindFace findFace(ctx);
111 FindFace::Code res = findFace.execute(faceId);
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000112
Junxiao Shi8f803f22017-02-10 03:04:28 +0000113 ctx.exitCode = static_cast<int>(res);
114 switch (res) {
115 case FindFace::Code::OK:
116 formatItemText(ctx.out, findFace.getFaceStatus(), true);
117 break;
118 case FindFace::Code::ERROR:
119 case FindFace::Code::NOT_FOUND:
120 ctx.err << findFace.getErrorReason() << '\n';
121 break;
122 default:
123 BOOST_ASSERT_MSG(false, "unexpected FindFace result");
124 break;
125 }
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000126}
127
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000128/** \brief order persistency in NONE < ON_DEMAND < PERSISTENCY < PERMANENT
129 */
130static bool
131persistencyLessThan(FacePersistency x, FacePersistency y)
132{
133 switch (x) {
134 case FacePersistency::FACE_PERSISTENCY_NONE:
135 return y != FacePersistency::FACE_PERSISTENCY_NONE;
136 case FacePersistency::FACE_PERSISTENCY_ON_DEMAND:
137 return y == FacePersistency::FACE_PERSISTENCY_PERSISTENT ||
138 y == FacePersistency::FACE_PERSISTENCY_PERMANENT;
139 case FacePersistency::FACE_PERSISTENCY_PERSISTENT:
140 return y == FacePersistency::FACE_PERSISTENCY_PERMANENT;
141 case FacePersistency::FACE_PERSISTENCY_PERMANENT:
142 return false;
143 }
144 return static_cast<int>(x) < static_cast<int>(y);
145}
146
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000147void
148FaceModule::create(ExecuteContext& ctx)
149{
150 auto faceUri = ctx.args.get<FaceUri>("remote");
151 auto persistency = ctx.args.get<FacePersistency>("persistency", FacePersistency::FACE_PERSISTENCY_PERSISTENT);
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000152 FaceUri canonicalUri;
153
154 auto printPositiveResult = [&] (const std::string& actionSummary, const ControlParameters& resp) {
155 text::ItemAttributes ia;
156 ctx.out << actionSummary << ' '
157 << ia("id") << resp.getFaceId()
158 << ia("remote") << canonicalUri
159 << ia("persistency") << resp.getFacePersistency()
160 << '\n';
161 ///\todo #3956 display local=localUri before 'remote' field
162 };
163
164 auto handle409 = [&] (const ControlResponse& resp) {
165 ControlParameters respParams(resp.getBody());
166 if (respParams.getUri() != canonicalUri.toString()) {
167 // we are conflicting with a different face, which is a general error
168 return false;
169 }
170
171 if (persistencyLessThan(respParams.getFacePersistency(), persistency)) {
172 // need to upgrade persistency
173 ctx.controller.start<ndn::nfd::FaceUpdateCommand>(
174 ControlParameters().setFaceId(respParams.getFaceId()).setFacePersistency(persistency),
175 bind(printPositiveResult, "face-updated", _1),
176 ctx.makeCommandFailureHandler("upgrading face persistency"),
177 ctx.makeCommandOptions());
178 }
179 else {
180 // don't downgrade persistency
181 printPositiveResult("face-exists", respParams);
182 }
183 return true;
184 };
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000185
186 faceUri.canonize(
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000187 [&] (const FaceUri& canonicalUri1) {
188 canonicalUri = canonicalUri1;
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000189 ctx.controller.start<ndn::nfd::FaceCreateCommand>(
190 ControlParameters().setUri(canonicalUri.toString()).setFacePersistency(persistency),
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000191 bind(printPositiveResult, "face-created", _1),
192 [&] (const ControlResponse& resp) {
193 if (resp.getCode() == 409 && handle409(resp)) {
194 return;
195 }
196 ctx.makeCommandFailureHandler("creating face")(resp); // invoke general error handler
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000197 },
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000198 ctx.makeCommandOptions());
199 },
200 [&] (const std::string& canonizeError) {
201 ctx.exitCode = 4;
202 ctx.err << "Error when canonizing FaceUri: " << canonizeError << '\n';
203 },
204 ctx.face.getIoService(), ctx.getTimeout());
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000205
206 ctx.face.processEvents();
207}
208
209void
Junxiao Shi05dd4442017-02-06 22:50:07 +0000210FaceModule::destroy(ExecuteContext& ctx)
211{
212 const boost::any faceIdOrUri = ctx.args.at("face");
213
214 FindFace findFace(ctx);
215 FindFace::Code res = FindFace::Code::ERROR;
216 const uint64_t* faceId = boost::any_cast<uint64_t>(&faceIdOrUri);
217 if (faceId != nullptr) {
218 res = findFace.execute(*faceId);
219 }
220 else {
221 res = findFace.execute(boost::any_cast<FaceUri>(faceIdOrUri));
222 }
223
224 ctx.exitCode = static_cast<int>(res);
225 switch (res) {
226 case FindFace::Code::OK:
227 break;
228 case FindFace::Code::ERROR:
229 case FindFace::Code::CANONIZE_ERROR:
230 case FindFace::Code::NOT_FOUND:
231 ctx.err << findFace.getErrorReason() << '\n';
232 return;
233 case FindFace::Code::AMBIGUOUS:
234 ctx.err << "Multiple faces match specified remote FaceUri. Re-run the command with a FaceId:";
235 findFace.printDisambiguation(ctx.err, FindFace::DisambiguationStyle::LOCAL_URI);
236 ctx.err << '\n';
237 return;
238 default:
239 BOOST_ASSERT_MSG(false, "unexpected FindFace result");
240 return;
241 }
242
243 const FaceStatus& face = findFace.getFaceStatus();
244
245 ctx.controller.start<ndn::nfd::FaceDestroyCommand>(
246 ControlParameters().setFaceId(face.getFaceId()),
247 [&] (const ControlParameters& resp) {
248 ctx.out << "face-destroyed ";
249 text::ItemAttributes ia;
250 ctx.out << ia("id") << face.getFaceId()
251 << ia("local") << face.getLocalUri()
252 << ia("remote") << face.getRemoteUri()
253 << ia("persistency") << face.getFacePersistency() << '\n';
254 },
255 ctx.makeCommandFailureHandler("destroying face"),
256 ctx.makeCommandOptions());
257
258 ctx.face.processEvents();
259}
260
261void
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000262FaceModule::fetchStatus(Controller& controller,
263 const function<void()>& onSuccess,
Junxiao Shi29b41282016-08-22 03:47:02 +0000264 const Controller::DatasetFailCallback& onFailure,
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000265 const CommandOptions& options)
266{
267 controller.fetch<ndn::nfd::FaceDataset>(
268 [this, onSuccess] (const std::vector<FaceStatus>& result) {
269 m_status = result;
270 onSuccess();
271 },
272 onFailure, options);
273}
274
275void
276FaceModule::formatStatusXml(std::ostream& os) const
277{
278 os << "<faces>";
279 for (const FaceStatus& item : m_status) {
280 this->formatItemXml(os, item);
281 }
282 os << "</faces>";
283}
284
285void
286FaceModule::formatItemXml(std::ostream& os, const FaceStatus& item) const
287{
288 os << "<face>";
289
290 os << "<faceId>" << item.getFaceId() << "</faceId>";
291 os << "<remoteUri>" << xml::Text{item.getRemoteUri()} << "</remoteUri>";
292 os << "<localUri>" << xml::Text{item.getLocalUri()} << "</localUri>";
293
294 if (item.hasExpirationPeriod()) {
295 os << "<expirationPeriod>" << xml::formatDuration(item.getExpirationPeriod())
296 << "</expirationPeriod>";
297 }
298 os << "<faceScope>" << item.getFaceScope() << "</faceScope>";
299 os << "<facePersistency>" << item.getFacePersistency() << "</facePersistency>";
300 os << "<linkType>" << item.getLinkType() << "</linkType>";
301
Eric Newberry6d932e82016-11-24 05:05:43 +0000302 if (item.getFlags() == 0) {
303 os << "<flags/>";
304 }
305 else {
306 os << "<flags>";
307 if (item.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)) {
308 os << "<localFieldsEnabled/>";
309 }
310 os << "</flags>";
311 }
312
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000313 os << "<packetCounters>";
314 os << "<incomingPackets>"
315 << "<nInterests>" << item.getNInInterests() << "</nInterests>"
316 << "<nDatas>" << item.getNInDatas() << "</nDatas>"
317 << "<nNacks>" << item.getNInNacks() << "</nNacks>"
318 << "</incomingPackets>";
319 os << "<outgoingPackets>"
320 << "<nInterests>" << item.getNOutInterests() << "</nInterests>"
321 << "<nDatas>" << item.getNOutDatas() << "</nDatas>"
322 << "<nNacks>" << item.getNOutNacks() << "</nNacks>"
323 << "</outgoingPackets>";
324 os << "</packetCounters>";
325
326 os << "<byteCounters>";
327 os << "<incomingBytes>" << item.getNInBytes() << "</incomingBytes>";
328 os << "<outgoingBytes>" << item.getNOutBytes() << "</outgoingBytes>";
329 os << "</byteCounters>";
330
331 os << "</face>";
332}
333
334void
335FaceModule::formatStatusText(std::ostream& os) const
336{
337 os << "Faces:\n";
338 for (const FaceStatus& item : m_status) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000339 os << " ";
340 formatItemText(os, item, false);
341 os << '\n';
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000342 }
343}
344
345void
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000346FaceModule::formatItemText(std::ostream& os, const FaceStatus& item, bool wantMultiLine)
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000347{
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000348 text::ItemAttributes ia(wantMultiLine, 8);
349
350 os << ia("faceid") << item.getFaceId();
351 os << ia("remote") << item.getRemoteUri();
352 os << ia("local") << item.getLocalUri();
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000353
354 if (item.hasExpirationPeriod()) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000355 os << ia("expires") << text::formatDuration(item.getExpirationPeriod());
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000356 }
357
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000358 os << ia("counters")
359 << "{in={"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000360 << item.getNInInterests() << "i "
361 << item.getNInDatas() << "d "
362 << item.getNInNacks() << "n "
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000363 << item.getNInBytes() << "B} "
364 << "out={"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000365 << item.getNOutInterests() << "i "
366 << item.getNOutDatas() << "d "
367 << item.getNOutNacks() << "n "
368 << item.getNOutBytes() << "B}}";
369
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000370 os << ia("flags") << '{';
371 text::Separator flagSep("", " ");
372 os << flagSep << item.getFaceScope();
373 os << flagSep << item.getFacePersistency();
374 os << flagSep << item.getLinkType();
Eric Newberry6d932e82016-11-24 05:05:43 +0000375 if (item.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000376 os << flagSep << "local-fields";
Eric Newberry6d932e82016-11-24 05:05:43 +0000377 }
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000378 os << '}';
Eric Newberry6d932e82016-11-24 05:05:43 +0000379
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000380 os << ia.end();
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000381}
382
Junxiao Shi331ade72016-08-19 14:07:19 +0000383} // namespace nfdc
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000384} // namespace tools
385} // namespace nfd