blob: 285bd9d8d3c9885c5abfe9e855ade5a4ade9289e [file] [log] [blame]
hilata198cadb2014-02-15 23:46:19 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (C) 2014 Named Data Networking Project
4 * See COPYING for copyright and distribution information.
5 */
6#include "nfdc.hpp"
7#include <boost/lexical_cast.hpp>
8#include <boost/algorithm/string.hpp>
9#include <boost/algorithm/string/regex_find_format.hpp>
10#include <boost/regex.hpp>
11
12void
13usage(const char* programName)
14{
15 std::cout << "Usage:\n" << programName << " [-h] COMMAND\n"
16 " -h print usage and exit\n"
17 "\n"
18 " COMMAND can be one of following:\n"
hilata198cadb2014-02-15 23:46:19 -060019 " add-nexthop <name> <faceId> [<cost>]\n"
hilatadc947ec2014-03-10 12:48:31 -050020 " Add a nexthop to a FIB entry\n"
hilata198cadb2014-02-15 23:46:19 -060021 " remove-nexthop <name> <faceId> \n"
22 " Remove a nexthop from a FIB entry\n"
hilata198cadb2014-02-15 23:46:19 -060023 " create <uri> \n"
24 " Create a face in one of the following formats:\n"
25 " UDP unicast: udp[4|6]://<remote-IP-or-host>[:<remote-port>]\n"
26 " TCP: tcp[4|6]://<remote-IP-or-host>[:<remote-port>] \n"
27 " destroy <faceId> \n"
28 " Destroy a face\n"
hilata141eaae2014-03-13 19:54:47 -050029 " set-strategy <name> <strategy> \n"
30 " Set the strategy for a namespace \n"
31 " unset-strategy <name> \n"
32 " Unset the strategy for a namespace \n"
hilata198cadb2014-02-15 23:46:19 -060033 << std::endl;
34}
35
36namespace nfdc {
37
38Controller::Controller(ndn::Face& face)
39 : ndn::nfd::Controller(face)
40{
41}
42
43Controller::~Controller()
44{
45}
46bool
47Controller::dispatch(const std::string& command, const char* commandOptions[], int nOptions)
48{
hilatadc947ec2014-03-10 12:48:31 -050049 if (command == "add-nexthop") {
hilata198cadb2014-02-15 23:46:19 -060050 if (nOptions == 2)
51 fibAddNextHop(commandOptions, false);
52 else if (nOptions == 3)
53 fibAddNextHop(commandOptions, true);
54 else
55 return false;
56 }
57 else if (command == "remove-nexthop") {
58 if (nOptions != 2)
59 return false;
60 fibRemoveNextHop(commandOptions);
61 }
hilata198cadb2014-02-15 23:46:19 -060062 else if (command == "create") {
63 if (nOptions != 1)
64 return false;
65 faceCreate(commandOptions);
66 }
67 else if (command == "destroy") {
68 if (nOptions != 1)
69 return false;
70 faceDestroy(commandOptions);
71 }
hilata141eaae2014-03-13 19:54:47 -050072 else if (command == "set-strategy") {
73 if (nOptions != 2)
74 return false;
75 strategyChoiceSet(commandOptions);
76 }
77 else if (command == "unset-strategy") {
78 if (nOptions != 1)
79 return false;
80 strategyChoiceUnset(commandOptions);
81 }
hilata198cadb2014-02-15 23:46:19 -060082 else
83 usage(m_programName);
84
85 return true;
86}
hilata198cadb2014-02-15 23:46:19 -060087
88void
89Controller::fibAddNextHop(const char* commandOptions[], bool hasCost)
90{
91 ndn::nfd::FibManagementOptions fibOptions;
92
93 const std::string& name = commandOptions[0];
94 const int faceId = boost::lexical_cast<int>(commandOptions[1]);
95
96 fibOptions.setName(name);
97 fibOptions.setFaceId(faceId);
98
99 if (hasCost)
100 {
101 const int cost = boost::lexical_cast<int>(commandOptions[2]);
102 fibOptions.setCost(cost);
103 }
104 startFibCommand("add-nexthop",
105 fibOptions,
106 bind(&Controller::onFibSuccess, this, _1, "Nexthop insertion succeeded"),
107 bind(&Controller::onError, this, _1, "Nexthop insertion failed"));
108}
109
110void
111Controller::fibRemoveNextHop(const char* commandOptions[])
112{
113 const std::string& name = commandOptions[0];
114 const int faceId = boost::lexical_cast<int>(commandOptions[1]);
115 ndn::nfd::FibManagementOptions fibOptions;
116
117 fibOptions.setName(name);
118 fibOptions.setFaceId(faceId);
119 startFibCommand("remove-nexthop",
120 fibOptions,
121 bind(&Controller::onFibSuccess, this, _1, "Nexthop Removal succeeded"),
122 bind(&Controller::onError, this, _1, "Nexthop Removal failed"));
123}
hilata9b27e692014-02-25 15:43:19 -0600124
hilata198cadb2014-02-15 23:46:19 -0600125namespace {
126bool
127isValidUri(const std::string& input)
128{
129 // an extended regex to support the validation of uri structure
130 // boost::regex e("^[a-z0-9]+-?+[a-z0-9]+\\:\\/\\/.*");
131 boost::regex e("^[a-z0-9]+\\:.*");
132 return boost::regex_match(input, e);
133}
134} // anonymous namespace
135
136void
137Controller::faceCreate(const char* commandOptions[])
138{
139 ndn::nfd::FaceManagementOptions faceOptions;
140 const std::string& uri = commandOptions[0];
141 faceOptions.setUri(uri);
142
143 if (isValidUri(uri))
144 {
145 startFaceCommand("create",
146 faceOptions,
147 bind(&Controller::onFaceSuccess, this, _1, "Face creation succeeded"),
148 bind(&Controller::onError, this, _1, "Face creation failed"));
149 }
150 else
151 throw Error("invalid uri format");
152}
153
154void
155Controller::faceDestroy(const char* commandOptions[])
156{
157 ndn::nfd::FaceManagementOptions faceOptions;
158 const int faceId = boost::lexical_cast<int>(commandOptions[0]);
159 faceOptions.setFaceId(faceId);
160
161 startFaceCommand("destroy",
162 faceOptions,
163 bind(&Controller::onFaceSuccess, this, _1, "Face destroy succeeded"),
164 bind(&Controller::onError, this, _1, "Face destroy failed"));
165}
hilata141eaae2014-03-13 19:54:47 -0500166
167void
168Controller::strategyChoiceSet(const char* commandOptions[])
169{
170 const std::string& name = commandOptions[0];
171 const std::string& strategy = commandOptions[1];
172 ndn::nfd::StrategyChoiceOptions strategyChoiceOptions;
173
174 strategyChoiceOptions.setName(name);
175 strategyChoiceOptions.setStrategy(strategy);
176
177 startStrategyChoiceCommand("set",
178 strategyChoiceOptions,
179 bind(&Controller::onSetStrategySuccess,
180 this,
181 _1,
182 "Successfully set strategy choice"),
183 bind(&Controller::onError, this, _1, "Failed to set strategy choice"));
184
185}
186
187void
188Controller::strategyChoiceUnset(const char* commandOptions[])
189{
190 const std::string& name = commandOptions[0];
191 ndn::nfd::StrategyChoiceOptions strategyChoiceOptions;
192
193 strategyChoiceOptions.setName(name);
194 startStrategyChoiceCommand("unset",
195 strategyChoiceOptions,
196 bind(&Controller::onSetStrategySuccess,
197 this,
198 _1,
199 "Successfully unset strategy choice"),
200 bind(&Controller::onError, this, _1, "Failed to unset strategy choice"));
201}
202
hilata198cadb2014-02-15 23:46:19 -0600203void
204Controller::onFibSuccess(const ndn::nfd::FibManagementOptions& resp, const std::string& message)
205{
hilata141eaae2014-03-13 19:54:47 -0500206 std::cout << message << ": " << resp << std::endl;
hilata198cadb2014-02-15 23:46:19 -0600207}
208
209void
210Controller::onFaceSuccess(const ndn::nfd::FaceManagementOptions& resp, const std::string& message)
211{
hilata141eaae2014-03-13 19:54:47 -0500212 std::cout << message << ": " << resp << std::endl;
213}
214void
215Controller::onSetStrategySuccess(const ndn::nfd::StrategyChoiceOptions& resp,
216 const std::string& message)
217{
218 std::cout << message << ": " << resp << std::endl;
hilata198cadb2014-02-15 23:46:19 -0600219}
220
221void
222Controller::onError(const std::string& error, const std::string& message)
223{
224 throw Error(message + ": " + error);
225}
hilata141eaae2014-03-13 19:54:47 -0500226} // namespace nfdc
hilata198cadb2014-02-15 23:46:19 -0600227
228int
229main(int argc, char** argv)
230{
231 ndn::Face face;
232 nfdc::Controller p(face);
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800233
hilata198cadb2014-02-15 23:46:19 -0600234 p.m_programName = argv[0];
235 int opt;
236 while ((opt = getopt(argc, argv, "h")) != -1) {
237 switch (opt) {
238 case 'h':
239 usage(p.m_programName);
240 return 0;
241
242 default:
243 usage(p.m_programName);
244 return 1;
245 }
246 }
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800247
248 if (argc == optind) {
249 usage(p.m_programName);
250 return 1;
251 }
252
hilata198cadb2014-02-15 23:46:19 -0600253 try {
254 bool hasSucceeded = p.dispatch(argv[optind],
255 const_cast<const char**>(argv + optind + 1),
256 argc - optind - 1);
257 if (hasSucceeded == false) {
258 usage(p.m_programName);
259 return 1;
260 }
261
262 face.processEvents();
263 }
264 catch (const std::exception& e) {
265 std::cerr << "ERROR: " << e.what() << std::endl;
266 return 2;
267 }
268 return 0;
269}
270