blob: f0c9dfc7f985e5056e5d27d52161fe558ac54c4d [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{
Junxiao Shi918e5d42017-02-25 03:58:21 +0000212 const boost::any& faceIdOrUri = ctx.args.at("face");
Junxiao Shi05dd4442017-02-06 22:50:07 +0000213
214 FindFace findFace(ctx);
Junxiao Shi918e5d42017-02-25 03:58:21 +0000215 FindFace::Code res = findFace.execute(faceIdOrUri);
Junxiao Shi05dd4442017-02-06 22:50:07 +0000216
217 ctx.exitCode = static_cast<int>(res);
218 switch (res) {
219 case FindFace::Code::OK:
220 break;
221 case FindFace::Code::ERROR:
222 case FindFace::Code::CANONIZE_ERROR:
223 case FindFace::Code::NOT_FOUND:
224 ctx.err << findFace.getErrorReason() << '\n';
225 return;
226 case FindFace::Code::AMBIGUOUS:
227 ctx.err << "Multiple faces match specified remote FaceUri. Re-run the command with a FaceId:";
228 findFace.printDisambiguation(ctx.err, FindFace::DisambiguationStyle::LOCAL_URI);
229 ctx.err << '\n';
230 return;
231 default:
232 BOOST_ASSERT_MSG(false, "unexpected FindFace result");
233 return;
234 }
235
236 const FaceStatus& face = findFace.getFaceStatus();
237
238 ctx.controller.start<ndn::nfd::FaceDestroyCommand>(
239 ControlParameters().setFaceId(face.getFaceId()),
240 [&] (const ControlParameters& resp) {
241 ctx.out << "face-destroyed ";
242 text::ItemAttributes ia;
243 ctx.out << ia("id") << face.getFaceId()
244 << ia("local") << face.getLocalUri()
245 << ia("remote") << face.getRemoteUri()
246 << ia("persistency") << face.getFacePersistency() << '\n';
247 },
248 ctx.makeCommandFailureHandler("destroying face"),
249 ctx.makeCommandOptions());
250
251 ctx.face.processEvents();
252}
253
254void
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000255FaceModule::fetchStatus(Controller& controller,
256 const function<void()>& onSuccess,
Junxiao Shi29b41282016-08-22 03:47:02 +0000257 const Controller::DatasetFailCallback& onFailure,
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000258 const CommandOptions& options)
259{
260 controller.fetch<ndn::nfd::FaceDataset>(
261 [this, onSuccess] (const std::vector<FaceStatus>& result) {
262 m_status = result;
263 onSuccess();
264 },
265 onFailure, options);
266}
267
268void
269FaceModule::formatStatusXml(std::ostream& os) const
270{
271 os << "<faces>";
272 for (const FaceStatus& item : m_status) {
273 this->formatItemXml(os, item);
274 }
275 os << "</faces>";
276}
277
278void
279FaceModule::formatItemXml(std::ostream& os, const FaceStatus& item) const
280{
281 os << "<face>";
282
283 os << "<faceId>" << item.getFaceId() << "</faceId>";
284 os << "<remoteUri>" << xml::Text{item.getRemoteUri()} << "</remoteUri>";
285 os << "<localUri>" << xml::Text{item.getLocalUri()} << "</localUri>";
286
287 if (item.hasExpirationPeriod()) {
288 os << "<expirationPeriod>" << xml::formatDuration(item.getExpirationPeriod())
289 << "</expirationPeriod>";
290 }
291 os << "<faceScope>" << item.getFaceScope() << "</faceScope>";
292 os << "<facePersistency>" << item.getFacePersistency() << "</facePersistency>";
293 os << "<linkType>" << item.getLinkType() << "</linkType>";
294
Eric Newberry6d932e82016-11-24 05:05:43 +0000295 if (item.getFlags() == 0) {
296 os << "<flags/>";
297 }
298 else {
299 os << "<flags>";
300 if (item.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)) {
301 os << "<localFieldsEnabled/>";
302 }
303 os << "</flags>";
304 }
305
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000306 os << "<packetCounters>";
307 os << "<incomingPackets>"
308 << "<nInterests>" << item.getNInInterests() << "</nInterests>"
309 << "<nDatas>" << item.getNInDatas() << "</nDatas>"
310 << "<nNacks>" << item.getNInNacks() << "</nNacks>"
311 << "</incomingPackets>";
312 os << "<outgoingPackets>"
313 << "<nInterests>" << item.getNOutInterests() << "</nInterests>"
314 << "<nDatas>" << item.getNOutDatas() << "</nDatas>"
315 << "<nNacks>" << item.getNOutNacks() << "</nNacks>"
316 << "</outgoingPackets>";
317 os << "</packetCounters>";
318
319 os << "<byteCounters>";
320 os << "<incomingBytes>" << item.getNInBytes() << "</incomingBytes>";
321 os << "<outgoingBytes>" << item.getNOutBytes() << "</outgoingBytes>";
322 os << "</byteCounters>";
323
324 os << "</face>";
325}
326
327void
328FaceModule::formatStatusText(std::ostream& os) const
329{
330 os << "Faces:\n";
331 for (const FaceStatus& item : m_status) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000332 os << " ";
333 formatItemText(os, item, false);
334 os << '\n';
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000335 }
336}
337
338void
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000339FaceModule::formatItemText(std::ostream& os, const FaceStatus& item, bool wantMultiLine)
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000340{
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000341 text::ItemAttributes ia(wantMultiLine, 8);
342
343 os << ia("faceid") << item.getFaceId();
344 os << ia("remote") << item.getRemoteUri();
345 os << ia("local") << item.getLocalUri();
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000346
347 if (item.hasExpirationPeriod()) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000348 os << ia("expires") << text::formatDuration(item.getExpirationPeriod());
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000349 }
350
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000351 os << ia("counters")
352 << "{in={"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000353 << item.getNInInterests() << "i "
354 << item.getNInDatas() << "d "
355 << item.getNInNacks() << "n "
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000356 << item.getNInBytes() << "B} "
357 << "out={"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000358 << item.getNOutInterests() << "i "
359 << item.getNOutDatas() << "d "
360 << item.getNOutNacks() << "n "
361 << item.getNOutBytes() << "B}}";
362
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000363 os << ia("flags") << '{';
364 text::Separator flagSep("", " ");
365 os << flagSep << item.getFaceScope();
366 os << flagSep << item.getFacePersistency();
367 os << flagSep << item.getLinkType();
Eric Newberry6d932e82016-11-24 05:05:43 +0000368 if (item.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000369 os << flagSep << "local-fields";
Eric Newberry6d932e82016-11-24 05:05:43 +0000370 }
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000371 os << '}';
Eric Newberry6d932e82016-11-24 05:05:43 +0000372
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000373 os << ia.end();
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000374}
375
Junxiao Shi331ade72016-08-19 14:07:19 +0000376} // namespace nfdc
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000377} // namespace tools
378} // namespace nfd