blob: 6432acf78e7250c7f2893083fe307ca899a3c521 [file] [log] [blame]
Jeff Thompson25b4e612013-10-10 16:03:24 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -07002/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 *
12 * Based on code originally written by Jeff Thompson <jefft0@remap.ucla.edu>
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070013 */
14
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080015#include "common.hpp"
16
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080017#include "face.hpp"
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070018
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080019#include "security/signature-sha256-with-rsa.hpp"
20
21#include "util/time.hpp"
22#include "util/random.hpp"
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -060023#include "util/config-file.hpp"
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080024#include <cstdlib>
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080025
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080026#include "management/nfd-controller.hpp"
Jeff Thompsonb982b6d2013-07-15 18:15:45 -070027
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070028namespace ndn {
Alexander Afanasyevb790d952014-01-24 12:07:53 -080029
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080030Face::Face()
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -070031 : m_nfdController(new nfd::Controller(*this))
32 , m_isDirectNfdFibManagementRequested(false)
Jeff Thompsonfb29cda2013-08-24 10:26:54 -070033{
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -060034 const std::string socketName = UnixTransport::getDefaultSocketName(m_config);
Alexander Afanasyevf73f0632014-05-12 18:02:37 -070035 construct(make_shared<UnixTransport>(socketName),
Alexander Afanasyev505646e2014-02-24 20:13:37 -080036 make_shared<boost::asio::io_service>());
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080037}
38
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080039Face::Face(const shared_ptr<boost::asio::io_service>& ioService)
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -070040 : m_nfdController(new nfd::Controller(*this))
41 , m_isDirectNfdFibManagementRequested(false)
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080042{
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -060043 const std::string socketName = UnixTransport::getDefaultSocketName(m_config);
Alexander Afanasyevf73f0632014-05-12 18:02:37 -070044 construct(make_shared<UnixTransport>(socketName),
Alexander Afanasyev505646e2014-02-24 20:13:37 -080045 ioService);
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080046}
47
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070048class NullIoDeleter
49{
50public:
51 void
52 operator()(boost::asio::io_service*)
53 {
54 }
55};
56
57Face::Face(boost::asio::io_service& ioService)
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -070058 : m_nfdController(new nfd::Controller(*this))
59 , m_isDirectNfdFibManagementRequested(false)
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070060{
61 const std::string socketName = UnixTransport::getDefaultSocketName(m_config);
Alexander Afanasyevf73f0632014-05-12 18:02:37 -070062 construct(make_shared<UnixTransport>(socketName),
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070063 shared_ptr<boost::asio::io_service>(&ioService, NullIoDeleter()));
64}
65
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080066Face::Face(const std::string& host, const std::string& port/* = "6363"*/)
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -070067 : m_nfdController(new nfd::Controller(*this))
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080068{
Alexander Afanasyevf73f0632014-05-12 18:02:37 -070069 construct(make_shared<TcpTransport>(host, port),
Alexander Afanasyev505646e2014-02-24 20:13:37 -080070 make_shared<boost::asio::io_service>());
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080071}
72
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080073Face::Face(const shared_ptr<Transport>& transport)
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -070074 : m_nfdController(new nfd::Controller(*this))
75 , m_isDirectNfdFibManagementRequested(false)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080076{
77 construct(transport,
Alexander Afanasyev505646e2014-02-24 20:13:37 -080078 make_shared<boost::asio::io_service>());
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080079}
80
81Face::Face(const shared_ptr<Transport>& transport,
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070082 boost::asio::io_service& ioService)
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -070083 : m_nfdController(new nfd::Controller(*this))
84 , m_isDirectNfdFibManagementRequested(false)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080085{
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070086 construct(transport,
87 shared_ptr<boost::asio::io_service>(&ioService, NullIoDeleter()));
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080088}
89
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -070090Face::~Face()
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080091{
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -070092 delete m_nfdController;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080093}
94
95void
96Face::construct(const shared_ptr<Transport>& transport,
Alexander Afanasyev505646e2014-02-24 20:13:37 -080097 const shared_ptr<boost::asio::io_service>& ioService)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080098{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -080099 m_pitTimeoutCheckTimerActive = false;
100 m_transport = transport;
101 m_ioService = ioService;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800102
Alexander Afanasyevb67090a2014-04-29 22:31:01 -0700103 m_pitTimeoutCheckTimer = make_shared<monotonic_deadline_timer>(ref(*m_ioService));
104 m_processEventsTimeoutTimer = make_shared<monotonic_deadline_timer>(ref(*m_ioService));
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800105
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600106 std::string protocol = "nrd-0.1";
107
108 try
Alexander Afanasyevefe3ab22014-02-19 14:57:50 -0800109 {
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600110 protocol = m_config.getParsedConfiguration().get<std::string>("protocol");
111 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700112 catch (boost::property_tree::ptree_bad_path& error)
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600113 {
114 // protocol not specified
115 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700116 catch (boost::property_tree::ptree_bad_data& error)
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600117 {
118 throw ConfigFile::Error(error.what());
119 }
120
121 if (isSupportedNrdProtocol(protocol))
122 {
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -0700123 // do nothing
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600124 }
Steve DiBenedettoacab8802014-03-24 11:15:57 -0600125 else if (isSupportedNfdProtocol(protocol))
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600126 {
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -0700127 m_isDirectNfdFibManagementRequested = true;
Alexander Afanasyevefe3ab22014-02-19 14:57:50 -0800128 }
Jeff Thompsonfb29cda2013-08-24 10:26:54 -0700129 else
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600130 {
131 throw Face::Error("Cannot create controller for unsupported protocol \"" + protocol + "\"");
132 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800133}
134
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800135const PendingInterestId*
136Face::expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout)
137{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800138 if (!m_transport->isConnected())
139 m_transport->connect(*m_ioService,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800140 bind(&Face::onReceiveElement, this, _1));
141
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700142 shared_ptr<Interest> interestToExpress = make_shared<Interest>(interest);
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800143
Alexander Afanasyev4e50b972014-03-25 10:57:50 -0700144 // If the same ioService thread, dispatch directly calls the method
145 m_ioService->dispatch(bind(&Face::asyncExpressInterest, this,
146 interestToExpress, onData, onTimeout));
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800147
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800148 return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
149}
150
151const PendingInterestId*
152Face::expressInterest(const Name& name,
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800153 const Interest& tmpl,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800154 const OnData& onData, const OnTimeout& onTimeout/* = OnTimeout()*/)
155{
156 return expressInterest(Interest(name,
157 tmpl.getMinSuffixComponents(),
158 tmpl.getMaxSuffixComponents(),
159 tmpl.getExclude(),
160 tmpl.getChildSelector(),
161 tmpl.getMustBeFresh(),
162 tmpl.getScope(),
163 tmpl.getInterestLifetime()),
164 onData, onTimeout);
165}
166
167void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800168Face::asyncExpressInterest(const shared_ptr<const Interest>& interest,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800169 const OnData& onData, const OnTimeout& onTimeout)
170{
Alexander Afanasyev4e50b972014-03-25 10:57:50 -0700171 if (!m_transport->isExpectingData())
172 m_transport->resume();
173
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700174 m_pendingInterestTable.push_back(make_shared<PendingInterest>(interest, onData, onTimeout));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800175
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800176 if (!interest->getLocalControlHeader().empty(false, true))
177 {
178 // encode only NextHopFaceId towards the forwarder
179 m_transport->send(interest->getLocalControlHeader().wireEncode(*interest, false, true),
180 interest->wireEncode());
181 }
182 else
183 {
184 m_transport->send(interest->wireEncode());
185 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800186
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800187 if (!m_pitTimeoutCheckTimerActive) {
188 m_pitTimeoutCheckTimerActive = true;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700189 m_pitTimeoutCheckTimer->expires_from_now(time::milliseconds(100));
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800190 m_pitTimeoutCheckTimer->async_wait(bind(&Face::checkPitExpire, this));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800191 }
192}
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800193
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800194void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800195Face::put(const Data& data)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800196{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800197 if (!m_transport->isConnected())
198 m_transport->connect(*m_ioService,
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800199 bind(&Face::onReceiveElement, this, _1));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800200
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800201 if (!data.getLocalControlHeader().empty(false, true))
202 {
Alexander Afanasyev83018352014-02-18 19:52:15 -0800203 m_transport->send(data.getLocalControlHeader().wireEncode(data, false, true),
204 data.wireEncode());
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800205 }
206 else
207 {
Alexander Afanasyev83018352014-02-18 19:52:15 -0800208 m_transport->send(data.wireEncode());
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800209 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800210}
211
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800212void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800213Face::removePendingInterest(const PendingInterestId* pendingInterestId)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800214{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800215 m_ioService->post(bind(&Face::asyncRemovePendingInterest, this, pendingInterestId));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800216}
217
218
219void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800220Face::asyncRemovePendingInterest(const PendingInterestId* pendingInterestId)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800221{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800222 m_pendingInterestTable.remove_if(MatchPendingInterestId(pendingInterestId));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800223}
224
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -0700225
226template<class SignatureGenerator>
227const RegisteredPrefixId*
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700228Face::registerPrefixImpl(const Name& prefix,
229 const shared_ptr<InterestFilterRecord>& filter,
230 const RegisterPrefixSuccessCallback& onSuccess,
231 const RegisterPrefixFailureCallback& onFailure,
232 const SignatureGenerator& signatureGenerator)
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -0700233{
234 typedef void (nfd::Controller::*Registrator)
235 (const nfd::ControlParameters&,
236 const nfd::Controller::CommandSucceedCallback&,
237 const nfd::Controller::CommandFailCallback&,
238 const SignatureGenerator&,
239 const time::milliseconds&);
240
241 Registrator registrator, unregistrator;
242 if (!m_isDirectNfdFibManagementRequested) {
243 registrator = static_cast<Registrator>(&nfd::Controller::start<nfd::RibRegisterCommand>);
244 unregistrator = static_cast<Registrator>(&nfd::Controller::start<nfd::RibUnregisterCommand>);
245 }
246 else {
247 registrator = static_cast<Registrator>(&nfd::Controller::start<nfd::FibAddNextHopCommand>);
248 unregistrator = static_cast<Registrator>(&nfd::Controller::start<nfd::FibRemoveNextHopCommand>);
249 }
250
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -0700251 nfd::ControlParameters parameters;
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700252 parameters.setName(prefix);
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -0700253
254 RegisteredPrefix::Unregistrator bindedUnregistrator =
255 bind(unregistrator, m_nfdController, parameters, _1, _2,
256 signatureGenerator,
257 m_nfdController->getDefaultCommandTimeout());
258
259 shared_ptr<RegisteredPrefix> prefixToRegister =
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700260 ndn::make_shared<RegisteredPrefix>(prefix, filter, bindedUnregistrator);
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -0700261
262 (m_nfdController->*registrator)(parameters,
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700263 bind(&Face::afterPrefixRegistered, this, prefixToRegister, onSuccess),
264 bind(onFailure, prefixToRegister->getPrefix(), _2),
Alexander Afanasyevee8bb1e2014-05-02 17:39:54 -0700265 signatureGenerator,
266 m_nfdController->getDefaultCommandTimeout());
267
268 return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
269}
270
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800271const RegisteredPrefixId*
Alexander Afanasyev90164962014-03-06 08:29:59 +0000272Face::setInterestFilter(const InterestFilter& interestFilter,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800273 const OnInterest& onInterest,
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700274 const RegisterPrefixSuccessCallback& onSuccess,
275 const RegisterPrefixFailureCallback& onFailure,
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700276 const IdentityCertificate& certificate)
277{
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700278 shared_ptr<InterestFilterRecord> filter =
279 make_shared<InterestFilterRecord>(interestFilter, onInterest);
280
281 return registerPrefixImpl(interestFilter.getPrefix(), filter,
282 onSuccess, onFailure,
283 certificate);
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700284}
285
286const RegisteredPrefixId*
Alexander Afanasyev90164962014-03-06 08:29:59 +0000287Face::setInterestFilter(const InterestFilter& interestFilter,
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700288 const OnInterest& onInterest,
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700289 const RegisterPrefixFailureCallback& onFailure,
290 const IdentityCertificate& certificate)
291{
292 shared_ptr<InterestFilterRecord> filter =
293 make_shared<InterestFilterRecord>(interestFilter, onInterest);
294
295 return registerPrefixImpl(interestFilter.getPrefix(), filter,
296 RegisterPrefixSuccessCallback(), onFailure,
297 certificate);
298}
299
300const RegisteredPrefixId*
301Face::setInterestFilter(const InterestFilter& interestFilter,
302 const OnInterest& onInterest,
303 const RegisterPrefixSuccessCallback& onSuccess,
304 const RegisterPrefixFailureCallback& onFailure,
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700305 const Name& identity)
306{
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700307 shared_ptr<InterestFilterRecord> filter =
308 make_shared<InterestFilterRecord>(interestFilter, onInterest);
309
310 return registerPrefixImpl(interestFilter.getPrefix(), filter,
311 onSuccess, onFailure,
312 identity);
313}
314
315const RegisteredPrefixId*
316Face::setInterestFilter(const InterestFilter& interestFilter,
317 const OnInterest& onInterest,
318 const RegisterPrefixFailureCallback& onFailure,
319 const Name& identity)
320{
321 shared_ptr<InterestFilterRecord> filter =
322 make_shared<InterestFilterRecord>(interestFilter, onInterest);
323
324 return registerPrefixImpl(interestFilter.getPrefix(), filter,
325 RegisterPrefixSuccessCallback(), onFailure,
326 identity);
327}
328
329
330const InterestFilterId*
331Face::setInterestFilter(const InterestFilter& interestFilter,
332 const OnInterest& onInterest)
333{
334 shared_ptr<InterestFilterRecord> filter =
335 make_shared<InterestFilterRecord>(interestFilter, onInterest);
336
337 getIoService().post(bind(&Face::asyncSetInterestFilter, this, filter));
338
339 return reinterpret_cast<const InterestFilterId*>(filter.get());
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700340}
341
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800342void
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700343Face::asyncSetInterestFilter(const shared_ptr<InterestFilterRecord>& interestFilterRecord)
344{
345 m_interestFilterTable.push_back(interestFilterRecord);
346}
347
348const RegisteredPrefixId*
349Face::registerPrefix(const Name& prefix,
350 const RegisterPrefixSuccessCallback& onSuccess,
351 const RegisterPrefixFailureCallback& onFailure,
352 const IdentityCertificate& certificate)
353{
354 return registerPrefixImpl(prefix, shared_ptr<InterestFilterRecord>(),
355 onSuccess, onFailure,
356 certificate);
357}
358
359const RegisteredPrefixId*
360Face::registerPrefix(const Name& prefix,
361 const RegisterPrefixSuccessCallback& onSuccess,
362 const RegisterPrefixFailureCallback& onFailure,
363 const Name& identity)
364{
365 return registerPrefixImpl(prefix, shared_ptr<InterestFilterRecord>(),
366 onSuccess, onFailure,
367 identity);
368}
369
370
371void
372Face::afterPrefixRegistered(const shared_ptr<RegisteredPrefix>& registeredPrefix,
373 const RegisterPrefixSuccessCallback& onSuccess)
Alexander Afanasyev90164962014-03-06 08:29:59 +0000374{
375 m_registeredPrefixTable.push_back(registeredPrefix);
376
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700377 if (static_cast<bool>(registeredPrefix->getFilter())) {
378 // it was a combined operation
379 m_interestFilterTable.push_back(registeredPrefix->getFilter());
380 }
381
382 if (static_cast<bool>(onSuccess)) {
383 onSuccess(registeredPrefix->getPrefix());
384 }
Alexander Afanasyev90164962014-03-06 08:29:59 +0000385}
386
387void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800388Face::unsetInterestFilter(const RegisteredPrefixId* registeredPrefixId)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800389{
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700390 m_ioService->post(bind(&Face::asyncUnregisterPrefix, this, registeredPrefixId,
391 UnregisterPrefixSuccessCallback(), UnregisterPrefixFailureCallback()));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800392}
393
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700394
395void
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700396Face::unregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
397 const UnregisterPrefixSuccessCallback& onSuccess,
398 const UnregisterPrefixFailureCallback& onFailure)
399{
400 m_ioService->post(bind(&Face::asyncUnregisterPrefix, this, registeredPrefixId,
401 onSuccess, onFailure));
402}
403
404
405void
406Face::asyncUnsetInterestFilter(const InterestFilterId* interestFilterId)
407{
408 InterestFilterTable::iterator i = std::find_if(m_interestFilterTable.begin(),
409 m_interestFilterTable.end(),
410 MatchInterestFilterId(interestFilterId));
411 if (i != m_interestFilterTable.end())
412 {
413 m_interestFilterTable.erase(i);
414 }
415}
416
417
418void
419Face::asyncUnregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
420 const UnregisterPrefixSuccessCallback& onSuccess,
421 const UnregisterPrefixFailureCallback& onFailure)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800422{
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700423 RegisteredPrefixTable::iterator i = std::find_if(m_registeredPrefixTable.begin(),
424 m_registeredPrefixTable.end(),
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800425 MatchRegisteredPrefixId(registeredPrefixId));
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800426 if (i != m_registeredPrefixTable.end())
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800427 {
Alexander Afanasyev90164962014-03-06 08:29:59 +0000428 const shared_ptr<InterestFilterRecord>& filter = (*i)->getFilter();
429 if (static_cast<bool>(filter))
430 {
431 // it was a combined operation
432 m_interestFilterTable.remove(filter);
433 }
434
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700435 (*i)->unregister(bind(&Face::finalizeUnregisterPrefix, this, i, onSuccess),
436 bind(onFailure, _2));
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700437 }
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700438 else
439 onFailure("Unrecognized PrefixId");
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700440
441 // there cannot be two registered prefixes with the same id
442}
443
444void
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700445Face::finalizeUnregisterPrefix(RegisteredPrefixTable::iterator item,
446 const UnregisterPrefixSuccessCallback& onSuccess)
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800447{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800448 m_registeredPrefixTable.erase(item);
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800449
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800450 if (!m_pitTimeoutCheckTimerActive && m_registeredPrefixTable.empty())
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800451 {
Alexander Afanasyev52afb3f2014-03-07 09:05:35 +0000452 m_transport->pause();
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800453 if (!m_ioServiceWork) {
454 m_processEventsTimeoutTimer->cancel();
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800455 }
456 }
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700457 onSuccess();
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800458}
459
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800460void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700461Face::processEvents(const time::milliseconds& timeout/* = time::milliseconds::zero()*/,
462 bool keepThread/* = false*/)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800463{
464 try
465 {
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700466 if (timeout < time::milliseconds::zero())
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800467 {
468 // do not block if timeout is negative, but process pending events
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800469 m_ioService->poll();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800470 return;
471 }
472
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700473 if (timeout > time::milliseconds::zero())
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800474 {
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700475 m_processEventsTimeoutTimer->expires_from_now(time::milliseconds(timeout));
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800476 m_processEventsTimeoutTimer->async_wait(&fireProcessEventsTimeout);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800477 }
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800478
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800479 if (keepThread) {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800480 // work will ensure that m_ioService is running until work object exists
Alexander Afanasyevb67090a2014-04-29 22:31:01 -0700481 m_ioServiceWork = make_shared<boost::asio::io_service::work>(ref(*m_ioService));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800482 }
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800483
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800484 m_ioService->run();
485 m_ioService->reset(); // so it is possible to run processEvents again (if necessary)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800486 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700487 catch (Face::ProcessEventsTimeout&)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800488 {
489 // break
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800490 m_ioService->reset();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800491 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700492 catch (std::exception&)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800493 {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800494 m_ioService->reset();
495 m_pendingInterestTable.clear();
496 m_registeredPrefixTable.clear();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800497 throw;
498 }
Jeff Thompsonfb29cda2013-08-24 10:26:54 -0700499}
500
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800501void
Jeff Thompson0050abe2013-09-17 12:50:25 -0700502Face::shutdown()
Jeff Thompson517ffa82013-08-05 16:04:34 -0700503{
Alexander Afanasyev7dced462014-03-19 15:12:32 -0700504 m_ioService->post(bind(&Face::asyncShutdown, this));
505}
506
507void
508Face::asyncShutdown()
509{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800510 m_pendingInterestTable.clear();
511 m_registeredPrefixTable.clear();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800512
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700513 if (m_transport->isConnected())
514 m_transport->close();
515
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800516 m_pitTimeoutCheckTimer->cancel();
517 m_processEventsTimeoutTimer->cancel();
518 m_pitTimeoutCheckTimerActive = false;
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700519}
520
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800521void
522Face::fireProcessEventsTimeout(const boost::system::error_code& error)
523{
524 if (!error) // can fire for some other reason, e.g., cancelled
525 throw Face::ProcessEventsTimeout();
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700526}
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800527
528void
529Face::checkPitExpire()
530{
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700531 // Check for PIT entry timeouts.
532 time::steady_clock::TimePoint now = time::steady_clock::now();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800533
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800534 PendingInterestTable::iterator i = m_pendingInterestTable.begin();
535 while (i != m_pendingInterestTable.end())
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800536 {
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700537 if ((*i)->isTimedOut(now))
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800538 {
539 // Save the PendingInterest and remove it from the PIT. Then call the callback.
540 shared_ptr<PendingInterest> pendingInterest = *i;
541
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800542 i = m_pendingInterestTable.erase(i);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800543
544 pendingInterest->callTimeout();
545 }
546 else
547 ++i;
548 }
549
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800550 if (!m_pendingInterestTable.empty()) {
551 m_pitTimeoutCheckTimerActive = true;
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800552
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700553 m_pitTimeoutCheckTimer->expires_from_now(time::milliseconds(100));
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800554 m_pitTimeoutCheckTimer->async_wait(bind(&Face::checkPitExpire, this));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800555 }
556 else {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800557 m_pitTimeoutCheckTimerActive = false;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800558
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800559 if (m_registeredPrefixTable.empty()) {
Alexander Afanasyev52afb3f2014-03-07 09:05:35 +0000560 m_transport->pause();
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800561 if (!m_ioServiceWork) {
562 m_processEventsTimeoutTimer->cancel();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800563 }
564 }
565 }
566}
567
568
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800569void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800570Face::onReceiveElement(const Block& blockFromDaemon)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800571{
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800572 const Block& block = nfd::LocalControlHeader::getPayload(blockFromDaemon);
573
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800574 if (block.type() == Tlv::Interest)
575 {
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700576 shared_ptr<Interest> interest = make_shared<Interest>();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800577 interest->wireDecode(block);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800578 if (&block != &blockFromDaemon)
579 interest->getLocalControlHeader().wireDecode(blockFromDaemon);
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800580
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800581 processInterestFilters(*interest);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800582 }
583 else if (block.type() == Tlv::Data)
584 {
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700585 shared_ptr<Data> data = make_shared<Data>();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800586 data->wireDecode(block);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800587 if (&block != &blockFromDaemon)
588 data->getLocalControlHeader().wireDecode(blockFromDaemon);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800589
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800590 satisfyPendingInterests(*data);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800591
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800592 if (m_pendingInterestTable.empty()) {
593 m_pitTimeoutCheckTimer->cancel(); // this will cause checkPitExpire invocation
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800594 }
595 }
Yingdi Yuf9fa52f2014-02-06 12:27:32 -0800596 // ignore any other type
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800597}
598
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800599void
600Face::satisfyPendingInterests(Data& data)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800601{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800602 for (PendingInterestTable::iterator i = m_pendingInterestTable.begin ();
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800603 i != m_pendingInterestTable.end();
604 )
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800605 {
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700606 if ((*i)->getInterest()->matchesData(data))
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800607 {
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700608 // Copy pointers to the objects and remove the PIT entry before calling the callback.
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800609 OnData onData = (*i)->getOnData();
610 shared_ptr<const Interest> interest = (*i)->getInterest();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800611
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800612 PendingInterestTable::iterator next = i;
613 ++next;
614 m_pendingInterestTable.erase(i);
615 i = next;
616
617 if (static_cast<bool>(onData)) {
618 onData(*interest, data);
619 }
620 }
621 else
622 ++i;
623 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800624}
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800625
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800626void
627Face::processInterestFilters(Interest& interest)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800628{
Alexander Afanasyev90164962014-03-06 08:29:59 +0000629 for (InterestFilterTable::iterator i = m_interestFilterTable.begin();
630 i != m_interestFilterTable.end();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800631 ++i)
632 {
Alexander Afanasyev90164962014-03-06 08:29:59 +0000633 if ((*i)->doesMatch(interest.getName()))
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800634 {
Alexander Afanasyev90164962014-03-06 08:29:59 +0000635 (**i)(interest);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800636 }
637 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800638}
639
640} // namespace ndn