blob: a603cd6a36a3d4f9ed6b65725b1c4ea9e4070505 [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"
37 " add-nexthop <name> <faceId> [<cost>]\n"
38 " Add a nexthop to a FIB entry\n"
39 " remove-nexthop <name> <faceId> \n"
40 " Remove a nexthop from a FIB entry\n"
41 " create <uri> \n"
42 " Create a face in one of the following formats:\n"
43 " UDP unicast: udp[4|6]://<remote-IP-or-host>[:<remote-port>]\n"
44 " TCP: tcp[4|6]://<remote-IP-or-host>[:<remote-port>] \n"
45 " destroy <faceId> \n"
46 " Destroy a face\n"
47 " set-strategy <name> <strategy> \n"
48 " Set the strategy for a namespace \n"
49 " unset-strategy <name> \n"
50 " Unset the strategy for a namespace \n"
51 << std::endl;
hilata198cadb2014-02-15 23:46:19 -060052}
53
54namespace nfdc {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070055
56Nfdc::Nfdc(ndn::Face& face)
57 : m_controller(face)
hilata198cadb2014-02-15 23:46:19 -060058{
59}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070060
61Nfdc::~Nfdc()
hilata198cadb2014-02-15 23:46:19 -060062{
63}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070064
hilata198cadb2014-02-15 23:46:19 -060065bool
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070066Nfdc::dispatch(const std::string& command, const char* commandOptions[], int nOptions)
hilata198cadb2014-02-15 23:46:19 -060067{
hilatadc947ec2014-03-10 12:48:31 -050068 if (command == "add-nexthop") {
hilata198cadb2014-02-15 23:46:19 -060069 if (nOptions == 2)
70 fibAddNextHop(commandOptions, false);
71 else if (nOptions == 3)
72 fibAddNextHop(commandOptions, true);
73 else
74 return false;
75 }
76 else if (command == "remove-nexthop") {
77 if (nOptions != 2)
78 return false;
79 fibRemoveNextHop(commandOptions);
80 }
hilata198cadb2014-02-15 23:46:19 -060081 else if (command == "create") {
82 if (nOptions != 1)
83 return false;
84 faceCreate(commandOptions);
85 }
86 else if (command == "destroy") {
87 if (nOptions != 1)
88 return false;
89 faceDestroy(commandOptions);
90 }
hilata141eaae2014-03-13 19:54:47 -050091 else if (command == "set-strategy") {
92 if (nOptions != 2)
93 return false;
94 strategyChoiceSet(commandOptions);
95 }
96 else if (command == "unset-strategy") {
97 if (nOptions != 1)
98 return false;
99 strategyChoiceUnset(commandOptions);
100 }
hilata198cadb2014-02-15 23:46:19 -0600101 else
102 usage(m_programName);
103
104 return true;
105}
hilata198cadb2014-02-15 23:46:19 -0600106
107void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700108Nfdc::fibAddNextHop(const char* commandOptions[], bool hasCost)
hilata198cadb2014-02-15 23:46:19 -0600109{
hilata198cadb2014-02-15 23:46:19 -0600110 const std::string& name = commandOptions[0];
111 const int faceId = boost::lexical_cast<int>(commandOptions[1]);
112
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700113 ControlParameters parameters;
114 parameters
115 .setName(name)
116 .setFaceId(faceId);
hilata198cadb2014-02-15 23:46:19 -0600117
118 if (hasCost)
119 {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700120 const uint64_t cost = boost::lexical_cast<uint64_t>(commandOptions[2]);
121 parameters.setCost(cost);
hilata198cadb2014-02-15 23:46:19 -0600122 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700123
124 m_controller.start<FibAddNextHopCommand>(
125 parameters,
126 bind(&Nfdc::onSuccess, this, _1, "Nexthop insertion succeeded"),
127 bind(&Nfdc::onError, this, _1, _2, "Nexthop insertion failed"));
hilata198cadb2014-02-15 23:46:19 -0600128}
129
130void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700131Nfdc::fibRemoveNextHop(const char* commandOptions[])
hilata198cadb2014-02-15 23:46:19 -0600132{
133 const std::string& name = commandOptions[0];
134 const int faceId = boost::lexical_cast<int>(commandOptions[1]);
hilata198cadb2014-02-15 23:46:19 -0600135
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700136 ControlParameters parameters;
137 parameters
138 .setName(name)
139 .setFaceId(faceId);
140
141 m_controller.start<FibRemoveNextHopCommand>(
142 parameters,
143 bind(&Nfdc::onSuccess, this, _1, "Nexthop removal succeeded"),
144 bind(&Nfdc::onError, this, _1, _2, "Nexthop removal failed"));
hilata198cadb2014-02-15 23:46:19 -0600145}
hilata9b27e692014-02-25 15:43:19 -0600146
hilata198cadb2014-02-15 23:46:19 -0600147namespace {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700148
149inline bool
hilata198cadb2014-02-15 23:46:19 -0600150isValidUri(const std::string& input)
151{
152 // an extended regex to support the validation of uri structure
153 // boost::regex e("^[a-z0-9]+-?+[a-z0-9]+\\:\\/\\/.*");
154 boost::regex e("^[a-z0-9]+\\:.*");
155 return boost::regex_match(input, e);
156}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700157
hilata198cadb2014-02-15 23:46:19 -0600158} // anonymous namespace
159
160void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700161Nfdc::faceCreate(const char* commandOptions[])
hilata198cadb2014-02-15 23:46:19 -0600162{
hilata198cadb2014-02-15 23:46:19 -0600163 const std::string& uri = commandOptions[0];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700164 if (!isValidUri(uri))
hilata198cadb2014-02-15 23:46:19 -0600165 throw Error("invalid uri format");
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700166
167 ControlParameters parameters;
168 parameters
169 .setUri(uri);
170
171 m_controller.start<FaceCreateCommand>(
172 parameters,
173 bind(&Nfdc::onSuccess, this, _1, "Face creation succeeded"),
174 bind(&Nfdc::onError, this, _1, _2, "Face creation failed"));
hilata198cadb2014-02-15 23:46:19 -0600175}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700176
hilata198cadb2014-02-15 23:46:19 -0600177void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700178Nfdc::faceDestroy(const char* commandOptions[])
hilata198cadb2014-02-15 23:46:19 -0600179{
hilata198cadb2014-02-15 23:46:19 -0600180 const int faceId = boost::lexical_cast<int>(commandOptions[0]);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700181
182 ControlParameters parameters;
183 parameters
184 .setFaceId(faceId);
185
186 m_controller.start<FaceDestroyCommand>(
187 parameters,
188 bind(&Nfdc::onSuccess, this, _1, "Face destroy succeeded"),
189 bind(&Nfdc::onError, this, _1, _2, "Face destroy failed"));
hilata198cadb2014-02-15 23:46:19 -0600190}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700191
hilata141eaae2014-03-13 19:54:47 -0500192void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700193Nfdc::strategyChoiceSet(const char* commandOptions[])
hilata141eaae2014-03-13 19:54:47 -0500194{
195 const std::string& name = commandOptions[0];
196 const std::string& strategy = commandOptions[1];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700197
198 ControlParameters parameters;
199 parameters
200 .setName(name)
201 .setStrategy(strategy);
202
203 m_controller.start<StrategyChoiceSetCommand>(
204 parameters,
205 bind(&Nfdc::onSuccess, this, _1, "Successfully set strategy choice"),
206 bind(&Nfdc::onError, this, _1, _2, "Failed to set strategy choice"));
hilata141eaae2014-03-13 19:54:47 -0500207}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700208
hilata141eaae2014-03-13 19:54:47 -0500209void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700210Nfdc::strategyChoiceUnset(const char* commandOptions[])
hilata141eaae2014-03-13 19:54:47 -0500211{
212 const std::string& name = commandOptions[0];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700213
214 ControlParameters parameters;
215 parameters
216 .setName(name);
217
218 m_controller.start<StrategyChoiceUnsetCommand>(
219 parameters,
220 bind(&Nfdc::onSuccess, this, _1, "Successfully unset strategy choice"),
221 bind(&Nfdc::onError, this, _1, _2, "Failed to unset strategy choice"));
hilata141eaae2014-03-13 19:54:47 -0500222}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700223
hilata198cadb2014-02-15 23:46:19 -0600224void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700225Nfdc::onSuccess(const ControlParameters& parameters, const std::string& message)
hilata198cadb2014-02-15 23:46:19 -0600226{
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700227 std::cout << message << ": " << parameters << std::endl;
hilata198cadb2014-02-15 23:46:19 -0600228}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700229
hilata198cadb2014-02-15 23:46:19 -0600230void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700231Nfdc::onError(uint32_t code, const std::string& error, const std::string& message)
hilata198cadb2014-02-15 23:46:19 -0600232{
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700233 std::ostringstream os;
234 os << message << ": " << error << " (code: " << code << ")";
235 throw Error(os.str());
hilata141eaae2014-03-13 19:54:47 -0500236}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700237
hilata141eaae2014-03-13 19:54:47 -0500238} // namespace nfdc
hilata198cadb2014-02-15 23:46:19 -0600239
240int
241main(int argc, char** argv)
242{
243 ndn::Face face;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700244 nfdc::Nfdc p(face);
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800245
hilata198cadb2014-02-15 23:46:19 -0600246 p.m_programName = argv[0];
247 int opt;
248 while ((opt = getopt(argc, argv, "h")) != -1) {
249 switch (opt) {
250 case 'h':
251 usage(p.m_programName);
252 return 0;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700253
hilata198cadb2014-02-15 23:46:19 -0600254 default:
255 usage(p.m_programName);
256 return 1;
257 }
258 }
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800259
260 if (argc == optind) {
261 usage(p.m_programName);
262 return 1;
263 }
264
hilata198cadb2014-02-15 23:46:19 -0600265 try {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700266 bool isOk = p.dispatch(argv[optind],
267 const_cast<const char**>(argv + optind + 1),
268 argc - optind - 1);
269 if (!isOk) {
hilata198cadb2014-02-15 23:46:19 -0600270 usage(p.m_programName);
271 return 1;
272 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700273
hilata198cadb2014-02-15 23:46:19 -0600274 face.processEvents();
275 }
276 catch (const std::exception& e) {
277 std::cerr << "ERROR: " << e.what() << std::endl;
278 return 2;
279 }
280 return 0;
281}