blob: a3c804144aeb5513fc367114acb6d931dd66b91e [file] [log] [blame]
hilatadd50ada2014-03-13 12:48:47 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -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 * 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/>.
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -070024 */
Davide Pesavento6fc750f2014-03-18 19:49:39 +010025
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070026#include "version.hpp"
27
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -070028#include "core/face-uri.hpp"
29
Alexander Afanasyev4a771362014-04-24 21:29:33 -070030#include <ndn-cxx/face.hpp>
31#include <ndn-cxx/management/nfd-controller.hpp>
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -070032#include <ndn-cxx/management/nfd-face-status.hpp>
Alexander Afanasyev4a771362014-04-24 21:29:33 -070033#include <ndn-cxx/security/key-chain.hpp>
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -070034#include <ndn-cxx/encoding/buffer-stream.hpp>
hilatadd50ada2014-03-13 12:48:47 -050035
Alexander Afanasyevb3893c92014-05-15 01:49:54 -070036#include <boost/lexical_cast.hpp>
37
hilatadd50ada2014-03-13 12:48:47 -050038#include <sys/types.h>
39#include <netinet/in.h>
40#include <arpa/nameser.h>
41#include <resolv.h>
42
43#ifdef __APPLE__
44#include <arpa/nameser_compat.h>
45#endif
46
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -070047namespace ndn {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070048namespace tools {
49
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070050void
51usage(const char* programName)
52{
53 std::cout << "Usage:\n" << programName << " [-h] [-V]\n"
54 << " -h - print usage and exit\n"
55 << " -V - print version number and exit\n"
56 << std::endl;
57}
58
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070059class NdnAutoconfig
hilatadd50ada2014-03-13 12:48:47 -050060{
61public:
62 union QueryAnswer
63 {
64 HEADER header;
65 uint8_t buf[NS_PACKETSZ];
66 };
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070067
68 class Error : public std::runtime_error
hilatadd50ada2014-03-13 12:48:47 -050069 {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070070 public:
71 explicit
72 Error(const std::string& what)
73 : std::runtime_error(what)
hilatadd50ada2014-03-13 12:48:47 -050074 {
75 }
76 };
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070077
hilatadd50ada2014-03-13 12:48:47 -050078 explicit
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070079 NdnAutoconfig()
80 : m_controller(m_face)
hilatadd50ada2014-03-13 12:48:47 -050081 {
82 }
Davide Pesavento6fc750f2014-03-18 19:49:39 +010083
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -070084 void
85 run()
86 {
87 m_face.processEvents();
88 }
89
90 void
91 fetchSegments(const Data& data, const shared_ptr<OBufferStream>& buffer,
92 void (NdnAutoconfig::*onDone)(const shared_ptr<OBufferStream>&))
93 {
94 buffer->write(reinterpret_cast<const char*>(data.getContent().value()),
95 data.getContent().value_size());
96
97 uint64_t currentSegment = data.getName().get(-1).toSegment();
98
99 const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
100 if (finalBlockId.empty() ||
101 finalBlockId.toSegment() > currentSegment)
102 {
103 m_face.expressInterest(data.getName().getPrefix(-1).appendSegment(currentSegment+1),
104 bind(&NdnAutoconfig::fetchSegments, this, _2, buffer, onDone),
105 bind(&NdnAutoconfig::discoverHubStage2, this, "Timeout"));
106 }
107 else
108 {
109 return (this->*onDone)(buffer);
110 }
111 }
112
hilatadd50ada2014-03-13 12:48:47 -0500113 void
114 discoverHubStage1()
115 {
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700116 shared_ptr<OBufferStream> buffer = make_shared<OBufferStream>();
117
118 Interest interest("/localhost/nfd/faces/list");
119 interest.setChildSelector(1);
120 interest.setMustBeFresh(true);
121
122 m_face.expressInterest(interest,
123 bind(&NdnAutoconfig::fetchSegments, this, _2, buffer,
124 &NdnAutoconfig::discoverHubStage1_registerLocalhubNdnAutoconfHub),
125 bind(&NdnAutoconfig::discoverHubStage2, this, "Timeout"));
126 }
127
128 void
129 discoverHubStage1_registerLocalhubNdnAutoconfHub(const shared_ptr<OBufferStream>& buffer)
130 {
131 ConstBufferPtr buf = buffer->buf();
132 std::vector<uint64_t> multicastFaces;
133
134 size_t offset = 0;
135 while (offset < buf->size())
136 {
137 Block block;
138 bool ok = Block::fromBuffer(buf, offset, block);
139 if (!ok)
140 {
141 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
142 break;
143 }
144
145 offset += block.size();
146
147 nfd::FaceStatus faceStatus(block);
148
149 ::nfd::FaceUri uri(faceStatus.getRemoteUri());
150 if (uri.getScheme() == "udp4") {
151 namespace ip = boost::asio::ip;
152 boost::system::error_code ec;
153 ip::address address = ip::address::from_string(uri.getHost(), ec);
154
155 if (!ec && address.is_multicast()) {
156 multicastFaces.push_back(faceStatus.getFaceId());
157 }
158 else
159 continue;
160 }
161 }
162
163 if (multicastFaces.empty()) {
164 discoverHubStage2("No multicast faces available, skipping stage 1");
165 }
166 else {
167 shared_ptr<nfd::Controller> controller = make_shared<nfd::Controller>(ref(m_face));
168 shared_ptr<std::pair<size_t, size_t> > nRegistrations =
169 make_shared<std::pair<size_t, size_t> >(0, 0);
170
171 nfd::ControlParameters parameters;
172 parameters
173 .setName("/localhop/ndn-autoconf/hub")
174 .setCost(1);
175
176 nRegistrations->first = multicastFaces.size();
177
178 for (std::vector<uint64_t>::iterator i = multicastFaces.begin();
179 i != multicastFaces.end(); ++i) {
180 parameters.setFaceId(*i);
181
182 controller->start<nfd::RibRegisterCommand>(parameters,
183 bind(&NdnAutoconfig::discoverHubStage1_onRegisterSuccess,
184 this, controller, nRegistrations),
185 bind(&NdnAutoconfig::discoverHubStage1_onRegisterFailure,
186 this, _1, _2, controller, nRegistrations));
187 }
188 }
189 }
190
191 void
192 discoverHubStage1_onRegisterSuccess(const shared_ptr<nfd::Controller>& controller,
193 const shared_ptr<std::pair<size_t, size_t> >& nRegistrations)
194 {
195 nRegistrations->second++;
196
197 if (nRegistrations->first == nRegistrations->second) {
198 discoverHubStage1_requestHubData();
199 }
200 }
201
202 void
203 discoverHubStage1_onRegisterFailure(uint32_t code, const std::string& error,
204 const shared_ptr<nfd::Controller> controller,
205 const shared_ptr<std::pair<size_t, size_t> >& nRegistrations)
206 {
207 std::cerr << "ERROR: " << error << " (code: " << code << ")" << std::endl;
208 nRegistrations->first--;
209
210 if (nRegistrations->first == nRegistrations->second) {
211 if (nRegistrations->first > 0) {
212 discoverHubStage1_requestHubData();
213 } else {
214 discoverHubStage2("Failed to register /localhop/ndn-autoconf/hub for all multicast faces");
215 }
216 }
217 }
218
219 // Start to look for a hub (NDN hub discovery first stage)
220 void
221 discoverHubStage1_requestHubData()
222 {
223 Interest interest(Name("/localhop/ndn-autoconf/hub"));
224 interest.setInterestLifetime(time::milliseconds(4000)); // 4 seconds
hilatadd50ada2014-03-13 12:48:47 -0500225 interest.setMustBeFresh(true);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700226
hilata3a4eb5c2014-04-29 00:32:05 -0500227 std::cerr << "Stage 1: Trying multicast discovery..." << std::endl;
hilatadd50ada2014-03-13 12:48:47 -0500228 m_face.expressInterest(interest,
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700229 bind(&NdnAutoconfig::onDiscoverHubStage1Success, this, _1, _2),
230 bind(&NdnAutoconfig::discoverHubStage2, this, "Timeout"));
hilatadd50ada2014-03-13 12:48:47 -0500231 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700232
hilatadd50ada2014-03-13 12:48:47 -0500233 // First stage OnData Callback
234 void
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700235 onDiscoverHubStage1Success(const Interest& interest, Data& data)
hilatadd50ada2014-03-13 12:48:47 -0500236 {
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700237 const Block& content = data.getContent();
hilatadd50ada2014-03-13 12:48:47 -0500238 content.parse();
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700239
hilatadd50ada2014-03-13 12:48:47 -0500240 // Get Uri
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700241 Block::element_const_iterator blockValue = content.find(tlv::nfd::Uri);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700242 if (blockValue == content.elements_end())
hilatadd50ada2014-03-13 12:48:47 -0500243 {
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700244 discoverHubStage2("Incorrect reply to stage1");
hilatadd50ada2014-03-13 12:48:47 -0500245 return;
246 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700247 std::string faceMgmtUri(reinterpret_cast<const char*>(blockValue->value()),
248 blockValue->value_size());
hilatadd50ada2014-03-13 12:48:47 -0500249 connectToHub(faceMgmtUri);
250 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700251
hilatadd50ada2014-03-13 12:48:47 -0500252 // First stage OnTimeout callback - start 2nd stage
253 void
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700254 discoverHubStage2(const std::string& message)
hilatadd50ada2014-03-13 12:48:47 -0500255 {
256 std::cerr << message << std::endl;
257 std::cerr << "Stage 2: Trying DNS query with default suffix..." << std::endl;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700258
259 _res.retry = 2;
hilatadd50ada2014-03-13 12:48:47 -0500260 _res.ndots = 10;
261
262 QueryAnswer queryAnswer;
263
264 int answerSize = res_search("_ndn._udp",
265 ns_c_in,
266 ns_t_srv,
267 queryAnswer.buf,
268 sizeof(queryAnswer));
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700269
hilatadd50ada2014-03-13 12:48:47 -0500270 // 2nd stage failed - move on to the third stage
271 if (answerSize < 0)
272 {
273 discoverHubStage3("Failed to find NDN router using default suffix DNS query");
274 }
275 else
276 {
277 bool isParsed = parseHostAndConnectToHub(queryAnswer, answerSize);
278 if (isParsed == false)
279 {
280 // Failed to parse DNS response, try stage 3
281 discoverHubStage3("Failed to parse DNS response");
282 }
283 }
284 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700285
hilatadd50ada2014-03-13 12:48:47 -0500286 // Second stage OnTimeout callback
287 void
288 discoverHubStage3(const std::string& message)
289 {
290 std::cerr << message << std::endl;
291 std::cerr << "Stage 3: Trying to find home router..." << std::endl;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700292
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700293 KeyChain keyChain;
294 Name identity = keyChain.getDefaultIdentity();
hilatadd50ada2014-03-13 12:48:47 -0500295 std::string serverName = "_ndn._udp.";
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700296
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700297 for (Name::const_reverse_iterator i = identity.rbegin(); i != identity.rend(); i++)
hilatadd50ada2014-03-13 12:48:47 -0500298 {
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700299 serverName.append(i->toUri());
hilatadd50ada2014-03-13 12:48:47 -0500300 serverName.append(".");
301 }
302 serverName += "_homehub._autoconf.named-data.net";
303 std::cerr << "Stage3: About to query for a home router: " << serverName << std::endl;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700304
hilatadd50ada2014-03-13 12:48:47 -0500305 QueryAnswer queryAnswer;
306
307 int answerSize = res_query(serverName.c_str(),
308 ns_c_in,
309 ns_t_srv,
310 queryAnswer.buf,
311 sizeof(queryAnswer));
312
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700313
hilatadd50ada2014-03-13 12:48:47 -0500314 // 3rd stage failed - abort
315 if (answerSize < 0)
316 {
317 std::cerr << "Failed to find a home router" << std::endl;
318 std::cerr << "exit" << std::endl;
319 }
320 else
321 {
322 bool isParsed = parseHostAndConnectToHub(queryAnswer, answerSize);
323 if (isParsed == false)
324 {
325 // Failed to parse DNS response
326 throw Error("Failed to parse DNS response");
327 }
328 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700329
hilatadd50ada2014-03-13 12:48:47 -0500330 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700331
hilatadd50ada2014-03-13 12:48:47 -0500332 void
333 connectToHub(const std::string& uri)
334 {
335 std::cerr << "about to connect to: " << uri << std::endl;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700336
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700337 m_controller.start<nfd::FaceCreateCommand>(
338 nfd::ControlParameters()
hilata3a4eb5c2014-04-29 00:32:05 -0500339 .setUri(uri),
340 bind(&NdnAutoconfig::onHubConnectSuccess, this, _1),
341 bind(&NdnAutoconfig::onHubConnectError, this, _1, _2)
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700342 );
hilatadd50ada2014-03-13 12:48:47 -0500343 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700344
hilatadd50ada2014-03-13 12:48:47 -0500345 void
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700346 onHubConnectSuccess(const nfd::ControlParameters& resp)
hilatadd50ada2014-03-13 12:48:47 -0500347 {
hilata3a4eb5c2014-04-29 00:32:05 -0500348 std::cerr << "Successfully created face: " << resp << std::endl;
hilataf4f86732014-05-03 19:06:34 -0500349
350 // Register a prefix in RIB
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700351 nfd::ControlParameters ribParameters;
hilataf4f86732014-05-03 19:06:34 -0500352 ribParameters
353 .setName("/ndn")
354 .setFaceId(resp.getFaceId());
355
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700356 m_controller.start<nfd::RibRegisterCommand>(
hilataf4f86732014-05-03 19:06:34 -0500357 ribParameters,
358 bind(&NdnAutoconfig::onPrefixRegistrationSuccess, this, _1),
359 bind(&NdnAutoconfig::onPrefixRegistrationError, this, _1, _2));
hilatadd50ada2014-03-13 12:48:47 -0500360 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700361
hilatadd50ada2014-03-13 12:48:47 -0500362 void
hilata3a4eb5c2014-04-29 00:32:05 -0500363 onHubConnectError(uint32_t code, const std::string& error)
hilatadd50ada2014-03-13 12:48:47 -0500364 {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700365 std::ostringstream os;
hilata3a4eb5c2014-04-29 00:32:05 -0500366 os << "Failed to create face: " << error << " (code: " << code << ")";
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700367 throw Error(os.str());
hilatadd50ada2014-03-13 12:48:47 -0500368 }
369
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700370
hilatadd50ada2014-03-13 12:48:47 -0500371 bool parseHostAndConnectToHub(QueryAnswer& queryAnswer, int answerSize)
372 {
373 // The references of the next classes are:
374 // http://www.diablotin.com/librairie/networking/dnsbind/ch14_02.htm
375 // https://gist.github.com/mologie/6027597
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700376
377 struct rechdr
hilatadd50ada2014-03-13 12:48:47 -0500378 {
hilatadd50ada2014-03-13 12:48:47 -0500379 uint16_t type;
380 uint16_t iclass;
381 uint32_t ttl;
382 uint16_t length;
383 };
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700384
385 struct srv_t
hilatadd50ada2014-03-13 12:48:47 -0500386 {
hilatadd50ada2014-03-13 12:48:47 -0500387 uint16_t priority;
388 uint16_t weight;
389 uint16_t port;
390 uint8_t* target;
391 };
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700392
hilatadd50ada2014-03-13 12:48:47 -0500393 if (ntohs(queryAnswer.header.ancount) == 0)
394 {
395 std::cerr << "No records found\n" << std::endl;
396 return false;
397 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700398
hilatadd50ada2014-03-13 12:48:47 -0500399 uint8_t* blob = queryAnswer.buf + NS_HFIXEDSZ;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700400
hilatadd50ada2014-03-13 12:48:47 -0500401 blob += dn_skipname(blob, queryAnswer.buf + answerSize) + NS_QFIXEDSZ;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700402
hilatadd50ada2014-03-13 12:48:47 -0500403 for (int i = 0; i < ntohs(queryAnswer.header.ancount); i++)
404 {
hilata3a4eb5c2014-04-29 00:32:05 -0500405 char srvName[NS_MAXDNAME];
406 int serverNameSize = dn_expand(queryAnswer.buf, // message pointer
407 queryAnswer.buf + answerSize, // end of message
408 blob, // compressed server name
409 srvName, // expanded server name
hilatadd50ada2014-03-13 12:48:47 -0500410 NS_MAXDNAME);
hilata3a4eb5c2014-04-29 00:32:05 -0500411 if (serverNameSize < 0)
hilatadd50ada2014-03-13 12:48:47 -0500412 {
413 return false;
414 }
Davide Pesavento6fc750f2014-03-18 19:49:39 +0100415
416 srv_t* server = reinterpret_cast<srv_t*>(&blob[sizeof(rechdr)]);
hilatadd50ada2014-03-13 12:48:47 -0500417 uint16_t convertedPort = be16toh(server->port);
hilata3a4eb5c2014-04-29 00:32:05 -0500418
419 blob += serverNameSize + NS_HFIXEDSZ + NS_QFIXEDSZ;
420
421 char hostName[NS_MAXDNAME];
422 int hostNameSize = dn_expand(queryAnswer.buf, // message pointer
423 queryAnswer.buf + answerSize, // end of message
424 blob, // compressed host name
425 hostName, // expanded host name
426 NS_MAXDNAME);
427 if (hostNameSize < 0)
428 {
429 return false;
430 }
431
hilatadd50ada2014-03-13 12:48:47 -0500432 std::string uri = "udp://";
433 uri.append(hostName);
434 uri.append(":");
435 uri.append(boost::lexical_cast<std::string>(convertedPort));
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700436
hilatadd50ada2014-03-13 12:48:47 -0500437 connectToHub(uri);
438 return true;
439 }
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700440
441 return false;
hilatadd50ada2014-03-13 12:48:47 -0500442 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700443
hilataf4f86732014-05-03 19:06:34 -0500444 void
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700445 onPrefixRegistrationSuccess(const nfd::ControlParameters& commandSuccessResult)
hilataf4f86732014-05-03 19:06:34 -0500446 {
447 std::cerr << "Successful in name registration: " << commandSuccessResult << std::endl;
448 }
449
450 void
451 onPrefixRegistrationError(uint32_t code, const std::string& error)
452 {
453 std::ostringstream os;
454 os << "Failed in name registration, " << error << " (code: " << code << ")";
455 throw Error(os.str());
456 }
457
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700458private:
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700459 Face m_face;
460 nfd::Controller m_controller;
hilatadd50ada2014-03-13 12:48:47 -0500461};
462
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700463} // namespace tools
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700464} // namespace ndn
hilatadd50ada2014-03-13 12:48:47 -0500465
466int
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700467main(int argc, char** argv)
hilatadd50ada2014-03-13 12:48:47 -0500468{
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700469 int opt;
470 const char* programName = argv[0];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700471
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700472 while ((opt = getopt(argc, argv, "hV")) != -1) {
473 switch (opt) {
474 case 'h':
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700475 ndn::tools::usage(programName);
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700476 return 0;
477 case 'V':
478 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
479 return 0;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700480 }
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700481 }
482
483 try {
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700484 ndn::tools::NdnAutoconfig autoConfigInstance;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700485
486 autoConfigInstance.discoverHubStage1();
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700487 autoConfigInstance.run();
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700488 }
489 catch (const std::exception& error) {
490 std::cerr << "ERROR: " << error.what() << std::endl;
491 return 1;
492 }
hilatadd50ada2014-03-13 12:48:47 -0500493 return 0;
494}