blob: d075cc600df1baf2801db0796aebd232797ec5c4 [file] [log] [blame]
Vince Lehmandbf3f702014-07-15 13:00:43 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2014 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 "nfd-rib-entry.hpp"
23
24#include "management/nfd-control-command.hpp"
25
26namespace ndn {
27namespace nfd {
28
29const time::milliseconds Route::INFINITE_EXPIRATION_PERIOD(time::milliseconds::max());
30
31Route::Route()
32 : m_faceId(0)
33 , m_origin(0)
34 , m_cost(0)
35 , m_flags(ROUTE_FLAG_CHILD_INHERIT)
36 , m_expirationPeriod(INFINITE_EXPIRATION_PERIOD)
37 , m_hasInfiniteExpirationPeriod(true)
38{
39}
40
41Route::Route(const Block& block)
42{
43 wireDecode(block);
44}
45
46template<bool T>
47size_t
48Route::wireEncode(EncodingImpl<T>& block) const
49{
50 size_t totalLength = 0;
51
52 // Absence of an ExpirationPeriod signifies non-expiration
53 if (!m_hasInfiniteExpirationPeriod) {
54 totalLength += prependNonNegativeIntegerBlock(block,
55 ndn::tlv::nfd::ExpirationPeriod,
56 m_expirationPeriod.count());
57 }
58
59 totalLength += prependNonNegativeIntegerBlock(block,
60 ndn::tlv::nfd::Flags,
61 m_flags);
62
63 totalLength += prependNonNegativeIntegerBlock(block,
64 ndn::tlv::nfd::Cost,
65 m_cost);
66
67 totalLength += prependNonNegativeIntegerBlock(block,
68 ndn::tlv::nfd::Origin,
69 m_origin);
70
71 totalLength += prependNonNegativeIntegerBlock(block,
72 ndn::tlv::nfd::FaceId,
73 m_faceId);
74
75 totalLength += block.prependVarNumber(totalLength);
76 totalLength += block.prependVarNumber(ndn::tlv::nfd::Route);
77
78 return totalLength;
79}
80
81template size_t
82Route::wireEncode<true>(EncodingImpl<true>& block) const;
83
84template size_t
85Route::wireEncode<false>(EncodingImpl<false>& block) const;
86
87const Block&
88Route::wireEncode() const
89{
90 if (m_wire.hasWire()) {
91 return m_wire;
92 }
93
94 EncodingEstimator estimator;
95 size_t estimatedSize = wireEncode(estimator);
96
97 EncodingBuffer buffer(estimatedSize, 0);
98 wireEncode(buffer);
99
100 m_wire = buffer.block();
101
102 return m_wire;
103}
104
105void
106Route::wireDecode(const Block& wire)
107{
108 m_faceId = 0;
109 m_origin = 0;
110 m_cost = 0;
111 m_flags = 0;
112 m_expirationPeriod = time::milliseconds::min();
113
114 m_wire = wire;
115
116 if (m_wire.type() != tlv::nfd::Route) {
117 std::stringstream error;
118 error << "Expected Route Block, but Block is of a different type: #"
119 << m_wire.type();
120 throw Error(error.str());
121 }
122
123 m_wire.parse();
124
125 Block::element_const_iterator val = m_wire.elements_begin();
126
127 if (val != m_wire.elements_end() && val->type() == tlv::nfd::FaceId) {
128 m_faceId = readNonNegativeInteger(*val);
129 ++val;
130 }
131 else {
132 throw Error("Missing required FaceId field");
133 }
134
135 if (val != m_wire.elements_end() && val->type() == tlv::nfd::Origin) {
136 m_origin = readNonNegativeInteger(*val);
137 ++val;
138 }
139 else {
140 throw Error("Missing required Origin field");
141 }
142
143 if (val != m_wire.elements_end() && val->type() == tlv::nfd::Cost) {
144 m_cost = readNonNegativeInteger(*val);
145 ++val;
146 }
147 else {
148 throw Error("Missing required Cost field");
149 }
150
151 if (val != m_wire.elements_end() && val->type() == tlv::nfd::Flags) {
152 m_flags = readNonNegativeInteger(*val);
153 ++val;
154 }
155 else {
156 throw Error("Missing required Flags field");
157 }
158
159 if (val != m_wire.elements_end() && val->type() == tlv::nfd::ExpirationPeriod) {
160 m_expirationPeriod = time::milliseconds(readNonNegativeInteger(*val));
161 m_hasInfiniteExpirationPeriod = false;
162 }
163 else {
164 m_expirationPeriod = INFINITE_EXPIRATION_PERIOD;
165 m_hasInfiniteExpirationPeriod = true;
166 }
167}
168
169std::ostream&
170operator<<(std::ostream& os, const Route& route)
171{
172 os << "Route("
173 << "FaceId: " << route.getFaceId() << ", "
174 << "Origin: " << route.getOrigin() << ", "
175 << "Cost: " << route.getCost() << ", "
176 << "Flags: " << route.getFlags() << ", ";
177
178 if (!route.hasInfiniteExpirationPeriod()) {
179 os << "ExpirationPeriod: " << route.getExpirationPeriod();
180 }
181 else {
182 os << "ExpirationPeriod: Infinity";
183 }
184
185 os << ")";
186
187 return os;
188}
189
190
191//////////////////////////////////////////////////////////////////////
192//////////////////////////////////////////////////////////////////////
193//////////////////////////////////////////////////////////////////////
194
195
196RibEntry::RibEntry()
197{
198}
199
200RibEntry::RibEntry(const Block& block)
201{
202 wireDecode(block);
203}
204
205
206template<bool T>
207size_t
208RibEntry::wireEncode(EncodingImpl<T>& block) const
209{
210 size_t totalLength = 0;
211
212 for (std::list<Route>::const_reverse_iterator it = m_routes.rbegin();
213 it != m_routes.rend(); ++it)
214 {
215 totalLength += it->wireEncode(block);
216 }
217
218 totalLength += m_prefix.wireEncode(block);
219
220 totalLength += block.prependVarNumber(totalLength);
221 totalLength += block.prependVarNumber(tlv::nfd::RibEntry);
222
223 return totalLength;
224}
225
226template size_t
227RibEntry::wireEncode<true>(EncodingImpl<true>& block) const;
228
229template size_t
230RibEntry::wireEncode<false>(EncodingImpl<false>& block) const;
231
232const Block&
233RibEntry::wireEncode() const
234{
235 if (m_wire.hasWire()) {
236 return m_wire;
237 }
238
239 EncodingEstimator estimator;
240 size_t estimatedSize = wireEncode(estimator);
241
242 EncodingBuffer buffer(estimatedSize, 0);
243 wireEncode(buffer);
244
245 m_wire = buffer.block();
246
247 return m_wire;
248}
249
250void
251RibEntry::wireDecode(const Block& wire)
252{
253 m_prefix.clear();
254 m_routes.clear();
255
256 m_wire = wire;
257
258 if (m_wire.type() != tlv::nfd::RibEntry) {
259 std::stringstream error;
260 error << "Expected RibEntry Block, but Block is of a different type: #"
261 << m_wire.type();
262 throw Error(error.str());
263 }
264
265 m_wire.parse();
266
267 Block::element_const_iterator val = m_wire.elements_begin();
268
269 if (val != m_wire.elements_end() && val->type() == Tlv::Name) {
270 m_prefix.wireDecode(*val);
271 ++val;
272 }
273 else {
274 throw Error("Missing required Name field");
275 }
276
277 for (; val != m_wire.elements_end(); ++val) {
278
279 if (val->type() == tlv::nfd::Route) {
280 m_routes.push_back(Route(*val));
281 }
282 else {
283 std::stringstream error;
284 error << "Expected Route Block, but Block is of a different type: #"
285 << m_wire.type();
286 throw Error(error.str());
287 }
288 }
289}
290
291std::ostream&
292operator<<(std::ostream& os, const RibEntry& entry)
293{
294 os << "RibEntry{\n"
295 << " Name: " << entry.getName() << "\n";
296
297 for (RibEntry::iterator it = entry.begin(); it != entry.end(); ++it) {
298 os << " " << *it << "\n";
299 }
300
301 os << "}";
302
303 return os;
304}
305
306} // namespace nfd
307} // namespace ndn