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