blob: 7c056cd4b49b38812c2c702f72df948c2c4cf443 [file] [log] [blame]
Vince Lehmandbf3f702014-07-15 13:00:43 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev74633892015-02-08 18:08:46 -08003 * Copyright (c) 2013-2015 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
22#include "nfd-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()
45 : m_faceId(0)
46 , 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{
56 wireDecode(block);
57}
58
Alexander Afanasyev74633892015-02-08 18:08:46 -080059template<encoding::Tag TAG>
Vince Lehmandbf3f702014-07-15 13:00:43 -050060size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -080061Route::wireEncode(EncodingImpl<TAG>& block) const
Vince Lehmandbf3f702014-07-15 13:00:43 -050062{
63 size_t totalLength = 0;
64
65 // Absence of an ExpirationPeriod signifies non-expiration
66 if (!m_hasInfiniteExpirationPeriod) {
67 totalLength += prependNonNegativeIntegerBlock(block,
68 ndn::tlv::nfd::ExpirationPeriod,
69 m_expirationPeriod.count());
70 }
71
72 totalLength += prependNonNegativeIntegerBlock(block,
73 ndn::tlv::nfd::Flags,
74 m_flags);
75
76 totalLength += prependNonNegativeIntegerBlock(block,
77 ndn::tlv::nfd::Cost,
78 m_cost);
79
80 totalLength += prependNonNegativeIntegerBlock(block,
81 ndn::tlv::nfd::Origin,
82 m_origin);
83
84 totalLength += prependNonNegativeIntegerBlock(block,
85 ndn::tlv::nfd::FaceId,
86 m_faceId);
87
88 totalLength += block.prependVarNumber(totalLength);
89 totalLength += block.prependVarNumber(ndn::tlv::nfd::Route);
90
91 return totalLength;
92}
93
94template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -080095Route::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block) const;
Vince Lehmandbf3f702014-07-15 13:00:43 -050096
97template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -080098Route::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block) const;
Vince Lehmandbf3f702014-07-15 13:00:43 -050099
100const Block&
101Route::wireEncode() const
102{
103 if (m_wire.hasWire()) {
104 return m_wire;
105 }
106
107 EncodingEstimator estimator;
108 size_t estimatedSize = wireEncode(estimator);
109
110 EncodingBuffer buffer(estimatedSize, 0);
111 wireEncode(buffer);
112
113 m_wire = buffer.block();
114
115 return m_wire;
116}
117
118void
119Route::wireDecode(const Block& wire)
120{
121 m_faceId = 0;
122 m_origin = 0;
123 m_cost = 0;
124 m_flags = 0;
125 m_expirationPeriod = time::milliseconds::min();
126
127 m_wire = wire;
128
129 if (m_wire.type() != tlv::nfd::Route) {
130 std::stringstream error;
131 error << "Expected Route Block, but Block is of a different type: #"
132 << m_wire.type();
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700133 BOOST_THROW_EXCEPTION(Error(error.str()));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500134 }
135
136 m_wire.parse();
137
138 Block::element_const_iterator val = m_wire.elements_begin();
139
140 if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceId) {
141 m_faceId = readNonNegativeInteger(*val);
142 ++val;
143 }
144 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700145 BOOST_THROW_EXCEPTION(Error("Missing required FaceId field"));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500146 }
147
148 if (val != m_wire.elements_end() && val->type() == tlv::nfd::Origin) {
149 m_origin = readNonNegativeInteger(*val);
150 ++val;
151 }
152 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700153 BOOST_THROW_EXCEPTION(Error("Missing required Origin field"));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500154 }
155
156 if (val != m_wire.elements_end() && val->type() == tlv::nfd::Cost) {
157 m_cost = readNonNegativeInteger(*val);
158 ++val;
159 }
160 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700161 BOOST_THROW_EXCEPTION(Error("Missing required Cost field"));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500162 }
163
164 if (val != m_wire.elements_end() && val->type() == tlv::nfd::Flags) {
165 m_flags = readNonNegativeInteger(*val);
166 ++val;
167 }
168 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700169 BOOST_THROW_EXCEPTION(Error("Missing required Flags field"));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500170 }
171
172 if (val != m_wire.elements_end() && val->type() == tlv::nfd::ExpirationPeriod) {
173 m_expirationPeriod = time::milliseconds(readNonNegativeInteger(*val));
174 m_hasInfiniteExpirationPeriod = false;
175 }
176 else {
177 m_expirationPeriod = INFINITE_EXPIRATION_PERIOD;
178 m_hasInfiniteExpirationPeriod = true;
179 }
180}
181
182std::ostream&
183operator<<(std::ostream& os, const Route& route)
184{
185 os << "Route("
186 << "FaceId: " << route.getFaceId() << ", "
187 << "Origin: " << route.getOrigin() << ", "
188 << "Cost: " << route.getCost() << ", "
189 << "Flags: " << route.getFlags() << ", ";
190
191 if (!route.hasInfiniteExpirationPeriod()) {
192 os << "ExpirationPeriod: " << route.getExpirationPeriod();
193 }
194 else {
195 os << "ExpirationPeriod: Infinity";
196 }
197
198 os << ")";
199
200 return os;
201}
202
203
204//////////////////////////////////////////////////////////////////////
205//////////////////////////////////////////////////////////////////////
206//////////////////////////////////////////////////////////////////////
207
208
209RibEntry::RibEntry()
210{
211}
212
213RibEntry::RibEntry(const Block& block)
214{
215 wireDecode(block);
216}
217
218
Alexander Afanasyev74633892015-02-08 18:08:46 -0800219template<encoding::Tag TAG>
Vince Lehmandbf3f702014-07-15 13:00:43 -0500220size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800221RibEntry::wireEncode(EncodingImpl<TAG>& block) const
Vince Lehmandbf3f702014-07-15 13:00:43 -0500222{
223 size_t totalLength = 0;
224
225 for (std::list<Route>::const_reverse_iterator it = m_routes.rbegin();
226 it != m_routes.rend(); ++it)
227 {
228 totalLength += it->wireEncode(block);
229 }
230
231 totalLength += m_prefix.wireEncode(block);
232
233 totalLength += block.prependVarNumber(totalLength);
234 totalLength += block.prependVarNumber(tlv::nfd::RibEntry);
235
236 return totalLength;
237}
238
239template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800240RibEntry::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& block) const;
Vince Lehmandbf3f702014-07-15 13:00:43 -0500241
242template size_t
Alexander Afanasyev74633892015-02-08 18:08:46 -0800243RibEntry::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& block) const;
Vince Lehmandbf3f702014-07-15 13:00:43 -0500244
245const Block&
246RibEntry::wireEncode() const
247{
248 if (m_wire.hasWire()) {
249 return m_wire;
250 }
251
252 EncodingEstimator estimator;
253 size_t estimatedSize = wireEncode(estimator);
254
255 EncodingBuffer buffer(estimatedSize, 0);
256 wireEncode(buffer);
257
258 m_wire = buffer.block();
259
260 return m_wire;
261}
262
263void
264RibEntry::wireDecode(const Block& wire)
265{
266 m_prefix.clear();
267 m_routes.clear();
268
269 m_wire = wire;
270
271 if (m_wire.type() != tlv::nfd::RibEntry) {
272 std::stringstream error;
273 error << "Expected RibEntry Block, but Block is of a different type: #"
274 << m_wire.type();
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700275 BOOST_THROW_EXCEPTION(Error(error.str()));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500276 }
277
278 m_wire.parse();
279
280 Block::element_const_iterator val = m_wire.elements_begin();
281
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600282 if (val != m_wire.elements_end() && val->type() == tlv::Name) {
Vince Lehmandbf3f702014-07-15 13:00:43 -0500283 m_prefix.wireDecode(*val);
284 ++val;
285 }
286 else {
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700287 BOOST_THROW_EXCEPTION(Error("Missing required Name field"));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500288 }
289
290 for (; val != m_wire.elements_end(); ++val) {
291
292 if (val->type() == tlv::nfd::Route) {
293 m_routes.push_back(Route(*val));
294 }
295 else {
296 std::stringstream error;
297 error << "Expected Route Block, but Block is of a different type: #"
298 << m_wire.type();
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700299 BOOST_THROW_EXCEPTION(Error(error.str()));
Vince Lehmandbf3f702014-07-15 13:00:43 -0500300 }
301 }
302}
303
304std::ostream&
305operator<<(std::ostream& os, const RibEntry& entry)
306{
307 os << "RibEntry{\n"
308 << " Name: " << entry.getName() << "\n";
309
310 for (RibEntry::iterator it = entry.begin(); it != entry.end(); ++it) {
311 os << " " << *it << "\n";
312 }
313
314 os << "}";
315
316 return os;
317}
318
319} // namespace nfd
320} // namespace ndn