blob: 4efcec60ee3c2e56892a16e665ce1e425596c897 [file] [log] [blame]
Alexander Afanasyev2a655f72015-01-26 18:38:33 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shi29b41282016-08-22 03:47:02 +00003 * Copyright (c) 2014-2016, Regents of the University of California,
Alexander Afanasyev2a655f72015-01-26 18:38:33 -08004 * 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.
10 *
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/>.
24 */
25
26#include "multicast-discovery.hpp"
27
28#include <ndn-cxx/util/segment-fetcher.hpp>
29
30namespace ndn {
31namespace tools {
32namespace autoconfig {
33
34static const Name LOCALHOP_HUB_DISCOVERY_PREFIX = "/localhop/ndn-autoconf/hub";
35
36MulticastDiscovery::MulticastDiscovery(Face& face, KeyChain& keyChain,
37 const NextStageCallback& nextStageOnFailure)
38 : Base(face, keyChain, nextStageOnFailure)
Junxiao Shi52fa45c2016-11-29 21:18:13 +000039 , m_nRequestedRegs(0)
40 , m_nFinishedRegs(0)
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080041{
42}
43
44void
45MulticastDiscovery::start()
46{
47 std::cerr << "Trying multicast discovery..." << std::endl;
48
Junxiao Shi52fa45c2016-11-29 21:18:13 +000049 util::SegmentFetcher::fetch(
50 m_face, Interest("/localhost/nfd/faces/list"),
51 m_validator,
52 [this] (const ConstBufferPtr& data) { registerHubDiscoveryPrefix(data); },
53 [this] (uint32_t code, const std::string& msg) { m_nextStageOnFailure(msg); });
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080054}
55
56void
57MulticastDiscovery::registerHubDiscoveryPrefix(const ConstBufferPtr& buffer)
58{
59 std::vector<uint64_t> multicastFaces;
60
61 size_t offset = 0;
62 while (offset < buffer->size()) {
Junxiao Shi78926c92015-02-28 22:56:06 -070063 bool isOk = false;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080064 Block block;
Junxiao Shi78926c92015-02-28 22:56:06 -070065 std::tie(isOk, block) = Block::fromBuffer(buffer, offset);
66 if (!isOk) {
67 std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
68 break;
69 }
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080070
71 offset += block.size();
72
Junxiao Shi52fa45c2016-11-29 21:18:13 +000073 ndn::nfd::FaceStatus faceStatus(block);
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080074
Junxiao Shi52fa45c2016-11-29 21:18:13 +000075 FaceUri uri(faceStatus.getRemoteUri());
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080076 if (uri.getScheme() == "udp4") {
77 namespace ip = boost::asio::ip;
78 boost::system::error_code ec;
79 ip::address address = ip::address::from_string(uri.getHost(), ec);
80
81 if (!ec && address.is_multicast()) {
82 multicastFaces.push_back(faceStatus.getFaceId());
83 }
84 else
85 continue;
86 }
87 }
88
89 if (multicastFaces.empty()) {
90 m_nextStageOnFailure("No multicast faces available, skipping multicast discovery stage");
91 }
92 else {
Junxiao Shi52fa45c2016-11-29 21:18:13 +000093 ControlParameters parameters;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080094 parameters
95 .setName(LOCALHOP_HUB_DISCOVERY_PREFIX)
96 .setCost(1)
97 .setExpirationPeriod(time::seconds(30));
98
Junxiao Shi52fa45c2016-11-29 21:18:13 +000099 m_nRequestedRegs = multicastFaces.size();
100 m_nFinishedRegs = 0;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800101
102 for (const auto& face : multicastFaces) {
103 parameters.setFaceId(face);
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000104 m_controller.start<ndn::nfd::RibRegisterCommand>(
105 parameters,
106 bind(&MulticastDiscovery::onRegisterSuccess, this),
107 bind(&MulticastDiscovery::onRegisterFailure, this, _1));
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800108 }
109 }
110}
111
112void
113MulticastDiscovery::onRegisterSuccess()
114{
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000115 ++m_nFinishedRegs;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800116
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000117 if (m_nRequestedRegs == m_nFinishedRegs) {
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800118 MulticastDiscovery::setStrategy();
119 }
120}
121
122void
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000123MulticastDiscovery::onRegisterFailure(const ControlResponse& response)
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800124{
Junxiao Shi29b41282016-08-22 03:47:02 +0000125 std::cerr << "ERROR: " << response.getText() << " (code: " << response.getCode() << ")" << std::endl;
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000126 --m_nRequestedRegs;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800127
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000128 if (m_nRequestedRegs == m_nFinishedRegs) {
129 if (m_nRequestedRegs > 0) {
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800130 MulticastDiscovery::setStrategy();
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000131 }
132 else {
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800133 m_nextStageOnFailure("Failed to register " + LOCALHOP_HUB_DISCOVERY_PREFIX.toUri() +
134 " for all multicast faces, skipping multicast discovery stage");
135 }
136 }
137}
138
139void
140MulticastDiscovery::setStrategy()
141{
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000142 ControlParameters parameters;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800143 parameters
144 .setName(LOCALHOP_HUB_DISCOVERY_PREFIX)
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700145 .setStrategy("/localhost/nfd/strategy/multicast");
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800146
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000147 m_controller.start<ndn::nfd::StrategyChoiceSetCommand>(
148 parameters,
149 bind(&MulticastDiscovery::requestHubData, this),
150 bind(&MulticastDiscovery::onSetStrategyFailure, this, _1));
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800151}
152
153void
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000154MulticastDiscovery::onSetStrategyFailure(const ControlResponse& response)
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800155{
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700156 m_nextStageOnFailure("Failed to set multicast strategy for " +
Junxiao Shi29b41282016-08-22 03:47:02 +0000157 LOCALHOP_HUB_DISCOVERY_PREFIX.toUri() + " namespace (" + response.getText() + "). "
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800158 "Skipping multicast discovery stage");
159}
160
161void
162MulticastDiscovery::requestHubData()
163{
164 Interest interest(LOCALHOP_HUB_DISCOVERY_PREFIX);
165 interest.setInterestLifetime(time::milliseconds(4000)); // 4 seconds
166 interest.setMustBeFresh(true);
167
168 m_face.expressInterest(interest,
169 bind(&MulticastDiscovery::onSuccess, this, _2),
170 bind(m_nextStageOnFailure, "Timeout"));
171}
172
173void
174MulticastDiscovery::onSuccess(Data& data)
175{
176 const Block& content = data.getContent();
177 content.parse();
178
179 // Get Uri
180 Block::element_const_iterator blockValue = content.find(tlv::nfd::Uri);
181 if (blockValue == content.elements_end()) {
182 m_nextStageOnFailure("Incorrect reply to multicast discovery stage");
183 return;
184 }
185 std::string hubUri(reinterpret_cast<const char*>(blockValue->value()), blockValue->value_size());
186 this->connectToHub(hubUri);
187}
188
189} // namespace autoconfig
190} // namespace tools
191} // namespace ndn