blob: 1add5db3e9b6d62a5f434b8aa948e2aa4dc38830 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi4460e822017-08-07 22:02:45 +00002/*
Alexander Afanasyev4c9a3d52017-01-03 17:45:19 -08003 * Copyright (c) 2013-2017 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.
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070020 */
21
Alexander Afanasyev09c613f2014-01-29 00:23:58 -080022#include "face.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070023#include "detail/face-impl.hpp"
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070024
Junxiao Shi468abc32014-11-04 09:12:47 -070025#include "encoding/tlv.hpp"
Junxiao Shi25467942017-06-30 02:53:14 +000026#include "net/face-uri.hpp"
Junxiao Shic6acc7a2015-06-23 10:03:56 -070027#include "security/signing-helpers.hpp"
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080028#include "util/random.hpp"
Junxiao Shi4460e822017-08-07 22:02:45 +000029#include "util/time.hpp"
30
31// NDN_LOG_INIT(ndn.Face) is declared in face-impl.hpp
Jeff Thompsonb982b6d2013-07-15 18:15:45 -070032
Junxiao Shiae0b4182016-08-08 22:53:17 +000033// A callback scheduled through io.post and io.dispatch may be invoked after the face
34// is destructed. To prevent this situation, these macros captures Face::m_impl as weak_ptr,
35// and skips callback execution if the face has been destructed.
36#define IO_CAPTURE_WEAK_IMPL(OP) \
37 { \
38 weak_ptr<Impl> implWeak(m_impl); \
39 m_ioService.OP([=] { \
40 auto impl = implWeak.lock(); \
41 if (impl != nullptr) {
42#define IO_CAPTURE_WEAK_IMPL_END \
43 } \
44 }); \
45 }
46
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -070047namespace ndn {
Alexander Afanasyevb790d952014-01-24 12:07:53 -080048
Junxiao Shi103d8ed2016-08-07 20:34:10 +000049Face::Face(shared_ptr<Transport> transport)
Junxiao Shi2cced062014-11-02 21:27:38 -070050 : m_internalIoService(new boost::asio::io_service())
51 , m_ioService(*m_internalIoService)
52 , m_internalKeyChain(new KeyChain())
Junxiao Shiae0b4182016-08-08 22:53:17 +000053 , m_impl(make_shared<Impl>(*this))
Jeff Thompsonfb29cda2013-08-24 10:26:54 -070054{
Junxiao Shi103d8ed2016-08-07 20:34:10 +000055 construct(transport, *m_internalKeyChain);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080056}
57
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070058Face::Face(boost::asio::io_service& ioService)
Junxiao Shi2cced062014-11-02 21:27:38 -070059 : m_ioService(ioService)
60 , m_internalKeyChain(new KeyChain())
Junxiao Shiae0b4182016-08-08 22:53:17 +000061 , m_impl(make_shared<Impl>(*this))
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070062{
Alexander Afanasyevbb64c172015-12-29 20:32:45 -080063 construct(nullptr, *m_internalKeyChain);
Alexander Afanasyev691c3ce2014-04-23 14:28:04 -070064}
65
Junxiao Shi103d8ed2016-08-07 20:34:10 +000066Face::Face(const std::string& host, const std::string& port)
Junxiao Shi2cced062014-11-02 21:27:38 -070067 : m_internalIoService(new boost::asio::io_service())
68 , m_ioService(*m_internalIoService)
69 , m_internalKeyChain(new KeyChain())
Junxiao Shiae0b4182016-08-08 22:53:17 +000070 , m_impl(make_shared<Impl>(*this))
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080071{
Joao Pereira68c0d882015-05-19 14:27:55 -040072 construct(make_shared<TcpTransport>(host, port), *m_internalKeyChain);
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080073}
74
Alexander Afanasyev8cf1c562016-06-23 16:01:55 -070075Face::Face(shared_ptr<Transport> transport, KeyChain& keyChain)
76 : m_internalIoService(new boost::asio::io_service())
77 , m_ioService(*m_internalIoService)
Junxiao Shiae0b4182016-08-08 22:53:17 +000078 , m_impl(make_shared<Impl>(*this))
Alexander Afanasyev8cf1c562016-06-23 16:01:55 -070079{
80 construct(transport, keyChain);
81}
82
83Face::Face(shared_ptr<Transport> transport, boost::asio::io_service& ioService)
Junxiao Shi2cced062014-11-02 21:27:38 -070084 : m_ioService(ioService)
85 , m_internalKeyChain(new KeyChain())
Junxiao Shiae0b4182016-08-08 22:53:17 +000086 , m_impl(make_shared<Impl>(*this))
Alexander Afanasyev0222fba2014-02-09 23:16:02 -080087{
Joao Pereira68c0d882015-05-19 14:27:55 -040088 construct(transport, *m_internalKeyChain);
Junxiao Shiedd834e2014-10-28 20:28:58 -070089}
90
Alexander Afanasyev8cf1c562016-06-23 16:01:55 -070091Face::Face(shared_ptr<Transport> transport, boost::asio::io_service& ioService, KeyChain& keyChain)
Junxiao Shi2cced062014-11-02 21:27:38 -070092 : m_ioService(ioService)
Junxiao Shiae0b4182016-08-08 22:53:17 +000093 , m_impl(make_shared<Impl>(*this))
Junxiao Shiedd834e2014-10-28 20:28:58 -070094{
Joao Pereira68c0d882015-05-19 14:27:55 -040095 construct(transport, keyChain);
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -080096}
97
Alexander Afanasyevbb64c172015-12-29 20:32:45 -080098shared_ptr<Transport>
99Face::makeDefaultTransport()
Steve DiBenedettoa8659ff2014-12-04 14:50:28 -0700100{
101 // transport=unix:///var/run/nfd.sock
102 // transport=tcp://localhost:6363
103
Alexander Afanasyev57e00362016-06-23 13:22:54 -0700104 std::string transportUri;
105
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000106 const char* transportEnviron = getenv("NDN_CLIENT_TRANSPORT");
107 if (transportEnviron != nullptr) {
108 transportUri = transportEnviron;
Alexander Afanasyev57e00362016-06-23 13:22:54 -0700109 }
110 else {
111 ConfigFile config;
112 transportUri = config.getParsedConfiguration().get<std::string>("transport", "");
113 }
114
115 if (transportUri.empty()) {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800116 // transport not specified, use default Unix transport.
Alexander Afanasyev57e00362016-06-23 13:22:54 -0700117 return UnixTransport::create("");
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800118 }
Steve DiBenedettoa8659ff2014-12-04 14:50:28 -0700119
Alexander Afanasyevbb64c172015-12-29 20:32:45 -0800120 std::string protocol;
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800121 try {
Junxiao Shi25467942017-06-30 02:53:14 +0000122 FaceUri uri(transportUri);
Alexander Afanasyevbb64c172015-12-29 20:32:45 -0800123 protocol = uri.getScheme();
Alexander Afanasyev57e00362016-06-23 13:22:54 -0700124
125 if (protocol == "unix") {
126 return UnixTransport::create(transportUri);
127 }
128 else if (protocol == "tcp" || protocol == "tcp4" || protocol == "tcp6") {
129 return TcpTransport::create(transportUri);
130 }
131 else {
132 BOOST_THROW_EXCEPTION(ConfigFile::Error("Unsupported transport protocol \"" + protocol + "\""));
133 }
134 }
135 catch (const Transport::Error& error) {
136 BOOST_THROW_EXCEPTION(ConfigFile::Error(error.what()));
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800137 }
Junxiao Shi25467942017-06-30 02:53:14 +0000138 catch (const FaceUri::Error& error) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700139 BOOST_THROW_EXCEPTION(ConfigFile::Error(error.what()));
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800140 }
Steve DiBenedettoa8659ff2014-12-04 14:50:28 -0700141}
142
143void
Joao Pereira68c0d882015-05-19 14:27:55 -0400144Face::construct(shared_ptr<Transport> transport, KeyChain& keyChain)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800145{
Alexander Afanasyevbb64c172015-12-29 20:32:45 -0800146 if (transport == nullptr) {
147 transport = makeDefaultTransport();
148 }
149 BOOST_ASSERT(transport != nullptr);
Alexander Afanasyevf39c5372014-02-17 19:42:56 -0800150 m_transport = transport;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800151
Alexander Afanasyevbb64c172015-12-29 20:32:45 -0800152 m_nfdController.reset(new nfd::Controller(*this, keyChain));
153
Junxiao Shiae0b4182016-08-08 22:53:17 +0000154 IO_CAPTURE_WEAK_IMPL(post) {
155 impl->ensureConnected(false);
156 } IO_CAPTURE_WEAK_IMPL_END
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800157}
158
Joao Pereira68c0d882015-05-19 14:27:55 -0400159Face::~Face() = default;
Junxiao Shiedd834e2014-10-28 20:28:58 -0700160
Alexander Afanasyev3a6da362015-12-29 20:31:03 -0800161shared_ptr<Transport>
162Face::getTransport()
163{
164 return m_transport;
165}
166
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800167const PendingInterestId*
Eric Newberry83872fd2015-08-06 17:01:24 -0700168Face::expressInterest(const Interest& interest,
169 const DataCallback& afterSatisfied,
170 const NackCallback& afterNacked,
171 const TimeoutCallback& afterTimeout)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800172{
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700173 shared_ptr<Interest> interestToExpress = make_shared<Interest>(interest);
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800174
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700175 // Use `interestToExpress` to avoid wire format creation for the original Interest
Eric Newberry83872fd2015-08-06 17:01:24 -0700176 if (interestToExpress->wireEncode().size() > MAX_NDN_PACKET_SIZE) {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700177 BOOST_THROW_EXCEPTION(Error("Interest size exceeds maximum limit"));
Eric Newberry83872fd2015-08-06 17:01:24 -0700178 }
Junxiao Shi4460e822017-08-07 22:02:45 +0000179 NDN_LOG_DEBUG("<I " << *interestToExpress); // interestToExpress is guaranteed to have nonce
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700180
Alexander Afanasyev4e50b972014-03-25 10:57:50 -0700181 // If the same ioService thread, dispatch directly calls the method
Junxiao Shiae0b4182016-08-08 22:53:17 +0000182 IO_CAPTURE_WEAK_IMPL(dispatch) {
183 impl->asyncExpressInterest(interestToExpress, afterSatisfied, afterNacked, afterTimeout);
184 } IO_CAPTURE_WEAK_IMPL_END
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800185
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800186 return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
187}
188
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800189void
Junxiao Shiae0b4182016-08-08 22:53:17 +0000190Face::removePendingInterest(const PendingInterestId* pendingInterestId)
191{
192 IO_CAPTURE_WEAK_IMPL(post) {
193 impl->asyncRemovePendingInterest(pendingInterestId);
194 } IO_CAPTURE_WEAK_IMPL_END
195}
196
197void
198Face::removeAllPendingInterests()
199{
200 IO_CAPTURE_WEAK_IMPL(post) {
201 impl->asyncRemoveAllPendingInterests();
202 } IO_CAPTURE_WEAK_IMPL_END
203}
204
205size_t
206Face::getNPendingInterests() const
207{
208 return m_impl->m_pendingInterestTable.size();
209}
210
211void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800212Face::put(const Data& data)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800213{
Junxiao Shie7bb6c82016-08-08 23:16:35 +0000214 Block wire = data.wireEncode();
215
Eric Newberry4d261b62016-11-10 13:40:09 -0700216 lp::Packet packet;
217 bool hasLpFields = false;
218
Junxiao Shie7bb6c82016-08-08 23:16:35 +0000219 shared_ptr<lp::CachePolicyTag> cachePolicyTag = data.getTag<lp::CachePolicyTag>();
220 if (cachePolicyTag != nullptr) {
Junxiao Shie7bb6c82016-08-08 23:16:35 +0000221 packet.add<lp::CachePolicyField>(*cachePolicyTag);
Eric Newberry4d261b62016-11-10 13:40:09 -0700222 hasLpFields = true;
223 }
224
225 shared_ptr<lp::CongestionMarkTag> congestionMarkTag = data.getTag<lp::CongestionMarkTag>();
226 if (congestionMarkTag != nullptr) {
227 packet.add<lp::CongestionMarkField>(*congestionMarkTag);
228 hasLpFields = true;
229 }
230
231 if (hasLpFields) {
Junxiao Shie7bb6c82016-08-08 23:16:35 +0000232 packet.add<lp::FragmentField>(std::make_pair(wire.begin(), wire.end()));
233 wire = packet.wireEncode();
234 }
235
236 if (wire.size() > MAX_NDN_PACKET_SIZE)
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700237 BOOST_THROW_EXCEPTION(Error("Data size exceeds maximum limit"));
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700238
Junxiao Shi4460e822017-08-07 22:02:45 +0000239 NDN_LOG_DEBUG("<D " << data.getName());
Junxiao Shiae0b4182016-08-08 22:53:17 +0000240 IO_CAPTURE_WEAK_IMPL(dispatch) {
Junxiao Shie7bb6c82016-08-08 23:16:35 +0000241 impl->asyncSend(wire);
Junxiao Shiae0b4182016-08-08 22:53:17 +0000242 } IO_CAPTURE_WEAK_IMPL_END
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800243}
244
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800245void
Eric Newberry83872fd2015-08-06 17:01:24 -0700246Face::put(const lp::Nack& nack)
247{
Junxiao Shie7bb6c82016-08-08 23:16:35 +0000248 lp::Packet packet;
249 packet.add<lp::NackField>(nack.getHeader());
250 const Block& interestWire = nack.getInterest().wireEncode();
251 packet.add<lp::FragmentField>(std::make_pair(interestWire.begin(), interestWire.end()));
252
Eric Newberry4d261b62016-11-10 13:40:09 -0700253 shared_ptr<lp::CongestionMarkTag> congestionMarkTag = nack.getTag<lp::CongestionMarkTag>();
254 if (congestionMarkTag != nullptr) {
255 packet.add<lp::CongestionMarkField>(*congestionMarkTag);
256 }
257
Junxiao Shie7bb6c82016-08-08 23:16:35 +0000258 Block wire = packet.wireEncode();
259
260 if (wire.size() > MAX_NDN_PACKET_SIZE)
261 BOOST_THROW_EXCEPTION(Error("Nack size exceeds maximum limit"));
Eric Newberry83872fd2015-08-06 17:01:24 -0700262
Junxiao Shi4460e822017-08-07 22:02:45 +0000263 NDN_LOG_DEBUG("<N " << nack.getInterest() << '~' << nack.getHeader().getReason());
Junxiao Shiae0b4182016-08-08 22:53:17 +0000264 IO_CAPTURE_WEAK_IMPL(dispatch) {
Junxiao Shie7bb6c82016-08-08 23:16:35 +0000265 impl->asyncSend(wire);
Junxiao Shiae0b4182016-08-08 22:53:17 +0000266 } IO_CAPTURE_WEAK_IMPL_END
Alexander Afanasyev6fcdde22014-08-22 19:03:36 -0700267}
268
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800269const RegisteredPrefixId*
Alexander Afanasyev90164962014-03-06 08:29:59 +0000270Face::setInterestFilter(const InterestFilter& interestFilter,
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000271 const InterestCallback& onInterest,
272 const RegisterPrefixFailureCallback& onFailure,
273 const security::SigningInfo& signingInfo,
274 uint64_t flags)
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700275{
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000276 return setInterestFilter(interestFilter, onInterest, nullptr, onFailure, signingInfo, flags);
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700277}
278
279const RegisteredPrefixId*
Alexander Afanasyev90164962014-03-06 08:29:59 +0000280Face::setInterestFilter(const InterestFilter& interestFilter,
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000281 const InterestCallback& onInterest,
282 const RegisterPrefixSuccessCallback& onSuccess,
283 const RegisterPrefixFailureCallback& onFailure,
284 const security::SigningInfo& signingInfo,
285 uint64_t flags)
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700286{
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000287 auto filter = make_shared<InterestFilterRecord>(interestFilter, onInterest);
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700288
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000289 nfd::CommandOptions options;
290 options.setSigningInfo(signingInfo);
Junxiao Shi388ec252014-11-02 15:19:57 -0700291
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000292 return m_impl->registerPrefix(interestFilter.getPrefix(), filter,
293 onSuccess, onFailure, flags, options);
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700294}
295
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700296const InterestFilterId*
297Face::setInterestFilter(const InterestFilter& interestFilter,
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000298 const InterestCallback& onInterest)
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700299{
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000300 auto filter = make_shared<InterestFilterRecord>(interestFilter, onInterest);
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700301
Junxiao Shiae0b4182016-08-08 22:53:17 +0000302 IO_CAPTURE_WEAK_IMPL(post) {
303 impl->asyncSetInterestFilter(filter);
304 } IO_CAPTURE_WEAK_IMPL_END
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700305
306 return reinterpret_cast<const InterestFilterId*>(filter.get());
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700307}
308
Joao Pereira0b3cac52015-07-02 14:49:49 -0400309const RegisteredPrefixId*
310Face::registerPrefix(const Name& prefix,
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000311 const RegisterPrefixSuccessCallback& onSuccess,
312 const RegisterPrefixFailureCallback& onFailure,
313 const security::SigningInfo& signingInfo,
314 uint64_t flags)
Joao Pereira0b3cac52015-07-02 14:49:49 -0400315{
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000316 nfd::CommandOptions options;
317 options.setSigningInfo(signingInfo);
Joao Pereira0b3cac52015-07-02 14:49:49 -0400318
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000319 return m_impl->registerPrefix(prefix, nullptr, onSuccess, onFailure, flags, options);
Joao Pereira0b3cac52015-07-02 14:49:49 -0400320}
321
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700322void
Alexander Afanasyev7682ccb2014-02-20 10:29:35 -0800323Face::unsetInterestFilter(const RegisteredPrefixId* registeredPrefixId)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800324{
Junxiao Shiae0b4182016-08-08 22:53:17 +0000325 IO_CAPTURE_WEAK_IMPL(post) {
326 impl->asyncUnregisterPrefix(registeredPrefixId, nullptr, nullptr);
327 } IO_CAPTURE_WEAK_IMPL_END
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800328}
329
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700330void
331Face::unsetInterestFilter(const InterestFilterId* interestFilterId)
332{
Junxiao Shiae0b4182016-08-08 22:53:17 +0000333 IO_CAPTURE_WEAK_IMPL(post) {
334 impl->asyncUnsetInterestFilter(interestFilterId);
335 } IO_CAPTURE_WEAK_IMPL_END
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700336}
Yingdi Yue66bf2a2014-04-28 17:07:36 -0700337
338void
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700339Face::unregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
340 const UnregisterPrefixSuccessCallback& onSuccess,
341 const UnregisterPrefixFailureCallback& onFailure)
342{
Junxiao Shiae0b4182016-08-08 22:53:17 +0000343 IO_CAPTURE_WEAK_IMPL(post) {
344 impl->asyncUnregisterPrefix(registeredPrefixId, onSuccess, onFailure);
345 } IO_CAPTURE_WEAK_IMPL_END
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700346}
347
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800348void
Junxiao Shi2ed9e072017-08-13 16:45:48 +0000349Face::doProcessEvents(time::milliseconds timeout, bool keepThread)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800350{
Alexander Afanasyev8e158542014-11-18 00:47:18 -0500351 if (m_ioService.stopped()) {
352 m_ioService.reset(); // ensure that run()/poll() will do some work
353 }
354
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700355 try {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800356 if (timeout < time::milliseconds::zero()) {
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000357 // do not block if timeout is negative, but process pending events
358 m_ioService.poll();
359 return;
360 }
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800361
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800362 if (timeout > time::milliseconds::zero()) {
363 boost::asio::io_service& ioService = m_ioService;
364 unique_ptr<boost::asio::io_service::work>& work = m_impl->m_ioServiceWork;
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000365 m_impl->m_processEventsTimeoutEvent = m_impl->m_scheduler.scheduleEvent(timeout,
366 [&ioService, &work] {
367 ioService.stop();
368 work.reset();
369 });
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800370 }
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700371
372 if (keepThread) {
373 // work will ensure that m_ioService is running until work object exists
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800374 m_impl->m_ioServiceWork.reset(new boost::asio::io_service::work(m_ioService));
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800375 }
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700376
Junxiao Shi2cced062014-11-02 21:27:38 -0700377 m_ioService.run();
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700378 }
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700379 catch (...) {
380 m_impl->m_ioServiceWork.reset();
Alexander Afanasyev49bb1fb2014-07-21 12:54:01 -0700381 m_impl->m_pendingInterestTable.clear();
382 m_impl->m_registeredPrefixTable.clear();
383 throw;
384 }
Jeff Thompsonfb29cda2013-08-24 10:26:54 -0700385}
386
Alexander Afanasyeva68aa7f2014-02-11 15:42:33 -0800387void
Jeff Thompson0050abe2013-09-17 12:50:25 -0700388Face::shutdown()
Jeff Thompson517ffa82013-08-05 16:04:34 -0700389{
Junxiao Shiae0b4182016-08-08 22:53:17 +0000390 IO_CAPTURE_WEAK_IMPL(post) {
391 this->asyncShutdown();
392 } IO_CAPTURE_WEAK_IMPL_END
Alexander Afanasyev7dced462014-03-19 15:12:32 -0700393}
394
395void
396Face::asyncShutdown()
397{
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700398 m_impl->m_pendingInterestTable.clear();
399 m_impl->m_registeredPrefixTable.clear();
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800400
Alexander Afanasyev984ad192014-05-02 19:11:15 -0700401 if (m_transport->isConnected())
402 m_transport->close();
403
Alexander Afanasyev1f5486e2014-07-10 17:45:49 -0700404 m_impl->m_ioServiceWork.reset();
Jeff Thompsonaa4e6db2013-07-15 17:25:23 -0700405}
406
Eric Newberry83872fd2015-08-06 17:01:24 -0700407/**
408 * @brief extract local fields from NDNLPv2 packet and tag onto a network layer packet
409 */
Eric Newberry4d261b62016-11-10 13:40:09 -0700410template<typename NetPkt>
Eric Newberry83872fd2015-08-06 17:01:24 -0700411static void
Eric Newberry4d261b62016-11-10 13:40:09 -0700412extractLpLocalFields(NetPkt& netPacket, const lp::Packet& lpPacket)
Eric Newberry83872fd2015-08-06 17:01:24 -0700413{
414 if (lpPacket.has<lp::IncomingFaceIdField>()) {
Junxiao Shi4b469982015-12-03 18:20:19 +0000415 netPacket.setTag(make_shared<lp::IncomingFaceIdTag>(lpPacket.get<lp::IncomingFaceIdField>()));
Eric Newberry83872fd2015-08-06 17:01:24 -0700416 }
Eric Newberry4d261b62016-11-10 13:40:09 -0700417
418 if (lpPacket.has<lp::CongestionMarkField>()) {
419 netPacket.setTag(make_shared<lp::CongestionMarkTag>(lpPacket.get<lp::CongestionMarkField>()));
420 }
Eric Newberry83872fd2015-08-06 17:01:24 -0700421}
422
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800423void
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800424Face::onReceiveElement(const Block& blockFromDaemon)
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800425{
Eric Newberry83872fd2015-08-06 17:01:24 -0700426 lp::Packet lpPacket(blockFromDaemon); // bare Interest/Data is a valid lp::Packet,
427 // no need to distinguish
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800428
Eric Newberry83872fd2015-08-06 17:01:24 -0700429 Buffer::const_iterator begin, end;
430 std::tie(begin, end) = lpPacket.get<lp::FragmentField>();
431 Block netPacket(&*begin, std::distance(begin, end));
432 switch (netPacket.type()) {
433 case tlv::Interest: {
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000434 auto interest = make_shared<Interest>(netPacket);
Eric Newberry83872fd2015-08-06 17:01:24 -0700435 if (lpPacket.has<lp::NackField>()) {
436 auto nack = make_shared<lp::Nack>(std::move(*interest));
437 nack->setHeader(lpPacket.get<lp::NackField>());
438 extractLpLocalFields(*nack, lpPacket);
Junxiao Shi4460e822017-08-07 22:02:45 +0000439 NDN_LOG_DEBUG(">N " << nack->getInterest() << '~' << nack->getHeader().getReason());
Eric Newberry83872fd2015-08-06 17:01:24 -0700440 m_impl->nackPendingInterests(*nack);
441 }
442 else {
443 extractLpLocalFields(*interest, lpPacket);
Junxiao Shi4460e822017-08-07 22:02:45 +0000444 NDN_LOG_DEBUG(">I " << *interest);
Eric Newberry83872fd2015-08-06 17:01:24 -0700445 m_impl->processInterestFilters(*interest);
446 }
447 break;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800448 }
Eric Newberry83872fd2015-08-06 17:01:24 -0700449 case tlv::Data: {
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000450 auto data = make_shared<Data>(netPacket);
Eric Newberry83872fd2015-08-06 17:01:24 -0700451 extractLpLocalFields(*data, lpPacket);
Junxiao Shi4460e822017-08-07 22:02:45 +0000452 NDN_LOG_DEBUG(">D " << data->getName());
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700453 m_impl->satisfyPendingInterests(*data);
Eric Newberry83872fd2015-08-06 17:01:24 -0700454 break;
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800455 }
Eric Newberry83872fd2015-08-06 17:01:24 -0700456 }
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800457}
458
Alexander Afanasyev0222fba2014-02-09 23:16:02 -0800459} // namespace ndn