blob: e6fae95215215e2f47552444b5e997a56d4742af [file] [log] [blame]
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
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.
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080011 */
12
13#ifndef NDN_MANAGEMENT_NFD_LOCAL_CONTROL_HEADER_HPP
14#define NDN_MANAGEMENT_NFD_LOCAL_CONTROL_HEADER_HPP
15
16#include "../encoding/encoding-buffer.hpp"
17#include "../encoding/tlv-nfd.hpp"
18
19namespace ndn {
20namespace nfd {
21
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080022class LocalControlHeader
23{
24public:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070025 class Error : public std::runtime_error
26 {
27 public:
28 explicit
29 Error(const std::string& what)
30 : std::runtime_error(what)
31 {
32 }
33 };
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080034
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080035 LocalControlHeader()
36 : m_incomingFaceId(INVALID_FACE_ID)
37 , m_nextHopFaceId(INVALID_FACE_ID)
38 {
39 }
40
41 /**
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070042 * @brief Create from wire encoding
43 *
44 * @sa wireDecode
45 */
46 explicit
47 LocalControlHeader(const Block& wire,
48 bool encodeIncomingFaceId = true, bool encodeNextHopFaceId = true)
49 {
50 wireDecode(wire, encodeIncomingFaceId, encodeNextHopFaceId);
51 }
52
53 /**
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080054 * @brief Create wire encoding with options LocalControlHeader and the supplied item
55 *
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080056 * The caller is responsible of checking whether LocalControlHeader contains
57 * any information.
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080058 *
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080059 * !It is an error to call this method if neither IncomingFaceId nor NextHopFaceId is
60 * set, or neither of them is enabled.
61 *
62 * @throws LocalControlHeader::Error when empty LocalControlHeader be produced
63 *
64 * @returns Block, containing LocalControlHeader. Top-level length field of the
65 * returned LocalControlHeader includes payload length, but the memory
66 * block is independent of the payload's wire buffer. It is expected
67 * that both LocalControlHeader's and payload's wire will be send out
68 * together within a single send call.
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080069 *
70 * @see http://redmine.named-data.net/projects/nfd/wiki/LocalControlHeader
71 */
72 template<class U>
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080073 inline Block
74 wireEncode(const U& payload,
75 bool encodeIncomingFaceId, bool encodeNextHopFaceId) const;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070076
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080077 /**
78 * @brief Decode from the wire format and set LocalControlHeader on the supplied item
79 *
80 * The supplied wire MUST contain LocalControlHeader. Determination whether the optional
81 * LocalControlHeader should be done before calling this method.
82 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070083 inline void
Alexander Afanasyev37bb1902014-02-19 23:57:23 -080084 wireDecode(const Block& wire,
85 bool encodeIncomingFaceId = true, bool encodeNextHopFaceId = true);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080086
87 inline static const Block&
88 getPayload(const Block& wire);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070089
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080090 ///////////////////////////////////////////////////////////////////////////////
91 ///////////////////////////////////////////////////////////////////////////////
92 ///////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080093 // Getters/setters
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080094
95 bool
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080096 empty(bool encodeIncomingFaceId, bool encodeNextHopFaceId) const
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080097 {
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080098 return !((encodeIncomingFaceId && hasIncomingFaceId()) ||
99 (encodeNextHopFaceId && hasNextHopFaceId()));
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800100 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700101
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800102 //
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700103
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800104 bool
105 hasIncomingFaceId() const
106 {
107 return m_incomingFaceId != INVALID_FACE_ID;
108 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700109
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800110 uint64_t
111 getIncomingFaceId() const
112 {
113 return m_incomingFaceId;
114 }
115
116 void
117 setIncomingFaceId(uint64_t incomingFaceId)
118 {
119 m_incomingFaceId = incomingFaceId;
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800120 }
121
122 //
123
124 bool
125 hasNextHopFaceId() const
126 {
127 return m_nextHopFaceId != INVALID_FACE_ID;
128 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700129
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800130 uint64_t
131 getNextHopFaceId() const
132 {
133 return m_nextHopFaceId;
134 }
135
136 void
137 setNextHopFaceId(uint64_t nextHopFaceId)
138 {
139 m_nextHopFaceId = nextHopFaceId;
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800140 }
141
142private:
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800143 template<bool T>
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800144 inline size_t
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800145 wireEncode(EncodingImpl<T>& block, size_t payloadSize,
146 bool encodeIncomingFaceId, bool encodeNextHopFaceId) const;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700147
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800148private:
149 uint64_t m_incomingFaceId;
150 uint64_t m_nextHopFaceId;
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800151};
152
153
154/**
155 * @brief Fast encoding or block size estimation
156 */
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800157template<bool T>
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800158inline size_t
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800159LocalControlHeader::wireEncode(EncodingImpl<T>& block, size_t payloadSize,
160 bool encodeIncomingFaceId, bool encodeNextHopFaceId) const
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800161{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700162 size_t totalLength = payloadSize;
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800163
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800164 if (encodeIncomingFaceId && hasIncomingFaceId())
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800165 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700166 totalLength += prependNonNegativeIntegerBlock(block,
167 tlv::nfd::IncomingFaceId, getIncomingFaceId());
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800168 }
169
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800170 if (encodeNextHopFaceId && hasNextHopFaceId())
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800171 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700172 totalLength += prependNonNegativeIntegerBlock(block,
173 tlv::nfd::NextHopFaceId, getNextHopFaceId());
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800174 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700175
176 totalLength += block.prependVarNumber(totalLength);
177 totalLength += block.prependVarNumber(tlv::nfd::LocalControlHeader);
178 return totalLength;
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800179}
180
181template<class U>
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800182inline Block
183LocalControlHeader::wireEncode(const U& payload,
184 bool encodeIncomingFaceId, bool encodeNextHopFaceId) const
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800185{
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800186 /// @todo should this be BOOST_ASSERT instead? This is kind of unnecessary overhead
187 if (empty(encodeIncomingFaceId, encodeNextHopFaceId))
188 throw Error("Requested wire for LocalControlHeader, but none of the fields are set or enabled");
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800189
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800190 EncodingEstimator estimator;
191 size_t length = wireEncode(estimator, payload.wireEncode().size(),
192 encodeIncomingFaceId, encodeNextHopFaceId);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700193
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800194 EncodingBuffer buffer(length);
195 wireEncode(buffer, payload.wireEncode().size(),
196 encodeIncomingFaceId, encodeNextHopFaceId);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800197
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800198 return buffer.block(false);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800199}
200
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700201inline void
Alexander Afanasyev37bb1902014-02-19 23:57:23 -0800202LocalControlHeader::wireDecode(const Block& wire,
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -0700203 bool encodeIncomingFaceId/* = true*/,
204 bool encodeNextHopFaceId/* = true*/)
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800205{
206 BOOST_ASSERT(wire.type() == tlv::nfd::LocalControlHeader);
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800207 wire.parse();
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800208
209 m_incomingFaceId = INVALID_FACE_ID;
210 m_nextHopFaceId = INVALID_FACE_ID;
211
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800212 for (Block::element_const_iterator i = wire.elements_begin();
213 i != wire.elements_end();
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800214 ++i)
215 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700216 switch (i->type())
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800217 {
218 case tlv::nfd::IncomingFaceId:
Alexander Afanasyev37bb1902014-02-19 23:57:23 -0800219 if (encodeIncomingFaceId)
220 m_incomingFaceId = readNonNegativeInteger(*i);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800221 break;
222 case tlv::nfd::NextHopFaceId:
Alexander Afanasyev37bb1902014-02-19 23:57:23 -0800223 if (encodeNextHopFaceId)
224 m_nextHopFaceId = readNonNegativeInteger(*i);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800225 break;
226 default:
227 // ignore all unsupported
228 break;
229 }
230 }
231}
232
233inline const Block&
234LocalControlHeader::getPayload(const Block& wire)
235{
236 if (wire.type() == tlv::nfd::LocalControlHeader)
237 {
238 wire.parse();
239 if (wire.elements_size() < 1)
240 return wire; // don't throw an error, but don't continue processing
241
242 return wire.elements()[wire.elements().size()-1];
243 }
244 else
245 {
246 return wire;
247 }
248}
249
250
251} // namespace nfd
252} // namespace ndn
253
254#endif // NDN_MANAGEMENT_NFD_LOCAL_CONTROL_HEADER_HPP