blob: 3608ac2069a170475d24e4efcdce481abe520fd4 [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{
37 CommandDefinition defFaceShow("face", "show");
38 defFaceShow
39 .setTitle("show face information")
40 .addArg("id", ArgValueType::UNSIGNED, Required::YES, Positional::YES);
41 parser.addCommand(defFaceShow, &FaceModule::show);
Junxiao Shi1d7fef52017-02-02 05:33:14 +000042
43 CommandDefinition defFaceCreate("face", "create");
44 defFaceCreate
45 .setTitle("create a face")
46 .addArg("remote", ArgValueType::FACE_URI, Required::YES, Positional::YES)
47 .addArg("persistency", ArgValueType::FACE_PERSISTENCY, Required::NO, Positional::YES);
48 parser.addCommand(defFaceCreate, &FaceModule::create);
Junxiao Shi05dd4442017-02-06 22:50:07 +000049
50 CommandDefinition defFaceDestroy("face", "destroy");
51 defFaceDestroy
52 .setTitle("destroy a face")
53 .addArg("face", ArgValueType::FACE_ID_OR_URI, Required::YES, Positional::YES);
54 parser.addCommand(defFaceDestroy, &FaceModule::destroy);
Junxiao Shi1f481fa2017-01-26 15:14:43 +000055}
56
57void
58FaceModule::show(ExecuteContext& ctx)
59{
60 uint64_t faceId = ctx.args.get<uint64_t>("id");
61
Junxiao Shi8f803f22017-02-10 03:04:28 +000062 FindFace findFace(ctx);
63 FindFace::Code res = findFace.execute(faceId);
Junxiao Shi1d7fef52017-02-02 05:33:14 +000064
Junxiao Shi8f803f22017-02-10 03:04:28 +000065 ctx.exitCode = static_cast<int>(res);
66 switch (res) {
67 case FindFace::Code::OK:
68 formatItemText(ctx.out, findFace.getFaceStatus(), true);
69 break;
70 case FindFace::Code::ERROR:
71 case FindFace::Code::NOT_FOUND:
72 ctx.err << findFace.getErrorReason() << '\n';
73 break;
74 default:
75 BOOST_ASSERT_MSG(false, "unexpected FindFace result");
76 break;
77 }
Junxiao Shi1d7fef52017-02-02 05:33:14 +000078}
79
Yanbiao Li58ba3f92017-02-15 14:27:18 +000080/** \brief order persistency in NONE < ON_DEMAND < PERSISTENCY < PERMANENT
81 */
82static bool
83persistencyLessThan(FacePersistency x, FacePersistency y)
84{
85 switch (x) {
86 case FacePersistency::FACE_PERSISTENCY_NONE:
87 return y != FacePersistency::FACE_PERSISTENCY_NONE;
88 case FacePersistency::FACE_PERSISTENCY_ON_DEMAND:
89 return y == FacePersistency::FACE_PERSISTENCY_PERSISTENT ||
90 y == FacePersistency::FACE_PERSISTENCY_PERMANENT;
91 case FacePersistency::FACE_PERSISTENCY_PERSISTENT:
92 return y == FacePersistency::FACE_PERSISTENCY_PERMANENT;
93 case FacePersistency::FACE_PERSISTENCY_PERMANENT:
94 return false;
95 }
96 return static_cast<int>(x) < static_cast<int>(y);
97}
98
Junxiao Shi1d7fef52017-02-02 05:33:14 +000099void
100FaceModule::create(ExecuteContext& ctx)
101{
102 auto faceUri = ctx.args.get<FaceUri>("remote");
103 auto persistency = ctx.args.get<FacePersistency>("persistency", FacePersistency::FACE_PERSISTENCY_PERSISTENT);
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000104 FaceUri canonicalUri;
105
106 auto printPositiveResult = [&] (const std::string& actionSummary, const ControlParameters& resp) {
107 text::ItemAttributes ia;
108 ctx.out << actionSummary << ' '
109 << ia("id") << resp.getFaceId()
110 << ia("remote") << canonicalUri
111 << ia("persistency") << resp.getFacePersistency()
112 << '\n';
113 ///\todo #3956 display local=localUri before 'remote' field
114 };
115
116 auto handle409 = [&] (const ControlResponse& resp) {
117 ControlParameters respParams(resp.getBody());
118 if (respParams.getUri() != canonicalUri.toString()) {
119 // we are conflicting with a different face, which is a general error
120 return false;
121 }
122
123 if (persistencyLessThan(respParams.getFacePersistency(), persistency)) {
124 // need to upgrade persistency
125 ctx.controller.start<ndn::nfd::FaceUpdateCommand>(
126 ControlParameters().setFaceId(respParams.getFaceId()).setFacePersistency(persistency),
127 bind(printPositiveResult, "face-updated", _1),
128 ctx.makeCommandFailureHandler("upgrading face persistency"),
129 ctx.makeCommandOptions());
130 }
131 else {
132 // don't downgrade persistency
133 printPositiveResult("face-exists", respParams);
134 }
135 return true;
136 };
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000137
138 faceUri.canonize(
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000139 [&] (const FaceUri& canonicalUri1) {
140 canonicalUri = canonicalUri1;
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000141 ctx.controller.start<ndn::nfd::FaceCreateCommand>(
142 ControlParameters().setUri(canonicalUri.toString()).setFacePersistency(persistency),
Yanbiao Li58ba3f92017-02-15 14:27:18 +0000143 bind(printPositiveResult, "face-created", _1),
144 [&] (const ControlResponse& resp) {
145 if (resp.getCode() == 409 && handle409(resp)) {
146 return;
147 }
148 ctx.makeCommandFailureHandler("creating face")(resp); // invoke general error handler
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000149 },
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000150 ctx.makeCommandOptions());
151 },
152 [&] (const std::string& canonizeError) {
153 ctx.exitCode = 4;
154 ctx.err << "Error when canonizing FaceUri: " << canonizeError << '\n';
155 },
156 ctx.face.getIoService(), ctx.getTimeout());
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000157
158 ctx.face.processEvents();
159}
160
161void
Junxiao Shi05dd4442017-02-06 22:50:07 +0000162FaceModule::destroy(ExecuteContext& ctx)
163{
164 const boost::any faceIdOrUri = ctx.args.at("face");
165
166 FindFace findFace(ctx);
167 FindFace::Code res = FindFace::Code::ERROR;
168 const uint64_t* faceId = boost::any_cast<uint64_t>(&faceIdOrUri);
169 if (faceId != nullptr) {
170 res = findFace.execute(*faceId);
171 }
172 else {
173 res = findFace.execute(boost::any_cast<FaceUri>(faceIdOrUri));
174 }
175
176 ctx.exitCode = static_cast<int>(res);
177 switch (res) {
178 case FindFace::Code::OK:
179 break;
180 case FindFace::Code::ERROR:
181 case FindFace::Code::CANONIZE_ERROR:
182 case FindFace::Code::NOT_FOUND:
183 ctx.err << findFace.getErrorReason() << '\n';
184 return;
185 case FindFace::Code::AMBIGUOUS:
186 ctx.err << "Multiple faces match specified remote FaceUri. Re-run the command with a FaceId:";
187 findFace.printDisambiguation(ctx.err, FindFace::DisambiguationStyle::LOCAL_URI);
188 ctx.err << '\n';
189 return;
190 default:
191 BOOST_ASSERT_MSG(false, "unexpected FindFace result");
192 return;
193 }
194
195 const FaceStatus& face = findFace.getFaceStatus();
196
197 ctx.controller.start<ndn::nfd::FaceDestroyCommand>(
198 ControlParameters().setFaceId(face.getFaceId()),
199 [&] (const ControlParameters& resp) {
200 ctx.out << "face-destroyed ";
201 text::ItemAttributes ia;
202 ctx.out << ia("id") << face.getFaceId()
203 << ia("local") << face.getLocalUri()
204 << ia("remote") << face.getRemoteUri()
205 << ia("persistency") << face.getFacePersistency() << '\n';
206 },
207 ctx.makeCommandFailureHandler("destroying face"),
208 ctx.makeCommandOptions());
209
210 ctx.face.processEvents();
211}
212
213void
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000214FaceModule::fetchStatus(Controller& controller,
215 const function<void()>& onSuccess,
Junxiao Shi29b41282016-08-22 03:47:02 +0000216 const Controller::DatasetFailCallback& onFailure,
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000217 const CommandOptions& options)
218{
219 controller.fetch<ndn::nfd::FaceDataset>(
220 [this, onSuccess] (const std::vector<FaceStatus>& result) {
221 m_status = result;
222 onSuccess();
223 },
224 onFailure, options);
225}
226
227void
228FaceModule::formatStatusXml(std::ostream& os) const
229{
230 os << "<faces>";
231 for (const FaceStatus& item : m_status) {
232 this->formatItemXml(os, item);
233 }
234 os << "</faces>";
235}
236
237void
238FaceModule::formatItemXml(std::ostream& os, const FaceStatus& item) const
239{
240 os << "<face>";
241
242 os << "<faceId>" << item.getFaceId() << "</faceId>";
243 os << "<remoteUri>" << xml::Text{item.getRemoteUri()} << "</remoteUri>";
244 os << "<localUri>" << xml::Text{item.getLocalUri()} << "</localUri>";
245
246 if (item.hasExpirationPeriod()) {
247 os << "<expirationPeriod>" << xml::formatDuration(item.getExpirationPeriod())
248 << "</expirationPeriod>";
249 }
250 os << "<faceScope>" << item.getFaceScope() << "</faceScope>";
251 os << "<facePersistency>" << item.getFacePersistency() << "</facePersistency>";
252 os << "<linkType>" << item.getLinkType() << "</linkType>";
253
Eric Newberry6d932e82016-11-24 05:05:43 +0000254 if (item.getFlags() == 0) {
255 os << "<flags/>";
256 }
257 else {
258 os << "<flags>";
259 if (item.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)) {
260 os << "<localFieldsEnabled/>";
261 }
262 os << "</flags>";
263 }
264
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000265 os << "<packetCounters>";
266 os << "<incomingPackets>"
267 << "<nInterests>" << item.getNInInterests() << "</nInterests>"
268 << "<nDatas>" << item.getNInDatas() << "</nDatas>"
269 << "<nNacks>" << item.getNInNacks() << "</nNacks>"
270 << "</incomingPackets>";
271 os << "<outgoingPackets>"
272 << "<nInterests>" << item.getNOutInterests() << "</nInterests>"
273 << "<nDatas>" << item.getNOutDatas() << "</nDatas>"
274 << "<nNacks>" << item.getNOutNacks() << "</nNacks>"
275 << "</outgoingPackets>";
276 os << "</packetCounters>";
277
278 os << "<byteCounters>";
279 os << "<incomingBytes>" << item.getNInBytes() << "</incomingBytes>";
280 os << "<outgoingBytes>" << item.getNOutBytes() << "</outgoingBytes>";
281 os << "</byteCounters>";
282
283 os << "</face>";
284}
285
286void
287FaceModule::formatStatusText(std::ostream& os) const
288{
289 os << "Faces:\n";
290 for (const FaceStatus& item : m_status) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000291 os << " ";
292 formatItemText(os, item, false);
293 os << '\n';
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000294 }
295}
296
297void
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000298FaceModule::formatItemText(std::ostream& os, const FaceStatus& item, bool wantMultiLine)
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000299{
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000300 text::ItemAttributes ia(wantMultiLine, 8);
301
302 os << ia("faceid") << item.getFaceId();
303 os << ia("remote") << item.getRemoteUri();
304 os << ia("local") << item.getLocalUri();
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000305
306 if (item.hasExpirationPeriod()) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000307 os << ia("expires") << text::formatDuration(item.getExpirationPeriod());
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000308 }
309
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000310 os << ia("counters")
311 << "{in={"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000312 << item.getNInInterests() << "i "
313 << item.getNInDatas() << "d "
314 << item.getNInNacks() << "n "
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000315 << item.getNInBytes() << "B} "
316 << "out={"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000317 << item.getNOutInterests() << "i "
318 << item.getNOutDatas() << "d "
319 << item.getNOutNacks() << "n "
320 << item.getNOutBytes() << "B}}";
321
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000322 os << ia("flags") << '{';
323 text::Separator flagSep("", " ");
324 os << flagSep << item.getFaceScope();
325 os << flagSep << item.getFacePersistency();
326 os << flagSep << item.getLinkType();
Eric Newberry6d932e82016-11-24 05:05:43 +0000327 if (item.getFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED)) {
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000328 os << flagSep << "local-fields";
Eric Newberry6d932e82016-11-24 05:05:43 +0000329 }
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000330 os << '}';
Eric Newberry6d932e82016-11-24 05:05:43 +0000331
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000332 os << ia.end();
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000333}
334
Junxiao Shi331ade72016-08-19 14:07:19 +0000335} // namespace nfdc
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000336} // namespace tools
337} // namespace nfd