blob: fdd8ba977118e868393ab73eb2e18051be546a74 [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 Afanasyev4a771362014-04-24 21:29:33 -070028#include <ndn-cxx/face.hpp>
Junxiao Shi8e273ca2014-11-12 00:42:29 -070029#include <ndn-cxx/security/key-chain.hpp>
Alexander Afanasyev4a771362014-04-24 21:29:33 -070030#include <ndn-cxx/management/nfd-controller.hpp>
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -070031#include <ndn-cxx/management/nfd-face-status.hpp>
Alexander Afanasyev4a771362014-04-24 21:29:33 -070032#include <ndn-cxx/security/key-chain.hpp>
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -070033#include <ndn-cxx/encoding/buffer-stream.hpp>
Junxiao Shia1937bf2014-11-06 11:43:40 -070034#include <ndn-cxx/util/face-uri.hpp>
hilatadd50ada2014-03-13 12:48:47 -050035
Alexander Afanasyevb3893c92014-05-15 01:49:54 -070036#include <boost/lexical_cast.hpp>
Junxiao Shia1937bf2014-11-06 11:43:40 -070037#include <boost/noncopyable.hpp>
Alexander Afanasyevb3893c92014-05-15 01:49:54 -070038
hilatadd50ada2014-03-13 12:48:47 -050039#include <sys/types.h>
40#include <netinet/in.h>
41#include <arpa/nameser.h>
42#include <resolv.h>
43
44#ifdef __APPLE__
45#include <arpa/nameser_compat.h>
46#endif
47
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -070048namespace ndn {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070049namespace tools {
50
Alexander Afanasyev6fce0782014-06-18 16:59:54 -070051static const Name LOCALHOP_HUB_DISCOVERY_PREFIX = "/localhop/ndn-autoconf/hub";
52
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070053void
54usage(const char* programName)
55{
56 std::cout << "Usage:\n" << programName << " [-h] [-V]\n"
57 << " -h - print usage and exit\n"
58 << " -V - print version number and exit\n"
59 << std::endl;
60}
61
Junxiao Shia1937bf2014-11-06 11:43:40 -070062class NdnAutoconfig : boost::noncopyable
hilatadd50ada2014-03-13 12:48:47 -050063{
64public:
65 union QueryAnswer
66 {
67 HEADER header;
68 uint8_t buf[NS_PACKETSZ];
69 };
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070070
71 class Error : public std::runtime_error
hilatadd50ada2014-03-13 12:48:47 -050072 {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070073 public:
74 explicit
75 Error(const std::string& what)
76 : std::runtime_error(what)
hilatadd50ada2014-03-13 12:48:47 -050077 {
78 }
79 };
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070080
hilatadd50ada2014-03-13 12:48:47 -050081 explicit
Alexander Afanasyev352e14e2014-03-27 16:02:12 -070082 NdnAutoconfig()
Junxiao Shi8e273ca2014-11-12 00:42:29 -070083 : m_controller(m_face, m_keyChain)
hilatadd50ada2014-03-13 12:48:47 -050084 {
85 }
Davide Pesavento6fc750f2014-03-18 19:49:39 +010086
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -070087 void
88 run()
89 {
90 m_face.processEvents();
91 }
92
93 void
94 fetchSegments(const Data& data, const shared_ptr<OBufferStream>& buffer,
95 void (NdnAutoconfig::*onDone)(const shared_ptr<OBufferStream>&))
96 {
97 buffer->write(reinterpret_cast<const char*>(data.getContent().value()),
98 data.getContent().value_size());
99
100 uint64_t currentSegment = data.getName().get(-1).toSegment();
101
102 const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
103 if (finalBlockId.empty() ||
104 finalBlockId.toSegment() > currentSegment)
105 {
106 m_face.expressInterest(data.getName().getPrefix(-1).appendSegment(currentSegment+1),
Davide Pesaventoab1e8f22014-10-21 22:45:33 +0200107 ndn::bind(&NdnAutoconfig::fetchSegments, this, _2, buffer, onDone),
108 ndn::bind(&NdnAutoconfig::discoverHubStage2, this, "Timeout"));
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700109 }
110 else
111 {
112 return (this->*onDone)(buffer);
113 }
114 }
115
hilatadd50ada2014-03-13 12:48:47 -0500116 void
117 discoverHubStage1()
118 {
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700119 shared_ptr<OBufferStream> buffer = make_shared<OBufferStream>();
120
121 Interest interest("/localhost/nfd/faces/list");
122 interest.setChildSelector(1);
123 interest.setMustBeFresh(true);
124
125 m_face.expressInterest(interest,
Davide Pesaventoab1e8f22014-10-21 22:45:33 +0200126 ndn::bind(&NdnAutoconfig::fetchSegments, this, _2, buffer,
127 &NdnAutoconfig::discoverHubStage1_registerHubDiscoveryPrefix),
128 ndn::bind(&NdnAutoconfig::discoverHubStage2, this, "Timeout"));
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700129 }
130
131 void
Alexander Afanasyev6fce0782014-06-18 16:59:54 -0700132 discoverHubStage1_registerHubDiscoveryPrefix(const shared_ptr<OBufferStream>& buffer)
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700133 {
134 ConstBufferPtr buf = buffer->buf();
135 std::vector<uint64_t> multicastFaces;
136
137 size_t offset = 0;
138 while (offset < buf->size())
139 {
140 Block block;
141 bool ok = Block::fromBuffer(buf, offset, block);
142 if (!ok)
143 {
144 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
145 break;
146 }
147
148 offset += block.size();
149
150 nfd::FaceStatus faceStatus(block);
151
Junxiao Shia1937bf2014-11-06 11:43:40 -0700152 ndn::util::FaceUri uri(faceStatus.getRemoteUri());
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700153 if (uri.getScheme() == "udp4") {
154 namespace ip = boost::asio::ip;
155 boost::system::error_code ec;
156 ip::address address = ip::address::from_string(uri.getHost(), ec);
157
158 if (!ec && address.is_multicast()) {
159 multicastFaces.push_back(faceStatus.getFaceId());
160 }
161 else
162 continue;
163 }
164 }
165
166 if (multicastFaces.empty()) {
167 discoverHubStage2("No multicast faces available, skipping stage 1");
168 }
169 else {
170 shared_ptr<nfd::Controller> controller = make_shared<nfd::Controller>(ref(m_face));
171 shared_ptr<std::pair<size_t, size_t> > nRegistrations =
172 make_shared<std::pair<size_t, size_t> >(0, 0);
173
174 nfd::ControlParameters parameters;
175 parameters
Alexander Afanasyev6fce0782014-06-18 16:59:54 -0700176 .setName(LOCALHOP_HUB_DISCOVERY_PREFIX)
Junxiao Shia753f1b2014-07-01 22:25:14 -0700177 .setCost(1)
178 .setExpirationPeriod(time::seconds(30));
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700179
180 nRegistrations->first = multicastFaces.size();
181
182 for (std::vector<uint64_t>::iterator i = multicastFaces.begin();
183 i != multicastFaces.end(); ++i) {
184 parameters.setFaceId(*i);
185
186 controller->start<nfd::RibRegisterCommand>(parameters,
187 bind(&NdnAutoconfig::discoverHubStage1_onRegisterSuccess,
188 this, controller, nRegistrations),
189 bind(&NdnAutoconfig::discoverHubStage1_onRegisterFailure,
190 this, _1, _2, controller, nRegistrations));
191 }
192 }
193 }
194
195 void
196 discoverHubStage1_onRegisterSuccess(const shared_ptr<nfd::Controller>& controller,
197 const shared_ptr<std::pair<size_t, size_t> >& nRegistrations)
198 {
199 nRegistrations->second++;
200
201 if (nRegistrations->first == nRegistrations->second) {
Alexander Afanasyev6fce0782014-06-18 16:59:54 -0700202 discoverHubStage1_setStrategy(controller);
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700203 }
204 }
205
206 void
207 discoverHubStage1_onRegisterFailure(uint32_t code, const std::string& error,
Alexander Afanasyev6fce0782014-06-18 16:59:54 -0700208 const shared_ptr<nfd::Controller>& controller,
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700209 const shared_ptr<std::pair<size_t, size_t> >& nRegistrations)
210 {
211 std::cerr << "ERROR: " << error << " (code: " << code << ")" << std::endl;
212 nRegistrations->first--;
213
214 if (nRegistrations->first == nRegistrations->second) {
215 if (nRegistrations->first > 0) {
Alexander Afanasyev6fce0782014-06-18 16:59:54 -0700216 discoverHubStage1_setStrategy(controller);
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700217 } else {
Alexander Afanasyev6fce0782014-06-18 16:59:54 -0700218 discoverHubStage2("Failed to register " + LOCALHOP_HUB_DISCOVERY_PREFIX.toUri() +
219 " for all multicast faces");
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700220 }
221 }
222 }
223
Alexander Afanasyev6fce0782014-06-18 16:59:54 -0700224 void
225 discoverHubStage1_setStrategy(const shared_ptr<nfd::Controller>& controller)
226 {
227 nfd::ControlParameters parameters;
228 parameters
229 .setName(LOCALHOP_HUB_DISCOVERY_PREFIX)
230 .setStrategy("/localhost/nfd/strategy/broadcast");
231
232 controller->start<nfd::StrategyChoiceSetCommand>(parameters,
233 bind(&NdnAutoconfig::discoverHubStage1_onSetStrategySuccess,
234 this, controller),
235 bind(&NdnAutoconfig::discoverHubStage1_onSetStrategyFailure,
236 this, _2, controller));
237 }
238
239 void
240 discoverHubStage1_onSetStrategySuccess(const shared_ptr<nfd::Controller>& controller)
241 {
242 discoverHubStage1_requestHubData();
243 }
244
245 void
246 discoverHubStage1_onSetStrategyFailure(const std::string& error,
247 const shared_ptr<nfd::Controller>& controller)
248 {
249 discoverHubStage2("Failed to set broadcast strategy for " +
250 LOCALHOP_HUB_DISCOVERY_PREFIX.toUri() + " namespace (" + error + ")");
251 }
252
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700253 // Start to look for a hub (NDN hub discovery first stage)
254 void
255 discoverHubStage1_requestHubData()
256 {
Alexander Afanasyev6fce0782014-06-18 16:59:54 -0700257 Interest interest(LOCALHOP_HUB_DISCOVERY_PREFIX);
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700258 interest.setInterestLifetime(time::milliseconds(4000)); // 4 seconds
hilatadd50ada2014-03-13 12:48:47 -0500259 interest.setMustBeFresh(true);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700260
hilata3a4eb5c2014-04-29 00:32:05 -0500261 std::cerr << "Stage 1: Trying multicast discovery..." << std::endl;
hilatadd50ada2014-03-13 12:48:47 -0500262 m_face.expressInterest(interest,
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700263 bind(&NdnAutoconfig::onDiscoverHubStage1Success, this, _1, _2),
264 bind(&NdnAutoconfig::discoverHubStage2, this, "Timeout"));
hilatadd50ada2014-03-13 12:48:47 -0500265 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700266
hilatadd50ada2014-03-13 12:48:47 -0500267 // First stage OnData Callback
268 void
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700269 onDiscoverHubStage1Success(const Interest& interest, Data& data)
hilatadd50ada2014-03-13 12:48:47 -0500270 {
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700271 const Block& content = data.getContent();
hilatadd50ada2014-03-13 12:48:47 -0500272 content.parse();
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700273
hilatadd50ada2014-03-13 12:48:47 -0500274 // Get Uri
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700275 Block::element_const_iterator blockValue = content.find(tlv::nfd::Uri);
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700276 if (blockValue == content.elements_end())
hilatadd50ada2014-03-13 12:48:47 -0500277 {
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700278 discoverHubStage2("Incorrect reply to stage1");
hilatadd50ada2014-03-13 12:48:47 -0500279 return;
280 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700281 std::string faceMgmtUri(reinterpret_cast<const char*>(blockValue->value()),
282 blockValue->value_size());
hilatadd50ada2014-03-13 12:48:47 -0500283 connectToHub(faceMgmtUri);
284 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700285
hilatadd50ada2014-03-13 12:48:47 -0500286 // First stage OnTimeout callback - start 2nd stage
287 void
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700288 discoverHubStage2(const std::string& message)
hilatadd50ada2014-03-13 12:48:47 -0500289 {
290 std::cerr << message << std::endl;
291 std::cerr << "Stage 2: Trying DNS query with default suffix..." << std::endl;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700292
293 _res.retry = 2;
hilatadd50ada2014-03-13 12:48:47 -0500294 _res.ndots = 10;
295
296 QueryAnswer queryAnswer;
297
298 int answerSize = res_search("_ndn._udp",
299 ns_c_in,
300 ns_t_srv,
301 queryAnswer.buf,
302 sizeof(queryAnswer));
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700303
hilatadd50ada2014-03-13 12:48:47 -0500304 // 2nd stage failed - move on to the third stage
305 if (answerSize < 0)
306 {
307 discoverHubStage3("Failed to find NDN router using default suffix DNS query");
308 }
309 else
310 {
311 bool isParsed = parseHostAndConnectToHub(queryAnswer, answerSize);
312 if (isParsed == false)
313 {
314 // Failed to parse DNS response, try stage 3
315 discoverHubStage3("Failed to parse DNS response");
316 }
317 }
318 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700319
hilatadd50ada2014-03-13 12:48:47 -0500320 // Second stage OnTimeout callback
321 void
322 discoverHubStage3(const std::string& message)
323 {
324 std::cerr << message << std::endl;
325 std::cerr << "Stage 3: Trying to find home router..." << std::endl;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700326
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700327 KeyChain keyChain;
328 Name identity = keyChain.getDefaultIdentity();
hilatadd50ada2014-03-13 12:48:47 -0500329 std::string serverName = "_ndn._udp.";
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700330
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700331 for (Name::const_reverse_iterator i = identity.rbegin(); i != identity.rend(); i++)
hilatadd50ada2014-03-13 12:48:47 -0500332 {
Alexander Afanasyevb3893c92014-05-15 01:49:54 -0700333 serverName.append(i->toUri());
hilatadd50ada2014-03-13 12:48:47 -0500334 serverName.append(".");
335 }
336 serverName += "_homehub._autoconf.named-data.net";
337 std::cerr << "Stage3: About to query for a home router: " << serverName << std::endl;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700338
hilatadd50ada2014-03-13 12:48:47 -0500339 QueryAnswer queryAnswer;
340
341 int answerSize = res_query(serverName.c_str(),
342 ns_c_in,
343 ns_t_srv,
344 queryAnswer.buf,
345 sizeof(queryAnswer));
346
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700347
hilatadd50ada2014-03-13 12:48:47 -0500348 // 3rd stage failed - abort
349 if (answerSize < 0)
350 {
351 std::cerr << "Failed to find a home router" << std::endl;
352 std::cerr << "exit" << std::endl;
353 }
354 else
355 {
356 bool isParsed = parseHostAndConnectToHub(queryAnswer, answerSize);
357 if (isParsed == false)
358 {
359 // Failed to parse DNS response
360 throw Error("Failed to parse DNS response");
361 }
362 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700363
hilatadd50ada2014-03-13 12:48:47 -0500364 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700365
hilatadd50ada2014-03-13 12:48:47 -0500366 void
367 connectToHub(const std::string& uri)
368 {
369 std::cerr << "about to connect to: " << uri << std::endl;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700370
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700371 m_controller.start<nfd::FaceCreateCommand>(
372 nfd::ControlParameters()
hilata3a4eb5c2014-04-29 00:32:05 -0500373 .setUri(uri),
374 bind(&NdnAutoconfig::onHubConnectSuccess, this, _1),
375 bind(&NdnAutoconfig::onHubConnectError, this, _1, _2)
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700376 );
hilatadd50ada2014-03-13 12:48:47 -0500377 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700378
hilatadd50ada2014-03-13 12:48:47 -0500379 void
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700380 onHubConnectSuccess(const nfd::ControlParameters& resp)
hilatadd50ada2014-03-13 12:48:47 -0500381 {
hilata3a4eb5c2014-04-29 00:32:05 -0500382 std::cerr << "Successfully created face: " << resp << std::endl;
hilataf4f86732014-05-03 19:06:34 -0500383
384 // Register a prefix in RIB
Junxiao Shia753f1b2014-07-01 22:25:14 -0700385 static const Name TESTBED_PREFIX("/ndn");
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700386 m_controller.start<nfd::RibRegisterCommand>(
Junxiao Shia753f1b2014-07-01 22:25:14 -0700387 nfd::ControlParameters()
388 .setName(TESTBED_PREFIX)
389 .setFaceId(resp.getFaceId())
390 .setOrigin(nfd::ROUTE_ORIGIN_AUTOCONF)
391 .setCost(100)
392 .setExpirationPeriod(time::milliseconds::max()),
hilataf4f86732014-05-03 19:06:34 -0500393 bind(&NdnAutoconfig::onPrefixRegistrationSuccess, this, _1),
394 bind(&NdnAutoconfig::onPrefixRegistrationError, this, _1, _2));
hilatadd50ada2014-03-13 12:48:47 -0500395 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700396
hilatadd50ada2014-03-13 12:48:47 -0500397 void
hilata3a4eb5c2014-04-29 00:32:05 -0500398 onHubConnectError(uint32_t code, const std::string& error)
hilatadd50ada2014-03-13 12:48:47 -0500399 {
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700400 std::ostringstream os;
hilata3a4eb5c2014-04-29 00:32:05 -0500401 os << "Failed to create face: " << error << " (code: " << code << ")";
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700402 throw Error(os.str());
hilatadd50ada2014-03-13 12:48:47 -0500403 }
404
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700405
hilatadd50ada2014-03-13 12:48:47 -0500406 bool parseHostAndConnectToHub(QueryAnswer& queryAnswer, int answerSize)
407 {
408 // The references of the next classes are:
409 // http://www.diablotin.com/librairie/networking/dnsbind/ch14_02.htm
410 // https://gist.github.com/mologie/6027597
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700411
412 struct rechdr
hilatadd50ada2014-03-13 12:48:47 -0500413 {
hilatadd50ada2014-03-13 12:48:47 -0500414 uint16_t type;
415 uint16_t iclass;
416 uint32_t ttl;
417 uint16_t length;
418 };
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700419
420 struct srv_t
hilatadd50ada2014-03-13 12:48:47 -0500421 {
hilatadd50ada2014-03-13 12:48:47 -0500422 uint16_t priority;
423 uint16_t weight;
424 uint16_t port;
425 uint8_t* target;
426 };
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700427
hilatadd50ada2014-03-13 12:48:47 -0500428 if (ntohs(queryAnswer.header.ancount) == 0)
429 {
430 std::cerr << "No records found\n" << std::endl;
431 return false;
432 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700433
hilatadd50ada2014-03-13 12:48:47 -0500434 uint8_t* blob = queryAnswer.buf + NS_HFIXEDSZ;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700435
hilatadd50ada2014-03-13 12:48:47 -0500436 blob += dn_skipname(blob, queryAnswer.buf + answerSize) + NS_QFIXEDSZ;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700437
hilatadd50ada2014-03-13 12:48:47 -0500438 for (int i = 0; i < ntohs(queryAnswer.header.ancount); i++)
439 {
hilata3a4eb5c2014-04-29 00:32:05 -0500440 char srvName[NS_MAXDNAME];
441 int serverNameSize = dn_expand(queryAnswer.buf, // message pointer
442 queryAnswer.buf + answerSize, // end of message
443 blob, // compressed server name
444 srvName, // expanded server name
hilatadd50ada2014-03-13 12:48:47 -0500445 NS_MAXDNAME);
hilata3a4eb5c2014-04-29 00:32:05 -0500446 if (serverNameSize < 0)
hilatadd50ada2014-03-13 12:48:47 -0500447 {
448 return false;
449 }
Davide Pesavento6fc750f2014-03-18 19:49:39 +0100450
451 srv_t* server = reinterpret_cast<srv_t*>(&blob[sizeof(rechdr)]);
hilatadd50ada2014-03-13 12:48:47 -0500452 uint16_t convertedPort = be16toh(server->port);
hilata3a4eb5c2014-04-29 00:32:05 -0500453
454 blob += serverNameSize + NS_HFIXEDSZ + NS_QFIXEDSZ;
455
456 char hostName[NS_MAXDNAME];
457 int hostNameSize = dn_expand(queryAnswer.buf, // message pointer
458 queryAnswer.buf + answerSize, // end of message
459 blob, // compressed host name
460 hostName, // expanded host name
461 NS_MAXDNAME);
462 if (hostNameSize < 0)
463 {
464 return false;
465 }
466
hilatadd50ada2014-03-13 12:48:47 -0500467 std::string uri = "udp://";
468 uri.append(hostName);
469 uri.append(":");
470 uri.append(boost::lexical_cast<std::string>(convertedPort));
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700471
hilatadd50ada2014-03-13 12:48:47 -0500472 connectToHub(uri);
473 return true;
474 }
Alexander Afanasyeveb3197f2014-03-17 19:28:18 -0700475
476 return false;
hilatadd50ada2014-03-13 12:48:47 -0500477 }
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700478
hilataf4f86732014-05-03 19:06:34 -0500479 void
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700480 onPrefixRegistrationSuccess(const nfd::ControlParameters& commandSuccessResult)
hilataf4f86732014-05-03 19:06:34 -0500481 {
482 std::cerr << "Successful in name registration: " << commandSuccessResult << std::endl;
483 }
484
485 void
486 onPrefixRegistrationError(uint32_t code, const std::string& error)
487 {
488 std::ostringstream os;
489 os << "Failed in name registration, " << error << " (code: " << code << ")";
490 throw Error(os.str());
491 }
492
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700493private:
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700494 Face m_face;
Junxiao Shi8e273ca2014-11-12 00:42:29 -0700495 KeyChain m_keyChain;
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700496 nfd::Controller m_controller;
hilatadd50ada2014-03-13 12:48:47 -0500497};
498
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700499} // namespace tools
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700500} // namespace ndn
hilatadd50ada2014-03-13 12:48:47 -0500501
502int
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700503main(int argc, char** argv)
hilatadd50ada2014-03-13 12:48:47 -0500504{
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700505 int opt;
506 const char* programName = argv[0];
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700507
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700508 while ((opt = getopt(argc, argv, "hV")) != -1) {
509 switch (opt) {
510 case 'h':
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700511 ndn::tools::usage(programName);
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700512 return 0;
513 case 'V':
514 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
515 return 0;
Alexander Afanasyev352e14e2014-03-27 16:02:12 -0700516 }
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700517 }
518
519 try {
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700520 ndn::tools::NdnAutoconfig autoConfigInstance;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700521
522 autoConfigInstance.discoverHubStage1();
Alexander Afanasyev554ef7a2014-06-15 16:10:43 -0700523 autoConfigInstance.run();
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700524 }
525 catch (const std::exception& error) {
526 std::cerr << "ERROR: " << error.what() << std::endl;
527 return 1;
528 }
hilatadd50ada2014-03-13 12:48:47 -0500529 return 0;
530}