blob: 2f2937f2cbfc9767f0fbea043462e8182d568890 [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"
23 " set-strategy <name> <stratgy>\n"
24 " Set a forwarding strategy for a namespace\n"
25 " create <uri> \n"
26 " Create a face in one of the following formats:\n"
27 " UDP unicast: udp[4|6]://<remote-IP-or-host>[:<remote-port>]\n"
28 " TCP: tcp[4|6]://<remote-IP-or-host>[:<remote-port>] \n"
29 " destroy <faceId> \n"
30 " Destroy a face\n"
31 << std::endl;
32}
33
34namespace nfdc {
35
36Controller::Controller(ndn::Face& face)
37 : ndn::nfd::Controller(face)
38{
39}
40
41Controller::~Controller()
42{
43}
44bool
45Controller::dispatch(const std::string& command, const char* commandOptions[], int nOptions)
46{
hilatadc947ec2014-03-10 12:48:31 -050047 if (command == "add-nexthop") {
hilata198cadb2014-02-15 23:46:19 -060048 if (nOptions == 2)
49 fibAddNextHop(commandOptions, false);
50 else if (nOptions == 3)
51 fibAddNextHop(commandOptions, true);
52 else
53 return false;
54 }
55 else if (command == "remove-nexthop") {
56 if (nOptions != 2)
57 return false;
58 fibRemoveNextHop(commandOptions);
59 }
60 else if (command == "set-strategy") {
61 if (nOptions != 2)
62 return false;
63 fibSetStrategy(commandOptions);
64 }
65 else if (command == "create") {
66 if (nOptions != 1)
67 return false;
68 faceCreate(commandOptions);
69 }
70 else if (command == "destroy") {
71 if (nOptions != 1)
72 return false;
73 faceDestroy(commandOptions);
74 }
75 else
76 usage(m_programName);
77
78 return true;
79}
hilata198cadb2014-02-15 23:46:19 -060080
81void
82Controller::fibAddNextHop(const char* commandOptions[], bool hasCost)
83{
84 ndn::nfd::FibManagementOptions fibOptions;
85
86 const std::string& name = commandOptions[0];
87 const int faceId = boost::lexical_cast<int>(commandOptions[1]);
88
89 fibOptions.setName(name);
90 fibOptions.setFaceId(faceId);
91
92 if (hasCost)
93 {
94 const int cost = boost::lexical_cast<int>(commandOptions[2]);
95 fibOptions.setCost(cost);
96 }
97 startFibCommand("add-nexthop",
98 fibOptions,
99 bind(&Controller::onFibSuccess, this, _1, "Nexthop insertion succeeded"),
100 bind(&Controller::onError, this, _1, "Nexthop insertion failed"));
101}
102
103void
104Controller::fibRemoveNextHop(const char* commandOptions[])
105{
106 const std::string& name = commandOptions[0];
107 const int faceId = boost::lexical_cast<int>(commandOptions[1]);
108 ndn::nfd::FibManagementOptions fibOptions;
109
110 fibOptions.setName(name);
111 fibOptions.setFaceId(faceId);
112 startFibCommand("remove-nexthop",
113 fibOptions,
114 bind(&Controller::onFibSuccess, this, _1, "Nexthop Removal succeeded"),
115 bind(&Controller::onError, this, _1, "Nexthop Removal failed"));
116}
hilata9b27e692014-02-25 15:43:19 -0600117
hilata198cadb2014-02-15 23:46:19 -0600118void
119Controller::fibSetStrategy(const char* commandOptions[])
120{
hilata9b27e692014-02-25 15:43:19 -0600121 const std::string& name = commandOptions[0];
122 const std::string& strategy = commandOptions[1];
123 ndn::nfd::FibManagementOptions fibOptions;
124
125 fibOptions.setName(name);
126 fibOptions.setStrategy(strategy);
127
128 startFibCommand("set-strategy",
129 fibOptions,
130 bind(&Controller::onFibSuccess,this, _1, "Successfully set forwarding strategy"),
131 bind(&Controller::onError,this, _1, "Failed to set forwarding strategy"));
132
hilata198cadb2014-02-15 23:46:19 -0600133}
hilata9b27e692014-02-25 15:43:19 -0600134
hilata198cadb2014-02-15 23:46:19 -0600135namespace {
136bool
137isValidUri(const std::string& input)
138{
139 // an extended regex to support the validation of uri structure
140 // boost::regex e("^[a-z0-9]+-?+[a-z0-9]+\\:\\/\\/.*");
141 boost::regex e("^[a-z0-9]+\\:.*");
142 return boost::regex_match(input, e);
143}
144} // anonymous namespace
145
146void
147Controller::faceCreate(const char* commandOptions[])
148{
149 ndn::nfd::FaceManagementOptions faceOptions;
150 const std::string& uri = commandOptions[0];
151 faceOptions.setUri(uri);
152
153 if (isValidUri(uri))
154 {
155 startFaceCommand("create",
156 faceOptions,
157 bind(&Controller::onFaceSuccess, this, _1, "Face creation succeeded"),
158 bind(&Controller::onError, this, _1, "Face creation failed"));
159 }
160 else
161 throw Error("invalid uri format");
162}
163
164void
165Controller::faceDestroy(const char* commandOptions[])
166{
167 ndn::nfd::FaceManagementOptions faceOptions;
168 const int faceId = boost::lexical_cast<int>(commandOptions[0]);
169 faceOptions.setFaceId(faceId);
170
171 startFaceCommand("destroy",
172 faceOptions,
173 bind(&Controller::onFaceSuccess, this, _1, "Face destroy succeeded"),
174 bind(&Controller::onError, this, _1, "Face destroy failed"));
175}
176
177void
178Controller::onFibSuccess(const ndn::nfd::FibManagementOptions& resp, const std::string& message)
179{
180 std::cout << resp << std::endl;
181}
182
183void
184Controller::onFaceSuccess(const ndn::nfd::FaceManagementOptions& resp, const std::string& message)
185{
186 std::cout << resp << std::endl;
187}
188
189void
190Controller::onError(const std::string& error, const std::string& message)
191{
192 throw Error(message + ": " + error);
193}
194}// namespace nfdc
195
196int
197main(int argc, char** argv)
198{
199 ndn::Face face;
200 nfdc::Controller p(face);
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800201
hilata198cadb2014-02-15 23:46:19 -0600202 p.m_programName = argv[0];
203 int opt;
204 while ((opt = getopt(argc, argv, "h")) != -1) {
205 switch (opt) {
206 case 'h':
207 usage(p.m_programName);
208 return 0;
209
210 default:
211 usage(p.m_programName);
212 return 1;
213 }
214 }
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800215
216 if (argc == optind) {
217 usage(p.m_programName);
218 return 1;
219 }
220
hilata198cadb2014-02-15 23:46:19 -0600221 try {
222 bool hasSucceeded = p.dispatch(argv[optind],
223 const_cast<const char**>(argv + optind + 1),
224 argc - optind - 1);
225 if (hasSucceeded == false) {
226 usage(p.m_programName);
227 return 1;
228 }
229
230 face.processEvents();
231 }
232 catch (const std::exception& e) {
233 std::cerr << "ERROR: " << e.what() << std::endl;
234 return 2;
235 }
236 return 0;
237}
238