blob: 207d3eeec92c5813b0d99b7a7e1bfd7c2697a4ab [file] [log] [blame]
hilata198cadb2014-02-15 23:46:19 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev7c10b3b2015-01-20 12:24:27 -08003 * Copyright (c) 2014-2015, Regents of the University of California,
4 * 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.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
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/>.
Syed Obaid4ae0ce32014-06-17 13:59:20 -050024 */
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070025
hilata198cadb2014-02-15 23:46:19 -060026#include "nfdc.hpp"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070027#include "version.hpp"
28
hilata198cadb2014-02-15 23:46:19 -060029#include <boost/lexical_cast.hpp>
30#include <boost/algorithm/string.hpp>
31#include <boost/algorithm/string/regex_find_format.hpp>
32#include <boost/regex.hpp>
33
Chengyu Fan27be0b02014-11-24 20:52:53 -070034#include <ndn-cxx/management/nfd-face-query-filter.hpp>
35#include <ndn-cxx/management/nfd-face-status.hpp>
36#include <ndn-cxx/util/segment-fetcher.hpp>
37
hilata198cadb2014-02-15 23:46:19 -060038void
39usage(const char* programName)
40{
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070041 std::cout << "Usage:\n" << programName << " [-h] [-V] COMMAND [<Command Options>]\n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070042 " -h print usage and exit\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070043 " -V print version and exit\n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070044 "\n"
Obaiddca50792014-04-24 18:38:40 -050045 " COMMAND can be one of the following:\n"
Syed Obaid4ae0ce32014-06-17 13:59:20 -050046 " register [-I] [-C] [-c cost] [-e expiration time] [-o origin] name <faceId | faceUri>\n"
Obaiddca50792014-04-24 18:38:40 -050047 " register name to the given faceId or faceUri\n"
48 " -I: unset CHILD_INHERIT flag\n"
49 " -C: set CAPTURE flag\n"
Syed Obaid818e8a62014-07-02 18:24:11 -050050 " -c: specify cost (default 0)\n"
51 " -e: specify expiration time in ms\n"
52 " (by default the entry remains in FIB for the lifetime of the associated face)\n"
Syed Obaid4ae0ce32014-06-17 13:59:20 -050053 " -o: specify origin\n"
Syed Obaid818e8a62014-07-02 18:24:11 -050054 " 0 for Local producer applications, 128 for NLSR, 255(default) for static routes\n"
Chengyu Fan27be0b02014-11-24 20:52:53 -070055 " unregister [-o origin] name <faceId | faceUri>\n"
Obaiddca50792014-04-24 18:38:40 -050056 " unregister name from the given faceId\n"
57 " create <faceUri> \n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070058 " Create a face in one of the following formats:\n"
59 " UDP unicast: udp[4|6]://<remote-IP-or-host>[:<remote-port>]\n"
60 " TCP: tcp[4|6]://<remote-IP-or-host>[:<remote-port>] \n"
Obaiddca50792014-04-24 18:38:40 -050061 " destroy <faceId | faceUri> \n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070062 " Destroy a face\n"
63 " set-strategy <name> <strategy> \n"
64 " Set the strategy for a namespace \n"
65 " unset-strategy <name> \n"
66 " Unset the strategy for a namespace \n"
hilata6ee6e072014-04-20 17:10:18 -050067 " add-nexthop [-c <cost>] <name> <faceId | faceUri>\n"
68 " Add a nexthop to a FIB entry\n"
Syed Obaid818e8a62014-07-02 18:24:11 -050069 " -c: specify cost (default 0)\n"
Chengyu Fan27be0b02014-11-24 20:52:53 -070070 " remove-nexthop <name> <faceId | faceUri> \n"
hilata6ee6e072014-04-20 17:10:18 -050071 " Remove a nexthop from a FIB entry\n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070072 << std::endl;
hilata198cadb2014-02-15 23:46:19 -060073}
74
75namespace nfdc {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070076
Junxiao Shicd55cde2014-11-13 16:03:24 -070077using std::bind;
Davide Pesaventoab1e8f22014-10-21 22:45:33 +020078
Syed Obaid818e8a62014-07-02 18:24:11 -050079const ndn::time::milliseconds Nfdc::DEFAULT_EXPIRATION_PERIOD = ndn::time::milliseconds::max();
Syed Obaid4ae0ce32014-06-17 13:59:20 -050080const uint64_t Nfdc::DEFAULT_COST = 0;
81
Chengyu Fan27be0b02014-11-24 20:52:53 -070082Nfdc::FaceIdFetcher::FaceIdFetcher(ndn::Face& face,
83 Controller& controller,
84 bool allowCreate,
85 const SuccessCallback& onSucceed,
86 const FailureCallback& onFail)
87 : m_face(face)
88 , m_controller(controller)
89 , m_allowCreate(allowCreate)
90 , m_onSucceed(onSucceed)
91 , m_onFail(onFail)
92{
93}
94
95void
96Nfdc::FaceIdFetcher::start(ndn::Face& face,
97 Controller& controller,
98 const std::string& input,
99 bool allowCreate,
100 const SuccessCallback& onSucceed,
101 const FailureCallback& onFail)
102{
103 // 1. Try parse input as FaceId, if input is FaceId, succeed with parsed FaceId
104 // 2. Try parse input as FaceUri, if input is not FaceUri, fail
105 // 3. Canonize faceUri
106 // 4. If canonization fails, fail
107 // 5. Query for face
108 // 6. If query succeeds and finds a face, succeed with found FaceId
109 // 7. Create face
110 // 8. If face creation succeeds, succeed with created FaceId
111 // 9. Fail
112
113 boost::regex e("^[a-z0-9]+\\:.*");
114 if (!boost::regex_match(input, e)) {
115 try
116 {
117 u_int32_t faceId = boost::lexical_cast<uint32_t>(input);
118 onSucceed(faceId);
119 return;
120 }
121 catch (boost::bad_lexical_cast&)
122 {
123 onFail("No valid faceId or faceUri is provided");
124 return;
125 }
126 }
127 else {
128 ndn::util::FaceUri faceUri;
129 if (!faceUri.parse(input)) {
130 onFail("FaceUri parse failed");
131 return;
132 }
133
134 auto fetcher = new FaceIdFetcher(std::ref(face), std::ref(controller),
135 allowCreate, onSucceed, onFail);
136
137 fetcher->startGetFaceId(faceUri);
138 }
139}
140
141void
142Nfdc::FaceIdFetcher::startGetFaceId(const ndn::util::FaceUri& faceUri)
143{
144 faceUri.canonize(bind(&FaceIdFetcher::onCanonizeSuccess, this, _1),
145 bind(&FaceIdFetcher::onCanonizeFailure, this, _1),
146 m_face.getIoService(), ndn::time::seconds(4));
147}
148
149void
150Nfdc::FaceIdFetcher::onCanonizeSuccess(const ndn::util::FaceUri& canonicalUri)
151{
152 ndn::Name queryName("/localhost/nfd/faces/query");
153 ndn::nfd::FaceQueryFilter queryFilter;
154 queryFilter.setRemoteUri(canonicalUri.toString());
155 queryName.append(queryFilter.wireEncode());
156
157 ndn::Interest interestPacket(queryName);
158 interestPacket.setMustBeFresh(true);
159 interestPacket.setInterestLifetime(ndn::time::milliseconds(4000));
160 auto interest = std::make_shared<ndn::Interest>(interestPacket);
161
162 ndn::util::SegmentFetcher::fetch(m_face, *interest,
163 ndn::util::DontVerifySegment(),
164 bind(&FaceIdFetcher::onQuerySuccess,
165 this, _1, canonicalUri),
166 bind(&FaceIdFetcher::onQueryFailure,
167 this, _1, canonicalUri));
168}
169
170void
171Nfdc::FaceIdFetcher::onCanonizeFailure(const std::string& reason)
172{
173 fail("Canonize faceUri failed : " + reason);
174}
175
176void
177Nfdc::FaceIdFetcher::onQuerySuccess(const ndn::ConstBufferPtr& data,
178 const ndn::util::FaceUri& canonicalUri)
179{
180 size_t offset = 0;
Junxiao Shi78926c92015-02-28 22:56:06 -0700181 bool isOk = false;
Chengyu Fan27be0b02014-11-24 20:52:53 -0700182 ndn::Block block;
Junxiao Shi78926c92015-02-28 22:56:06 -0700183 std::tie(isOk, block) = ndn::Block::fromBuffer(data, offset);
Chengyu Fan27be0b02014-11-24 20:52:53 -0700184
Junxiao Shi78926c92015-02-28 22:56:06 -0700185 if (!isOk) {
Chengyu Fan27be0b02014-11-24 20:52:53 -0700186 if (m_allowCreate) {
187 startFaceCreate(canonicalUri);
188 }
189 else {
190 fail("Fail to find faceId");
191 }
192 }
193 else {
194 try {
195 FaceStatus status(block);
196 succeed(status.getFaceId());
197 }
198 catch (const ndn::tlv::Error& e) {
199 std::string errorMessage(e.what());
200 fail("ERROR: " + errorMessage);
201 }
202 }
203}
204
205void
206Nfdc::FaceIdFetcher::onQueryFailure(uint32_t errorCode,
207 const ndn::util::FaceUri& canonicalUri)
208{
209 std::stringstream ss;
210 ss << "Cannot fetch data (code " << errorCode << ")";
211 fail(ss.str());
212}
213
214void
215Nfdc::FaceIdFetcher::onFaceCreateError(uint32_t code,
216 const std::string& error,
217 const std::string& message)
218{
219 std::stringstream ss;
220 ss << message << " : " << error << " (code " << code << ")";
221 fail(ss.str());
222}
223
224void
225Nfdc::FaceIdFetcher::startFaceCreate(const ndn::util::FaceUri& canonicalUri)
226{
227 ControlParameters parameters;
228 parameters.setUri(canonicalUri.toString());
229
230 m_controller.start<FaceCreateCommand>(parameters,
231 [this] (const ControlParameters& result) {
232 succeed(result.getFaceId());
233 },
234 bind(&FaceIdFetcher::onFaceCreateError, this, _1, _2,
235 "Face creation failed"));
236}
237
238void
239Nfdc::FaceIdFetcher::succeed(uint32_t faceId)
240{
241 m_onSucceed(faceId);
242 delete this;
243}
244
245void
246Nfdc::FaceIdFetcher::fail(const std::string& reason)
247{
248 m_onFail(reason);
249 delete this;
250}
251
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700252Nfdc::Nfdc(ndn::Face& face)
Obaiddca50792014-04-24 18:38:40 -0500253 : m_flags(ROUTE_FLAG_CHILD_INHERIT)
Syed Obaid4ae0ce32014-06-17 13:59:20 -0500254 , m_cost(DEFAULT_COST)
255 , m_origin(ROUTE_ORIGIN_STATIC)
256 , m_expires(DEFAULT_EXPIRATION_PERIOD)
Chengyu Fan27be0b02014-11-24 20:52:53 -0700257 , m_face(face)
Junxiao Shi8e273ca2014-11-12 00:42:29 -0700258 , m_controller(face, m_keyChain)
Chengyu Fandae25302014-10-16 11:40:11 -0600259 , m_ioService(face.getIoService())
hilata198cadb2014-02-15 23:46:19 -0600260{
261}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700262
263Nfdc::~Nfdc()
hilata198cadb2014-02-15 23:46:19 -0600264{
265}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700266
hilata198cadb2014-02-15 23:46:19 -0600267bool
hilata54e4eaf2014-04-10 23:38:33 -0500268Nfdc::dispatch(const std::string& command)
hilata198cadb2014-02-15 23:46:19 -0600269{
Obaiddca50792014-04-24 18:38:40 -0500270 if (command == "add-nexthop") {
271 if (m_nOptions != 2)
hilata54e4eaf2014-04-10 23:38:33 -0500272 return false;
Obaiddca50792014-04-24 18:38:40 -0500273 fibAddNextHop();
hilata198cadb2014-02-15 23:46:19 -0600274 }
275 else if (command == "remove-nexthop") {
hilata54e4eaf2014-04-10 23:38:33 -0500276 if (m_nOptions != 2)
hilata198cadb2014-02-15 23:46:19 -0600277 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500278 fibRemoveNextHop();
hilata198cadb2014-02-15 23:46:19 -0600279 }
Obaiddca50792014-04-24 18:38:40 -0500280 else if (command == "register") {
281 if (m_nOptions != 2)
282 return false;
283 ribRegisterPrefix();
284 }
285 else if (command == "unregister") {
286 if (m_nOptions != 2)
287 return false;
288 ribUnregisterPrefix();
289 }
hilata198cadb2014-02-15 23:46:19 -0600290 else if (command == "create") {
hilata54e4eaf2014-04-10 23:38:33 -0500291 if (m_nOptions != 1)
hilata198cadb2014-02-15 23:46:19 -0600292 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500293 faceCreate();
hilata198cadb2014-02-15 23:46:19 -0600294 }
295 else if (command == "destroy") {
hilata54e4eaf2014-04-10 23:38:33 -0500296 if (m_nOptions != 1)
hilata198cadb2014-02-15 23:46:19 -0600297 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500298 faceDestroy();
hilata198cadb2014-02-15 23:46:19 -0600299 }
hilata141eaae2014-03-13 19:54:47 -0500300 else if (command == "set-strategy") {
hilata54e4eaf2014-04-10 23:38:33 -0500301 if (m_nOptions != 2)
hilata141eaae2014-03-13 19:54:47 -0500302 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500303 strategyChoiceSet();
hilata141eaae2014-03-13 19:54:47 -0500304 }
305 else if (command == "unset-strategy") {
hilata54e4eaf2014-04-10 23:38:33 -0500306 if (m_nOptions != 1)
hilata141eaae2014-03-13 19:54:47 -0500307 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500308 strategyChoiceUnset();
hilata141eaae2014-03-13 19:54:47 -0500309 }
hilata198cadb2014-02-15 23:46:19 -0600310 else
311 usage(m_programName);
312
313 return true;
314}
hilata198cadb2014-02-15 23:46:19 -0600315
hilata198cadb2014-02-15 23:46:19 -0600316void
Obaiddca50792014-04-24 18:38:40 -0500317Nfdc::fibAddNextHop()
hilata198cadb2014-02-15 23:46:19 -0600318{
Obaiddca50792014-04-24 18:38:40 -0500319 m_name = m_commandLineArguments[0];
Chengyu Fan27be0b02014-11-24 20:52:53 -0700320 const std::string& faceName = m_commandLineArguments[1];
hilata54e4eaf2014-04-10 23:38:33 -0500321
Chengyu Fan27be0b02014-11-24 20:52:53 -0700322 FaceIdFetcher::start(m_face, m_controller, faceName, true,
323 [this] (const uint32_t faceId) {
324 ControlParameters parameters;
325 parameters
326 .setName(m_name)
327 .setCost(m_cost)
328 .setFaceId(faceId);
hilata54e4eaf2014-04-10 23:38:33 -0500329
Chengyu Fan27be0b02014-11-24 20:52:53 -0700330 m_controller
331 .start<FibAddNextHopCommand>(parameters,
332 bind(&Nfdc::onSuccess, this, _1,
333 "Nexthop insertion succeeded"),
334 bind(&Nfdc::onError, this, _1, _2,
335 "Nexthop insertion failed"));
336 },
337 bind(&Nfdc::onObtainFaceIdFailure, this, _1));
hilata54e4eaf2014-04-10 23:38:33 -0500338}
339
340void
341Nfdc::fibRemoveNextHop()
342{
Obaiddca50792014-04-24 18:38:40 -0500343 m_name = m_commandLineArguments[0];
Chengyu Fan27be0b02014-11-24 20:52:53 -0700344 const std::string& faceName = m_commandLineArguments[1];
hilata54e4eaf2014-04-10 23:38:33 -0500345
Chengyu Fan27be0b02014-11-24 20:52:53 -0700346 FaceIdFetcher::start(m_face, m_controller, faceName, false,
347 [this] (const uint32_t faceId) {
348 ControlParameters parameters;
349 parameters
350 .setName(m_name)
351 .setFaceId(faceId);
hilata54e4eaf2014-04-10 23:38:33 -0500352
Chengyu Fan27be0b02014-11-24 20:52:53 -0700353 m_controller
354 .start<FibRemoveNextHopCommand>(parameters,
355 bind(&Nfdc::onSuccess, this, _1,
356 "Nexthop removal succeeded"),
357 bind(&Nfdc::onError, this, _1, _2,
358 "Nexthop removal failed"));
359 },
360 bind(&Nfdc::onObtainFaceIdFailure, this, _1));
Obaiddca50792014-04-24 18:38:40 -0500361}
362
363void
364Nfdc::ribRegisterPrefix()
365{
366 m_name = m_commandLineArguments[0];
Chengyu Fan27be0b02014-11-24 20:52:53 -0700367 const std::string& faceName = m_commandLineArguments[1];
Alexander Afanasyevf67cf082014-07-18 16:47:29 -0700368
Chengyu Fan27be0b02014-11-24 20:52:53 -0700369 FaceIdFetcher::start(m_face, m_controller, faceName, true,
370 [this] (const uint32_t faceId) {
371 ControlParameters parameters;
372 parameters
373 .setName(m_name)
374 .setCost(m_cost)
375 .setFlags(m_flags)
376 .setOrigin(m_origin)
377 .setFaceId(faceId);
Obaiddca50792014-04-24 18:38:40 -0500378
Chengyu Fan27be0b02014-11-24 20:52:53 -0700379 if (m_expires != DEFAULT_EXPIRATION_PERIOD)
380 parameters.setExpirationPeriod(m_expires);
Obaiddca50792014-04-24 18:38:40 -0500381
Chengyu Fan27be0b02014-11-24 20:52:53 -0700382 m_controller
383 .start<RibRegisterCommand>(parameters,
384 bind(&Nfdc::onSuccess, this, _1,
385 "Successful in name registration"),
386 bind(&Nfdc::onError, this, _1, _2,
387 "Failed in name registration"));
388 },
389 bind(&Nfdc::onObtainFaceIdFailure, this, _1));
Obaiddca50792014-04-24 18:38:40 -0500390}
391
392void
393Nfdc::ribUnregisterPrefix()
394{
395 m_name = m_commandLineArguments[0];
Chengyu Fan27be0b02014-11-24 20:52:53 -0700396 const std::string& faceName = m_commandLineArguments[1];
Obaiddca50792014-04-24 18:38:40 -0500397
Chengyu Fan27be0b02014-11-24 20:52:53 -0700398 FaceIdFetcher::start(m_face, m_controller, faceName, false,
399 [this] (const uint32_t faceId) {
400 ControlParameters parameters;
401 parameters
402 .setName(m_name)
403 .setFaceId(faceId)
404 .setOrigin(m_origin);
Obaiddca50792014-04-24 18:38:40 -0500405
Chengyu Fan27be0b02014-11-24 20:52:53 -0700406 m_controller
407 .start<RibUnregisterCommand>(parameters,
408 bind(&Nfdc::onSuccess, this, _1,
409 "Successful in unregistering name"),
410 bind(&Nfdc::onError, this, _1, _2,
411 "Failed in unregistering name"));
412 },
413 bind(&Nfdc::onObtainFaceIdFailure, this, _1));
hilata54e4eaf2014-04-10 23:38:33 -0500414}
415
416void
Chengyu Fandae25302014-10-16 11:40:11 -0600417Nfdc::onCanonizeFailure(const std::string& reason)
418{
Chengyu Fan50101232015-01-20 14:55:59 -0700419 throw Error(reason);
Chengyu Fandae25302014-10-16 11:40:11 -0600420}
421
422void
Chengyu Fan27be0b02014-11-24 20:52:53 -0700423Nfdc::onObtainFaceIdFailure(const std::string& message)
424{
Chengyu Fan50101232015-01-20 14:55:59 -0700425 throw Error(message);
Chengyu Fan27be0b02014-11-24 20:52:53 -0700426}
427
428void
hilata54e4eaf2014-04-10 23:38:33 -0500429Nfdc::faceCreate()
430{
Chengyu Fan27be0b02014-11-24 20:52:53 -0700431 boost::regex e("^[a-z0-9]+\\:.*");
432 if (!boost::regex_match(m_commandLineArguments[0], e))
hilata54e4eaf2014-04-10 23:38:33 -0500433 throw Error("invalid uri format");
434
Chengyu Fandae25302014-10-16 11:40:11 -0600435 ndn::util::FaceUri faceUri;
436 faceUri.parse(m_commandLineArguments[0]);
437
438 faceUri.canonize(bind(&Nfdc::startFaceCreate, this, _1),
439 bind(&Nfdc::onCanonizeFailure, this, _1),
440 m_ioService, ndn::time::seconds(4));
441}
442
443void
444Nfdc::startFaceCreate(const ndn::util::FaceUri& canonicalUri)
445{
hilata54e4eaf2014-04-10 23:38:33 -0500446 ControlParameters parameters;
Chengyu Fandae25302014-10-16 11:40:11 -0600447 parameters.setUri(canonicalUri.toString());
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700448
Obaiddca50792014-04-24 18:38:40 -0500449 m_controller.start<FaceCreateCommand>(parameters,
450 bind(&Nfdc::onSuccess, this, _1,
451 "Face creation succeeded"),
452 bind(&Nfdc::onError, this, _1, _2,
453 "Face creation failed"));
hilata198cadb2014-02-15 23:46:19 -0600454}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700455
hilata198cadb2014-02-15 23:46:19 -0600456void
hilata54e4eaf2014-04-10 23:38:33 -0500457Nfdc::faceDestroy()
hilata198cadb2014-02-15 23:46:19 -0600458{
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700459 ControlParameters parameters;
Chengyu Fan27be0b02014-11-24 20:52:53 -0700460 const std::string& faceName = m_commandLineArguments[0];
Chengyu Fandae25302014-10-16 11:40:11 -0600461
Chengyu Fan27be0b02014-11-24 20:52:53 -0700462 FaceIdFetcher::start(m_face, m_controller, faceName, false,
463 [this] (const uint32_t faceId) {
464 ControlParameters faceParameters;
465 faceParameters.setFaceId(faceId);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700466
Chengyu Fan27be0b02014-11-24 20:52:53 -0700467 m_controller.start<FaceDestroyCommand>(faceParameters,
468 bind(&Nfdc::onSuccess, this, _1,
469 "Face destroy succeeded"),
470 bind(&Nfdc::onError, this, _1, _2,
471 "Face destroy failed"));
472 },
473 bind(&Nfdc::onObtainFaceIdFailure, this, _1));
hilata198cadb2014-02-15 23:46:19 -0600474}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700475
hilata141eaae2014-03-13 19:54:47 -0500476void
hilata54e4eaf2014-04-10 23:38:33 -0500477Nfdc::strategyChoiceSet()
hilata141eaae2014-03-13 19:54:47 -0500478{
hilata54e4eaf2014-04-10 23:38:33 -0500479 const std::string& name = m_commandLineArguments[0];
480 const std::string& strategy = m_commandLineArguments[1];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700481
482 ControlParameters parameters;
483 parameters
484 .setName(name)
485 .setStrategy(strategy);
486
Obaiddca50792014-04-24 18:38:40 -0500487 m_controller.start<StrategyChoiceSetCommand>(parameters,
488 bind(&Nfdc::onSuccess, this, _1,
489 "Successfully set strategy choice"),
490 bind(&Nfdc::onError, this, _1, _2,
491 "Failed to set strategy choice"));
hilata141eaae2014-03-13 19:54:47 -0500492}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700493
hilata141eaae2014-03-13 19:54:47 -0500494void
hilata54e4eaf2014-04-10 23:38:33 -0500495Nfdc::strategyChoiceUnset()
hilata141eaae2014-03-13 19:54:47 -0500496{
hilata54e4eaf2014-04-10 23:38:33 -0500497 const std::string& name = m_commandLineArguments[0];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700498
499 ControlParameters parameters;
Obaiddca50792014-04-24 18:38:40 -0500500 parameters.setName(name);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700501
Obaiddca50792014-04-24 18:38:40 -0500502 m_controller.start<StrategyChoiceUnsetCommand>(parameters,
503 bind(&Nfdc::onSuccess, this, _1,
504 "Successfully unset strategy choice"),
505 bind(&Nfdc::onError, this, _1, _2,
506 "Failed to unset strategy choice"));
hilata141eaae2014-03-13 19:54:47 -0500507}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700508
hilata198cadb2014-02-15 23:46:19 -0600509void
Obaiddca50792014-04-24 18:38:40 -0500510Nfdc::onSuccess(const ControlParameters& commandSuccessResult, const std::string& message)
hilata198cadb2014-02-15 23:46:19 -0600511{
Obaiddca50792014-04-24 18:38:40 -0500512 std::cout << message << ": " << commandSuccessResult << std::endl;
hilata198cadb2014-02-15 23:46:19 -0600513}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700514
hilata198cadb2014-02-15 23:46:19 -0600515void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700516Nfdc::onError(uint32_t code, const std::string& error, const std::string& message)
hilata198cadb2014-02-15 23:46:19 -0600517{
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700518 std::ostringstream os;
519 os << message << ": " << error << " (code: " << code << ")";
520 throw Error(os.str());
hilata141eaae2014-03-13 19:54:47 -0500521}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700522
hilata141eaae2014-03-13 19:54:47 -0500523} // namespace nfdc
hilata198cadb2014-02-15 23:46:19 -0600524
525int
526main(int argc, char** argv)
527{
528 ndn::Face face;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700529 nfdc::Nfdc p(face);
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800530
hilata198cadb2014-02-15 23:46:19 -0600531 p.m_programName = argv[0];
hilata54e4eaf2014-04-10 23:38:33 -0500532
Obaiddca50792014-04-24 18:38:40 -0500533 if (argc < 2) {
534 usage(p.m_programName);
535 return 0;
536 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700537
Obaiddca50792014-04-24 18:38:40 -0500538 if (!strcmp(argv[1], "-h")) {
539 usage(p.m_programName);
540 return 0;
541 }
542
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700543 if (!strcmp(argv[1], "-V")) {
544 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
545 return 0;
546 }
547
Junxiao Shi22295032014-04-29 22:57:40 -0700548 ::optind = 2; //start reading options from 2nd argument i.e. Command
Obaiddca50792014-04-24 18:38:40 -0500549 int opt;
Syed Obaid4ae0ce32014-06-17 13:59:20 -0500550 while ((opt = ::getopt(argc, argv, "ICc:e:o:")) != -1) {
Obaiddca50792014-04-24 18:38:40 -0500551 switch (opt) {
552 case 'I':
553 p.m_flags = p.m_flags & ~(nfdc::ROUTE_FLAG_CHILD_INHERIT);
554 break;
555
556 case 'C':
557 p.m_flags = p.m_flags | nfdc::ROUTE_FLAG_CAPTURE;
558 break;
559
560 case 'c':
561 try {
Syed Obaid4ae0ce32014-06-17 13:59:20 -0500562 p.m_cost = boost::lexical_cast<uint64_t>(::optarg);
Obaiddca50792014-04-24 18:38:40 -0500563 }
Junxiao Shi22295032014-04-29 22:57:40 -0700564 catch (boost::bad_lexical_cast&) {
Syed Obaid4ae0ce32014-06-17 13:59:20 -0500565 std::cerr << "Error: cost must be in unsigned integer format" << std::endl;
566 return 1;
567 }
568 break;
569
570 case 'e':
571 uint64_t expires;
572 try {
573 expires = boost::lexical_cast<uint64_t>(::optarg);
574 }
575 catch (boost::bad_lexical_cast&) {
576 std::cerr << "Error: expiration time must be in unsigned integer format" << std::endl;
577 return 1;
578 }
579 p.m_expires = ndn::time::milliseconds(expires);
580 break;
581
582 case 'o':
583 try {
584 p.m_origin = boost::lexical_cast<uint64_t>(::optarg);
585 }
586 catch (boost::bad_lexical_cast&) {
587 std::cerr << "Error: origin must be in unsigned integer format" << std::endl;
hilata198cadb2014-02-15 23:46:19 -0600588 return 1;
Obaiddca50792014-04-24 18:38:40 -0500589 }
590 break;
Junxiao Shi22295032014-04-29 22:57:40 -0700591
Obaiddca50792014-04-24 18:38:40 -0500592 default:
593 usage(p.m_programName);
594 return 1;
hilata198cadb2014-02-15 23:46:19 -0600595 }
596 }
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800597
Junxiao Shi22295032014-04-29 22:57:40 -0700598 if (argc == ::optind) {
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800599 usage(p.m_programName);
600 return 1;
601 }
602
hilata198cadb2014-02-15 23:46:19 -0600603 try {
Junxiao Shi22295032014-04-29 22:57:40 -0700604 p.m_commandLineArguments = argv + ::optind;
605 p.m_nOptions = argc - ::optind;
Obaiddca50792014-04-24 18:38:40 -0500606
607 //argv[1] points to the command, so pass it to the dispatch
608 bool isOk = p.dispatch(argv[1]);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700609 if (!isOk) {
hilata198cadb2014-02-15 23:46:19 -0600610 usage(p.m_programName);
611 return 1;
612 }
hilata198cadb2014-02-15 23:46:19 -0600613 face.processEvents();
614 }
615 catch (const std::exception& e) {
616 std::cerr << "ERROR: " << e.what() << std::endl;
617 return 2;
618 }
619 return 0;
620}