blob: ed7fd6731e5f85cb479a20c255695fb89ff64942 [file] [log] [blame]
Vince Lehmandbf3f702014-07-15 13:00:43 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Davide Pesaventof8503d22017-02-17 01:19:10 -05003 * Copyright (c) 2013-2017 Regents of the University of California.
Vince Lehmandbf3f702014-07-15 13:00:43 -05004 *
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
Junxiao Shi7357ef22016-09-07 02:39:37 +000022#include "rib-entry.hpp"
Junxiao Shi65f1a712014-11-20 14:59:36 -070023#include "encoding/tlv-nfd.hpp"
24#include "encoding/block-helpers.hpp"
25#include "util/concepts.hpp"
Vince Lehmandbf3f702014-07-15 13:00:43 -050026
27namespace ndn {
28namespace nfd {
29
Junxiao Shi65f1a712014-11-20 14:59:36 -070030//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Route>));
31BOOST_CONCEPT_ASSERT((WireEncodable<Route>));
32BOOST_CONCEPT_ASSERT((WireDecodable<Route>));
33static_assert(std::is_base_of<tlv::Error, Route::Error>::value,
34 "Route::Error must inherit from tlv::Error");
35
36//BOOST_CONCEPT_ASSERT((boost::EqualityComparable<RibEntry>));
37BOOST_CONCEPT_ASSERT((WireEncodable<RibEntry>));
38BOOST_CONCEPT_ASSERT((WireDecodable<RibEntry>));
39static_assert(std::is_base_of<tlv::Error, RibEntry::Error>::value,
40 "RibEntry::Error must inherit from tlv::Error");
41
Vince Lehmandbf3f702014-07-15 13:00:43 -050042const time::milliseconds Route::INFINITE_EXPIRATION_PERIOD(time::milliseconds::max());
43
44Route::Route()
Davide Pesaventof8503d22017-02-17 01:19:10 -050045 : m_faceId(INVALID_FACE_ID)
Vince Lehmandbf3f702014-07-15 13:00:43 -050046 , m_origin(0)
47 , m_cost(0)
48 , m_flags(ROUTE_FLAG_CHILD_INHERIT)
49 , m_expirationPeriod(INFINITE_EXPIRATION_PERIOD)
50 , m_hasInfiniteExpirationPeriod(true)
51{
52}
53
54Route::Route(const Block& block)
55{
Davide Pesavento6ad3d532017-02-17 01:43:57 -050056 this->wireDecode(block);
57}
58
59Route&
60Route::setFaceId(uint64_t faceId)
61{
62 m_faceId = faceId;
63 m_wire.reset();
64 return *this;
65}
66
67Route&
68Route::setOrigin(uint64_t origin)
69{
70 m_origin = origin;
71 m_wire.reset();
72 return *this;
73}
74
75Route&
76Route::setCost(uint64_t cost)
77{
78 m_cost = cost;
79 m_wire.reset();
80 return *this;
81}
82
83Route&
84Route::setFlags(uint64_t flags)
85{
86 m_flags = flags;
87 m_wire.reset();
88 return *this;
89}
90
91Route&
92Route::setExpirationPeriod(time::milliseconds expirationPeriod)
93{
94 m_expirationPeriod = expirationPeriod;
95 m_hasInfiniteExpirationPeriod = m_expirationPeriod == INFINITE_EXPIRATION_PERIOD;
96 m_wire.reset();
97 return *this;
Vince Lehmandbf3f702014-07-15 13:00:43 -050098}
99
Alexander Afanasyev74633892015-02-08 18:08:46 -0800100template<encoding::Tag TAG>
Vince Lehmandbf3f702014-07-15 13:00:43 -0500101size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800102Route::wireEncode(EncodingImpl<TAG>& block) const
Vince Lehmandbf3f702014-07-15 13:00:43 -0500103{
104 size_t totalLength = 0;
105
106 // Absence of an ExpirationPeriod signifies non-expiration
107 if (!m_hasInfiniteExpirationPeriod) {
Davide Pesavento6ad3d532017-02-17 01:43:57 -0500108 totalLength += prependNonNegativeIntegerBlock(block, ndn::tlv::nfd::ExpirationPeriod,
109 static_cast<uint64_t>(m_expirationPeriod.count()));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500110 }
Davide Pesavento6ad3d532017-02-17 01:43:57 -0500111 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);
Vince Lehmandbf3f702014-07-15 13:00:43 -0500115
116 totalLength += block.prependVarNumber(totalLength);
117 totalLength += block.prependVarNumber(ndn::tlv::nfd::Route);
Vince Lehmandbf3f702014-07-15 13:00:43 -0500118 return totalLength;
119}
120
121template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800122Route::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block) const;
Vince Lehmandbf3f702014-07-15 13:00:43 -0500123
124template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800125Route::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block) const;
Vince Lehmandbf3f702014-07-15 13:00:43 -0500126
127const Block&
128Route::wireEncode() const
129{
Davide Pesavento6ad3d532017-02-17 01:43:57 -0500130 if (m_wire.hasWire())
Vince Lehmandbf3f702014-07-15 13:00:43 -0500131 return m_wire;
Vince Lehmandbf3f702014-07-15 13:00:43 -0500132
133 EncodingEstimator estimator;
134 size_t estimatedSize = wireEncode(estimator);
135
136 EncodingBuffer buffer(estimatedSize, 0);
137 wireEncode(buffer);
138
139 m_wire = buffer.block();
Vince Lehmandbf3f702014-07-15 13:00:43 -0500140 return m_wire;
141}
142
143void
144Route::wireDecode(const Block& wire)
145{
146 m_faceId = 0;
147 m_origin = 0;
148 m_cost = 0;
149 m_flags = 0;
150 m_expirationPeriod = time::milliseconds::min();
151
152 m_wire = wire;
153
154 if (m_wire.type() != tlv::nfd::Route) {
155 std::stringstream error;
156 error << "Expected Route Block, but Block is of a different type: #"
157 << m_wire.type();
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700158 BOOST_THROW_EXCEPTION(Error(error.str()));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500159 }
160
161 m_wire.parse();
162
163 Block::element_const_iterator val = m_wire.elements_begin();
164
165 if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceId) {
166 m_faceId = readNonNegativeInteger(*val);
167 ++val;
168 }
169 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700170 BOOST_THROW_EXCEPTION(Error("Missing required FaceId field"));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500171 }
172
173 if (val != m_wire.elements_end() && val->type() == tlv::nfd::Origin) {
174 m_origin = readNonNegativeInteger(*val);
175 ++val;
176 }
177 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700178 BOOST_THROW_EXCEPTION(Error("Missing required Origin field"));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500179 }
180
181 if (val != m_wire.elements_end() && val->type() == tlv::nfd::Cost) {
182 m_cost = readNonNegativeInteger(*val);
183 ++val;
184 }
185 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700186 BOOST_THROW_EXCEPTION(Error("Missing required Cost field"));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500187 }
188
189 if (val != m_wire.elements_end() && val->type() == tlv::nfd::Flags) {
190 m_flags = readNonNegativeInteger(*val);
191 ++val;
192 }
193 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700194 BOOST_THROW_EXCEPTION(Error("Missing required Flags field"));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500195 }
196
197 if (val != m_wire.elements_end() && val->type() == tlv::nfd::ExpirationPeriod) {
198 m_expirationPeriod = time::milliseconds(readNonNegativeInteger(*val));
199 m_hasInfiniteExpirationPeriod = false;
200 }
201 else {
202 m_expirationPeriod = INFINITE_EXPIRATION_PERIOD;
203 m_hasInfiniteExpirationPeriod = true;
204 }
205}
206
207std::ostream&
208operator<<(std::ostream& os, const Route& route)
209{
210 os << "Route("
211 << "FaceId: " << route.getFaceId() << ", "
212 << "Origin: " << route.getOrigin() << ", "
213 << "Cost: " << route.getCost() << ", "
214 << "Flags: " << route.getFlags() << ", ";
215
216 if (!route.hasInfiniteExpirationPeriod()) {
217 os << "ExpirationPeriod: " << route.getExpirationPeriod();
218 }
219 else {
220 os << "ExpirationPeriod: Infinity";
221 }
222
223 os << ")";
224
225 return os;
226}
227
Davide Pesavento6ad3d532017-02-17 01:43:57 -0500228////////////////////
Vince Lehmandbf3f702014-07-15 13:00:43 -0500229
Davide Pesavento6ad3d532017-02-17 01:43:57 -0500230RibEntry::RibEntry() = default;
Vince Lehmandbf3f702014-07-15 13:00:43 -0500231
232RibEntry::RibEntry(const Block& block)
233{
Davide Pesavento6ad3d532017-02-17 01:43:57 -0500234 this->wireDecode(block);
Vince Lehmandbf3f702014-07-15 13:00:43 -0500235}
236
Davide Pesavento6ad3d532017-02-17 01:43:57 -0500237RibEntry&
238RibEntry::setName(const Name& prefix)
239{
240 m_prefix = prefix;
241 m_wire.reset();
242 return *this;
243}
244
245RibEntry&
246RibEntry::addRoute(const Route& route)
247{
248 m_routes.push_back(route);
249 m_wire.reset();
250 return *this;
251}
252
253RibEntry&
254RibEntry::clearRoutes()
255{
256 m_routes.clear();
257 m_wire.reset();
258 return *this;
259}
Vince Lehmandbf3f702014-07-15 13:00:43 -0500260
Alexander Afanasyev74633892015-02-08 18:08:46 -0800261template<encoding::Tag TAG>
Vince Lehmandbf3f702014-07-15 13:00:43 -0500262size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800263RibEntry::wireEncode(EncodingImpl<TAG>& block) const
Vince Lehmandbf3f702014-07-15 13:00:43 -0500264{
265 size_t totalLength = 0;
266
267 for (std::list<Route>::const_reverse_iterator it = m_routes.rbegin();
268 it != m_routes.rend(); ++it)
269 {
270 totalLength += it->wireEncode(block);
271 }
272
273 totalLength += m_prefix.wireEncode(block);
274
275 totalLength += block.prependVarNumber(totalLength);
276 totalLength += block.prependVarNumber(tlv::nfd::RibEntry);
Vince Lehmandbf3f702014-07-15 13:00:43 -0500277 return totalLength;
278}
279
280template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800281RibEntry::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block) const;
Vince Lehmandbf3f702014-07-15 13:00:43 -0500282
283template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800284RibEntry::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block) const;
Vince Lehmandbf3f702014-07-15 13:00:43 -0500285
286const Block&
287RibEntry::wireEncode() const
288{
Davide Pesavento6ad3d532017-02-17 01:43:57 -0500289 if (m_wire.hasWire())
Vince Lehmandbf3f702014-07-15 13:00:43 -0500290 return m_wire;
Vince Lehmandbf3f702014-07-15 13:00:43 -0500291
292 EncodingEstimator estimator;
293 size_t estimatedSize = wireEncode(estimator);
294
295 EncodingBuffer buffer(estimatedSize, 0);
296 wireEncode(buffer);
297
298 m_wire = buffer.block();
Vince Lehmandbf3f702014-07-15 13:00:43 -0500299 return m_wire;
300}
301
302void
303RibEntry::wireDecode(const Block& wire)
304{
305 m_prefix.clear();
306 m_routes.clear();
307
308 m_wire = wire;
309
310 if (m_wire.type() != tlv::nfd::RibEntry) {
311 std::stringstream error;
312 error << "Expected RibEntry Block, but Block is of a different type: #"
313 << m_wire.type();
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700314 BOOST_THROW_EXCEPTION(Error(error.str()));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500315 }
316
317 m_wire.parse();
318
319 Block::element_const_iterator val = m_wire.elements_begin();
320
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600321 if (val != m_wire.elements_end() && val->type() == tlv::Name) {
Vince Lehmandbf3f702014-07-15 13:00:43 -0500322 m_prefix.wireDecode(*val);
323 ++val;
324 }
325 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700326 BOOST_THROW_EXCEPTION(Error("Missing required Name field"));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500327 }
328
329 for (; val != m_wire.elements_end(); ++val) {
330
331 if (val->type() == tlv::nfd::Route) {
332 m_routes.push_back(Route(*val));
333 }
334 else {
335 std::stringstream error;
336 error << "Expected Route Block, but Block is of a different type: #"
337 << m_wire.type();
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700338 BOOST_THROW_EXCEPTION(Error(error.str()));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500339 }
340 }
341}
342
343std::ostream&
344operator<<(std::ostream& os, const RibEntry& entry)
345{
346 os << "RibEntry{\n"
347 << " Name: " << entry.getName() << "\n";
348
349 for (RibEntry::iterator it = entry.begin(); it != entry.end(); ++it) {
350 os << " " << *it << "\n";
351 }
352
353 os << "}";
354
355 return os;
356}
357
358} // namespace nfd
359} // namespace ndn