blob: b2356c05692c7028f344fc693024cca7cdf03ada [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -07002/**
Alexander Afanasyev9d158f02015-02-17 21:30:19 -08003 * Copyright (c) 2013-2015 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
25#include "../common.hpp"
26#include "../face.hpp"
27
28#include "registered-prefix.hpp"
29#include "pending-interest.hpp"
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080030#include "container-with-on-empty-signal.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070031
32#include "../util/scheduler.hpp"
33#include "../util/config-file.hpp"
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080034#include "../util/signal.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070035
Junxiao Shi0fa28452014-12-13 22:02:36 -070036#include "../transport/transport.hpp"
37#include "../transport/unix-transport.hpp"
38#include "../transport/tcp-transport.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070039
Junxiao Shi0fa28452014-12-13 22:02:36 -070040#include "../management/nfd-controller.hpp"
41#include "../management/nfd-command-options.hpp"
Eric Newberry83872fd2015-08-06 17:01:24 -070042
43#include "../lp/packet.hpp"
Junxiao Shi4b469982015-12-03 18:20:19 +000044#include "../lp/tags.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070045
46namespace ndn {
47
48class Face::Impl : noncopyable
49{
50public:
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080051 typedef ContainerWithOnEmptySignal<shared_ptr<PendingInterest>> PendingInterestTable;
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070052 typedef std::list<shared_ptr<InterestFilterRecord> > InterestFilterTable;
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080053 typedef ContainerWithOnEmptySignal<shared_ptr<RegisteredPrefix>> RegisteredPrefixTable;
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070054
55 explicit
56 Impl(Face& face)
57 : m_face(face)
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080058 , m_scheduler(m_face.getIoService())
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070059 {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080060 auto postOnEmptyPitOrNoRegisteredPrefixes = [this] {
Alexander Afanasyev787be412016-09-08 15:15:43 -070061 m_scheduler.scheduleEvent(time::seconds(0), bind(&Impl::onEmptyPitOrNoRegisteredPrefixes, this));
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080062 // without this extra "post", transport can get paused (-async_read) and then resumed
63 // (+async_read) from within onInterest/onData callback. After onInterest/onData
64 // finishes, there is another +async_read with the same memory block. A few of such
65 // async_read duplications can cause various effects and result in segfault.
66 };
67
68 m_pendingInterestTable.onEmpty.connect(postOnEmptyPitOrNoRegisteredPrefixes);
69 m_registeredPrefixTable.onEmpty.connect(postOnEmptyPitOrNoRegisteredPrefixes);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070070 }
71
72 /////////////////////////////////////////////////////////////////////////////////////////////////
73 /////////////////////////////////////////////////////////////////////////////////////////////////
74
75 void
76 satisfyPendingInterests(Data& data)
77 {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080078 for (auto entry = m_pendingInterestTable.begin(); entry != m_pendingInterestTable.end(); ) {
Eric Newberry83872fd2015-08-06 17:01:24 -070079 if ((*entry)->getInterest()->matchesData(data)) {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080080 shared_ptr<PendingInterest> matchedEntry = *entry;
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070081
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080082 entry = m_pendingInterestTable.erase(entry);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070083
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080084 matchedEntry->invokeDataCallback(data);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070085 }
Alexander Afanasyev9d158f02015-02-17 21:30:19 -080086 else
87 ++entry;
88 }
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070089 }
90
91 void
Eric Newberry83872fd2015-08-06 17:01:24 -070092 nackPendingInterests(const lp::Nack& nack)
93 {
94 for (auto entry = m_pendingInterestTable.begin(); entry != m_pendingInterestTable.end(); ) {
95 const Interest& pendingInterest = *(*entry)->getInterest();
96 if (pendingInterest == nack.getInterest()) {
97 shared_ptr<PendingInterest> matchedEntry = *entry;
98
99 entry = m_pendingInterestTable.erase(entry);
100
101 matchedEntry->invokeNackCallback(nack);
102 }
103 else {
104 ++entry;
105 }
106 }
107 }
108
109 void
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700110 processInterestFilters(Interest& interest)
111 {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800112 for (const auto& filter : m_interestFilterTable) {
113 if (filter->doesMatch(interest.getName())) {
114 filter->invokeInterestCallback(interest);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700115 }
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800116 }
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700117 }
118
119 /////////////////////////////////////////////////////////////////////////////////////////////////
120 /////////////////////////////////////////////////////////////////////////////////////////////////
121
122 void
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800123 ensureConnected(bool wantResume)
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700124 {
Alexander Afanasyev407e9492014-07-10 18:50:44 -0700125 if (!m_face.m_transport->isConnected())
Alexander Afanasyev787be412016-09-08 15:15:43 -0700126 m_face.m_transport->connect(m_face.getIoService(),
Alexander Afanasyev407e9492014-07-10 18:50:44 -0700127 bind(&Face::onReceiveElement, &m_face, _1));
128
Junxiao Shia1ea5062014-12-27 22:33:39 -0700129 if (wantResume && !m_face.m_transport->isExpectingData())
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700130 m_face.m_transport->resume();
Junxiao Shia1ea5062014-12-27 22:33:39 -0700131 }
132
133 void
Eric Newberry83872fd2015-08-06 17:01:24 -0700134 asyncExpressInterest(shared_ptr<const Interest> interest,
135 const DataCallback& afterSatisfied,
136 const NackCallback& afterNacked,
137 const TimeoutCallback& afterTimeout)
Junxiao Shia1ea5062014-12-27 22:33:39 -0700138 {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800139 this->ensureConnected(true);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700140
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800141 auto entry =
142 m_pendingInterestTable.insert(make_shared<PendingInterest>(interest,
Eric Newberry83872fd2015-08-06 17:01:24 -0700143 afterSatisfied,
144 afterNacked,
145 afterTimeout,
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800146 ref(m_scheduler))).first;
147 (*entry)->setDeleter([this, entry] { m_pendingInterestTable.erase(entry); });
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700148
Eric Newberry83872fd2015-08-06 17:01:24 -0700149 lp::Packet packet;
150
Junxiao Shi4b469982015-12-03 18:20:19 +0000151 shared_ptr<lp::NextHopFaceIdTag> nextHopFaceIdTag = interest->getTag<lp::NextHopFaceIdTag>();
152 if (nextHopFaceIdTag != nullptr) {
153 packet.add<lp::NextHopFaceIdField>(*nextHopFaceIdTag);
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800154 }
Eric Newberry83872fd2015-08-06 17:01:24 -0700155
156 packet.add<lp::FragmentField>(std::make_pair(interest->wireEncode().begin(),
157 interest->wireEncode().end()));
158
159 m_face.m_transport->send(packet.wireEncode());
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700160 }
161
162 void
163 asyncRemovePendingInterest(const PendingInterestId* pendingInterestId)
164 {
165 m_pendingInterestTable.remove_if(MatchPendingInterestId(pendingInterestId));
166 }
167
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -0700168 void
Ilya Moiseenko56b0bf82015-11-08 11:14:28 -0500169 asyncRemoveAllPendingInterests()
170 {
171 m_pendingInterestTable.clear();
172 }
173
174 void
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -0700175 asyncPutData(const shared_ptr<const Data>& data)
176 {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800177 this->ensureConnected(true);
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -0700178
Eric Newberry83872fd2015-08-06 17:01:24 -0700179 lp::Packet packet;
180
Junxiao Shi4b469982015-12-03 18:20:19 +0000181 shared_ptr<lp::CachePolicyTag> cachePolicyTag = data->getTag<lp::CachePolicyTag>();
182 if (cachePolicyTag != nullptr) {
183 packet.add<lp::CachePolicyField>(*cachePolicyTag);
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800184 }
Eric Newberry83872fd2015-08-06 17:01:24 -0700185
186 packet.add<lp::FragmentField>(std::make_pair(data->wireEncode().begin(),
187 data->wireEncode().end()));
188
189 m_face.m_transport->send(packet.wireEncode());
190 }
191
192 void
193 asyncPutNack(shared_ptr<const lp::Nack> nack)
194 {
195 this->ensureConnected(true);
196
197 lp::Packet packet;
198 packet.add<lp::NackField>(nack->getHeader());
199
200 Block interest = nack->getInterest().wireEncode();
201 packet.add<lp::FragmentField>(std::make_pair(interest.begin(), interest.end()));
202
203 m_face.m_transport->send(packet.wireEncode());
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -0700204 }
205
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700206 /////////////////////////////////////////////////////////////////////////////////////////////////
207 /////////////////////////////////////////////////////////////////////////////////////////////////
208
209 void
210 asyncSetInterestFilter(const shared_ptr<InterestFilterRecord>& interestFilterRecord)
211 {
212 m_interestFilterTable.push_back(interestFilterRecord);
213 }
214
215 void
216 asyncUnsetInterestFilter(const InterestFilterId* interestFilterId)
217 {
218 InterestFilterTable::iterator i = std::find_if(m_interestFilterTable.begin(),
219 m_interestFilterTable.end(),
220 MatchInterestFilterId(interestFilterId));
221 if (i != m_interestFilterTable.end())
222 {
223 m_interestFilterTable.erase(i);
224 }
225 }
226
227 /////////////////////////////////////////////////////////////////////////////////////////////////
228 /////////////////////////////////////////////////////////////////////////////////////////////////
229
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700230 const RegisteredPrefixId*
231 registerPrefix(const Name& prefix,
232 const shared_ptr<InterestFilterRecord>& filter,
233 const RegisterPrefixSuccessCallback& onSuccess,
234 const RegisterPrefixFailureCallback& onFailure,
Alexander Afanasyev0866f512014-08-11 13:25:09 -0700235 uint64_t flags,
Junxiao Shi388ec252014-11-02 15:19:57 -0700236 const nfd::CommandOptions& options)
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700237 {
238 using namespace nfd;
239
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400240 ControlParameters params;
241 params.setName(prefix);
242 params.setFlags(flags);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700243
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400244 auto prefixToRegister = make_shared<RegisteredPrefix>(prefix, filter, options);
Alexander Afanasyev0866f512014-08-11 13:25:09 -0700245
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400246 m_face.m_nfdController->start<RibRegisterCommand>(params,
247 bind(&Impl::afterPrefixRegistered, this,
248 prefixToRegister, onSuccess),
249 bind(onFailure, prefixToRegister->getPrefix(), _2),
250 options);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700251
252 return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
253 }
254
255 void
256 afterPrefixRegistered(const shared_ptr<RegisteredPrefix>& registeredPrefix,
257 const RegisterPrefixSuccessCallback& onSuccess)
258 {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800259 m_registeredPrefixTable.insert(registeredPrefix);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700260
261 if (static_cast<bool>(registeredPrefix->getFilter())) {
262 // it was a combined operation
263 m_interestFilterTable.push_back(registeredPrefix->getFilter());
264 }
265
266 if (static_cast<bool>(onSuccess)) {
267 onSuccess(registeredPrefix->getPrefix());
268 }
269 }
270
271 void
272 asyncUnregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
273 const UnregisterPrefixSuccessCallback& onSuccess,
274 const UnregisterPrefixFailureCallback& onFailure)
275 {
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400276 using namespace nfd;
277 auto i = std::find_if(m_registeredPrefixTable.begin(),
278 m_registeredPrefixTable.end(),
279 MatchRegisteredPrefixId(registeredPrefixId));
280 if (i != m_registeredPrefixTable.end()) {
281 RegisteredPrefix& record = **i;
282
283 const shared_ptr<InterestFilterRecord>& filter = record.getFilter();
284
285 if (filter != nullptr) {
286 // it was a combined operation
287 m_interestFilterTable.remove(filter);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700288 }
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400289
290 ControlParameters params;
291 params.setName(record.getPrefix());
292 m_face.m_nfdController->start<RibUnregisterCommand>(params,
293 bind(&Impl::finalizeUnregisterPrefix, this, i, onSuccess),
294 bind(onFailure, _2),
295 record.getCommandOptions());
296 }
Alexander Afanasyev851228a2014-10-20 15:55:28 -0400297 else {
Joao Pereiraba1e3b92015-06-01 17:50:37 -0400298 if (onFailure != nullptr) {
Alexander Afanasyev851228a2014-10-20 15:55:28 -0400299 onFailure("Unrecognized PrefixId");
300 }
301 }
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700302
303 // there cannot be two registered prefixes with the same id
304 }
305
306 void
307 finalizeUnregisterPrefix(RegisteredPrefixTable::iterator item,
308 const UnregisterPrefixSuccessCallback& onSuccess)
309 {
310 m_registeredPrefixTable.erase(item);
311
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700312 if (static_cast<bool>(onSuccess)) {
313 onSuccess();
314 }
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700315 }
316
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700317 void
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800318 onEmptyPitOrNoRegisteredPrefixes()
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700319 {
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800320 if (m_pendingInterestTable.empty() && m_registeredPrefixTable.empty()) {
321 m_face.m_transport->pause();
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700322 }
323 }
324
325private:
326 Face& m_face;
Alexander Afanasyev9d158f02015-02-17 21:30:19 -0800327 util::Scheduler m_scheduler;
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700328
329 PendingInterestTable m_pendingInterestTable;
330 InterestFilterTable m_interestFilterTable;
331 RegisteredPrefixTable m_registeredPrefixTable;
332
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700333 friend class Face;
334};
335
336} // namespace ndn
337
338#endif // NDN_DETAIL_FACE_IMPL_HPP