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