blob: 08ad859dc60ce1705448c8194fa2cb2e578599f3 [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
9 *
10 * This file is part of NFD (Named Data Networking Forwarding Daemon).
11 * See AUTHORS.md for complete list of NFD authors and contributors.
12 *
13 * NFD is free software: you can redistribute it and/or modify it under the terms
14 * of the GNU General Public License as published by the Free Software Foundation,
15 * either version 3 of the License, or (at your option) any later version.
16 *
17 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 * PURPOSE. See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
23 **/
hilata198cadb2014-02-15 23:46:19 -060024#include "nfdc.hpp"
25#include <boost/lexical_cast.hpp>
26#include <boost/algorithm/string.hpp>
27#include <boost/algorithm/string/regex_find_format.hpp>
28#include <boost/regex.hpp>
29
30void
31usage(const char* programName)
32{
33 std::cout << "Usage:\n" << programName << " [-h] COMMAND\n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070034 " -h print usage and exit\n"
35 "\n"
36 " COMMAND can be one of following:\n"
hilata54e4eaf2014-04-10 23:38:33 -050037 " add <name> <faceUri> [<cost>]\n"
38 " Create a face, and add a nexthop for this face to a FIB entry\n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070039 " add-nexthop <name> <faceId> [<cost>]\n"
40 " Add a nexthop to a FIB entry\n"
41 " remove-nexthop <name> <faceId> \n"
42 " Remove a nexthop from a FIB entry\n"
43 " create <uri> \n"
44 " Create a face in one of the following formats:\n"
45 " UDP unicast: udp[4|6]://<remote-IP-or-host>[:<remote-port>]\n"
46 " TCP: tcp[4|6]://<remote-IP-or-host>[:<remote-port>] \n"
47 " destroy <faceId> \n"
48 " Destroy a face\n"
49 " set-strategy <name> <strategy> \n"
50 " Set the strategy for a namespace \n"
51 " unset-strategy <name> \n"
52 " Unset the strategy for a namespace \n"
53 << std::endl;
hilata198cadb2014-02-15 23:46:19 -060054}
55
56namespace nfdc {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070057
58Nfdc::Nfdc(ndn::Face& face)
59 : m_controller(face)
hilata198cadb2014-02-15 23:46:19 -060060{
61}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070062
63Nfdc::~Nfdc()
hilata198cadb2014-02-15 23:46:19 -060064{
65}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070066
hilata198cadb2014-02-15 23:46:19 -060067bool
hilata54e4eaf2014-04-10 23:38:33 -050068Nfdc::dispatch(const std::string& command)
hilata198cadb2014-02-15 23:46:19 -060069{
hilata54e4eaf2014-04-10 23:38:33 -050070 if (command == "add") {
71 if (m_nOptions == 2)
72 addName();
73 else if (m_nOptions == 3)
74 addName();
75 else
76 return false;
77 }
78 else if (command == "add-nexthop") {
79 if (m_nOptions == 2)
80 fibAddNextHop(false);
81 else if (m_nOptions == 3)
82 fibAddNextHop(true);
hilata198cadb2014-02-15 23:46:19 -060083 else
84 return false;
85 }
86 else if (command == "remove-nexthop") {
hilata54e4eaf2014-04-10 23:38:33 -050087 if (m_nOptions != 2)
hilata198cadb2014-02-15 23:46:19 -060088 return false;
hilata54e4eaf2014-04-10 23:38:33 -050089 fibRemoveNextHop();
hilata198cadb2014-02-15 23:46:19 -060090 }
hilata198cadb2014-02-15 23:46:19 -060091 else if (command == "create") {
hilata54e4eaf2014-04-10 23:38:33 -050092 if (m_nOptions != 1)
hilata198cadb2014-02-15 23:46:19 -060093 return false;
hilata54e4eaf2014-04-10 23:38:33 -050094 faceCreate();
hilata198cadb2014-02-15 23:46:19 -060095 }
96 else if (command == "destroy") {
hilata54e4eaf2014-04-10 23:38:33 -050097 if (m_nOptions != 1)
hilata198cadb2014-02-15 23:46:19 -060098 return false;
hilata54e4eaf2014-04-10 23:38:33 -050099 faceDestroy();
hilata198cadb2014-02-15 23:46:19 -0600100 }
hilata141eaae2014-03-13 19:54:47 -0500101 else if (command == "set-strategy") {
hilata54e4eaf2014-04-10 23:38:33 -0500102 if (m_nOptions != 2)
hilata141eaae2014-03-13 19:54:47 -0500103 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500104 strategyChoiceSet();
hilata141eaae2014-03-13 19:54:47 -0500105 }
106 else if (command == "unset-strategy") {
hilata54e4eaf2014-04-10 23:38:33 -0500107 if (m_nOptions != 1)
hilata141eaae2014-03-13 19:54:47 -0500108 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500109 strategyChoiceUnset();
hilata141eaae2014-03-13 19:54:47 -0500110 }
hilata198cadb2014-02-15 23:46:19 -0600111 else
112 usage(m_programName);
113
114 return true;
115}
hilata198cadb2014-02-15 23:46:19 -0600116
hilata9b27e692014-02-25 15:43:19 -0600117
hilata198cadb2014-02-15 23:46:19 -0600118namespace {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700119
120inline bool
hilata198cadb2014-02-15 23:46:19 -0600121isValidUri(const std::string& input)
122{
123 // an extended regex to support the validation of uri structure
124 // boost::regex e("^[a-z0-9]+-?+[a-z0-9]+\\:\\/\\/.*");
125 boost::regex e("^[a-z0-9]+\\:.*");
126 return boost::regex_match(input, e);
127}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700128
hilata198cadb2014-02-15 23:46:19 -0600129} // anonymous namespace
130
131void
hilata54e4eaf2014-04-10 23:38:33 -0500132Nfdc::addName()
hilata198cadb2014-02-15 23:46:19 -0600133{
hilata54e4eaf2014-04-10 23:38:33 -0500134 if (!isValidUri(m_commandLineArguments[1]))
hilata198cadb2014-02-15 23:46:19 -0600135 throw Error("invalid uri format");
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700136
137 ControlParameters parameters;
138 parameters
hilata54e4eaf2014-04-10 23:38:33 -0500139 .setUri(m_commandLineArguments[1]);
140
141 m_controller.start<FaceCreateCommand>(
142 parameters,
143 bind(&Nfdc::onAddSuccess, this, _1, "nfdc add:Face creation succeeded"),
144 bind(&Nfdc::onError, this, _1, _2, "nfdc add: Face creation failed"));
145
146}
147
148void
149Nfdc::fibAddNextHop(bool hasCost)
150{
151 const std::string& name = m_commandLineArguments[0];
152 const int faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
153
154 fibAddNextHop(name, faceId, hasCost);
155
156}
157
158void
159Nfdc::fibAddNextHop(const std::string& name, const uint64_t faceId, bool hasCost)
160{
161 ControlParameters parameters;
162 parameters
163 .setName(name)
164 .setFaceId(faceId);
165
166 if (hasCost)
167 {
168 const uint64_t cost = boost::lexical_cast<uint64_t>(m_commandLineArguments[2]);
169 parameters.setCost(cost);
170 }
171
172 m_controller.start<FibAddNextHopCommand>(
173 parameters,
174 bind(&Nfdc::onSuccess, this, _1, "Nexthop insertion succeeded"),
175 bind(&Nfdc::onError, this, _1, _2, "Nexthop insertion failed"));
176}
177
178void
179Nfdc::fibRemoveNextHop()
180{
181 const std::string& name = m_commandLineArguments[0];
182 const int faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
183
184 ControlParameters parameters;
185 parameters
186 .setName(name)
187 .setFaceId(faceId);
188
189 m_controller.start<FibRemoveNextHopCommand>(
190 parameters,
191 bind(&Nfdc::onSuccess, this, _1, "Nexthop removal succeeded"),
192 bind(&Nfdc::onError, this, _1, _2, "Nexthop removal failed"));
193}
194
195void
196Nfdc::faceCreate()
197{
198 if (!isValidUri(m_commandLineArguments[0]))
199 throw Error("invalid uri format");
200
201 ControlParameters parameters;
202 parameters
203 .setUri(m_commandLineArguments[0]);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700204
205 m_controller.start<FaceCreateCommand>(
206 parameters,
207 bind(&Nfdc::onSuccess, this, _1, "Face creation succeeded"),
208 bind(&Nfdc::onError, this, _1, _2, "Face creation failed"));
hilata198cadb2014-02-15 23:46:19 -0600209}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700210
hilata198cadb2014-02-15 23:46:19 -0600211void
hilata54e4eaf2014-04-10 23:38:33 -0500212Nfdc::faceDestroy()
hilata198cadb2014-02-15 23:46:19 -0600213{
hilata54e4eaf2014-04-10 23:38:33 -0500214 const int faceId = boost::lexical_cast<int>(m_commandLineArguments[0]);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700215
216 ControlParameters parameters;
217 parameters
218 .setFaceId(faceId);
219
220 m_controller.start<FaceDestroyCommand>(
221 parameters,
222 bind(&Nfdc::onSuccess, this, _1, "Face destroy succeeded"),
223 bind(&Nfdc::onError, this, _1, _2, "Face destroy failed"));
hilata198cadb2014-02-15 23:46:19 -0600224}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700225
hilata141eaae2014-03-13 19:54:47 -0500226void
hilata54e4eaf2014-04-10 23:38:33 -0500227Nfdc::strategyChoiceSet()
hilata141eaae2014-03-13 19:54:47 -0500228{
hilata54e4eaf2014-04-10 23:38:33 -0500229 const std::string& name = m_commandLineArguments[0];
230 const std::string& strategy = m_commandLineArguments[1];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700231
232 ControlParameters parameters;
233 parameters
234 .setName(name)
235 .setStrategy(strategy);
236
237 m_controller.start<StrategyChoiceSetCommand>(
238 parameters,
239 bind(&Nfdc::onSuccess, this, _1, "Successfully set strategy choice"),
240 bind(&Nfdc::onError, this, _1, _2, "Failed to set strategy choice"));
hilata141eaae2014-03-13 19:54:47 -0500241}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700242
hilata141eaae2014-03-13 19:54:47 -0500243void
hilata54e4eaf2014-04-10 23:38:33 -0500244Nfdc::strategyChoiceUnset()
hilata141eaae2014-03-13 19:54:47 -0500245{
hilata54e4eaf2014-04-10 23:38:33 -0500246 const std::string& name = m_commandLineArguments[0];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700247
248 ControlParameters parameters;
249 parameters
250 .setName(name);
251
252 m_controller.start<StrategyChoiceUnsetCommand>(
253 parameters,
254 bind(&Nfdc::onSuccess, this, _1, "Successfully unset strategy choice"),
255 bind(&Nfdc::onError, this, _1, _2, "Failed to unset strategy choice"));
hilata141eaae2014-03-13 19:54:47 -0500256}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700257
hilata198cadb2014-02-15 23:46:19 -0600258void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700259Nfdc::onSuccess(const ControlParameters& parameters, const std::string& message)
hilata198cadb2014-02-15 23:46:19 -0600260{
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700261 std::cout << message << ": " << parameters << std::endl;
hilata198cadb2014-02-15 23:46:19 -0600262}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700263
hilata198cadb2014-02-15 23:46:19 -0600264void
hilata54e4eaf2014-04-10 23:38:33 -0500265Nfdc::onAddSuccess(const ControlParameters& parameters, const std::string& message)
266{
267 uint64_t faceId = parameters.getFaceId();
268
269 if (m_nOptions == 2)
270 fibAddNextHop(m_commandLineArguments[0], faceId, false);
271 else if (m_nOptions == 3)
272 fibAddNextHop(m_commandLineArguments[0], faceId, true);
273 else
274 throw Error("invalid number of arguments");
275}
276void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700277Nfdc::onError(uint32_t code, const std::string& error, const std::string& message)
hilata198cadb2014-02-15 23:46:19 -0600278{
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700279 std::ostringstream os;
280 os << message << ": " << error << " (code: " << code << ")";
281 throw Error(os.str());
hilata141eaae2014-03-13 19:54:47 -0500282}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700283
hilata141eaae2014-03-13 19:54:47 -0500284} // namespace nfdc
hilata198cadb2014-02-15 23:46:19 -0600285
286int
287main(int argc, char** argv)
288{
289 ndn::Face face;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700290 nfdc::Nfdc p(face);
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800291
hilata198cadb2014-02-15 23:46:19 -0600292 p.m_programName = argv[0];
hilata54e4eaf2014-04-10 23:38:33 -0500293
hilata198cadb2014-02-15 23:46:19 -0600294 int opt;
295 while ((opt = getopt(argc, argv, "h")) != -1) {
296 switch (opt) {
297 case 'h':
298 usage(p.m_programName);
299 return 0;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700300
hilata198cadb2014-02-15 23:46:19 -0600301 default:
302 usage(p.m_programName);
303 return 1;
304 }
305 }
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800306
307 if (argc == optind) {
308 usage(p.m_programName);
309 return 1;
310 }
311
hilata198cadb2014-02-15 23:46:19 -0600312 try {
hilata54e4eaf2014-04-10 23:38:33 -0500313 p.m_commandLineArguments = const_cast<const char**>(argv + optind + 1);
314 p.m_nOptions = argc - optind - 1;
315 bool isOk = p.dispatch(argv[optind]);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700316 if (!isOk) {
hilata198cadb2014-02-15 23:46:19 -0600317 usage(p.m_programName);
318 return 1;
319 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700320
hilata198cadb2014-02-15 23:46:19 -0600321 face.processEvents();
322 }
323 catch (const std::exception& e) {
324 std::cerr << "ERROR: " << e.what() << std::endl;
325 return 2;
326 }
327 return 0;
328}