NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
face-impl.hpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
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"
31 
32 #include "../util/scheduler.hpp"
33 #include "../util/config-file.hpp"
34 #include "../util/signal.hpp"
35 
36 #include "../transport/transport.hpp"
37 #include "../transport/unix-transport.hpp"
38 #include "../transport/tcp-transport.hpp"
39 
40 #include "../management/nfd-controller.hpp"
41 #include "../management/nfd-command-options.hpp"
42 
43 #include "../lp/packet.hpp"
44 #include "../lp/tags.hpp"
45 
46 namespace ndn {
47 
48 class Face::Impl : noncopyable
49 {
50 public:
51  typedef ContainerWithOnEmptySignal<shared_ptr<PendingInterest>> PendingInterestTable;
52  typedef std::list<shared_ptr<InterestFilterRecord> > InterestFilterTable;
53  typedef ContainerWithOnEmptySignal<shared_ptr<RegisteredPrefix>> RegisteredPrefixTable;
54 
55  explicit
57  : m_face(face)
58  , m_scheduler(m_face.getIoService())
59  {
60  auto postOnEmptyPitOrNoRegisteredPrefixes = [this] {
61  m_scheduler.scheduleEvent(time::seconds(0), bind(&Impl::onEmptyPitOrNoRegisteredPrefixes, this));
62  // 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);
70  }
71 
74 
75  void
77  {
78  for (auto entry = m_pendingInterestTable.begin(); entry != m_pendingInterestTable.end(); ) {
79  if ((*entry)->getInterest()->matchesData(data)) {
80  shared_ptr<PendingInterest> matchedEntry = *entry;
81 
82  entry = m_pendingInterestTable.erase(entry);
83 
84  matchedEntry->invokeDataCallback(data);
85  }
86  else
87  ++entry;
88  }
89  }
90 
91  void
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
111  {
112  for (const auto& filter : m_interestFilterTable) {
113  if (filter->doesMatch(interest.getName())) {
114  filter->invokeInterestCallback(interest);
115  }
116  }
117  }
118 
121 
122  void
123  ensureConnected(bool wantResume)
124  {
125  if (!m_face.m_transport->isConnected())
126  m_face.m_transport->connect(m_face.getIoService(),
127  bind(&Face::onReceiveElement, &m_face, _1));
128 
129  if (wantResume && !m_face.m_transport->isExpectingData())
130  m_face.m_transport->resume();
131  }
132 
133  void
134  asyncExpressInterest(shared_ptr<const Interest> interest,
135  const DataCallback& afterSatisfied,
136  const NackCallback& afterNacked,
137  const TimeoutCallback& afterTimeout)
138  {
139  this->ensureConnected(true);
140 
141  auto entry =
142  m_pendingInterestTable.insert(make_shared<PendingInterest>(interest,
143  afterSatisfied,
144  afterNacked,
145  afterTimeout,
146  ref(m_scheduler))).first;
147  (*entry)->setDeleter([this, entry] { m_pendingInterestTable.erase(entry); });
148 
149  lp::Packet packet;
150 
151  shared_ptr<lp::NextHopFaceIdTag> nextHopFaceIdTag = interest->getTag<lp::NextHopFaceIdTag>();
152  if (nextHopFaceIdTag != nullptr) {
153  packet.add<lp::NextHopFaceIdField>(*nextHopFaceIdTag);
154  }
155 
156  packet.add<lp::FragmentField>(std::make_pair(interest->wireEncode().begin(),
157  interest->wireEncode().end()));
158 
159  m_face.m_transport->send(packet.wireEncode());
160  }
161 
162  void
163  asyncRemovePendingInterest(const PendingInterestId* pendingInterestId)
164  {
165  m_pendingInterestTable.remove_if(MatchPendingInterestId(pendingInterestId));
166  }
167 
168  void
170  {
171  m_pendingInterestTable.clear();
172  }
173 
174  void
175  asyncPutData(const shared_ptr<const Data>& data)
176  {
177  this->ensureConnected(true);
178 
179  lp::Packet packet;
180 
181  shared_ptr<lp::CachePolicyTag> cachePolicyTag = data->getTag<lp::CachePolicyTag>();
182  if (cachePolicyTag != nullptr) {
183  packet.add<lp::CachePolicyField>(*cachePolicyTag);
184  }
185 
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());
204  }
205 
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 
229 
230  const RegisteredPrefixId*
231  registerPrefix(const Name& prefix,
232  const shared_ptr<InterestFilterRecord>& filter,
233  const RegisterPrefixSuccessCallback& onSuccess,
234  const RegisterPrefixFailureCallback& onFailure,
235  uint64_t flags,
236  const nfd::CommandOptions& options)
237  {
238  using namespace nfd;
239 
240  ControlParameters params;
241  params.setName(prefix);
242  params.setFlags(flags);
243 
244  auto prefixToRegister = make_shared<RegisteredPrefix>(prefix, filter, options);
245 
246  m_face.m_nfdController->start<RibRegisterCommand>(params,
247  bind(&Impl::afterPrefixRegistered, this,
248  prefixToRegister, onSuccess),
249  bind(onFailure, prefixToRegister->getPrefix(), _2),
250  options);
251 
252  return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
253  }
254 
255  void
256  afterPrefixRegistered(const shared_ptr<RegisteredPrefix>& registeredPrefix,
257  const RegisterPrefixSuccessCallback& onSuccess)
258  {
259  m_registeredPrefixTable.insert(registeredPrefix);
260 
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  {
276  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);
288  }
289 
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  }
297  else {
298  if (onFailure != nullptr) {
299  onFailure("Unrecognized PrefixId");
300  }
301  }
302 
303  // there cannot be two registered prefixes with the same id
304  }
305 
306  void
308  const UnregisterPrefixSuccessCallback& onSuccess)
309  {
310  m_registeredPrefixTable.erase(item);
311 
312  if (static_cast<bool>(onSuccess)) {
313  onSuccess();
314  }
315  }
316 
317  void
319  {
320  if (m_pendingInterestTable.empty() && m_registeredPrefixTable.empty()) {
321  m_face.m_transport->pause();
322  }
323  }
324 
325 private:
326  Face& m_face;
327  util::Scheduler m_scheduler;
328 
329  PendingInterestTable m_pendingInterestTable;
330  InterestFilterTable m_interestFilterTable;
331  RegisteredPrefixTable m_registeredPrefixTable;
332 
333  friend class Face;
334 };
335 
336 } // namespace ndn
337 
338 #endif // NDN_DETAIL_FACE_IMPL_HPP
Copyright (c) 2011-2015 Regents of the University of California.
ContainerWithOnEmptySignal< shared_ptr< RegisteredPrefix > > RegisteredPrefixTable
Definition: face-impl.hpp:53
void ensureConnected(bool wantResume)
Definition: face-impl.hpp:123
size_t wireEncode(EncodingImpl< TAG > &encoder) const
append packet to encoder
Definition: packet.cpp:42
function< void(const std::string &)> UnregisterPrefixFailureCallback
Callback called when unregisterPrefix or unsetInterestFilter command fails.
Definition: face.hpp:114
void asyncExpressInterest(shared_ptr< const Interest > interest, const DataCallback &afterSatisfied, const NackCallback &afterNacked, const TimeoutCallback &afterTimeout)
Definition: face-impl.hpp:134
void afterPrefixRegistered(const shared_ptr< RegisteredPrefix > &registeredPrefix, const RegisterPrefixSuccessCallback &onSuccess)
Definition: face-impl.hpp:256
Packet & add(const typename FIELD::ValueType &value)
add a FIELD with value
Definition: packet.hpp:156
Impl(Face &face)
Definition: face-impl.hpp:56
void nackPendingInterests(const lp::Nack &nack)
Definition: face-impl.hpp:92
void asyncPutData(const shared_ptr< const Data > &data)
Definition: face-impl.hpp:175
void asyncUnsetInterestFilter(const InterestFilterId *interestFilterId)
Definition: face-impl.hpp:216
void asyncUnregisterPrefix(const RegisteredPrefixId *registeredPrefixId, const UnregisterPrefixSuccessCallback &onSuccess, const UnregisterPrefixFailureCallback &onFailure)
Definition: face-impl.hpp:272
represents a Network Nack
Definition: nack.hpp:40
provides a tag type for simple types
Definition: tag.hpp:58
Table::const_iterator iterator
Definition: cs-internal.hpp:41
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
friend class Face
Definition: face-impl.hpp:333
std::list< shared_ptr< InterestFilterRecord > > InterestFilterTable
Definition: face-impl.hpp:52
void finalizeUnregisterPrefix(RegisteredPrefixTable::iterator item, const UnregisterPrefixSuccessCallback &onSuccess)
Definition: face-impl.hpp:307
void asyncRemoveAllPendingInterests()
Definition: face-impl.hpp:169
void processInterestFilters(Interest &interest)
Definition: face-impl.hpp:110
function< void(const Name &, const std::string &)> RegisterPrefixFailureCallback
Callback called when registerPrefix or setInterestFilter command fails.
Definition: face.hpp:104
function< void(const Name &)> RegisterPrefixSuccessCallback
Callback called when registerPrefix or setInterestFilter command succeeds.
Definition: face.hpp:99
boost::asio::io_service & getIoService()
Return nullptr (cannot use IoService in simulations), preserved for API compatibility.
Definition: face.hpp:664
void asyncSetInterestFilter(const shared_ptr< InterestFilterRecord > &interestFilterRecord)
Definition: face-impl.hpp:210
function< void()> UnregisterPrefixSuccessCallback
Callback called when unregisterPrefix or unsetInterestFilter command succeeds.
Definition: face.hpp:109
void satisfyPendingInterests(Data &data)
Definition: face-impl.hpp:76
void asyncRemovePendingInterest(const PendingInterestId *pendingInterestId)
Definition: face-impl.hpp:163
const RegisteredPrefixId * registerPrefix(const Name &prefix, const shared_ptr< InterestFilterRecord > &filter, const RegisterPrefixSuccessCallback &onSuccess, const RegisterPrefixFailureCallback &onFailure, uint64_t flags, const nfd::CommandOptions &options)
Definition: face-impl.hpp:231
function< void(const Interest &)> TimeoutCallback
Callback called when expressed Interest times out.
Definition: face.hpp:77
ContainerWithOnEmptySignal< shared_ptr< PendingInterest > > PendingInterestTable
Definition: face-impl.hpp:51
function< void(const Interest &, const lp::Nack &)> NackCallback
Callback called when Nack is sent in response to expressed Interest.
Definition: face.hpp:72
void asyncPutNack(shared_ptr< const lp::Nack > nack)
Definition: face-impl.hpp:193
const Interest & getInterest() const
Definition: nack.hpp:53
function< void(const Interest &, const Data &)> DataCallback
Callback called when expressed Interest gets satisfied with a Data packet.
Definition: face.hpp:67
void onEmptyPitOrNoRegisteredPrefixes()
Definition: face-impl.hpp:318