rib-entry.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2017 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 "rib-entry.hpp"
25 #include "encoding/tlv-nfd.hpp"
26 #include "util/concepts.hpp"
27 #include "util/string-helper.hpp"
28 
29 #include <boost/range/adaptor/reversed.hpp>
30 
31 namespace ndn {
32 namespace nfd {
33 
34 BOOST_CONCEPT_ASSERT((StatusDatasetItem<Route>));
35 BOOST_CONCEPT_ASSERT((StatusDatasetItem<RibEntry>));
36 
38  : m_faceId(INVALID_FACE_ID)
39  , m_origin(ROUTE_ORIGIN_APP)
40  , m_cost(0)
41  , m_flags(ROUTE_FLAG_CHILD_INHERIT)
42 {
43 }
44 
45 Route::Route(const Block& block)
46 {
47  this->wireDecode(block);
48 }
49 
50 Route&
51 Route::setFaceId(uint64_t faceId)
52 {
53  m_faceId = faceId;
54  m_wire.reset();
55  return *this;
56 }
57 
58 Route&
60 {
61  m_origin = origin;
62  m_wire.reset();
63  return *this;
64 }
65 
66 Route&
67 Route::setCost(uint64_t cost)
68 {
69  m_cost = cost;
70  m_wire.reset();
71  return *this;
72 }
73 
74 Route&
75 Route::setFlags(uint64_t flags)
76 {
77  m_flags = flags;
78  m_wire.reset();
79  return *this;
80 }
81 
82 Route&
83 Route::setExpirationPeriod(time::milliseconds expirationPeriod)
84 {
85  if (expirationPeriod == time::milliseconds::max())
86  return unsetExpirationPeriod();
87 
88  m_expirationPeriod = expirationPeriod;
89  m_wire.reset();
90  return *this;
91 }
92 
93 Route&
95 {
96  m_expirationPeriod = nullopt;
97  m_wire.reset();
98  return *this;
99 }
100 
101 template<encoding::Tag TAG>
102 size_t
103 Route::wireEncode(EncodingImpl<TAG>& block) const
104 {
105  size_t totalLength = 0;
106 
107  if (m_expirationPeriod) {
109  static_cast<uint64_t>(m_expirationPeriod->count()));
110  }
111  totalLength += prependNonNegativeIntegerBlock(block, ndn::tlv::nfd::Flags, m_flags);
112  totalLength += prependNonNegativeIntegerBlock(block, ndn::tlv::nfd::Cost, m_cost);
113  totalLength += prependNonNegativeIntegerBlock(block, ndn::tlv::nfd::Origin, m_origin);
114  totalLength += prependNonNegativeIntegerBlock(block, ndn::tlv::nfd::FaceId, m_faceId);
115 
116  totalLength += block.prependVarNumber(totalLength);
117  totalLength += block.prependVarNumber(ndn::tlv::nfd::Route);
118  return totalLength;
119 }
120 
122 
123 const Block&
125 {
126  if (m_wire.hasWire())
127  return m_wire;
128 
129  EncodingEstimator estimator;
130  size_t estimatedSize = wireEncode(estimator);
131 
132  EncodingBuffer buffer(estimatedSize, 0);
133  wireEncode(buffer);
134 
135  m_wire = buffer.block();
136  return m_wire;
137 }
138 
139 void
141 {
142  if (block.type() != tlv::nfd::Route) {
143  BOOST_THROW_EXCEPTION(Error("expecting Route, but Block has type " + to_string(block.type())));
144  }
145  m_wire = block;
146  m_wire.parse();
147  Block::element_const_iterator val = m_wire.elements_begin();
148 
149  if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceId) {
150  m_faceId = readNonNegativeInteger(*val);
151  ++val;
152  }
153  else {
154  BOOST_THROW_EXCEPTION(Error("missing required FaceId field"));
155  }
156 
157  if (val != m_wire.elements_end() && val->type() == tlv::nfd::Origin) {
158  m_origin = readNonNegativeIntegerAs<RouteOrigin>(*val);
159  ++val;
160  }
161  else {
162  BOOST_THROW_EXCEPTION(Error("missing required Origin field"));
163  }
164 
165  if (val != m_wire.elements_end() && val->type() == tlv::nfd::Cost) {
166  m_cost = readNonNegativeInteger(*val);
167  ++val;
168  }
169  else {
170  BOOST_THROW_EXCEPTION(Error("missing required Cost field"));
171  }
172 
173  if (val != m_wire.elements_end() && val->type() == tlv::nfd::Flags) {
174  m_flags = readNonNegativeInteger(*val);
175  ++val;
176  }
177  else {
178  BOOST_THROW_EXCEPTION(Error("missing required Flags field"));
179  }
180 
181  if (val != m_wire.elements_end() && val->type() == tlv::nfd::ExpirationPeriod) {
182  m_expirationPeriod.emplace(readNonNegativeInteger(*val));
183  ++val;
184  }
185  else {
186  m_expirationPeriod = nullopt;
187  }
188 }
189 
190 bool
191 operator==(const Route& a, const Route& b)
192 {
193  return a.getFaceId() == b.getFaceId() &&
194  a.getOrigin() == b.getOrigin() &&
195  a.getCost() == b.getCost() &&
196  a.getFlags() == b.getFlags() &&
198 }
199 
200 std::ostream&
201 operator<<(std::ostream& os, const Route& route)
202 {
203  os << "Route("
204  << "FaceId: " << route.getFaceId() << ", "
205  << "Origin: " << route.getOrigin() << ", "
206  << "Cost: " << route.getCost() << ", "
207  << "Flags: " << AsHex{route.getFlags()} << ", ";
208 
209  if (route.hasExpirationPeriod()) {
210  os << "ExpirationPeriod: " << route.getExpirationPeriod();
211  }
212  else {
213  os << "ExpirationPeriod: infinite";
214  }
215 
216  return os << ")";
217 }
218 
220 
221 RibEntry::RibEntry() = default;
222 
224 {
225  this->wireDecode(block);
226 }
227 
228 RibEntry&
229 RibEntry::setName(const Name& prefix)
230 {
231  m_prefix = prefix;
232  m_wire.reset();
233  return *this;
234 }
235 
236 RibEntry&
238 {
239  m_routes.push_back(route);
240  m_wire.reset();
241  return *this;
242 }
243 
244 RibEntry&
246 {
247  m_routes.clear();
248  m_wire.reset();
249  return *this;
250 }
251 
252 template<encoding::Tag TAG>
253 size_t
254 RibEntry::wireEncode(EncodingImpl<TAG>& block) const
255 {
256  size_t totalLength = 0;
257 
258  for (const auto& route : m_routes | boost::adaptors::reversed) {
259  totalLength += route.wireEncode(block);
260  }
261  totalLength += m_prefix.wireEncode(block);
262 
263  totalLength += block.prependVarNumber(totalLength);
264  totalLength += block.prependVarNumber(tlv::nfd::RibEntry);
265  return totalLength;
266 }
267 
269 
270 const Block&
272 {
273  if (m_wire.hasWire())
274  return m_wire;
275 
276  EncodingEstimator estimator;
277  size_t estimatedSize = wireEncode(estimator);
278 
279  EncodingBuffer buffer(estimatedSize, 0);
280  wireEncode(buffer);
281 
282  m_wire = buffer.block();
283  return m_wire;
284 }
285 
286 void
288 {
289  if (block.type() != tlv::nfd::RibEntry) {
290  BOOST_THROW_EXCEPTION(Error("expecting RibEntry, but Block has type " + to_string(block.type())));
291  }
292  m_wire = block;
293  m_wire.parse();
294  Block::element_const_iterator val = m_wire.elements_begin();
295 
296  if (val == m_wire.elements_end()) {
297  BOOST_THROW_EXCEPTION(Error("unexpected end of RibEntry"));
298  }
299  else if (val->type() != tlv::Name) {
300  BOOST_THROW_EXCEPTION(Error("expecting Name, but Block has type " + to_string(val->type())));
301  }
302  m_prefix.wireDecode(*val);
303  ++val;
304 
305  m_routes.clear();
306  for (; val != m_wire.elements_end(); ++val) {
307  if (val->type() != tlv::nfd::Route) {
308  BOOST_THROW_EXCEPTION(Error("expecting Route, but Block has type " + to_string(val->type())));
309  }
310  m_routes.emplace_back(*val);
311  }
312 }
313 
314 bool
315 operator==(const RibEntry& a, const RibEntry& b)
316 {
317  const auto& aRoutes = a.getRoutes();
318  const auto& bRoutes = b.getRoutes();
319 
320  if (a.getName() != b.getName() ||
321  aRoutes.size() != bRoutes.size())
322  return false;
323 
324  std::vector<bool> matched(bRoutes.size(), false);
325  return std::all_of(aRoutes.begin(), aRoutes.end(),
326  [&] (const Route& route) {
327  for (size_t i = 0; i < bRoutes.size(); ++i) {
328  if (!matched[i] && bRoutes[i] == route) {
329  matched[i] = true;
330  return true;
331  }
332  }
333  return false;
334  });
335 }
336 
337 std::ostream&
338 operator<<(std::ostream& os, const RibEntry& entry)
339 {
340  os << "RibEntry(Prefix: " << entry.getName() << ",\n"
341  << " Routes: [";
342 
343  std::copy(entry.getRoutes().begin(), entry.getRoutes().end(),
344  make_ostream_joiner(os, ",\n "));
345 
346  os << "]\n";
347 
348  return os << " )";
349 }
350 
351 } // namespace nfd
352 } // namespace ndn
constexpr nullopt_t nullopt
Copyright (c) 2013-2017 Regents of the University of California.
Definition: common.hpp:66
uint64_t getCost() const
Definition: rib-entry.hpp:79
size_t prependNonNegativeIntegerBlock(EncodingImpl< TAG > &encoder, uint32_t type, uint64_t value)
Prepend a TLV element containing a non-negative integer.
Route & setFlags(uint64_t flags)
Definition: rib-entry.cpp:75
uint64_t getFaceId() const
Definition: rib-entry.hpp:61
element_container::const_iterator element_const_iterator
Definition: block.hpp:47
void wireDecode(const Block &block)
Definition: rib-entry.cpp:287
Route & setOrigin(RouteOrigin origin)
Definition: rib-entry.cpp:59
Helper class to convert a number to hexadecimal format, for use with stream insertion operators...
Represents a TLV element of NDN packet format.
Definition: block.hpp:42
represents a route in a RibEntry
Definition: rib-entry.hpp:42
void wireDecode(const Block &block)
Definition: rib-entry.cpp:140
Route & setCost(uint64_t cost)
Definition: rib-entry.cpp:67
bool hasExpirationPeriod() const
Definition: rib-entry.hpp:97
void emplace(Args &&...args)
uint64_t readNonNegativeInteger(const Block &block)
Read a non-negative integer from a TLV element.
const Name & getName() const
Definition: rib-entry.hpp:176
ostream_joiner< typename std::decay< DelimT >::type, CharT, Traits > make_ostream_joiner(std::basic_ostream< CharT, Traits > &os, DelimT &&delimiter)
BOOST_CONCEPT_ASSERT((StatusDatasetItem< ChannelStatus >))
const Block & wireEncode() const
Definition: rib-entry.cpp:271
time::milliseconds getExpirationPeriod() const
Definition: rib-entry.hpp:103
const std::vector< Route > & getRoutes() const
Definition: rib-entry.hpp:185
uint64_t getFlags() const
Definition: rib-entry.hpp:88
bool operator==(const ChannelStatus &a, const ChannelStatus &b)
#define NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(ClassName)
RibEntry & addRoute(const Route &route)
Definition: rib-entry.cpp:237
size_t size() const
Get number of components.
Definition: name.hpp:154
const Block & wireEncode() const
Definition: rib-entry.cpp:124
std::ostream & operator<<(std::ostream &os, FaceScope faceScope)
void reset()
Reset wire buffer of the element.
Definition: block.cpp:256
Represents an absolute name.
Definition: name.hpp:42
void parse() const
Parse TLV-VALUE into sub elements.
Definition: block.cpp:334
uint32_t type() const
Get TLV-TYPE.
Definition: block.hpp:235
Route & unsetExpirationPeriod()
Definition: rib-entry.cpp:94
bool hasWire() const
Check if the Block has fully encoded wire.
Definition: block.cpp:250
Route & setFaceId(uint64_t faceId)
Definition: rib-entry.cpp:51
RouteOrigin getOrigin() const
Definition: rib-entry.hpp:70
std::string to_string(const V &v)
Definition: backports.hpp:84
Route & setExpirationPeriod(time::milliseconds expirationPeriod)
Definition: rib-entry.cpp:83
RibEntry & setName(const Name &prefix)
Definition: rib-entry.cpp:229
represents an item in NFD RIB dataset
Definition: rib-entry.hpp:157
EncodingImpl< EncoderTag > EncodingBuffer
const uint64_t INVALID_FACE_ID
EncodingImpl< EstimatorTag > EncodingEstimator
RibEntry & clearRoutes()
Definition: rib-entry.cpp:245