blob: 2041a7bba2af6af8990a96b6a01ec4c030bb3efc [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
26#include "management/ndnd-controller.hpp"
27#include "management/nfd-controller.hpp"
Alexander Afanasyevefe3ab22014-02-19 14:57:50 -080028#include "management/nrd-controller.hpp"
Jeff Thompsonb982b6d2013-07-15 18:15:45 -070029
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070030namespace ndn {
Alexander Afanasyevb790d952014-01-24 12:07:53 -080031
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080032Face::Face()
Jeff Thompsonfb29cda2013-08-24 10:26:54 -070033{
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -060034 const std::string socketName = UnixTransport::getDefaultSocketName(m_config);
35 construct(shared_ptr<Transport>(new 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)
40{
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -060041 const std::string socketName = UnixTransport::getDefaultSocketName(m_config);
42 construct(shared_ptr<Transport>(new UnixTransport(socketName)),
Alexander Afanasyev505646e2014-02-24 20:13:37 -080043 ioService);
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080044}
45
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070046class NullIoDeleter
47{
48public:
49 void
50 operator()(boost::asio::io_service*)
51 {
52 }
53};
54
55Face::Face(boost::asio::io_service& ioService)
56{
57 const std::string socketName = UnixTransport::getDefaultSocketName(m_config);
58 construct(shared_ptr<Transport>(new UnixTransport(socketName)),
59 shared_ptr<boost::asio::io_service>(&ioService, NullIoDeleter()));
60}
61
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080062Face::Face(const std::string& host, const std::string& port/* = "6363"*/)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080063{
64 construct(shared_ptr<Transport>(new TcpTransport(host, port)),
Alexander Afanasyev505646e2014-02-24 20:13:37 -080065 make_shared<boost::asio::io_service>());
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080066}
67
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080068Face::Face(const shared_ptr<Transport>& transport)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080069{
70 construct(transport,
Alexander Afanasyev505646e2014-02-24 20:13:37 -080071 make_shared<boost::asio::io_service>());
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080072}
73
74Face::Face(const shared_ptr<Transport>& transport,
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070075 boost::asio::io_service& ioService)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080076{
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070077 construct(transport,
78 shared_ptr<boost::asio::io_service>(&ioService, NullIoDeleter()));
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080079}
80
Alexander Afanasyev505646e2014-02-24 20:13:37 -080081void
82Face::setController(const shared_ptr<Controller>& controller)
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080083{
Alexander Afanasyev505646e2014-02-24 20:13:37 -080084 m_fwController = controller;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080085}
86
87void
88Face::construct(const shared_ptr<Transport>& transport,
Alexander Afanasyev505646e2014-02-24 20:13:37 -080089 const shared_ptr<boost::asio::io_service>& ioService)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080090{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -080091 m_pitTimeoutCheckTimerActive = false;
92 m_transport = transport;
93 m_ioService = ioService;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080094
Alexander Afanasyevb67090a2014-04-29 22:31:01 -070095 m_pitTimeoutCheckTimer = make_shared<monotonic_deadline_timer>(ref(*m_ioService));
96 m_processEventsTimeoutTimer = make_shared<monotonic_deadline_timer>(ref(*m_ioService));
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -080097
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -060098 std::string protocol = "nrd-0.1";
99
100 try
Alexander Afanasyevefe3ab22014-02-19 14:57:50 -0800101 {
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600102 protocol = m_config.getParsedConfiguration().get<std::string>("protocol");
103 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700104 catch (boost::property_tree::ptree_bad_path& error)
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600105 {
106 // protocol not specified
107 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700108 catch (boost::property_tree::ptree_bad_data& error)
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600109 {
110 throw ConfigFile::Error(error.what());
111 }
112
113 if (isSupportedNrdProtocol(protocol))
114 {
Alexander Afanasyevb67090a2014-04-29 22:31:01 -0700115 m_fwController = make_shared<nrd::Controller>(ref(*this));
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600116 }
Steve DiBenedettoacab8802014-03-24 11:15:57 -0600117 else if (isSupportedNfdProtocol(protocol))
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600118 {
Alexander Afanasyevb67090a2014-04-29 22:31:01 -0700119 m_fwController = make_shared<nfd::Controller>(ref(*this));
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600120 }
121 else if (isSupportedNdndProtocol(protocol))
122 {
Alexander Afanasyevb67090a2014-04-29 22:31:01 -0700123 m_fwController = make_shared<ndnd::Controller>(ref(*this));
Alexander Afanasyevefe3ab22014-02-19 14:57:50 -0800124 }
Jeff Thompsonfb29cda2013-08-24 10:26:54 -0700125 else
Steve DiBenedettoc07b3a22014-03-19 12:32:52 -0600126 {
127 throw Face::Error("Cannot create controller for unsupported protocol \"" + protocol + "\"");
128 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800129}
130
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800131const PendingInterestId*
132Face::expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout)
133{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800134 if (!m_transport->isConnected())
135 m_transport->connect(*m_ioService,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800136 bind(&Face::onReceiveElement, this, _1));
137
Alexander Afanasyevb67090a2014-04-29 22:31:01 -0700138 shared_ptr<Interest> interestToExpress(new Interest(interest));
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800139
Alexander Afanasyev4e50b972014-03-25 10:57:50 -0700140 // If the same ioService thread, dispatch directly calls the method
141 m_ioService->dispatch(bind(&Face::asyncExpressInterest, this,
142 interestToExpress, onData, onTimeout));
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800143
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800144 return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
145}
146
147const PendingInterestId*
148Face::expressInterest(const Name& name,
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800149 const Interest& tmpl,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800150 const OnData& onData, const OnTimeout& onTimeout/* = OnTimeout()*/)
151{
152 return expressInterest(Interest(name,
153 tmpl.getMinSuffixComponents(),
154 tmpl.getMaxSuffixComponents(),
155 tmpl.getExclude(),
156 tmpl.getChildSelector(),
157 tmpl.getMustBeFresh(),
158 tmpl.getScope(),
159 tmpl.getInterestLifetime()),
160 onData, onTimeout);
161}
162
163void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800164Face::asyncExpressInterest(const shared_ptr<const Interest>& interest,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800165 const OnData& onData, const OnTimeout& onTimeout)
166{
Alexander Afanasyev4e50b972014-03-25 10:57:50 -0700167 if (!m_transport->isExpectingData())
168 m_transport->resume();
169
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800170 m_pendingInterestTable.push_back(shared_ptr<PendingInterest>(new PendingInterest
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800171 (interest, onData, onTimeout)));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800172
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800173 if (!interest->getLocalControlHeader().empty(false, true))
174 {
175 // encode only NextHopFaceId towards the forwarder
176 m_transport->send(interest->getLocalControlHeader().wireEncode(*interest, false, true),
177 interest->wireEncode());
178 }
179 else
180 {
181 m_transport->send(interest->wireEncode());
182 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800183
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800184 if (!m_pitTimeoutCheckTimerActive) {
185 m_pitTimeoutCheckTimerActive = true;
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700186 m_pitTimeoutCheckTimer->expires_from_now(time::milliseconds(100));
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800187 m_pitTimeoutCheckTimer->async_wait(bind(&Face::checkPitExpire, this));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800188 }
189}
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800190
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800191void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800192Face::put(const Data& data)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800193{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800194 if (!m_transport->isConnected())
195 m_transport->connect(*m_ioService,
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800196 bind(&Face::onReceiveElement, this, _1));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800197
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800198 if (!data.getLocalControlHeader().empty(false, true))
199 {
Alexander Afanasyev83018352014-02-18 19:52:15 -0800200 m_transport->send(data.getLocalControlHeader().wireEncode(data, false, true),
201 data.wireEncode());
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800202 }
203 else
204 {
Alexander Afanasyev83018352014-02-18 19:52:15 -0800205 m_transport->send(data.wireEncode());
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800206 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800207}
208
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800209void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800210Face::removePendingInterest(const PendingInterestId* pendingInterestId)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800211{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800212 m_ioService->post(bind(&Face::asyncRemovePendingInterest, this, pendingInterestId));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800213}
214
215
216void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800217Face::asyncRemovePendingInterest(const PendingInterestId* pendingInterestId)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800218{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800219 m_pendingInterestTable.remove_if(MatchPendingInterestId(pendingInterestId));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800220}
221
222const RegisteredPrefixId*
Alexander Afanasyev90164962014-03-06 08:29:59 +0000223Face::setInterestFilter(const InterestFilter& interestFilter,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800224 const OnInterest& onInterest,
225 const OnSetInterestFilterFailed& onSetInterestFilterFailed)
226{
Alexander Afanasyev90164962014-03-06 08:29:59 +0000227 shared_ptr<InterestFilterRecord> filter =
228 make_shared<InterestFilterRecord>(cref(interestFilter), onInterest);
229 shared_ptr<RegisteredPrefix> prefixToRegister =
230 make_shared<RegisteredPrefix>(cref(interestFilter.getPrefix()), filter);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800231
232 m_fwController->selfRegisterPrefix(prefixToRegister->getPrefix(),
Alexander Afanasyev90164962014-03-06 08:29:59 +0000233 bind(&Face::afterPrefixRegistered, this, prefixToRegister),
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700234 bind(onSetInterestFilterFailed,
235 prefixToRegister->getPrefix(), _1));
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800236
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800237 return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
238}
239
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700240const RegisteredPrefixId*
Alexander Afanasyev90164962014-03-06 08:29:59 +0000241Face::setInterestFilter(const InterestFilter& interestFilter,
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700242 const OnInterest& onInterest,
243 const OnSetInterestFilterFailed& onSetInterestFilterFailed,
244 const IdentityCertificate& certificate)
245{
Alexander Afanasyev90164962014-03-06 08:29:59 +0000246 shared_ptr<InterestFilterRecord> filter =
247 make_shared<InterestFilterRecord>(cref(interestFilter), onInterest);
248 shared_ptr<RegisteredPrefix> prefixToRegister =
249 make_shared<RegisteredPrefix>(cref(interestFilter.getPrefix()), filter);
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700250
251 m_fwController->selfRegisterPrefix(prefixToRegister->getPrefix(),
Alexander Afanasyev90164962014-03-06 08:29:59 +0000252 bind(&Face::afterPrefixRegistered, this, prefixToRegister),
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700253 bind(onSetInterestFilterFailed,
254 prefixToRegister->getPrefix(), _1),
255 certificate);
256
257 return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
258}
259
260const RegisteredPrefixId*
Alexander Afanasyev90164962014-03-06 08:29:59 +0000261Face::setInterestFilter(const InterestFilter& interestFilter,
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700262 const OnInterest& onInterest,
263 const OnSetInterestFilterFailed& onSetInterestFilterFailed,
264 const Name& identity)
265{
Alexander Afanasyev90164962014-03-06 08:29:59 +0000266 // without ptr_lib:: here, reference to cref becomes ambiguous on OSX 10.9
267 shared_ptr<InterestFilterRecord> filter =
268 make_shared<InterestFilterRecord>(cref(interestFilter), onInterest);
269 shared_ptr<RegisteredPrefix> prefixToRegister =
270 make_shared<RegisteredPrefix>(cref(interestFilter.getPrefix()), filter);
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700271
272 m_fwController->selfRegisterPrefix(prefixToRegister->getPrefix(),
Alexander Afanasyev90164962014-03-06 08:29:59 +0000273 bind(&Face::afterPrefixRegistered, this, prefixToRegister),
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700274 bind(onSetInterestFilterFailed,
275 prefixToRegister->getPrefix(), _1),
276 identity);
277
278 return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
279}
280
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800281void
Alexander Afanasyev90164962014-03-06 08:29:59 +0000282Face::afterPrefixRegistered(const shared_ptr<RegisteredPrefix>& registeredPrefix)
283{
284 m_registeredPrefixTable.push_back(registeredPrefix);
285
286 if (static_cast<bool>(registeredPrefix->getFilter()))
287 {
288 // it was a combined operation
289 m_interestFilterTable.push_back(registeredPrefix->getFilter());
290 }
291}
292
293void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800294Face::unsetInterestFilter(const RegisteredPrefixId* registeredPrefixId)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800295{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800296 m_ioService->post(bind(&Face::asyncUnsetInterestFilter, this, registeredPrefixId));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800297}
298
299void
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700300Face::unsetInterestFilter(const RegisteredPrefixId* registeredPrefixId,
301 const IdentityCertificate& certificate)
302{
303 m_ioService->post(bind(&Face::asyncUnsetInterestFilterWithCertificate, this,
304 registeredPrefixId, certificate));
305}
306
307void
308Face::unsetInterestFilter(const RegisteredPrefixId* registeredPrefixId,
309 const Name& identity)
310{
311 m_ioService->post(bind(&Face::asyncUnsetInterestFilterWithIdentity, this,
312 registeredPrefixId, identity));
313}
314
315void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800316Face::asyncUnsetInterestFilter(const RegisteredPrefixId* registeredPrefixId)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800317{
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700318 RegisteredPrefixTable::iterator i = std::find_if(m_registeredPrefixTable.begin(),
319 m_registeredPrefixTable.end(),
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800320 MatchRegisteredPrefixId(registeredPrefixId));
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800321 if (i != m_registeredPrefixTable.end())
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800322 {
Alexander Afanasyev90164962014-03-06 08:29:59 +0000323 const shared_ptr<InterestFilterRecord>& filter = (*i)->getFilter();
324 if (static_cast<bool>(filter))
325 {
326 // it was a combined operation
327 m_interestFilterTable.remove(filter);
328 }
329
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800330 m_fwController->selfDeregisterPrefix((*i)->getPrefix(),
Alexander Afanasyev90164962014-03-06 08:29:59 +0000331 bind(&Face::finalizeUnregisterPrefix, this, i),
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800332 Controller::FailCallback());
333 }
334
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700335 // there cannot be two registered prefixes with the same id
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800336}
337
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800338void
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700339Face::asyncUnsetInterestFilterWithCertificate(const RegisteredPrefixId* registeredPrefixId,
340 const IdentityCertificate& certificate)
341{
342 RegisteredPrefixTable::iterator i = std::find_if(m_registeredPrefixTable.begin(),
343 m_registeredPrefixTable.end(),
344 MatchRegisteredPrefixId(registeredPrefixId));
345 if (i != m_registeredPrefixTable.end())
346 {
Alexander Afanasyev90164962014-03-06 08:29:59 +0000347 const shared_ptr<InterestFilterRecord>& filter = (*i)->getFilter();
348 if (static_cast<bool>(filter))
349 {
350 // it was a combined operation
351 m_interestFilterTable.remove(filter);
352 }
353
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700354 m_fwController->selfDeregisterPrefix((*i)->getPrefix(),
Alexander Afanasyev90164962014-03-06 08:29:59 +0000355 bind(&Face::finalizeUnregisterPrefix, this, i),
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700356 Controller::FailCallback(),
357 certificate);
358 }
359
360 // there cannot be two registered prefixes with the same id
361}
362
363void
364Face::asyncUnsetInterestFilterWithIdentity(const RegisteredPrefixId* registeredPrefixId,
365 const Name& identity)
366{
367 RegisteredPrefixTable::iterator i = std::find_if(m_registeredPrefixTable.begin(),
368 m_registeredPrefixTable.end(),
369 MatchRegisteredPrefixId(registeredPrefixId));
370 if (i != m_registeredPrefixTable.end())
371 {
Alexander Afanasyev90164962014-03-06 08:29:59 +0000372 const shared_ptr<InterestFilterRecord>& filter = (*i)->getFilter();
373 if (static_cast<bool>(filter))
374 {
375 // it was a combined operation
376 m_interestFilterTable.remove(filter);
377 }
378
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700379 m_fwController->selfDeregisterPrefix((*i)->getPrefix(),
Alexander Afanasyev90164962014-03-06 08:29:59 +0000380 bind(&Face::finalizeUnregisterPrefix, this, i),
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700381 Controller::FailCallback(),
382 identity);
383 }
384
385 // there cannot be two registered prefixes with the same id
386}
387
388void
Alexander Afanasyev90164962014-03-06 08:29:59 +0000389Face::finalizeUnregisterPrefix(RegisteredPrefixTable::iterator item)
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800390{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800391 m_registeredPrefixTable.erase(item);
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800392
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800393 if (!m_pitTimeoutCheckTimerActive && m_registeredPrefixTable.empty())
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800394 {
Alexander Afanasyev52afb3f2014-03-07 09:05:35 +0000395 m_transport->pause();
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800396 if (!m_ioServiceWork) {
397 m_processEventsTimeoutTimer->cancel();
Alexander Afanasyev12dfbad2014-02-11 14:42:46 -0800398 }
399 }
400}
401
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800402void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700403Face::processEvents(const time::milliseconds& timeout/* = time::milliseconds::zero()*/,
404 bool keepThread/* = false*/)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800405{
406 try
407 {
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700408 if (timeout < time::milliseconds::zero())
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800409 {
410 // do not block if timeout is negative, but process pending events
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800411 m_ioService->poll();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800412 return;
413 }
414
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700415 if (timeout > time::milliseconds::zero())
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800416 {
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700417 m_processEventsTimeoutTimer->expires_from_now(time::milliseconds(timeout));
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800418 m_processEventsTimeoutTimer->async_wait(&fireProcessEventsTimeout);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800419 }
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800420
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800421 if (keepThread) {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800422 // work will ensure that m_ioService is running until work object exists
Alexander Afanasyevb67090a2014-04-29 22:31:01 -0700423 m_ioServiceWork = make_shared<boost::asio::io_service::work>(ref(*m_ioService));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800424 }
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800425
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800426 m_ioService->run();
427 m_ioService->reset(); // so it is possible to run processEvents again (if necessary)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800428 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700429 catch (Face::ProcessEventsTimeout&)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800430 {
431 // break
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800432 m_ioService->reset();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800433 }
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -0700434 catch (std::exception&)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800435 {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800436 m_ioService->reset();
437 m_pendingInterestTable.clear();
438 m_registeredPrefixTable.clear();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800439 throw;
440 }
Jeff Thompsonfb29cda2013-08-24 10:26:54 -0700441}
442
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800443void
Jeff Thompson0050abe2013-09-17 12:50:25 -0700444Face::shutdown()
Jeff Thompson517ffa82013-08-05 16:04:34 -0700445{
Alexander Afanasyev7dced462014-03-19 15:12:32 -0700446 m_ioService->post(bind(&Face::asyncShutdown, this));
447}
448
449void
450Face::asyncShutdown()
451{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800452 m_pendingInterestTable.clear();
453 m_registeredPrefixTable.clear();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800454
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800455 m_transport->close();
456 m_pitTimeoutCheckTimer->cancel();
457 m_processEventsTimeoutTimer->cancel();
458 m_pitTimeoutCheckTimerActive = false;
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700459}
460
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800461void
462Face::fireProcessEventsTimeout(const boost::system::error_code& error)
463{
464 if (!error) // can fire for some other reason, e.g., cancelled
465 throw Face::ProcessEventsTimeout();
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700466}
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800467
468void
469Face::checkPitExpire()
470{
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700471 // Check for PIT entry timeouts.
472 time::steady_clock::TimePoint now = time::steady_clock::now();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800473
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800474 PendingInterestTable::iterator i = m_pendingInterestTable.begin();
475 while (i != m_pendingInterestTable.end())
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800476 {
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700477 if ((*i)->isTimedOut(now))
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800478 {
479 // Save the PendingInterest and remove it from the PIT. Then call the callback.
480 shared_ptr<PendingInterest> pendingInterest = *i;
481
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800482 i = m_pendingInterestTable.erase(i);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800483
484 pendingInterest->callTimeout();
485 }
486 else
487 ++i;
488 }
489
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800490 if (!m_pendingInterestTable.empty()) {
491 m_pitTimeoutCheckTimerActive = true;
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800492
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700493 m_pitTimeoutCheckTimer->expires_from_now(time::milliseconds(100));
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800494 m_pitTimeoutCheckTimer->async_wait(bind(&Face::checkPitExpire, this));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800495 }
496 else {
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800497 m_pitTimeoutCheckTimerActive = false;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800498
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800499 if (m_registeredPrefixTable.empty()) {
Alexander Afanasyev52afb3f2014-03-07 09:05:35 +0000500 m_transport->pause();
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800501 if (!m_ioServiceWork) {
502 m_processEventsTimeoutTimer->cancel();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800503 }
504 }
505 }
506}
507
508
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800509void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800510Face::onReceiveElement(const Block& blockFromDaemon)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800511{
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800512 const Block& block = nfd::LocalControlHeader::getPayload(blockFromDaemon);
513
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800514 if (block.type() == Tlv::Interest)
515 {
516 shared_ptr<Interest> interest(new Interest());
517 interest->wireDecode(block);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800518 if (&block != &blockFromDaemon)
519 interest->getLocalControlHeader().wireDecode(blockFromDaemon);
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800520
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800521 processInterestFilters(*interest);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800522 }
523 else if (block.type() == Tlv::Data)
524 {
525 shared_ptr<Data> data(new Data());
526 data->wireDecode(block);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800527 if (&block != &blockFromDaemon)
528 data->getLocalControlHeader().wireDecode(blockFromDaemon);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800529
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800530 satisfyPendingInterests(*data);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800531
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800532 if (m_pendingInterestTable.empty()) {
533 m_pitTimeoutCheckTimer->cancel(); // this will cause checkPitExpire invocation
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800534 }
535 }
Yingdi Yuf9fa52f2014-02-06 12:27:32 -0800536 // ignore any other type
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800537}
538
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800539void
540Face::satisfyPendingInterests(Data& data)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800541{
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800542 for (PendingInterestTable::iterator i = m_pendingInterestTable.begin ();
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800543 i != m_pendingInterestTable.end();
544 )
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800545 {
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700546 if ((*i)->getInterest()->matchesData(data))
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800547 {
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -0700548 // Copy pointers to the objects and remove the PIT entry before calling the callback.
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800549 OnData onData = (*i)->getOnData();
550 shared_ptr<const Interest> interest = (*i)->getInterest();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800551
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800552 PendingInterestTable::iterator next = i;
553 ++next;
554 m_pendingInterestTable.erase(i);
555 i = next;
556
557 if (static_cast<bool>(onData)) {
558 onData(*interest, data);
559 }
560 }
561 else
562 ++i;
563 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800564}
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800565
Alexander Afanasyev42c81852014-02-25 21:37:26 -0800566void
567Face::processInterestFilters(Interest& interest)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800568{
Alexander Afanasyev90164962014-03-06 08:29:59 +0000569 for (InterestFilterTable::iterator i = m_interestFilterTable.begin();
570 i != m_interestFilterTable.end();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800571 ++i)
572 {
Alexander Afanasyev90164962014-03-06 08:29:59 +0000573 if ((*i)->doesMatch(interest.getName()))
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800574 {
Alexander Afanasyev90164962014-03-06 08:29:59 +0000575 (**i)(interest);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800576 }
577 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800578}
579
580} // namespace ndn