blob: 6e1402363d43e344a5a4d0e92f79eb0796172bbc [file] [log] [blame]
hilata198cadb2014-02-15 23:46:19 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -07003 * Copyright (c) 2014 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
Obaiddca50792014-04-24 18:38:40 -05009 * 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/>.
24 **/
hilata198cadb2014-02-15 23:46:19 -060025#include "nfdc.hpp"
26#include <boost/lexical_cast.hpp>
27#include <boost/algorithm/string.hpp>
28#include <boost/algorithm/string/regex_find_format.hpp>
29#include <boost/regex.hpp>
30
31void
32usage(const char* programName)
33{
Obaiddca50792014-04-24 18:38:40 -050034 std::cout << "Usage:\n" << programName << " [-h] COMMAND [<Command Options>]\n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070035 " -h print usage and exit\n"
36 "\n"
Obaiddca50792014-04-24 18:38:40 -050037 " COMMAND can be one of the following:\n"
38 " add-nexthop [-c <cost>] <name> <faceId | faceUri>\n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070039 " Add a nexthop to a FIB entry\n"
Obaiddca50792014-04-24 18:38:40 -050040 " -c: specify cost\n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070041 " remove-nexthop <name> <faceId> \n"
42 " Remove a nexthop from a FIB entry\n"
Obaiddca50792014-04-24 18:38:40 -050043 " register [-I] [-C] [-c cost] name <faceId | faceUri>\n"
44 " register name to the given faceId or faceUri\n"
45 " -I: unset CHILD_INHERIT flag\n"
46 " -C: set CAPTURE flag\n"
47 " -c: specify cost\n"
48 " unregister name <faceId>\n"
49 " unregister name from the given faceId\n"
50 " create <faceUri> \n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070051 " Create a face in one of the following formats:\n"
52 " UDP unicast: udp[4|6]://<remote-IP-or-host>[:<remote-port>]\n"
53 " TCP: tcp[4|6]://<remote-IP-or-host>[:<remote-port>] \n"
Obaiddca50792014-04-24 18:38:40 -050054 " destroy <faceId | faceUri> \n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070055 " Destroy a face\n"
56 " set-strategy <name> <strategy> \n"
57 " Set the strategy for a namespace \n"
58 " unset-strategy <name> \n"
59 " Unset the strategy for a namespace \n"
60 << std::endl;
hilata198cadb2014-02-15 23:46:19 -060061}
62
63namespace nfdc {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070064
65Nfdc::Nfdc(ndn::Face& face)
Obaiddca50792014-04-24 18:38:40 -050066 : m_flags(ROUTE_FLAG_CHILD_INHERIT)
67 , m_cost(0)
68 , m_controller(face)
hilata198cadb2014-02-15 23:46:19 -060069{
70}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070071
72Nfdc::~Nfdc()
hilata198cadb2014-02-15 23:46:19 -060073{
74}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070075
hilata198cadb2014-02-15 23:46:19 -060076bool
hilata54e4eaf2014-04-10 23:38:33 -050077Nfdc::dispatch(const std::string& command)
hilata198cadb2014-02-15 23:46:19 -060078{
Obaiddca50792014-04-24 18:38:40 -050079 if (command == "add-nexthop") {
80 if (m_nOptions != 2)
hilata54e4eaf2014-04-10 23:38:33 -050081 return false;
Obaiddca50792014-04-24 18:38:40 -050082 fibAddNextHop();
hilata198cadb2014-02-15 23:46:19 -060083 }
84 else if (command == "remove-nexthop") {
hilata54e4eaf2014-04-10 23:38:33 -050085 if (m_nOptions != 2)
hilata198cadb2014-02-15 23:46:19 -060086 return false;
hilata54e4eaf2014-04-10 23:38:33 -050087 fibRemoveNextHop();
hilata198cadb2014-02-15 23:46:19 -060088 }
Obaiddca50792014-04-24 18:38:40 -050089 else if (command == "register") {
90 if (m_nOptions != 2)
91 return false;
92 ribRegisterPrefix();
93 }
94 else if (command == "unregister") {
95 if (m_nOptions != 2)
96 return false;
97 ribUnregisterPrefix();
98 }
hilata198cadb2014-02-15 23:46:19 -060099 else if (command == "create") {
hilata54e4eaf2014-04-10 23:38:33 -0500100 if (m_nOptions != 1)
hilata198cadb2014-02-15 23:46:19 -0600101 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500102 faceCreate();
hilata198cadb2014-02-15 23:46:19 -0600103 }
104 else if (command == "destroy") {
hilata54e4eaf2014-04-10 23:38:33 -0500105 if (m_nOptions != 1)
hilata198cadb2014-02-15 23:46:19 -0600106 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500107 faceDestroy();
hilata198cadb2014-02-15 23:46:19 -0600108 }
hilata141eaae2014-03-13 19:54:47 -0500109 else if (command == "set-strategy") {
hilata54e4eaf2014-04-10 23:38:33 -0500110 if (m_nOptions != 2)
hilata141eaae2014-03-13 19:54:47 -0500111 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500112 strategyChoiceSet();
hilata141eaae2014-03-13 19:54:47 -0500113 }
114 else if (command == "unset-strategy") {
hilata54e4eaf2014-04-10 23:38:33 -0500115 if (m_nOptions != 1)
hilata141eaae2014-03-13 19:54:47 -0500116 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500117 strategyChoiceUnset();
hilata141eaae2014-03-13 19:54:47 -0500118 }
hilata198cadb2014-02-15 23:46:19 -0600119 else
120 usage(m_programName);
121
122 return true;
123}
hilata198cadb2014-02-15 23:46:19 -0600124
hilata198cadb2014-02-15 23:46:19 -0600125namespace {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700126
127inline bool
hilata198cadb2014-02-15 23:46:19 -0600128isValidUri(const std::string& input)
129{
130 // an extended regex to support the validation of uri structure
131 // boost::regex e("^[a-z0-9]+-?+[a-z0-9]+\\:\\/\\/.*");
132 boost::regex e("^[a-z0-9]+\\:.*");
133 return boost::regex_match(input, e);
134}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700135
hilata198cadb2014-02-15 23:46:19 -0600136} // anonymous namespace
137
138void
Obaiddca50792014-04-24 18:38:40 -0500139Nfdc::fibAddNextHop()
hilata198cadb2014-02-15 23:46:19 -0600140{
Obaiddca50792014-04-24 18:38:40 -0500141 m_name = m_commandLineArguments[0];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700142 ControlParameters parameters;
143 parameters
Obaiddca50792014-04-24 18:38:40 -0500144 .setName(m_name)
145 .setCost(m_cost);
hilata54e4eaf2014-04-10 23:38:33 -0500146
Obaiddca50792014-04-24 18:38:40 -0500147 if (!isValidUri(m_commandLineArguments[1])) {
148 try { //So the uri is not valid, may be a faceId is provided.
149 m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
150 }
151 catch (const std::exception& e) {
152 std::cerr << "No valid faceUri or faceId is provided"<< std::endl;
153 return;
154 }
155 parameters.setFaceId(m_faceId);
156 fibAddNextHop(parameters);
hilata54e4eaf2014-04-10 23:38:33 -0500157 }
Obaiddca50792014-04-24 18:38:40 -0500158 else {
159 ControlParameters faceParameters;
160 faceParameters.setUri(m_commandLineArguments[1]);
hilata54e4eaf2014-04-10 23:38:33 -0500161
Obaiddca50792014-04-24 18:38:40 -0500162 m_controller.start<FaceCreateCommand>(faceParameters,
163 bind(&Nfdc::fibAddNextHop, this, _1),
164 bind(&Nfdc::onError, this, _1, _2,
165 "Face creation failed"));
166 }
167}
168
169void
170Nfdc::fibAddNextHop(const ControlParameters& faceCreateResult)
171{
172 ControlParameters ribParameters;
173 ribParameters
174 .setName(m_name)
175 .setCost(m_cost)
176 .setFaceId(faceCreateResult.getFaceId());
177
178 m_controller.start<FibAddNextHopCommand>(ribParameters,
179 bind(&Nfdc::onSuccess, this, _1,
180 "Nexthop insertion succeeded"),
181 bind(&Nfdc::onError, this, _1, _2,
182 "Nexthop insertion failed"));
hilata54e4eaf2014-04-10 23:38:33 -0500183}
184
185void
186Nfdc::fibRemoveNextHop()
187{
Obaiddca50792014-04-24 18:38:40 -0500188 m_name = m_commandLineArguments[0];
189 try {
190 m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
191 }
192 catch (const std::exception& e) {
193 std::cerr << "No valid faceUri or faceId is provided"<< std::endl;
194 return;
195 }
hilata54e4eaf2014-04-10 23:38:33 -0500196
197 ControlParameters parameters;
198 parameters
Obaiddca50792014-04-24 18:38:40 -0500199 .setName(m_name)
200 .setFaceId(m_faceId);
hilata54e4eaf2014-04-10 23:38:33 -0500201
Obaiddca50792014-04-24 18:38:40 -0500202 m_controller.start<FibRemoveNextHopCommand>(parameters,
203 bind(&Nfdc::onSuccess, this, _1,
204 "Nexthop removal succeeded"),
205 bind(&Nfdc::onError, this, _1, _2,
206 "Nexthop removal failed"));
207}
208
209void
210Nfdc::ribRegisterPrefix()
211{
212 m_name = m_commandLineArguments[0];
213 ControlParameters parameters;
214 parameters
215 .setName(m_name)
216 .setCost(m_cost)
217 .setFlags(m_flags);
218
219 if (!isValidUri(m_commandLineArguments[1])) {
220 try { //So the uri is not valid, may be a faceId is provided.
221 m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
222 }
223 catch (const std::exception& e) {
224 std::cerr << "No valid faceUri or faceId is provided"<< std::endl;
225 return;
226 }
227 parameters.setFaceId(m_faceId);
228 ribRegisterPrefix(parameters);
229 }
230 else {
231 ControlParameters faceParameters;
232 faceParameters.setUri(m_commandLineArguments[1]);
233
234 m_controller.start<FaceCreateCommand>(faceParameters,
235 bind(&Nfdc::ribRegisterPrefix, this, _1),
236 bind(&Nfdc::onError, this, _1, _2,
237 "Face creation failed"));
238 }
239}
240
241void
242Nfdc::ribRegisterPrefix(const ControlParameters& faceCreateResult)
243{
244 ControlParameters ribParameters;
245 ribParameters
246 .setName(m_name)
247 .setCost(m_cost)
248 .setFlags(m_flags)
249 .setFaceId(faceCreateResult.getFaceId());
250
251 m_controller.start<RibRegisterCommand>(ribParameters,
252 bind(&Nfdc::onSuccess, this, _1,
253 "Successful in name registration"),
254 bind(&Nfdc::onError, this, _1, _2,
255 "Failed in name registration"));
256}
257
258void
259Nfdc::ribUnregisterPrefix()
260{
261 m_name = m_commandLineArguments[0];
262 try {
263 m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
264 }
265 catch (const std::exception& e) {
266 std::cerr << "No valid faceUri or faceId is provided"<< std::endl;
267 return;
268 }
269
270 ControlParameters parameters;
271 parameters
272 .setName(m_name)
273 .setFaceId(m_faceId);
274
275 m_controller.start<RibUnregisterCommand>(parameters,
276 bind(&Nfdc::onSuccess, this, _1,
277 "Successful in unregistering name"),
278 bind(&Nfdc::onError, this, _1, _2,
279 "Failed in unregistering name"));
hilata54e4eaf2014-04-10 23:38:33 -0500280}
281
282void
283Nfdc::faceCreate()
284{
285 if (!isValidUri(m_commandLineArguments[0]))
286 throw Error("invalid uri format");
287
288 ControlParameters parameters;
Obaiddca50792014-04-24 18:38:40 -0500289 parameters.setUri(m_commandLineArguments[0]);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700290
Obaiddca50792014-04-24 18:38:40 -0500291 m_controller.start<FaceCreateCommand>(parameters,
292 bind(&Nfdc::onSuccess, this, _1,
293 "Face creation succeeded"),
294 bind(&Nfdc::onError, this, _1, _2,
295 "Face creation failed"));
hilata198cadb2014-02-15 23:46:19 -0600296}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700297
hilata198cadb2014-02-15 23:46:19 -0600298void
hilata54e4eaf2014-04-10 23:38:33 -0500299Nfdc::faceDestroy()
hilata198cadb2014-02-15 23:46:19 -0600300{
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700301 ControlParameters parameters;
Obaiddca50792014-04-24 18:38:40 -0500302 if (!isValidUri(m_commandLineArguments[0])) {
303 try { //So the uri is not valid, may be a faceId is provided.
304 m_faceId = boost::lexical_cast<int>(m_commandLineArguments[0]);
305 }
306 catch (const std::exception& e) {
307 std::cerr << "No valid faceUri or faceId is provided" << std::endl;
308 return;
309 }
310 parameters.setFaceId(m_faceId);
311 faceDestroy(parameters);
312 }
313 else{
314 ControlParameters faceParameters;
315 faceParameters.setUri(m_commandLineArguments[0]);
316 m_controller.start<FaceCreateCommand>(faceParameters,
317 bind(&Nfdc::faceDestroy, this, _1),
318 bind(&Nfdc::onError, this, _1, _2,
319 "Face destroy failed"));
320 }
321}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700322
Obaiddca50792014-04-24 18:38:40 -0500323void
324Nfdc::faceDestroy(const ControlParameters& faceCreateResult)
325{
326 ControlParameters faceParameters;
327 faceParameters.setFaceId(faceCreateResult.getFaceId());
328
329 m_controller.start<FaceDestroyCommand>(faceParameters,
330 bind(&Nfdc::onSuccess, this, _1,
331 "Face destroy succeeded"),
332 bind(&Nfdc::onError, this, _1, _2,
333 "Face destroy failed"));
hilata198cadb2014-02-15 23:46:19 -0600334}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700335
hilata141eaae2014-03-13 19:54:47 -0500336void
hilata54e4eaf2014-04-10 23:38:33 -0500337Nfdc::strategyChoiceSet()
hilata141eaae2014-03-13 19:54:47 -0500338{
hilata54e4eaf2014-04-10 23:38:33 -0500339 const std::string& name = m_commandLineArguments[0];
340 const std::string& strategy = m_commandLineArguments[1];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700341
342 ControlParameters parameters;
343 parameters
344 .setName(name)
345 .setStrategy(strategy);
346
Obaiddca50792014-04-24 18:38:40 -0500347 m_controller.start<StrategyChoiceSetCommand>(parameters,
348 bind(&Nfdc::onSuccess, this, _1,
349 "Successfully set strategy choice"),
350 bind(&Nfdc::onError, this, _1, _2,
351 "Failed to set strategy choice"));
hilata141eaae2014-03-13 19:54:47 -0500352}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700353
hilata141eaae2014-03-13 19:54:47 -0500354void
hilata54e4eaf2014-04-10 23:38:33 -0500355Nfdc::strategyChoiceUnset()
hilata141eaae2014-03-13 19:54:47 -0500356{
hilata54e4eaf2014-04-10 23:38:33 -0500357 const std::string& name = m_commandLineArguments[0];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700358
359 ControlParameters parameters;
Obaiddca50792014-04-24 18:38:40 -0500360 parameters.setName(name);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700361
Obaiddca50792014-04-24 18:38:40 -0500362 m_controller.start<StrategyChoiceUnsetCommand>(parameters,
363 bind(&Nfdc::onSuccess, this, _1,
364 "Successfully unset strategy choice"),
365 bind(&Nfdc::onError, this, _1, _2,
366 "Failed to unset strategy choice"));
hilata141eaae2014-03-13 19:54:47 -0500367}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700368
hilata198cadb2014-02-15 23:46:19 -0600369void
Obaiddca50792014-04-24 18:38:40 -0500370Nfdc::onSuccess(const ControlParameters& commandSuccessResult, const std::string& message)
hilata198cadb2014-02-15 23:46:19 -0600371{
Obaiddca50792014-04-24 18:38:40 -0500372 std::cout << message << ": " << commandSuccessResult << std::endl;
hilata198cadb2014-02-15 23:46:19 -0600373}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700374
hilata198cadb2014-02-15 23:46:19 -0600375void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700376Nfdc::onError(uint32_t code, const std::string& error, const std::string& message)
hilata198cadb2014-02-15 23:46:19 -0600377{
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700378 std::ostringstream os;
379 os << message << ": " << error << " (code: " << code << ")";
380 throw Error(os.str());
hilata141eaae2014-03-13 19:54:47 -0500381}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700382
Obaiddca50792014-04-24 18:38:40 -0500383
384
hilata141eaae2014-03-13 19:54:47 -0500385} // namespace nfdc
hilata198cadb2014-02-15 23:46:19 -0600386
387int
388main(int argc, char** argv)
389{
390 ndn::Face face;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700391 nfdc::Nfdc p(face);
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800392
hilata198cadb2014-02-15 23:46:19 -0600393 p.m_programName = argv[0];
hilata54e4eaf2014-04-10 23:38:33 -0500394
Obaiddca50792014-04-24 18:38:40 -0500395 if (argc < 2) {
396 usage(p.m_programName);
397 return 0;
398 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700399
Obaiddca50792014-04-24 18:38:40 -0500400 if (!strcmp(argv[1], "-h")) {
401 usage(p.m_programName);
402 return 0;
403 }
404
405
406 int opt;
407 //start reading options from 2nd argument i.e. Command
408 optind=2;
409 while ((opt = getopt(argc, argv, "ICc:")) != -1) {
410 switch (opt) {
411 case 'I':
412 p.m_flags = p.m_flags & ~(nfdc::ROUTE_FLAG_CHILD_INHERIT);
413 break;
414
415 case 'C':
416 p.m_flags = p.m_flags | nfdc::ROUTE_FLAG_CAPTURE;
417 break;
418
419 case 'c':
420 try {
421 p.m_cost = boost::lexical_cast<int>(optarg);
422 }
423 catch (const std::exception& e) {
424 std::cerr << "Error: cost must be in integer format" << std::endl;
hilata198cadb2014-02-15 23:46:19 -0600425 return 1;
Obaiddca50792014-04-24 18:38:40 -0500426 }
427 break;
428 default:
429 usage(p.m_programName);
430 return 1;
hilata198cadb2014-02-15 23:46:19 -0600431 }
432 }
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800433
434 if (argc == optind) {
435 usage(p.m_programName);
436 return 1;
437 }
438
hilata198cadb2014-02-15 23:46:19 -0600439 try {
Obaiddca50792014-04-24 18:38:40 -0500440 p.m_commandLineArguments = const_cast<const char**>(argv + optind);
441 p.m_nOptions = argc - optind;
442
443 //argv[1] points to the command, so pass it to the dispatch
444 bool isOk = p.dispatch(argv[1]);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700445 if (!isOk) {
hilata198cadb2014-02-15 23:46:19 -0600446 usage(p.m_programName);
447 return 1;
448 }
hilata198cadb2014-02-15 23:46:19 -0600449 face.processEvents();
450 }
451 catch (const std::exception& e) {
452 std::cerr << "ERROR: " << e.what() << std::endl;
453 return 2;
454 }
455 return 0;
456}