blob: 015beba42b7b683f72820c9fc88c979ad11c9acd [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Steve DiBenedetto6d792d72014-03-15 19:01:36 -06002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * 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.
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060020 */
21
22#ifndef NDN_MANAGEMENT_NFD_FIB_ENTRY_HPP
23#define NDN_MANAGEMENT_NFD_FIB_ENTRY_HPP
24
25#include "../encoding/block.hpp"
Alexander Afanasyev15f67312014-07-22 15:11:09 -070026#include "../encoding/block-helpers.hpp"
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060027#include "../encoding/encoding-buffer.hpp"
28#include "../encoding/tlv-nfd.hpp"
29#include "../name.hpp"
30
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070031#include <list>
Alexander Afanasyev15f67312014-07-22 15:11:09 -070032#include <sstream>
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070033
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060034namespace ndn {
35namespace nfd {
36
37// NextHopRecord := NEXT-HOP-RECORD TLV-LENGTH
38// FaceId
39// Cost
40
Alexander Afanasyev4671bf72014-05-19 09:01:37 -040041/**
42 * @ingroup management
43 */
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060044class NextHopRecord
45{
46public:
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060047 class Error : public tlv::Error
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060048 {
49 public:
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060050 Error(const std::string& what) : tlv::Error(what) {}
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060051 };
52
53 NextHopRecord()
54 : m_faceId(std::numeric_limits<uint64_t>::max())
55 , m_cost(0)
56 {
57 }
58
Alexander Afanasyev44b438a2014-03-19 12:51:49 -070059 explicit
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060060 NextHopRecord(const Block& block)
61 {
62 wireDecode(block);
63 }
64
65 uint64_t
66 getFaceId() const
67 {
68 return m_faceId;
69 }
70
71 NextHopRecord&
72 setFaceId(uint64_t faceId)
73 {
74 m_faceId = faceId;
75 m_wire.reset();
76 return *this;
77 }
78
79 uint64_t
80 getCost() const
81 {
82 return m_cost;
83 }
84
85 NextHopRecord&
86 setCost(uint64_t cost)
87 {
88 m_cost = cost;
89 m_wire.reset();
90 return *this;
91 }
92
93 template<bool T>
94 size_t
95 wireEncode(EncodingImpl<T>& block) const
96 {
97 size_t totalLength = 0;
98 totalLength += prependNonNegativeIntegerBlock(block,
99 ndn::tlv::nfd::Cost,
100 m_cost);
101
102 totalLength += prependNonNegativeIntegerBlock(block,
103 ndn::tlv::nfd::FaceId,
104 m_faceId);
105
106 totalLength += block.prependVarNumber(totalLength);
107 totalLength += block.prependVarNumber(ndn::tlv::nfd::NextHopRecord);
108 return totalLength;
109 }
110
111 const Block&
112 wireEncode() const
113 {
114 if (m_wire.hasWire())
115 {
116 return m_wire;
117 }
118
119 EncodingEstimator estimator;
120 size_t estimatedSize = wireEncode(estimator);
121
122 EncodingBuffer buffer(estimatedSize, 0);
123 wireEncode(buffer);
124
125 m_wire = buffer.block();
126 return m_wire;
127 }
128
129 void
130 wireDecode(const Block& wire)
131 {
132 m_faceId = std::numeric_limits<uint64_t>::max();
133 m_cost = 0;
134
135 m_wire = wire;
136
137 if (m_wire.type() != tlv::nfd::NextHopRecord)
138 {
139 std::stringstream error;
140 error << "Requested decoding of NextHopRecord, but Block is of a different type: #"
141 << m_wire.type();
142 throw Error(error.str());
143 }
144 m_wire.parse();
145
146 Block::element_const_iterator val = m_wire.elements_begin();
147 if (val == m_wire.elements_end())
148 {
149 throw Error("Unexpected end of NextHopRecord");
150 }
151 else if (val->type() != tlv::nfd::FaceId)
152 {
153 std::stringstream error;
154 error << "Expected FaceId, but Block is of a different type: #"
155 << val->type();
156 throw Error(error.str());
157 }
158 m_faceId = readNonNegativeInteger(*val);
159 ++val;
160
161 if (val == m_wire.elements_end())
162 {
163 throw Error("Unexpected end of NextHopRecord");
164 }
165 else if (val->type() != tlv::nfd::Cost)
166 {
167 std::stringstream error;
168 error << "Expected Cost, but Block is of a different type: #"
Alexander Afanasyev1c5a1a92014-03-21 13:32:36 -0700169 << m_wire.type();
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600170 throw Error(error.str());
171 }
172 m_cost = readNonNegativeInteger(*val);
173 }
174
175
176private:
177 uint64_t m_faceId;
178 uint64_t m_cost;
179
180 mutable Block m_wire;
181};
182
183
184// FibEntry := FIB-ENTRY-TYPE TLV-LENGTH
185// Name
186// NextHopRecord*
187
Alexander Afanasyev4671bf72014-05-19 09:01:37 -0400188/**
189 * @ingroup management
190 */
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600191class FibEntry
192{
193public:
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600194 class Error : public tlv::Error
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600195 {
196 public:
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600197 Error(const std::string& what) : tlv::Error(what)
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600198 {
199 }
200 };
201
202 FibEntry()
203 {
Alexander Afanasyev44b438a2014-03-19 12:51:49 -0700204 }
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600205
Alexander Afanasyev44b438a2014-03-19 12:51:49 -0700206 explicit
207 FibEntry(const Block& block)
208 {
209 wireDecode(block);
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600210 }
211
212 const Name&
213 getPrefix() const
214 {
215 return m_prefix;
216 }
217
218 FibEntry&
219 setPrefix(const Name& prefix)
220 {
221 m_prefix = prefix;
222 m_wire.reset();
223 return *this;
224 }
225
226 const std::list<NextHopRecord>&
227 getNextHopRecords() const
228 {
229 return m_nextHopRecords;
230 }
231
232 FibEntry&
233 addNextHopRecord(const NextHopRecord& nextHopRecord)
234 {
235 m_nextHopRecords.push_back(nextHopRecord);
236 m_wire.reset();
237 return *this;
238 }
239
240 template<typename T>
241 FibEntry&
242 setNextHopRecords(const T& begin, const T& end)
243 {
244 m_nextHopRecords.clear();
245 m_nextHopRecords.assign(begin, end);
246 m_wire.reset();
247 return *this;
248 }
249
250 template<bool T>
251 size_t
252 wireEncode(EncodingImpl<T>& block) const
253 {
254 size_t totalLength = 0;
255
Alexander Afanasyev1c5a1a92014-03-21 13:32:36 -0700256 for (std::list<NextHopRecord>::const_reverse_iterator i = m_nextHopRecords.rbegin();
257 i != m_nextHopRecords.rend();
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600258 ++i)
259 {
260 totalLength += i->wireEncode(block);
261 }
262
263 totalLength += m_prefix.wireEncode(block);
264 totalLength += block.prependVarNumber(totalLength);
265 totalLength += block.prependVarNumber(tlv::nfd::FibEntry);
266
267 return totalLength;
268 }
269
270 const Block&
271 wireEncode() const
272 {
273 if (m_wire.hasWire())
274 {
275 return m_wire;
276 }
277
278 EncodingEstimator estimator;
279 size_t estimatedSize = wireEncode(estimator);
280
281 EncodingBuffer buffer(estimatedSize, 0);
282 wireEncode(buffer);
283
284 m_wire = buffer.block();
285
286 return m_wire;
287 }
288
289 void
290 wireDecode(const Block& wire)
291 {
292 m_prefix.clear();
293 m_nextHopRecords.clear();
294
295 m_wire = wire;
296
297 if (m_wire.type() != tlv::nfd::FibEntry)
298 {
299 std::stringstream error;
300 error << "Requested decoding of FibEntry, but Block is of a different type: #"
301 << m_wire.type();
302 throw Error(error.str());
303 }
304
305 m_wire.parse();
306
307 Block::element_const_iterator val = m_wire.elements_begin();
308 if (val == m_wire.elements_end())
309 {
310 throw Error("Unexpected end of FibEntry");
311 }
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600312 else if (val->type() != tlv::Name)
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600313 {
314 std::stringstream error;
315 error << "Expected Name, but Block is of a different type: #"
316 << val->type();
317 throw Error(error.str());
318 }
319 m_prefix.wireDecode(*val);
320 ++val;
321
322 for (; val != m_wire.elements_end(); ++val)
323 {
324 if (val->type() != tlv::nfd::NextHopRecord)
325 {
326 std::stringstream error;
327 error << "Expected NextHopRecords, but Block is of a different type: #"
328 << val->type();
329 throw Error(error.str());
330 }
Alexander Afanasyev44b438a2014-03-19 12:51:49 -0700331 m_nextHopRecords.push_back(NextHopRecord(*val));
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600332 }
333 }
334
335private:
336 Name m_prefix;
337 std::list<NextHopRecord> m_nextHopRecords;
338
339 mutable Block m_wire;
340};
341
342} // namespace nfd
343} // namespace ndn
344
345#endif // NDN_MANAGEMENT_NFD_FIB_ENTRY_HPP