blob: b419e13c7f93d37b92f57387d65596a8125191ea [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -07002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * Based on code originally written by Jeff Thompson <jefft0@remap.ucla.edu>
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070022 */
23
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080024#include "face.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070025#include "detail/face-impl.hpp"
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070026
Junxiao Shi468abc32014-11-04 09:12:47 -070027#include "encoding/tlv.hpp"
Junxiao Shiedd834e2014-10-28 20:28:58 -070028#include "security/key-chain.hpp"
Junxiao Shic6acc7a2015-06-23 10:03:56 -070029#include "security/signing-helpers.hpp"
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080030#include "util/time.hpp"
31#include "util/random.hpp"
Steve DiBenedettoa8659ff2014-12-04 14:50:28 -070032#include "util/face-uri.hpp"
Jeff Thompsonb982b6d2013-07-15 18:15:45 -070033
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070034namespace ndn {
Alexander Afanasyevb790d952014-01-24 12:07:53 -080035
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080036Face::Face()
Junxiao Shi2cced062014-11-02 21:27:38 -070037 : m_internalIoService(new boost::asio::io_service())
38 , m_ioService(*m_internalIoService)
39 , m_internalKeyChain(new KeyChain())
Junxiao Shiedd834e2014-10-28 20:28:58 -070040 , m_impl(new Impl(*this))
Jeff Thompsonfb29cda2013-08-24 10:26:54 -070041{
Joao Pereira68c0d882015-05-19 14:27:55 -040042 construct(*m_internalKeyChain);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080043}
44
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070045Face::Face(boost::asio::io_service& ioService)
Junxiao Shi2cced062014-11-02 21:27:38 -070046 : m_ioService(ioService)
47 , m_internalKeyChain(new KeyChain())
Junxiao Shiedd834e2014-10-28 20:28:58 -070048 , m_impl(new Impl(*this))
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070049{
Joao Pereira68c0d882015-05-19 14:27:55 -040050 construct(*m_internalKeyChain);
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070051}
52
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080053Face::Face(const std::string& host, const std::string& port/* = "6363"*/)
Junxiao Shi2cced062014-11-02 21:27:38 -070054 : m_internalIoService(new boost::asio::io_service())
55 , m_ioService(*m_internalIoService)
56 , m_internalKeyChain(new KeyChain())
Junxiao Shiedd834e2014-10-28 20:28:58 -070057 , m_impl(new Impl(*this))
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080058{
Joao Pereira68c0d882015-05-19 14:27:55 -040059 construct(make_shared<TcpTransport>(host, port), *m_internalKeyChain);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080060}
61
Alexander Afanasyevf7ca3202014-02-14 22:28:31 -080062Face::Face(const shared_ptr<Transport>& transport)
Junxiao Shi2cced062014-11-02 21:27:38 -070063 : m_internalIoService(new boost::asio::io_service())
64 , m_ioService(*m_internalIoService)
65 , m_internalKeyChain(new KeyChain())
Junxiao Shiedd834e2014-10-28 20:28:58 -070066 , m_impl(new Impl(*this))
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080067{
Joao Pereira68c0d882015-05-19 14:27:55 -040068 construct(transport, *m_internalKeyChain);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080069}
70
71Face::Face(const shared_ptr<Transport>& transport,
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070072 boost::asio::io_service& ioService)
Junxiao Shi2cced062014-11-02 21:27:38 -070073 : m_ioService(ioService)
74 , m_internalKeyChain(new KeyChain())
Junxiao Shiedd834e2014-10-28 20:28:58 -070075 , m_impl(new Impl(*this))
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080076{
Joao Pereira68c0d882015-05-19 14:27:55 -040077 construct(transport, *m_internalKeyChain);
Junxiao Shiedd834e2014-10-28 20:28:58 -070078}
79
80Face::Face(shared_ptr<Transport> transport,
81 boost::asio::io_service& ioService,
82 KeyChain& keyChain)
Junxiao Shi2cced062014-11-02 21:27:38 -070083 : m_ioService(ioService)
84 , m_internalKeyChain(nullptr)
Junxiao Shiedd834e2014-10-28 20:28:58 -070085 , m_impl(new Impl(*this))
86{
Joao Pereira68c0d882015-05-19 14:27:55 -040087 construct(transport, keyChain);
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080088}
89
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080090void
Joao Pereira68c0d882015-05-19 14:27:55 -040091Face::construct(KeyChain& keyChain)
Steve DiBenedettoa8659ff2014-12-04 14:50:28 -070092{
93 // transport=unix:///var/run/nfd.sock
94 // transport=tcp://localhost:6363
95
96 const ConfigFile::Parsed& parsed = m_impl->m_config.getParsedConfiguration();
97
98 const auto transportType = parsed.get_optional<std::string>("transport");
99 if (!transportType)
100 {
101 // transport not specified, use default Unix transport.
102 construct(UnixTransport::create(m_impl->m_config), keyChain);
103 return;
104 }
105
106 unique_ptr<util::FaceUri> uri;
107 try
108 {
109 uri.reset(new util::FaceUri(*transportType));
110 }
111 catch (const util::FaceUri::Error& error)
112 {
113 throw ConfigFile::Error(error.what());
114 }
115
Steve DiBenedettoa8659ff2014-12-04 14:50:28 -0700116 const std::string protocol = uri->getScheme();
117
118 if (protocol == "unix")
119 {
120 construct(UnixTransport::create(m_impl->m_config), keyChain);
121
122 }
123 else if (protocol == "tcp" || protocol == "tcp4" || protocol == "tcp6")
124 {
125 construct(TcpTransport::create(m_impl->m_config), keyChain);
126 }
127 else
128 {
129 throw ConfigFile::Error("Unsupported transport protocol \"" + protocol + "\"");
130 }
131}
132
133void
Joao Pereira68c0d882015-05-19 14:27:55 -0400134Face::construct(shared_ptr<Transport> transport, KeyChain& keyChain)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800135{
Joao Pereira68c0d882015-05-19 14:27:55 -0400136 m_nfdController.reset(new nfd::Controller(*this, keyChain));
Junxiao Shiedd834e2014-10-28 20:28:58 -0700137
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700138 m_impl->m_pitTimeoutCheckTimerActive = false;
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800139 m_transport = transport;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800140
Junxiao Shi2cced062014-11-02 21:27:38 -0700141 m_impl->m_pitTimeoutCheckTimer = make_shared<monotonic_deadline_timer>(ref(m_ioService));
142 m_impl->m_processEventsTimeoutTimer = make_shared<monotonic_deadline_timer>(ref(m_ioService));
Junxiao Shia1ea5062014-12-27 22:33:39 -0700143 m_impl->ensureConnected(false);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800144}
145
Joao Pereira68c0d882015-05-19 14:27:55 -0400146Face::~Face() = default;
Junxiao Shiedd834e2014-10-28 20:28:58 -0700147
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800148const PendingInterestId*
149Face::expressInterest(const Interest& interest, const OnData& onData, const OnTimeout& onTimeout)
150{
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700151 shared_ptr<Interest> interestToExpress = make_shared<Interest>(interest);
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800152
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700153 // Use `interestToExpress` to avoid wire format creation for the original Interest
154 if (interestToExpress->wireEncode().size() > MAX_NDN_PACKET_SIZE)
155 throw Error("Interest size exceeds maximum limit");
156
Alexander Afanasyev4e50b972014-03-25 10:57:50 -0700157 // If the same ioService thread, dispatch directly calls the method
Joao Pereira68c0d882015-05-19 14:27:55 -0400158 m_ioService.dispatch([=] { m_impl->asyncExpressInterest(interestToExpress, onData, onTimeout); });
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800159
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800160 return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
161}
162
163const PendingInterestId*
164Face::expressInterest(const Name& name,
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800165 const Interest& tmpl,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800166 const OnData& onData, const OnTimeout& onTimeout/* = OnTimeout()*/)
167{
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700168 return expressInterest(Interest(tmpl)
Steve DiBenedettoa8659ff2014-12-04 14:50:28 -0700169 .setName(name)
170 .setNonce(0),
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800171 onData, onTimeout);
172}
173
174void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800175Face::put(const Data& data)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800176{
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700177 // Use original `data`, since wire format should already exist for the original Data
178 if (data.wireEncode().size() > MAX_NDN_PACKET_SIZE)
179 throw Error("Data size exceeds maximum limit");
180
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -0700181 shared_ptr<const Data> dataPtr;
182 try {
183 dataPtr = data.shared_from_this();
184 }
185 catch (const bad_weak_ptr& e) {
186 std::cerr << "Face::put WARNING: the supplied Data should be created using make_shared<Data>()"
187 << std::endl;
188 dataPtr = make_shared<Data>(data);
189 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800190
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -0700191 // If the same ioService thread, dispatch directly calls the method
Joao Pereira68c0d882015-05-19 14:27:55 -0400192 m_ioService.dispatch([=] { m_impl->asyncPutData(dataPtr); });
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800193}
194
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800195void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800196Face::removePendingInterest(const PendingInterestId* pendingInterestId)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800197{
Joao Pereira68c0d882015-05-19 14:27:55 -0400198 m_ioService.post([=] { m_impl->asyncRemovePendingInterest(pendingInterestId); });
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800199}
200
Alexander Afanasyev6fcdde22014-08-22 19:03:36 -0700201size_t
202Face::getNPendingInterests() const
203{
204 return m_impl->m_pendingInterestTable.size();
205}
206
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800207const RegisteredPrefixId*
Alexander Afanasyev90164962014-03-06 08:29:59 +0000208Face::setInterestFilter(const InterestFilter& interestFilter,
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800209 const OnInterest& onInterest,
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700210 const RegisterPrefixSuccessCallback& onSuccess,
211 const RegisterPrefixFailureCallback& onFailure,
Alexander Afanasyev0866f512014-08-11 13:25:09 -0700212 const IdentityCertificate& certificate,
213 uint64_t flags)
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700214{
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700215 shared_ptr<InterestFilterRecord> filter =
216 make_shared<InterestFilterRecord>(interestFilter, onInterest);
217
Junxiao Shi388ec252014-11-02 15:19:57 -0700218 nfd::CommandOptions options;
Junxiao Shic6acc7a2015-06-23 10:03:56 -0700219 if (!certificate.getName().empty()) {
220 options.setSigningInfo(signingByCertificate(certificate.getName()));
Junxiao Shi388ec252014-11-02 15:19:57 -0700221 }
222
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700223 return m_impl->registerPrefix(interestFilter.getPrefix(), filter,
224 onSuccess, onFailure,
Junxiao Shi388ec252014-11-02 15:19:57 -0700225 flags, options);
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700226}
227
228const RegisteredPrefixId*
Alexander Afanasyev90164962014-03-06 08:29:59 +0000229Face::setInterestFilter(const InterestFilter& interestFilter,
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700230 const OnInterest& onInterest,
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700231 const RegisterPrefixFailureCallback& onFailure,
Alexander Afanasyev0866f512014-08-11 13:25:09 -0700232 const IdentityCertificate& certificate,
233 uint64_t flags)
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700234{
235 shared_ptr<InterestFilterRecord> filter =
236 make_shared<InterestFilterRecord>(interestFilter, onInterest);
237
Junxiao Shi388ec252014-11-02 15:19:57 -0700238 nfd::CommandOptions options;
Junxiao Shic6acc7a2015-06-23 10:03:56 -0700239 if (!certificate.getName().empty()) {
240 options.setSigningInfo(signingByCertificate(certificate.getName()));
Junxiao Shi388ec252014-11-02 15:19:57 -0700241 }
242
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700243 return m_impl->registerPrefix(interestFilter.getPrefix(), filter,
244 RegisterPrefixSuccessCallback(), onFailure,
Junxiao Shi388ec252014-11-02 15:19:57 -0700245 flags, options);
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700246}
247
248const RegisteredPrefixId*
249Face::setInterestFilter(const InterestFilter& interestFilter,
250 const OnInterest& onInterest,
251 const RegisterPrefixSuccessCallback& onSuccess,
252 const RegisterPrefixFailureCallback& onFailure,
Alexander Afanasyev0866f512014-08-11 13:25:09 -0700253 const Name& identity,
254 uint64_t flags)
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700255{
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700256 shared_ptr<InterestFilterRecord> filter =
257 make_shared<InterestFilterRecord>(interestFilter, onInterest);
258
Junxiao Shi388ec252014-11-02 15:19:57 -0700259 nfd::CommandOptions options;
Junxiao Shic6acc7a2015-06-23 10:03:56 -0700260 options.setSigningInfo(signingByIdentity(identity));
Junxiao Shi388ec252014-11-02 15:19:57 -0700261
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700262 return m_impl->registerPrefix(interestFilter.getPrefix(), filter,
263 onSuccess, onFailure,
Junxiao Shi388ec252014-11-02 15:19:57 -0700264 flags, options);
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700265}
266
267const RegisteredPrefixId*
268Face::setInterestFilter(const InterestFilter& interestFilter,
269 const OnInterest& onInterest,
270 const RegisterPrefixFailureCallback& onFailure,
Alexander Afanasyev0866f512014-08-11 13:25:09 -0700271 const Name& identity,
272 uint64_t flags)
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700273{
274 shared_ptr<InterestFilterRecord> filter =
275 make_shared<InterestFilterRecord>(interestFilter, onInterest);
276
Junxiao Shi388ec252014-11-02 15:19:57 -0700277 nfd::CommandOptions options;
Junxiao Shic6acc7a2015-06-23 10:03:56 -0700278 options.setSigningInfo(signingByIdentity(identity));
Junxiao Shi388ec252014-11-02 15:19:57 -0700279
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700280 return m_impl->registerPrefix(interestFilter.getPrefix(), filter,
281 RegisterPrefixSuccessCallback(), onFailure,
Junxiao Shi388ec252014-11-02 15:19:57 -0700282 flags, options);
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700283}
284
285
286const InterestFilterId*
287Face::setInterestFilter(const InterestFilter& interestFilter,
288 const OnInterest& onInterest)
289{
290 shared_ptr<InterestFilterRecord> filter =
291 make_shared<InterestFilterRecord>(interestFilter, onInterest);
292
Joao Pereira68c0d882015-05-19 14:27:55 -0400293 getIoService().post([=] { m_impl->asyncSetInterestFilter(filter); });
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700294
295 return reinterpret_cast<const InterestFilterId*>(filter.get());
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700296}
297
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700298const RegisteredPrefixId*
299Face::registerPrefix(const Name& prefix,
300 const RegisterPrefixSuccessCallback& onSuccess,
301 const RegisterPrefixFailureCallback& onFailure,
Alexander Afanasyev0866f512014-08-11 13:25:09 -0700302 const IdentityCertificate& certificate,
303 uint64_t flags)
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700304{
Junxiao Shi388ec252014-11-02 15:19:57 -0700305 nfd::CommandOptions options;
Junxiao Shic6acc7a2015-06-23 10:03:56 -0700306 if (!certificate.getName().empty()) {
307 options.setSigningInfo(signingByCertificate(certificate.getName()));
Junxiao Shi388ec252014-11-02 15:19:57 -0700308 }
309
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700310 return m_impl->registerPrefix(prefix, shared_ptr<InterestFilterRecord>(),
311 onSuccess, onFailure,
Junxiao Shi388ec252014-11-02 15:19:57 -0700312 flags, options);
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700313}
314
315const RegisteredPrefixId*
316Face::registerPrefix(const Name& prefix,
317 const RegisterPrefixSuccessCallback& onSuccess,
318 const RegisterPrefixFailureCallback& onFailure,
Alexander Afanasyev0866f512014-08-11 13:25:09 -0700319 const Name& identity,
320 uint64_t flags)
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700321{
Junxiao Shi388ec252014-11-02 15:19:57 -0700322 nfd::CommandOptions options;
Junxiao Shic6acc7a2015-06-23 10:03:56 -0700323 options.setSigningInfo(signingByIdentity(identity));
Junxiao Shi388ec252014-11-02 15:19:57 -0700324
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700325 return m_impl->registerPrefix(prefix, shared_ptr<InterestFilterRecord>(),
326 onSuccess, onFailure,
Junxiao Shi388ec252014-11-02 15:19:57 -0700327 flags, options);
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700328}
329
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700330void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800331Face::unsetInterestFilter(const RegisteredPrefixId* registeredPrefixId)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800332{
Joao Pereira68c0d882015-05-19 14:27:55 -0400333 m_ioService.post([=] { m_impl->asyncUnregisterPrefix(registeredPrefixId,
334 UnregisterPrefixSuccessCallback(),
335 UnregisterPrefixFailureCallback()); });
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800336}
337
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700338void
339Face::unsetInterestFilter(const InterestFilterId* interestFilterId)
340{
Joao Pereira68c0d882015-05-19 14:27:55 -0400341 m_ioService.post([=] { m_impl->asyncUnsetInterestFilter(interestFilterId); });
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700342}
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700343
344void
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700345Face::unregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
346 const UnregisterPrefixSuccessCallback& onSuccess,
347 const UnregisterPrefixFailureCallback& onFailure)
348{
Joao Pereira68c0d882015-05-19 14:27:55 -0400349 m_ioService.post([=] { m_impl->asyncUnregisterPrefix(registeredPrefixId,onSuccess, onFailure); });
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700350}
351
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800352void
Alexander Afanasyevaa0e7da2014-03-17 14:37:33 -0700353Face::processEvents(const time::milliseconds& timeout/* = time::milliseconds::zero()*/,
354 bool keepThread/* = false*/)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800355{
Alexander Afanasyev8e158542014-11-18 00:47:18 -0500356 if (m_ioService.stopped()) {
357 m_ioService.reset(); // ensure that run()/poll() will do some work
358 }
359
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700360 try {
361 if (timeout < time::milliseconds::zero())
362 {
363 // do not block if timeout is negative, but process pending events
Junxiao Shi2cced062014-11-02 21:27:38 -0700364 m_ioService.poll();
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700365 return;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800366 }
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800367
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700368 if (timeout > time::milliseconds::zero())
369 {
370 m_impl->m_processEventsTimeoutTimer->expires_from_now(time::milliseconds(timeout));
371 m_impl->m_processEventsTimeoutTimer->async_wait(&fireProcessEventsTimeout);
372 }
373
374 if (keepThread) {
375 // work will ensure that m_ioService is running until work object exists
Junxiao Shi2cced062014-11-02 21:27:38 -0700376 m_impl->m_ioServiceWork = make_shared<boost::asio::io_service::work>(ref(m_ioService));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800377 }
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700378
Junxiao Shi2cced062014-11-02 21:27:38 -0700379 m_ioService.run();
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700380 }
381 catch (Face::ProcessEventsTimeout&) {
382 // break
383 m_impl->m_ioServiceWork.reset();
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700384 }
385 catch (...) {
386 m_impl->m_ioServiceWork.reset();
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700387 m_impl->m_pendingInterestTable.clear();
388 m_impl->m_registeredPrefixTable.clear();
389 throw;
390 }
Jeff Thompsonfb29cda2013-08-24 10:26:54 -0700391}
392
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800393void
Jeff Thompson0050abe2013-09-17 12:50:25 -0700394Face::shutdown()
Jeff Thompson517ffa82013-08-05 16:04:34 -0700395{
Joao Pereira68c0d882015-05-19 14:27:55 -0400396 m_ioService.post([this] { this->asyncShutdown(); });
Alexander Afanasyev7dced462014-03-19 15:12:32 -0700397}
398
399void
400Face::asyncShutdown()
401{
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700402 m_impl->m_pendingInterestTable.clear();
403 m_impl->m_registeredPrefixTable.clear();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800404
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700405 if (m_transport->isConnected())
406 m_transport->close();
407
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700408 m_impl->m_pitTimeoutCheckTimer->cancel();
409 m_impl->m_processEventsTimeoutTimer->cancel();
410 m_impl->m_pitTimeoutCheckTimerActive = false;
Alexander Afanasyev1f5486e2014-07-10 17:45:49 -0700411
412 m_impl->m_ioServiceWork.reset();
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700413}
414
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800415void
416Face::fireProcessEventsTimeout(const boost::system::error_code& error)
417{
418 if (!error) // can fire for some other reason, e.g., cancelled
419 throw Face::ProcessEventsTimeout();
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700420}
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800421
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800422
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800423void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800424Face::onReceiveElement(const Block& blockFromDaemon)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800425{
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800426 const Block& block = nfd::LocalControlHeader::getPayload(blockFromDaemon);
427
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600428 if (block.type() == tlv::Interest)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800429 {
Alexander Afanasyevea719672015-02-10 20:25:23 -0800430 shared_ptr<Interest> interest = make_shared<Interest>(block);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800431 if (&block != &blockFromDaemon)
432 interest->getLocalControlHeader().wireDecode(blockFromDaemon);
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800433
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700434 m_impl->processInterestFilters(*interest);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800435 }
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600436 else if (block.type() == tlv::Data)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800437 {
Alexander Afanasyevea719672015-02-10 20:25:23 -0800438 shared_ptr<Data> data = make_shared<Data>(block);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800439 if (&block != &blockFromDaemon)
440 data->getLocalControlHeader().wireDecode(blockFromDaemon);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800441
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700442 m_impl->satisfyPendingInterests(*data);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800443
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700444 if (m_impl->m_pendingInterestTable.empty()) {
445 m_impl->m_pitTimeoutCheckTimer->cancel(); // this will cause checkPitExpire invocation
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800446 }
447 }
Yingdi Yuf9fa52f2014-02-06 12:27:32 -0800448 // ignore any other type
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800449}
450
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800451
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800452
453} // namespace ndn