NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
link.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
22 #include "link.hpp"
23 #include "interest.hpp"
25 #include "util/crypto.hpp"
26 #include "security/key-chain.hpp"
27 
28 #include <algorithm>
29 
30 #include <boost/range/adaptors.hpp>
31 
32 namespace ndn {
33 
34 BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Link>));
35 BOOST_CONCEPT_ASSERT((WireEncodable<Link>));
36 BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<Link>));
37 BOOST_CONCEPT_ASSERT((WireDecodable<Link>));
38 static_assert(std::is_base_of<Data::Error, Link::Error>::value,
39  "Link::Error should inherit from Data::Error");
40 
41 Link::Link(const Block& block)
42 {
43  wireDecode(block);
44 }
45 
47  : Data(name)
48 {
49 }
50 
51 Link::Link(const Name& name, std::initializer_list<std::pair<uint32_t, Name>> links)
52  : Data(name)
53 {
54  m_delegations.insert(links);
55  encodeContent();
56 }
57 
58 void
59 Link::addDelegation(uint32_t preference, const Name& name)
60 {
61  this->removeDelegationNoEncode(name);
62  m_delegations.insert({preference, name});
63  encodeContent();
64 }
65 
66 bool
68 {
69  bool hasRemovedDelegation = this->removeDelegationNoEncode(name);
70  if (hasRemovedDelegation) {
71  encodeContent();
72  }
73  return hasRemovedDelegation;
74 }
75 
78 {
79  return m_delegations;
80 }
81 
82 template<encoding::Tag TAG>
83 size_t
84 Link::encodeContent(EncodingImpl<TAG>& encoder) const
85 {
86  // LinkContent ::= CONTENT-TYPE TLV-LENGTH
87  // Delegation+
88 
89  // Delegation ::= LINK-DELEGATION-TYPE TLV-LENGTH
90  // Preference
91  // Name
92 
93  // Preference ::= LINK-PREFERENCE-TYPE TLV-LENGTH
94  // nonNegativeInteger
95 
96  size_t totalLength = 0;
97  for (const auto& delegation : m_delegations | boost::adaptors::reversed) {
98  size_t delegationLength = 0;
99  delegationLength += std::get<1>(delegation).wireEncode(encoder);
100  delegationLength += prependNonNegativeIntegerBlock(encoder, tlv::LinkPreference,
101  std::get<0>(delegation));
102  delegationLength += encoder.prependVarNumber(delegationLength);
103  delegationLength += encoder.prependVarNumber(tlv::LinkDelegation);
104  totalLength += delegationLength;
105  }
106  totalLength += encoder.prependVarNumber(totalLength);
107  totalLength += encoder.prependVarNumber(tlv::Content);
108  return totalLength;
109 }
110 
111 template size_t
112 Link::encodeContent<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& encoder) const;
113 
114 template size_t
115 Link::encodeContent<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& encoder) const;
116 
117 void
119 {
120  onChanged();
121 
122  EncodingEstimator estimator;
123  size_t estimatedSize = encodeContent(estimator);
124 
125  EncodingBuffer buffer(estimatedSize, 0);
126  encodeContent(buffer);
127 
129  setContent(buffer.block());
130 }
131 
132 void
134 {
135  // LinkContent ::= CONTENT-TYPE TLV-LENGTH
136  // Delegation+
137 
138  // Delegation ::= LINK-DELEGATION-TYPE TLV-LENGTH
139  // Preference
140  // Name
141 
142  // Preference ::= LINK-PREFERENCE-TYPE TLV-LENGTH
143  // nonNegativeInteger
144 
146  {
147  BOOST_THROW_EXCEPTION(Error("Expected Content Type Link"));
148  }
149 
150  const Block& content = getContent();
151  content.parse();
152 
153  for (auto& delegation : content.elements()) {
154  delegation.parse();
155  Block::element_const_iterator val = delegation.elements_begin();
156  if (val == delegation.elements_end()) {
157  BOOST_THROW_EXCEPTION(Error("Unexpected Link Encoding"));
158  }
159  uint32_t preference;
160  try {
161  preference = static_cast<uint32_t>(readNonNegativeInteger(*val));
162  }
163  catch (tlv::Error&) {
164  BOOST_THROW_EXCEPTION(Error("Missing preference field in Link Encoding"));
165  }
166  ++val;
167  if (val == delegation.elements_end()) {
168  BOOST_THROW_EXCEPTION(Error("Missing name field in Link Encoding"));
169  }
170  Name name(*val);
171  m_delegations.insert({preference, name});
172  }
173 }
174 
175 void
177 {
178  Data::wireDecode(wire);
179  decodeContent();
180 }
181 
182 std::tuple<uint32_t, Name>
183 Link::getDelegationFromWire(const Block& block, size_t index)
184 {
185  block.parse();
186  const Block& contentBlock = block.get(tlv::Content);
187  contentBlock.parse();
188  const Block& delegationBlock = contentBlock.elements().at(index);
189  delegationBlock.parse();
190  if (delegationBlock.type() != tlv::LinkDelegation) {
191  BOOST_THROW_EXCEPTION(Error("Unexpected TLV-TYPE, expecting LinkDelegation"));
192  }
193  return std::make_tuple(
194  static_cast<uint32_t>(
196  Name(delegationBlock.get(tlv::Name)));
197 }
198 
199 ssize_t
200 Link::findDelegationFromWire(const Block& block, const Name& delegationName)
201 {
202  block.parse();
203  const Block& contentBlock = block.get(tlv::Content);
204  contentBlock.parse();
205  size_t counter = 0;
206  for (auto&& delegationBlock : contentBlock.elements()) {
207  delegationBlock.parse();
208  if (delegationBlock.type() != tlv::LinkDelegation) {
209  BOOST_THROW_EXCEPTION(Error("Unexpected TLV-TYPE, expecting LinkDelegation"));
210  }
211  Name name(delegationBlock.get(tlv::Name));
212  if (name == delegationName) {
213  return counter;
214  }
215  ++counter;
216  }
218 }
219 
220 ssize_t
222 {
223  block.parse();
224  const Block& contentBlock = block.get(tlv::Content);
225  contentBlock.parse();
226  return contentBlock.elements_size();
227 }
228 
229 bool
230 Link::removeDelegationNoEncode(const Name& name)
231 {
232  bool hasRemoved = false;
233  auto i = m_delegations.begin();
234  while (i != m_delegations.end()) {
235  if (i->second == name) {
236  hasRemoved = true;
237  i = m_delegations.erase(i);
238  }
239  else {
240  ++i;
241  }
242  }
243  return hasRemoved;
244 }
245 
246 } // namespace ndn
Data & setContentType(uint32_t type)
Definition: data.cpp:203
Copyright (c) 2011-2015 Regents of the University of California.
void wireDecode(const Block &wire)
Decode from the wire format.
Definition: data.cpp:135
size_t prependNonNegativeIntegerBlock(EncodingImpl< TAG > &encoder, uint32_t type, uint64_t value)
Helper to prepend TLV block type type containing non-negative integer value.
uint32_t getContentType() const
Definition: data.hpp:355
EncodingImpl< EstimatorTag > EncodingEstimator
const element_container & elements() const
Get all subelements.
Definition: block.hpp:364
Data & setContent(const uint8_t *buffer, size_t bufferSize)
Set the content from the buffer (buffer will be copied)
Definition: data.cpp:241
Class representing a wire element of NDN-TLV packet format.
Definition: block.hpp:43
uint64_t readNonNegativeInteger(const Block &block)
Helper to read a non-negative integer from a block.
void onChanged()
Clear the wire encoding.
Definition: data.cpp:313
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:50
EncodingImpl< EncoderTag > EncodingBuffer
const Block & get(uint32_t type) const
Get the first subelement of the requested type.
Definition: block.cpp:409
element_container::const_iterator element_const_iterator
Definition: block.hpp:48
size_t elements_size() const
Definition: block.cpp:601
Name abstraction to represent an absolute name.
Definition: name.hpp:46
const Block & wireEncode() const
Encode to a wire format.
Definition: data.cpp:119
void parse() const
Parse wire buffer into subblocks.
Definition: block.cpp:322
uint32_t type() const
Definition: block.hpp:346
const Block & getContent() const
Get content Block.
Definition: data.cpp:230
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:34
represents a Data packet
Definition: data.hpp:39
a concept check for TLV abstraction with .wireDecode method and constructible from Block ...
Definition: concepts.hpp:70
indicates content is another name which identifies actual data content
Definition: tlv.hpp:126
represents an error in TLV encoding or decoding
Definition: tlv.hpp:50
const size_t INVALID_SELECTED_DELEGATION_INDEX
Definition: link.hpp:30