blob: 0b5d8895297116b1bdb594d4d09abeb7fd5c2fa2 [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"
Joao Pereirac6184cd2015-09-03 15:27:29 -040057 " create [-P] <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"
Joao Pereirac6184cd2015-09-03 15:27:29 -040061 " -P: create permanent (instead of persistent) face\n"
Obaiddca50792014-04-24 18:38:40 -050062 " destroy <faceId | faceUri> \n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070063 " Destroy a face\n"
64 " set-strategy <name> <strategy> \n"
65 " Set the strategy for a namespace \n"
66 " unset-strategy <name> \n"
67 " Unset the strategy for a namespace \n"
hilata6ee6e072014-04-20 17:10:18 -050068 " add-nexthop [-c <cost>] <name> <faceId | faceUri>\n"
69 " Add a nexthop to a FIB entry\n"
Syed Obaid818e8a62014-07-02 18:24:11 -050070 " -c: specify cost (default 0)\n"
Chengyu Fan27be0b02014-11-24 20:52:53 -070071 " remove-nexthop <name> <faceId | faceUri> \n"
hilata6ee6e072014-04-20 17:10:18 -050072 " Remove a nexthop from a FIB entry\n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070073 << std::endl;
hilata198cadb2014-02-15 23:46:19 -060074}
75
76namespace nfdc {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070077
Junxiao Shicd55cde2014-11-13 16:03:24 -070078using std::bind;
Davide Pesaventoab1e8f22014-10-21 22:45:33 +020079
Syed Obaid818e8a62014-07-02 18:24:11 -050080const ndn::time::milliseconds Nfdc::DEFAULT_EXPIRATION_PERIOD = ndn::time::milliseconds::max();
Syed Obaid4ae0ce32014-06-17 13:59:20 -050081const uint64_t Nfdc::DEFAULT_COST = 0;
82
Chengyu Fan27be0b02014-11-24 20:52:53 -070083Nfdc::FaceIdFetcher::FaceIdFetcher(ndn::Face& face,
84 Controller& controller,
85 bool allowCreate,
86 const SuccessCallback& onSucceed,
87 const FailureCallback& onFail)
88 : m_face(face)
89 , m_controller(controller)
90 , m_allowCreate(allowCreate)
91 , m_onSucceed(onSucceed)
92 , m_onFail(onFail)
93{
94}
95
96void
97Nfdc::FaceIdFetcher::start(ndn::Face& face,
98 Controller& controller,
99 const std::string& input,
100 bool allowCreate,
101 const SuccessCallback& onSucceed,
102 const FailureCallback& onFail)
103{
104 // 1. Try parse input as FaceId, if input is FaceId, succeed with parsed FaceId
105 // 2. Try parse input as FaceUri, if input is not FaceUri, fail
106 // 3. Canonize faceUri
107 // 4. If canonization fails, fail
108 // 5. Query for face
109 // 6. If query succeeds and finds a face, succeed with found FaceId
110 // 7. Create face
111 // 8. If face creation succeeds, succeed with created FaceId
112 // 9. Fail
113
114 boost::regex e("^[a-z0-9]+\\:.*");
115 if (!boost::regex_match(input, e)) {
116 try
117 {
118 u_int32_t faceId = boost::lexical_cast<uint32_t>(input);
119 onSucceed(faceId);
120 return;
121 }
122 catch (boost::bad_lexical_cast&)
123 {
124 onFail("No valid faceId or faceUri is provided");
125 return;
126 }
127 }
128 else {
129 ndn::util::FaceUri faceUri;
130 if (!faceUri.parse(input)) {
131 onFail("FaceUri parse failed");
132 return;
133 }
134
135 auto fetcher = new FaceIdFetcher(std::ref(face), std::ref(controller),
136 allowCreate, onSucceed, onFail);
137
138 fetcher->startGetFaceId(faceUri);
139 }
140}
141
142void
143Nfdc::FaceIdFetcher::startGetFaceId(const ndn::util::FaceUri& faceUri)
144{
145 faceUri.canonize(bind(&FaceIdFetcher::onCanonizeSuccess, this, _1),
146 bind(&FaceIdFetcher::onCanonizeFailure, this, _1),
147 m_face.getIoService(), ndn::time::seconds(4));
148}
149
150void
151Nfdc::FaceIdFetcher::onCanonizeSuccess(const ndn::util::FaceUri& canonicalUri)
152{
153 ndn::Name queryName("/localhost/nfd/faces/query");
154 ndn::nfd::FaceQueryFilter queryFilter;
155 queryFilter.setRemoteUri(canonicalUri.toString());
156 queryName.append(queryFilter.wireEncode());
157
158 ndn::Interest interestPacket(queryName);
159 interestPacket.setMustBeFresh(true);
160 interestPacket.setInterestLifetime(ndn::time::milliseconds(4000));
161 auto interest = std::make_shared<ndn::Interest>(interestPacket);
162
163 ndn::util::SegmentFetcher::fetch(m_face, *interest,
164 ndn::util::DontVerifySegment(),
165 bind(&FaceIdFetcher::onQuerySuccess,
166 this, _1, canonicalUri),
167 bind(&FaceIdFetcher::onQueryFailure,
168 this, _1, canonicalUri));
169}
170
171void
172Nfdc::FaceIdFetcher::onCanonizeFailure(const std::string& reason)
173{
174 fail("Canonize faceUri failed : " + reason);
175}
176
177void
178Nfdc::FaceIdFetcher::onQuerySuccess(const ndn::ConstBufferPtr& data,
179 const ndn::util::FaceUri& canonicalUri)
180{
181 size_t offset = 0;
Junxiao Shi78926c92015-02-28 22:56:06 -0700182 bool isOk = false;
Chengyu Fan27be0b02014-11-24 20:52:53 -0700183 ndn::Block block;
Junxiao Shi78926c92015-02-28 22:56:06 -0700184 std::tie(isOk, block) = ndn::Block::fromBuffer(data, offset);
Chengyu Fan27be0b02014-11-24 20:52:53 -0700185
Junxiao Shi78926c92015-02-28 22:56:06 -0700186 if (!isOk) {
Chengyu Fan27be0b02014-11-24 20:52:53 -0700187 if (m_allowCreate) {
188 startFaceCreate(canonicalUri);
189 }
190 else {
191 fail("Fail to find faceId");
192 }
193 }
194 else {
195 try {
196 FaceStatus status(block);
197 succeed(status.getFaceId());
198 }
199 catch (const ndn::tlv::Error& e) {
200 std::string errorMessage(e.what());
201 fail("ERROR: " + errorMessage);
202 }
203 }
204}
205
206void
207Nfdc::FaceIdFetcher::onQueryFailure(uint32_t errorCode,
208 const ndn::util::FaceUri& canonicalUri)
209{
210 std::stringstream ss;
211 ss << "Cannot fetch data (code " << errorCode << ")";
212 fail(ss.str());
213}
214
215void
216Nfdc::FaceIdFetcher::onFaceCreateError(uint32_t code,
217 const std::string& error,
218 const std::string& message)
219{
220 std::stringstream ss;
221 ss << message << " : " << error << " (code " << code << ")";
222 fail(ss.str());
223}
224
225void
226Nfdc::FaceIdFetcher::startFaceCreate(const ndn::util::FaceUri& canonicalUri)
227{
228 ControlParameters parameters;
229 parameters.setUri(canonicalUri.toString());
230
231 m_controller.start<FaceCreateCommand>(parameters,
232 [this] (const ControlParameters& result) {
233 succeed(result.getFaceId());
234 },
235 bind(&FaceIdFetcher::onFaceCreateError, this, _1, _2,
236 "Face creation failed"));
237}
238
239void
240Nfdc::FaceIdFetcher::succeed(uint32_t faceId)
241{
242 m_onSucceed(faceId);
243 delete this;
244}
245
246void
247Nfdc::FaceIdFetcher::fail(const std::string& reason)
248{
249 m_onFail(reason);
250 delete this;
251}
252
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700253Nfdc::Nfdc(ndn::Face& face)
Obaiddca50792014-04-24 18:38:40 -0500254 : m_flags(ROUTE_FLAG_CHILD_INHERIT)
Syed Obaid4ae0ce32014-06-17 13:59:20 -0500255 , m_cost(DEFAULT_COST)
256 , m_origin(ROUTE_ORIGIN_STATIC)
257 , m_expires(DEFAULT_EXPIRATION_PERIOD)
Joao Pereirac6184cd2015-09-03 15:27:29 -0400258 , m_facePersistency(ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERSISTENT)
Chengyu Fan27be0b02014-11-24 20:52:53 -0700259 , m_face(face)
Junxiao Shi8e273ca2014-11-12 00:42:29 -0700260 , m_controller(face, m_keyChain)
Chengyu Fandae25302014-10-16 11:40:11 -0600261 , m_ioService(face.getIoService())
hilata198cadb2014-02-15 23:46:19 -0600262{
263}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700264
265Nfdc::~Nfdc()
hilata198cadb2014-02-15 23:46:19 -0600266{
267}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700268
hilata198cadb2014-02-15 23:46:19 -0600269bool
hilata54e4eaf2014-04-10 23:38:33 -0500270Nfdc::dispatch(const std::string& command)
hilata198cadb2014-02-15 23:46:19 -0600271{
Obaiddca50792014-04-24 18:38:40 -0500272 if (command == "add-nexthop") {
273 if (m_nOptions != 2)
hilata54e4eaf2014-04-10 23:38:33 -0500274 return false;
Obaiddca50792014-04-24 18:38:40 -0500275 fibAddNextHop();
hilata198cadb2014-02-15 23:46:19 -0600276 }
277 else if (command == "remove-nexthop") {
hilata54e4eaf2014-04-10 23:38:33 -0500278 if (m_nOptions != 2)
hilata198cadb2014-02-15 23:46:19 -0600279 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500280 fibRemoveNextHop();
hilata198cadb2014-02-15 23:46:19 -0600281 }
Obaiddca50792014-04-24 18:38:40 -0500282 else if (command == "register") {
283 if (m_nOptions != 2)
284 return false;
285 ribRegisterPrefix();
286 }
287 else if (command == "unregister") {
288 if (m_nOptions != 2)
289 return false;
290 ribUnregisterPrefix();
291 }
hilata198cadb2014-02-15 23:46:19 -0600292 else if (command == "create") {
hilata54e4eaf2014-04-10 23:38:33 -0500293 if (m_nOptions != 1)
hilata198cadb2014-02-15 23:46:19 -0600294 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500295 faceCreate();
hilata198cadb2014-02-15 23:46:19 -0600296 }
297 else if (command == "destroy") {
hilata54e4eaf2014-04-10 23:38:33 -0500298 if (m_nOptions != 1)
hilata198cadb2014-02-15 23:46:19 -0600299 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500300 faceDestroy();
hilata198cadb2014-02-15 23:46:19 -0600301 }
hilata141eaae2014-03-13 19:54:47 -0500302 else if (command == "set-strategy") {
hilata54e4eaf2014-04-10 23:38:33 -0500303 if (m_nOptions != 2)
hilata141eaae2014-03-13 19:54:47 -0500304 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500305 strategyChoiceSet();
hilata141eaae2014-03-13 19:54:47 -0500306 }
307 else if (command == "unset-strategy") {
hilata54e4eaf2014-04-10 23:38:33 -0500308 if (m_nOptions != 1)
hilata141eaae2014-03-13 19:54:47 -0500309 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500310 strategyChoiceUnset();
hilata141eaae2014-03-13 19:54:47 -0500311 }
hilata198cadb2014-02-15 23:46:19 -0600312 else
multicast proxyd6474642015-03-21 16:09:15 +0100313 return false;
hilata198cadb2014-02-15 23:46:19 -0600314
315 return true;
316}
hilata198cadb2014-02-15 23:46:19 -0600317
hilata198cadb2014-02-15 23:46:19 -0600318void
Obaiddca50792014-04-24 18:38:40 -0500319Nfdc::fibAddNextHop()
hilata198cadb2014-02-15 23:46:19 -0600320{
Obaiddca50792014-04-24 18:38:40 -0500321 m_name = m_commandLineArguments[0];
Chengyu Fan27be0b02014-11-24 20:52:53 -0700322 const std::string& faceName = m_commandLineArguments[1];
hilata54e4eaf2014-04-10 23:38:33 -0500323
Chengyu Fan27be0b02014-11-24 20:52:53 -0700324 FaceIdFetcher::start(m_face, m_controller, faceName, true,
325 [this] (const uint32_t faceId) {
326 ControlParameters parameters;
327 parameters
328 .setName(m_name)
329 .setCost(m_cost)
330 .setFaceId(faceId);
hilata54e4eaf2014-04-10 23:38:33 -0500331
Chengyu Fan27be0b02014-11-24 20:52:53 -0700332 m_controller
333 .start<FibAddNextHopCommand>(parameters,
334 bind(&Nfdc::onSuccess, this, _1,
335 "Nexthop insertion succeeded"),
336 bind(&Nfdc::onError, this, _1, _2,
337 "Nexthop insertion failed"));
338 },
339 bind(&Nfdc::onObtainFaceIdFailure, this, _1));
hilata54e4eaf2014-04-10 23:38:33 -0500340}
341
342void
343Nfdc::fibRemoveNextHop()
344{
Obaiddca50792014-04-24 18:38:40 -0500345 m_name = m_commandLineArguments[0];
Chengyu Fan27be0b02014-11-24 20:52:53 -0700346 const std::string& faceName = m_commandLineArguments[1];
hilata54e4eaf2014-04-10 23:38:33 -0500347
Chengyu Fan27be0b02014-11-24 20:52:53 -0700348 FaceIdFetcher::start(m_face, m_controller, faceName, false,
349 [this] (const uint32_t faceId) {
350 ControlParameters parameters;
351 parameters
352 .setName(m_name)
353 .setFaceId(faceId);
hilata54e4eaf2014-04-10 23:38:33 -0500354
Chengyu Fan27be0b02014-11-24 20:52:53 -0700355 m_controller
356 .start<FibRemoveNextHopCommand>(parameters,
357 bind(&Nfdc::onSuccess, this, _1,
358 "Nexthop removal succeeded"),
359 bind(&Nfdc::onError, this, _1, _2,
360 "Nexthop removal failed"));
361 },
362 bind(&Nfdc::onObtainFaceIdFailure, this, _1));
Obaiddca50792014-04-24 18:38:40 -0500363}
364
365void
366Nfdc::ribRegisterPrefix()
367{
368 m_name = m_commandLineArguments[0];
Chengyu Fan27be0b02014-11-24 20:52:53 -0700369 const std::string& faceName = m_commandLineArguments[1];
Alexander Afanasyevf67cf082014-07-18 16:47:29 -0700370
Chengyu Fan27be0b02014-11-24 20:52:53 -0700371 FaceIdFetcher::start(m_face, m_controller, faceName, true,
372 [this] (const uint32_t faceId) {
373 ControlParameters parameters;
374 parameters
375 .setName(m_name)
376 .setCost(m_cost)
377 .setFlags(m_flags)
378 .setOrigin(m_origin)
379 .setFaceId(faceId);
Obaiddca50792014-04-24 18:38:40 -0500380
Chengyu Fan27be0b02014-11-24 20:52:53 -0700381 if (m_expires != DEFAULT_EXPIRATION_PERIOD)
382 parameters.setExpirationPeriod(m_expires);
Obaiddca50792014-04-24 18:38:40 -0500383
Chengyu Fan27be0b02014-11-24 20:52:53 -0700384 m_controller
385 .start<RibRegisterCommand>(parameters,
386 bind(&Nfdc::onSuccess, this, _1,
387 "Successful in name registration"),
388 bind(&Nfdc::onError, this, _1, _2,
389 "Failed in name registration"));
390 },
391 bind(&Nfdc::onObtainFaceIdFailure, this, _1));
Obaiddca50792014-04-24 18:38:40 -0500392}
393
394void
395Nfdc::ribUnregisterPrefix()
396{
397 m_name = m_commandLineArguments[0];
Chengyu Fan27be0b02014-11-24 20:52:53 -0700398 const std::string& faceName = m_commandLineArguments[1];
Obaiddca50792014-04-24 18:38:40 -0500399
Chengyu Fan27be0b02014-11-24 20:52:53 -0700400 FaceIdFetcher::start(m_face, m_controller, faceName, false,
401 [this] (const uint32_t faceId) {
402 ControlParameters parameters;
403 parameters
404 .setName(m_name)
405 .setFaceId(faceId)
406 .setOrigin(m_origin);
Obaiddca50792014-04-24 18:38:40 -0500407
Chengyu Fan27be0b02014-11-24 20:52:53 -0700408 m_controller
409 .start<RibUnregisterCommand>(parameters,
410 bind(&Nfdc::onSuccess, this, _1,
411 "Successful in unregistering name"),
412 bind(&Nfdc::onError, this, _1, _2,
413 "Failed in unregistering name"));
414 },
415 bind(&Nfdc::onObtainFaceIdFailure, this, _1));
hilata54e4eaf2014-04-10 23:38:33 -0500416}
417
418void
Chengyu Fandae25302014-10-16 11:40:11 -0600419Nfdc::onCanonizeFailure(const std::string& reason)
420{
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700421 BOOST_THROW_EXCEPTION(Error(reason));
Chengyu Fandae25302014-10-16 11:40:11 -0600422}
423
424void
Chengyu Fan27be0b02014-11-24 20:52:53 -0700425Nfdc::onObtainFaceIdFailure(const std::string& message)
426{
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700427 BOOST_THROW_EXCEPTION(Error(message));
Chengyu Fan27be0b02014-11-24 20:52:53 -0700428}
429
430void
hilata54e4eaf2014-04-10 23:38:33 -0500431Nfdc::faceCreate()
432{
Chengyu Fan27be0b02014-11-24 20:52:53 -0700433 boost::regex e("^[a-z0-9]+\\:.*");
434 if (!boost::regex_match(m_commandLineArguments[0], e))
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700435 BOOST_THROW_EXCEPTION(Error("invalid uri format"));
hilata54e4eaf2014-04-10 23:38:33 -0500436
Chengyu Fandae25302014-10-16 11:40:11 -0600437 ndn::util::FaceUri faceUri;
438 faceUri.parse(m_commandLineArguments[0]);
439
440 faceUri.canonize(bind(&Nfdc::startFaceCreate, this, _1),
441 bind(&Nfdc::onCanonizeFailure, this, _1),
442 m_ioService, ndn::time::seconds(4));
443}
444
445void
446Nfdc::startFaceCreate(const ndn::util::FaceUri& canonicalUri)
447{
hilata54e4eaf2014-04-10 23:38:33 -0500448 ControlParameters parameters;
Chengyu Fandae25302014-10-16 11:40:11 -0600449 parameters.setUri(canonicalUri.toString());
Joao Pereirac6184cd2015-09-03 15:27:29 -0400450 parameters.setFacePersistency(m_facePersistency);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700451
Obaiddca50792014-04-24 18:38:40 -0500452 m_controller.start<FaceCreateCommand>(parameters,
453 bind(&Nfdc::onSuccess, this, _1,
454 "Face creation succeeded"),
455 bind(&Nfdc::onError, this, _1, _2,
456 "Face creation failed"));
hilata198cadb2014-02-15 23:46:19 -0600457}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700458
hilata198cadb2014-02-15 23:46:19 -0600459void
hilata54e4eaf2014-04-10 23:38:33 -0500460Nfdc::faceDestroy()
hilata198cadb2014-02-15 23:46:19 -0600461{
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700462 ControlParameters parameters;
Chengyu Fan27be0b02014-11-24 20:52:53 -0700463 const std::string& faceName = m_commandLineArguments[0];
Chengyu Fandae25302014-10-16 11:40:11 -0600464
Chengyu Fan27be0b02014-11-24 20:52:53 -0700465 FaceIdFetcher::start(m_face, m_controller, faceName, false,
466 [this] (const uint32_t faceId) {
467 ControlParameters faceParameters;
468 faceParameters.setFaceId(faceId);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700469
Chengyu Fan27be0b02014-11-24 20:52:53 -0700470 m_controller.start<FaceDestroyCommand>(faceParameters,
471 bind(&Nfdc::onSuccess, this, _1,
472 "Face destroy succeeded"),
473 bind(&Nfdc::onError, this, _1, _2,
474 "Face destroy failed"));
475 },
476 bind(&Nfdc::onObtainFaceIdFailure, this, _1));
hilata198cadb2014-02-15 23:46:19 -0600477}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700478
hilata141eaae2014-03-13 19:54:47 -0500479void
hilata54e4eaf2014-04-10 23:38:33 -0500480Nfdc::strategyChoiceSet()
hilata141eaae2014-03-13 19:54:47 -0500481{
hilata54e4eaf2014-04-10 23:38:33 -0500482 const std::string& name = m_commandLineArguments[0];
483 const std::string& strategy = m_commandLineArguments[1];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700484
485 ControlParameters parameters;
486 parameters
487 .setName(name)
488 .setStrategy(strategy);
489
Obaiddca50792014-04-24 18:38:40 -0500490 m_controller.start<StrategyChoiceSetCommand>(parameters,
491 bind(&Nfdc::onSuccess, this, _1,
492 "Successfully set strategy choice"),
493 bind(&Nfdc::onError, this, _1, _2,
494 "Failed to set strategy choice"));
hilata141eaae2014-03-13 19:54:47 -0500495}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700496
hilata141eaae2014-03-13 19:54:47 -0500497void
hilata54e4eaf2014-04-10 23:38:33 -0500498Nfdc::strategyChoiceUnset()
hilata141eaae2014-03-13 19:54:47 -0500499{
hilata54e4eaf2014-04-10 23:38:33 -0500500 const std::string& name = m_commandLineArguments[0];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700501
502 ControlParameters parameters;
Obaiddca50792014-04-24 18:38:40 -0500503 parameters.setName(name);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700504
Obaiddca50792014-04-24 18:38:40 -0500505 m_controller.start<StrategyChoiceUnsetCommand>(parameters,
506 bind(&Nfdc::onSuccess, this, _1,
507 "Successfully unset strategy choice"),
508 bind(&Nfdc::onError, this, _1, _2,
509 "Failed to unset strategy choice"));
hilata141eaae2014-03-13 19:54:47 -0500510}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700511
hilata198cadb2014-02-15 23:46:19 -0600512void
Obaiddca50792014-04-24 18:38:40 -0500513Nfdc::onSuccess(const ControlParameters& commandSuccessResult, const std::string& message)
hilata198cadb2014-02-15 23:46:19 -0600514{
Obaiddca50792014-04-24 18:38:40 -0500515 std::cout << message << ": " << commandSuccessResult << std::endl;
hilata198cadb2014-02-15 23:46:19 -0600516}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700517
hilata198cadb2014-02-15 23:46:19 -0600518void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700519Nfdc::onError(uint32_t code, const std::string& error, const std::string& message)
hilata198cadb2014-02-15 23:46:19 -0600520{
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700521 std::ostringstream os;
522 os << message << ": " << error << " (code: " << code << ")";
Spyridon Mastorakis149e02c2015-07-27 13:22:22 -0700523 BOOST_THROW_EXCEPTION(Error(os.str()));
hilata141eaae2014-03-13 19:54:47 -0500524}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700525
hilata141eaae2014-03-13 19:54:47 -0500526} // namespace nfdc
hilata198cadb2014-02-15 23:46:19 -0600527
528int
529main(int argc, char** argv)
530{
531 ndn::Face face;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700532 nfdc::Nfdc p(face);
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800533
hilata198cadb2014-02-15 23:46:19 -0600534 p.m_programName = argv[0];
hilata54e4eaf2014-04-10 23:38:33 -0500535
Obaiddca50792014-04-24 18:38:40 -0500536 if (argc < 2) {
537 usage(p.m_programName);
538 return 0;
539 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700540
Obaiddca50792014-04-24 18:38:40 -0500541 if (!strcmp(argv[1], "-h")) {
542 usage(p.m_programName);
543 return 0;
544 }
545
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700546 if (!strcmp(argv[1], "-V")) {
547 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
548 return 0;
549 }
550
Junxiao Shi22295032014-04-29 22:57:40 -0700551 ::optind = 2; //start reading options from 2nd argument i.e. Command
Obaiddca50792014-04-24 18:38:40 -0500552 int opt;
Joao Pereirac6184cd2015-09-03 15:27:29 -0400553 while ((opt = ::getopt(argc, argv, "ICc:e:o:P")) != -1) {
Obaiddca50792014-04-24 18:38:40 -0500554 switch (opt) {
Joao Pereirac6184cd2015-09-03 15:27:29 -0400555 case 'I':
556 p.m_flags = p.m_flags & ~(nfdc::ROUTE_FLAG_CHILD_INHERIT);
557 break;
Obaiddca50792014-04-24 18:38:40 -0500558
Joao Pereirac6184cd2015-09-03 15:27:29 -0400559 case 'C':
560 p.m_flags = p.m_flags | nfdc::ROUTE_FLAG_CAPTURE;
561 break;
Obaiddca50792014-04-24 18:38:40 -0500562
Joao Pereirac6184cd2015-09-03 15:27:29 -0400563 case 'c':
564 try {
565 p.m_cost = boost::lexical_cast<uint64_t>(::optarg);
566 }
567 catch (boost::bad_lexical_cast&) {
568 std::cerr << "Error: cost must be in unsigned integer format" << std::endl;
569 return 1;
570 }
571 break;
572
573 case 'e':
574 uint64_t expires;
575 try {
576 expires = boost::lexical_cast<uint64_t>(::optarg);
577 }
578 catch (boost::bad_lexical_cast&) {
579 std::cerr << "Error: expiration time must be in unsigned integer format" << std::endl;
580 return 1;
581 }
582 p.m_expires = ndn::time::milliseconds(expires);
583 break;
584
585 case 'o':
586 try {
587 p.m_origin = boost::lexical_cast<uint64_t>(::optarg);
588 }
589 catch (boost::bad_lexical_cast&) {
590 std::cerr << "Error: origin must be in unsigned integer format" << std::endl;
591 return 1;
592 }
593 break;
594
595 case 'P':
596 p.m_facePersistency = ndn::nfd::FacePersistency::FACE_PERSISTENCY_PERMANENT;
597 break;
598
599 default:
600 usage(p.m_programName);
Syed Obaid4ae0ce32014-06-17 13:59:20 -0500601 return 1;
hilata198cadb2014-02-15 23:46:19 -0600602 }
603 }
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800604
Junxiao Shi22295032014-04-29 22:57:40 -0700605 if (argc == ::optind) {
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800606 usage(p.m_programName);
607 return 1;
608 }
609
hilata198cadb2014-02-15 23:46:19 -0600610 try {
Junxiao Shi22295032014-04-29 22:57:40 -0700611 p.m_commandLineArguments = argv + ::optind;
612 p.m_nOptions = argc - ::optind;
Obaiddca50792014-04-24 18:38:40 -0500613
614 //argv[1] points to the command, so pass it to the dispatch
615 bool isOk = p.dispatch(argv[1]);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700616 if (!isOk) {
hilata198cadb2014-02-15 23:46:19 -0600617 usage(p.m_programName);
618 return 1;
619 }
hilata198cadb2014-02-15 23:46:19 -0600620 face.processEvents();
621 }
622 catch (const std::exception& e) {
623 std::cerr << "ERROR: " << e.what() << std::endl;
624 return 2;
625 }
626 return 0;
627}