NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
delegation-list.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 
24 
25 namespace ndn {
26 
27 BOOST_CONCEPT_ASSERT((boost::EqualityComparable<DelegationList>));
29 BOOST_CONCEPT_ASSERT((WireDecodable<DelegationList>));
30 
32  : m_isSorted(true)
33 {
34 }
35 
36 DelegationList::DelegationList(std::initializer_list<Delegation> dels)
37  : m_isSorted(true)
38 {
39  for (const Delegation& del : dels) {
40  this->insert(del, INS_REPLACE);
41  }
42 }
43 
44 DelegationList::DelegationList(const Block& block, bool wantSort)
45 {
46  this->wireDecode(block, wantSort);
47 }
48 
49 bool
50 DelegationList::isValidTlvType(uint32_t type)
51 {
52  switch (type) {
53  case tlv::Content:
55  return true;
56  default:
57  return false;
58  }
59 }
60 
61 template<encoding::Tag TAG>
62 size_t
63 DelegationList::wireEncode(EncodingImpl<TAG>& encoder, uint32_t type) const
64 {
65  if (!isValidTlvType(type)) {
66  NDN_THROW(std::invalid_argument("Unexpected TLV-TYPE " + to_string(type) +
67  " while encoding DelegationList"));
68  }
69 
70  if (this->size() == 0) {
71  NDN_THROW(Error("Empty DelegationList"));
72  }
73 
74  // LinkContent ::= (type) TLV-LENGTH
75  // Delegation+
76 
77  // Delegation ::= LINK-DELEGATION-TYPE TLV-LENGTH
78  // Preference
79  // Name
80 
81  // Preference ::= LINK-PREFERENCE-TYPE TLV-LENGTH
82  // nonNegativeInteger
83 
84  size_t totalLen = 0;
85  for (auto i = m_dels.rbegin(); i != m_dels.rend(); ++i) {
86  size_t delLen = 0;
87  delLen += i->name.wireEncode(encoder);
88  delLen += prependNonNegativeIntegerBlock(encoder, tlv::LinkPreference, i->preference);
89  delLen += encoder.prependVarNumber(delLen);
90  delLen += encoder.prependVarNumber(tlv::LinkDelegation);
91  totalLen += delLen;
92  }
93  totalLen += encoder.prependVarNumber(totalLen);
94  totalLen += encoder.prependVarNumber(type);
95  return totalLen;
96 }
97 
98 template size_t
99 DelegationList::wireEncode<encoding::EncoderTag>(EncodingBuffer&, uint32_t) const;
100 
101 template size_t
102 DelegationList::wireEncode<encoding::EstimatorTag>(EncodingEstimator&, uint32_t) const;
103 
104 void
105 DelegationList::wireDecode(const Block& block, bool wantSort)
106 {
107  if (!isValidTlvType(block.type())) {
108  NDN_THROW(Error("Unexpected TLV-TYPE " + to_string(block.type()) + " while decoding DelegationList"));
109  }
110 
111  m_isSorted = wantSort;
112  m_dels.clear();
113 
114  block.parse();
115  for (const auto& del : block.elements()) {
116  if (del.type() != tlv::LinkDelegation) {
117  NDN_THROW(Error("Unexpected TLV-TYPE " + to_string(del.type()) + " while decoding Delegation"));
118  }
119  del.parse();
120 
121  auto val = del.elements_begin();
122  if (val == del.elements_end() || val->type() != tlv::LinkPreference) {
123  NDN_THROW(Error("Missing Preference field in Delegation"));
124  }
125  uint64_t preference = 0;
126  try {
127  preference = readNonNegativeInteger(*val);
128  }
129  catch (const tlv::Error&) {
130  NDN_THROW_NESTED(Error("Invalid Preference field in Delegation"));
131  }
132 
133  ++val;
134  if (val == del.elements_end() || val->type() != tlv::Name) {
135  NDN_THROW(Error("Missing Name field in Delegation"));
136  }
137  Name name;
138  try {
139  name.wireDecode(*val);
140  }
141  catch (const tlv::Error&) {
142  NDN_THROW_NESTED(Error("Invalid Name field in Delegation"));
143  }
144 
145  this->insertImpl(preference, name);
146  }
147 
148  if (this->size() == 0) {
149  NDN_THROW(Error("Empty DelegationList"));
150  }
151 }
152 
153 void
155 {
156  if (m_isSorted) {
157  return;
158  }
159 
160  std::vector<Delegation> dels;
161  dels.swap(m_dels);
162 
163  m_isSorted = true;
164  for (const Delegation& del : dels) {
165  this->insertImpl(del.preference, del.name);
166  }
167 }
168 
169 bool
170 DelegationList::insert(uint64_t preference, const Name& name,
171  InsertConflictResolution onConflict)
172 {
173  switch (onConflict) {
174  case INS_REPLACE:
175  this->eraseImpl(nullopt, name);
176  this->insertImpl(preference, name);
177  return true;
178  case INS_APPEND:
179  this->insertImpl(preference, name);
180  return true;
181  case INS_SKIP:
182  if (!std::any_of(m_dels.begin(), m_dels.end(),
183  [name] (const Delegation& del) { return del.name == name; })) {
184  this->insertImpl(preference, name);
185  return true;
186  }
187  return false;
188  }
189 
190  NDN_THROW(std::invalid_argument("Unknown InsertConflictResolution"));
191 }
192 
193 void
194 DelegationList::insertImpl(uint64_t preference, const Name& name)
195 {
196  if (!m_isSorted) {
197  m_dels.push_back({preference, name});
198  return;
199  }
200 
201  Delegation del{preference, name};
202  auto pos = std::upper_bound(m_dels.begin(), m_dels.end(), del);
203  m_dels.insert(pos, del);
204 }
205 
206 size_t
207 DelegationList::eraseImpl(optional<uint64_t> preference, const Name& name)
208 {
209  size_t nErased = 0;
210  for (auto i = m_dels.begin(); i != m_dels.end();) {
211  if ((!preference || i->preference == *preference) &&
212  i->name == name) {
213  ++nErased;
214  i = m_dels.erase(i);
215  }
216  else {
217  ++i;
218  }
219  }
220  return nErased;
221 }
222 
223 std::ostream&
224 operator<<(std::ostream& os, const DelegationList& dl)
225 {
226  os << '[';
227  std::copy(dl.begin(), dl.end(), make_ostream_joiner(os, ','));
228  return os << ']';
229 }
230 
231 } // namespace ndn
ndn::Block::elements
const element_container & elements() const
Get container of sub-elements.
Definition: block.hpp:391
ndn::DelegationList::size
size_t size() const noexcept
Definition: delegation-list.hpp:108
ndn::DelegationList::wireEncode
size_t wireEncode(EncodingImpl< TAG > &encoder, uint32_t type=tlv::ForwardingHint) const
encode into wire format
Definition: delegation-list.cpp:63
ndn::tlv::ForwardingHint
@ ForwardingHint
Definition: tlv.hpp:73
ndn::DelegationList::INS_APPEND
@ INS_APPEND
multiple delegations with the same name are kept in the DelegationList
Definition: delegation-list.hpp:158
ndn::DelegationList::DelegationList
DelegationList()
construct an empty DelegationList
Definition: delegation-list.cpp:31
ndn::DelegationList::INS_SKIP
@ INS_SKIP
new delegation is not inserted if an existing delegation has the same name
Definition: delegation-list.hpp:162
ndn::DelegationList::Error
Definition: delegation-list.hpp:41
NDN_THROW_NESTED
#define NDN_THROW_NESTED(e)
Definition: exception.hpp:71
ndn::make_ostream_joiner
ostream_joiner< std::decay_t< DelimT >, CharT, Traits > make_ostream_joiner(std::basic_ostream< CharT, Traits > &os, DelimT &&delimiter)
Definition: ostream-joiner.hpp:117
ndn::DelegationList::InsertConflictResolution
InsertConflictResolution
what to do when inserting a duplicate name
Definition: delegation-list.hpp:150
ndn::WireDecodable
a concept check for TLV abstraction with .wireDecode method and constructible from Block
Definition: concepts.hpp:81
ndn::encoding::EncodingEstimator
EncodingImpl< EstimatorTag > EncodingEstimator
Definition: encoding-buffer-fwd.hpp:39
ndn::Delegation
Represents a Delegation.
Definition: delegation.hpp:33
ndn::encoding::readNonNegativeInteger
uint64_t readNonNegativeInteger(const Block &block)
Read a non-negative integer from a TLV element.
Definition: block-helpers.cpp:64
ndn::DelegationList::sort
void sort()
sort the delegation list
Definition: delegation-list.cpp:154
ndn::Name
Represents an absolute name.
Definition: name.hpp:44
ndn::DelegationList::insert
bool insert(uint64_t preference, const Name &name, InsertConflictResolution onConflict=INS_REPLACE)
insert Delegation
Definition: delegation-list.cpp:170
ns3::ndn::Name
Name
Definition: ndn-common.cpp:25
ndn::Block::type
uint32_t type() const
Return the TLV-TYPE of the Block.
Definition: block.hpp:274
ostream-joiner.hpp
Backport of ostream_joiner from the Library Fundamentals v2 TS.
NDN_THROW
#define NDN_THROW(e)
Definition: exception.hpp:61
ndn::DelegationList::end
const_iterator end() const noexcept
Definition: delegation-list.hpp:96
nonstd::optional_lite::nullopt
const nullopt_t nullopt((nullopt_t::init()))
ndn::tlv::LinkPreference
@ LinkPreference
Definition: tlv.hpp:89
ndn::tlv::Name
@ Name
Definition: tlv.hpp:67
ndn::DelegationList
represents a list of Delegations
Definition: delegation-list.hpp:38
ndn::Block::parse
void parse() const
Parse TLV-VALUE into sub-elements.
Definition: block.cpp:325
ndn::encoding::prependNonNegativeIntegerBlock
size_t prependNonNegativeIntegerBlock(EncodingImpl< TAG > &encoder, uint32_t type, uint64_t value)
Prepend a TLV element containing a non-negative integer.
Definition: block-helpers.cpp:35
ndn::DelegationList::INS_REPLACE
@ INS_REPLACE
existing delegation(s) with the same name are replaced with the new delegation
Definition: delegation-list.hpp:153
ndn::encoding::EncodingImpl
Definition: encoding-buffer-fwd.hpp:36
ndn::Block
Represents a TLV element of NDN packet format.
Definition: block.hpp:43
ndn::to_string
std::string to_string(const T &val)
Definition: backports.hpp:102
ndn::operator<<
std::ostream & operator<<(std::ostream &os, const Data &data)
Definition: data.cpp:322
ndn::name
Definition: name-component-types.hpp:33
delegation-list.hpp
ndn::tlv::Error
represents an error in TLV encoding or decoding
Definition: tlv.hpp:53
ndn::DelegationList::wireDecode
void wireDecode(const Block &block, bool wantSort=true)
decode a DelegationList
Definition: delegation-list.cpp:105
ndn::tlv::LinkDelegation
@ LinkDelegation
Definition: tlv.hpp:88
ndn::DelegationList::begin
const_iterator begin() const noexcept
Definition: delegation-list.hpp:90
ndn::WireEncodableWithEncodingBuffer
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:61
ndn
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-strategy-choice-helper.hpp:34
ndn::encoding::EncodingBuffer
EncodingImpl< EncoderTag > EncodingBuffer
Definition: encoding-buffer-fwd.hpp:38
ndn::tlv::Content
@ Content
Definition: tlv.hpp:79