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-2019 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"
27 #include "ndn-cxx/util/time.hpp"
28 
29 #include "ns3/node-list.h"
30 #include "ns3/ndnSIM/helper/ndn-stack-helper.hpp"
31 #include "ns3/ndnSIM/NFD/daemon/face/generic-link-service.hpp"
32 #include "ns3/ndnSIM/NFD/daemon/face/internal-transport.hpp"
33 
34 // NDN_LOG_INIT(ndn.Face) is declared in face-impl.hpp
35 
36 // A callback scheduled through io.post and io.dispatch may be invoked after the face is destructed.
37 // To prevent this situation, use these macros to capture Face::m_impl as weak_ptr and skip callback
38 // execution if the face has been destructed.
39 #define IO_CAPTURE_WEAK_IMPL(OP) \
40  { \
41  weak_ptr<Impl> implWeak(m_impl); \
42  m_impl->m_scheduler.schedule(time::seconds(0), [=] { \
43  auto impl = implWeak.lock(); \
44  if (impl != nullptr) {
45 #define IO_CAPTURE_WEAK_IMPL_END \
46  } \
47  }); \
48  }
49 
50 namespace ndn {
51 
52 Face::OversizedPacketError::OversizedPacketError(char pktType, const Name& name, size_t wireSize)
53  : Error((pktType == 'I' ? "Interest " : pktType == 'D' ? "Data " : "Nack ") +
54  name.toUri() + " encodes into " + to_string(wireSize) + " octets, "
55  "exceeding the implementation limit of " + to_string(MAX_NDN_PACKET_SIZE) + " octets")
56  , pktType(pktType)
57  , name(name)
58  , wireSize(wireSize)
59 {
60 }
61 
63 {
64  construct(nullptr, ns3::ndn::StackHelper::getKeyChain());
65 }
66 
67 Face::Face(shared_ptr<Transport> transport)
68 {
69  construct(transport, ns3::ndn::StackHelper::getKeyChain());
70 }
71 
72 Face::Face(shared_ptr<Transport> transport, KeyChain& keyChain)
73 {
74  construct(std::move(transport), keyChain);
75 }
76 
77 shared_ptr<Transport>
78 Face::makeDefaultTransport()
79 {
80  ns3::Ptr<ns3::Node> node = ns3::NodeList::GetNode(ns3::Simulator::GetContext());
81  NS_ASSERT_MSG(node->GetObject<ns3::ndn::L3Protocol>() != 0,
82  "NDN stack should be installed on the node " << node);
83 
84  auto uri = ::nfd::FaceUri("ndnFace://" + boost::lexical_cast<std::string>(node->GetId()));
85 
87  serviceOpts.allowLocalFields = true;
88 
89  auto nfdFace = make_shared<::nfd::Face>(make_unique<::nfd::face::GenericLinkService>(serviceOpts),
90  make_unique<::nfd::face::InternalForwarderTransport>(uri, uri));
91  auto forwarderTransport = static_cast<::nfd::face::InternalForwarderTransport*>(nfdFace->getTransport());
92 
93  auto clientTransport = make_shared<::nfd::face::InternalClientTransport>();
94  clientTransport->connectToForwarder(forwarderTransport);
95 
96  node->GetObject<ns3::ndn::L3Protocol>()->addFace(nfdFace);;
97 
98  return clientTransport;
99 }
100 
101 void
102 Face::construct(shared_ptr<Transport> transport, KeyChain& keyChain)
103 {
104  BOOST_ASSERT(m_impl == nullptr);
105  m_impl = make_shared<Impl>(*this, keyChain);
106 
107  if (transport == nullptr) {
108  transport = makeDefaultTransport();
109  BOOST_ASSERT(transport != nullptr);
110  }
111  m_transport = std::move(transport);
112 
113  IO_CAPTURE_WEAK_IMPL(post) {
114  impl->ensureConnected(false);
116 }
117 
118 Face::~Face() = default;
119 
120 PendingInterestHandle
122  const DataCallback& afterSatisfied,
123  const NackCallback& afterNacked,
124  const TimeoutCallback& afterTimeout)
125 {
126  auto id = m_impl->m_pendingInterestTable.allocateId();
127 
128  auto interest2 = make_shared<Interest>(interest);
129  interest2->getNonce();
130 
131  IO_CAPTURE_WEAK_IMPL(post) {
132  impl->asyncExpressInterest(id, interest2, afterSatisfied, afterNacked, afterTimeout);
134 
135  return PendingInterestHandle(*this, reinterpret_cast<const PendingInterestId*>(id));
136 }
137 
138 void
139 Face::cancelPendingInterest(const PendingInterestId* pendingInterestId)
140 {
141  IO_CAPTURE_WEAK_IMPL(post) {
142  impl->asyncRemovePendingInterest(reinterpret_cast<RecordId>(pendingInterestId));
144 }
145 
146 void
148 {
149  IO_CAPTURE_WEAK_IMPL(post) {
150  impl->asyncRemoveAllPendingInterests();
152 }
153 
154 size_t
156 {
157  return m_impl->m_pendingInterestTable.size();
158 }
159 
160 void
162 {
163  IO_CAPTURE_WEAK_IMPL(post) {
164  impl->asyncPutData(data);
166 }
167 
168 void
170 {
171  IO_CAPTURE_WEAK_IMPL(post) {
172  impl->asyncPutNack(nack);
174 }
175 
177 Face::setInterestFilter(const InterestFilter& filter, const InterestCallback& onInterest,
178  const RegisterPrefixFailureCallback& onFailure,
179  const security::SigningInfo& signingInfo, uint64_t flags)
180 {
181  return setInterestFilter(filter, onInterest, nullptr, onFailure, signingInfo, flags);
182 }
183 
185 Face::setInterestFilter(const InterestFilter& filter, const InterestCallback& onInterest,
186  const RegisterPrefixSuccessCallback& onSuccess,
187  const RegisterPrefixFailureCallback& onFailure,
188  const security::SigningInfo& signingInfo, uint64_t flags)
189 {
190  nfd::CommandOptions options;
191  options.setSigningInfo(signingInfo);
192 
193  auto id = m_impl->registerPrefix(filter.getPrefix(), onSuccess, onFailure, flags, options,
194  filter, onInterest);
195  return RegisteredPrefixHandle(*this, reinterpret_cast<const RegisteredPrefixId*>(id));
196 }
197 
199 Face::setInterestFilter(const InterestFilter& filter, const InterestCallback& onInterest)
200 {
201  auto id = m_impl->m_interestFilterTable.allocateId();
202 
203  IO_CAPTURE_WEAK_IMPL(post) {
204  impl->asyncSetInterestFilter(id, filter, onInterest);
206 
207  return InterestFilterHandle(*this, reinterpret_cast<const InterestFilterId*>(id));
208 }
209 
210 void
211 Face::clearInterestFilter(const InterestFilterId* interestFilterId)
212 {
213  IO_CAPTURE_WEAK_IMPL(post) {
214  impl->asyncUnsetInterestFilter(reinterpret_cast<RecordId>(interestFilterId));
216 }
217 
218 RegisteredPrefixHandle
220  const RegisterPrefixSuccessCallback& onSuccess,
221  const RegisterPrefixFailureCallback& onFailure,
222  const security::SigningInfo& signingInfo,
223  uint64_t flags)
224 {
225  nfd::CommandOptions options;
226  options.setSigningInfo(signingInfo);
227 
228  auto id = m_impl->registerPrefix(prefix, onSuccess, onFailure, flags, options, nullopt, nullptr);
229  return RegisteredPrefixHandle(*this, reinterpret_cast<const RegisteredPrefixId*>(id));
230 }
231 
232 void
233 Face::unregisterPrefixImpl(const RegisteredPrefixId* registeredPrefixId,
234  const UnregisterPrefixSuccessCallback& onSuccess,
235  const UnregisterPrefixFailureCallback& onFailure)
236 {
237  IO_CAPTURE_WEAK_IMPL(post) {
238  impl->asyncUnregisterPrefix(reinterpret_cast<RecordId>(registeredPrefixId),
239  onSuccess, onFailure);
241 }
242 
243 void
244 Face::doProcessEvents(time::milliseconds timeout, bool keepThread)
245 {
246 }
247 
248 void
250 {
251  IO_CAPTURE_WEAK_IMPL(post) {
252  impl->shutdown();
253  if (m_transport->isConnected())
254  m_transport->close();
256 }
257 
261 template<typename NetPkt>
262 static void
263 extractLpLocalFields(NetPkt& netPacket, const lp::Packet& lpPacket)
264 {
265  addTagFromField<lp::IncomingFaceIdTag, lp::IncomingFaceIdField>(netPacket, lpPacket);
266  addTagFromField<lp::CongestionMarkTag, lp::CongestionMarkField>(netPacket, lpPacket);
267 
268  if (lpPacket.has<lp::HopCountTagField>()) {
269  netPacket.setTag(make_shared<lp::HopCountTag>(lpPacket.get<lp::HopCountTagField>() + 1));
270  }
271 }
272 
273 void
274 Face::onReceiveElement(const Block& blockFromDaemon)
275 {
276  lp::Packet lpPacket(blockFromDaemon); // bare Interest/Data is a valid lp::Packet,
277  // no need to distinguish
278 
279  Buffer::const_iterator begin, end;
280  std::tie(begin, end) = lpPacket.get<lp::FragmentField>();
281  Block netPacket(&*begin, std::distance(begin, end));
282  switch (netPacket.type()) {
283  case tlv::Interest: {
284  auto interest = make_shared<Interest>(netPacket);
285  if (lpPacket.has<lp::NackField>()) {
286  auto nack = make_shared<lp::Nack>(std::move(*interest));
287  nack->setHeader(lpPacket.get<lp::NackField>());
288  extractLpLocalFields(*nack, lpPacket);
289  NDN_LOG_DEBUG(">N " << nack->getInterest() << '~' << nack->getHeader().getReason());
290  m_impl->nackPendingInterests(*nack);
291  }
292  else {
293  extractLpLocalFields(*interest, lpPacket);
294  NDN_LOG_DEBUG(">I " << *interest);
295  m_impl->processIncomingInterest(std::move(interest));
296  }
297  break;
298  }
299  case tlv::Data: {
300  auto data = make_shared<Data>(netPacket);
301  extractLpLocalFields(*data, lpPacket);
302  NDN_LOG_DEBUG(">D " << data->getName());
303  m_impl->satisfyPendingInterests(*data);
304  break;
305  }
306  }
307 }
308 
309 PendingInterestHandle::PendingInterestHandle(Face& face, const PendingInterestId* id)
310  : CancelHandle([&face, id] { face.cancelPendingInterest(id); })
311 {
312 }
313 
314 RegisteredPrefixHandle::RegisteredPrefixHandle(Face& face, const RegisteredPrefixId* id)
315  : CancelHandle([&face, id] { face.unregisterPrefixImpl(id, nullptr, nullptr); })
316  , m_face(&face)
317  , m_id(id)
318 {
319  // The lambda passed to CancelHandle constructor cannot call this->unregister,
320  // because base class destructor cannot access the member fields of this subclass.
321 }
322 
323 void
325  const UnregisterPrefixFailureCallback& onFailure)
326 {
327  if (m_id == nullptr) {
328  if (onFailure != nullptr) {
329  onFailure("RegisteredPrefixHandle is empty");
330  }
331  return;
332  }
333 
334  m_face->unregisterPrefixImpl(m_id, onSuccess, onFailure);
335  m_face = nullptr;
336  m_id = nullptr;
337 }
338 
339 InterestFilterHandle::InterestFilterHandle(Face& face, const InterestFilterId* id)
340  : CancelHandle([&face, id] { face.clearInterestFilter(id); })
341 {
342 }
343 
344 } // namespace ndn
ndn::lp::Packet
Definition: packet.hpp:31
ndn::RegisterPrefixFailureCallback
function< void(const Name &, const std::string &)> RegisterPrefixFailureCallback
Callback invoked when registerPrefix or setInterestFilter command fails.
Definition: face.hpp:74
ndn::InterestFilterHandle::InterestFilterHandle
InterestFilterHandle() noexcept=default
tlv.hpp
ndn::RegisteredPrefixHandle
A handle of registered prefix.
Definition: face.hpp:520
nonstd::optional_lite::std11::move
T & move(T &t)
Definition: optional.hpp:421
ndn::extractLpLocalFields
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:263
ndn::tlv::Interest
@ Interest
Definition: tlv.hpp:65
ndn::FaceUri
represents the underlying protocol and address used by a Face
Definition: face-uri.hpp:45
IO_CAPTURE_WEAK_IMPL
#define IO_CAPTURE_WEAK_IMPL(OP)
Definition: face.cpp:39
ndn::lp::Packet::has
NDN_CXX_NODISCARD bool has() const
Definition: packet.hpp:74
ndn::Face::expressInterest
PendingInterestHandle expressInterest(const Interest &interest, const DataCallback &afterSatisfied, const NackCallback &afterNacked, const TimeoutCallback &afterTimeout)
Express Interest.
Definition: face.cpp:121
ndn::PendingInterestHandle
A handle of pending Interest.
Definition: face.hpp:493
face-impl.hpp
signing-helpers.hpp
ndn::RecordId
uintptr_t RecordId
Definition: record-container.hpp:32
ndn::security::SigningInfo
Signing parameters passed to KeyChain.
Definition: signing-info.hpp:42
ndn::InterestFilterHandle
A handle of registered Interest filter.
Definition: face.hpp:572
ndn::Face::shutdown
void shutdown()
Shutdown face operations.
Definition: face.cpp:249
ndn::Face
Provide a communication channel with local or remote NDN forwarder.
Definition: face.hpp:90
ndn::InterestFilter::getPrefix
const Name & getPrefix() const
Definition: interest-filter.hpp:107
ndn::Face::registerPrefix
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:219
ndn::Face::getNPendingInterests
size_t getNPendingInterests() const
Get number of pending Interests.
Definition: face.cpp:155
ndn::Face::put
void put(Data data)
Publish data packet.
Definition: face.cpp:161
face-uri.hpp
ndn::Name
Represents an absolute name.
Definition: name.hpp:44
ndn::UnregisterPrefixSuccessCallback
function< void()> UnregisterPrefixSuccessCallback
Callback invoked when unregisterPrefix or unsetInterestFilter command succeeds.
Definition: face.hpp:79
ndn::InterestFilter
declares the set of Interests a producer can serve, which starts with a name prefix,...
Definition: interest-filter.hpp:36
ndn::RegisteredPrefixHandle::unregister
void unregister(const UnregisterPrefixSuccessCallback &onSuccess=nullptr, const UnregisterPrefixFailureCallback &onFailure=nullptr)
Unregister the prefix.
Definition: face.cpp:324
ndn::InterestCallback
function< void(const InterestFilter &, const Interest &)> InterestCallback
Callback invoked when incoming Interest matches the specified InterestFilter.
Definition: face.hpp:64
ndn::security::v2::KeyChain
The interface of signing key management.
Definition: key-chain.hpp:47
nfd::face::GenericLinkService::Options::allowLocalFields
bool allowLocalFields
enables encoding of IncomingFaceId, and decoding of NextHopFaceId and CachePolicy
Definition: generic-link-service.hpp:110
ndn::DummyIoService
Definition: asio-fwd.hpp:28
ndn::lp::FieldDecl
Declare a field.
Definition: field-decl.hpp:180
ndn::Face::Face
Face(shared_ptr< Transport > transport=nullptr)
Create Face using given transport (or default transport if omitted)
Definition: face.cpp:67
ndn::nfd::CommandOptions::setSigningInfo
CommandOptions & setSigningInfo(const security::SigningInfo &signingInfo)
sets signing parameters
Definition: command-options.cpp:55
ndn::Face::doProcessEvents
virtual void doProcessEvents(time::milliseconds timeout, bool keepThread)
Definition: face.cpp:244
ndn::DataCallback
function< void(const Interest &, const Data &)> DataCallback
Callback invoked when expressed Interest gets satisfied with a Data packet.
Definition: face.hpp:44
nfd::face::GenericLinkService::Options
Options that control the behavior of GenericLinkService.
Definition: generic-link-service.hpp:101
IO_CAPTURE_WEAK_IMPL_END
#define IO_CAPTURE_WEAK_IMPL_END
Definition: face.cpp:45
ndn::RegisteredPrefixHandle::RegisteredPrefixHandle
RegisteredPrefixHandle() noexcept
Definition: face.hpp:522
nonstd::optional_lite::nullopt
const nullopt_t nullopt((nullopt_t::init()))
ndn::Interest
Represents an Interest packet.
Definition: interest.hpp:44
nfd::face
Definition: ndn-common.hpp:84
ndn::Face::removeAllPendingInterests
void removeAllPendingInterests()
Cancel all previously expressed Interests.
Definition: face.cpp:147
ndn::Data
Represents a Data packet.
Definition: data.hpp:36
ndn::RegisterPrefixSuccessCallback
function< void(const Name &)> RegisterPrefixSuccessCallback
Callback invoked when registerPrefix or setInterestFilter command succeeds.
Definition: face.hpp:69
ndn::nfd::CommandOptions
contains options for ControlCommand execution
Definition: command-options.hpp:35
ndn::NackCallback
function< void(const Interest &, const lp::Nack &)> NackCallback
Callback invoked when Nack is sent in response to expressed Interest.
Definition: face.hpp:54
ndn::Face::~Face
virtual ~Face()
ndn::tlv::Data
@ Data
Definition: tlv.hpp:66
NDN_LOG_DEBUG
#define NDN_LOG_DEBUG(expression)
Definition: logger.hpp:99
ndn::MAX_NDN_PACKET_SIZE
const size_t MAX_NDN_PACKET_SIZE
practical limit of network layer packet size
Definition: tlv.hpp:41
face.hpp
nfd::face::InternalForwarderTransport
Implements a forwarder-side transport that can be paired with another transport.
Definition: internal-transport.hpp:51
ndn::PendingInterestHandle::PendingInterestHandle
PendingInterestHandle() noexcept=default
ndn::lp::Nack
represents a Network Nack
Definition: nack.hpp:39
ndn::to_string
std::string to_string(const T &val)
Definition: backports.hpp:102
ndn::name
Definition: name-component-types.hpp:33
ns3::ndn::L3Protocol
Implementation network-layer of NDN stack.
Definition: ndn-l3-protocol.hpp:81
ndn::security::v2::KeyChain
ndn security v2 KeyChain
Definition: key-chain.cpp:68
ndn::TimeoutCallback
function< void(const Interest &)> TimeoutCallback
Callback invoked when expressed Interest times out.
Definition: face.hpp:59
ndn::Face::Error
Definition: face.hpp:93
time.hpp
ndn::UnregisterPrefixFailureCallback
function< void(const std::string &)> UnregisterPrefixFailureCallback
Callback invoked when unregisterPrefix or unsetInterestFilter command fails.
Definition: face.hpp:84
ns3::ndn::StackHelper::getKeyChain
static KeyChain & getKeyChain()
Definition: ndn-stack-helper.cpp:77
ndn::Face::OversizedPacketError::OversizedPacketError
OversizedPacketError(char pktType, const Name &name, size_t wireSize)
Constructor.
Definition: face.cpp:52
ndn::lp::Packet::get
FIELD::ValueType get(size_t index=0) const
Definition: packet.hpp:96
ndn
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-strategy-choice-helper.hpp:34
ndn::Face::setInterestFilter
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:177