blob: 44e659320ed8544bca8c1cdf226bc508f560887c [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 Afanasyev1013fd02017-01-03 13:19:03 -08003 * Copyright (c) 2013-2017 Regents of the University of California.
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -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 Afanasyev258ec2b2014-05-14 16:15:37 -070020 */
21
22#ifndef NDN_DETAIL_FACE_IMPL_HPP
23#define NDN_DETAIL_FACE_IMPL_HPP
24
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070025#include "../face.hpp"
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080026#include "container-with-on-empty-signal.hpp"
Junxiao Shib6e276f2017-08-14 20:10:04 +000027#include "lp-field-tag.hpp"
Junxiao Shi4460e822017-08-07 22:02:45 +000028#include "pending-interest.hpp"
29#include "registered-prefix.hpp"
Eric Newberry83872fd2015-08-06 17:01:24 -070030#include "../lp/packet.hpp"
Junxiao Shi4b469982015-12-03 18:20:19 +000031#include "../lp/tags.hpp"
Junxiao Shi4460e822017-08-07 22:02:45 +000032#include "../mgmt/nfd/command-options.hpp"
33#include "../mgmt/nfd/controller.hpp"
Alexander Afanasyevc37bf162018-05-08 19:54:16 -040034#include "../transport/transport.hpp"
35// #include "../transport/tcp-transport.hpp"
36// #include "../transport/unix-transport.hpp"
Junxiao Shi4460e822017-08-07 22:02:45 +000037#include "../util/config-file.hpp"
38#include "../util/logger.hpp"
39#include "../util/scheduler.hpp"
40#include "../util/signal.hpp"
41
42NDN_LOG_INIT(ndn.Face);
43// INFO level: prefix registration, etc.
44//
45// DEBUG level: packet logging.
46// Each log entry starts with a direction symbol ('<' denotes an outgoing packet, '>' denotes an
47// incoming packet) and a packet type symbol ('I' denotes an Interest, 'D' denotes a Data, 'N'
48// denotes a Nack). Interest is printed as its string representation, Data is printed as name only,
49// Nack is printed as the Interest followed by the Nack reason and delimited by a '~' symbol. A
50// log line about an incoming packet may be followed by zero or more lines about Interest matching
51// InterestFilter, Data satisfying Interest, or Nack rejecting Interest, which are also written at
52// DEBUG level.
53//
54// TRACE level: more detailed unstructured messages.
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070055
56namespace ndn {
57
Junxiao Shib6e276f2017-08-14 20:10:04 +000058/** @brief implementation detail of Face
Junxiao Shi103d8ed2016-08-07 20:34:10 +000059 */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070060class Face::Impl : noncopyable
61{
62public:
Junxiao Shib6e276f2017-08-14 20:10:04 +000063 using PendingInterestTable = ContainerWithOnEmptySignal<shared_ptr<PendingInterest>>;
64 using InterestFilterTable = std::list<shared_ptr<InterestFilterRecord>>;
65 using RegisteredPrefixTable = ContainerWithOnEmptySignal<shared_ptr<RegisteredPrefix>>;
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070066
67 explicit
68 Impl(Face& face)
69 : m_face(face)
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080070 , m_scheduler(m_face.getIoService())
71 , m_processEventsTimeoutEvent(m_scheduler)
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070072 {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080073 auto postOnEmptyPitOrNoRegisteredPrefixes = [this] {
Spyridon Mastorakisb42184a2016-11-28 18:03:05 -080074 m_scheduler.scheduleEvent(time::seconds(0), bind(&Impl::onEmptyPitOrNoRegisteredPrefixes, this));
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080075 // without this extra "post", transport can get paused (-async_read) and then resumed
76 // (+async_read) from within onInterest/onData callback. After onInterest/onData
77 // finishes, there is another +async_read with the same memory block. A few of such
78 // async_read duplications can cause various effects and result in segfault.
79 };
80
81 m_pendingInterestTable.onEmpty.connect(postOnEmptyPitOrNoRegisteredPrefixes);
82 m_registeredPrefixTable.onEmpty.connect(postOnEmptyPitOrNoRegisteredPrefixes);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070083 }
84
Junxiao Shi103d8ed2016-08-07 20:34:10 +000085public: // consumer
Junxiao Shia1ea5062014-12-27 22:33:39 -070086 void
Eric Newberry83872fd2015-08-06 17:01:24 -070087 asyncExpressInterest(shared_ptr<const Interest> interest,
88 const DataCallback& afterSatisfied,
89 const NackCallback& afterNacked,
90 const TimeoutCallback& afterTimeout)
Junxiao Shia1ea5062014-12-27 22:33:39 -070091 {
Junxiao Shib6828912017-11-20 14:06:32 +000092 NDN_LOG_DEBUG("<I " << *interest);
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080093 this->ensureConnected(true);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070094
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000095 const Interest& interest2 = *interest;
Junxiao Shi79a7a162017-09-09 08:33:57 +000096 auto i = m_pendingInterestTable.insert(make_shared<PendingInterest>(
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +000097 std::move(interest), afterSatisfied, afterNacked, afterTimeout, ref(m_scheduler))).first;
Junxiao Shib6828912017-11-20 14:06:32 +000098 // In dispatchInterest, an InterestCallback may respond with Data right away and delete
99 // the PendingInterestTable entry. shared_ptr is retained to ensure PendingInterest instance
100 // remains valid in this case.
101 shared_ptr<PendingInterest> entry = *i;
102 entry->setDeleter([this, i] { m_pendingInterestTable.erase(i); });
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700103
Junxiao Shib6e276f2017-08-14 20:10:04 +0000104 lp::Packet lpPacket;
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000105 addFieldFromTag<lp::NextHopFaceIdField, lp::NextHopFaceIdTag>(lpPacket, interest2);
106 addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, interest2);
Eric Newberry83872fd2015-08-06 17:01:24 -0700107
Junxiao Shib6828912017-11-20 14:06:32 +0000108 entry->recordForwarding();
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000109 m_face.m_transport->send(finishEncoding(std::move(lpPacket), interest2.wireEncode(),
110 'I', interest2.getName()));
Junxiao Shib6828912017-11-20 14:06:32 +0000111 dispatchInterest(*entry, interest2);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700112 }
113
114 void
115 asyncRemovePendingInterest(const PendingInterestId* pendingInterestId)
116 {
117 m_pendingInterestTable.remove_if(MatchPendingInterestId(pendingInterestId));
118 }
119
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -0700120 void
Ilya Moiseenko56b0bf82015-11-08 11:14:28 -0500121 asyncRemoveAllPendingInterests()
122 {
123 m_pendingInterestTable.clear();
124 }
125
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000126 /** @return whether the Data should be sent to the forwarder, if it does not come from the forwarder
127 */
128 bool
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000129 satisfyPendingInterests(const Data& data)
130 {
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000131 bool hasAppMatch = false, hasForwarderMatch = false;
Junxiao Shi79a7a162017-09-09 08:33:57 +0000132 for (auto i = m_pendingInterestTable.begin(); i != m_pendingInterestTable.end(); ) {
133 shared_ptr<PendingInterest> entry = *i;
134 if (!entry->getInterest()->matchesData(data)) {
135 ++i;
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000136 continue;
137 }
138
Junxiao Shi79a7a162017-09-09 08:33:57 +0000139 NDN_LOG_DEBUG(" satisfying " << *entry->getInterest() << " from " << entry->getOrigin());
140 i = m_pendingInterestTable.erase(i);
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000141
Junxiao Shi79a7a162017-09-09 08:33:57 +0000142 if (entry->getOrigin() == PendingInterestOrigin::APP) {
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000143 hasAppMatch = true;
Junxiao Shi79a7a162017-09-09 08:33:57 +0000144 entry->invokeDataCallback(data);
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000145 }
146 else {
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000147 hasForwarderMatch = true;
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000148 }
149 }
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000150 // if Data matches no pending Interest record, it is sent to the forwarder as unsolicited Data
151 return hasForwarderMatch || !hasAppMatch;
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000152 }
153
Junxiao Shi79a7a162017-09-09 08:33:57 +0000154 /** @return a Nack to be sent to the forwarder, or nullopt if no Nack should be sent
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000155 */
Junxiao Shi79a7a162017-09-09 08:33:57 +0000156 optional<lp::Nack>
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000157 nackPendingInterests(const lp::Nack& nack)
158 {
Junxiao Shi79a7a162017-09-09 08:33:57 +0000159 optional<lp::Nack> outNack;
160 for (auto i = m_pendingInterestTable.begin(); i != m_pendingInterestTable.end(); ) {
161 shared_ptr<PendingInterest> entry = *i;
162 if (!nack.getInterest().matchesInterest(*entry->getInterest())) {
163 ++i;
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000164 continue;
165 }
166
Junxiao Shi79a7a162017-09-09 08:33:57 +0000167 NDN_LOG_DEBUG(" nacking " << *entry->getInterest() << " from " << entry->getOrigin());
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000168
Junxiao Shi79a7a162017-09-09 08:33:57 +0000169 optional<lp::Nack> outNack1 = entry->recordNack(nack);
170 if (!outNack1) {
171 ++i;
172 continue;
173 }
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000174
Junxiao Shi79a7a162017-09-09 08:33:57 +0000175 if (entry->getOrigin() == PendingInterestOrigin::APP) {
176 entry->invokeNackCallback(*outNack1);
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000177 }
178 else {
Junxiao Shi79a7a162017-09-09 08:33:57 +0000179 outNack = outNack1;
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000180 }
Junxiao Shi79a7a162017-09-09 08:33:57 +0000181 i = m_pendingInterestTable.erase(i);
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000182 }
Junxiao Shi79a7a162017-09-09 08:33:57 +0000183 // send "least severe" Nack from any PendingInterest record originated from forwarder, because
184 // it is unimportant to consider Nack reason for the unlikely case when forwarder sends multiple
185 // Interests to an app in a short while
186 return outNack;
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000187 }
188
189public: // producer
190 void
191 asyncSetInterestFilter(shared_ptr<InterestFilterRecord> interestFilterRecord)
192 {
Junxiao Shi4460e822017-08-07 22:02:45 +0000193 NDN_LOG_INFO("setting InterestFilter: " << interestFilterRecord->getFilter());
194 m_interestFilterTable.push_back(std::move(interestFilterRecord));
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000195 }
196
197 void
198 asyncUnsetInterestFilter(const InterestFilterId* interestFilterId)
199 {
200 InterestFilterTable::iterator i = std::find_if(m_interestFilterTable.begin(),
201 m_interestFilterTable.end(),
202 MatchInterestFilterId(interestFilterId));
203 if (i != m_interestFilterTable.end()) {
Junxiao Shi4460e822017-08-07 22:02:45 +0000204 NDN_LOG_INFO("unsetting InterestFilter: " << (*i)->getFilter());
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000205 m_interestFilterTable.erase(i);
206 }
207 }
208
209 void
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000210 processIncomingInterest(shared_ptr<const Interest> interest)
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000211 {
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000212 const Interest& interest2 = *interest;
Junxiao Shi79a7a162017-09-09 08:33:57 +0000213 auto i = m_pendingInterestTable.insert(make_shared<PendingInterest>(
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000214 std::move(interest), ref(m_scheduler))).first;
Junxiao Shib6828912017-11-20 14:06:32 +0000215 // In dispatchInterest, an InterestCallback may respond with Data right away and delete
216 // the PendingInterestTable entry. shared_ptr is retained to ensure PendingInterest instance
217 // remains valid in this case.
Junxiao Shi859888f2017-09-12 14:29:16 +0000218 shared_ptr<PendingInterest> entry = *i;
219 entry->setDeleter([this, i] { m_pendingInterestTable.erase(i); });
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000220
Junxiao Shib6828912017-11-20 14:06:32 +0000221 this->dispatchInterest(*entry, interest2);
222 }
223
224 void
225 dispatchInterest(PendingInterest& entry, const Interest& interest)
226 {
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000227 for (const auto& filter : m_interestFilterTable) {
Junxiao Shib6828912017-11-20 14:06:32 +0000228 if (filter->doesMatch(entry)) {
Junxiao Shi4460e822017-08-07 22:02:45 +0000229 NDN_LOG_DEBUG(" matches " << filter->getFilter());
Junxiao Shib6828912017-11-20 14:06:32 +0000230 entry.recordForwarding();
231 filter->invokeInterestCallback(interest);
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000232 }
233 }
234 }
235
236 void
Junxiao Shib6e276f2017-08-14 20:10:04 +0000237 asyncPutData(const Data& data)
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -0700238 {
Junxiao Shib6828912017-11-20 14:06:32 +0000239 NDN_LOG_DEBUG("<D " << data.getName());
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000240 bool shouldSendToForwarder = satisfyPendingInterests(data);
241 if (!shouldSendToForwarder) {
242 return;
243 }
244
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800245 this->ensureConnected(true);
Junxiao Shib6e276f2017-08-14 20:10:04 +0000246
247 lp::Packet lpPacket;
248 addFieldFromTag<lp::CachePolicyField, lp::CachePolicyTag>(lpPacket, data);
249 addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, data);
250
251 m_face.m_transport->send(finishEncoding(std::move(lpPacket), data.wireEncode(),
252 'D', data.getName()));
253 }
254
255 void
256 asyncPutNack(const lp::Nack& nack)
257 {
Junxiao Shib6828912017-11-20 14:06:32 +0000258 NDN_LOG_DEBUG("<N " << nack.getInterest() << '~' << nack.getHeader().getReason());
Junxiao Shi79a7a162017-09-09 08:33:57 +0000259 optional<lp::Nack> outNack = nackPendingInterests(nack);
260 if (!outNack) {
Junxiao Shi1ad0b4b2017-08-18 14:19:14 +0000261 return;
262 }
263
Junxiao Shib6e276f2017-08-14 20:10:04 +0000264 this->ensureConnected(true);
265
266 lp::Packet lpPacket;
Junxiao Shi79a7a162017-09-09 08:33:57 +0000267 lpPacket.add<lp::NackField>(outNack->getHeader());
268 addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, *outNack);
Junxiao Shib6e276f2017-08-14 20:10:04 +0000269
Junxiao Shi79a7a162017-09-09 08:33:57 +0000270 const Interest& interest = outNack->getInterest();
Junxiao Shib6e276f2017-08-14 20:10:04 +0000271 m_face.m_transport->send(finishEncoding(std::move(lpPacket), interest.wireEncode(),
272 'N', interest.getName()));
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -0700273 }
274
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000275public: // prefix registration
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700276 const RegisteredPrefixId*
277 registerPrefix(const Name& prefix,
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000278 shared_ptr<InterestFilterRecord> filter,
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700279 const RegisterPrefixSuccessCallback& onSuccess,
280 const RegisterPrefixFailureCallback& onFailure,
Alexander Afanasyev0866f512014-08-11 13:25:09 -0700281 uint64_t flags,
Junxiao Shi388ec252014-11-02 15:19:57 -0700282 const nfd::CommandOptions& options)
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700283 {
Junxiao Shi4460e822017-08-07 22:02:45 +0000284 NDN_LOG_INFO("registering prefix: " << prefix);
285 auto record = make_shared<RegisteredPrefix>(prefix, filter, options);
286
Junxiao Shie7c7f152016-08-20 22:36:22 +0000287 nfd::ControlParameters params;
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400288 params.setName(prefix);
289 params.setFlags(flags);
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000290 m_face.m_nfdController->start<nfd::RibRegisterCommand>(
291 params,
Junxiao Shi4460e822017-08-07 22:02:45 +0000292 [=] (const nfd::ControlParameters&) { this->afterPrefixRegistered(record, onSuccess); },
293 [=] (const nfd::ControlResponse& resp) {
294 NDN_LOG_INFO("register prefix failed: " << record->getPrefix());
295 onFailure(record->getPrefix(), resp.getText());
296 },
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000297 options);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700298
Junxiao Shi4460e822017-08-07 22:02:45 +0000299 return reinterpret_cast<const RegisteredPrefixId*>(record.get());
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700300 }
301
302 void
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000303 afterPrefixRegistered(shared_ptr<RegisteredPrefix> registeredPrefix,
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700304 const RegisterPrefixSuccessCallback& onSuccess)
305 {
Junxiao Shi4460e822017-08-07 22:02:45 +0000306 NDN_LOG_INFO("registered prefix: " << registeredPrefix->getPrefix());
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800307 m_registeredPrefixTable.insert(registeredPrefix);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700308
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000309 if (registeredPrefix->getFilter() != nullptr) {
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700310 // it was a combined operation
311 m_interestFilterTable.push_back(registeredPrefix->getFilter());
312 }
313
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000314 if (onSuccess != nullptr) {
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700315 onSuccess(registeredPrefix->getPrefix());
316 }
317 }
318
319 void
320 asyncUnregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
321 const UnregisterPrefixSuccessCallback& onSuccess,
322 const UnregisterPrefixFailureCallback& onFailure)
323 {
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400324 auto i = std::find_if(m_registeredPrefixTable.begin(),
325 m_registeredPrefixTable.end(),
326 MatchRegisteredPrefixId(registeredPrefixId));
327 if (i != m_registeredPrefixTable.end()) {
328 RegisteredPrefix& record = **i;
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400329 const shared_ptr<InterestFilterRecord>& filter = record.getFilter();
330
331 if (filter != nullptr) {
332 // it was a combined operation
333 m_interestFilterTable.remove(filter);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700334 }
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400335
Junxiao Shi4460e822017-08-07 22:02:45 +0000336 NDN_LOG_INFO("unregistering prefix: " << record.getPrefix());
337
Junxiao Shie7c7f152016-08-20 22:36:22 +0000338 nfd::ControlParameters params;
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400339 params.setName(record.getPrefix());
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000340 m_face.m_nfdController->start<nfd::RibUnregisterCommand>(
341 params,
Junxiao Shie7c7f152016-08-20 22:36:22 +0000342 [=] (const nfd::ControlParameters&) { this->finalizeUnregisterPrefix(i, onSuccess); },
Junxiao Shi4460e822017-08-07 22:02:45 +0000343 [=] (const nfd::ControlResponse& resp) {
344 NDN_LOG_INFO("unregister prefix failed: " << params.getName());
345 onFailure(resp.getText());
346 },
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000347 record.getCommandOptions());
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400348 }
Alexander Afanasyev851228a2014-10-20 15:55:28 -0400349 else {
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400350 if (onFailure != nullptr) {
Alexander Afanasyev851228a2014-10-20 15:55:28 -0400351 onFailure("Unrecognized PrefixId");
352 }
353 }
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700354
355 // there cannot be two registered prefixes with the same id
356 }
357
358 void
359 finalizeUnregisterPrefix(RegisteredPrefixTable::iterator item,
360 const UnregisterPrefixSuccessCallback& onSuccess)
361 {
Junxiao Shi4460e822017-08-07 22:02:45 +0000362 NDN_LOG_INFO("unregistered prefix: " << (*item)->getPrefix());
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700363 m_registeredPrefixTable.erase(item);
364
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000365 if (onSuccess != nullptr) {
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700366 onSuccess();
367 }
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700368 }
369
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000370public: // IO routine
371 void
372 ensureConnected(bool wantResume)
373 {
374 if (!m_face.m_transport->isConnected())
Alexander Afanasyevc37bf162018-05-08 19:54:16 -0400375 m_face.m_transport->connect([=] (const Block& wire) { m_face.onReceiveElement(wire); });
Junxiao Shi103d8ed2016-08-07 20:34:10 +0000376
377 if (wantResume && !m_face.m_transport->isReceiving()) {
378 m_face.m_transport->resume();
379 }
380 }
381
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700382 void
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800383 onEmptyPitOrNoRegisteredPrefixes()
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700384 {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800385 if (m_pendingInterestTable.empty() && m_registeredPrefixTable.empty()) {
386 m_face.m_transport->pause();
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700387 }
388 }
389
390private:
Junxiao Shib6e276f2017-08-14 20:10:04 +0000391 /** @brief Finish packet encoding
392 * @param lpPacket NDNLP packet without FragmentField
393 * @param wire wire encoding of Interest or Data
394 * @param pktType packet type, 'I' for Interest, 'D' for Data, 'N' for Nack
395 * @param name packet name
396 * @return wire encoding of either NDNLP or bare network packet
397 * @throw Face::OversizedPacketError wire encoding exceeds limit
398 */
399 Block
400 finishEncoding(lp::Packet&& lpPacket, Block wire, char pktType, const Name& name)
401 {
402 if (!lpPacket.empty()) {
403 lpPacket.add<lp::FragmentField>(std::make_pair(wire.begin(), wire.end()));
404 wire = lpPacket.wireEncode();
405 }
406
407 if (wire.size() > MAX_NDN_PACKET_SIZE) {
408 BOOST_THROW_EXCEPTION(Face::OversizedPacketError(pktType, name, wire.size()));
409 }
410
411 return wire;
412 }
413
414private:
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700415 Face& m_face;
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800416 util::Scheduler m_scheduler;
417 util::scheduler::ScopedEventId m_processEventsTimeoutEvent;
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700418
419 PendingInterestTable m_pendingInterestTable;
420 InterestFilterTable m_interestFilterTable;
421 RegisteredPrefixTable m_registeredPrefixTable;
422
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700423 friend class Face;
424};
425
426} // namespace ndn
427
428#endif // NDN_DETAIL_FACE_IMPL_HPP