blob: 2a5a12d4396875932c4912a9e967af5e537fb31b [file] [log] [blame]
Yanbiao Lic17de832014-11-21 17:51:45 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * 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
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 "remote-registrator.hpp"
27#include "core/logger.hpp"
28#include "core/scheduler.hpp"
29
30namespace nfd {
31namespace rib {
32
33NFD_LOG_INIT("RemoteRegistrator");
34
35using ndn::nfd::ControlParameters;
36using ndn::nfd::CommandOptions;
37
38
39const Name RemoteRegistrator::RM_LOCAL_PREFIX = "/localhost";
40const Name RemoteRegistrator::RM_HUB_PREFIX = "/localhop/nfd";
41const name::Component RemoteRegistrator::RM_IGNORE_COMMPONENT("rib");
42
43RemoteRegistrator::RemoteRegistrator(ndn::nfd::Controller& controller,
44 ndn::KeyChain& keyChain,
45 Rib& rib)
46 : m_nfdController(controller)
47 , m_keyChain(keyChain)
48 , m_rib(rib)
49 , m_refreshInterval(time::seconds(25))
50 , m_hasConnectedHub(false)
51 , m_nRetries(0)
52{
53}
54
55RemoteRegistrator::~RemoteRegistrator()
56{
57 // cancel all periodically refresh events.
58 for (auto&& entry : m_regEntries)
59 {
60 scheduler::cancel(entry.second);
61 }
62}
63
64void
65RemoteRegistrator::loadConfig(const ConfigSection& configSection)
66{
67 size_t cost = 15, timeout = 10000;
68 size_t retry = 0;
69 size_t interval = 0;
70 const size_t intervalDef = 25, intervalMax = 600;
71
72 NFD_LOG_INFO("Load remote_register section in rib section");
73 for (auto&& i : configSection)
74 {
75 if (i.first == "cost")
76 {
77 cost = i.second.get_value<size_t>();
78 }
79 else if (i.first == "timeout")
80 {
81 timeout = i.second.get_value<size_t>();
82 }
83 else if (i.first == "retry")
84 {
85 retry = i.second.get_value<size_t>();
86 }
87 else if (i.first == "refresh_interval")
88 {
89 interval = i.second.get_value<size_t>();
90 }
91 else
92 {
93 throw ConfigFile::Error("Unrecognized option \"" + i.first +
94 "\" in \"remote-registrator\" section");
95 }
96 }
97
98 m_controlParameters
99 .setCost(cost)
100 .setOrigin(ndn::nfd::ROUTE_ORIGIN_CLIENT)// set origin to client.
101 .setFaceId(0);// the remote hub will take the input face as the faceId.
102
103 m_commandOptions
104 .setPrefix(RM_HUB_PREFIX)
105 .setTimeout(time::milliseconds(timeout));
106
107 m_nRetries = retry;
108
109 if (interval == 0)
110 {
111 interval = intervalDef;
112 }
113
114 interval = std::min(interval, intervalMax);
115
116 m_refreshInterval = time::seconds(interval);
117}
118
119void
120RemoteRegistrator::registerPrefix(const Name& prefix)
121{
122 if (RM_LOCAL_PREFIX.isPrefixOf(prefix))
123 {
124 NFD_LOG_INFO("local registration only for " << prefix);
125 return;
126 }
127
128 bool isHubPrefix = prefix == RM_HUB_PREFIX;
129
130 if (isHubPrefix)
131 {
132 NFD_LOG_INFO("this is a prefix registered by some hub: " << prefix);
133
134 m_hasConnectedHub = true;
135
136 redoRegistration();
137 return;
138 }
139
140 if (!m_hasConnectedHub)
141 {
142 NFD_LOG_INFO("no hub connected when registering " << prefix);
143 return;
144 }
145
146 std::pair<Name, size_t> identity = findIdentityForRegistration(prefix);
147
148 if (0 == identity.second)
149 {
150 NFD_LOG_INFO("no proper identity found for registering " << prefix);
151 return;
152 }
153
154 Name prefixForRegistration;
155 if (identity.first.size() == identity.second)
156 {
157 prefixForRegistration = identity.first;
158 }
159 else
160 {
161 prefixForRegistration = identity.first.getPrefix(-1);
162 }
163
164 if (m_regEntries.find(prefixForRegistration) != m_regEntries.end())
165 {
166 NFD_LOG_INFO("registration already in process for " << prefix);
167 return;
168 }
169
170 // make copies of m_controlParameters and m_commandOptions to
171 // avoid unreasonable overwriting during concurrent registration
172 // and unregistration.
173 ControlParameters parameters = m_controlParameters;
174 CommandOptions options = m_commandOptions;
175
176 startRegistration(parameters.setName(prefixForRegistration),
177 options.setSigningIdentity(identity.first),
178 m_nRetries);
179}
180
181void
182RemoteRegistrator::unregisterPrefix(const Name& prefix)
183{
184 if (prefix == RM_HUB_PREFIX)
185 {
186 NFD_LOG_INFO("disconnected to hub with prefix: " << prefix);
187
188 // for phase 1: suppose there is at most one hub connected.
189 // if the hub prefix has been unregistered locally, there may
190 // be no connected hub.
191 m_hasConnectedHub = false;
192
193 clearRefreshEvents();
194 return;
195 }
196
197 if (!m_hasConnectedHub)
198 {
199 NFD_LOG_INFO("no hub connected when unregistering " << prefix);
200 return;
201 }
202
203 std::pair<Name, size_t> identity = findIdentityForRegistration(prefix);
204
205 if (0 == identity.second)
206 {
207 NFD_LOG_INFO("no proper identity found for unregistering " << prefix);
208 return;
209 }
210
211 Name prefixForRegistration;
212 if (identity.first.size() == identity.second)
213 {
214 prefixForRegistration = identity.first;
215 }
216 else
217 {
218 prefixForRegistration = identity.first.getPrefix(-1);
219 }
220
221 RegisteredEntryIt iRegEntry = m_regEntries.find(prefixForRegistration);
222 if (m_regEntries.end() == iRegEntry)
223 {
224 NFD_LOG_INFO("no existing entry found when unregistering " << prefix);
225 return;
226 }
227
228 for (auto&& entry : m_rib)
229 {
230 if (prefixForRegistration.isPrefixOf(entry.first) &&
231 findIdentityForRegistration(entry.first) == identity)
232 {
233 NFD_LOG_INFO("this identity should be kept for other rib entry: "
234 << entry.first);
235 return;
236 }
237 }
238
239 scheduler::cancel(iRegEntry->second);
240 m_regEntries.erase(iRegEntry);
241
242 // make copies of m_controlParameters and m_commandOptions to
243 // avoid unreasonable overwriting during concurrent registration
244 // and unregistration.
245 ControlParameters parameters = m_controlParameters;
246 CommandOptions options = m_commandOptions;
247
248 startUnregistration(parameters.setName(prefixForRegistration).unsetCost(),
249 options.setSigningIdentity(identity.first),
250 m_nRetries);
251}
252
253std::pair<Name, size_t>
254RemoteRegistrator::findIdentityForRegistration(const Name& prefix)
255{
256 std::pair<Name, size_t> candidateIdentity;
257 std::vector<Name> identities;
258 bool isPrefix = false;
259 size_t maxLength = 0, curLength = 0;
260
261 // get all identies from the key-cahin except the default one.
262 m_keyChain.getAllIdentities(identities, false);
263
264 // get the default identity.
265 identities.push_back(m_keyChain.getDefaultIdentity());
266
267 // longest prefix matching to all indenties.
268 for (auto&& i : identities)
269 {
270 if (!i.empty() && RM_IGNORE_COMMPONENT == i.at(-1))
271 {
272 isPrefix = i.getPrefix(-1).isPrefixOf(prefix);
273 curLength = i.size() - 1;
274 }
275 else
276 {
277 isPrefix = i.isPrefixOf(prefix);
278 curLength = i.size();
279 }
280
281 if (isPrefix && curLength > maxLength)
282 {
283 candidateIdentity.first = i;
284 maxLength = curLength;
285 }
286 }
287
288 candidateIdentity.second = maxLength;
289
290 return candidateIdentity;
291}
292
293void
294RemoteRegistrator::startRegistration(const ControlParameters& parameters,
295 const CommandOptions& options,
296 int nRetries)
297{
298 NFD_LOG_INFO("start register " << parameters.getName());
299
300 m_nfdController.start<ndn::nfd::RibRegisterCommand>(
301 parameters,
302 bind(&RemoteRegistrator::onRegSuccess,
303 this, parameters, options),
304 bind(&RemoteRegistrator::onRegFailure,
305 this, _1, _2, parameters, options, nRetries),
306 options);
307}
308
309void
310RemoteRegistrator::startUnregistration(const ControlParameters& parameters,
311 const CommandOptions& options,
312 int nRetries)
313{
314 NFD_LOG_INFO("start unregister " << parameters.getName());
315
316 m_nfdController.start<ndn::nfd::RibUnregisterCommand>(
317 parameters,
318 bind(&RemoteRegistrator::onUnregSuccess,
319 this, parameters, options),
320 bind(&RemoteRegistrator::onUnregFailure,
321 this, _1, _2, parameters, options, nRetries),
322 options);
323}
324
325void
326RemoteRegistrator::onRegSuccess(const ControlParameters& parameters,
327 const CommandOptions& options)
328{
329 NFD_LOG_INFO("success to register " << parameters.getName());
330
331 RegisteredEntryIt iRegEntry = m_regEntries.find(parameters.getName());
332
333 if (m_regEntries.end() != iRegEntry)
334 {
335 NFD_LOG_DEBUG("Existing Entry: (" << iRegEntry->first
336 << ", " << iRegEntry->second
337 << ")");
338
339 scheduler::cancel(iRegEntry->second);
340 iRegEntry->second = scheduler::schedule(
341 m_refreshInterval,
342 bind(&RemoteRegistrator::startRegistration,
343 this, parameters, options, m_nRetries));
344 }
345 else
346 {
347 NFD_LOG_DEBUG("New Entry");
348 m_regEntries.insert(RegisteredEntry(
349 parameters.getName(),
350 scheduler::schedule(
351 m_refreshInterval,
352 bind(&RemoteRegistrator::startRegistration,
353 this, parameters, options, m_nRetries))));
354 }
355}
356
357void
358RemoteRegistrator::onRegFailure(uint32_t code, const std::string& reason,
359 const ControlParameters& parameters,
360 const CommandOptions& options,
361 int nRetries)
362{
363 NFD_LOG_INFO("fail to unregister " << parameters.getName()
364 << "\n\t reason:" << reason
365 << "\n\t remain retries:" << nRetries);
366
367 if (nRetries > 0)
368 {
369 startRegistration(parameters, options, nRetries - 1);
370 }
371}
372
373void
374RemoteRegistrator::onUnregSuccess(const ControlParameters& parameters,
375 const CommandOptions& options)
376{
377 NFD_LOG_INFO("success to unregister " << parameters.getName());
378}
379
380void
381RemoteRegistrator::onUnregFailure(uint32_t code, const std::string& reason,
382 const ControlParameters& parameters,
383 const CommandOptions& options,
384 int nRetries)
385{
386 NFD_LOG_INFO("fail to unregister " << parameters.getName()
387 << "\n\t reason:" << reason
388 << "\n\t remain retries:" << nRetries);
389
390 if (nRetries > 0)
391 {
392 startUnregistration(parameters, options, nRetries - 1);
393 }
394}
395
396void
397RemoteRegistrator::redoRegistration()
398{
399 NFD_LOG_INFO("redo " << m_regEntries.size()
400 << " registration when new Hub connection is built.");
401
402 for (auto&& entry : m_regEntries)
403 {
404 // make copies to avoid unreasonable overwrite.
405 ControlParameters parameters = m_controlParameters;
406 CommandOptions options = m_commandOptions;
407 startRegistration(parameters.setName(entry.first),
408 options.setSigningIdentity(entry.first),
409 m_nRetries);
410 }
411}
412
413void
414RemoteRegistrator::clearRefreshEvents()
415{
416 for (auto&& entry : m_regEntries)
417 {
418 scheduler::cancel(entry.second);
419 }
420}
421
422} // namespace rib
423} // namespace nfd