blob: 353491777056bbf8b792b4aa470066b894c561bb [file] [log] [blame]
hilata198cadb2014-02-15 23:46:19 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Syed Obaid4ae0ce32014-06-17 13:59:20 -05003 * 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 * 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/>.
Syed Obaid4ae0ce32014-06-17 13:59:20 -050024 */
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070025
hilata198cadb2014-02-15 23:46:19 -060026#include "nfdc.hpp"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070027#include "version.hpp"
28
hilata198cadb2014-02-15 23:46:19 -060029#include <boost/lexical_cast.hpp>
30#include <boost/algorithm/string.hpp>
31#include <boost/algorithm/string/regex_find_format.hpp>
32#include <boost/regex.hpp>
33
34void
35usage(const char* programName)
36{
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070037 std::cout << "Usage:\n" << programName << " [-h] [-V] COMMAND [<Command Options>]\n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070038 " -h print usage and exit\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070039 " -V print version and exit\n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070040 "\n"
Obaiddca50792014-04-24 18:38:40 -050041 " COMMAND can be one of the following:\n"
Syed Obaid4ae0ce32014-06-17 13:59:20 -050042 " register [-I] [-C] [-c cost] [-e expiration time] [-o origin] name <faceId | faceUri>\n"
Obaiddca50792014-04-24 18:38:40 -050043 " register name to the given faceId or faceUri\n"
44 " -I: unset CHILD_INHERIT flag\n"
45 " -C: set CAPTURE flag\n"
46 " -c: specify cost\n"
Syed Obaid4ae0ce32014-06-17 13:59:20 -050047 " -e: specify expiring time in ms\n"
48 " -o: specify origin\n"
49 " 0 for Local producer applications, 128 for NLSR, 255 for static routes\n"
Obaiddca50792014-04-24 18:38:40 -050050 " unregister name <faceId>\n"
51 " unregister name from the given faceId\n"
52 " create <faceUri> \n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070053 " Create a face in one of the following formats:\n"
54 " UDP unicast: udp[4|6]://<remote-IP-or-host>[:<remote-port>]\n"
55 " TCP: tcp[4|6]://<remote-IP-or-host>[:<remote-port>] \n"
Obaiddca50792014-04-24 18:38:40 -050056 " destroy <faceId | faceUri> \n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070057 " Destroy a face\n"
58 " set-strategy <name> <strategy> \n"
59 " Set the strategy for a namespace \n"
60 " unset-strategy <name> \n"
61 " Unset the strategy for a namespace \n"
hilata6ee6e072014-04-20 17:10:18 -050062 " add-nexthop [-c <cost>] <name> <faceId | faceUri>\n"
63 " Add a nexthop to a FIB entry\n"
64 " -c: specify cost\n"
65 " remove-nexthop <name> <faceId> \n"
66 " Remove a nexthop from a FIB entry\n"
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070067 << std::endl;
hilata198cadb2014-02-15 23:46:19 -060068}
69
70namespace nfdc {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070071
Syed Obaid4ae0ce32014-06-17 13:59:20 -050072const ndn::time::milliseconds Nfdc::DEFAULT_EXPIRATION_PERIOD = ndn::time::milliseconds(3600000);
73const uint64_t Nfdc::DEFAULT_COST = 0;
74
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070075Nfdc::Nfdc(ndn::Face& face)
Obaiddca50792014-04-24 18:38:40 -050076 : m_flags(ROUTE_FLAG_CHILD_INHERIT)
Syed Obaid4ae0ce32014-06-17 13:59:20 -050077 , m_cost(DEFAULT_COST)
78 , m_origin(ROUTE_ORIGIN_STATIC)
79 , m_expires(DEFAULT_EXPIRATION_PERIOD)
Obaiddca50792014-04-24 18:38:40 -050080 , m_controller(face)
hilata198cadb2014-02-15 23:46:19 -060081{
82}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070083
84Nfdc::~Nfdc()
hilata198cadb2014-02-15 23:46:19 -060085{
86}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070087
hilata198cadb2014-02-15 23:46:19 -060088bool
hilata54e4eaf2014-04-10 23:38:33 -050089Nfdc::dispatch(const std::string& command)
hilata198cadb2014-02-15 23:46:19 -060090{
Obaiddca50792014-04-24 18:38:40 -050091 if (command == "add-nexthop") {
92 if (m_nOptions != 2)
hilata54e4eaf2014-04-10 23:38:33 -050093 return false;
Obaiddca50792014-04-24 18:38:40 -050094 fibAddNextHop();
hilata198cadb2014-02-15 23:46:19 -060095 }
96 else if (command == "remove-nexthop") {
hilata54e4eaf2014-04-10 23:38:33 -050097 if (m_nOptions != 2)
hilata198cadb2014-02-15 23:46:19 -060098 return false;
hilata54e4eaf2014-04-10 23:38:33 -050099 fibRemoveNextHop();
hilata198cadb2014-02-15 23:46:19 -0600100 }
Obaiddca50792014-04-24 18:38:40 -0500101 else if (command == "register") {
102 if (m_nOptions != 2)
103 return false;
104 ribRegisterPrefix();
105 }
106 else if (command == "unregister") {
107 if (m_nOptions != 2)
108 return false;
109 ribUnregisterPrefix();
110 }
hilata198cadb2014-02-15 23:46:19 -0600111 else if (command == "create") {
hilata54e4eaf2014-04-10 23:38:33 -0500112 if (m_nOptions != 1)
hilata198cadb2014-02-15 23:46:19 -0600113 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500114 faceCreate();
hilata198cadb2014-02-15 23:46:19 -0600115 }
116 else if (command == "destroy") {
hilata54e4eaf2014-04-10 23:38:33 -0500117 if (m_nOptions != 1)
hilata198cadb2014-02-15 23:46:19 -0600118 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500119 faceDestroy();
hilata198cadb2014-02-15 23:46:19 -0600120 }
hilata141eaae2014-03-13 19:54:47 -0500121 else if (command == "set-strategy") {
hilata54e4eaf2014-04-10 23:38:33 -0500122 if (m_nOptions != 2)
hilata141eaae2014-03-13 19:54:47 -0500123 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500124 strategyChoiceSet();
hilata141eaae2014-03-13 19:54:47 -0500125 }
126 else if (command == "unset-strategy") {
hilata54e4eaf2014-04-10 23:38:33 -0500127 if (m_nOptions != 1)
hilata141eaae2014-03-13 19:54:47 -0500128 return false;
hilata54e4eaf2014-04-10 23:38:33 -0500129 strategyChoiceUnset();
hilata141eaae2014-03-13 19:54:47 -0500130 }
hilata198cadb2014-02-15 23:46:19 -0600131 else
132 usage(m_programName);
133
134 return true;
135}
hilata198cadb2014-02-15 23:46:19 -0600136
hilata198cadb2014-02-15 23:46:19 -0600137namespace {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700138
139inline bool
hilata198cadb2014-02-15 23:46:19 -0600140isValidUri(const std::string& input)
141{
142 // an extended regex to support the validation of uri structure
143 // boost::regex e("^[a-z0-9]+-?+[a-z0-9]+\\:\\/\\/.*");
144 boost::regex e("^[a-z0-9]+\\:.*");
145 return boost::regex_match(input, e);
146}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700147
hilata198cadb2014-02-15 23:46:19 -0600148} // anonymous namespace
149
150void
Obaiddca50792014-04-24 18:38:40 -0500151Nfdc::fibAddNextHop()
hilata198cadb2014-02-15 23:46:19 -0600152{
Obaiddca50792014-04-24 18:38:40 -0500153 m_name = m_commandLineArguments[0];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700154 ControlParameters parameters;
155 parameters
Obaiddca50792014-04-24 18:38:40 -0500156 .setName(m_name)
157 .setCost(m_cost);
hilata54e4eaf2014-04-10 23:38:33 -0500158
Obaiddca50792014-04-24 18:38:40 -0500159 if (!isValidUri(m_commandLineArguments[1])) {
160 try { //So the uri is not valid, may be a faceId is provided.
161 m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
162 }
163 catch (const std::exception& e) {
164 std::cerr << "No valid faceUri or faceId is provided"<< std::endl;
165 return;
166 }
167 parameters.setFaceId(m_faceId);
168 fibAddNextHop(parameters);
hilata54e4eaf2014-04-10 23:38:33 -0500169 }
Obaiddca50792014-04-24 18:38:40 -0500170 else {
171 ControlParameters faceParameters;
172 faceParameters.setUri(m_commandLineArguments[1]);
hilata54e4eaf2014-04-10 23:38:33 -0500173
Obaiddca50792014-04-24 18:38:40 -0500174 m_controller.start<FaceCreateCommand>(faceParameters,
175 bind(&Nfdc::fibAddNextHop, this, _1),
176 bind(&Nfdc::onError, this, _1, _2,
177 "Face creation failed"));
178 }
179}
180
181void
182Nfdc::fibAddNextHop(const ControlParameters& faceCreateResult)
183{
184 ControlParameters ribParameters;
185 ribParameters
186 .setName(m_name)
187 .setCost(m_cost)
188 .setFaceId(faceCreateResult.getFaceId());
189
190 m_controller.start<FibAddNextHopCommand>(ribParameters,
191 bind(&Nfdc::onSuccess, this, _1,
192 "Nexthop insertion succeeded"),
193 bind(&Nfdc::onError, this, _1, _2,
194 "Nexthop insertion failed"));
hilata54e4eaf2014-04-10 23:38:33 -0500195}
196
197void
198Nfdc::fibRemoveNextHop()
199{
Obaiddca50792014-04-24 18:38:40 -0500200 m_name = m_commandLineArguments[0];
201 try {
202 m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
203 }
204 catch (const std::exception& e) {
205 std::cerr << "No valid faceUri or faceId is provided"<< std::endl;
206 return;
207 }
hilata54e4eaf2014-04-10 23:38:33 -0500208
209 ControlParameters parameters;
210 parameters
Obaiddca50792014-04-24 18:38:40 -0500211 .setName(m_name)
212 .setFaceId(m_faceId);
hilata54e4eaf2014-04-10 23:38:33 -0500213
Obaiddca50792014-04-24 18:38:40 -0500214 m_controller.start<FibRemoveNextHopCommand>(parameters,
215 bind(&Nfdc::onSuccess, this, _1,
216 "Nexthop removal succeeded"),
217 bind(&Nfdc::onError, this, _1, _2,
218 "Nexthop removal failed"));
219}
220
221void
222Nfdc::ribRegisterPrefix()
223{
224 m_name = m_commandLineArguments[0];
225 ControlParameters parameters;
226 parameters
227 .setName(m_name)
228 .setCost(m_cost)
Syed Obaid4ae0ce32014-06-17 13:59:20 -0500229 .setFlags(m_flags)
230 .setOrigin(m_origin)
231 .setExpirationPeriod(m_expires);
Obaiddca50792014-04-24 18:38:40 -0500232
233 if (!isValidUri(m_commandLineArguments[1])) {
234 try { //So the uri is not valid, may be a faceId is provided.
235 m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
236 }
237 catch (const std::exception& e) {
238 std::cerr << "No valid faceUri or faceId is provided"<< std::endl;
239 return;
240 }
241 parameters.setFaceId(m_faceId);
242 ribRegisterPrefix(parameters);
243 }
244 else {
245 ControlParameters faceParameters;
246 faceParameters.setUri(m_commandLineArguments[1]);
247
248 m_controller.start<FaceCreateCommand>(faceParameters,
249 bind(&Nfdc::ribRegisterPrefix, this, _1),
250 bind(&Nfdc::onError, this, _1, _2,
251 "Face creation failed"));
252 }
253}
254
255void
256Nfdc::ribRegisterPrefix(const ControlParameters& faceCreateResult)
257{
258 ControlParameters ribParameters;
259 ribParameters
260 .setName(m_name)
261 .setCost(m_cost)
262 .setFlags(m_flags)
Syed Obaid4ae0ce32014-06-17 13:59:20 -0500263 .setExpirationPeriod(m_expires)
264 .setOrigin(m_origin)
Obaiddca50792014-04-24 18:38:40 -0500265 .setFaceId(faceCreateResult.getFaceId());
266
267 m_controller.start<RibRegisterCommand>(ribParameters,
268 bind(&Nfdc::onSuccess, this, _1,
269 "Successful in name registration"),
270 bind(&Nfdc::onError, this, _1, _2,
271 "Failed in name registration"));
272}
273
274void
275Nfdc::ribUnregisterPrefix()
276{
277 m_name = m_commandLineArguments[0];
278 try {
279 m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
280 }
281 catch (const std::exception& e) {
Syed Obaid4ae0ce32014-06-17 13:59:20 -0500282 std::cerr << "No valid faceId is provided" << std::endl;
Obaiddca50792014-04-24 18:38:40 -0500283 return;
284 }
285
286 ControlParameters parameters;
287 parameters
288 .setName(m_name)
289 .setFaceId(m_faceId);
290
291 m_controller.start<RibUnregisterCommand>(parameters,
292 bind(&Nfdc::onSuccess, this, _1,
293 "Successful in unregistering name"),
294 bind(&Nfdc::onError, this, _1, _2,
295 "Failed in unregistering name"));
hilata54e4eaf2014-04-10 23:38:33 -0500296}
297
298void
299Nfdc::faceCreate()
300{
301 if (!isValidUri(m_commandLineArguments[0]))
302 throw Error("invalid uri format");
303
304 ControlParameters parameters;
Obaiddca50792014-04-24 18:38:40 -0500305 parameters.setUri(m_commandLineArguments[0]);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700306
Obaiddca50792014-04-24 18:38:40 -0500307 m_controller.start<FaceCreateCommand>(parameters,
308 bind(&Nfdc::onSuccess, this, _1,
309 "Face creation succeeded"),
310 bind(&Nfdc::onError, this, _1, _2,
311 "Face creation failed"));
hilata198cadb2014-02-15 23:46:19 -0600312}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700313
hilata198cadb2014-02-15 23:46:19 -0600314void
hilata54e4eaf2014-04-10 23:38:33 -0500315Nfdc::faceDestroy()
hilata198cadb2014-02-15 23:46:19 -0600316{
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700317 ControlParameters parameters;
Obaiddca50792014-04-24 18:38:40 -0500318 if (!isValidUri(m_commandLineArguments[0])) {
319 try { //So the uri is not valid, may be a faceId is provided.
320 m_faceId = boost::lexical_cast<int>(m_commandLineArguments[0]);
321 }
322 catch (const std::exception& e) {
323 std::cerr << "No valid faceUri or faceId is provided" << std::endl;
324 return;
325 }
326 parameters.setFaceId(m_faceId);
327 faceDestroy(parameters);
328 }
329 else{
330 ControlParameters faceParameters;
331 faceParameters.setUri(m_commandLineArguments[0]);
332 m_controller.start<FaceCreateCommand>(faceParameters,
333 bind(&Nfdc::faceDestroy, this, _1),
334 bind(&Nfdc::onError, this, _1, _2,
335 "Face destroy failed"));
336 }
337}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700338
Obaiddca50792014-04-24 18:38:40 -0500339void
340Nfdc::faceDestroy(const ControlParameters& faceCreateResult)
341{
342 ControlParameters faceParameters;
343 faceParameters.setFaceId(faceCreateResult.getFaceId());
344
345 m_controller.start<FaceDestroyCommand>(faceParameters,
346 bind(&Nfdc::onSuccess, this, _1,
347 "Face destroy succeeded"),
348 bind(&Nfdc::onError, this, _1, _2,
349 "Face destroy failed"));
hilata198cadb2014-02-15 23:46:19 -0600350}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700351
hilata141eaae2014-03-13 19:54:47 -0500352void
hilata54e4eaf2014-04-10 23:38:33 -0500353Nfdc::strategyChoiceSet()
hilata141eaae2014-03-13 19:54:47 -0500354{
hilata54e4eaf2014-04-10 23:38:33 -0500355 const std::string& name = m_commandLineArguments[0];
356 const std::string& strategy = m_commandLineArguments[1];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700357
358 ControlParameters parameters;
359 parameters
360 .setName(name)
361 .setStrategy(strategy);
362
Obaiddca50792014-04-24 18:38:40 -0500363 m_controller.start<StrategyChoiceSetCommand>(parameters,
364 bind(&Nfdc::onSuccess, this, _1,
365 "Successfully set strategy choice"),
366 bind(&Nfdc::onError, this, _1, _2,
367 "Failed to set strategy choice"));
hilata141eaae2014-03-13 19:54:47 -0500368}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700369
hilata141eaae2014-03-13 19:54:47 -0500370void
hilata54e4eaf2014-04-10 23:38:33 -0500371Nfdc::strategyChoiceUnset()
hilata141eaae2014-03-13 19:54:47 -0500372{
hilata54e4eaf2014-04-10 23:38:33 -0500373 const std::string& name = m_commandLineArguments[0];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700374
375 ControlParameters parameters;
Obaiddca50792014-04-24 18:38:40 -0500376 parameters.setName(name);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700377
Obaiddca50792014-04-24 18:38:40 -0500378 m_controller.start<StrategyChoiceUnsetCommand>(parameters,
379 bind(&Nfdc::onSuccess, this, _1,
380 "Successfully unset strategy choice"),
381 bind(&Nfdc::onError, this, _1, _2,
382 "Failed to unset strategy choice"));
hilata141eaae2014-03-13 19:54:47 -0500383}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700384
hilata198cadb2014-02-15 23:46:19 -0600385void
Obaiddca50792014-04-24 18:38:40 -0500386Nfdc::onSuccess(const ControlParameters& commandSuccessResult, const std::string& message)
hilata198cadb2014-02-15 23:46:19 -0600387{
Obaiddca50792014-04-24 18:38:40 -0500388 std::cout << message << ": " << commandSuccessResult << std::endl;
hilata198cadb2014-02-15 23:46:19 -0600389}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700390
hilata198cadb2014-02-15 23:46:19 -0600391void
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700392Nfdc::onError(uint32_t code, const std::string& error, const std::string& message)
hilata198cadb2014-02-15 23:46:19 -0600393{
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700394 std::ostringstream os;
395 os << message << ": " << error << " (code: " << code << ")";
396 throw Error(os.str());
hilata141eaae2014-03-13 19:54:47 -0500397}
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700398
Obaiddca50792014-04-24 18:38:40 -0500399
400
hilata141eaae2014-03-13 19:54:47 -0500401} // namespace nfdc
hilata198cadb2014-02-15 23:46:19 -0600402
403int
404main(int argc, char** argv)
405{
406 ndn::Face face;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700407 nfdc::Nfdc p(face);
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800408
hilata198cadb2014-02-15 23:46:19 -0600409 p.m_programName = argv[0];
hilata54e4eaf2014-04-10 23:38:33 -0500410
Obaiddca50792014-04-24 18:38:40 -0500411 if (argc < 2) {
412 usage(p.m_programName);
413 return 0;
414 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700415
Obaiddca50792014-04-24 18:38:40 -0500416 if (!strcmp(argv[1], "-h")) {
417 usage(p.m_programName);
418 return 0;
419 }
420
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700421 if (!strcmp(argv[1], "-V")) {
422 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
423 return 0;
424 }
425
Junxiao Shi22295032014-04-29 22:57:40 -0700426 ::optind = 2; //start reading options from 2nd argument i.e. Command
Obaiddca50792014-04-24 18:38:40 -0500427 int opt;
Syed Obaid4ae0ce32014-06-17 13:59:20 -0500428 while ((opt = ::getopt(argc, argv, "ICc:e:o:")) != -1) {
Obaiddca50792014-04-24 18:38:40 -0500429 switch (opt) {
430 case 'I':
431 p.m_flags = p.m_flags & ~(nfdc::ROUTE_FLAG_CHILD_INHERIT);
432 break;
433
434 case 'C':
435 p.m_flags = p.m_flags | nfdc::ROUTE_FLAG_CAPTURE;
436 break;
437
438 case 'c':
439 try {
Syed Obaid4ae0ce32014-06-17 13:59:20 -0500440 p.m_cost = boost::lexical_cast<uint64_t>(::optarg);
Obaiddca50792014-04-24 18:38:40 -0500441 }
Junxiao Shi22295032014-04-29 22:57:40 -0700442 catch (boost::bad_lexical_cast&) {
Syed Obaid4ae0ce32014-06-17 13:59:20 -0500443 std::cerr << "Error: cost must be in unsigned integer format" << std::endl;
444 return 1;
445 }
446 break;
447
448 case 'e':
449 uint64_t expires;
450 try {
451 expires = boost::lexical_cast<uint64_t>(::optarg);
452 }
453 catch (boost::bad_lexical_cast&) {
454 std::cerr << "Error: expiration time must be in unsigned integer format" << std::endl;
455 return 1;
456 }
457 p.m_expires = ndn::time::milliseconds(expires);
458 break;
459
460 case 'o':
461 try {
462 p.m_origin = boost::lexical_cast<uint64_t>(::optarg);
463 }
464 catch (boost::bad_lexical_cast&) {
465 std::cerr << "Error: origin must be in unsigned integer format" << std::endl;
hilata198cadb2014-02-15 23:46:19 -0600466 return 1;
Obaiddca50792014-04-24 18:38:40 -0500467 }
468 break;
Junxiao Shi22295032014-04-29 22:57:40 -0700469
Obaiddca50792014-04-24 18:38:40 -0500470 default:
471 usage(p.m_programName);
472 return 1;
hilata198cadb2014-02-15 23:46:19 -0600473 }
474 }
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800475
Junxiao Shi22295032014-04-29 22:57:40 -0700476 if (argc == ::optind) {
Alexander Afanasyev9f935b82014-02-24 15:14:22 -0800477 usage(p.m_programName);
478 return 1;
479 }
480
hilata198cadb2014-02-15 23:46:19 -0600481 try {
Junxiao Shi22295032014-04-29 22:57:40 -0700482 p.m_commandLineArguments = argv + ::optind;
483 p.m_nOptions = argc - ::optind;
Obaiddca50792014-04-24 18:38:40 -0500484
485 //argv[1] points to the command, so pass it to the dispatch
486 bool isOk = p.dispatch(argv[1]);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700487 if (!isOk) {
hilata198cadb2014-02-15 23:46:19 -0600488 usage(p.m_programName);
489 return 1;
490 }
hilata198cadb2014-02-15 23:46:19 -0600491 face.processEvents();
492 }
493 catch (const std::exception& e) {
494 std::cerr << "ERROR: " << e.what() << std::endl;
495 return 2;
496 }
497 return 0;
498}