blob: eaa372c63121f8c3406510e60876d3b1c028f982 [file] [log] [blame]
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Steve DiBenedetto6d792d72014-03-15 19:01:36 -06002/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060011 */
12
13#ifndef NDN_MANAGEMENT_NFD_FIB_ENTRY_HPP
14#define NDN_MANAGEMENT_NFD_FIB_ENTRY_HPP
15
16#include "../encoding/block.hpp"
17#include "../encoding/encoding-buffer.hpp"
18#include "../encoding/tlv-nfd.hpp"
19#include "../name.hpp"
20
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070021#include <list>
22
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060023namespace ndn {
24namespace nfd {
25
26// NextHopRecord := NEXT-HOP-RECORD TLV-LENGTH
27// FaceId
28// Cost
29
30class NextHopRecord
31{
32public:
33 class Error : public Tlv::Error
34 {
35 public:
Alexander Afanasyev1c5a1a92014-03-21 13:32:36 -070036 Error(const std::string& what) : Tlv::Error(what) {}
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060037 };
38
39 NextHopRecord()
40 : m_faceId(std::numeric_limits<uint64_t>::max())
41 , m_cost(0)
42 {
43 }
44
Alexander Afanasyev44b438a2014-03-19 12:51:49 -070045 explicit
Steve DiBenedetto6d792d72014-03-15 19:01:36 -060046 NextHopRecord(const Block& block)
47 {
48 wireDecode(block);
49 }
50
51 uint64_t
52 getFaceId() const
53 {
54 return m_faceId;
55 }
56
57 NextHopRecord&
58 setFaceId(uint64_t faceId)
59 {
60 m_faceId = faceId;
61 m_wire.reset();
62 return *this;
63 }
64
65 uint64_t
66 getCost() const
67 {
68 return m_cost;
69 }
70
71 NextHopRecord&
72 setCost(uint64_t cost)
73 {
74 m_cost = cost;
75 m_wire.reset();
76 return *this;
77 }
78
79 template<bool T>
80 size_t
81 wireEncode(EncodingImpl<T>& block) const
82 {
83 size_t totalLength = 0;
84 totalLength += prependNonNegativeIntegerBlock(block,
85 ndn::tlv::nfd::Cost,
86 m_cost);
87
88 totalLength += prependNonNegativeIntegerBlock(block,
89 ndn::tlv::nfd::FaceId,
90 m_faceId);
91
92 totalLength += block.prependVarNumber(totalLength);
93 totalLength += block.prependVarNumber(ndn::tlv::nfd::NextHopRecord);
94 return totalLength;
95 }
96
97 const Block&
98 wireEncode() const
99 {
100 if (m_wire.hasWire())
101 {
102 return m_wire;
103 }
104
105 EncodingEstimator estimator;
106 size_t estimatedSize = wireEncode(estimator);
107
108 EncodingBuffer buffer(estimatedSize, 0);
109 wireEncode(buffer);
110
111 m_wire = buffer.block();
112 return m_wire;
113 }
114
115 void
116 wireDecode(const Block& wire)
117 {
118 m_faceId = std::numeric_limits<uint64_t>::max();
119 m_cost = 0;
120
121 m_wire = wire;
122
123 if (m_wire.type() != tlv::nfd::NextHopRecord)
124 {
125 std::stringstream error;
126 error << "Requested decoding of NextHopRecord, but Block is of a different type: #"
127 << m_wire.type();
128 throw Error(error.str());
129 }
130 m_wire.parse();
131
132 Block::element_const_iterator val = m_wire.elements_begin();
133 if (val == m_wire.elements_end())
134 {
135 throw Error("Unexpected end of NextHopRecord");
136 }
137 else if (val->type() != tlv::nfd::FaceId)
138 {
139 std::stringstream error;
140 error << "Expected FaceId, but Block is of a different type: #"
141 << val->type();
142 throw Error(error.str());
143 }
144 m_faceId = readNonNegativeInteger(*val);
145 ++val;
146
147 if (val == m_wire.elements_end())
148 {
149 throw Error("Unexpected end of NextHopRecord");
150 }
151 else if (val->type() != tlv::nfd::Cost)
152 {
153 std::stringstream error;
154 error << "Expected Cost, but Block is of a different type: #"
Alexander Afanasyev1c5a1a92014-03-21 13:32:36 -0700155 << m_wire.type();
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600156 throw Error(error.str());
157 }
158 m_cost = readNonNegativeInteger(*val);
159 }
160
161
162private:
163 uint64_t m_faceId;
164 uint64_t m_cost;
165
166 mutable Block m_wire;
167};
168
169
170// FibEntry := FIB-ENTRY-TYPE TLV-LENGTH
171// Name
172// NextHopRecord*
173
174class FibEntry
175{
176public:
177 class Error : public Tlv::Error
178 {
179 public:
180 Error(const std::string& what) : Tlv::Error(what)
181 {
182 }
183 };
184
185 FibEntry()
186 {
Alexander Afanasyev44b438a2014-03-19 12:51:49 -0700187 }
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600188
Alexander Afanasyev44b438a2014-03-19 12:51:49 -0700189 explicit
190 FibEntry(const Block& block)
191 {
192 wireDecode(block);
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600193 }
194
195 const Name&
196 getPrefix() const
197 {
198 return m_prefix;
199 }
200
201 FibEntry&
202 setPrefix(const Name& prefix)
203 {
204 m_prefix = prefix;
205 m_wire.reset();
206 return *this;
207 }
208
209 const std::list<NextHopRecord>&
210 getNextHopRecords() const
211 {
212 return m_nextHopRecords;
213 }
214
215 FibEntry&
216 addNextHopRecord(const NextHopRecord& nextHopRecord)
217 {
218 m_nextHopRecords.push_back(nextHopRecord);
219 m_wire.reset();
220 return *this;
221 }
222
223 template<typename T>
224 FibEntry&
225 setNextHopRecords(const T& begin, const T& end)
226 {
227 m_nextHopRecords.clear();
228 m_nextHopRecords.assign(begin, end);
229 m_wire.reset();
230 return *this;
231 }
232
233 template<bool T>
234 size_t
235 wireEncode(EncodingImpl<T>& block) const
236 {
237 size_t totalLength = 0;
238
Alexander Afanasyev1c5a1a92014-03-21 13:32:36 -0700239 for (std::list<NextHopRecord>::const_reverse_iterator i = m_nextHopRecords.rbegin();
240 i != m_nextHopRecords.rend();
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600241 ++i)
242 {
243 totalLength += i->wireEncode(block);
244 }
245
246 totalLength += m_prefix.wireEncode(block);
247 totalLength += block.prependVarNumber(totalLength);
248 totalLength += block.prependVarNumber(tlv::nfd::FibEntry);
249
250 return totalLength;
251 }
252
253 const Block&
254 wireEncode() const
255 {
256 if (m_wire.hasWire())
257 {
258 return m_wire;
259 }
260
261 EncodingEstimator estimator;
262 size_t estimatedSize = wireEncode(estimator);
263
264 EncodingBuffer buffer(estimatedSize, 0);
265 wireEncode(buffer);
266
267 m_wire = buffer.block();
268
269 return m_wire;
270 }
271
272 void
273 wireDecode(const Block& wire)
274 {
275 m_prefix.clear();
276 m_nextHopRecords.clear();
277
278 m_wire = wire;
279
280 if (m_wire.type() != tlv::nfd::FibEntry)
281 {
282 std::stringstream error;
283 error << "Requested decoding of FibEntry, but Block is of a different type: #"
284 << m_wire.type();
285 throw Error(error.str());
286 }
287
288 m_wire.parse();
289
290 Block::element_const_iterator val = m_wire.elements_begin();
291 if (val == m_wire.elements_end())
292 {
293 throw Error("Unexpected end of FibEntry");
294 }
295 else if (val->type() != Tlv::Name)
296 {
297 std::stringstream error;
298 error << "Expected Name, but Block is of a different type: #"
299 << val->type();
300 throw Error(error.str());
301 }
302 m_prefix.wireDecode(*val);
303 ++val;
304
305 for (; val != m_wire.elements_end(); ++val)
306 {
307 if (val->type() != tlv::nfd::NextHopRecord)
308 {
309 std::stringstream error;
310 error << "Expected NextHopRecords, but Block is of a different type: #"
311 << val->type();
312 throw Error(error.str());
313 }
Alexander Afanasyev44b438a2014-03-19 12:51:49 -0700314 m_nextHopRecords.push_back(NextHopRecord(*val));
Steve DiBenedetto6d792d72014-03-15 19:01:36 -0600315 }
316 }
317
318private:
319 Name m_prefix;
320 std::list<NextHopRecord> m_nextHopRecords;
321
322 mutable Block m_wire;
323};
324
325} // namespace nfd
326} // namespace ndn
327
328#endif // NDN_MANAGEMENT_NFD_FIB_ENTRY_HPP