NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
face.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2022 Regents of the University of California.
4  *
5  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6  *
7  * 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.
20  */
21 
22 #include "ndn-cxx/face.hpp"
23 #include "ndn-cxx/encoding/tlv.hpp"
25 #include "ndn-cxx/net/face-uri.hpp"
28 #include "ndn-cxx/util/scope.hpp"
29 #include "ndn-cxx/util/time.hpp"
30 
31 #include "ns3/node-list.h"
32 #include "ns3/ndnSIM/helper/ndn-stack-helper.hpp"
33 #include "ns3/ndnSIM/NFD/daemon/face/generic-link-service.hpp"
34 #include "ns3/ndnSIM/NFD/daemon/face/internal-transport.hpp"
35 
36 // NDN_LOG_INIT(ndn.Face) is declared in face-impl.hpp
37 
38 // A callback scheduled through io.post and io.dispatch may be invoked after the face is destructed.
39 // To prevent this situation, use these macros to capture Face::m_impl as weak_ptr and skip callback
40 // execution if the face has been destructed.
41 #define IO_CAPTURE_WEAK_IMPL(OP) \
42  { \
43  weak_ptr<Impl> implWeak(m_impl); \
44  m_impl->m_scheduler.schedule(time::seconds(0), [=] { \
45  auto impl = implWeak.lock(); \
46  if (impl != nullptr) {
47 #define IO_CAPTURE_WEAK_IMPL_END \
48  } \
49  }); \
50  }
51 
52 namespace ndn {
53 
54 Face::OversizedPacketError::OversizedPacketError(char pktType, const Name& name, size_t wireSize)
55  : Error((pktType == 'I' ? "Interest " : pktType == 'D' ? "Data " : "Nack ") +
56  name.toUri() + " encodes into " + to_string(wireSize) + " octets, "
57  "exceeding the implementation limit of " + to_string(MAX_NDN_PACKET_SIZE) + " octets")
58  , pktType(pktType)
59  , name(name)
60  , wireSize(wireSize)
61 {
62 }
63 
65 {
66  construct(nullptr, ns3::ndn::StackHelper::getKeyChain());
67 }
68 
69 Face::Face(shared_ptr<Transport> transport)
70 {
71  construct(transport, ns3::ndn::StackHelper::getKeyChain());
72 }
73 
74 Face::Face(shared_ptr<Transport> transport, KeyChain& keyChain)
75 {
76  construct(std::move(transport), keyChain);
77 }
78 
79 shared_ptr<Transport>
80 Face::makeDefaultTransport()
81 {
82  ns3::Ptr<ns3::Node> node = ns3::NodeList::GetNode(ns3::Simulator::GetContext());
83  NS_ASSERT_MSG(node->GetObject<ns3::ndn::L3Protocol>() != 0,
84  "NDN stack should be installed on the node " << node);
85 
86  auto uri = ::nfd::FaceUri("ndnFace://" + boost::lexical_cast<std::string>(node->GetId()));
87 
88  ::nfd::face::GenericLinkService::Options serviceOpts;
89  serviceOpts.allowLocalFields = true;
90 
91  auto nfdFace = make_shared<::nfd::Face>(make_unique<::nfd::face::GenericLinkService>(serviceOpts),
92  make_unique<::nfd::face::InternalForwarderTransport>(uri, uri));
93  auto forwarderTransport = static_cast<::nfd::face::InternalForwarderTransport*>(nfdFace->getTransport());
94 
95  auto clientTransport = make_shared<::nfd::face::InternalClientTransport>();
96  clientTransport->connectToForwarder(forwarderTransport);
97 
98  node->GetObject<ns3::ndn::L3Protocol>()->addFace(nfdFace);;
99 
100  return clientTransport;
101 }
102 
103 void
104 Face::construct(shared_ptr<Transport> transport, KeyChain& keyChain)
105 {
106  BOOST_ASSERT(m_impl == nullptr);
107  m_impl = make_shared<Impl>(*this, keyChain);
108 
109  if (transport == nullptr) {
110  transport = makeDefaultTransport();
111  BOOST_ASSERT(transport != nullptr);
112  }
113  m_transport = std::move(transport);
114 
115  IO_CAPTURE_WEAK_IMPL(post) {
116  impl->ensureConnected(false);
118 }
119 
120 Face::~Face() = default;
121 
124  const DataCallback& afterSatisfied,
125  const NackCallback& afterNacked,
126  const TimeoutCallback& afterTimeout)
127 {
128  auto id = m_impl->m_pendingInterestTable.allocateId();
129 
130  auto interest2 = make_shared<Interest>(interest);
131  interest2->getNonce();
132 
133  IO_CAPTURE_WEAK_IMPL(post) {
134  impl->expressInterest(id, interest2, afterSatisfied, afterNacked, afterTimeout);
136 
137  return PendingInterestHandle(m_impl, id);
138 }
139 
140 void
142 {
143  IO_CAPTURE_WEAK_IMPL(post) {
144  impl->removeAllPendingInterests();
146 }
147 
148 size_t
150 {
151  return m_impl->m_pendingInterestTable.size();
152 }
153 
154 void
156 {
157  IO_CAPTURE_WEAK_IMPL(post) {
158  impl->putData(data);
160 }
161 
162 void
164 {
165  IO_CAPTURE_WEAK_IMPL(post) {
166  impl->putNack(nack);
168 }
169 
171 Face::setInterestFilter(const InterestFilter& filter, const InterestCallback& onInterest,
172  const RegisterPrefixFailureCallback& onFailure,
173  const security::SigningInfo& signingInfo, uint64_t flags)
174 {
175  return setInterestFilter(filter, onInterest, nullptr, onFailure, signingInfo, flags);
176 }
177 
179 Face::setInterestFilter(const InterestFilter& filter, const InterestCallback& onInterest,
180  const RegisterPrefixSuccessCallback& onSuccess,
181  const RegisterPrefixFailureCallback& onFailure,
182  const security::SigningInfo& signingInfo, uint64_t flags)
183 {
184  nfd::CommandOptions options;
185  options.setSigningInfo(signingInfo);
186 
187  auto id = m_impl->registerPrefix(filter.getPrefix(), onSuccess, onFailure, flags, options,
188  filter, onInterest);
189  return RegisteredPrefixHandle(m_impl, id);
190 }
191 
193 Face::setInterestFilter(const InterestFilter& filter, const InterestCallback& onInterest)
194 {
195  auto id = m_impl->m_interestFilterTable.allocateId();
196 
197  IO_CAPTURE_WEAK_IMPL(post) {
198  impl->setInterestFilter(id, filter, onInterest);
200 
201  return InterestFilterHandle(m_impl, id);
202 }
203 
206  const RegisterPrefixSuccessCallback& onSuccess,
207  const RegisterPrefixFailureCallback& onFailure,
208  const security::SigningInfo& signingInfo,
209  uint64_t flags)
210 {
211  nfd::CommandOptions options;
212  options.setSigningInfo(signingInfo);
213 
214  auto id = m_impl->registerPrefix(prefix, onSuccess, onFailure, flags, options, nullopt, nullptr);
215  return RegisteredPrefixHandle(m_impl, id);
216 }
217 
218 void
220 {
221 }
222 
223 void
225 {
226  IO_CAPTURE_WEAK_IMPL(post) {
227  impl->shutdown();
228  if (m_transport->isConnected())
229  m_transport->close();
231 }
232 
236 template<typename NetPkt>
237 static void
238 extractLpLocalFields(NetPkt& netPacket, const lp::Packet& lpPacket)
239 {
240  addTagFromField<lp::IncomingFaceIdTag, lp::IncomingFaceIdField>(netPacket, lpPacket);
241  addTagFromField<lp::CongestionMarkTag, lp::CongestionMarkField>(netPacket, lpPacket);
242 
243  if (lpPacket.has<lp::HopCountTagField>()) {
244  netPacket.setTag(make_shared<lp::HopCountTag>(lpPacket.get<lp::HopCountTagField>() + 1));
245  }
246 }
247 
248 void
249 Face::onReceiveElement(const Block& blockFromDaemon)
250 {
251  lp::Packet lpPacket(blockFromDaemon); // bare Interest/Data is a valid lp::Packet,
252  // no need to distinguish
253 
254  auto frag = lpPacket.get<lp::FragmentField>();
255  Block netPacket({frag.first, frag.second});
256  switch (netPacket.type()) {
257  case tlv::Interest: {
258  auto interest = make_shared<Interest>(netPacket);
259  if (lpPacket.has<lp::NackField>()) {
260  auto nack = make_shared<lp::Nack>(std::move(*interest));
261  nack->setHeader(lpPacket.get<lp::NackField>());
262  extractLpLocalFields(*nack, lpPacket);
263  NDN_LOG_DEBUG(">N " << nack->getInterest() << '~' << nack->getHeader().getReason());
264  m_impl->nackPendingInterests(*nack);
265  }
266  else {
267  extractLpLocalFields(*interest, lpPacket);
268  NDN_LOG_DEBUG(">I " << *interest);
269  m_impl->processIncomingInterest(std::move(interest));
270  }
271  break;
272  }
273  case tlv::Data: {
274  auto data = make_shared<Data>(netPacket);
275  extractLpLocalFields(*data, lpPacket);
276  NDN_LOG_DEBUG(">D " << data->getName());
277  m_impl->satisfyPendingInterests(*data);
278  break;
279  }
280  }
281 }
282 
283 PendingInterestHandle::PendingInterestHandle(weak_ptr<Face::Impl> weakImpl, detail::RecordId id)
284  : CancelHandle([w = std::move(weakImpl), id] {
285  auto impl = w.lock();
286  if (impl != nullptr) {
287  impl->asyncRemovePendingInterest(id);
288  }
289  })
290 {
291 }
292 
293 RegisteredPrefixHandle::RegisteredPrefixHandle(weak_ptr<Face::Impl> weakImpl, detail::RecordId id)
294  : CancelHandle([=] { unregister(weakImpl, id, nullptr, nullptr); })
295  , m_weakImpl(std::move(weakImpl))
296  , m_id(id)
297 {
298  // The lambda passed to CancelHandle constructor cannot call the non-static unregister(),
299  // because the base class destructor cannot access the member fields of this subclass.
300 }
301 
302 void
304  const UnregisterPrefixFailureCallback& onFailure)
305 {
306  if (m_id == 0) {
307  if (onFailure) {
308  onFailure("RegisteredPrefixHandle is empty");
309  }
310  return;
311  }
312 
313  unregister(m_weakImpl, m_id, onSuccess, onFailure);
314  *this = {};
315 }
316 
317 void
318 RegisteredPrefixHandle::unregister(const weak_ptr<Face::Impl>& weakImpl, detail::RecordId id,
319  const UnregisterPrefixSuccessCallback& onSuccess,
320  const UnregisterPrefixFailureCallback& onFailure)
321 {
322  auto impl = weakImpl.lock();
323  if (impl != nullptr) {
324  impl->asyncUnregisterPrefix(id, onSuccess, onFailure);
325  }
326  else if (onFailure) {
327  onFailure("Face already closed");
328  }
329 }
330 
331 InterestFilterHandle::InterestFilterHandle(weak_ptr<Face::Impl> weakImpl, detail::RecordId id)
332  : CancelHandle([w = std::move(weakImpl), id] {
333  auto impl = w.lock();
334  if (impl != nullptr) {
335  impl->asyncUnsetInterestFilter(id);
336  }
337  })
338 {
339 }
340 
341 } // namespace ndn
NDN_CXX_NODISCARD bool has() const
Definition: packet.hpp:74
Copyright (c) 2011-2015 Regents of the University of California.
virtual void doProcessEvents(time::milliseconds timeout, bool keepThread)
Definition: face.cpp:219
function< void(const std::string &)> UnregisterPrefixFailureCallback
Callback invoked when unregistering a prefix fails.
Definition: face.hpp:85
virtual ~Face()
std::string to_string(const T &val)
Definition: backports.hpp:86
void unregister(const UnregisterPrefixSuccessCallback &onSuccess=nullptr, const UnregisterPrefixFailureCallback &onFailure=nullptr)
Unregister the prefix.
Definition: face.cpp:303
ndn security KeyChain
Definition: key-chain.cpp:70
const Name & getPrefix() const
declares the set of Interests a producer can serve, which starts with a name prefix, plus an optional regular expression
#define IO_CAPTURE_WEAK_IMPL_END
Definition: face.cpp:47
#define NDN_LOG_DEBUG(expression)
Definition: logger.hpp:99
Represents a TLV element of the NDN packet format.
Definition: block.hpp:44
Represents an Interest packet.
Definition: interest.hpp:48
static void extractLpLocalFields(NetPkt &netPacket, const lp::Packet &lpPacket)
extract local fields from NDNLPv2 packet and tag onto a network layer packet
Definition: face.cpp:238
Signing parameters passed to KeyChain.
represents a Network Nack
Definition: nack.hpp:38
Declare a field.
Definition: field-decl.hpp:176
void removeAllPendingInterests()
Cancel all previously expressed Interests.
Definition: face.cpp:141
FIELD::ValueType get(size_t index=0) const
Definition: packet.hpp:96
Implements a forwarder-side transport that can be paired with another transport.
RegisteredPrefixHandle registerPrefix(const Name &prefix, const RegisterPrefixSuccessCallback &onSuccess, const RegisterPrefixFailureCallback &onFailure, const security::SigningInfo &signingInfo=security::SigningInfo(), uint64_t flags=nfd::ROUTE_FLAG_CHILD_INHERIT)
Register prefix with the connected NDN forwarder.
Definition: face.cpp:205
contains options for ControlCommand execution
#define IO_CAPTURE_WEAK_IMPL(OP)
Definition: face.cpp:41
Handle for a pending Interest.
Definition: face.hpp:437
size_t getNPendingInterests() const
Get number of pending Interests.
Definition: face.cpp:149
void shutdown()
Shutdown face operations.
Definition: face.cpp:224
function< void(const Name &, const std::string &)> RegisterPrefixFailureCallback
Callback invoked when registerPrefix or setInterestFilter command fails.
Definition: face.hpp:75
function< void(const Name &)> RegisterPrefixSuccessCallback
Callback invoked when registerPrefix or setInterestFilter command succeeds.
Definition: face.hpp:70
Represents an absolute name.
Definition: name.hpp:41
represents the underlying protocol and address used by a Face
Definition: face-uri.hpp:44
CommandOptions & setSigningInfo(const security::SigningInfo &signingInfo)
sets signing parameters
PendingInterestHandle expressInterest(const Interest &interest, const DataCallback &afterSatisfied, const NackCallback &afterNacked, const TimeoutCallback &afterTimeout)
Express Interest.
Definition: face.cpp:123
Implementation network-layer of NDN stack.
function< void(const InterestFilter &, const Interest &)> InterestCallback
Callback invoked when an incoming Interest matches the specified InterestFilter.
Definition: face.hpp:65
InterestFilterHandle() noexcept=default
uint64_t RecordId
Definition: face.hpp:44
function< void()> UnregisterPrefixSuccessCallback
Callback invoked when unregistering a prefix succeeds.
Definition: face.hpp:80
RegisteredPrefixHandle() noexcept=default
static KeyChain & getKeyChain()
void put(Data data)
Publish data packet.
Definition: face.cpp:155
OversizedPacketError(char pktType, const Name &name, size_t wireSize)
Constructor.
Definition: face.cpp:54
Handle for a registered Interest filter.
Definition: face.hpp:512
PendingInterestHandle() noexcept=default
function< void(const Interest &)> TimeoutCallback
Callback invoked when an expressed Interest times out.
Definition: face.hpp:60
function< void(const Interest &, const lp::Nack &)> NackCallback
Callback invoked when a Nack is received in response to an expressed Interest.
Definition: face.hpp:55
Represents a Data packet.
Definition: data.hpp:37
RegisteredPrefixHandle setInterestFilter(const InterestFilter &filter, const InterestCallback &onInterest, const RegisterPrefixFailureCallback &onFailure, const security::SigningInfo &signingInfo=security::SigningInfo(), uint64_t flags=nfd::ROUTE_FLAG_CHILD_INHERIT)
Set InterestFilter to dispatch incoming matching interest to onInterest callback and register the fil...
Definition: face.cpp:171
Face(shared_ptr< Transport > transport=nullptr)
Create Face using given transport (or default transport if omitted)
Definition: face.cpp:69
const nullopt_t nullopt((nullopt_t::init()))
Handle for a registered prefix.
Definition: face.hpp:464
function< void(const Interest &, const Data &)> DataCallback
Callback invoked when an expressed Interest is satisfied by a Data packet.
Definition: face.hpp:50
const size_t MAX_NDN_PACKET_SIZE
Practical size limit of a network-layer packet.
Definition: tlv.hpp:41
boost::chrono::milliseconds milliseconds
Definition: time.hpp:48