blob: 1086707fc2697390a51d7a30afde9e6f0035f043 [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"
26#include "../encoding/encoding-buffer.hpp"
27#include "../encoding/tlv-nfd.hpp"
28#include "../name.hpp"
29
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070030#include <list>
31
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060032namespace ndn {
33namespace nfd {
34
35// NextHopRecord := NEXT-HOP-RECORD TLV-LENGTH
36// FaceId
37// Cost
38
Alexander Afanasyev4671bf72014-05-19 09:01:37 -040039/**
40 * @ingroup management
41 */
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060042class NextHopRecord
43{
44public:
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060045 class Error : public tlv::Error
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060046 {
47 public:
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060048 Error(const std::string& what) : tlv::Error(what) {}
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060049 };
50
51 NextHopRecord()
52 : m_faceId(std::numeric_limits<uint64_t>::max())
53 , m_cost(0)
54 {
55 }
56
Alexander Afanasyev44b438a2014-03-19 12:51:49 -070057 explicit
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060058 NextHopRecord(const Block& block)
59 {
60 wireDecode(block);
61 }
62
63 uint64_t
64 getFaceId() const
65 {
66 return m_faceId;
67 }
68
69 NextHopRecord&
70 setFaceId(uint64_t faceId)
71 {
72 m_faceId = faceId;
73 m_wire.reset();
74 return *this;
75 }
76
77 uint64_t
78 getCost() const
79 {
80 return m_cost;
81 }
82
83 NextHopRecord&
84 setCost(uint64_t cost)
85 {
86 m_cost = cost;
87 m_wire.reset();
88 return *this;
89 }
90
91 template<bool T>
92 size_t
93 wireEncode(EncodingImpl<T>& block) const
94 {
95 size_t totalLength = 0;
96 totalLength += prependNonNegativeIntegerBlock(block,
97 ndn::tlv::nfd::Cost,
98 m_cost);
99
100 totalLength += prependNonNegativeIntegerBlock(block,
101 ndn::tlv::nfd::FaceId,
102 m_faceId);
103
104 totalLength += block.prependVarNumber(totalLength);
105 totalLength += block.prependVarNumber(ndn::tlv::nfd::NextHopRecord);
106 return totalLength;
107 }
108
109 const Block&
110 wireEncode() const
111 {
112 if (m_wire.hasWire())
113 {
114 return m_wire;
115 }
116
117 EncodingEstimator estimator;
118 size_t estimatedSize = wireEncode(estimator);
119
120 EncodingBuffer buffer(estimatedSize, 0);
121 wireEncode(buffer);
122
123 m_wire = buffer.block();
124 return m_wire;
125 }
126
127 void
128 wireDecode(const Block& wire)
129 {
130 m_faceId = std::numeric_limits<uint64_t>::max();
131 m_cost = 0;
132
133 m_wire = wire;
134
135 if (m_wire.type() != tlv::nfd::NextHopRecord)
136 {
137 std::stringstream error;
138 error << "Requested decoding of NextHopRecord, but Block is of a different type: #"
139 << m_wire.type();
140 throw Error(error.str());
141 }
142 m_wire.parse();
143
144 Block::element_const_iterator val = m_wire.elements_begin();
145 if (val == m_wire.elements_end())
146 {
147 throw Error("Unexpected end of NextHopRecord");
148 }
149 else if (val->type() != tlv::nfd::FaceId)
150 {
151 std::stringstream error;
152 error << "Expected FaceId, but Block is of a different type: #"
153 << val->type();
154 throw Error(error.str());
155 }
156 m_faceId = readNonNegativeInteger(*val);
157 ++val;
158
159 if (val == m_wire.elements_end())
160 {
161 throw Error("Unexpected end of NextHopRecord");
162 }
163 else if (val->type() != tlv::nfd::Cost)
164 {
165 std::stringstream error;
166 error << "Expected Cost, but Block is of a different type: #"
Alexander Afanasyev1c5a1a92014-03-21 13:32:36 -0700167 << m_wire.type();
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600168 throw Error(error.str());
169 }
170 m_cost = readNonNegativeInteger(*val);
171 }
172
173
174private:
175 uint64_t m_faceId;
176 uint64_t m_cost;
177
178 mutable Block m_wire;
179};
180
181
182// FibEntry := FIB-ENTRY-TYPE TLV-LENGTH
183// Name
184// NextHopRecord*
185
Alexander Afanasyev4671bf72014-05-19 09:01:37 -0400186/**
187 * @ingroup management
188 */
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600189class FibEntry
190{
191public:
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600192 class Error : public tlv::Error
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600193 {
194 public:
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600195 Error(const std::string& what) : tlv::Error(what)
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600196 {
197 }
198 };
199
200 FibEntry()
201 {
Alexander Afanasyev44b438a2014-03-19 12:51:49 -0700202 }
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600203
Alexander Afanasyev44b438a2014-03-19 12:51:49 -0700204 explicit
205 FibEntry(const Block& block)
206 {
207 wireDecode(block);
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600208 }
209
210 const Name&
211 getPrefix() const
212 {
213 return m_prefix;
214 }
215
216 FibEntry&
217 setPrefix(const Name& prefix)
218 {
219 m_prefix = prefix;
220 m_wire.reset();
221 return *this;
222 }
223
224 const std::list<NextHopRecord>&
225 getNextHopRecords() const
226 {
227 return m_nextHopRecords;
228 }
229
230 FibEntry&
231 addNextHopRecord(const NextHopRecord& nextHopRecord)
232 {
233 m_nextHopRecords.push_back(nextHopRecord);
234 m_wire.reset();
235 return *this;
236 }
237
238 template<typename T>
239 FibEntry&
240 setNextHopRecords(const T& begin, const T& end)
241 {
242 m_nextHopRecords.clear();
243 m_nextHopRecords.assign(begin, end);
244 m_wire.reset();
245 return *this;
246 }
247
248 template<bool T>
249 size_t
250 wireEncode(EncodingImpl<T>& block) const
251 {
252 size_t totalLength = 0;
253
Alexander Afanasyev1c5a1a92014-03-21 13:32:36 -0700254 for (std::list<NextHopRecord>::const_reverse_iterator i = m_nextHopRecords.rbegin();
255 i != m_nextHopRecords.rend();
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600256 ++i)
257 {
258 totalLength += i->wireEncode(block);
259 }
260
261 totalLength += m_prefix.wireEncode(block);
262 totalLength += block.prependVarNumber(totalLength);
263 totalLength += block.prependVarNumber(tlv::nfd::FibEntry);
264
265 return totalLength;
266 }
267
268 const Block&
269 wireEncode() const
270 {
271 if (m_wire.hasWire())
272 {
273 return m_wire;
274 }
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
284 return m_wire;
285 }
286
287 void
288 wireDecode(const Block& wire)
289 {
290 m_prefix.clear();
291 m_nextHopRecords.clear();
292
293 m_wire = wire;
294
295 if (m_wire.type() != tlv::nfd::FibEntry)
296 {
297 std::stringstream error;
298 error << "Requested decoding of FibEntry, but Block is of a different type: #"
299 << m_wire.type();
300 throw Error(error.str());
301 }
302
303 m_wire.parse();
304
305 Block::element_const_iterator val = m_wire.elements_begin();
306 if (val == m_wire.elements_end())
307 {
308 throw Error("Unexpected end of FibEntry");
309 }
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600310 else if (val->type() != tlv::Name)
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600311 {
312 std::stringstream error;
313 error << "Expected Name, but Block is of a different type: #"
314 << val->type();
315 throw Error(error.str());
316 }
317 m_prefix.wireDecode(*val);
318 ++val;
319
320 for (; val != m_wire.elements_end(); ++val)
321 {
322 if (val->type() != tlv::nfd::NextHopRecord)
323 {
324 std::stringstream error;
325 error << "Expected NextHopRecords, but Block is of a different type: #"
326 << val->type();
327 throw Error(error.str());
328 }
Alexander Afanasyev44b438a2014-03-19 12:51:49 -0700329 m_nextHopRecords.push_back(NextHopRecord(*val));
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600330 }
331 }
332
333private:
334 Name m_prefix;
335 std::list<NextHopRecord> m_nextHopRecords;
336
337 mutable Block m_wire;
338};
339
340} // namespace nfd
341} // namespace ndn
342
343#endif // NDN_MANAGEMENT_NFD_FIB_ENTRY_HPP