multicast-discovery.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "multicast-discovery.hpp"
27 
28 namespace ndn {
29 namespace tools {
30 namespace autoconfig {
31 
32 static const Name LOCALHOP_HUB_DISCOVERY_PREFIX = "/localhop/ndn-autoconf/hub";
33 
34 MulticastDiscovery::MulticastDiscovery(Face& face, KeyChain& keyChain,
35  const NextStageCallback& nextStageOnFailure)
36  : Base(face, keyChain, nextStageOnFailure)
37  , m_nRequestedRegs(0)
38  , m_nFinishedRegs(0)
39 {
40 }
41 
42 void
44 {
45  std::cerr << "Trying multicast discovery..." << std::endl;
46 
47  this->collectMulticastFaces();
48 }
49 
50 void
51 MulticastDiscovery::collectMulticastFaces()
52 {
53  ndn::nfd::FaceQueryFilter filter;
54  filter.setLinkType(ndn::nfd::LINK_TYPE_MULTI_ACCESS);
55  m_controller.fetch<ndn::nfd::FaceQueryDataset>(
56  filter,
57  bind(&MulticastDiscovery::registerHubDiscoveryPrefix, this, _1),
58  bind(m_nextStageOnFailure, _2)
59  );
60 }
61 
62 void
63 MulticastDiscovery::registerHubDiscoveryPrefix(const std::vector<ndn::nfd::FaceStatus>& dataset)
64 {
65  std::vector<uint64_t> multicastFaces;
66  std::transform(dataset.begin(), dataset.end(), std::back_inserter(multicastFaces),
67  [] (const ndn::nfd::FaceStatus& faceStatus) { return faceStatus.getFaceId(); });
68 
69  if (multicastFaces.empty()) {
70  m_nextStageOnFailure("No multicast faces available, skipping multicast discovery stage");
71  }
72  else {
73  ControlParameters parameters;
74  parameters
75  .setName(LOCALHOP_HUB_DISCOVERY_PREFIX)
76  .setCost(1)
77  .setExpirationPeriod(time::seconds(30));
78 
79  m_nRequestedRegs = multicastFaces.size();
80  m_nFinishedRegs = 0;
81 
82  for (const auto& face : multicastFaces) {
83  parameters.setFaceId(face);
84  m_controller.start<ndn::nfd::RibRegisterCommand>(
85  parameters,
86  bind(&MulticastDiscovery::onRegisterSuccess, this),
87  bind(&MulticastDiscovery::onRegisterFailure, this, _1));
88  }
89  }
90 }
91 
92 void
93 MulticastDiscovery::onRegisterSuccess()
94 {
95  ++m_nFinishedRegs;
96 
97  if (m_nRequestedRegs == m_nFinishedRegs) {
98  MulticastDiscovery::setStrategy();
99  }
100 }
101 
102 void
103 MulticastDiscovery::onRegisterFailure(const ControlResponse& response)
104 {
105  std::cerr << "ERROR: " << response.getText() << " (code: " << response.getCode() << ")" << std::endl;
106  --m_nRequestedRegs;
107 
108  if (m_nRequestedRegs == m_nFinishedRegs) {
109  if (m_nRequestedRegs > 0) {
110  MulticastDiscovery::setStrategy();
111  }
112  else {
113  m_nextStageOnFailure("Failed to register " + LOCALHOP_HUB_DISCOVERY_PREFIX.toUri() +
114  " for all multicast faces, skipping multicast discovery stage");
115  }
116  }
117 }
118 
119 void
120 MulticastDiscovery::setStrategy()
121 {
122  ControlParameters parameters;
123  parameters
124  .setName(LOCALHOP_HUB_DISCOVERY_PREFIX)
125  .setStrategy("/localhost/nfd/strategy/multicast");
126 
127  m_controller.start<ndn::nfd::StrategyChoiceSetCommand>(
128  parameters,
129  bind(&MulticastDiscovery::requestHubData, this),
130  bind(&MulticastDiscovery::onSetStrategyFailure, this, _1));
131 }
132 
133 void
134 MulticastDiscovery::onSetStrategyFailure(const ControlResponse& response)
135 {
136  m_nextStageOnFailure("Failed to set multicast strategy for " +
137  LOCALHOP_HUB_DISCOVERY_PREFIX.toUri() + " namespace (" + response.getText() + "). "
138  "Skipping multicast discovery stage");
139 }
140 
141 void
142 MulticastDiscovery::requestHubData()
143 {
144  Interest interest(LOCALHOP_HUB_DISCOVERY_PREFIX);
145  interest.setInterestLifetime(time::milliseconds(4000)); // 4 seconds
146  interest.setMustBeFresh(true);
147 
148  m_face.expressInterest(interest,
149  bind(&MulticastDiscovery::onSuccess, this, _2),
150  bind(m_nextStageOnFailure, "HUB Data not received: nacked"),
151  bind(m_nextStageOnFailure, "HUB Data not received: timeout"));
152 }
153 
154 void
155 MulticastDiscovery::onSuccess(const Data& data)
156 {
157  const Block& content = data.getContent();
158  content.parse();
159 
160  // Get Uri
161  Block::element_const_iterator blockValue = content.find(tlv::nfd::Uri);
162  if (blockValue == content.elements_end()) {
163  m_nextStageOnFailure("Incorrect reply to multicast discovery stage");
164  return;
165  }
166  std::string hubUri(reinterpret_cast<const char*>(blockValue->value()), blockValue->value_size());
167  this->connectToHub(hubUri);
168 }
169 
170 } // namespace autoconfig
171 } // namespace tools
172 } // namespace ndn
Copyright (c) 2014-2016, Regents of the University of California, Arizona Board of Regents...
Definition: nfd.hpp:35
void start() override
Start the stage.
static const Name LOCALHOP_HUB_DISCOVERY_PREFIX
NextStageCallback m_nextStageOnFailure
Definition: base.hpp:114
void connectToHub(const std::string &uri)
Attempt to connect to local hub using the uri FaceUri.
Definition: base.cpp:41
ndn::nfd::Controller m_controller
Definition: base.hpp:113
std::function< void(const std::string &)> NextStageCallback
Callback to be called when the stage fails.
Definition: base.hpp:64
Base class for discovery stages.
Definition: base.hpp:48
MulticastDiscovery(Face &face, KeyChain &keyChain, const NextStageCallback &nextStageOnFailure)
Create multicast discovery stage.