tools: Refactoring ndn-autoconfig implementation

Change-Id: Ib92942ba40f04aaee83479177b9ba5d32a09af04
Refs: #2421
This commit is contained in:
Alexander Afanasyev committed 2015-01-28 14:17:10 -08:00
1 parent 262203b644
commit 2a655f70a1
12 files changed
+1156 -537

No files matched your search

-537
View File
@@ -1,537 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "version.hpp"
#include <ndn-cxx/face.hpp>
#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/management/nfd-controller.hpp>
#include <ndn-cxx/management/nfd-face-status.hpp>
#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/encoding/buffer-stream.hpp>
#include <ndn-cxx/util/face-uri.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/noncopyable.hpp>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#ifdef __APPLE__
#include <arpa/nameser_compat.h>
#endif
namespace ndn {
namespace tools {
static const Name LOCALHOP_HUB_DISCOVERY_PREFIX = "/localhop/ndn-autoconf/hub";
void
usage(const char* programName)
{
std::cout << "Usage:\n" << programName << " [-h] [-V]\n"
<< " -h - print usage and exit\n"
<< " -V - print version number and exit\n"
<< std::endl;
}
class NdnAutoconfig : boost::noncopyable
{
public:
union QueryAnswer
{
HEADER header;
uint8_t buf[NS_PACKETSZ];
};
class Error : public std::runtime_error
{
public:
explicit
Error(const std::string& what)
: std::runtime_error(what)
{
}
};
explicit
NdnAutoconfig()
: m_controller(m_face, m_keyChain)
{
}
void
run()
{
m_face.processEvents();
}
void
fetchSegments(const Data& data, const shared_ptr<OBufferStream>& buffer,
void (NdnAutoconfig::*onDone)(const shared_ptr<OBufferStream>&))
{
buffer->write(reinterpret_cast<const char*>(data.getContent().value()),
data.getContent().value_size());
uint64_t currentSegment = data.getName().get(-1).toSegment();
const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
if (finalBlockId.empty() ||
finalBlockId.toSegment() > currentSegment)
{
m_face.expressInterest(data.getName().getPrefix(-1).appendSegment(currentSegment+1),
ndn::bind(&NdnAutoconfig::fetchSegments, this, _2, buffer, onDone),
ndn::bind(&NdnAutoconfig::discoverHubStage2, this, "Timeout"));
}
else
{
return (this->*onDone)(buffer);
}
}
void
discoverHubStage1()
{
shared_ptr<OBufferStream> buffer = make_shared<OBufferStream>();
Interest interest("/localhost/nfd/faces/list");
interest.setChildSelector(1);
interest.setMustBeFresh(true);
m_face.expressInterest(interest,
ndn::bind(&NdnAutoconfig::fetchSegments, this, _2, buffer,
&NdnAutoconfig::discoverHubStage1_registerHubDiscoveryPrefix),
ndn::bind(&NdnAutoconfig::discoverHubStage2, this, "Timeout"));
}
void
discoverHubStage1_registerHubDiscoveryPrefix(const shared_ptr<OBufferStream>& buffer)
{
ConstBufferPtr buf = buffer->buf();
std::vector<uint64_t> multicastFaces;
size_t offset = 0;
while (offset < buf->size())
{
Block block;
bool ok = Block::fromBuffer(buf, offset, block);
if (!ok)
{
std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
break;
}
offset += block.size();
nfd::FaceStatus faceStatus(block);
ndn::util::FaceUri uri(faceStatus.getRemoteUri());
if (uri.getScheme() == "udp4") {
namespace ip = boost::asio::ip;
boost::system::error_code ec;
ip::address address = ip::address::from_string(uri.getHost(), ec);
if (!ec && address.is_multicast()) {
multicastFaces.push_back(faceStatus.getFaceId());
}
else
continue;
}
}
if (multicastFaces.empty()) {
discoverHubStage2("No multicast faces available, skipping stage 1");
}
else {
shared_ptr<nfd::Controller> controller = make_shared<nfd::Controller>(ref(m_face));
shared_ptr<std::pair<size_t, size_t> > nRegistrations =
make_shared<std::pair<size_t, size_t> >(0, 0);
nfd::ControlParameters parameters;
parameters
.setName(LOCALHOP_HUB_DISCOVERY_PREFIX)
.setCost(1)
.setExpirationPeriod(time::seconds(30));
nRegistrations->first = multicastFaces.size();
for (std::vector<uint64_t>::iterator i = multicastFaces.begin();
i != multicastFaces.end(); ++i) {
parameters.setFaceId(*i);
controller->start<nfd::RibRegisterCommand>(parameters,
bind(&NdnAutoconfig::discoverHubStage1_onRegisterSuccess,
this, controller, nRegistrations),
bind(&NdnAutoconfig::discoverHubStage1_onRegisterFailure,
this, _1, _2, controller, nRegistrations));
}
}
}
void
discoverHubStage1_onRegisterSuccess(const shared_ptr<nfd::Controller>& controller,
const shared_ptr<std::pair<size_t, size_t> >& nRegistrations)
{
nRegistrations->second++;
if (nRegistrations->first == nRegistrations->second) {
discoverHubStage1_setStrategy(controller);
}
}
void
discoverHubStage1_onRegisterFailure(uint32_t code, const std::string& error,
const shared_ptr<nfd::Controller>& controller,
const shared_ptr<std::pair<size_t, size_t> >& nRegistrations)
{
std::cerr << "ERROR: " << error << " (code: " << code << ")" << std::endl;
nRegistrations->first--;
if (nRegistrations->first == nRegistrations->second) {
if (nRegistrations->first > 0) {
discoverHubStage1_setStrategy(controller);
} else {
discoverHubStage2("Failed to register " + LOCALHOP_HUB_DISCOVERY_PREFIX.toUri() +
" for all multicast faces");
}
}
}
void
discoverHubStage1_setStrategy(const shared_ptr<nfd::Controller>& controller)
{
nfd::ControlParameters parameters;
parameters
.setName(LOCALHOP_HUB_DISCOVERY_PREFIX)
.setStrategy("/localhost/nfd/strategy/broadcast");
controller->start<nfd::StrategyChoiceSetCommand>(parameters,
bind(&NdnAutoconfig::discoverHubStage1_onSetStrategySuccess,
this, controller),
bind(&NdnAutoconfig::discoverHubStage1_onSetStrategyFailure,
this, _2, controller));
}
void
discoverHubStage1_onSetStrategySuccess(const shared_ptr<nfd::Controller>& controller)
{
discoverHubStage1_requestHubData();
}
void
discoverHubStage1_onSetStrategyFailure(const std::string& error,
const shared_ptr<nfd::Controller>& controller)
{
discoverHubStage2("Failed to set broadcast strategy for " +
LOCALHOP_HUB_DISCOVERY_PREFIX.toUri() + " namespace (" + error + ")");
}
// Start to look for a hub (NDN hub discovery first stage)
void
discoverHubStage1_requestHubData()
{
Interest interest(LOCALHOP_HUB_DISCOVERY_PREFIX);
interest.setInterestLifetime(time::milliseconds(4000)); // 4 seconds
interest.setMustBeFresh(true);
std::cerr << "Stage 1: Trying multicast discovery..." << std::endl;
m_face.expressInterest(interest,
bind(&NdnAutoconfig::onDiscoverHubStage1Success, this, _1, _2),
bind(&NdnAutoconfig::discoverHubStage2, this, "Timeout"));
}
// First stage OnData Callback
void
onDiscoverHubStage1Success(const Interest& interest, Data& data)
{
const Block& content = data.getContent();
content.parse();
// Get Uri
Block::element_const_iterator blockValue = content.find(tlv::nfd::Uri);
if (blockValue == content.elements_end()) {
discoverHubStage2("Incorrect reply to stage1");
return;
}
std::string faceMgmtUri(reinterpret_cast<const char*>(blockValue->value()),
blockValue->value_size());
connectToHub(faceMgmtUri);
}
// First stage OnTimeout callback - start 2nd stage
void
discoverHubStage2(const std::string& message)
{
std::cerr << message << std::endl;
std::cerr << "Stage 2: Trying DNS query with default suffix..." << std::endl;
_res.retry = 2;
_res.ndots = 10;
QueryAnswer queryAnswer;
int answerSize = res_search("_ndn._udp",
ns_c_in,
ns_t_srv,
queryAnswer.buf,
sizeof(queryAnswer));
// 2nd stage failed - move on to the third stage
if (answerSize < 0) {
discoverHubStage3("Failed to find NDN router using default suffix DNS query");
}
else
{
bool isParsed = parseHostAndConnectToHub(queryAnswer, answerSize);
if (isParsed == false) {
// Failed to parse DNS response, try stage 3
discoverHubStage3("Failed to parse DNS response");
}
}
}
// Second stage OnTimeout callback
void
discoverHubStage3(const std::string& message)
{
std::cerr << message << std::endl;
std::cerr << "Stage 3: Trying to find home router..." << std::endl;
KeyChain keyChain;
Name identity = keyChain.getDefaultIdentity();
std::string serverName = "_ndn._udp.";
for (Name::const_reverse_iterator i = identity.rbegin(); i != identity.rend(); i++) {
serverName.append(i->toUri());
serverName.append(".");
}
serverName += "_homehub._autoconf.named-data.net";
std::cerr << "Stage3: About to query for a home router: " << serverName << std::endl;
QueryAnswer queryAnswer;
int answerSize = res_query(serverName.c_str(),
ns_c_in,
ns_t_srv,
queryAnswer.buf,
sizeof(queryAnswer));
// 3rd stage failed - abort
if (answerSize < 0) {
std::cerr << "Failed to find a home router" << std::endl;
std::cerr << "exit" << std::endl;
}
else
{
bool isParsed = parseHostAndConnectToHub(queryAnswer, answerSize);
if (isParsed == false) {
// Failed to parse DNS response
throw Error("Failed to parse DNS response");
}
}
}
bool
parseHostAndConnectToHub(QueryAnswer& queryAnswer, int answerSize)
{
// The references of the next classes are:
// http://www.diablotin.com/librairie/networking/dnsbind/ch14_02.htm
// https://gist.github.com/mologie/6027597
struct rechdr
{
uint16_t type;
uint16_t iclass;
uint32_t ttl;
uint16_t length;
};
struct srv_t
{
uint16_t priority;
uint16_t weight;
uint16_t port;
uint8_t* target;
};
if (ntohs(queryAnswer.header.ancount) == 0) {
std::cerr << "No records found\n" << std::endl;
return false;
}
uint8_t* blob = queryAnswer.buf + NS_HFIXEDSZ;
blob += dn_skipname(blob, queryAnswer.buf + answerSize) + NS_QFIXEDSZ;
for (int i = 0; i < ntohs(queryAnswer.header.ancount); i++) {
char srvName[NS_MAXDNAME];
int serverNameSize = dn_expand(queryAnswer.buf, // message pointer
queryAnswer.buf + answerSize, // end of message
blob, // compressed server name
srvName, // expanded server name
NS_MAXDNAME);
if (serverNameSize < 0) {
return false;
}
srv_t* server = reinterpret_cast<srv_t*>(&blob[sizeof(rechdr)]);
uint16_t convertedPort = be16toh(server->port);
blob += serverNameSize + NS_HFIXEDSZ + NS_QFIXEDSZ;
char hostName[NS_MAXDNAME];
int hostNameSize = dn_expand(queryAnswer.buf, // message pointer
queryAnswer.buf + answerSize, // end of message
blob, // compressed host name
hostName, // expanded host name
NS_MAXDNAME);
if (hostNameSize < 0) {
return false;
}
std::string uri = "udp://";
uri.append(hostName);
uri.append(":");
uri.append(boost::lexical_cast<std::string>(convertedPort));
connectToHub(uri);
return true;
}
return false;
}
void
connectToHub(const std::string& uri)
{
ndn::util::FaceUri faceUri(uri);
faceUri.canonize(bind(&NdnAutoconfig::onCanonizeSuccess, this, _1),
bind(&NdnAutoconfig::onCanonizeFailure, this, _1),
m_face.getIoService(), ndn::time::seconds(4));
}
void onCanonizeSuccess(const ndn::util::FaceUri& canonicalUri)
{
std::cerr << "about to connect to: " << canonicalUri.toString() << std::endl;
m_controller.start<nfd::FaceCreateCommand>(
nfd::ControlParameters()
.setUri(canonicalUri.toString()),
bind(&NdnAutoconfig::onHubConnectSuccess, this, _1),
bind(&NdnAutoconfig::onHubConnectError, this, _1, _2));
}
void
onCanonizeFailure(const std::string& reason)
{
std::ostringstream os;
os << "Canonize faceUri failed: " << reason;
throw Error(os.str());
}
void
onHubConnectSuccess(const nfd::ControlParameters& resp)
{
std::cerr << "Successfully created face: " << resp << std::endl;
// Register a prefix in RIB
static const Name TESTBED_PREFIX("/ndn");
m_controller.start<nfd::RibRegisterCommand>(
nfd::ControlParameters()
.setName(TESTBED_PREFIX)
.setFaceId(resp.getFaceId())
.setOrigin(nfd::ROUTE_ORIGIN_AUTOCONF)
.setCost(100)
.setExpirationPeriod(time::milliseconds::max()),
bind(&NdnAutoconfig::onPrefixRegistrationSuccess, this, _1),
bind(&NdnAutoconfig::onPrefixRegistrationError, this, _1, _2));
}
void
onHubConnectError(uint32_t code, const std::string& error)
{
std::ostringstream os;
os << "Failed to create face: " << error << " (code: " << code << ")";
throw Error(os.str());
}
void
onPrefixRegistrationSuccess(const nfd::ControlParameters& commandSuccessResult)
{
std::cerr << "Successful in name registration: " << commandSuccessResult << std::endl;
}
void
onPrefixRegistrationError(uint32_t code, const std::string& error)
{
std::ostringstream os;
os << "Failed in name registration, " << error << " (code: " << code << ")";
throw Error(os.str());
}
private:
Face m_face;
KeyChain m_keyChain;
nfd::Controller m_controller;
};
} // namespace tools
} // namespace ndn
int
main(int argc, char** argv)
{
int opt;
const char* programName = argv[0];
while ((opt = getopt(argc, argv, "hV")) != -1) {
switch (opt) {
case 'h':
ndn::tools::usage(programName);
return 0;
case 'V':
std::cout << NFD_VERSION_BUILD_STRING << std::endl;
return 0;
}
}
try {
ndn::tools::NdnAutoconfig autoConfigInstance;
autoConfigInstance.discoverHubStage1();
autoConfigInstance.run();
}
catch (const std::exception& error) {
std::cerr << "ERROR: " << error.what() << std::endl;
return 1;
}
return 0;
}
+161
View File
@@ -0,0 +1,161 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base-dns.hpp"
#include <sys/types.h>
#include <netinet/in.h>
#include <resolv.h>
#include <arpa/nameser.h>
#ifdef __APPLE__
#include <arpa/nameser_compat.h>
#endif
namespace ndn {
namespace tools {
namespace autoconfig {
union BaseDns::QueryAnswer
{
HEADER header;
uint8_t buf[NS_PACKETSZ];
};
BaseDns::BaseDns(Face& face, KeyChain& keyChain, const NextStageCallback& nextStageOnFailure)
: Base(face, keyChain, nextStageOnFailure)
{
}
std::string
BaseDns::querySrvRr(const std::string& fqdn)
{
std::string srvDomain = "_ndn._udp." + fqdn;
std::cerr << "Sending DNS query for SRV record for " << srvDomain << std::endl;
QueryAnswer queryAnswer;
int answerSize = res_query(srvDomain.c_str(),
ns_c_in,
ns_t_srv,
queryAnswer.buf,
sizeof(queryAnswer));
if (answerSize == 0) {
throw Error("No DNS SRV records found for " + srvDomain);
}
return parseSrvRr(queryAnswer, answerSize);
}
/**
* @brief Send DNS SRV request using search domain list
*/
std::string
BaseDns::querySrvRrSearch()
{
std::cerr << "Sending DNS query for SRV record for _ndn._udp" << std::endl;
QueryAnswer queryAnswer;
_res.retry = 2;
_res.ndots = 10;
int answerSize = res_search("_ndn._udp",
ns_c_in,
ns_t_srv,
queryAnswer.buf,
sizeof(queryAnswer));
if (answerSize == 0) {
throw Error("No DNS SRV records found for _ndn._udp");
}
return parseSrvRr(queryAnswer, answerSize);
}
std::string
BaseDns::parseSrvRr(const QueryAnswer& queryAnswer, int answerSize)
{
// The references of the next classes are:
// http://www.diablotin.com/librairie/networking/dnsbind/ch14_02.htm
struct rechdr
{
uint16_t type;
uint16_t iclass;
uint32_t ttl;
uint16_t length;
};
struct srv_t
{
uint16_t priority;
uint16_t weight;
uint16_t port;
uint8_t* target;
};
if (ntohs(queryAnswer.header.ancount) == 0) {
throw Error("SRV record cannot be parsed");
}
const uint8_t* blob = queryAnswer.buf + NS_HFIXEDSZ;
blob += dn_skipname(blob, queryAnswer.buf + answerSize) + NS_QFIXEDSZ;
char srvName[NS_MAXDNAME];
int serverNameSize = dn_expand(queryAnswer.buf, // message pointer
queryAnswer.buf + answerSize, // end of message
blob, // compressed server name
srvName, // expanded server name
NS_MAXDNAME);
if (serverNameSize <= 0) {
throw Error("SRV record cannot be parsed (error decoding domain name)");
}
const srv_t* server = reinterpret_cast<const srv_t*>(&blob[sizeof(rechdr)]);
uint16_t convertedPort = be16toh(server->port);
blob += serverNameSize + NS_HFIXEDSZ + NS_QFIXEDSZ;
char hostName[NS_MAXDNAME];
int hostNameSize = dn_expand(queryAnswer.buf, // message pointer
queryAnswer.buf + answerSize, // end of message
blob, // compressed host name
hostName, // expanded host name
NS_MAXDNAME);
if (hostNameSize <= 0) {
throw Error("SRV record cannot be parsed (error decoding host name)");
}
std::string uri = "udp://";
uri.append(hostName);
uri.append(":");
uri.append(std::to_string(convertedPort));
return uri;
}
} // namespace autoconfig
} // namespace tools
} // namespace ndn
+85
View File
@@ -0,0 +1,85 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_TOOLS_NDN_AUTOCONFIG_BASE_DNS_HPP
#define NFD_TOOLS_NDN_AUTOCONFIG_BASE_DNS_HPP
#include "base.hpp"
namespace ndn {
namespace tools {
namespace autoconfig {
/**
* @brief Base class for stages that use DNS-based guessing
*/
class BaseDns : public Base
{
protected:
class Error : public std::runtime_error
{
public:
explicit
Error(const std::string& what)
: std::runtime_error(what)
{
}
};
BaseDns(Face& face, KeyChain& keyChain, const NextStageCallback& nextStageOnFailure);
/**
* @brief Send DNS SRV request for a @p fqdn fully qualified domain name
* @return FaceUri of the hub from the requested SRV record
* @throw Error if query returns nothing or SRV record cannot be parsed
*/
std::string
querySrvRr(const std::string& fqdn);
/**
* @brief Send DNS SRV request using search domain list
* @return FaceUri of the hub from the requested SRV record
* @throw Error if query returns nothing or SRV record cannot be parsed
*/
std::string
querySrvRrSearch();
private:
union QueryAnswer;
/**
* @brief Parse SRV record
* @return FaceUri of the hub from the SRV record
* @throw Error if SRV record cannot be parsed
*/
std::string
parseSrvRr(const QueryAnswer& queryAnswer, int answerSize);
};
} // namespace autoconfig
} // namespace tools
} // namespace ndn
#endif // NFD_TOOLS_NDN_AUTOCONFIG_BASE_DNS_HPP
+119
View File
@@ -0,0 +1,119 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base.hpp"
namespace ndn {
namespace tools {
namespace autoconfig {
Base::Base(Face& face, KeyChain& keyChain, const NextStageCallback& nextStageOnFailure)
: m_face(face)
, m_keyChain(keyChain)
, m_controller(face, keyChain)
, m_nextStageOnFailure(nextStageOnFailure)
{
}
void
Base::connectToHub(const std::string& uri)
{
util::FaceUri faceUri(uri);
faceUri.canonize(bind(&Base::onCanonizeSuccess, this, _1),
bind(&Base::onCanonizeFailure, this, _1),
m_face.getIoService(), time::seconds(4));
}
void
Base::onCanonizeSuccess(const util::FaceUri& canonicalUri)
{
std::cerr << "About to connect to: " << canonicalUri.toString() << std::endl;
m_controller.start<nfd::FaceCreateCommand>(nfd::ControlParameters()
.setUri(canonicalUri.toString()),
bind(&Base::onHubConnectSuccess, this, _1),
bind(&Base::onHubConnectError, this, _1, _2));
}
void
Base::onCanonizeFailure(const std::string& reason)
{
std::ostringstream os;
os << "FaceUri canonization failed: " << reason;
throw Error(os.str());
}
void
Base::onHubConnectSuccess(const nfd::ControlParameters& resp)
{
std::cerr << "Successfully created face: " << resp << std::endl;
static const Name TESTBED_PREFIX = "/ndn";
registerPrefix(TESTBED_PREFIX, resp.getFaceId());
}
void
Base::onHubConnectError(uint32_t code, const std::string& error)
{
std::ostringstream os;
os << "Failed to create face: " << error << " (code: " << code << ")";
throw Error(os.str());
}
void
Base::registerPrefix(const Name& prefix, uint64_t faceId)
{
// Register a prefix in RIB
m_controller.start<nfd::RibRegisterCommand>(nfd::ControlParameters()
.setName(prefix)
.setFaceId(faceId)
.setOrigin(nfd::ROUTE_ORIGIN_AUTOCONF)
.setCost(100)
.setExpirationPeriod(time::milliseconds::max()),
bind(&Base::onPrefixRegistrationSuccess, this, _1),
bind(&Base::onPrefixRegistrationError, this, _1, _2));
}
void
Base::onPrefixRegistrationSuccess(const nfd::ControlParameters& commandSuccessResult)
{
std::cerr << "Successful in name registration: " << commandSuccessResult << std::endl;
}
void
Base::onPrefixRegistrationError(uint32_t code, const std::string& error)
{
std::ostringstream os;
os << "Failed in name registration, " << error << " (code: " << code << ")";
throw Error(os.str());
}
} // namespace autoconfig
} // namespace tools
} // namespace ndn
+120
View File
@@ -0,0 +1,120 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_TOOLS_NDN_AUTOCONFIG_BASE_HPP
#define NFD_TOOLS_NDN_AUTOCONFIG_BASE_HPP
#include "common.hpp"
#include <boost/noncopyable.hpp>
#include <ndn-cxx/face.hpp>
#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/management/nfd-controller.hpp>
#include <ndn-cxx/management/nfd-face-status.hpp>
#include <ndn-cxx/encoding/buffer-stream.hpp>
#include <ndn-cxx/util/face-uri.hpp>
namespace ndn {
namespace tools {
namespace autoconfig {
/**
* @brief Base class for discovery stages
*/
class Base : boost::noncopyable
{
public:
class Error : public std::runtime_error
{
public:
explicit
Error(const std::string& what)
: std::runtime_error(what)
{
}
};
/**
* @brief Callback to be called when the stage fails
*/
typedef std::function<void(const std::string&)> NextStageCallback;
/**
* @brief Start the stage
*/
virtual void
start() = 0;
protected:
/**
* @brief Initialize variables and create nfd::Controller instance
* @param face Face to be used for all operations (e.g., will send registration commands)
* @param keyChain KeyChain object
* @param nextStageOnFailure Callback to be called after the stage failed
*/
Base(Face& face, KeyChain& keyChain, const NextStageCallback& nextStageOnFailure);
/**
* @brief Attempt to connect to local hub using the \p uri FaceUri
* @throw Base::Error when failed to establish the tunnel
*/
void
connectToHub(const std::string& uri);
private:
void
onCanonizeSuccess(const util::FaceUri& canonicalUri);
void
onCanonizeFailure(const std::string& reason);
void
onHubConnectSuccess(const nfd::ControlParameters& resp);
void
onHubConnectError(uint32_t code, const std::string& error);
void
registerPrefix(const Name& prefix, uint64_t faceId);
void
onPrefixRegistrationSuccess(const nfd::ControlParameters& commandSuccessResult);
void
onPrefixRegistrationError(uint32_t code, const std::string& error);
protected:
Face& m_face;
KeyChain& m_keyChain;
nfd::Controller m_controller;
NextStageCallback m_nextStageOnFailure;
};
} // namespace autoconfig
} // namespace tools
} // namespace ndn
#endif // NFD_TOOLS_NDN_AUTOCONFIG_BASE_HPP
@@ -0,0 +1,63 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "guess-from-identity-name.hpp"
namespace ndn {
namespace tools {
namespace autoconfig {
GuessFromIdentityName::GuessFromIdentityName(Face& face, KeyChain& keyChain,
const NextStageCallback& nextStageOnFailure)
: BaseDns(face, keyChain, nextStageOnFailure)
{
}
void
GuessFromIdentityName::start()
{
std::cerr << "Trying to find home router based on the default identity name..." << std::endl;
Name identity = m_keyChain.getDefaultIdentity();
std::ostringstream serverName;
for (auto i = identity.rbegin(); i != identity.rend(); ++i) {
serverName << i->toUri() << ".";
}
serverName << "_homehub._autoconf.named-data.net";
try {
std::string hubUri = BaseDns::querySrvRr(serverName.str());
this->connectToHub(hubUri);
}
catch (const BaseDns::Error& e) {
m_nextStageOnFailure(std::string("Failed to find a home router based on the default identity "
"name (") + e.what() + ")");
}
}
} // namespace autoconfig
} // namespace tools
} // namespace ndn
@@ -0,0 +1,74 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_TOOLS_NDN_AUTOCONFIG_GUESS_FROM_IDENTITY_NAME_HPP
#define NFD_TOOLS_NDN_AUTOCONFIG_GUESS_FROM_IDENTITY_NAME_HPP
#include "base-dns.hpp"
namespace ndn {
namespace tools {
namespace autoconfig {
/**
* @brief Guessing home router based on the default identity name
*
* This stage assumes that user has configured default certificate using
* http://ndncert.named-data.net/
*
* - Request
*
* The end host loads the default user identity (eg. /ndn/edu/ucla/cs/afanasev), and
* converts it to DNS format.
*
* The end host sends a DNS query for an SRV record of name _ndn._udp. + user identity in
* DNS format + _homehub._auto-conf.named-data.net. For example:
*
* _ndn._udp.afanasev.cs.ucla.edu.ndn._homehub._autoconf.named-data.net
*
* - Response
*
* The DNS server should answer with an SRV record that contains the hostname and UDP port
* number of the home NDN router of this user's site.
*/
class GuessFromIdentityName : public BaseDns
{
public:
/**
* @brief Create stage to guess home router based on the default identity name
* @sa Base::Base
*/
GuessFromIdentityName(Face& face, KeyChain& keyChain,
const NextStageCallback& nextStageOnFailure);
virtual void
start() DECL_OVERRIDE;
};
} // namespace autoconfig
} // namespace tools
} // namespace ndn
#endif // NFD_TOOLS_NDN_AUTOCONFIG_GUESSING_FROM_IDENTITY_NAME_HPP
@@ -0,0 +1,53 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "guess-from-search-domains.hpp"
namespace ndn {
namespace tools {
namespace autoconfig {
GuessFromSearchDomains::GuessFromSearchDomains(Face& face, KeyChain& keyChain,
const NextStageCallback& nextStageOnFailure)
: BaseDns(face, keyChain, nextStageOnFailure)
{
}
void
GuessFromSearchDomains::start()
{
try {
std::string hubUri = BaseDns::querySrvRrSearch();
this->connectToHub(hubUri);
}
catch (const BaseDns::Error& e) {
m_nextStageOnFailure(std::string("Failed to find NDN router using default suffix DNS query (") +
e.what() + ")");
}
}
} // namespace autoconfig
} // namespace tools
} // namespace ndn
@@ -0,0 +1,67 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_TOOLS_NDN_AUTOCONFIG_GUESS_FROM_SEARCH_DOMAINS_HPP
#define NFD_TOOLS_NDN_AUTOCONFIG_GUESS_FROM_SEARCH_DOMAINS_HPP
#include "base-dns.hpp"
namespace ndn {
namespace tools {
namespace autoconfig {
/**
* @brief Guessing home router based on DNS query with default suffix
*
* - Request
*
* The end host sends a DNS query that is equivalent to this command:
*
* dig +search +short +cmd +tries=2 +ndots=10 _ndn._udp srv
*
* - Response
*
* The DNS server should answer with an SRV record that contains the hostname and UDP port
* number of the NDN router.
*/
class GuessFromSearchDomains : public BaseDns
{
public:
/**
* @brief Create stage to guess home router based on DNS query with default suffix
* @sa Base::Base
*/
GuessFromSearchDomains(Face& face, KeyChain& keyChain,
const NextStageCallback& nextStageOnFailure);
virtual void
start() DECL_OVERRIDE;
};
} // namespace autoconfig
} // namespace tools
} // namespace ndn
#endif // NFD_TOOLS_NDN_AUTOCONFIG_GUESSING_FROM_SEARCH_DOMAINS_HPP
+126
View File
@@ -0,0 +1,126 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "version.hpp"
#include "multicast-discovery.hpp"
#include "guess-from-search-domains.hpp"
#include "guess-from-identity-name.hpp"
#include <boost/noncopyable.hpp>
namespace ndn {
namespace tools {
class NdnAutoconfig : boost::noncopyable
{
public:
class Error : public std::runtime_error
{
public:
explicit
Error(const std::string& what)
: std::runtime_error(what)
{
}
};
NdnAutoconfig()
: m_stage1(m_face, m_keyChain,
[&] (const std::string& errorMessage) {
std::cerr << "Stage 1 failed: " << errorMessage << std::endl;
m_stage2.start();
})
, m_stage2(m_face, m_keyChain,
[&] (const std::string& errorMessage) {
std::cerr << "Stage 2 failed: " << errorMessage << std::endl;
m_stage3.start();
})
, m_stage3(m_face, m_keyChain,
[&] (const std::string& errorMessage) {
std::cerr << "Stage 3 failed: " << errorMessage << std::endl;
throw Error("No more stages, automatic discovery failed");
})
{
m_stage1.start();
}
void
run()
{
m_face.processEvents();
}
static void
usage(const char* programName)
{
std::cout << "Usage:\n"
<< " " << programName << " [options]\n"
<< "\n"
<< "Options:\n"
<< " [-h] - print usage and exit\n"
<< " [-V] - print version number and exit\n"
<< std::endl;
}
private:
Face m_face;
KeyChain m_keyChain;
autoconfig::MulticastDiscovery m_stage1;
autoconfig::GuessFromSearchDomains m_stage2;
autoconfig::GuessFromIdentityName m_stage3;
};
} // namespace tools
} // namespace ndn
int
main(int argc, char** argv)
{
int opt;
const char* programName = argv[0];
while ((opt = getopt(argc, argv, "hV")) != -1) {
switch (opt) {
case 'h':
ndn::tools::NdnAutoconfig::usage(programName);
return 0;
case 'V':
std::cout << NFD_VERSION_BUILD_STRING << std::endl;
return 0;
}
}
try {
ndn::tools::NdnAutoconfig autoConfigInstance;
autoConfigInstance.run();
}
catch (const std::exception& error) {
std::cerr << "ERROR: " << error.what() << std::endl;
return 1;
}
return 0;
}
@@ -0,0 +1,194 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "multicast-discovery.hpp"
#include <ndn-cxx/util/segment-fetcher.hpp>
namespace ndn {
namespace tools {
namespace autoconfig {
static const Name LOCALHOP_HUB_DISCOVERY_PREFIX = "/localhop/ndn-autoconf/hub";
MulticastDiscovery::MulticastDiscovery(Face& face, KeyChain& keyChain,
const NextStageCallback& nextStageOnFailure)
: Base(face, keyChain, nextStageOnFailure)
, nRequestedRegs(0)
, nFinishedRegs(0)
{
}
void
MulticastDiscovery::start()
{
std::cerr << "Trying multicast discovery..." << std::endl;
util::SegmentFetcher::fetch(m_face, Interest("/localhost/nfd/faces/list"),
ndn::util::DontVerifySegment(),
[this] (const ConstBufferPtr& data) {
registerHubDiscoveryPrefix(data);
},
[this] (uint32_t code, const std::string& msg) {
m_nextStageOnFailure(msg);
});
}
void
MulticastDiscovery::registerHubDiscoveryPrefix(const ConstBufferPtr& buffer)
{
std::vector<uint64_t> multicastFaces;
size_t offset = 0;
while (offset < buffer->size()) {
Block block;
bool ok = Block::fromBuffer(buffer, offset, block);
if (!ok)
{
std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
break;
}
offset += block.size();
nfd::FaceStatus faceStatus(block);
ndn::util::FaceUri uri(faceStatus.getRemoteUri());
if (uri.getScheme() == "udp4") {
namespace ip = boost::asio::ip;
boost::system::error_code ec;
ip::address address = ip::address::from_string(uri.getHost(), ec);
if (!ec && address.is_multicast()) {
multicastFaces.push_back(faceStatus.getFaceId());
}
else
continue;
}
}
if (multicastFaces.empty()) {
m_nextStageOnFailure("No multicast faces available, skipping multicast discovery stage");
}
else {
nfd::ControlParameters parameters;
parameters
.setName(LOCALHOP_HUB_DISCOVERY_PREFIX)
.setCost(1)
.setExpirationPeriod(time::seconds(30));
nRequestedRegs = multicastFaces.size();
nFinishedRegs = 0;
for (const auto& face : multicastFaces) {
parameters.setFaceId(face);
m_controller.start<nfd::RibRegisterCommand>(parameters,
bind(&MulticastDiscovery::onRegisterSuccess,
this),
bind(&MulticastDiscovery::onRegisterFailure,
this, _1, _2));
}
}
}
void
MulticastDiscovery::onRegisterSuccess()
{
++nFinishedRegs;
if (nRequestedRegs == nFinishedRegs) {
MulticastDiscovery::setStrategy();
}
}
void
MulticastDiscovery::onRegisterFailure(uint32_t code, const std::string& error)
{
std::cerr << "ERROR: " << error << " (code: " << code << ")" << std::endl;
--nRequestedRegs;
if (nRequestedRegs == nFinishedRegs) {
if (nRequestedRegs > 0) {
MulticastDiscovery::setStrategy();
} else {
m_nextStageOnFailure("Failed to register " + LOCALHOP_HUB_DISCOVERY_PREFIX.toUri() +
" for all multicast faces, skipping multicast discovery stage");
}
}
}
void
MulticastDiscovery::setStrategy()
{
nfd::ControlParameters parameters;
parameters
.setName(LOCALHOP_HUB_DISCOVERY_PREFIX)
.setStrategy("/localhost/nfd/strategy/broadcast");
m_controller.start<nfd::StrategyChoiceSetCommand>(parameters,
bind(&MulticastDiscovery::requestHubData, this),
bind(&MulticastDiscovery::onSetStrategyFailure,
this, _2));
}
void
MulticastDiscovery::onSetStrategyFailure(const std::string& error)
{
m_nextStageOnFailure("Failed to set broadcast strategy for " +
LOCALHOP_HUB_DISCOVERY_PREFIX.toUri() + " namespace (" + error + "). "
"Skipping multicast discovery stage");
}
void
MulticastDiscovery::requestHubData()
{
Interest interest(LOCALHOP_HUB_DISCOVERY_PREFIX);
interest.setInterestLifetime(time::milliseconds(4000)); // 4 seconds
interest.setMustBeFresh(true);
m_face.expressInterest(interest,
bind(&MulticastDiscovery::onSuccess, this, _2),
bind(m_nextStageOnFailure, "Timeout"));
}
void
MulticastDiscovery::onSuccess(Data& data)
{
const Block& content = data.getContent();
content.parse();
// Get Uri
Block::element_const_iterator blockValue = content.find(tlv::nfd::Uri);
if (blockValue == content.elements_end()) {
m_nextStageOnFailure("Incorrect reply to multicast discovery stage");
return;
}
std::string hubUri(reinterpret_cast<const char*>(blockValue->value()), blockValue->value_size());
this->connectToHub(hubUri);
}
} // namespace autoconfig
} // namespace tools
} // namespace ndn
@@ -0,0 +1,94 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NFD_TOOLS_NDN_AUTOCONFIG_MULTICAST_DISCOVERY_HPP
#define NFD_TOOLS_NDN_AUTOCONFIG_MULTICAST_DISCOVERY_HPP
#include "base.hpp"
namespace ndn {
namespace tools {
namespace autoconfig {
/**
* @brief Multicast discovery stage
*
* - Request
*
* The end host sends an Interest over a multicast face.
*
* Interest Name is /localhop/ndn-autoconf/hub.
*
* - Response
*
* A producer app on the HUB answer this Interest with a Data packet that contains a
* TLV-encoded Uri block. The value of this block is the URI for the HUB, preferably a
* UDP tunnel.
*/
class MulticastDiscovery : public Base
{
public:
/**
* @brief Create multicast discovery stage
* @sa Base::Base
*/
MulticastDiscovery(Face& face, KeyChain& keyChain, const NextStageCallback& nextStageOnFailure);
virtual void
start() DECL_OVERRIDE;
private:
void
registerHubDiscoveryPrefix(const ConstBufferPtr& buffer);
void
onRegisterSuccess();
void
onRegisterFailure(uint32_t code, const std::string& error);
void
setStrategy();
void
onSetStrategyFailure(const std::string& error);
// Start to look for a hub (NDN hub discovery first stage)
void
requestHubData();
void
onSuccess(Data& data);
private:
size_t nRequestedRegs;
size_t nFinishedRegs;
};
} // namespace autoconfig
} // namespace tools
} // namespace ndn
#endif // NFD_TOOLS_NDN_AUTOCONFIG_MULTICAST_DISCOVERY_HPP